Fabella / DATASET.md
OpenCode
docs: point all dataset references at build-small-hackathon/fabella-traces
d2ed801
|
Raw
History Blame Contribute Delete
5.56 kB
# Fabella Anonymized Agent Traces
When the public publisher is enabled, one anonymized row per request lands at
[`build-small-hackathon/fabella-traces`](https://huggingface.co/datasets/build-small-hackathon/fabella-traces).
The dataset repo is public and contains the live card, the publisher schema, and 5 seed rows for the data viewer. The Space publishes to it only when `FABELLA_SHARE_TRACES=1` is set on the Space (default `0`); with the flag off, rows only live in the per-parent bucket and are exportable via the Space's **Settings β†’ Download my history** button.
This file is a local copy of the Hugging Face dataset card for Fabella's anonymized agent-trace publication. The live card on the Hub is the source of truth; this file is a convenience for reviewers reading the source repo.
## Why this exists
Fabella is a small Hugging Face Space that drafts short, kind, age-appropriate explanations a parent can use to talk to their child about a hard thing (a hospitalization, a move, a pet dying). The first version is generated by `google/gemma-4-E4B-it`; a `nvidia/NVIDIA-Nemotron-3-Nano-4B-BF16` judge scores it against a six-criterion rubric; the drafter revises if needed. An optional read-aloud uses `openbmb/VoxCPM2`.
The dataset captures the full ReAct loop for every successful generation, with PII removed before the row leaves the Space. It's the **Sharing is Caring** merit-badge artifact for the [Build Small Hackathon](https://huggingface.co/spaces/build-small-hackathon/README) submission.
## Where it lives
- **Live dataset (when enabled):** https://huggingface.co/datasets/build-small-hackathon/fabella-traces (default)
- **Personal-namespace fallback:** set `FABELLA_TRACE_REPO=Kiy-K/fabella-traces` to publish to the maker's personal dataset instead. Used for local dev where the Space's HF_TOKEN can't create in the org namespace.
- **Default for this demo:** the publisher is OFF (`FABELLA_SHARE_TRACES=0`); data lives in the per-parent bucket and is exportable via the Space's **Settings β†’ Download my history** button.
The dataset repo is created on first publish by `trace.py::_ensure_repo` via `HfApi.create_repo(exist_ok=True)`, so a fresh deployment does not require a one-time setup step.
## Schema (one row per request, when publishing is enabled)
```jsonc
{
"trace_id": "<uuid>",
"created_at": "2026-06-14T14:04:05+00:00",
"schema_version": 1,
"app_version": "fabella-1",
"model_versions": {
"drafter": "google/gemma-4-E4B-it",
"judge": "nvidia/NVIDIA-Nemotron-3-Nano-4B-BF16"
},
"request": {
"age": 7,
"tone": "gentle",
"child_name_present": true,
"child_name_redacted": "[name]",
"situation_hash": "sha256:9a3ba115d57a3789",
"situation_preview": "My 7yo's grandma is in the hospital.",
"situation_length": 36,
"history_turns": 0
},
"agent": {
"system_prompt": "<static, public, in-repo>",
"user_prompt": "A parent needs help...\n\nThe latest thing the parent is asking about: <redacted, see request.situation_length>",
"messages": [ /* full LangChain ReAct trace */ ],
"final_draft": { "opener": "...", "body": "...", "closer": "...", "followup": "..." }
},
"judge": {
"ok": true,
"issues": [],
"score": 0.92,
"verdict": "approve",
"reasoning": "good"
},
"latency_ms": 1234,
"tool_calls": 1
}
```
## Anonymization
The publisher in `trace.py` runs every row through five anonymization passes before the row leaves the Space:
1. **Child name** is dropped from the request and replaced with `"[name]"` in the final draft.
2. **Raw situation** is never stored. Only its SHA-256 hash, the first 60 chars as a topic preview, and its character length are kept.
3. **Freeform history turns** are replaced with role + length counts. The drafter's user prompt additionally replaces the embedded situation with a length-only marker.
4. **System prompt** is shipped in full (it's a static string in this repo, not user input).
5. **LangChain 1.x `content` lists** are normalized so list-of-blocks content is joined to its text.
## Self-export
Every parent can pull their own data via **Settings β†’ Download my history** in the running Space. The downloaded JSON bundle contains:
- All chat turns stored under the parent's owner key (full, not redacted β€” the parent already has this in their browser).
- The durable memory summary.
- A `trace_publication` section that says exactly which dataset the redacted rows go to, the URL, the per-session row estimate, and the same five anonymization passes above.
The download path exists for two reasons: (1) the parent can verify that what we ship to the public dataset does not include raw situation text, child name, or anything that would link a row back to them; and (2) for a 3-day hackathon demo, it sidesteps the cold-start tax of the Hub push entirely.
## Opt-out
- Set `FABELLA_SHARE_TRACES=0` on the Space to kill the publisher (this is the default).
- Or pass `share_trace=False` on `make_explanation` to opt out per request.
The default for this demo is **off**: rows only live in the per-parent bucket, accessible via the Download button.
## Source code
- `trace.py` β€” the source of truth for the schema and the anonymization rules.
- `agent.py::_maybe_publish_trace` β€” the call site that builds and submits each row.
- `app.py` β€” calls `_trace.publisher.start()` at import time, exposes `GET /api/history/download` for the parent self-export.
- `app.py` `INDEX_HTML` β€” wires the **Download my history** button in the settings dialog.