AI Coding Agent:从需求到代码修改的完整过程
AI Coding Agent:从需求到代码修改的完整过程
这篇笔记用一个具体例子说明:
用户提出需求
-> AI coding 工具接收
-> Agent 检索项目上下文
-> 模型基于上下文推理
-> 定位文件、变量、行号
-> 生成 patch
-> 修改代码
-> 运行验证
-> 输出结论
先强调一个关键点:
当前项目上下文不是在一次任务中“后训练进模型权重”的。它是在推理阶段由 Agent 检索、筛选、压缩后放进模型上下文窗口的。
更准确地说:
预训练/后训练:让模型学会如何理解代码、如何使用上下文、如何按工具反馈工作。
推理时上下文注入:把当前项目的真实文件片段、搜索结果、报错、diff 放进 prompt,让模型基于这些证据推理。
所以在 AI coding 中:
模型权重通常不变。
变化的是每一轮 prompt 里的上下文。
1. 总览图
这个流程有效,不是因为模型一次性知道整个项目,而是因为 Agent 不断把“与当前任务最相关的证据”放进模型上下文。
2. 示例需求
用户输入:
登录失败时页面没有错误提示,请修复。
这个 prompt 进入 AI coding 工具后,会被转成一个工程任务:
目标:登录失败时展示用户可见的错误信息。
需要找:
1. 登录表单组件
2. 提交处理函数
3. API 调用和错误分支
4. UI 中是否已有 error state
5. 相关测试是否存在
3. Agent 如何把需求转成检索动作
模型不会凭空知道代码在哪里。Agent 会先用工具查证。
可能的检索动作:
rg "login|Login|signIn|auth" src tests
rg "setError|errorMessage|toast|role=\"alert\"" src tests
rg "useLogin|loginUser|authApi" src
假设搜索结果返回:
src/components/LoginForm.tsx:12:function LoginForm()
src/components/LoginForm.tsx:28:const [errorMessage, setErrorMessage] = useState("")
src/components/LoginForm.tsx:41:await authApi.login(email, password)
src/api/auth.ts:8:export async function login(email, password)
tests/LoginForm.test.tsx:15:it("submits credentials")
这一步的关键是:
行号不是模型猜出来的。
行号来自工具对真实文件的搜索和读取结果。
4. 上下文如何进入模型
Agent 会读取相关文件片段,并组装成模型可读的上下文包。
例如:
用户需求:
登录失败时页面没有错误提示,请修复。
相关搜索结果:
- src/components/LoginForm.tsx:28 errorMessage state
- src/components/LoginForm.tsx:41 authApi.login
- tests/LoginForm.test.tsx 登录测试
文件片段:
src/components/LoginForm.tsx:24-48
24 export function LoginForm() {
25 const [email, setEmail] = useState("")
26 const [password, setPassword] = useState("")
27 const [loading, setLoading] = useState(false)
28 const [errorMessage, setErrorMessage] = useState("")
29
30 async function handleSubmit(event) {
31 event.preventDefault()
32 setLoading(true)
33
34 try {
35 await authApi.login(email, password)
36 navigate("/dashboard")
37 } catch (error) {
38 console.error(error)
39 } finally {
40 setLoading(false)
41 }
42 }
43
44 return (
45 <form onSubmit={handleSubmit}>
46 {errorMessage && <p className="error">{errorMessage}</p>}
47 ...
48 </form>
注意:这些内容是推理时 prompt 的一部分,不是训练数据写进权重。
模型此时看到的是:
需求 + 搜索结果 + 文件路径 + 行号 + 真实代码片段
然后才开始推理。
5. 模型如何推理
模型基于上下文会形成因果链:
1. LoginForm 已经有 errorMessage 状态。
2. UI 第 46 行已经会展示 errorMessage。
3. 但 catch 分支第 37-39 行只 console.error,没有 setErrorMessage。
4. 因此登录失败时 UI 状态没有变化。
5. 最小修复是在 catch 分支设置 errorMessage。
这不是模型“记住项目”,而是模型对上下文片段做局部推理。
6. 如何定位到哪一行、哪些变量
定位通常靠三类信息共同完成。
1. 工具给出的行号
搜索和读取文件会返回路径和行号:
src/components/LoginForm.tsx:28
src/components/LoginForm.tsx:37
src/components/LoginForm.tsx:46
模型把这些行号作为证据引用。
2. 代码结构和变量关系
模型看到:
const [errorMessage, setErrorMessage] = useState("")
它会推断:
errorMessage 是 UI 显示状态。
setErrorMessage 是更新错误信息的 setter。
看到:
catch (error) {
console.error(error)
}
它会推断:
错误发生时没有调用 setErrorMessage。
看到:
{errorMessage && <p className="error">{errorMessage}</p>}
它会推断:
只要设置 errorMessage,页面就会显示错误。
3. 修改 anchor
真正应用 patch 时,Agent 不应只依赖“第 37 行”。因为文件可能变化,行号会漂移。
更稳的方式是用 anchor 文本:
} catch (error) {
console.error(error)
} finally {
然后替换成:
} catch (error) {
console.error(error)
setErrorMessage("登录失败,请检查邮箱和密码。")
} finally {
所以精确定位不是单点能力,而是:
工具行号 + 代码结构理解 + anchor 文本 patch
7. 修改前后代码
修改前
async function handleSubmit(event) {
event.preventDefault()
setLoading(true)
try {
await authApi.login(email, password)
navigate("/dashboard")
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
修改后
async function handleSubmit(event) {
event.preventDefault()
setLoading(true)
setErrorMessage("")
try {
await authApi.login(email, password)
navigate("/dashboard")
} catch (error) {
console.error(error)
setErrorMessage("登录失败,请检查邮箱和密码。")
} finally {
setLoading(false)
}
}
这里有两个修改点:
1. 提交开始时清空旧错误:setErrorMessage("")
2. 登录失败时设置新错误:setErrorMessage("登录失败,请检查邮箱和密码。")
为什么要清空旧错误?
如果用户第一次失败,页面显示错误;第二次重新提交时,旧错误不应一直残留。
8. 这个 patch 是如何生成的
模型生成的不是“随便写一段代码”,而是基于上下文做最小编辑:
目标变量:errorMessage / setErrorMessage
目标函数:handleSubmit
目标分支:catch
辅助位置:try 前清空旧错误
不改动:authApi.login、navigate、form 结构
伪代码:
context = retrieve_relevant_context(user_request)
analysis = model.reason(
request=user_request,
files=context.files,
search_results=context.search_results,
)
edit_plan = {
"file": "src/components/LoginForm.tsx",
"anchors": [
"setLoading(true)",
"} catch (error) {\n console.error(error)\n } finally {",
],
"changes": [
"insert setErrorMessage(\"\") after setLoading(true)",
"insert setErrorMessage(\"登录失败,请检查邮箱和密码。\") after console.error(error)",
],
}
patch = model.generate_patch(edit_plan, context)
agent.apply_patch(patch)
9. 验证过程
修改后 Agent 会运行测试:
npm test LoginForm
如果测试失败,比如:
TestingLibraryElementError: Unable to find role="alert"
Agent 会再次读取 UI 片段:
{errorMessage && <p className="error">{errorMessage}</p>}
模型会推断:
测试希望错误提示具备 role="alert"。
当前 p 标签只有 className,没有 role。
于是二次修改:
{errorMessage && (
<p className="error" role="alert">
{errorMessage}
</p>
)}
这就是闭环:
修改 -> 测试 -> 报错 -> 补上下文 -> 再推理 -> 再修改
10. Sequence Diagram
11. 大模型和 Agent 分别负责什么
大模型负责
理解自然语言需求
解释代码片段
建立因果链
识别变量和函数关系
判断最小修改点
生成 patch
阅读测试失败信息
总结结果
Agent 负责
搜索文件
读取文件
管理上下文窗口
提供路径和行号
应用 patch
运行命令
收集报错
循环验证
控制任务状态
一句话:
模型负责推理。
Agent 负责取证、执行和验证。
12. 为什么它能很好地工作
它能工作,不是因为模型一次性知道全部代码,而是因为形成了工程闭环:
真实代码上下文
+ 模型代码推理能力
+ 工具精确定位
+ patch 小步修改
+ 测试硬反馈
= 相对可靠的 AI coding 过程
其中最关键的是上下文注入:
没有上下文,模型只能猜。
有上下文,模型可以基于真实代码推理。
有测试反馈,模型可以从错误中修正。
13. 再次澄清:上下文和后训练的关系
要区分两个概念:
后训练阶段
后训练发生在模型发布或使用前:
SFT / DPO / RLHF / GRPO / agent trajectory training
它改变模型参数,让模型学会:
如何听指令
如何看代码
如何调用工具
如何根据报错修复
如何输出 patch
推理阶段上下文
AI coding 时,当前项目文件片段是推理输入:
用户需求 + 文件片段 + 搜索结果 + 报错 + diff
它不改变模型参数,只改变当前这一次回答的依据。
所以正确理解是:
后训练教会模型“如何使用上下文”。
Agent 在推理时把“当前项目上下文”放进去。
模型基于这些上下文进行代码推理和 patch 生成。
14. 最小伪代码
def ai_coding_task(user_prompt):
task = model.parse_task(user_prompt)
search_queries = model.plan_search(task)
search_results = tools.rg(search_queries)
files = tools.read_relevant_files(search_results)
context_pack = build_context_pack(
user_prompt=user_prompt,
search_results=search_results,
files=files,
)
diagnosis = model.reason(context_pack)
edit_plan = model.plan_edit(diagnosis)
patch = model.generate_patch(edit_plan, context_pack)
tools.apply_patch(patch)
result = tools.run_tests(edit_plan.related_tests)
while not result.ok:
failure_context = build_context_pack(
user_prompt=user_prompt,
previous_patch=patch,
test_output=result.output,
files=tools.read_relevant_files(result.related_files),
)
diagnosis = model.reason(failure_context)
patch = model.generate_patch(diagnosis, failure_context)
tools.apply_patch(patch)
result = tools.run_tests(edit_plan.related_tests)
return summarize_changes_and_verification()
这个伪代码就是 AI coding agent 的核心:
检索真实上下文 -> 模型推理 -> 修改 -> 验证 -> 失败再循环。
更多推荐





所有评论(0)