wangliang
|
54eefba6f8
|
fix: 修复 JSON 解析导致的 tool_name 丢失问题
## 问题
商品搜索时工具名丢失,导致 404 错误:
```
HTTP Request: POST http://product_mcp:8004/tools/ "HTTP/1.1 404 Not Found"
```
URL 应该是 `/tools/search_products` 但实际是 `/tools/`(工具名丢失)
## 根本原因
当 LLM 返回带 ```json``` 代码块格式的 JSON 时:
```
```json
{
"action": "call_tool",
"tool_name": "search_products",
"arguments": {"keyword": "ring"}
}
```
```
解析逻辑处理后:
1. 移除 ```` → 得到 `json\n{\n...`
2. 移除 `json` → 得到 `\n{\n...`
3. 内容以换行符开头,不是 `{`
4. 被误判为非 JSON 格式(`tool_name\n{args}`)
5. 按换行符分割,第一行为空 → `tool_name = ""`
## 解决方案
**第 189 行**:添加 `content.strip()` 去除前后空白
```python
if content.startswith("```"):
content = content.split("```")[1]
if content.startswith("json"):
content = content[4:]
# Remove leading/trailing whitespace after removing code block markers
content = content.strip() # ← 新增
```
## 额外改进
**第 217-224 行**:添加工具调用日志
```python
logger.info(
"Product agent calling tool",
tool_name=tool_name,
arguments=arguments,
conversation_id=state["conversation_id"]
)
```
便于调试工具调用问题。
## 测试验证
修复前:
```
tool_name = "" (空字符串)
URL: /tools/ (缺少工具名)
```
修复后:
```
tool_name = "search_products" (正确)
URL: /tools/search_products (完整路径)
```
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 18:36:27 +08:00 |
|
wangliang
|
74c28eb838
|
fix: 添加工具注册表和 HTTP 路由,修复 MCP 工具调用 404 错误
## 问题
Product MCP 工具调用返回 404:
```
POST /tools/search_products HTTP/1.1 404 Not Found
```
## 根本原因
1. Product MCP 缺少 `/tools/{tool_name}` HTTP 路由
2. FastMCP 的 `mcp.http_app()` 默认不暴露此路由
3. Order MCP 有自定义路由处理,Product MCP 没有
## 解决方案
### 1. 添加工具注册表
**位置**: 第 32-41 行
```python
# Tool registry for HTTP access
_tools: Dict[str, Any] = {}
def register_tool(name: str):
"""Decorator to register tool in _tools dict"""
def decorator(func):
_tools[name] = func
return func
return decorator
```
### 2. 为所有工具添加注册装饰器
**修改的工具**:
- `get_product_detail`
- `recommend_products`
- `get_quote`
- `check_inventory`
- `get_categories`
- `search_products`
- `health_check`
**示例**:
```python
@register_tool("search_products")
@mcp.tool()
async def search_products(...):
```
### 3. 添加 HTTP 路由处理
**位置**: 第 352-401 行
参考 Order MCP 实现,添加:
- `/tools/{tool_name}` POST 路由
- 工具调用逻辑:`tool_obj.run(arguments)`
- 结果提取和 JSON 解析
- 错误处理(404, 400, 500)
### 4. 配置路由列表
**位置**: 第 407-415 行
```python
routes = [
Route('/health', health_check, methods=['GET']),
Route('/tools/{tool_name}', execute_tool, methods=['POST'])
]
```
## 测试结果
```bash
curl -X POST http://localhost:8004/tools/search_products \
-H "Content-Type: application/json" \
-d '{"keyword": "ring"}'
```
返回:
```json
{
"success": true,
"result": {
"success": false,
"error": "用户未登录,请先登录账户以搜索商品",
"products": [],
"total": 0,
"require_login": true
}
}
```
✅ 工具调用成功(user_token 缺失是预期行为)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 18:32:16 +08:00 |
|
wangliang
|
ad7f30d54c
|
fix: 删除旧的 search_products 工具,解决工具名冲突
## 问题
Product MCP 启动时出现警告:
```
WARNING Tool already exists: search_products
```
导致工具调用时返回 404 错误:
```
POST /tools/search_products HTTP/1.1 404 Not Found
```
## 根本原因
Product MCP 中有两个同名工具:
1. **第 40-99 行**:旧的 `search_products`(使用 Hyperf API)
2. **第 292-378 行**:新的 `search_products`(使用 Mall API)
FastMCP 无法注册同名工具,导致注册失败。
## 解决方案
删除旧的 `search_products` 工具定义(第 40-99 行),保留新的使用 Mall API 的版本。
## 修改内容
**文件**: mcp_servers/product_mcp/server.py
- 删除第 40-99 行(旧的 search_products 工具)
- 保留第 291 行开始的新的 search_products 工具
## 影响
- 移除了基于 Hyperf API 的旧搜索功能
- 所有商品搜索统一使用 Mall API
- 不再支持复杂过滤条件(category, brand, price_range 等)
- 简化为关键词搜索,返回商品卡片格式
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 18:25:06 +08:00 |
|
wangliang
|
7b676f8015
|
refactor: 将 search_spu_products 重命名为 search_products
## 修改内容
### 1. Product Agent prompt
- 将工具名从 `search_spu_products` 改为 `search_products`
- 更新所有示例代码
- 保持功能说明不变(Mall API SPU 搜索)
### 2. Product Agent 代码
**文件**: agent/agents/product.py
**修改**:
- 第 24 行:工具名改为 `search_products`
- 第 65、77 行:示例中的工具名更新
- 第 219-230 行:注入逻辑改为检查 `search_products`
- 第 284 行:工具结果检查改为 `search_products`
- 第 279-333 行:变量名 `spu_products` → `products`
- 第 280 行:`has_spu_search_result` → `has_product_search_result`
### 3. Product MCP Server
**文件**: mcp_servers/product_mcp/server.py
**修改**:
- 第 292 行:函数名 `search_spu_products` → `search_products`
- 第 300 行:文档字符串更新
- 功能完全相同,只是重命名
### 4. 移除映射逻辑
- 移除了 `search_products` → `search_spu_products` 的工具名映射
- 保留了 `query` → `keyword` 的参数映射(向后兼容)
## 好处
1. **简化命名**:`search_products` 比 `search_spu_products` 更简洁
2. **统一接口**:与系统中其他搜索工具命名一致
3. **降低复杂度**:减少名称长度和冗余
## 向后兼容
参数映射保留:
```python
# 仍然支持旧参数名
{"query": "ring"} → {"keyword": "ring"}
```
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 18:22:23 +08:00 |
|
wangliang
|
1aeb17fcce
|
refactor: 移除 search_products 工具,统一使用 search_spu_products
## 修改内容
### 1. 简化 Product Agent prompt
- 移除 `search_products` 工具说明
- 移除工具选择警告和说明
- 只保留 `search_spu_products` 作为唯一商品搜索工具
- 调整工具序号 1-5
### 2. 添加工具名自动映射
**位置**:第 195-201 行(非 JSON 格式),第 221-227 行(JSON 格式)
**功能**:
- 自动将 `search_products` 转换为 `search_spu_products`
- 防止 LLM 缓存或习惯导致的旧工具调用
- 添加日志记录映射操作
**示例**:
```python
# LLM 返回
{"tool_name": "search_products", "arguments": {"query": "ring"}}
# 自动转换为
{"tool_name": "search_spu_products", "arguments": {"keyword": "ring"}}
```
### 3. 添加参数自动映射
**位置**:第 240-246 行
**功能**:
- 自动将 `query` 参数转换为 `keyword` 参数
- 兼容 LLM 使用旧参数名的情况
**示例**:
```python
# LLM 返回
{"arguments": {"query": "ring"}}
# 自动转换为
{"arguments": {"keyword": "ring"}}
```
## 优势
1. **简化逻辑**:LLM 只有一个搜索工具可选,不会选错
2. **向后兼容**:即使 LLM 调用旧工具,也能自动转换
3. **参数兼容**:支持旧参数名 `query`,自动转为 `keyword`
4. **可观测性**:所有映射操作都有日志记录
## 预期效果
- LLM 调用 `search_spu_products`(Mall API)
- 返回商品卡片到 Chatwoot
- 即使调用旧工具也能正常工作
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 18:19:12 +08:00 |
|
wangliang
|
e58c3f0caf
|
fix: 修复 Product Agent LLM 响应格式解析和工具选择问题
## 问题 1: LLM 返回非标准 JSON 格式
**现象**:
LLM 返回:`search_products\n{"query": "ring"}`
期望格式:`{"action": "call_tool", "tool_name": "...", "arguments": {...}}`
**原因**:
LLM 有时会返回简化格式 `tool_name\n{args}`,导致 JSON 解析失败
**解决方案**:
添加格式兼容逻辑(第 172-191 行):
- 检测 `\n` 分隔的格式
- 解析工具名和参数
- 转换为标准 JSON 结构
## 问题 2: LLM 选择错误的搜索工具
**现象**:
LLM 选择 `search_products`(Hyperf API)而非 `search_spu_products`(Mall API)
**原因**:
Prompt 中工具说明不够突出,LLM 优先选择第一个工具
**解决方案**:
1. 在 prompt 开头添加醒目警告(第 22-29 行):
- ⚠️ 强调必须使用 `search_spu_products`
- 标注适用场景
- 添加 ⭐ 标记推荐工具
2. 添加具体示例(第 78-89 行):
- 展示正确的工具调用格式
- 示例:搜索 "ring" 应使用 `search_spu_products`
## 修改内容
### agent/agents/product.py:172-191
添加非标准格式兼容逻辑
### agent/agents/product.py:14-105
重写 PRODUCT_AGENT_PROMPT:
- 开头添加工具选择警告
- 突出 `search_spu_products` 优先级
- 添加具体使用示例
- 标注各工具适用场景
## 预期效果
1. 兼容 LLM 的简化格式输出
2. LLM 优先选择 `search_spu_products` 进行商品搜索
3. 返回 Mall API 数据并以 Chatwoot cards 展示
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 18:17:37 +08:00 |
|
wangliang
|
15a4bdeb75
|
fix: 为 search_spu_products 工具注入 user_token 参数
## 问题
即使更新了 Product Agent prompt,LLM 仍然调用 search_products 而非 search_spu_products
## 根本原因
search_spu_products 工具需要 user_token 参数(Mall API 认证必需),
但 product_agent 函数中没有注入此参数,导致工具调用失败或被忽略
## 修改内容
### agent/agents/product.py:169-173
在工具调用前注入 user_token、user_id、account_id 参数:
```python
# Inject context for SPU product search (Mall API)
if result["tool_name"] == "search_spu_products":
arguments["user_token"] = state.get("user_token")
arguments["user_id"] = state["user_id"]
arguments["account_id"] = state["account_id"]
```
## 参数来源
- user_token: 从 Chatwoot webhook 提取(contact.custom_attributes.jwt_token)
- user_id: 从 AgentState 获取
- account_id: 从 AgentState 获取
## 预期效果
LLM 现在可以成功调用 search_spu_products 工具,
返回 Mall API 商品数据并以 Chatwoot cards 格式展示
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 18:10:36 +08:00 |
|
wangliang
|
fa2c8f8102
|
fix: 更新 Product Agent prompt 添加 search_spu_products 工具说明
## 问题
搜索商品时返回错误的工具调用 search_products 而非 search_spu_products
## 根本原因
Product Agent 的 PRODUCT_AGENT_PROMPT 中没有列出 search_spu_products 工具,
导致 LLM 不知道可以使用 Mall API 的 SPU 搜索工具
## 修改内容
### agent/agents/product.py
- 将 search_spu_products 设为第一个工具(推荐使用)
- 说明此工具使用 Mall API 搜索商品 SPU,支持用户 token 认证,返回卡片格式展示
- 原有的 search_products 标记为高级搜索工具(使用 Hyperf API)
- 调整工具序号 1-6
### docs/PRODUCT_SEARCH_SERVICE.md
- 添加 Product Agent Prompt 更新说明章节
- 调整章节序号
## 预期效果
LLM 现在应该优先使用 search_spu_products 工具进行商品搜索,
返回 Mall API 的商品数据并以 Chatwoot cards 格式展示
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 17:50:29 +08:00 |
|
wangliang
|
2dd46a8626
|
feat: 添加 typing status 状态指示器
- 在处理消息时自动显示"正在输入..."状态
- 处理完成后自动隐藏状态指示器
- 错误处理时确保状态指示器被关闭
- 提升用户体验,让用户知道 AI 正在处理请求
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 13:15:59 +08:00 |
|
wangliang
|
9fe29ff3fe
|
feat: 完善物流信息展示功能
- 修复物流信息中 order_id 字段缺失的问题,确保按钮正常生成
- 添加 tracking_url 支持,新增"官网追踪"按钮
- "官网追踪"按钮在新标签页打开 (target: "_blank")
- 改进日志记录,添加完整的 payload 预览
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-26 13:15:47 +08:00 |
|
wangliang
|
0b5d0a8086
|
feat: 重构订单和物流信息展示格式
主要改动:
- 订单列表:使用 order_list 格式,展示 5 个订单(全部状态)
- 订单详情:使用 order_detail 格式,优化价格和时间显示
- 物流信息:使用 logistics 格式,根据 track id 动态生成步骤
- 商品图片:从 orderProduct.imageUrl 字段获取
- 时间格式:统一为 YYYY-MM-DD HH:MM:SS
- 多语言支持:amountLabel、orderTime 支持中英文
- 配置管理:新增 FRONTEND_URL 环境变量
- API 集成:改进 Mall API tracks 数据解析
- 认证优化:account_id 从 webhook 动态获取
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-23 18:49:40 +08:00 |
|
wangliang
|
e8e89601a5
|
feat: 修复订单查询和物流查询功能
主要修改:
1. 订单数据解析修复 (agent/agents/order.py)
- 修复 Mall API 返回数据的嵌套结构解析
- 更新字段映射:orderId→order_id, orderProduct→items, statusText→status_text
- 支持多种商品图片字段:image, pic, thumb, productImg
- 添加详细的调试日志
2. 物流查询修复 (mcp_servers/order_mcp/server.py)
- 修复物流接口返回数据结构解析 (data[].trackingCode→tracking_number)
- 添加 print() 日志用于调试
- 支持多种字段名映射
3. Chatwoot 集成优化 (agent/integrations/chatwoot.py)
- 添加 json 模块导入
- 完善订单卡片和表单展示功能
4. API 请求头优化 (mcp_servers/shared/mall_client.py)
- 更新 User-Agent 和 Accept 头
- 修正 Origin 和 Referer 大小写
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-20 19:10:21 +08:00 |
|
wangliang
|
6b6172d8f0
|
feat: 优化 FAQ 处理和系统稳定性
- 添加本地 FAQ 库快速路径(问候语等社交响应)
- 修复 Chatwoot 重启循环问题(PID 文件清理)
- 添加 LLM 响应缓存(Redis 缓存,提升性能)
- 添加智能推理模式(根据查询复杂度自动启用)
- 添加订单卡片消息功能(Chatwoot 富媒体)
- 增加 LLM 超时时间至 60 秒
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-20 14:51:30 +08:00 |
|
wangliang
|
c4e97cf312
|
feat: 添加物流查询功能和完善 token 传递
- 添加 get_logistics 工具查询 Mall API /mall/api/order/parcel
- 修复 Cookie token 传递到 MCP 的问题
- 增强 LLM 客户端超时处理和日志
- 移除 MALL_API_TOKEN,使用用户登录 token
- 更新测试页面使用 setUser 设置用户属性
- 增强 webhook 调试日志
|
2026-01-16 18:36:17 +08:00 |
|
wangliang
|
cd787d608b
|
docs: 添加项目 README 文档
|
2026-01-16 16:50:36 +08:00 |
|
wangliang
|
e093995368
|
feat: 增强 Agent 系统和完善项目结构
主要改进:
- Agent 增强: 订单查询、售后支持、客服路由等功能优化
- 新增语言检测和 Token 管理模块
- 改进 Chatwoot webhook 处理和用户标识
- MCP 服务器增强: 订单 MCP 和 Strapi MCP 功能扩展
- 新增商城客户端、知识库、缓存和同步模块
- 添加多语言提示词系统 (YAML)
- 完善项目结构: 整理文档、脚本和测试文件
- 新增调试和测试工具脚本
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-16 16:28:47 +08:00 |
|
wangliang
|
0e59f3067e
|
feat: 添加 Strapi 配置文件支持
- 新增 config.yaml:集中管理 Strapi API 配置
- 新增 config_loader.py:配置加载模块
- 更新 http_routes.py:从配置文件读取 API 端点
- 支持从 YAML 文件配置 FAQ 分类和语言
- 更新 requirements.txt:添加 pyyaml 依赖
优势:
- 配置与代码分离,易于维护
- 添加新分类无需修改代码
- 支持热加载配置
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-15 10:39:25 +08:00 |
|
|
|
3ad6eee0d9
|
feat: 初始化 B2B AI Shopping Assistant 项目
- 配置 Docker Compose 多服务编排
- 实现 Chatwoot + Agent 集成
- 配置 Strapi MCP 知识库
- 支持 7 种语言的 FAQ 系统
- 实现 LangGraph AI 工作流
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
2026-01-14 19:25:22 +08:00 |
|