大模型应用需要把自然语言任务转化为可检查的输入、输出和执行过程。Prompt 工程 负责描述任务与约束,上下文工程 负责选择和组织模型能够看到的信息;二者共同影响模型的判断,但系统可靠性还需要类型校验、工具执行和测试反馈。

以代码审查为例,模型需要知道审查哪些文件、使用哪些规则、项目依赖什么版本,以及如何表示发现的问题。缺少这些信息时,即使回答流畅,也可能引用不存在的 API、误判代码行为,或者生成下游程序无法读取的结果。

课程定位

本系列八章对应整门课程的 AI 应用单元。课程整体还包括服务端开发、数据库与分布式系统:服务端关注状态、并发、通信、事务和缓存;数据库部分关注存储、索引、恢复与不同数据模型;分布式部分关注容器、集群和批流处理。AI 助手最终仍要运行在这些应用基础设施上。

电子书店贯穿这些内容。例如“推荐算法相关的书并购买”需要先查当前商品与库存,再读取促销规则,最后按权限处理订单。Prompt 描述目标,MCP/Tool 取得或修改真实数据,RAG 提供私有资料,Skill 组织复用方法,Agent 协调步骤,Graph 与 Harness 控制执行和验证。

AI 生成的代码也需要明确架构要求。只要求“做一个书店前端”,可能得到功能集中在单个 JavaScript 文件中的实现;若要求区分页面、组件、接口访问和状态管理,还需检查这些职责是否真的分开。能运行是验收的一部分,理解生成代码的依赖、状态和修改范围同样重要。

生成机制

自回归语言模型根据已有 Token 预测下一个 Token。对于序列 w1,…,wnw_1,\ldots,w_n,其概率可以分解为:

P(w1:n)=∏t=1nP(wt∣w<t).P(w_{1:n})=\prod_{t=1}^{n}P(w_t\mid w_{<t}).

生成的早期内容会成为后续生成的条件。若模型先写错了一个方法名,后面可能继续沿用该名称,并围绕它生成相关类和调用。这种现象称为 错误级联。例如把真实方法 getUserInformation() 写成 getUserInfomation(),会使调用、测试和类型定义一起偏离项目实际接口。

Transformer 使用注意力建立上下文中不同位置的关联。缩放点积注意力为:

Attention⁡(Q,K,V)=softmax⁡(QKTdk)V.\operatorname{Attention}(Q,K,V) =\operatorname{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V.

QQ、KK、VV 分别是查询、键和值,dkd_k 是键向量的维数。注意力帮助模型关联变量声明、函数定义和引用,但不等同于编译器的符号解析。模型仍可能忽略远处的约束,或者把文本中一个合理的名称误当成真实接口。

生成过程本身没有“编译通过”的保证。应用应把真实接口、类型和测试结果作为可核验条件,并允许后续修改已经生成的内容。

温度控制对候选 Token 的采样。设模型输出 logits 为 ziz_i,在 T>0T>0 时可以表示为:

pi(T)=exp⁡(zi/T)∑jexp⁡(zj/T).p_i(T)=\frac{\exp(z_i/T)}{\sum_j\exp(z_j/T)}.

较小的 TT 使高分候选更占优势,较大的 TT 使分布更平缓。T=1T=1 表示使用原来的 softmax 分布,不表示从全部 Token 均匀随机选择;T=0T=0 在接口中通常表示贪心选择或相应近似规则,而不是直接代入上式。

这可以与“利用已有较好方案”和“探索其他方案”类比:总选同一家已知餐馆比较稳定,尝试其他餐馆则可能找到新选择。采样增加多样性,但不会保证找到全局最优,也不能单靠温度消除事实错误。代码验证通常偏重稳定,多候选搜索可以适度增加多样性。

同一个问题在已有对话中再次提出时,上下文也已经变化,因此回答变化未必只由温度造成。temperature=0 仍可能产生错误,也不保证在不同服务实现和运行环境中获得逐字相同的结果。

闭式计算与迭代方法可以帮助理解这种权衡。例如已知方程形式时可以直接代入求根公式,Newton 方法则用 xt+1=xt−f(xt)/f′(xt)x_{t+1}=x_t-f(x_t)/f'(x_t) 逐步修正近似解,结果受函数与初值等条件影响。模型训练也常使用迭代优化,但推理时调整 temperature 只是改变采样分布,不会重新训练权重,也不等同于对损失函数执行一次跳出局部最优的优化。

Prompt 契约

一个完整的 Prompt 应包含 角色、任务、约束。角色限定职责和分析视角,任务描述操作对象与目标,约束规定允许的修改、输出形式和失败行为。

要素 代码审查中的含义 可检查的表达
角色 以安全和性能为审查范围 检查 SQL 注入、资源泄漏、并发问题
任务 分析给定文件或差异 逐项给出规则编号、位置和修复建议
约束 限制结论与输出 只报告有代码证据的问题,返回约定 JSON

“代码要优雅”“性能要很好”等要求缺少验收标准。可以改成“不改变公开方法签名”“避免在循环中执行重复查询”“圈复杂度不超过约定阈值”等具体条件。角色描述只能引导模型,不能赋予数据库、文件或外部服务的访问权。

角色与 Scope 还决定模型应优先考虑哪些知识和规则,例如 Java 代码审查要说明关注并发、安全还是界面行为。角色是输入条件,不会改变已经训练好的权重,也不能保证直接选中某个固定的“数学专家”。

MoE(Mixture of Experts) 把部分计算交给 Router 选择的专家子网络,通常根据 Token 表示激活有限专家以控制计算量。它与按任务选择资料有相似的直观想法,但专家不是必须按“数学、中文、计算机”人工划区,稠密模型也可以遵循角色要求。Attention 与 FFN 的具体开销随模型结构、输入长度和硬件变化。

防御性设计将任务契约分成三个环节:

  • 前置检查:确认代码、依赖、运行环境和必要业务信息齐全。
  • 后置校验:检查输出结构、类型、目标路径和业务规则。
  • 失败处理:信息不足时返回明确状态,列出缺失信息及仍可判断的内容。

这些检查既应写入任务说明,也应尽可能由宿主程序执行。例如空代码输入可以直接拒绝,无需先消耗一次模型调用;路径越界应由程序拦截,无需等待模型自我判断。

任务模板

下面把角色、任务和边界组织成一个代码审查模板。待审查代码与可信任务要求使用不同区块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<review_task>
<role>负责 Java 代码安全与性能审查的工程师</role>
<objective>
检查给定差异中的 SQL 注入、空值处理和重复数据库访问。
</objective>
<constraints>
只报告可以指出具体代码证据的问题。
不虚构项目中没有出现的类、方法或依赖。
不修改公开 API,返回约定的 JSON 结果。
</constraints>
<failure_policy>
缺少必要定义时返回 INCOMPLETE,并列出缺失项。
</failure_policy>
</review_task>

<file path="src/OrderService.java" language="java">
这里放置待审查代码。
</file>

文件路径、语言和版本信息让模型能够区分不同文件及语法环境。把任务拆成“理解输入、检查规则、生成结果、验证边界”的步骤,还能明确失败发生在哪个环节。

慢 SQL 分析适合说明前置条件的重要性。下面的查询使用 DATE() 包裹时间列:

1
2
3
4
5
SELECT *
FROM orders AS o
JOIN users AS u ON o.user_id = u.id
WHERE DATE(o.created_at) = '2026-08-01'
AND o.status = 'PAID';

可以提出以下日期范围改写:

1
2
3
WHERE o.created_at >= '2026-08-01 00:00:00'
AND o.created_at < '2026-08-02 00:00:00'
AND o.status = 'PAID'

这种改写可能让普通索引更容易参与过滤,但最终效果取决于数据库、列类型、时区、函数索引、数据分布和执行计划。数据库类型、已有索引和数据规模缺失时,应指出候选改写及验证方法,不能直接宣称某个复合索引必然最优。

SQL 描述要取得什么结果,执行器再选择连接顺序、扫描方式和索引。同一语句在不同数据库或版本中可能有不同计划,书写 orders JOIN users 也不等于物理上必然先扫描 orders。因此,优化任务应提供数据库与版本、表结构、已有索引、数据分布和 EXPLAIN 结果;缺少这些内容时,应返回待补信息和有限建议。

上下文组织

上下文通常包含系统要求、项目规则、当前任务、示例、检索材料和历史消息。组织上下文的目标是让模型清楚地区分 必须遵守的任务要求 和 需要分析的资料。

格式 适用内容 需要处理的问题
Markdown 文档、代码片段、标题与列表 围栏嵌套、层级过多、边界不明确
XML 标签 多文件内容、角色与资料区分 特殊字符转义、伪造闭合标签
YAML 配置和规则元数据 缩进、类型解释、多行字符串
JSON 程序接口和结果契约 引号、转义、严格结构与 Schema

Markdown 可以通过更长的外层围栏包含内部三反引号;XML 可以用 path 和 language 属性表达文件信息;YAML 适合表示参数和规则。格式选择应依据输入内容和解析方式,而不是假设某一种格式天然安全。

输入组织与输出序列化是两个独立决定。程序可以用 XML 包装多文件输入,同时要求模型返回 JSON;普通聊天界面则不必让用户手写 XML。YAML 的空白与缩进是正式语法的一部分,需要正确解析;不能从它更省字符或人看起来更简洁,推出机器无法可靠处理。

多文件任务还需要区分依赖关系。例如先提供 Order 的类型、公开接口和调用者,再提供待修改的 OrderService,通常比无序粘贴全部文件更容易理解。检索时可以保留 AST 中的类、方法签名与相关调用,省略与当前目标无关的实现。

注意力分布

上下文窗口限制可输入的 Token 数,但窗口较大不意味着模型能同等有效地利用每个位置的信息。Lost in the Middle 指部分长上下文任务中,相关信息放在中间位置时,模型表现比放在开头或结尾更差。

上下文位置与信息利用率

图示用于说明位置效应,其中比例不应解释为所有模型固定不变的分界。设计上下文时可以在开头说明核心约束,在任务末尾简要重申最重要的验收条件;检索材料则按相关性组织。重复要求应保持简短,避免与原规则冲突。

对于长历史,应区分近期工作信息和已经确认的长期事实。把所有旧方案、失败补丁和无关日志持续加入上下文,会增加噪声,并挤占当前任务需要的资料。

前缀缓存

自回归生成中,已经处理的 Token 在各层产生 K、V 表示。KV Cache 保存这些中间计算,后续生成可以复用,不必重新计算已有前缀。它保存的是模型内部张量,不是向量知识库,也不是在 Prompt 后追加的一段文本。

支持跨请求前缀复用的推理服务,还可以复用多个请求共有的前部内容。因此,反复执行同类任务时,可以把稳定的角色、规则、工具说明放在前面,把每次变化的问题和文件放在后面。

1
2
固定前缀:代码审查角色、允许规则、输出 Schema。
变化后缀:本次待审查的文件、差异和用户目标。

前缀缓存依赖实际 Token 序列及相应模型配置,不能把“意思相近”直接当成命中。随意改写固定模板、打乱工具顺序或在开头插入变化字段,都可能降低可复用长度。能否跨请求缓存、保存多久以及如何计费由具体服务决定。命中缓存的前缀仍属于逻辑输入,减少重复计算不等于扩大模型的上下文窗口。

缓存中间计算不等于缓存最终答案。共用审查规则的两个任务仍需分别检查各自代码;相同库存问题也可能因业务状态变化得到不同结果。

窗口管理

一次请求的预算需要同时覆盖System Prompt、工具定义、历史、检索文本和预留输出:

Bsystem+Btools+Bhistory+Bretrieval+Boutput≤Bwindow.B_{\mathrm{system}}+B_{\mathrm{tools}}+B_{\mathrm{history}} +B_{\mathrm{retrieval}}+B_{\mathrm{output}}\le B_{\mathrm{window}}.

剪枝 删除无关内容,压缩 把较长资料转成保留关键事实的摘要,滑动窗口 控制近期对话的长度。三者可以结合,但摘要应保留目标、限制、已确认事实、失败原因和后续行动,不能只留下“已讨论过某问题”这样的概括。

上下文污染发生在错误内容被后续轮次当作事实使用时。处理方式是标明错误、替换已过时结果,并保留修正依据。必要时重置会话或重新装配上下文;不必在每次失败后丢弃全部有效历史。完整日志和原始资料应保存在可检索位置,以便摘要不够时回溯。

界面里看到的最后一句问题通常不是完整 API 输入。宿主还可能附加 System Prompt、工具 Schema、检索片段、历史工具结果与摘要,预算需要以实际发送内容为准。只数用户输入字数,无法解释整个请求的 Token 用量。

三种缩减方式也有不同语义:AST 剪枝可以保留方法签名与说明、暂时省略方法体;摘要用新的短文本概括较长内容;滑动窗口保留限定轮次或时间范围内的原记录。需要分析具体实现时,只有签名通常不够,应重新读取相关方法体。摘要也可能失真,不能当成未经改动的原文。

结构化输出

自由文本适合解释,但程序接口通常需要明确字段。代码审查结果应包含文件、行号、严重程度、规则编号、建议和可选补丁;PR 总结应包含变更范围、行为影响、风险和实际测试记录。

结构化输出可以分为几种约束强度:

方式 实际作用 局限
Prompt 要求 JSON 引导输出格式 仍可能夹带说明或围栏
Few-Shot 示例 示范字段与取值 示例错误可能被模仿
JSON Schema 描述类型与结构 需要确认生成接口支持的子集
受限解码 在生成时限制合法形式 不保证字段内容正确
运行时校验 收到结果后检查契约 失败时仍需修正或终止

GBNF 等文法可以描述允许生成的结构,语法状态与 Token 屏蔽共同约束输出。Pydantic 校验则发生在结果返回之后,两者作用阶段不同。

json.loads() 只完成 JSON 解析,不检查业务含义,也不会自动构造经过类型校验的对象。即使格式完全符合 Schema,审查结论仍可能错误,文件路径也可能不属于当前项目。

格式正确、类型正确、业务正确 是三个不同层次。可靠接口需要逐层验证。

类型校验

Pydantic 可以把结果契约写成 Python 模型。字段描述既用于说明数据含义,也可以导出到 JSON Schema,帮助模型理解要求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from enum import Enum
from pydantic import BaseModel, ConfigDict, Field


class Severity(str, Enum):
"""限定审查问题的严重级别。"""

CRITICAL = "CRITICAL"
WARNING = "WARNING"
INFO = "INFO"


class CodeIssue(BaseModel):
"""表示一个有明确代码位置和修复建议的审查问题。"""

model_config = ConfigDict(extra="forbid")

file_path: str = Field(description="相对项目根目录的文件路径")
line_number: int = Field(
ge=1,
strict=True,
description="问题所在的一基行号",
)
severity: Severity
rule_id: str = Field(description="审查规则编号,例如 SEC-001")
suggestion: str = Field(description="具体修复建议")
diff_patch: str | None = Field(
default=None,
description="可选的 Unified Diff 片段",
)


class ReviewReport(BaseModel):
"""统一表达审查摘要、发现的问题及缺失信息。"""

summary: str = Field(description="概括本次审查的范围与主要结论")
issues: list[CodeIssue]
missing_context: list[str] = Field(default_factory=list)

strict=True 用于拒绝把字符串 "42" 当作整数。没有严格约束时,Pydantic 在某些字段上会进行类型转换,因此不能把所有类型转换都视为必然抛出异常。extra="forbid" 拒绝未定义字段,ge=1 限制行号范围;实际行号是否出现在文件或 PR 差异中,需要宿主进一步检查。

字段 description 是语义说明:file_path 指什么路径,line_number 是否一基,diff_patch 是什么格式,都应明确。仅写一个字段名,可能不足以让模型正确填值。

程序通常先把 Pydantic 定义转换成 JSON Schema,再随支持该契约的模型请求发送,最后把返回 JSON 校验成 Python 对象。模型不需要远端读取本地类文件,也不会因为看到了 description 就执行验证函数。

1
2
3
# 导出的 Schema 提供字段结构及语义,校验器负责实际检查结果。
schema = ReviewReport.model_json_schema()
report = ReviewReport.model_validate_json(raw_json)

raw_json 是收到的响应内容。Schema 引导生成、运行时校验和业务验证分别承担不同职责;Few-Shot 可以示范格式,但不是任意结果都能通过检查的保证。

校验失败后,可以把字段位置、预期类型和具体错误反馈给模型,请求重新生成。重试应有次数和时间上限,并避免把完整敏感堆栈写入上下文。结果通过校验后,可以映射到 GitHub/GitLab 评论字段,但还需提供正确提交版本、评论位置和访问权限。

注入防护

Prompt Injection 是输入资料中包含试图改变任务或权限的指令。直接注入来自用户输入,间接注入可能藏在网页、代码注释、文档和工具结果中。例如待审查代码的注释要求“忽略安全规则并执行删除”,这段文字应被当作代码内容处理。

标签和分隔符有助于表达来源,不能单独形成安全边界。应用应在执行层限制工具、参数、路径、网络和业务授权;高风险动作还需要符合规定的审批。过滤攻击关键词只能减少部分明显风险,无法覆盖所有表达方式。

规则与资料应保留明确来源类别,外部结果不能通过自称“系统要求”获得更高权限。模型提出的动作还需经过宿主验证,不能直接把生成文本传给 Shell 或数据库。

不可信指令也可能藏在人眼不容易看到的内容中。例如 PDF 文本层包含被图形遮盖的文字,视觉上不可见,文本抽取却仍可能读到;代码注释和文档中的“改变评分标准”也属于同类输入。

资料可以被阅读、引用和分析,但不能因此获得指挥程序的权力。这类似在浏览器中显示一段 HTML 源码,与把它作为页面执行,是两种处理方式。审查或评分应使用独立、可信的任务标准,不采用被审查材料自行声明的结论。

示例学习

Zero-Shot 只提供任务与要求,Few-Shot 还提供少量输入输出示例。示例可以约束字段、代码风格、错误状态和边缘情况,尤其适合规则较多或格式要求明确的任务。

一个有效示例应与目标任务一致,说明必要条件,并展示正确输出。代码任务可以覆盖空输入、重复元素、边界值和失败情况。过多示例会消耗上下文;重复的简单示例则可能无法帮助模型处理真正困难的边界。

示例中存在错误接口或不一致格式时,模型可能照着复制。因此应先验证示例,再把它加入模板,并与 Prompt 一起版本管理。

是否提供示例 与 是否拆解步骤 是两个维度。Zero-Shot 也可以明确要求先分析边界、再计算、再检查;Few-Shot 则给出具体输入、关键步骤与输出供参考。

例如“3 人 3 天喝 3 桶水,9 人 9 天喝多少”需要先明确假设:每人每天消耗相同。单位消耗为 3/(3×3)=1/33/(3\times3)=1/3 桶/人/天,总量为 9×9×1/3=279\times9\times1/3=27 桶。示例应展示这个数量关系,而不只让模型模仿“3 对应 9”的数字替换。人数、书本数和公交站数也不能未经语义判断直接相加。

推理方法

Chain-of-Thought(CoT) 通过中间推导组织复杂问题。若 xx 是问题、zz 是中间步骤、yy 是答案,可以把答案概率写为:

P(y∣x)=∑zP(y∣x,z)P(z∣x).P(y\mid x)=\sum_z P(y\mid x,z)P(z\mid x).

Zero-Shot CoT 通过“逐步分析”等要求引导分解;Few-Shot CoT 提供问题、关键推导与答案的示例。代码任务中,关键步骤可以包括识别约束、选择数据结构、分析复杂度和验证边界。

例如寻找两个数之和时,可以先解释哈希表保存已见值,再判断当前值的补数是否存在,并说明重复元素和无解情况。这样的推导比直接给代码更容易审核,但推导文本仍可能有错。

应用通常需要 可核验的关键步骤与结果,无需依赖模型完整的内部推理。对于已有推理能力的模型,应给出明确目标和验证要求,再用运行结果检查答案。

多路径搜索

Self-Consistency 对同一问题生成多个候选,再聚合答案。算术任务可以对归一化数值投票;代码任务更适合按测试表现筛选,因为不同代码文本可能具有相同行为,同样的代码结构也可能包含共同错误。

奇数候选可以减少二元投票的平票机会,但不保证一定形成多数:三个候选也可能分别给出三个不同答案。聚合规则需要明确如何归一化答案、处理并列与无法验证的结果;不能把“一致”自动解释成“正确”。

Least-to-Most 将复杂问题拆成逐步依赖的子问题,先求解较简单部分,再把结果用于后续步骤。每个子问题应有输入、输出和验收条件,防止前一步错误持续传播。

Tree-of-Thoughts(ToT) 把候选中间步骤组织成搜索树,通过扩展、评估、剪枝和回退探索不同路线。宽度、深度和评分器决定成本;代码搜索可以用编译和测试评分,模型自评只作为辅助。

任务分解树与候选搜索树需要区分。把任务拆成读取、修改和测试等子任务时,可能必须完成所有依赖步骤;探索几个不同解法时,则可以只保留通过验证的一条路线。到达叶子仅表示某条路径结束,是否成功仍由验收条件判断。

方法 主要用途 额外成本
CoT 梳理单条推导路线 更长输出
Self-Consistency 比较多个答案候选 多次生成与聚合
Least-to-Most 处理子问题依赖 多阶段调用与验证
ToT 搜索并回退多个方向 分支展开与评分

困难算法题可以比较这些方法,但必须固定模型、题集、采样数、测试环境和判分规则。没有这些条件的胜率只能帮助理解趋势,不能用于判断某方法在所有代码任务中更好。

反馈修订

Self-Refinement 由生成、检查和修订组成。检查可以来自模型评论,也可以来自编译器、静态分析、测试和真实运行结果。外部验证更容易提供可复现证据,例如指出某个测试输入对应错误输出。

修订应针对具体失败条件。空列表测试失败时,应修正边界处理;接口兼容测试失败时,应恢复公开签名。每轮还要检查原本通过的任务,避免修复一个问题后引入其他回归。

当重复尝试没有获得新证据,或者相同错误持续出现时,应停止、重新获取信息或转交处理。无界自我修改会消耗预算,并可能让代码逐渐偏离原目标。

工具闭环

纯文本推理不能确认当前文件内容、数据库状态或测试结果。ReAct 将任务分析、动作和观察交替进行,让真实工具结果影响下一步决策。

ReAct 的执行时序

典型 Bug 修复流程是先读取代码并复现故障,再定位原因、生成最小补丁、执行测试,最后判断是否完成。模型负责提出候选动作,控制器负责验证参数、执行工具和回传结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
目标:修复登录接口的空值异常。

动作:读取 auth_service.py 和对应测试。
观察:调用者可能传入 None,当前实现没有检查。

动作:执行能复现该输入的测试。
观察:测试失败,异常出现在 user.id 的访问处。

动作:生成边界检查补丁并应用到目标文件。
观察:补丁成功应用。

动作:运行相关测试与兼容性检查。
观察:测试通过,再核对修改是否满足原任务。

控制器需要保留调用和结果的对应关系。原生 Function Calling 使用工具名称、参数和调用 ID 表达动作,文本 ReAct 则常使用显式区块或结构化对象。两者属于协议与控制方式的不同层次,可以共同使用。

循环控制

工具循环需要成功、失败、等待审批和预算耗尽等出口。重复动作可以通过工具名与规范化参数的指纹检测,但还应判断观察是否变化;合法轮询可能反复请求同一状态。

错误应区分参数错误、运行故障和业务失败。缺少参数可以反馈字段错误,临时网络故障可以有限重试,权限拒绝不能通过改写提示绕过。测试日志需要保留失败名称、堆栈关键位置、退出码和相关上下文,并给完整日志留出查询入口。

下面用控制流程表达一个最小编码助手。工具执行器、模型客户端和验证器属于明确的接口,不能把未实现的占位函数当作完整系统。

1
2
3
4
5
6
7
8
9
10
11
12
接收任务并检查上下文。
装配系统要求、项目规则和可用工具。

在步数、时间和成本预算内循环:
请求模型提出下一步动作或最终结果。
若为动作:校验名称、参数、权限和目标。
在受控环境执行工具,记录结果与副作用。
将必要观察和错误写回状态。
若目标通过验证:结束任务。
若等待审批:持久化后挂起。

预算耗尽或无法继续时,返回明确的未完成状态。

项目规则

Cursor、GitHub Copilot、Cline 等 AI 编程工具会组合不同上下文来源。FIM 补全关注光标前后的代码,项目检索提供相关定义和文件,AST 与依赖分析帮助理解影响范围,工具循环则连接终端、测试和修改行为。

规则应按组织、项目、路径和当前任务分层加载。公共规范规定安全与代码风格,局部规则说明模块接口和业务不变量。规则文件需要版本管理,避免多个文件重复或冲突,并在修改后运行回归评测。

重构任务可以固定为“读取依赖、建立测试基线、生成受限补丁、验证行为”四个阶段。约束应包括公开 API 兼容、依赖限制、目标目录、补丁规模和失败处理。AST 分析还需与运行时信息结合,因为反射、配置和动态调用可能不出现在普通静态调用图中。

PR 总结生成器同样适合这一结构:先读取差异,再识别行为变化,最后生成结构化摘要。测试字段只能来自执行记录;未运行的测试应说明未运行,不能填成通过。

Prompt 评测

Prompt 优化需要固定评测集。Pass@1 表示一次候选成功的比例,Pass@k 表示 kk 个候选中至少一个成功的情况。若一次生成 nn 个候选,其中 cc 个正确,常用估计为:

Pass@k⁡=1−(n−ck)(nk).\operatorname{Pass@k}=1-\frac{\binom{n-c}{k}}{\binom{n}{k}}.

函数级任务可以使用 HumanEval 一类测试,仓库级修复可以使用 SWE-bench 一类任务;二者的上下文、执行环境和验收不同。评测应覆盖正常、边缘和历史失败任务,并同时记录调用次数、延迟、成本和失败类型。LLM-as-a-Judge 可以辅助判断解释质量,编译、测试和业务断言则负责可重复的硬验证。

Prompt、示例、规则和模型配置应一起版本管理。修改后比较新旧结果,通过 CI 检查关键场景退化;线上 Trace 和失败日志可以补充后续评测集。

可靠的 Prompt 系统应让任务边界可表达、结果可校验、动作可控制、失败可追踪。Prompt、上下文、推理方法与工具闭环共同服务于这些要求。