(几乎)任一LLM在bind_tools时,都是习惯先定义一个Function或BaseTool,然后再bind(bind_tools)具体方式可参考我的这篇文章
AI菜鸟向前飞 — LangChain系列之十三 - 关于Tool的必知必会
但这里的tool未必需要Function或BaseTool,例如,BaseModel也可以
通过convert_to_openai_function把转换成dict(也有人称json),再bind也行,我的公众号也有描述这种方式
BaseModel(Pydantic)
-
bind_tools
先定义
# 我们首先定义一个BaseModel
class Info(BaseModel):
""" 个人信息 """
nickname: str = Field(description="昵称")
name: str = Field(description="真实姓名")
age: int = Field(description="年龄")
然后绑上
llm_bound_tool = llm.bind_tool(Info)
# 居然也可以绑定,不报错,你猜猜为啥...
# 调用一下看看效果
llm_bound_tool.invoke("'Song榆钱儿',你的真实个人信息资料是什么呢")
输出结果
(此处省略一些没必要的内容)
id='run-23ddbdbb-126e-4ab5-af19-85d0d3a41416-0' tool_calls=[{'name': 'Info', 'args': {'age': 0, 'name': '', 'nickname': "'Song榆钱儿'"}, 'id': '8a7a9fb949094ca1953db76891864157'}]
观察:跟平时你bind普通的function很类似吧
-
Agent
再看看用Agent行不行
agent = create_tool_calling_agent(llm=llm, tools=[Info], prompt=prompt)
# 调用一下试试
agent.invoke({"input": "'Song榆钱儿',你的真实个人信息资料是什么呢", "intermediate_steps": []})
输出结果
(此处省略一些没必要的内容)
'tool_calls': [{'id': 'eb5e268e468b49478ed158715328a8e0', 'function': {'name': 'Info', 'arguments': '{"age": 0, "name": "", "nickname": "\'Song\\u6986\\u94b1\\u513f\'"}'}, 'type': 'function'}], 'token_count': {'output_tokens': 17}} id='run-1bd63fff-047c-4ffd-b7bd-004122bafd1d-0' tool_calls=[{'name': 'Info', 'args': {'age': 0, 'name': '', 'nickname': "'Song榆钱儿'"}, 'id': '60be844b22e743279fa7f56314625510'}]
其实,通过Agent源码你就能看到
虽然在函数传参的时候,必须指定,但暂时看来“无所谓”。。。
-
最后一种
为了实现Tool,还可以用coze的方式,请参考我的这篇文章
AI菜鸟向前飞 — 属于你的AI机器人(无需编码篇)
可以用Python的方式调用即可
就不演示了, GPTs也类似这种
本篇结语
再回到LangChain用到BaseModel的作用,基本上都是结构化输入或者输出, 有些资料告诉你,可以通过create_openai_fn_runnable,这个函数在0.1版本已经过时
现在更多推荐使用with_structured_output的方式实现,如下所示:
llm_with_output = llm.with_structured_output(Info)
res = llm_with_output.invoke("'Song榆钱儿',你的真实个人信息资料是什么呢")