intent.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. # -*- coding: utf-8 -*-
  2. """
  3. 意图分类 —— 使用 LLM Agent 推理用户意图,替代关键词匹配
  4. """
  5. import re
  6. import asyncio
  7. from api.prompts import _INTENT_CLASSIFY_PROMPT
  8. from api.chat_model import get_chat_model
  9. async def classify_intent(message: str, filename: str | None = None) -> str:
  10. """使用 LLM Agent 推理用户意图,替代关键词匹配。
  11. 用轻量级模型调用做意图分类,支持三种路由:
  12. - "needq_calc" → 需风量计算 Agent
  13. - "review" → 配风计划审查管线
  14. - "dialog" → 对话解读 Agent(默认)
  15. Args:
  16. message: 用户消息文本
  17. filename: 可选,上传的附件文件名(用于辅助意图判断)
  18. Returns:
  19. "needq_calc" / "review" / "dialog"
  20. """
  21. try:
  22. model = get_chat_model()
  23. # 构建附件信息行
  24. attachment_info = f"附件文件名:{filename}" if filename else "(无附件)"
  25. prompt = _INTENT_CLASSIFY_PROMPT.format(
  26. message=message[:500], # 截断防过长
  27. attachment_info=attachment_info,
  28. )
  29. # 在 executor 中运行同步 invoke,避免阻塞事件循环
  30. loop = asyncio.get_event_loop()
  31. result = await loop.run_in_executor(
  32. None,
  33. lambda: model.invoke([{"role": "user", "content": prompt}])
  34. )
  35. raw = result.content if hasattr(result, "content") else str(result)
  36. raw = raw.strip().lower()
  37. # 提取第一个有效词
  38. match = re.search(r'(needq_calc|review|dialog)', raw)
  39. if match:
  40. return match.group(1)
  41. except Exception as e:
  42. print(f"[意图分类] Agent 分类失败,回退到 dialog: {e}")
  43. return "dialog"