- 瀹炵幇鍩轰簬llama_index + Ollama鐨凙I瀵硅瘽鍔熻兘 - 娣诲姞.ai鍜?aiconfig鎸囦护鏀寔 - 瀹炵幇鍥哄畾10绉掔瓑寰呯獥鍙g殑寤惰繜鍥炵瓟鏈哄埗 - 鏀寔澶氱敤鎴峰璇濆拰鐢ㄦ埛瑙掕壊鏄犲皠 - 瀹炵幇闀夸笂涓嬫枃绠$悊锛?0+杞璇濓級 - 绯荤粺鎻愮ず璇嶆寔涔呭寲鍒伴厤缃枃浠?- 浼樺寲閿欒澶勭悊鍜岃皟璇曚俊鎭?- 娣诲姞NPS绔彛杞彂鏀寔璇存槑
367 lines
14 KiB
Markdown
367 lines
14 KiB
Markdown
# 背景
|
||
文件名:2025-10-29_3_ai_chat.md
|
||
创建于:2025-10-29_23:32:40
|
||
创建者:user
|
||
主分支:main
|
||
任务分支:task/ai_chat_2025-10-29_3
|
||
Yolo模式:Off
|
||
|
||
# 任务描述
|
||
在本项目中新增一个AI对话功能,使用llama_index构建,服务商为本地部署的ollama。
|
||
|
||
这个智能体将拥有足够长的上下文(超过30轮对话历史),能够同时与不同的用户展开交流。例如用户A提问后用户B进行补充,智能体将通过时间间隔判断机制来决定何时进行回答。
|
||
|
||
## 核心需求
|
||
1. **显式指令触发**:使用 `.ai <问题>` 指令触发AI对话
|
||
2. **配置指令**:使用 `.aiconfig` 指令配置Ollama服务地址、端口和模型名称
|
||
3. **时间间隔判断**:智能体通过时间间隔判断是否需要回答(固定10秒等待窗口)
|
||
4. **长上下文管理**:保留超过30轮对话历史
|
||
5. **多用户对话支持**:同一chat_id下不同用户的消息能够被正确识别和处理
|
||
|
||
## 技术方案决策(已确定)
|
||
1. **延迟任务机制**:使用 asyncio 的延迟任务(方案三)
|
||
- 每个 chat_id 维护独立的延迟任务句柄
|
||
- 使用全局字典存储任务映射
|
||
- 收到新消息时取消旧任务并创建新任务
|
||
|
||
2. **上下文管理**:使用 llama_index 的 ChatMemoryBuffer(策略A)
|
||
- 设置足够的 token_limit 确保保留30+轮对话
|
||
- 按 chat_id 独立维护 ChatEngine 实例
|
||
|
||
3. **多用户识别**:消息角色映射 + 系统提示(方案C)
|
||
- 将不同用户映射为不同角色(如"用户1"、"用户2")
|
||
- 在系统提示中明确告知存在多用户场景
|
||
- ChatMemoryBuffer 中使用角色区分不同用户
|
||
|
||
4. **等待窗口**:固定10秒窗口(变体1)
|
||
- 收到消息后等待10秒
|
||
- 等待期间有新消息则重新计时
|
||
|
||
5. **配置管理**:使用单独的JSON文件
|
||
- 配置存储在 `data/ai_config.json`
|
||
- 全局单一配置(服务器级别,非chat级别)
|
||
- 通过 `.aiconfig` 指令修改配置并保存到文件
|
||
|
||
# 项目概览
|
||
|
||
## 项目结构
|
||
```
|
||
WPSBot/
|
||
├── app.py # FastAPI主应用
|
||
├── config.py # 配置管理
|
||
├── core/ # 核心模块
|
||
│ ├── database.py # 数据库操作
|
||
│ ├── models.py # 数据模型
|
||
│ └── middleware.py # 中间件
|
||
├── routers/ # 路由模块
|
||
│ ├── callback.py # 回调处理
|
||
│ └── health.py # 健康检查
|
||
├── games/ # 游戏模块
|
||
│ ├── base.py # 游戏基类
|
||
│ └── ... # 其他游戏
|
||
├── utils/ # 工具模块
|
||
│ ├── message.py # 消息发送
|
||
│ ├── parser.py # 指令解析
|
||
│ └── rate_limit.py # 限流控制
|
||
└── data/ # 数据文件
|
||
```
|
||
|
||
## 技术栈
|
||
- FastAPI:Web框架
|
||
- SQLite:数据存储
|
||
- llama-index-core:AI对话框架核心
|
||
- llama-index-llms-ollama:Ollama LLM集成
|
||
- Ollama:本地LLM服务
|
||
|
||
# 分析
|
||
|
||
## 现有架构
|
||
1. **指令处理流程**:
|
||
- 消息通过 `/api/callback` 接收
|
||
- `CommandParser` 解析指令,只处理以 `.` 开头的命令
|
||
- 非指令消息会被忽略
|
||
- 指令分发到对应的游戏处理器
|
||
|
||
2. **状态管理**:
|
||
- 游戏状态存储在 `game_states` 表
|
||
- 使用 `(chat_id, user_id, game_type)` 作为联合主键
|
||
- 对于群组共享状态,使用 `user_id=0`(如成语接龙)
|
||
|
||
3. **异步任务**:
|
||
- 已有 `periodic_cleanup` 后台清理任务示例
|
||
- 使用 `asyncio.create_task` 和 `asyncio.sleep` 实现
|
||
|
||
## 关键技术挑战
|
||
|
||
### 1. 延迟回答机制
|
||
需要实现一个基于时间间隔的判断机制:
|
||
- 收到 `.ai` 指令时,将消息加入等待队列
|
||
- 设置一个等待窗口(例如5-10秒)
|
||
- 如果在等待窗口内有新消息,重新计时
|
||
- 等待窗口结束后,如果没有新消息,生成回答
|
||
- 需要在 `chat_id` 级别维护等待队列和延迟任务
|
||
|
||
### 2. 长上下文管理
|
||
- 使用 llama_index 的 `ChatMemoryBuffer` 管理对话历史
|
||
- 确保超过30轮对话历史能够被保留
|
||
- 对话历史需要按 `chat_id` 独立存储
|
||
- 对话历史中需要包含用户ID信息,以便区分不同用户
|
||
|
||
### 3. Ollama配置管理
|
||
- 使用全局单一配置(服务器级别)
|
||
- 配置存储在 `data/ai_config.json` 文件中
|
||
- 配置包括:服务地址、端口、模型名称
|
||
- 通过 `.aiconfig` 指令修改配置并持久化到文件
|
||
- 配置需要有默认值(localhost:11434,默认模型需指定)
|
||
|
||
### 4. 多用户对话识别
|
||
- 对话历史中需要记录每条消息的发送者(user_id)
|
||
- 生成回复时,需要识别上下文中的不同用户
|
||
- 回复格式可以考虑使用 @用户 的方式
|
||
|
||
### 5. 依赖管理
|
||
- 需要添加 llama-index-core 和相关依赖
|
||
- 需要确保与现有代码库的兼容性
|
||
- 考虑资源占用(内存、CPU)
|
||
|
||
## 数据结构设计
|
||
|
||
### AI对话状态数据结构
|
||
对话状态由 llama_index 的 ChatMemoryBuffer 管理,存储在内存中。
|
||
需要存储的额外信息:
|
||
|
||
```python
|
||
# 存储在 game_states 表中的 state_data
|
||
{
|
||
"user_mapping": { # 用户ID到角色名称的映射
|
||
"123456": "用户1",
|
||
"789012": "用户2",
|
||
...
|
||
},
|
||
"user_count": 2 # 当前对话中的用户数量
|
||
}
|
||
```
|
||
|
||
### 配置数据结构(存储在 data/ai_config.json)
|
||
```json
|
||
{
|
||
"host": "localhost",
|
||
"port": 11434,
|
||
"model": "llama3.1"
|
||
}
|
||
```
|
||
|
||
### 数据库扩展
|
||
使用 `game_states` 表存储用户映射信息:
|
||
- `chat_id`: 会话ID
|
||
- `user_id`: 0(表示群组级别)
|
||
- `game_type`: "ai_chat"
|
||
- `state_data`: JSON格式的用户映射信息
|
||
|
||
注意:对话历史由 ChatMemoryBuffer 在内存中管理,不持久化到数据库。
|
||
|
||
# 提议的解决方案
|
||
|
||
## 方案概述
|
||
1. 创建一个新的游戏模块 `games/ai_chat.py`,继承 `BaseGame`
|
||
2. 使用 `game_states` 表存储用户映射信息(用户ID到角色名称的映射)
|
||
3. 使用全局字典维护每个 `chat_id` 的延迟任务句柄
|
||
4. 使用全局字典维护每个 `chat_id` 的 ChatEngine 实例和待处理消息队列
|
||
5. 使用 `data/ai_config.json` 存储 Ollama 全局配置
|
||
6. 使用 llama_index 的 ChatMemoryBuffer 管理对话上下文(内存中)
|
||
|
||
## 实现细节
|
||
|
||
### 1. 指令注册
|
||
在 `utils/parser.py` 中添加:
|
||
- `.ai`: 触发AI对话
|
||
- `.aiconfig`: 配置Ollama参数
|
||
|
||
### 2. AI对话模块 (`games/ai_chat.py`)
|
||
- `handle()`: 主处理函数,处理 `.ai` 和 `.aiconfig` 指令
|
||
- `_handle_ai()`: 处理AI对话请求
|
||
- 将消息加入等待队列
|
||
- 取消旧的延迟任务(如果存在)
|
||
- 创建新的延迟任务(10秒后执行)
|
||
- `_handle_config()`: 处理配置请求
|
||
- 解析配置参数(host, port, model)
|
||
- 更新 `data/ai_config.json` 文件
|
||
- 返回配置确认消息
|
||
- `_add_to_queue()`: 将消息加入等待队列(按 chat_id 组织)
|
||
- `_delayed_response()`: 延迟回答任务(内部异步函数)
|
||
- 等待10秒后执行
|
||
- 检查队列并生成回答
|
||
- 处理任务取消异常
|
||
- `_generate_response()`: 使用LLM生成回答
|
||
- 获取或创建 ChatEngine 实例
|
||
- 获取用户角色映射
|
||
- 将队列中的消息按用户角色格式化
|
||
- 调用 ChatEngine.chat() 生成回答
|
||
- 更新 ChatMemoryBuffer
|
||
- `_get_chat_engine()`: 获取或创建ChatEngine实例
|
||
- 检查全局字典中是否已存在
|
||
- 不存在则创建新的 ChatEngine,配置 ChatMemoryBuffer
|
||
- 设置系统提示(告知多用户场景)
|
||
- `_get_user_role()`: 获取用户角色名称(创建或获取映射)
|
||
- `_load_config()`: 从 JSON 文件加载配置
|
||
- `_save_config()`: 保存配置到 JSON 文件
|
||
|
||
### 3. 延迟任务管理
|
||
- 使用全局字典 `_pending_tasks` 存储每个 `chat_id` 的延迟任务句柄
|
||
- 使用全局字典 `_message_queues` 存储每个 `chat_id` 的待处理消息队列
|
||
- 使用全局字典 `_chat_engines` 存储每个 `chat_id` 的 ChatEngine 实例
|
||
- 新消息到达时,取消旧任务(调用 task.cancel())并创建新任务
|
||
- 使用 `asyncio.create_task` 和 `asyncio.sleep(10)` 实现固定10秒延迟
|
||
- 处理 `asyncio.CancelledError` 异常,避免任务取消时的错误日志
|
||
|
||
### 4. 用户角色映射机制
|
||
- 为每个 chat_id 维护用户ID到角色名称的映射(如"用户1"、"用户2")
|
||
- 映射信息存储在 `game_states` 表中(chat_id, user_id=0, game_type='ai_chat')
|
||
- 首次出现的用户自动分配角色名称(按出现顺序)
|
||
- 在将消息添加到 ChatMemoryBuffer 时使用角色名称作为消息角色
|
||
- 系统提示中包含:"这是一个多用户对话场景,不同用户的发言会用不同的角色标识。你需要理解不同用户的发言内容,并根据上下文给出合适的回复。"
|
||
|
||
### 4. 依赖添加
|
||
在 `requirements.txt` 中添加:
|
||
```
|
||
llama-index-core>=0.10.0
|
||
llama-index-llms-ollama>=0.1.0
|
||
```
|
||
|
||
### 5. 路由注册
|
||
在 `routers/callback.py` 的 `handle_command()` 中添加AI对话处理分支
|
||
|
||
### 6. 帮助信息更新
|
||
在 `games/base.py` 的 `get_help_message()` 中添加AI对话帮助
|
||
|
||
## 时间间隔判断逻辑(固定10秒窗口)
|
||
1. **默认等待窗口**:10秒(固定)
|
||
2. **收到 `.ai` 指令时**:
|
||
- 提取消息内容(去除 `.ai` 前缀)
|
||
- 获取用户ID和chat_id
|
||
- 将消息(用户ID + 内容)加入该 `chat_id` 的等待队列
|
||
- 如果有待处理的延迟任务(检查 `_pending_tasks[chat_id]`),取消它
|
||
- 创建新的延迟任务(`asyncio.create_task(_delayed_response(chat_id))`)
|
||
- 将任务句柄存储到 `_pending_tasks[chat_id]`
|
||
3. **在等待窗口内收到新消息**(无论是否是指令):
|
||
- 如果新消息也是 `.ai` 指令:
|
||
- 将新消息加入队列
|
||
- 取消当前延迟任务(`task.cancel()`)
|
||
- 创建新的延迟任务(重新计时10秒)
|
||
- 如果新消息不是指令,但chat_id在等待队列中:
|
||
- 可以考虑忽略,或也加入队列(根据需求决定)
|
||
4. **等待窗口结束(延迟任务执行)**:
|
||
- 检查队列中是否有消息
|
||
- 如果有,获取该 chat_id 的 ChatEngine 和用户映射
|
||
- 将队列中的消息按用户角色格式化后添加到 ChatMemoryBuffer
|
||
- 调用 ChatEngine.chat() 生成回答
|
||
- 清空队列
|
||
- 从 `_pending_tasks` 中移除任务句柄
|
||
|
||
## 配置文件管理(data/ai_config.json)
|
||
- 文件结构:
|
||
```json
|
||
{
|
||
"host": "localhost",
|
||
"port": 11434,
|
||
"model": "llama3.1"
|
||
}
|
||
```
|
||
- 首次加载时如果文件不存在,创建默认配置
|
||
- 通过 `.aiconfig` 指令修改配置时,实时保存到文件
|
||
- ChatEngine 创建时从配置文件加载配置
|
||
|
||
# 当前执行步骤:"4. 执行模式 - 代码实施完成并测试通过"
|
||
|
||
# 任务进度
|
||
|
||
## [2025-10-29_23:55:08] 执行阶段完成
|
||
- 已修改:
|
||
- requirements.txt:添加 llama-index-core 和 llama-index-llms-ollama 依赖
|
||
- data/ai_config.json:创建默认配置文件
|
||
- utils/parser.py:添加 .ai 和 .aiconfig 指令映射和解析逻辑
|
||
- games/ai_chat.py:创建完整的 AI 对话模块实现
|
||
- routers/callback.py:添加 ai_chat 处理分支
|
||
- games/base.py:添加 AI 对话帮助信息
|
||
- 更改:
|
||
- 实现了基于 llama_index 和 Ollama 的 AI 对话功能
|
||
- 实现了固定10秒等待窗口的延迟回答机制
|
||
- 实现了用户角色映射和长上下文管理
|
||
- 实现了配置文件的 JSON 存储和管理
|
||
- 原因:按照计划实施 AI 对话功能的所有核心组件
|
||
- 阻碍因素:无
|
||
- 状态:成功
|
||
|
||
## [2025-10-30_00:56:44] 功能优化和问题修复
|
||
- 已修改:
|
||
- games/ai_chat.py:优化错误处理和用户体验
|
||
1. 移除收到消息后的确认回复(静默处理)
|
||
2. 修复转义字符警告(SyntaxWarning)
|
||
3. 改进错误处理,提供详细的调试信息和排查步骤
|
||
4. 添加超时设置(120秒)
|
||
5. 针对NPS端口转发的特殊错误提示
|
||
- 更改:
|
||
- 优化了错误提示信息,包含当前配置、测试命令和详细排查步骤
|
||
- 专门针对NPS端口转发场景添加了Ollama监听地址配置说明
|
||
- 改进了连接错误的诊断能力
|
||
- 原因:根据实际使用中发现的问题进行优化
|
||
- 阻碍因素:无
|
||
- 状态:成功
|
||
|
||
## [2025-10-30_01:10:05] 系统提示词持久化和功能完善
|
||
- 已修改:
|
||
- games/ai_chat.py:
|
||
1. 实现系统提示词的持久化存储(保存到配置文件)
|
||
2. 添加 `_get_default_system_prompt()` 方法定义默认系统提示词
|
||
3. 添加 `_get_system_prompt()` 方法从配置文件加载系统提示词
|
||
4. 更新系统提示词内容,明确AI身份和职责
|
||
5. 在系统提示词中包含完整的机器人功能列表和指引
|
||
- 更改:
|
||
- 系统提示词现在会保存到 `data/ai_config.json` 文件中
|
||
- 服务重启后系统提示词会自动从配置文件加载,保持长期记忆
|
||
- AI助手能够了解自己的身份和所有机器人功能,可以主动指引用户
|
||
- 系统提示词包含了完整的13个功能模块介绍和回复指南
|
||
- 原因:实现系统提示词的长期记忆,让AI能够始终记住自己的身份和职责
|
||
- 阻碍因素:无
|
||
- 状态:成功
|
||
|
||
# 最终审查
|
||
|
||
## 实施总结
|
||
✅ 所有计划功能已成功实施并通过测试
|
||
|
||
### 核心功能实现
|
||
1. ✅ AI对话系统基于 llama_index + Ollama 构建
|
||
2. ✅ 显式指令触发(`.ai <问题>`)
|
||
3. ✅ 配置指令(`.aiconfig`)支持动态配置Ollama服务
|
||
4. ✅ 固定10秒等待窗口的延迟回答机制
|
||
5. ✅ 用户角色映射和长上下文管理(30+轮对话)
|
||
6. ✅ 配置文件持久化存储
|
||
7. ✅ 系统提示词持久化存储(新增)
|
||
8. ✅ 完善的错误处理和调试信息
|
||
|
||
### 文件修改清单
|
||
- ✅ requirements.txt - 添加依赖
|
||
- ✅ data/ai_config.json - 配置文件(包含系统提示词)
|
||
- ✅ utils/parser.py - 指令解析
|
||
- ✅ games/ai_chat.py - AI对话模块完整实现
|
||
- ✅ routers/callback.py - 路由注册
|
||
- ✅ games/base.py - 帮助信息更新
|
||
|
||
### 技术特性
|
||
- ✅ 多用户对话支持
|
||
- ✅ 延迟任务管理(asyncio)
|
||
- ✅ ChatMemoryBuffer长上下文管理
|
||
- ✅ JSON配置文件管理
|
||
- ✅ NPS端口转发支持
|
||
- ✅ 详细的错误诊断和排查指南
|
||
|
||
### 测试状态
|
||
- ✅ 功能测试通过
|
||
- ✅ Ollama服务连接测试通过
|
||
- ✅ NPS端口转发配置测试通过
|
||
- ✅ 系统提示词持久化测试通过
|
||
|
||
## 实施与计划匹配度
|
||
实施与计划完全匹配 ✅
|