Agent开发快速入门
说明 本文档面向有Python基础的人群,旨在帮助大家快速了解Agent开发流程,掌握大模型调用。 Pyhton版本建议>3.12, 推荐使用uv作为包管理器(学习阶段pip也可以) |
前置准备工作
开发环境
uv工具安装参考:https://docs.astral.sh/uv/getting-started/installation/
Python开发通常会建立虚拟环境,uv也可以管理虚拟环境。
再准备一个称手的IDE工具用于编写代码和调试
大模型资源
由于网络和政策问题,国内无法使用OpenAI的服务,需要准备一个国内大模型平台的大模型密钥和API调用信息,用于替代OpenAI。国内大模型基本都兼容OpenAI协议。
初始化
项目开始前,先找个路径纯英文的目录(例如:D:\project\llm\demo),使用uv进行初始化
Shell # 使用uv创建虚拟环境,目录为.venv uv venv .venv |
在当前目录在创建.env文件存放OpenAI的密钥信息,文档格式内容如下:
TOML OPENAI_API_KEY=sk-e12629bxxxxxxxx OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 |
OPENAI_API_KEY 第三方大模型服务平台的密钥
OPENAI_BASE_URL 第三方大模型服务平台提供的请求路径,示例为阿里百炼平台
Agent入门
首先安装Langchain相关包:
Langchain: 官方包
Langchain-openai: OpenAI提供对接langchian的包(也可以接其他模型,比较通用)
Langchain-community: 社区包,包含一些工具
langgraph: 官方包
Shell uv add langchain langchain-openai langchain-community langgraph |
1.大模型最简单的使用
安装完成后来实现第一个示例。通过最简单的调用大模型提问,测试大模型是否正确加载。代码如下:
Python import os
from dotenv import load_dotenv from langchain_openai import ChatOpenAI
# 加载配置文件为环境变量 load_dotenv()
# 创建大模型调用对象 llm = ChatOpenAI( model="qwen-flash", # 必须是平台支持的模型名称 api_key=os.getenv("OPENAI_API_KEY"), # 可以省略 base_url=os.getenv("OPENAI_BASE_URL"), # 可以省略 )
# 发起对话 response = llm.invoke("你好!你用的是什么模型?") # 查看响应结果 print(response.content) |

2.创建Agent并定义角色
直接使用大模型对象提问是没有任何角色定义的,很多时候我们希望大模型是某一类类型的角色,因此需要给他定义角色信息。下面的代码展示了如何通过系统提示词来限制大模型的行为。
Python from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import create_agent
# 加载配置文件为环境变量 load_dotenv()
# 创建大模型调用对象(因为设置了环境变量,这里省略了api_key和base_url参数) llm = ChatOpenAI(model="qwen-flash")
# 使用大模型对象,创建一个Agent,并且设置角色信息 agent = create_agent( model=llm, system_prompt="你是快快网络公司的AI助手,你的名字叫:快快知己", )
# 提问。注意格式,role代表这句话是用户发起的问题,content代表提问内容 response = agent.invoke({"messages": [{"role": "user", "content": "你好,你叫什么名字?"}]}) print(response["messages"][-1].content) |

3.让Agent调用工具
Agent最强大的地方是它可以调用工具来和外部进行数据交互。现在就给大模型添加工具,让他来获取信息。
Python from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import create_agent from langchain.tools import tool
# 加载配置文件为环境变量 load_dotenv()
# 创建大模型调用对象(因为设置了环境变量,这里省略了api_key和base_url参数) llm = ChatOpenAI(model="qwen-flash")
# 创建函数并使用装饰器修饰为大模型可调用的工具,模拟获取用户信息功能 @tool def get_user_name(user_id: str) -> str: """通过用户ID获取用户名称""" user_map = { "uid_123": "张三", "uid_456": "李四", "uid_789": "老七", } return user_map.get(user_id, "未知用户")
# 使用大模型对象,创建一个Agent,并且设置角色信息 agent = create_agent( model=llm, tools=[get_user_name], system_prompt="你是快快网络公司的AI助手,你的名字叫:快快知己", )
# 提问。注意格式,role代表这句话是用户发起的问题,content代表提问内容 response = agent.invoke({"messages": [ {"role": "assistant", "content": "当前用户ID:uid_456"}, {"role": "user", "content": "你知道我的名字是什么吗?"}, ]}) print(response["messages"][-1].content) |

在这个示例中,调用大模型时传入了两句话:
当前用户ID:uid_456,这句话的角色为assistant,代表这是系统提示信息
你知道我的名字是什么吗, 这句话是用户的问题
因为两句话是一起发送的,大模型在处理问题会根据已有信息(用户ID、可用的根据)去调用工具获取结果
并非所有大模型都能调用工具 早期的大模型基本都不能调用工具,因此模型本身的能力非常重要!选择模型时一定要确认模型能力。 |
4.让Agent输出指定格式
很多时候大模型输出的都是文本信息,而我们可能想要的是json格式数据,这个时候我们就需要对输出格式进行限制。在Langchain 1.0版本之后,这个实现变得容易很多,只需要定义格式并将其传给agent对象即可。以意图识别为例:
Python from dataclasses import dataclass from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import create_agent
# 加载配置文件为环境变量 load_dotenv()
# 创建大模型调用对象(因为设置了环境变量,这里省略了api_key和base_url参数) llm = ChatOpenAI(model="qwen-flash")
# 定义需要大模型返回的数据结构 @dataclass class Intent: """意图识别结果结构体""" intent: str # 意图识别结果 reason: str # 原因
system_prompt = """ 你的任务是根据用户问题,分析用户意图,并且给出原因。 意图分类如下: - `knowledge`: 知识库检索查询,企业相关信息查询时为此意图 - `drawing`: AI会话,当用户明确表示需要绘制图片时分类为此意图 - `chat`: 普通聊天,闲聊,打招呼等所有不属于上面的情况都是chat """
# 使用大模型对象,创建一个Agent,并且设置角色信息 agent = create_agent( model=llm, system_prompt=system_prompt, response_format=Intent )
# 提问。注意格式,role代表这句话是用户发起的问题,content代表提问内容 response = agent.invoke({"messages": [ {"role": "user", "content": "帮我画一张蓝天白云的画?"}, ]}) print(response['structured_response']) |

需要注意的是最后获取结果的时候,不再是从 messages中获取聊天内容,而是从structured_response 中获取返回的对象。从输出的对象信息来看,意图识别正确,并且给出了分析原因。
实际项目中的提示词都比较长,不是一两句简单的文字,因此,可以将系统提示词单独写在其他地方,便于管理。提示词支持Markdown格式,也支持普通文本,甚至可以使用json格式。 |
5.给Agent添加记忆能力
大模型本身是没有记忆效果的,需要我们手动添加记忆能力,如果不添加记忆能力,每次对话都是一个全新会话,它完全不记得前面的学习,给人的体验非常不好。
没有添加记忆能力时的效果:
Python from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import create_agent
load_dotenv()
llm = ChatOpenAI(model="qwen-flash") agent = create_agent( model=llm, system_prompt="你是快快网络公司的AI助手,你的名字叫:快快知己", )
# 首次提问,告诉大模型我的名字 response = agent.invoke({"messages": [ {"role": "user", "content": "你好,我叫张三,你叫什么呢?"}, ]}) print(f"首次提问后的回答:{response["messages"][-1].content}")
# 再次提问,询问大模型是否还记得我的信息 response = agent.invoke({"messages": [ {"role": "user", "content": "你知道我叫什么吗?"}, ]}) print(f"再次提问后的回复:{response["messages"][-1].content}") |
回复内容:
Plain Text 首次提问后的回答:你好呀,张三!我是快快网络公司的AI助手,你可以叫我快快知己哦~很高兴认识你!有什么我可以帮你的吗?😊 再次提问后的回复:嗨,亲爱的用户!我是快快知己,不过我还不知道你的名字呢~ 你可以告诉我你的名字吗?这样我就能用更亲切的方式和你聊天啦!*开心地眨眨眼* |
可以看到第二次再问的时候它就不记得之前的信息了。
现在来给大模型添加记忆能力
Python from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import create_agent from langgraph.checkpoint.memory import InMemorySaver
load_dotenv() checkpointer = InMemorySaver() # 创建内存记忆对象 config = {"configurable": {"thread_id": "uid_123"}} # 创建配置项,用于设置会话信息,将使用thread_id来关联上下文
llm = ChatOpenAI(model="qwen-flash") agent = create_agent( model=llm, system_prompt="你是快快网络公司的AI助手,你的名字叫:快快知己", checkpointer=checkpointer # 设置检查点,这里会保存历史对话记录来提供记忆能力 )
# 首次提问,告诉大模型我的名字 response = agent.invoke({"messages": [ {"role": "user", "content": "你好,我叫张三,你叫什么呢?"}, ]}, config=config) print(f"首次提问后的回答:{response["messages"][-1].content}")
# 再次提问,询问大模型是否还记得我的信息 response = agent.invoke({"messages": [ {"role": "user", "content": "你知道我叫什么吗?"}, ]}, config=config) print(f"再次提问后的回复:{response["messages"][-1].content}") |
添加记忆的步骤如下:
创建检查点,用于处理对话记录,示例中使用的是Langchain提供的简单对象,实际可能需要存储到数据库
配置统一的会话ID,在每次调用大模型时都需要传递配置信息以确保关联上
在创建agent时设置检查点信息,以此来保存对话记录
最后执行效果:

6.流式响应(Stream)
普通的invoke调用方式是要等待大模型全部处理完成后再一起输出。而流式调用是只要有结果了就开始输出。
当工具调用较慢,或者大模型深度思考时间较长时,等待时间会很久,给用户的体验并不好。因此,大部分应用都会使用流式输出方式来提升用户体验。
下面是一个流式输出的示例:
Python import time
from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import create_agent
load_dotenv()
llm = ChatOpenAI(model="qwen-flash") agent = create_agent( model=llm, system_prompt="你是快快网络公司的AI助手,你的名字叫:快快知己", )
# 设置stream模式为messages,即按照token进行流式输出 chunks = agent.stream({"messages": [ {"role": "user", "content": "你好,我叫张三,你叫什么呢?"}, ]}, stream_mode="messages")
# 有新的token产生时及时打印,并且延迟0.2秒,后输出下一个token,这能更清晰看出流式更新效果 for token, metadata in chunks: print(token.content, end='', flush=True) time.sleep(0.2) |
这个示例允许时就能看到文字是一个一个出来的,而不是所有结果一起出现,并且这种方式的等待时间很短,几乎是刚执行就开始出现结果了。
综合演练