Initial commit

This commit is contained in:
2026-09-04 14:58:42 +08:00
commit 439cad87d9
4601 changed files with 29440 additions and 0 deletions
+134
View File
@@ -0,0 +1,134 @@
"""领域模型。"""
from __future__ import annotations
from dataclasses import asdict, dataclass
from typing import Any
DIMENSIONS = (
"Clarity",
"Structure",
"Executability",
"Completeness",
"Constraint Salience",
)
@dataclass
class SkillUnit:
unit_id: str
level: str
parent_id: str | None
heading: str
text: str
order: int
start: int
end: int
heading_depth: int | None = None
@dataclass
class CellScore:
score: float
evidence: list[str]
reason: str
@dataclass
class Coordinate:
unit_id: str
dimension: str
normalized_gap: float
@dataclass
class LocalEdit:
unit_id: str
dimension: str
new_text: str
edit_summary: str
reason: str
@classmethod
def from_dict(cls, value: dict[str, Any]) -> "LocalEdit":
required = {"unit_id", "dimension", "new_text", "edit_summary", "reason"}
missing = sorted(required - value.keys())
if missing:
raise ValueError(f"local edit missing fields: {', '.join(missing)}")
if not all(isinstance(value[key], str) for key in required):
raise ValueError("local edit fields must be strings")
return cls(**{key: value[key] for key in cls.__dataclass_fields__})
@dataclass
class ScoreMatrix:
level: str
units: list[SkillUnit]
columns: dict[str, dict[str, CellScore]]
def to_dict(self) -> dict[str, Any]:
return {
"level": self.level,
"units": [asdict(unit) for unit in self.units],
"columns": {
dimension: {unit_id: asdict(cell) for unit_id, cell in column.items()}
for dimension, column in self.columns.items()
},
}
@classmethod
def from_dict(cls, value: dict[str, Any]) -> "ScoreMatrix":
return cls(
level=str(value["level"]),
units=[SkillUnit(**item) for item in value["units"]],
columns={
dimension: {
unit_id: CellScore(float(cell["score"]), list(cell["evidence"]), str(cell["reason"]))
for unit_id, cell in column.items()
}
for dimension, column in value["columns"].items()
},
)
def unit(self, unit_id: str) -> SkillUnit:
return next(unit for unit in self.units if unit.unit_id == unit_id)
def normalized_gaps(self) -> dict[str, float]:
gaps: dict[str, float] = {}
for dimension in DIMENSIONS:
values = [self.columns[dimension][unit.unit_id].score for unit in self.units]
gaps[dimension] = (max(values) - min(values)) / 4.0 if values else 0.0
return gaps
def select_coordinate(
self,
threshold: float,
dimension: str | None = None,
excluded: set[tuple[str, str]] | None = None,
) -> Coordinate | None:
gaps = self.normalized_gaps()
excluded = excluded or set()
def weak_units(item: str) -> list[SkillUnit]:
column = self.columns[item]
maximum = max((cell.score for cell in column.values()), default=0.0)
return [
unit for unit in self.units
if (unit.unit_id, item) not in excluded
and (maximum - column[unit.unit_id].score) / 4.0 > threshold
]
available = [
item for item in ([dimension] if dimension else DIMENSIONS)
if item is not None and gaps[item] > threshold and weak_units(item)
]
if not available:
return None
dimension = max(available, key=lambda item: gaps[item])
target = min(
weak_units(dimension),
key=lambda unit: (self.columns[dimension][unit.unit_id].score, unit.order),
)
return Coordinate(
target.unit_id,
dimension,
gaps[dimension],
)