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

132 lines
8.6 KiB
Markdown
Raw 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.
---
name: Agent 路线与多源架构(2026-10-15)
description: dwg_review agent 的总目标、多源图纸分层架构(视觉为最大公约数)、工具层与 agent 层的正交分工、多源证据层、截图去 UI、grounding 实测、热力图 + 自适应瓦片规划 + VLM 分辨率标定与后续路线
type: 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
(等价于全用文字判据,代价是同样预算下覆盖面积减半)。