Project Info
Inspiration
We kept noticing how often your genes decide whether a drug is safe — most importantly in oncology, which we all cared about. The DPYD gene, for example, makes the enzyme that breaks down the chemotherapy drug 5-fluorouracil. If you inherit a variant that weakens that enzyme, the drug never clears and builds up to toxic levels, so the same dose that cures one patient can land another in the hospital. And it isn't just cancer. For most everyday drugs, it comes down to the liver's cytochrome P450 enzymes, and the genes behind them vary widely from person to person. Slow metabolizers can't clear a drug, so it climbs to dangerous levels; ultrarapid metabolizers burn through it before it can work. One person's right dose is another's overdose, and another's waste of time. Hospitals already act on this with genetic panels and pharmacist-applied CPIC guidelines, but the millions of people sitting on a 23andMe, Ancestry, or other customer DNA file had no private way to ask what their results meant for a medication. That's the gap we built DoseDNA for.
What it does
You drop in your raw 23andMe or Ancestry file and ask plain-language questions like "I was prescribed clopidogrel — what should I know?" DoseDNA reads your DNA, works out how you'd process that drug, and explains what it means in clear terms. The whole thing runs in your browser, so your genome never leaves your device. And when your data can't actually answer the question — which happens more often than you'd think — it tells you so instead of guessing.
How we built it
DoseDNA is built on CPIC, the standard that hospitals and health providers reference. Its engine reads your raw DNA file and works through it step by step: which variants you carry, what they mean for how you process a drug, and what the guidance is. Because it follows fixed rules, the medical reasoning runs entirely on your own device (no API key, no model), and the answer is always computed, never guessed. A language layer (Claude Opus 4.8) sits on top only to put that verified answer into plain words, but it can't invent any of the medicine itself.
Challenges we ran into
The first challenge was simply being a team that had never met! We only came together at the start of the event, so we had to quickly adapt to each other's work styles and abilities. We managed it by splitting the work by piece — one of us on the CPIC engine and data, another on the interface, another on the validation tests. The next was getting it clinically right, because in pharmacogenomics, a wrong answer is worse than no answer at all. Our mentor's bar was that validation had to trace back to real patient data — not our own memory, and not the model's training. So we anchored every test to a landmark trial — CYP2C19 poor metabolizers on clopidogrel (TAILOR-PCI, 2020), or SLCO1B1 and statin-induced myopathy (SEARCH, 2008) — and checked that our answer carried the exact concept each paper proved, while catching falsely reassuring phrases like "standard dose is fine."
Accomplishments we're proud of
We're proud that the medicine is never made up — every answer comes from a CPIC clinical table, and the AI only phrases what the engine has already verified. As well, we're proud that the genome never leaves the device, so privacy is built into the architecture rather than promised in a policy. And honestly, we're proud that we shipped something this careful as a team that had only just met!
What we learned
We were honestly surprised by how much you can build in a single weekend. We also finally understood why a single variant can flip a drug's effect: with an ordinary, already-active drug, a slow metabolizer overdoses because they can't clear it; but with a prodrug, the same person gets no effect because the drug never activates. Whether the body needs to clear the drug or switch it on is the hinge on which everything turns.
What's next
Right now, we cover a focused set of genes and drugs to prove the idea works; the natural next step is broadening that to more gene–drug pairs and supporting more file formats. We'd also want a real pharmacist and clinician review of the guidance before anyone relies on it. Longer term, we see the same rigorous engine living in two places: helping individuals understand their own results, and giving clinicians a faster, trustworthy tool — moving "genotype before treatment" from something only hospitals do toward something everyone can reach.
DoseDNA
Ask your genome a straight question. A chat agent that reads your 23andMe / AncestryDNA file in your browser, calls your phenotypes with a deterministic engine, fetches CPIC's verbatim clinical recommendation live, and answers in plain language — with provider-side anonymity via cover traffic.
The conversation is on top. Underneath, it's a deterministic engine that
calls your phenotypes from PharmVar variant tables and CPIC diplotype
rules, fetches the actual CPIC drug recommendation from
api.cpicpgx.org, and grounds every clinical claim in a click-through
citation. The LLM only paraphrases verified output.
Status
Built for AI Hackathon 2026 at Berkeley, Best Beginner Hack track. Science-fair judging Sunday June 21, 1–3pm.
Live preview (landing page only, chat requires the local proxy): alejandro-publius.github.io/dosedna
For the competitive landscape and where DoseDNA fits in the existing PGx market, see MARKET_LANDSCAPE.md — cited comparison vs. 23andMe Health (and its 2023 breach + 2025 bankruptcy), Genomind, OneOme, PharmCAT, and vanilla LLMs.
For the judging-day pitch script, timing, and Q&A drills, see DEMO.md.
What's built
Chat agent UI (4-agent-chat.html / index.html)
Lindsay's landing page is the demo entry point. Load a DNA file, ask a question in natural English. Replies render with:
- CPIC evidence-strength chips (green Strong / amber Moderate / gray
Optional) that link to the published guideline on
cpicpgx.org. - Tool-call cards under each reply showing which tools the agent invoked and with what arguments.
- Cover-traffic chip indicating how many decoy queries were fired in parallel to the same provider.
Deterministic PGx engine (src/pgx.js)
- 6 genes called locally in the browser: CYP2C19, CYP2C9, VKORC1, SLCO1B1, TPMT, CYP2D6.
- CYP2D6 is always "Coverage limited" — consumer arrays cannot reliably call its structural variants, and the engine refuses to guess.
- Phenotype-if-invariant rule (BUILD_SPEC §7): when phase or coverage is ambiguous, enumerate every possible assignment; only report a phenotype if every branch agrees. Otherwise "Not determined."
- 79/79 unit tests in
tests/pgx.test.mjs, against PharmVar's variant definitions and CPIC's published diplotype tables.
In-browser parser (src/parser.worker.js)
- 23andMe and AncestryDNA TSV formats — auto-detected from header + column count.
- Runs in a Web Worker; UI never freezes.
- File bytes stay in worker scope; only
{rsid: "AG", ...}for the 10 target SNPs is handed back to the page. - 33 parser tests in
tests/parser.test.mjs.
Hardened proxy (server/proxy.py)
- One endpoint,
POST /api/explain, discriminated by akindfield (explain|questions|interactions|chat). - Holds
ANTHROPIC_API_KEY. Browser never sees it. - Allowlist built from
genes.json+drugs.jsonat startup — every(gene, phenotype, drug)tuple validated before any string reaches Claude. - Defense-in-depth: rejects payloads containing rsID-shaped strings or long ACGT runs.
- Per-IP rate limit, CORS locked to localhost.
- No request body logging.
- Model:
claude-opus-4-8.
Four agent tools (Anthropic tool-use)
get_gene_status(gene)— reads the user's phenotype for one gene from the deterministic engine's output.lookup_cpic_recommendation(gene, drug, phenotype)— fetches CPIC's verbatim implications + recommendation + evidence classification fromapi.cpicpgx.org/v1/recommendation.check_drug_interactions()— runs the deterministic engine over the user's medications: drug-drug pairs + phenoconversion shifts.suggest_clinician_questions(focus_topic)— generates 4–6 concrete questions for a clinician visit.
CPIC integration
- Live:
api.cpicpgx.org/v1/recommendationqueried in real time. - Disk-cached:
src/data/cpic_recommendations.json— pre-pulled CPIC recommendations for all 17 bundled drugs (built byscripts/cache_cpic.py). The proxy pre-seeds its in-memory caches at startup, so the demo works even ifapi.cpicpgx.orgis down.
Deterministic interactions (src/data/interactions.json)
- 8 phenoconversion entries (inhibitor / inducer pairs) with FDA / CPIC / DPWG citations.
- 6 drug-drug interactions (clopidogrel + omeprazole, warfarin + amiodarone, simvastatin + clarithromycin, etc.) with FDA / CPIC citations.
- No live LLM reasoning — every clinical claim is grounded in a bundled, citable source.
Cover-traffic / decoy queries (server/proxy.py)
- Every real chat turn spawns 5 decoy Anthropic calls on daemon
threads — same model, same system prompt, random
(gene, phenotype, drug)from the allowlist. Their responses are read and discarded. - The provider's API log therefore contains 6 indistinguishable requests per real user turn; they cannot identify which call was the user's real question.
- Zero added user-perceived latency (decoys fire in the background after the real reply is computed).
Bundled data
src/data/genes.json— variants, function tables, diplotype rules.src/data/drugs.json— 17 drugs × phenotypes with CPIC-derived guidance.src/data/interactions.json— phenoconversion + drug-drug pairs.src/data/cpic_recommendations.json— disk cache of CPIC API responses.sample/sample_23andme.txt— bundled demo file.sample/patients/— 5 synthetic patient files curated by our bio collaborator, with documented ground-truth seeded variants insample/patients/expected/patient_0X.json.
Privacy posture
We do NOT claim "perfect privacy." We claim architectural minimization plus provider-side anonymity:
-
Raw DNA never leaves the browser. The parser worker and the PGx engine run in-page; file bytes stay in worker scope. The Privacy Console makes this falsifiable in real time — open it, watch the "0 raw DNA bytes uploaded" counter.
-
Only de-identified labels reach the LLM. Every payload to Anthropic contains
{gene, phenotype, drug name}. No rsIDs, no genotypes, no age, sex, name, location, or file content. The proxy's allowlist + DNA-shape regex enforce this at the boundary. -
Provider-side anonymity via cover traffic. Even those minimal labels are mixed with 5 decoy queries per real chat turn. Anthropic's API log shows 6 indistinguishable requests; they cannot link any of them to a user.
-
We log nothing on the proxy. Request bodies are never written to disk; no analytics, no telemetry.
What we do NOT do today: ship a local LLM. That's a real future direction (WebLLM in the browser, or per-user BYOK keys) — see ROADMAP.md below. Honest about what's prototype vs. production.
Validation
Honest about what's external and what's internal — full audit in
tests/.
External validation
- 79 PGx engine unit tests (
tests/pgx.test.mjs): synthetic genotypes → expected phenotypes against PharmVar + CPIC reference tables. This part is externally validated against the field's authoritative sources. - 33 parser tests (
tests/parser.test.mjs): 23andMe + AncestryDNA format coverage. - Literature-grounded test, 7/7 passing (
tests/literature-grounded.test.mjs): each case anchored to a specific peer-reviewed paper or landmark RCT. Sources: TAILOR-PCI (JAMA 2020), SEARCH (NEJM 2008), EU-PACT (NEJM 2013), Colombel et al. (Gastroenterology 2000), Smith et al. (Genetics in Medicine 2019), Hicks et al. (Clin Pharmacol Ther 2017), Bishop et al. (Frontiers Pharmacology 2019). - PGxQA benchmark (
tests/pgxqa.test.mjs, Keat et al., PSB 2025): expert-review tier — 5/6 partial matches on in-scope cases, 4/4 clean refusal on out-of-scope. - Patient benchmark — 19/19 passing (
tests/patient-benchmark.test.mjs,make benchmark): synthetic patient files curated by our bio collaborator with seeded variants AND the independently-known CPIC phenotype each diplotype should produce. Tests the full pipeline: file → parser → engine → phenotype + coverage_state. Includes the deliberate "Not determined" honesty case on patient 05 where coverage is partial — proving the engine refuses to guess.
Internal-only (regression, not validation)
- 14-case agent regression suite (
tests/agent.test.mjs): questions and expected answers were written by the development team using CPIC patterns, not externally curated. Useful as a smoke test; not external validation — labeled as such in the file header.
Not done (honest gaps)
- No clinician sign-off on agent paraphrases.
- No patient outcome data, no prospective study.
- No FDA / regulatory clearance — we're a research prototype.
Architecture
4-agent-chat.html / index.html (Lindsay's chat UI)
│
▼
Load DNA → parser.worker.js → src/pgx.js → phenotypes
(in-browser; raw DNA never leaves this tab)
│
▼
Type a question
│
▼
src/explain.js → POST /api/explain {kind: "chat", phenotypes, message}
│
▼
server/proxy.py → Anthropic tool-use loop
│ +
│ 5 decoy queries fired in parallel (provider anonymity)
│
├──→ get_gene_status (in-memory)
├──→ lookup_cpic_recommendation (CPIC API or disk cache)
├──→ check_drug_interactions (interactions.json)
└──→ suggest_clinician_questions (LLM paraphrase)
│
▼
Reply with CPIC evidence chips + tool trace + decoy indicator
How to run
Requires Python 3.10+ and Node 18+.
make install # pip install proxy deps
cp server/.env.example server/.env # paste your Anthropic key inside
Two terminals:
make proxy # FastAPI on http://localhost:8001
make web # static server on http://localhost:8000/
Open http://localhost:8000/ — chat agent landing page.
Run the tests:
make test # 79 PGx engine cases
make parser-test # 33 parser cases
make lit-test # 7 literature-grounded cases (requires proxy + API key)
make benchmark # 19 patient-pipeline assertions, no API required
make pgxqa-test # PGxQA expert-review benchmark (requires proxy + API key)
Rebuild the CPIC cache:
server/.venv/bin/python3 scripts/cache_cpic.py
Roadmap
Current architecture is correct for a hackathon prototype, not a shipped product. Honest path beyond Phase 1:
- Phase 1 — today (demo). Centralized proxy with shared key, allowlist + decoys for privacy. Single-laptop install.
- Phase 2 — bring-your-own-key. User pastes their own Anthropic
key into the UI, stored in
localStorage. Allowlist and decoys still enforced by the client. Removes shared-key scaling concern. - Phase 3 — clinical content review. Pharmacist / clinician reviews the agent's paraphrases against CPIC source text for N=50+ cases.
- Phase 4 — broader sources. Add PharmGKB clinical annotations and FDA Table of Pharmacogenomic Biomarkers as additional authoritative tools the agent can query.
LLM dependency lives entirely behind a single tool boundary
(lookup_cpic_recommendation's paraphrase step), so swapping it
(BYOK, different model, eventual local fallback) is a single-file
change rather than a rewrite.
Not medical advice
DoseDNA is a research prototype. Informational only. Confirm any medication decision with a clinician or pharmacist. The agent never gives a specific dose, never tells the user to start or stop a medication, and refuses out-of-scope drugs cleanly. When a metabolizer status cannot be determined from the file, it is reported as "not determined," never as normal.
Contributing
Built at AI Hackathon 2026 (Berkeley) by:
- Alex (@alejandro-publius) — engine, proxy, validation suites, system integration
- Lindsay (@lindsayy-l) — chat UI / landing page design, CPIC data integration
- Varsha (@varsha106-pixel) — frontend prototype + UI direction
- Rachel (@rachelselbrede) — bio collaborator: synthetic patient curation, ground-truth seeding
The deterministic spine (src/pgx.js, src/data/*.json,
tests/pgx.test.mjs) is the highest-bar part of the codebase —
changes there should keep make test green.
License
TBD.
Analysis
View
Metric
- 64
- 9
- 3
- 1
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- FastAPIIn code
- HTMLIn code
- JavaScriptIn code
- PythonIn code
- Node.jsClaimed
5 of 6 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
- Claude CodeCommits
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
249 KB
Source files
16
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
alejandro-publius/dosedna
61 files · 2.4 MB · @ ebaa3a6
Structure
Interface
2 files · 3%Screens, components and styles rendered to the user.
API & routing
2 files · 3%Request entry points: routes, handlers and controllers.
Application logic
23 files · 38%Domain rules, services and shared utilities.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- HTML41%
- Python33%
- JavaScript13%
- Markdown12%
- Shell1%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
server/requirements.txt
pypi · 5- anthropic
- fastapi
- pydantic
- python-dotenv
- uvicorn[standard]
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.