一、聊天模型--定义工具

        LLM本身是封闭的知识系统,为解决直接计算、查询实时信息、操作数据库或调⽤任何外部 API等问题可以进行工具调用实现与外界交互

1.1创建工具

(1)@tool+python函数

注:

#定义时要有函数名、类型提⽰和⽂档字符串,相当于工具的三个属性:工具名称、工具参数、工具描述
#这些信息会传给工具schema进行相关内容的匹配和校验
#Schema 就是描述其他数据结构的声明格式,⽤于⾃动验证数据⽽存在。
#为什么要有这些属性字段:
#相当于在调用LLM时给大模型的提示词,使调用更加高效准确
#工具名称:让LLM知道有哪些工具可以调用
#工具描述:相当于提示词,告诉模型工具具备哪些能力,让LLM知道调谁
#工具参数:让LLM知道怎么调用工具

a.定义工具属性1--常规
@tool
def add (a:int, b:int)->int: #加法工具
    """
    两数相加
    Args:
        a : 一个整数
        b : 另一个整数
    """
    return a + b
print(add.invoke({"a": 2, "b": 3}))
print(add.description)
print(add.name)
print(add.args)
b.定义工具属性2--Pydantic类(分离描述、参数)
# 方式二
class AddInput(BaseModel): #类中定义函数描述和参数描述
    """两数相加"""

    a: int = Field(..., description="第一个整数")#...表示必填字段
    b: int = Field(..., description="第二个整数")


@tool(args_schema=AddInput)
def add(a: int, b: int) -> int:
    return a + b
c.定义工具属性3 -- 依赖Annotated(参数类型与描述)
@tool
def add(
        a : Annotated[int, ..., "第一个整数"], #...表示必填字段
        b : Annotated[int, ..., "第二个整数"],
) -> int:
    """两数相加

    Args:
        a: 第一个整数
        b: 第二个整数
    """
    return a + b
注:工具属性在任何方式定义都不能省略
(2)使⽤ StructuredTool 类提供的函数创建⼯具

用法:

classmethod from_function(
    func: Callable | None = None,
    coroutine: Callable[[...], Awaitable[Any]] | None = None,
    name: str | None = None,
    description: str | None = None,
    return_direct: bool = False,
    args_schema: type[BaseModel] | dict[str, Any] | None = None,
    infer_schema: bool = True,
    *,
    response_format: Literal['content', 'content_and_artifact'] = 'content',
    parse_docstring: bool = False,
    error_on_invalid_docstring: bool = False,
    **kwargs: Any,
) → StructuredTool

参数:

a.定义1--常规
# 方式一:
def add(a: int, b: int) -> int:
    """两数相加"""
    return a + b

add_tool = StructuredTool.from_function(func=add)
b.定义2 --Pydantic类
#方式二:
class AddInput(BaseModel):
    a:int = Field(description="第一个整数")
    b:int = Field(description="第二个整数")


def add(a: int, b: int) -> int:
    return a + b

add_tool = StructuredTool.from_function(
    func=add,
    name="ADD",             # 工具名
    description="两数相加",   # 工具描述
    args_schema=AddInput,   # 工具参数
)
c.加⼊ response_format 配置,调整回复方式

对于想要追求看过程的问题我们就必须在回复上加上过程

class AddInput(BaseModel):
    a:int = Field(description="第一个整数")
    b:int = Field(description="第二个整数")

#调整回复方式,改为结果 + 过程元组
def add(a: int, b: int) -> Tuple[str, List[int]]:
    nums = [a, b]
    content = f"{nums}相加的结果是{a + b}"
    return content, nums

# response_format将结果与过程元组分离
add_tool = StructuredTool.from_function(
    func=add,
    name="ADD",             # 工具名
    description="两数相加",   # 工具描述
    args_schema=AddInput,   # 工具参数
    response_format="content_and_artifact"
)

# 模拟大模型调用姿势
print(add_tool.invoke(
    {
        "name": "ADD",
        "args": {"a": 3, "b": 4},
        "type": "tool_call",  # 必填
        "id": "111",  # 必填, 用来将工具调用请求和结果关联起来。
    }
))

1.2绑定工具.bind_tools()

为了实际将这些⼯具绑定到聊天模型,可以使⽤聊天模型的 .bind_tools() ⽅法

from langchain_openai import ChatOpenAI
# 定义⼤模型
model = ChatOpenAI(model="gpt-4o-mini")
...
# 绑定⼯具,返回⼀个 Runnable 实例
tools = [add, multiply]
model_with_tools = model.bind_tools(tools)

定义:
bind_tools(
tools: Sequence[dict[str, Any] | type | Callable | BaseTool],
*,
tool_choice: dict | str | Literal['auto', 'none', 'required', 'any'] | bool
| None = None,
) → Runnable

参数:

返回值:

1.3调用工具

        通过 .bind_tools() ⽅法我们可知,它返回了⼀个 Runnable 实例,因此我们可以使⽤该 Runnable 实例,调⽤ .invoke() ⽅法,完成⼯具调⽤。

        ⼯具调⽤的⼀个关键原则是,模型根据输⼊的相关性决定何时使⽤⼯具。模型并不总是需要调⽤⼯具

        本质工具的调用其实分为工具的选择和工具的使用。

(1)绑定好的工具返回一个Runnable实例在.invoke输出后返回的是AIMessage,(并没有输出的结果)

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from typing_extensions import Annotated
# 定义⼤模型
model = ChatOpenAI(model="gpt-4o-mini")

@tool
def add(
    a: Annotated[int, ..., "First integer"],
    b: Annotated[int, ..., "Second integer"]
) -> int:
    """Add two integers."""
    return a + b

@tool
def multiply(
    a: Annotated[int, ..., "First integer"],
    b: Annotated[int, ..., "Second integer"]
) -> int:
    """Multiply two integers."""
    return a * b

# 绑定⼯具
tools = [add, multiply]
model_with_tools = model.bind_tools(tools)

# 调⽤⼯具
result = model_with_tools.invoke("9乘6等于多少?")
print(result)

(2)该返回结果包含一个tool_calls属性,包含要调用的工具名称,工具参数等信息

model_with_tools = model.bind_tools(tools, tool_choice="any")
result = model_with_tools.invoke("9乘6等于多少?")
print(result.tool_calls)

根据该属性进行选择后再进行.invoke()返回一个ToolMessage(包含结果)将我们的问题HumanMessage,AIMessage,ToolMessage集体再传给大模型输出后才是我们想要的形式输出

#HumanMessage
messages = [
HumanMessage("9乘6等于多少?5加3等于多少?")
] 

#AIMessage
ai_msg = model_with_tools.invoke(messages)
messages.append(ai_msg)

#选择进行使用工具返回ToolMessage
for tool_call in ai_msg.tool_calls:
    # 根据⼯具名选择对应⼯具函数(不区分⼤⼩写)
    selected_tool = {"add": add, "multiply": multiply}[tool_call["name"].lower()]
    # 执⾏⼯具调⽤,返回 ToolMessage
    tool_msg = selected_tool.invoke(tool_call)

# 将 ToolMessage 加⼊消息
messages.append(tool_msg)
print(messages)

result = model.invoke(messages)
print(result)

1.4LangChain提供的工具

        angChain 官⽅也已经给我们提供了很多现成的⼯具(Tool)和⼯具包(Toolkit)。
LangChain 提供的⼯具⻅这⾥。写好的⼯具⼀般都是为了使⽤ LangChain 中集成的三⽅组件或⼯具⽽创造的,有搜索、数据库、⽹⻚浏览器等相关的⼯具。

        示例:TavilySearch 类可以⽀持我们进⾏搜索,Tavily 是⼀个专⻔为 AI 设计的搜索引擎,专为智能体检索与推理需求量⾝打造的⼯具

注:需要pip安装所需的包pip install -U langchain-tavily

        并在官网申请API添加到环境变量中

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain_tavily import TavilySearch

# 定义⼤模型
model = ChatOpenAI(model="gpt-4o-mini")
# 绑定⼯具
tool = TavilySearch(max_results=4) # max_results 返回的最⼤搜索结果
model_with_tools = model.bind_tools([tool])

# 添加AIMessage到消息中去
messages = [
    HumanMessage("中国西安今天的天⽓怎么样?")
] 

ai_msg = model_with_tools.invoke(messages)
messages.append(ai_msg)
for tool_call in ai_msg.tool_calls:
    # 执⾏⼯具调⽤,返回 ToolMessage
    tool_msg = tool.invoke(tool_call)
    # 将 ToolMessage 加⼊消息
    messages.append(tool_msg)
result = model_with_tools.invoke(messages)
print(result.content)

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐