# pegasus-agent-base **Repository Path**: lsq2025/pegasus-agent-base ## Basic Information - **Project Name**: pegasus-agent-base - **Description**: pegasus系列 基线版本 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-04 - **Last Updated**: 2026-07-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Pegasus Chat Agent 自研轻量级智能对话 Agent 服务,支持多 LLM Provider 降级重试、多模态图片识别、分布式会话管理、用户画像、定时任务、RAG 知识搜索。 > **核心特性**: 3阶段主循环 + 多Provider降级 + Redis Session + SSE流式输出 + 用户画像 + 定时任务 + RAG知识库 --- ## 目录 - [核心特性](#核心特性) - [架构设计](#架构设计) - [项目结构](#项目结构) - [安装配置](#安装配置) - [LLM Provider 配置](#llm-provider-配置) - [API 接口](#api-接口) - [工具系统](#工具系统) - [用户画像系统](#用户画像系统) - [定时任务系统](#定时任务系统) - [RAG 知识搜索](#rag-知识搜索) - [会话管理](#会话管理) - [Docker 部署](#docker-部署) - [与 v1/v2 对比](#与-v1v2-对比) - [License](#license) --- ## 核心特性 ### 🔄 3阶段主循环 简化架构,告别复杂的6阶段流程: ``` THINKING → EXECUTING → ANSWERING → COMPLETE ``` | 阶段 | 功能 | 说明 | |------|------|------| | THINKING | 分析推理 | 流式调用 LLM,累积 tool_calls | | EXECUTING | 工具执行 | 执行本地/远程工具,获取结果 | | ANSWERING | 生成回答 | 流式输出,打字机效果 | | COMPLETE | 完成返回 | 返回最终结果和数据来源 | ### 🎯 多 Provider 降级重试 ### 🖼️ 多模态图片识别 支持两种图片输入方式: - **Base64**: 直接传输图片数据(推荐,避免跨境下载超时) - **URL**: 图片链接地址 支持格式:JPEG、PNG、GIF、WebP ### 📡 SSE 流式输出 Server-Sent Events 实时推送: ``` event: thinking data: {"phase":"thinking","type":"status","content":"Analyzing..."} event: executing data: {"phase":"executing","type":"status","content":"Fetching data...", "metadata":{"tools":["get_weather"]}} event: answering data: {"phase":"answering","type":"delta","content":"南京"} event: answering data: {"phase":"answering","type":"delta","content":"当前"} event: complete data: {"phase":"complete","type":"final","content":"南京当前天气:晴...", "metadata":{"sources":[{"tool":"get_weather","summary":"..."}]}} ``` ### 🔧 合并工具管理器 远程工具 + 本地工具合并执行: | 类型 | 来源 | 工具 | |------|------|------| | **本地工具** | tools/local.py | get_weather (wttr.in)、get_current_time | | **远程工具** | pufferfish-server | 动态获取工具清单 | ### 💾 Redis 分布式会话 完整的分布式会话管理: - **分布式锁**: 防止并发冲突 - **TTL 自动清理**: 会话过期自动删除 - **用户隔离**: `session:{agent_id}:{user_id}:{session_id}` - **序列管理**: 自动生成会话序号 - **Token 裁剪**: 超限自动裁剪历史消息 - **请求幂等**: request_id 防重复请求 --- ## 架构设计 ### 系统架构图 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Pegasus Chat Agent 轻量版) │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Flutter │ │ FastAPI │ │ Agent │ │ Fallback │ │ 前端 │────▶│ API │────▶│ 核心 │────▶│ LLM │ │ │ │ (SSE) │ │ (3阶段循环) │ │ (5 Provider) │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ │ SSE 流 │ │ │ ▼ ▼ ▼ ▼ 用户界面 路由/数据模型 主循环/事件 降级重试/流式 打字机效果 SSE 推送 工具调用 tool_calls ``` **Agent 对比:** | Agent | 模型 | 多模态 | Function Calling | 适用场景 | |-------|------|--------|------------------|----------| | **多模态 Agent** | qwen3.6-plus | ✅ 支持 | ❌ 弱 | 图片识别、视觉问答 | | **推理 Agent** | deepseek-v4-pro | ❌ 不支持 | ✅ 强 | 定时任务、工具调用 | ### 主循环流程 ``` 用户输入: "帮我查一下南京的天气" │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 1. THINKING 阶段(流式推理) │ │ │ │ stream_iter = llm.chat_completion_stream(messages, tools, tool_choice) │ │ async for chunk_data in stream_iter: │ │ if "tool_calls" in chunk_data: │ │ tool_calls_accumulated.extend(chunk_data["tool_calls"]) │ │ if content: │ │ yield Event(phase="answering", type="delta", content=content) │ │ │ │ 优化:基础对话只需 1 次流式调用(节省 ~50% 时间) │ └─────────────────────────────────────────────────────────────────────────────┘ │ ├─── 有 tool_calls ────┐ │ │ ▼ ▼ ┌─────────────────┐ ┌─────────────────────────────────────────────────────┐ │ 直接回复 │ │ 2. EXECUTING 阶段 │ │ │ │ │ │ yield Event( │ │ results = tools.execute_tools(tool_calls) │ │ phase=ANSWERING│ │ │ │ ) │ │ 区分本地工具和远程工具: │ │ │ │ • get_weather → LocalToolManager │ │ │ │ • 其他 → pufferfish-server │ └─────────────────┘ └─────────────────────────────────────────────────────┘ │ │ │ ▼ │ ┌─────────────────────────────────────────────────────┐ │ │ 3. ANSWERING 阶段(第二次流式调用) │ │ │ │ │ │ messages.append(tool_results) │ │ │ stream_iter = llm.chat_completion_stream( │ │ │ messages, tools=None │ │ │ ) │ │ │ async for delta in stream_iter: │ │ │ yield Event(phase="answering", delta=delta) │ │ └─────────────────────────────────────────────────────┘ │ │ └ │ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 4. COMPLETE 阶段 │ │ │ │ yield Event( │ │ phase=Phase.COMPLETE, │ │ type=EventType.FINAL, │ │ content=full_text, │ │ metadata={"sources": [{"tool": "get_weather", "summary": "..."}]} │ │ ) │ │ │ │ 更新会话历史:session.add_assistant_message(full_text) │ │ 保存会话:sessions.save_session(session) │ └─────────────────────────────────────────────────────────────────────────────┘ ``` --- ## 项目结构 ``` pegasus-chat-agent/ ├── agent/ # Agent 核心模块 │ ├── __init__.py # 导出 create_agent │ ├── agent.py # 主循环 (THINKING → EXECUTING → ANSWERING) │ ├── events.py # Event, Phase, EventType │ ├── prompts.py # System Prompt 构建 │ └── context.py # AgentContext(可选) │ ├── api/ # API 层 │ ├── __init__.py │ ├── routes/ │ │ ├── __init__.py │ │ ├── assistant.py # POST /chat, GET /health (SSE + 双Agent路由) │ │ └── session.py # 会话管理 API │ └── schemas/ │ │ ├── __init__.py │ │ ├── assistant.py # ChatRequest, EventResponse │ │ └── session.py # SessionResponse │ ├── llm/ # LLM 客户端 │ ├── __init__.py # create_llm_client 工厂 │ ├── openai.py # OpenAI 客户端 │ ├── gemini.py # Gemini 客户端(多模态) │ ├── claude.py # Claude 客户端 │ ├── doubao.py # 豆包客户端(火山引擎) │ └── fallback_client.py # 多 Provider 降级重试 │ ├── config/ # 配置层(新增) │ ├── __init__.py │ ├── persistence.py # MySQL/Redis/MongoDB/Qdrant 配置 │ └── profile_sync.py # 用户画像同步配置 │ ├── memory/ # 记忆系统(新增) │ ├── __init__.py │ ├── memory_prompts.py # 记忆 Prompt │ ├── memory_tool.py # 记忆工具 │ └── user_profile/ # 用户画像系统 │ ├── core/ # 核心逻辑 │ │ ├── profile_manager.py │ │ ├── tag_manager.py │ │ └── interest_updater.py │ ├── tool/ # 工具层 │ │ ├── memory_tool.py │ │ └── prompt_builder.py │ └── behavior/ # 行为分析(备用) │ ├── rag/ # RAG 知识库(新增) │ ├── __init__.py │ ├── document_parser.py # 文档解析(PDF/Excel/Word/TXT) │ ├── embedding_service.py # Embedding(all-MiniLM-L6-v2) │ └── knowledge_service.py # Qdrant 向量检索 │ ├── scheduler/ # 定时任务系统(新增) │ ├── __init__.py │ ├── scheduler.py # APScheduler 调度器 │ ├── tool.py # 定时任务工具(create/list/delete) │ ├── sender.py # 消息发送器 │ ├── holiday.py # 节日提醒 │ ├── timezone_updater.py # 时区更新 │ ├── models.py # 数据模型 │ └── api.py # 任务管理 API │ ├── services/ # 服务层(新增) │ ├── __init__.py │ ├── document_parser.py # 文档解析服务 │ ├── embedding_service.py # Embedding 服务 │ ├── knowledge_service.py # 知识库服务 │ └── profile_sync_service.py # 用户画像同步服务 │ ├── tools/ # 工具系统 │ ├── __init__.py │ ├── combined.py # 合并工具管理器(远程+本地) │ ├── remote.py # pufferfish 远程工具 │ ├── local.py # 本地工具(天气、时间) │ └── knowledge_tool.py # 知识库搜索工具(新增) │ ├── session/ # 会话管理 │ ├── __init__.py │ ├── manager.py # Session 基类 │ └── redis_manager.py # Redis 分布式会话 │ ├── utils/ # 工具函数 │ ├── __init__.py │ ├── logger.py # 日志配置 │ └── time_resolver.py # 时间解析 │ ├── scripts/ # 脚本目录(新增) │ ├── import_documents.py # 文档导入脚本 │ ├── init_qdrant.py # Qdrant 初始化 │ ├── init_interest_tags.py # 用户标签初始化 │ └── sync_user_profiles.py # 用户画像同步 │ ├── workspace/ # 工作目录(文件会话存储) ├── logs/ # 日志目录 │ ├── main.py # CLI 入口 ├── server.py # FastAPI 服务入口 ├── requirements.txt # Python 依赖 ├── Dockerfile # Docker 构建文件 ├── docker-compose.yml # Docker Compose 配置 ├── .env # 环境变量配置 ├── .gitignore # Git 忽略文件 ├── .dockerignore # Docker 忽略文件 └── README.md # 本文档 ``` --- ## 安装配置 ### 安装依赖 ```bash pip install -r requirements.txt ``` 依赖列表: ``` fastapi>=0.100.0 # API 框架 uvicorn>=0.23.0 # ASGI 服务器 httpx>=0.24.0 # HTTP 客户端 redis>=4.5.0 # Redis 客户端 pytz>=2023.3 # 时区支持 python-dotenv>=1.0.0 # 环境变量 ``` # 日志配置 LOG_LEVEL=DEBUG LOG_DIR=./logs LOG_CONSOLE=true LOG_FILE=true --- ## LLM Provider 配置 ### Provider 分层架构 采用 **路由层 + 降级层** 双层架构: ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ LLM Provider 分层架构 │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ 路由层(API 层决策) │ │ │ │ │ ├─ 有图片 → qwen_multimodal (qwen3.6-plus) │ │ │ ✅ 多模态 ❌ Function Calling 弱 │ │ │ │ │ └─ 无图片 → deepseek_reasoning (deepseek-v4-pro) │ │ ❌ 多模态 ✅ Function Calling 强 │ │ │ │ 降级层(LLM 层容错) │ │ │ │ │ └─ Provider 失败时自动切换 │ │ aliyun → doubao → gemini_lite → gemini_flash → claude │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` **两层职责:** | 层级 | 位置 | 职责 | 配置项 | |------|------|------|--------| | **路由层** | API 层 | 根据图片选择 Agent | `LLM_PROVIDERS_MULTIMODAL`、`LLM_PROVIDERS_REASONING` | | **降级层** | LLM 层 | Provider 失败时降级 | `LLM_PROVIDERS` | ### 路由层配置 | Agent | Provider | 模型 | 能力 | |-------|----------|------|------| | **多模态 Agent** | qwen_multimodal | qwen3.6-plus | ✅ 图片识别 ❌ 复杂任务 | | **推理 Agent** | deepseek_reasoning | deepseek-v4-pro | ❌ 图片 ✅ Function Calling | ### 降级层配置 **推理 Agent 降级流程(LLM_PROVIDERS_REASONING):** ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ FallbackLLMClient 降级流程 │ │ (推理 Agent - deepseek-v4-pro) │ └─────────────────────────────────────────────────────────────────────────────┘ 请求到达 │ ▼ ┌─────────────────┐ │ Provider 1 │ deepseek_reasoning (deepseek-v4-pro) │ Priority=0 │ 阿里云代理 └─────────────────┘ │ ├─── 成功 ───────────────────────────▶ 返回结果 │ ├─── 失败 ───▶ 重试 MAX_RETRIES=3 次 ───▶ 重试耗尽 │ ▼ ┌─────────────────┐ │ Provider 2 │ deepseek_v3_2 (deepseek-v3.2) │ Priority=1 │ 阿里云代理 └─────────────────┘ │ ├─── 成功 ───────────────────────────▶ 返回结果 │ ├─── 失败 ───▶ 重试耗尽 │ ▼ ┌─────────────────┐ │ Provider 3 │ doubao (doubao-seed-2-0-pro-260215) │ Priority=5 │ 火山引擎豆包 └─────────────────┘ │ ▼ ... ┌─────────────────┐ │ Provider 6 │ claude_key1 (claude-opus-4-6) │ Priority=8 │ Claude Opus (API代理) └─────────────────┘ │ ├─── 成功 ───────────────────────────▶ 返回结果 │ ├─── 失败 ───▶ 重试耗尽 │ ▼ ┌─────────────────┐ │ Provider 7 │ claude_key2 (claude-opus-4-6) │ Priority=9 │ Claude Opus (API代理备用) └─────────────────┘ │ ├─── 成功 ───────────────────────────▶ 返回结果 │ ├─── 失败 ───▶ 所有 Provider 失败 │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 返回: "所有 AI 服务都繁忙,请稍后再试" │ └─────────────────────────────────────────────────────────────────────────────┘ ``` **多模态 Agent 降级流程(LLM_PROVIDERS_MULTIMODAL):** | Priority | Provider | Model | 说明 | |----------|----------|-------|------| | 0 | qwen_multimodal | qwen3.6-plus | 阿里云多模态(最高优先级) | | 1 | qwen_omni | qwen3.5-omni-plus | 阿里云全模态 | | 5 | doubao | doubao-seed-2-0-pro | 火山引擎豆包 | | 6 | gemini_pro | gemini-3.1-pro-preview | Gemini Pro | | 7 | gemini_flash | gemini-3-flash-preview | Gemini Flash | | 8 | claude_key1 | claude-opus-4-6 | Claude Opus (Key-1) | | 9 | claude_key2 | claude-opus-4-6 | Claude Opus (Key-2) | --- ## API 接口 ### POST /internal/v1/assistant/chat 聊天接口,SSE 流式输出。 **请求体:** ```json { "message": "帮我查一下南京的天气", "user_id": "12345", "session_id": "session-001", "agent_id": "default-assistant", "request_id": "req-uuid-123", "metadata": { "timezone": "Asia/Shanghai" }, "input_info": { "attachments": [ { "type": "image", "url": "https://example.com/image.jpg", "data": "base64-data", "mime_type": "image/jpeg" } ] } } ``` **响应(SSE):** ``` event: thinking data: {"phase":"thinking","type":"status","content":"Analyzing..."} event: executing data: {"phase":"executing","type":"status","content":"Fetching data...", "metadata":{"tools":["get_weather"]}} event: answering data: {"phase":"answering","type":"delta","content":"南京"} event: answering data: {"phase":"answering","type":"delta","content":"当前"} event: complete data: {"phase":"complete","type":"final","content":"南京当前天气:晴...", "metadata":{"sources":[{"tool":"get_weather","summary":"..."}]}} ``` ### Session API | 接口 | 说明 | |------|------| | `GET /internal/v1/session/list` | 用户会话列表 | | `POST /internal/v1/session/create` | 创建新会话 | | `GET /internal/v1/session/messages` | 获取会话消息 | | `DELETE /internal/v1/session` | 删除会话 | --- ## 工具系统 ### 合并工具管理器 ### 本地工具 | 工具 | 说明 | API | |------|------|-----| | `get_weather` | 查询天气 | wttr.in(免费无需 API Key) | | `get_current_time` | 查询时间 | pytz(本地) | **get_weather 参数:** ```json { "city": "南京", "format": "now" // now(实时)或 3d(3天预报) } ``` **get_current_time 参数:** ```json { "timezone": "Asia/Shanghai" // 时区名称 } ``` ### 远程工具 通过 pufferfish-server 动态获取: | 接口 | 说明 | |------|------| | `GET /tools/specs` | 获取工具清单 | | `POST /tools/execute` | 执行工具调用 | **支持的远程工具(示例):** - 查询数据库 - 发送消息 - 搜索知识库 - 业务定制工具 --- ## RAG 知识搜索 ### 知识搜索流程 用户提问 → Embedding → 向量搜索 → 返回结果 → 生成回答 ``` 用户提问: "公司报销流程是什么?" │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 步骤 1: Agent 接收并判断 │ │ │ │ 用户消息 → LLM → tool_calls │ │ │ │ LLM 决策: │ │ "用户问公司报销流程,我需要调用 search_knowledge 工具" │ │ │ │ 返回: │ │ tool_calls = [ │ │ { │ │ "id": "call_abc123", │ │ "function": { │ │ "name": "search_knowledge", │ │ "arguments": '{"query": "公司报销流程"}' │ │ } │ │ } │ │ ] │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 步骤 2: 执行 search_knowledge │ │ │ │ tools/knowledge_tool.py │ │ │ │ async def search_knowledge(query, file_type, limit): │ │ service = get_knowledge_service() │ │ results = service.search(query, ...) │ │ return format_results(results) │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 步骤 3: Embedding - 文本转向量 │ │ │ │ rag/embedding_service.py │ │ │ │ 输入: "公司报销流程是什么?" │ │ │ │ SentenceTransformer.encode(query) │ │ │ │ 输出: [384 个浮点数] │ │ [0.123, -0.456, 0.789, 0.234, -0.567, ..., 0.089] │ │ ↓ │ │ query_vector = [0.123, -0.456, ..., 0.089] # 384维向量 │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 步骤 4: 向量搜索 - Qdrant │ │ │ │ Qdrant 容器: pegasus-qdrant │ │ Collection: "knowledge" │ │ 存储的向量: [N 个文档块向量] │ │ │ │ 搜索算法: Cosine 相似度 │ │ │ │ 计算 query_vector 与每个存储向量的相似度: │ │ │ │ stored_vector_1 → similarity=0.85 │ │ stored_vector_2 → similarity=0.72 │ │ stored_vector_3 → similarity=0.91 │ │ ... │ │ │ │ 按 similarity 排序,取 top-5: │ │ │ │ Result 1: score=0.91, content="公司报销流程..." │ │ Result 2: score=0.85, content="报销审批流程..." │ │ Result 3: score=0.72, content="财务报销规定..." │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 步骤 5: LLM 生成回答 │ │ │ │ 搜索结果作为 tool_result 注入对话 │ │ │ │ LLM 根据搜索结果生成回答: │ │ │ │ "根据公司规定,报销流程如下: │ │ 1. 员工提交报销申请,附上发票原件 │ │ 2. 部门主管审批 │ │ 3. 财务部门审核 │ │ 4. 审核通过后5个工作日内付款 │ │ 注意:超过5000元需要额外审批" │ └─────────────────────────────────────────────────────────────────────┘ ``` ### 关键步骤详解 #### Embedding - 文本转向量 **代码位置:** `rag/embedding_service.py` ``` 输入文本: "公司报销流程是什么?" │ ▼ ┌─────────────────────────────────────────┐ │ SentenceTransformer 模型处理 │ │ │ │ all-MiniLM-L6-v2 (384维) │ │ │ │ 内部步骤: │ │ 1. Tokenization (分词) │ │ "公司 报销 流程 是 什么" │ │ │ │ 2. Transformer 编码 │ │ 每个词 → 向量表示 │ │ │ │ 3. 池化聚合 │ │ 所有词向量 → 单个句子向量 │ │ │ │ 4. 归一化 │ │ 向量归一化到 [-1, 1] 范围 │ └─────────────────────────────────────────┘ │ ▼ 输出向量: [0.123, -0.456, 0.789, ..., 0.089] # 384 个浮点数 ``` #### 向量搜索 - Qdrant **代码位置:** `rag/knowledge_service.py` ``` Query Vector: [0.123, -0.456, 0.789, ..., 0.089] │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ Qdrant 搜索过程 │ │ │ │ Collection "knowledge" 中有 N 个向量点: │ │ │ │ Point 1: vector=[0.11, -0.42, ...], payload={"content": "..."} │ │ Point 2: vector=[0.09, -0.50, ...], payload={"content": "..."} │ │ ... │ │ │ │ 对每个 Point 计算 Cosine 相似度: │ │ │ │ Cosine(query, point) = (query · point) / (|query| × |point|) │ │ │ │ 按相似度排序,返回 top-K │ └─────────────────────────────────────────────────────────────────────┘ ``` ### 配置参数 | 参数 | 值 | 说明 | |------|-----|------| | **Embedding 模型** | all-MiniLM-L6-v2 | 本地模型,384维 | | **距离算法** | Cosine | 余弦相似度 | | **Chunk Size** | 500 | 文本分块大小(字符) | | **Chunk Overlap** | 50 | 分块重叠(保留上下文) | | **搜索 Limit** | 5 | 默认返回 5 条结果 | --- ## 会话管理 ### Redis 会话管理器 **Key 结构:** ``` session:{agent_id}:{user_id}:{session_id} # 会话数据 lock:session:{agent_id}:{user_id}:{session_id} # 分布式锁 user_sessions:{agent_id}:{user_id} # 用户会话集合 agent_sessions:{agent_id} # Agent 会话集合 request_status:{request_id} # 请求状态 request_result:{request_id} # 请求结果缓存 user_session_seq:{user_id} # 会话序号 user_last_session:{agent_id}:{user_id} # 最近会话 ``` **核心功能:** | 功能 | 方法 | 说明 | |------|------|------| | 分布式锁 | `acquire_lock`, `release_lock` | 防止并发冲突 | | 会话获取 | `get_or_create` | 获取或创建会话 | | 会话保存 | `save_session` | TTL + Token 裁剪 | | 会话删除 | `delete_session` | 删除会话 | | 会话列表 | `list_sessions`, `list_sessions_detail` | 用户会话列表 | | 序列管理 | `get_next_sequence`, `create_next_session` | 自动序号 | | 幂等检查 | `check_request_idempotent` | request_id 防重复 | | 健康检查 | `health_check` | Redis 连接状态 | ### Token 裁剪机制 ```python # 配置 SESSION_MAX_TOKENS = 10000 # 自动裁剪 if session.token_count > max_tokens: session.messages = trim_messages(session.messages, max_tokens) ``` ### 幂等性保证 --- ## 与 v1/v2 对比 ### 架构对比 | 维度 | v1/v2(复杂版) | v3(轻量版) | |------|----------------|-------------| | **主循环阶段** | 6 阶段 | 3 阶段 | | | UNDERSTAND → PLAN → ACT | THINKING → EXECUTING → ANSWERING | | | → OBSERVE → REFLECT → RESPOND | → COMPLETE | | **代码量** | ~7,000 行 | ~1,500 行 | | **LLM Provider** | 单一 Provider | 5 Provider 降级 | | **会话管理** | 内存/文件 | Redis 分布式 | | **工具管理** | 本地硬编码 | 远程 + 本地合并 | | **API** | 无 | FastAPI + SSE | | **Docker** | 无 | docker-compose | ### 功能对比 | 功能 | v1/v2 | v3 | |------|-------|-----| | Reflect 智能判断 | ✅ | ❌(简化) | | 任务类型区分 | ✅ S2 | ❌(LLM 自动判断) | | 无效循环检测 | ✅ | ❌(降级切换) | | 多模态图片 | ❌ | ✅ | | 分布式会话 | ❌ | ✅ Redis | | 请求幂等 | ❌ | ✅ | | SSE 流式 | ❌ | ✅ | | Docker 部署 | ❌ | ✅ | ### 设计原则 ``` v1/v2(复杂版): - 规则代替 LLM 判断 - 硬编码城市列表 - 本地工具注册 - 无 API 层 v3(轻量版): ✅ LLM 自动判断意图 ✅ 无硬编码 ✅ 远程工具动态获取 ✅ FastAPI + SSE ✅ 多 Provider 降级 ✅ Redis 分布式会话 ✅ Docker 部署 ``` ## 用户画像系统 ### 功能概述 用户画像系统用于记录和管理用户的兴趣偏好和个人信息,实现个性化对话体验。 ### 数据结构 | 集合 | 作用 | |------|------| | user_tags | 预定义标签库(26个兴趣标签) | | user_profiles | 用户画像(个人信息 + 兴趣标签) | | user_evidence_records | 证据记录(每次更新的原始记录) | ### 核心流程 ``` ┌──────────────────────────────────────────────────────────────────────┐ │ 用户画像更新流程 │ ├──────────────────────────────────────────────────────────────────────┤ │ │ │ 用户输入:"我非常喜欢打网球" │ │ ↓ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ Phase 1: 注入用户画像到 System Prompt │ │ │ │ - ProfileManager.get_profile(user_id) → MongoDB │ │ │ │ - PromptBuilder.build_simple_profile_prompt() │ │ │ │ - 注入:用户画像 + 预定义标签列表 + 情感判断标准 │ │ │ └────────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ Phase 2: LLM 分析并调用工具 │ │ │ │ - LLM 看到触发规则:"用户表达喜欢 → update_user_memory" │ │ │ │ - LLM 从标签列表选择:网球 → tag_id=14 │ │ │ │ - LLM 返回 tool_calls │ │ │ └────────────────────────────────────────────────────────────────┐ │ │ ↓ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ Phase 3: 工具执行 │ │ │ │ - MemoryToolExecutor.execute() │ │ │ │ - InterestUpdater.update_from_llm() │ │ │ │ - 参数验证(置信度 >= 0.7) │ │ │ │ - 计算得分:positive=+1, negative=-1 │ │ │ └────────────────────────────────────────────────────────────────┐ │ │ ↓ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ Phase 4: MongoDB 写入 │ │ │ │ - user_profiles.tags[] 更新(创建或累加分数) │ │ │ │ - user_evidence_records 插入(记录原始证据) │ │ │ │ - 静默返回 {"status": "success"} │ │ │ └────────────────────────────────────────────────────────────────┐ │ │ ↓ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ Phase 5: LLM 生成回复 │ │ │ │ - 根据静默规则,不提及"已记录" │ │ │ │ - 直接回复:"网球是一项很棒的运动!" │ │ │ └────────────────────────────────────────────────────────────────┐ │ │ │ └──────────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────┐ │ 下次对话注入画像 │ ├──────────────────────────────────────────────────────────────────────┤ │ │ │ 用户下次对话时: │ │ ↓ │ │ ProfileManager.get_profile(user_id) │ │ ↓ │ │ 构建 Prompt: │ │ - 当前用户画像(年龄、职业、已记录兴趣) │ │ - 预定义兴趣标签(26个标签表格) │ │ - 情感判断标准 │ │ ↓ │ │ 注入到 System Prompt │ │ ↓ │ │ LLM 看到画像 → 可个性化回复 │ │ │ └──────────────────────────────────────────────────────────────────────┘ ``` ### 打分规则 | 情感类型 | 分数 | 说明 | |----------|------|------| | positive | +1 | 用户表达喜欢、认可、赞赏 | | negative | -1 | 用户表达不喜欢、厌恶 | | neutral | 0 | 中性(不更新) | ### 工具定义 | 工具名称 | 功能 | 触发条件 | |----------|------|----------| | update_user_memory | 更新用户兴趣标签 | 用户表达喜欢/不喜欢某话题 | | update_user_info | 更新用户个人信息 | 用户透露年龄/职业/国家/性别 | --- ## 作者 LANSHANQUAN © 2026 --- ## 版本发布 采用月末发布策略,每月最后一个工作日发布新版本。 ### 当前版本 | 版本号 | 发布日期 | |--------|----------| | 2026.06 | 2026-06-30 | ### 版本历史 | 版本 | 发布日期 | 主要更新 | |------|----------|----------| | 2026.04 | 2026-04-29 | 多 Provider 降级、时区支持、工具调用、Redis 分布式会话、图片识别、多轮对话 | | 2026.05 | 2026-05-30 | 双Agent架构、RAG 知识库、定时任务系统、用户画像系统、Web Search、日志优化 | | 2026.06 | 2026-06-30 | 长期记忆系统设计(每日摘要+轮级摘要+向量检索记忆+user fact)、安全与审计、每日新闻推送、数据库操作重构、工具设计优化、提示词Token消耗优化、修复幻觉问题等等 | > 版本号格式为 YYYY.MM,每月月末发布。