Langchain的Agent智能体开发
基于Python+Langchain的Agent智能体开发
1 | # 智能体概念与技术全景 |
学习目标
1 | # 理解传统程序与智能体(Agent)的本质区别1 |
掌握Agent”感知→决策→行动”核心能力闭环2
认识现代Agent技术栈关键组件3
识别典型应用场景和技术演进方向4
1 | # 传统程序与智能体的区别 |
传统程序: 输入固定指令,输出固定结果
智能体:更像一个拥有‘思考能力’的智能助手
传统程序示例:计算器
Agent智能体示例:个人助手
1 | def calculator(a, b, operator): |
Agent核心能力
1 感知引擎: 像人类的眼睛耳朵
自然语言理解(如‘帮我订个便宜酒店’→解析为{动作:预定,对象:酒店,条件:低价})
多模态输入(文本/语音/图像)
2 决策大脑: 像人类的思考判断
基于LLM的推理能力
工具选择策略(调用API、搜索知识库等)
1 | def personal_agent(user_input): |
自动判断需查天气
1 | 10 |
代际核心技术局限性
第一代规则引擎+固定模板只能处理预设问题
第二代NLP模型+意图识别无法执行复杂操作
第三代LLM+工具调用+记忆系统全能但需优化稳定性
3 执行器官: 像人类的手脚
API调用(获取实时数据)
工具执行(操作外部系统)
输出生成(文本/语音/图像响应)
技术演进
从2016年的Siri到至今的Agents,技术栈大致经历了三次革新:
当前最先进的Agent架构:
1 | # 决策流程伪代码 |
return
1 | call_weather_tool(user_input) |
# 使用LLM生成回复
1 | return llm_generate(user_input) |
应用场景
客服助手
数据分析专家
个人效率管家
“明早9点提醒我提交报告并推荐通勤路线” → 自动创建日历事项+查询实时交通
技术栈解析
现代Agent开发四大支柱技术:
1 大语言模型(LLM) - 大脑皮层
主流选择:GPT-4, Claude,Llama 3,DeepSeek
作用:理解、推理、内容生成
1 | 2 工具调用(Tool Calling) |
3 记忆系统(Memory) - 海马体
1 |
|
解决LLM知识静态性问题
实时获取最新信息
传统程序 vs Agent对比分析
1 | # 传统程序(固定流程) |
Agent工作流程
1 | # 智能体常用技术-LLM |
学习目标
了解什么是LLM1
LLM 介绍
LLM(大语言模型,Large Language Model) 就像一个超级聪明
的“语言大脑”,它是通过海量文本数据训练出来的人工智能模型,
能理解和生成类似人类语言的文字。简单点说,它是个会聊天、能
回答问题、写文章、甚至帮你出主意的智能助手。
LLM 核心
LLM 是一个基于深度学习的神经网络,训练时“读”了无数的书、文
章、网页,学会了语言的规律和知识。
LLM 功能
它能干很多事,比如:
回答问题(“明天北京天气咋样?”)
生成文本(写故事、代码、邮件)
翻译、总结、分析文本
推理(比如帮你分析“为啥我的计划总失败”)
LLM 例子
像 GPT-4、Claude、Llama 、DeepSeek 、Gemini Flash都是当下
主流的 LLM,课程里提到的这些就是 Agent 的“大脑皮层”。
LLM 与 Agent 关系
在智能体(Agent)开发中,LLM 是核心的“思考”部件,负责:
理解:听懂你说的话,搞清楚你的意图。
推理:想办法解决问题,比如判断要不要查天气或算个数。
生成:输出自然、好懂的回答。
注意
LLM 也有短板,比如:
知识可能不是最新的(训练数据到某天就截止了)
不能直接调外部工具(像查实时数据)
这时候就需要课程里提到的其他技术(工具调用、RAG、记忆
系统)来辅助,组成一个完整的 Agent
1 | # 智能体常用技术-Langchain |
学习目标
了解什么是Langchain1
Langchain文档
LangChain中文网:https://www.langchain.com.cn/
Langchain 介绍
LangChain 是一个开源框架,简单来说,它帮开发者更方便地构建
基于大语言模型(LLM)的智能应用。把它想象成一个“工具箱”,专
门用来让 Agent(智能体)更聪明、更能干。它不是 Agent 本身,
而是让 Agent 开发更顺手的工具集合。
Langchain 作用
LangChain 解决的是 LLM 的一些“短板”,让 Agent 能干更多事,比
如:
连接外部数据:LLM 脑子里装的知识是静态的,LangChain 能让它去查数据库、搜网页、调 API,
获取最新信息。
记东西:它能帮 Agent 记住对话上下文(短期记忆)或者用户偏好(长期记忆),让交互更个性
化。
用工具:LangChain 让 Agent 能调用各种工具,比如计算器、天气 API,甚至跑 Python 代码。3
复杂任务拆解:它能把用户的大需求(比如“帮我计划旅行”)拆成小步骤,逐步搞定。4
Langchain 与Agent关系
LangChain 很像 Agent 的“万能工具箱”,但没那么“万能”。它提供
了很多现成的模块,比如:
链(Chains):把多个操作串起来,比如先理解用户意图,再查数据,最后生成回答。
工具(Tools):让 Agent 能用外部功能,比如搜索、计算、翻译。
记忆(Memory):存对话历史或用户数据。
检索(RAG):从知识库或网上抓最新信息。
但它也有局限:
不是开箱即用:得开发者自己搭配合适的模块和 LLM。
性能依赖 LLM:如果底层的 LLM 不够强,LangChain 再好也有限。
复杂场景还得定制:比如超复杂的任务流,可能还得自己写代码。
1 | 10 |
核心优势
无需重造轮子,标准化开发流程
举个例子
假如想让 Agent 回答“明天北京天气咋样?”,LangChain 可以:
帮 Agent 理解你的问题(感知)。1
决定调用天气 API(决策)。2
去调 API 查数据,再把结果整理成一句人话(行动)。 整个过程就像给 Agent 配了个“工具箱”,让
它能自己找工具、干活。
总结
LangChain 确实像 Agent 的“工具箱”,帮它接外部世界、记东
西、干复杂活儿,但不是万能的,得看你怎么用它和 LLM 配合
Langchain环境搭建-通义模型
学习目标
了解配置Langchain环境搭建1
了解接入模型的流程2
环境配置
1 创建虚拟环境
2 安装Langchain包
3 注册API的Key
不同的运营商,有不同的注册方式。在这以通义为例子。
地址:
大模型服务平台百炼控制台:https://bailian.console.aliyun.co
m/#/home
1 | conda create -n agent_env python=3.121 |
创建Key: https://bailian.console.aliyun.com/?tab=model#/ap
1 |
|
Tongyi
1 | key = 'sk-603a62' |
个水果名称就好’)
1 | print(info) |
Langchain环境搭建-其它模型
模型支持链接:https://www.langchain.com.cn/docs/integration
s/providers/
学习目标
了解接入模型的流程1
安装模块
示例代码
1 | # 智谱AI |
AIMessage, HumanMessage, SystemMessage
1 | import os |
“2cb2ef28c37b42f38c2f7329795aba4b.8CFwsx98t0
TxNaag”
1 | 14 |
Langchain环境搭建-本地模型
学习目标
了解接入模型的流程1
1 | chat = ChatZhipuAI( |
SystemMessage(content=”你是一个助手,请以中
1 |
|
1句话回复即可。”),
1 | ]) |
了解如何使用本地模型2
下载Ollama
地址:https://ollama.com/download
安装Ollama
1 | 16 |
下载模型
命令:
模型参考:
deepseek-r1:1.5b (1.1GB): 约 2-4GB 显存
deepseek-r1:7b (4.7GB): 约 10-12GB 显存
deepseek-r1:8b (5.2GB): 约 12-16GB 显存
deepseek-r1:14b (9.0GB): 约 20-24GB 显存
deepseek-r1:32b (20GB): 约 40-50GB 显存
deepseek-r1:70b (43GB): 约 80-100GB 显存
deepseek-r1:671b (404GB): 约 700-800GB 显存
注意:
这些数值是理论估算,实际需求可能因优化技术(如 4-bit 量化可减半显存需求)而降低。
大模型(如 70b 和 671b)通常需要多 GPU 或分片加载。
确保 GPU 显存充足,否则可能无法运行或需要调整配置。
模块安装
代码示例
ollama run deepseek-r1:1.5b1
1 | pip install "langchain-ollama==0.3.3"1 |
Langchain关键对象-提示词模板
学习目标
了解 提示词模板 的作用1
了解 提示词模板 的使用方式2
1 | from langchain_ollama import ChatOllama |
(“system”,”你是个饮食健康专家,请根据用户的输
入给出相应的建议。”),
(“human”, “夏天吃什么水果合适?”),
1 | response = llm.invoke(messages) |
response
1 | 10 |
介绍
LangChain 的提示词模板引擎(Prompt Template Engine)是其
核心组件之一,主要用于构建和管理与大语言模型(LLM)交互的
提示词(Prompt)。
它的作用是将用户的输入或动态数据结构化地嵌入到预定义的模板
中,从而生成适合模型处理的提示词,提升模型输出的准确性和一
致性
示例
方法1:
1 | key= '506b011ee51c4a82833' |
之间。 值越小,随机性越低
1 | 10 |
方法2:
1 | template = '你是一个{role},请用{style}风格回答问 |
PromptTemplate.from_template(template)
1 | # 变量的填充 |
‘style’:’通俗易懂’, ‘question’:’勾股定理是什
么?’})
1 | # 模型响应数据 |
答问题”
1 | user_template = "请用简单易懂的方式解释: |
{question}”
1 | # 创建对话模板 |
Langchain关键对象-输出格式化
学习目标
了解 输出格式化 的作用1
了解 输出格式化 的使用方式2
介绍
在 LangChain 中,输出格式化(Output Parsing)是关键功能之
一,用于将大语言模型(LLM)的原始输出(通常是自由格式的文
本)解析为结构化的数据格式,如 JSON、字典或自定义对象。这不
仅便于后续处理,还能提高输出的可读性和一致性。
示例
1 | 22 |
(response_schemas)
1 | # 创建提示模板,包含格式化指令 |
提取姓名和年龄,并以 JSON 格式返回:
1 | 10 |
文本:{input_text}
{format_instructions}”””
1 | prompt = PromptTemplate( |
{“format_instructions”:
1 | output_parser.get_format_instructions()} |
填充输入
input_text = “张三今年25岁,来自北京。”
filled_prompt =
prompt.format(input_text=input_text)
调用模型
response = chat.invoke(filled_prompt)
parsed_output =
1 | output_parser.parse(response.content) |
print(parsed_output)
输出示例: {“name”: “张三”, “age”: 25}
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from langchain.output_parsers import
PydanticOutputParser
from pydantic import BaseModel, Field
定义 Pydantic 模型
class Person(BaseModel):
name: str = Field(description=”人的姓名”)
age: int = Field(description=”人的年龄”)
24
创建 Pydantic 输出解析器
output_parser =
PydanticOutputParser(pydantic_object=Person)
创建提示模板
template = “””你是一个信息提取助手,请从以下文本中
1 |
|
{“format_instructions”:
1 | output_parser.get_format_instructions()} |
填充输入
input_text = “李四今年30岁,住在上海。”
filled_prompt =
prompt.format(input_text=input_text)
调用模型
response = chat.invoke(filled_prompt)
parsed_output =
1 | output_parser.parse(response.content) |
print(parsed_output)
输出示例: Person(name=”李四”, age=30)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
25
1 |
|
了解什么是链式调用
了解如何使用链式调用
介绍
在 LangChain 中,LLMChain 是一个核心对象,用于实现基于大语
言模型(LLM)的链式调用。它将提示词模板(Prompt
Template)、语言模型(LLM)以及可选的输出解析器(Output
Parser)组合在一起,形成一个可重复执行的流程,简化了与 LLM
的交互。
LLMChain 的核心组件
1 PromptTemplate:
定义提示词的模板,包含占位符(如 {input}),用于动态生成提示词。
示例:”请用{style}风格解释:{question}”
2 LLM:
1 | 大语言模型(如 ChatZhipuAI、OpenAI 等),负责根据提示词生成输出。 |
3 OutputParser(可选):
用于将 LLM 的原始文本输出解析为结构化格式(如 JSON、列表)。
1 | 示例:StructuredOutputParser 或 PydanticOutputParser。 |
4 Memory(可选):
可集成上下文记忆(如 ConversationBufferMemory),支持对话历史管理
示例
from langchain.chains import LLMChain
1 | from langchain.prompts import PromptTemplate |
“506b011ee51c4a82833”
1 | chat = ChatZhipuAI(model="glm-4", |
(response_schemas)
1 | # 定义提示模板 |
答以下问题,并以 JSON 格式返回答案和置信度:
问题:{question}
{format_instructions}”””
1 | prompt = PromptTemplate( |
{“format_instructions”:
1 | output_parser.get_format_instructions()} |
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1 |
|
“style”: “通俗易懂”,
“question”: “勾股定理是什么?”
1 | }) |
边的平方等于两直角边平方之和,即 a² + b² = c²。’,
1 |
|
模式特点
1 | 普通输出(非流式)用户提交问题 → 等待几秒 → 一次性返回完整答案 |
流式输出用户提交问题 → AI边生成边显示 → 逐步输出答案
介绍
流式输出是指在用户输入问题后,AI模型边生成边显示响应内容,
逐步展示AI的”思考”过程,而不是等待所有内容生成完毕后再一次
性返回完整答案
与传统非流式输出相比,流式输出的差异如下表所示:
示例
1 | from langchain.output_parsers import |
(response_schemas)
1 | # 定义提示模板 |
答以下问题,并以 JSON 格式返回答案和置信度:
问题:{question}
{format_instructions}”””
1 | 10 |
Langchain记忆系统-ConversationBufferMemory
1 | prompt = PromptTemplate( |
{“format_instructions”:
1 | output_parser.get_format_instructions()} |
llm_chain = prompt | chat
chunks = []
运行链
for chunk in llm_chain.stream({
1 |
|
chunks.append(chunk)
1 | print(chunk.content,end='',flush=True) |
学习目标
了解为什么使用记忆系统
了解ConversationBufferMemory的特点与使用
为什么需要记忆系统
与LLM对话系统中,每次交互(调用API)都是独立的”无状态”处理,
导致对话缺乏连贯性。LangChain的记忆系统通过以下方式解决这
个问题。
注意
虽然目前看到许多聊天机器人是有记忆的,是因为借助了代码
的帮助,提供了历史消息作为和LLM对话的上下文。
所以就可以基于之前所说过的会话内容,再生成新的内容。从
而感觉好像“记得”说过的话!
作用
上下文保持:记住用户之前的输入和系统的输出
个性化交互:存储用户偏好和关键信息(如姓名、职业等)
长期学习:积累历史交互数据用于改进后续响应
注意
随之历史内容的变多,tokens的数量也会变多,而平台的计费
方式往往是通过tokens的数量来计算的!!
ConversationBufferMemory(缓冲记忆)
完整存储所有对话历史,不做任何压缩或筛选
优点:保留全部细节,适合需要完整上下文的场景(如法律咨
询、复杂问题追踪)
1 | 32 |
缺点:Token消耗随对话线性增长,易超出模型上下文窗口限制
示例
ConversationBufferMemory
1 | from langchain import ConversationChain |
memory = ConversationBufferMemory()
1 | conversation = ConversationChain(llm=chat, |
员”)
1 | conversation.predict(input="你叫什么名字?") |
B 自动压缩对话历史以减少Token消耗
C 完整存储所有对话历史,不做压缩或筛选
D 只存储用户的输入,不保存系统的输出
答案
1 | 1=>B 2=>C |
Langchain记忆系统-ConversationBufferWindowMemory
学习目标
了解ConversationBufferWindowMemory的特点与使用
定义
ConversationBufferWindowMemory 是 LangChain 提供的一种记忆机制,它只
存储最近的 k 条对话记录(包括用户输入和模型输出)。这里的 k
是用户指定的窗口大小,表示保留多少轮对话(每轮对话包括一条
用户消息和一条模型响应)。当新的对话发生时,最旧的对话会被
移出窗口,确保内存和 Token 使用量保持在可控范围内。
1 | 34 |
特点
滑动窗口机制:只保留最近的 k 轮对话,新的对话会覆盖最早的对话记录。
固定内存占用:无论对话进行多久,内存中只存储固定数量的对话记录,Token 消耗不会随时间线
性增长。
可配置性:用户可以通过设置 k 参数控制窗口大小,灵活调整上下文的深度。
缺点
丢失早期上下文:由于只保留最近 k 条记录,早期的重要信息可能会被遗忘,影响对话的连贯
性。
不适合复杂场景:对于需要完整对话历史或长期依赖的场景(如法律咨询、长篇故事生成),效果
不如 ConversationBufferMemory 。
窗口大小选择困难:设置合适的 k 值需要权衡上下文完整性和资源消耗,过小的窗口可能导致信
息不足,过大的窗口则失去效率优势
示例
示例 1:基本使用
1 | from langchain.memory import |
ConversationBufferWindowMemory
1 | from langchain.chains import |
OpenAI 的 LLM
# 初始化 LLM(这里以 OpenAI 为例,需替换为实际模
型)
1 | llm = OpenAI(temperature=0.7) |
# 初始化 ConversationBufferWindowMemory,设置窗
1 | 口大小 k=2 |
memory = ConversationBufferWindowMemory(k=2)
1 | # 创建 ConversationChain |
输出示例(假设 LLM 的响应如下):
1 | # 模拟对话 |
字是小明”))
1 | print(conversation.predict(input="我是一个程序 |
员”))
1 | print(conversation.predict(input="你还记得我的 |
名字吗?”))
1 | print(conversation.predict(input="我的职业是什 |
么?”))
1 | # 查看内存中的对话历史 |
好的,小明,很高兴认识你!你今天有什么想聊的吗?
1 | > 我是一个程序员 |
哇,程序员!那你平时写什么语言的代码呢?
1 | > 你还记得我的名字吗? |
当然记得,你是小明,对吧?
1 | > 我的职业是什么? |
你是程序员!
当前内存中的对话历史:
1 | Human: 我是一个程序员 |
解析:
1 | k=2 表示只保留最近两轮对话(每轮包括用户输入和模型输出)。 |
第一次和第二次对话后,内存中存储了“小明”和“程序员”的信息。
第三次和第四次对话时,最早的对话(“你好,我的名字是小明”)被移出窗口,但模型仍能通过上
下文推断出名字(取决于 LLM 的能力)。
1 | memory.buffer 显示当前内存中只保留最近两轮对话。 |
示例 2:手动添加对话
1 | from langchain.memory import |
ConversationBufferWindowMemory
# 初始化 ConversationBufferWindowMemory,设置窗
1 | 口大小 k=3 |
memory = ConversationBufferWindowMemory(k=3)
1 | # 手动添加对话记录 |
{“output”: “您好!有什么可以帮助您的?”})
1 | memory.save_context({"input": "我喜欢编程"}, |
{“output”: “太棒了!您喜欢用哪种编程语言?”})
1 | memory.save_context({"input": "Python 是我的最 |
爱”}, {“output”: “Python 很强大!您用它做什么项
目?”})
1 | memory.save_context({"input": "我在做一个聊天机 |
器人”}, {“output”: “酷!像我这样的吗?😄”})
1 | # 查看当前内存中的对话历史 |
输出示例:
解析:
1 | k=3 表示保留最近三轮对话。 |
手动添加四轮对话后,最早的一轮(“你好!”)被移出窗口。
1 | memory.buffer 显示当前存储的对话历史,load_memory_variables 返回结构化的内存内容。 |
ConversationBufferWindowMemory?
A 需要保留完整对话历史的法律咨询场景
B 对 Token 消耗要求极高,需精确控制 Token 数量
C 长时间对话,需要总结早期内容以节省 Token
D 短时客服对话,只需记住最近几轮交互
1 | print(memory.load_memory_variables({}))18 |
当前内存中的对话历史:
1 | Human: 我喜欢编程 |
内存变量:
{‘history’: ‘Human: 我喜欢编程\nAI: 太棒了!您喜
欢用哪种编程语言?\nHuman: Python 是我的最爱\nAI:
Python 很强大!您用它做什么项目?\nHuman: 我在做一
个聊天机器人\nAI: 酷!像我这样的吗?😄’}
1 | 10 |
答案
1 | 1=>D |
LangChain 记忆系统 -ConversationTokenBufferMemory
学习目标
了解ConversationTokenBufferMemory的特点与使用
定义
ConversationTokenBufferMemory 是一种 LangChain 记忆机制,它根据
Token 数量(而非对话轮数)来限制存储的对话历史。用户可以指
定一个最大 Token 数(max_token_limit ),系统会保留不超过该限制的
最近对话内容。当新对话的加入导致 Token 总数超过限制时,最早
的对话记录会被自动移除,以保持总 Token 数在指定范围内。
1 | 39 |
特点
Token 驱动的截断:对话历史的截断基于 Token 数量,而非固定的消息条数,更加灵活。
模型适配性:需要指定所使用的 LLM 来计算 Token 数,因为不同模型的 Token 化规则可能不同
(如 OpenAI 的 GPT 模型与 LLaMA 模型的 Token 计算方式不同)。
动态窗口:不像 ConversationBufferWindowMemory 固定对话轮数,
ConversationTokenBufferMemory 的窗口大小随消息内容长度动态变化。
高效存储:仅保存不超过 max_token_limit 的对话内容,优化内存和计算资源使用。
缺点
依赖 LLM 模型:需要指定 LLM 的 Token 化规则,不同模型的 Token 计算方式可能导致不一致。1
可能丢失早期信息:当 Token 限制较严格时,早期的重要对话可能被截断,影响上下文完整性。2
设置复杂性:需要合理设置 max_token_limit ,否则可能导致信息不足或资源浪费。3
不适合需要完整历史的场景:对于需要长期依赖完整对话历史的复杂任务(如法律咨询、长篇叙
事),效果不如 ConversationBufferMemory
示例
示例 1:基本使用
1 | from langchain.memory import |
ConversationTokenBufferMemory
1 | from langchain.chains import |
# 初始化 LLM(这里以 OpenAI 为例,需替换为实际模
型)
1 | llm = OpenAI(temperature=0.7) |
# 初始化 ConversationTokenBufferMemory,设置最
大 Token 限制为 100
1 | memory = |
ConversationTokenBufferMemory(llm=llm,
1 | max_token_limit=100) |
输出示例(假设 LLM 的响应如下,实际 Token 数取决于模型的
Token 化规则):
1 | conversation = ConversationChain(llm=llm, |
字是小明”))
1 | print(conversation.predict(input="我是一个程序 |
员,喜欢用 Python”))
1 | print(conversation.predict(input="你还记得我的 |
名字吗?”))
1 | print(conversation.predict(input="我的职业是什 |
么?”))
1 | # 查看内存中的对话历史 |
好的,小明,很高兴认识你!你今天有什么想聊的吗?
1 | > 我是一个程序员,喜欢用 Python |
酷!Python 是个很棒的语言。你用它做什么项目?
1 | > 你还记得我的名字吗? |
当然记得,你是小明,对吧?
1 | > 我的职业是什么? |
你是程序员,喜欢用 Python!
当前内存中的对话历史:
1 | 10 |
解析:
1 | max_token_limit=100 表示内存中存储的对话历史总 Token 数不超过 100。 |
随着对话进行,早期对话(如“你好,我的名字是小明”)可能因 Token 超限被移除。
1 | memory.buffer 显示当前保留的对话历史,具体保留多少轮取决于每条消息的 Token 数。 |
llm 参数用于指定 Token 化规则,确保准确计算 Token 数量。
示例 2:手动添加对话
1 | Human: 你还记得我的名字吗? |
ConversationTokenBufferMemory
1 | from langchain.llms import OpenAI |
# 初始化 LLM
1 | llm = OpenAI(temperature=0.7) |
# 初始化 ConversationTokenBufferMemory,设置最
大 Token 限制为 50
1 | memory = |
ConversationTokenBufferMemory(llm=llm,
1 | max_token_limit=50) |
{“output”: “您好!有什么可以帮助您的?”})
1 | memory.save_context({"input": "我喜欢编程"}, |
{“output”: “太棒了!您喜欢用哪种编程语言?”})
1 | memory.save_context({"input": "Python 是我的最 |
爱”}, {“output”: “Python 很强大!您用它做什么项
目?”})
1 | 10 |
输出示例(实际输出取决于 Token 数):
解析:
1 | max_token_limit=50 限制对话历史总 Token 数不超过 50。 |
添加四轮对话后,早期对话(如“你好!”)因 Token 超限被移除。
1 | memory.buffer 和 load_memory_variables 显示当前保留的对话历史,具体保留内容取决于每条 |
消息的 Token 数。
ConversationBufferWindowMemory 的主要区别是什么?
A 前者存储完整对话历史,后者只存储固定轮数
B 前者根据 Token 数量限制对话,后者根据固定轮数限制
C 前者通过总结早期对话减少 Token,后者存储原始对话
D 前者无需指定 LLM,后者需要 LLM 计算 Token
答案
1 | 1=>B |
LangChain 记忆系统 -ConversationSummaryBufferMemory
定义
1 | 44 |
ConversationSummaryBufferMemory 是一种混合型记忆机制,结合了
ConversationBufferMemory 和 ConversationSummaryMemory 的优点。它的工作方式
如下:
近期对话:直接存储最近的对话内容(原始消息),以保留完整细节。
早期对话:当对话历史超过指定的 Token 限制(max_token_limit )时,系统会调用 LLM 将早期
对话总结为紧凑的文本,替换原始内容。
动态管理:通过总结早期对话并保留近期对话,保持上下文在 Token 限制内,同时尽量保留关键
信息。
这种机制通过智能压缩历史对话,减少 Token 消耗,同时仍能提供
长期上下文支持。
特点
混合存储机制:
近期对话以原始形式存储,确保细节完整。
早期对话被 LLM 总结为简洁的文本,保留关键信息。
Token 驱动的截断:当对话历史的 Token 数超过 max_token_limit
时,触发总结机制,移除最早的原始对话并替换为总结。
依赖 LLM 进行总结:需要一个 LLM 来生成对话总结,总结质量
取决于 LLM 的能力。
动态平衡:在完整细节(近期对话)和压缩信息(早期对话总
结)之间找到平衡,适合长期对话。
缺点
依赖 LLM 总结质量:总结的准确性和完整性取决于使用的 LLM,如果总结遗漏关键信息,可能影
响上下文连贯性。
额外计算开销:生成对话总结需要额外的 LLM 调用,增加计算成本和响应时间。2
复杂性较高:相比 ConversationBufferMemory 或 ConversationBufferWindowMemory ,实现和
调试更复杂。
不适合短对话:对于只需要短期上下文的场景,总结机制可能增加不必要的开销。4
示例
示例 1:基本使用
1 | from langchain.memory import |
ConversationSummaryBufferMemory
1 | 45 |
# 初始化 LLM(这里以 OpenAI 为例,需替换为实际模
型)
1 | llm = OpenAI(temperature=0.7) |
# 初始化 ConversationSummaryBufferMemory,设置
最大 Token 限制为 100
1 | memory = |
ConversationSummaryBufferMemory(llm=llm,
1 | max_token_limit=100) |
字是小明”))
1 | print(conversation.predict(input="我是一个程序 |
员,喜欢用 Python”))
1 | print(conversation.predict(input="我最近在做一 |
个聊天机器人项目”))
1 | print(conversation.predict(input="你还记得我的 |
名字和职业吗?”))
1 | # 查看内存中的对话历史 |
输出示例(假设 LLM 的响应和总结如下,实际输出取决于 Token
数和总结内容):
解析:
1 | max_token_limit=100 表示对话历史总 Token 数不超过 100。 |
早期对话(“你好,我的名字是小明”和“我是一个程序员,喜欢用 Python”)被总结为一句紧凑的文
本。
近期对话以原始形式保留,确保细节完整。
1 | memory.buffer 显示总结后的早期对话和原始的近期对话。 |
你好,我的名字是小明
1 |
|
酷!Python 是个很棒的语言。你用它做什么项目?
1 | > 我最近在做一个聊天机器人项目 |
听起来很有趣!你这个聊天机器人有什么特别的功能吗?
1 | > 你还记得我的名字和职业吗? |
当然记得!你是小明,一个喜欢用 Python 的程序员,正在
做一个聊天机器人项目,对吧?
当前内存中的对话历史:
1 | System: Summary: 小明介绍自己是一个程序员,喜欢用 |
Python。
1 | Human: 我最近在做一个聊天机器人项目 |
吗?
1 | Human: 你还记得我的名字和职业吗? |
员,正在做一个聊天机器人项目,对吧?
1 | 10 |
示例 2:手动添加对话
此示例展示如何手动向 ConversationSummaryBufferMemory 添加对话记录。
1 | from langchain.memory import |
ConversationSummaryBufferMemory
1 | from langchain.llms import OpenAI |
# 初始化 LLM
1 | llm = OpenAI(temperature=0.7) |
# 初始化 ConversationSummaryBufferMemory,设置
最大 Token 限制为 50
1 | memory = |
ConversationSummaryBufferMemory(llm=llm,
1 | max_token_limit=50) |
明”}, {“output”: “您好,小明!有什么可以帮助您
的?”})
1 | memory.save_context({"input": "我喜欢编程,用 |
Python”}, {“output”: “Python 很棒!您用它做什
么?”})
1 | memory.save_context({"input": "我在做一个聊天机 |
器人”}, {“output”: “酷!有什么特别功能吗?”})
1 | memory.save_context({"input": "你记得我的职业 |
吗?”}, {“output”: “你是程序员,喜欢用 Python,对
吧?”})
1 | # 查看当前内存中的对话历史 |
输出示例(实际输出取决于 Token 数和总结内容):
解析:
1 | max_token_limit=50 触发早期对话的总结,生成紧凑的摘要。 |
早期对话(“你好!我是小明”和“我喜欢编程,用 Python”)被总结为一句。
近期对话(最后两轮)以原始形式保留。
1 | memory.buffer 和 load_memory_variables 显示总结和原始对话的组合。 |
LangChain 文本嵌入模型
学习目标
了解文本嵌入模型作用与使用
什么是文本嵌入
文本嵌入(Text Embedding)是将文本(如单词、句子或段落)转换为固定长度的数值向量表
示。
这些向量捕捉文本的语义信息,相似语义的文本在向量空间中距离较近
1 | 50 |
例如:
“Hi there!” 和 “Oh, hello!” 的向量相似度高
“What’s your name?” 和 “My friends call me World” 的向量相似度较低
为什么需要文本嵌入
电脑不认识文字,对自然语言理解的不够。但它能算数字!通过这
些向量,电脑就能理解文字的含义
文本嵌入能做什么?
找相似内容:让电脑明白哪些文字意思接近,比如搜索的时候不只是找关键词,还能找到意思差不
多的内容。
分类文字:比如看一条评论是好评还是差评,电脑通过向量就能判断。
推荐东西:像推荐文章、电影啥的,基于内容的意思来推荐,而不是瞎猜。
跨语言也能搞:中文、英文都能转成向量,意思相近的还能凑一块儿。
示例
情感分析:评论是夸还是骂
场景:你开个网店,想知道客户评论是正面还是负面
1 | # 智普AI |
‘506b011ee51c4a828124883fa3604ecd.3kOXCerJRy
D5md33’
1 | os.environ["ZHIPUAI_API_KEY"] = key |
圾!”]
1 | labels = [1, 0] # 1是好评,0是差评 |
labels)
1 | # 测试新评论 |
LangChain 文本嵌入-本地模型
1 | 53 |
学习目标
了解如何搭建 本地文本嵌入模型 环境
了解如何使用 本地文本嵌入模型
模块下载
模型下载
1 | pip install langchain_huggingface==0.3.0 |
git clone https://huggingface.co/BAAI/bge-
small-zh-v1.5
1 | # 不能科学上网 |
git clone https://www.modelscope.cn/BAAI/bge-
small-zh-v1.5.git
1 | 54 |
示例
“政策文件.txt” 内容
中文文档加载与处理
公司年假政策:
员工工作满1年可享受5天带薪年假
年假有效期至次年3月31日
部门经理审批后方可使用
考勤制度:
工作日上班时间:9:00-18:00
迟到超过30分钟记为缺勤
1 | # 文件:embedding_demo.py |
中文标点分割
1 | 10 |
本地中文嵌入模型初始化
构建向量数据库
1 | splits = |
text_splitter.split_documents(documents)
1 | print(f"生成 {len(splits)} 个文本块,首段内容: |
\n{splits[0].page_content[:100]}…”)
1415
1 | 16 |
时使用
1 | encode_kwargs={"normalize_embeddings": |
True} # 提升相似度计算精度
1 | # 测试向量化 |
{vector[:5]}”)
1 | 10 |
LangChain工具-工具封装
学习目标
理解工具调用在智能体开发中的重要性
学会封装外部API为LangChain工具
1 | embedding=embeddings, |
为什么需要工具调用?
解决LLM的局限性:大语言模型存在”幻觉”问题(生成虚假信
息),且无法直接访问实时数据或执行具体操作
扩展能力边界:通过工具集成,Agent可以获得计算、API访
问、数据库查询等实际能力
模块化设计:将不同功能封装为独立工具,便于维护和复用
LangChain工具开发核心组件
1 |
用于将普通Python函数转换为LangChain工具
自动生成JSON Schema,描述工具的输入参数和功能
示例:
JSON Schema规范
工具的输入参数需要明确类型(如str 、int )
文档字符串(docstring)描述工具功能,Agent依靠此判断是否
调用
JSON Schema示例(自动生成):
1 | from langchain.tools import tool |
“””将两个数字相加”””
1 | return a + b |
LangChain工具-实战案例:天气查询工具
案例背景
目标:开发一个天气查询工具,供Agent调用
数据源:APISpace(免费,需注册获取API Key)
功能:输入城市名,返回实时温度和天气状况
环境准备
1 安装依赖:
2 获取API Key:
注册APIspace账户 https://www.apispace.com/
工具实现代码
以下是天气查询工具的完整实现:
1 | pip install requests |
“””返回城市编码和经纬度,格式固定为 int”””
1 | try: |
== city_name]
1 | if not match.empty: |
城市ID’]
1 | # 其次匹配城市 |
city_name]
1 | if not match.empty: |
城市ID’]
1 | # 模糊匹配 |
me, na=False)]
1 | if not match.empty: |
城市ID’]
1 | # 默认返回北京 |
LangChain工具-模型调用工具
1 | import re |
“””调用实时天气API,返回温度及天气状况
1 | 参数: |
“””
1 | try: |
city)[0]
1 | city_code= get_city_code(city) |
f”https://eolink.o.apispace.com/456456/weath
er/v001/now”
1 | headers = {"X-APISpace-Token": |
“h72uhbhva2t9s4k5ozrx23f8vmwqcds0”}
1 | response = requests.get(url, |
[‘realtime’][‘text’]}, 温度: {data[‘result’]
[‘realtime’][‘temp’]}°C”
1 | except Exception as e: |
学习目标
掌握模型如何调用工具
LangChain工具调用机制
LangChain通过@tool 装饰器将Python函数转换为Agent可调用的
工具
工具定义遵循JSON Schema规范,确保结构化输入与输出
Agent通过提示词(Prompt)决定何时调用哪个工具
流程:
用户输入 → Agent解析意图1
匹配工具 → 执行函数2
返回结果 → 整合到Agent响应3
示例
工具
1 | import pandas as pd |
“””返回城市编码和经纬度,格式固定为 int”””
1 | try: |
== city_name]
1 | if not match.empty: |
城市ID’]
1 | # 其次匹配城市 |
city_name]
1 | if not match.empty: |
城市ID’]
1 | # 模糊匹配 |
me, na=False)]
1 | if not match.empty: |
城市ID’]
1 | # 默认返回北京 |
调用工具
1 |
|
“””调用实时天气API,返回温度及天气状况
1 | 参数: |
“””
1 | try: |
city)[0]
1 | city_code= get_city_code(city) |
f”https://eolink.o.apispace.com/456456/weath
er/v001/now”
1 | headers = {"X-APISpace-Token": |
“h72uhbhva2t9s4k5ozrx23f8vmwqcds0”}
1 | response = requests.get(url, |
[‘realtime’][‘text’]}, 温度: {data[‘result’]
[‘realtime’][‘temp’]}°C”
1 | except Exception as e: |
检索增强生成-RAG
1 | # 1. 定义工具 |
Hub模板
1 | # 2. 创建Agent |
prompt)
1 | # 3. 创建AgentExecutor,作用是运行Agent |
“请告诉我上海的天气”,
“北京今天冷吗?”,
“帮我修电脑”
1 | for user_input in test_inputs: |
诉我上海的天气”}))
1 | 10 |
学习目标
了聊RAG的作用
了解RAG的工作原理
基本定义
1 | # RAG(Retrieval-Augmented Generation,检索增强生成)是一种 |
将信息检索与文本生成相结合的AI技术。例如,我们向 LLM 提问一
个问题,RAG 从各种数据源检索相关的信息,并将检索到的信息和
问题注入到 LLM 提示中,LLM 最后给出答案。
为什么有这个技术
当我们将大模型应用于实际业务场景时会发现,通用的基础大模型
基本无法满足我们的实际业务需求,主要有以下几方面原因:
知识的局限性
模型自身的知识完全源于它的训练数据,而现有的主流大模型的
训练集基本都是源于网络公开的数据,对于一些实时性的、非公
开的或离线的数据是无法获取到的,这部分知识也就无从具备。
幻觉问题
所有AI模型的核心基于数学概率,输出本质是一系列数值运算,
大模型也不例外。因此,在知识欠缺或不擅长的领域,大模型可
能一本正经地输出错误信息。这种“幻觉”问题难以辨别,因为它
要求使用者具备相关领域知识。
1 | 67 |
数据安全性
对企业而言,数据安全至关重要,没有企业愿意冒数据泄露风险
将私域数据上传至第三方平台进行训练。因此,完全依赖通用大
模型的应用方案往往需在数据安全与效果之间权衡。
RAG 的工作原理
RAG 的核心思想是在 LLM 回答用户问题之前,先进行一次信息检
索。这个过程通常分为以下几个主要步骤:
用户查询1
知识库2
检索3
增强提示词 4
生成5
想象你是一名学生,需要回答一道复杂的历史问题。
没有 RAG: 你只能凭记忆回答,如果问题超出了你的记忆范围,你可能会胡编乱造。
有了 RAG: 你会先去图书馆(知识库)查找相关的历史书籍(检索),然后阅读书中的相关章节
(增强),最后结合这些信息和自己的理解来回答问题(生成)。
RAG系统搭建实战
1 | 69 |
RAG系统搭建流程
收集数据
数据分块
选择文本嵌入模型
初始化向量数据库
存储向量
整合大语言模型 (LLM)
收集数据
数据分块
选择嵌入模型
1 | from langchain_community.document_loaders |
件.txt”,encoding=’utf-8’)
1 | documents= loader.load() |
初始化向量数据库与存储向量
整合大语言模型 (LLM)
1 | from langchain_huggingface import |
False} #提升相似度计算精度
1 | splits = |
text_splitter.split_documents(documents)
1 | from langchain_community.vectorstores import |
‘506b011ee51c4a828124883fa3604ecd.3kOXCerJRy
D5md33’
1 | os.environ["ZHIPUAI_API_KEY"] = key |
{“k”: 1}),
1 | return_source_documents=True |





