Downloads · 30 days
33
9% of all-time downloads
VertexAGI/copal-1-mini
copal-1-mini is a text generation model from VertexAGI. Use it when you need the model to write or continue text. It is set up for mlx. The card lists the license as gemma.
Copal 1 Mini is an agentic, tool-calling fine-tune of Gemma 3 4B IT — trained to decide when to call a tool, select the right one, interpret its result, and either continue acting or respond, using a lightweight text-…
Downloads · 30 days
33
9% of all-time downloads
All-time downloads
354
Public
Parameters
4.6B
2.6 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors2.6 GB · 99%
How the weights are stored.
U324.6B · 100%
From the Hugging Face model README
Copal 1 Mini is an agentic, tool-calling fine-tune of Gemma 3 4B IT — trained to decide when to call a tool, select the right one, interpret its result, and either continue acting or respond, using a lightweight text-based <tool_call> / <tool_result> convention. It is the first model in the Copal series, focused on tool-use judgment rather than general chat.
| Developed by | Independent research project |
| Base model | google/gemma-3-4b-it |
| Fine-tuning base checkpoint | mlx-community/gemma-3-4b-it-qat-4bit |
| Architecture | Gemma 3, 4B parameters (dense, decoder-only transformer) |
| Fine-tuning method | LoRA (rank 8, scale 20.0), fused into the base weights |
| Fine-tuning framework | MLX / mlx-lm, on Apple Silicon |
| Trained modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj across 16 layers |
| Weights | Released 4-bit quantized (same quantization as the QAT base checkpoint), fused with the adapter — not dequantized |
| Language | English |
| License | Gemma Terms of Use |
Copal 1 Mini was trained on a simple, model-native text convention rather than a JSON-schema function-calling API. The assistant emits:
<tool_call>
{"name": "tool_name", "arguments": {"key": "value"}}
</tool_call>
and the caller returns:
<tool_result name="tool_name">
{...result...}
</tool_result>
as the next user turn. This loop repeats until the model responds with plain text instead of a <tool_call> block. See Usage below for a full example.
Copal 1 Mini was fine-tuned on 930 cleaned agentic trajectories (of 1,152 originally generated, with malformed/incomplete ones filtered out), distilled from z-ai/glm-5.2 via the NVIDIA NIM API. Each trajectory is a full multi-turn tool-use episode: a task prompt, the model's tool call(s), simulated tool results, and either further calls or a final response.
Tasks span 10 agentic categories, generated programmatically across many entities (companies, endpoints, databases, file paths, etc.) to avoid template overfitting:
Evaluated against the un-tuned base model on 12 held-out agentic tasks (not seen during training), using the same simulated tool environment and RNG seed for both arms so they see identical tool results:
| Used tools when appropriate | Tool-call parse errors | |
|---|---|---|
| Base (Gemma 3 4B IT) | 8 / 12 | 0 |
| Copal 1 Mini | 11 / 12 | 0 |
Copal invokes tools in more of the situations that call for them, with no degradation in output-format reliability.
Copal 1 Mini is intended for experimentation with lightweight, locally-run agentic/tool-calling assistants — task automation, API orchestration, and agent-loop research on consumer hardware. It is not intended for high-stakes, safety-critical, or production use, and it does not use a JSON-schema/OpenAI-style function-calling interface — integrate it via the <tool_call>/<tool_result> convention above, or adapt your tool-calling harness to it.
from mlx_lm import load, generate
from mlx_lm.sample_utils import make_sampler
model, tokenizer = load("VertexAIco/copal-1-mini")
system_prompt = """You are Copal, an agentic assistant with access to tools.
When you need a tool, respond with exactly:
<tool_call>
{"name": "...", "arguments": {...}}
</tool_call>
Otherwise, respond normally in plain text."""
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": "Check the status of https://api.example.com/health and tell me if it's up."},
]
prompt = tokenizer.apply_chat_template(messages, add_generation_prompt=True)
text = generate(model, tokenizer, prompt=prompt, max_tokens=300, sampler=make_sampler(temp=0.0))
print(text)
# -> <tool_call>{"name": "http_request", "arguments": {"method": "GET", "url": "https://api.example.com/health"}}</tool_call>
# Execute the tool yourself, then feed the result back as the next user turn:
messages.append({"role": "assistant", "content": text})
messages.append({"role": "user", "content": '<tool_result name="http_request">\n{"status": 200, "ok": true}\n</tool_result>'})
prompt = tokenizer.apply_chat_template(messages, add_generation_prompt=True)
text = generate(model, tokenizer, prompt=prompt, max_tokens=300, sampler=make_sampler(temp=0.0))
print(text)
@misc{copal1mini,
title = {Copal 1 Mini},
author = {Independent research project},
year = {2026},
note = {LoRA fine-tune of Gemma 3 4B IT for agentic tool-calling, distilled from GLM 5.2}
}
This model is built on Gemma and subject to the Gemma Terms of Use.