首页 / 资讯中心 / 文章详情

Langchain简单快速上手教程(三)—— 聊天模型之工具调用

Langchain简单快速上手教程(三)—— 聊天模型之工具调用 ★ FEATURED ARTICLE
前言在讲述了如何用Langchain的接口来进行聊天模型的定义后我们本期来具体介绍聊天模型中的工具。一、聊天模型的工具定义工具调用根本作用是让大语言模型LLM具备与外部世界交互的能力。工具调用打破了LLM因受限于其训练数据存在滞后性和内在的文本生成逻辑无法执行直接计算、查询实时信息、操作数据库或调用任何外部 API的壁垒使其获得更多权限与能力。一创建工具1、使用 tool 装饰器创建工具这种方式需要注意以下几点该装饰器默认使用函数名称作为工具名称。该装饰器将使用函数的文档字符串作为工具的描述。而函数名、类型提示和文档字符串都是传递给工具 Schema 的⼀部分不可缺失。Schema 是一个描述工具的Json串。1依赖 Pydantic 类模式from langchain_core.tools import tool from pydantic import BaseModel,Field class AddInput(BaseModel): 两数相加 x : int Field(...,description第一个整数) y : int Field(...,description第二个整数) tool(args_schemaAddInput) def add(x:int,y:int)-int: return xy值得注意的是代码中 tool 的 args_schema 参数其表示工具函数在未提供描述、文档字符串等需要传递给工具 Schema 的内容时依赖 Pydantic 类使用 args_schema 参数来定义并提供工具输⼊参数的schema默认为 None。2依赖 Annotated依赖 Annotated 和文档字符串传递给工具 Schema。tool def add( x:Annotated[int,...,第一个整数], y:Annotated[int,...,第二个整数], )-int: 两数相加 Args: x: 第一个整数 y: 第二个整数 return x y print(add.invoke({x:1,y:2})) print(add.name) print(add.description) print(add.args)2、使用 StructuredTool 类提供的函数创建工具class langchain_core.tools.structured.StructuredTool 这个类使用来初始化工具的可以用其中的 from_function 类方法通过给定的函数来创建并返回一个工具。from_function 的具体参数可查看此处。1常规方法使用from_function 类方法同样要将函数名、类型提示和文档字符串传递给工具 Schema 。from langchain_core.tools import StructuredTool def add(x:int,y:int)-int: 两数相加 Args: x: 第一个整数 y: 第二个整数 return x y add_tool StructuredTool.from_function(func add) print(add_tool.invoke({x:1,y:2}))2依赖 Pydantic 类我们同样可以用Pydantic 类来传递所需信息传递给 Schema 。from langchain_core.tools import StructuredTool from pydantic import BaseModel, Field from pydantic_core.core_schema import arguments_schema class addInput(BaseModel): x:int Field(...,description第一个整数) y:int Field(...,description第二个整数) def add(x:int,y:int)-int: return xy add_tool StructuredTool.from_function( func add, description两数相加, arguments_schemaaddInput ) print(add_tool.invoke({x:1,y:2}))3加入 response_format 配置设想如果我们让大模型读取content的同时将一些用来构造 content 的原始数据保存下来当后续有⼀些记录、分析的步骤就可以派上用了。而部分这就是artifact。而artifact 通常需要使用字典 Dict 或列表 List 保存。通过artifact里存放的原生数据我们能更有效地做日志记录、分析或自定义后续的处理。因此我们可以在工具区中分消息内容content和其他工件artifact需要在定义工具时指定 response_formatcontent_and_artifact 参数并确保我们返回一个元组 (content, artifact)。from langchain_core.tools import StructuredTool from pydantic import BaseModel, Field class addInput(BaseModel): x:int Field(...,description第一个整数) y:int Field(...,description第二个整数) def add(x:int,y:int)-tuple[str,list[int]]: nums [x,y] content f{nums} 相加结果是{xy} return content,nums add_tool StructuredTool.from_function( func add, description两数相加, arguments_schemaaddInput, response_formatcontent_and_artifact, ) print(add_tool.invoke( { name: add, args: {x: 3, y: 6}, type: tool_call, # 必填 id: 111, # 必填用来将工具调用请求和结果关联起来 } ))在链Chain中⼯具调用之后的其他组件或函数可能需要工具的原始且结构化数据即artifact 来执行特定操作。而这些大量数据不适合直接交给LLM所以artifact 里的数据其实是为了给链中后续的组件或函数使用的。二绑定与调用工具为了实际将这些⼯具绑定到聊天模型可以使用聊天模型的 .bind_tools() 方法。tool def add( x: Annotated[int,...,第一个整数], y: Annotated[int,...,第二个整数], )-int: 两数相加 return x y tool def multiply( x:Annotated[int,...,第一个整数], y:Annotated[int,...,第二个整数], )-int: 两数相乘 return x * y model ChatOpenAI( model deepseek-v4-flash, api_keyos.environ.get(DEEPSEEK_API_KEY), base_urlhttps://api.deepseek.com, ) # 绑定工具 tools [add, multiply] model_with_tools model.bind_tools(toolstools)同时.bind_tools()方法所返回的是一个Runnable实例所以我们可以用调用 .invoke() 方法完成工具的调用。工具调用 的⼀个关键原则是模型根据输入的相关性决定何时使用⼯具。模型并不总是需要调用工具。所以如果给定一个不相关的输入模型不会调用该工具。当然如果我们想让模型强制调用工具那就需要在绑定工具时设置 tool_choiceany 表示强制调用至少一个工具。model_with_tools model.bind_tools(toolstools,tool_choiceany)此时可通过两种不同的工具绑定方式来让模型来调用工具看一下效果。print(model_with_tools.invoke(2乘以3等于多少?)) # print(model_with_tools.invoke(who are you?)) # 模型在没有强制选择工具的情况下会根据问题来决定是否使用工具三工具与聊天模型的交互在这之前我们都是将工具与聊天模型进行绑定后让聊天模型对工具进行调用但大模型没有使用到工具的结果来进行问题的处理。此时就需要将工具输出传递给聊天模型。1、工具的属性在将工具输出传递给聊天模型之前我们要了解工具的属性以及工具的具体输出是什么。我们知道.invoke()的输出结果是一个 AIMessage如果调用了工具则 输出结果里将具有一个 tool_calls 属性。此属性包括执行该工具所需的一切包括工具名称和输入参数。2、将工具输出传递给聊天模型要将工具输出传递给聊天模型就要包括 HumanMessage、AIMessage 工具调用、ToolMessage。而聊天模型会根据以上消息输入将最终结果 AIMessage 返回。import os from langchain_core.messages import HumanMessage from langchain_openai import ChatOpenAI from typing_extensions import Annotated from langchain_core.tools import tool tool def add( x: Annotated[int,...,第一个整数], y: Annotated[int,...,第二个整数], )-int: 两数相加 return x y tool def multiply( x:Annotated[int,...,第一个整数], y:Annotated[int,...,第二个整数], )-int: 两数相乘 return x * y model ChatOpenAI( model deepseek-v4-flash, api_keyos.environ.get(DEEPSEEK_API_KEY), base_urlhttps://api.deepseek.com, ) # 绑定工具 tools [add, multiply] model_with_tools model.bind_tools(toolstools) # 定义消息列表添加要传递给聊天模型的消息 messages [ HumanMessage(2乘以3等于多少6加3等于多少) ] ai_msg model_with_tools.invoke(messages) # print(ai_msg) messages.append(ai_msg) # 构造ToolMessage,并添加到消息列表中去 for tool_call in ai_msg.tool_calls: selected_tool {add:add,multiply:multiply}[tool_call[name].lower()] tool_msg selected_tool.invoke(tool_call) messages.append(tool_msg) print(messages) print(model_with_tools.invoke(messages).content)通过运行上面的代码我们发现实际上我们调用了两次聊天模型。第一次仅将【 HumanMessage 】发送给聊天模型进行处理结果返回了【包含⼯具调用的AIMessage】然后执行工具得到 ToolMessage 。第二次将【HumanMessage AIMessage ToolMessage 】消息记录发送给聊天模型进行处理结果返回了【包含结果的 AIMessage 】。四LangChain 提供的工具我们除了可以自己写的工具LangChain 官⽅也已经给我们提供了很多现成的工具Tool和工具包Toolkit具体见官网此处。同时我们也可以去官网查找里面工具的具体说明与使用方法具体见官网此处。结语以上就是在Langchain中如何具体给聊天模型绑定工具与调用工具的内容了。如果喜欢我的内容请点赞、收藏加关注多多支持我以及欢迎各位在评论区讨论交流并指出我的不足谢谢大家
阅读完成 · 觉得有帮助?
咨询建站