@TOC
代码仓库入口:
系列文章规划:
- (OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(1):从开发的视角看下CAD画出那些好看的图形们))
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(2):看似"老派"的 C++ 底层优化,恰恰是这些前沿领域最需要的基础设施)
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(3):你的 CAD 终于能画标准零件了,但用户想要"弧面"、"流线型",怎么办?)
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(4):GstarCAD / AutoCAD 客户端相关产品 ------ 深入骨髓的数据库哲学)
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(5)番外篇:给 CAD 加上"控制台"------让用户能实时"调参数、看性能")
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(6)番外篇:让视图"活"起来------鼠标拖拽、缩放背后的数学魔法
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(7)-番外篇:点击的瞬间,发生了什么?
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(8)-番外篇:当你的 CAD 遇上"活"的零件)
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-2-(1)-当你的CAD想"联网"时:从单机绘图到多人实时协作)
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-2-(2)-当你的CAD需要处理"百万个螺栓"时:从内存爆炸到丝般顺滑)
- OpenGL渲染与几何内核那点事-项目实践理论补充(一-2-(3)-当你的协同CAD服务器面临"千人同屏"时:从单机优化到分布式高并发)
巨人的肩膀:
- deepseek
- gemini
当你的CAD学会"听话":从鼠标点击到自然语言命令
故事续章:你的CAD已经能处理千人协同了,但用户说:"能不能直接跟我说,把螺栓加粗?"
你作为辣个蓝人【那个男人】,刚刚看了并发和内存那点事,又搞了搞CAD和图形渲染的小九九,正准备庆祝。产品经理又来了:"小C,现在AI这么火,我们的CAD能不能加个'语音助手'?用户说一句'帮我把所有螺栓加粗2mm',软件就自动执行。"
你愣了一下:"这......不就是自然语言转成API调用吗?"但仔细一想,问题远比想象中复杂。
用户说的"螺栓"在图纸里可能是一堆三角形的集合(STL文件),或者是一个块引用(DWG),或者是一个参数化特征(SolidWorks)。计算机不认识"螺栓"这个词 。你开始意识到,你需要一个 Agentic CAD Workflow(智能代理CAD工作流)------让AI当"翻译官",把人类的自然语言,翻译成CAD能执行的指令。
第一步:最原始的方式------硬编码命令,用户得像机器人一样说话
最早的CAD当然没有AI。用户想"加粗螺栓",得手动操作:
- 点击"选择工具"
- 框选所有螺栓(可能得一个个点)
- 点击"偏移面"命令
- 输入"2mm"
- 点击"确定"
你作为开发者,觉得这太繁琐了。你尝试做了一个命令行输入框,支持一些"宏命令":
SELECT ALL BOLTS
OFFSET 2.0
你在代码里写了一个词法解析器 :遇到SELECT就进入选择模式,ALL表示全选,BOLTS是一个预定义的关键词(你得提前把图纸里的物体打上标签)。遇到OFFSET就调用offsetEntity(2.0)。
但问题是:
- 用户必须记住精确的命令词,说"加粗"不行,得说
OFFSET。 - 你无法处理模糊语义:"把螺栓弄粗一点"------"一点"是多大?
- 每个新命令都要你写解析逻辑,累死。
你意识到,这不是真正的"自然语言",只是换了个马甲的命令行。
第二步:引入大语言模型------让AI"猜"用户意图
2023年,ChatGPT火了。你想:能不能让LLM(大语言模型)来解析用户的话?
你设计了一个最简单的架构:
用户输入 :"帮我把所有螺栓加粗2mm"
→ 发送给LLM (调用OpenAI API)
→ LLM返回 :{"action": "offset", "target": "bolt", "value": 2.0, "unit": "mm"}
→ 你的CAD程序解析这个JSON,调用对应的C++函数。
你发现,LLM真的能理解"加粗"就是"沿法线向外偏移","螺栓"就是图纸中标记为bolt的物体。你不需要再写死关键词了。
但问题来了:
- 每次调用都走云端API,延迟高(几秒钟),用户体验差。
- 敏感图纸不能上传到第三方服务器。
- LLM有时候"幻觉":用户说"把螺栓变胖",它可能返回
{"action": "scale", "factor": 1.5},但"变胖"是径向缩放,不是沿法线偏移------你需要在提示词里做大量工程。
你开始研究 LangChain 和 Coze。
第三步:Agentic CAD Workflow------把"大脑"和"躯干"分开
你意识到,一个完整的自然语言控制CAD系统,应该分成四个层次,就像人的神经系统:
1. 感知层 (NLP) ------ 耳朵和嘴巴
接收用户的自然语言指令,转换成结构化的"意图"。你用了 Coze (国内字节跳动的AI Agent平台)或者 LangChain(开源框架)。Coze提供了拖拽式的Bot搭建,你可以快速做一个"CAD助手"原型,不需要自己写LLM调用代码。
在Coze里,你设计了一个工作流:
- 输入:"帮我把所有螺栓加粗2mm"
- 插件:调用一个你自己写的"CAD控制"插件(暴露为HTTP接口)
- 输出:执行结果
2. 决策层 (LLM) ------ 大脑
LLM负责理解意图,并拆解成可执行的步骤。你发现,对于"加粗2mm",LLM需要推理出:
- "螺栓"是哪些物体? → 需要查找图纸中所有"螺栓"标签的物体。
- "加粗"是什么几何操作? → 沿每个面的法线方向向外偏移2mm。
- 偏移后会不会自交? → 需要调用布尔运算检查。
你写了一个提示词模板 ,告诉LLM你的CAD支持哪些原子操作:find_objects_by_label、offset_faces、check_intersection等。LLM会生成一个计划(Plan),例如:
json
{
"plan": [
{"step": 1, "action": "find_objects", "args": {"label": "bolt"}},
{"step": 2, "action": "offset_faces", "args": {"distance": 2.0, "direction": "normal"}},
{"step": 3, "action": "check_collision", "args": {}}
]
}
3. 接口层 (Control API) ------ 神经
你的CAD项目需要暴露一个本地控制接口 。你选择了 WebSocket 或 HTTP (RESTful),因为Coze/LangChain都支持。你在CAD程序里启动一个后台线程,监听localhost:8765。
接口设计:
POST /find→ 根据标签查找物体ID列表POST /offset→ 对指定物体ID执行偏移操作POST /undo→ 撤销
Coze的插件会调用这些接口。这样,你的CAD项目不需要改造成"AI原生",只需要加上一层薄薄的API外壳。
4. 执行层 (Renderer) ------ 肌肉
你的CAD程序收到指令后,调用现有的渲染管理器和几何内核:
- 在
render_manager.cpp中,你遍历所有顶点,沿法线方向移动2mm。 - 如果用的是精确几何(如Open CASCADE的B-Rep),你调用
BRepOffsetAPI_MakeOffset。 - 修改完成后,触发重绘。
你终于实现了:用户说一句话,屏幕上所有螺栓真的变粗了。
第四步:混合架构------"大脑"与"躯干"分离
你决定不要另起炉灶重写整个CAD。而是保持原来的C++核心不变,用LangChain/Coze搭建一个"控制端(Controller)",你的CAD项目作为"执行端(Executor)"。两者通过本地网络通信。
为什么这样做?
- 解耦:AI技术迭代快(今天LangChain,明天可能又有新框架),你的CAD核心不需要跟着改。
- 安全:图纸数据可以只留在本地,只把必要的文本信息(如物体标签)发给云端LLM,或者干脆用本地小模型(如Ollama + Llama 3)。
- 复用:你可以把同样的API暴露给其他客户端(比如手机App、命令行脚本)。
你画了一个架构图:
[用户] -> [Coze/LangChain] -> [本地WebSocket/HTTP] -> [你的CAD C++程序]
|
+-> [修改顶点数据/Model矩阵]
+-> [重渲染]
第五步:技术挑战------STL文件不认识"螺栓"
你很快遇到了最棘手的问题:STL文件只是一堆三角形,没有语义。它不知道哪堆三角形属于"螺栓",哪堆属于"齿轮"。
你的CAD项目原本支持导入STL,但用户说"把螺栓加粗"时,程序根本不知道哪些三角形是螺栓。
你需要零件语义化。你开始研究几种方案:
方案A:人工打标签(最原始)
用户导入STL后,手动框选螺栓部分的三角形,然后右键"标记为螺栓"。你在代码里记录一个map<triangleId, string>。这是最可靠的,但费时。
方案B:基于几何特征自动识别(进阶)
螺栓有特征:圆柱面+螺纹+六角头。你可以写一个识别算法,遍历所有三角形,计算曲率、法线分布,找出符合螺栓几何特征的区域。这需要你懂计算机图形学和机器学习。
方案C:从STEP文件中读取语义(工业标准)
STEP文件本身就带有"产品结构",每个零件有名称、ID。你之前已经集成了Open CASCADE,可以读取STEP文件中的标签。例如:
cpp
Handle(TDataStd_Name) nameAttr;
if (shape.FindAttribute(TDataStd_Name::GetID(), nameAttr)) {
TCollection_ExtendedString name = nameAttr->Get();
// name 可能是 "Bolt_M12"
}
这样,你不需要自己识别,用户直接导入带语义的STEP文件即可。
你决定在项目中同时支持三种方案:用户手动标记、几何特征识别(简单版本)、STEP语义读取。这样无论用户上传什么格式,都能理解"螺栓"。
几何变换逻辑:从"加粗"到"顶点位移"
当LLM决定"加粗2mm"后,你需要修改几何。对于网格模型(STL),做法是:
- 找出所有属于"螺栓"的三角形。
- 对每个三角形,计算法线方向(归一化)。
- 将三个顶点沿法线方向移动2mm。
注意:相邻三角形共享顶点,你不能重复移动。你需要先收集所有受影响顶点,去重,再统一移动。
对于精确模型(B-Rep),调用OCCT的偏移API:
cpp
BRepOffsetAPI_MakeOffset offset(face);
offset.SetOffsetValue(2.0);
TopoDS_Shape newFace = offset.Shape();
你把这些逻辑封装成offsetEntityById(entityId, distance)函数,供接口层调用。
第六步:进阶挑战------让你的CAD助手"惊艳"全场
你完成了基础版:用户说"加粗螺栓2mm",程序执行。但产品经理说:"能不能更智能?比如用户指着屏幕说'加粗这颗',或者写一段Python脚本自动生成齿轮?"
你开始研究2026年的高阶路径。
挑战一:多模态交互------让AI"看"屏幕
用户不仅说话,还能用鼠标指向屏幕上的螺栓,然后说"加粗这颗"。你的助手需要"看懂"截图。
你集成了GPT-4o(支持图像输入)或类似的视觉语言模型。流程:
- 用户说"加粗这颗",同时鼠标在屏幕上点击。
- 你的CAD程序截取当前渲染画面,并记录鼠标坐标。
- 将截图+鼠标坐标+用户语音转文字,一起发给多模态LLM。
- LLM理解"这颗"指的是截图里鼠标位置附近的物体,返回该物体的ID。
- 然后执行加粗操作。
你需要在渲染器中给每个物体分配唯一颜色(ID Render Pass),这样鼠标点击时,你读取该像素的颜色,就能反查出物体ID。这是图形学里的经典技巧。
挑战二:Code Interpreter模式------让AI写代码改模型
用户说:"我想生成一个渐开线齿轮,模数2,齿数20。" 这不是简单的"偏移",而是参数化建模。
你的方案:不让LLM直接调用你的C++ API(太复杂),而是让LLM生成一小段Python脚本,然后由你的CAD程序内置的Python解释器执行。
你在项目中嵌入了Python.h (CPython的C API),或者用pybind11暴露一些几何操作给Python。然后:
- LLM生成脚本,例如:
python
from cad_api import create_gear
gear = create_gear(module=2, teeth=20)
add_to_scene(gear)
- 你的C++程序调用
PyRun_SimpleString执行这段脚本。 - 脚本通过pybind11调回C++的几何内核,生成齿轮的B-Rep。
这就是 Code Interpreter 模式 ------ 让AI编程,而不是发JSON。好处是:你可以复用已有的Python生态(如numpy、scipy),而且用户也可以自己写脚本扩展功能。
第七步:你的"CAD助手"诞生了
经过几个月的开发,你终于拿出了原型:
- 感知层:用Coze搭建的Bot,支持语音输入(用户对着麦克风说话)。
- 决策层:接入GPT-4o,能理解模糊指令,拆解成计划。
- 接口层 :你的CAD程序暴露了WebSocket API,支持
find_by_label、offset_faces、run_python等操作。 - 执行层:支持网格和B-Rep的几何变换,支持Code Interpreter。
- 语义化:自动从STEP文件读取零件名称,也支持用户手动标记STL的三角形组。
- 多模态:用户鼠标指向+语音,AI能定位物体。
产品经理演示给老板看:他打开一个复杂的齿轮箱装配图,说"把所有的M6螺栓加粗1mm,然后把输出轴的长度缩短5mm"。几秒钟后,图纸自动更新。老板惊呼:"这就像钢铁侠的贾维斯!"
你笑了,你知道这背后是无数个日夜的工程:LLM的提示词调优、WebSocket的稳定性、法线计算的数值精度、Python解释器的隔离......但这一切都值得。
深度解析:Agentic CAD Workflow 从入门到精通
通过上面的故事,你已经对"CAD助手"的构建有了直观理解。下面,我们来系统地、由浅入深地剖析每一个技术点,确保你从零基础到能够自己动手实现。
1. 自然语言控制CAD:从硬编码到Agentic Workflow
阶段一:关键词匹配(远古时代)
- 实现:
if (cmd.find("加粗") != string::npos) { offset(2.0); }- 缺点:无法处理同义词、无法理解复杂语义、扩展性差。
阶段二:正则表达式 + 模板填充
- 实现:正则
/(加粗|变粗|放大) (\d+)mm/提取数值。- 缺点:用户必须按固定模板说话。
阶段三:传统NLP(词性标注、句法分析)
- 实现:用Stanford CoreNLP提取"动作-对象-参数"三元组。
- 缺点:需要大量标注数据,难以处理"所有螺栓"这种集合。
阶段四:大语言模型 + 函数调用(Function Calling)
- 实现:OpenAI的
tools参数,让模型返回结构化JSON。- 优点:零样本泛化,理解自然语言。
- 缺点:依赖云端,延迟高,幻觉风险。
阶段五:Agentic Workflow(代理工作流)
- 实现:LLM作为"大脑",调用多个原子工具(查找、偏移、检查),自主规划步骤。
- 代表框架:LangChain、Coze、AutoGen。
- 关键组件:ReAct模式(Reason + Act),模型先推理再行动。
2. LangChain vs Coze:选哪个?
维度 LangChain Coze 性质 开源Python框架 字节跳动云端平台(免费) 适用场景 需要深度定制、自托管、本地模型 快速原型、国内网络友好、拖拽式开发 核心概念 Chain, Agent, Tool, Memory Bot, Plugin, Workflow, Knowledge 代码示例 agent.run("加粗螺栓")画布上拖拽"大模型节点"+"代码节点" 本地部署 支持(Ollama等) 不支持,必须走云端 多模态 需自行集成 内置图像理解(需申请) 建议:初学者用Coze快速跑通原型,生产环境自托管LangChain以保护图纸数据。
3. 感知层:如何让CAD"听"懂指令?
语音转文字:
- 本地方案:Vosk、Whisper.cpp(离线、隐私安全)
- 云端方案:讯飞、阿里云、Azure Speech-to-Text
文字到意图:
- 用LLM的函数调用(Function Calling)定义你的CAD工具集:
json{ "name": "offset_faces", "description": "沿法线方向偏移指定物体的表面", "parameters": { "object_ids": ["string"], "distance_mm": "number" } }
- 提示词工程:告诉LLM"加粗"等价于
offset_faces,距离为正表示向外。4. 决策层:LLM如何拆解复杂指令?
ReAct模式原理:
Thought: 用户要求"加粗螺栓2mm"。我需要先找到所有螺栓。 Action: find_objects(label="bolt") Observation: 返回了 [id1, id2, id3] Thought: 找到了3个螺栓,现在执行偏移。 Action: offset_faces(object_ids=[id1,id2,id3], distance=2.0) Observation: 偏移成功,无自交。 Thought: 任务完成,回复用户。 Answer: 已成功加粗3个螺栓。LangChain实现:
pythonfrom langchain.agents import initialize_agent, Tool from langchain_openai import ChatOpenAI tools = [ Tool(name="find_objects", func=call_cad_find, description="根据标签查找物体"), Tool(name="offset_faces", func=call_cad_offset, description="偏移物体表面") ] agent = initialize_agent(tools, ChatOpenAI(), agent="zero-shot-react-description") agent.run("帮我把所有螺栓加粗2mm")Coze实现:在Bot的工作流中,添加"大模型节点",配置提示词和输出格式,然后接"代码节点"调用HTTP插件。
防止幻觉:
- 给LLM提供"原子操作列表",禁止它发明新操作。
- 要求LLM输出JSON Schema,并做校验。
- 让LLM在行动前先"反思"(Self-ask)。
5. 接口层:如何安全地暴露CAD控制API?
技术选型:
- WebSocket(双向通信,适合长连接,可推送进度)
- HTTP REST(简单,适合单次调用)
- gRPC(高性能,适合内部微服务)
本地WebSocket示例(C++,使用
websocketpp库):
cppclass CADWebSocketServer { public: void on_message(websocketpp::connection_hdl hdl, message_ptr msg) { auto json = nlohmann::json::parse(msg->get_payload()); if (json["action"] == "find") { auto ids = findObjectsByLabel(json["label"]); send(ids.dump()); } else if (json["action"] == "offset") { offsetFaces(json["object_ids"], json["distance"]); send("{\"status\":\"ok\"}"); } } };安全考虑:
- 只监听
127.0.0.1,不暴露到公网。- 加上简单的Token验证(防止本地其他恶意程序调用)。
- 限制请求频率,避免恶意循环。
6. 执行层:几何变换的细节
网格(STL)的偏移算法:
- 遍历每个三角形,计算单位法线(归一化后的叉积)。
- 三个顶点分别沿法线移动:
v' = v + normal * distance。- 注意:相邻三角形共享顶点,需要合并移动。做法:先收集所有受影响顶点的偏移量,再平均(或按面积加权)。
- 重新计算法线(用于光照)。
- 更新VBO,触发重绘。
精确几何(B-Rep)的偏移:
- Open CASCADE:
BRepOffsetAPI_MakeOffset- 内部算法:沿法线方向偏移曲面,再裁剪、缝合。
- 注意:偏移量过大会导致自交,需要检测并报错。
参数化建模(Code Interpreter模式):
- 嵌入Python:用
pybind11暴露C++类。- 安全沙箱:限制Python脚本的访问权限(文件、网络、CPU时间)。
- 示例暴露函数:
cppPYBIND11_MODULE(cad_api, m) { m.def("create_cylinder", &createCylinder, "半径", "高度"); m.def("boolean_union", &booleanUnion, "两个形状"); }
- 用户脚本:
import cad_api; bolt = cad_api.create_cylinder(5, 20); ...7. 零件语义化:让计算机认识"螺栓"
方案对比:
方法 原理 优点 缺点 人工打标签 用户手动框选三角形 100%准确 费时 文件名/图层约定 按规则命名(如 bolt_*)简单 依赖用户习惯 STEP语义 读取标准格式中的产品结构 工业标准 需要用户提供STEP而非STL 几何特征识别 基于曲率、厚度、螺纹特征 自动化 算法复杂,可能误判 深度学习分割 PointNet++等直接识别点云 前沿 需要训练数据,推理慢 你的项目实现 :混合策略。优先用STEP语义;如果没有,尝试基于文件名(如
bolt.stl);再不行,让用户手动标记一次,保存标记结果到附属文件。8. 进阶挑战深度解析
多模态交互:视觉定位
- 实现"点击屏幕识别物体"的技术:ID Render Pass 。
- 正常渲染前,额外渲染一次"ID Pass":每个物体用唯一颜色(如物体索引映射为RGB)。
- 鼠标点击时,读取该像素的颜色,解码回物体ID。
- 将物体ID和截图一起发给多模态LLM,LLM就能理解"这颗"指的是ID。
- GPT-4o的输入:
[图像] + [鼠标坐标] + [文字],模型输出物体ID。Code Interpreter的安全沙箱:
- 限制内存 :
setrlimit(RLIMIT_AS, ...)- 限制CPU时间 :
alarm()或sandbox2- 限制模块导入 :重写
__import__,只允许白名单模块- 隔离文件系统 :用
chroot或Docker容器执行脚本- 参考:Google的Sandboxed API 、Python的RestrictedPython
性能优化:
- LLM推理延迟:用本地小模型(如Phi-3、Llama 3 8B)量化后,可在CPU上实时运行。
- WebSocket消息:批量传输,减少往返。
- 几何变换:对于大量物体,用OpenMP并行处理每个三角形的偏移。
9. 完整项目架构图
┌─────────────────────────────────────────────────────────────┐ │ 用户界面 (语音/文字) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Coze / LangChain (控制端) │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ 感知层(NLP) │→│ 决策层(LLM) │→│ 规划与工具调用 │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ WebSocket / HTTP ▼ ┌─────────────────────────────────────────────────────────────┐ │ 你的 CAD C++ 程序 (执行端) │ │ ┌─────────────────────────────────────────────────────────┐│ │ │ 接口层: WebSocket Server, 解析JSON, 调用核心函数 ││ │ └─────────────────────────────────────────────────────────┘│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ 几何内核 │ │ 渲染管理器 │ │ Python解释器 │ │ │ │ (OCCT/自研) │ │ (OpenGL) │ │ (Code Interpreter)│ │ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ └─────────────────────────────────────────────────────────────┘10. 学习路线总结
- 入门:用Coze拖拽一个Bot,调用公开API(如天气查询),理解Agent概念。
- 进阶:用LangChain + OpenAI搭建本地Agent,实现"查找+偏移"两个工具。
- 实践:给你的CAD项目加上WebSocket接口,用Python脚本调用,实现"语音控制"。
- 深入:研究ReAct论文,自己实现一个简单的Agent循环(不用LangChain)。
- 精通:集成多模态模型、Code Interpreter沙箱,优化延迟和安全性。
你现在已经掌握了从零构建"CAD助手"的全部知识。剩下的就是动手写代码了。记住:AI不会取代CAD开发者,但会用AI的CAD开发者会取代不用AI的。
-
如果想了解一些成像系统、图像、人眼、颜色等等的小知识,快去看看视频吧 :
- 抖音:数字图像哪些好玩的事,咱就不照课本念,轻轻松松谝闲传
- 快手:数字图像哪些好玩的事,咱就不照课本念,轻轻松松谝闲传
- B站:数字图像哪些好玩的事,咱就不照课本念,轻轻松松谝闲传
- 认准一个头像,保你不迷路:

- 认准一个头像,保你不迷路:
-
您要是也想站在文章开头的巨人的肩膀啦,可以动动您发财的小指头,然后把您的想要展现的名称和公开信息发我,这些信息会跟随每篇文章,屹立在文章的顶部哦
