【免费下载链接】gemma-4-12b-constraintkit-GGUF
gemma-4-12b-constraintkit 是一个把自然语言变成精确 CAD 装配体的 12B 开源模型,它最特别的地方不是"会建模",而是知道什么时候该说"我不会"。这篇文章逐行拆解仓库里的 train_sys.txt——训练时使用的系统提示词(system prompt)——看这短短 4 行文字如何给 AI 定下词汇表、连接规则和"诚实底线",并解释推理时为什么必须原样使用它。
一、先看项目全貌:它到底是个什么模型?
在拆提示词之前,先花 30 秒建立背景,否则很多规则会看不懂。
| 维度 | 说明 |
|---|---|
| 基座模型 | Gemma 4 12B,LoRA 微调(r=16),见 lora/ 目录下的 adapter_config.json |
| 任务 | 自然语言 → constraint-kit DSL 程序(零件 + 参数 + 连接),再由确定性数学内核编译成真实 B-rep 实体并导出 STEP |
| 产出文件 | 9.8 GB 的 Q6_K 量化模型 gemma4-12b-constraintkit-grpo-Q6_K.gguf,供 llama.cpp 本地运行 |
| 招牌能力 | 93% 的构建能通过真实几何校验;87% 的超纲请求会诚实拒绝,而不是拿错误零件糊弄你 |
关键点在于:这个模型不画网格(mesh),它只写一段"零件-参数-连接"的小程序,几何全部由 constraint-kit 的确定性求解器算出。所以输出的每一处尺寸都可以被校验——这也是它能被"驯服"诚实的前提。
二、train_sys.txt 全景:4 行文字,4 层任务
整个系统提示词只有 4 行,但信息密度极高。先看结构:
| 行号 | 内容 | 作用 |
|---|---|---|
| 第 1 行 | 任务定义 + 零件词汇表 + 连接(MATES)规则 + 诚实规则 | 教模型"说什么、怎么输出、什么时候闭嘴" |
| 第 2 行 | HONESTY 补充清单 | 把拒绝范围扩展到另一批"不能表达"的零件 |
| 第 3 行 | VITAMINS 库件调用规范 | 开一个受控的"后门":少量可直接渲染的库件 |
| 第 4 行 | "N 件套"约定 | 处理"a set/pack of N 个相同零件"的边界情况 |
下面逐行拆解。
三、第 1 行拆解:任务、词汇表与诚实规则
第 1 行是最长的一行(train_sys.txt#L1),其实可以切成 4 个语义块。
3.1 任务定义:只输出 JSON,不许说人话
开头就锁死了输入输出契约:
Translate a plain-English mechanical-part/assembly description into a constraint-kit DSL program.Output ONLY JSON:
{"parts":[{"id","type","material","params":{...}}],"mates":[...]}
注意 "ONLY" 和结尾再次强调的 "Output JSON only, no prose"——首尾呼应,是典型的防跑偏写法:模型在推理后必须交出纯 JSON,方便下游程序直接解析,不用清洗自然语言。
3.2 零件词汇表:一个封闭的"合法零件世界"
第 1 行用分号串起了 11 种零件类型和参数(单位 mm),这是全文最核心的设计——词汇表是封闭的:
| 零件类型 | 参数 | 一句话理解 |
|---|---|---|
spacer | outer_d, bore_d, height | 垫圈/衬套,轴孔垫圈类零件 |
spur_gear | module, teeth, width, bore_d | 直齿圆柱齿轮 |
plate | width, depth, thick, boss_d, boss_h, bolt_d, bolt_circle, bolt_count | 带凸台和螺栓孔的底板 |
shaft | diameter, length | 轴 |
washer | outer_d, bore_d, thick | 平垫圈 |
nut | af, height, bore_d | 六角螺母 |
bolt | shank_d, length, head_d, head_h | 螺栓 |
panel | width, depth, height | 薄壁面板 |
link | length, width, thickness | 连杆(四杆机构用) |
housing | width, depth, height, wall, bore_d | 带壁厚的壳体 |
sheet_bracket | thickness, base_length, flange_length, width | 折弯钣金支架 |
这套词汇表同时出现在 README.md 的 Limitations 一节——它划定了模型的能力边界:词汇表之外的东西,正确行为就是拒绝。
3.3 MATES 连接规则:给零件"装配语法"
有了零件还不够,零件之间怎么装?第 1 行给出了两套表达法:
- 意图式:
{"a","b","intent"},intent 取seat_on(坐落)、insert(插入)、fasten(紧固)、mesh(啮合)——口语化,适合"把垫圈套在轴上"这种描述; - 几何式:
{"a","a_joint","b","b_joint","type"},type 取coincident / rigid / contact / mesh / revolute——精确指定两个零件的哪两个配合面之间是什么装配关系。
同时提示词给出了各零件的锚点(anchor)命名:plate 有mount和bolt0..N,spur_gear 有bore_base / bore_top,spacer 有top / bottom,并规定第一个零件是固定基准(The FIRST part is the fixed base)。这一段相当于给装配体定下了"谁是地基",防止模型把装配关系挂空。
3.4 HONESTY RULE:全文的灵魂
第 1 行末尾是行最后一段:
if the description needs a part type or feature you have NO match for …do NOT substitute a different part— output exactly
{"unsupported":"<what you cannot express>"}
这是整份提示词里最有价值的一句。它做三件事:
- 禁止近似替代:想要螺旋伞齿轮?不许偷换成直齿锥齿轮"先凑合交付";
- 给出固定拒绝格式:
{"unsupported": "..."},让下游程序能机器识别"这次没辙"; - 拒绝时要说出缺的是哪个变体——README 里的例子是"我需要螺旋锥齿轮",模型会回答"只建模了直齿锥齿轮",而不是含糊其辞。
这就是标题里"诚实"的来源:拒绝本身被设计成了一种合法的、可校验的输出格式。
四、第 2 行拆解:把拒绝清单再扩大一圈
第 2 行 以HONESTY:开头,是对第 1 行诚实规则的补充,列出了另一批明确"表达不了"的零件:jaw/flexible coupling(爪式/弹性联轴器)、living or concealed hinge(隐形铰链)、spiral bevel(螺旋锥齿轮)、worm WHEEL(蜗轮)、tapered/needle/thrust bearing(锥/滚针/推力轴承)、cam(凸轮)、spring(弹簧)、universal joint(万向节)、keyway(键槽)、spline(花键)、timing/GT2 pulley(同步带轮)。
值得对比的一个细节:第 1 行说"helical/bevel/worm gear 不能建模",而第 3 行的 VITAMINS 又提供了bevel_gear和worm库件——闭合物语表 + 受控例外,边界划得非常清楚。
五、第 3 行拆解:VITAMINS——受控的"库件后门"
第 3 行(train_sys.txt#L3)定义了 VITAMINS(维生素,即"库件"):用{"type":"vitamin","params":{"scad":"<call>","name":...,"fn":48}}的格式调用预渲染的库零件,包括:
nema_stepper_motor(17/23 号 NEMA 步进电机)rack(齿条)worm(蜗杆)bevel_gear(锥齿轮)knuckle_hinge(铰链,支持union()组合出活页铰链)
这行提示词的设计意图是:模型不需要"懂"这些复杂零件的几何,只需会在正确时机引用库件。README 里那台 NEMA 步进电机装配,就是靠这种 vitamin 库件放上去的。它把模型的职责进一步收窄到"决策选什么",几何细节全部外包给库。
六、第 4 行拆解:"N 件套"的边界情况
最后一行只有一条规则(train_sys.txt#L4):
A 'set/pack of N' identical parts = N parts and mates [].
即用户说"3 个一样的垫圈叠起来"时,输出 3 个零件、mates 留空(或由后续意图式连接补上)。这种把高频歧义场景写进提示词的做法,省去了训练数据里反复纠偏的成本。
七、为什么推理时必须原样使用这份系统提示词?
README.md 在 Files 一节把话说得很死:train_sys.txt 是Required,because the model was not trained on any other prompt(模型只在它上面训练过,换任何措辞都等于换了一个它没学过的任务)。这也解释了推理流程为什么长这样:
- 用 llama.cpp 加载模型:
llama-server -m gemma4-12b-constraintkit-grpo-Q6_K.gguf -c 8192 -ngl 99 --port 8086- 调用
/completion时,system 轮以<|think|>开头、把 train_sys.txt 全文原样塞入、以<turn|>结束,采样参数保持低温(temperature 0.2)以稳定 JSON 输出; - 模型先输出一段推理(thinking trace),再输出 JSON 程序或
{"unsupported": ...}——所以它"会展示思考过程",你可以看到它为什么选这个零件、为什么拒绝。
💡 对新手来说,最容易踩的坑就是"提示词自己随便改两句"。对这个模型而言,系统提示词不是风格偏好,而是训练分布的一部分。
八、这份提示词"驯化"出了什么?训练结果速览
提示词定规则,训练把规则练成习惯。根据 README.md 的 Results 表:
| 阶段 | 几何校验通过的构建 | 诚实拒绝 |
|---|---|---|
| SFT(bf16) | 56/60(93%) | 26/30(87%) |
| SFT(Q6_K GGUF) | 55/60(92%) | 25/30(83%) |
| SFT + GRPO(本模型) | 6/6 保持 | 9/10,错误变体"偷换构建"减半 |
GRPO 阶段的奖励模型没有用 LLM 打分,而是直接拿 constraint-kit 的 DSL 校验器当奖励:检查通过、能构建、几何签名接近才得分。这正是"诚实"能被量化的原因——能不能拒绝、拒绝得对不对,都可以被几何事实判卷。
九、使用边界与注意事项 ⚠️
README 的 Limitations 一节值得照单全收:
- 它只认识 train_sys.txt 里的词汇表,其余请求应该被拒绝;
- 拒绝仍是薄弱点:约 1/10 的超纲请求仍会被"近似构建"出来;
- 信任几何之前,先让输出过一遍 constraint-kit 的校验接口(
POST /dsl/verify)。
十、写在最后:这份系统提示词值得学什么 🎯
回看 train_sys.txt 的 4 行,它示范了一套很干净的小模型微调提示词工程:
- 闭集词汇表:明确列出"你会什么",而不是模糊地说"你是机械专家";
- 固定拒绝格式:把"我不会"变成可解析、可评分的输出;
- 规则首尾呼应:格式约束在开头和结尾各强调一次;
- 受控例外(VITAMINS):例外也写进契约,而不是留白;
- 提示词即训练分布:推理端原样复用,一个字都不改。
对于想本地跑一个"既会干活又不会瞎编"的专业领域小模型,这份 4 行提示词 + 校验器做奖励的配方,比任何花哨的话术都更值得抄。
相关文件索引:系统提示词 train_sys.txt · 使用说明 README.md · 量化模型 gemma4-12b-constraintkit-grpo-Q6_K.gguf · LoRA 配置 lora/adapter_config.json
【免费下载链接】gemma-4-12b-constraintkit-GGUF
相关推荐
不是提示词工程:Gemma-4-12B 三阶段微调如何造出"人味"
不是提示词工程:Gemma 4 12B 三阶段微调如何造出"人味" "AI 味"已经成了大模型文本最容易被一眼看穿的东西:句长均匀得像被排版过、连接词堆砌、"首
人工智能大模型微调本地部署AI 写作lm-evaluation-harness实战:gemma-4-12B-it-w8a8-llmcompressor评测命令参数逐个拆解
lm evaluation harness实战:gemma 4 12B it w8a8 llmcompressor评测命令参数逐个拆解 如果你想知道 AMD 推
如何正确喂给humanizer-12b-OptiQ-4bit输入?逐步拆解prompt_format.json提示词契约
如何正确喂给humanizer 12b OptiQ 4bit输入?逐步拆解prompt_format.json提示词契约 humanizer 12b OptiQ
大模型模型量化本地部署NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考