LangChain入门学习教程三
引言
嘿,小伙伴们!欢迎来到《LangChain入门学习教程三》。如果你已经跟随我们的脚步走过了前两篇教程,那么恭喜你,现在已经是 LangChain 小能手啦!不过别急着庆祝哦,今天我们还有更多的惊喜等着你呢!
在上一篇中,我们聊了聊如何与语言模型交互、使用提示模板、处理大规模数据集以及构建链式结构等高级话题。今天,我们将深入探讨记忆模块和代理人模块这两个关键组件,带你解锁更多 LangChain 的魔法。
记忆模块:让聊天机器人更有"人情味"
什么是记忆模块?
想象一下,你正在和一个老朋友聊天。你们聊了很多很多的事情,从最近的工作进展到周末计划,再到那些共同度过的美好时光。当你再次提起某个特定的话题时,你的朋友立刻就能想起之前的对话内容,并且能够流畅地继续讨论下去。这是因为你们之间存在着一种"记忆",这种记忆不仅包括具体的事件,还包括彼此的情感和互动模式。
同样,在构建智能聊天机器人时,我们也希望它具备一定的"记忆力"。这样,无论是多轮对话还是长时间的交流,聊天机器人都能记住之前的内容,并据此生成更自然、更贴合上下文的回复。这就是 LangChain 中的记忆模块(Memory)所要解决的问题。
记忆模块的作用
- 增强连贯性:确保对话的前后一致,避免重复提问或回答。
- 提升个性化:根据用户的偏好和历史行为提供个性化的服务。
- 支持复杂任务:处理涉及多个步骤或依赖先前信息的任务。
记忆模块的类型
LangChain 提供了几种不同类型的记忆模块,每种都有其独特的用途和特点:
1. 简单内存(Simple Memory)
简单内存是最基础的一种记忆模块,适用于不需要复杂操作的场景。它会将所有的对话历史保存在一个列表中,并在每次生成回复时将其作为输入的一部分传递给语言模型。
python
from langchain.memory import SimpleMemory
memory = SimpleMemory()
# 添加对话历史
memory.save_context({"input": "你好"}, {"output": "你好!有什么我可以帮忙的吗?"})
memory.save_context({"input": "我想了解一下机器学习"}, {"output": "当然可以!机器学习是一种人工智能技术...'})
# 获取对话历史
history = memory.load_memory_variables({})
print(history)
2. 向量存储记忆(Vector Store Memory)
向量存储记忆结合了向量数据库的强大功能,可以高效地存储和检索大量的对话历史。这对于需要处理大量对话记录的应用非常有用。
python
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.memory import VectorStoreRetrieverMemory
# 初始化嵌入模型
embeddings = OpenAIEmbeddings(openai_api_key="your-openai-api-key")
# 创建向量存储
vectorstore = FAISS(embeddings.embedding_dim)
# 初始化记忆模块
memory = VectorStoreRetrieverMemory(vectorstore=vectorstore, embeddings=embeddings)
# 添加对话历史
memory.save_context({"input": "你好"}, {"output": "你好!有什么我可以帮忙的吗?"})
memory.save_context({"input": "我想了解一下机器学习"}, {"output": "当然可以!机器学习是一种人工智能技术..."})
# 获取相关对话历史
related_history = memory.load_memory_variables({})
print(related_history)
3. 数据库记忆(Database Memory)
数据库记忆则利用关系型数据库来存储对话历史,适合需要长期保存和频繁访问的历史记录。你可以选择 MySQL、PostgreSQL 等多种数据库来实现。
python
from langchain.memory import SQLDatabaseChatMessageHistory
from sqlalchemy import create_engine
# 创建数据库引擎
engine = create_engine('sqlite:///chat_history.db')
# 初始化记忆模块
memory = SQLDatabaseChatMessageHistory(engine=engine, session_id="session_123")
# 添加对话历史
memory.add_user_message("你好")
memory.add_ai_message("你好!有什么我可以帮忙的吗?")
memory.add_user_message("我想了解一下机器学习")
memory.add_ai_message("当然可以!机器学习是一种人工智能技术...")
# 获取对话历史
history = memory.messages
for msg in history:
print(msg)
自定义记忆模块
除了上述几种内置的记忆模块外,LangChain 还允许你自定义自己的记忆模块。你可以根据具体的需求编写代码,实现特定的功能。
python
from langchain.memory.base import BaseMemory
class CustomMemory(BaseMemory):
def __init__(self):
self.history = []
def save_context(self, inputs: dict, outputs: dict) -> None:
self.history.append((inputs, outputs))
def load_memory_variables(self, inputs: dict) -> dict:
return {"history": self.history}
# 使用自定义记忆模块
memory = CustomMemory()
# 添加对话历史
memory.save_context({"input": "你好"}, {"output": "你好!有什么我可以帮忙的吗?"})
memory.save_context({"input": "我想了解一下机器学习"}, {"output": "当然可以!机器学习是一种人工智能技术..."})
# 获取对话历史
history = memory.load_memory_variables({})
print(history)
代理人模块:让 AI 成为真正的"助手"
什么是代理人?
还记得我们在第二篇中提到的那个智能助手吗?它可以帮你完成一系列复杂的任务,比如预定机票、订酒店等等。这样的智能助手并不是简单的聊天机器人,而是具备更强自主性的代理系统。这些系统可以根据用户的需求动态决策,选择合适的工具并执行相应的操作,最终达到解决问题的目的。
代理人模块的作用
- 自动化任务:自动完成一系列预设的任务,减少人工干预。
- 多工具协作:整合多种工具和服务,提高工作效率。
- 适应性强:能够应对不同的场景和需求变化。
代理人模块的工作原理
代理人模块的核心思想是通过语言模型来指导整个任务的执行过程。具体来说,代理人会按照以下步骤工作:
- 接收任务请求:获取用户提出的任务需求。
- 分解任务:将复杂任务分解成多个子任务。
- 选择工具:根据当前任务需求选择合适的工具。
- 执行工具:调用选定的工具执行相应的操作。
- 观察结果:分析工具返回的结果,判断是否满足要求。
- 调整策略:如果结果不符合预期,重新评估任务并调整策略。
- 完成任务:当所有子任务完成后,生成最终的输出。
构建一个简单的代理人
接下来,我们一起来构建一个简单的代理人,帮助用户预订酒店。这个代理人将包含以下几个部分:
- 工具集合:用于查询酒店和确认预订的工具。
- 语言模型:用于生成指令和解析结果的语言模型。
- 记忆模块:用于存储对话历史和中间状态。
- 代理人控制器:负责协调各个组件的协同工作。
1. 定义工具
首先,我们需要定义一些工具来处理具体的任务。这里我们模拟两个工具:HotelSearchTool
和 BookingConfirmationTool
。
python
from langchain.tools import Tool
class HotelSearchTool(Tool):
name = "hotel_search"
description = "Search for hotels based on location and date range."
def _run(self, location: str, start_date: str, end_date: str) -> str:
# 模拟查询酒店的过程
return f"Found hotels in {location} from {start_date} to {end_date}: Hotel A, Hotel B"
async def _arun(self, location: str, start_date: str, end_date: str) -> str:
raise NotImplementedError("This tool does not support async execution.")
class BookingConfirmationTool(Tool):
name = "booking_confirmation"
description = "Confirm booking details with the user."
def _run(self, booking_details: str) -> str:
# 模拟确认预订的过程
return f"Confirmed booking for {booking_details}"
async def _arun(self, booking_details: str) -> str:
raise NotImplementedError("This tool does not support async execution.")
2. 初始化语言模型
接下来,我们需要初始化一个语言模型来生成指令和解析结果。这里我们使用 OpenAI 的 GPT-3 模型。
python
from langchain.llms import OpenAI
llm = OpenAI(api_key="your-openai-api-key")
3. 初始化记忆模块
为了确保对话的连贯性,我们需要一个记忆模块来存储对话历史和中间状态。
python
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
4. 创建代理人控制器
最后,我们需要创建一个代理人控制器来协调各个组件的协同工作。LangChain 提供了一个灵活的框架来实现这一点。
python
from langchain.agents import initialize_agent, AgentType
# 定义工具集合
tools = [HotelSearchTool(), BookingConfirmationTool()]
# 创建代理人
agent = initialize_agent(
tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
memory=memory
)
5. 测试代理人
现在,我们可以测试一下我们的代理人,看看它能否正确地处理用户的预订请求。
python
# 用户请求
user_input = "我想在巴黎从2025年4月1日到2025年4月5日预订酒店。"
# 使用代理人处理请求
response = agent.run(user_input)
print(response)
运行上述代码后,你应该会看到类似如下的输出:
vbnet
> Entering new AgentExecutor chain...
Action: hotel_search
Action Input: {"location": "巴黎", "start_date": "2025年4月1日", "end_date": "2025年4月5日"}
Observation: Found hotels in 巴黎 from 2025年4月1日 to 2025年4月5日: Hotel A, Hotel B
Thought: 我找到了两家酒店:Hotel A 和 Hotel B。你想预订哪家?
Action: booking_confirmation
Action Input: {"booking_details": "Hotel A, Paris, 2025-04-01 to 2025-04-05"}
Observation: Confirmed booking for Hotel A, Paris, 2025-04-01 to 2025-04-05
Thought: 预订已确认。祝您旅途愉快!
Final Answer: 预订已确认。祝您旅途愉快!
可以看到,代理人成功地完成了以下步骤:
- 接收任务请求:获取用户的预订请求。
- 分解任务:将预订任务分解成查询酒店和确认预订两个子任务。
- 选择工具:根据当前任务需求选择合适的工具。
- 执行工具:调用选定的工具执行相应的操作。
- 观察结果:分析工具返回的结果,判断是否满足要求。
- 调整策略:如果结果符合预期,则生成最终的回答。
- 完成任务:生成最终的输出。
自定义代理人
除了使用 LangChain 提供的标准代理人外,你还可以根据具体的需求自定义代理人。这包括自定义工具、语言模型、记忆模块等各个组件。
python
from langchain.agents import AgentExecutor
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
# 自定义提示模板
prompt_template = PromptTemplate.from_template("""
You are a helpful assistant. Here is the conversation so far:
{chat_history}
Current task: {task_description}
Choose an action from the list below:
1. hotel_search
2. booking_confirmation
Your decision:
""")
# 创建 LLM 链
llm_chain = LLMChain(llm=llm, prompt=prompt_template)
# 自定义代理人
custom_agent = AgentExecutor.from_agent_and_tools(
agent=llm_chain,
tools=[HotelSearchTool(), BookingConfirmationTool()],
verbose=True,
memory=memory
)
# 测试自定义代理人
user_input = "我想在巴黎从2025年4月1日到2025年4月5日预订酒店。"
response = custom_agent.run(task_description=user_input)
print(response)
在这个示例中,我们自定义了一个提示模板,并使用它来创建一个 LLM 链。然后,我们将这个 LLM 链与工具集合和记忆模块结合起来,创建了一个自定义的代理人。运行上述代码后,你会看到类似的输出结果。
实战演练 - 构建一个问答机器人
步骤 1: 初始化项目
首先,创建一个新的项目目录并初始化 npm 项目:
sh
mkdir my-langchain-chatbot
cd my-langchain-chatbot
npm init -y
步骤 2: 安装必要的依赖
安装 LangChain 和 OpenAI 的 SDK:
sh
npm install langchain openai
步骤 3: 编写代码
创建一个名为 index.js
的文件,并编写以下代码:
javascript
const { ChatOpenAI } = require("langchain/chat_models/openai");
const { HumanMessage, AIMessage } = require("langchain/schema");
const { ConversationBufferMemory } = require("langchain/memory");
// 初始化 ChatOpenAI 模型
const chatModel = new ChatOpenAI({ openAIApiKey: "your-openai-api-key" });
// 初始化记忆模块
const memory = new ConversationBufferMemory();
// 处理用户输入
async function handleUserInput(userInput) {
// 添加用户消息到记忆模块
await memory.saveContext({ input: userInput }, {});
// 获取对话历史
const chatHistory = await memory.loadMemoryVariables({});
// 使用 predict_messages 方法生成回复
const responseMessages = await chatModel.predict_messages(chatHistory.chat_history);
let latestResponse = null;
responseMessages.forEach((message) => {
if (message instanceof HumanMessage) {
console.log(`You: ${message.content}`);
} else if (message instanceof AIMessage) {
console.log(`AI: ${message.content}`);
latestResponse = message.content;
}
});
// 更新记忆模块
await memory.saveContext({}, { output: latestResponse });
// 模拟继续对话
continueConversation(latestResponse);
}
// 模拟继续对话
function continueConversation(lastResponse) {
if (lastResponse.includes("再见")) {
console.log("对话结束!");
return;
}
const nextInput = prompt("请输入您的下一个问题: ");
handleUserInput(nextInput);
}
// 启动对话
console.log("欢迎来到问答机器人!您可以开始提问了。");
const initialInput = prompt("请输入您的问题: ");
handleUserInput(initialInput);
步骤 4: 运行应用
确保你已经安装了所有依赖项,然后运行你的应用程序:
sh
node index.js
你应该会看到类似如下的输出:
makefile
欢迎来到问答机器人!您可以开始提问了。
请输入您的问题: 什么是机器学习?
You: 什么是机器学习?
AI: 机器学习是一种人工智能技术,通过算法使计算机从数据中自动学习并改进。
请输入您的下一个问题: 有哪些常见的机器学习算法?
You: 有哪些常见的机器学习算法?
AI: 常见的机器学习算法包括线性回归、逻辑回归、决策树、支持向量机、神经网络等。
请输入您的下一个问题: 再见
You: 再见
AI: 再见!祝您有愉快的一天!
对话结束!
总结
通过本篇文章,我们深入了解了 LangChain 中的记忆模块和代理人模块。记忆模块可以帮助聊天机器人记住对话历史,从而生成更自然、更贴合上下文的回复;而代理人模块则可以让 AI 具备更强的自主性,自动完成一系列复杂的任务。这两种模块的结合使得 LangChain 成为了构建智能应用的强大工具。
希望这篇教程能让你对 LangChain 有更深的理解,并激发你探索更多有趣的应用场景。如果你有任何问题或需要进一步的帮助,请随时提问。快来加入 LangChain 的大家庭,开启你的语言模型之旅吧!