Langchain中Pydantic互递归模型JSON解析报错求助
解决方案:Pydantic互递归结构适配Langchain JSON解析
问题根源
Pydantic 2.x中互递归模型的ForwardRef解析依赖正确的命名空间,Langchain的Pydantic输出解析器无法处理未完全解析的ForwardRef,导致TypeError;单独调用单模型的update_forward_refs()会因命名空间不全引发NameError。
解决步骤
- 用字符串引用定义递归字段:定义模型时,对互递归的字段使用字符串形式的类名(如
List["ProofStep"]),避免定义阶段的循环引用冲突。 - 统一更新ForwardRefs:所有模型定义完成后,一次性传递全局命名空间给每个模型的
update_forward_refs()方法,确保所有递归类能被正确识别。 - 确保解析器使用已解析的模型:仅在ForwardRef完全解析后,将模型传递给Langchain的
PydanticOutputParser。
可运行代码示例
from pydantic import BaseModel, Field from typing import List, Optional from langchain.output_parsers import PydanticOutputParser from langchain.prompts import PromptTemplate from langchain_openai import ChatOpenAI # 定义互递归模型,使用字符串形式的类名引用 class Theorem(BaseModel): statement: str proof: Optional["Proof"] = Field(None, description="递归引用的证明结构") class ProofStep(BaseModel): explanation: str theorem: Optional[Theorem] = Field(None, description="递归引用的定理") sub_steps: Optional[List["ProofStep"]] = Field(None, description="递归的子步骤") class Proof(BaseModel): steps: List[ProofStep] = Field(..., description="证明步骤列表") # 统一更新所有模型的ForwardRef,传递全局命名空间 Theorem.update_forward_refs(**globals()) ProofStep.update_forward_refs(**globals()) Proof.update_forward_refs(**globals()) # 配置Langchain组件 llm = ChatOpenAI(model="gpt-4", temperature=0) parser = PydanticOutputParser(pydantic_object=Proof) prompt = PromptTemplate( template="请生成关于{topic}的数学证明,严格按照指定格式输出:\n{format_instructions}\n", input_variables=["topic"], partial_variables={"format_instructions": parser.get_format_instructions()} ) # 执行调用 chain = prompt | llm | parser result = chain.invoke({"topic": "勾股定理"}) print(result.model_dump_json(indent=2))
关键说明
- 字符串形式的类名引用会让Pydantic延迟类型解析,避免定义时的循环引用错误。
**globals()将当前所有已定义的类传递给update_forward_refs(),解决单个模型更新时找不到其他递归类的NameError。- 必须在全部模型定义完成后执行更新操作,否则会出现未定义类的引用问题。
- 若使用模块化代码,需确保在导入所有相关模型后再执行
update_forward_refs(),或启用from __future__ import annotations(Python 3.7+)辅助延迟解析,但显式更新更适配Pydantic 2.x的Langchain集成场景。
内容的提问来源于stack exchange,提问作者bahab
相关产品推荐
相关产品推荐

