feat: add AI学习助手 agent (KG+RAG ideal) and renshenguo feishu bot

- Add AI学习助手 agent creation script with all 39 tools, 3-layer KG+RAG memory
- Add renshenguo (人参果) feishu bot integration (app_service + ws_handler)
- Register renshenguo WS client in main.py startup
- Add RENSHENGUO_APP_ID / RENSHENGUO_APP_SECRET / RENSHENGUO_AGENT_ID config
- Reorganize docs from root into docs/ subdirectories
- Move startup scripts to scripts/startup/
- Various backend optimizations and tool improvements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
renjianbo
2026-05-06 01:37:13 +08:00
parent f33bc461ff
commit eabf90c496
171 changed files with 4906 additions and 445 deletions

View File

@@ -0,0 +1,86 @@
# Agent 记忆实现方案(以「知你客服 13 号」为例)
本文说明「知你客服 13 号」所采用的**会话记忆**在平台上的实现方式、与 12 号的关系、持久化与性能边界,便于对接、运维与二次开发。
---
## 1. 与「知你客服 12 号」的关系
- **13 号在 12 号能力上增加**:工作流连线整理(去自环/重复边、分层布局、统一左右锚点)、工具调用纪律提示(避免同轮重复 `file_write`、勿刷屏 DSML 等)。
- **记忆机制本身与 12 号一致**:仍依赖工作流中的 **Cache 节点**、键名 **`user_memory_*`**、Redis 热缓存与可选MySQL 持久化;引擎侧对占位符解析、`user_profile` 与末行 JSON 的处理对两条线通用。
---
## 2. 总体架构(分层)
| 层级 | 作用 |
|------|------|
| **工作流 Cache 节点** | 业务主路径:按配置的 **key**(如 `user_memory_{{user_id}}`)执行 `get` / `set`,读写一整包 JSON通常含 `conversation_history``user_profile``context` 等)。 |
| **Redis** | 热缓存;可配置 **TTL**(引擎侧 Cache 节点默认常见为 **3600 秒**,以节点 `ttl` 为准)。 |
| **MySQL`persistent_user_memories`** | 与 **`user_memory_*`** 键对齐的持久化;在开关开启时,`get` 可合并 DB 与 Redis`set` 后同步写入 DB。 |
| **工作流引擎(`WorkflowEngine`** | 合并输入、占位符解析、LLM 输出补全(如末行 JSON 中的 `user_profile`、Cache 写入时的历史截断等。 |
---
## 3. 会话隔离(`user_id`
- Cache 键通常包含 **`{{user_id}}`**。请求执行时需携带稳定的 **`user_id`**(或引擎能从 Start 节点输入中解析到),否则会退化为 **`default`**,多用户会共用同一记忆键。
- 持久化 scope执行上下文中的 `workflow_id` 为 Agent 时形如 `agent_{uuid}`,用于将 DB 记录绑定到**具体 Agent**(见 `parse_memory_scope`)。
---
## 4. 数据流(简版)
1. **开始**:用户输入进入工作流;若存在 **Cache `get`**,从 Redis及必要时 MySQL取出上一轮的 payload合并进当轮输入。
2. **LLM**:提示词中通过 `{{memory.user_profile}}``{{memory.conversation_history}}``{{memory.recent_turns}}` 等注入上下文;引擎支持 **`memory.*` 与 Cache 合并后的顶层字段**对齐,避免「只有顶层 `user_profile`、没有 `memory` 包裹」时画像为空。
3. **模型输出**:约定**最后一行为单行 JSON**(含 `intent``reply``user_profile` 等)。若实际为「多行说明 + 末行 JSON」引擎会解析**末行 JSON**以合并 `user_profile`、供后续 Cache 使用。
4. **写回****Cache `set`**(及可能的代码节点)根据模板更新 `conversation_history` 等并写入 Redis若满足条件则**同步 MySQL**。
5. **截断**:写入时若存在 `conversation_history` 列表,按节点 **`max_history_length`** 保留最近若干条(引擎默认 **20**,可在 Cache 节点 `data` 中配置)。
---
## 5. MySQL 持久化的作用
- 配置项:**`MEMORY_PERSIST_DB_ENABLED`**(默认 **`True`**,见 `app.core.config`)。
- **有用场景**Redis **过期**、**重启/清空**、**冷启动**时,仍可从 DB 拉回与 Redis **合并**(对话历史取**更长**列表;`user_profile` / `context` 为**浅合并**)。
- **不适用**:键名不是 `user_memory_*`、或 scope 无法解析为 Agent/工作流时,不会走该表。
---
## 6. 「能记住多少对话」
- **条数**:以 Cache 写入路径上的 **`max_history_length`** 为准,**默认保留最近 20 条**对话条目(多出的丢弃旧条目)。
- **时间**:受 Redis **TTL** 影响热数据是否在内存;持久化打开时,**逻辑数据**仍可通过 DB + 下次合并恢复(以实际合并结果为准)。
- **模型侧**:即使存储 20 条,提示词是否注入全文或摘要字段取决于**工作流模板**;过长时还受 **LLM 上下文长度**与成本约束。
---
## 7. 性能与瓶颈
- 单次对话:**主要耗时在 LLM 与工具调用**;记忆层一般为 **少量 Redis 读写**及(若开启)**单次 MySQL 读/写**,通常为毫秒~十毫秒量级,相对模型耗时可忽略。
- **瓶颈**:高并发同一 `user_id` 串行执行工作流时的排队;超大 `conversation_history` 带来的序列化与提示词体积(已通过条数截断缓解)。
---
## 8. 排查要点
- **串用户 / 丢记忆**:检查执行入参是否带 **`user_id`**、Cache **key** 是否与预期一致。
- **改代码不生效**:工作流在 **Celery Worker** 中执行,需**重启 API 与 Celery** 后再测。
- **画像为空但上一轮已告知姓名**:检查末行 JSON 是否包含 `user_profile`、是否为空对象覆盖;并确认引擎已支持「末行 JSON」解析`WorkflowEngine``_parse_zhini_final_json_dict``_enrich_llm_json_user_profile` 等)。
- **画布预览/聊天发送报 500「数据库操作失败」**:① 浏览器访问 **`/health`**,响应中应有 **`checks` / `builtin_tools`**(否则 8037 可能不是当前仓库 API或存在多实例② 在 **`backend`** 目录执行 **`alembic upgrade head`**,保证 `executions` 等表含最新列(如 `parent_execution_id``depth``pause_state`);③ 前端预览请求需带稳定 **`user_id`**`AgentChatPreview` 已按 Agent 维度写入 `localStorage`),否则记忆键会退化为 `default`
---
## 9. 相关代码与脚本(索引)
| 说明 | 路径 |
|------|------|
| 引擎 Cache、合并、截断 | `backend/app/services/workflow_engine.py` |
| DB 读写与合并 | `backend/app/services/persistent_memory_service.py` |
| 持久化开关 | `backend/app/core/config.py``MEMORY_PERSIST_DB_ENABLED` |
| 13 号工作流/提示更新脚本 | `backend/scripts/create_zhini_kefu_13.py` |
| 12 号基线提示与工具 | `backend/scripts/create_zhini_kefu_12.py` |
---
*文档随实现迭代可能变化,以仓库内代码与平台工作流配置为准。*

View File

@@ -0,0 +1,447 @@
# 智能体聊天助手性能优化方案
## 一、当前性能瓶颈分析
### 1. 主要瓶颈识别
#### 🔴 **最大瓶颈LLM API 调用(串行执行)**
当前工作流包含多个 LLM 节点,**串行执行**
1. **意图理解节点** (`llm-intent`) - 约 1-2 秒
2. **问题回答节点** (`llm-question`) - 约 2-5 秒
3. **格式化回复节点** (`llm-format`) - 约 1-2 秒
**总耗时**:约 **4-9 秒**(取决于 LLM API 响应速度)
#### 🟡 **次要瓶颈:前端轮询机制**
- 当前轮询间隔:**500ms**
- 每次轮询需要 2 个 API 请求(状态 + 详情)
- 在 5 秒的执行时间内,会产生 **20 次请求**
#### 🟢 **较小瓶颈Redis 查询和数据库写入**
- Redis 查询:通常 < 10ms可忽略
- 数据库日志写入:可能影响性能(但已在 Celery 中异步处理)
### 2. 性能测试数据
```
单次对话执行时间分解:
├─ 开始节点: ~1ms
├─ 查询记忆: ~5ms (Redis)
├─ 合并上下文: ~1ms
├─ 意图理解: ~1500ms (LLM API)
├─ 意图路由: ~1ms
├─ 问题回答: ~3000ms (LLM API)
├─ 合并回复: ~1ms
├─ 更新记忆: ~5ms (Redis)
├─ 格式化回复: ~1500ms (LLM API)
└─ 结束节点: ~1ms
总计: ~6015ms (约6秒)
```
## 二、优化方案
### 方案 1LLM 调用优化 ⭐⭐⭐⭐⭐
#### 1.1 并行执行可并行的 LLM 节点
**问题**:当前 `llm-format` 节点必须等待 `llm-question` 完成,但实际上可以优化。
**优化方案**:合并 `llm-question``llm-format` 节点
```python
# 修改 llm-question 节点的 prompt直接生成格式化好的回复
prompt = """你是一个知识渊博、乐于助人的AI助手。请回答用户的问题。
用户问题:{{user_input}}
对话历史:{{memory.conversation_history}}
意图分析:{{output}}
请提供:
1. 直接、准确的答案
2. 必要的解释和说明
3. 如果问题不明确,友好地询问更多信息
请以自然、易懂的方式回答长度控制在200字以内。直接输出回答内容确保回复自然、流畅无需额外格式化。"""
```
**效果**:减少 1 个 LLM 调用,节省 **1-2 秒**
#### 1.2 使用流式响应Streaming
**当前**:等待完整响应后才返回
**优化**:使用流式响应,边生成边返回
```python
# backend/app/services/llm_service.py
async def call_llm_stream(
self,
prompt: str,
provider: str = "openai",
model: Optional[str] = None,
**kwargs
) -> AsyncIterator[str]:
"""流式调用LLM"""
if provider == "deepseek":
client = self.deepseek_client
response = await client.chat.completions.create(
model=model or "deepseek-chat",
messages=[{"role": "user", "content": prompt}],
stream=True, # 启用流式
**kwargs
)
async for chunk in response:
if chunk.choices[0].delta.content:
yield chunk.choices[0].delta.content
```
**效果**
- 用户感知延迟降低 **50-70%**
- 首字响应时间从 3 秒降至 **0.5-1 秒**
#### 1.3 LLM 响应缓存
**场景**:相同或相似的问题可以复用之前的回答
```python
# 在 cache-query 节点后添加缓存检查
# 使用问题的 hash 作为缓存 key
import hashlib
question_hash = hashlib.md5(user_input.encode()).hexdigest()
cache_key = f"llm_response_{question_hash}"
# 检查缓存
cached_response = redis_client.get(cache_key)
if cached_response:
return cached_response # 直接返回,节省 LLM 调用
```
**效果**:重复问题响应时间从 5 秒降至 **< 100ms**
#### 1.4 减少 max_tokens 限制
**当前配置**
- `llm-intent`: max_tokens=1000
- `llm-question`: max_tokens=2000
- `llm-format`: max_tokens=500
**优化**
- `llm-intent`: max_tokens=200意图识别不需要太长
- `llm-question`: max_tokens=1000200字约500 tokens
- 删除 `llm-format` 节点
**效果**:减少 token 生成时间,节省 **0.5-1 秒**
### 方案 2前端优化 ⭐⭐⭐⭐
#### 2.1 使用 WebSocket 替代轮询
**当前**:每 500ms 轮询一次,产生大量请求
**优化**:使用 WebSocket 实时推送执行状态
```typescript
// frontend/src/composables/useWebSocket.ts
// 已有 WebSocket 实现,但未在聊天组件中使用
// 修改 AgentChatPreview.vue
import { useWebSocket } from '@/composables/useWebSocket'
const { status, result, connect, disconnect } = useWebSocket(execution.id)
watch(result, (newResult) => {
if (newResult && !replyAdded) {
replyAdded = true
messages.value.push({
role: 'agent',
content: extractReply(newResult),
timestamp: Date.now()
})
}
})
```
**效果**
- 减少 90% 的 HTTP 请求
- 实时性提升(延迟从 500ms 降至 < 100ms
- 服务器负载降低
#### 2.2 智能轮询(自适应间隔)
如果无法使用 WebSocket可以优化轮询策略
```typescript
// 动态调整轮询间隔
let pollingInterval = 500 // 初始 500ms
let consecutiveNoChange = 0
const checkStatus = async () => {
const oldStatus = lastStatus
const newStatus = await getStatus()
if (oldStatus === newStatus) {
consecutiveNoChange++
// 如果连续3次状态未变化增加轮询间隔
if (consecutiveNoChange >= 3) {
pollingInterval = Math.min(pollingInterval * 1.5, 2000) // 最大2秒
}
} else {
consecutiveNoChange = 0
pollingInterval = 500 // 重置为初始值
}
setTimeout(checkStatus, pollingInterval)
}
```
**效果**:减少 30-50% 的无效请求
### 方案 3工作流优化 ⭐⭐⭐
#### 3.1 简化工作流结构
**当前流程**
```
开始 → 查询记忆 → 合并上下文 → 意图理解 → 意图路由 →
[5个分支] → 合并回复 → 更新记忆 → 格式化回复 → 结束
```
**优化流程**
```
开始 → 查询记忆 → 合并上下文 → 意图理解 → 意图路由 →
[5个分支直接生成最终回复] → 更新记忆 → 结束
```
**关键修改**
- 删除 `llm-format` 节点
- 在各个分支节点中直接生成格式化好的回复
- 删除 `merge-response` 节点(如果只有一个分支被激活)
**效果**:减少 1-2 个节点执行,节省 **1-2 秒**
#### 3.2 条件优化:跳过不必要的节点
**场景**:如果用户只是简单问候,不需要完整的问题回答流程
```python
# 在 switch-intent 节点后,对于 greeting 意图
# 可以直接使用模板回复,跳过 LLM 调用
if intent == "greeting":
# 使用预定义模板
response = "你好!很高兴见到你,有什么我可以帮助你的吗?"
# 跳过 llm-greeting 节点
else:
# 正常执行 LLM 节点
response = await llm_question(...)
```
**效果**:简单场景响应时间从 5 秒降至 **< 1 秒**
### 方案 4缓存优化 ⭐⭐⭐
#### 4.1 对话历史截断
**问题**:对话历史过长会增加 LLM prompt 长度,影响响应速度
**优化**:只保留最近 N 条对话
```python
# 在 cache-update 节点中
conversation_history = memory.conversation_history[-20:] # 只保留最近20条
```
**效果**
- 减少 prompt 长度,节省 **0.2-0.5 秒**
- 降低 token 消耗
#### 4.2 智能摘要
**更高级的方案**:将旧对话压缩为摘要
```python
# 如果对话历史超过50条生成摘要
if len(conversation_history) > 50:
# 保留最近20条
recent_history = conversation_history[-20:]
# 将前面的对话压缩为摘要
old_history = conversation_history[:-20]
summary = await llm_summarize(old_history) # 异步生成摘要
conversation_history = [{"role": "system", "content": summary}] + recent_history
```
**效果**:在保持上下文的同时,减少 prompt 长度
### 方案 5数据库优化 ⭐⭐
#### 5.1 异步日志写入
**当前**:每个节点执行后立即写入日志
**优化**:批量写入日志
```python
# 收集日志,定期批量写入
log_buffer = []
async def flush_logs():
if log_buffer:
db.bulk_insert_mappings(ExecutionLog, log_buffer)
db.commit()
log_buffer.clear()
# 每100ms或每10条日志刷新一次
```
**效果**:减少数据库写入次数,提升 **5-10%** 性能
#### 5.2 减少日志详细程度
**生产环境**:只记录关键日志(错误、警告)
```python
# 根据环境变量控制日志级别
if settings.DEBUG:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.WARNING) # 只记录警告和错误
```
**效果**:减少日志 I/O提升 **2-5%** 性能
## 三、实施优先级
### 🔥 **高优先级(立即实施)**
1. **删除 llm-format 节点** ⭐⭐⭐⭐⭐
- 实施难度:低
- 效果:节省 1-2 秒
- 预计时间30 分钟
2. **优化 max_tokens 配置** ⭐⭐⭐⭐
- 实施难度:低
- 效果:节省 0.5-1 秒
- 预计时间15 分钟
3. **对话历史截断** ⭐⭐⭐⭐
- 实施难度:低
- 效果:节省 0.2-0.5 秒 + 降低 token 消耗
- 预计时间30 分钟
### 🟡 **中优先级(近期实施)**
4. **使用 WebSocket 替代轮询** ⭐⭐⭐⭐
- 实施难度:中
- 效果:提升实时性,减少服务器负载
- 预计时间2-3 小时
5. **简化工作流结构** ⭐⭐⭐
- 实施难度:中
- 效果:节省 1-2 秒
- 预计时间1-2 小时
6. **智能轮询(如果不用 WebSocket** ⭐⭐⭐
- 实施难度:低
- 效果:减少 30-50% 无效请求
- 预计时间1 小时
### 🟢 **低优先级(长期优化)**
7. **流式响应** ⭐⭐⭐⭐⭐
- 实施难度:高
- 效果:显著提升用户体验(首字响应时间降低 50-70%
- 预计时间4-6 小时
8. **LLM 响应缓存** ⭐⭐⭐
- 实施难度:中
- 效果:重复问题响应时间 < 100ms
- 预计时间2-3 小时
9. **条件优化(跳过不必要节点)** ⭐⭐⭐
- 实施难度:中
- 效果:简单场景响应时间 < 1 秒
- 预计时间2-3 小时
## 四、预期效果
### 优化前
- **平均响应时间**5-6 秒
- **首字响应时间**3-4 秒
- **HTTP 请求数**20+ 次/对话
### 优化后(实施高优先级方案)
- **平均响应时间****3-4 秒**(提升 40%
- **首字响应时间****2-3 秒**(提升 25%
- **HTTP 请求数****2-5 次/对话**(减少 75%
### 优化后(实施所有方案)
- **平均响应时间****1.5-2.5 秒**(提升 60%
- **首字响应时间****0.5-1 秒**(提升 75%,使用流式响应)
- **HTTP 请求数****1-2 次/对话**(使用 WebSocket
## 五、具体实施步骤
### 步骤 1快速优化30 分钟)
```bash
# 1. 修改工作流配置,删除 llm-format 节点
# 2. 优化各 LLM 节点的 max_tokens
# 3. 添加对话历史截断逻辑
```
### 步骤 2前端优化2-3 小时)
```bash
# 1. 在 AgentChatPreview.vue 中集成 WebSocket
# 2. 替换轮询逻辑
# 3. 测试实时性
```
### 步骤 3高级优化可选4-6 小时)
```bash
# 1. 实现流式响应
# 2. 添加 LLM 响应缓存
# 3. 优化工作流结构
```
## 六、监控指标
实施优化后,建议监控以下指标:
1. **响应时间分布**
- P50中位数
- P9595% 分位数)
- P9999% 分位数)
2. **LLM 调用时间**
- 各节点的平均调用时间
- Token 消耗
3. **前端指标**
- 首字响应时间TTFB
- 完整响应时间
- HTTP 请求数量
4. **服务器负载**
- CPU 使用率
- 内存使用率
- 数据库连接数
## 七、注意事项
1. **流式响应**:需要修改前端 UI支持逐步显示文本
2. **缓存策略**:需要考虑缓存失效和更新机制
3. **向后兼容**:优化不应破坏现有功能
4. **测试覆盖**:每个优化都需要充分测试
---
**文档版本**v1.0
**创建时间**2024年
**维护人员**AI Assistant

View File

@@ -0,0 +1,296 @@
# 智能体聊天助手记忆存储说明
## 一、数据存储位置
### 1. 主要存储Redis
智能体聊天助手使用 **Redis** 作为记忆数据的持久化存储后端。
- **存储键名格式**`user_memory_{user_id}`
- 例如:`user_memory_default``user_memory_12345`
- **存储位置**Redis 数据库(默认 DB 0
- **数据格式**JSON 字符串
### 2. 备用存储:内存缓存
如果 Redis 不可用,系统会回退到**内存缓存**Memory Cache
⚠️ **重要提示**:内存缓存只在**单次执行会话内有效**,执行结束后数据会丢失,无法跨会话保留。
### 3. 存储结构
每个用户的记忆数据包含以下字段:
```json
{
"conversation_history": [
{
"role": "user",
"content": "我的名字叫老七",
"timestamp": "2024-01-01T10:00:00"
},
{
"role": "assistant",
"content": "好的,我记住了你的名字是老七。",
"timestamp": "2024-01-01T10:00:01"
}
],
"user_profile": {
// 用户画像信息(可扩展)
},
"context": {
// 上下文信息(可扩展)
}
}
```
## 二、数据大小限制
### 1. Redis 存储限制
- **单条记录大小**
- Redis 理论上单个 key 的值最大可达 **512MB**(默认配置)
- 实际使用中,受 Redis 服务器配置的 `maxmemory` 限制
- 当前系统:**无硬编码限制**(取决于 Redis 服务器配置)
- **对话历史累积**
- 对话历史会**不断累积**,没有自动截断机制
- 每次对话会添加 2 条记录(用户消息 + 助手回复)
- 假设每条消息平均 200 字(约 600 字节1000 轮对话约 1.2MB
### 2. 实际使用情况
根据当前系统检查:
- 当前用户记忆 key 数量:**1 个**
- 示例 key 大小:**约 5.73 KB**20 条对话历史)
- Redis 已使用内存:**2.52 MB**
- Redis 最大内存限制:**无限制**(取决于服务器配置)
### 3. 建议的容量规划
| 对话轮数 | 预估大小 | 说明 |
|---------|---------|------|
| 100 轮 | ~120 KB | 适合短期对话 |
| 500 轮 | ~600 KB | 适合中期对话 |
| 1000 轮 | ~1.2 MB | 适合长期对话 |
| 5000 轮 | ~6 MB | 需要监控内存使用 |
| 10000 轮 | ~12 MB | 建议实施截断策略 |
## 三、数据持久化与丢失风险
### 1. 数据持久化机制
#### Redis 持久化(推荐)
- **持久化方式**:取决于 Redis 配置
- **RDB**:定期快照,默认开启
- **AOF**:追加日志,可选开启
- **Docker 卷持久化**
- 使用 `redis_data` 卷存储数据
- 即使容器重启,数据也会保留
- 数据存储在 Docker 卷中,位置:`/var/lib/docker/volumes/redis_data`
#### 内存缓存(不持久化)
- 数据仅存在于进程内存中
- 进程重启后数据丢失
- 仅用于 Redis 不可用时的临时回退
### 2. 数据丢失风险分析
| 场景 | 数据是否丢失 | 说明 |
|------|------------|------|
| Redis 正常重启 | ❌ 不丢失 | 数据已持久化到磁盘 |
| Docker 容器重启 | ❌ 不丢失 | 数据存储在 Docker 卷中 |
| Redis 数据卷被删除 | ✅ **会丢失** | 需要重新创建卷 |
| 超过 TTL 时间 | ✅ **会过期** | 默认 24 小时后过期 |
| Redis 服务器故障 | ⚠️ 取决于持久化配置 | 如果持久化配置不当可能丢失 |
| 使用内存缓存时 | ✅ **会丢失** | 每次执行后丢失 |
### 3. TTL生存时间设置
当前配置:
- **TTL****86400 秒**24 小时)
- **位置**`cache-update` 节点的 `ttl` 配置
- **默认值**:如果未配置,默认 3600 秒1 小时)
⚠️ **重要**:如果用户在 24 小时内没有新的对话,记忆数据会**自动过期删除**。
## 四、配置说明
### 1. Redis 配置
**环境变量**`docker-compose.dev.yml`
```yaml
REDIS_URL=redis://redis:6379/0
```
**配置文件**`backend/.env`
```env
REDIS_URL=redis://localhost:6379/0
```
### 2. Cache 节点配置
**查询记忆节点**`cache-query`
```python
{
"id": "cache-query",
"type": "cache",
"data": {
"operation": "get",
"key": "user_memory_{user_id}",
"default_value": '{"conversation_history": [], "user_profile": {}, "context": {}}'
}
}
```
**更新记忆节点**`cache-update`
```python
{
"id": "cache-update",
"type": "cache",
"data": {
"operation": "set",
"key": "user_memory_{user_id}",
"value": '{"conversation_history": {{memory.conversation_history}} + [...], ...}',
"ttl": 86400 # 24小时
}
}
```
## 五、优化建议
### 1. 对话历史截断策略
如果对话历史过长,建议实施截断策略:
**方案 A保留最近 N 条**
```python
# 在 cache-update 节点中,限制 conversation_history 长度
conversation_history = memory.conversation_history[-100:] # 只保留最近100条
```
**方案 B按时间截断**
```python
# 只保留最近7天的对话
from datetime import datetime, timedelta
cutoff_date = (datetime.now() - timedelta(days=7)).isoformat()
conversation_history = [
msg for msg in memory.conversation_history
if msg.get('timestamp', '') > cutoff_date
]
```
**方案 C智能摘要**
```python
# 将旧对话历史压缩为摘要
# 使用 LLM 节点生成摘要,保留关键信息
```
### 2. 增加 TTL 时间
如果需要更长的记忆保留时间,可以修改 TTL
```python
"ttl": 604800 # 7天
"ttl": 2592000 # 30天
"ttl": 0 # 永不过期(不推荐,可能导致内存溢出)
```
### 3. 监控 Redis 内存使用
定期检查 Redis 内存使用情况:
```bash
# 进入 Redis 容器
docker exec -it aiagent-redis-1 redis-cli
# 查看内存信息
INFO memory
# 查看所有用户记忆 key
KEYS user_memory_*
# 查看特定 key 的大小
MEMORY USAGE user_memory_default
```
### 4. 数据备份策略
**定期备份 Redis 数据**
```bash
# 备份 Redis 数据
docker exec aiagent-redis-1 redis-cli SAVE
docker cp aiagent-redis-1:/data/dump.rdb ./backup/dump_$(date +%Y%m%d).rdb
```
**恢复 Redis 数据**
```bash
# 恢复 Redis 数据
docker cp ./backup/dump_20240101.rdb aiagent-redis-1:/data/dump.rdb
docker restart aiagent-redis-1
```
## 六、常见问题
### Q1: 数据会丢失吗?
**A**:
- 如果使用 Redis 且配置了持久化:**不会丢失**(除非数据卷被删除或超过 TTL
- 如果使用内存缓存:**会丢失**(每次执行后丢失)
### Q2: 可以存储多少对话?
**A**:
- 理论上:取决于 Redis 服务器内存限制
- 实际建议:**1000-5000 轮对话**(约 1-6 MB
- 超过 10000 轮建议实施截断策略
### Q3: 如何延长记忆保留时间?
**A**:
- 修改 `cache-update` 节点的 `ttl` 配置
- 设置为更大的值(如 2592000 = 30 天)
- 或设置为 0永不过期需谨慎
### Q4: 如何清理特定用户的记忆?
**A**:
```bash
# 通过 Redis CLI
docker exec -it aiagent-redis-1 redis-cli DEL user_memory_{user_id}
# 或通过工作流添加 delete 操作节点
```
### Q5: 多个用户的数据会互相影响吗?
**A**:
- **不会**,每个用户使用独立的 key`user_memory_{user_id}`
- 数据完全隔离
## 七、总结
### 当前配置
-**存储位置**Redis持久化
-**TTL**24 小时
-**数据格式**JSON包含对话历史、用户画像、上下文
-**大小限制**:无硬编码限制(取决于 Redis 配置)
- ⚠️ **数据丢失风险**:低(除非数据卷被删除或超过 TTL
### 建议
1. **短期使用**< 1000 轮对话):当前配置足够
2. **长期使用**> 5000 轮对话):建议实施对话历史截断策略
3. **生产环境**:建议定期备份 Redis 数据,监控内存使用
4. **高可用场景**:考虑 Redis 主从复制或集群模式
---
**文档版本**v1.0
**最后更新**2024年
**维护人员**AI Assistant

View File

@@ -0,0 +1,344 @@
# 智能体聊天助手记忆问题修复文档
## 问题描述
智能聊天助手无法记住用户信息,具体表现为:
1. 第一次对话:用户输入 "我的名字叫老七"
2. 第二次对话:用户输入 "你还记得我的名字吗?"
3. **预期结果**:助手应该回答 "是的,我记得你叫老七"
4. **实际结果**:助手无法记住用户名字,或者回答错误
**额外问题**:助手有时会回复两次相同的消息。
## 问题分析
### 工作流结构
智能聊天助手的工作流包含以下关键节点:
1. **开始节点** (`start-1`) - 接收用户输入
2. **查询记忆节点** (`cache-query`) - 从Redis查询对话历史
3. **合并上下文节点** (`transform-merge`) - 合并用户输入和记忆
4. **意图理解节点** (`llm-intent`) - 分析用户意图
5. **意图路由节点** (`switch-intent`) - 根据意图分发到不同分支
6. **问题回答节点** (`llm-question`) - 生成回答
7. **合并回复节点** (`merge-response`) - 合并各分支结果
8. **更新记忆节点** (`cache-update`) - 更新对话历史到Redis
9. **格式化回复节点** (`llm-format`) - 格式化最终回复
10. **结束节点** (`end-1`) - 返回最终结果
### 根本原因
经过深入调试,发现以下问题:
#### 1. Cache节点数据存储问题
- **问题**`cache-update` 节点的 `value_template` 中,`{{user_input}}``{{output}}``{{timestamp}}` 等变量在Python表达式执行时被当作字符串 `"null"` 处理
- **原因**变量替换逻辑在Python表达式执行之后导致变量未正确替换
#### 2. Cache节点数据读取问题
- **问题**`cache-query` 节点的 `default_value` 中,`conversation_history` 初始化为 `null`,导致后续 `null + [...]` 操作失败
- **原因**JSON解析后空值被解析为 `None`,而不是空列表 `[]`
#### 3. Transform节点数据丢失问题
- **问题**`transform-merge` 节点的 `mapping` 中,`{{output}}` 映射到 `memory` 字段,但 `cache-query` 的输出结构不包含完整的 `memory` 对象
- **原因**`cache-query` 返回的数据结构是 `{"right": {...}}`,而 `transform-merge` 期望的是完整的 `memory` 对象
#### 4. 边连接导致的数据丢失问题
- **问题**`cache-query → transform-merge` 的边设置了 `sourceHandle='right'`,导致只有 `right` 字段被传递,其他内存相关字段丢失
- **原因**`get_node_input` 方法在处理 `sourceHandle` 时,只传递了指定字段,没有保留内存相关字段
#### 5. LLM节点变量替换问题
- **问题1**LLM节点的prompt模板中`{{user_input}}``{{memory.conversation_history}}` 无法正确替换
- **原因**:变量替换逻辑不支持嵌套路径(如 `{{memory.conversation_history}}`
- **问题2**`{{output}}` 变量无法从嵌套的 `right.right.right` 结构中提取
- **原因**:变量提取逻辑只检查顶层字段,没有递归查找
#### 6. 前端重复回复问题
- **问题**:助手有时会回复两次相同的消息
- **原因**:轮询逻辑中,`checkStatus` 函数在状态为 `completed` 时可能被多次调用,导致重复添加消息
## 修复方案
### 1. 修复Cache节点的变量替换逻辑
**文件**`backend/app/services/workflow_engine.py`
**修改位置**`execute_node` 方法中的 `cache` 节点处理逻辑
**关键修改**
```python
# 在Python表达式执行之前先替换变量
if '{{user_input}}' in value_template:
user_input_value = input_data.get('user_input') or input_data.get('query') or input_data.get('input') or input_data.get('USER_INPUT') or ''
user_input_escaped = json_module.dumps(user_input_value, ensure_ascii=False)[1:-1] # 移除外层引号
value_template = value_template.replace('{{user_input}}', user_input_escaped)
if '{{output}}' in value_template:
output_value = self._extract_output_value(input_data)
output_escaped = json_module.dumps(output_value, ensure_ascii=False)[1:-1] # 移除外层引号
value_template = value_template.replace('{{output}}', output_escaped)
if '{{timestamp}}' in value_template:
timestamp_value = input_data.get('timestamp') or datetime.now().isoformat()
timestamp_escaped = json_module.dumps(timestamp_value, ensure_ascii=False)[1:-1] # 移除外层引号
value_template = value_template.replace('{{timestamp}}', timestamp_escaped)
```
**说明**
- 使用 `json.dumps()[1:-1]` 来正确转义字符串,同时移除外层引号
- 在Python表达式执行之前完成变量替换
### 2. 修复Cache节点的默认值初始化
**文件**`backend/app/services/workflow_engine.py`
**修改位置**`execute_node` 方法中的 `cache-query` 处理逻辑
**关键修改**
```python
# 确保default_value中的conversation_history初始化为空列表
default_value_str = node_data.get('default_value', '{}')
try:
default_value = json_module.loads(default_value_str)
# 确保conversation_history是列表而不是null
if 'conversation_history' not in default_value or default_value.get('conversation_history') is None:
default_value['conversation_history'] = []
except:
default_value = {"conversation_history": [], "user_profile": {}, "context": {}}
```
### 3. 修复Transform节点的Memory字段构建
**文件**`backend/app/services/workflow_engine.py`
**修改位置**`execute_node` 方法中的 `transform` 节点处理逻辑(`merge` 模式)
**关键修改**
```python
# 如果memory字段为空尝试从顶层字段构建
if key == 'memory' and (value is None or value == '' or value == '{{output}}'):
# 尝试从expanded_input中构建memory对象
memory = {}
for field in ['conversation_history', 'user_profile', 'context']:
if field in expanded_input:
memory[field] = expanded_input[field]
if memory:
result[key] = memory
else:
# 如果还是找不到保留原有的memory字段如果有
if 'memory' in expanded_input:
result[key] = expanded_input['memory']
else:
result[key] = value
```
### 4. 修复边连接导致的数据丢失
**文件**`backend/app/services/workflow_engine.py`
**修改位置**`get_node_input` 方法
**关键修改**
```python
# 即使有sourceHandle也要保留内存相关字段
if edge.get('sourceHandle'):
input_data[edge['sourceHandle']] = source_output
# 显式保留内存相关字段
if isinstance(source_output, dict):
for field in ['conversation_history', 'user_profile', 'context', 'memory']:
if field in source_output:
input_data[field] = source_output[field]
else:
# ... 原有逻辑
```
### 5. 修复LLM节点的嵌套路径变量支持
**文件**`backend/app/services/workflow_engine.py`
**修改位置**`execute_node` 方法中的 `llm` 节点处理逻辑(变量替换部分)
**关键修改**
```python
# 支持嵌套路径,如 {{memory.conversation_history}}
if '.' in var_name:
value = self._get_nested_value(input_data, var_name)
else:
# 原有逻辑:检查别名和直接字段
value = input_data.get(var_name)
if value is None:
# 检查别名
aliases = {
'user_input': ['query', 'input', 'USER_INPUT', 'user_input'],
'output': ['result', 'response', 'text', 'content']
}
for alias_key, alias_list in aliases.items():
if var_name == alias_key:
for alias in alias_list:
value = input_data.get(alias)
if value is not None:
break
```
**特殊处理**`{{memory.conversation_history}}` 格式化
```python
# 如果是conversation_history格式化为可读格式
if var_name == 'memory.conversation_history' and isinstance(value, list):
formatted_history = []
for msg in value:
role = msg.get('role', 'unknown')
content = msg.get('content', '')
if role == 'user':
formatted_history.append(f"用户: {content}")
elif role == 'assistant':
formatted_history.append(f"助手: {content}")
value = '\n'.join(formatted_history) if formatted_history else '无对话历史'
```
### 6. 修复{{output}}变量的递归提取
**文件**`backend/app/services/workflow_engine.py`
**修改位置**`execute_node` 方法中的 `llm` 节点处理逻辑(`{{output}}` 变量处理)
**关键修改**
```python
# 特殊处理output变量递归查找right字段
if var_path == 'output':
right_value = input_data.get('right')
if right_value:
# 递归查找字符串值
def extract_string_from_right(obj, depth=0):
if isinstance(obj, str):
return obj
elif isinstance(obj, dict):
# 优先检查常见字段
for key in ['content', 'text', 'message', 'output']:
if key in obj and isinstance(obj[key], str):
return obj[key]
# 递归查找right字段
if 'right' in obj:
return extract_string_from_right(obj['right'], depth + 1)
return None
value = extract_string_from_right(right_value)
if value:
logger.info(f"[rjb] LLM节点从right字段提取output: {value[:100]}")
```
### 7. 修复前端重复回复问题
**文件**`frontend/src/components/AgentChatPreview.vue`
**修改位置**`handleSendMessage` 方法中的 `checkStatus` 函数
**关键修改**
```typescript
// 添加标志位,防止重复添加回复
let replyAdded = false
const checkStatus = async () => {
try {
// 如果已经添加过回复,直接返回
if (replyAdded) {
return
}
// ... 获取执行状态 ...
if (exec.status === 'completed') {
// 防止重复添加
if (replyAdded) {
return
}
// 标记已添加回复
replyAdded = true
// 添加回复消息
messages.value.push({
role: 'agent',
content: agentReply || '执行完成',
timestamp: Date.now()
})
// ... 其他逻辑 ...
}
} catch (error) {
// 同样添加防重复逻辑
if (replyAdded) {
return
}
replyAdded = true
// ... 错误处理 ...
}
}
// 每次发送新消息时重置标志位
replyAdded = false
```
## 测试验证
### 测试步骤
1. **第一次对话**
- 输入:`我的名字叫老七`
- 预期:助手正常回复,并将信息存储到记忆
2. **第二次对话**
- 输入:`你还记得我的名字吗?`
- 预期:助手回答 `是的,我记得你叫老七`
3. **验证重复回复**
- 观察是否只收到一次回复
### 测试结果
**记忆功能**:正常工作,能正确记住用户名字
**重复回复**:已修复,每次对话只回复一次
## 关键代码文件
1. **后端核心逻辑**
- `backend/app/services/workflow_engine.py` - 工作流执行引擎
- `backend/scripts/generate_chat_agent.py` - 智能聊天助手工作流定义
2. **前端组件**
- `frontend/src/components/AgentChatPreview.vue` - 聊天预览组件
3. **测试脚本**
- `test_memory_functionality.py` - 记忆功能测试脚本
- `test_output_variable_extraction.py` - 输出变量提取测试脚本
## 修复时间线
1. **问题发现**:用户报告无法记住名字
2. **初步分析**:检查工作流定义和节点配置
3. **深入调试**:添加详细日志,追踪数据流
4. **修复Cache节点**:修复数据存储和读取逻辑
5. **修复Transform节点**:修复数据合并逻辑
6. **修复LLM节点**:修复变量替换和嵌套路径支持
7. **修复前端**:修复重复回复问题
8. **测试验证**:确认所有问题已解决
## 经验总结
1. **数据流追踪**:在复杂工作流中,需要仔细追踪数据在每个节点之间的传递
2. **变量替换时机**:变量替换必须在表达式执行之前完成
3. **数据结构一致性**:确保上下游节点对数据结构的期望一致
4. **边界情况处理**:注意处理 `null`、空值、嵌套结构等边界情况
5. **前端防重复**:轮询逻辑中需要添加防重复机制
## 后续优化建议
1. **统一数据结构**:定义统一的数据结构规范,避免节点间数据格式不一致
2. **增强日志**:添加更详细的调试日志,方便问题排查
3. **单元测试**:为关键节点添加单元测试,确保修复的稳定性
4. **性能优化**优化轮询频率减少不必要的API调用
5. **错误处理**:增强错误处理机制,提供更友好的错误提示
---
**修复完成时间**2024年根据实际时间填写
**修复人员**AI Assistant
**文档版本**v1.0

View File

@@ -0,0 +1,167 @@
# 智能聊天助手性能优化实施报告
## 📊 优化完成情况
### ✅ 已完成的优化
#### 1. 删除 llm-format 节点 ⭐⭐⭐⭐⭐
- **状态**:✅ 已完成
- **优化内容**
- 删除了 `llm-format` 节点原第14个节点
- 优化了 `llm-question` 节点的 prompt直接生成格式化好的回复
- 更新了工作流边连接:`cache-update` 直接连接到 `end-1`
- **效果**:减少 1 个 LLM 调用,节省 **1-2 秒**
#### 2. 优化 max_tokens 配置 ⭐⭐⭐⭐
- **状态**:✅ 已完成
- **优化内容**
- `llm-intent`: 1000 → **200** (减少 80%)
- `llm-greeting`: 500 → **200** (减少 60%)
- `llm-question`: 2000 → **1000** (减少 50%)
- `llm-emotion`: 1000 → **500** (减少 50%)
- `llm-request`: 1500 → **800** (减少 47%)
- `llm-goodbye`: 300 → **150** (减少 50%)
- `llm-general`: 1000 → **500** (减少 50%)
- **效果**:减少 token 生成时间,节省 **0.5-1 秒**,降低 **30-40%** token 消耗
#### 3. 对话历史截断 ⭐⭐⭐⭐
- **状态**:✅ 已完成
- **优化内容**
-`workflow_engine.py` 中添加了对话历史截断逻辑
- 自动保留最近 **20 条**对话记录
-`cache-update` 节点执行后自动截断
- **效果**
- 减少 prompt 长度,节省 **0.2-0.5 秒**
- 降低 token 消耗
- 提升 LLM 响应速度
## 📈 性能提升预期
### 优化前
- **平均响应时间**5-6 秒
- **LLM 调用次数**3 次(意图理解 + 问题回答 + 格式化)
- **Token 消耗**:约 3500-4500 tokens/对话
- **节点数量**15 个
### 优化后
- **平均响应时间****3-4 秒**(提升 **40%**
- **LLM 调用次数****2 次**(意图理解 + 问题回答)
- **Token 消耗**:约 **2000-2800 tokens/对话**(减少 **30-40%**
- **节点数量****14 个**(减少 1 个)
## 🔧 技术实现细节
### 1. 工作流结构优化
**优化前流程**
```
开始 → 查询记忆 → 合并上下文 → 意图理解 → 意图路由 →
[5个分支] → 合并回复 → 更新记忆 → 格式化回复 → 结束
```
**优化后流程**
```
开始 → 查询记忆 → 合并上下文 → 意图理解 → 意图路由 →
[5个分支直接生成最终回复] → 合并回复 → 更新记忆 → 结束
```
### 2. LLM 节点 Prompt 优化
**llm-question 节点优化**
- 添加了"确保回复格式自然、完整,无需额外格式化"的指令
- 让 LLM 直接生成最终格式的回复,避免二次格式化
### 3. 对话历史截断实现
**位置**`backend/app/services/workflow_engine.py`
**实现逻辑**
```python
# 确保conversation_history只保留最近的20条性能优化
if isinstance(value, dict) and 'conversation_history' in value:
if isinstance(value['conversation_history'], list):
max_history_length = 20
if len(value['conversation_history']) > max_history_length:
value['conversation_history'] = value['conversation_history'][-max_history_length:]
logger.info(f"[rjb] 对话历史已截断,保留最近 {max_history_length}")
```
## 📋 优化清单
| 优化项 | 状态 | 预期效果 | 实际效果 |
|--------|------|----------|----------|
| 删除 llm-format 节点 | ✅ 完成 | 节省 1-2 秒 | 待测试 |
| 优化 max_tokens | ✅ 完成 | 节省 0.5-1 秒 | 待测试 |
| 对话历史截断 | ✅ 完成 | 节省 0.2-0.5 秒 | 待测试 |
## 🚀 下一步建议
### 中优先级优化(可选)
1. **使用 WebSocket 替代轮询** ⭐⭐⭐⭐
- 实施难度:中
- 效果:提升实时性,减少服务器负载
- 预计时间2-3 小时
2. **智能轮询(如果不用 WebSocket** ⭐⭐⭐
- 实施难度:低
- 效果:减少 30-50% 无效请求
- 预计时间1 小时
### 高级优化(可选)
3. **流式响应** ⭐⭐⭐⭐⭐
- 实施难度:高
- 效果:首字响应时间降低 50-70%
- 预计时间4-6 小时
4. **LLM 响应缓存** ⭐⭐⭐
- 实施难度:中
- 效果:重复问题响应时间 < 100ms
- 预计时间2-3 小时
## 📝 测试建议
1. **性能测试**
- 测试优化前后的响应时间对比
- 监控 LLM API 调用次数和耗时
- 检查对话历史是否正确截断
2. **功能测试**
- 验证删除 llm-format 节点后,回复格式是否正常
- 验证各分支节点的回复质量
- 验证记忆功能是否正常
3. **压力测试**
- 测试长时间对话超过20条时的性能
- 测试并发请求的处理能力
## ⚠️ 注意事项
1. **向后兼容**:优化后的配置已更新到数据库,现有对话会使用新配置
2. **对话历史**超过20条的旧对话历史会被自动截断
3. **回复格式**:由于删除了格式化节点,需要确保各分支节点生成的回复格式正确
## 📊 监控指标
建议监控以下指标以验证优化效果:
1. **响应时间**
- P50中位数
- P9595% 分位数)
- P9999% 分位数)
2. **LLM 调用**
- 各节点的平均调用时间
- Token 消耗统计
3. **系统资源**
- CPU 使用率
- 内存使用率
- 数据库连接数
---
**优化完成时间**2024年
**优化版本**v1.0
**维护人员**AI Assistant

View File

@@ -0,0 +1,270 @@
# 智能需求分析与解决方案生成器 - 使用说明
## 📋 Agent 基本信息
- **名称**: 智能需求分析与解决方案生成器
- **状态**: 已发布(可直接使用)
- **节点数量**: 8个节点
- **连接数量**: 8条连接
- **Agent ID**: `9195f8df-3340-46a0-b761-b955a57acc6c`
## 🎯 功能概述
这是一个智能的多节点Agent能够
1. **自动理解用户需求** - 分析用户输入,提取关键信息
2. **智能需求分类** - 根据需求类型自动分类(技术方案/业务流程/数据分析等)
3. **专业方案生成** - 调用专业模板或LLM生成针对性解决方案
4. **方案整合优化** - 整合各分支结果,优化输出格式
5. **专业文档输出** - 生成结构化的Markdown文档
## 🔄 工作流结构
```
开始节点
需求理解与分析节点LLM
需求分类节点(条件判断)
├─→ [技术方案分支] → 技术方案设计节点Template/LLM
└─→ [业务流程分支] → 业务流程设计节点Template/LLM
↓ ↓
└────→ 方案整合节点Transform
输出优化与格式化节点LLM
结束节点
```
## 📊 节点详细说明
### 1. 开始节点start-1
- **功能**: 接收用户输入
- **输入格式**: JSON格式
- **输出**: 将用户输入传递给需求理解节点
### 2. 需求理解与分析节点llm-requirement-analysis
- **类型**: LLM节点
- **模型**: DeepSeek Chat
- **功能**:
- 分析用户需求
- 提取关键信息
- 识别需求类型、复杂度、领域等
- **输出格式**: JSON
```json
{
"requirement_type": "技术方案|业务流程|数据分析|工作流设计|其他",
"key_points": ["关键点1", "关键点2", ...],
"complexity": "简单|中等|复杂",
"domain": "领域(如:电商、金融、教育等)",
"summary": "需求摘要"
}
```
### 3. 需求分类节点condition-classify
- **类型**: 条件节点
- **功能**: 根据需求类型进行分支
- **判断条件**:
- 如果需求类型是"技术方案"或"API集成" → 走技术方案分支
- 否则 → 走业务流程分支
### 4. 技术方案设计节点
- **类型**: Template节点优先或LLM节点备用
- **功能**: 生成技术方案
- **输出内容**:
- 技术选型建议
- 架构设计
- 实施步骤
- 风险评估
- 最佳实践建议
### 5. 业务流程设计节点
- **类型**: Template节点优先或LLM节点备用
- **功能**: 生成业务流程方案
- **输出内容**:
- 流程概述
- 关键步骤
- 角色与职责
- 流程优化建议
- 实施路线图
### 6. 方案整合节点transform-integration
- **类型**: Transform节点
- **功能**: 整合各分支的结果
- **模式**: 合并模式
- **输出**: 包含解决方案、需求分析、时间戳的整合数据
### 7. 输出优化与格式化节点llm-optimization
- **类型**: LLM节点
- **模型**: DeepSeek Chat
- **功能**:
- 优化文档结构
- 补充关键细节
- 添加实施建议
- 统一格式
- **输出**: 完整的Markdown文档
### 8. 结束节点end-1
- **功能**: 返回最终结果
## 🚀 使用方法
### 方法一通过Agent管理界面测试
1. **进入Agent管理页面**
- 在左侧菜单选择"Agent管理"
- 找到"智能需求分析与解决方案生成器"
2. **测试Agent**
- 点击Agent名称进入详情页
- 点击"测试"按钮
- 在输入框中输入你的需求
3. **输入示例**:
```json
{
"query": "我需要设计一个电商系统的用户订单处理流程,包括下单、支付、发货、售后等环节"
}
```
或者简单输入:
```json
{
"query": "设计一个微服务架构的在线教育平台"
}
```
4. **查看结果**
- 等待Agent执行完成通常需要30-60秒
- 查看生成的解决方案文档
### 方法二通过API调用
```bash
POST /api/v1/executions
Content-Type: application/json
Authorization: Bearer <your_token>
{
"agent_id": "9195f8df-3340-46a0-b761-b955a57acc6c",
"input_data": {
"query": "你的需求描述"
}
}
```
## 💡 使用场景示例
### 场景1技术方案设计
**输入**:
```
设计一个高并发的实时推荐系统,需要支持千万级用户,毫秒级响应
```
**输出**:
- 技术选型Redis、Kafka、Spark等
- 架构设计图
- 实施步骤
- 性能优化建议
### 场景2业务流程优化
**输入**:
```
优化我们公司的客户服务流程,提高客户满意度
```
**输出**:
- 当前流程分析
- 优化建议
- 新流程设计
- 实施路线图
### 场景3系统架构设计
**输入**:
```
设计一个微服务架构的电商平台,包括用户、商品、订单、支付等模块
```
**输出**:
- 微服务拆分方案
- 服务间通信设计
- 数据一致性方案
- 部署架构
## ⚙️ 配置说明
### 节点配置参数
- **LLM节点温度**: 0.5-0.7(平衡创造性和准确性)
- **最大Token数**: 2000-3000确保输出完整
- **模型**: DeepSeek Chat默认
### 自定义配置
如果需要修改Agent配置
1. 进入Agent管理页面
2. 点击"设计"按钮
3. 在可视化编辑器中修改节点配置
4. 保存并发布
## 📝 输出格式
Agent最终输出为结构化的Markdown文档包含
1. **需求摘要**
2. **需求分析结果**
- 需求类型
- 关键点
- 复杂度评估
- 领域识别
3. **解决方案**
- 详细方案内容
- 实施建议
- 最佳实践
4. **附录**
- 相关资源
- 注意事项
## 🔍 注意事项
1. **输入格式**: 建议使用JSON格式包含`query`字段
2. **执行时间**: 复杂需求可能需要60-120秒
3. **Token限制**: 如果输出被截断,可以增加`max_tokens`参数
4. **需求描述**: 越详细的需求描述,生成的方案越准确
## 🛠️ 故障排查
### 问题1Agent执行超时
**解决方案**:
- 检查网络连接
- 确认LLM服务正常
- 简化需求描述
### 问题2输出不完整
**解决方案**:
- 增加`max_tokens`参数
- 分段处理复杂需求
### 问题3分类不准确
**解决方案**:
- 在需求描述中明确说明需求类型
- 例如:"我需要一个技术方案..."或"请帮我设计业务流程..."
## 📈 性能优化建议
1. **缓存机制**: 对于相似需求,可以复用之前的分析结果
2. **并行处理**: 对于多个独立需求,可以并行执行
3. **模板优化**: 根据使用频率优化模板选择逻辑
## 🔄 更新日志
- **v1.0** (2026-01-19): 初始版本
- 支持需求理解和分类
- 支持技术方案和业务流程生成
- 支持输出优化和格式化
## 📞 技术支持
如有问题或建议,请联系系统管理员或查看系统日志。
---
**最后更新**: 2026-01-19

View File

@@ -0,0 +1,374 @@
{
"name": "智能聊天助手(完整示例)",
"description": "一个完整的聊天智能体示例,展示平台的核心能力:\n- ✅ 记忆管理:使用缓存节点存储和查询对话历史\n- ✅ 意图识别使用LLM节点分析用户意图\n- ✅ 多分支路由使用Switch节点根据意图分发到不同处理分支\n- ✅ 上下文传递使用Transform节点合并数据\n- ✅ 多轮对话:支持上下文记忆和连贯对话\n- ✅ 个性化回复:根据不同意图生成针对性回复\n\n适用场景情感陪聊、客服助手、智能问答等聊天场景。",
"workflow_config": {
"nodes": [
{
"id": "start-1",
"type": "start",
"position": {
"x": 50,
"y": 400
},
"data": {
"label": "开始",
"output_format": "json"
}
},
{
"id": "cache-query",
"type": "cache",
"position": {
"x": 250,
"y": 400
},
"data": {
"label": "查询记忆",
"operation": "get",
"key": "user_memory_{user_id}",
"default_value": "{\"conversation_history\": [], \"user_profile\": {}, \"context\": {}}"
}
},
{
"id": "transform-merge",
"type": "transform",
"position": {
"x": 450,
"y": 400
},
"data": {
"label": "合并上下文",
"mode": "merge",
"mapping": {
"user_input": "{{query}}",
"memory": "{{output}}",
"timestamp": "{{timestamp}}"
}
}
},
{
"id": "llm-intent",
"type": "llm",
"position": {
"x": 650,
"y": 400
},
"data": {
"label": "意图理解",
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": "0.3",
"max_tokens": "1000",
"prompt": "你是一个专业的对话意图分析助手。请分析用户的输入,识别用户的意图和情感。\n\n用户输入{{user_input}}\n对话历史{{memory.conversation_history}}\n用户画像{{memory.user_profile}}\n\n请以JSON格式输出分析结果\n{\n \"intent\": \"意图类型greeting/question/emotion/request/goodbye/other\",\n \"emotion\": \"情感状态positive/neutral/negative\",\n \"keywords\": [\"关键词1\", \"关键词2\"],\n \"topic\": \"话题主题\",\n \"needs_response\": true\n}\n\n请确保输出是有效的JSON格式不要包含其他文字。"
}
},
{
"id": "switch-intent",
"type": "switch",
"position": {
"x": 850,
"y": 400
},
"data": {
"label": "意图路由",
"field": "intent",
"cases": {
"greeting": "greeting-handle",
"question": "question-handle",
"emotion": "emotion-handle",
"request": "request-handle",
"goodbye": "goodbye-handle"
},
"default": "general-handle"
}
},
{
"id": "llm-greeting",
"type": "llm",
"position": {
"x": 1050,
"y": 200
},
"data": {
"label": "问候回复",
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": "0.7",
"max_tokens": "500",
"prompt": "你是一个温暖、友好的AI助手。用户向你打招呼请用自然、亲切的方式回应。\n\n用户输入{{user_input}}\n对话历史{{memory.conversation_history}}\n\n请生成一个友好、自然的问候回复长度控制在50字以内。直接输出回复内容不要包含其他说明。"
}
},
{
"id": "llm-question",
"type": "llm",
"position": {
"x": 1050,
"y": 300
},
"data": {
"label": "问题回答",
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": "0.5",
"max_tokens": "2000",
"prompt": "你是一个知识渊博、乐于助人的AI助手。请回答用户的问题。\n\n用户问题{{user_input}}\n对话历史{{memory.conversation_history}}\n意图分析{{output}}\n\n请提供\n1. 直接、准确的答案\n2. 必要的解释和说明\n3. 如果问题不明确,友好地询问更多信息\n\n请以自然、易懂的方式回答长度控制在200字以内。直接输出回答内容。"
}
},
{
"id": "llm-emotion",
"type": "llm",
"position": {
"x": 1050,
"y": 400
},
"data": {
"label": "情感回应",
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": "0.8",
"max_tokens": "1000",
"prompt": "你是一个善解人意的AI助手。请根据用户的情感状态给予适当的回应。\n\n用户输入{{user_input}}\n情感状态{{output.emotion}}\n对话历史{{memory.conversation_history}}\n\n请根据用户的情感\n- 如果是积极情感:给予鼓励和共鸣\n- 如果是消极情感:给予理解、安慰和支持\n- 如果是中性情感:给予关注和陪伴\n\n请生成一个温暖、共情的回复长度控制在150字以内。直接输出回复内容。"
}
},
{
"id": "llm-request",
"type": "llm",
"position": {
"x": 1050,
"y": 500
},
"data": {
"label": "请求处理",
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": "0.4",
"max_tokens": "1500",
"prompt": "你是一个专业的AI助手。用户提出了一个请求请分析并回应。\n\n用户请求{{user_input}}\n意图分析{{output}}\n对话历史{{memory.conversation_history}}\n\n请\n1. 理解用户的请求内容\n2. 如果可以满足,说明如何满足\n3. 如果无法满足,友好地说明原因并提供替代方案\n\n请以清晰、友好的方式回应长度控制在200字以内。直接输出回复内容。"
}
},
{
"id": "llm-goodbye",
"type": "llm",
"position": {
"x": 1050,
"y": 600
},
"data": {
"label": "告别回复",
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": "0.6",
"max_tokens": "300",
"prompt": "你是一个友好的AI助手。用户要结束对话请给予温暖的告别。\n\n用户输入{{user_input}}\n对话历史{{memory.conversation_history}}\n\n请生成一个温暖、友好的告别回复表达期待下次交流。长度控制在50字以内。直接输出回复内容。"
}
},
{
"id": "llm-general",
"type": "llm",
"position": {
"x": 1050,
"y": 700
},
"data": {
"label": "通用回复",
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": "0.6",
"max_tokens": "1000",
"prompt": "你是一个友好、专业的AI助手。请回应用户的输入。\n\n用户输入{{user_input}}\n对话历史{{memory.conversation_history}}\n意图分析{{output}}\n\n请生成一个自然、有意义的回复保持对话的连贯性。长度控制在150字以内。直接输出回复内容。"
}
},
{
"id": "merge-response",
"type": "merge",
"position": {
"x": 1250,
"y": 400
},
"data": {
"label": "合并回复",
"mode": "merge_first",
"strategy": "object"
}
},
{
"id": "cache-update",
"type": "cache",
"position": {
"x": 1450,
"y": 400
},
"data": {
"label": "更新记忆",
"operation": "set",
"key": "user_memory_{user_id}",
"value": "{\"conversation_history\": {{memory.conversation_history}} + [{\"role\": \"user\", \"content\": \"{{user_input}}\", \"timestamp\": \"{{timestamp}}\"}, {\"role\": \"assistant\", \"content\": \"{{output}}\", \"timestamp\": \"{{timestamp}}\"}], \"user_profile\": {{memory.user_profile}}, \"context\": {{memory.context}}}",
"ttl": 86400
}
},
{
"id": "llm-format",
"type": "llm",
"position": {
"x": 1650,
"y": 400
},
"data": {
"label": "格式化回复",
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": "0.3",
"max_tokens": "500",
"prompt": "请将以下回复内容格式化为最终输出。确保回复自然、流畅。\n\n原始回复{{output}}\n\n请直接输出格式化后的回复内容不要包含其他说明或标记。如果原始回复已经是合适的格式直接输出即可。"
}
},
{
"id": "end-1",
"type": "end",
"position": {
"x": 1850,
"y": 400
},
"data": {
"label": "结束",
"output_format": "text"
}
}
],
"edges": [
{
"id": "e1",
"source": "start-1",
"target": "cache-query",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e2",
"source": "cache-query",
"target": "transform-merge",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e3",
"source": "transform-merge",
"target": "llm-intent",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e4",
"source": "llm-intent",
"target": "switch-intent",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e5-greeting",
"source": "switch-intent",
"target": "llm-greeting",
"sourceHandle": "greeting-handle",
"targetHandle": "left"
},
{
"id": "e5-question",
"source": "switch-intent",
"target": "llm-question",
"sourceHandle": "question-handle",
"targetHandle": "left"
},
{
"id": "e5-emotion",
"source": "switch-intent",
"target": "llm-emotion",
"sourceHandle": "emotion-handle",
"targetHandle": "left"
},
{
"id": "e5-request",
"source": "switch-intent",
"target": "llm-request",
"sourceHandle": "request-handle",
"targetHandle": "left"
},
{
"id": "e5-goodbye",
"source": "switch-intent",
"target": "llm-goodbye",
"sourceHandle": "goodbye-handle",
"targetHandle": "left"
},
{
"id": "e5-general",
"source": "switch-intent",
"target": "llm-general",
"sourceHandle": "default",
"targetHandle": "left"
},
{
"id": "e6-greeting",
"source": "llm-greeting",
"target": "merge-response",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e6-question",
"source": "llm-question",
"target": "merge-response",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e6-emotion",
"source": "llm-emotion",
"target": "merge-response",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e6-request",
"source": "llm-request",
"target": "merge-response",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e6-goodbye",
"source": "llm-goodbye",
"target": "merge-response",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e6-general",
"source": "llm-general",
"target": "merge-response",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e7",
"source": "merge-response",
"target": "cache-update",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e8",
"source": "cache-update",
"target": "llm-format",
"sourceHandle": "right",
"targetHandle": "left"
},
{
"id": "e9",
"source": "llm-format",
"target": "end-1",
"sourceHandle": "right",
"targetHandle": "left"
}
]
}
}

View File

@@ -0,0 +1,337 @@
# 智能聊天Agent完整示例说明
## 📋 概述
这是一个完整的聊天智能体示例,展示了如何使用平台的核心能力构建一个功能完善的聊天助手。该示例包含了记忆管理、意图识别、多分支路由、上下文传递等核心功能。
## 🎯 功能特性
### ✅ 核心能力展示
1. **记忆管理**
- 使用缓存节点存储对话历史
- 支持用户画像和上下文信息
- 自动更新记忆内容
2. **意图识别**
- 使用LLM节点分析用户意图
- 识别情感状态
- 提取关键词和话题
3. **多分支路由**
- 使用Switch节点根据意图分发
- 支持6种不同场景的处理分支
- 默认分支处理未知意图
4. **上下文传递**
- 使用Transform节点合并数据
- 保持对话历史的连贯性
- 支持多轮对话
5. **个性化回复**
- 根据不同意图生成针对性回复
- 考虑用户情感状态
- 保持对话风格一致
## 🔄 工作流结构
```
开始节点
查询记忆Cache节点
合并上下文Transform节点
意图理解LLM节点
意图路由Switch节点
├─→ 问候处理greeting
├─→ 问题回答question
├─→ 情感回应emotion
├─→ 请求处理request
├─→ 告别回复goodbye
└─→ 通用回复default
合并回复Merge节点
更新记忆Cache节点
格式化回复LLM节点
结束节点
```
## 📊 节点详细说明
### 1. 开始节点start-1
- **功能**: 接收用户输入
- **输入格式**: JSON格式包含 `query` 字段
- **输出**: 将用户输入传递给后续节点
### 2. 查询记忆节点cache-query
- **类型**: Cache节点
- **操作**: `get` - 获取用户记忆
- **Key**: `user_memory_{user_id}`
- **默认值**: 空记忆结构
- **功能**: 从缓存中读取用户的对话历史和画像信息
### 3. 合并上下文节点transform-merge
- **类型**: Transform节点
- **模式**: `merge` - 合并模式
- **功能**: 将用户输入、记忆数据、时间戳合并为完整上下文
### 4. 意图理解节点llm-intent
- **类型**: LLM节点
- **模型**: DeepSeek Chat
- **功能**:
- 分析用户输入
- 识别意图类型greeting/question/emotion/request/goodbye/other
- 识别情感状态positive/neutral/negative
- 提取关键词和话题
- **输出格式**: JSON
```json
{
"intent": "意图类型",
"emotion": "情感状态",
"keywords": ["关键词"],
"topic": "话题主题",
"needs_response": true
}
```
### 5. 意图路由节点switch-intent
- **类型**: Switch节点
- **功能**: 根据意图类型路由到不同的处理分支
- **分支**:
- `greeting` → 问候处理
- `question` → 问题回答
- `emotion` → 情感回应
- `request` → 请求处理
- `goodbye` → 告别回复
- `default` → 通用回复
### 6. 各分支处理节点llm-*
- **类型**: LLM节点
- **功能**: 根据不同意图生成针对性的回复
- **特点**:
- 问候分支:友好、亲切
- 问题分支:准确、详细
- 情感分支:共情、温暖
- 请求分支:专业、清晰
- 告别分支:温暖、期待
- 通用分支:自然、连贯
### 7. 合并回复节点merge-response
- **类型**: Merge节点
- **模式**: `merge_first` - 合并第一个结果
- **功能**: 将各分支的回复结果合并
### 8. 更新记忆节点cache-update
- **类型**: Cache节点
- **操作**: `set` - 设置记忆
- **功能**:
- 将本次对话添加到历史记录
- 更新用户画像(如需要)
- 保存上下文信息
- **TTL**: 86400秒24小时
### 9. 格式化回复节点llm-format
- **类型**: LLM节点
- **功能**: 对最终回复进行格式化和优化
- **输出**: 自然、流畅的文本回复
### 10. 结束节点end-1
- **功能**: 返回最终回复
- **输出格式**: 纯文本
## 🚀 使用方法
### 方法一:使用生成脚本(推荐)
```bash
cd backend/scripts
python3 generate_chat_agent.py
```
脚本会自动创建Agent包含完整的工作流配置。
### 方法二:手动创建
1. **进入Agent管理页面**
- 点击"创建Agent"按钮
- 填写名称和描述
2. **进入工作流编辑器**
- 点击"设计"按钮
- 使用节点工具箱添加节点
- 按照工作流结构连接节点
3. **配置节点**
- **LLM节点**: 配置API密钥、模型、Prompt
- **Cache节点**: 配置缓存Key和操作
- **Switch节点**: 配置路由规则
- **Transform节点**: 配置数据映射
4. **测试Agent**
- 点击"测试"按钮
- 输入测试消息
- 查看执行结果
5. **发布Agent**
- 点击"发布"按钮
- Agent状态变为"已发布"
- 可以开始使用
## 📝 配置要点
### 1. LLM节点配置
- **Provider**: 选择AI模型提供商如DeepSeek、OpenAI
- **Model**: 选择具体模型如deepseek-chat、gpt-3.5-turbo
- **Temperature**:
- 意图识别0.3(需要准确性)
- 情感回应0.8(需要创造性)
- 问题回答0.5(平衡准确性和灵活性)
- **Max Tokens**: 根据回复长度需求设置
- **Prompt**: 明确角色、任务、输出格式要求
### 2. Cache节点配置
- **Operation**:
- `get`: 查询记忆
- `set`: 更新记忆
- **Key**: 使用用户ID确保记忆隔离
- **TTL**: 设置合适的过期时间如24小时
### 3. Switch节点配置
- **Field**: 指定用于路由的字段(如`intent`
- **Cases**: 配置各分支的路由规则
- **Default**: 配置默认分支
### 4. Transform节点配置
- **Mode**: 选择合并模式(`merge`
- **Mapping**: 配置数据映射规则
- **变量引用**: 使用`{{variable}}`引用上游数据
## 🎨 自定义扩展
### 1. 添加新的意图分支
1. 在Switch节点中添加新的case
2. 创建对应的LLM处理节点
3. 连接Switch节点和处理节点
4. 连接处理节点到Merge节点
### 2. 增强记忆功能
- 添加用户画像更新逻辑
- 实现长期记忆和短期记忆分离
- 添加记忆检索和总结功能
### 3. 添加外部工具
- 集成知识库查询
- 添加天气、新闻等外部API
- 实现文件处理功能
### 4. 优化回复质量
- 添加回复质量评估节点
- 实现多候选回复生成和选择
- 添加回复风格控制
## 🔍 测试示例
### 测试用例1问候
```
输入: "你好"
预期: 友好的问候回复
```
### 测试用例2问题
```
输入: "今天天气怎么样?"
预期: 尝试回答问题或说明无法获取天气信息
```
### 测试用例3情感表达
```
输入: "我今天心情不太好"
预期: 共情、安慰的回复
```
### 测试用例4请求
```
输入: "帮我写一首诗"
预期: 生成诗歌或说明能力范围
```
### 测试用例5告别
```
输入: "再见"
预期: 温暖的告别回复
```
## ⚠️ 注意事项
1. **API密钥配置**
- 确保所有LLM节点都配置了有效的API密钥
- 检查API配额和限制
2. **记忆管理**
- Cache节点使用内存缓存重启后会丢失
- 生产环境建议使用Redis等持久化缓存
3. **性能优化**
- 减少不必要的LLM调用
- 优化Prompt长度
- 合理设置Token限制
4. **错误处理**
- 添加错误处理节点
- 配置重试机制
- 提供友好的错误提示
## 📚 相关文档
- [创建Agent经验总结](./创建Agent经验.md)
- [工作流节点类型说明](./可新增节点类型建议.md)
- [Agent使用说明](./Agent使用说明.md)
## 🎯 适用场景
- ✅ 情感陪聊助手
- ✅ 客服机器人
- ✅ 智能问答系统
- ✅ 对话式AI应用
- ✅ 个性化聊天助手
## 💡 最佳实践
1. **Prompt设计**
- 明确角色定位
- 明确输出格式
- 提供示例和上下文
2. **工作流设计**
- 保持流程清晰
- 合理使用分支
- 避免过度复杂
3. **记忆管理**
- 定期清理过期记忆
- 控制记忆大小
- 保护用户隐私
4. **测试验证**
- 覆盖各种场景
- 测试边界情况
- 验证回复质量
---
**创建时间**: 2024年
**版本**: 1.0
**作者**: AI Agent Platform