Langchain简单快速上手教程(四)——聊天模型之结构化输出

@

前言

本期我将要介绍LangChain 中聊天模型的另一功能结构化输出。这将原来大模型输出的AIMessage变成以例如Json等格式化输出,以适应特定的开发场景。

一、with_structured_output() 方法

要想使用结构化输出能力,LangChain提供了一种方法.with_structured_output() 。该方法需要先定义输出结构,然后执行通过 .with_structured_output() 得到Runnable 实例。

(一)返回 Pydantic 对象

我们可以设置执行Runnable 后的输出结果指定为 Pydantic 类,这将返回一个 Pydantic 对象。当收到模型的响应后,LangChain 会提取出代表 Pydantic 参数的 JSON 对象,并用 Pydantic 模型对其进行解析和验证,将这个验证后的 JSON 转换为⼀个可用的 Pydantic 对象实例返回。

# 结构化返回 Pydantic
model = ChatDeepSeek(model='deepseek-v4-flash')

class Joke(BaseModel):
    """给用户讲的一个笑话"""
    setup:str = Field(description="笑话的开头")
    punchline: str = Field(description='笑话的妙语')
    rating: Optional[int] = Field(default=None,description="从1-10分,给这个笑话评分")

class Data(BaseModel):
    """获取关于笑话的数据列表"""
    jokes: List[Joke]

# print(model.invoke("讲一个关于薛定谔的猫的笑话").content)
model_with_structured = model.with_structured_output(Data)
print(model_with_structured.invoke("讲一个关于薛定谔的猫的笑话"))

(二)返回 TypedDict

TypedDict 主要用于为字典对象提供精确的、结构化的类型提示。它允许我们指定字典中应该有哪些键,以及每个键对应的值的类型。它其中一个重要的能力就是捕捉键名拼写错误与类型错误。

因此我们也可以设置执行Runnable 后的输出结果指定为 TypedDict 类,这将就会返回一个字典,且输出后,会根据设定进行验证。

model = ChatDeepSeek(model='deepseek-v4-flash')

# 结构化返回 TypedDict
class Joke(TypedDict):
    """给用户讲的一个笑话"""
    setup:str = Field(description="笑话的开头")
    punchline: str = Field(description='笑话的妙语')
    rating: Optional[int] = Field(description="从1-10分,给这个笑话评分")

model_with_structured = model.with_structured_output(Joke,include_raw=True)
print(model_with_structured.invoke("讲一个关于薛定谔的猫的笑话"))

(三)返回 JSON

为了声明 JSON,我们同时需要定义 JSON Schema。

model = ChatDeepSeek(model='deepseek-v4-flash')

# 结构化返回 JSON Schema
json_schema = {
    "title": "joke",
    "description": "给用户讲一个笑话。",
    "type": "object",
    "properties": {
        "setup": {
            "type": "string",
            "description": "这个笑话的开头",
        },
        "punchline": {
            "type": "string",
            "description": "这个笑话的妙语",
        },
        "rating": {
            "type": "integer",
            "description": "从1到10分,给这个笑话评分",
            "default": None,
        },
    },
    "required": ["setup", "punchline"],
}

model_with_structured = model.with_structured_output(json_schema)
print(model_with_structured.invoke("讲一个关于薛定谔的猫的笑话"))

(四)选择输出格式

创建具有联合类型属性的父模式。

model = ChatDeepSeek(model='deepseek-v4-flash')

class Joke(BaseModel):
    """给用户讲的一个笑话"""

    setup: str = Field(description="这个笑话的开头")
    punchline: str = Field(description="这个笑话的妙语")
    rating: Optional[int] = Field(default=None, description="从1-10分,给这个笑话评分")

class Response(BaseModel):
    """以对话的方式回应"""

    content: str = Field(description="用于对用户查询的会话响应")

class FinalResponse(BaseModel):
    """最终回复,选择合适的输出结构"""

    final_output: Union[Joke, Response]

model_with_structured = model.with_structured_output(FinalResponse)
print(model_with_structured.invoke("讲一个关于薛定谔的猫的笑话"))
print(model_with_structured.invoke("你是谁?"))

二、实用案例

(一)信息提取

model = ChatDeepSeek(model='deepseek-v4-flash')

# 结构化输出常见使用场景:信息提取

class Person(BaseModel):
    """一个人的信息。"""

    # 注意:
    # 1. 每个字段都是 Optional “可选的” —— 允许 LLM 在不知道答案时输出 None。
    # 2. 每个字段都有一个 description “描述” —— LLM使用这个描述。
    # 有一个好的描述可以帮助提高提取结果。
    name: Optional[str] = Field(default=None, description="这个人的名字")
    hair_color: Optional[str] = Field(default=None, description="如果知道这个人头发的颜色")
    skin_color: Optional[str] = Field(default=None, description="如果知道这个人的肤色")
    height_in_meters: Optional[str] = Field(default=None, description="以米为单位的高度")


structured_model = model.with_structured_output(schema=Person)
messages = [
    SystemMessage(content="你是一个提取信息的专家,只从文本中提取相关信息。如果您不知道要提取的属性的值,属性值返回null"),
    HumanMessage(content="史密斯身高6英尺,金发。")
]
result = structured_model.invoke(messages)
print(result)

(二)与工具结合使用

model = ChatOpenAI(
    model='deepseek-v4-flash',
    api_key=os.environ.get('DEEPSEEK_API_KEY'),
    base_url="https://api.deepseek.com",
)

# 结构化输出常见使用场景:与工具结合使用

tool = TavilySearch(max_results=4)

model_with_tools = model.bind_tools([tool])

messages = [
    HumanMessage("北京今天的天气怎么样?")
]
ai_message = model_with_tools.invoke(messages)
messages.append(ai_message)

for tool_call in ai_message.tool_calls:
    tool_message = tool.invoke(tool_call)
    messages.append(tool_message)

class SearchResult(BaseModel):
    """结构化搜索对象"""

    query: str = Field(description="搜索查询")
    findings: str = Field(description="查询结果摘要")

model_with_structured = model_with_tools.with_structured_output(SearchResult)
print(model_with_structured.invoke(messages))

与工具相结合的方式下,它并不能直接帮我们输出想要的SearchResult搜索结果,而是只返回了AIMessage。所以with_structured_output 方法只是让模型知道有哪些工具可以调用,但是并不会自动执行工具。要获得工具执行后的结果并整合到最终的结构化输出中,我们需要手动执行。

结语

以上便是Langchain中如何使用聊天模型的格式化输出的内容了。如果喜欢我的内容,请点赞、收藏加关注,多多支持我,以及欢迎各位在评论区讨论交流,并指出我的不足,谢谢大家。

posted @ 2026-09-08 20:35  _梦影  阅读(28)  评论(0)    收藏  举报