feat: 优化 FAQ 处理和系统稳定性
- 添加本地 FAQ 库快速路径(问候语等社交响应) - 修复 Chatwoot 重启循环问题(PID 文件清理) - 添加 LLM 响应缓存(Redis 缓存,提升性能) - 添加智能推理模式(根据查询复杂度自动启用) - 添加订单卡片消息功能(Chatwoot 富媒体) - 增加 LLM 超时时间至 60 秒 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -141,32 +141,89 @@ class ChatwootClient:
|
||||
content_attributes: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Send a rich message (cards, buttons, etc.)
|
||||
|
||||
|
||||
Args:
|
||||
conversation_id: Conversation ID
|
||||
content: Fallback text content
|
||||
content_type: Rich content type (cards, input_select, etc.)
|
||||
content_attributes: Rich content attributes
|
||||
|
||||
|
||||
Returns:
|
||||
Created message data
|
||||
"""
|
||||
client = await self._get_client()
|
||||
|
||||
|
||||
payload = {
|
||||
"content": content,
|
||||
"message_type": MessageType.OUTGOING.value,
|
||||
"content_type": content_type,
|
||||
"content_attributes": content_attributes
|
||||
}
|
||||
|
||||
|
||||
response = await client.post(
|
||||
f"/conversations/{conversation_id}/messages",
|
||||
json=payload
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
|
||||
return response.json()
|
||||
|
||||
async def send_order_card(
|
||||
self,
|
||||
conversation_id: int,
|
||||
order_data: dict[str, Any],
|
||||
actions: list[dict[str, Any]]
|
||||
) -> dict[str, Any]:
|
||||
"""发送订单卡片消息(Markdown 文本 + 操作按钮)
|
||||
|
||||
Args:
|
||||
conversation_id: 会话 ID
|
||||
order_data: 订单数据,包含:
|
||||
- order_id: 订单号
|
||||
- status: 订单状态
|
||||
- status_text: 状态文本
|
||||
- created_at: 下单时间(可选)
|
||||
- items: 商品列表(可选)
|
||||
- total_amount: 总金额
|
||||
- shipping_fee: 运费(可选)
|
||||
- logistics: 物流信息(可选)
|
||||
- remark: 备注(可选)
|
||||
actions: 操作按钮配置列表,每个按钮包含:
|
||||
- type: "link" 或 "postback"
|
||||
- text: 按钮文字
|
||||
- uri: 链接地址(type=link 时必需)
|
||||
- payload: 回传数据(type=postback 时必需)
|
||||
|
||||
Returns:
|
||||
发送结果
|
||||
|
||||
Example:
|
||||
>>> order_data = {
|
||||
... "order_id": "123456789",
|
||||
... "status": "shipped",
|
||||
... "status_text": "已发货",
|
||||
... "total_amount": "1058.00",
|
||||
... "items": [...]
|
||||
... }
|
||||
>>> actions = [
|
||||
... {"type": "link", "text": "查看详情", "uri": "https://..."},
|
||||
... {"type": "postback", "text": "联系客服", "payload": "CONTACT_SUPPORT"}
|
||||
... ]
|
||||
>>> await chatwoot.send_order_card(123, order_data, actions)
|
||||
"""
|
||||
# 生成 Markdown 内容
|
||||
markdown_content = format_order_card_markdown(order_data)
|
||||
|
||||
# 生成按钮卡片
|
||||
buttons = create_action_buttons(actions)
|
||||
|
||||
# 发送富媒体消息
|
||||
return await self.send_rich_message(
|
||||
conversation_id=conversation_id,
|
||||
content=markdown_content,
|
||||
content_type="cards",
|
||||
content_attributes=buttons
|
||||
)
|
||||
|
||||
# ============ Conversations ============
|
||||
|
||||
@@ -342,6 +399,130 @@ class ChatwootClient:
|
||||
return data.get("payload", [])
|
||||
|
||||
|
||||
# ============ Helper Functions ============
|
||||
|
||||
def format_order_card_markdown(order_data: dict[str, Any]) -> str:
|
||||
"""格式化订单信息为 Markdown 卡片
|
||||
|
||||
Args:
|
||||
order_data: 订单数据,包含订单号、状态、商品、金额、物流等信息
|
||||
|
||||
Returns:
|
||||
格式化的 Markdown 字符串
|
||||
|
||||
Example:
|
||||
>>> order = {
|
||||
... "order_id": "123456789",
|
||||
... "status": "shipped",
|
||||
... "status_text": "已发货",
|
||||
... "created_at": "2023-10-27 14:30",
|
||||
... "items": [...],
|
||||
... "total_amount": "1058.00",
|
||||
... "shipping_fee": "0.00",
|
||||
... "logistics": {...}
|
||||
... }
|
||||
>>> markdown = format_order_card_markdown(order)
|
||||
"""
|
||||
# 订单状态 emoji 映射
|
||||
status_emoji = {
|
||||
"pending": "⏳",
|
||||
"paid": "💰",
|
||||
"processing": "⚙️",
|
||||
"shipped": "📦",
|
||||
"delivered": "✅",
|
||||
"completed": "✅",
|
||||
"cancelled": "❌",
|
||||
"refunded": "💸",
|
||||
"failed": "⚠️",
|
||||
}
|
||||
|
||||
# 获取状态文本和 emoji
|
||||
status = order_data.get("status", "unknown")
|
||||
status_text = order_data.get("status_text", status)
|
||||
emoji = status_emoji.get(status, "📦")
|
||||
|
||||
lines = [
|
||||
f"{emoji} **订单状态:{status_text}**",
|
||||
f"📝 **订单号:** `{order_data.get('order_id', '')}`",
|
||||
]
|
||||
|
||||
# 添加下单时间(如果有)
|
||||
if order_data.get("created_at"):
|
||||
lines.append(f"📅 **下单时间:** {order_data['created_at']}")
|
||||
|
||||
lines.append("") # 空行
|
||||
lines.append("**商品详情**")
|
||||
|
||||
# 添加商品列表
|
||||
items = order_data.get("items", [])
|
||||
if items:
|
||||
for item in items:
|
||||
name = item.get("name", "未知商品")
|
||||
quantity = item.get("quantity", 1)
|
||||
price = item.get("price", "0.00")
|
||||
# 可选:添加图片链接
|
||||
image_markdown = ""
|
||||
if item.get("image_url"):
|
||||
image_markdown = f" [图片]({item['image_url']})"
|
||||
lines.append(f"▫️{image_markdown} {name} × {quantity} ¥{price}")
|
||||
else:
|
||||
lines.append("▫️ 无商品信息")
|
||||
|
||||
# 添加金额信息
|
||||
lines.extend([
|
||||
"",
|
||||
f"💰 **实付:** ¥{order_data.get('total_amount', '0.00')} (含运费 ¥{order_data.get('shipping_fee', '0.00')})"
|
||||
])
|
||||
|
||||
# 添加物流信息(如果有)
|
||||
logistics = order_data.get("logistics")
|
||||
if logistics:
|
||||
lines.extend([
|
||||
"",
|
||||
"🚚 **物流信息**",
|
||||
f"承运商:{logistics.get('carrier', '未知')}",
|
||||
f"单号:{logistics.get('tracking_number', '未知')}",
|
||||
"*点击单号可复制跟踪*"
|
||||
])
|
||||
|
||||
# 添加备注(如果有)
|
||||
if order_data.get("remark"):
|
||||
lines.extend([
|
||||
"",
|
||||
f"📋 **备注:** {order_data['remark']}"
|
||||
])
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def create_action_buttons(actions: list[dict[str, Any]]) -> dict[str, Any]:
|
||||
"""创建 Chatwoot 操作按钮卡片
|
||||
|
||||
Args:
|
||||
actions: 按钮配置列表,每个按钮包含:
|
||||
- type: "link" 或 "postback"
|
||||
- text: 按钮文字
|
||||
- uri: 链接地址(type=link 时)
|
||||
- payload: 回传数据(type=postback 时)
|
||||
|
||||
Returns:
|
||||
符合 Chatwoot content_attributes 格式的字典
|
||||
|
||||
Example:
|
||||
>>> actions = [
|
||||
... {"type": "link", "text": "查看详情", "uri": "https://example.com"},
|
||||
... {"type": "postback", "text": "联系客服", "payload": "CONTACT_SUPPORT"}
|
||||
... ]
|
||||
>>> buttons = create_action_buttons(actions)
|
||||
"""
|
||||
return {
|
||||
"items": [{
|
||||
"title": "操作",
|
||||
"actions": actions
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
# Global Chatwoot client instance
|
||||
chatwoot_client: Optional[ChatwootClient] = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user