Files
PlantAI-rag-new/sdk/app/services/docgen/intent.py
T
jerryandClaude Fable 5 5db3ead73e feat(docgen): doc_writer 能力全链——vstore 独立服务 + BFF docgen 路由 + 前端文档工作台
- vstore 独立安装包(8094):解析/嵌入/加密 vault/faiss 检索,存储路径支持本地 file 与 http(s):// URL,启动握手校验,集群化预留(embed 独立模块)
- BFF docgen 路由:上传入库/generate/编辑/导出/下载/主库管理,意图护栏(与前端同词典),vstore 失败兜底,quota 507 与 TTL 惰性清理
- 前端:自然触发意图路由、拖拽上传 chips、能力徽标、右侧文档 TAB(WYSIWYG 编辑/prompt 修改/PDF+DOCX 导出下载)、右栏拖宽+手柄仿左栏
- 批量导入工具 docgen_import.py(并发 8、导入即加密+删源明文)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-03 21:13:37 +08:00

95 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""services/docgen/intent.py —— 服务端意图路由(规则词典法)。
唯一事实源:docs/team/cases_intent.md(30 条用例表,前后端同表测试)。
漏判安全原则:不命中一律 qa。
判定顺序(按优先级,命中即返回):
1. export:has_active_artifact 且 EXPORT_WORD + FORMAT_WORD
2. edit:has_active_artifact 且 EDIT_WORD
3. docgen:WRITE_VERB + DOC_TYPE
4. docgen:has_attachments + WRITE_VERB
5. 其余 qa
"""
from __future__ import annotations
# ---- 词典(与 cases_intent.md 逐条一致,不得自造)----
EXPORT_WORD = ["导出", "转成", "转为", "转换成", "下载成", "输出为", "存为", "转pdf", "转word"]
FORMAT_WORD = ["pdf", "docx", "doc", "word"] # 英文不区分大小写(contains 判定)
EDIT_WORD = ["改", "修改", "调整", "删", "删除", "加一段", "补充", "润色",
"缩写", "扩写", "重写", "改写", "优化", "加个", "增加一段"]
WRITE_VERB = ["写", "撰写", "拟", "起草", "编制", "生成", "编写", "拟定", "草拟", "制定"]
DOC_TYPE = [
"论文", "报告", "通知", "通告", "公告", "请示", "批复", "函", "申请书",
"申请", "申报书", "标书", "合同", "协议", "方案", "计划", "总结", "汇报",
"讲话稿", "致辞", "证明", "纪要", "简报", "材料", "说明书", "指南", "文档",
"申报材料", "工作总结", "调研报告", "可行性报告", "项目书", "策划书",
"演讲稿", "新闻稿", "文案", "简历", "制度", "规定", "办法", "细则", "章程",
"声明", "邀请函", "感谢信", "慰问信", "介绍信", "推荐信", "倡议书",
"述职报告", "开题报告", "结题报告", "实验报告", "分析报告", "会议纪要",
]
# 明确排除(防误判,不属于 DOC_TYPE)
DOC_TYPE_EXCLUDE = ["介绍", "内容", "代码", "诗", "作业", "问题", "建议", "想法"]
def _contains_any(text: str, words: list[str]) -> bool:
"""text 含 words 任一子串。"""
return any(w in text for w in words)
def _contains_any_ci(text: str, words: list[str]) -> bool:
"""不区分大小写匹配(英文词典用)。"""
lower = text.lower()
return any(w.lower() in lower for w in words)
def _has_doc_type(text: str) -> bool:
"""含 DOC_TYPE 任一,且不含 DOC_TYPE_EXCLUDE 任一(排除优先)。"""
if _contains_any(text, DOC_TYPE_EXCLUDE):
return False
return _contains_any(text, DOC_TYPE)
def route(text: str, has_attachments: bool, has_active_artifact: bool) -> str:
"""意图路由:qa | docgen | edit | export。
判定顺序按 cases_intent.md 冻结表,漏判安全(不命中一律 qa)。
"""
if not text or not text.strip():
return "qa"
# 1. export(需有活动文档)
if has_active_artifact:
if _contains_any(text, EXPORT_WORD) and _contains_any_ci(text, FORMAT_WORD):
return "export"
# 2. edit(需有活动文档)
if _contains_any(text, EDIT_WORD):
return "edit"
# 3. docgen:写类动词 + 文档类型词
if _contains_any(text, WRITE_VERB) and _has_doc_type(text):
return "docgen"
# 4. docgen:附件信号(拖入文件 + 写类动词)
if has_attachments and _contains_any(text, WRITE_VERB):
return "docgen"
# 5. 漏判安全:其余一律 qa
return "qa"
async def is_docgen_intent(text: str) -> bool:
"""dev2 护栏布尔接口(async 契约):route(...) == "docgen"。
dev2 的 generate/edit/export 均 await 此函数;路由异常时护栏
放行(与 dev2 桩行为一致,护栏不阻断)。
"""
try:
return route(text, has_attachments=False, has_active_artifact=False) == "docgen"
except Exception:
return True