【AI-agent】LangChain开发智能体工具流程

目录

  • [1 智能体开发流程概述](#1 智能体开发流程概述)
  • [2 使用LangChain调用大模型](#2 使用LangChain调用大模型)
    • [2.1 大模型实例化](#2.1 大模型实例化)
    • [2.2 初始化提示词模板](#2.2 初始化提示词模板)
      • [2.2.1 文本提示词模板PromptTemplate](#2.2.1 文本提示词模板PromptTemplate)
      • [2.2.2 聊天提示词模板ChatPromptTemplate](#2.2.2 聊天提示词模板ChatPromptTemplate)
      • [2.2.3 提示词及消息体的抽象复用](#2.2.3 提示词及消息体的抽象复用)
      • [2.2.4 少样本提示词模板FewShotPromptTemplate](#2.2.4 少样本提示词模板FewShotPromptTemplate)
      • [2.2.5 常用提示词模板类特性及使用场景对比](#2.2.5 常用提示词模板类特性及使用场景对比)
    • [2.3 链式调用大模型](#2.3 链式调用大模型)
  • [3 自定义工具](#3 自定义工具)
    • [3.1 绑定自定义工具流程](#3.1 绑定自定义工具流程)
    • [3.2 tool装饰器注册工具及使用args_schema控制工具入参](#3.2 tool装饰器注册工具及使用args_schema控制工具入参)
  • 写在最后

1 智能体开发流程概述

开发一个智能体,本质上就是让AI具备"思考-行动-反馈"的循环能力。简单来说,我们需要让AI能够:

  1. 调用大模型进行推理(包含合适的提示词模板)
  2. 使用各种工具(比如搜索、计算、文件操作等)
  3. 根据结果做出决策,然后继续执行下一步操作

下面,我们将从"查询城市天气"的例子出发,看下如何使用LangChain开发一个简单的智能体

2 使用LangChain调用大模型

2.1 大模型实例化

使用 LangChain 实例化大模型,并将 api_key 使用 Pydantic 的 SecretStr 类型加密。其中,Pydantic 是一个基于 Python 类型注解的数据验证库,主要用于确保数据符合预期的格式和类型。

python 复制代码
from langchain_openai import ChatOpenAI
import os
from dotenv import load_dotenv
from pydantic import SecretStr


# 加载.env文件中的环境变量
load_dotenv()

llm = ChatOpenAI(
    model="qwen-flash",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=SecretStr(os.getenv("DASHSCOPE_API_KEY")),
    streaming=True
)

print(llm)

2.2 初始化提示词模板

示例如下:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate


prompt = ChatPromptTemplate.from_prompt([
    ("system", "你是一名经验丰富的Python开发工程师, 名字叫小黄"),
    ("human", "{user_input}")
])

2.2.1 文本提示词模板PromptTemplate

PromptTemplate 是 LangChain 框架中的核心组件,用于结构化和管理与语言模型交互的提示文本。它通过模板化的方式动态生成提示,支持变量插入和格式化。

适用场景:

  • 用于文本补全模型,输入是纯文本
  • 适用于简单的任务,如生成一段文本、回答问题或执行指令

特点:

  • 输入变量插值:通过{}占位符动态替换变量
  • 模板格式:支持f-string
  • 输出形式:生成一个完整的字符串作为模型输入

示例代码:

python 复制代码
from langchain_core.prompts import PromptTemplate


# 创建提示词模板
prompt_template = PromptTemplate.from_template("你做的{something}真棒!")
# 模板 -> 提示词
prompt = prompt_template.format(something="程序")
print(prompt)

结合之前实例的大模型,传入生成的prompt就能实现如下效果:

2.2.2 聊天提示词模板ChatPromptTemplate

ChatPromptTemplate 是 LangChain 中专门用于 多轮对话场景 的提示模板,支持定义 角色(Role) 和 消息类型(Message),适用于构建聊天机器人、对话系统等需要上下文交互的应用。

适用场景:

  • 用于聊天模型(ChatGPT等),输入是多轮对话的消息列表(SystemMessage、HumanMessage、AIMessage等)
  • 适用于需要模拟多轮对话和角色扮演的场景

特点:

  • 多消息类型支持:可以组合系统指令、用户输入和助手回复
  • 消息格式化:生成结构化的消息列表,供聊天模型处理
  • 使用灵活:支持动态替换变量(如SystemMessage中的占位符)

示例代码:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
import os
from dotenv import load_dotenv
from pydantic import SecretStr


# 加载.env文件中的环境变量
load_dotenv()

llm = ChatOpenAI(
    model="qwen-flash",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=SecretStr(os.getenv("DASHSCOPE_API_KEY")),
    streaming=True
)

# 创建提示词模板
chat_prompt_template = ChatPromptTemplate.from_messages([
    ("system", "你是一位{role}专家, 擅长解决{domain}领域的问题"),
    ("user", "用户的问题:{question}")
])
# 模板 -> 提示词
prompt = chat_prompt_template.format_messages(
    role="Python编程",
    domain="AI-agent开发",
    question="如何创建一个简单的智能体?")
# 输入给AI模型, 获取结果
resp = llm.stream(prompt)
for chunk in resp:
    print(chunk.content, end="")

2.2.3 提示词及消息体的抽象复用

通过 ChatPromptTemplate 和 ChatMessagePromptTemplate 实现对消息体的抽象和复用。

示例代码:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, ChatMessagePromptTemplate
from langchain_openai import ChatOpenAI
import os
from dotenv import load_dotenv
from pydantic import SecretStr


# 加载.env文件中的环境变量
load_dotenv()

llm = ChatOpenAI(
    model="qwen-flash",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=SecretStr(os.getenv("DASHSCOPE_API_KEY")),
    streaming=True
)

# 系统消息模板
system_message_template = ChatMessagePromptTemplate.from_template(
    template="你是一位{role}专家, 擅长解决{domain}领域的问题",
    role="system"
)
# 用户消息模板
human_message_template = ChatMessagePromptTemplate.from_template(
    template="用户的问题:{question}",
    role="user"
)
# 创建提示词模板
chat_prompt_template = ChatPromptTemplate.from_messages([
    system_message_template,
    human_message_template
])
# 模板 -> 提示词
prompt = chat_prompt_template.format_messages(
    role="Python编程",
    domain="AI-agent开发",
    question="如何创建一个简单的智能体?")
# 输入给AI模型, 获取结果
resp = llm.stream(prompt)
for chunk in resp:
    print(chunk.content, end="")

2.2.4 少样本提示词模板FewShotPromptTemplate

适用场景:

  • 用于少样本学习,在提示词中包含示例,帮助模型理解任务
  • 适用于复杂任务(翻译、分类、推理等),需要引入来引导模型行为

特点:

  • 示例嵌入:通过 examples 参数提供示例输入和输出
  • 动态示例选择:支持 ExampleSelector 动态选择最相关的示例
  • 模板格式:通常包含前缀(Prefix)、示例(Examples)和后缀(Suffix)

示例代码:

python 复制代码
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_openai import ChatOpenAI
import os
from dotenv import load_dotenv
from pydantic import SecretStr


# 加载.env文件中的环境变量
load_dotenv()

llm = ChatOpenAI(
    model="qwen-flash",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=SecretStr(os.getenv("DASHSCOPE_API_KEY")),
    streaming=True
)

# 示例模板
example_template = "输入:{input}\n输出:{output}"

# 示例
examples = [
    {"input": "将'你好'翻译成英文", "output": "Hello"},
    {"input": "将'好的'翻译成英文", "output": "Ok"}
]

# 少样本提示词模板
few_shot_prompt_template = FewShotPromptTemplate(
    examples=examples,
    example_prompt=PromptTemplate.from_template(example_template),
    prefix="请将下面的中文翻译为英文:",
    suffix="输入:{text}\n输出:",
    input_variables=["text"]
)

prompt = few_shot_prompt_template.format(text="我热爱编程")
# print(prompt)

resp = llm.stream(prompt)
for chunk in resp:
    print(chunk.content, end="")

上述代码中传给llm的prompt如下:

请将下面的中文翻译为英文:

输入:将'你好'翻译成英文

输出:Hello

输入:将'好的'翻译成英文

输出:Ok

输入:我热爱编程

输出:

以下是调用llm后返回的结果,可以看到llm根据example进行了少样本学习,直接返回了翻译的结果。

2.2.5 常用提示词模板类特性及使用场景对比

子类 适用模型类型 输入类型 主要用途
PromptTemplate 文本补全模型 单字符串 生成单轮文本任务提示
ChatPromptTemplate 聊天模型 多消息列表 模拟多轮对话或角色扮演
FewShotPromptTemplate 所有模型 包含示例的模板 通过示例引导模型完成复杂任务

2.3 链式调用大模型

链式调用大模型(Chained LLM Invocation)是指将多个大模型相关的操作或组件通过某种连接方式串联起来,形成一个处理管道或工作流。这种模式允许数据在不同的处理阶段之间流动,每个阶段对数据进行特定的转换或处理。

链式调用的特点:

  • 模块化设计:将复杂任务分解为多个独立的处理模块
  • 数据流驱动:数据在各个组件之间顺序流动和处理
  • 可组合性:可以灵活地组合不同的组件来构建不同的处理流程
  • 可读性强:代码表达清晰,易于理解和维护

以下两段代码等价:

python 复制代码
chain = few_shot_prompt_template | llm
resp = chain.stream(input={"text": "你好"})
# 等价于以下步骤:
prompt = few_shot_prompt_template.format()  # 生成提示词
resp = llm.invoke(prompt)  

在表达式 chain = few_shot_prompt_template | llm 中,管道符 | 的作用是连接两个组件,形成数据流管道。数据流向 few_shot_prompt_template → | → llm → chain

链式调用代码示例:

python 复制代码
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_openai import ChatOpenAI
import os
from dotenv import load_dotenv
from pydantic import SecretStr


"""使用langchain链式调用大模型"""
# 加载.env文件中的环境变量
load_dotenv()

llm = ChatOpenAI(
    model="qwen-flash",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=SecretStr(os.getenv("DASHSCOPE_API_KEY")),
    streaming=True
)

# 示例模板
example_template = "输入:{input}\n输出:{output}"

# 示例
examples = [
    {"input": "将'你好'翻译成英文", "output": "Hello"},
    {"input": "将'好的'翻译成英文", "output": "Ok"}
]

# 少样本提示词模板
few_shot_prompt_template = FewShotPromptTemplate(
    examples=examples,
    example_prompt=PromptTemplate.from_template(example_template),
    prefix="请将下面的中文翻译为英文:",
    suffix="输入:{text}\n输出:",
    input_variables=["text"]
)

chain = few_shot_prompt_template | llm
resp = chain.stream(input={"text": "你好"})

for chunk in resp:
    print(chunk.content, end="")

3 自定义工具

3.1 绑定自定义工具流程

在第二章,我们了解了大模型实例,以及如何设计提示词,仅仅只实现了与大模型"对话",如果想让大模型帮助我们解决问题,还有至关重要的一步:将自定义工具与大模型绑定,让大模型了解工具的使用。主要有如下五个步骤:

  1. 开发工具方法
  2. 将工具方法转为LangChain Tool对象
  3. 将大模型与Tool对象绑定
  4. 调用大模型,尝试让大模型调用工具
  5. 调用工具

示例代码:

python 复制代码
from langchain_core.tools import Tool
from app.bailian.common import chat_prompt_template, llm


"绑定自定义工具"


# 1.开发自定义工具
def fetch_weather(city: str) -> str:
    """获取某个城市的真实天气"""
    # 模拟调用天气API逻辑...
    weather_data = {
        '北京': '多云',
        '深圳': '晴朗'
    }
    if city not in weather_data.keys():
        return '天气多变'
    return weather_data[city]


# 2.将工具方法转为LangChain Tool对象
fetch_weather_tool = Tool.from_function(
    func=fetch_weather,  # 与工具方法关联
    name='fetch_weather',  # 工具名, 唯一
    description='获取某个城市的真实天气',  # 工具说明
)
# 定义工具字典, value为python方法
tool_dict = {
    'fetch_weather': fetch_weather
}
# 3.将大模型与Tool对象绑定
llm_with_tool = llm.bind_tools([fetch_weather_tool])
# 链式声明
chain = chat_prompt_template | llm_with_tool
# 4.调用大模型
resp = chain.invoke(input={"role": "气象学", "domain": "天气领域", "question": "深圳天气怎么样?"})
print(resp)  # content='' additional_kwargs={} response_metadata={'finish_reason': 'tool_calls', 'model_name': 'qwen-flash', 'model_provider': 'openai'} id='lc_run--22c45fc8-81dd-49dc-bdea-aa7ef5288321' tool_calls=[{'name': 'fetch_weather', 'args': {'__arg1': '深圳'}, 'id': 'call_5bea195addc242cbafc984', 'type': 'tool_call'}]
# 5.调用工具
for tool_calls in resp.tool_calls:
    print(tool_calls)  # {'name': 'fetch_weather', 'args': {'__arg1': '深圳'}, 'id': 'call_a74fe41dae4d4b85a69ddb', 'type': 'tool_call'}
    args = tool_calls["args"]
    print(args)  # {'__arg1': '深圳'}
    func_name = tool_calls["name"]
    print(func_name)  # fetch_weather
    tool_func = tool_dict[func_name]
    tool_content = tool_func(args["__arg1"])
    print(tool_content)  # 晴朗

在上述代码中,我们粗略 实现了绑定自定义工具的流程。在示例中,我们定义了一个简单的查询城市天气的方法,并将方法与大模型绑定。而后,我们向大模型提问:"深圳天气怎么样?",大模型返回了使用工具的方法:

content='' additional_kwargs={} response_metadata={'finish_reason': 'tool_calls', 'model_name': 'qwen-flash', 'model_provider': 'openai'} id='lc_run--d2285936-24b3-435d-aca6-d3fde28111e7' tool_calls=[{'name': 'fetch_weather', 'args': {'__arg1': '深圳'}, 'id': 'call_4d384d81ae1548b1bd2cbf', 'type': 'tool_call'}]
大模型通过问题,判断出该用什么工具、怎么用工具,并将该信息返回(tool_calls),说明最终使用工具解决问题的不是大模型而是Agent!: 通过大模型返回的信息中的tool_calls['args']、tool_calls['name'],我们能提炼出解决问题该调用什么工具,传入什么参数。

3.2 tool装饰器注册工具及使用args_schema控制工具入参

上一节,粗略实现了llm调用自定义工具的流程,但还是有比较大的问题:

  1. 自定义工具方法参数没有类型规范
  2. 调用自定义工具时非常笨拙、粗糙,需要做一些类型转化、参数命名等,而我们更希望llm能帮我们处理这些问题

而这个需求,我们可以通过装饰器 @tool 装饰器实现:

@tool 是 LangChain 框架中的核心装饰器,用于将普通 Python 函数转换为大模型可以调用的工具(Tool),其主要作用如下:

  • 函数注册:将函数注册为大模型可调用的工具
  • 元数据提取:自动提取函数名、参数信息、文档字符串
  • 类型转换:将 Python 函数转换为 LangChain 的 Tool 对象

args_schema 是 @tool 装饰器的重要参数,用于定义工具参数的结构和验证规则,其主要作用如下:

  • 参数验证:确保传入参数符合预期格式
  • 类型安全:定义参数的数据类型和约束
  • 文档生成:为大模型提供清晰的参数说明
  • 默认值处理:支持参数默认值

使用示例如下:

python 复制代码
from langchain.tools import tool
from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    query: str = Field(description="搜索关键词")
    limit: int = Field(default=10, description="返回结果数量限制")

@tool(args_schema=SearchInput)
def search_web(input_data: SearchInput) -> str:
    """根据输入参数搜索网络信息"""
    return f"搜索结果: {input_data.query}, 限制: {input_data.limit}"
    

对于3.1中实现的demo,引入tool装饰器后,修改后的示例代码如下:

python 复制代码
from langchain_core.tools import tool
from app.bailian.common import chat_prompt_template, llm
from pydantic import BaseModel, Field


"绑定自定义工具-使用tool装饰器"


class FetchWeatherInputArgs(BaseModel):
    city: str = Field(description="城市名称")


# 1.开发自定义工具, 并注册tool
@tool(
    description="获取某个城市的真实天气",
    args_schema=FetchWeatherInputArgs
)
def fetch_weather(city: str) -> str:
    """获取某个城市的真实天气"""
    # 模拟调用天气API逻辑...
    weather_data = {
        '北京': '多云',
        '深圳': '晴朗'
    }
    if city not in weather_data.keys():
        return '天气多变'
    return weather_data[city]


# 定义工具字典, value为python方法
tool_dict = {
    'fetch_weather': fetch_weather
}
# 3.将大模型与Tool对象绑定
llm_with_tool = llm.bind_tools([fetch_weather])
# 链式声明
chain = chat_prompt_template | llm_with_tool
# 4.调用大模型
resp = chain.invoke(input={"role": "气象学", "domain": "天气领域", "question": "深圳天气怎么样?"})
# 5.调用工具
for tool_calls in resp.tool_calls:
    # 获取要调用的参数和工具
    args = tool_calls["args"]
    func_name = tool_calls["name"]
    tool_func = tool_dict[func_name]
    # 调用工具
    tool_content = tool_func.invoke(args)
    print(tool_content)  # 晴朗

写在最后

本文已被专栏 AI agent实战开发 收录,欢迎 点击订阅专栏

以上便是本文的全部内容啦!创作不易,如果你有任何问题,欢迎私信,感谢您的支持!

相关推荐
出门吃三碗饭2 小时前
Transformer前世今生——使用pytorch实现多头注意力(八)
人工智能·深度学习·transformer
l1t2 小时前
利用DeepSeek改写SQLite版本的二进制位数独求解SQL
数据库·人工智能·sql·sqlite
说私域2 小时前
开源AI智能名片链动2+1模式S2B2C商城小程序FAQ设计及其意义探究
人工智能·小程序
开利网络3 小时前
合规底线:健康产品营销的红线与避坑指南
大数据·前端·人工智能·云计算·1024程序员节
非著名架构师3 小时前
量化“天气风险”:金融与保险机构如何利用气候大数据实现精准定价与投资决策
大数据·人工智能·新能源风光提高精度·疾风气象大模型4.0
熙梦数字化4 小时前
2025汽车零部件行业数字化转型落地方案
大数据·人工智能·汽车
刘海东刘海东4 小时前
逻辑方程结构图语言的机器实现(草稿)
人工智能
亮剑20184 小时前
第2节:程序逻辑与控制流——让程序“思考”
开发语言·c++·人工智能
hixiong1234 小时前
C# OpenCVSharp使用 读光-票证检测矫正模型
人工智能·opencv·c#