intent.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  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. - "review" → 配风计划审查管线
  13. - "dialog" → 通风对话助手(统一处理数据解读、需风量计算等)
  14. Args:
  15. message: 用户消息文本
  16. filename: 可选,上传的附件文件名(用于辅助意图判断)
  17. Returns:
  18. "review" / "dialog"
  19. """
  20. try:
  21. model = get_chat_model()
  22. # 构建附件信息行
  23. attachment_info = f"附件文件名:{filename}" if filename else "(无附件)"
  24. prompt = _INTENT_CLASSIFY_PROMPT.format(
  25. message=message[:500], # 截断防过长
  26. attachment_info=attachment_info,
  27. )
  28. # 在 executor 中运行同步 invoke,避免阻塞事件循环
  29. loop = asyncio.get_event_loop()
  30. result = await loop.run_in_executor(
  31. None,
  32. lambda: model.invoke([{"role": "user", "content": prompt}])
  33. )
  34. raw = result.content if hasattr(result, "content") else str(result)
  35. raw = raw.strip().lower()
  36. # 提取第一个有效词
  37. match = re.search(r'(review|dialog)', raw)
  38. if match:
  39. return match.group(1)
  40. except Exception as e:
  41. print(f"[意图分类] Agent 分类失败,回退到 dialog: {e}")
  42. return "dialog"