☰
REA工作模式:让Agent读懂代码仓库并讲清登录存储更新流程
2026/11/3 5:18:55 网站建设 项目流程

1. 先想清楚:REA 要解决的是"答得对",不是"答得像"

REA 这个名字是我自己起的,三个字母对应Reason、Explore、Act——推理、探索、行动,一个循环里反复走这三步。它本质上是把 ReAct 那套"边想边查"的范式做了一次工程收敛:推理负责拆问题,探索负责找证据,行动负责把证据读进来。这套方法落到应用代码理解这个场景上,就变成了一件事:让 Agent 面对一个陌生的代码仓库,能把"登录怎么走"、"数据存到哪"、"版本怎么更新"这三条链路讲清楚,而且每一句都能落到具体的文件和行号上。

为什么挑这三条流程?因为它们是绝大多数应用里跨层最多、隐式约定最多、文档最容易过期的部分。登录牵涉路由入口、凭证获取、令牌存放、刷新与失效、权限校验,横跨前后端;存储牵涉内存缓存、本地持久化、服务端持久层三层,写在哪、读在哪、什么时候失效,经常只有代码自己知道;更新流程更麻烦,Web 端、移动端、服务端三套逻辑完全不同,光"更新"两个字就能让 Agent 答偏。我试过直接拿一段裸问题丢给通用模型,问"这个应用的登录流程是怎样的",它给出的回答通顺、结构漂亮、每一段都有小标题,但一半以上是行业通用套路,不是这个仓库里的真实实现。这种东西拿去做新人上手文档,比没有更危险。

所以这篇文章适合谁?适合手上有一堆历史项目、要接手别人代码的同学;适合在团队里做知识沉淀、想让 AI 帮忙写架构说明的同学;也适合已经在搭 Agent、但发现"检索一堆文件塞进上下文"效果很差、想搞明白问题出在哪的同学。文中的实操部分我会给出可以直接抄的代码骨架和提示词结构,基础薄弱的读者照着改参数也能跑,有经验的读者可以直接跳到第 4 节的编排细节。

需要先声明一点:REA 不是什么现成框架,也不是某家平台的私有方案,它是一套可以自己在几十行到几百行代码里搭出来的工作模式。文中涉及的模型调用、向量检索、语法解析这些环节,我都用通用接口描述,你换成自己团队在用的那套服务即可,思路完全一致。

1.1 三个问题背后的真实业务场景

把这三条流程放在一起看,会发现它们共享一个特征:答案藏在代码的"连接处",而不在代码的"主体"里。登录流程的关键不在登录页那个表单组件,而在路由守卫、请求拦截器、令牌刷新这几处横切逻辑;存储流程的关键不在数据模型定义,而在谁调用了写入方法、谁在什么时机清了缓存;更新流程的关键不在版本号常量,而在构建脚本、发布清单、迁移脚本的执行顺序。

我在一个中型项目上做过统计:问"登录流程",接入点最密集的文件分布在前端的请求封装层和后端的鉴权中间件,加起来不到八个文件,但这八个文件分散在三个不同目录,文件名里没有一个是"login"。这就是普通检索的失效点——关键词搜索 "login" 只能捞到表单和接口定义,捞不到拦截器。Agent 必须具备顺着调用关系往外走的能力,这正是 Explore 这一步存在的理由。

另一层是词义消歧。举一个我踩过的坑:某次问"更新流程",Agent 一头扎进客户端的版本检查逻辑,给了一份完整的应用商店更新说明,但实际项目里更关键的是服务端的数据库迁移脚本执行顺序,因为那才是真正的风险点。它没错,但答的不是我问的。后来我在提示词里强制加了第一步:先判断问题涉及哪一层,列出可能的解释,选一个并说明理由,答偏的概率直接降了一大截。

1.2 裸模型为什么必然翻车

翻车有三个典型模式,值得挨个拆。

第一个是路径幻觉。让模型凭记忆说"登录逻辑在src/auth/login.ts",它会给你一个语法完全合理、命名符合直觉、但根本不存在的路径。这不是模型不聪明,是它在做概率补全,而真实仓库的文件名往往反直觉——真实项目里可能是src/views/entry/index.tsx里套了一个useSession。解决办法很土但有效:所有路径必须来自工具返回,禁止模型自己拼。这条规则写进系统提示,效果立竿见影。

第二个是上下文稀释。一个文件八百行,全塞进去,模型对中间那几十行的注意力会被摊薄。我做过对比,同一个鉴权中间件,整文件输入和只给关键一百二十行,后者在"令牌过期后走哪条分支"这个问题上的正确率明显更高。所以读文件必须带行区间,一次不超过两百行,这是个硬约束。

第三个是证据链断裂。模型说"令牌存在本地存储里",但它看的是写入的那一行,没有看读取的那一行,也没有看失效清理的那一行。真实情况可能是写入用了一个封装过的方法,读取走了另一条路径,清理在拦截器里。三处不一致,才是这个仓库真正的知识。所以我要求 Agent 对每个结论至少给出两处证据:一处写入、一处读取或消费。

1.3 我最后的取舍:探索优先,推理兜底

搭这类 Agent 有两种思路。一种是把整个仓库向量化,问题进来直接检索片段,一次调用出答案,快但浅;另一种是给模型工具,让它自己决定查什么,慢但深。

我选的是后者,但不是纯后者。纯工具调用的问题是不稳定,同一个问题问两次,走的路径可能完全不同,有时候绕了十轮还没摸到主链路。我的做法是给它一张粗糙的地图:索引阶段先跑一遍轻量静态分析,产出一份目录摘要、符号表、配置清单、最近的提交摘要,把这些压缩成两三千字的"仓库速览"放进系统提示。模型拿到速览之后再决定往哪钻,路径选择就稳多了。

这个取舍的核心逻辑是:检索决定下限,推理决定上限。检索把模型拉进真实代码,推理负责把散落的证据串成流程。两个都不能省,但优先保证检索的可靠性,因为推理再强也救不回一份错的证据。

2. REA 的整体架构与工具选型

整套东西我拆成三层:索引层、工具层、编排层。分层不是为了好看,是为了让每一层都能单独测。索引层出错,表现是所有问题都答偏;工具层出错,表现是模型反复重试;编排层出错,表现是烧了一堆 token 却什么都没查。分开测,定位问题能省掉大量时间。

2.1 索引层:不追求全,追求"找得到入口"

索引层我做了六件事,按重要性排序:

  • 文件清单与语言识别:遍历仓库,排除依赖目录、构建产物、二进制资源。这一步能砍掉 60% 以上的噪音文件。
  • 文本倒排索引:关键词到文件:行号的映射,支持正则。这是最朴素也最管用的东西,比向量检索在代码场景下更可控。
  • 符号表:用语法解析提取函数、类、方法的定义位置。注意,只要定义位置,不做类型推导,够用就行。
  • 调用关系近似:基于符号名的文本匹配建立"谁调用了谁",允许误报,不允许漏报。
  • 配置清单标记:把构建配置、依赖清单、环境变量示例、数据库迁移目录单独标出来,这些文件在流程问题里出现频率极高。
  • 提交摘要:取最近两三百条提交的标题和前几个改动文件,压缩成短列表。更新流程这类问题,光看代码经常串不起来,得靠提交信息补上下文。

这里有个关键取舍:不做全量向量化。原因很实际,代码片段的向量相似度经常被注释和命名风格带偏,两个功能毫不相干的函数,只要注释写得像,向量距离就很近。而且向量检索给不出行号边界,返回的是模糊片段,对"证据必须精确到行"这个要求是硬伤。我的做法是文本检索为主,向量检索只在"找语义相近的实现"这种模糊场景下作为补充,并且明确告诉模型这是模糊结果。

符号表这块也有坑。有些语言的语法解析器对动态特性支持一般,遇到装饰器包装、元类、宏展开,符号位置会偏。我的处理是解析失败就回退到正则,宁可粗糙也别丢。实测下来,正则兜底能把符号召回率补回来不少。

2.2 工具层:五个工具,少而狠

工具给多了模型会挑花眼,这是我在别的项目上验证过的教训。给到十几个工具之后,模型经常在"该用哪个"上纠结,或者连续调用三个功能重叠的工具做重复劳动。最后我压到五个:

工具名作用关键参数设计要点
list_tree看目录结构路径、深度限制深度,避免一次吐出上千条
search_text全文正则搜索表达式、文件范围、上限必须返回行号和命中行内容
read_slice按行区间读文件路径、起止行强制带行号返回,单次上限两百行
trace_symbol查定义与调用方符号名、方向双向,既能找定义也能找调用者
git_pick查提交记录关键词或路径、条数返回标题、哈希前七位、改动文件

五个工具里,search_text是使用频率最高的,占我统计里六成以上的调用。所以它的返回质量决定一切。我的做法是每次最多返回三十条命中,每条带文件路径、行号、该行原文,外加前后各一行的上下文。三十条这个数字是调出来的:太少会漏,太多模型看不过来,还会占掉本该留给read_slice的预算。

trace_symbol是这套方案跟普通检索的分水岭。它让 Agent 能从一个具体函数往上追调用方,往下追实现。登录流程能串起来,靠的就是这个——从接口定义往上追到路由注册,往下追到鉴权中间件,再横向追到令牌工具类。

注意:trace_symbol的结果一定要标注"置信度"。基于文本匹配的调用关系,遇到同名方法、反射调用、依赖注入,会给出假阳性。我在工具返回值里加了一个hint字段,写明"基于名称匹配,可能存在同名干扰",模型看到这个提示后会主动去read_slice验证,误判率明显下降。

2.3 上下文预算:留白比塞满更重要

这一块是很多人忽略的地方。我的分配是:系统提示与仓库速览占三成,证据(工具返回内容)占五成,推理历史占一成半,剩下半成留白。

为什么留白?因为模型的输出也需要空间,而且在多轮循环里,如果历史对话把窗口占满,最后一轮的推理质量会明显下滑——它没地方"想"了。我吃过这个亏,早期版本经常在第七八轮突然给出一个含糊的结论,后来加了预算控制,情况好转很多。

压缩策略是摘要式淘汰。工具返回的原始内容在保留一轮之后,折叠成一行摘要,格式是"读过path:120-180,关键信息:令牌在此处写入本地存储,键名由常量拼接"。原始内容丢进可回溯缓存,需要时可以重新读。这样既省窗口,又保留线索。

3. 三条流程怎么被讲清楚

这一节是全文最实的部分。我按"要查什么、怎么查、容易漏什么"来拆,每一条都可以直接对应到工具调用序列。

3.1 登录流程:从入口一路追到令牌失效

登录这条链路,Agent 最容易做的事是找到登录页面就宣布结束。真正的流程节点远比这多。我给它的检索清单是七项,按顺序走:

第一,找到入口。搜索路由注册、页面清单、接口定义,确认登录是从哪个入口触发的。这里要区分是页面跳转、弹窗还是回调,不同入口对应的后续路径差别很大。

第二,找到凭证提交。搜索表单提交、请求方法定义,确认凭证字段名和提交地址。这一步的关键是拿到字段名的真实拼写,因为后面追后端校验全靠它。

第三,找到后端接收。用字段名去搜后端,通常能命中控制器或处理器。命中之后再往上追一层鉴权中间件,这里往往是整条链路的核心。

第四,找到令牌签发。搜索令牌生成、签名、过期时间设置。这一步要记录三件事:令牌有效期、刷新机制是否存在、签名密钥来源。

第五,找到令牌存放。这是最容易漏的一步。搜索写入操作,同时搜索读取操作,两边对不上就要警惕——我见过写入用封装方法、读取直接取存储的案例,这种不一致本身就是重要信息。

第六,找到失效处理。搜索状态码处理、拦截器、路由守卫。重点是"过期之后跳哪里、有没有静默刷新"。

第七,找到权限校验。搜索角色判断、权限装饰器、菜单过滤。

七步走完,一份登录流程才算立起来。这里我要强调一个原则:每个节点至少两处证据。签发一处、校验一处;写入一处、读取一处。单点证据的结论,我要求在输出里标注"待确认"。

提示:追登录链路时,search_text的搜索词不要用 "login",用字段名和错误码。字段名是跨层传递最稳定的锚点,错误码往往能一次性定位到所有分支处理逻辑。

3.2 存储流程:三层结构,先分清再下钻

存储问题最容易答偏,因为"存哪"这三个字至少有三层含义。我让 Agent 先做一个判断:问题是问客户端本地存储、内存缓存,还是服务端持久层。判断不清楚就问,不要猜。

分清之后,每层的追法不一样。

客户端本地存储,追的是写入点、读取点、清理点、键名生成规则。键名生成规则特别值得追,因为很多项目会用用户标识拼前缀,这意味着换账号时数据是否隔离,答案就在这几行拼接代码里。

内存缓存,追的是缓存实例的创建位置、过期策略、失效触发条件。这里最常见的坑是缓存与数据源不同步——写入数据库之后忘了清缓存,或者清了缓存但没清关联键。Agent 只要把"写"和"清"两处代码摆在一起,问题一眼就看出来。

服务端持久层,追的是模型定义、读写封装、事务边界、迁移脚本。迁移脚本这块要单独看目录,很多项目的表结构演进全在那里,光看模型定义看不出历史包袱。

三层追完之后,我会要求 Agent 输出一张数据流向表,列是"层 / 写入位置 / 读取位置 / 失效位置 / 备注"。这张表是整篇回答里信息密度最高的部分,新人拿着它基本能自己摸下去。

3.3 更新流程:先问是哪一种更新

前面提过这个词的歧义。我的处理是在提示词里写死四种解释,让 Agent 先选:

  • 客户端版本更新:版本检查、下载、校验、安装、强制更新判断。
  • 服务端发布:构建、打包、滚动发布、健康检查、回滚。
  • 数据迁移:迁移脚本的命名规则、执行顺序、幂等性、回滚脚本。
  • 配置热更新:配置来源、拉取时机、生效范围、降级策略。

选错解释的代价很大,所以这一步不允许跳过。选完之后,追法就明确了。

以客户端版本更新为例,关键节点是:版本号来源(配置文件还是构建时注入)、检查时机(启动、切前台、定时)、比较逻辑(语义化版本比较还是数值比较,这里经常有边界 bug)、下载与校验(有没有完整性校验)、强制更新判断(最低支持版本从哪来)、灰度开关(有没有按渠道或用户分组)。

数据迁移这块,重点看三件事:命名规则决定执行顺序、有没有幂等保护、有没有对应的回滚脚本。我见过最危险的情况是迁移脚本没有幂等保护,重跑一次就重复插入,而发布流程里恰好有个重试机制。这种问题,Agent 把两处代码并排摆出来,人一眼就能发现。

4. 实操:把 REA 跑起来

前面讲的是思路,这一节讲落地。代码我用 Python 写,模型调用抽象成一个chat方法,你换成自己那套服务即可,参数名对应调整就行。

4.1 索引构建:半小时能跑完的第一版

第一版不要追求完美,能跑就行。我的建议是先做文件清单、文本索引、符号表三样,调用关系和提交摘要放到第二轮补。

import os, re, json SKIP_DIRS = {".git", "node_modules", "dist", "build", "vendor", "__pycache__", ".venv"} CODE_EXT = {".py", ".js", ".ts", ".tsx", ".jsx", ".go", ".java", ".kt", ".rb", ".php"} def walk_repo(root): files = [] for dirpath, dirnames, filenames in os.walk(root): dirnames[:] = [d for d in dirnames if d not in SKIP_DIRS] for name in filenames: ext = os.path.splitext(name)[1] if ext in CODE_EXT: files.append(os.path.join(dirpath, name)) return files

这段看着平淡,但跳过目录这个集合是踩过坑才定下来的。早期我没排除构建产物,结果搜索"令牌"命中的全是压缩后的 bundle 文件,行号长得离谱,读进来毫无意义。另外vendor和.venv也要排,第三方库的实现会严重干扰判断——你问的是这个项目怎么做,不是那个库怎么做。

符号表我用了两种方式:优先走语法解析,失败回退正则。

DEF_PATTERN = re.compile( r"^\s*(?:async\s+)?(?:def|function|class|func)\s+([A-Za-z_][A-Za-z0-9_]*)", re.MULTILINE, ) def build_symbols(files): symbols = {} for path in files: try: text = open(path, encoding="utf-8", errors="ignore").read() except OSError: continue for m in DEF_PATTERN.finditer(text): name = m.group(1) line = text[:m.start()].count("\n") + 1 symbols.setdefault(name, []).append({"file": path, "line": line}) return symbols

正则版召回率高但精确度一般,会把注释里的示例代码也扫进来。所以在使用的时候,我让trace_symbol的返回值带上"置信度"标记,模型看到低置信度结果会自己去read_slice确认。这比在索引阶段死磕精确度划算得多,索引阶段的目标是快,精确度交给后续验证。

仓库速览的生成,我压到两三千字:顶层目录树两层、文件数统计、符号数量前二十的文件名、配置清单、最近一百条提交的标题。这份东西放进系统提示,模型第一轮就能判断"这是个前后端一体的项目"还是"纯前端",路径选择准很多。

4.2 工具实现:返回值格式比逻辑更重要

这五个工具的实现都不难,难的是返回什么格式。我调了很多次,最后定下来的格式是:结果 + 行号 + 上下文 + 提示。

def search_text(pattern, root=".", glob=None, limit=30): hits = [] regex = re.compile(pattern) for path in walk_repo(root): if glob and not path.endswith(glob): continue try: lines = open(path, encoding="utf-8", errors="ignore").read().splitlines() except OSError: continue for i, line in enumerate(lines, start=1): if regex.search(line): hits.append({ "file": path, "line": i, "text": line.strip()[:200], "context": lines[max(0, i-2):i+1], }) if len(hits) >= limit: return {"hits": hits, "truncated": True, "hint": "结果已截断,建议收紧正则或限定目录"} return {"hits": hits, "truncated": False}

三个细节值得说。第一,text截断到两百字符,太长的行会挤爆预算,而且模型也不需要完整长行。第二,truncated字段很重要,模型看到它就知道该收紧搜索而不是硬着头皮往下猜。第三,hint是我加的引导字段,用自然语言告诉模型下一步该干什么,比在系统提示里写一堆规则管用。

read_slice有个硬约束必须写死:

def read_slice(path, start, end): if end - start > 200: end = start + 200 lines = open(path, encoding="utf-8", errors="ignore").read().splitlines() body = "\n".join(f"{i:>5}| {lines[i-1]}" for i in range(start, min(end, len(lines)) + 1)) return {"file": path, "range": [start, end], "content": body}

两百行这个上限,我试过放到五百,结果模型经常在长篇内容里迷路,抓不住重点。压到两百之后,倒逼它先search_text定位再读,反而更准。行号前缀用竖线分隔,是我试过几种格式里模型引用最不容易出错的一种。

4.3 编排循环:三轮定框架,两轮补细节

循环结构本身很简单,难的是什么时候停。

def rea_loop(question, tools, chat, max_turns=10): messages = [ {"role": "system", "content": SYSTEM_PROMPT + REPO_OVERVIEW}, {"role": "user", "content": question}, ] evidence = [] for turn in range(max_turns): resp = chat(messages, tools=tools) if resp.tool_calls: for call in resp.tool_calls: result = dispatch(call) evidence.append({"call": call.name, "args": call.args, "result": result}) messages.append({"role": "tool", "content": json.dumps(result, ensure_ascii=False)}) continue # 无工具调用,进入反思 messages.append({"role": "assistant", "content": resp.content}) if turn >= 3 and enough_evidence(evidence): break return resp.content, evidence

真正起作用的是enough_evidence这个判断。我的规则是:三条流程问题,至少要覆盖三个不同目录、五个以上不同文件、十个以上精确行号引用,且每个关键节点有两处证据。不满足就再来一轮,但不超过十轮。超过十轮基本说明问题本身有歧义,该回去问人了。

提示词这块,系统提示里我固定写四条铁律:

一、所有文件路径必须来自工具返回,不得自行拼写。 二、每条结论至少两处证据,格式为路径:起始行-结束行,写不出就标"待确认"。 三、先判断问题涉及哪一层(客户端/服务端/构建流程),判断不清先列出候选并说明理由。 四、不要复述行业通用做法,只描述本仓库的实际实现;找不到证据就说找不到。

第三条和第四条是效果最明显的。第三条解决答偏,第四条解决那种"通顺但空洞"的回答。加进去之后,回答里"通常会""一般来说"这类词的频率断崖式下降。

反思轮的提示词我单独写了一段:让模型列出"为了确认结论,还缺哪三处证据",然后针对这三处再调工具。这一轮经常能补上前面漏掉的失效处理或者配置来源,性价比很高。

4.4 输出结构:表格是给新人看的,证据是给自己看的

最终输出我定了一个四段结构:一句话结论、流程节点表、关键代码证据、风险提示。

流程节点表长这样:

阶段触发位置处理位置证据
凭证提交登录表单组件请求封装层统一加签路径A:45-62
服务端校验路由注册处鉴权中间件路径B:88-121
令牌签发中间件内调用令牌工具类路径C:12-40
令牌存放拦截器写入本地存储封装路径D:30-58
失效处理状态码拦截跳转逻辑路径E:70-95

这张表的价值在于它是可验证的。新人拿到表,逐个点开行号看,对不上就说明 Agent 错了。这比一段流畅的散文强太多。

风险提示那一段,我要求写具体的,比如"令牌刷新逻辑只在前端拦截器里,服务端未见刷新接口,可能存在过期后强制重登录的情况",而不是"建议加强安全性"这种空话。

5. 常见问题与排查实录

这部分全是踩坑换来的,按出现频率排。

5.1 动态注册导致调用链断掉

这是最头疼的问题。装饰器注册路由、依赖注入容器、配置驱动加载、字符串反射——这几种写法都会让静态文本搜索断链。你搜函数名,只能搜到定义,搜不到它在哪被挂上去。

我的应对是三招并用。第一招,搜注册表:找register、bind、route这类词,很多时候注册表是集中写的,找到表就等于找到全部。第二招,搜字符串字面量:反射调用一定会有字符串形式的类名或方法名,用search_text精确搜这个名字,往往能定位到配置文件。第三招,搜入口文件:主入口里通常有初始化逻辑,从那儿往下读两三层,注册过程就露出来了。

这三招里第二招命中率最高,但前提是你得先知道那个字符串长什么样。所以顺序上我会让 Agent 先做第一招和第三招建立整体认知,再用第二招补精确位置。

5.2 上下文超限与信息蒸发

表现很典型:前几轮明明读到了关键代码,最后一轮结论里却没提。原因是历史被压缩时把关键信息压掉了。

我的修法是"关键证据提前固化"。每轮结束时,让模型用一句话把本轮确认的事实写进一个独立的facts列表,格式是"事实 + 证据位置"。这个列表不进压缩池,全程保留。后面所有推理都从facts里取,不从历史对话里翻。改完之后,关键信息丢失的情况基本没有了。

另一个小技巧:facts列表超过十五条就做一次归并,把同一文件的多条合成一条,只留位置和一句摘要。这样既控制长度,又不丢线索。

5.3 幻觉路径与证据校验

即便写了"路径必须来自工具返回",还是会有漏网。我在输出前加了一个机械校验环节:把最终回答里所有路径:行号形式的引用抽出来,逐个检查文件是否存在、行号是否在文件范围内、该行附近是否真有关键词命中。不通过的引用直接标红,让模型重写那一段。

这一步是纯代码实现的,不需要模型参与,成本极低但效果很好。实测能拦掉大部分凭空生成的路径。行号偏移也归它管——有时候文件在索引之后改过,行号整体位移,校验会发现对不上,然后触发重新读取。

5.4 问题速查表

现象可能原因排查动作
反复调同一个工具结果不满足预期,模型在重试检查返回是否被截断,放宽 limit
只读不写结论缺"够了"的判定信号补足够的证据门槛,或加轮次提醒
答成通用行业方案系统提示约束不够硬加"只描述本仓库实现"的强约束
流程缺一环漏了横切逻辑用字段名而不是功能名搜
引用路径不存在自拼路径开输出校验环节
行号对不上索引后文件被改重新校验,必要时重建索引
同名函数混淆文本匹配假阳性返回值带置信度,强制二次验证

一个额外的经验:把问题拆成两问效果更好。先问"登录流程涉及哪些文件",再问"这几个文件里的登录流程是怎样的"。一步到位反而容易浅。这可能跟模型在长链路推理上的特性有关,先建立地图再走路线,稳得多。

6. 评测:怎么判断它真的讲清楚了

没有评测,这套东西就是玄学。我的做法不算复杂,但够用。

6.1 评测集怎么造

我挑了五个不同规模的项目,每个项目手工标注二十个问题,覆盖三条流程,每个问题标一个黄金文件集合(三到八个文件)。评测指标就两个:文件召回率(Agent 实际读到的文件里,覆盖了多少黄金文件)和引用正确率(输出里的路径行号有多少经校验是真的)。

召回率低于七成,说明检索策略有问题;引用正确率低于九成五,说明约束不够硬。这两个数字比人工读回答靠谱,而且能自动化跑。

还有一个人工环节:随机抽五条回答,让不熟悉这个项目的同学照着回答去改一个相关的 bug,改得动就算讲清楚了。这个测试很残酷但很真实——能指导操作的说明才是好说明。

6.2 我自己的一条经验

不要用"回答看起来对不对"来调参。我早期就是这么干的,结果陷进局部最优——调整了七八轮,回答读起来越来越顺,但召回率没动。后来改成只看数字,改一处测一次,进度快得多。

另外,评测集一定要包含答不出来的问题。我在里面故意放了几个"这个项目根本没有的功能",看 Agent 会不会硬编一个答案出来。这个测试特别能暴露问题,早期版本有一半是硬编的,加了几轮约束之后才老实说"未找到相关实现"。

最后分享一个我觉得最值钱的观察:这套东西真正提升的不是"写文档的速度",而是代码审查时的提问质量。用熟了之后,我自己看陌生仓库会下意识地找写入点和读取点是否一致、横切逻辑挂在哪,这些问题比让 Agent 直接给答案更有价值。工具改变的是提问方式,这个收获比自动化本身大。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询