SW-07 pipeline 策略 profile 化:重试/定向重生成/自检开关/检索 top-k(ADR-0016) - #12
Conversation
- pipeline.pass_attempts(缺省 2)→ _retry_pass;显式 attempts 参数优先 - pipeline.phase_attempts(缺省 3)→ p3/p4、p5、p6 三个相位循环 - retrieval.top_k(缺省 3)→ cli._make_retrieval → RetrievalService.k - revise.gate_mode(缺省 lenient)→ p5 self-check 采纳策略; revise.self_check 开关既有(T-31),本次入 schema 正名 - profiles/_schema.py 新增 PipelineSettings/RetrievalSettings/ReviseSettings (extra=forbid);两个在库 profile 显式写入缺省值,行为零变化 - 测试:tests/test_profile_strategy.py(4 例,先红后绿)
There was a problem hiding this comment.
🟡 Changes recommended
新增的 profile 解析路径在多处对配置值直接 int(...) / 透传 mode,配置写错会抛未捕获异常绕过现有 PassFailure 重试/诊断链路,且 ADR 日期存在未来时间。
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
该 PR 将 SW-07 中“管线策略”从代码常量下沉到 profile(pipeline/retrieval/revise 三段),以便按不同模型/场景在资产层调参,同时保持缺省值与历史常量一致,实现“零行为变化”的可配置化。
Changes:
- 在
profiles/_schema.py增加PipelineSettings/RetrievalSettings/ReviseSettings并挂到Profile上,约束并提供缺省值。 - 将
pipeline.py的 pass/phase 重试次数、p5_dialogue.py的 gate_mode、cli.py的检索 top-k 改为从 profile 读取(缺省回退到原常量)。 - 新增
tests/test_profile_strategy.py覆盖上述配置读取与缺省回退语义,并为两个在库 profile 显式写入缺省段落。
File summaries
| File | Description |
|---|---|
| tests/test_profile_strategy.py | 新增针对 pass_attempts/phase_attempts/gate_mode/top_k 的回归测试与缺省回退验证 |
| src/nsc/passes/pipeline.py | pass/phase 重试次数从 profile 读取,并用于 p3/p4、p5、p6 三个相位循环 |
| src/nsc/passes/p5_dialogue.py | self-check 修订采纳策略 gate_mode 从 profile 读取并用于 revisionGate |
| src/nsc/cli.py | 将 RetrievalService 的 top-k 从 profile 读取并封装为 _make_retrieval |
| profiles/short_video_v1.yaml | 显式写入 pipeline/retrieval/revise 三段缺省值以提升可发现性 |
| profiles/short_drama_v1.yaml | 同上:显式写入三段缺省值 |
| profiles/_schema.py | 增加三段 settings schema(extra=forbid、Literal gate_mode 等)并挂到 Profile |
| adr/0016-pipeline-strategy-profile-sections.md | 新增 ADR-0016,说明 profile 化决策与迁移/验证 |
Review details
Suppressed comments (1)
src/nsc/passes/pipeline.py:91
- _phase_attempts 同样对 profile 值做 int(...);解析失败会抛 TypeError/ValueError 并绕过 phase 重试的 PassFailure 捕获,可能导致状态未回滚且直接退出。建议把解析错误转成 PassFailure 并带上清晰诊断。
def _phase_attempts(ctx: PassContext) -> int:
"""SW-07:p3/p4、p5、p6 相位级定向重生成次数(profile.pipeline.phase_attempts,缺省 3)。"""
return max(1, int(ctx.profile.get("pipeline", {}).get("phase_attempts", 3)))
- Files reviewed: 8/8 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| def _pass_attempts(ctx: PassContext) -> int: | ||
| """SW-07:单 Pass 输出波动重试次数(profile.pipeline.pass_attempts,缺省 2)。""" | ||
| return max(1, int(ctx.profile.get("pipeline", {}).get("pass_attempts", 2))) |
There was a problem hiding this comment.
已修正(64d17ba):新增 _attempts_of(ctx, key, default) 统一读次数旋钮,pass_attempts/phase_attempts 两处共用;解析失败(TypeError/ValueError)转 PassFailure,诊断句指明 profile 键与当前值,走既有失败/快照链路而非裸崩溃。回归测试 test_bad_profile_values_fail_with_clear_errors 覆盖两个键的坏值路径。
| findings2 = _scene_findings(ctx, scene, beats, lines2, characters) | ||
| if decide(_counts(findings), _counts(findings2), "lenient"): | ||
| if decide(_counts(findings), _counts(findings2), _gate_mode(ctx)): | ||
| return lines2, out2 |
There was a problem hiding this comment.
已修正(64d17ba):_gate_mode 先对 nsc.revise.gate.MODES 校验,非法值直接 PassFailure(None, 诊断句)——不再把 decide() 的 ValueError 留给无人捕获的编排层。schema 的 Literal 约束仍作为第一道防线(校验过的 profile 到不了这里),这道是裸 dict profile 的兜底。
| def _make_retrieval(ctx: Any) -> Any: | ||
| """SW-07:检索服务,注入条数 top_k 读 profile.retrieval(缺省 3=原常量)。""" | ||
| from nsc.retrieval import RetrievalService | ||
|
|
||
| return RetrievalService( | ||
| db_path="cases/cases.db", | ||
| k=max(1, int(ctx.profile.get("retrieval", {}).get("top_k", 3))), | ||
| ) |
There was a problem hiding this comment.
已修正(64d17ba):_make_retrieval 对 retrieval.top_k 的解析失败转 typer.BadParameter(消息含键名与当前值),CLI 层用户可读,不再是裸堆栈。同测试覆盖。
Copilot review(PR #12): - _pass_attempts/_phase_attempts 对非整数/None 抛 TypeError/ValueError 击穿编排 → 统一 _attempts_of:解析失败转 PassFailure(诊断句指明 profile 键与当前值) - p5 gate_mode 非法时 revise.gate.decide 的 ValueError 无人捕获 → _gate_mode 先校验 MODES,非法即 PassFailure - cli._make_retrieval 对坏 top_k 裸堆栈 → typer.BadParameter 用户可读报错 - 回归:test_bad_profile_values_fail_with_clear_errors(4 断言齐备)
这个 PR 改的是哪一层?(必选其一)
spec/profiles/brands/cases/export/)→ 必须打标签asset-change并附 ADRsrc/tests/)→ 无需 ADRADR:adr/0016-pipeline-strategy-profile-sections.md(status: proposed,含 profiles/_schema.py 变更,等确认)
工单
Closes # · 工单号:SW-07(上游依赖卡,Lab 仓 docs/WORK_ORDERS.md §上游依赖卡)
问题
各 phase 重试次数、定向重生成策略、self-check 子步骤开关、检索注入条数(rerank n)是
pipeline.py/p5_dialogue.py/cli.py里的代码常量(attempts=2、range(3)、"lenient"、k=3)。弱/强模型需要不同重试预算,改常量就要动代码层。改动
pipeline.pass_attempts_retry_pass(显式 attempts 参数仍优先)pipeline.phase_attemptsretrieval.top_kcli._make_retrieval→RetrievalService.krevise.gate_modensc.revise.gate.MODES)revise.self_checkprofiles/_schema.py:新增PipelineSettings/RetrievalSettings/ReviseSettings(extra=forbid,Literal 约束 gate_mode)revise.self_check在 main 已是 profile 可读(卡面该项已完成,仅补 schema 正名);CLI--rerank旗标在 main 即为死参数(声明未用),未清理(超出本卡范围);eval l1 的 RetrievalService 仍用构造缺省 k=3(与 profile 缺省一致)验收命令(贴出你本地跑通的输出)
检查表
prompts/影响生成结果吗?