Mockapapella/clinicaltrials-q2viz
ClinicalTrials.gov Query-to-Visualization Backend
FastAPI service that turns clinical-trials questions into frontend-ready visualization JSON backed by ClinicalTrials.gov API v2 records.
Non-visual questions return a normal text answer from the same endpoint.
Install
uv syncEnter an OpenAI API key in the browser UI, or send it with x-openai-api-key.
Run
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000Open http://localhost:8000 to use the browser UI.
Open http://localhost:8000/docs/ for the generated FastAPI API documentation. That OpenAPI page is the documented API surface for requests and schemas.
Docker
docker build -t clinicaltrials-q2viz .
docker run --rm -p 8000:8000 clinicaltrials-q2vizThe same Dockerfile powers the Hugging Face Space deployment. Hugging Face reads the YAML block at the top of this README, sees sdk: docker, builds the root Dockerfile, runs its CMD, and exposes app_port: 8000.
Query Example
curl -s http://localhost:8000/v1/visualizations \
-H 'content-type: application/json' \
-H "x-openai-api-key: $OPENAI_API_KEY" \
-d '{"query":"Melanoma trials by phase"}' | jqRequest fields:
query: natural-language clinical-trials question.
The planner fetches 500 ClinicalTrials.gov studies by default, or the study count requested in the query. Chart data is not capped separately.
Design
The runtime path is intentionally small:
request -> LLM plan or answer -> ClinicalTrials.gov studies -> evidence values -> visualization JSONFor visualizations, the LLM only chooses the executable QuerySpec: filters, chart mode, dimensions, cohorts, and requested fetch count. It does not create counts, chart rows, citations, or trial facts. ClinicalTrials.gov API v2 is the only data source for visualized values.
Important boundaries:
app/schemas.py: request, planning, response, and error models.app/planner.py: OpenAI structured-output planning.app/ctgov.py: ClinicalTrials.gov API v2 requests and pagination.app/fields.py: CT.gov field extraction and citation paths.app/engine.py: aggregation, relationships, points, chart encoding, and evidence rollup.app/static/index.html: optional browser demo.
Tradeoffs:
- The service uses generated FastAPI OpenAPI instead of a separate hand-written schema.
- It fetches live ClinicalTrials.gov data per request, with the official OpenAPI schema cached locally for planner context.
- It stays stateless: no database, queue, or result cache.
- It favors one flexible
QuerySpecover separate handlers for every question family.
Supported Questions
Trials for pembrolizumab per year since 2015Melanoma trials by phaseCompare pembrolizumab vs nivolumab by phaseCountries with most recruiting diabetes trialsSponsors and drugs for breast cancer trialsEnrollment distribution for Phase 3 asthma trialsEnrollment vs start year by phase
Response
Visualization responses contain:
spec: executable interpretation of the request.visualization: chart type, encoding, and data rows.meta: request ID, study count, chart data point count, truncation flag, and timing.warnings: empty-result or truncation notes.
Each non-empty data row includes:
- contributing
nct_ids total_records- capped source citations with CT.gov field paths
omitted_citationswhen the detailed citation cap is exceeded
In the browser UI, each chart table row has a Sources action that opens the NCT records counted for that row.
Answer responses contain kind: "answer", question, answer, and timing metadata.
Example Runs
example_runs.json contains five actual JSON outputs generated by the app pipeline against live ClinicalTrials.gov API v2 data:
melanoma trials by phasemelanoma trials over timediabetes trials by countrysponsors and interventions network for breast cancer trialsenrollment vs start year for asthma trials by phase
Limits
This service summarizes trial metadata. It does not provide medical advice, treatment efficacy claims, safety claims, or outcome-results analysis.
Current limitations:
- Successful planning requires an OpenAI API key supplied by the UI or
x-openai-api-key. - ClinicalTrials.gov search semantics can be broad; large requests may return partial data with a truncation warning.
- Scatter plots use one point per study when both numeric axes are available.
- Network graphs can become dense for broad queries.
Validation
Validation is layered:
- FastAPI and Pydantic validate requests before planning.
- OpenAI responses must parse as
PlanDecisionand validatedQuerySpec. QuerySpecmode invariants prevent mixed aggregate, relationship, and point shapes.- Every requested dimension must exist in the field registry.
- Every non-empty visual datum must carry NCT IDs and source citations.
- Responses are validated as
VisualizationResponseorAnswerResponsebefore returning.
Manual verification covered generated OpenAPI, request validation, invalid-key behavior, live CT.gov fetch/render paths for all chart families, and Chrome/Firefox rendering of every frontend chart type.
AI Tool Usage
AI plans visualization requests and answers non-visual questions. Application code retrieves ClinicalTrials.gov records, computes values, groups rows, and creates citations. The implementation and verification were developed with AI coding assistance, then checked through live API calls and visible-browser UI runs.
