一、基本结构与概念
什么是 LangChain
LangChain 是一个用于构建大语言模型应用的开发框架。它提供了一系列标准化的组件和接口,让开发者能够轻松地将大模型与外部工具、数据源连接起来,构建复杂的 AI 应用。
核心价值:
- 标准化:统一的接口和组件
- 可组合:像搭积木一样组合功能
- 可扩展:支持自定义组件和第三方集成
1. Models(模型)
LangChain 统一封装了各种大模型的调用接口。
from langchain_community.chat_models import ChatTongyi from langchain_openai import ChatOpenAI from langchain_community.llms import Ollama
通义千问
llm_tongyi = ChatTongyi( api_key="your-api-key", model_name="qwen-turbo" )
OpenAI
llm_openai = ChatOpenAI( api_key="your-api-key", model="gpt-3.5-turbo" )
本地模型
llm_local = Ollama( model="llama2", base_url="http://localhost:11434" )
统一调用方式
response = llm_tongyi.invoke("你好") print(response.content) # 输出:你好!有什么我可以帮助你的吗?
2. Prompts(提示词)
管理、格式化、优化提示词的工具。
from langchain_core.prompts import (
PromptTemplate, # 基础模板
ChatPromptTemplate, # 对话模板
SystemMessagePromptTemplate,
HumanMessagePromptTemplate
)
# 基础提示词模板
template = PromptTemplate.from_template(
"请用{style}的风格写一首关于{topic}的诗"
)
prompt = template.format(style="浪漫", topic="月亮")
# 输出:请用浪漫的风格写一首关于月亮的诗
# 对话提示词模板
chat_template = ChatPromptTemplate.from_messages([
("system", "你是一个{role}专家"),
("user", "{question}")
])
prompt = chat_template.format(role="历史学家", question="秦始皇统一六国的意义")
3. Output Parsers(输出解析器)
将模型输出解析为结构化数据。
from langchain_core.output_parsers import (
StrOutputParser, # 字符串解析器
JsonOutputParser, # JSON解析器
CommaSeparatedListOutputParser # 列表解析器
)
# 字符串解析器
parser = StrOutputParser()
result = parser.parse("这是一段文本") # 直接返回字符串
# JSON解析器
json_parser = JsonOutputParser()
result = json_parser.parse('{"name": "张三", "age": 25}')
# 输出:{'name': '张三', 'age': 25}
# 列表解析器
list_parser = CommaSeparatedListOutputParser()
result = list_parser.parse("苹果,香蕉,橘子")
# 输出:['苹果', '香蕉', '橘子']
4. Chains(链)
将多个组件串联起来形成完整的处理流程。
from langchain_core.runnables import RunnableSequence
# 方式1:使用管道操作符
chain = prompt | llm | parser
# 方式2:使用 RunnableSequence
chain = RunnableSequence(prompt, llm, parser)
# 调用链
result = chain.invoke({"topic": "人工智能"})
5. 流式
流式调用是指大模型在生成内容时,边生成边返回,而不是等全部生成完再一次性返回。就像打字机一样,一个字一个字地显示出来。
对比示例:
- 普通调用:等待10秒 → 一次性显示完整文章
- 流式调用:边生成边显示 → 逐字出现,用户体验更流畅
在 LCEL 链中使用流式输出。
# 构建链
chain = prompt | llm | parser
# 流式执行
for chunk in chain.stream({"question": "写一首诗"}):
print(chunk, end="", flush=True)
每个流式返回的 chunk 包含:
chunk = {
"content": "本次返回的文本", # 文本内容
"additional_kwargs": {}, # 额外信息
"response_metadata": { # 响应元数据
"model": "qwen-turbo",
"finish_reason": None, # 最后一块会显示 stop
"token_usage": {} # 令牌使用情况(仅最后一块)
}
}
大模型生成文本时,本质上是预测下一个 token 的过程:
- 模型逐字生成:token1 → token2 → token3 → ... → tokenN
- 流式调用每生成一个 token 就返回一次
- 客户端每收到一个 token 就立即显示
二、记忆系统
(一)记忆
1.为什么要有记忆系统
A:上下文保持 个性化交互 长期学习
历史内容变多,token变多,收费也就随之变多
2.ConversationBufferMemory(缓冲记忆)
1)完整的存储所有的记忆,适合完整的上下文
2)Token消随着对话耗线性增长,可能超出窗口内存
3.ConversationBufferWindowMemory
是LangChain提供的一种记忆机制,它只存储最近的K条对话记录(包括用户输入和模型输出)。这里的k指的是用户指定的窗口大小,表示保留多少轮对话,确保Token在可控范围内。 memory = ConversationBufferWindowMemory(k =1)
4.ConversationTokenBufferMemory根据Token数量来限制存储对话历史,用户可以指定一个最大的Token数
特点:Token驱动截断;模型适配性(不同模型token不同);动态窗口;高效存储
缺点:更依赖LLM,需要LLM的Token存取规则;可能丢失早期信息 ;设置复杂性;不适合需要完整历史的场景信息
5.ConversationSummaryBufferMemory
一种混合型记忆机制,结合了buffer和Summary
近期对话:直接存储最近的对话内容为原始内容
早期对话:对话历史超过指定的Token限制时,系统会调用llm将早期的对话总结为紧凑的文字,替换原始内容
动态管理:通过总结早期对话并保留近期对话,保持上下文在Token限制内,保留关键信息,同时仍能提供长期上下文支持。
特点: 混合存储机制;Token驱动截断;依赖LLM进行总结;动态平衡;
缺点:依赖LLM总结;额外设计开销(生成对话总结需要额外的LLM调用,增加成本和响应时间);复杂性较高;不适合短对话
(二)查询记忆
printf(memory.buffer) printf(memory.load_memory_variables({}))
verbose = True #打印调试信息
三、文本嵌入模型
(一)文本模型(向量)
Q:什么是文本嵌入
A:将文本信息转换为固定长度的数值向量,电脑不认识文字,但是认识数字
向量捕捉文本的语义信息,相似的语义在向量空间距离较近 例如 hi hello 可以用来做推荐,跨语言也可以(相似度矩阵,TextBox)
(二)搭建本地文本模型
1.示例:
2.分文调用分类示例
3.数据持久化
pip install chromadb
示例为使用本地模型embeddings,documents为上面已经分好块的splite;
similarity_search为匹配数据;
PS:网络版和本地版维度可能不同而报错,因为网络版在第一次运行时,在本地已经产生了文件,再次运行无法替换。
四、工具封装
(一)基本概念
1.为什么需要工具调用?
A:解决LLM的局限性:大模型会出现幻觉问题,且无法直接访问实时数据或者执行具体操作;
扩展边界能力:通过工具集成,Agent可以获得计算API访问等能力;
模块化设计;
@tool装饰器 用于将普通Python函数转化为LangChain工具; 自动生成JSON Schema,描述工具的输入参数和功能;
示例: @tool def add(a:int,b:int)->int: return a+b ;
Json Schema规范: 工具输入需要明确的参数;文档字符串描述功能
相关API 可以在网络中找到开源如: APISpace
(二)封装天气事例
request//向其他服务器发送请求
panda//将不同平台的编码城市转换(读取)
CSV格式数据
动态查询事例
调用实战
1.先创建工具列表
2.智能体创建+调用
工作原理(ReAct Agent 的自动调用机制) 当你调用 agent.invoke() 时,内部发生了以下步骤: LLM 分析问题 → "现在是几点?" LLM 查看可用工具列表 → 发现有 get_current_time 工具 LLM 决定调用工具 → 生成工具调用指令 LangGraph 执行工具 → 实际运行 get_current_time() 函数 返回结果给 LLM → "2026-04-01 14:30:00" LLM 组织语言回答 → "现在的时间是..."