Files
cad-agent/ai.memory/project_agent_roadmap.md
T
gjm 9c4ab62dc1 feat(tiling): CAD 实测标定 R_text/R_line + 瓦片粒度内容过滤 + 默认参数定稿
Stage B2(CAD 实测标定)与收尾:

- 新增 verify_text_resolution.py:临时加字(字高 200 图形单位 = 1:100 纸面 2mm)+
  平行线对,按目标像素换算 zoom 窗口 → 截图 → 问 VLM;测完 delete_entities 清理不保存。
- 标定结论:
  * **可读下限与字体强相关**——离线合成(Consolas 抗锯齿填充字体)12px;
    真实 CAD 单线体 .shx(描边字体)6px 即可读对(3/3,两轮)。
  * 线条「1 条 vs 2 条」:2/3/4px 失败,5/8/12px 成功 → R_line ≈ 5px。
  * **必须用 ACI 7 白字**:实测红字(ACI 1)12px 因对比度不足完全读不出。
- config 定稿:TEXT_READABLE_PX=8(折中)、LINE_READABLE_PX=6、
  EVIDENCE_MAX_IMAGES=12(原 5 会把规划结果截到只剩 4 张瓦片)。
- 新增 heatmap.occupied_boxes:占用格的**世界 bbox**。
- tiling.plan_regions 新增 keep 谓词;evidence._plan_tiles 按占用格剔除**空瓦片**
  (簇 bbox 是包围盒,L 形/斜向分布含大片空白,实测有效)。
- 测试:test_heatmap 补 occupied_boxes;test_tiling 补 keep 过滤;全量 286 项全绿。
- 真实图纸端到端验证:A0 图框出 12 张(1 整体 + 11 瓦片),单框审查 1m38s 通过。
- 记忆库同步:工具语义坑(type_filter 必须传列表 / layer_filter 是通配字符串 /
  add_* 返回句柄在 created 键)、标定结论与默认值。
2026-10-15 23:22:15 +08:00

8.6 KiB
Raw Blame History

name, description, type
name description type
Agent 路线与多源架构(2026-10-15) dwg_review agent 的总目标、多源图纸分层架构(视觉为最大公约数)、工具层与 agent 层的正交分工、多源证据层、截图去 UI、grounding 实测、热力图 + 自适应瓦片规划 + VLM 分辨率标定与后续路线 project

Agent 路线与多源架构

总目标(用户 2026-10-15 明确)

实现 AI 自动识别 + 评审 DWG 图纸。分阶段:先 MCP(已完成),再 agent(进行中)。 最终要支持的图纸来源不限于自家自定义实体:

  1. 自家软件的自定义实体 DWG;
  2. 其他软件出的 DWG(各种自定义实体);
  3. 将来 PDF 图纸;
  4. 将来纯图片图纸。

架构分层(用户认可)

核心洞察:视觉模型(VLM)是"最大公约数"。DWG 自定义实体 / PDF / 图片本质是 "拿不到结构化数据时靠视觉理解"的同一件事——任何图纸只要能渲染成图,VLM 就能审。 所以结构化数据(ARX 读普通实体)是增强,视觉是兜底。

Agent 推理层(审查逻辑 / 清单 / 规则)
        ▲  统一 evidence schema
感知适配层(能力从高到低降级)
  CAD结构化(ARX) → CAD几何 → 离线解析(DWG/PDF) → 视觉(VLM)
  • MCP 工具层只管 CAD(进程内能力);PDF / 图片在 agent 侧(PyMuPDF / Pillow), 不塞进 MCP、不编 DLL。
  • 统一证据模型 + 多源适配 + 能力降级;agent 推理层不关心来源格式。

How to apply:新增"支持某格式"时,优先在 agent 侧感知层加适配器;只有"CAD 进程内的 正交感知能力"才考虑加 MCP 工具。

第一步已落地(2026-10-15,提交 1c9fc72)

取证层多源化 + 视觉多图:

  • 新增 dwg_review/evidence_model.py:统一证据模型(source_type + images:[{b64,mime,label}]),访问器 evidence_images() 兼容旧 image_b64/image_mime 单图字段(历史 evidence.json 仍可读)。
  • phases/evidence.py:collect() 多源分发 seam(当前仅 CAD)、capture_images() 整体 + 等分象限多图(结束复位视口)、sub_windows()。
  • 默认 EVIDENCE_DETAIL_TILES=4 / EVIDENCE_MAX_IMAGES=5(每图框 5 图,默认开启)。
  • 实测:真实 Plant 3D 图纸上多图让审查更细(多报出线型误用 CENTER2、图签块属性为空、 按 handle 定位的图层混用等)。

截图去 CAD 界面元素(2026-10-15,提交 f8bd12d)

get_viewport_screenshot 原先截 adsw_acadDocWnd() 客户区,含视口控件、ViewCube、滚动条, 污染截图并误导 VLM(曾把视口标签当成"需放大的内容")。已修复:

  • 改用 acedGetAcadDwgView() 只截图形区(排除滚动条/状态栏)。
  • 截图期间临时置 NAVVCUBEDISPLAY=0(关 ViewCube)与 VPCONTROL=0(关视口控件), 用 RAII 守卫(TempSysVarOff)自动恢复原值,不影响用户 CAD 界面设置; 配合 RedrawWindow(RDW_UPDATENOW) 同步重绘。
  • 实测:三项 UI 均消失,VLM 不再提界面元素。

残留(无解,已知):绘图区右上角仍有绘图窗口的最小化/最大化/关闭按钮——由 AutoCAD 画在图形区内的固有 UI,无系统变量可关。它很小且在角落,实测未影响 VLM。 (区别于应用窗口的按钮;用户最初要清的是 视口控件/ViewCube/滚动条,不含此项。)

grounding 实测(2026-10-15)

用 verify_grounding.py 拿真实截图问 deepseek-flash"哪里要放大":grounding 可用—— 给出的归一化坐标区域级定位准确(放大后确实套住目标,如图签栏、图框角), 但语义描述略有偏差(把图签栏说成"状态栏")。结论:可支撑"按区域放大",但位置对、语义别全信。

后续路线(未做)

  1. VLM 主动放大(自适应取证):复用受控只读取证子循环,让 VLM 请求放大看不清处。
    • 两条路径:① 按实体 zoom_to_entity(handle)(可靠);② 按区域(把 VLM 归一化坐标映射成 WCS)——grounding 已实测可用(见上节)。
    • 必须设迭代上限 + 兜底;不把"看清没"完全交给 VLM(会过度自信/幻觉)。
    • 现有 zoom_to_window/zoom_to_entity/get_viewport_screenshot 已在只读白名单, 无需新增工具。
  2. PDF / 图片源:在 phases/evidence.collect() 加分支,产出同形 evidence (window=None、结构化空信封、images 带 label);规划阶段抽象"审查单元" (CAD=图框 / PDF=页 / 图片=单);批注对非 CAD 源降级(annotator 已天然跳过无 handle 的 issue)。
  3. 审图规范接入:清单升级为规范库。

热力图 → 自适应瓦片规划 → VLM 分辨率标定(2026-10-15,进行中)

动机:固定「整体 + 2x2 象限」截图对 A0/A1 大图幅读不清。用户拍板:驱动信号是实体分布 (热力图),不是文字(有的图没有文字),且实际工况下实体占据图框大部分,稀疏/稠密都要能处理。 用户方案:图框类型 → 纸张真实尺寸 + 比例 → CAD 世界尺寸 → 换算像素 → 知道 VLM 分辨率 → 算出一个图框要截几张、截哪里。

用户已拍板的关键决定:

  • 热力图在 Python 侧(agent 层) 算(派生量,工具层只给原始事实)。密集图若受 query_entities 的 limit≤1000 / 帧上限拉不全 → 给现有 query_entities 加 brief 模式 (只回 handle/type/bbox、放开 limit),而不是新增"热力图工具"。
  • CollisionDetection.h/cpp(用户写的 BVH)本步不用,留作后续几何相交/干涉检查引擎。 其按质心中位分割 → 节点框可能重叠,不适合铺屏瓦片;瓦片切分用四叉树/网格(空间不相交)。
  • 标定判据:同时测「读出文字」与「分辨线细节」;标定字高 200 图形单位(1:100 = 纸面 2mm,国标最小)。

已落地(提交 9b8a232 热力图;cba05b0 瓦片规划 + 离线标定):

  • dwg_review/heatmap.py(纯函数):entity_boxes / build_grid(counts+coverage)/ cluster_cells(4-连通,可选膨胀)/ grid_to_windows / grid_stats / render_overlay。 drop_oversized:丢掉 bbox 占满图框的实体(实测每框恰 1 个,即图框块),否则热力图全满。
  • dwg_review/tiling.py(纯函数):frame_scale(sheet_scale>0 用之;否则由 bbox/纸张反算; 否则 default)/ world_per_px / is_text_type / plan_regions(文字簇优先、空白区不出图、 max_tiles 截断、窗口夹到图框)。
  • phases/evidence.capture_images:先截整体图并测绘图区像素 → 规划成功用规划窗口, 否则退回 sub_windows(行为零变化);任一信封 total>returned(截断)→ 退回固定策略。
  • verify_heatmap.py(不耗 token,出 PNG + bbox 缓存)、verify_vlm_resolution_offline.py、 verify_text_resolution.py(CAD 实测)。

标定结论:

  • 该模型无法可靠计数线条(6 条线在 2~10px 间距下答 4/10/4/5/4/4)→ 线条判据改用 「1 条 vs 2 条」二选一。
  • 可读下限与字体强相关:离线合成(Consolas 抗锯齿填充字体)12px(白底 10px); 真实 CAD 单线体 .shx(描边字体)6px 就能读对(3/3,两轮)。
  • 真实 CAD 线条:2/3/4px 失败,5/8/12px 成功 → R_line ≈ 5px。
  • 标定必须用 ACI 7(白/黑自适应):实测红字(ACI 1)12px 完全读不出——否则把 "对比度不足"误当"分辨率不足"。
  • 实测绘图区 2110×462 → 有效 1280×280(长边 1280),视口宽高比 4.567。

用户拍板的默认值(2026-10-15):TEXT_READABLE_PX=8(折中,兼顾描边与 TrueType)、 LINE_READABLE_PX=6、EVIDENCE_MAX_IMAGES=12(原 5 会把规划结果截到只剩 4 张瓦片)。

瓦片粒度内容过滤:簇 bbox 是包围盒,L 形/斜向分布(如管道走向)含大片空白 → plan_regions(keep=...) 按 heatmap.occupied_boxes 剔除空瓦片(实测有效)。

已知局限:本图纸的文字在块 / 自定义实体内,get_text_content 检不到 → 该簇会按 线条判据出图(6px),块内文字可能读不清。要更保险可把 LINE_READABLE_PX 调到 8 (等价于全用文字判据,代价是同样预算下覆盖面积减半)。