Files
my-v0-server/app/schemas/requirement.py
T

74 lines
3.5 KiB
Python

"""需求理解的输出协议,描述用户诉求,不包含前端执行动作。"""
from typing import Literal, Self
from pydantic import Field, model_validator
from .base import ExtensibleModel, JsonObject, NonBlankString
Intent = Literal["create_screen", "modify_screen", "qa", "unclear"]
TargetScope = Literal["nodes", "canvas", "screen", "unresolved"]
class RequirementChange(ExtensibleModel):
"""一项需求变更。目标范围显式声明,避免空 ID 被理解成修改整个大屏。"""
target_scope: TargetScope = Field(
description="nodes=已有节点;canvas=画布属性;screen=整体或新增内容;unresolved=目标待确认"
)
target_ids: list[NonBlankString] = Field(
default_factory=list, description="已有节点的 ID;新增组件不能虚构 ID"
)
target_description: NonBlankString | None = Field(
default=None, description="目标的自然语言描述,例如右侧区域、用户所说的那个图"
)
operation: NonBlankString = Field(
description="需求操作,例如 move、resize、add、delete、restyle;允许后续扩展"
)
parameters: JsonObject = Field(
default_factory=dict,
description="需求参数,例如 delta_x=50;保留用户要求的单位与相对变化语义",
)
@model_validator(mode="after")
def validate_target(self) -> Self:
if len(self.target_ids) != len(set(self.target_ids)):
raise ValueError("target_ids 不能包含重复 ID")
if self.target_scope == "nodes":
if not self.target_ids:
raise ValueError("nodes 范围必须提供 target_ids")
elif self.target_ids:
raise ValueError("只有 nodes 范围可以提供 target_ids")
if self.target_scope == "unresolved" and self.target_description is None:
raise ValueError("目标待确认时必须提供 target_description")
return self
class Requirement(ExtensibleModel):
intent: Intent
goal: NonBlankString = Field(description="忠实概括用户目标,不能擅自扩大修改范围")
changes: list[RequirementChange] = Field(default_factory=list)
needs_clarification: bool
clarification_question: NonBlankString | None = None
needs_planning: bool = Field(description="是否需要布局或设计规划,与修改范围分别判断")
needs_resources: bool = Field(description="是否需要补充查询组件、数据、模板或素材")
assumptions: list[NonBlankString] = Field(
default_factory=list, description="非阻塞信息采用的默认假设,不可用来猜测删除目标"
)
constraints: list[NonBlankString] = Field(
default_factory=list, description="用户明确提出的约束,例如只修改右侧、保留其他组件"
)
@model_validator(mode="after")
def validate_consistency(self) -> Self:
if self.needs_clarification != (self.clarification_question is not None):
raise ValueError("需要澄清时必须提供问题,不需要澄清时问题应为 null")
if self.intent == "unclear" and not self.needs_clarification:
raise ValueError("意图不明确时必须澄清")
if any(change.target_scope == "unresolved" for change in self.changes):
if not self.needs_clarification:
raise ValueError("存在待确认目标时必须澄清")
if self.intent == "qa" and self.changes:
raise ValueError("纯问答需求不应包含大屏变更")
return self