schemas.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Pydantic schemas for data_modules outputs.
  5. """
  6. from __future__ import annotations
  7. from typing import Any, Dict, List, Optional
  8. from pydantic import BaseModel, Field, ValidationError, ConfigDict
  9. class EntityAppeared(BaseModel):
  10. model_config = ConfigDict(extra="allow")
  11. id: str
  12. type: str
  13. mentions: List[str] = Field(default_factory=list)
  14. confidence: float = 1.0
  15. class EntityNew(BaseModel):
  16. model_config = ConfigDict(extra="allow")
  17. suggested_id: str
  18. name: str
  19. type: str
  20. tier: str = "装饰"
  21. class StateChange(BaseModel):
  22. model_config = ConfigDict(extra="allow")
  23. entity_id: str
  24. field: str
  25. old: Optional[str] = None
  26. new: str
  27. reason: Optional[str] = None
  28. class RelationshipNew(BaseModel):
  29. model_config = ConfigDict(extra="allow", populate_by_name=True)
  30. from_entity: str = Field(alias="from")
  31. to_entity: str = Field(alias="to")
  32. type: str
  33. description: Optional[str] = None
  34. chapter: Optional[int] = None
  35. class UncertainCandidate(BaseModel):
  36. model_config = ConfigDict(extra="allow")
  37. type: str
  38. id: str
  39. class UncertainMention(BaseModel):
  40. model_config = ConfigDict(extra="allow")
  41. mention: str
  42. candidates: List[UncertainCandidate] = Field(default_factory=list)
  43. confidence: float = 0.0
  44. adopted: Optional[str] = None
  45. class DataAgentOutput(BaseModel):
  46. model_config = ConfigDict(extra="allow")
  47. entities_appeared: List[EntityAppeared] = Field(default_factory=list)
  48. entities_new: List[EntityNew] = Field(default_factory=list)
  49. state_changes: List[StateChange] = Field(default_factory=list)
  50. relationships_new: List[RelationshipNew] = Field(default_factory=list)
  51. scenes_chunked: int = 0
  52. uncertain: List[UncertainMention] = Field(default_factory=list)
  53. warnings: List[str] = Field(default_factory=list)
  54. class ErrorSchema(BaseModel):
  55. model_config = ConfigDict(extra="allow")
  56. code: str
  57. message: str
  58. suggestion: Optional[str] = None
  59. details: Optional[Dict[str, Any]] = None
  60. def validate_data_agent_output(payload: Dict[str, Any]) -> DataAgentOutput:
  61. return DataAgentOutput.model_validate(payload)
  62. def format_validation_error(exc: ValidationError) -> Dict[str, Any]:
  63. return {
  64. "code": "SCHEMA_VALIDATION_FAILED",
  65. "message": "数据结构校验失败",
  66. "details": {"errors": exc.errors()},
  67. "suggestion": "请检查 data-agent 输出字段是否完整且类型正确",
  68. }
  69. def normalize_data_agent_output(payload: Dict[str, Any]) -> Dict[str, Any]:
  70. if not isinstance(payload, dict):
  71. return {}
  72. def _ensure_list(key: str):
  73. value = payload.get(key)
  74. if value is None:
  75. payload[key] = []
  76. elif isinstance(value, list):
  77. return
  78. else:
  79. payload[key] = [value]
  80. for key in [
  81. "entities_appeared",
  82. "entities_new",
  83. "state_changes",
  84. "relationships_new",
  85. "uncertain",
  86. "warnings",
  87. ]:
  88. _ensure_list(key)
  89. payload.setdefault("scenes_chunked", 0)
  90. return payload