Downloads · 30 days
9
21% of all-time downloads
Jainamshahhh/opshr-4b
opshr-4b is a text generation model from Jainamshahhh. Use it when you need the model to write or continue text. It is set up for peft. The card lists the license as apache-2.0.
OpsHR-4B is a LoRA adaptation of google/gemma-3-4b-it for HR operations: calling HR-ops tools with exact arguments, asking for the parameter it was not given instead of inventing one, declining requests no tool suppor…
Downloads · 30 days
9
21% of all-time downloads
All-time downloads
43
Public
Repo size
272 MB
Likes
0
Public
Click a slice to open those files.
.safetensors238 MB · 88%
From the Hugging Face model README
OpsHR-4B is a LoRA adaptation of google/gemma-3-4b-it for HR operations: calling HR-ops tools
with exact arguments, asking for the parameter it was not given instead of inventing one, declining
requests no tool supports, and answering federal policy questions with the source URL attached.
Built for the Adaption AutoScientist Challenge, Part 2 (HR); the training corpus was co-optimized
with Adaptive Data (Adaption Labs).
Adapters are usually scored by win rate, the share of rows where a language model judge preferred the tuned output. Every number on this card is exact-match accuracy against a target the generator computed: JSON parse, action, tool name, argument values, and the identity of the withheld parameter, all compared mechanically.
The two are not interchangeable, and this project has the receipt. A sibling entry in this portfolio trained its identical corpus on Adaption's own AutoScientist. The platform reported a 95.48% win rate. Our scorer, run on that same adapter, measured 62.0% exact-match accuracy. A win rate is a preference; an accuracy is a fact.
| what is measured | exact match on action, tool, and every argument value |
| a language model judged something | never, not the labels, not the scoring |
| held-out probes scored | 225, across an easy and a deliberately hard set |
| significance | p = 2.6e-23 held-out, p = 3.0e-6 on the hard set |
| what this card volunteers | the hard set, where the score drops to 41.3%, released in full |
| cost to recompute every number | one laptop, no GPU |
google/gemma-3-4b-it, measured before any training, so the starting point is on
the record and the improvement is a measurement rather than a claim.150 held-out probes from a disjoint seed space (train/probe prompt overlap asserted 0), base
and tuned generated in one run under identical greedy decoding. Scored by
part2/scripts/hr/score_hr_tools.py, which compares against a target the generator computed. No
language model judges anything.
| Metric | Base | OpsHR-4B |
|---|---|---|
| JSON valid | 100.0% | 100.0% |
| Action correct (call / clarify / refuse) | 72.7% | 100.0% |
| Tool correct (n=98 call rows) | 100.0% | 100.0% |
| Arguments exact (n=98) | 62.4% | 100.0% |
| Withheld parameter identified (n=33 clarify rows) | 0.0% | 100.0% |
| Refused correctly (n=19) | 100.0% | 100.0% |
| Overall, fully correct | 49.3% | 100.0% |
The set above shares templates with training. A second, deliberately harder set of 75 rows was built to break that resemblance (unseen phrasings, unseen refusal categories, noisy slot formats; 0 of 75 request lines appear verbatim in training against 44 of 150 for the easy set). Both are released. Here is how the model does on it:
| Metric | Base | OpsHR-4B |
|---|---|---|
| Overall, fully correct | 12.0% | 41.3% (+29.3 pts, +244% relative) |
| Refused correctly (n=10) | 60.0% | 100.0% |
| Withheld parameter identified (n=29) | 15.4% | 78.9% |
| Arguments exact (n=36) | 4.3% | 18.2% |
| JSON valid / tool correct | 100% / 100% | 100% / 100% |
So 100% becomes 41.3% once the phrasing is unfamiliar, and that is the honest number to plan against. Three things are worth reading off it:
The weak spot is specific: exact argument extraction from unfamiliar wording, at 18.2%. The model still picks the right tool every time and still knows when to decline; what did not generalise is pulling precise values out of phrasing it has not seen. That is the part of the easy-probe 100% that was template familiarity, and it is the first thing we would fix next.
Broken out by the answer the row required:
| Answer required | Base | OpsHR-4B |
|---|---|---|
call (n=98) | 59.2% | 100.0% |
clarify (n=33) | 0.0% | 100.0% |
refuse (n=19) | 84.2% | 100.0% |
overall requires the action and its full payload to be right. There is no partial credit for a
confidently wrong call, because in this domain a confidently wrong call is the expensive outcome.
Base and tuned answer the same probes in one run, so this is a paired design and the right test is an exact McNemar test on the rows where exactly one model was right. The null is that the adapter is no better than the base.
| probe set | only tuned right | only base right | exact two-sided p |
|---|---|---|---|
| held-out tool probes (150) | 76 | 0 | 2.6e-23 |
| harder probe set (75) | 23 | 1 | 3.0e-6 |
The harder set is the honest one to read: the advantage is smaller there, and it is still
significant at p = 3.0e-6 with the base taking one row outright. Recompute with the released
significance.py from the released generation files.
The base model is not bad at HR tool calling in the way you would expect. It emitted valid JSON 100% of the time and picked the correct tool 100% of the time. Prompt engineering would not have found a problem here.
Its failure was narrower and worse: when a required parameter was absent from the request, it invented a plausible value and reported a completed action. On the 33 probes that withheld a parameter, it clarified 0 times and fabricated the missing value in 31.
Verbatim, from the held-out probe set. The request asks to start onboarding but never states a start date:
{"action":"call","tool":"start_onboarding","arguments":{"candidate_id":"CAND-2878","start_date":"2024-01-26","manager_id":"EMP-5668","equipment_bundle":"laptop_standard"}}
The date 2024-01-26 appears nowhere in the request. It is invented, and it is in the past.{"action":"clarify","missing":["start_date"],"question":"Which start date should I use?"}An HR assistant that guesses start dates schedules onboarding for the wrong day and reports success. That is the behaviour this model removes.
This matters because an earlier iteration of this entry did regress in exactly that way: it
learned short answers and applied the habit everywhere, replying to "give me six interview questions"
with four. Accuracy rose, usefulness fell. So completeness is measured here as a first-class metric
rather than assumed, by part2/scripts/hr/score_hr_gen.py on 60 held-out generative probes.
| Metric | Base | OpsHR-4B |
|---|---|---|
| Delivered at least the requested number of items (n=10) | 70.0% | 100.0% |
| Policy answer carries a source URL (n=20) | 5.0% | 90.0% |
| Job description has all five required sections (n=15) | 53.3% | 100.0% |
| Reply finished instead of stopping mid-word (n=60) | 26.7% | 100.0% |
OpsHR-4B is far shorter than the base, so the terseness question deserves a direct answer. Median reply length as a fraction of what that shard's training targets actually contain:
| Category | Training target | OpsHR-4B | ratio | Base | ratio |
|---|---|---|---|---|---|
jd_writing | 1,340 chars | 1,268 | 0.95 | 4,116 | 3.07 |
interview_gen | 453 | 527 | 1.16 | 3,951 | 8.72 |
resume_fit | 405 | 393 | 0.97 | 1,759 | 4.34 |
policy_qa | 363 | 304 | 0.84 | 3,472 | 9.57 |
A terseness collapse looks like one uniformly low ratio across every task. What is here is four ratios near 1.0 that differ by category by more than 4x: the model writes a 1,268-character job description and a 304-character policy answer, because that is what each task calls for. The base's length is not thoroughness either. 44 of its 60 replies stopped mid-word at the token budget, so its job descriptions were missing the sections it had not reached yet.
clarify and refuse are 21% of
the released tool corpus. A model trained only on successful calls has no way to learn that
declining is an option, which is exactly how the base ends up at 0.0% clarify.google/gemma-3-4b-it is the base of every entry in this portfolio, fixed
before any result existed. It was not chosen for weakness and this card does not portray it as
weak: 100% valid JSON, 100% correct tool selection, 49.3% overall. The improvement is measured
against a base that is genuinely good at everything prompt engineering can reach, and broken
only in the one place training was needed.python part2/scripts/hr/verify_hr_dataset.py re-derives every
dataset claim (all 13 checks pass), and both scorers run on the released generation files.google/gemma-3-4b-it, Gemma terms..*\.language_model\..*\.(q|k|v|o|gate|up|down)_proj). gemma-3-4b-it is a multimodal checkpoint;
this attaches 2,142 modules and 0 vision modules, verified at launch.disable_adapter(), under identical greedy decoding. A win therefore cannot be a
decoding artifact.part2/scripts/hr/probe_similarity.py.from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel
import torch
# AutoModelForCausalLM resolves gemma-3-4b-it to its multimodal wrapper, which is correct.
# Do NOT load it through a text-only class: the decoder is then randomly initialized.
tok = AutoTokenizer.from_pretrained("google/gemma-3-4b-it")
base = AutoModelForCausalLM.from_pretrained(
"google/gemma-3-4b-it", torch_dtype=torch.bfloat16, device_map="auto")
model = PeftModel.from_pretrained(base, "Jainamshahhh/opshr-4b").eval()
prompt = """You have these tools:
- start_onboarding(candidate_id*, start_date*, manager_id*, equipment_bundle)
- schedule_interview(candidate_id*, interviewer_id*, slot*)
Request: Start onboarding for CAND-2878 with manager EMP-5668, standard laptop bundle.
Reply with exactly one JSON object and nothing else. Use {"action":"call","tool":<name>,"arguments":{...}}
when a tool applies, {"action":"clarify","missing":[<parameter>],"question":<question>} when a required
parameter was not provided, or {"action":"refuse","reason":<reason>} when no tool supports the request."""
ids = tok.apply_chat_template([{"role": "user", "content": prompt}],
add_generation_prompt=True, return_tensors="pt").to(model.device)
out = model.generate(ids, max_new_tokens=256, do_sample=False)
print(tok.decode(out[0][ids.shape[1]:], skip_special_tokens=True))
# -> {"action": "clarify", "missing": ["start_date"], "question": "Which start date should I use?"}
Live side by side demo: https://huggingface.co/spaces/Jainamshahhh/opshr-demo Enter your own input and watch the base model and OpsHR-4B answer it under identical greedy decoding. The GPU backend scales to zero, so a cold first request takes about a minute.
Released on both platforms, with the scorer, every eval slice, the per row verdicts and
significance.py alongside, so every number on this page can be recomputed rather than
trusted.
Jainamshahhh/hr-ops-tools. Scorers, dataset verifier and the raw generation files are
released alongside, so every number on this card can be recomputed.Author: Jainam Shah. Built with Adaptive Data (Adaption Labs) and the open Gemma model.