尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
Links coroners' Prevention of Future Deaths reports where the same warning comes back to the same organisation. NVIDIA Nemotron on Nebius Token Factory.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Coroners in England and Wales write Prevention of Future Deaths (PFD) reports when a death reveals a risk to others. The organisation that receives one must reply within 56 days with what it will change. Years later, a similar death can happen in front of a different coroner who has no way of knowing the concern was raised before.
Recurance reads every published report and response, links later concerns to earlier warnings sent to the same organisation, and shows where a concern recurred after a stated action, with verbatim quotes from both documents.
PFD Monitor groups concerns. The Preventable Deaths Tracker chases deadlines. Recurance tests whether promises held.
Built for the Nebius x NVIDIA Global AI Hackathon, Best Apps and Agents track.
On the site:
Every model call goes to Nebius Token Factory through one wrapper (pipeline/llm.py, and web/lib/llm.ts for the app). The wrapper caches by request hash, writes every call to a cost ledger, and refuses any call that could cross a stage budget.
| Step | Model on Token Factory | Why this model |
|---|---|---|
| Concern extraction (Stage A) | nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B | Cheap, fast, enforced JSON schema, good at copying exact quotes |
| Promise extraction (Stage B) | nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B | Same task shape on response letters |
| Recurrence judge (Stage C) | nvidia/nemotron-3-super-120b-a12b, reasoning on, low effort | The hard semantic call: same hazard or merely the same topic |
| Flagship dossiers (Stage D) | nvidia/Nemotron-3-Ultra-550b-a55b | Long context (1M) for a whole chain in one prompt |
| Follow-up classification (Stage F) | nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B | Classifies Tavily results with quotes |
| Embeddings | Qwen/Qwen3-Embedding-8B | No NVIDIA embedding model is served; this keeps retrieval on Token Factory |
| Live agent (runtime) | Super with native tool calling chooses the tools; Nano extracts; Qwen3 embeddings retrieve | Runs on every new report a user submits, with the fixed pipeline as fallback |
Features of Token Factory used:
Check a report runs an agent. Nemotron Super chooses among five tools until it submits its findings:
| Tool | What it does |
|---|---|
| search_earlier_concerns | Finds the earlier concerns sent to the same organisation that are closest in meaning (Qwen3 embeddings, pgvector) |
| judge_candidate | Runs the recurrence judge (Super, structured output) and checks both quotes word for word |
| get_response_promises | Reads the actions stated in the organisation's published response |
| get_chain | Looks up whether the earlier report is already part of a recurrence chain |
| tavily_check | Searches the web for evidence of what happened next, reusing an earlier check when there is one |
The limits are 5 rounds and $0.015 per run. The model never writes a shown quote: verdicts come from judge_candidate, and every quote is checked in code. If the agent fails or hits a limit, the fixed pipeline runs instead. The loop and its checks are tested offline with a scripted model (web/tests/agent.test.ts).
The site runs on one Linux server with Docker Compose: PostgreSQL with pgvector, the web app, a weekly refresh worker, and Caddy for HTTPS or an existing web server in front (deploy/README.md). It is live at https://recurance.com. Every model call runs on Nebius Token Factory.
Tavily checks what happened after an organisation stated an action. For each promise in a chain, two searches and one extract gather sources. Nemotron Nano then classifies them as evidence found, not found or contradicting, quoting the source word for word. "Not found" is never shown as "did not happen". Credits are budgeted from the balance read from Tavily's usage endpoint (D28). The checks went first to the demo chains, then to the chains with a dossier, then to the chains with the most recurrences. 269 promises have been checked: evidence found for 28, contradicting for 2, not found for 239. The live agent can run its own checks, with a daily cap.
| Stage | Model | Paid calls | Spend |
|---|---|---|---|
| A, concerns from 6,196 reports | Nano | 6,780 | $0.77 |
| B, promises from responses, including one incremental refresh | Nano | 1,751 | $0.23 |
| C, 4,543 report pairs judged, plus evaluation and systemic clusters | Super | 4,608 | $3.37 |
| D, flagship dossiers | Ultra | 76 | $0.97 |
| F, follow-up classification | Nano | 266 | $0.05 |
| Embeddings | Qwen3-Embedding-8B | 310 | $0.01 |
| Pilots, development, chain titles, live tests and 28 precomputed briefs | mixed | 1,217 | $0.26 |
| Total | 15,008 | $5.65 |
Every call is in the llm_calls ledger (15,267 rows, including 258 free cache hits). One row is a local attempt made before the key was loaded; it sent nothing and cost nothing. Stage F used 801 Tavily credits by the ledger's count, every call logged in tavily_calls.
| Path | Contents |
|---|---|
| pipeline/ | Python 3.11 pipeline: scrape, parse, normalise, link, extract, judge, dossier, followup, evaluate, export, publish |
| pipeline/cli.py | One entry point with a subcommand per step |
| web/ | Next.js app (App Router, TypeScript, Tailwind) that reads PostgreSQL |
| deploy/ | Docker Compose for one server: PostgreSQL with pgvector, the web app, a refresh worker and Caddy |
| tests/ | Offline tests. They use recorded fixtures and never call the live API |
| docs/ | Research log, decisions, evaluation, feedback, demo script |
The data is not in this repository: the scraped reports and working database come to about 1.3 GB. To explore the results without building anything, use https://recurance.com or its read-only API (/api/v1/chains). To rebuild everything, follow the steps below and "Running the pipeline" with your own Token Factory key: a few hours of scraping at one request a second, and about $6 of model calls. The tests need neither data nor keys.
python -m venv .venv
.venv/Scripts/pip install -r requirements.txt # Windows
.venv/bin/pip install -r requirements.txt # macOS and Linux
Each step is a subcommand of python -m pipeline.cli. Steps that spend money print an estimate first, and full runs need --confirm-spend.
python -m pipeline.cli scrape all # sitemaps, report pages, report PDFs, listing cross-check (1 request/second)
python -m pipeline.cli build # parse into data/recurrence.sqlite
python -m pipeline.cli normalise # organisations and aliases
python -m pipeline.cli stage-a --pilot # 20-report pilot, prints measured and extrapolated cost
python -m pipeline.cli stage-a --confirm-spend --cost-per-item <measured>
python -m pipeline.cli embed
python -m pipeline.cli link
python -m pipeline.cli responses --fetch # only responses in Stage B scope
python -m pipeline.cli stage-b --pilot
python -m pipeline.cli stage-b --confirm-spend --cost-per-item <measured>
python -m pipeline.cli stage-c --pilot
python -m pipeline.cli stage-c --confirm-spend --cost-per-item <measured>
python -m pipeline.cli chains
python -m pipeline.cli dossiers # at most 25, stored unreviewed
python -m pipeline.cli followup # Tavily, capped at 250 credits
python -m pipeline.cli evaluate
python -m pipeline.cli titles # short chain titles (Nano)
python -m pipeline.cli publish # display-safe rows into PostgreSQL; the site reads these
python -m pipeline.cli spend # ledger summary
To pick up new reports later, python scripts/refresh.py runs every step on new reports only, with a spending ceiling (--max-spend, default $0.50), then publishes.
cd web
npm install
npm run build
npm start
web/.env.local sets DATABASE_URL to a read-only role on the published tables. Pages read PostgreSQL directly, so a publish shows up within two minutes with no rebuild. On Windows, start_site.cmd starts PostgreSQL in WSL and then the site.
Without a local PostgreSQL, Docker can run just the database while the site runs natively:
services:
db:
ports:
- "127.0.0.1:5433:5432"
docker compose --env-file .env up -d db from deploy/, then load the tables with python -m pipeline.cli publish.postgresql://rw_web:<WEB_DB_PASSWORD>@127.0.0.1:5433/recurrence.Until a publish has run, most pages load empty and the home page cannot render.
The live brief needs NEBIUS_LIVE_API_KEY, a separate key from the pipeline's. Without it the brief shows precomputed examples.
deploy/README.md has the steps for one Linux server with Docker Compose. A worker refreshes the data weekly and republishes.
Recurance builds on earlier work with the same reports, and differs in what it asks of them.
| Project | What it does | How Recurance differs |
|---|---|---|
| PFD Monitor (pfdmonitor.org) | AI-extracted concerns grouped into themes, with stated actions | Links each later concern to the earlier warning to the same organisation, with quotes from both |
| Preventable Deaths Tracker (preventabledeathstracker.net, Georgia Richards) | Tracks responses and overdue replies | Asks whether the concern came back after a response stated an action |
| PFD Toolkit (github.com/Sam-Osian/PFD-toolkit) | Open-source loader and thematic analysis | Written from scratch; no PFD Toolkit code is used |