4.5 KiB
Summary Loop 工作说明
1. 目的
本文档说明 scripts/run_summary_loop.py 如何把以下流程串成一个最小闭环:
提取 JSON -> LLM 生成摘要 JSON -> validator 校验 -> 失败则修复重试
这个脚本的目标不是单次调用 LLM,而是让 LLM 输出进入一个“生成后验收”的自动反馈回路。
2. 核心思路
这个闭环由三部分组成:
-
提取结果
- 来自
outputs/*.extracted.json - 提供标题、链接、正文、质量标记
- 来自
-
LLM 摘要
- 基于提取结果和 prompt 生成
result.json
- 基于提取结果和 prompt 生成
-
validator
- 检查
result.json是否符合结构和业务规则 - 不通过则返回错误列表
- 检查
因此,LLM 不是“自己知道哪里错了”,而是脚本在每轮生成后用 validator 明确指出错误,再要求它修复。
3. 运行顺序
脚本入口:
scripts/run_summary_loop.py
执行顺序如下:
- 读取提取结果 JSON
- 读取摘要 prompt 模板
- 从提取结果中裁剪出摘要真正需要的输入字段
- 调用 LLM 生成摘要 JSON
- 解析模型输出中的 JSON
- 将结果写入输出文件
- 调用 validator 校验结果
- 如果通过,结束
- 如果失败,构造修复 prompt,再次调用 LLM
4. 输入来源
脚本主要使用两个输入文件:
- 提取结果:
outputs/read-flow-2026.extracted.json - 摘要 prompt:
outputs/llm-summary-prompt.txt
提取结果不会整包无差别塞给 LLM,而是先裁剪成更小的摘要输入:
article.titlearticle.urlarticle.plain_textarticle.quality_flagswarnings
这样做是为了减少 payload,降低模型超时概率,也让 prompt 更聚焦。
5. 首次生成
第一次生成时,脚本会把:
- prompt 模板
- 结构化文章输入
拼成一个完整请求,发给 LLM。
对应函数:
build_initial_prompt(...)call_llm(...)
模型返回后,脚本会尝试提取一个 JSON 对象。
如果模型输出不是合法 JSON:
- 这一轮直接视为失败
- 会生成一份失败校验结果
- 然后进入修复重试
6. validator 如何加入流程
validator 不是附加步骤,而是主流程里的硬门槛。
对应函数:
validate_llm_result(...)
校验内容包括两层:
6.1 结构校验
- 必填字段是否存在
- 字段类型是否正确
category是否属于允许枚举summary长度是否合规highlights/keywords/topics数量是否合规
6.2 业务校验
keywords和topics不能重复- 列表内部不能重复
title和url必须与提取结果一致
只有 validator 返回 valid: true,这一轮结果才会被接受。
7. LLM 如何知道自己生成错了
LLM 本身不会主动知道哪些字段不合规。
脚本会在校验失败后,把以下信息重新发给 LLM:
- validator 错误列表
- 原始提取结果
- 当前错误的摘要 JSON
然后要求它:
- 只修复错误字段
- 保留已经正确的字段
- 继续只输出合法 JSON
对应函数:
build_repair_prompt(...)
也就是说:
- prompt 负责提出目标
- validator 负责判错
- repair prompt 负责把错误喂回模型
这三者一起形成自动修复回路。
8. 时序图
Extracted JSON
|
v
run_summary_loop.py
|
|-- 读取 prompt 模板
|-- 构造摘要输入
|
v
LLM
|
v
摘要 JSON
|
v
validator
|
|-- valid = true ------> 结束
|
|-- valid = false
| |
| |-- errors
| v
| repair prompt
| |
+------> LLM 重试
9. 生成的中间文件
每次执行脚本都会在输出目录下留下调试痕迹:
-
result.loop.attempt-1.raw.txt- 模型原始输出
-
result.loop.attempt-1.json- 提取出的 JSON 结果
-
result.loop.attempt-1.validation.json- 这一轮的校验报告
-
result.loop.json- 当前最终结果
这些文件的价值是:
- 可以回看模型原始输出
- 可以定位是 JSON 解析失败还是 schema 校验失败
- 可以看每轮修复到底修了什么
10. 当前脚本参数
当前脚本支持:
--extracted--prompt--output--max-retries--timeout--api-key--model--api-url
这意味着它既可以走环境变量,也可以直接用命令行传入模型配置。
11. 一句话结论
run_summary_loop.py 的本质不是“调一次 LLM”,而是“让 LLM 生成结果后必须经过 validator 验收,失败就拿着错误清单继续修”,直到结果通过或达到重试上限。