Pydantic + Function Calling的结合
1、Pydantic
Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括:
- 数据验证:通过类型注解自动验证输入数据。
- 数据转换:将原始数据转换为指定的 Python 类型(如 JSON → 模型实例)。
- 编辑器支持:与 IDE 类型提示完美兼容。
- JSON 序列化:快速将模型转换为 JSON 或字典。
数据验证
from pydantic import BaseModelclass User(BaseModel):id: intname: str = "John Doe"email: str
输入数据会自动验证类型,无效数据会引发 ValidationError
:
user_data = {"id": "123", "email": "user@example.com"} # 类型错误(id 应为 int)
user = User(**user_data) # 报错:id 不是整数
修正后:
user_data = {"id": 123, "email": "user@example.com"}
user = User(**user_data) # 成功创建实例
print(user.name) # 输出默认值 "John Doe"
JSON 序列化
将模型转换为 JSON 或字典:
user = User(id=123, email="user@example.com")
print(user.json()) # 输出 JSON 字符串
print(user.dict()) # 输出 Python 字典
2、使用Pydantic 构建Function Calling
function_calling的格式
{"type": "function","function": {"name": "get_current_weather","description": "当你想查询指定城市的天气时非常有用。","parameters": {"type": "object","properties": {"location": {"type": "string","description": "城市或县区,比如北京市、杭州市、余杭区等。",}},"required": ["location"]}}
}
使用Pydantic 构建
from langchain_core.utils.function_calling import convert_to_openai_function
from pydantic import BaseModel, Fieldclass Text_tag(BaseModel):tag: str =Field(description="文本情感类别:取值为 `pos`(正面)、`neg`(负面)或 `neutral`(中性)")lan: str = Field(description="文本语言")tag_fn =convert_to_openai_function(Text_tag)
print(tag_fn)
输出结果:
{'name': 'Text_tag', 'description': '', 'parameters': {'properties': {'tag': {'description': '文本情感类别:取值为 `pos`(正面)、`neg`(负面)或 `neutral`(中性)', 'type': 'string'}, 'lan': {'description': '文本语言', 'type': 'string'}}, 'required': ['tag', 'lan'], 'type': 'object'}}
调用模型并绑定函数
以天气查询为例:
class Getlocation(BaseModel):"""通过地点获取天气信息"""weather_data: str = Field(..., description="获取天气信息的地点")weather_function=convert_to_openai_function(Getlocation)model = ChatOpenAI(model="qwen-turbo",base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",api_key=os.getenv("DASHSCOPE_API_KEY"))
prompt = ChatPromptTemplate.from_messages([("system","你是一个有用的助手"),("user","{input}")
])result =model.invoke("旧金山天气如何?", functions=[weather_function])
得到结果:
content='' additional_kwargs={'function_call': {'arguments': '{"weather_data": "旧金山"}', 'name': 'Getlocation'}, 'refusal': None} response_metadata={'token_usage': {'completion_tokens': 19, 'prompt_tokens': 176, 'total_tokens': 195, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'qwen-turbo', 'system_fingerprint': None, 'id': 'chatcmpl-35d6656d-14a1-907f-8886-f45ad6f26619', 'service_tier': None, 'finish_reason': 'function_call', 'logprobs': None} id='run--2882f85d-6023-4c0c-bf67-376caee8ef6e-0' usage_metadata={'input_tokens': 176, 'output_tokens': 19, 'total_tokens': 195, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
与工具函数配合使用
def get_weather(code: str) -> str:return f"Weather in {code}: 30°C"class Getlocation(BaseModel):"""通过地点获取天气信息"""weather_data: str = Field(..., description="获取天气信息的地点")model = ChatOpenAI(model="qwen-turbo",base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",api_key=os.getenv("DASHSCOPE_API_KEY"))
prompt = ChatPromptTemplate.from_messages([("system","你是一个有用的助手"),("user","{input}")
])
weather_function=convert_to_openai_function(Getlocation)
# 调用模型,绑定函数
result =model.invoke("旧金山天气如何?", functions=[weather_function])获取结果,调用工具
if result.additional_kwargs and 'function_call' in result.additional_kwargs:func_args = result.additional_kwargs["function_call"]["arguments"]location_code=eval(func_args).get("weather_data")weather_info =get_weather.invoke(location_code)print(f"查询结果: {weather_info}")
输出结果:
查询结果: Weather in 旧金山: 30°C