Spaces:
Sleeping
Sleeping
improve: intent classifier
Browse files- modules/info_extractor.py +9 -4
- modules/intent_classifier.py +55 -0
- modules/travel_assistant.py +27 -10
modules/info_extractor.py
CHANGED
|
@@ -10,10 +10,15 @@ class InfoExtractor:
|
|
| 10 |
|
| 11 |
def _build_prompt_template(self) -> str:
|
| 12 |
|
| 13 |
-
return """
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
{{
|
| 19 |
"destination": {{
|
|
|
|
| 10 |
|
| 11 |
def _build_prompt_template(self) -> str:
|
| 12 |
|
| 13 |
+
return """你是一个专业的旅游信息提取AI。
|
| 14 |
+
你的任务是仔细阅读用户的请求,并从中提取出关键的旅行信息。
|
| 15 |
+
|
| 16 |
+
请严格按照以下嵌套的JSON格式返回
|
| 17 |
+
---
|
| 18 |
+
**重要规则**
|
| 19 |
+
1. 如果某个信息在用户请求中没有明确提及,请将对应的值设为 null。
|
| 20 |
+
2. **如果用户的请求只是简单的问候 (例如 "hi", "你好"),或者完全不包含任何目的地、时间、预算等旅行信息,请必须返回一个空的JSON对象,即 `{}`。**
|
| 21 |
+
---
|
| 22 |
|
| 23 |
{{
|
| 24 |
"destination": {{
|
modules/intent_classifier.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
from .ai_model import AIModel
|
| 3 |
+
|
| 4 |
+
class IntentClassifier:
|
| 5 |
+
"""
|
| 6 |
+
一个专门用于识别用户输入意uto的分类器。
|
| 7 |
+
它使用LLM来判断用户的消息属于预定义的哪个类别。
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
def __init__(self, ai_model: AIModel):
|
| 11 |
+
self.ai_model = ai_model
|
| 12 |
+
self.VALID_INTENTS = ['PROVIDING_TRAVEL_INFO', 'GREETING', 'OTHER']
|
| 13 |
+
|
| 14 |
+
def _build_prompt(self, message: str) -> str:
|
| 15 |
+
"""构建用于意图分类的、轻量级的Prompt。"""
|
| 16 |
+
return f"""
|
| 17 |
+
你的任务是分析用户的单条消息,并判断其意图。
|
| 18 |
+
请从以下几个意图中选择一个最匹配的,并且只返回这个意图的字符串,不要添加任何其他解释或标点符号。
|
| 19 |
+
|
| 20 |
+
可用意图:
|
| 21 |
+
- PROVIDING_TRAVEL_INFO: 用户明确提到了旅行相关的具体信息,如目的地、时间、预算、人数等。例如:"我想去巴黎玩一周" 或 "预算5000块钱"。
|
| 22 |
+
- GREETING: 用户只是在打招呼或进行简单的问候。例如:"你好", "hi", "在吗?"。
|
| 23 |
+
- OTHER: 不属于以上任何一种的通用查询或闲聊。例如:"法国有什么好玩的?" 或 "帮我订票"。
|
| 24 |
+
|
| 25 |
+
用户消息:
|
| 26 |
+
---
|
| 27 |
+
{message}
|
| 28 |
+
---
|
| 29 |
+
|
| 30 |
+
你的判断结果 (请只返回一个意图字符串):
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
def classify(self, message: str) -> str:
|
| 34 |
+
"""对给定的消息进行意图分类。"""
|
| 35 |
+
log.info(f"🚀 开始对消息进行意图分类: '{message[:30]}...'")
|
| 36 |
+
prompt = self._build_prompt(message)
|
| 37 |
+
|
| 38 |
+
try:
|
| 39 |
+
response = self.ai_model.chat_completion(
|
| 40 |
+
model="gpt-3.5-turbo",
|
| 41 |
+
messages=[{"role": "user", "content": prompt}],
|
| 42 |
+
temperature=0.0,
|
| 43 |
+
max_tokens=10
|
| 44 |
+
)
|
| 45 |
+
intent = response.strip().replace("'", "").replace("\"", "")
|
| 46 |
+
|
| 47 |
+
if intent in self.VALID_INTENTS:
|
| 48 |
+
log.info(f"✅ 意图分类成功: {intent}")
|
| 49 |
+
return intent
|
| 50 |
+
else:
|
| 51 |
+
log.warning(f"⚠️ LLM返回了未知的意图 '{intent}',将回退到 'OTHER'")
|
| 52 |
+
return 'OTHER'
|
| 53 |
+
except Exception as e:
|
| 54 |
+
log.error(f"❌ 意图分类时发生错误: {e}", exc_info=True)
|
| 55 |
+
return 'OTHER'
|
modules/travel_assistant.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
| 2 |
from .config_loader import ConfigLoader
|
| 3 |
from .ai_model import AIModel
|
| 4 |
from .knowledge_base import KnowledgeBase
|
|
|
|
| 5 |
from .info_extractor import InfoExtractor
|
| 6 |
from .session_manager import SessionManager
|
| 7 |
from .response_generator import ResponseGenerator
|
|
@@ -15,7 +16,8 @@ class TravelAssistant:
|
|
| 15 |
self.kb = KnowledgeBase()
|
| 16 |
self.ai_model = AIModel()
|
| 17 |
self.session_manager = SessionManager()
|
| 18 |
-
self.info_extractor = InfoExtractor(self.ai_model)
|
|
|
|
| 19 |
self.response_generator = ResponseGenerator(self.ai_model, self.kb)
|
| 20 |
log.info("✅ Travel Assistant 核心模块全部初始化完成!")
|
| 21 |
|
|
@@ -43,17 +45,32 @@ class TravelAssistant:
|
|
| 43 |
session_state = self.session_manager.get_or_create_session(current_session_id)
|
| 44 |
log.info(f"✅ 设置persona: {persona_info['name']}")
|
| 45 |
|
| 46 |
-
# 3.
|
| 47 |
-
|
| 48 |
-
log.info(f"🔍
|
|
|
|
|
|
|
| 49 |
|
| 50 |
-
# 4
|
| 51 |
-
if
|
| 52 |
-
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
-
# 5. 生成回复
|
| 56 |
-
bot_response = self.response_generator.generate(message, session_state, extracted_info)
|
| 57 |
|
| 58 |
# 6. 返回结果
|
| 59 |
status_info = self.session_manager.format_session_info(session_state)
|
|
|
|
| 2 |
from .config_loader import ConfigLoader
|
| 3 |
from .ai_model import AIModel
|
| 4 |
from .knowledge_base import KnowledgeBase
|
| 5 |
+
from .intent_classifier import IntentClassifier
|
| 6 |
from .info_extractor import InfoExtractor
|
| 7 |
from .session_manager import SessionManager
|
| 8 |
from .response_generator import ResponseGenerator
|
|
|
|
| 16 |
self.kb = KnowledgeBase()
|
| 17 |
self.ai_model = AIModel()
|
| 18 |
self.session_manager = SessionManager()
|
| 19 |
+
self.info_extractor = InfoExtractor(self.ai_model)
|
| 20 |
+
self.intent_classifier = IntentClassifier(self.ai_model)
|
| 21 |
self.response_generator = ResponseGenerator(self.ai_model, self.kb)
|
| 22 |
log.info("✅ Travel Assistant 核心模块全部初始化完成!")
|
| 23 |
|
|
|
|
| 45 |
session_state = self.session_manager.get_or_create_session(current_session_id)
|
| 46 |
log.info(f"✅ 设置persona: {persona_info['name']}")
|
| 47 |
|
| 48 |
+
# 3. 意图识别 (前置守卫)
|
| 49 |
+
intent = self.intent_classifier.classify(message)
|
| 50 |
+
log.info(f"🔍 用户意图识别结果: '{intent}'")
|
| 51 |
+
|
| 52 |
+
extracted_info = {}
|
| 53 |
|
| 54 |
+
# 4.: 根据意图进行逻辑分流
|
| 55 |
+
if intent == 'PROVIDING_TRAVEL_INFO':
|
| 56 |
+
# 场景A: 用户提供了旅行信息,执行完整的信息提取
|
| 57 |
+
extracted_info = self.info_extractor.extract(message)
|
| 58 |
+
if extracted_info:
|
| 59 |
+
self.session_manager.update_session(current_session_id, extracted_info)
|
| 60 |
+
session_state = self.session_manager.get_or_create_session(current_session_id)
|
| 61 |
+
|
| 62 |
+
# 无论是否提取成功,都让 response_generator 来生成上下文感知的回复
|
| 63 |
+
bot_response = self.response_generator.generate(message, session_state, extracted_info)
|
| 64 |
+
|
| 65 |
+
else:
|
| 66 |
+
# 场景B: 用户意图是问候或其它,直接生成引导性回复,完全绕过信息提取
|
| 67 |
+
log.info(f"💬 意图为 '{intent}',绕过信息提取,直接生成引导性回复。")
|
| 68 |
+
if intent == 'GREETING':
|
| 69 |
+
bot_response = "您好!很高兴能为您规划旅程。请问您想去哪里,玩几天,预算大概是多少呢?"
|
| 70 |
+
else: # 'OTHER'
|
| 71 |
+
# 对于其它问题,可以调用通用的生成器,让它决定如何回复
|
| 72 |
+
bot_response = self.response_generator.generate(message, session_state, {})
|
| 73 |
|
|
|
|
|
|
|
| 74 |
|
| 75 |
# 6. 返回结果
|
| 76 |
status_info = self.session_manager.format_session_info(session_state)
|