122 lines
5.0 KiB
Python
122 lines
5.0 KiB
Python
|
|
"""
|
|||
|
|
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
|