現(xiàn)text-to-cad:自然語言到STEP模型)
這兩年AI輔助設(shè)計(jì)的話題算是在行業(yè)里徹底熱起來了尤其是text-to-cad這個(gè)方向幾乎每次聊到都有人問真的輸一句人話就能出一份能用的CAD模型我的回答是能但得先把期望曲線拉平——它不是你喊一句“給我畫個(gè)飛機(jī)”就直接出裝配圖而是把自然語言里的幾何參數(shù)、約束關(guān)系、加工需求轉(zhuǎn)成一段可執(zhí)行建模腳本再通過CAD內(nèi)核生成帶尺寸的實(shí)體模型。我前前后后折騰了差不多一個(gè)多月用Python CadQuery搭了一套最小可用的text-to-cad工作流從一個(gè)“長寬高加四個(gè)孔”的描述到導(dǎo)出STEP整個(gè)過程不到二十秒。這篇文章就把我從選型到踩坑的完整過程拆開聊適合那些已經(jīng)在用CAD、又想用自動化思路提高建模效率的工程師也適合剛想入坑CAD制圖的新手。1. text-to-cad到底是什么從文本到可編輯模型的完整閉環(huán)1.1 一句話想法背后的真實(shí)需求text-to-cad最核心的價(jià)值不是“生成圖片”而是生成真正可以編輯、可以加工、可以進(jìn)裝配的CAD文件。你嘴上說“我要一塊400乘300乘10毫米的基板四角打直徑6毫米的孔孔心距離邊15毫米”系統(tǒng)要能理解長度、寬度、高度、陣列位置、孔徑這些維度再落到CAD內(nèi)核里創(chuàng)建特征。這和AI畫圖完全是兩條路圖片只是像素而CAD模型背后每一根邊線、每一個(gè)孔都帶著毫米單位的實(shí)體數(shù)據(jù)。我觀察到的真實(shí)需求分三類第一類是有經(jīng)驗(yàn)的工程師做重復(fù)性設(shè)計(jì)每天就是改幾個(gè)尺寸重新出圖torture得不行第二類是剛接觸CAD制圖的新人面對一堆草圖約束和命令覺得學(xué)習(xí)曲線太陡想通過自然語言降低門檻第三類是設(shè)計(jì)迭代階段需要快速對比多個(gè)尺寸方案手工逐個(gè)建模太慢text-to-cad正好適合做參數(shù)掃掠。這三類人其實(shí)都在問同一個(gè)問題能不能把“腦子里的形狀”快速變成“能用的模型文件”text-to-cad就是切這個(gè)題。1.2 技術(shù)鏈條其實(shí)沒有你想的那么玄完整鏈路可以拆成三段語義理解、參數(shù)映射、內(nèi)核建模。語義理解負(fù)責(zé)把用戶的話變成結(jié)構(gòu)化數(shù)據(jù)比如“四個(gè)角開孔”中的“四角”轉(zhuǎn)換成坐標(biāo)數(shù)組參數(shù)映射負(fù)責(zé)把用戶口語里的單位、參考基準(zhǔn)、特征類型對應(yīng)到CAD操作比如“距離邊15mm”翻譯成偏移約束內(nèi)核建模則是真正調(diào)用幾何內(nèi)核生成實(shí)體。很多人以為難點(diǎn)全在第一段實(shí)際上三段都有坑。第二段最容易被忽略同一個(gè)“四角”中文里可能指“兩個(gè)對角”“四個(gè)角點(diǎn)”還是“所有端點(diǎn)”模型必須靠上下文判斷。我常用一個(gè)小技巧在自然語言解析之后不直接建模而是先生成一個(gè)中間JSON把它打印出來給用戶確認(rèn)。這個(gè)JSON里會寫明operation、dimensions、hole_positions等字段相當(dāng)于讓AI先把“它聽到的內(nèi)容”復(fù)述一遍確認(rèn)無誤再往后走。這一步能擋掉大量歧義也方便調(diào)試。2. 技術(shù)方案選型為什么我最后選了Python CadQuery2.1 實(shí)現(xiàn)text-to-cad的幾條主流路線想實(shí)現(xiàn)“文本到模型”市面上大致有四條路。第一條是讓大模型直接輸出OpenSCAD代碼OpenSCAD本身就是腳本化建模代碼即模型非常契合自動生成第二條是讓大模型輸出CadQuery代碼CadQuery基于OpenCascade內(nèi)核支持STEP/STL/AMS等格式鏈?zhǔn)紸PI寫起來比OpenSCAD更接近人類建模直覺第三條是走AutoCAD的AutoLISP或pyautocad直接驅(qū)動AutoCAD內(nèi)部實(shí)體問題是依賴Windows環(huán)境和AutoCAD授權(quán)而且自動化程度容易被GUI卡住第四條是端到端的神經(jīng)網(wǎng)絡(luò)直接從文本體生成三維體素或點(diǎn)云再轉(zhuǎn)網(wǎng)格速度快但精度和可編輯性很難保證。這四條路各有取舍。如果你做的是機(jī)械零件、板件、外殼這類規(guī)則幾何OpenSCAD和CadQuery都夠用如果你要的是真正能放進(jìn)CAM加工的標(biāo)準(zhǔn)STEP文件CadQuery比OpenSCAD更直接因?yàn)镺penSCAD的導(dǎo)入經(jīng)常出現(xiàn)面片化損失如果想調(diào)用現(xiàn)成AutoCAD圖庫或者干脆就在AutoCAD生態(tài)里工作pyautocad也有價(jià)值但你需要先解決“cad安裝”“cad激活頁面腳本發(fā)生錯(cuò)誤”之類的軟件環(huán)境問題我這種開源潔癖基本不碰。2.2 我的選型邏輯與對比結(jié)論我最后選了“大模型生成結(jié)構(gòu)化JSON CadQuery執(zhí)行建?!钡慕M合。理由有三。第一CadQuery的API對參數(shù)化非常友好幾何實(shí)體是由一連串操作疊加出來的而這一連串操作正好可以由程序持久化、復(fù)用、批處理第二輸出STEP可以直接被中望CAD、SolidWorks、FreeCAD讀寫后續(xù)標(biāo)注、Layout布局都不受限制第三全鏈路開源不需要裝一堆破解工具也沒有“徹底卸載不影響二次安裝”那種難受的清理問題。選型過程中我列過一個(gè)對比表現(xiàn)在放出來給大家參考方案學(xué)習(xí)成本幾何精度文件兼容性適合場景OpenSCAD LLM低中等一般STL為主簡單外形快速嘗試CadQuery LLM中高B-Rep內(nèi)核STEP/STL/DXF/SVG都行真正可加工的機(jī)械件pyautocad高高與AutoCAD一致已有AutoCAD環(huán)境的重度用戶端到端神經(jīng)網(wǎng)絡(luò)中低網(wǎng)格文件為主概念造型、視覺預(yù)覽表格說明我的思路如果你是做結(jié)構(gòu)件、鈑金件、工裝夾具CadQuery那條線是性價(jià)比最高的。它不像端到端方案那樣“看起來聰明但落不了地”也不像pyautocad那樣被商業(yè)軟件綁定。2.3 環(huán)境準(zhǔn)備繞開那些安裝坑搭建環(huán)境時(shí)最大的坑是CadQuery的安裝。PyPI上的cadquery包目前要求Python 3.9到3.11之間如果你圖省事直接裝了3.12import就會報(bào)一堆DLL錯(cuò)誤。我建議直接用conda建獨(dú)立環(huán)境指定python3.10然后pip install cadquery。另外CadQuery底層依賴OpenCascadeWindows下會用到一些Visual C運(yùn)行庫。熱詞里那句“安裝cad一直出現(xiàn)c2005cpi錯(cuò)誤”描寫的其實(shí)就是這類問題你的系統(tǒng)缺VC Redistributable或者conda環(huán)境里混入了老版本的MSVC Runtime。解決辦法很簡單裝一下微軟官方的“Visual C Redistributable for Visual Studio”合集包再把conda環(huán)境重建一遍即可。這事別自己瞎折騰重裝系統(tǒng)什么的完全沒必要。3. 一個(gè)能跑通的最小系統(tǒng)從自然語言到STEP文件3.1 第一步先把自然語言翻譯成結(jié)構(gòu)化參數(shù)這一層我采用“提示詞模板”的方式而不是直接讓大模型寫CadQuery代碼。為什么不直接寫代碼因?yàn)榇a容易多出變量命名、注釋、錯(cuò)誤分支這些噪音后面解析困難而JSON是固定的鍵值結(jié)構(gòu)校驗(yàn)邏輯寫起來非常省心。我的提示詞大致長這樣你可以直接抄去改你是一個(gè)CAD參數(shù)解析器。用戶會給出機(jī)械零件的自然語言描述你需要提取出 - operation: 建模操作類型可選值為 box_with_holes, cylinder_with_holes, sweep_base - dimensions: 主尺寸對象包含length/width/height或diameter/height - fillet_radius: 統(tǒng)一圓角半徑?jīng)]有則填0 - hole_diameter: 孔徑?jīng)]有則填0 - hole_positions: 孔中心坐標(biāo)列表格式為[{x: 毫米, y: 毫米}] 如果描述中包含四角、四個(gè)孔等短語按中心距邊緣15mm推導(dǎo)。 只輸出JSON不要任何解釋。用戶輸入“400乘300乘10的基板四角開直徑6的孔孔心距邊15”大模型輸出的JSON就是{ operation: box_with_holes, dimensions: {length: 400, width: 300, height: 10}, fillet_radius: 0, hole_diameter: 6, hole_positions: [ {x: 15, y: 15}, {x: 385, y: 15}, {x: 385, y: 285}, {x: 15, y: 285} ] }注意這里有一個(gè)關(guān)鍵點(diǎn)LLM給出了“x: 385”而不是“長邊減去15”。CAD里很多孔位習(xí)慣用“距邊距”表達(dá)坐標(biāo)值本身是絕對定位如果你不把語言里的約束關(guān)系翻譯成坐標(biāo)后面建模就會經(jīng)常出現(xiàn)偏移半個(gè)板厚的情況。我專門在提示詞里強(qiáng)調(diào)了“按孔心距邊推導(dǎo)”這樣省去后面二次計(jì)算。3.2 第二步把參數(shù)扔給CadQuery生成模型拿到JSON之后建模部分就純粹了。核心是寫一個(gè)映射函數(shù)把JSON里的operation和字段變成CadQuery的鏈?zhǔn)秸{(diào)用。下面是我精簡過的最小實(shí)現(xiàn)import cadquery as cq def build_from_json(data): if data[operation] box_with_holes: length data[dimensions][length] width data[dimensions][width] height data[dimensions][height] fillet data.get(fillet_radius, 0) hole_d data.get(hole_diameter, 0) positions data.get(hole_positions, []) result cq.Workplane(XY).box(length, width, height) if fillet and fillet 0: result result.edges().fillet(fillet) if hole_d and positions: workplane result.faces(Z).workplane() for pos in positions: workplane workplane.pushPoint((pos[x], pos[y])) result workplane.hole(hole_d) return result # 其他operation可以繼續(xù)擴(kuò)展 raise ValueError(fUnsupported operation: {data[operation]})這個(gè)方法有個(gè)細(xì)節(jié)我在每個(gè)孔位都調(diào)用了pushPoint而不是用一次pushPoints傳入全部坐標(biāo)。CadQuery的hole()在同一個(gè)workplane上只會作用于當(dāng)前選擇的所有點(diǎn)如果你把四個(gè)點(diǎn)一次性pushPoints然后調(diào)hole四個(gè)孔確實(shí)會同時(shí)出現(xiàn)。但實(shí)踐下來分開pushPoint更利于后續(xù)給某個(gè)孔增加沉孔臺階或螺紋標(biāo)記程序結(jié)構(gòu)也更容易擴(kuò)展。3.3 第三步導(dǎo)出STEP/STL并快速預(yù)覽建模完成后導(dǎo)出是最后一道工序。CadQuery支持多種格式我的習(xí)慣是STEP為主、STL為輔。STEP文件保存的是B-Rep實(shí)體邊界表示能被主流CAD軟件讀取STL則是三角網(wǎng)格適合快速預(yù)覽和3D打印切片。cq.exporters.export(result, 基板.step) cq.exporters.export(result, 基板.stl)導(dǎo)出STL之前建議先設(shè)置弦偏差參數(shù)CadQuery的export函數(shù)默認(rèn)精度對大多數(shù)零件夠用但如果你做的是弧面較大的外觀件導(dǎo)出后可能出現(xiàn)明顯棱邊。這時(shí)可以在export前用result.val().tessellate(tolerance, angleTolerance)手動控制三角化密度再自己寫入STL。這里不展開提醒一句就夠了??焖兕A(yù)覽有一個(gè)很省事的辦法把模型導(dǎo)出成SVG投影。CadQuery自帶cq.exporters.export(result, preview.svg)它會按照當(dāng)前視圖生成一個(gè)2D線框預(yù)覽圖你不需要打開CAD軟件就能在瀏覽器里看到形狀對不對。我把它放在web界面上用戶提交一句描述后返回STEP下載鏈接和SVG縮略圖體驗(yàn)比直接發(fā)文件舒服很多。熱詞里“cad快速看”其實(shí)要的就是這個(gè)效果。4. 實(shí)操中跑出來的四條避坑經(jīng)驗(yàn)4.1 LLM參數(shù)不守規(guī)矩校驗(yàn)比生成更重要合規(guī)性校驗(yàn)是text-to-cad最容易被跳過、又最容易翻車的一環(huán)。大模型想象力豐富給你輸出一個(gè)負(fù)數(shù)的長度、孔徑大于板寬、孔位跑到零件邊界外面都是常規(guī)操作。不校驗(yàn)的話CadQuery輕則報(bào)錯(cuò)重則生成一個(gè)變形的怪異實(shí)體。我處理的辦法是寫一個(gè)參數(shù)校驗(yàn)函數(shù)在調(diào)用CadQuery之前先做一趟語義檢查。對box_with_holes我至少檢查所有尺寸都大于0孔徑小于板長和板寬的三分之一孔位x坐標(biāo)在孔徑一半到長度減孔徑一半之間y坐標(biāo)同理。不滿足條件的直接返回錯(cuò)誤提示讓用戶修改描述而不是讓程序硬著頭皮建模。實(shí)際測試下來加入校驗(yàn)后成功率從七成提到九成以上。剩下的失敗基本都是描述本身太模糊比如“一個(gè)中等的孔”沒有給出直徑這種系統(tǒng)沒法猜只能提示用戶補(bǔ)參數(shù)。4.2 坐標(biāo)系與語義之間的鴻溝CAD里的“四角開孔”在建模時(shí)到底該放哪這件事比你想的更值得較真。CadQuery里的Workplane是以XY平面為基準(zhǔn)box的左下角默認(rèn)在原點(diǎn)所以四角孔的坐標(biāo)是從原點(diǎn)開始算的。但很多用戶的口語習(xí)慣是從板子中心開始算比如“距離中心線各50mm”如果你不統(tǒng)一基準(zhǔn)孔位就會差出上百毫米。我后來在JSON結(jié)構(gòu)里增加一個(gè)可選的ref_point字段默認(rèn)是origin支持center或center_of_mass。在解析層就把參考基準(zhǔn)統(tǒng)一換算成以原點(diǎn)為基準(zhǔn)的絕對坐標(biāo)。這樣做的好處是用戶描述“中心對稱兩個(gè)孔”解析器也能處理不需要他記住每個(gè)孔的坐標(biāo)。這是text-to-cad里很有價(jià)值的一個(gè)設(shè)計(jì)決策。4.3 導(dǎo)出文件前先確認(rèn)單位和精度單位問題出現(xiàn)的頻率高到值得單列一條。CadQuery內(nèi)部默認(rèn)單位是毫米但如果你從某些渠道復(fù)制了以“cm”或“inch”描述的參數(shù)導(dǎo)出STEP時(shí)單位標(biāo)簽可能會變成英寸或保持無單位。很多軟件在導(dǎo)入STEP時(shí)按自帶單位推測尺寸結(jié)果一進(jìn)CAD里零件變成了原尺寸的25.4倍或0.1倍。我在導(dǎo)出前固定統(tǒng)一設(shè)置cq.exporters.export(result, path, exportTypeSTEP)然后在文件開頭檢查STEP頭部的單位關(guān)鍵字。另外建議在用戶描述里強(qiáng)制標(biāo)注單位提示詞里寫明“所有尺寸默認(rèn)毫米”。熱詞里有些人搜“cad圖紙合并”其實(shí)就是在對尺寸不一致的零件做適配如果源頭單位就亂后面合并時(shí)全亂套。4.4 安裝依賴時(shí)的常見報(bào)錯(cuò)與解決方案最后說說環(huán)境問題。熱詞里“安裝cad一直出現(xiàn)c2005cpi錯(cuò)誤”“cad激活頁面腳本發(fā)生錯(cuò)誤”這類搜索暴露的是Windows下軟件依賴混亂的普遍痛點(diǎn)。CadQuery的安裝也有類似的坑但沒那么玄。最常見的報(bào)錯(cuò)是ImportError: DLL load failed while importing OCP。我建議先檢查Python版本如果用的是3.9以下或3.12以上大概率版本不兼容其次檢查conda環(huán)境直接conda install -c conda-forge cadquery會比純pip少踩很多編譯鏈的坑。還有一個(gè)隱蔽問題如果你以前裝過舊版OpenCascade相關(guān)的包可能和cadquery的OCP發(fā)生沖突必須建新環(huán)境解決。還有一個(gè)來自熱詞但不局限的話題“cad如何徹底卸載不影響二次安裝”。這其實(shí)是新手對系統(tǒng)環(huán)境不放心。我的經(jīng)驗(yàn)是除非遇到嚴(yán)重沖突否則沒必要“徹底卸載”用conda管理項(xiàng)目環(huán)境才是最干凈的方案。想換版本就刪掉整個(gè)env對系統(tǒng)沒有任何殘留污染。5. 從玩具到工具text-to-cad的進(jìn)階玩法5.1 批量變體批量生成不同尺寸的零件當(dāng)你能把一個(gè)JSON轉(zhuǎn)成模型之后批量變化就是水到渠成的事。我日常最常用場景是生成一批相同結(jié)構(gòu)、不同尺寸的墊圈和框架零件。原來手工做一個(gè)要五分鐘用text-to-cad只需把參數(shù)列表丟進(jìn)一個(gè)for循環(huán)。variants [ {name: A型, length: 400, width: 300, height: 10, hole_d: 6}, {name: B型, length: 500, width: 320, height: 12, hole_d: 8}, {name: C型, length: 600, width: 350, height: 15, hole_d: 10}, ] for v in variants: data { operation: box_with_holes, dimensions: {length: v[length], width: v[width], height: v[height]}, fillet_radius: 0, hole_diameter: v[hole_d], hole_positions: [ {x: 15, y: 15}, {x: v[length]-15, y: 15}, {x: v[length]-15, y: v[width]-15}, {x: 15, y: v[width]-15} ] } part build_from_json(data) cq.exporters.export(part, f{v[name]}.step)這里有熱詞“python批量對cad修改”的影子和apply思路。批量生成時(shí)我給每個(gè)文件名的模板字段寫在JSON詞典里實(shí)際上就是一個(gè)微型產(chǎn)品配置表。再結(jié)合工程變更單改動非常快。這比打開CAD、一個(gè)個(gè)雙擊改尺寸再導(dǎo)出要可靠得多而且不會漏改。5.2 裝配到一起讓單零件走向部件單零件生成只是起點(diǎn)真正到做產(chǎn)品結(jié)構(gòu)時(shí)需要把多個(gè)文本生成的零件按位置關(guān)系裝起來。CadQuery里有Assembly類可以把每個(gè)零件通過add(part, loccq.Location(...))放進(jìn)同一個(gè)裝配坐標(biāo)系然后導(dǎo)出STEP裝配文件。我常用一個(gè)辦法先在文本層約定好基準(zhǔn)點(diǎn)比如“上板左下角放在坐標(biāo)原點(diǎn)四個(gè)安裝孔對應(yīng)立柱位置”程序生成每個(gè)子零件后用同一個(gè)location對象裝配。這樣從文本描述到裝配體只差一步。熱詞里“cad圖紙合并”在傳統(tǒng)CAD里是靠外部引用、塊、新建Layout來做但在CadQuery的代碼世界里合并就是數(shù)學(xué)坐標(biāo)變換反而更直觀。5.3 和主流CAD軟件協(xié)同導(dǎo)入、標(biāo)注、Layout布局text-to-cad的目的不是替代CAD而是把讓機(jī)器頭疼的重復(fù)結(jié)構(gòu)化建模先做掉再把人拉回真正的設(shè)計(jì)工作中。我目前的工作流是用text-to-cad生成STEP基礎(chǔ)件然后在主流CAD軟件里做標(biāo)注、裝配、出圖。很多朋友會問“cad導(dǎo)入layout步驟詳解”其實(shí)在主流CAD軟件里導(dǎo)入STEP后進(jìn)入布局空間調(diào)整視口比例、標(biāo)注尺寸流程穩(wěn)定。CadQuery導(dǎo)出的STEP文件從底層是B-Rep實(shí)體不像網(wǎng)格文件那樣會有碎面因此標(biāo)注時(shí)可以直接選面選邊非常順滑。中望CAD、AutoCAD都能正常打開不需要轉(zhuǎn)線框。這一步的額外好處是設(shè)計(jì)師可以把“重復(fù)勞動”甩給文本管線自己專心處理公差、表面處理、工藝結(jié)構(gòu)這些機(jī)器不擅長的事情。我試過讓實(shí)習(xí)生用這套流程做一個(gè)鈑金外殼原來一天的工作量縮到半天還不容易出錯(cuò)。這也讓我更看好text-to-cad的落地價(jià)值——它不制造“全自動”但實(shí)實(shí)在在把“半自動”做出了生產(chǎn)力。最后再說一點(diǎn)個(gè)人體會不要迷信一步到位的端到端生成也不要覺得必須懂圖形學(xué)才能玩。我實(shí)際用下來最順手的方式是把text-to-cad當(dāng)成草稿生成器和參數(shù)探索器先快速出模型再人工調(diào)整細(xì)節(jié)效率提升非常明顯。如果你正被重復(fù)建模折磨不妨從今天這個(gè)最小工作流開始把第一句“給我一塊板子四角打孔”變成自己的第一個(gè)STEP文件。