[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"i-ri:search-line":3,"i-ri:moon-line":8,"i-ri:sun-line":10,"i-ri:menu-3-line":12,"i-ri:close-line":14,"notes-module-items-ai":16,"notes-page-ai-02-agent-architecture\u002F05-review-diff-chunking":74,"i-ri:arrow-left-s-line":219,"i-ri:menu-2-line":221,"i-ri:arrow-right-s-line":223,"i-ep:copy-document":225},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"currentColor\" d=\"m18.031 16.617l4.283 4.282l-1.415 1.415l-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9s9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617m-2.006-.742A6.98 6.98 0 0 0 18 11c0-3.867-3.133-7-7-7s-7 3.133-7 7s3.133 7 7 7a6.98 6.98 0 0 0 4.875-1.975z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2h.1A6.98 6.98 0 0 0 10 7m-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938A8 8 0 0 0 4 12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cpath fill=\"currentColor\" d=\"M12 18a6 6 0 1 1 0-12a6 6 0 0 1 0 12m0-2a4 4 0 1 0 0-8a4 4 0 0 0 0 8M11 1h2v3h-2zm0 19h2v3h-2zM3.515 4.929l1.414-1.414L7.05 5.636L5.636 7.05zM16.95 18.364l1.414-1.414l2.121 2.121l-1.414 1.414zm2.121-14.85l1.414 1.415l-2.121 2.121l-1.414-1.414zM5.636 16.95l1.414 1.414l-2.121 2.121l-1.414-1.414zM23 11v2h-3v-2zM4 11v2H1v-2z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm6 7h12v2H9zm-6 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cpath fill=\"currentColor\" d=\"m12 10.587l4.95-4.95l1.414 1.414l-4.95 4.95l4.95 4.95l-1.415 1.414l-4.95-4.95l-4.949 4.95l-1.414-1.415l4.95-4.95l-4.95-4.95L7.05 5.638z\"\u002F>",[17,22,26,30,34,38,42,46,50,54,58,62,66,70],{"path":18,"title":19,"meta":20},"\u002Fnotes\u002Fai\u002F01-llm-basics\u002F01-hello-llm","LLM 交互基础：透过现象看本质",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},"2026-11-05T09:47:15.000Z",{"path":23,"title":24,"meta":25},"\u002Fnotes\u002Fai\u002F01-llm-basics\u002F02-streaming-and-prompts","进阶交互：流式传输与提示词工程",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":27,"title":28,"meta":29},"\u002Fnotes\u002Fai\u002F01-llm-basics\u002F03-function-calling","结构化输出与 Function Calling",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":31,"title":32,"meta":33},"\u002Fnotes\u002Fai\u002F02-agent-architecture\u002F01-tool-use","Agent 核心能力 ①：Tool Use（工具调用）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":35,"title":36,"meta":37},"\u002Fnotes\u002Fai\u002F02-agent-architecture\u002F02-mini-cursor-cli","实战项目：Mini Cursor（CLI 版）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":39,"title":40,"meta":41},"\u002Fnotes\u002Fai\u002F02-agent-architecture\u002F03-memory","Agent 核心能力 ②：Memory（记忆管理）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":43,"title":44,"meta":45},"\u002Fnotes\u002Fai\u002F02-agent-architecture\u002F04-planning","Agent 核心能力 ③：Planning（规划能力）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":47,"title":48,"meta":49},"\u002Fnotes\u002Fai\u002F02-agent-architecture\u002F05-review-diff-chunking","代码改了很多，AI 为什么只审了前面？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":51,"title":52,"meta":53},"\u002Fnotes\u002Fai\u002F02-agent-architecture","Agent 架构笔记",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":55,"title":56,"meta":57},"\u002Fnotes\u002Fai\u002F03-rag\u002F01-vector-db-and-embeddings-node","RAG ①：Embeddings 与向量数据库入门（Node.js 优先）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":59,"title":60,"meta":61},"\u002Fnotes\u002Fai\u002F04-document-extraction\u002F01-ocr-field-evidence","OCR 读对了字，为什么地址仍然错？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":63,"title":64,"meta":65},"\u002Fnotes\u002Fai\u002F05-development-workflow\u002F01-task-recovery","AI 任务做一半，中断后怎么继续？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":67,"title":68,"meta":69},"\u002Fnotes\u002Fai","AI 应用开发",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":71,"title":72,"meta":73},"\u002Fnotes\u002Fai\u002Froadmap","AI Agent 全栈开发学习路线图 (Roadmap)",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"id":75,"type":76,"sourcePath":77,"routePath":47,"path":47,"title":48,"description":78,"updatedAt":21,"meta":79,"body":88,"toc":212},"bm90ZTpub3Rlcy9haS8wMi1hZ2VudC1hcmNoaXRlY3R1cmUvMDUtcmV2aWV3LWRpZmYtY2h1bmtpbmcubWQ","note","notes\u002Fai\u002F02-agent-architecture\u002F05-review-diff-chunking.md","把 Git 修改交给 AI 审查时，输入很快就会超过一次请求能容纳的范围。一个直接的办法是截取 diff 的前 N 个字符，再让模型给出意见。",{"id":75,"type":76,"sourcePath":77,"slug":80,"title":48,"updatedAt":21,"description":78,"tags":81,"date":85,"comment":86,"summary":87,"lastUpdated":21},"ai\u002F02-agent-architecture\u002F05-review-diff-chunking",[82,83,84],"AI","Agent","代码审查","2026-04-03",true,"控制审查输入长度时，直接截断会漏掉后面的文件。按文件和修改片段分块，并让报告说明实际看到了哪些内容。",{"type":89,"children":90},"root",[91,99,104,109,116,121,126,131,137,142,147,160,165,170,175,181,186,191,196,202,207],{"type":92,"tag":93,"props":94,"children":96},"element","h1",{"id":95},"代码改了很多ai-为什么只审了前面",[97],{"type":98,"value":48},"text",{"type":92,"tag":100,"props":101,"children":102},"p",{},[103],{"type":98,"value":78},{"type":92,"tag":100,"props":105,"children":106},{},[107],{"type":98,"value":108},"这会产生一个不太显眼的问题：第一个文件大一点，后面的修改就完全进不了输入，模型却仍能给出一份正常报告。读报告的人如果不知道截断发生过，就可能把它理解为整批修改已经审完。",{"type":92,"tag":110,"props":111,"children":113},"h2",{"id":112},"先减输入还是先确定要审什么",[114],{"type":98,"value":115},"先减输入，还是先确定要审什么？",{"type":92,"tag":100,"props":117,"children":118},{},[119],{"type":98,"value":120},"需要先确定范围。审暂存区、整个工作区，还是两个提交之间的差异，对应的输入不同。把范围收错了，后面分得再细也没有用。",{"type":92,"tag":100,"props":122,"children":123},{},[124],{"type":98,"value":125},"项目会收集已暂存、未暂存和未跟踪文件。未跟踪文件不在普通 diff 中，需要单独读取并按新增文件组织。同一文件既有暂存又有未暂存修改时，当前收集器组合的是两个阶段的差异，还不能把它当成某个基线到最终工作区的唯一补丁。",{"type":92,"tag":100,"props":127,"children":128},{},[129],{"type":98,"value":130},"未跟踪项也可能是目录、嵌套仓库或二进制文件，不能假定每个路径都能按 UTF-8 文本读。",{"type":92,"tag":110,"props":132,"children":134},{"id":133},"大批修改有哪些拆法",[135],{"type":98,"value":136},"大批修改有哪些拆法？",{"type":92,"tag":100,"props":138,"children":139},{},[140],{"type":98,"value":141},"可以按字符硬切，简单，但容易切断文件头和修改上下文；也可以按文件分，每份输入比较完整，但单个大文件仍然可能超限。更细的一层是 hunk，也就是 diff 中带原始行号范围的连续修改片段。",{"type":92,"tag":100,"props":143,"children":144},{},[145],{"type":98,"value":146},"项目采用文件优先、过大再拆 hunk 的方式。只有一个 hunk 本身仍然过大，才裁剪内容并标记截断：",{"type":92,"tag":148,"props":149,"children":154},"pre",{"className":150,"code":152,"language":98,"meta":153},[151],"language-text","文件 A 放得下     → 完整保留\n文件 B 太大       → 按 B1、B2、B3 三个修改片段拆开\nB2 本身仍然太大   → 截断 B2，并标明内容不完整\n文件 C 放得下     → 继续保留 C\n","",[155],{"type":92,"tag":156,"props":157,"children":158},"code",{"__ignoreMap":153},[159],{"type":98,"value":152},{"type":92,"tag":100,"props":161,"children":162},{},[163],{"type":98,"value":164},"拆开的每块都附带文件头、文件名和原始行范围，方便定位。范围表示内容原来位于哪里；如果这块被裁过，并不代表范围内的每一行都已经交给模型。",{"type":92,"tag":100,"props":166,"children":167},{},[168],{"type":98,"value":169},"这种拆法至少不会让第一个大文件吞掉后续所有文件，也能保留一部分局部上下文。",{"type":92,"tag":100,"props":171,"children":172},{},[173],{"type":98,"value":174},"已有回归用例使用真实临时 Git 仓库，构造两个文件，让总 diff 超预算、每个文件各自不超，检查两个文件都能进入分块；另有用例检查未跟踪目录项。它们验证收集和分块，不验证模型是否善于发现缺陷。后者需要带已知问题的修改样本，另看漏报、误报、定位和调用成本。",{"type":92,"tag":110,"props":176,"children":178},{"id":177},"每块都没超限为什么仍然可能很贵",[179],{"type":98,"value":180},"每块都没超限，为什么仍然可能很贵？",{"type":92,"tag":100,"props":182,"children":183},{},[184],{"type":98,"value":185},"这里的预算按字符串长度计算，没有经过 tokenizer。同样长度的中文、代码和符号，token 数可能不同。多个块加起来也会超过单块预算，重复文件头还会增加总输入。",{"type":92,"tag":100,"props":187,"children":188},{},[189],{"type":98,"value":190},"如果要限制最终请求大小，需要在组装完系统提示、上下文和输出预留后计算；要限制整轮成本，还要统计所有调用。现有分块只负责组织输入，没有提供这两个硬保证。预算极小时，连文件头和截断标记都可能放不下，也需要单独定义处理方式。",{"type":92,"tag":100,"props":192,"children":193},{},[194],{"type":98,"value":195},"拆分还会损失关联。例如文件 A 改了函数签名，文件 B 改调用，单看一块可能发现不了不一致。可以按符号、import 或调用关系补上下文，但这是后续能力。现有多个审查者及汇总环节，无法凭空补回从未收到的代码。",{"type":92,"tag":110,"props":197,"children":199},{"id":198},"怎么知道这次审查漏看了什么",[200],{"type":98,"value":201},"怎么知道这次审查漏看了什么？",{"type":92,"tag":100,"props":203,"children":204},{},[205],{"type":98,"value":206},"项目把分块中的截断状态汇总到审查输入，再带到最终报告。某个审查者调用失败，也与“审查成功但没有发现问题”分别记录。",{"type":92,"tag":100,"props":208,"children":209},{},[210],{"type":98,"value":211},"目前一个截断布尔值还不能列出所有遗漏行和跨文件关系，但至少能提醒调用方：这份报告使用的输入并不完整。",{"title":153,"searchDepth":213,"depth":213,"links":214},2,[215,216,217,218],{"id":112,"depth":213,"text":115},{"id":133,"depth":213,"text":136},{"id":177,"depth":213,"text":180},{"id":198,"depth":213,"text":201},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":220},"\u003Cpath fill=\"currentColor\" d=\"m10.828 12l4.95 4.95l-1.414 1.415L8 12l6.364-6.364l1.414 1.414z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":222},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm0 7h12v2H3zm0 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":224},"\u003Cpath fill=\"currentColor\" d=\"m13.172 12l-4.95-4.95l1.414-1.413L16 12l-6.364 6.364l-1.414-1.415z\"\u002F>",{"left":4,"top":4,"width":226,"height":226,"rotate":4,"vFlip":6,"hFlip":6,"body":227},1024,"\u003Cpath fill=\"currentColor\" d=\"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z\"\u002F>\u003Cpath fill=\"currentColor\" d=\"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64\"\u002F>"]