Files
cad-agent/dwg_review/evidence_model.py
T

107 lines
3.6 KiB
Python
Raw Normal View History

"""统一证据模型:多来源(CAD / PDF / 图片)证据的字段常量与访问器。
设计要点:
- evidence 是跨阶段 + 落盘的「线格式」数据,统一用 dict 承载(不用 dataclass)。
- 图片统一为 `images: [{"b64","mime","label"}]`;访问器兼容旧的 `image_b64/image_mime`
单图字段(历史 evidence.json 与旧测试构造仍可读)。
- 本模块不含任何 CAD / 工具逻辑,可被 phases、findings、__main__、tests 共同引用。
"""
SOURCE_CAD = "cad"
SOURCE_PDF = "pdf"
SOURCE_IMAGE = "image"
# 结构化证据键(CAD 侧各查询工具产出的信封);下游 handle 收集 / 派生检查统一引用,
# 避免在多处硬编码同一组键名。
STRUCTURED_SOURCES = ("entities", "texts", "dimensions", "blocks", "polylines")
def empty_envelope(total=0):
"""构造空的**结构化信封** `{"total": N, "items": []}`。
CAD 侧各查询工具统一返回此形(`items` 明细 + `total` 计数)。非 CAD 源
(PDF / 图片)没有结构化数据,用本工厂补齐同形键,使下游 handle 收集 /
派生检查无需分支即可统一遍历(空 items 自然不产出任何检查项)。
"""
return {"total": int(total), "items": []}
def make_image(b64, mime="image/png", label=None, window=None):
"""构造 images 列表元素。
`window` 为该截图**实际可见的世界范围** `(min_x,min_y,max_x,max_y)`(可选)。
审查阶段的 `inspect_region` 靠它把「截图上的归一化坐标」映射回 WCS(逐级下钻)。
"""
img = {"b64": b64, "mime": mime or "image/png", "label": label}
if window is not None:
img["window"] = window
return img
def source_type_of(container):
"""读取来源类型,缺省视为 CAD。
container 可以是审查单元(unit)/ 图框 / evidence 等任何 dict。
"""
if isinstance(container, dict):
value = container.get("source_type")
if isinstance(value, str) and value:
return value
return SOURCE_CAD
def evidence_images(evidence):
"""规范化证据里的图片列表(单点归一)。
优先读 `images`;否则回退旧的 `image_b64` / `image_mime` 单图字段。
统一返回 `[{"b64","mime","label","window"}]`,过滤掉空 b64。
"""
if not isinstance(evidence, dict):
return []
images = []
raw = evidence.get("images")
if isinstance(raw, list):
for item in raw:
if not isinstance(item, dict):
continue
b64 = item.get("b64")
if not b64:
continue
images.append(
{
"b64": b64,
"mime": item.get("mime") or "image/png",
"label": item.get("label"),
"window": item.get("window"),
}
)
if images:
return images
# 回退:旧的单图字段
b64 = evidence.get("image_b64")
if b64:
return [
{
"b64": b64,
"mime": evidence.get("image_mime") or "image/png",
"label": None,
"window": None,
}
]
return []
def primary_image(evidence):
"""返回首图(label == "overall" 优先),无图返回 None。"""
images = evidence_images(evidence)
if not images:
return None
for img in images:
if img.get("label") == "overall":
return img
return images[0]
def image_labels(evidence):
"""返回图片标签列表(用于日志 / payload 说明)。"""
return [img.get("label") for img in evidence_images(evidence)]