gjm
|
6143bb9ab2
|
feat(review): PDF/图片离线源适配(C1)—— 无需 CAD 的整条审查链路
支持直接审查 PDF 与位图图纸,全链路离线(不连 CAD、不连 8080 端口)。
渲染在内存内完成,复用既有墨迹热力图 + 自适应瓦片规划。
- 新增 dwg_review/sources.py
- detect_source / plan_file / collect 统一入口
- PdfReader:pypdfium2 惰性导入,页序即图框序,处理 /Rotate 与 crop 边距
- ImageReader:世界单位 = 源像素,snap_box 整数对齐保证窗口与像素严格一致
- ink_grid:纯 PIL 灰度阈值 → 占用网格(不引入 numpy)
- ReviewContext.create(connect_cad=False):离线时 client/tools 均为 None
- 全链路 ctx.tools is None 守卫:review 只读子循环 / inspect_region / annotator /
checks 的窗口类检查 / 绘图区最大化
- checklist.build_system_prompt(allow_tools=False, offline=True):离线提示词
- __main__:位置参数 source,按扩展名自动判定源类型并决定是否连 CAD
- config 新增 8 个常量(PDF_MAX_PAGES / 文本最小字数 / 各源缩放上限 / 墨迹阈值等)
- tiling.content_predicate 与 heatmap.cell_box 提升为公开函数
验证:
- pytest 457 passed
- verify_pdf_source.py:PDF 23/23、图片 9/9(不需 CAD),含实测瓦片字高像素与
旋转映射自检(文本区墨迹 0.311 vs 忽略 /Rotate 反向对照 0.145)
- 真实 LLM 端到端:20 页 HVAC 图纸前 3 页跑通,结论具体可核验且未编造 handle
已知局限:页边线在墨迹网格里会把整页连成单簇,瓦片常退化为整页象限(CAD 侧
靠 drop_oversized 丢图框块,离线侧暂无等价手段),留待后续打磨。
|
2026-10-16 23:07:23 +08:00 |
|
gjm
|
d4a9442e30
|
feat(review): 几何干涉检查 find_collisions(BVH 粗筛 + 容器过滤)
C++(cad_mcp_plugins):
- 新增 bvh.h:header-only 2D BVH(质心中位分割,叶<=4,SelfPairs 交叉对枚举)
- 新增 find_collisions.cpp:粗筛 AABB 相交实体对,附重叠盒 + 逐轴重叠比 ratio
(= 逐轴重叠长/较短长 之积,退化轴取 1.0),按 ratio 降序 + 分页;
narrow=true 只对返回页跑 intersectWith 细筛(附 exact)
- 容器过滤(关键):图框块/分区边界会与一切相交,用重叠【度】判定
deg >= max(exclude_container_deg=8, exclude_container_frac=0.25 * 其他实体数),
与图幅/缩放无关;被剔除者在 excluded_containers 里如实报告
(初版用面积判据对多图框并排失效:3 框只占并集 27/13/7% 全部漏过,
全模型 163 对噪声;改度判据后图框 deg=35/25/23 vs 其余 deg<=3,分离干净)
- cmakelists.txt + 两个 mcp_config.json 注册(28 工具)
agent 侧(Python):
- cad_tools.READ_ONLY_TOOLS += find_collisions(受控子循环可调用)
- checks.check_collisions + run_deterministic_checks(受 CHECK_COLLISIONS 开关,默认关)
- config += CHECK_COLLISIONS=False / COLLISION_MIN_OVERLAP=0.5
- checklist.py / review_checklist.json += 「干涉/碰撞」类别(high)+ 提示词协议
(先 find_collisions 拿候选 → inspect_region 目视确认;AABB 相交 != 真干涉)
验证:
- verify_collisions.py 17/17 PASS:全模型候选 163→80(全部 ratio=0.000),
min_overlap=0.5 → 0 对;逐图框 0 对;narrow top-5 中 4 条 exact=true;
--inject 注入深重叠矩形报出 ratio=0.902 并清理 2/2
- pytest 355 passed(新增 12 项)
- 端到端:LLM 主动调用 find_collisions{min_overlap:0.2,narrow:true,window:<图框>},未误报
|
2026-10-16 19:46:44 +08:00 |
|
gjm
|
b757892c67
|
feat(review): agent 侧虚拟工具 inspect_region —— 按可读分辨率放大指定区域
解决三个缺口:① 放大没复用标定/瓦片数学(LLM 一次 zoom 只出一张,宽区域仍读不清);
②「看清没」由 VLM 自评(易过度自信/幻觉);③ 只能按 handle / 手算 bbox 指认,
图上看到但没 handle 的东西指认不了。
核心思路:把「放大」升级成一个语义化工具——LLM 只指认「要看哪里」,由 agent 复用
tiling.py 的标定数学算出该切几张、每张覆盖多大,用构造保证可读。
新增 dwg_review/inspect.py(agent 侧,不编 DLL):
- TOOL_SCHEMA:inspect_region(target, purpose);target 三形态 {handle} / {window} /
{label,cx,cy,span},purpose = text(8px) / line(6px)。
- InspectState:单图框内「截图标签 → 世界可见范围」登记表,支持逐级下钻
(返回的 inspect-N 可继续作为 label 指认)。
- resolve_target / _point_box:label+cx+cy → WCS。cy 是图像坐标(上→下),
世界 y 必须翻转(y = y2 - cy*H)——单测专门钉住。
- plan_tiles:复用 world_per_px + tiles_for_box + subdivide;超 INSPECT_MAX_TILES(4)
则硬失败并给出「缩小 target / 分多次请求」的指引(不静默降级);拿不到比例/像素
则退回单张并如实告知。
关键几何:CAD 的 _.ZOOM _W 是等比适配(不拉伸),故「截图上的归一化坐标」必须按
max(W/ew, H/eh) 反算真实可见范围(新增 tiling.visible_box)——直接用送进去的窗口会偏。
zoom_to_window 返回的 view 是「加过 margin 的窗口」,不是可见范围,不能混用。
证据层配套:evidence_model.make_image(..., window=) 记录每张图的可见世界范围;
capture_images 用 view_px(overall 图原始像素)+ visible_box 逐张登记。
子循环接入:_run_readonly_tool 在只读白名单校验之前拦截 inspect_region(它不在
READ_ONLY_TOOLS 里,内部只调白名单内的只读 MCP 工具);_review_tools 启用时用
inspect_region 取代三个裸视口工具;inspect_region 计入 _VIEW_TOOLS → 结束复位视口。
配置:INSPECT_ENABLED(True) / INSPECT_MAX_TILES(4)。
端到端实测(真实图纸 1 图框):取证与审查两阶段均在最大化态、结束精确还原(4 项 PASS);
LLM 的 11 次取证调用里 2 次是 inspect_region,且都显式给 window + purpose:"text"
(x[20000,115000] y[-6500,3000],即 A0 图框底部横条=标题栏所在)。
验收口径达成:报告报出标题栏乱码 ???????????????,而 get_text_content 对全图返回 0 条文字
(本图文字全在块/自定义实体内)→ 块内文字是被视觉放大读出来的。
pytest 343 passed。
|
2026-10-16 19:15:32 +08:00 |
|
gjm
|
e8140f2bc5
|
feat(review): 审查阶段对齐绘图区分辨率 + 放大取证闭环
发现的缺口:maximized_drawing_area 原先只包住取证循环,审查阶段没被包住 →
LLM 在受控子循环里 zoom + 截图拿到的是未最大化的 2110x462(正是上一轮刚解决的
低分辨率问题,在最需要放大看细节的审查阶段又出现了);且审查中的 zoom 不复位视口,
跑完把用户的 CAD 留在最后一次放大处。
改动:
1. __main__.run_review:把 maximized_drawing_area 从「只包取证」扩到「包取证 + 审查」
(两者都要截图);report/annotate 留在 with 之外。
2. phases/review.py:新增 _VIEW_TOOLS;review_frame 拆成外壳 + _review_frame,
外壳 try/finally 里仅当确实动过视口才复位到该图框整幅视图
(zoom_to_window(win, margin=0.02))。纯查结构化数据的路径不受影响。
3. checklist.build_system_prompt:把「可调用只读工具」改写成明确的放大取证协议——
截图看不清时用 zoom_to_window(坐标由图框/实体 bbox 算)或 zoom_to_entity,
再 get_viewport_screenshot 复核;并约束不要为看图而反复放大。
次生问题(同轮修复):_MAX_OBS_IMAGES 原为硬编码 3,而模型一轮内会发 8 次截图 →
拍了 8 张只回灌 3 张。改为配置项 REVIEW_OBS_IMAGES(默认 6),并把预算耗尽的占位
文案改成明确告知模型「不要再请求截图,请给出结论」。
实测(真实图纸 1 图框,新增 verify_review_maximized.py):取证与审查两阶段窗口均为
[-4,-2,3444,1442](最大化态),结束精确还原 [68,0,2316,960],三项全 PASS;
子循环里 LLM 连发 8 组 zoom_to_window + get_viewport_screenshot,提示词生效。
pytest 304 passed。
|
2026-10-16 18:55:31 +08:00 |
|
gjm
|
1e5bff268a
|
feat(review): 截屏前最大化绘图区 + 空瓦片过滤覆盖回退路径
新增 MCP 工具 set_drawing_area(mode="max"|"restore"):最大化主窗口 + CLEANSCREENON
(隐藏功能区/命令行/面板)。实测绘图区 2110x462 -> 3310x1084(面积 3.68x),
restore 精确回位(窗口矩形/最大化态/绘图区尺寸全部还原)。
坑:CLEANSCREENOFF 是异步命令,AutoCAD 会按「进入干净屏幕时的布局」重设窗口几何,
把同步的 SetWindowPlacement 覆盖掉(表现为窗口停在最大化)。解法是插件内
SetTimer 延迟 700ms 再压回;实测窗口在 0.5~1.0s 之间收敛,故调用方等待取 1.5s。
取证层:
- 新增 maximized_drawing_area(ctx) 上下文管理器,__main__ 用它包住整个取证循环
(多图框只进出一次);受 DRAWING_AREA_MAXIMIZE 控制,工具缺失/调用失败静默降级,
restore 失败不掩盖业务异常。
- 内容过滤统一到规划与回退两条路径,共用同一谓词;过滤后为空则退回原集合。
- 判定改用「实体 bbox」而非「占用格」:格子量化会把跨界内容算进相邻格,反而更粗
(实测实体 bbox 正好压象限边界时 4 个象限全判有内容)。heatmap.occupied_boxes 随之删除。
实测(真实图纸 A0/A1/A2 三图框):截图张数 12/8/4 -> 8/5/4;pytest 296 passed。
新增 verify_drawing_area.py 作为该工具的验收脚本。
|
2026-10-15 23:44:32 +08:00 |
|
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 |
|
gjm
|
32d552f1f0
|
docs(memory): Agent 多源架构 + 工具分层;补真实测试图纸与启动方式
- 新增 project_agent_roadmap.md(总目标/多源分层/第一步/后续路线)
- 新增 feedback_tool_layering.md(工具层正交分工,反对无休止加工具)
- reference_environment.md 补 e:\desktop\agent_test.dwg 与 /p SHS-ENVI2026 启动方式
- 一并提交上次会话遗留的记忆更新
|
2026-10-15 19:48:56 +08:00 |
|
gjm
|
8c0fcfee83
|
chore: 删除 5 个遗留调试脚本并同步文档引用
- 删除 agent_loop.py / dwg_review_agent.py / countOfCircle.py
(硬编码 DeepSeek API Key)与 test.py / test_autoagent.py
(重复实现;且 test_autoagent.py 名字与 pytest 的 test_*.py 收集规则冲突)
- CODEBUDDY.md 测试章节改为「pytest 快层 + verify_* 慢层」
- review_checklist.json 描述改指 dwg_review 包
- ai.memory 同步引用与历史说明
安全:Key 已随提交 bdd77af 进入 git 历史并推到远程,删除文件不能清除历史,
需去 DeepSeek 控制台轮换该 Key(已在 ai.memory 备案)。
|
2026-10-14 19:07:35 +08:00 |
|
gjm
|
0b4ffdec0c
|
chore(memory): 沉淀基座 c++_dll 加载/执行的排查结论
- 新增 ai.memory/project_mcp_frame_dll_loader.md:
1) 运行时 acrxGetApiVersion() 有状态、不可用于版本比对;
2) DLL 工具写数据库需文档锁(应用上下文 → eLockViolation);
3) 同一 DLL 只加载一次(模块缓存)及代理不再 FreeLibrary 的原因。
- 更新索引 MEMORY.md;reference_environment.md 的 c++_dll 说明改为「只加载一次」
并指向新文件,测试脚本表补 verify_annotate.py。
- 修正 feedback_preferences.md 中 ai.memory「尚未入库」的过时说明。
|
2026-10-09 22:37:31 +08:00 |
|
gjm
|
0bd290c96e
|
chore(memory): 记录 SSH 密钥变更(改用 id_ed25519_guojianming)
|
2026-10-09 15:19:02 +08:00 |
|
gjm
|
e25aa0a650
|
chore(memory): 新增 ai.memory 记忆库
- MEMORY.md 索引 + 分主题记忆文件
- project: 图纸审查 Agent 工作汇总
- feedback: 协作偏好(含 Git 推送规则:refs/for/main 触发 Gitea PR)
- reference: 环境与外部资源
|
2026-10-09 09:43:21 +08:00 |
|