aps-agent/tests/golden/test_drawing_process.py

130 lines
6.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ============================================================
# 图纸工艺/工序/细节识别黄金测试(R71.2 增强)
# 覆盖:合成文本识别、真实图纸标题栏/零件名、不误判比例、候选门禁。
# ============================================================
from __future__ import annotations
from pathlib import Path
from server.aps_domain.drawing_dxf import build_drawing_master_candidates, inspect_dxf
from server.aps_domain.drawing_process import (
recognize_process_candidates,
recognize_process_text,
)
from server.aps_domain.drawing_understanding import build_drawing_understanding
from tests.external_data import external_dir
_RUIYANG_DIR = external_dir("RUIYANG_DEMO_DIR", "ruiyang")
_DEFAULT_SAMPLE = _RUIYANG_DIR / "5060102101-001-e(1).dxf"
_SAMPLE_003 = _RUIYANG_DIR / "5060102101-003-e(1).dxf"
def _sample(path: Path) -> Path:
if not path.is_file():
import pytest
pytest.skip(f"real DXF fixture not available: {path}")
return path
def test_synthetic_process_and_detail_recognition():
parsed = {
"asset": {"sha256": "0" * 64},
"texts": [
{"text": "DREHEN Ø20 TOLERANZ ±0.01", "evidence": {"source": "drawingText", "page": 1}},
{"text": "OBERFLÄCHE Ra 3.2", "evidence": {"source": "drawingText", "page": 1}},
{"text": "M30x1.5 16 TIEF", "evidence": {"source": "drawingText", "page": 1}},
{"text": "MONTAGE", "evidence": {"source": "drawingText", "page": 1}},
{"text": "SCALE 1:5", "evidence": {"source": "drawingText", "page": 1}},
],
}
process = recognize_process_candidates(parsed)
codes = {row["processCode"] for row in process["operations"]}
assert {"TURNING", "ASSEMBLY", "THREADING"} <= codes
assert "SURFACE_TREATMENT" in codes
details = {row["field"]: row["value"] for row in process["details"]}
assert details["tolerance"] == "±0.01"
assert details["surfaceRoughness"] == "Ra 3.2"
assert details["threadSpecification"] == "M30x1.5"
assert details["depthMm"] == "16 TIEF"
assert "M1" not in [row["value"] for row in process["details"]]
def test_real_dxf_recognizes_process_and_details():
parsed = inspect_dxf(_sample(_DEFAULT_SAMPLE))
fields = {row["field"]: row["value"] for row in parsed["fieldCandidates"]}
assert fields.get("threadSpecification") in {"M10", "M12", "M6", "M18x1.5"}
assert "M1" not in [row["value"] for row in parsed["fieldCandidates"]]
change_set = build_drawing_master_candidates(parsed)
ops = change_set["routingOperations"]
assert any(row["operationCode"] != "ENGINEERING_REVIEW" for row in ops)
assert change_set["processDetails"]
assert "processBlocks" in change_set
assert "processAssemblies" in change_set
assert "processLocations" in change_set
assert "processSequenceSteps" in change_set
for row in ops:
assert row["reviewRequired"] is True
assert row["standardTime"] is None
assert row["resourceCode"] is None
assert row["evidence"]
def test_real_parts_list_extracts_assembly_thread_and_depth():
understanding = build_drawing_understanding(inspect_dxf(_sample(_SAMPLE_003)))
assert understanding["processCandidates"]
assert understanding["routingOperations"]
details = {row["field"]: row["value"] for row in understanding["processDetails"]}
assert details.get("threadSpecification")
assert details.get("depthMm")
assert any(row["processCode"] == "ASSEMBLY" for row in understanding["processCandidates"])
assert any(row["processCode"] == "THREADING" for row in understanding["processCandidates"])
_CHINESE_PROCESS_TEXT = """
烟囱(9005)分段分为首面围壁组立、尾面围壁组立、侧壁组立、顶板组立等。
2.1首、尾围壁组立、侧壁组立、顶板组立在上建场地平胎位制作完成。
2.2烟囱分段在经托架改造的胎架上以首面围壁为胎,依次装配顶板组立、侧壁组立和尾面围壁组立,根据《9004分段建造工艺》要求穿插进行管系、舾装作业。
上建主体分段(9011、9012、9013、9014、9015、9016、9017分段)主要分为甲板组立、围堰双壳组立、外围壁组立、内部隔舱壁组立、伙食吊筒壁(仅9016分段)等组立。
3.1外围壁组立、内部隔舱壁组立在平胎位拼板,装焊骨材,形成平面组立。甲板板在分片制作场地拼板,然后甲板板上大组胎架进行拼板(单面焊)、划线、装焊骨材、横梁、纵桁等形成甲板组立。伙食吊筒壁在联合厂房进行下料、卷制、焊接。
3.2围堰双壳组立内的板片、隔板、顶板、骨材、筋板肘板等在联合厂房下料送至上建场地。在上建场地以一侧围板为胎装焊内部构件,翻身与另一侧围板装焊形成完整的围堰双壳组立。
9212/9312围堰分段的建造流程与3.2项类似。
9211/9311/9411/9412/9512分段在上建场地以甲板为胎反造。
9216/9316分段在上建场地制作成型。分段主要包含驾驶甲板平台组立、FR46横壁组立、箱形立柱和斜纵壁等组立。
6.2驾驶甲板平台中组立先以驾驶甲板为基装配隔板组立,完成焊接后翻身装配到驾驶甲板平台组立上,再装配FR46舷墙组立。
"""
def test_chinese_process_text_extracts_rich_key_information():
result = recognize_process_text(_CHINESE_PROCESS_TEXT)
codes = {row["blockCode"] for row in result["blocks"]}
assert "9005" in codes
assert any("9011" in code for code in codes)
assert any("9212/9312" in code or "9212" in code for code in codes)
assert any("9211/9311/9411/9412/9512" in code or "9211" in code for code in codes)
assert any("9216/9316" in code or "9216" in code for code in codes)
assert any("FR46" in code for code in codes)
assemblies = {row["assemblyName"] for row in result["assemblies"]}
assert {"首面围壁组立", "尾面围壁组立", "侧壁组立", "顶板组立", "甲板组立",
"围堰双壳组立", "外围壁组立", "内部隔舱壁组立", "驾驶甲板平台组立"} <= assemblies
assert any("FR46横壁组立" in name for name in assemblies)
ops = {row["processName"] for row in result["operations"]}
assert {"拼板", "装焊", "下料", "卷制", "翻身", "反造", "舾装", "管系", "焊接", "划线"} <= ops
locations = {row["location"] for row in result["locations"]}
assert {"上建场地", "联合厂房", "平胎位", "大组胎架"} <= locations
assert result["sequenceSteps"]
assert result["status"] == "PENDING_REVIEW"
def test_process_candidates_stay_pending_with_evidence():
understanding = build_drawing_understanding(inspect_dxf(_sample(_SAMPLE_003)))
for row in understanding["processCandidates"] + understanding["processDetails"]:
assert row["status"] == "PENDING_REVIEW"
assert row["reviewRequired"] is True
assert 0 < row["confidence"] <= 1
assert row["evidence"]