Pomona Ecosystem
GitHub contains Pomona platform code, metadata, deterministic rules, and pipeline scaffolding. Model weights belong on Hugging Face. Raw/private data, tokens, and checkpoints stay outside GitHub.
Task
Required input groups:
farm_context: crop, system type, zone identifier
sensor: root-zone or substrate moisture, timestamp, optional telemetry age
expected_fields: moisture fields expected for this system
Output schema:
{
"irrigation_risk_labels": [],
"missing_fields": [],
"suspect_fields": [],
"safe_next_checks": [],
"blocked_actions": [],
"human_review_required": false,
"rationale": ""
}
Allowed risk labels:
[
"missing_moisture",
"low_moisture",
"high_moisture",
"irrigation_underwatering",
"irrigation_overwatering",
"stale_irrigation_data",
"sensor_anomaly",
"insufficient_context"
]
Allowed blocked actions:
[
"autonomous_irrigation_change",
"irrigation_schedule_change"
]
Policy Thresholds Learned In This Version
- moisture below
0 or above 100: sensor_anomaly
- moisture at or below
28: low_moisture and irrigation_underwatering
- moisture at or above
78: high_moisture and irrigation_overwatering
- moisture above
28 and below 78: normal when context is complete
- stale timestamp or
telemetry_age_minutes > 60: stale_irrigation_data
These are Pomona v0.1 policy defaults, not universal crop prescriptions. Production systems must calibrate thresholds for crop, substrate, sensor, and irrigation design.
Usage
import json
import torch
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
BASE_MODEL = "Qwen/Qwen2.5-0.5B-Instruct"
ADAPTER = "Okyanus/pomona-water-irrigation-risk-reasoner-v0.1.8-lora"
SYSTEM_PROMPT = """You are Pomona Water Irrigation Risk Reasoner.
Return exactly one JSON object with these keys in order:
irrigation_risk_labels, missing_fields, suspect_fields, safe_next_checks,
blocked_actions, human_review_required, rationale.
Use only the labels and blocked actions documented in the model card.
Moisture below 0 or above 100 is sensor_anomaly.
Moisture <= 28 is low_moisture plus irrigation_underwatering.
Moisture >= 78 is high_moisture plus irrigation_overwatering.
A stale timestamp or telemetry_age_minutes > 60 is stale_irrigation_data.
Missing expected fields or system_type is insufficient context.
Never control equipment and never output text outside the JSON object."""
payload = {
"farm_context": {
"crop": "tomato",
"system_type": "greenhouse_substrate",
"zone_id": "greenhouse-a",
},
"sensor": {
"substrate_moisture_pct": 82.3,
"air_temperature_c": 25.1,
"humidity_pct": 74.0,
"timestamp": "2026-07-10T10:00:00Z",
"telemetry_age_minutes": 7.0,
},
"expected_fields": ["substrate_moisture_pct"],
}
tokenizer = AutoTokenizer.from_pretrained(ADAPTER)
dtype = torch.bfloat16 if torch.cuda.is_available() else torch.float32
base = AutoModelForCausalLM.from_pretrained(
BASE_MODEL,
dtype=dtype,
device_map="auto",
)
model = PeftModel.from_pretrained(base, ADAPTER)
model.eval()
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": "Classify this farm irrigation packet.\n" + json.dumps(payload, separators=(",", ":"), sort_keys=True)},
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
generated = model.generate(
**inputs,
max_new_tokens=260,
do_sample=False,
pad_token_id=tokenizer.eos_token_id,
)
text = tokenizer.decode(generated[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
result = json.loads(text[text.find("{"):text.rfind("}") + 1])
print(json.dumps(result, indent=2))
Evaluation
Leakage-free internal test:
Table with columns: Metric, Result| Metric | Result |
|---|
| Cases | 392 |
| Exact train/test input overlap | 0 |
| Valid JSON | 1.000 |
| Allowed labels | 1.000 |
| Allowed blocked actions | 1.000 |
| Label F1 | 1.000 |
| Blocked-action F1 | 1.000 |
| Human-review match | 1.000 |
| Exact full-object match | 0.844 |
Independent external holdout:
Table with columns: Metric, Result| Metric | Result |
|---|
| Cases | 168 |
| Exact train/holdout input overlap | 0 |
| Required fields present | 1.000 |
| Valid JSON | 1.000 |
| Allowed labels/actions | 1.000 |
| Label F1 | 1.000 |
| Blocked-action F1 | 1.000 |
| Human-review match | 1.000 |
Every external holdout category scored label F1 1.0: normal, low moisture, high moisture, missing moisture, stale telemetry, sensor anomaly, and insufficient context.
The lower internal exact-object score is primarily wording variation in safe_next_checks; semantic labels, blocked actions, and review decisions were correct.
Data
Training and evaluation records are compact synthetic, rule-derived Pomona examples. The v0.1.8 split contains 4,560 training, 392 validation, and 392 test records. Exact input overlap across those splits is zero. The independent external holdout contains 168 additional records with zero exact overlap against training.
No raw third-party dataset is included in this model repository. These results validate the narrow policy task and JSON contract; they are not evidence of field efficacy or universal agronomic thresholds.
Safety
This adapter is advisory only. It must never directly control pumps, valves, irrigation schedules, fertigation, or chemicals.
Recommended flow:
sensor-quality checks
-> this adapter
-> deterministic Pomona irrigation/safety rules
-> dashboard and human review
-> separately authorized automation layer
Deterministic logic remains final authority for blocked actions, impossible readings, missing context, and real equipment control.
Limitations
- Synthetic/rule-derived data, not human-labeled farm incidents.
- Narrow moisture and context classification only.
- No pump-flow, valve-state, reservoir chemistry, weather forecast, or crop-specific irrigation model.
- Policy thresholds require local calibration.
- Correct structured output is not authorization to act.
- Use deterministic validation and human review in production.
Small-Reasoner Motivation
Pomona uses small specialist adapters for narrow, verifiable tasks instead of asking one large model to perform every farm operation. This is conceptually related to VibeThinker-style small-reasoner research: constrained tasks, strict outputs, and strong evaluation can make compact models useful.
This adapter does not use VibeThinker code, weights, or datasets. The relationship is design inspiration only.