
纲要容错机制自动重试解析器RetryOutputParser修复解析器OutputFixingParser自定义解析器案例一纳美星语转换解析器基于正则案例二布尔值解析器继承BaseOutputParser完整可运行代码模拟错误场景展示容错修复与自定义解析全流程引言在前几篇文章中我们学习了如何用 LangChain 的输出解析器将大模型的自然语言输出转换为结构化的 Python 对象。但在实际应用中模型输出的随机性受 temperature 等参数影响会导致解析失败比如缺少字段、JSON 格式错误等。LangChain 为此提供了两种容错机制自动重试和修复。此外当内置解析器不满足需求时开发者还可以通过自定义解析器实现任意格式的转换。本文将结合可运行代码深入介绍这两项实用技能。输出解析器的容错机制自动重试RetryOutputParser当解析失败时自动重试解析器会将原始提示词、错误输出以及错误信息一起重新交给大模型让模型再次生成符合格式的回答。其核心思想是将解析错误作为反馈信号引导模型修正输出。修复解析器OutputFixingParser与重试不同修复解析器会直接调用另一个大模型尝试将错误的输出修正为目标格式不依赖原始提示词。它更适用于那些输出已经“离正确格式不远”的情况例如 JSON 中少了一个花括号。两种容错方式的对比特性RetryOutputParserOutputFixingParser输入原始提示词 错误输出 错误信息错误输出 原解析器依赖模型需要可用任意模型需要通常更轻量适用场景格式完全错误需要重新理解任务小范围格式瑕疵快速修补自定义解析器实战纳美星语解析器我们基于电影《阿凡达》中的纳美星语Na’vi构造一个趣味解析器将英文问候语转换为带有纳美语特征的正则替换结果。该解析器不依赖模型完全由正则规则驱动并可直接作为链的一环。布尔值解析器通过继承BaseOutputParser实现一个简洁的布尔值解析器将常见的“yes/no”、“true/false”等自然语言表达统一转换为 Python 的True或False并支持自定义真值映射。完整可运行代码以下代码整合了容错机制与两种自定义解析器的完整示例使用FakeListChatModel模拟大模型响应因此无需任何 API Key 即可直接运行。安装依赖pipinstalllangchain langchain-core langchain-community pydantic代码实现fromtypingimportAny,Dict,ListfrompydanticimportBaseModel,Fieldfromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimport(BaseOutputParser,PydanticOutputParser,OutputFixingParser,)fromlangchain_core.language_modelsimportBaseChatModelfromlangchain_community.chat_models.fakeimportFakeListChatModelfromlangchain.output_parsers.retryimportRetryOutputParserfromlangchain_core.messagesimportAIMessage# 1. 定义数据模型 classAction(BaseModel):action:strField(description下一步行动名称)action_input:strField(description行动所需的输入)# 2. 模拟错误的模型响应 # 正确的 JSONcorrect_json{action: search, action_input: 北京天气}# 错误响应缺少 action_input 字段bad_json{action: search}# 用于容错机制的假模型第一次返回错误第二次返回正确fix_modelFakeListChatModel(responses[correct_json])# 用于重试的假模型同样返回正确结果retry_modelFakeListChatModel(responses[correct_json])# 用于原始解析的模型返回错误响应base_modelFakeListChatModel(responses[bad_json])# 3. 构建解析器与提示词 parserPydanticOutputParser(pydantic_objectAction)format_instructionsparser.get_format_instructions()promptChatPromptTemplate.from_template(根据用户的问题制定下一步计划。\n{format_instructions}\n问题{question})promptprompt.partial(format_instructionsformat_instructions)# 4. 演示解析失败 print( 1. 无容错的原始解析预期失败 )try:bad_chainprompt|base_model|parser resultbad_chain.invoke({question:今天北京天气怎么样})print(解析成功:,result)exceptExceptionase:print(解析失败错误信息:,str(e)[:100],...)# 5. 使用 OutputFixingParser 修复 print(\n 2. OutputFixingParser 修复示例 )fixing_parserOutputFixingParser.from_llm(parserparser,llmfix_model,max_retries1)# 手动构造一个 AIMessage 模拟错误输出bad_messageAIMessage(contentbad_json)try:fixed_resultfixing_parser.parse(bad_message.content)print(修复后解析成功:,fixed_result)exceptExceptionase:print(修复失败:,e)# 6. 使用 RetryOutputParser 重试 print(\n 3. RetryOutputParser 重示例 )retry_parserRetryOutputParser.from_llm(parserparser,llmretry_model,max_retries2)# 需要提供原始提示词值和错误的输出prompt_valueprompt.invoke({question:今天北京天气怎么样})try:retry_resultretry_parser.parse_with_prompt(bad_message.content,prompt_value)print(重试后解析成功:,retry_result)exceptExceptionase:print(重试失败:,e)# 7. 自定义解析器纳美星语转换 importredefnavi_transformer(text:str)-str:将英文转换为带有纳美语特征的文本# 常见问候替换textre.sub(r\bhello\b,Kaltxì,text,flagsre.IGNORECASE)textre.sub(r\bthank you\b,Irayo,text,flagsre.IGNORECASE)# 形容词加前缀 le-textre.sub(r\b(beautiful|pretty|great)\b,rle-\1,text,flagsre.IGNORECASE)# 动词加语气后缀textre.sub(r\b(go|come|see|help)\b,r\1-ti,text,flagsre.IGNORECASE)# 句首添加特征前缀ifnottext.startswith(Tsa\u):textTsa\u textreturntextclassNaviOutputParser(BaseOutputParser[str]):自定义纳美星语解析器defparse(self,text:str)-str:# 假设模型输出纯文本returnnavi_transformer(text)defget_format_instructions(self)-str:return请输出一段简短的英文问候或陈述。propertydef_type(self)-str:returnnavi_parserprint(\n 4. 纳美星语解析器 )navi_parserNaviOutputParser()# 模拟模型的英文输出english_responseHello, how can I help you? You are beautiful.navi_responsenavi_parser.parse(english_response)print(英文输入:,english_response)print(纳美语输出:,navi_response)# 8. 自定义布尔值解析器 classBooleanOutputParser(BaseOutputParser[bool]):将自然语言 yes/no 转换为布尔值true_values:List[str][yes,true,ok,1]false_values:List[str][no,false,nok,0]defparse(self,text:str)-bool:cleantext.strip().lower()ifcleaninself.true_values:returnTrueelifcleaninself.false_values:returnFalseelse:raiseValueError(f无法识别的布尔值:{text}仅支持{self.true_valuesself.false_values})defget_format_instructions(self)-str:returnf请仅返回以下单词之一{, .join(self.true_valuesself.false_values)}propertydef_type(self)-str:returnboolean_parserprint(\n 5. 布尔值解析器 )bool_parserBooleanOutputParser()print(输入 yes -,bool_parser.parse(yes))print(输入 No -,bool_parser.parse(No))# 自定义真值映射custom_bool_parserBooleanOutputParser(true_values[go],false_values[stop])print(输入 go -,custom_bool_parser.parse(go))try:custom_bool_parser.parse(maybe)exceptValueErrorase:print(输入 maybe 触发错误:,e)运行结果解读无容错解析直接抛出ValidationError因为模型输出缺少action_input字段。修复解析OutputFixingParser使用另一个模型模拟为FakeListChatModel将{action: search}补全为{action: search, action_input: 北京天气}成功解析。重试解析RetryOutputParser将错误输出和原始提示词一同交给模型重新生成符合格式的结果。纳美星语解析器通过正则替换实现趣味转换完全不依赖外部服务。布尔值解析器简洁地完成了自然语言到布尔值的映射并支持自定义参数错误输入会触发异常。最佳实践与注意事项容错机制会额外消耗模型调用次数生产环境中需合理设置max_retries。修复解析器适合“小修小补”如果输出与目标格式相差甚远优先使用重试。自定义解析器时建议同时实现get_format_instructions()方法以便在提示词中注入格式要求。布尔值解析器可通过配置文件动态注入真假映射方便国际化。总结本文介绍了 LangChain 输出解析器的容错方案重试与修复并通过两个实战案例展示了如何构建自定义解析器。这些工具让 LLM 应用在面对不可预测的模型输出时更加强健也为特殊业务逻辑提供了灵活的解析能力。掌握它们你就能在构建 AI Agent 时游刃有余地处理各种结构化输出需求。