# karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant architecture

> Architecture diagram of the GitHub repository karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-14). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant
- Repository: https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant

## Overview

#### Purpose and Entry Points
This repository is a standalone Streamlit clinical-literature retrieval demo. It compares general and medical-tuned embedding models during a conversation, retrieves evidence from Qdrant, synthesizes answers with Anthropic Claude, and verifies citations/numeric claims afterward.

Primary deployment entry point: `app.py`. Earlier iteration entry points remain in `V1/app.py` and `V2/app.py`.

#### Application Orchestration
`app.py` owns the Streamlit UI, session/conversation state, sidebar model and provider selectors, secrets validation, and the query lifecycle. It presents source availability transparently: literature retrieval is live; claims, FDA labels, and evidence-document sources are intentionally unconnected.

Relevant paths:
- `app.py`
- `requirements.txt`

#### Input Safety / HIPAA Boundary
Before retrieval, user input passes a two-layer PHI screen. Regex detection blocks known structured identifiers; if it passes, Claude Haiku performs semantic PHI detection for free-text identifiers. API failures are fail-closed, preventing the query from reaching retrieval or synthesis.

This is a privacy boundary between public user input and external Qdrant/Anthropic calls.

Relevant paths:
- `app.py`

#### Embedding and Retrieval Stage
The app selects between `BAAI/bge-small-en-v1.5` and `abhinand/MedEmbed-small-v0.1`; Streamlit resource caching keeps loaded models warm across model switches. Query embeddings are sent to Qdrant, whose returned chunks contain document stem, section title, and text.

Retrieval over-fetches candidates and applies per-document caps (`MAX_CHUNKS_PER_STEM=2`) to avoid a single source dominating the evidence set. The selected chunks are formatted as guideline-style clinical evidence because bibliographic metadata is unavailable.

Relevant paths:
- `app.py`
- `formatter.py`

#### Prompting and Answer Synthesis
Retrieved context and user-selected provider role/type framing are assembled into the clinical system prompt. Anthropic Claude Sonnet produces the final answer using grounded evidence, low-temperature synthesis, and streaming output. Prompt definitions are isolated from UI/retrieval mechanics, allowing production-aligned clinical behavior to evolve independently.

Relevant paths:
- `prompts.py`
- `app.py`

#### Post-Synthesis Verification
After streaming completes, answer text is checked against retrieved data. Citation verification flags author/year-style citations that cannot be supported by the corpus; numeric verification compares stated percentages, ratios, and lab-like values against retrieved chunk text. Results are surfaced in the answer Details area rather than silently modifying the response.

Relevant paths:
- `citation_verify.py`
- `numeric_verify.py`
- `app.py`

#### Runtimes and External Services
The runtime is Python with Streamlit, deployed locally or on Streamlit Community Cloud. Required secrets configure:
- Qdrant Cloud for vector search (`QDRANT_URL`, `QDRANT_API_KEY`)
- Anthropic APIs for Claude Sonnet synthesis and Claude Haiku PHI review (`ANTHROPIC_API_KEY`)
- Hugging Face-compatible embedding model downloads/caching at runtime

Dependency definitions are in `requirements.txt`; prior version-specific dependency sets are in `V1/requirements.txt` and `V2/requirements.txt`.

#### Version Layout
The repository root is the current integrated implementation, including verification modules. `V1/` and `V2/` preserve earlier standalone Streamlit variants; `V2/` includes its own prompt module and represents the earlier production-prompt/retrieval-alignment stage.

Relevant paths:
- `V1/app.py`
- `V2/app.py`
- `V2/prompts.py`

Main entry points: [`app.py`](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py) (Diversified evidence set), [`citation_verify.py`](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/citation_verify.py) (Citation verification), [`numeric_verify.py`](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/numeric_verify.py) (Numeric verification), [`formatter.py`](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/formatter.py) (Evidence formatter)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_current["Current application"]
  node_streamlit_app["Streamlit orchestration<br/>Python app<br/>[app.py]"]
  node_dependencies["Runtime dependencies<br/>Python requirements<br/>[requirements.txt]"]
end

subgraph group_safety["Privacy boundary"]
  node_phi_regex["Structured PHI screen<br/>input guard<br/>[app.py]"]
  node_phi_haiku["Semantic PHI review<br/>Claude Haiku check<br/>[app.py]"]
end

subgraph group_retrieval["Retrieval pipeline"]
  node_model_selector["Embedding model selector<br/>model routing<br/>[app.py]"]
  node_embedding_cache["Cached embedding models<br/>Streamlit resource<br/>[app.py]"]
  node_qdrant_retrieval["Candidate retrieval<br/>vector search<br/>[app.py]"]
  node_evidence_selection["Diversified evidence set<br/>reranker/filter<br/>[app.py]"]
  node_evidence_formatter["Evidence formatter<br/>context formatter<br/>[formatter.py]"]
end

subgraph group_answer["Answer and verification"]
  node_prompt_definitions["Clinical prompt definitions<br/>prompt module<br/>[prompts.py]"]
  node_prompt_assembly["Grounded prompt assembly<br/>prompt builder<br/>[app.py]"]
  node_claude_synthesis["Streaming answer synthesis<br/>Claude Sonnet client<br/>[app.py]"]
  node_citation_verifier["Citation verification<br/>post-synthesis check<br/>[citation_verify.py]"]
  node_numeric_verifier["Numeric verification<br/>post-synthesis check<br/>[numeric_verify.py]"]
end

subgraph group_external["External services"]
  node_qdrant_cloud[("Qdrant Cloud<br/>external vector database")]
  node_anthropic_api{{"Anthropic API<br/>external AI service"}}
  node_huggingface_models{{"Embedding model downloads<br/>model hosting"}}
end

subgraph group_history["Earlier variants"]
  node_v1_variant["V1 standalone app<br/>legacy Streamlit variant<br/>[app.py]"]
  node_v2_variant["V2 production-aligned variant<br/>legacy Streamlit variant<br/>[app.py]"]
  node_v2_prompts["V2 prompts<br/>legacy prompt module<br/>[prompts.py]"]
end

node_dependencies -->|"defines runtime"| node_streamlit_app
node_streamlit_app -->|"screens query"| node_phi_regex
node_phi_regex -->|"if regex passes"| node_phi_haiku
node_phi_haiku -->|"approved query"| node_model_selector
node_phi_haiku -->|"PHI review"| node_anthropic_api
node_model_selector -->|"loads selected model"| node_embedding_cache
node_embedding_cache -->|"downloads models"| node_huggingface_models
node_embedding_cache -->|"query embedding"| node_qdrant_retrieval
node_qdrant_retrieval -->|"vector search"| node_qdrant_cloud
node_qdrant_retrieval -->|"retrieved chunks"| node_evidence_selection
node_evidence_selection -->|"capped chunks"| node_evidence_formatter
node_evidence_formatter -->|"clinical evidence"| node_prompt_assembly
node_prompt_definitions -->|"system prompt"| node_prompt_assembly
node_prompt_assembly -->|"grounded request"| node_claude_synthesis
node_claude_synthesis -->|"Sonnet streaming"| node_anthropic_api
node_claude_synthesis -->|"completed answer"| node_citation_verifier
node_claude_synthesis -->|"completed answer"| node_numeric_verifier
node_evidence_selection -->|"evidence corpus"| node_citation_verifier
node_evidence_selection -->|"evidence corpus"| node_numeric_verifier
node_citation_verifier -->|"Details findings"| node_streamlit_app
node_numeric_verifier -->|"Details findings"| node_streamlit_app
node_v2_prompts -->|"used by"| node_v2_variant

click node_streamlit_app "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_dependencies "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/requirements.txt"
click node_phi_regex "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_phi_haiku "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_model_selector "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_embedding_cache "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_qdrant_retrieval "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_evidence_selection "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_evidence_formatter "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/formatter.py"
click node_prompt_definitions "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/prompts.py"
click node_prompt_assembly "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_claude_synthesis "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py"
click node_citation_verifier "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/citation_verify.py"
click node_numeric_verifier "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/numeric_verify.py"
click node_v1_variant "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/V1/app.py"
click node_v2_variant "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/V2/app.py"
click node_v2_prompts "https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/V2/prompts.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_streamlit_app,node_dependencies toneBlue
class node_phi_regex,node_phi_haiku toneAmber
class node_model_selector,node_embedding_cache,node_qdrant_retrieval,node_evidence_selection,node_evidence_formatter toneMint
class node_prompt_definitions,node_prompt_assembly,node_claude_synthesis,node_citation_verifier,node_numeric_verifier toneRose
class node_qdrant_cloud,node_anthropic_api,node_huggingface_models toneIndigo
class node_v1_variant,node_v2_variant,node_v2_prompts toneTeal
```

## Components

### Current application

- [Streamlit orchestration](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): Python app · Owns UI, session state, selectors, secrets, and query lifecycle. · `app.py`
- [Runtime dependencies](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/requirements.txt): Python requirements · `requirements.txt`

### Privacy boundary

- [Structured PHI screen](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): input guard · Blocks known structured identifiers before external calls. · `app.py`
- [Semantic PHI review](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): Claude Haiku check · Fails closed when review fails or identifies free-text PHI. · `app.py`

### Retrieval pipeline

- [Embedding model selector](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): model routing · Selects BGE Small or MedEmbed Small. · `app.py`
- [Cached embedding models](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): Streamlit resource · Keeps downloaded embedding models warm across switches. · `app.py`
- [Candidate retrieval](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): vector search · Queries Qdrant for evidence chunks. · `app.py`
- [Diversified evidence set](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): reranker/filter · Over-fetches then caps chunks per document stem. · `app.py`
- [Evidence formatter](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/formatter.py): context formatter · Formats chunks as guideline-style evidence without bibliographic metadata. · `formatter.py`

### Answer and verification

- [Clinical prompt definitions](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/prompts.py): prompt module · `prompts.py`
- [Grounded prompt assembly](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): prompt builder · Combines evidence with selected provider role and type framing. · `app.py`
- [Streaming answer synthesis](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/app.py): Claude Sonnet client · Generates low-temperature answers grounded in retrieved evidence. · `app.py`
- [Citation verification](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/citation_verify.py): post-synthesis check · Flags author/year citations unsupported by the retrieved corpus. · `citation_verify.py`
- [Numeric verification](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/numeric_verify.py): post-synthesis check · Compares stated numbers with retrieved chunk text. · `numeric_verify.py`

### External services

- **Qdrant Cloud**: external vector database · Configured by QDRANT_URL and QDRANT_API_KEY.
- **Anthropic API**: external AI service · Provides Haiku review and Sonnet synthesis.
- **Embedding model downloads**: model hosting · Hugging Face-compatible runtime model source.

### Earlier variants

- [V1 standalone app](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/V1/app.py): legacy Streamlit variant · `V1/app.py`
- [V2 production-aligned variant](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/V2/app.py): legacy Streamlit variant · Earlier prompt and retrieval-alignment stage. · `V2/app.py`
- [V2 prompts](https://github.com/karkavelrajaj-coder/pharmaforceiq-clinical-ai-assistant/blob/main/V2/prompts.py): legacy prompt module · `V2/prompts.py`

## Connections

- Runtime dependencies → Streamlit orchestration: defines runtime
- Streamlit orchestration → Structured PHI screen: screens query
- Structured PHI screen → Semantic PHI review: if regex passes
- Semantic PHI review → Embedding model selector: approved query
- Semantic PHI review → Anthropic API: PHI review
- Embedding model selector → Cached embedding models: loads selected model
- Cached embedding models → Embedding model downloads: downloads models
- Cached embedding models → Candidate retrieval: query embedding
- Candidate retrieval → Qdrant Cloud: vector search
- Candidate retrieval → Diversified evidence set: retrieved chunks
- Diversified evidence set → Evidence formatter: capped chunks
- Evidence formatter → Grounded prompt assembly: clinical evidence
- Clinical prompt definitions → Grounded prompt assembly: system prompt
- Grounded prompt assembly → Streaming answer synthesis: grounded request
- Streaming answer synthesis → Anthropic API: Sonnet streaming
- Streaming answer synthesis → Citation verification: completed answer
- Streaming answer synthesis → Numeric verification: completed answer
- Diversified evidence set → Citation verification: evidence corpus
- Diversified evidence set → Numeric verification: evidence corpus
- Citation verification → Streamlit orchestration: Details findings
- Numeric verification → Streamlit orchestration: Details findings
- V2 prompts → V2 production-aligned variant: used by
