feat: extend MetadataFieldDefinition with field_roles and add SlotDefinition model [AC-MRS-01,02,03,07,08]

This commit is contained in:
MerCry 2026-03-05 17:10:09 +08:00
parent 5ded0c5f75
commit d534b4ef32
1 changed files with 301 additions and 2 deletions

View File

@ -110,6 +110,33 @@ class ChatMessageCreate(SQLModel):
content: str
class SharedSession(SQLModel, table=True):
"""
[AC-IDMP-SHARE] Shared session entity for dialogue sharing.
Allows sharing chat sessions via unique token with expiration and concurrent user limits.
"""
__tablename__ = "shared_sessions"
__table_args__ = (
Index("ix_shared_sessions_share_token", "share_token", unique=True),
Index("ix_shared_sessions_tenant_session", "tenant_id", "session_id"),
Index("ix_shared_sessions_expires_at", "expires_at"),
)
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
share_token: str = Field(..., description="Unique share token (UUID)", index=True)
session_id: str = Field(..., description="Associated session ID", index=True)
tenant_id: str = Field(..., description="Tenant ID for multi-tenant isolation", index=True)
title: str | None = Field(default=None, description="Share title")
description: str | None = Field(default=None, description="Share description")
expires_at: datetime = Field(..., description="Expiration time")
is_active: bool = Field(default=True, description="Whether share is active")
max_concurrent_users: int = Field(default=10, description="Maximum concurrent users allowed")
current_users: int = Field(default=0, description="Current number of online users")
created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation time")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="Last update time")
class DocumentStatus(str, Enum):
PENDING = "pending"
PROCESSING = "processing"
@ -956,6 +983,17 @@ class MetadataFieldType(str, Enum):
ARRAY_ENUM = "array_enum"
class FieldRole(str, Enum):
"""
[AC-MRS-01] 字段角色枚举
用于标识元数据字段的职责分层
"""
RESOURCE_FILTER = "resource_filter"
SLOT = "slot"
PROMPT_VAR = "prompt_var"
ROUTING_SIGNAL = "routing_signal"
class MetadataFieldStatus(str, Enum):
"""[AC-IDSMETA-13] 元数据字段状态"""
DRAFT = "draft"
@ -992,6 +1030,7 @@ class MetadataField(SQLModel):
class MetadataFieldDefinition(SQLModel, table=True):
"""
[AC-IDSMETA-13] 元数据字段定义表
[AC-MRS-01,02,03] 支持字段角色分层配置
每个字段独立存储支持字段级状态管理draft/active/deprecated
"""
@ -1029,6 +1068,11 @@ class MetadataFieldDefinition(SQLModel, table=True):
)
is_filterable: bool = Field(default=True, description="是否可用于过滤")
is_rank_feature: bool = Field(default=False, description="是否用于排序特征")
field_roles: list[str] = Field(
default_factory=list,
sa_column=Column("field_roles", JSON, nullable=False, server_default="'[]'"),
description="[AC-MRS-01] 字段角色列表: resource_filter/slot/prompt_var/routing_signal"
)
status: str = Field(
default=MetadataFieldStatus.DRAFT.value,
description="字段状态: draft/active/deprecated"
@ -1039,7 +1083,7 @@ class MetadataFieldDefinition(SQLModel, table=True):
class MetadataFieldDefinitionCreate(SQLModel):
"""[AC-IDSMETA-13] 创建元数据字段定义"""
"""[AC-IDSMETA-13] [AC-MRS-01] 创建元数据字段定义"""
field_key: str = Field(..., min_length=1, max_length=64)
label: str = Field(..., min_length=1, max_length=64)
@ -1050,11 +1094,12 @@ class MetadataFieldDefinitionCreate(SQLModel):
scope: list[str] = Field(default_factory=lambda: [MetadataScope.KB_DOCUMENT.value])
is_filterable: bool = Field(default=True)
is_rank_feature: bool = Field(default=False)
field_roles: list[str] = Field(default_factory=list)
status: str = Field(default=MetadataFieldStatus.DRAFT.value)
class MetadataFieldDefinitionUpdate(SQLModel):
"""[AC-IDSMETA-14] 更新元数据字段定义"""
"""[AC-IDSMETA-14] [AC-MRS-01] 更新元数据字段定义"""
label: str | None = Field(default=None, min_length=1, max_length=64)
required: bool | None = None
@ -1063,9 +1108,129 @@ class MetadataFieldDefinitionUpdate(SQLModel):
scope: list[str] | None = None
is_filterable: bool | None = None
is_rank_feature: bool | None = None
field_roles: list[str] | None = None
status: str | None = None
class ExtractStrategy(str, Enum):
"""
[AC-MRS-07] 槽位值提取策略
"""
RULE = "rule"
LLM = "llm"
USER_INPUT = "user_input"
class SlotValueSource(str, Enum):
"""
[AC-MRS-09] 槽位值来源
"""
USER_CONFIRMED = "user_confirmed"
RULE_EXTRACTED = "rule_extracted"
LLM_INFERRED = "llm_inferred"
DEFAULT = "default"
class SlotDefinition(SQLModel, table=True):
"""
[AC-MRS-07,08] 槽位定义表
独立的槽位定义模型与元数据字段解耦但可复用
"""
__tablename__ = "slot_definitions"
__table_args__ = (
Index("ix_slot_definitions_tenant", "tenant_id"),
Index("ix_slot_definitions_tenant_key", "tenant_id", "slot_key", unique=True),
Index("ix_slot_definitions_linked_field", "linked_field_id"),
)
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
tenant_id: str = Field(..., description="Tenant ID for multi-tenant isolation", index=True)
slot_key: str = Field(
...,
description="槽位键名,可与元数据字段 field_key 关联",
min_length=1,
max_length=100,
)
type: str = Field(
default=MetadataFieldType.STRING.value,
description="槽位类型: string/number/boolean/enum/array_enum"
)
required: bool = Field(default=False, description="是否必填槽位")
extract_strategy: str | None = Field(
default=None,
description="提取策略: rule/llm/user_input"
)
validation_rule: str | None = Field(
default=None,
description="校验规则(正则或 JSON Schema"
)
ask_back_prompt: str | None = Field(
default=None,
description="追问提示语模板"
)
default_value: dict[str, Any] | None = Field(
default=None,
sa_column=Column("default_value", JSON, nullable=True),
description="默认值"
)
linked_field_id: uuid.UUID | None = Field(
default=None,
description="关联的元数据字段 ID",
foreign_key="metadata_field_definitions.id",
)
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="更新时间")
class SlotDefinitionCreate(SQLModel):
"""[AC-MRS-07,08] 创建槽位定义"""
slot_key: str = Field(..., min_length=1, max_length=100)
type: str = Field(default=MetadataFieldType.STRING.value)
required: bool = Field(default=False)
extract_strategy: str | None = None
validation_rule: str | None = None
ask_back_prompt: str | None = None
default_value: dict[str, Any] | None = None
linked_field_id: str | None = None
class SlotDefinitionUpdate(SQLModel):
"""[AC-MRS-07] 更新槽位定义"""
type: str | None = None
required: bool | None = None
extract_strategy: str | None = None
validation_rule: str | None = None
ask_back_prompt: str | None = None
default_value: dict[str, Any] | None = None
linked_field_id: str | None = None
class SlotValue(SQLModel):
"""
[AC-MRS-09] 运行时槽位值
"""
key: str = Field(..., description="槽位键名")
value: Any = Field(..., description="槽位值")
source: str = Field(
default=SlotValueSource.DEFAULT.value,
description="来源: user_confirmed/rule_extracted/llm_inferred/default"
)
confidence: float = Field(
default=1.0,
ge=0.0,
le=1.0,
description="置信度 0.0~1.0"
)
updated_at: datetime = Field(
default_factory=datetime.utcnow,
description="最后更新时间"
)
class MetadataSchema(SQLModel, table=True):
"""
元数据模式定义保留兼容性
@ -1213,3 +1378,137 @@ class DecompositionResult(SQLModel):
confidence: float | None = Field(default=None, description="拆解置信度")
error: str | None = Field(default=None, description="错误信息")
latency_ms: int | None = Field(default=None, description="处理耗时(毫秒)")
class HighRiskScenarioType(str, Enum):
"""[AC-IDMP-20] 高风险场景类型"""
REFUND = "refund"
COMPLAINT_ESCALATION = "complaint_escalation"
PRIVACY_SENSITIVE_PROMISE = "privacy_sensitive_promise"
TRANSFER = "transfer"
class HighRiskPolicy(SQLModel, table=True):
"""
[AC-IDMP-20] 高风险场景策略配置
定义高风险场景的最小集支持动态配置
"""
__tablename__ = "high_risk_policies"
__table_args__ = (
Index("ix_high_risk_policies_tenant", "tenant_id"),
Index("ix_high_risk_policies_tenant_enabled", "tenant_id", "is_enabled"),
)
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
tenant_id: str = Field(..., description="Tenant ID for multi-tenant isolation", index=True)
scenario: str = Field(..., description="场景类型: refund/complaint_escalation/privacy_sensitive_promise/transfer")
handler_mode: str = Field(
default="micro_flow",
description="处理模式: micro_flow/transfer"
)
flow_id: uuid.UUID | None = Field(
default=None,
description="微流程ID (handler_mode=micro_flow时使用)",
foreign_key="script_flows.id"
)
transfer_message: str | None = Field(
default=None,
description="转人工消息 (handler_mode=transfer时使用)"
)
keywords: list[str] | None = Field(
default=None,
sa_column=Column("keywords", JSON, nullable=True),
description="触发关键词列表"
)
patterns: list[str] | None = Field(
default=None,
sa_column=Column("patterns", JSON, nullable=True),
description="触发正则模式列表"
)
priority: int = Field(default=0, description="优先级 (值越高优先级越高)")
is_enabled: bool = Field(default=True, description="是否启用")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="更新时间")
class HighRiskPolicyCreate(SQLModel):
"""[AC-IDMP-20] 创建高风险策略"""
scenario: str
handler_mode: str = "micro_flow"
flow_id: str | None = None
transfer_message: str | None = None
keywords: list[str] | None = None
patterns: list[str] | None = None
priority: int = 0
class HighRiskPolicyUpdate(SQLModel):
"""[AC-IDMP-20] 更新高风险策略"""
handler_mode: str | None = None
flow_id: str | None = None
transfer_message: str | None = None
keywords: list[str] | None = None
patterns: list[str] | None = None
priority: int | None = None
is_enabled: bool | None = None
class SessionModeRecord(SQLModel, table=True):
"""
[AC-IDMP-09] 会话模式记录
记录会话的当前模式状态
"""
__tablename__ = "session_mode_records"
__table_args__ = (
Index("ix_session_mode_records_tenant_session", "tenant_id", "session_id", unique=True),
)
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
tenant_id: str = Field(..., description="Tenant ID for multi-tenant isolation", index=True)
session_id: str = Field(..., description="会话ID", index=True)
mode: str = Field(
default="BOT_ACTIVE",
description="会话模式: BOT_ACTIVE/HUMAN_ACTIVE"
)
reason: str | None = Field(default=None, description="模式切换原因")
switched_at: datetime | None = Field(default=None, description="模式切换时间")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="更新时间")
class MidAuditLog(SQLModel, table=True):
"""
[AC-IDMP-07] 中台审计日志
记录 generation/request 维度的审计字段
"""
__tablename__ = "mid_audit_logs"
__table_args__ = (
Index("ix_mid_audit_logs_tenant_session", "tenant_id", "session_id"),
Index("ix_mid_audit_logs_tenant_request", "tenant_id", "request_id"),
Index("ix_mid_audit_logs_tenant_generation", "tenant_id", "generation_id"),
Index("ix_mid_audit_logs_created", "created_at"),
)
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
tenant_id: str = Field(..., description="Tenant ID for multi-tenant isolation", index=True)
session_id: str = Field(..., description="会话ID", index=True)
request_id: str = Field(..., description="请求ID", index=True)
generation_id: str = Field(..., description="生成ID", index=True)
mode: str = Field(..., description="执行模式: agent/micro_flow/fixed/transfer")
intent: str | None = Field(default=None, description="意图")
tool_calls: list[dict[str, Any]] | None = Field(
default=None,
sa_column=Column("tool_calls", JSON, nullable=True),
description="工具调用记录"
)
guardrail_triggered: bool = Field(default=False, description="护栏是否触发")
fallback_reason_code: str | None = Field(default=None, description="降级原因码")
react_iterations: int | None = Field(default=None, description="ReAct循环次数")
high_risk_scenario: str | None = Field(default=None, description="触发的高风险场景")
latency_ms: int | None = Field(default=None, description="总耗时(ms)")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间", index=True)