business_models.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. """业务输入附件及平台结果的公共契约,不绑定特定研判业务。"""
  2. from typing import Any, Literal
  3. from pydantic import BaseModel, ConfigDict, Field, model_validator
  4. from runtime.result_models import PlatformResultPayload
  5. class RemoteFile(BaseModel):
  6. model_config = ConfigDict(extra="forbid")
  7. file_id: str = Field(min_length=1, max_length=128)
  8. version: str = Field(min_length=1, max_length=128)
  9. filename: str = Field(min_length=1, max_length=255)
  10. path: str = Field(min_length=1, description="文件系统内相对接口路径,以 / 开头")
  11. params: dict[str, Any] = Field(default_factory=dict)
  12. class Clue(BaseModel):
  13. model_config = ConfigDict(extra="forbid", populate_by_name=True)
  14. clue_type: Literal["text", "table", "image", "file", "video", "curve"] = Field(alias="clueType")
  15. clue_name: str = Field(default="", alias="clueName")
  16. clue_content: str = Field(default="", alias="clueContent")
  17. class ResultArtifact(BaseModel):
  18. model_config = ConfigDict(extra="forbid")
  19. filename: str = Field(min_length=1, max_length=255)
  20. path: str = Field(pattern=r"^/workspace/", max_length=1024,
  21. description="本次会话中由业务工具生成的文件路径")
  22. class JudgmentResult(BaseModel):
  23. model_config = ConfigDict(extra="forbid")
  24. status: Literal["completed", "needs_materials", "not_implemented"]
  25. mine_code: str = ""
  26. mine_name: str = ""
  27. check_object: str = Field(min_length=1)
  28. result_title: str = Field(min_length=1)
  29. result: str = Field(min_length=1)
  30. check_process: str = ""
  31. alarm_level: Literal["红", "橙", "黄", "蓝"] | None = None
  32. missing_materials: list[str] = Field(default_factory=list)
  33. clues: list[Clue] = Field(default_factory=list)
  34. artifacts: list[ResultArtifact] = Field(default_factory=list, max_length=30)
  35. platform_payload: PlatformResultPayload | None = None
  36. @model_validator(mode="after")
  37. def completed_identity(self):
  38. if any(not getattr(self, key).strip() for key in ("check_object", "result_title", "result")):
  39. raise ValueError("研判对象、标题和结论不能仅为空白")
  40. if self.status == "completed" and (not self.mine_code.strip() or not self.mine_name.strip()):
  41. raise ValueError("正式结果必须具有矿井编码和名称")
  42. return self
  43. def platform_result(value: dict[str, Any]) -> JudgmentResult:
  44. """保留业务专有结果供审计,平台映射只取公共契约字段。"""
  45. return JudgmentResult.model_validate({key: item for key, item in value.items()
  46. if key in JudgmentResult.model_fields})