LangChain Agent 会话持久化系统(Redis版)
1. 项目概述
1.1 项目简介
本项目是一个基于LangChain框架构建的智能 Agent 系统,集成了多种工具(百科检索、实时搜索),并使用Redis实现会话历史的持久化存储。系统支持多用户、多对话的会话管理,具备完整的降级机制,在网络受限环境下也能正常运行。
1.2 核心功能
| 功能模块 | 描述 | 状态 |
|---|
| 百科检索工具 | 基于向量数据库的文档检索,支持本地知识库查询 | ✅ 已实现 |
| 实时搜索工具 | 集成 Tavily 搜索引擎,支持实时信息获取 | ✅ 已实现 |
| 智能 Agent | 基于 GPT-3.5 的工具调用决策引擎 | ✅ 已实现 |
| Redis 会话存储 | 使用 Redis 持久化会话历史 | ✅ 已实现 |
| 多轮对话支持 | 支持同一用户的多轮上下文对话 | ✅ 已实现 |
| 降级机制 | 网络异常时自动切换到模拟数据模式 | ✅ 已实现 |
2. 技术架构
2.1 系统架构图
┌─────────────────────────────────────────────────────────────────────────────┐ │ 用户查询入口 │ │ user_id + conversation_id + input │ └─────────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ RunnableWithMessageHistory │ │ (会话历史管理 + 自动保存/加载) │ └─────────────────────────────────────────────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ ▼ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ Redis 存储 │ │ Agent │ │ LLM │ │ (会话历史) │ │ Executor │ │ GPT-3.5-turbo │ └───────────────┘ └───────────────┘ └───────────────┘ │ │ ▼ ▼ ┌───────────────┐ ┌───────────────┐ │ Redis DB │ │ Tool Set │ │ 127.0.0.1 │ │ 百科/搜索 │ └───────────────┘ └───────────────┘
2.2 技术栈
| 类别 | 技术 | 版本要求 | 用途 |
|---|
| 核心框架 | LangChain | 1.0+ | 构建 Agent 和工具链 |
| LLM | OpenAI ChatGPT | gpt-3.5-turbo | 智能决策和回答生成 |
| 向量数据库 | FAISS | 最新 | 文档向量存储和检索 |
| 搜索引擎 | Tavily | 最新 | 实时信息搜索 |
| 会话存储 | Redis | 6.0+ | 会话历史持久化 |
| 文档加载 | WebBaseLoader | 最新 | 网页内容抓取 |
| 文本分块 | RecursiveCharacterTextSplitter | 最新 | 长文本分块处理 |
| 向量化 | FakeEmbeddings | 最新 | 模拟向量(无 token 消耗) |
3. 核心模块详解
3.1 向量化模块
设计目的: 使用FakeEmbeddings进行模拟向量化,完全不消耗 token,适合开发测试环境。
| 参数 | 值 | 说明 |
|---|
size | 1536 | 向量维度,与 OpenAI Embeddings 保持一致 |
使用示例:
fromlangchain_core.embeddingsimportFakeEmbeddings embeddings=FakeEmbeddings(size=1536)
向量化降级策略:
| 步骤 | 方案 | 条件 | 代码行 |
|---|
| 1 | FakeEmbeddings | 默认使用 | L6 |
| 2 | 备用 FakeEmbeddings | 主方案失败时 | L35-L36 |
3.2 百科检索工具
核心流程:
| 步骤 | 组件 | 作用 | 代码行 |
|---|
| 1 | WebBaseLoader | 加载网页内容 | L21-L26 |
| 2 | RecursiveCharacterTextSplitter | 文本分块 | L28-L29 |
| 3 | FakeEmbeddings | 生成模拟向量 | L32 |
| 4 | FAISS | 向量存储 | L32 |
| 5 | create_retriever_tool | 创建检索工具 | L38-L39 |
分块参数配置:
| 参数 | 值 | 说明 |
|---|
chunk_size | 1000 | 每个文本块的最大字符数 |
chunk_overlap | 200 | 相邻文本块的重叠字符数 |
降级机制:
| 异常场景 | 处理方式 | 代码行 |
|---|
| 网页加载失败 | 使用预定义的模拟文档 | L21-L26 |
| 向量化失败 | 使用备用 FakeEmbeddings | L31-L36 |
3.3 实时搜索工具
核心流程:
| 步骤 | 组件 | 作用 | 代码行 |
|---|
| 1 | langchain_tavily.TavilySearch | 初始化搜索工具 | L50-L54 |
| 2 | max_results=1 | 配置返回结果数量 | L53 |
降级机制:
| 异常场景 | 处理方式 | 代码行 |
|---|
| API Key 缺失/无效 | 创建模拟工具函数 | L55-L60 |
模拟工具定义:
@tooldeftavily_search_tool(query:str)->str:returnf"搜索结果:{query}- 模拟数据"
3.4 智能 Agent
核心组件:
| 组件 | 类名 | 作用 | 代码行 |
|---|
| LLM | ChatOpenAI | 大语言模型 | L87 |
| Prompt | ChatPromptTemplate | 对话模板 | L80-L85 |
| Agent | create_tool_calling_agent | 创建工具调用 Agent | L88 |
| Executor | AgentExecutor | Agent 执行器 | L89 |
Prompt 结构:
| 消息类型 | 内容 | 说明 |
|---|
| system | “你是一个专业的助手,使用提供的工具回答用户问题。” | 系统角色定义 |
| history | MessagesPlaceholder(variable_name=“history”) | 会话历史 |
| human | “{input}” | 用户输入 |
| agent_scratchpad | MessagesPlaceholder(variable_name=“agent_scratchpad”) | Agent 思考过程 |
3.5 Redis 会话存储(核心模块)
3.5.1 Redis 连接配置
| 参数 | 值 | 说明 |
|---|
redis_url | redis://localhost:6379/2 | Redis 连接地址,使用第 2 个数据库 |
host | localhost | Redis 服务器地址 |
port | 6379 | Redis 默认端口 |
db | 2 | 使用的数据库编号 |
连接测试:
importredis r=redis.Redis.from_url(redis_url)r.ping()# 返回 True 表示连接成功
3.5.2 会话历史获取函数
defget_history(user_id:str,conversation_id:str)->RedisChatMessageHistory:returnRedisChatMessageHistory(session_id=f"{user_id}:{conversation_id}",url=redis_url)
| 参数 | 类型 | 说明 |
|---|
user_id | str | 用户唯一标识符 |
conversation_id | str | 对话唯一标识符 |
session_id | str | 组合键{user_id}:{conversation_id} |
3.5.3 RunnableWithMessageHistory 配置
配置字段:
| 字段 | ID | 类型 | 默认值 | 说明 |
|---|
| User ID | user_id | str | “” | 用户的唯一标识符 |
| Conversation ID | conversation_id | str | “” | 对话的唯一标识符 |
配置参数:
| 参数 | 值 | 说明 |
|---|
input_messages_key | “input” | 用户输入的键名 |
history_messages_key | “history” | 历史消息的键名 |
is_shared | True | 配置是否在多次调用间共享 |
4. 工具注册与调用
4.1 工具列表
| 工具名称 | 变量名 | 类型 | 描述 |
|---|
search_baike | retriever_tool | RetrieverTool | 百科检索,基于向量数据库 |
tavily_search | tavily_search_tool | TavilySearch/Tool | 实时搜索,基于 Tavily API |
4.2 多轮对话调用流程
┌─────────────────────────────────────────────────────────────────────┐ │ 第一次调用 │ │ input: "Hi,我的名字是Cyber" │ │ config: {"user_id": "user01", "conversation_id": "conversation_1"} │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ Redis 存储: "user01:conversation_1" → [HumanMessage, AIMessage] │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 第二次调用 │ │ input: "我叫什么名字?" │ │ config: {"user_id": "user01", "conversation_id": "conversation_1"} │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ Redis 读取历史 → Agent 理解上下文 → 回答: "你叫Cyber" │ └─────────────────────────────────────────────────────────────────────┘
4.3 调用示例
# 第一次对话response=with_agent_history.invoke({"input":"Hi,我的名字是Cyber"},config={"configurable":{"user_id":"user01","conversation_id":"conversation_1"}})# 第二次对话(同一会话)response=with_agent_history.invoke({"input":"我叫什么名字?"},config={"configurable":{"user_id":"user01","conversation_id":"conversation_1"}})
5. 环境变量配置
5.1 必需环境变量
| 环境变量 | 说明 | 获取方式 |
|---|
OPENAI_API_KEY | OpenAI API Key | https://platform.openai.com/ |
TAVILY_API_KEY | Tavily 搜索 API Key | https://tavily.com/ |
5.2 Redis 配置
| 参数 | 默认值 | 说明 |
|---|
redis_url | redis://localhost:6379/2 | Redis 连接地址 |
REDIS_HOST | localhost | Redis 服务器地址 |
REDIS_PORT | 6379 | Redis 端口 |
REDIS_DB | 2 | 数据库编号 |
5.3 设置方法
Windows PowerShell:
# 临时设置(当前终端有效)$env:OPENAI_API_KEY="your-key"$env:TAVILY_API_KEY="your-key"# 永久设置(用户级别)[Environment]::SetEnvironmentVariable("OPENAI_API_KEY","your-key","User")[Environment]::SetEnvironmentVariable("TAVILY_API_KEY","your-key","User")
6. 依赖安装
6.1 核心依赖
| 依赖包 | 安装命令 | 用途 |
|---|
| langchain | pip install langchain | 核心框架 |
| langchain-openai | pip install langchain-openai | OpenAI 集成 |
| langchain-community | pip install langchain-community | 社区工具集 |
| langchain-tavily | pip install langchain-tavily | Tavily 搜索 |
| faiss-cpu | pip install faiss-cpu | 向量数据库 |
| redis | pip install redis | Redis 客户端 |
| python-dotenv | pip install python-dotenv | 环境变量加载 |
6.2 一键安装
pip install langchain langchain-openai langchain-community langchain-tavily faiss-cpu redis python-dotenv
7. Redis 安装与配置
7.1 Windows 安装
方式一:使用 Chocolatey
choco install redis-64
方式二:手动安装
- 下载 Redis: https://github.com/tporadowski/redis/releases
- 解压到
D:\Redis - 添加到 PATH 环境变量
7.2 启动 Redis
# 启动 Redis 服务器redis-server.exe# 连接测试redis-cli.exe ping# 返回 PONG 表示成功
![]()
7.3 Redis 数据结构
| 键名格式 | 存储内容 | 数据类型 |
|---|
user_id:conversation_id | 会话消息列表 | List |
![]()
8. 运行说明
8.1 前提条件
| 条件 | 说明 |
|---|
| Redis 服务 | 必须运行在 localhost:6379 |
| Python 环境 | 3.10+ |
| 环境变量 | 已设置 OPENAI_API_KEY |
8.2 运行步骤
# 1. 启动 Redis(如果未运行)redis-server.exe# 2. 切换到项目目录cd e:\AI-Study\AI-demo\day-07\agent# 3. 设置环境变量$env:OPENAI_API_KEY="your-key"# 4. 运行脚本python agent_tools_llm_memory_redis.py
8.3 预期输出
正常模式:
✅ Redis 连接成功! True > Entering new AgentExecutor chain... 你好,Cyber,很高兴见到你!有什么我可以帮助你的吗? > Finished chain. {'input': 'Hi,我的名字是Cyber', 'history': [...], 'output': '你好,Cyber...'} > Entering new AgentExecutor chain... 你说你的名字是Cyber。有什么我可以帮你的吗,Cyber? > Finished chain. {'input': '我叫什么名字?', 'history': [...], 'output': '你说你的名字是Cyber...'}
Redis 连接失败:
❌ Redis 连接失败: Connection refused
实战演示:
![]()
9. 代码优化建议
9.1 改进方向
| 建议 | 当前状态 | 优先级 |
|---|
添加.env文件支持 | 未实现 | 高 |
| Redis 连接配置外部化 | 硬编码 | 高 |
| 添加日志系统 | 使用 print | 中 |
| 添加会话管理 API | 未实现 | 中 |
| 支持 Redis 密码认证 | 未实现 | 中 |
| 添加配置文件 | 硬编码 | 中 |
9.2 待修复的废弃警告
| 警告来源 | 当前使用 | 建议替换 |
|---|
| langchain-community | WebBaseLoader,FAISS,RedisChatMessageHistory | 使用独立包 |
10. 故障排除
10.1 常见问题
| 错误信息 | 原因 | 解决方案 |
|---|
Connection refused | Redis 服务未启动 | 运行redis-server.exe |
Request timed out | 网络无法访问外网 | 检查网络连接 |
Invalid API key | API Key 无效 | 确认 API Key 正确性 |
ModuleNotFoundError: redis | 未安装 Redis 依赖 | pip install redis |
PydanticValidationError | Redis URL 格式错误 | 检查redis_url格式 |
10.2 调试命令
# 检查 Redis 连接redis-cli.exe ping# 查看 Redis 中的会话数据redis-cli.exe-n 2 keys"*"# 查看会话历史redis-cli.exe-n 2 lrange user01:conversation_1 0-1
11. 版本历史
| 版本 | 日期 | 修改内容 |
|---|
| v1.0 | 2026-07-03 | 初始版本,实现基本功能 |
| v1.1 | 2026-07-03 | 添加 Redis 会话持久化 |
| v1.2 | 2026-07-03 | 使用 FakeEmbeddings 减少 token 消耗 |
12. 附录
12.1 Redis 会话管理命令
# 获取会话历史history=get_history("user01","conversation_1")messages=history.messages# 手动添加消息history.add_user_message("Hello")history.add_ai_message("Hi there!")# 清空会话历史history.clear()# 删除会话importredis r=redis.Redis.from_url("redis://localhost:6379/2")r.delete("user01:conversation_1")
12.2 多用户多对话示例
# 用户1 - 对话1response=with_agent_history.invoke({"input":"今天天气怎么样?"},config={"configurable":{"user_id":"user01","conversation_id":"conv_001"}})# 用户1 - 对话2(独立会话)response=with_agent_history.invoke({"input":"推荐一些电影"},config={"configurable":{"user_id":"user01","conversation_id":"conv_002"}})# 用户2 - 对话1(完全独立)response=with_agent_history.invoke({"input":"你好"},config={"configurable":{"user_id":"user02","conversation_id":"conv_001"}})
想要获取源代码,有三种路径:记得给个star哦!
访问我的gitee仓库(推荐)https://gitee.com/weh_coder/weh-langchain-agent-demo/blob/master/agent_tools_llm_memory_redis.py