Text Generation
MLX
Safetensors
English
gemma3
gemma
lora
agentic
tool-calling
function-calling
distillation
conversational
4-bit precision
Instructions to use VertexAIco/copal-1-mini with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use VertexAIco/copal-1-mini with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("VertexAIco/copal-1-mini") prompt = "Write a story about Einstein" messages = [{"role": "user", "content": prompt}] prompt = tokenizer.apply_chat_template( messages, add_generation_prompt=True ) text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- MLX LM
How to use VertexAIco/copal-1-mini with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Interactive chat REPL mlx_lm.chat --model "VertexAIco/copal-1-mini"
Run an OpenAI-compatible server
# Install MLX LM uv tool install mlx-lm # Start the server mlx_lm.server --model "VertexAIco/copal-1-mini" # Calling the OpenAI-compatible server with curl curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "VertexAIco/copal-1-mini", "messages": [ {"role": "user", "content": "Hello"} ] }'
| license: gemma | |
| base_model: google/gemma-3-4b-it | |
| language: | |
| - en | |
| library_name: mlx | |
| pipeline_tag: text-generation | |
| tags: | |
| - gemma | |
| - gemma3 | |
| - lora | |
| - mlx | |
| - agentic | |
| - tool-calling | |
| - function-calling | |
| - distillation | |
| # Copal 1 Mini | |
| **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. | |
| ## Model Details | |
| | | | | |
| |---|---| | |
| | **Developed by** | Independent research project | | |
| | **Base model** | [google/gemma-3-4b-it](https://huggingface.co/google/gemma-3-4b-it) | | |
| | **Fine-tuning base checkpoint** | [mlx-community/gemma-3-4b-it-qat-4bit](https://huggingface.co/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](https://github.com/ml-explore/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](https://ai.google.dev/gemma/terms) | | |
| ## Tool-Calling Format | |
| 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. | |
| ## Training Data | |
| 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: | |
| - API orchestration | |
| - State tracking | |
| - Tool selection | |
| - Multi-step planning | |
| - Clarification (recognizing under-specified requests) | |
| - Error recovery | |
| - Read-and-decide (branching on tool output) | |
| - Concise execution | |
| - Browser workflow | |
| - Structured output | |
| ## Training Procedure | |
| - **Method:** Supervised fine-tuning via LoRA (rank 8, dropout 0.0, scale 20.0) | |
| - **Optimizer:** Adam, learning rate 1e-5 (constant schedule) | |
| - **Sequence length:** 4096 tokens (agentic trajectories run long — multiple tool round-trips per example) | |
| - **Gradient checkpointing:** enabled | |
| - **Training steps:** 2,500 iterations, with validation every 50 steps | |
| - **Checkpoint selection:** the released weights use the **iteration 2,250 checkpoint**, selected for lowest validation loss (0.236); validation loss plateaued with noise from ~iteration 1,000 onward rather than continuing to improve, so later checkpoints offered no reliable benefit on this dataset size | |
| ## Evaluation | |
| 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. | |
| ## Intended Use | |
| 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. | |
| ## Limitations | |
| - Trained on a small (930-example), synthetically generated dataset — behavior can be inconsistent outside the categories represented in training. | |
| - Distilled from a single teacher model without human review of every trajectory; teacher biases or occasional tool-use mistakes may be present. | |
| - Uses a custom tool-call text format, not a standardized function-calling schema — not a drop-in replacement for APIs expecting OpenAI-style tool calls. | |
| - Inherits the general limitations and knowledge cutoff of its base model, Gemma 3 4B IT. | |
| - This is an early, first-generation checkpoint in an ongoing series. | |
| ## Usage | |
| ```python | |
| 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) | |
| ``` | |
| ## Citation | |
| ``` | |
| @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](https://ai.google.dev/gemma/terms). | |