Instructions to use agentbyumer/gemma4-e2b-structured-output with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use agentbyumer/gemma4-e2b-structured-output with Transformers:
# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("agentbyumer/gemma4-e2b-structured-output", device_map="auto") - Notebooks
- Google Colab
- Kaggle
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 |
| 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
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.