"""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 = ""