How to use from
llama.cpp
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh
# Start a local OpenAI-compatible server with a web UI:
llama serve -hf distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
# Run inference directly in the terminal:
llama cli -hf distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
Install from WinGet (Windows)
winget install llama.cpp
# Start a local OpenAI-compatible server with a web UI:
llama serve -hf distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
# Run inference directly in the terminal:
llama cli -hf distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
Use pre-built binary
# Download pre-built binary from:
# https://github.com/ggerganov/llama.cpp/releases
# Start a local OpenAI-compatible server with a web UI:
./llama-server -hf distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
# Run inference directly in the terminal:
./llama-cli -hf distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
cmake -B build
cmake --build build -j --target llama-server llama-cli
# Start a local OpenAI-compatible server with a web UI:
./build/bin/llama-server -hf distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
# Run inference directly in the terminal:
./build/bin/llama-cli -hf distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
Use Docker
docker model run hf.co/distil-labs/distil-qwen3.5-4b-invoice-decision-gguf:Q8_0
Quick Links

Distil-Qwen3.5-4B-Invoice-Decision (GGUF)

A fine-tuned Qwen3.5-4B that reads a vendor invoice, the purchase order and the goods receipt, reasons through four checks, and answers pay or hold with one of five decisions. It is step 2a of the invoice processing pipeline: the decision-only variant, built to compare a model that reasons with Jev on an output Jev can produce. The pipeline itself uses the grounded decision model.

Trained on the distil labs platform from 40 seed examples: a teacher model (GLM 5.3 with reasoning) generated 4,156 synthetic training examples, and the student was fine-tuned on them. This repo holds the Q8_0 GGUF build (distil-qwen3.5-4b-invoice-decision-q8_0.gguf). Safetensors weights: distil-labs/distil-qwen3.5-4b-invoice-decision.

Results

Model Correct decisions (100 test invoices)
This model 98
Qwen3.5-4B untuned, thinking on, same prompt LLM-as-a-judge 0.41
Jev, average of three setups (84, 77, 75) 79
GPT-5.6 Luna, reasoning high 100
GLM 5.3, reasoning high (the teacher) 96
GPT-5.6 Luna, reasoning off 81
Gemini 3.5 Flash Lite 76

The test set has 32 invoices to approve (20 of them near misses, such as a price 1.8% above the PO price), 60 that fail one check and 8 that fail two. Models that answer in one pass score 75 to 84; this model reasons first and catches all 16 wrong totals. Both of its errors are slips in the running sum on line totals in the thousands.

How it was scored, all baselines, and the raw outputs: https://github.com/distil-labs/invoice-processing-pipeline.

How to use it

The model was trained to reason before it answers, in a short fixed format (the checks in policy order, one line per invoice line, a running sum, stop at the first failure; about 160 tokens). Serve it with thinking on: chat_template_kwargs: {"enable_thinking": true}. The answer follows the reasoning.

Serve it behind an OpenAI-compatible endpoint:

hf download distil-labs/distil-qwen3.5-4b-invoice-decision-gguf distil-qwen3.5-4b-invoice-decision-q8_0.gguf --local-dir models
llama-server -m models/distil-qwen3.5-4b-invoice-decision-q8_0.gguf --port 8001 --jinja -c 16384 -np 4

--jinja is required: the chat template carries the thinking switch.

Call it with the system prompt it was trained with, at temperature 0:

from openai import OpenAI

client = OpenAI(base_url="http://127.0.0.1:8001/v1", api_key="EMPTY")
response = client.chat.completions.create(
    model="model",
    messages=[{"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": text}],
    temperature=0,
    extra_body={"chat_template_kwargs": {"enable_thinking": True}},
)

Example answer:

{"decision": "hold_price"}

The model degrades outside its training setup, so keep the system prompt exactly as below. The pipeline repo loads it from training/decider/job_description.json and shows the input format.

System prompt
You check vendor invoices for the accounts payable team of Northwind before they are paid.

You receive three documents: the invoice message as it arrived by email, the purchase order (PO) from the ERP, and the goods receipt from the ERP. Invoice lines can be in a different order than the PO lines and can use the vendor's own item names or abbreviations, so match each invoice line to its PO line by item. Amounts in the message that are not part of this invoice (a previous balance, a payment received, a quote) are ignored.

Run these checks in order and stop at the first one that fails:
1. The PO number referenced on the invoice is exactly the number of the PO. If not: hold_no_po.
2. On every invoice line, the invoiced quantity is not more than the received quantity of that item. If not: hold_quantity.
3. On every invoice line, the invoiced unit price is not more than 2% above the PO unit price of that item. A lower price is fine. If not: hold_price.
4. The total stated on the invoice equals the sum of the invoice line totals, plus the freight charge only if the PO says freight may be added by the vendor. If the PO says freight is not allowed, a freight charge must not be part of the total. If not: hold_total.
If every check passes: approve.

Answer with a JSON object and nothing else: {"decision": "<label>"}, where <label> is one of approve, hold_no_po, hold_quantity, hold_price, hold_total.

Training

Base model Qwen/Qwen3.5-4B
Teacher GLM 5.3, reasoning effort high
Task type question answering with JSON output
Seed examples 40
Synthetic examples 4,156
Method LoRA (rank 64), 4 epochs, merged weights

Seed data, test set, job description and config: training/decider.

Limits

The data is synthetic, written for this demo around a fictional company, in English, with amounts in one currency. The model is trained for this one task and this one policy; it is not a general assistant.

Links

distil labs · GitHub · Hugging Face · LinkedIn · Slack · X

Downloads last month
165
GGUF
Model size
4B params
Architecture
qwen35
Hardware compatibility
Log In to add your hardware

8-bit

Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for distil-labs/distil-qwen3.5-4b-invoice-decision-gguf

Finetuned
Qwen/Qwen3.5-4B
Quantized
(520)
this model