A model with just 350 million parameters may seem too small for demanding formatting tasks. However, an experiment with GRPO shows that targeted fine-tuning can significantly improve its ability to generate valid JSON and YAML, follow schemas, and return exactly the requested structure.
The model went from achieving 22.6% to 29.7% correct responses on the IFStruct benchmark after just 100 training steps. The improvement does not turn the model into a perfect solution, but it does show something important: when the objective is clearly defined, a small model can become much more useful for integration with real-world systems.
The problem: a correct answer must also have the right shape
Language models are often evaluated based on their ability to reason, summarize, or extract information. But in a production application, another less flashy and much more practical question comes up: can the response be parsed automatically without breaking the system?
If an application expects a JSON object with five fields and the model returns a list, adds a property that is not allowed, or leaves a string unclosed, the response may be useless even if its content is reasonable.
This is known as schema compliance or schema compliance. In simple terms, it means that the output:
- Can be parsed correctly.
- Uses the requested format, such as JSON, YAML, or a code block.
- Includes the required fields.
- Respects the data types and schema constraints.
- Has the expected quantity and structure.
The IFStruct benchmark measures precisely this type of reliability. Its evaluation set contains 2,000 samples and checks whether the model's output is valid and compatible with the specified schema.
The starting point: LFM2.5-350M
The experiment uses LiquidAI/LFM2.5-350M, a compact model with 350 million parameters. Before training it, the team served it locally through llama.cpp and evaluated its performance using the BF16 version in GGUF format.
The initial result was 452 correct responses out of 2,000, equivalent to 22.6%. This figure is close to the 21.1% previously reported for the same model in the IFStruct paper, although the authors clarify that their training pipeline does not attempt to reproduce that result exactly.
The evaluation was run on a MacBook Pro with an Apple M5 Max chip and 36 GB of unified memory. The training, on the other hand, was designed to run on a 16 GB GPU available through free services such as Colab or Kaggle.
This separation matters. You do not need massive infrastructure to evaluate the model locally, and training can remain relatively inexpensive when the task is well defined.
How it was trained with GRPO and LoRA
The team used data from nvidia/Nemotron-RL-instruction_following-structured_outputs, which includes instructions, a target JSON schema, and the expected number of fields. Approximately 500 examples were used for training.
Because the distribution of this data does not exactly match IFStruct, two types of variations were added:
- In 40% of the examples, the instructions said that the response had to appear inside a delimited code block.
- A separate 20% was transformed into tasks whose output had to be a top-level list with a specific number of elements.
This meant the model did not learn only to produce valid JSON. It also practiced two common difficulties in real-world applications: distinguishing between a response wrapped in a key and a direct list, and following instructions about code blocks.
LoRA was used to update the model, an efficient fine-tuning technique that trains a small number of additional parameters instead of modifying all the original weights. In this case, nearly 6 million parameters were trained, around 1.66% of the complete model.
The adjustment was applied to modules related to the attention projections and the internal layers of LFM2.5's hybrid architecture. This makes it possible to adapt the model's behavior while using far less memory than full fine-tuning.
Three rewards for measuring the quality of each response
GRPO, or Group Relative Policy Optimization, generates several responses for the same instruction and uses a reward function to favor the best ones. In this experiment, each response received scores between 0 and 1 according to three criteria.
1. Format reward
It checks whether the response can be parsed and whether it uses the requested format. For example, a JSON output without a code block receives the maximum score when that is what was expected. If it is valid JSON but appears in the wrong format, it receives partial credit. If it cannot be parsed, it gets zero.
2. Field-count reward
It measures whether the object contains the correct number of top-level fields. An exact match receives the maximum score, while the reward decreases according to the difference.
3. Schema-validation reward
It checks whether the response complies with the associated JSON Schema. The system counts errors such as missing required fields, incorrect types, out-of-range values, or additional properties that are not allowed.
The rewards were combined using these weights:
- JSON format:
1.0 - Field count:
0.5 - Schema validation:
2.0
The greatest weight was assigned to schema validation because it is the criterion most closely related to the output's real usefulness inside software.
Just 100 steps, but a clear improvement
The training used 100 steps, eight generations per instruction group, a learning rate of 5e-5, and a KL penalty of 0.01 to prevent the model from straying too far from its original behavior.
The LoRA adapter was then merged with the base model, and the result was converted to GGUF BF16 so it could be served again through llama.cpp. This way, both evaluations used a comparable execution stack.
The results were as follows:
| IFStruct group | Base model | Fine-tuned model | Improvement |
|---|---|---|---|
| General | 22.6% | 29.7% | +7.1 points |
| JSON | 18.0% | 31.9% | +13.9 points |
| YAML | 27.2% | 27.5% | +0.3 points |
| Object with wrapper key | 28.5% | 29.7% | +1.2 points |
| Direct list | 16.6% | 29.7% | +13.1 points |
The most important improvement appeared exactly in the areas that received attention during training. JSON performance rose by nearly 14 percentage points, and the ability to produce direct lists increased by 13.1 points.
YAML, on the other hand, barely changed. This suggests that the training was specific and did not produce a general improvement across all formats. Is that a limitation? Yes, but it is also a sign of control: the model mainly improved at what the rewards taught it to prioritize.
What errors are still present
The fine-tuning did not eliminate compliance problems. The trained model still produced thousands of cases with missing required fields, as well as errors involving element counts and incompatible types.
Additional properties such as metadata.tone, speaker_labels, and notes also appeared. In other words, the model learned to follow some instructions more reliably, but it can still add information that the schema does not authorize.
The 29.7% result also remained below the 33.15% reported for Qwen3.5-2B. This comparison should be interpreted carefully because these are models with different sizes and characteristics. Even so, the 350M model came considerably closer to one several times larger through a short and relatively inexpensive training process.
Why this matters for small projects
Many applications do not need a huge model to solve a specific task. An internal assistant that converts invoices into data, classifies tickets, or extracts information from documents may benefit more from predictable output than from broad reasoning ability.
This experiment suggests a practical strategy:
- Choose a small model that can run at a moderate cost.
- Create examples close to the format the application will use.
- Define rewards that measure specific errors.
- Fine-tune the model with LoRA and GRPO.
- Evaluate it with an independent and reproducible benchmark.
The key is not to confuse an improvement in the training reward with a production-ready solution. IFStruct helps identify progress, but it is still a good idea to validate responses at runtime, log errors, and use retries or decoding constraints when necessary.
A small model does not have to know how to do everything. If it can reliably deliver the structure your system expects, it may be more useful than a much larger model that responds brilliantly but breaks the format at critical moments.
