generated from kgod/ai-review-template
自内部仓库剥离深度优化与 RAG 知识库后的交付版本: - Builder 对话式简历生成(FSM + 意图路由 LLM 兜底增强) - 条目级轻度优化:事实覆盖门禁 + STAR/bullet 修复链,功能/简介/成果与技术栈同级保护 - 简历导入:DOCX/PDF 解析、结构归一、手机号脱敏 - PostgreSQL 运行时 + Alembic 迁移链 Co-Authored-By: Claude <noreply@anthropic.com>
76 lines
3.3 KiB
Python
76 lines
3.3 KiB
Python
"""Chat intent registry: taxonomy, descriptions, few-shots, and output schema.
|
|
|
|
Single source of truth for Builder free-text intents. The LLM classifier may only
|
|
choose from this registry; handlers are bound deterministically in code (LLM
|
|
proposes, code disposes). Bump CHAT_INTENT_REGISTRY_VERSION on any taxonomy change.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from enum import StrEnum
|
|
from typing import Literal
|
|
|
|
from pydantic import Field
|
|
|
|
from .llm_services import StrictSchema
|
|
|
|
CHAT_INTENT_REGISTRY_VERSION = "1"
|
|
|
|
|
|
class ChatIntent(StrEnum):
|
|
PROVIDE_FACTS = "provide_facts"
|
|
NEW_ENTRY = "new_entry"
|
|
EDIT_ENTRY = "edit_entry"
|
|
EDIT_IDENTITY = "edit_identity"
|
|
REVISE_PROPOSAL = "revise_proposal"
|
|
NO_INFO = "no_info"
|
|
ASK_QUESTION = "ask_question"
|
|
CHITCHAT = "chitchat"
|
|
UNCLEAR = "unclear"
|
|
|
|
|
|
INTENT_DESCRIPTIONS: dict[ChatIntent, str] = {
|
|
ChatIntent.PROVIDE_FACTS: "在给当前草稿补充事实(含回答追问):动作、方法、工具、规模、结果等",
|
|
ChatIntent.NEW_ENTRY: "想新增另一段经历(教育/工作/实习/项目/校园),不是在改当前这段",
|
|
ChatIntent.EDIT_ENTRY: "想修改某段已确认写入简历的经历,可提到公司/学校/项目名",
|
|
ChatIntent.EDIT_IDENTITY: "想改当前这段的基础信息:学校、公司、职位、时间等",
|
|
ChatIntent.REVISE_PROPOSAL: "对当前候选优化稿的调整指令:保留原文、不要跳过、再专业一点等",
|
|
ChatIntent.NO_INFO: "明确表示没有、无、暂无,是对追问的否定回答",
|
|
ChatIntent.ASK_QUESTION: "在提问:关于简历怎么写、流程、建议等;不是在提供事实",
|
|
ChatIntent.CHITCHAT: "寒暄、感谢、好的、可以等纯应答,不含新事实",
|
|
ChatIntent.UNCLEAR: "无法判断意图,需要向用户澄清",
|
|
}
|
|
|
|
INTENT_FEWSHOTS: tuple[dict[str, object], ...] = (
|
|
{"message": "负责后端接口开发,使用 Python 和 FastAPI,覆盖 3 个业务流程", "intent": ChatIntent.PROVIDE_FACTS},
|
|
{"message": "新增一段教育经历", "intent": ChatIntent.NEW_ENTRY},
|
|
{"message": "修改一下我之前写的那个 AI Career Copilot 项目经历", "intent": ChatIntent.EDIT_ENTRY},
|
|
{"message": "把学校名字改成东莞城市学院", "intent": ChatIntent.EDIT_IDENTITY},
|
|
{"message": "保留原文,不要用这版优化稿", "intent": ChatIntent.REVISE_PROPOSAL},
|
|
{"message": "没有", "intent": ChatIntent.NO_INFO},
|
|
{"message": "这段经历你觉得怎么写比较好?", "intent": ChatIntent.ASK_QUESTION},
|
|
{"message": "好的,谢谢", "intent": ChatIntent.CHITCHAT},
|
|
{"message": "嗯……那个嘛", "intent": ChatIntent.UNCLEAR},
|
|
)
|
|
|
|
|
|
class ExtractedFact(StrictSchema):
|
|
"""One atomic fact copied or tightly paraphrased from the user's own message."""
|
|
|
|
text: str
|
|
kind: Literal["action", "method", "tool", "scale", "result", "other"] = "other"
|
|
|
|
|
|
class ChatTurnClassification(StrictSchema):
|
|
"""Structured output of the chat intent classifier (one call per message)."""
|
|
|
|
intent: ChatIntent
|
|
confidence: float = Field(default=0.5, ge=0, le=1)
|
|
target_section: str | None = None
|
|
target_entry_hint: str | None = None
|
|
facts: list[ExtractedFact] = Field(default_factory=list)
|
|
identity_updates: dict[str, str] | None = None
|
|
revision_instruction: str | None = None
|
|
user_question: str | None = None
|
|
reason: str = ""
|