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>
This commit is contained in:
@@ -21,26 +21,33 @@ PRODUCT_AGENT_PROMPT = """你是一个专业的 B2B 商品顾问助手。
|
|||||||
|
|
||||||
## 可用工具
|
## 可用工具
|
||||||
|
|
||||||
1. **search_products** - 搜索商品
|
1. **search_spu_products** - 搜索商品(使用 Mall API,推荐)
|
||||||
|
- keyword: 搜索关键词(商品名称、编号等)
|
||||||
|
- page_size: 每页数量(默认 60,最大 100)
|
||||||
|
- page: 页码(默认 1)
|
||||||
|
- 说明:此工具使用 Mall API 搜索商品 SPU,支持用户 token 认证,返回卡片格式展示
|
||||||
|
|
||||||
|
2. **search_products** - 搜索商品(使用 Hyperf API)
|
||||||
- query: 搜索关键词
|
- query: 搜索关键词
|
||||||
- filters: 过滤条件(category, price_range, brand 等)
|
- filters: 过滤条件(category, price_range, brand 等)
|
||||||
- sort: 排序方式(price_asc/price_desc/sales/latest)
|
- sort: 排序方式(price_asc/price_desc/sales/latest)
|
||||||
- page: 页码
|
- page: 页码
|
||||||
- page_size: 每页数量
|
- page_size: 每页数量
|
||||||
|
- 说明:此工具用于高级搜索,支持多维度过滤
|
||||||
|
|
||||||
2. **get_product_detail** - 获取商品详情
|
3. **get_product_detail** - 获取商品详情
|
||||||
- product_id: 商品ID
|
- product_id: 商品ID
|
||||||
|
|
||||||
3. **recommend_products** - 智能推荐
|
4. **recommend_products** - 智能推荐
|
||||||
- context: 推荐上下文(可包含当前查询、浏览历史等)
|
- context: 推荐上下文(可包含当前查询、浏览历史等)
|
||||||
- limit: 推荐数量
|
- limit: 推荐数量
|
||||||
|
|
||||||
4. **get_quote** - B2B 询价
|
5. **get_quote** - B2B 询价
|
||||||
- product_id: 商品ID
|
- product_id: 商品ID
|
||||||
- quantity: 采购数量
|
- quantity: 采购数量
|
||||||
- delivery_address: 收货地址(可选,用于计算运费)
|
- delivery_address: 收货地址(可选,用于计算运费)
|
||||||
|
|
||||||
5. **check_inventory** - 库存查询
|
6. **check_inventory** - 库存查询
|
||||||
- product_ids: 商品ID列表
|
- product_ids: 商品ID列表
|
||||||
- warehouse: 仓库(可选)
|
- warehouse: 仓库(可选)
|
||||||
|
|
||||||
@@ -205,13 +212,70 @@ async def product_agent(state: AgentState) -> AgentState:
|
|||||||
|
|
||||||
async def _generate_product_response(state: AgentState) -> AgentState:
|
async def _generate_product_response(state: AgentState) -> AgentState:
|
||||||
"""Generate response based on product tool results"""
|
"""Generate response based on product tool results"""
|
||||||
|
|
||||||
|
# 特殊处理:如果是 search_spu_products 工具返回,直接发送商品卡片
|
||||||
|
has_spu_search_result = False
|
||||||
|
spu_products = []
|
||||||
|
|
||||||
|
for result in state["tool_results"]:
|
||||||
|
if result["success"] and result["tool_name"] == "search_spu_products":
|
||||||
|
data = result["data"]
|
||||||
|
if isinstance(data, dict) and data.get("success"):
|
||||||
|
spu_products = data.get("products", [])
|
||||||
|
has_spu_search_result = True
|
||||||
|
logger.info(
|
||||||
|
"SPU product search results found",
|
||||||
|
products_count=len(spu_products),
|
||||||
|
keyword=data.get("keyword", "")
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
# 如果有 SPU 搜索结果,直接发送商品卡片
|
||||||
|
if has_spu_search_result and spu_products:
|
||||||
|
try:
|
||||||
|
from integrations.chatwoot import ChatwootClient
|
||||||
|
from core.language_detector import detect_language
|
||||||
|
|
||||||
|
# 检测语言
|
||||||
|
detected_language = state.get("detected_language", "en")
|
||||||
|
|
||||||
|
# 发送商品卡片
|
||||||
|
chatwoot = ChatwootClient(account_id=int(state.get("account_id", 1)))
|
||||||
|
conversation_id = state.get("conversation_id")
|
||||||
|
|
||||||
|
if conversation_id:
|
||||||
|
await chatwoot.send_product_cards(
|
||||||
|
conversation_id=int(conversation_id),
|
||||||
|
products=spu_products,
|
||||||
|
language=detected_language
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Product cards sent successfully",
|
||||||
|
conversation_id=conversation_id,
|
||||||
|
products_count=len(spu_products),
|
||||||
|
language=detected_language
|
||||||
|
)
|
||||||
|
|
||||||
|
# 清空响应,避免重复发送
|
||||||
|
state = set_response(state, "")
|
||||||
|
state["state"] = ConversationState.GENERATING.value
|
||||||
|
return state
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(
|
||||||
|
"Failed to send product cards, falling back to text response",
|
||||||
|
error=str(e),
|
||||||
|
products_count=len(spu_products)
|
||||||
|
)
|
||||||
|
|
||||||
|
# 常规处理:生成文本响应
|
||||||
tool_context = []
|
tool_context = []
|
||||||
for result in state["tool_results"]:
|
for result in state["tool_results"]:
|
||||||
if result["success"]:
|
if result["success"]:
|
||||||
data = result["data"]
|
data = result["data"]
|
||||||
tool_context.append(f"工具 {result['tool_name']} 返回:\n{json.dumps(data, ensure_ascii=False, indent=2)}")
|
tool_context.append(f"工具 {result['tool_name']} 返回:\n{json.dumps(data, ensure_ascii=False, indent=2)}")
|
||||||
|
|
||||||
# Extract product context
|
# Extract product context
|
||||||
if isinstance(data, dict):
|
if isinstance(data, dict):
|
||||||
if data.get("product_id"):
|
if data.get("product_id"):
|
||||||
@@ -222,7 +286,7 @@ async def _generate_product_response(state: AgentState) -> AgentState:
|
|||||||
state = update_context(state, {"recent_product_ids": product_ids})
|
state = update_context(state, {"recent_product_ids": product_ids})
|
||||||
else:
|
else:
|
||||||
tool_context.append(f"工具 {result['tool_name']} 执行失败: {result['error']}")
|
tool_context.append(f"工具 {result['tool_name']} 执行失败: {result['error']}")
|
||||||
|
|
||||||
prompt = f"""基于以下商品系统返回的信息,生成对用户的回复。
|
prompt = f"""基于以下商品系统返回的信息,生成对用户的回复。
|
||||||
|
|
||||||
用户问题: {state["current_message"]}
|
用户问题: {state["current_message"]}
|
||||||
@@ -238,18 +302,18 @@ async def _generate_product_response(state: AgentState) -> AgentState:
|
|||||||
- 结果较多时可以总结关键信息
|
- 结果较多时可以总结关键信息
|
||||||
|
|
||||||
只返回回复内容,不要返回 JSON。"""
|
只返回回复内容,不要返回 JSON。"""
|
||||||
|
|
||||||
messages = [
|
messages = [
|
||||||
Message(role="system", content="你是一个专业的商品顾问,请根据系统返回的信息回答用户的商品问题。"),
|
Message(role="system", content="你是一个专业的商品顾问,请根据系统返回的信息回答用户的商品问题。"),
|
||||||
Message(role="user", content=prompt)
|
Message(role="user", content=prompt)
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
llm = get_llm_client()
|
llm = get_llm_client()
|
||||||
response = await llm.chat(messages, temperature=0.7)
|
response = await llm.chat(messages, temperature=0.7)
|
||||||
state = set_response(state, response.content)
|
state = set_response(state, response.content)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Product response generation failed", error=str(e))
|
logger.error("Product response generation failed", error=str(e))
|
||||||
state = set_response(state, "抱歉,处理商品信息时遇到问题。请稍后重试或联系人工客服。")
|
state = set_response(state, "抱歉,处理商品信息时遇到问题。请稍后重试或联系人工客服。")
|
||||||
|
|||||||
408
docs/PRODUCT_SEARCH_SERVICE.md
Normal file
408
docs/PRODUCT_SEARCH_SERVICE.md
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
# 商品搜索服务实现文档
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
|
||||||
|
添加了基于 Mall API 的商品搜索服务,支持根据关键词搜索 SPU 商品,并以 Chatwoot cards 格式展示搜索结果。
|
||||||
|
|
||||||
|
## 技术架构
|
||||||
|
|
||||||
|
```
|
||||||
|
用户发送搜索请求
|
||||||
|
↓
|
||||||
|
Router Agent 识别商品意图
|
||||||
|
↓
|
||||||
|
Product Agent 处理
|
||||||
|
↓
|
||||||
|
调用 Product MCP 工具: search_spu_products
|
||||||
|
↓
|
||||||
|
MallClient 调用 Mall API: /mall/api/spu
|
||||||
|
↓
|
||||||
|
返回商品列表
|
||||||
|
↓
|
||||||
|
发送 Chatwoot Cards 展示商品
|
||||||
|
```
|
||||||
|
|
||||||
|
## 修改的文件
|
||||||
|
|
||||||
|
### 1. MallClient - SPU 搜索 API
|
||||||
|
**文件**: `mcp_servers/shared/mall_client.py:267-306`
|
||||||
|
|
||||||
|
**新增方法**:
|
||||||
|
```python
|
||||||
|
async def search_spu_products(
|
||||||
|
self,
|
||||||
|
keyword: str,
|
||||||
|
page_size: int = 60,
|
||||||
|
page: int = 1
|
||||||
|
) -> dict[str, Any]
|
||||||
|
```
|
||||||
|
|
||||||
|
**功能**: 调用 Mall API `/mall/api/spu` 接口搜索商品
|
||||||
|
|
||||||
|
### 2. Product MCP - SPU 搜索工具
|
||||||
|
**文件**: `mcp_servers/product_mcp/server.py:291-378`
|
||||||
|
|
||||||
|
**新增工具**: `search_spu_products`
|
||||||
|
|
||||||
|
**参数**:
|
||||||
|
- `keyword` (必需): 搜索关键词
|
||||||
|
- `page_size`: 每页数量(默认 60,最大 100)
|
||||||
|
- `page`: 页码(默认 1)
|
||||||
|
- `user_token` (必需): 用户 JWT token,用于 Mall API 认证
|
||||||
|
- `user_id`: 用户 ID(自动注入)
|
||||||
|
- `account_id`: 账户 ID(自动注入)
|
||||||
|
|
||||||
|
**返回数据格式**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"spu_id": "12345",
|
||||||
|
"spu_sn": "61607",
|
||||||
|
"product_name": "Product Name",
|
||||||
|
"product_image": "https://...",
|
||||||
|
"price": "99.99",
|
||||||
|
"special_price": "89.99",
|
||||||
|
"stock": 100,
|
||||||
|
"sales_count": 50
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 156,
|
||||||
|
"keyword": "61607"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Chatwoot 集成 - 商品卡片发送
|
||||||
|
**文件**: `agent/integrations/chatwoot.py:1086-1243`
|
||||||
|
|
||||||
|
**新增方法**:
|
||||||
|
```python
|
||||||
|
async def send_product_cards(
|
||||||
|
self,
|
||||||
|
conversation_id: int,
|
||||||
|
products: list[dict[str, Any]],
|
||||||
|
language: str = "en"
|
||||||
|
) -> dict[str, Any]
|
||||||
|
```
|
||||||
|
|
||||||
|
**功能**: 发送商品搜索结果卡片到 Chatwoot
|
||||||
|
|
||||||
|
**卡片数据结构**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"content": "Found 3 products",
|
||||||
|
"content_type": "cards",
|
||||||
|
"content_attributes": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Product Name",
|
||||||
|
"description": "Special: €89.99 | Stock: 100 | Sold: 50",
|
||||||
|
"media_url": "https://...",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"text": "View Details",
|
||||||
|
"uri": "https://www.gaia888.com/product/detail?spuId=12345"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"text": "Buy Now",
|
||||||
|
"uri": "https://www.gaia888.com/product/detail?spuId=12345"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Product Agent - 搜索结果处理
|
||||||
|
**文件**: `agent/agents/product.py:206-313`
|
||||||
|
|
||||||
|
**修改内容**: 在 `_generate_product_response` 方法中添加特殊处理逻辑
|
||||||
|
|
||||||
|
**逻辑**:
|
||||||
|
1. 检测是否为 `search_spu_products` 工具返回
|
||||||
|
2. 如果是,直接调用 `send_product_cards` 发送商品卡片
|
||||||
|
3. 如果失败,降级到文本响应
|
||||||
|
|
||||||
|
### 5. Product Agent - Prompt 更新
|
||||||
|
**文件**: `agent/agents/product.py:22-52`
|
||||||
|
|
||||||
|
**修改内容**: 更新 PRODUCT_AGENT_PROMPT 可用工具列表
|
||||||
|
|
||||||
|
**更新**:
|
||||||
|
- 将 `search_spu_products` 设为第一个工具(推荐使用)
|
||||||
|
- 说明此工具使用 Mall API 搜索商品 SPU,支持用户 token 认证,返回卡片格式展示
|
||||||
|
- 原有的 `search_products` 标记为高级搜索工具(使用 Hyperf API)
|
||||||
|
|
||||||
|
### 6. Docker Compose - 环境变量配置
|
||||||
|
**文件**: `docker-compose.yml:146-170`
|
||||||
|
|
||||||
|
**修改内容**: 为 Product MCP 添加 Mall API 相关环境变量和 env_file
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
product_mcp:
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
MALL_API_URL: ${MALL_API_URL}
|
||||||
|
MALL_TENANT_ID: ${MALL_TENANT_ID:-2}
|
||||||
|
MALL_CURRENCY_CODE: ${MALL_CURRENCY_CODE:-EUR}
|
||||||
|
MALL_LANGUAGE_ID: ${MALL_LANGUAGE_ID:-1}
|
||||||
|
MALL_SOURCE: ${MALL_SOURCE:-us.qa1.gaia888.com}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用方式
|
||||||
|
|
||||||
|
### 用户在 Chatwoot 中搜索商品
|
||||||
|
|
||||||
|
**示例对话**:
|
||||||
|
```
|
||||||
|
用户: 搜索 61607
|
||||||
|
用户: 我想找手机
|
||||||
|
用户: 查找电脑产品
|
||||||
|
```
|
||||||
|
|
||||||
|
### Agent 调用流程
|
||||||
|
|
||||||
|
1. **Router Agent** 识别商品搜索意图
|
||||||
|
2. **Product Agent** 接收请求
|
||||||
|
3. **LLM** 决定调用 `search_spu_products` 工具
|
||||||
|
4. **Product MCP** 执行工具调用:
|
||||||
|
- 从 state 获取 `user_token`(用户的 JWT token)
|
||||||
|
- 创建 MallClient 实例
|
||||||
|
- 调用 Mall API `/mall/api/spu?keyword=xxx&pageSize=60&page=1`
|
||||||
|
- 解析返回结果
|
||||||
|
5. **Product Agent** 接收工具结果
|
||||||
|
6. **Chatwoot 集成** 发送商品卡片
|
||||||
|
|
||||||
|
## 商品卡片展示
|
||||||
|
|
||||||
|
### 中文界面
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ 找到 3 个商品 │
|
||||||
|
├─────────────────────────────────┤
|
||||||
|
│ ┌─────────────────────────────┐ │
|
||||||
|
│ │ [图片] │ │
|
||||||
|
│ │ Product Name │ │
|
||||||
|
│ │ 特价: €89.99 | 库存: 100 │ │
|
||||||
|
│ │ [查看详情] [立即购买] │ │
|
||||||
|
│ └─────────────────────────────┘ │
|
||||||
|
│ ┌─────────────────────────────┐ │
|
||||||
|
│ │ [图片] │ │
|
||||||
|
│ │ Product Name 2 │ │
|
||||||
|
│ │ €99.99 | 库存: 50 │ │
|
||||||
|
│ │ [查看详情] [立即购买] │ │
|
||||||
|
│ └─────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 英文界面
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Found 3 products │
|
||||||
|
├─────────────────────────────────┤
|
||||||
|
│ ┌─────────────────────────────┐ │
|
||||||
|
│ │ [Image] │ │
|
||||||
|
│ │ Product Name │ │
|
||||||
|
│ │ Special: €89.99 | Stock: 100 │ │
|
||||||
|
│ │ [View Details] [Buy Now] │ │
|
||||||
|
│ └─────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 多语言支持
|
||||||
|
|
||||||
|
商品卡片支持以下语言:
|
||||||
|
|
||||||
|
| 语言 | 代码 | 示例描述 |
|
||||||
|
|------|------|----------|
|
||||||
|
| 中文 | zh | 特价: €89.99 \| 库存: 100 |
|
||||||
|
| 英语 | en | Special: €89.99 \| Stock: 100 |
|
||||||
|
| 荷兰语 | nl | Aanbieding: €89.99 \| Voorraad: 100 |
|
||||||
|
| 德语 | de | Angebot: €89.99 \| Lager: 100 |
|
||||||
|
| 西班牙语 | es | Oferta: €89.99 \| Stock: 100 |
|
||||||
|
| 法语 | fr | Spécial: €89.99 \| Stock: 100 |
|
||||||
|
| 意大利语 | it | Offerta: €89.99 \| Stock: 100 |
|
||||||
|
| 土耳其语 | tr | Özel: €89.99 \| Stok: 100 |
|
||||||
|
|
||||||
|
## API 接口说明
|
||||||
|
|
||||||
|
### Mall API: 搜索 SPU 商品
|
||||||
|
|
||||||
|
**端点**: `GET /mall/api/spu`
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
```
|
||||||
|
keyword: 搜索关键词(商品名称、编号等)
|
||||||
|
pageSize: 每页数量(默认 60,最大 100)
|
||||||
|
page: 页码(默认 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
**请求头**:
|
||||||
|
```
|
||||||
|
Authorization: Bearer {user_token}
|
||||||
|
Content-Type: application/json
|
||||||
|
tenant-Id: 2
|
||||||
|
currency-code: EUR
|
||||||
|
language-id: 1
|
||||||
|
source: us.qa1.gaia888.com
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应格式**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"result": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"spuId": "12345",
|
||||||
|
"spuSn": "61607",
|
||||||
|
"productName": "Product Name",
|
||||||
|
"productImage": "https://...",
|
||||||
|
"price": "99.99",
|
||||||
|
"specialPrice": "89.99",
|
||||||
|
"stock": 100,
|
||||||
|
"salesCount": 50
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 156
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置要求
|
||||||
|
|
||||||
|
### 环境变量
|
||||||
|
|
||||||
|
在 `.env` 文件中配置:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Mall API
|
||||||
|
MALL_API_URL=https://apicn.qa1.gaia888.com
|
||||||
|
MALL_TENANT_ID=2
|
||||||
|
MALL_CURRENCY_CODE=EUR
|
||||||
|
MALL_LANGUAGE_ID=1
|
||||||
|
MALL_SOURCE=us.qa1.gaia888.com
|
||||||
|
|
||||||
|
# 前端 URL(用于生成商品详情链接)
|
||||||
|
FRONTEND_URL=https://www.gaia888.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 必需条件
|
||||||
|
|
||||||
|
1. **用户认证**: 商品搜索需要用户登录,获取 JWT token
|
||||||
|
2. **Token 注入**: Agent 会自动从 Chatwoot webhook 中提取 `user_token`
|
||||||
|
3. **网络访问**: Agent 需要能够访问 Mall API(`apicn.qa1.gaia888.com`)
|
||||||
|
|
||||||
|
## 测试
|
||||||
|
|
||||||
|
### 1. 测试脚本
|
||||||
|
|
||||||
|
运行测试脚本(需要提供有效的 user token):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python test_product_search.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 在 Chatwoot 中测试
|
||||||
|
|
||||||
|
1. 打开 Chatwoot 对话框
|
||||||
|
2. 发送搜索请求,例如:
|
||||||
|
- "搜索 61607"
|
||||||
|
- "我想找手机"
|
||||||
|
- "查找商品:电脑"
|
||||||
|
|
||||||
|
### 3. 查看 MCP 工具
|
||||||
|
|
||||||
|
访问 Product MCP 健康检查:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8004/health
|
||||||
|
```
|
||||||
|
|
||||||
|
预期响应:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "healthy",
|
||||||
|
"service": "product_mcp",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 故障排查
|
||||||
|
|
||||||
|
### 问题 1: 返回 "用户未登录"
|
||||||
|
|
||||||
|
**原因**: 缺少有效的 `user_token`
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 确保用户已在 Chatwoot 中登录
|
||||||
|
2. 检查 webhook 是否正确提取 `user_token`
|
||||||
|
3. 查看日志:`docker-compose logs -f agent`
|
||||||
|
|
||||||
|
### 问题 2: 返回空商品列表
|
||||||
|
|
||||||
|
**原因**:
|
||||||
|
- 关键词不匹配
|
||||||
|
- Mall API 返回空结果
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 尝试不同的关键词
|
||||||
|
2. 检查 Mall API 是否可访问
|
||||||
|
3. 查看 Mall API 响应日志
|
||||||
|
|
||||||
|
### 问题 3: 卡片无法显示
|
||||||
|
|
||||||
|
**原因**:
|
||||||
|
- 商品图片 URL 无效
|
||||||
|
- Chatwoot 不支持 cards 格式
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 检查 `product_image` 字段是否为有效 URL
|
||||||
|
2. 验证 Chatwoot API 版本是否支持 cards
|
||||||
|
3. 查看 Chatwoot 集成日志
|
||||||
|
|
||||||
|
## 性能优化
|
||||||
|
|
||||||
|
### 已实现的优化
|
||||||
|
|
||||||
|
1. **分页限制**: 默认返回 60 个商品,避免数据过大
|
||||||
|
2. **用户认证**: 使用用户 token 而不是全局 API token,更安全
|
||||||
|
3. **错误处理**: 优雅降级到文本响应
|
||||||
|
|
||||||
|
### 未来可优化
|
||||||
|
|
||||||
|
1. **缓存热门搜索**: 缓存常见关键词的搜索结果
|
||||||
|
2. **并行搜索**: 支持多关键词并行搜索
|
||||||
|
3. **智能推荐**: 基于搜索历史智能推荐
|
||||||
|
|
||||||
|
## 相关文件清单
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `mcp_servers/shared/mall_client.py` | Mall API 客户端(新增 SPU 搜索方法) |
|
||||||
|
| `mcp_servers/product_mcp/server.py` | Product MCP(新增 SPU 搜索工具) |
|
||||||
|
| `agent/integrations/chatwoot.py` | Chatwoot 集成(新增商品卡片方法) |
|
||||||
|
| `agent/agents/product.py` | Product Agent(新增卡片处理逻辑) |
|
||||||
|
| `docker-compose.yml` | 容器配置(Product MCP 环境变量) |
|
||||||
|
|
||||||
|
## 版本历史
|
||||||
|
|
||||||
|
- **2026-01-26**: 初始版本
|
||||||
|
- 添加 Mall API SPU 搜索支持
|
||||||
|
- 添加 Chatwoot cards 商品展示
|
||||||
|
- 支持多语言商品卡片
|
||||||
|
- 集成用户认证
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文档版本**: 1.0
|
||||||
|
**最后更新**: 2026-01-26
|
||||||
|
**维护者**: Claude Code
|
||||||
Reference in New Issue
Block a user