Turn raw clinical data — including messy real-world inputs — into an ICH E3 / NMPA-aligned Clinical Study Report (CSR) in Word.
AutoCSR is an open-source, end-to-end pipeline: upload → router → cleansing → analysis → outline → multi-agent writing → conversational editing → DOCX / TLF / eCTD export. Every step keeps an audit trail; nothing leaves the cleansing stage without a human-readable rule yaml; every LLM call is logged; every reference is validated against the corpus.
- Heterogeneous ingest router — six typed workers (SDTM/ADaM, messy Excel, PDF forms, scanned CRFs, handwritten notes, literature) routed by mime + content heuristics + LLM tiebreaker.
- Cleansing workbench — 10 proposal types (rename, cast, unit
convert, normalize, map_to_cdisc, impute, outlier flag, PII hash,
split, merge, derive) with mandatory
hash_pii; user accepts / edits / rejects each rule; exportablecleansing_pipeline.yamlre-applicable to new batches. - Medical coding — bundled CC0 dictionaries (ICD-10 / ATC / LOINC, ~1500 codes) plus configurable paths for commercial dictionaries (MedDRA, WHODrug, SNOMED-CT).
- Clinical analysis — basics (descriptive, inferential t/Wilcoxon/chi-square/Fisher, survival KM+Cox via lifelines, safety AE × SOC × severity) + advanced (multitest Bonferroni/FDR, subgroup forest plots, sensitivity ITT/PP/LOCF/MMRM, CONSORT flow diagram, SMD baseline balance).
- Plan-first mode — outline points editable before full draft.
- Writer tool loop — autonomous calls to
sandbox_python/search_corpus/call_analyst/fetch_ref/ etc., withrespondterminator, capped at 5 turns, JSON schema constrained. - Three-phase orchestrator — background → results → discussion;
asyncio.gatherwith bounded parallelism;AnalystFuturePooldedupes identical queries across parallel writers. - Harmonizer — pairwise tone + terminology unification; rejects
LLM output that drops
Ref<…>codes or changes paragraph length beyond a threshold. - Data Ask — natural-language query → analyst writes Python →
sandbox runs → returns
StatBlockwith both markdown table and ECharts JSON.
- Conversational editor — 4 atomic patch ops (
replace_section/insert_paragraph/replace_paragraph/patch_field), automatic version snapshots, one-click rollback. - Comments + apply batch — collect inline comments, then one call applies all unresolved comments via editor LLM.
- Markers — 4 colored tags (important / todo / question / risk) with character-range anchoring.
- Multi-version diff — paragraph-level structured diff between any two SectionDraft revisions.
- Multi-user tasks — Kanban (open / in_progress / resolved / wont_fix), from-issue / from-comment promotion, per-task assignee.
- Cross-project compare — outline + draft diff across two projects for protocol-amendment impact analysis.
- Four parallel checkers (M10): structure (ICH E3 coverage),
consistency (sandbox cross-checks numbers vs StatBlock), citation
(every
Ref<…>resolves), completeness (outline required + bound stat_refs + non-empty markdown). - Three expert reviewer agents (M16): statistician (assumptions, CI/p-value reporting, subgroup interpretation), medical (dose / regimen / AE causality / drug interactions), regulatory (ICH E3 / FDA / NMPA jurisdiction-specific compliance).
- Hallucination guard — every
Ref<…>produced by writer or editor is validated against the corpus; unresolved refs flag the paragraph and surface in DOCX export.
- 21 CFR Part 11 audit trail — append-only JSONL with SHA-256
chain; pluggable
AuditBackendfor S3 Object Lock / IPFS upgrade; monthly file rotation with gzip. - ed25519 e-signatures — per-project keypair (HSM-ready interface); demo signing for unblind / database-lock / final approval.
- Sequential sign chain —
statistician → medical → regulatory → approver; out-of-order advance returns 403. - PII pre-check — regex + optional LLM second-pass scans every LLM payload (ID / phone / email / MRN / names / address); four modes: strict / auto_redact / warn / off.
- LLM call logging — full prompt / response / tokens / latency per call, hash-only mode available.
- AI provenance markers — every paragraph tracks
source: ai|human|hybrid; optional grey shading in DOCX export. - Blinding mode — arm names masked in LLM context until unblind-with-signature.
- Database lock — mutations 403 unless
X-Addendum: true.
- DOCX — programmatic ICH E3 template, cover with cleansing
pipeline reference, auto TOC field, real Word tables (not images),
References + Appendix A (cleansing) + Appendix B (analyses);
4 presets (standard / pharma / academic / regulatory) + user
.docxtemplate upload with placeholder injection; configurable fonts / sizes / margins / header / footer / watermark. - TLF zip — per-StatBlock RTF + CSV + minimal define.xml.
- eCTD M5.3.5 package —
m1/cover+m5/53-clin-stud-rep/...directory with CSR docx, TLF zip, define.xml, signed sign_chain manifest. - CSR reverse import — parse existing
.docxCSR back into outline + drafts via Heading-style detection.
- Bilingual UI (zh / en) — vue-i18n with ja stub for future.
- Multi-language prompts — writer / harmonizer / proposer / analyst / reviewer prompt libraries per project language.
- Dark mode — design tokens + Element Plus dark + md-editor-v3 dark + ECharts dark theme.
- Responsive — ≥ 1280 three-pane; < 1280 drawer + bottom sheet; < 1024 card stack (mobile not supported below 768).
- Onboarding tour — first-visit walkthrough + inline tooltips for advanced features.
- Keyboard shortcuts — j/k tree navigation, ⌘+S save, ⌘+K search, Esc close, Tab pane cycle.
- Accessibility — aria-labels, focus indicators, role semantics, WCAG-AA contrast.
- OpenAPI 3.0 —
/openapi.json, Swagger UI/docs, ReDoc/redoc; routes tagged into 14 logical groups. - SDK generation —
scripts/generate_sdk.pyproduces TypeScript (sdk/ts/) and Python (sdk/py/) SDKs from the live OpenAPI spec. - Prometheus
/metrics— agent runs, LLM tokens, queue depth, active projects, request latency histograms. - Error sink hooks —
register_error_sink(callable)for Sentry / Webhook / custom error reporting; no SaaS dependency by default. - Checkpoint resume — long tasks (report generation, cleansing apply) can resume from disk after SIGTERM.
- Pluggable LLM backend — DeepSeek / OpenAI / Ark / Anthropic-
compatible endpoints; mock mode (
CSR_*_MOCK=1) for all agents.
upload export
│ ▲
▼ │
┌──────────┐ ┌──────────┐ ┌─────────┐ ┌─────────┐ ┌──┴──┐
│ Router │──▶ │ Workers │──▶│ Cleanse │──▶│ Analyze │─▶│Write│
└──────────┘ └──────────┘ └─────────┘ └─────────┘ └──┬──┘
│ │
audit + yaml ◀────┘ │
▼
┌───────────┐
│ Chat │
│ Editor │
└─────┬─────┘
▼
┌───────────┐
│ DOCX │
└───────────┘
Every node persists to data/projects/<pid>/ so any failure is
recoverable and any output is auditable.
Requires Python 3.11+ and Node 18+.
git clone https://github.com/<you>/AutoCSR.git
cd AutoCSR
# 1. backend
cd backend
python -m venv .venv && source .venv/Scripts/activate # Windows: .venv\Scripts\activate
pip install -e .
cp app/config/settings.example.yaml app/config/settings.yaml
# Edit settings.yaml or `export LLM_API_KEY=sk-...`
python -m uvicorn app.server.main:app --port 8766 --reload
# 2. frontend (new shell)
cd ../frontend
npm install
npm run devOpen http://127.0.0.1:5174, create a project, follow the top nav:
上传 → 清洗 → 分析 → 大纲 → 撰写 → 导出.
backend/app/config/settings.yaml (gitignored — copy from
settings.example.yaml):
| Section | Key | Notes |
|---|---|---|
llm |
base_url / api_key / model |
Defaults to DeepSeek; OpenAI / Ark / Anthropic-compatible endpoints work as drop-ins. Override api_key with LLM_API_KEY env var to keep it out of disk. |
server |
host / port / data_dir |
Default 127.0.0.1:8766. data_dir is relative to the repo root. |
pipeline |
pii_strip |
Mandatory PII hashing on every cleansing run. Default true and cannot be silently skipped. |
pipeline |
max_parallel_writers |
Caps writer-agent concurrency (default 4). |
pipeline |
max_parallel_ingest_workers |
Caps router worker concurrency (default 4). |
pipeline |
llm_data_redaction |
strict / mild / off. Strict (default) sends only column profiles and ≤5 sample rows to the LLM during cleansing proposals. |
Environment variables LLM_API_KEY, LLM_BASE_URL, LLM_MODEL
always override settings.yaml.
Reproduce the full demo against synthetic ADaM data — no real patients, no LLM key required (mock mode):
# Each script is self-contained: spins up uvicorn on a private port,
# runs one milestone's checks, tears down.
python scripts/m2_e2e_test.py # ingest + cleansing + corpus
python scripts/m3_e2e_test.py # analysis + outline
python scripts/m4_e2e_test.py # multi-agent writers
python scripts/m5_e2e_test.py # chat editor + DOCX exportm5_e2e_test.py prints the produced docx path on success; open it in
Word to inspect cover, TOC (press F9 to refresh), chapters, and
appendices.
To exercise a real DeepSeek call instead of the deterministic mock:
export LLM_API_KEY=sk-...
REAL_LLM=1 python scripts/m4_e2e_test.py # 5-leaf real writer passIssues and pull requests are welcome. See CONTRIBUTING.md for the issue templates, code style, and the e2e check you must run before submitting.
Released under the MIT License — see LICENSE.
This project relies on excellent open-source work: lifelines (survival), python-docx (Word output), python-markdown (md → html), rapidfuzz (corpus search), FastAPI, Vue.js, Element Plus, md-editor-v3.
Built with AI pair programming: Claude Opus 4.7 (architecture + implementation) + OpenAI Codex (testing iteration + security hardening). All code reviewed and integrated by the project maintainer.
AutoCSR is designed so patient identifiers never leave your machine:
- The cleansing pipeline applies
hash_piiby default and refuses to proceed without it; PII columns are detected from semantic heuristics and the user must explicitly opt out. - When the cleansing LLM proposes rules, it sees only column names,
dtypes, missing-rate, top frequencies, and at most five sample rows
with PII columns masked.
pipeline.llm_data_redaction=strictis the default. - Writer / editor LLM calls operate on
StatBlockaggregates and literature snippets, never on row-level patient data.
Audit the redaction yourself: every LLM payload is logged at
DEBUG level in backend/app/llm/ark_client.py.
The first production-ready release. 18 milestones, 14 commits since
init, ~50K lines net added across 302 tracked files. 17 e2e scripts
(scripts/m2_e2e_test.py … m18_e2e_test.py) and 64 unit tests all
passing.
Highlights
- Full ICH E3 pipeline from raw clinical data to signed DOCX + TLF + eCTD M5.3.5.
- Six typed ingest workers, ten cleansing proposal types with mandatory PII hashing, four basic + five advanced statistical modules, multi-agent writer with autonomous tool loop.
- Eight reviewer perspectives (structure / consistency / citation / completeness / statistician / medical / regulatory / hallucination).
- 21 CFR Part 11 audit trail, ed25519 e-signatures, sequential sign chain, blinding mode, database lock, AI provenance markers.
- Bilingual UI (zh/en), dark mode, responsive ≥ 1024px, onboarding tour, keyboard navigation, full a11y pass.
- OpenAPI 3.0 + Swagger UI + auto-generated TypeScript / Python
SDKs, Prometheus
/metrics, pluggable error sinks, checkpoint resume for long tasks.
See CONTRIBUTING.md for the v2.x roadmap (PDF/HTML/PPT export, real OCR vision, treatment-area templates, Docker compose, multi-study knowledge base, regulatory inquiry tracker, and more).
The production deployment + therapeutic depth + multi-tenant release.
22 milestones total (M1-M22), 19 commits since init, ~70K lines net
across 435 tracked files. 22 e2e scripts (m2_e2e_test.py …
m22_e2e_test.py) and 78 unit tests all passing. New docs/ folder
with 6 guides.
Major increments since v1.0.0
- Infrastructure & deployment —
docker-compose.yml(backend + frontend + redis + optional prometheus profile), multi-stageDockerfiles, nginx SPA + API/WS reverse proxy; full arq + Redis task queue (inmemory mode preserved); rate-limit middleware (token-bucket); project zip backup + restore; GitHub Actions CI with pytest/lint/build/e2e-mock/docker-config jobs. - Multi-format export — PDF (reportlab), HTML (jinja2 + ECharts interactive), PowerPoint (python-pptx 16:9), Markdown bundle (zip).
- Therapeutic area templates — oncology (RECIST 1.1 / iRECIST, PFS/OS/DOR), rare disease (Bayesian + external control + propensity score), vaccine (GMT/SCR + VE), pediatric (ICH E11(R1) age strata + PopPK + growth z-score), cardiovascular (MACE composite + CEC adjudication + LVEF). 5 sample projects with synthetic ADaM data for one-click hands-on.
- 5 new AI agents — literature search (PubMed E-utilities, Wanfang stub), medical English polishing (3 modes with diff), chart selector (StatBlock → ECharts type), reference formatter (Vancouver / GB/T 7714 / AMA), LaTeX → DOCX formula render.
- Multi-tenant accounts —
User+Tenant+ProjectMembermodels, bcrypt password hashing, JWT (python-jose) with access + refresh tokens, dev_modeX-User-Idfallback for backward compatibility. Four-role ACL: owner / editor / reviewer / viewer. Login + Register + TenantSettings frontend views. - Reverse import suite — Protocol PDF → 8 trial-design fields, SAP docx → outline stat_hints injection, define.xml → ItemDef notes.
- Advanced visualizations — KM with risk table (dual-panel + median + log-rank p), Bland-Altman with LoA, heatmap (long → pivot → imshow + ECharts), PK profile 3D (matplotlib 3D + ECharts-GL with 2D fallback), composable dashboard (grid layout persistence).
- Mobile < 768 full support —
useResponsivecomposable, panes stack into el-tabs, simplified ChapterReader toolbar, native touch gestures (swipe chapters + long-press context menu); skip-to-content link, ARIA semantics, contrast bumps targeting Lighthouse a11y ≥ 95. - Onboarding upgrade — ProjectList Hero 5-domain card grid with icons; OnboardingTour gains "5 demo projects" step; HelpMenu gains video tutorial modal + 10-question FAQ.
- Documentation —
docs/quickstart.md(5-min walkthrough),architecture.md(data flow + module map),compliance.md(21 CFR Part 11 / NMPA reviewer checklist),api.md(OpenAPI + curl/Python/TS/WS examples),deployment.md(Docker Compose + Nginx TLS + backup),contributing.md(recipes for adding templates / agents / export formats / locales).
See CONTRIBUTING.md for the remaining v3.x backlog (SSO/OIDC, real HSM signing, true OCR vision, recording replay, multi-study knowledge base, regulatory inquiry tracking).
A maintenance + polish release driven by AI pair iteration.
Codex-contributed
- Route-level tenant + ACL guard (
server/middlewares/project_access.py) - Cross-project workbench search (
server/routes/workbench.py) - Normalized WebSocket task event DTOs (
server/task_events.py) - Upload path traversal guard + frontend input sanitization
- Tightened sandbox AST denylist
- Playwright e2e infrastructure (
frontend/e2e/) - 10 new backend unit tests + 16 prompt files tuned
Claude UI redesign
- Emoji-free interface (UI emoji across 5 files replaced with
lucide-vue-nexticons or numeric ordinals) - Warm orange primary (
#BA5535light /#DA7756dark) replacing the cyan-blue (#0891b2); aligned with Claude product aesthetic - Inter web font + 1.6 line-height for readable typography
- Flat shadows (
0 1px 2px rgba(0,0,0,0.04)) replacing heavy elevation - True-black dark mode background (
#0a0a0afrom#081421) - LoginView: solid white background + bordered card (was gradient + shadow)
- Element Plus theme fully overridden via CSS variables
Fixes
ProjectDTOfrontend types synced with backend M21 multi-tenant schema (tenant_id,created_by)literature_searchunknown source now raisesAgentError(was bareValueError); route maps non-retryable AgentError to 400- CI: added
frontend-e2ePlaywright job - README e2e badge: 17 -> 22 passing
docs/api.mdcurl/python/typescript examples for new endpoints
