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:
121
agent/utils/faq_library.py
Normal file
121
agent/utils/faq_library.py
Normal file
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
Local FAQ Library for instant responses
|
||||
Common questions can be answered immediately without API calls
|
||||
"""
|
||||
import re
|
||||
from typing import Optional, Dict
|
||||
from .logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class FAQLibrary:
|
||||
"""Local FAQ library for instant common question responses"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize FAQ library with ONLY common greetings and social responses
|
||||
|
||||
Note: Business-related FAQs (register, order, payment, shipment, return, etc.)
|
||||
should be handled by Strapi MCP to ensure accuracy and consistency.
|
||||
This library only contains instant social responses for better UX.
|
||||
"""
|
||||
self.faqs = {
|
||||
# ========== 问候类 Greetings ==========
|
||||
"你好": "你好!我是您的B2B客户服务助手,很高兴为您服务。我可以帮您处理订单查询、产品咨询、售后问题等。请问有什么可以帮到您的吗?",
|
||||
"您好": "您好!我是您的B2B客户服务助手,很高兴为您服务。我可以帮您处理订单查询、产品咨询、售后问题等。请问有什么可以帮到您的吗?",
|
||||
"hi": "Hello! I'm your B2B customer service assistant. How can I help you today?",
|
||||
"hello": "Hello! I'm here to assist you. How can I help you today?",
|
||||
"hey": "Hey there! How can I help you today?",
|
||||
|
||||
# ========== 感谢类 Gratitude ==========
|
||||
"谢谢": "不客气!如果还有其他问题,随时可以问我。祝您购物愉快!",
|
||||
"感谢": "感谢您的支持!如有任何问题,随时联系我们。",
|
||||
"thank you": "You're welcome! If you have any other questions, feel free to ask. Have a great day!",
|
||||
"thanks": "You're welcome! Let me know if you need anything else.",
|
||||
|
||||
# ========== 再见类 Farewell ==========
|
||||
"再见": "再见!如有需要,随时联系。祝您生活愉快!",
|
||||
"bye": "Goodbye! Feel free to reach out anytime. Have a great day!",
|
||||
"goodbye": "Goodbye! Have a wonderful day!",
|
||||
|
||||
# ========== 社交礼貌类 Social Politeness ==========
|
||||
"早上好": "早上好!很高兴为您服务。请问有什么可以帮到您的吗?",
|
||||
"下午好": "下午好!很高兴为您服务。请问有什么可以帮到您的吗?",
|
||||
"晚上好": "晚上好!很高兴为您服务。请问有什么可以帮到您的吗?",
|
||||
"good morning": "Good morning! How can I assist you today?",
|
||||
"good afternoon": "Good afternoon! How can I assist you today?",
|
||||
"good evening": "Good evening! How can I assist you today?",
|
||||
}
|
||||
|
||||
# Compile regex patterns for fuzzy matching
|
||||
self._compile_patterns()
|
||||
|
||||
def _compile_patterns(self):
|
||||
"""Compile regex patterns for fuzzy FAQ matching"""
|
||||
self.patterns = []
|
||||
for keyword, response in self.faqs.items():
|
||||
# Case-insensitive pattern with word boundaries
|
||||
pattern = re.compile(re.escape(keyword), re.IGNORECASE)
|
||||
self.patterns.append((pattern, response))
|
||||
|
||||
def find_match(self, query: str) -> Optional[str]:
|
||||
"""Find matching FAQ response
|
||||
|
||||
Args:
|
||||
query: User query text
|
||||
|
||||
Returns:
|
||||
Matching FAQ response or None if no match found
|
||||
"""
|
||||
# Remove HTML tags and extra whitespace
|
||||
clean_query = re.sub(r'<[^>]+>', '', query)
|
||||
clean_query = ' '.join(clean_query.split())
|
||||
|
||||
# Try exact match first
|
||||
if clean_query.lower() in (k.lower() for k in self.faqs.keys()):
|
||||
for key, response in self.faqs.items():
|
||||
if key.lower() == clean_query.lower():
|
||||
logger.info("FAQ exact match", key=key, query=clean_query[:50])
|
||||
return response
|
||||
|
||||
# Try fuzzy match (contains keyword)
|
||||
for pattern, response in self.patterns:
|
||||
if pattern.search(clean_query):
|
||||
logger.info("FAQ fuzzy match", pattern=pattern.pattern, query=clean_query[:50])
|
||||
return response
|
||||
|
||||
# No match found
|
||||
logger.debug("No FAQ match found", query=clean_query[:50])
|
||||
return None
|
||||
|
||||
def add_faq(self, keyword: str, response: str) -> None:
|
||||
"""Add or update FAQ entry
|
||||
|
||||
Args:
|
||||
keyword: Question keyword
|
||||
response: Answer text
|
||||
"""
|
||||
self.faqs[keyword] = response
|
||||
pattern = re.compile(re.escape(keyword), re.IGNORECASE)
|
||||
self.patterns.append((pattern, response))
|
||||
logger.info("FAQ added", keyword=keyword)
|
||||
|
||||
def get_all_keywords(self) -> list[str]:
|
||||
"""Get all FAQ keywords
|
||||
|
||||
Returns:
|
||||
List of FAQ keywords
|
||||
"""
|
||||
return list(self.faqs.keys())
|
||||
|
||||
|
||||
# Global FAQ library instance
|
||||
faq_library: Optional[FAQLibrary] = None
|
||||
|
||||
|
||||
def get_faq_library() -> FAQLibrary:
|
||||
"""Get or create global FAQ library instance"""
|
||||
global faq_library
|
||||
if faq_library is None:
|
||||
faq_library = FAQLibrary()
|
||||
return faq_library
|
||||
Reference in New Issue
Block a user