基于Python+Langchain的Agent智能体开发

1
# 智能体概念与技术全景

学习目标

1
# 理解传统程序与智能体(Agent)的本质区别1

掌握Agent”感知→决策→行动”核心能力闭环2

认识现代Agent技术栈关键组件3

识别典型应用场景和技术演进方向4

1
# 传统程序与智能体的区别

传统程序: 输入固定指令,输出固定结果

智能体:更像一个拥有‘思考能力’的智能助手

传统程序示例:计算器

Agent智能体示例:个人助手

1
2
3
4
5
6
7
def calculator(a, b, operator):
if operator == "+":
return a + b
elif operator == "-":
return a - b
# 其他运算符处理...
print(calculator(5, 3, "+"))  # 固定输出8

Agent核心能力

1 感知引擎: 像人类的眼睛耳朵

自然语言理解(如‘帮我订个便宜酒店’→解析为{动作:预定,对象:酒店,条件:低价})

多模态输入(文本/语音/图像)

2 决策大脑: 像人类的思考判断

基于LLM的推理能力

工具选择策略(调用API、搜索知识库等)

1
2
3
4
5
6
7
8
9
10
11
def personal_agent(user_input):
# 感知:理解用户需求
intent = understand_intent(user_input)
# 决策:选择最佳方案
if intent == "天气查询":
plan = "调用天气API"
elif intent == "日程安排":
plan = "查询日历并推荐时间"
# 行动:执行操作
return execute_plan(plan)
print(personal_agent("明天适合户外活动吗?"))  #

自动判断需查天气

1
2
10
11

代际核心技术局限性

第一代规则引擎+固定模板只能处理预设问题

第二代NLP模型+意图识别无法执行复杂操作

第三代LLM+工具调用+记忆系统全能但需优化稳定性

3 执行器官: 像人类的手脚

API调用(获取实时数据)

工具执行(操作外部系统)

输出生成(文本/语音/图像响应)

技术演进

从2016年的Siri到至今的Agents,技术栈大致经历了三次革新:

当前最先进的Agent架构:

1
2
3
4
# 决策流程伪代码
def make_decision(user_input):
if "天气" in user_input:
# 调用天气工具

return

1
2
3
4
5
call_weather_tool(user_input)
elif "计算" in user_input:
# 调用计算工具
return call_calculator(user_input)
else:

# 使用LLM生成回复

1
2
3
return llm_generate(user_input)
10
11

应用场景

客服助手

数据分析专家

个人效率管家

“明早9点提醒我提交报告并推荐通勤路线” → 自动创建日历事项+查询实时交通

技术栈解析

现代Agent开发四大支柱技术:

1 大语言模型(LLM) - 大脑皮层

主流选择:GPT-4, Claude,Llama 3,DeepSeek

作用:理解、推理、内容生成

1
2 工具调用(Tool Calling)

3 记忆系统(Memory) - 海马体

1
2
3
4
5
6
7
8
9

短期记忆:对话上下文


长期记忆:用户偏好/知识库


```python
4 RAG(检索增强) - 外部知识连接器

解决LLM知识静态性问题

实时获取最新信息

传统程序 vs Agent对比分析

1
2
3
4
5
# 传统程序(固定流程)
def travel_planner(destination):
print(f"已为您预订{destination}的机票")
print("推荐景点:自由广场")
travel_planner("巴黎")

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
2
3
4
conda create -n agent_env python=3.121
pip install "langchain-community==0.3.27"
pip install dashscope==1.23.7
12

创建Key: https://bailian.console.aliyun.com/?tab=model#/ap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

i-key


测试模型


注意


一般为了安全,Key在写代码时,不会硬编码写到代码中,


而是环境变量中加载。

```python
import os
from langchain_community.llms import

Tongyi

1
2
3
4
key = 'sk-603a62'
# key = os.getenv('TONGYI_API_KEY')
llm = Tongyi(api_key=key)
info = llm.invoke('夏天适合吃哪个水果?回复几

个水果名称就好’)

1
2
3
print(info)
10
13

Langchain环境搭建-其它模型

模型支持链接:https://www.langchain.com.cn/docs/integration

s/providers/

学习目标

了解接入模型的流程1

安装模块

示例代码

1
2
3
4
5
# 智谱AI
pip install pyjwt==2.10.1
from langchain_community.chat_models import
ChatZhipuAI
from langchain_core.messages import

AIMessage, HumanMessage, SystemMessage

1
2
import os
os.environ["ZHIPUAI_API_KEY"] =

“2cb2ef28c37b42f38c2f7329795aba4b.8CFwsx98t0

TxNaag”

1
14

Langchain环境搭建-本地模型

学习目标

了解接入模型的流程1

1
2
3
4
chat = ChatZhipuAI(
model="glm-4",
temperature=0.5,
rs = chat.invoke([

SystemMessage(content=”你是一个助手,请以中

1
2
3
4
5
6

文回答。"),


```python
HumanMessage(content="夏天适合吃西瓜吗?总结

1句话回复即可。”),

1
2
3
4
5
6
7
8
9
10
11
])
print(rs.content)
10
11
12
13
14
15
16
17
15

了解如何使用本地模型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
2
pip install "langchain-ollama==0.3.3"1
17

Langchain关键对象-提示词模板

学习目标

了解 提示词模板 的作用1

了解 提示词模板 的使用方式2

1
2
3
4
5
from langchain_ollama import ChatOllama
llm = ChatOllama(model="deepseek-r1:1.5b")
response = llm.invoke("夏天吃什么水果合适?")
print(response.content)
messages = [

(“system”,”你是个饮食健康专家,请根据用户的输

入给出相应的建议。”),

(“human”, “夏天吃什么水果合适?”),

1
response = llm.invoke(messages)

response

1
2
3
4
5
10
11
12
13
18

介绍

LangChain 的提示词模板引擎(Prompt Template Engine)是其

核心组件之一,主要用于构建和管理与大语言模型(LLM)交互的

提示词(Prompt)。

它的作用是将用户的输入或动态数据结构化地嵌入到预定义的模板

中,从而生成适合模型处理的提示词,提升模型输出的准确性和一

致性

示例

方法1:

1
2
3
4
5
6
7
8
key= '506b011ee51c4a82833'
from langchain_community.chat_models import
ChatZhipuAI
import os
os.environ["ZHIPUAI_API_KEY"] = key
chat = ChatZhipuAI(
model="glm-4",
temperature=0.5,     # 模型温度, 值在0-1

之间。 值越小,随机性越低

1
2
3
4
5
10
11
from langchain.prompts import PromptTemplate
# 定义模板
19

方法2:

1
2
3
4
template = '你是一个{role},请用{style}风格回答问
题:{question}'
# 创建模板对象
prompt_template =

PromptTemplate.from_template(template)

1
2
3
4
5
6
# 变量的填充
# filled_prompt =
prompt_template.format(role='数学老师',
style='通俗易懂', question='勾股定理是什么?')
filled_prompt =
prompt_template.invoke({'role':'数学老师',

‘style’:’通俗易懂’, ‘question’:’勾股定理是什

么?’})

1
2
3
4
5
6
7
8
9
10
11
12
13
# 模型响应数据
ai_msg = chat.invoke(filled_prompt)
print(ai_msg.content)
10
11
12
13
14
15
from langchain_core.prompts import
ChatPromptTemplate
# 定义模板
sys_template = "你是数学老师,请以{style}的风格回

答问题”

1
user_template = "请用简单易懂的方式解释:

{question}”

1
2
3
4
# 创建对话模板
prompt_template =
ChatPromptTemplate.from_messages([
20

Langchain关键对象-输出格式化

学习目标

了解 输出格式化 的作用1

了解 输出格式化 的使用方式2

介绍

在 LangChain 中,输出格式化(Output Parsing)是关键功能之

一,用于将大语言模型(LLM)的原始输出(通常是自由格式的文

本)解析为结构化的数据格式,如 JSON、字典或自定义对象。这不

仅便于后续处理,还能提高输出的可读性和一致性。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
22
StructuredOutputParser结构化输出
key= '506b011ee51c4a82833'
from langchain_community.chat_models import
ChatZhipuAI
import os
os.environ["ZHIPUAI_API_KEY"] = key
chat = ChatZhipuAI(
model="glm-4",
temperature=0.5
10
11
from langchain.output_parsers import
StructuredOutputParser, ResponseSchema
# 定义输出结构
response_schemas = [
ResponseSchema(name="name",
description="人的姓名", type="string"),
ResponseSchema(name="age",
description="人的年龄", type="integer")
output_parser =
StructuredOutputParser.from_response_schemas

(response_schemas)

1
2
# 创建提示模板,包含格式化指令
template = """你是一个信息提取助手,请从以下文本中

提取姓名和年龄,并以 JSON 格式返回:

1
2
3
4
5
10
11
12
23
PydanticOutputParser对象化输出

文本:{input_text}

{format_instructions}”””

1
2
3
prompt = PromptTemplate(
template=template,
partial_variables=

{“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
2
3
4
5
6
7
8
9
10
11
12
13
14

提取姓名和年龄,并以 Person 格式返回:


文本:{input_text}


{format_instructions}"""

```python
prompt = PromptTemplate(
template=template,
input_variables=["input_text"],
partial_variables=

{“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
2
3
4
5
6
7
8

## Langchain关键对象-执行链式调用


学习目标

```python
26

了解什么是链式调用

了解如何使用链式调用

介绍

在 LangChain 中,LLMChain 是一个核心对象,用于实现基于大语

言模型(LLM)的链式调用。它将提示词模板(Prompt

Template)、语言模型(LLM)以及可选的输出解析器(Output

Parser)组合在一起,形成一个可重复执行的流程,简化了与 LLM

的交互。

LLMChain 的核心组件

1 PromptTemplate:

定义提示词的模板,包含占位符(如 {input}),用于动态生成提示词。

示例:”请用{style}风格解释:{question}”

2 LLM:

1
2
大语言模型(如 ChatZhipuAI、OpenAI 等),负责根据提示词生成输出。
示例:ChatZhipuAI(model="glm-4")

3 OutputParser(可选):

用于将 LLM 的原始文本输出解析为结构化格式(如 JSON、列表)。

1
示例:StructuredOutputParser 或 PydanticOutputParser。

4 Memory(可选):

可集成上下文记忆(如 ConversationBufferMemory),支持对话历史管理

示例

from langchain.chains import LLMChain

1
2
3
4
5
6
7
8
9
from langchain.prompts import PromptTemplate
from langchain_community.chat_models import
ChatZhipuAI
from langchain.output_parsers import
StructuredOutputParser, ResponseSchema
27
import os
# 设置 API 密钥
os.environ["ZHIPUAI_API_KEY"] =

“506b011ee51c4a82833”

1
2
3
4
5
6
7
8
9
10
chat = ChatZhipuAI(model="glm-4",
temperature=0.5)
# 定义输出结构
response_schemas = [
ResponseSchema(name="answer",
description="问题的答案", type="string"),
ResponseSchema(name="confidence",
description="答案的置信度", type="float")
output_parser =
StructuredOutputParser.from_response_schemas

(response_schemas)

1
2
# 定义提示模板
template = """你是一名数学老师,请用{style}风格回

答以下问题,并以 JSON 格式返回答案和置信度:

问题:{question}

{format_instructions}”””

1
2
3
4
prompt = PromptTemplate(
template=template,
input_variables=["style", "question"],
partial_variables=

{“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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

## Langchain响应-流式输出


## # 创建 LLMChain


## llm_chain = LLMChain(

```python
llm=chat,
prompt=prompt,
output_parser=output_parser
# 使用管道操作符创建链
llm_chain = prompt | chat | output_parser
# 运行链式调用
result = llm_chain.run({

“style”: “通俗易懂”,

“question”: “勾股定理是什么?”

1
2
3
})
print(result)
# 输出示例: {'answer': '勾股定理是直角三角形中,斜

边的平方等于两直角边平方之和,即 a² + b² = c²。’,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

'confidence': 0.95}

```python
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
29

模式特点

1
普通输出(非流式)用户提交问题 → 等待几秒 → 一次性返回完整答案

流式输出用户提交问题 → AI边生成边显示 → 逐步输出答案

介绍

流式输出是指在用户输入问题后,AI模型边生成边显示响应内容,

逐步展示AI的”思考”过程,而不是等待所有内容生成完毕后再一次

性返回完整答案

与传统非流式输出相比,流式输出的差异如下表所示:

示例

1
2
3
4
5
6
7
8
9
10
11
from langchain.output_parsers import
StructuredOutputParser,ResponseSchema
from langchain.prompts import PromptTemplate
# 定义输出结构
response_schemas = [
ResponseSchema(name="answer",
description="问题的答案", type="string"),
ResponseSchema(name="confidence",
description="答案的置信度", type="float")
output_parser =
StructuredOutputParser.from_response_schemas

(response_schemas)

1
2
# 定义提示模板
template = """你是一名数学老师,请用{style}风格回

答以下问题,并以 JSON 格式返回答案和置信度:

问题:{question}

{format_instructions}”””

1
2
3
4
5
6
10
11
12
13
14
30

Langchain记忆系统-ConversationBufferMemory

1
2
3
prompt = PromptTemplate(
template=template,
partial_variables=

{“format_instructions”:

1
output_parser.get_format_instructions()}

llm_chain = prompt | chat
chunks = []

运行链

for chunk in llm_chain.stream({

1
2
3
4
5
6
7
8

'style':'通俗易懂',


'question':'勾股定理是什么?'

```python
})

chunks.append(chunk)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
print(chunk.content,end='',flush=True)
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

学习目标

了解为什么使用记忆系统

了解ConversationBufferMemory的特点与使用

为什么需要记忆系统

与LLM对话系统中,每次交互(调用API)都是独立的”无状态”处理,

导致对话缺乏连贯性。LangChain的记忆系统通过以下方式解决这

个问题。

注意

虽然目前看到许多聊天机器人是有记忆的,是因为借助了代码

的帮助,提供了历史消息作为和LLM对话的上下文。

所以就可以基于之前所说过的会话内容,再生成新的内容。从

而感觉好像“记得”说过的话!

作用

上下文保持:记住用户之前的输入和系统的输出

个性化交互:存储用户偏好和关键信息(如姓名、职业等)

长期学习:积累历史交互数据用于改进后续响应

注意

随之历史内容的变多,tokens的数量也会变多,而平台的计费

方式往往是通过tokens的数量来计算的!!

ConversationBufferMemory(缓冲记忆)

完整存储所有对话历史,不做任何压缩或筛选

优点:保留全部细节,适合需要完整上下文的场景(如法律咨

询、复杂问题追踪)

1
32

缺点:Token消耗随对话线性增长,易超出模型上下文窗口限制

示例

ConversationBufferMemory

1
from langchain import ConversationChain

memory = ConversationBufferMemory()

1
2
3
conversation = ConversationChain(llm=chat,
memory=memory ,verbose=False)
conversation.predict(input="你好,我是个程序

员”)

1
2
3
4
5
6
7
conversation.predict(input="你叫什么名字?")
conversation.predict(input="我是什么职业?")
print(memory.buffer)
memory.load_memory_variables({})
10
11
33

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
2
3
from langchain.chains import
ConversationChain
from langchain.llms import OpenAI  # 假设使用

OpenAI 的 LLM

# 初始化 LLM(这里以 OpenAI 为例,需替换为实际模

型)

1
llm = OpenAI(temperature=0.7)

# 初始化 ConversationBufferWindowMemory,设置窗

1
口大小 k=2

memory = ConversationBufferWindowMemory(k=2)

1
2
3
4
5
6
7
8
# 创建 ConversationChain
conversation = ConversationChain(llm=llm,
memory=memory, verbose=True)
10
11
12
13
35

输出示例(假设 LLM 的响应如下):

1
2
# 模拟对话
print(conversation.predict(input="你好,我的名

字是小明”))

1
print(conversation.predict(input="我是一个程序

员”))

1
print(conversation.predict(input="你还记得我的

名字吗?”))

1
print(conversation.predict(input="我的职业是什

么?”))

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看内存中的对话历史
print("当前内存中的对话历史:")
print(memory.buffer)
14
15
16
17
18
19
20
21
22
> 你好,我的名字是小明

好的,小明,很高兴认识你!你今天有什么想聊的吗?

1
> 我是一个程序员

哇,程序员!那你平时写什么语言的代码呢?

1
> 你还记得我的名字吗?

当然记得,你是小明,对吧?

1
> 我的职业是什么?

你是程序员!

当前内存中的对话历史:

1
2
3
4
5
6
7
8
9
10
11
12
13
Human: 我是一个程序员
AI: 哇,程序员!那你平时写什么语言的代码呢?
Human: 你还记得我的名字吗?
AI: 当然记得,你是小明,对吧?
10
11
12
13
14
15
16
17
36

解析:

1
k=2  表示只保留最近两轮对话(每轮包括用户输入和模型输出)。

第一次和第二次对话后,内存中存储了“小明”和“程序员”的信息。

第三次和第四次对话时,最早的对话(“你好,我的名字是小明”)被移出窗口,但模型仍能通过上

下文推断出名字(取决于 LLM 的能力)。

1
memory.buffer  显示当前内存中只保留最近两轮对话。

示例 2:手动添加对话

1
from langchain.memory import

ConversationBufferWindowMemory

# 初始化 ConversationBufferWindowMemory,设置窗

1
口大小 k=3

memory = ConversationBufferWindowMemory(k=3)

1
2
# 手动添加对话记录
memory.save_context({"input": "你好!"},

{“output”: “您好!有什么可以帮助您的?”})

1
memory.save_context({"input": "我喜欢编程"},

{“output”: “太棒了!您喜欢用哪种编程语言?”})

1
memory.save_context({"input": "Python 是我的最

爱”}, {“output”: “Python 很强大!您用它做什么项

目?”})

1
memory.save_context({"input": "我在做一个聊天机

器人”}, {“output”: “酷!像我这样的吗?😄”})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看当前内存中的对话历史
print("当前内存中的对话历史:")
print(memory.buffer)
# 查看内存变量
print("内存变量:")
10
11
12
13
14
15
16
17
37

输出示例:

解析:

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
2
3
4
5
6
Human: 我喜欢编程
AI: 太棒了!您喜欢用哪种编程语言?
Human: Python 是我的最爱
AI: Python 很强大!您用它做什么项目?
Human: 我在做一个聊天机器人
AI: 酷!像我这样的吗?😄

内存变量:

{‘history’: ‘Human: 我喜欢编程\nAI: 太棒了!您喜

欢用哪种编程语言?\nHuman: Python 是我的最爱\nAI:

Python 很强大!您用它做什么项目?\nHuman: 我在做一

个聊天机器人\nAI: 酷!像我这样的吗?😄’}

1
2
10
38

答案

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
2
3
from langchain.chains import
ConversationChain
from langchain.llms import OpenAI

# 初始化 LLM(这里以 OpenAI 为例,需替换为实际模

型)

1
llm = OpenAI(temperature=0.7)

# 初始化 ConversationTokenBufferMemory,设置最

大 Token 限制为 100

1
memory =

ConversationTokenBufferMemory(llm=llm,

1
2
3
4
5
max_token_limit=100)
# 创建 ConversationChain
10
11
40

输出示例(假设 LLM 的响应如下,实际 Token 数取决于模型的

Token 化规则):

1
2
3
4
conversation = ConversationChain(llm=llm,
memory=memory, verbose=True)
# 模拟对话
print(conversation.predict(input="你好,我的名

字是小明”))

1
print(conversation.predict(input="我是一个程序

员,喜欢用 Python”))

1
print(conversation.predict(input="你还记得我的

名字吗?”))

1
print(conversation.predict(input="我的职业是什

么?”))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看内存中的对话历史
print("当前内存中的对话历史:")
print(memory.buffer)
12
13
14
15
16
17
18
19
20
21
22
> 你好,我的名字是小明

好的,小明,很高兴认识你!你今天有什么想聊的吗?

1
> 我是一个程序员,喜欢用 Python

酷!Python 是个很棒的语言。你用它做什么项目?

1
> 你还记得我的名字吗?

当然记得,你是小明,对吧?

1
> 我的职业是什么?

你是程序员,喜欢用 Python!

当前内存中的对话历史:

1
2
3
4
5
10
11
12
13
41

解析:

1
max_token_limit=100  表示内存中存储的对话历史总 Token 数不超过 100

随着对话进行,早期对话(如“你好,我的名字是小明”)可能因 Token 超限被移除。

1
memory.buffer  显示当前保留的对话历史,具体保留多少轮取决于每条消息的 Token 数。

llm 参数用于指定 Token 化规则,确保准确计算 Token 数量。

示例 2:手动添加对话

1
2
3
4
5
6
7
8
9
Human: 你还记得我的名字吗?
AI: 当然记得,你是小明,对吧?
Human: 我的职业是什么?
AI: 你是程序员,喜欢用 Python!
14
15
16
17
from langchain.memory import

ConversationTokenBufferMemory

1
from langchain.llms import OpenAI

# 初始化 LLM

1
llm = OpenAI(temperature=0.7)

# 初始化 ConversationTokenBufferMemory,设置最

大 Token 限制为 50

1
memory =

ConversationTokenBufferMemory(llm=llm,

1
2
3
max_token_limit=50)
# 手动添加对话记录
memory.save_context({"input": "你好!"},

{“output”: “您好!有什么可以帮助您的?”})

1
memory.save_context({"input": "我喜欢编程"},

{“output”: “太棒了!您喜欢用哪种编程语言?”})

1
memory.save_context({"input": "Python 是我的最

爱”}, {“output”: “Python 很强大!您用它做什么项

目?”})

1
2
3
4
5
10
11
12
13
42

输出示例(实际输出取决于 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
2
3
4
45
from langchain.chains import
ConversationChain
from langchain.llms import OpenAI

# 初始化 LLM(这里以 OpenAI 为例,需替换为实际模

型)

1
llm = OpenAI(temperature=0.7)

# 初始化 ConversationSummaryBufferMemory,设置

最大 Token 限制为 100

1
memory =

ConversationSummaryBufferMemory(llm=llm,

1
2
3
4
5
6
max_token_limit=100)
# 创建 ConversationChain
conversation = ConversationChain(llm=llm,
memory=memory, verbose=True)
# 模拟对话
print(conversation.predict(input="你好,我的名

字是小明”))

1
print(conversation.predict(input="我是一个程序

员,喜欢用 Python”))

1
print(conversation.predict(input="我最近在做一

个聊天机器人项目”))

1
print(conversation.predict(input="你还记得我的

名字和职业吗?”))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看内存中的对话历史
print("当前内存中的对话历史:")
print(memory.buffer)
10
11
12
13
14
15
16
17
18
19
20
21
22
46

输出示例(假设 LLM 的响应和总结如下,实际输出取决于 Token

数和总结内容):

解析:

1
max_token_limit=100  表示对话历史总 Token 数不超过 100

早期对话(“你好,我的名字是小明”和“我是一个程序员,喜欢用 Python”)被总结为一句紧凑的文

本。

近期对话以原始形式保留,确保细节完整。

1
memory.buffer  显示总结后的早期对话和原始的近期对话。

你好,我的名字是小明

1
2
3
4
5

好的,小明,很高兴认识你!你今天有什么想聊的吗?

```python
> 我是一个程序员,喜欢用 Python

酷!Python 是个很棒的语言。你用它做什么项目?

1
> 我最近在做一个聊天机器人项目

听起来很有趣!你这个聊天机器人有什么特别的功能吗?

1
> 你还记得我的名字和职业吗?

当然记得!你是小明,一个喜欢用 Python 的程序员,正在

做一个聊天机器人项目,对吧?

当前内存中的对话历史:

1
System: Summary: 小明介绍自己是一个程序员,喜欢用

Python。

1
2
Human: 我最近在做一个聊天机器人项目
AI: 听起来很有趣!你这个聊天机器人有什么特别的功能

吗?

1
2
Human: 你还记得我的名字和职业吗?
AI: 当然记得!你是小明,一个喜欢用 Python 的程序

员,正在做一个聊天机器人项目,对吧?

1
2
3
4
5
6
7
8
9
10
10
11
12
13
14
15
16
17
18
47

示例 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
2
3
max_token_limit=50)
# 手动添加对话记录
memory.save_context({"input": "你好!我是小

明”}, {“output”: “您好,小明!有什么可以帮助您

的?”})

1
memory.save_context({"input": "我喜欢编程,用

Python”}, {“output”: “Python 很棒!您用它做什

么?”})

1
memory.save_context({"input": "我在做一个聊天机

器人”}, {“output”: “酷!有什么特别功能吗?”})

1
memory.save_context({"input": "你记得我的职业

吗?”}, {“output”: “你是程序员,喜欢用 Python,对

吧?”})

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看当前内存中的对话历史
print("当前内存中的对话历史:")
print(memory.buffer)
10
11
12
13
14
15
16
17
18
48

输出示例(实际输出取决于 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
2
3
4
5
# 智普AI
import os
from langchain_community.chat_models import
ChatZhipuAI
key=

‘506b011ee51c4a828124883fa3604ecd.3kOXCerJRy

D5md33’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
os.environ["ZHIPUAI_API_KEY"] = key
chat = ChatZhipuAI(
model="glm-4",
temperature=0.5
10
51
from langchain_community.embeddings import
ZhipuAIEmbeddings
from sklearn.linear_model import
LogisticRegression
# 加载模型
embeddings =
ZhipuAIEmbeddings(model="embedding-2")
# 准备评论和标签
comments = ["这产品太棒了!", "一天就坏了,垃

圾!”]

1
2
3
4
5
6
7
8
labels = [1, 0]  # 1是好评,0是差评
# 转成向量
vectors =
embeddings.embed_documents(comments)
print("向量维度:", len(vectors[0]))
print("向量内容:", vectors[0])
# 训练分类器
clf = LogisticRegression().fit(vectors,

labels)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 测试新评论
test_comment = ["这东西超好用!"]
test_vector =
embeddings.embed_documents(test_comment)
prediction = clf.predict(test_vector)
print("评价:", "好评" if prediction[0] == 1
else "差评")
10
11
12
13
14
15
16
17
18
19
20
21
22
23
52

LangChain 文本嵌入-本地模型

1
53

学习目标

了解如何搭建 本地文本嵌入模型 环境

了解如何使用 本地文本嵌入模型

模块下载

模型下载

1
2
3
4
5
pip install langchain_huggingface==0.3.0
pip install chromadb==1.0.15
pip install huggingface-hub==0.33.4
pip install transformers==4.53.2
# 可以科学上网

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. 员工工作满1年可享受5天带薪年假

  2. 年假有效期至次年3月31日

  3. 部门经理审批后方可使用

考勤制度:

  • 工作日上班时间:9:00-18:00

  • 迟到超过30分钟记为缺勤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 文件:embedding_demo.py
from langchain_community.document_loaders
import TextLoader
from langchain.text_splitter import
RecursiveCharacterTextSplitter
# 加载中文文档(注意编码)
loader = TextLoader("政策文档.txt",
encoding="utf-8")
documents = loader.load()
# 中文专用分块器
text_splitter =
RecursiveCharacterTextSplitter(
chunk_size=100,  # 适合中文的短段落
chunk_overlap=50,  # 避免上下文缺失
separators=["\n", "。", "!", "?"]  # 按

中文标点分割

1
2
3
4
5
10
11
12
13
55

本地中文嵌入模型初始化

构建向量数据库

1
splits =

text_splitter.split_documents(documents)

1
print(f"生成 {len(splits)} 个文本块,首段内容:

\n{splits[0].page_content[:100]}…”)

1415

1
2
3
4
5
6
7
16
from langchain_huggingface import
HuggingFaceEmbeddings
# 加载本地中文模型(需提前下载)
embeddings = HuggingFaceEmbeddings(
model_name="./bge-small-zh-v1.5",
model_kwargs={"device": "cpu"},  # 无GPU

时使用

1
encode_kwargs={"normalize_embeddings":

True}  # 提升相似度计算精度

1
2
3
4
# 测试向量化
query = "年假怎么申请?"
vector = embeddings.embed_query(query)
print(f"查询向量维度:{len(vector)},前5维:

{vector[:5]}”)

1
2
3
4
5
6
7
8
9
10
10
11
12
13
from langchain_community.vectorstores import
Chroma
# 持久化到本地
db = Chroma.from_documents(
documents=splits,
56

LangChain工具-工具封装

学习目标

理解工具调用在智能体开发中的重要性

学会封装外部API为LangChain工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
embedding=embeddings,
persist_directory="./chroma_db"
# 语义搜索示例
docs = db.similarity_search("迟到处罚", k=1)
# k表示返回最相关的k个结果
print("最相关结果:")
for doc in docs:
print(doc.page_content)
10
11
12
13
14
57

为什么需要工具调用?

解决LLM的局限性:大语言模型存在”幻觉”问题(生成虚假信

息),且无法直接访问实时数据或执行具体操作

扩展能力边界:通过工具集成,Agent可以获得计算、API访

问、数据库查询等实际能力

模块化设计:将不同功能封装为独立工具,便于维护和复用

LangChain工具开发核心组件

1
@tool 装饰器

用于将普通Python函数转换为LangChain工具

自动生成JSON Schema,描述工具的输入参数和功能

示例:

JSON Schema规范

工具的输入参数需要明确类型(如str 、int )

文档字符串(docstring)描述工具功能,Agent依靠此判断是否

调用

JSON Schema示例(自动生成):

1
2
3
from langchain.tools import tool
@tool
def add_numbers(a: int, b: int) -> int:

“””将两个数字相加”””

1
2
return a + b
58

LangChain工具-实战案例:天气查询工具

案例背景

目标:开发一个天气查询工具,供Agent调用

数据源:APISpace(免费,需注册获取API Key)

功能:输入城市名,返回实时温度和天气状况

环境准备

1 安装依赖:

2 获取API Key:

注册APIspace账户 https://www.apispace.com/

工具实现代码

以下是天气查询工具的完整实现:

1
2
3
4
5
6
pip install requests
pip install pandas
import pandas as pd
city_df = pd.read_csv('city.csv')
def get_city_code(city_name: str) -> int:
60

“””返回城市编码和经纬度,格式固定为 int”””

1
2
3
try:
# 优先匹配区县
match = city_df[city_df['district']

== city_name]

1
2
if not match.empty:
return match.iloc[0]['areacode/

城市ID’]

1
2
# 其次匹配城市
match = city_df[city_df['city'] ==

city_name]

1
2
if not match.empty:
return match.iloc[0]['areacode/

城市ID’]

1
2
3
# 模糊匹配
match =
city_df[city_df['city'].str.contains(city_na

me, na=False)]

1
2
if not match.empty:
return match.iloc[0]['areacode/

城市ID’]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 默认返回北京
return 101010100
except Exception as e:
print(f"城市编码查询错误: {e}")
return 101010100  # 确保始终返回相同格式
get_city_code('南京')
56
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
61

LangChain工具-模型调用工具

1
2
3
import re
@tool
def get_weather(city: str) :

“””调用实时天气API,返回温度及天气状况

1
2
参数:
city: 城市名称,如'北京'

“””

1
2
try:
city = re.findall(r"[\u4e00-\u9fa5]+",

city)[0]

1
2
3
city_code= get_city_code(city)
payload = {"areacode" : city_code}
url =

f”https://eolink.o.apispace.com/456456/weath

er/v001/now”

1
headers = {"X-APISpace-Token":

“h72uhbhva2t9s4k5ozrx23f8vmwqcds0”}

1
2
3
4
response = requests.get(url,
headers=headers,params=payload)
data = response.json()
return f"天气: {data['result']

[‘realtime’][‘text’]}, 温度: {data[‘result’]

[‘realtime’][‘temp’]}°C”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
except Exception as e:
return f"获取天气失败: {str(e)}"
get_weather('南京')
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
62

学习目标

掌握模型如何调用工具

LangChain工具调用机制

LangChain通过@tool 装饰器将Python函数转换为Agent可调用的

工具

工具定义遵循JSON Schema规范,确保结构化输入与输出

Agent通过提示词(Prompt)决定何时调用哪个工具

流程:

用户输入 → Agent解析意图1

匹配工具 → 执行函数2

返回结果 → 整合到Agent响应3

示例

工具

1
2
3
import pandas as pd
city_df = pd.read_csv('city.csv')
def get_city_code(city_name: str) -> int:

“””返回城市编码和经纬度,格式固定为 int”””

1
2
3
4
try:
# 优先匹配区县
63
match = city_df[city_df['district']

== city_name]

1
2
if not match.empty:
return match.iloc[0]['areacode/

城市ID’]

1
2
# 其次匹配城市
match = city_df[city_df['city'] ==

city_name]

1
2
if not match.empty:
return match.iloc[0]['areacode/

城市ID’]

1
2
3
# 模糊匹配
match =
city_df[city_df['city'].str.contains(city_na

me, na=False)]

1
2
if not match.empty:
return match.iloc[0]['areacode/

城市ID’]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 默认返回北京
return 101010100
except Exception as e:
print(f"城市编码查询错误: {e}")
return 101010100  # 确保始终返回相同格式
get_city_code('南京')
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import re1
64

调用工具

1
2
@tool
def get_weather(city: str) :

“””调用实时天气API,返回温度及天气状况

1
2
参数:
city: 城市名称,如'北京'

“””

1
2
try:
city = re.findall(r"[\u4e00-\u9fa5]+",

city)[0]

1
2
3
city_code= get_city_code(city)
payload = {"areacode" : city_code}
url =

f”https://eolink.o.apispace.com/456456/weath

er/v001/now”

1
headers = {"X-APISpace-Token":

“h72uhbhva2t9s4k5ozrx23f8vmwqcds0”}

1
2
3
4
response = requests.get(url,
headers=headers,params=payload)
data = response.json()
return f"天气: {data['result']

[‘realtime’][‘text’]}, 温度: {data[‘result’]

[‘realtime’][‘temp’]}°C”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
except Exception as e:
return f"获取天气失败: {str(e)}"
get_weather('南京')
10
11
12
13
14
15
16
17
18
19
20
21
from langchain.agents import
create_react_agent, AgentExecutor
from langchain import hub
65

检索增强生成-RAG

1
2
3
# 1. 定义工具
tools = [get_weather]
prompt = hub.pull("hwchase17/react")  # 使用

Hub模板

1
2
# 2. 创建Agent
agent = create_react_agent(chat, tools,

prompt)

1
2
3
4
# 3. 创建AgentExecutor,作用是运行Agent
agent_executor = AgentExecutor(agent=agent,
tools=tools, verbose=False)
test_inputs = [

“请告诉我上海的天气”,

“北京今天冷吗?”,

“帮我修电脑”

1
2
3
4
5
6
for user_input in test_inputs:
print(f"\n用户输入:{user_input}")
response =
agent_executor.invoke({"input": user_input})
print(f"Agent回答:{response['output']}")
# print(agent_executor.invoke({"input": "请告

诉我上海的天气”}))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
10
11
12
13
14
15
16
17
18
19
20
21
22
23
66

学习目标

了聊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
2
3
4
from langchain_community.document_loaders
import  TextLoader
# 加载文件
loader = TextLoader("./政策文

件.txt”,encoding=’utf-8’)

1
2
3
4
5
6
7
8
9
10
11
documents= loader.load()
from langchain.text_splitter import
RecursiveCharacterTextSplitter
# 中文分块
text_splitter =
RecursiveCharacterTextSplitter(
chunk_size=50,  # 适合中文段落,段落大小
chunk_overlap=10,  # 避免上下缺失
separators=["\n\n", "\n", "。", "!","?"]
# 段落分隔符
70

初始化向量数据库与存储向量

整合大语言模型 (LLM)

1
2
3
4
5
6
7
from langchain_huggingface import
HuggingFaceEmbeddings
# 加载本地模型
embeddings = HuggingFaceEmbeddings(
model_name='bge-small-zh-v1.5',
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings':

False}   #提升相似度计算精度

1
splits =

text_splitter.split_documents(documents)

1
2
3
4
5
6
7
8
9
10
11
12
13
from langchain_community.vectorstores import
Chroma
db = Chroma.from_documents(
documents=splits,
embedding=embeddings,
persist_directory="./chroma_db3"
import os
from langchain_community.chat_models import
ChatZhipuAI
from langchain.chains.retrieval_qa.base
import RetrievalQA
71
key=

‘506b011ee51c4a828124883fa3604ecd.3kOXCerJRy

D5md33’

1
2
3
4
5
6
7
8
os.environ["ZHIPUAI_API_KEY"] = key
chat = ChatZhipuAI(
model="glm-4",
temperature=0.5
# 构建 RAG 链
qa_chain = RetrievalQA.from_chain_type(
llm=chat,
retriever=db.as_retriever(search_kwargs=

{“k”: 1}),

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
return_source_documents=True
# 查询
query = "年假有效期"
result = qa_chain({"query": query})
print("答案:", result["result"])
10
11
12
13
14
15
16
17
18
19
20
21
22
72