Fine-tuning

[v4] GLM-4.7-Flash-Coder

Sergei Bratchikov, Konstantin Korolev, Oleg Smirnov, Mohamed Mekkouri, Dmitrii Kharlapenko, Daniil Oblakov in collaboration with others at White Circle

We fine-tuned GLM-4.7-Flash to boost its agentic coding capabilities: +26% on SWE-rebench-V2, at 14% lower inference cost.

This 30B Mixture-of-Experts model beats competitors 3-4× its size: Qwen3.5-122B-A10B, Ling-2.6-Flash, and Devstral-2.

Agentic coding score against cost · SWE-rebench-V2

better ↖Fable-5Opus-4.8GLM-5.1744B-A40BMiniMax-M3428B-A23BDeepSeek-V4-Pro1.6T-A49BGPT-5.5Kimi-K2.61T-A32BHaiku-4.5Qwen3.5-397B-A17B397B-A17BGPT-5.4-MiniGemini-3.1-ProLing-2.6-Flash104B-A7BDevstral-2123BQwen3.5-122B-A10B122B-A10BGemini-3.5-FlashQwen3-32B32BQwen3.6-35B-A3B35B-A3BGemini-2.5-FlashNemotron-3-Super*120B-A12BSolar-Pro-3*102B-A12BGLM-4.7-Flash+26%GLM-4.7-Flash-Coder30B-A3B0.00.10.20.30.40.50.60.7$0.01$0.1$1cost per task, USDscore (tasks solved / 500)
GLM-4.7-Flash, -Coder, and GLM-5.1: avg of 4 passes. All other models: single pass. ¹ Nemotron-3-Super frequently stopped after reasoning without emitting a tool call. ² Solar-Pro-3 generated invalid tool names, which crashed the tokenizer on the following turn.

More reasoning, fewer turns

Although GLM-4.7-Flash-Coder does 2.4× more reasoning than the base model, it completes tasks faster: 45% fewer turns, which translates to 14% lower inference cost.

Extended reasoning, fewer turns, cost efficiency

Base · GLM-4.7-FlashSFT · GLM-4.7-Flash-Coder

reasoning tokens
per response

assistant turns
per task

trace token length

average cost
per task

Boxes span the interquartile range, whiskers the range, bold line the median. SFT reasons 2.4x more per response (63→150) yet needs 45% fewer turns (82.5→44.0), shorter traces (52k→39k) and 14% lower cost ($0.0443→$0.0382).

The key to turn efficiency is concurrent tool calls

By allowing the model to dispatch multiple bash and read calls in a single turn, we significantly reduced the latency bottleneck of sequential execution.

Simultaneous tool calls · fraction of assistant turns

2+ read tool calls

2+ bash tool calls

2+ edit tool calls

Frequency of turns with two or more calls to the same tool. Each panel has its own scale. SFT batches reads 6x, bash 12x, and edits 91x more often than the base model.

SWE-rebench-V2

We trained and evaluated models on nebius/SWE-rebench-V2 — a dataset of 32k agentic coding tasks. It consists of real issues from public repositories, closely representing real-world SWE challenges.

SWE-rebench-V2 pipeline

Each task: a real repository and issue, an agentic loop over four tools inside a sandbox, a generated patch, and a binary reward from the repository's own test suite.

Teacher — GLM-5.1

The training data comes from GLM-5.1 acting as a teacher. We ran it on the train split with 4 rollouts per task and kept only trajectories that passed the tests — 7,777 successful multi-turn traces after rejection sampling.

We're releasing the training dataset alongside the train/test splits. All models run inside PI — a lightweight agent harness with four tools: bash, read, edit, write.

Training

We trained Coder with Supervised Fine-Tuning (SFT) using halo, our post-training framework we're open-sourcing today.

Parallelism modeDP16, multi-node
Context length76k
Global batch16
PackingEnabled
Learning rate schedulingCosine, linear warm-up
Training time3 hours on 16 B300 GPUs

Halo is driven entirely by a single YAML config:

model_name_or_path: zai-org/GLM-4.7-Flash
trust_remote_code: true
attn_implementation: flash_attention_4_hybrid

dataset:
- whitecircle/swe-rebench-v2-glm-5.1-pi-agent-successful-traces
test_size: 0.01

conversation_field: messages
tools_field: tools
interleaved_thinking: true

max_length: 75000
packing: true

learning_rate: 1e-5
lr_scheduler_type: cosine
warmup_steps: 25
per_device_train_batch_size: 1
per_device_eval_batch_size: 1

moe_balancing: none
liger_kernel_config:
  fused_linear_cross_entropy: true

assistant_message_template: "<|assistant|>"

output_dir: /mnt/research/GLM-4.7-Flash-Coder
save_steps: 50
save_only_model: true

eval_strategy: steps
eval_steps: 50
logging_steps: 1
logging_first_step: true
log_decoded_samples: true

report_to: wandb
project_name: agentic-sft
run_name: glm-4.7-flash-coder

enable_efficiency_metrics: true

Emergent skills

The model picked up several of the teacher's skills and patterns during fine-tuning:

Learned patterns · Base vs SFT vs Teacher

BaseSFT · CoderTeacher · GLM-5.1

self-corrections

occurrences per response

question marks in reasoning

occurrences per response

'git stash' usage

calls per task

timeouts passed to bash

fraction

Behavioral patterns transferred from teacher to student. Each panel has its own scale. On self-corrections and reasoning questions, SFT even overshoots the teacher.
  • A 10× higher rate of self-corrections in reasoning
  • Self-directed questions ("But wait, could this ever be True?")
  • Advanced tool calling patterns, e.g. setting timeout for the bash tool

Agent trace · GLM-4.7-Flash-Coder

Hmm, actually these look like pre-existing test differences unrelated to my fix. Let me revert my fix and run the test again.

git stash && python -m pytest tests/test_markdown.py::test_markdown_table -xvs

Loss decomposition into Reasoning & Tool Calls

We only train on assistant responses. Of 177 million tokens in the dataset, only 46 million carry loss — the remaining 131 million (system prompts and tool responses) are masked.

A packed training row, token by token

reasoningtool_callmasked (untrained)

step000001 · 2,360 trained tokens of 10,871 total · positions 2179–10534

Assistant spans carry loss; system prompts and tool outputs are masked. Reasoning spans (light) and tool-call spans (dark chips) are tracked separately.

Reasoning & content vs tool calls

Reasoning & contentTool calls

Token balance

Loss balance

Reasoning tokens are 56.7% of trained tokens but 83.9% of the loss — tool-call tokens are low-entropy and near-deterministic.

To track convergence separately, we decompose loss into two components — negative log-likelihood on reasoning and tool calling tokens, respectively.

Training loss decomposition

— per-step / eval loss┄ epoch boundary● global minimum

Train · Loss

Loss on reasoning & content tokens

Loss on tool call tokens

Eval · Loss

Eval · reasoning & content

Eval · tool calls

Total loss decomposed into reasoning-and-content and tool-call components over global steps. Both eval components reach their global minima simultaneously at the end of epoch 2 (glowing point, step 300).

Test scores

Below is the comparison of GLM-4.7-Flash, GLM-4.7-Flash-Coder, and its teacher GLM-5.1 on the test set of SWE-rebench-V2:

metricGLM-4.7-FlashGLM-4.7-Flash-CoderΔTeacher · GLM-5.1
pass@10.33150.4165+25.6%0.5650
pass@20.40870.5023+22.9%0.6063
pass@40.46200.5720+23.8%0.6300

How we enabled FA4

FlashAttention-4 is a fast attention kernel — but it's incompatible with GLM-4.7-Flash's architecture:

FlashAttention-4 produces NaN gradients for this model's head_dim-256 partial-rotary
attention; falling back to attn_implementation='sdpa'.

We found that the incompatibility only appears in the backward pass — the forward computation is correct. So we designed a hybrid scheme: FA4 handles the forward pass, while FA2 takes over for the backward. The hybrid approach gave a 1.36× increase in attention throughput.

Kernels

GLM-4.7-Flash is a Mixture-of-Experts model. Tokens are distributed unevenly across experts — that means MLP blocks receive tensors of varying width. The Grouped-GEMM kernel batches matrix multiplications of varying shapes into a single kernel launch. Enabling it gave a 1.6× speedup on the FFN step. Additionally, with Liger Fused Linear Cross-Entropy, we were able to compute loss without full logit matrix materialization in VRAM, preventing OOM on long sequences. Together, these improvements yield up to a 1.63× training speedup over TRL, raising throughput to 3000 tokens/s on a single B300 GPU:

GLM-4.7-Flash SFT throughput · single B300 · 4k–128k

Halo FA4-hybridHalo FA2TRL — SDPA
4k
8k
16k
32k
48k
75k
128k
GLM-4.7-Flash SFT on a single B300, grouped by context length; b# marks the best per-device batch. Halo FA4-hybrid leads at every length — up to 1.63x over TRL; at 128k TRL runs out of memory.

Agentic infra challenge

We faced a real challenge with agentic evaluation infrastructure. At a scale of thousands of concurrent agents, Docker introduces high startup overhead and heavy disk pressure, and quickly saturates the local network — resulting in a high rate of environment startup errors. Kubernetes struggled at high concurrency on a single host as well: it couldn't set up and tear down pods fast enough, triggering timeouts. The problem was worst on powerful hosts: they could support enormous concurrency, but pod scheduling couldn't keep up, so we never reached full CPU or RAM utilization.

Overlay sandboxes

Our solution is the Overlay Sandbox: instead of a container image, the agent runs on the bare host, in an isolated filesystem and process group. It has three layers: a base filesystem with the OS and repository, a hidden layer with the verifier suite, and an upper layer holding all edits and pip-installed packages. Because overlay mounts are lazy (they don't even index the filesystem!) and only track modified files, sandbox startup is essentially free.

Overlay sandbox · three layers

Lazy Overlay Mount

(writable layer)

Base Filesystem

(read-only)

Hidden Files

(not visible to agent)

The agent runs on the bare host in an isolated filesystem. All edits and pip installs land in the writable overlay; the verifier suite stays in a hidden layer the agent cannot see.

Since SWE-rebench-V2 is built from public repositories, agents must run without network access — otherwise, a model can simply fetch a real fix from GitHub. Before restricting network, we caught Fable 5 and Sonnet 5 doing exactly this — retrieving the upstream patches directly on 20-40% of tasks.

Traffic recorder

Our sandbox also includes a traffic recorder — a tiny proxy that forwards requests to the provider (OpenRouter / vLLM / SGLang) and records every response. It's a harness-agnostic way to assemble full trajectories in OpenAI format and collect performance metrics.

Traffic recorder · raw requests to OpenAI-format trace

Raw requests

The recorder sits between the agent and the provider, capturing every raw request. Deduplicating the prefixes assembles the full trajectory in OpenAI format.

Evaluation

Every agent runs with max_turns = 200, medium reasoning effort, and default sampling parameters. Inference costs are calculated from OpenRouter pricing tables. We report the theoretical price under the assumption of perfect caching — actual OpenRouter costs were higher due to inconsistent routing. For locally served GLM-4.7-Flash-Coder, we applied the per-request pricing of GLM-4.7-Flash via OpenRouter's DeepInfra provider.

Evaluation · OpenRouter pricing ($/Mtok)
ModelProviderinput $/Mtokoutputcache readcache write
Fable-5google-vertex/global1050112.5
Opus-4.8anthropic5250.56.25
GLM-5.1wafer/fp413.20.1
MiniMax-M3minimax/fp80.31.20.06
DeepSeek-V4-Prodeepinfra/fp41.32.60.1
GPT-5.5azure5300.5
Kimi-K2.6siliconflow/fp80.773.40.14
Haiku-4.5anthropic150.11.25
Qwen3.5-397B-A17Bdeepinfra/fp80.4530.22
GPT-5.4-Miniazure0.754.50.075
Gemini-3.1-Progoogle-ai-studio2120.20.375
GLM-4.7-Flash-Coderdeepinfra/bf160.060.40.01
Ling-2.6-Flashnovita0.10.30.02
Devstral-2mistral0.420.04
Qwen3.5-122B-A10Balibaba0.43.2
GLM-4.7-Flashdeepinfra/bf160.060.40.01
Gemini-3.5-Flashgoogle-vertex/global1.590.150.08333
Qwen3-32Bdeepinfra/fp80.080.28
Qwen3.6-35B-A3Bparasail/fp80.1510.05
Gemini-2.5-Flashgoogle-vertex/global0.32.50.030.08333
Nemotron-3-Superdigitalocean0.210.4550.06
Solar-Pro-3upstage0.150.60.015

Prompt template

You are solving a real GitHub issue in the `{repo}` repository. The repo is already
cloned and set up in the current working directory.

## Workflow

1. Understand the issue. Read the problem statement carefully. Identify the
   expected vs actual behavior.
2. Explore the codebase. Find the relevant files using grep, find, or by reading
   the project structure. Read the code that needs to change.
3. Reproduce the bug if possible — run the relevant test file or write a small
   script to confirm the issue exists.
4. Implement a minimal fix. Change only what is necessary. Do not refactor
   unrelated code, do not add features beyond what the issue asks for.
5. Verify your fix. Run the project's existing test suite to make sure you
   haven't introduced regressions. Look at the project's test configuration
   (Makefile, tox.ini, pyproject.toml, CI config) to find the right test command.
6. Mark the task complete only after you've verified existing tests pass with
   your changes.

## Issue

{problem_statement}

## Expected Interfaces

The following interfaces are expected by the test suite. Pay close attention to
function names, parameter signatures, and return types — the tests verify these
exactly.

{interface}

Want to deploy AI agents safely?

Control AI behavior in real time with White Circle