from enum import Enum from langchain_openai import ChatOpenAI from app.config import settings from app.prompt_service import get_prompt import logging logger = logging.getLogger(__name__) class Intent(str, Enum): CHAT = "chat" # 日常聊天 / 育儿交流 ANALYSIS = "analysis" # 报告解读 / 数据分析 RECOMMEND = "recommend" # 商品 / 活动推荐 TASK = "task" # 任务创建 / 进度查询 MIND = "mind" # 情绪疏导 / 心理支持 HEALTH = "health" # 健康咨询 / 舌诊 CLASSIFY_PROMPT = """从用户消息中识别意图, 只返回意图代码, 不要解释: - chat: 日常聊天、育儿交流、询问建议(非具体商品/报告) - analysis: 报告解读\数据分析\趋势查看(提到"报告"/"分析"/"评分") - recommend: 商品\活动\文章推荐(提到"推荐"/"买"/"吃什么"/"适合") - task: 任务相关(提到"任务"/"打卡"/"完成"/"奖励") - mind: 情绪问题\心理支持(提到"心情"/"难过"/"焦虑"/"不开心") - health: 健康咨询\舌诊(提到"舌"/"健康"/"体质") 用户消息: {query} 历史上下文: {context} 意图代码: """ class IntentClassifier: def __init__(self): self.llm = ChatOpenAI( model=settings.llm_model, api_key=settings.llm_api_key, base_url=settings.llm_base_url, temperature=settings.llm_temperature, max_tokens=20, ) async def classify(self, query: str, context: str = "") -> Intent: template = await get_prompt("intent_classifier") or CLASSIFY_PROMPT try: prompt = template.format(query=query[:200], context=context[:300]) except (KeyError, IndexError, ValueError): logger.warning("Java 配置的 intent_classifier 模板缺少占位符,回退本地模板") prompt = CLASSIFY_PROMPT.format(query=query[:200], context=context[:300]) try: resp = await self.llm.ainvoke(prompt) intent_str = resp.content.strip().lower() for intent in Intent: if intent.value in intent_str: return intent logger.warning("无法识别的意图: %s, 默认 chat", intent_str) return Intent.CHAT except Exception as e: logger.warning("意图分类失败: %s, 默认 chat", e) return Intent.CHAT