manifesta/verified-agronomy-17k
Verified Agronomy, 17,199 rows The arithmetic a working agronomist actually does: fertiliser rates, growing degree days, irrigation scheduling, seeding rates, grain moisture, sprayer calibration, forage budgeting. Every formula traced to a citable published source, and every number checked. And 1,796 rows (10.4%) that cannot be answered at all, where the correct response is to say so and name the missing input. Verify this card… See the full description on the dataset page: https://huggingface.co/datasets/manifesta/verified-agronomy-17k.
<p align="center"> <a href="https://huggingface.co/datasets/manifesta/verified-agronomy-17k"><img alt="Hugging Face" src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-verified--agronomy--17k-2a78d6"></a> <a href="https://www.kaggle.com/datasets/aivarasnavardauskas/verified-agronomy-17k"><img alt="Kaggle" src="https://img.shields.io/badge/Kaggle-verified--agronomy--17k-20beff"></a> <img alt="rows" src="https://img.shields.io/badge/rows-17%2C199-0b0b0b"> <img alt="formulas" src="https://img.shields.io/badge/formulas-26%2F26%20match%20published-1baf7a"> <img alt="arithmetic" src="https://img.shields.io/badge/arithmetic%20checked-25%2C324%20expressions-1baf7a"> <img alt="refusal" src="https://img.shields.io/badge/unanswerable-1%2C796%20(10.4%25)-eb6834"> <img alt="license" src="https://img.shields.io/badge/license-CC0--1.0-1baf7a"> </p>
<p align="center"> <a href="https://github.com/A1VARA5/verified-agronomy-17k/actions/workflows/verify.yml"><img alt="verify" src="https://github.com/A1VARA5/verified-agronomy-17k/actions/workflows/verify.yml/badge.svg"></a> <a href="https://github.com/A1VARA5/verified-agronomy-17k"><img alt="build code" src="https://img.shields.io/badge/GitHub-build%20pipeline%20%2B%2022%20checks-24292f?logo=github&logoColor=white"></a> <a href="https://huggingface.co/manifesta/adaptionagronomycalcproblems"><img alt="weights" src="https://img.shields.io/badge/%F0%9F%A4%97%20weights-adaptionagronomycalc_problems-2a78d6"></a> <img alt="autoscientist" src="https://img.shields.io/badge/AutoScientist-46%20vs%2054%20regression-c0392b"> </p>
Verified Agronomy, 17,199 rows
The arithmetic a working agronomist actually does: fertiliser rates, growing degree days, irrigation scheduling, seeding rates, grain moisture, sprayer calibration, forage budgeting. Every formula traced to a citable published source, and every number checked.
And 1,796 rows (10.4%) that cannot be answered at all, where the correct response is to say so and name the missing input.
Verify this card
Do not take my word for any of this. Here is how to check it yourself, from a terminal, with no account and no token.
The short way. One clone, one command, 22 checks.
git clone https://github.com/A1VARA5/verified-agronomy-17k
cd verified-agronomy-17k
python verify.pyStandard library only, no install step, Python 3.9 or newer. It prints a PASS or FAIL line per check and re-derives every number on this page: the row count from the Hub's own parquet index, that the licence is CC0 and the field is populated rather than empty, the 26 calculator assertions, the 25,324 arithmetic expressions, the 1,796 refusal rows, a per-row citation check, the weights and their exact byte size, the base model resolving, both Kaggle mirrors and the live interface. Use --offline for the eight checks that need no network. The same script runs in GitHub Actions on every push and once a day, which is what the badge above reports.
The long way, step by step. The expected results are in the comments.
# 1. Row count, read from the Hub's own parquet index instead of from this page.
# Expect "num_rows":17199
curl -s "https://datasets-server.huggingface.co/size?dataset=manifesta/verified-agronomy-17k" \
| grep -o '"num_rows":[0-9]*' | head -1
# 2. Do the formulas match the sources they cite? Expect "RESULT: 0 failed", 26 PASS lines.
B=https://huggingface.co/datasets/manifesta/verified-agronomy-17k/resolve/main/build
for f in agri_calc.py test_agri_calc.py check_agri.py; do curl -sLO $B/$f; done
python test_agri_calc.py
# 3. Does the arithmetic in the published solutions actually compute?
# Expect "25,324 expressions checked, 0 inconsistent" and "RESULT: 0 failed".
pip install pyarrow
curl -sLO https://huggingface.co/datasets/manifesta/verified-agronomy-17k/resolve/main/data/train-00000-of-00001.parquet
python check_agri.py train-00000-of-00001.parquetIf step 1 comes back with "the server is busier than usual", that is the Hub warming its cache. Run it again.
Step 2 runs every calculator against a worked example published by the source it cites, not against itself. 26 assertions, 0 failures. Anyone can open the referenced page and see the same number. This is the check that caught the P₂O₅ to P factor being 0.437 in the Cornell reference and 0.436 in my head, before that digit reached thousands of rows.
Step 3 re-parses the published parquet, pulls out every chained arithmetic expression written into the worked solutions, evaluates each one independently and compares. It also re-checks that the boxed answer equals the answer field on all 17,199 rows, that ids are unique, that no two questions are identical, that all 1,796 refusal rows actually refuse and name their missing input, and that no answerable row refuses. The download is 1,192,585 bytes and it finishes in seconds.
Two numbers I corrected on this card
The arithmetic count is 25,324, not 30,710. The 30,710 figure was real, but it was measured on the 18,900-row candidate pool before near-duplicate removal. The published file is 17,199 rows and gives 25,324. I would rather the card match what the script prints on the file you can download.
The calculator count is 26, not 25. test_agri_calc.py runs 26 assertions. Count the PASS lines.
The weights, and the checks that go with them
The AutoScientist run has reported and the adapter is published:
- Weights on Hugging Face: [`manifesta/adaption_agronomy_calc_problems`](https://huggingface.co/manifesta/adaption_agronomy_calc_problems)
- Weights on Kaggle: [adaption_agro-b3684c92](https://www.kaggle.com/models/aivarasnavardauskas/adaption_agro-b3684c92-06ce-42dc-863d-c2666a3f89d4)
# 4. Do the weights download, and are they the size the card claims?
# Expect HTTP 200 and content-length 119273568.
curl -sIL https://huggingface.co/manifesta/adaption_agronomy_calc_problems/resolve/main/adapter_model.safetensors \
| grep -iE "^HTTP|^content-length" | tail -2
# 5. Does the declared base model resolve? Expect 200, then 401 for the string the export wrote.
curl -s -o /dev/null -w "%{http_code}\n" https://huggingface.co/api/models/google/gemma-3-4b-it
curl -s -o /dev/null -w "%{http_code}\n" https://huggingface.co/api/models/togethercomputer/gemma-3-4b-it
# 6. Is the live interface up? Expect 200.
curl -s -o /dev/null -w "%{http_code}\n" https://manifestaagriculture.adaptionlabs.app/The 401 in step 5 is the point, not a mistake. adapter_config.json shipped from the platform export declaring togethercomputer/gemma-3-4b-it, a repository that does not exist, so nothing could resolve a base model from the artifact. I corrected it to `google/gemma-3-4b-it` on 2026-08-13 and kept the original string verbatim in the same file as original_base_model_name_or_path. No weight changed. Both values are readable in the published config, so you can see what shipped first and decide for yourself whether the change was right.
The training result, and it is not a good one
The adapted model scored 46 against the base model's 54. It went backwards. That is a regression, not a tie and not a win, and it belongs at the top of this section rather than after the data-quality number.
Two numbers, two different measurements. The +68.0% is the improvement in the data. The 46 against 54 is the model. The data got substantially better, the largest lift of the three entries in this series, and the model still got worse. Conflating those would be the easiest way to make this entry read better than it is.
The mechanism, out of trainer_state.json
I edited the recipe by hand instead of accepting the platform default: `n_epochs` from 1 to 3, and `learning_rate` from 1e-5 to 1e-4, on a Tiny AutoScientist (sub-10B) base with domain and diversity expansion enabled. The hypothesis was that the two earlier runs in this series had been starved of optimizer steps.
Five clipped steps, all five in the warmup before the learning rate reached its peak, and from step 6 onward the gradient never went above 2 again. That is a mild start, not a broken run.
The loss curve after it is textbook: eval loss fell at every single evaluation, and the model still lost the head-to-head. That is the useful finding here. A monotonic eval curve is not evidence the model got better at the task, it is evidence it got better at reproducing the training distribution. This corpus has one deliberately rigid output contract, every row closing with the same boxed line, and three epochs at 1e-4 is enough to fit that shape hard. A preference judge scores the answer, not the shape.
The hypothesis was that more steps at a higher learning rate would help. It did not. I am recording that rather than reporting only the +68.0%, because a card that documents a hypothesis that failed is more useful than one that hides it. The full diagnosis, the per-step numbers and a cross-run comparison against the three other adapters are on the model card.
What this means for the dataset. The corpus is verified, cited and internally consistent, and none of that is in question here. What has not been shown is that it improves a 4B model under this recipe. If you train on it, start from one epoch at 1e-5 rather than what I ran, and score against the judge rather than against loss.
Why this exists
Agronomy questions look like general knowledge and are actually arithmetic with domain constants. Get the constant wrong and the answer is confidently, precisely wrong. A fertiliser rate that is out by the P₂O₅ to P factor is still a plausible-looking number.
So this dataset takes the same stance as a verified math corpus: a row earns its place by passing a check. Two checks, in fact. The formula is checked against its source, and the arithmetic is checked against itself.
The two-layer verification
Layer 1, the formulas match their published sources. build/test_agri_calc.py checks every calculator against a worked example published by the source it cites. 26 checks, 0 failures, including:
Citing a formula is not evidence you implemented it correctly. Matching the source's own numbers is. This caught a real error: P₂O₅→P is 0.437, not the 0.436 that would otherwise have propagated into thousands of rows.
Layer 2, the arithmetic in every solution actually computes. build/check_agri.py re-parses the finished dataset, extracts every arithmetic expression written into the worked solutions, evaluates it independently, and compares. 25,324 expressions checked on the published file, 0 inconsistent. If a step says 31.8 x 10 x 20 = 6,360, that has been confirmed.
Each row also passed a generator-time check appropriate to its family: an inverse recomputation, a nutrient balance, a dimensional round-trip, or a dry-matter conservation check.
What is in it
15,403 rows (89.6%) are exactly gradable, see exactly_gradable. Difficulty: 3,784 hard, 8,462 medium, 4,953 easy.
The refusal slice
Fertiliser rate needs a current soil test. Irrigation run time needs site-specific reference evapotranspiration. Seeding rate in kg/ha needs the thousand-kernel weight of the actual seed lot. Product rates come from the registered label. Manure timing is governed by local regulation.
These questions are unanswerable by construction, and many include real but irrelevant context (field size, previous crop, soil texture, growth stage) precisely to test whether plausible detail gets mistaken for the input the calculation requires:
"The block is 18 ha. How many days can I graze the home paddock?" → cannot be determined without the current forage dry matter on offerField size is genuinely relevant to grazing days and still does not determine them without forage on offer. That is the trap, on purpose.
Output contract
Every row closes with one uniform line:
The final answer is $\boxed{ANSWER}$.Unit inside the box. This is deliberate and makes the corpus machine-gradable without an LLM judge. Verified on 100% of rows, and the boxed content matches the answer field on 100% of rows.
Loading
from datasets import load_dataset
ds = load_dataset("manifesta/verified-agronomy-17k", split="train")
print(ds[0]["question"], ds[0]["worked_solution"])
refusals = ds.filter(lambda r: r["family"] == "refusal") # 1,796
gradable = ds.filter(lambda r: r["exactly_gradable"]) # 15,403Provenance and licensing, CC0
There is one source, and it is a script in this repo. The same four scripts, byte identical, plus the build manifest and the training state, are in the GitHub repository, where verify.py SHA-256s both copies and fails if they ever stop matching.
No third-party corpus was read, so there is no attribution chain to inherit and no share-alike term to propagate. Released CC0-1.0, no restrictions.
The formulas are a different question from the text. Formulas are facts, and facts are not copyrightable, but a fact still has to come from somewhere and be checkable. Every row names the source its formula came from in the citation column. These are the counts:
Count them from the shipped file rather than trusting the table:
from datasets import load_dataset
from collections import Counter
ds = load_dataset("manifesta/verified-agronomy-17k", split="train")
print(Counter(ds["citation"]))build/test_agri_calc.py is the part that matters. It checks each calculator against a worked example published by the source in that table, so the citation is not decoration.
Limitations, read these
- It is arithmetic, not agronomy judgement. This teaches a model to compute correctly and to refuse honestly. It does not teach what rate to recommend. That is a soil-test, variety, season and jurisdiction specific decision, which is exactly what the refusal slice says.
- 100% generated. Realistic and internally verified, but not drawn from field records. There is no observational data here.
- Constants are largely North-American and FAO conventions: 56 lb/bu corn, 15.5% market moisture, °F degree-day bases alongside metric rates. A model trained on this inherits those conventions.
- Kc values are FAO-56 mid-season single coefficients. Real scheduling uses stage-specific and often dual coefficients; this is the simplified standard case.
- The refusal share (10.4%) is a design choice. A model trained on this may skew toward refusal; downsample that family if you want a more answer-eager model.
- Verification proves the arithmetic, not the agronomy. Every number computes and every formula matches its source. Whether a given scenario is agronomically sensible was spot-checked by hand, not reviewed at 17,199-row scale.
- No public agronomy benchmark exists to decontaminate against, so there is no contamination check to show. The set is internally exact- and near-deduplicated (MinHash 0.85, 1,701 removed). Every one of those 1,701 removed row ids is listed in `evidence/neardup_removed_ids.json`. I did not preserve the one-off script that ran that pass, so the id list is the audit record instead of the code. That is a real gap and it is better said than left out.
- The trained model lost to its base, 46 to 54. The corpus has not been shown to improve a 4B model under the recipe I ran.
Citation
@misc{verified_agronomy_17k,
title = {Verified Agronomy: 17,199 source-cited agricultural calculations with a refusal slice},
author = {Aivaras Navardauskas},
year = {2026},
url = {https://huggingface.co/datasets/manifesta/verified-agronomy-17k}
}Formula sources: FAO-56 · NDSU NDAWN · Cornell CSS412 · WSU extension · Purdue · Ohio State · Pioneer.
Build code, evidence files and 22 runnable checks: <https://github.com/A1VARA5/verified-agronomy-17k> Weights: <https://huggingface.co/manifesta/adaption_agronomy_calc_problems> Live interface: <https://manifestaagriculture.adaptionlabs.app/>
Built with Adaptive Data by [Adaption](https://adaptionlabs.ai).
