This is a LoRA adapter, not a standalone model. It attaches to
ibm-granite/granite-4.1-3b and specialises it
for the Bloomee agent: given a question about whether flowers are blooming
somewhere, decide which NDVI tool to call and with what arguments, then report the result plainly.
It was distilled from a larger teacher (granite-4.1-8b) driven through the production agent graph
— the same retrieval node, the same four tools, the same prompt — so what it learned is how the
application actually behaves rather than a reimplementation of it.
The adapter is 31.1 M trainable parameters (0.91% of the 3.43 B base), ~124 MB on disk.
Granite's chat template renders the four schemas into a ~400-token block inside the system message. Every training row contained it. Omit it and the model sees a prompt shape it has never encountered.
Use system_prompt.txt verbatim
It is the trained prompt, byte for byte. A paraphrase is a different prompt. inference.py checks its SHA-256 and refuses to run if it drifts.
Decode greedily
The model was evaluated at temperature 0. Sampling makes tool arguments non-reproducible.
Tool calls come back Hermes-style, as <tool_call>{"name": ..., "arguments": {...}}</tool_call>.
Under vLLM, serve with --enable-auto-tool-choice --tool-call-parser hermes.
📊 Results
Measured against the base model on the same harness, same frozen clock, same replayed upstream
fixtures. Train/serve prompt parity was verified token-identical (1266 vs 1266 tokens), so both
models were scored on prompts they were actually trained to see.
Metric
Base
Tuned
Eval loss (101 held-out rows)
0.5521
0.1884
−66%
First tool correct (41 tool rows)
26/41 · 63%
40/41 · 98%
▲
Correctly silent (7 no-tool rows)
0/7
6/7
▲
Golden conversations (15 held-out)
13/15
11/15
▼
Eval loss fell monotonically at every checkpoint, and final train loss (0.2280) sits above final
eval loss — no overfitting signature at 2 epochs:
4096 max; supervised tokens are 2.8% of each sequence
Data
1,787 train / 101 eval rows, split by seed id — never by row
Only the final assistant turn is unmasked, and only its spans. A row is ~2,700 tokens of system
prompt and retrieved context against ~60 tokens of assistant output, so training unmasked would
spend most of the gradient learning to reproduce context the model is handed at inference.
🛰️ Provenance
Trained on bloomee-app/bloomee-sft-nasasmd-grounded-5m
— a 1,899-row synthetic corpus generated by running the production agent graph against recorded
NDVI fixtures, sampling the teacher several times per seed and keeping only samples that survived
validation (39.4% acceptance). That dataset card documents the schema, the intent mix and the
source attributions in full.
The nasasmd in the name refers to NASA's Science Mission Directorate sentence transformer,
which scored how well each candidate answer was grounded in the chunks actually retrieved. It is
deliberately not the retrieval encoder: one model both selecting the chunks and judging groundedness
would measure self-agreement rather than grounding. It shaped which samples survived into the corpus;
it is not part of this adapter.
The golden-conversation score went down: 13/15 → 11/15. This is reported as measured.
All four tuned failures are extra tool calls, not wrong ones — the model learned to consult the
region catalogue (and occasionally the clock) before predicting:
Scenario
Called
Expected
GC-04
forecast + list_regions
forecast
GC-07
current_time + list_regions + predict
list_regions + predict
GC-14
list_regions + predict
predict
That behaviour is what the corpus teaches — region codes are meant to be validated against the live
catalogue rather than taken from model output — but the golden scenarios assert exact tool sets, so a
defensible extra call scores the same as an error. GC-08 fails for both base and tuned (it states
an NDVI value where the scenario forbids one); the fine-tune did not fix it.
So: tool selection improved sharply, tool economy got worse. If redundant catalogue calls
matter for your use case, treat this adapter as a starting point rather than a finished artifact.
Other constraints:
Eight regions only.japan_cherry, usa_cherry_dc, netherlands_tulips, france_lavender,
uk_bluebells, california_poppies, texas_bluebonnets, bandung_floriculture. Anything else
should be refused, and that refusal path is the corpus's thinnest intent (41 rows).
The prompt is still required. This taught behaviour, not knowledge — retrieval must still
supply the context block and the tools must still be bound.
Dates were frozen to 2026-07-30 during generation. The model can invent dates from its own
training prior; the tool wrapper is expected to default and clamp them.
English-dominant. 72 of 1,899 rows are non-English.