Update project and configurations

This commit is contained in:
Zou-Seay
2026-06-11 16:28:00 +08:00
parent 12d3922091
commit a29a91867d
237 changed files with 164880 additions and 90 deletions

View File

@@ -0,0 +1 @@
"""Pydantic schemas for the agent service."""

View File

@@ -0,0 +1,46 @@
from __future__ import annotations
from typing import Any, Literal
from pydantic import BaseModel, Field
from app.schemas.debug import RoutingDebug
from app.schemas.workflow import Workflow
class ChatRequest(BaseModel):
session_id: str
user_id: str
channel: str = "app"
input_text: str
input_type: Literal["text", "voice"] = "text"
metadata: dict[str, Any] = Field(default_factory=dict)
class FillSlotsRequest(BaseModel):
session_id: str
user_id: str
input_text: str
class ChatResponse(BaseModel):
session_id: str
reply_type: Literal["text", "ask_slot", "ask_confirmation", "workflow_result", "fallback", "clarify", "reject"] = "text"
reply_text: str
intent: str | None = None
domain: str | None = None
decision: str | None = None
decision_reason: str | None = None
status: str
pending_slots: list[str] = Field(default_factory=list)
filled_slots: dict[str, Any] = Field(default_factory=dict)
workflow: Workflow | None = None
routing_debug: RoutingDebug | None = None
first_response_latency_ms: float | None = None
total_latency_ms: float | None = None
processing_breakdown: dict[str, float] = Field(default_factory=dict)
trace_id: str
# ── 知识库查询结果LLM function call 命中时填充)──────────────────────────
knowledge_doc_id: str | None = None # 知识文档 IDMD 文件名)
knowledge_doc_title: str | None = None # 知识文档标题
knowledge_content: str | None = None # 完整 MD 正文,供前端渲染知识卡片

View File

@@ -0,0 +1,135 @@
from __future__ import annotations
from typing import Any, Literal
from pydantic import BaseModel, Field
from app.schemas.intent import IntentDefinition
class ActionDefinition(BaseModel):
action_id: str
plugin_id: str
risk_level: Literal["low", "medium", "high"] = "low"
metadata: dict[str, Any] = Field(default_factory=dict)
class DomainIntentDefinition(BaseModel):
intent_id: str
domain: str
action_id: str | None = None
plugin_id: str | None = None
risk_level: Literal["low", "medium", "high"] | None = None
label: str | None = None
required_slots: list[str] = Field(default_factory=list)
ask_templates: dict[str, str] = Field(default_factory=dict)
keywords: list[str] = Field(default_factory=list)
examples: list[str] = Field(default_factory=list)
def to_intent_definition(self, actions: dict[str, ActionDefinition]) -> IntentDefinition:
plugin_id = self.plugin_id
risk_level = self.risk_level
if self.action_id:
action = actions[self.action_id]
plugin_id = action.plugin_id
if risk_level is None:
risk_level = action.risk_level
if not plugin_id:
raise ValueError(f"intent {self.intent_id} is missing plugin_id/action_id mapping")
return IntentDefinition(
intent_id=self.intent_id,
plugin_id=plugin_id,
domain=self.domain,
risk_level=risk_level or "low",
required_slots=self.required_slots,
ask_templates=self.ask_templates,
keywords=self.keywords,
examples=self.examples,
)
class DomainConfig(BaseModel):
intents: list[DomainIntentDefinition] = Field(default_factory=list)
class ActionsConfig(BaseModel):
actions: list[ActionDefinition] = Field(default_factory=list)
class ResponsesConfig(BaseModel):
templates: dict[str, str] = Field(default_factory=dict)
class FormDefinition(BaseModel):
intent_id: str
required_slots: list[str] = Field(default_factory=list)
ask_templates: dict[str, str] = Field(default_factory=dict)
class FormsConfig(BaseModel):
forms: list[FormDefinition] = Field(default_factory=list)
class ConfirmationRuleConfig(BaseModel):
positive_tokens: list[str] = Field(default_factory=list)
negative_tokens: list[str] = Field(default_factory=list)
required_intents: list[str] = Field(default_factory=list)
required_risk_levels: list[Literal["low", "medium", "high"]] = Field(default_factory=list)
class StopRuleConfig(BaseModel):
phrases: list[str] = Field(default_factory=list)
class DialogRulesConfig(BaseModel):
stop: StopRuleConfig = Field(default_factory=StopRuleConfig)
confirmation: ConfirmationRuleConfig = Field(default_factory=ConfirmationRuleConfig)
class DialogActPatternDefinition(BaseModel):
act_id: str
phrases: list[str] = Field(default_factory=list)
# 正则列表:文本匹配任意一个则命中该 act用于数字类 inform
numeric_patterns: list[str] = Field(default_factory=list)
class DialogActsConfig(BaseModel):
acts: list[DialogActPatternDefinition] = Field(default_factory=list)
# ── Context Rewrite Config ────────────────────────────────────────────────────
class ParamContextDefinition(BaseModel):
"""一类可相对调节参数的上下文改写规则。"""
intent_ids: list[str]
slot_name: str
unit: str = ""
step: int | float = 1
min_value: int | float = 0
max_value: int | float = 9999
default_value: int | float = 0
up_phrases: list[str] = Field(default_factory=list)
down_phrases: list[str] = Field(default_factory=list)
rewrite_template: str = "{value}"
class ContextRewriteConfig(BaseModel):
param_contexts: list[ParamContextDefinition] = Field(default_factory=list)
class WorkflowTemplateStepOverride(BaseModel):
depends_on: list[int] = Field(default_factory=list)
condition: dict[str, Any] = Field(default_factory=dict)
requires_confirmation: bool = False
class WorkflowTemplateDefinition(BaseModel):
template_id: str
workflow_type: Literal["sequence", "conditional", "parallel"] = "sequence"
intent_sequence: list[str] = Field(default_factory=list)
step_overrides: list[WorkflowTemplateStepOverride] = Field(default_factory=list)
trigger_keywords: list[str] = Field(default_factory=list)
class WorkflowTemplatesConfig(BaseModel):
templates: list[WorkflowTemplateDefinition] = Field(default_factory=list)

View File

@@ -0,0 +1,42 @@
from __future__ import annotations
from typing import Any
from pydantic import BaseModel, Field
class IntentCandidate(BaseModel):
intent_id: str
score: float = 0.0
reason: str | None = None
model_name: str | None = None
raw_label: str | None = None
metadata: dict[str, Any] = Field(default_factory=dict)
class MatcherStageDebug(BaseModel):
stage: str
accepted: bool = False
selected_intent: str | None = None
score: float = 0.0
elapsed_ms: float | None = None
reason: str | None = None
model_name: str | None = None
backend: str | None = None
fallback_used: bool = False
raw_label: str | None = None
error_message: str | None = None
metadata: dict[str, Any] = Field(default_factory=dict)
candidates: list[IntentCandidate] = Field(default_factory=list)
class RoutingDebug(BaseModel):
selected_intent: str | None = None
matched_stage: str | None = None
decision: str = "reject"
decision_reason: str | None = None
confidence_grade: str | None = None
total_match_latency_ms: float | None = None
unknown_detected: bool = False
extracted_slots: dict[str, Any] = Field(default_factory=dict)
stages: list[MatcherStageDebug] = Field(default_factory=list)

View File

@@ -0,0 +1,20 @@
from __future__ import annotations
from typing import Literal
from pydantic import BaseModel, Field
class DemoRuntimeConfig(BaseModel):
matcher_pipeline: Literal["classifier"]
classifier_backend: Literal["mock", "bert", "remote", "joint_bert"]
session_backend: Literal["memory", "redis"]
slot_extractor_backend: str
planner_backend: str
planner_model_name: str
class DemoRuntimeUpdateRequest(BaseModel):
matcher_pipeline: Literal["classifier"] = Field(default="classifier")
classifier_backend: Literal["mock", "bert", "remote", "joint_bert"]
session_backend: Literal["memory", "redis"]

View File

@@ -0,0 +1,16 @@
from __future__ import annotations
from typing import Literal
from pydantic import BaseModel, Field
class IntentDefinition(BaseModel):
intent_id: str
plugin_id: str
domain: str
risk_level: Literal["low", "medium", "high"] = "low"
required_slots: list[str] = Field(default_factory=list)
ask_templates: dict[str, str] = Field(default_factory=dict)
keywords: list[str] = Field(default_factory=list)
examples: list[str] = Field(default_factory=list)

View File

@@ -0,0 +1,38 @@
from __future__ import annotations
from typing import Any, Literal
from pydantic import BaseModel, Field
class WorkflowStep(BaseModel):
step: int
step_id: str
intent_id: str
plugin_id: str
action: str
status: Literal["pending", "running", "completed", "failed", "skipped", "waiting_confirmation"] = "pending"
depends_on: list[str] = Field(default_factory=list)
slots: dict[str, Any] = Field(default_factory=dict)
condition: dict[str, Any] = Field(default_factory=dict)
requires_confirmation: bool = False
timeout_ms: int = 1500
class MissingSlot(BaseModel):
slot_name: str
ask_template: str
priority: int = 1
class Workflow(BaseModel):
workflow_id: str
workflow_type: Literal["single", "sequence", "conditional", "parallel"] = "single"
domain: str
intent_id: str
status: Literal["ready", "waiting_slot", "waiting_confirmation", "running", "completed", "failed"] = "ready"
risk_level: Literal["low", "medium", "high"] = "low"
slots: dict[str, Any] = Field(default_factory=dict)
missing_slots: list[MissingSlot] = Field(default_factory=list)
steps: list[WorkflowStep] = Field(default_factory=list)
meta: dict[str, Any] = Field(default_factory=dict)