refactor(backend): update data schemas
- schemas/orchestrator.py: update orchestrator schemas - schemas/settings.py: update settings schemas - schemas/user_agent.py: update user agent schemas
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
from typing import Any, Literal
|
from typing import Any, Literal
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
@@ -12,6 +13,7 @@ OrchestratorStatus = Literal["succeeded", "blocked", "failed"]
|
|||||||
class OrchestratorRequest(BaseModel):
|
class OrchestratorRequest(BaseModel):
|
||||||
source: OrchestratorSource = Field(description="请求来源。")
|
source: OrchestratorSource = Field(description="请求来源。")
|
||||||
user_id: str | None = Field(default=None, description="当前用户 ID,任务触发可为空。")
|
user_id: str | None = Field(default=None, description="当前用户 ID,任务触发可为空。")
|
||||||
|
conversation_id: str | None = Field(default=None, description="多轮对话会话 ID。")
|
||||||
message: str | None = Field(default=None, description="用户消息或任务描述。")
|
message: str | None = Field(default=None, description="用户消息或任务描述。")
|
||||||
task_id: str | None = Field(default=None, description="任务资产 ID,schedule 触发时优先使用。")
|
task_id: str | None = Field(default=None, description="任务资产 ID,schedule 触发时优先使用。")
|
||||||
context_json: dict[str, Any] = Field(
|
context_json: dict[str, Any] = Field(
|
||||||
@@ -34,6 +36,7 @@ class OrchestratorTraceSummary(BaseModel):
|
|||||||
|
|
||||||
class OrchestratorResponse(BaseModel):
|
class OrchestratorResponse(BaseModel):
|
||||||
run_id: str = Field(description="本次运行的唯一 run_id。")
|
run_id: str = Field(description="本次运行的唯一 run_id。")
|
||||||
|
conversation_id: str | None = Field(default=None, description="当前会话 ID。")
|
||||||
selected_agent: OrchestratorAgent | None = Field(
|
selected_agent: OrchestratorAgent | None = Field(
|
||||||
default=None,
|
default=None,
|
||||||
description="最终路由到的下游 Agent。",
|
description="最终路由到的下游 Agent。",
|
||||||
@@ -44,3 +47,37 @@ class OrchestratorResponse(BaseModel):
|
|||||||
result: dict[str, Any] = Field(default_factory=dict, description="对前端可直接展示的最小结果。")
|
result: dict[str, Any] = Field(default_factory=dict, description="对前端可直接展示的最小结果。")
|
||||||
requires_confirmation: bool = Field(default=False, description="是否需要用户或管理员确认。")
|
requires_confirmation: bool = Field(default=False, description="是否需要用户或管理员确认。")
|
||||||
trace_summary: OrchestratorTraceSummary = Field(description="简化后的 Trace 摘要。")
|
trace_summary: OrchestratorTraceSummary = Field(description="简化后的 Trace 摘要。")
|
||||||
|
|
||||||
|
|
||||||
|
class ConversationMessageRead(BaseModel):
|
||||||
|
id: str = Field(description="消息 ID。")
|
||||||
|
role: str = Field(description="消息角色。")
|
||||||
|
content: str = Field(description="消息正文。")
|
||||||
|
run_id: str | None = Field(default=None, description="关联运行 ID。")
|
||||||
|
message_json: dict[str, Any] = Field(default_factory=dict, description="扩展消息载荷。")
|
||||||
|
created_at: datetime | None = Field(default=None, description="消息创建时间。")
|
||||||
|
|
||||||
|
|
||||||
|
class ConversationRead(BaseModel):
|
||||||
|
conversation_id: str = Field(description="会话 ID。")
|
||||||
|
user_id: str | None = Field(default=None, description="所属用户 ID。")
|
||||||
|
source: str | None = Field(default=None, description="来源。")
|
||||||
|
entry_source: str | None = Field(default=None, description="入口来源。")
|
||||||
|
title: str | None = Field(default=None, description="会话标题。")
|
||||||
|
last_run_id: str | None = Field(default=None, description="最近一次运行 ID。")
|
||||||
|
last_scenario: str | None = Field(default=None, description="最近场景。")
|
||||||
|
last_intent: str | None = Field(default=None, description="最近意图。")
|
||||||
|
draft_claim_id: str | None = Field(default=None, description="关联草稿单 ID。")
|
||||||
|
state_json: dict[str, Any] = Field(default_factory=dict, description="会话状态。")
|
||||||
|
message_count: int = Field(default=0, ge=0, description="消息数量。")
|
||||||
|
updated_at: datetime | None = Field(default=None, description="更新时间。")
|
||||||
|
messages: list[ConversationMessageRead] = Field(default_factory=list, description="历史消息。")
|
||||||
|
|
||||||
|
|
||||||
|
class ConversationLookupResponse(BaseModel):
|
||||||
|
found: bool = Field(default=False, description="是否找到可恢复会话。")
|
||||||
|
conversation: ConversationRead | None = Field(default=None, description="会话详情。")
|
||||||
|
|
||||||
|
|
||||||
|
class ConversationDeleteResponse(BaseModel):
|
||||||
|
deleted_count: int = Field(default=0, ge=0, description="删除的会话数量。")
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ class SettingsAdminForm(BaseModel):
|
|||||||
return value.strip()
|
return value.strip()
|
||||||
|
|
||||||
|
|
||||||
|
class SettingsSessionForm(BaseModel):
|
||||||
|
conversationRetentionDays: int = Field(default=3, ge=1, le=10)
|
||||||
|
|
||||||
|
|
||||||
class SettingsLlmForm(BaseModel):
|
class SettingsLlmForm(BaseModel):
|
||||||
mainProvider: str = Field(min_length=1, max_length=64)
|
mainProvider: str = Field(min_length=1, max_length=64)
|
||||||
mainModel: str = Field(min_length=1, max_length=255)
|
mainModel: str = Field(min_length=1, max_length=255)
|
||||||
@@ -159,6 +163,7 @@ class SettingsMailForm(BaseModel):
|
|||||||
class SettingsRead(BaseModel):
|
class SettingsRead(BaseModel):
|
||||||
companyForm: SettingsCompanyForm
|
companyForm: SettingsCompanyForm
|
||||||
adminForm: SettingsAdminForm
|
adminForm: SettingsAdminForm
|
||||||
|
sessionForm: SettingsSessionForm
|
||||||
llmForm: SettingsLlmForm
|
llmForm: SettingsLlmForm
|
||||||
renderForm: SettingsRenderForm
|
renderForm: SettingsRenderForm
|
||||||
logForm: SettingsLogForm
|
logForm: SettingsLogForm
|
||||||
@@ -168,6 +173,7 @@ class SettingsRead(BaseModel):
|
|||||||
class SettingsWrite(BaseModel):
|
class SettingsWrite(BaseModel):
|
||||||
companyForm: SettingsCompanyForm
|
companyForm: SettingsCompanyForm
|
||||||
adminForm: SettingsAdminForm
|
adminForm: SettingsAdminForm
|
||||||
|
sessionForm: SettingsSessionForm
|
||||||
llmForm: SettingsLlmForm
|
llmForm: SettingsLlmForm
|
||||||
renderForm: SettingsRenderForm
|
renderForm: SettingsRenderForm
|
||||||
logForm: SettingsLogForm
|
logForm: SettingsLogForm
|
||||||
|
|||||||
@@ -34,6 +34,89 @@ class UserAgentDraftPayload(BaseModel):
|
|||||||
status: str | None = Field(default=None, description="当前报销草稿状态。")
|
status: str | None = Field(default=None, description="当前报销草稿状态。")
|
||||||
|
|
||||||
|
|
||||||
|
class UserAgentReviewRiskBrief(BaseModel):
|
||||||
|
title: str = Field(description="风险或注意事项标题。")
|
||||||
|
level: str = Field(default="info", description="级别,例如 info / warning / high。")
|
||||||
|
content: str = Field(description="面向用户展示的摘要说明。")
|
||||||
|
|
||||||
|
|
||||||
|
class UserAgentReviewSlotCard(BaseModel):
|
||||||
|
key: str = Field(description="槽位键名。")
|
||||||
|
label: str = Field(description="槽位展示名。")
|
||||||
|
value: str = Field(default="", description="当前识别值。")
|
||||||
|
source: str = Field(default="system", description="字段来源,例如 user_text / ocr / page_context。")
|
||||||
|
confidence: float = Field(default=0.0, ge=0.0, le=1.0, description="识别置信度。")
|
||||||
|
required: bool = Field(default=True, description="是否为关键字段。")
|
||||||
|
confirmed: bool = Field(default=False, description="是否可视为已确认。")
|
||||||
|
status: str = Field(default="identified", description="identified / inferred / missing。")
|
||||||
|
hint: str = Field(default="", description="字段补充提示。")
|
||||||
|
|
||||||
|
|
||||||
|
class UserAgentReviewDocumentField(BaseModel):
|
||||||
|
label: str = Field(description="字段名。")
|
||||||
|
value: str = Field(default="", description="字段值。")
|
||||||
|
source: str = Field(default="ocr", description="字段来源。")
|
||||||
|
|
||||||
|
|
||||||
|
class UserAgentReviewDocumentCard(BaseModel):
|
||||||
|
index: int = Field(description="票据顺序号,从 1 开始。")
|
||||||
|
filename: str = Field(description="原始文件名。")
|
||||||
|
document_type: str = Field(default="other", description="票据候选类型。")
|
||||||
|
suggested_expense_type: str = Field(default="other", description="建议归属费用类型。")
|
||||||
|
scene_label: str = Field(default="", description="面向用户展示的场景标签。")
|
||||||
|
summary: str = Field(default="", description="逐票据摘要。")
|
||||||
|
avg_score: float = Field(default=0.0, ge=0.0, le=1.0, description="OCR 平均得分。")
|
||||||
|
warnings: list[str] = Field(default_factory=list, description="该票据的识别提示。")
|
||||||
|
fields: list[UserAgentReviewDocumentField] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
description="逐票据关键字段。",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserAgentReviewClaimGroup(BaseModel):
|
||||||
|
group_code: str = Field(description="候选报销组编码。")
|
||||||
|
title: str = Field(description="候选报销组标题。")
|
||||||
|
expense_type: str = Field(description="归属费用类型编码。")
|
||||||
|
scene_label: str = Field(description="归属费用类型名称。")
|
||||||
|
document_indexes: list[int] = Field(default_factory=list, description="挂入该组的票据序号。")
|
||||||
|
amount_total: float = Field(default=0.0, ge=0.0, description="该组候选金额。")
|
||||||
|
rationale: str = Field(default="", description="为什么建议这样分组。")
|
||||||
|
|
||||||
|
|
||||||
|
class UserAgentReviewAction(BaseModel):
|
||||||
|
label: str = Field(description="动作名称。")
|
||||||
|
action_type: str = Field(description="动作类型。")
|
||||||
|
description: str = Field(default="", description="动作说明。")
|
||||||
|
emphasis: str = Field(default="secondary", description="primary / secondary / warning。")
|
||||||
|
|
||||||
|
|
||||||
|
class UserAgentReviewPayload(BaseModel):
|
||||||
|
intent_summary: str = Field(description="系统对本次报销意图的结构化摘要。")
|
||||||
|
scenario: str = Field(description="当前场景。")
|
||||||
|
intent: str = Field(description="当前意图。")
|
||||||
|
missing_slots: list[str] = Field(default_factory=list, description="当前仍缺失的关键槽位。")
|
||||||
|
risk_briefs: list[UserAgentReviewRiskBrief] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
description="历史风险和当前注意事项。",
|
||||||
|
)
|
||||||
|
slot_cards: list[UserAgentReviewSlotCard] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
description="待确认槽位卡片。",
|
||||||
|
)
|
||||||
|
document_cards: list[UserAgentReviewDocumentCard] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
description="逐票据识别卡片。",
|
||||||
|
)
|
||||||
|
claim_groups: list[UserAgentReviewClaimGroup] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
description="候选报销分单建议。",
|
||||||
|
)
|
||||||
|
confirmation_actions: list[UserAgentReviewAction] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
description="面向前端渲染的确认动作卡片。",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class UserAgentRequest(BaseModel):
|
class UserAgentRequest(BaseModel):
|
||||||
run_id: str = Field(description="关联的 AgentRun.run_id。")
|
run_id: str = Field(description="关联的 AgentRun.run_id。")
|
||||||
user_id: str | None = Field(default=None, description="当前请求用户 ID。")
|
user_id: str | None = Field(default=None, description="当前请求用户 ID。")
|
||||||
@@ -57,5 +140,9 @@ class UserAgentResponse(BaseModel):
|
|||||||
description="建议的下一步动作。",
|
description="建议的下一步动作。",
|
||||||
)
|
)
|
||||||
draft_payload: UserAgentDraftPayload | None = Field(default=None, description="可选草稿内容。")
|
draft_payload: UserAgentDraftPayload | None = Field(default=None, description="可选草稿内容。")
|
||||||
|
review_payload: UserAgentReviewPayload | None = Field(
|
||||||
|
default=None,
|
||||||
|
description="结构化预审结果,用于前端确认面板。",
|
||||||
|
)
|
||||||
risk_flags: list[str] = Field(default_factory=list, description="本次回答关联的风险标签。")
|
risk_flags: list[str] = Field(default_factory=list, description="本次回答关联的风险标签。")
|
||||||
requires_confirmation: bool = Field(default=False, description="是否需要人工确认。")
|
requires_confirmation: bool = Field(default=False, description="是否需要人工确认。")
|
||||||
|
|||||||
Reference in New Issue
Block a user