Rhino Coder 7B

A fine-tuned Qwen2.5-Coder-7B-Instruct model specialized for Rhino3D Python scripting β€” generating correct rhinoscriptsyntax and RhinoCommon code from natural language instructions.

This is the fused model (LoRA weights merged into base). For the standalone LoRA adapter, see rhino-coder-7b-lora.

Why Fine-Tune?

The base Qwen2.5-Coder-7B is a strong general code model, but it doesn't know Rhino's APIs. On 10 held-out Rhino scripting tasks:

Metric Base Model Fine-Tuned Delta
Avg code lines 11.9 8.2 -3.7 (more concise)
Avg code chars 427 258 -40% less bloat
  • Base model hallucinates APIs β€” invents Rhino.Commands.Command.AddPoint(), rs.filter.surface, rg.PipeSurface.Create() β€” none of these exist
  • Fine-tuned uses correct APIs β€” rs.CurveAreaCentroid(), rs.AddPipe(), rs.GetObject("...", 8) with the right filter constants
  • Fine-tuned matches reference style β€” several outputs are near-identical to the reference solutions

Example β€” "How do I find the centroid of a closed curve?"

# BASE MODEL β€” wrong (averages control points, not area centroid)
def find_centroid(curve_id):
    points = rs.CurvePoints(curve_id)
    centroid = [0, 0, 0]
    for point in points:
        centroid[0] += point[0]
        centroid[1] += point[1]
        centroid[2] += point[2]
    centroid[0] /= len(points)
    return centroid

# FINE-TUNED β€” correct, concise
crv = rs.GetObject('Select closed curve', 4)
if crv and rs.IsCurveClosed(crv):
    centroid = rs.CurveAreaCentroid(crv)
    if centroid:
        rs.AddPoint(centroid[0])

Usage

With MLX (Apple Silicon)

pip install mlx-lm
from mlx_lm import load, generate

model, tokenizer = load("quocvibui/rhino-coder-7b")

messages = [
    {"role": "system", "content": "You are an expert Rhino3D Python programmer. Write clean, working scripts using rhinoscriptsyntax and RhinoCommon. Include all necessary imports. Only output code, no explanations unless asked."},
    {"role": "user", "content": "Create a 10x10 grid of spheres with radius 0.5"},
]

prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
output = generate(model, tokenizer, prompt=prompt, max_tokens=1024)
print(output)

As an OpenAI-compatible server

mlx_lm server --model quocvibui/rhino-coder-7b --port 8080

Then query it like any OpenAI-compatible API:

import requests

response = requests.post("http://localhost:8080/v1/chat/completions", json={
    "model": "default",
    "messages": [
        {"role": "system", "content": "You are an expert Rhino3D Python programmer. Write clean, working scripts using rhinoscriptsyntax and RhinoCommon. Include all necessary imports. Only output code, no explanations unless asked."},
        {"role": "user", "content": "Draw a spiral staircase with 20 steps"}
    ],
    "max_tokens": 1024,
    "temperature": 0.1
})
print(response.json()["choices"][0]["message"]["content"])

Training Details

Method

LoRA (Low-Rank Adaptation) fine-tuning via MLX-LM, then fused into the base model.

Hyperparameters

Parameter Value
Base model Qwen2.5-Coder-7B-Instruct (4-bit)
Method LoRA
LoRA rank 8
LoRA scale 20.0
LoRA dropout 0.0
LoRA layers 16 / 28
Batch size 1
Learning rate 1e-5
Optimizer Adam
Max sequence length 2,048
Iterations 9,108 (2 epochs)
Validation loss 0.184
Training time ~1.2 hours on M2 Max

Dataset

5,060 instruction-code pairs for Rhino3D Python scripting (90/10 train/val split):

Source Count
RhinoCommon API docs 1,355
RhinoScriptSyntax source 926
Official samples 93
Synthetic generation 187
Backlabeled GitHub 1

API coverage:

API Pairs
RhinoCommon 1,409
rhinoscriptsyntax 1,134
rhino3dm 18
compute 1

Data was cleaned aggressively β€” 10,252 entries excluded from 12,814 total raw entries. Filters removed trivial getters, boilerplate, placeholder code, C#-only types, and duplicates.

Chat format

{
  "messages": [
    {"role": "system", "content": "You are an expert Rhino3D Python programmer..."},
    {"role": "user", "content": "<instruction>"},
    {"role": "assistant", "content": "<python code>"}
  ]
}

Intended Use

  • Generating Python scripts for Rhino3D (rhinoscriptsyntax / RhinoCommon)
  • Computational design and 3D modeling automation
  • Interactive code generation in a Rhino 8 REPL workflow

Limitations

  • Trained on Rhino3D Python APIs only β€” not a general-purpose coding model
  • Best results with rhinoscriptsyntax (rs.*) and RhinoCommon (Rhino.Geometry.*)
  • May not cover every API method β€” training data focused on the most commonly used patterns
  • Quantized to 4-bit β€” some precision tradeoffs vs. full-precision models
  • Optimized for MLX on Apple Silicon; for GPU inference, you may need to convert weights

Links

Downloads last month
49
Safetensors
Model size
8B params
Tensor type
F16
Β·
MLX
Hardware compatibility
Log In to add your hardware

Quantized

Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for quocvibui/rhino-coder-7b

Base model

Qwen/Qwen2.5-7B
Adapter
(378)
this model
Adapters
1 model