File size: 4,785 Bytes
8e8cf56
 
 
 
 
 
 
3889c70
 
 
 
8e8cf56
 
 
3889c70
 
8e8cf56
 
3889c70
8e8cf56
3889c70
 
 
 
8e8cf56
3889c70
8e8cf56
3889c70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
---
base_model: unsloth/gemma-4-e2b-it-unsloth-bnb-4bit
tags:
- text-generation-inference
- transformers
- gemma4
- trl
- structured-output
- json
- function-calling
- agentic-ai
license: apache-2.0
language:
- en
datasets:
- interstellarninja/json-mode-agentic
---

# Gemma 4 E2B — Structured Output

A QLoRA fine-tune of Google's Gemma 4 E2B, trained to convert natural-language text into 
valid, schema-conforming JSON. Built for use cases where an LLM needs to reliably hand off 
structured data to downstream code — agent tool calls, form extraction, data pipelines, 
and anywhere else "give me clean JSON, not prose" actually matters.

## Why this model exists

Most instruction-tuned models *can* produce JSON when asked, but they tend to wrap it in 
explanation, second-guess the schema, or take an unnecessarily long reasoning path to get 
there. This fine-tune trains that overhead away, so the model goes straight from a schema 
and a block of text to a clean, parseable JSON object.

## Training details

| | |
|---|---|
| Base model | unsloth/gemma-4-e2b-it-unsloth-bnb-4bit |
| Method | QLoRA |
| Dataset | [interstellarninja/json-mode-agentic](https://huggingface.co/datasets/interstellarninja/json-mode-agentic) |
| Task | Schema-guided JSON extraction from natural language |
| License | apache-2.0 |

## Evaluation

Tested informally against the base model on a set of hand-written extraction tasks, 
covering simple schemas, nested/typed schemas, and — most importantly — cases where the 
input text is missing information the schema asks for.

**Speed.** On every test, the fine-tuned model produced output immediately, with no visible 
reasoning phase. The base model consistently reasoned through a multi-step "analyze, map, 
construct, review" process first, taking 30+ seconds before reaching the same answer.

**Accuracy on typed schemas.** On a schema mixing strings, numbers, booleans, and arrays 
(e.g. `price: number`, `in_stock: boolean`, `tags: [string]`), the fine-tuned model matched 
every field type correctly, including nested arrays and decimal numbers. On a separate, 
simpler test, it returned one field (`age`) as a string instead of the integer the schema 
specified — the base model got this particular field right. Across the full test set this 
looked like an isolated slip rather than a systematic pattern, but it's a real, observed 
behavior worth knowing about if your use case depends on strict type fidelity.

**Handling missing data.** This was the most important test. When a required field wasn't 
present anywhere in the input text, the fine-tuned model correctly returned `null` for that 
field instead of inventing a plausible-looking value to fill the schema. This matters more 
than it might sound — a structured-output model that fabricates missing fields to "complete" 
a schema is a real liability in any pipeline that trusts its output, and this model didn't 
do that in testing.

**Bottom line:** significantly faster and more direct than the base model on structured 
extraction tasks, with strong type accuracy on complex schemas and correct, honest behavior 
on missing data. The one observed weak spot — an occasional type mismatch on simpler 
schemas — is worth validating against your own schema and data before relying on it in 
production.

This isn't a formal benchmark result, and it's a small test set. If you run it against 
something more rigorous (JSON-mode-eval, a custom test suite, or your own production data), 
I'd genuinely like to hear how it does — open an issue or start a discussion on this repo.

## How to use

```python
from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained(
    "agentbyumer/gemma4-e2b-structured-output", 
    device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("agentbyumer/gemma4-e2b-structured-output")

prompt = """Schema: {"name": "string", "age": "integer", "email": "string"}
Text: "Hi, I'm Sarah Ahmed, I'm 29 years old, you can reach me at sarah.ahmed@email.com"
Task: Extract the information into the given JSON schema."""

inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=200)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
```

A GGUF-quantized version for local/CPU inference is planned — check back or watch this repo 
for updates.

## Part of an ongoing series

This is one of several small, task-focused fine-tunes I'm building and evaluating as part 
of exploring what narrow specialization can (and can't) improve in sub-5B parameter models — 
covering function-calling, math reasoning, code generation, and structured output so far. 
More context on the approach and results across the series.