feat: 2026-07-11 全量更新 - 代办集成+会议室预定+知识迭代修复+UI统一+Bug修复
== 已部署上线 (9项) == - 代办事项真实数据源集成 (企微审批API 8bug修复链) - H5/坐席端 Logo样式统一+绿色背景 - 视频引导页修复 (localStorage key v2) - 坐席端 v9 Vue版本修复 (ElMessage._context) - 截图按钮 v10 修复 (getDisplayMedia user gesture) - 扫码样式恢复+H5扫码登录跳转修复 - H5截图快捷键提示 == 代码完成待部署 (3项) == - 知识迭代3Bug修复 (#8 POST端点/#7 MERGE幂等/#6 过期检查) - 会议室预定-小鱼易联终端 (40文件, 40/40测试通过) - IT资产升级审批推送 (asset_service.py) == 需求文档 (2项) == - 坐席端AI辅助消息框-PRD (4项新功能确认) - 坐席端布局优化建议 v2.0 (7天计划) == 新增文档 == - 日报-2026-07-11.md - 知识迭代Bug修复报告-20260711.md - 会议室预定-部署指南.md - CHANGELOG.md 更新 == 测试 == - test_todo_integration.py: 40/40 - test_meetingroom.py: 40/40 - test_bugfix_ki_suggestions.py: 21/21
This commit is contained in:
@@ -7,11 +7,15 @@
|
||||
# 生产基址(任务指定):http://yw-dify.dc.servyou-it.com/dify2openai/
|
||||
#
|
||||
# 返回结构(供 IntentRouter 使用):
|
||||
# {"scenario_key": str|None, "confidence": float, "raw": str, "error": str}
|
||||
# {"global_intent": str|None, "scenario_key": str|None, "confidence": float,
|
||||
# "corrected_field": str|None, "old_value": str|None, "new_value": str|None,
|
||||
# "supplement_field": str|None, "supplement_value": str|None,
|
||||
# "raw": str, "error": str}
|
||||
# global_intent ∈ {pause, resume_task, correct, supplement, None}
|
||||
# scenario_key ∈ {password_reset, software_install, virus_dispose, terminal_locate}
|
||||
#
|
||||
# 降级:Dify 未配置或调用失败 → _fallback_intent 走关键词兜底(关键词取自
|
||||
# app.services.automation.DEFAULT_SCENARIO_CONFIGS),保证无真实环境也能闭环。
|
||||
# 降级:Dify 未配置或调用失败 → _fallback_intent 走关键词兜底(先匹配全局意图
|
||||
# 关键词,未命中再匹配场景关键词),保证无真实环境也能闭环。
|
||||
# =============================================================================
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -32,12 +36,28 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
_DEFAULT_TIMEOUT = 30.0
|
||||
# 意图识别提示词:要求模型仅输出 JSON
|
||||
# 复杂场景重构:在现有4场景分类基础上,增加全局对话控制意图判断
|
||||
_SYSTEM_PROMPT = (
|
||||
"你是IT服务台意图分类器。根据用户诉求,判断其属于以下哪个场景之一,"
|
||||
"并仅输出一个 JSON 对象,不要输出任何额外文字:\n"
|
||||
'{"scenario_key": "password_reset|software_install|virus_dispose|terminal_locate|unknown", '
|
||||
'"confidence": 0.0~1.0}\n'
|
||||
"场景说明:\n"
|
||||
"你是IT服务台意图分类器。根据用户诉求,首先判断是否属于「全局对话控制意图」,"
|
||||
"如果不是全局控制意图,再判断其属于哪个IT场景。\n"
|
||||
"仅输出一个 JSON 对象,不要输出任何额外文字:\n"
|
||||
'{\n'
|
||||
' "global_intent": "pause|resume_task|correct|supplement|null",\n'
|
||||
' "scenario_key": "password_reset|software_install|virus_dispose|terminal_locate|unknown",\n'
|
||||
' "confidence": 0.0~1.0,\n'
|
||||
' "corrected_field": "字段名(仅correct时填写)",\n'
|
||||
' "old_value": "旧值(仅correct时填写)",\n'
|
||||
' "new_value": "新值(仅correct时填写)",\n'
|
||||
' "supplement_field": "字段名(仅supplement时填写)",\n'
|
||||
' "supplement_value": "补充值(仅supplement时填写)"\n'
|
||||
'}\n'
|
||||
"全局意图说明(优先判断,命中后 scenario_key 设为 unknown):\n"
|
||||
"- pause: 用户要暂停/离开当前任务(如\"先去开会\"\"等会继续\"\"暂停\")\n"
|
||||
"- resume_task: 用户要恢复之前暂停的任务(如\"继续\"\"继续刚才\"\"回来了\")\n"
|
||||
"- correct: 用户要更正之前提供的信息(如\"刚才说错了\"\"不是xx是xx\"\"应该是\")\n"
|
||||
"- supplement: 用户要补充额外信息(如\"再补充一下\"\"顺便说一下\"\"还有\")\n"
|
||||
"- null: 不属于以上任何全局意图,走场景分类\n"
|
||||
"场景说明(仅 global_intent 为 null 时判断):\n"
|
||||
"- password_reset: 忘记/重置密码、账号密码相关\n"
|
||||
"- software_install: 安装/下载软件\n"
|
||||
"- virus_dispose: 病毒、木马、勒索、杀毒\n"
|
||||
@@ -79,10 +99,12 @@ class DifyClient(BaseClient):
|
||||
async def detect_intent(
|
||||
self, description: str, employee_id: str = ""
|
||||
) -> Dict[str, Any]:
|
||||
"""调用 Dify 识别意图。
|
||||
"""调用 Dify 识别意图(含全局意图判断)。
|
||||
|
||||
Returns:
|
||||
Dict: {scenario_key, confidence, raw, error}
|
||||
Dict: {global_intent, scenario_key, confidence, corrected_field,
|
||||
old_value, new_value, supplement_field, supplement_value,
|
||||
raw, error}
|
||||
"""
|
||||
prompt = description or ""
|
||||
body = {
|
||||
@@ -114,11 +136,24 @@ class DifyClient(BaseClient):
|
||||
choices = data.get("choices") or []
|
||||
content = choices[0]["message"]["content"] if choices else ""
|
||||
parsed = json.loads(content)
|
||||
# 全局意图解析
|
||||
global_intent_raw = parsed.get("global_intent")
|
||||
global_intent: Optional[str] = None
|
||||
if global_intent_raw and global_intent_raw != "null":
|
||||
global_intent = global_intent_raw
|
||||
|
||||
scenario_key = parsed.get("scenario_key")
|
||||
confidence = float(parsed.get("confidence", 0.0))
|
||||
|
||||
return {
|
||||
"global_intent": global_intent,
|
||||
"scenario_key": scenario_key if scenario_key != "unknown" else None,
|
||||
"confidence": confidence,
|
||||
"corrected_field": parsed.get("corrected_field"),
|
||||
"old_value": parsed.get("old_value"),
|
||||
"new_value": parsed.get("new_value"),
|
||||
"supplement_field": parsed.get("supplement_field"),
|
||||
"supplement_value": parsed.get("supplement_value"),
|
||||
"raw": content,
|
||||
"error": "",
|
||||
}
|
||||
@@ -132,10 +167,33 @@ class DifyClient(BaseClient):
|
||||
def _fallback_intent(description: str) -> Dict[str, Any]:
|
||||
"""关键词兜底(无 Dify / 解析失败时)。
|
||||
|
||||
关键词取自 DEFAULT_SCENARIO_CONFIGS 的 trigger_conditions.keywords;
|
||||
命中即返回该场景,置信度取 0.6(恰好达到阈值,可继续编排)。
|
||||
复杂场景重构:先做全局意图关键词匹配,命中则返回全局意图;
|
||||
未命中则走原场景关键词匹配。
|
||||
"""
|
||||
text = (description or "").lower()
|
||||
|
||||
# 1. 全局意图关键词兜底
|
||||
try:
|
||||
from app.constants import GLOBAL_INTENT_KEYWORDS
|
||||
|
||||
for intent, keywords in GLOBAL_INTENT_KEYWORDS.items():
|
||||
if any(kw.lower() in text for kw in keywords):
|
||||
return {
|
||||
"global_intent": intent,
|
||||
"scenario_key": None,
|
||||
"confidence": 0.6,
|
||||
"corrected_field": None,
|
||||
"old_value": None,
|
||||
"new_value": None,
|
||||
"supplement_field": None,
|
||||
"supplement_value": None,
|
||||
"raw": "",
|
||||
"error": "fallback",
|
||||
}
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
|
||||
# 2. 场景关键词兜底
|
||||
scenario_key: Optional[str] = None
|
||||
try: # 懒加载,避免循环依赖
|
||||
from app.services.automation import DEFAULT_SCENARIO_CONFIGS
|
||||
@@ -149,8 +207,14 @@ class DifyClient(BaseClient):
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
return {
|
||||
"global_intent": None,
|
||||
"scenario_key": scenario_key,
|
||||
"confidence": 0.6 if scenario_key else 0.0,
|
||||
"corrected_field": None,
|
||||
"old_value": None,
|
||||
"new_value": None,
|
||||
"supplement_field": None,
|
||||
"supplement_value": None,
|
||||
"raw": "",
|
||||
"error": "fallback",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user