feat(review): 取证层多源化 + 视觉多图(整体+2x2 象限)

- 新增 evidence_model.py:统一证据模型(source_type + images 列表),访问器兼容旧 image_b64/image_mime 单图字段
- phases/evidence.py:新增 collect() 多源分发 seam(仅 CAD)、capture_images() 整体+等分象限多图(结束复位视口)、sub_windows()
- phases/review.py:多图逐张下采样喂 LLM,payload 增加 source_type
- config.py:EVIDENCE_DETAIL_TILES=4 / EVIDENCE_MAX_IMAGES=5(默认开启多图)
- 新增 tests/test_evidence_model.py,更新 evidence/review 断言与 fakes 归一
This commit is contained in:
gjm committed 2026-10-15 19:48:18 +08:00
1 parent 22db93b6f5
commit 1c9fc72839
10 files changed
+396 -32

No files matched your search

+18 -1
View File
@@ -28,8 +28,8 @@ from tests.fakes import (
def test_evidence_payload_strips_image():
ev = make_evidence(image_b64="QUJD", image_mime="image/png")
payload = evidence_payload(ev)
assert "images" not in payload
assert "image_b64" not in payload
assert "image_mime" not in payload
assert payload["frame_index"] == 1
@@ -243,3 +243,20 @@ def test_review_frame_intermediate_tool_turn_json_not_parsed():
out = review_frame(ctx, make_evidence(), "sys", log=lambda *a: None)
assert out["summary"] == "最终结论"
assert out["issues"] == []
def test_review_frame_includes_multiple_image_blocks():
llm = FakeLlmClient(script=[llm_text("ok")])
ctx = make_ctx(client=FakeMcpClient(), llm=llm)
ev = make_evidence(
images=[
{"b64": "A", "mime": "image/png", "label": "overall"},
{"b64": "B", "mime": "image/png", "label": "tile-1"},
]
)
review_frame(ctx, ev, "sys", log=lambda *a: None)
user_content = llm.calls[0]["messages"][1]["content"]
image_blocks = [b for b in user_content if b.get("type") == "image_url"]
assert len(image_blocks) == 2
assert any(b.get("text") == "(截图:overall)" for b in user_content)
assert any(b.get("text") == "(截图:tile-1)" for b in user_content)