Individual researcher — using Duecare for analysis¶
Persona. Academic, NGO research lead, investigative journalist, grad student. You don't deploy software for a living. You want to use Duecare as a tool: feed it data, get back structured analysis you can cite or build on.
Use cases. Code a labor-trafficking dataset. Compare Gemma 4 against alternatives on a domain rubric. Map fee-camouflage patterns across 10k posts on Facebook job groups. Analyze a year of court filings for ILO-indicator coverage. Reproduce someone else's published numbers to verify them.
What this doc gives you. Three concrete workflows + the citations + the reproducibility pattern researchers need to defend their results.
TL;DR¶
| You want to... | Use |
|---|---|
| Try the harness without installing anything | The active Kaggle exploration workbench and live demo |
| Run on your own dataset (≤ 1000 prompts) | Local CLI: examples/deployment/local-cli/duecare_cli.py |
| Run a batch (1000+ prompts) | A short Python script using duecare-llm-chat |
| Compare Gemma 4 vs other models | The A-00 omni experiment workbench |
| Add your domain (medical / fraud / etc.) | Extension pack format + a custom domain pack |
| Cite specific findings | The (git_sha, dataset_version, model_revision) provenance pattern |
Three concrete workflows¶
Workflow 1: Reproduce a published number¶
Suppose you read in the writeup: "+51.4 pp mean lift on the 200+ prompt proxy rubric" and you want to verify it.
# 1. Install
pip install duecare-llm-chat duecare-llm-tasks duecare-llm-domains
# 2. Get the dataset (the 200+ prompts + their rubric examples)
git clone https://github.com/TaylorAmarelTech/gemma4_comp.git
cd gemma4_comp
# 3. Pull the model (Apache 2.0, ungated)
ollama pull gemma4:e2b
# 4. Reproduce
python scripts/run_local_gemma.py --graded-only --output reproduce.jsonl
# 5. Compare your output to the published harness_lift_report.md numbers
python scripts/compare_to_published.py reproduce.jsonl docs/harness_lift_report.md
The reproduction tolerates ±2% per category (model nondeterminism) and prints any rows that diverge by more than that.
Workflow 2: Run on your own dataset¶
Suppose you have 500 job postings scraped from a regional Facebook group. You want to know: how many show recruitment-fraud patterns?
from duecare.chat.harness import apply_grep_rules, retrieve_rag_docs
import json
with open("my_postings.jsonl") as f:
postings = [json.loads(line) for line in f]
results = []
for posting in postings:
text = posting["body"]
grep_hits = apply_grep_rules(text)
if grep_hits:
results.append({
"post_id": posting["id"],
"rules_fired": [h["rule"] for h in grep_hits],
"indicators": list({h["indicator"] for h in grep_hits}),
"snippet": text[:200],
})
# Quick triage: the highest-severity hits
critical = [r for r in results
if any(rule.endswith("critical") for rule in r["rules_fired"])]
print(f"{len(critical)} of {len(postings)} show critical patterns.")
# Save for downstream analysis
with open("flagged.jsonl", "w") as f:
for r in results:
f.write(json.dumps(r) + "\n")
That's it. No model needed. The GREP layer alone gives you a deterministic first pass — fast (10k posts/sec on CPU), reproducible, defensible.
For a richer analysis with Gemma 4 reasoning per posting:
import requests
OLLAMA = "http://localhost:11434"
for r in results[:50]: # sample of 50
text = next(p["body"] for p in postings if p["id"] == r["post_id"])
prompt = f"""Analyze this job posting for trafficking indicators:
{text}
Cite specific ILO C029 indicators (1-11) by number, the controlling
statute if known, and what evidence in the post supports your
finding."""
resp = requests.post(f"{OLLAMA}/api/generate", json={
"model": "gemma4:e2b",
"prompt": prompt,
"stream": False,
})
r["gemma_analysis"] = resp.json().get("response", "")
Workflow 3: Compare Gemma 4 against alternatives¶
For "Gemma 4 vs GPT-4 vs Claude vs Mistral on the trafficking-rubric" papers:
# Use the A-00 comparison pipeline directly
# Open the active A-00 omni experiment workbench and export the report bundle
#
# OR locally:
python scripts/run_comparison.py \
--models gemma4:e2b gemma4:e4b claude-sonnet-4 gpt-4o \
--rubric trafficking_legal_citation_quality \
--n-prompts 200 \
--output comparison.jsonl
Caveats:
- Cloud models need API keys in env vars (ANTHROPIC_API_KEY,
OPENAI_API_KEY, etc.) — those rows in the output get redacted
to model names only, no prompt/response content
- Comparison is fair only if all models see the same prompt; the
harness layers can be on or off independently per model
- Cite the exact (git_sha, dataset_version, model_revision) for
each row so others can reproduce
Reproducibility — the citation contract¶
Every metric Duecare publishes is anchored to three IDs:
When you cite Duecare in a paper / post / report:
- git_sha: pin the repo to a specific commit SHA —
git checkout <sha> - dataset_version: the Kaggle dataset version pinned in the
notebook's
kernel-metadata.json, e.g.taylorsamarel/duecare-trafficking-prompts/v3 - model_revision: the HF Hub revision SHA of the model,
e.g.
google/gemma-4-e2b-it@a3f9c1d
All three together let any reader rerun your analysis and get the same numbers (within the model's nondeterminism tolerance).
Example footnote in a paper:
Proxy lift figures (+51.4 pp mean) computed against 200+ prompt proxies using the Duecare safety harness at git SHA
c235e14, datasettaylorsamarel/duecare-trafficking-prompts@v3, modelgoogle/gemma-4-e2b-it@mainas of 2026-05-02. Reproduction instructions:docs/scenarios/researcher-analysis.md, "Workflow 1".
Datasets you can use¶
Bundled / public:
| Dataset | Slug | Size | License |
|---|---|---|---|
| Trafficking prompts (public) | taylorsamarel/duecare-trafficking-prompts |
Large public prompt set; verify the current manifest before citing an exact count | CC-BY-4.0 |
| 5-grade rubric annotations | (in the same dataset) | 200+ prompt proxies; cite the current export for exact counts | CC-BY-4.0 |
| Corridor lookup tables | (bundled in duecare-llm-domains) |
Versioned corridor tables; cite the current package manifest for exact counts | MIT |
| Trafficking GREP rule catalog | (bundled in duecare-llm-chat) |
100+ rules | MIT |
| RAG legal corpus | (bundled in duecare-llm-chat) |
50+ docs | CC-BY-4.0 (each doc has its own attribution) |
For your own data:
- Hand-grade 50-100 prompts in your domain. That's the rubric you'll cite. The published 200+ prompt rubric took ~30 hours of focused hand-grading; budget similar.
- Save in JSONL:
{"id": "...", "prompt": "...", "expected": ["..."]}. - Use
duecare-llm-tasksto run the rubric against any model.
What makes a research finding defensible¶
If you're publishing a result like "Gemma 4 + Duecare improves legal citation quality by N pp on our domain":
- Pre-register the rubric — write the 12-point rubric BEFORE running the model. Otherwise post-hoc rubric design will leak the result you want.
- Hand-grade > 100 prompts — fewer and your confidence intervals are too wide to publish. The bundled rubric uses 200+.
- Report nondeterminism — run each prompt 3+ times with
temperature=0.7; report mean ± std. Or usetemperature=0for a deterministic single run (and note this disables Gemma's sampling behaviors that real users would see). - Pin everything —
(git_sha, dataset_version, model_revision). Without this, your paper isn't reproducible by anyone, including your future self. - Disclose what's BUNDLED vs CUSTOM — if you used the bundled GREP catalog + RAG corpus + tools, say so. If you added a domain-specific extension, link to the extension pack.
- Publish your prompts + your annotation — even if you can't release the model output (license / cost), publish the inputs. That's the minimum for replication.
How NOT to use Duecare for research¶
- Don't grade the model with the model. "Use Gemma 4 to score Gemma 4's responses" produces a self-flattering rubric that doesn't generalize. Hand-grade or use a different LLM as judge.
- Don't conflate harness lift with model improvement. The +51.4 pp number is the harness's contribution; it doesn't mean Gemma 4 got smarter. Always report harness OFF vs ON separately so the contributions are visible.
- Don't draw causal conclusions from cross-sectional data. "Posts with rule X fire are Y% more likely to be trafficking" needs longitudinal validation (do those posts actually correlate with confirmed cases?). The bundled rubric doesn't claim to.
- Don't anonymize by removing only obvious PII. Quasi-identifiers (corridor + recruiter name + date) re-identify a small population. Use proper k-anonymity / differential privacy if your data is sensitive.
Citation¶
If you use Duecare in academic work, please cite:
@software{amarel_duecare_2026,
author = {Taylor Amarel},
title = {Duecare: a content-safety harness for Gemma 4
on migrant-worker trafficking risk},
year = 2026,
publisher = {GitHub},
version = {0.1.0},
url = {https://github.com/TaylorAmarelTech/gemma4_comp},
note = {Submission to the Gemma 4 Good Hackathon}
}
If your work specifically uses the harness-lift methodology in
docs/harness_lift_report.md,
also cite the rubric DOI (TBD on rubric publication).
Adjacent reads¶
docs/embedding_guide.md— for embedding the harness into other research tools / dashboardsdocs/scenarios/lawyer-evidence-prep.md— adjacent persona; legal-aid clinicdocs/scenarios/regulator-pattern-analysis.md— adjacent persona; government regulatorkaggle/_INDEX.md— full notebook roster