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:
wangliang
2026-01-26 17:50:29 +08:00
parent 2dd46a8626
commit fa2c8f8102
2 changed files with 483 additions and 11 deletions

View File

@@ -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: 搜索关键词
- filters: 过滤条件category, price_range, brand 等)
- sort: 排序方式price_asc/price_desc/sales/latest
- page: 页码
- page_size: 每页数量
- 说明:此工具用于高级搜索,支持多维度过滤
2. **get_product_detail** - 获取商品详情
3. **get_product_detail** - 获取商品详情
- product_id: 商品ID
3. **recommend_products** - 智能推荐
4. **recommend_products** - 智能推荐
- context: 推荐上下文(可包含当前查询、浏览历史等)
- limit: 推荐数量
4. **get_quote** - B2B 询价
5. **get_quote** - B2B 询价
- product_id: 商品ID
- quantity: 采购数量
- delivery_address: 收货地址(可选,用于计算运费)
5. **check_inventory** - 库存查询
6. **check_inventory** - 库存查询
- product_ids: 商品ID列表
- warehouse: 仓库(可选)
@@ -205,13 +212,70 @@ async def product_agent(state: AgentState) -> AgentState:
async def _generate_product_response(state: AgentState) -> AgentState:
"""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 = []
for result in state["tool_results"]:
if result["success"]:
data = result["data"]
tool_context.append(f"工具 {result['tool_name']} 返回:\n{json.dumps(data, ensure_ascii=False, indent=2)}")
# Extract product context
if isinstance(data, dict):
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})
else:
tool_context.append(f"工具 {result['tool_name']} 执行失败: {result['error']}")
prompt = f"""基于以下商品系统返回的信息,生成对用户的回复。
用户问题: {state["current_message"]}
@@ -238,18 +302,18 @@ async def _generate_product_response(state: AgentState) -> AgentState:
- 结果较多时可以总结关键信息
只返回回复内容,不要返回 JSON。"""
messages = [
Message(role="system", content="你是一个专业的商品顾问,请根据系统返回的信息回答用户的商品问题。"),
Message(role="user", content=prompt)
]
try:
llm = get_llm_client()
response = await llm.chat(messages, temperature=0.7)
state = set_response(state, response.content)
return state
except Exception as e:
logger.error("Product response generation failed", error=str(e))
state = set_response(state, "抱歉,处理商品信息时遇到问题。请稍后重试或联系人工客服。")