如果你不使用LangChain调用大模型,也有很多办法对大模型的输出进行Json格式化,不过就是相对没有LangChain方便。本文会将如何使用Langchain进行Json格式化进行系统性梳理,希望能帮助到你。方法有三种
- 基础方法:提示词进行Json格式化
- 使用JsonOutputParser
- 使用PydanticOutputParser
下面是完整的示例代码,代码里面包含了详细的中文解释,这里就不再文字赘述了。另外,示例代码是可以执行的,建议想学习的同学copy一份下来自己调试一下哦
内容参考自LangChain官网
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
@author: Junius
@Email: see619055@gmail.com
@time: 2025/5/26 16:13
@file: 05.3 Json格式化输出
@project: OpenAppAI
@describe: LangChain JSON格式化输出示例
"""
from typing import List, Dict, Any, Optional
import json
from pydantic import BaseModel, Field
# 导入LangChain相关模块
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser, PydanticOutputParser
from langchain_core.pydantic_v1 import BaseModel, Field, validator
from langchain.output_parsers import OutputFixingParser
from langchain_core.exceptions import OutputParserException
# 定义一个模型类用于结构化JSON输出
class Person(BaseModel):
"""人物信息模型"""
name: str = Field(description="人物姓名")
age: int = Field(description="人物年龄")
occupation: str = Field(description="职业")
hobbies: List[str] = Field(description="爱好列表")
@validator("age")
def validate_age(cls, value):
if value < 0 or value > 150:
raise ValueError("年龄必须在0到150之间")
return value
# 初始化LLM模型
llm = ChatOpenAI(
openai_api_base="https://open.bigmodel.cn/api/paas/v4/",
# openai_api_key="你的API密钥", # 使用智谱免费的模型进行学习
model="glm-4-flash-250414"
)
# 示例1: 基础JSON输出
def basic_json_output():
"""基础的JSON输出示例"""
print("\n=== 示例1: 基础JSON输出 ===")
# 创建JSON解析器
json_parser = JsonOutputParser()
# 创建提示模板,明确指示模型输出JSON格式
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个提供JSON格式化数据的助手。请以有效的JSON格式回复,不要添加额外的文本说明。"),
("user", "请提供关于'{topic}'的基本信息,包括名称、描述和至少3个关键特点。")
])
# 构建链
chain = prompt | llm | json_parser
# 调用链并打印结果
result = chain.invoke({"topic": "人工智能"})
print(json.dumps(result, ensure_ascii=False, indent=2))
# 示例2: 使用Pydantic模型进行结构化输出
def pydantic_structured_output():
"""使用Pydantic模型进行结构化JSON输出示例"""
print("\n=== 示例2: 使用Pydantic模型进行结构化输出 ===")
# 创建Pydantic解析器
parser = PydanticOutputParser(pydantic_object=Person)
# 获取解析器的格式指令
format_instructions = parser.get_format_instructions()
# 创建提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个提供JSON格式化数据的助手。请按照指定的格式输出。\n{format_instructions}"),
("user", "请生成一个关于'{character}'的人物信息。")
])
# 构建链
chain = prompt | llm | parser
# 调用链并打印结果
result = chain.invoke({
"format_instructions": format_instructions,
"character": "爱因斯坦"
})
# 由于result已经是Person对象,我们可以直接访问其属性
print(f"姓名: {result.name}")
print(f"年龄: {result.age}")
print(f"职业: {result.occupation}")
print(f"爱好: {', '.join(result.hobbies)}")
print("\n完整JSON:")
print(json.dumps(result.dict(), ensure_ascii=False, indent=2))
# 示例3: 流式输出JSON
def streaming_json_output():
"""流式输出JSON示例"""
print("\n=== 示例3: 流式输出JSON ===")
json_parser = JsonOutputParser()
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个提供JSON格式化数据的助手。请以有效的JSON格式回复,不要添加额外的文本说明。"),
("user", "请列出'{country}'的5个主要城市,包括名称、人口和一句话描述。")
])
# 构建链
chain = prompt | llm | json_parser
print("流式输出开始:")
# 流式输出
result = {}
for chunk in chain.stream({"country": "中国"}):
print(f"收到chunk: {chunk}")
# 更新结果字典
if isinstance(chunk, dict):
result.update(chunk)
print("\n最终完整结果:")
print(json.dumps(result, ensure_ascii=False, indent=2))
# 示例4: 错误处理和修复
def error_handling_and_fixing():
"""JSON解析错误处理和修复示例"""
print("\n=== 示例4: 错误处理和修复 ===")
# 创建解析器
parser = PydanticOutputParser(pydantic_object=Person)
# 创建错误修复包装器
fixing_parser = OutputFixingParser.from_llm(
parser=parser,
llm=llm
)
# 创建提示模板 - 故意使用较弱的提示以演示错误修复
prompt = ChatPromptTemplate.from_messages([
("system", "请提供一个人物的信息。"),
("user", "描述'{character}'的信息。")
])
# 构建链
chain_with_fixing = prompt | llm | fixing_parser
try:
# 调用链并打印结果
result = chain_with_fixing.invoke({
"character": "马云"
})
print("修复后的结果:")
print(json.dumps(result.dict(), ensure_ascii=False, indent=2))
except OutputParserException as e:
print(f"解析错误: {e}")
# 示例5: 复杂嵌套JSON结构
def complex_nested_json():
"""复杂嵌套JSON结构示例"""
print("\n=== 示例5: 复杂嵌套JSON结构 ===")
# 定义更复杂的模型
class Address(BaseModel):
street: str = Field(description="街道名称")
city: str = Field(description="城市")
country: str = Field(description="国家")
class Contact(BaseModel):
email: str = Field(description="电子邮件")
phone: Optional[str] = Field(description="电话号码", default=None)
class Employee(BaseModel):
name: str = Field(description="员工姓名")
position: str = Field(description="职位")
address: Address = Field(description="地址信息")
contact: Contact = Field(description="联系方式")
skills: List[str] = Field(description="技能列表")
projects: Dict[str, str] = Field(description="项目名称和描述")
# 创建Pydantic解析器
complex_parser = PydanticOutputParser(pydantic_object=Employee)
format_instructions = complex_parser.get_format_instructions()
# 创建提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "请生成符合以下格式的JSON数据:\n{format_instructions}"),
("user", "创建一个名为'{name}'的技术领导者的详细信息。")
])
# 构建链
chain = prompt | llm | complex_parser
# 调用链并打印结果
result = chain.invoke({
"format_instructions": format_instructions,
"name": "张三"
})
print(json.dumps(result.dict(), ensure_ascii=False, indent=2))
if __name__ == "__main__":
print("LangChain JSON格式化输出示例")
print("="*50)
# 运行各示例
basic_json_output()
pydantic_structured_output()
streaming_json_output()
error_handling_and_fixing()
complex_nested_json()
print("\n所有示例执行完毕")