首页 / 资讯中心 / 文章详情

如何让LLM输出稳定JSON不翻车:Daily Paper Reader结构化输出三级回退与截断自动修复机制

如何让LLM输出稳定JSON不翻车:Daily Paper Reader结构化输出三级回退与截断自动修复机制 ★ FEATURED ARTICLE
【免费下载链接】daily-paper-reader开源的每日 arXiv / OpenReview 论文推荐与 AI 阅读平台支持 GitHub Actions 自动更新、GitHub Pages 部署与论文问答。项目地址https://gitcode.com/gh_mirrors/da/daily-paper-reader点击查看免费下载 开源项目Daily Paper Reader是一个每日自动推荐 arXiv / OpenReview 论文并生成 AI 阅读笔记的平台它的整个「论文精读、日报生成」链路都依赖 LLM 返回严格结构化的 JSON。这篇文章带你拆解它在 src/llm.py 中实现的结构化输出三级回退与截断 JSON 自动修复机制——即使模型「不听话」流水线也不会翻车。一、为什么让 LLM 输出 JSON 总是容易翻车Daily Paper Reader 的前后端整体链路LLM Refine 环节要求模型稳定输出 JSON在批量论文筛选场景下模型输出 JSON 时常见的「翻车」姿势有 4 种翻车场景表现直接后果API 不支持response_format返回 400 报错整个批次任务失败模型套了 Markdown 代码块json {...}json.loads直接炸掉输出被max_tokens截断JSON 缺右括号、字符串没闭合解析失败且重试仍会截断多吐/漏字段多出extra字段或漏了required字段下游取键报 KeyErrorDaily Paper Reader 的做法是不信任任何单一手段而是层层设防。核心入口是 src/llm.py 中的chat_structured()方法配合 src/4.llm_refine_papers.py 的业务层恢复逻辑形成了「格式回退 → 解析修复 → 业务重试/拆批」三道防线。二、第一道防线三级格式回退链json_schema → json_object → prompt_onlychat_structured()会先构造一条「格式尝试队列」由 _structured_response_format_names() 决定# 默认回退链DeepSeek 稳定入口是 json_object [json_object, prompt_only] # 环境变量 DPR_LLM_STRUCTURED_FORMATjson_schema 时 [json_schema, json_object, prompt_only]json_schema最严格的受控输出直接传 schemajson_object只保证「输出是合法 JSON 对象」DeepSeek 官方稳定的 JSON 模式入口prompt_only兜底方案——不发response_format改在 src/llm.py 的_ensure_json_instruction()中自动注入一条 system 提示Output valid JSON only. Do not output Markdown, code fences, or explanatory text.关键在回退的触发判断_is_structured_output_unsupported_error() 会检查 400/404/415/422 错误中是否包含response_format、not supported、must be one of等信号。命中就打印[INFO] Structured Outputs 不受支持回退到 ...然后换下一级格式重试而不是让整个任务报错退出。 想强制某种格式设置环境变量DPR_LLM_STRUCTURED_FORMAT或LLM_STRUCTURED_FORMAT为json_schema/json_object/prompt_only即可见 tests/test_llm_structured_output.py 中的回退用例。三、第二道防线脏 JSON 解析 截断自动修复就算模型「声称」只输出 JSON实际返回仍可能带代码块、多余文字甚至半截 JSON。parse_json_content() 按以下顺序抢救剥壳_strip_json_wrappers() 用正则去掉json/围栏多候选切片分别尝试「从第一个{到结尾」「从第一个{到最后一个}」、数组版本以及原文逐个用JSONDecoder.raw_decode试解析截断修复某个候选解析失败时调用 _repair_json_suffix()——这是整个机制里最巧的一招。_repair_json_suffix()的原理其实像一个「迷你括号配对器」逐字符扫描文本跟踪当前是否在字符串内含转义符用栈记录未闭合的{和[扫描结束后若字符串没闭合 → 补一个若栈里还有未闭合括号 → 按逆序补上}/]最后用正则re.sub(r,(\s*[}\]]), r\1, ...)清掉},],这类尾逗号这是截断 JSON 最常见的致命伤。也就是说哪怕模型输出被max_tokens拦腰截断成{papers: [{id: 1706.03762, title: Attention...它也能被自动补全成可解析的合法 JSON。️解析成功后还有一层本地 schema 校验_validate_json_schema_subset() 轻量检查type、enum、required缺失、additionalProperties: false时的多余字段递归覆盖对象和数组。校验不通过且还有回退档位可用时会打印[INFO] json_object 返回内容未通过 JSON 校验回退到 prompt_only再试一次。最终返回值里带着parsed、parse_error、response_format_used三个字段业务层可以清晰知道「数据是否可信、用的哪级格式」。四、第三道防线业务层重试 截断批次二分拆分格式和解析都救不回来时src/4.llm_refine_papers.py 的批量论文筛选环节还有一层「业务级容灾」截断识别响应finish_reason length会抛出专门的 FilterOutputTruncatedErrorsrc/4.llm_refine_papers.py带上下文重试recover_filter_results() 最多重试 3 次MAX_FILTER_RETRIES 3每次通过 build_filter_retry_note() 把上次的具体错误如missing idsp-2写进 prompt 让模型「纠错重答」二分拆批若是截断错误且批次内论文数 1立即中断重试把批次对半拆分递归处理split recovery——因为输出越长越容易截断拆小批次是从根上消除问题现场留证失败批次的原始输出会存到 debug 目录的filter_raw_*.txt方便排查src/4.llm_refine_papers.py。这套重试/拆批逻辑有完整的单元测试覆盖tests/test_llm_refine_recovery.py 验证了「缺 id 时带错误说明重试」和「重试耗尽后自动二分批次」两种恢复路径。五、最终效果结构化摘要直接写进你的笔记这套机制的下游收益非常直观——LLM Refine 环节返回的tldr_cn、motivation_cn、method_cn、result_cn、conclusion_cn等结构化字段最终会渲染成论文页摘要和 Zotero 笔记结构化 JSON 字段TLDR、motivation/method/result/conclusion稳定落到 Zotero 笔记在前端面板中你也可以看到这些由 LLM 结构化输出支撑的标签、评分与中文 evidenceDaily Paper Reader 后台面板论文评分、标签与中文摘要均来自稳定解析的 JSON 字段六、如果你想在自己的项目里复用这套思路不用照抄代码记住这 4 条「稳定 JSON 输出」的黄金法则即可格式请求要做降级链json_schema → json_object → prompt 约束识别「不支持」类错误自动换档而不是直接失败解析永远多备几个切片候选剥 Markdown 围栏、截取首个{到末个}比裸调json.loads健壮得多补括号 去尾逗号是截断 JSON 性价比最高的修复手段二十行代码就能实现截断要专门识别finish_reason: length并优先用「拆小批次」而非盲目重试。 想深入阅读源码可以从这几个文件入手核心实现src/llm.pychat_structured、parse_json_content、_repair_json_suffix业务重试与拆批src/4.llm_refine_papers.py格式回退测试tests/test_llm_structured_output.py截断恢复测试tests/test_llm_refine_recovery.py文档生成调用示例src/6.generate_docs.py掌握这套「三级回退 截断自修复」机制你调 LLM 输出 JSON 时翻车的概率会大幅下降。赞分享【免费下载链接】daily-paper-reader开源的每日 arXiv / OpenReview 论文推荐与 AI 阅读平台支持 GitHub Actions 自动更新、GitHub Pages 部署与论文问答。项目地址https://gitcode.com/gh_mirrors/da/daily-paper-reader点击查看免费下载相关推荐its-trip 提示词工程拆解JSON Schema 硬约束 自动修复如何逼 LLM 稳定输出结构化结果its trip 提示词工程拆解JSON Schema 硬约束 自动修复如何逼 LLM 稳定输出结构化结果 its trip 是 CANN 交通大模型人工智能大模型AI 应用AI Agent多智能体本地部署智慧城市CANNAscendopenEuler如何让LLM稳定输出JSONocrbase的JSON修复与候选解析策略源码全解如何让LLM稳定输出JSONocrbase的JSON修复与候选解析策略源码全解 在调用 LLM 做结构化数据提取时输出不稳定、JSON 解析失败几乎是每如何用 Web-Dev-For-Beginners 的 LangChain 结构输出让 LLM 返回可解析的 JSON如何用 Web Dev For Beginners 的 LangChain 结构输出让 LLM 返回可解析的 JSON 当你用 Web Dev For Begi文档教程教育上一篇Flutter状态管理利器Provider全面解析与最佳实践指南下一篇Orange3 数据挖掘工具包中的 Widget 开发入门指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站