目录
1. Memory(记忆管理)
1.1 技术概述
Memory 是 LangChain 中用于管理对话历史的核心模块,它允许 AI 应用在多轮对话中保持上下文信息。LangChain 提供了多种 Memory 类型,适用于不同的场景需求。
1.2 核心 Memory 类型
1.2.1 ConversationBufferMemory(缓冲区记忆)
特点:保存所有对话历史,无限制存储。
Demo 示例:
from langchain.memory import ConversationBufferMemory
from langchain_openai import ChatOpenAI
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
# 创建大模型实例
llm = ChatOpenAI(model="gpt-4o-mini")
# 提供提示词模板
prompt_template = PromptTemplate.from_template(
template="""
你可以与人类对话。
当前对话历史: {history}
人类问题: {question}
回复:
"""
)
# 提供memory实例
memory = ConversationBufferMemory()
# 提供Chain
chain = LLMChain(llm=llm, prompt=prompt_template, memory=memory)
# 第一轮对话
response = chain.invoke({"question": "你好,我的名字叫小明"})
print(response['text'])
# 第二轮对话(可以记住名字)
response = chain.invoke({"question": "我叫什么名字呢?"})
print(response['text']) # 输出:你叫小明
适用场景:
- 对话历史较短
- 需要完整保留所有上下文
- 对内存消耗不敏感
1.2.2 ConversationBufferWindowMemory(窗口记忆)
特点:只保留最近 N 轮对话,超出窗口的对话会被丢弃。
Demo 示例:
from langchain.memory import ConversationBufferWindowMemory
from langchain_openai import ChatOpenAI
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
llm = ChatOpenAI(model="gpt-4o-mini")
template = """以下是人类与AI之间的友好对话描述。
当前对话:
{history}
Human: {question}
AI:"""
prompt_template = PromptTemplate.from_template(template)
# 设置窗口大小为1(只保留最近1轮对话)
memory = ConversationBufferWindowMemory(k=1)
conversation_chain = LLMChain(
llm=llm,
prompt=prompt_template,
memory=memory,
)
# 多轮对话
conversation_chain.invoke({"question": "你好,我是孙小空"})
conversation_chain.invoke({"question": "我还有两个师弟,一个是猪小戒,一个是沙小僧"})
conversation_chain.invoke({"question": "我今年高考,竟然考上了1本"})
# 询问名字(由于窗口限制,可能不记得)
response = conversation_chain.invoke({"question": "我叫什么名字?"})
print(response['text'])
适用场景:
- 对话历史较长,需要限制内存使用
- 只关注最近的对话内容
- 避免上下文过长导致性能下降
1.2.3 ConversationSummaryMemory(摘要记忆)
特点:使用 LLM 将历史对话总结成摘要,节省空间。
Demo 示例:
from langchain.memory import ConversationSummaryMemory
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
# 定义ConversationSummaryMemory对象
memory = ConversationSummaryMemory(llm=llm)
# 存储消息
memory.save_context({"input": "你好"}, {"output": "怎么了"})
memory.save_context({"input": "你是谁"}, {"output": "我是AI助手小智"})
memory.save_context({"input": "初次对话,你能介绍一下你自己吗?"},
{"output": "当然可以了。我是一个无所不能的小智。"})
# 读取消息(总结后的)
print(memory.load_memory_variables({}))
# 输出:{'history': 'The human greets the AI...'}
适用场景:
- 需要长期记忆但空间有限
- 对话历史非常长
- 需要保留关键信息而非完整对话
1.2.4 ConversationSummaryBufferMemory(摘要缓冲记忆)
特点:结合缓冲区与摘要,当对话超过 token 限制时自动摘要。
Demo 示例:
from langchain.memory import ConversationSummaryBufferMemory
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.chains.llm import LLMChain
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.5, max_tokens=500)
# 定义提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是电商客服助手,用中文友好回复用户问题。"),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}")
])
# 创建带摘要缓冲的记忆系统
memory = ConversationSummaryBufferMemory(
llm=llm,
max_token_limit=400, # 控制缓冲区大小
memory_key="chat_history",
return_messages=True
)
# 创建对话链
chain = LLMChain(llm=llm, prompt=prompt, memory=memory)
# 模拟多轮对话
dialogue = [
"你好,我想查询订单12345的状态",
"这个订单是上周五下的",
"我现在急着用,能加急处理吗",
"等等,我可能记错订单号了,应该是12346",
"对了,你们退货政策是怎样的"
]
for user_input in dialogue:
response = chain.invoke({"input": user_input})
print(f"用户: {user_input}")
print(f"客服: {response['text']}\n")
适用场景:
- 需要平衡完整性和空间效率
- 对话长度不确定
- 客服、助手等需要长期记忆的应用
1.3 Memory 使用要点
- memory_key 设置:在提示词模板中使用的变量名必须与 memory 的
memory_key一致 - return_messages:设置为
True时返回消息列表,False时返回字符串 - 与 Chain 集成:Memory 通常与
LLMChain或ConversationChain配合使用
2. Tools(工具调用)
2.1 技术概述
Tools 允许 LLM 调用外部函数或 API,扩展模型的能力。LangChain 提供了多种工具定义方式,支持自定义工具和预构建工具。
2.2 自定义工具
2.2.1 使用 @tool 装饰器
Demo 示例:
from langchain_core.tools import tool
from pydantic import Field, BaseModel
# 方式1:基础用法
@tool
def add_number(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
# 方式2:自定义名称和描述
@tool(name_or_callable="add_two_number",
description="add two numbers",
return_direct=True)
def add_number(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
# 方式3:自定义参数描述
class FieldInfo(BaseModel):
a: int = Field(description="第1个整型参数")
b: int = Field(description="第2个整型参数")
@tool(name_or_callable="add_two_number",
description="add two numbers",
args_schema=FieldInfo)
def add_number(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
# 调用工具
result = add_number.invoke({"a": 10, "b": 20})
print(result) # 输出: 30
2.2.2 使用 StructuredTool.from_function()
Demo 示例:
from langchain_core.tools.structured import StructuredTool
from pydantic import BaseModel, Field
class FieldInfo(BaseModel):
query: str = Field(description="要检索的关键词")
def search_google(query: str):
return "最后查询的结果"
# 定义工具
search_tool = StructuredTool.from_function(
func=search_google,
name="Search",
description="查询google搜索引擎,并将结果返回",
return_direct=True,
args_schema=FieldInfo
)
# 调用工具
result = search_tool.invoke({"query": "中美AI的发展现状"})
print(result)
2.3 大模型分析工具调用
Demo 示例:
from langchain_community.tools import MoveFileTool
from langchain_core.messages import HumanMessage
from langchain_core.utils.function_calling import convert_to_openai_function
from langchain_openai import ChatOpenAI
# 定义LLM模型
chat_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 获取工具列表
tools = [MoveFileTool()]
# 将工具转换为函数格式
functions = [convert_to_openai_function(t) for t in tools]
# 获取消息列表
messages = [HumanMessage(content="将当前目录下的文件a.txt移动到C:\\Users\\shkst\\Desktop")]
# 调用大模型分析
response = chat_model.invoke(input=messages, functions=functions)
# 步骤1:分析要调用哪个工具
import json
if "function_call" in response.additional_kwargs:
tool_name = response.additional_kwargs["function_call"]["name"]
tool_args = json.loads(response.additional_kwargs["function_call"]["arguments"])
print(f"调用工具:{tool_name},参数:{tool_args}")
# 步骤2:调用对应的工具
if tool_name == "move_file":
tool = MoveFileTool()
result = tool.run(tool_args)
print("工具执行的结果", result)
else:
print(f"模型回复:{response.content}")
关键点:
- 大模型只能分析出要调用的工具,但不能真正执行
- 需要手动解析
function_call并执行工具 - Agent 可以自动完成工具调用和执行
3. Agents(智能代理)
3.1 技术概述
Agent 是 LangChain 的核心概念,它能够自主决策何时调用工具、调用哪个工具,并处理工具返回的结果。Agent 结合了 LLM 的推理能力和工具的实用性。
3.2 Agent 类型
3.2.1 ReAct 模式
特点:通过思考(Thought)、行动(Action)、观察(Observation)的循环来完成任务。
Demo 示例(传统方式):
from langchain.agents import initialize_agent, AgentType
from langchain.tools import Tool
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
# 获取Tavily搜索工具
search = TavilySearchResults(max_results=3)
search_tool = Tool(
func=search.run,
name="Search",
description="用于检索互联网上的信息",
)
# 获取大语言模型
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 获取AgentExecutor
agent_executor = initialize_agent(
tools=[search_tool],
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
# 执行查询
result = agent_executor.invoke("查询北京今天的天气情况")
print(result)
Demo 示例(通用方式):
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.prompts import PromptTemplate
from langchain import hub
# 使用LangChain Hub中的官方ReAct提示模板
prompt_template = hub.pull("hwchase17/react")
# 创建Agent
agent = create_react_agent(
llm=llm,
prompt=prompt_template,
tools=[search_tool]
)
# 创建AgentExecutor
agent_executor = AgentExecutor(
agent=agent,
tools=[search_tool],
verbose=True,
)
# 执行
result = agent_executor.invoke({"input": "查询今天北京的天气情况"})
3.2.2 Function Calling 模式
特点:利用 LLM 的原生函数调用能力,更高效。
Demo 示例(通用方式):
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# 提供提示词模板
prompt_template = ChatPromptTemplate.from_messages([
("system", "你是一个乐于助人的ai助手,根据用户的提问,必要时调用Search工具。"),
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
# 创建Agent
agent = create_tool_calling_agent(
llm=llm,
prompt=prompt_template,
tools=[search_tool]
)
# 创建AgentExecutor
agent_executor = AgentExecutor(
agent=agent,
tools=[search_tool],
verbose=True,
)
# 执行
result = agent_executor.invoke({"input": "查询今天北京的天气情况"})
3.3 多工具使用
Demo 示例:
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_experimental.utilities.python import PythonREPL
# 定义搜索工具
search = TavilySearchResults(max_results=3)
search_tool = Tool(
name="Search",
func=search.run,
description="用于搜索互联网上的信息,特别是股票价格和新闻"
)
# 定义计算工具
python_repl = PythonREPL()
calc_tool = Tool(
name="Calculator",
func=python_repl.run,
description="用于执行数学计算,例如计算百分比变化"
)
# 创建AgentExecutor
agent_executor = initialize_agent(
tools=[search_tool, calc_tool],
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
# 测试:查询股票价格并计算涨幅
query = "比亚迪当前股价是多少?比去年上涨了百分之几?"
result = agent_executor.invoke(query)
print(result)
3.4 Agent 与 Memory 结合
Demo 示例:
from langchain.memory import ConversationBufferMemory
# 获取记忆实例
memory = ConversationBufferMemory(
return_messages=True,
memory_key="chat_history"
)
# 在提示词模板中添加chat_history
prompt_template = ChatPromptTemplate.from_messages([
("system", "你是一个乐于助人的ai助手。"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}"),
])
# 创建Agent
agent = create_tool_calling_agent(llm=llm, prompt=prompt_template, tools=[search_tool])
# 创建AgentExecutor(添加memory)
agent_executor = AgentExecutor(
agent=agent,
tools=[search_tool],
verbose=True,
memory=memory,
)
# 第一轮对话
result1 = agent_executor.invoke({"input": "查询今天北京的天气情况"})
# 第二轮对话(可以引用之前的上下文)
result2 = agent_executor.invoke({"input": "上海的呢?"})
4. RAG(检索增强生成)
4.1 技术概述
RAG(Retrieval-Augmented Generation)通过检索外部知识库来增强 LLM 的生成能力,解决模型知识截止和幻觉问题。
4.2 RAG 核心组件
4.2.1 文档加载器(Document Loaders)
Demo 示例:
from langchain_community.document_loaders import TextLoader, PyPDFLoader, CSVLoader
# 加载TXT文档
text_loader = TextLoader(file_path="./documents/ai.txt", encoding="utf-8")
docs = text_loader.load()
# 加载PDF文档
pdf_loader = PyPDFLoader(file_path="./documents/report.pdf")
docs = pdf_loader.load()
# 加载CSV文档
csv_loader = CSVLoader(file_path="./documents/data.csv", encoding="utf-8")
docs = csv_loader.load()
4.2.2 文档拆分器(Text Splitters)
Demo 示例:
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 创建文本拆分器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # 每个块的最大字符数
chunk_overlap=200, # 块之间的重叠字符数
length_function=len,
add_start_index=True, # 在元数据中包含起始索引
)
# 拆分文档
split_docs = text_splitter.split_documents(docs)
4.2.3 嵌入模型(Embeddings)
Demo 示例:
from langchain_openai import OpenAIEmbeddings
# 创建嵌入模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
# 单个文本向量化
query_embedding = embeddings.embed_query("人工智能是什么?")
# 批量文档向量化
doc_embeddings = embeddings.embed_documents([
"人工智能是计算机科学的一个分支",
"机器学习是人工智能的核心技术"
])
4.2.4 向量数据库(Vector Stores)
Demo 示例:
from langchain_chroma import Chroma
from langchain_community.vectorstores import FAISS
# 使用Chroma存储
db = Chroma.from_documents(
documents=split_docs,
embedding=embeddings,
persist_directory="./vector_db/chroma_db"
)
# 使用FAISS存储
db = FAISS.from_documents(
documents=split_docs,
embedding=embeddings
)
db.save_local("./vector_db/faiss_db")
4.2.5 检索器(Retrievers)
Demo 示例:
# 创建检索器
retriever = db.as_retriever(
search_kwargs={"k": 3} # 返回前3个最相关文档
)
# 相似性检索
docs = retriever.invoke("人工智能的核心技术有哪些?")
# 带分数检索
docs_with_scores = db.similarity_search_with_score(
"人工智能的核心技术有哪些?",
k=3
)
# MMR检索(平衡相关性和多样性)
docs_mmr = db.max_marginal_relevance_search(
query="人工智能的核心技术有哪些?",
lambda_mult=0.7 # 0-1之间,0最大多样性,1最大相关性
)
4.3 完整 RAG 流程
Demo 示例:
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain.chains.combine_documents import create_stuff_documents_chain
# 1. 加载文档
loader = TextLoader("./documents/ai.txt", encoding="utf-8")
documents = loader.load()
# 2. 拆分文档
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
texts = text_splitter.split_documents(documents)
# 3. 创建向量存储
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
vectorstore = FAISS.from_documents(documents=texts, embedding=embeddings)
# 4. 创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 5. 创建提示词模板
prompt_template = """请使用以下提供的文本内容来回答问题。
仅使用提供的文本信息,如果文本中没有相关信息,请回答"抱歉,提供的文本中没有这个信息"。
文本内容:
{context}
问题:{question}
回答:"""
prompt = PromptTemplate.from_template(prompt_template)
# 6. 创建LLM
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 7. 创建文档链
document_chain = create_stuff_documents_chain(llm, prompt)
# 8. 检索相关文档
docs = retriever.invoke("人工智能的核心技术有哪些?")
# 9. 生成回答
result = document_chain.invoke({
"question": "人工智能的核心技术有哪些?",
"context": docs
})
print(result)
5. 完整综合案例
5.1 案例描述
构建一个智能对话助手,具备以下功能:
- 能够搜索互联网信息
- 能够检索本地知识库
- 具备对话记忆能力
- 能够根据问题自动选择工具
5.2 完整代码实现
import os
import dotenv
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.tools.retriever import create_retriever_tool
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
dotenv.load_dotenv()
# ========== 1. 初始化配置 ==========
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
os.environ['TAVILY_API_KEY'] = "your_tavily_api_key"
# ========== 2. 创建工具 ==========
# 工具1:互联网搜索工具
search = TavilySearchResults(max_results=3)
# 工具2:本地知识库检索工具
# 2.1 加载文档
loader = WebBaseLoader("https://zh.wikipedia.org/wiki/%E7%8C%AB")
docs = loader.load()
# 2.2 拆分文档
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
documents = splitter.split_documents(docs)
# 2.3 创建向量数据库
embedding_model = OpenAIEmbeddings()
vector_db = FAISS.from_documents(documents, embedding_model)
# 2.4 创建检索器工具
retriever = vector_db.as_retriever()
retriever_tool = create_retriever_tool(
retriever=retriever,
name="wiki_search",
description="搜索维基百科知识库,获取关于各种主题的详细信息",
)
# 工具列表
tools = [search, retriever_tool]
# ========== 3. 创建LLM ==========
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# ========== 4. 创建提示词模板 ==========
prompt = ChatPromptTemplate.from_messages([
("system", """你是一个智能助手,能够:
1. 搜索互联网获取最新信息
2. 检索本地知识库获取详细资料
3. 记住对话历史,提供连贯的对话体验
根据用户的问题,选择合适的工具来获取信息,然后给出准确、有用的回答。"""),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
# ========== 5. 创建Agent ==========
agent = create_tool_calling_agent(llm, tools, prompt)
# ========== 6. 创建AgentExecutor ==========
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
)
# ========== 7. 添加记忆功能 ==========
store = {}
def get_session_history(session_id: str) -> BaseChatMessageHistory:
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
agent_with_memory = RunnableWithMessageHistory(
runnable=agent_executor,
get_session_history=get_session_history,
input_messages_key="input",
history_messages_key="chat_history",
)
# ========== 8. 测试对话 ==========
# 测试1:搜索互联网信息
print("=" * 50)
print("测试1:搜索互联网信息")
print("=" * 50)
response = agent_with_memory.invoke(
{"input": "今天上海天气怎么样?"},
config={"configurable": {"session_id": "user_001"}},
)
print(f"回答: {response['output']}\n")
# 测试2:检索本地知识库
print("=" * 50)
print("测试2:检索本地知识库")
print("=" * 50)
response = agent_with_memory.invoke(
{"input": "猫的特征是什么?"},
config={"configurable": {"session_id": "user_001"}},
)
print(f"回答: {response['output']}\n")
# 测试3:对话记忆
print("=" * 50)
print("测试3:对话记忆")
print("=" * 50)
response = agent_with_memory.invoke(
{"input": "Hi,我的名字是Cyber"},
config={"configurable": {"session_id": "user_002"}},
)
print(f"回答: {response['output']}\n")
response = agent_with_memory.invoke(
{"input": "我叫什么名字?"},
config={"configurable": {"session_id": "user_002"}},
)
print(f"回答: {response['output']}\n")
5.3 案例功能说明
- 多工具集成:同时支持互联网搜索和本地知识库检索
- 智能工具选择:Agent 根据问题自动选择最合适的工具
- 对话记忆:使用
RunnableWithMessageHistory实现多会话记忆管理 - 会话隔离:通过
session_id实现不同用户的对话隔离
5.4 运行结果示例
==================================================
测试1:搜索互联网信息
==================================================
> Entering new AgentExecutor chain...
Invoking: `tavily_search_results_json` with `{'query': '上海天气'}`
今天上海的天气为28.8℃,微风(西南风),相对湿度72%...
==================================================
测试2:检索本地知识库
==================================================
> Entering new AgentExecutor chain...
Invoking: `wiki_search` with `{'query': '猫的特征'}`
猫的感官适于狩猎。在哺乳类动物中,猫的听觉、视觉、嗅觉、味觉、触觉极敏锐...
==================================================
测试3:对话记忆
==================================================
> Entering new AgentExecutor chain...
你好,Cyber!很高兴见到你...
> Entering new AgentExecutor chain...
你叫Cyber。有什么特别的事情想和我分享吗?
6. 总结
6.1 技术要点回顾
- Memory:管理对话历史,支持多种记忆策略
- Tools:扩展 LLM 能力,支持自定义和预构建工具
- Agents:智能决策,自动选择和执行工具
- RAG:检索增强生成,结合外部知识库提升回答质量
6.2 最佳实践
Memory 选择:
- 短对话用
ConversationBufferMemory - 长对话用
ConversationSummaryBufferMemory - 需要限制内存用
ConversationBufferWindowMemory
- 短对话用
工具设计:
- 工具描述要清晰准确
- 参数类型和描述要明确
- 工具功能要单一明确
Agent 配置:
- Function Calling 模式更高效
- ReAct 模式更灵活
- 根据场景选择合适的模式
RAG 优化:
- 合理设置 chunk_size 和 chunk_overlap
- 选择合适的嵌入模型
- 使用 MMR 平衡相关性和多样性
6.3 扩展学习
- LangChain 官方文档:https://python.langchain.com/
- LangGraph:更强大的 Agent 框架
- 向量数据库选择:Chroma、FAISS、Pinecone 等
- 提示词工程:优化提示词提升效果
浙公网安备 33010602011771号