第三章:集成外部工具的智能对话代理

3.1 为何需要工具集成?

虽然语言模型具备强大的对话能力,但它们无法直接访问外部信息或执行计算任务。集成工具后,代理可以:

  • 📚 查询实时资料(如 Tavily 搜索)
  • 🧮 执行数学计算
  • 📈 调用第三方 API 获取天气、新闻、股票等
  • 🧠 模拟“认知插件”,扩展智能体功能边界

3.2 DialogueAgentWithTools 架构概览

DialogueAgentWithTools 是对 DialogueAgent 的扩展,支持使用工具链进行任务处理

关键属性

  • tools: 工具列表(由 LangChain 的 Tool 对象构成)
  • model: 可使用工具的模型(如 ChatOpenAI + tool_calling 支持)

3.3 工具类构建

工具对象需满足 LangChain 的 Tool 接口规范。以 Tavily 搜索为例:

from langchain.tools.tavily_search import TavilySearchResults

search_tool = TavilySearchResults()

注册后,可用于任何支持调用工具的 LLM,如 ChatOpenAI


3.4 DialogueAgentWithTools 类定义

from langchain.agents import Tool
from langchain.agents.format_scratchpad.openai_tools import format_to_openai_tool_messages
from langchain_core.messages import ToolMessage

class DialogueAgentWithTools(DialogueAgent):
    def __init__(self, name, system_message, model, tools):
        super().__init__(name, system_message, model)
        self.tools = tools

    def send(self) -> str:
        messages = [self.system_message] + format_to_openai_tool_messages(self.message_history)
        response = self.model.invoke(messages)
        
        # 判断是否调用了工具
        if hasattr(response, "tool_calls") and response.tool_calls:
            for tool_call in response.tool_calls:
                tool_name = tool_call["name"]
                tool_input = tool_call["args"]
                tool = next((t for t in self.tools if t.name == tool_name), None)
                if tool:
                    tool_output = tool.invoke(tool_input)
                    self.message_history.append(
                        ToolMessage(tool_call_id=tool_call["id"], content=str(tool_output))
                    )
        return response.content

3.5 工具调用流程详解

  1. 生成请求消息格式(格式化为 OpenAI 工具调用标准)
  2. 识别响应中的工具调用指令
  3. 匹配工具对象并执行调用
  4. 将工具返回结果包装为 ToolMessage 添加回对话历史

📌 注意:需要使用支持工具调用的 ChatOpenAI 实例,并确保工具类实现了 nameinvoke(input) 接口。


3.6 系统配置示例

from langchain_openai import ChatOpenAI
from langchain.agents import Tool
from langchain.tools.tavily_search import TavilySearchResults

tools = [TavilySearchResults()]
model = ChatOpenAI(model="gpt-4", temperature=0, tools=tools)

agent = DialogueAgentWithTools(
    name="Researcher",
    system_message=SystemMessage(content="你是一个信息收集型助手,可以调用工具获取信息"),
    model=model,
    tools=tools,
)

3.7 小贴士:工具调试与提示优化

🛠 调试建议:

  • 给每个工具定义唯一 name,便于调用识别
  • 在 system_message 中说明工具用途,帮助模型合理选择
  • 限制工具数量,防止模型调用冲突或混淆

🧠 提示优化:

你可以调用一个名为 `search` 的工具来查找信息。只有在你不知道答案或需要实时资料时再使用它。

3.8 多代理工具对话示例

设置两个代理,一个负责辩论,另一个负责引用外部信息支持观点:

agent_a = DialogueAgentWithTools(
    name="DebaterA",
    system_message=SystemMessage(content="你是支持立场的辩论者,可以使用工具搜索支持证据。"),
    model=model,
    tools=tools
)

agent_b = DialogueAgent(
    name="DebaterB",
    system_message=SystemMessage(content="你是反对立场的辩论者,不可使用外部工具。"),
    model=ChatOpenAI(),
)

agents = [agent_a, agent_b]
simulator = DialogueSimulator(agents, round_robin)
simulator.inject("Moderator", "请围绕‘AI 是否有助于教育公平’展开讨论。")

for _ in range(6):
    speaker, message = simulator.step()
    print(f"{speaker}: {message}")

3.9 练习区:自定义工具与调用逻辑

🎯 目标任务

  1. 自定义一个返回当前时间的工具(CurrentTimeTool)
  2. 集成到 DialogueAgentWithTools 中
  3. 编写提示语,引导模型在需要时调用该工具

示例提示:

如果你需要当前的系统时间,请调用名为 `current_time` 的工具。

示例工具定义:

from langchain.agents import Tool
import datetime

def current_time_func(_):
    return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

current_time_tool = Tool(name="current_time", func=current_time_func, description="返回当前系统时间")

3.10 本章小结

在本章中,你学习了如何:

  • 扩展 DialogueAgent 以支持工具调用
  • 构建与集成外部工具(如 Tavily 搜索)
  • 理解工具调用的完整流程
  • 实现具备认知与任务执行能力的代理
Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐