说实话,对「用代码画 3D」这事并不陌生:能写,但写起来是真累。调坐标、算偏移、盯着 bpy 的函数名猜参数——一个简单的零件搞下来,代码比模型还重。
但这次不一样。Sandflow 这家公司做了件很聪明的事:他们写了一个专门给 LLM 用的 3D 语言。

CadQuery 是给人类工程师写的,FeatureScript 是给 Onshape 生态写的,Blender Python 是给 Blender 插件写的。而 Sand3D,从第一行 API 开始,就盯着一个目标:让大模型能轻松看懂、轻松生成、轻松修改 3D 物体。
他们做了两件事:第一,把 API 砍到极致精简,整个函数库塞进一个系统提示词里都够(约 3600 tokens);第二,把传统 CAD 里那些需要手动计算坐标的操作,全换成了「按名字找」。
同一个零件,用 Blender Python 写要 4 倍 token,CadQuery 要 2.3 倍,FeatureScript 要 6 倍。在 LLM 的世界里,token 就是钱。
Sand3D 是什么?
一句话:Sand3D 是一个跑在 Blender 上、为大语言模型设计的 Python 3D 建模库。

由法国里昂的初创公司 Sandflow 开发,2026 年 11 月 5 日正式开源,同时放出了用 Sand3D 代码写成的 10 万个 3D 物体数据集。
核心亮点
1. Token 效率碾压同类
官方做了详细的逐零件 token 对比统计,中位数来看:Blender Python 4.0 倍,CadQuery 2.3 倍,FeatureScript 6.0 倍,Articraft SDK 2.0 倍。这意味着同一个零件,LLM 用 Sand3D 写只需要别家 1/2 到 1/6 的 token。
2. 整个 API 塞进一个 Prompt
Sand3D 的完整 API 文档只有约 3600 tokens。你可以把整个 Sand3D 语言手册直接放进 system prompt,模型就能完整理解每一个函数的签名和用法。
3. 命名驱动,拒绝坐标地狱
传统 CAD 编程里,最折磨人的不是画形状本身,是找位置。Sand3D 把这套全换掉了。创建的每个对象、每个特征都有名字,后续操作用名字引用。不是 plate.faces[3].edges[1],而是 "top"。不是算坐标偏移,而是 s3d.grid() 自动布局。
plate = s3d.extrude("plate", s3d.rect(80, 40, r=4), 6)
s3d.hole(plate, 6.6, on=s3d.grid(2, 1, 50, 0))
s3d.fillet(plate, 1, edges="top")
4. 确定性输出(Deterministic)
同一段代码,跑一万遍,生成的网格 bit for bit 完全一致。工程需要可复现的结果,而不是每次都稍微不一样的「艺术创作」。
5. 关节和装配是一等公民
Sand3D 原生支持关节(joints)和装配(assemblies)。用一台滚筒洗衣机做示例——38 行代码搞定铰链门、旋转滚筒、伸缩抽屉、转动旋钮。每种运动都能精确描述,还能导出成 URDF 和 USD,直接喂给 ROS、PyBullet、MuJoCo、Isaac 这些机器人仿真器。
door = s3d.group("door", ring, glass, handle)
s3d.joint("door_hinge", door, hinge, axis="-Z", range=(0, 143))
s3d.joint("drum_spin", drum, front.move(0, 400), kind="continuous")
s3d.joint("drawer_slide", drawer, top_band.move(150), kind="prismatic", axis="+X", range=(0, 200))
return s3d.assembly("washing_machine", cab, drum, door, drawer, dial, front=front)
6. 数据集规模:10 万个,其中 1 万+ 带关节
这次开源的数据集覆盖了 5 个来源,总计 106,094 个 3D 物体:机械零件(螺丝、齿轮、轴承等)、家具(桌子、椅子、灯具)、交通工具(汽车、自行车)、玩具和乐器(钢琴、吉他)、日常用品(洗衣机、吹风机)。其中 10,456 个是带关节的可动模型,关节总数超过 36,000 个。
快速上手
安装只需一行:pip install sand3d 或 uv add sand3d。Blender 自带 bpy 模块,不需要单独装。
import sand3d as s3d
def bracket(w=80, d=40, t=6, hole_d=6.6, pitch=50):
plate = s3d.extrude("plate", s3d.rect(w, d, r=4), t)
s3d.hole(plate, hole_d, on=s3d.grid(2, 1, pitch, 0))
s3d.fillet(plate, 1, edges="top")
return plate
s3d.export(bracket(), "bracket.glb")
导出格式也只需改扩展名:GLB(网页/游戏引擎)、URDF(ROS/PyBullet/MuJoCo)、USDA(Omniverse/Isaac Sim)、OBJ/STL(通用 3D 工具/3D 打印)。
喂给 LLM 的方法很简单:把 docs/api.md 里的内容放进 system prompt,模型自然就会用这门语言生成 3D 物体代码。
写在最后
Sand3D 在语言设计层面给填平了。token 效率的数据摆在那,10 万数据集的规模摆在那,这不是玩具项目。而且它的成功某种程度上也说明了当前 AI 3D 领域的一个尴尬:生成式 3D 模型还没到能直接产生产级资产的程度,所以我们还得靠编程语言这条路。
Sand3D 做了一件有价值的事:它把「3D 资产」从黑盒网格文件,变成了可读、可编辑、可训练的程序代码。