# AI Providers This document covers the AI provider system, model management, prompt configuration, and usage logging for the Pediatric AI Scribe application. --- ## Provider Selection The active AI provider is determined in one of two ways: 1. **Explicit**: Set the `AI_PROVIDER` environment variable to one of the supported provider names. 2. **Auto-detect**: If `AI_PROVIDER` is not set, the system checks for provider-specific credentials in the environment and selects the first match using this priority order: `bedrock` > `azure` > `vertex` > `litellm` > `openrouter` All providers expose a unified `callAI()` interface defined in `src/utils/ai.js`. Calling code does not need to know which backend is active. --- ## Provider Details ### 1. AWS Bedrock (HIPAA-eligible with BAA) - **SDK**: `@aws-sdk/client-bedrock-runtime` - Uses **inference profiles** for newer models, enabling cross-region routing. - **Available model families**: vendor model (Anthropic), Amazon Nova, Llama (Meta), Mistral, DeepSeek, Cohere. - **Default temperature**: 0.3 ### 2. Azure OpenAI (HIPAA-eligible with BAA) - **SDK**: OpenAI SDK configured to point at an Azure endpoint. - Requires a **deployment name** that maps to the desired model. - **Available model families**: GPT-4o family, GPT-4.1 family. ### 3. Google Vertex AI (HIPAA-eligible with BAA) - **SDK**: `@google-cloud/vertexai` - In addition to text generation, Vertex AI handles: - **Speech-to-Text (STT)**: via Gemini inline audio capabilities. - **Text-to-Speech (TTS)**: via Vertex AI TTS endpoint. - **Available model families**: Gemini 2.5/2.0, vendor model on Vertex (Anthropic models hosted on Google Cloud), Llama. ### 4. LiteLLM Proxy (self-hosted) - **SDK**: OpenAI SDK pointed at the `LITELLM_API_BASE` URL. - Acts as a proxy that routes requests to any backend configured within LiteLLM. - **Model discovery**: queries `/v1/models` on the LiteLLM instance to populate the available model list. - Also supports **TTS and STT** passthrough. - Model names are used **as-configured in LiteLLM** -- the application does not auto-prefix or transform them. ### 5. OpenRouter (NOT HIPAA-compliant) - **SDK**: OpenAI SDK pointed at `https://openrouter.ai`. - **Cost discovery**: queries the OpenRouter API to retrieve per-model pricing. - Offers the **cheapest option** and the **widest model selection** across many providers. - Not suitable for environments that require HIPAA compliance. --- ## Model Management ### Model Definitions Models are defined in `src/utils/models.js` and organized into four categories: | Category | Description | |-----------|------------------------------------------------| | `free` | No-cost models (typically smaller or rate-limited) | | `fast` | Low-latency models optimized for speed | | `smart` | Balanced models with strong reasoning ability | | `premium` | Top-tier models with the highest capability | ### Admin Controls Administrators manage models from **Admin Panel > Models**: - **Enable/Disable** -- toggle visibility of any model for users (`PUT /api/admin/config/models/toggle`). Disabled models are stored in the `models.disabled` setting as a JSON array of model IDs. - **Set Default** -- choose which model is pre-selected for new users (`PUT /api/admin/config/models/default`). Stored in `models.default` setting. - **Add Custom Models** -- manually add any model not in the built-in list (`POST /api/admin/config/models/custom`). Each custom model has: - `id` -- the model identifier as the provider expects it (e.g., `openai-gpt-4.1-mini` for LiteLLM, `anthropic.agent-config-3-haiku` for Bedrock) - `name` -- display name shown to users - `cost` -- cost string shown in the UI (e.g., `~$0.002`, `FREE`) - `category` -- one of `free`, `fast`, `smart`, `premium` (determines grouping in dropdown) - **Delete Custom Models** -- remove a manually added model (`DELETE /api/admin/config/models/custom/:modelId`) - **Clear All** -- remove all custom models and reset the disabled list (`POST /api/admin/config/models/clear`) Custom models are stored in the `models.custom` setting as a JSON array in the `app_settings` table. ### Model Discovery The **Discover** button (`GET /api/admin/config/models/discover`) queries the active provider's API: - **LiteLLM**: calls `/v1/models` on the LiteLLM proxy - **OpenRouter**: calls `https://openrouter.ai/api/v1/models` (includes pricing data) - **Bedrock**: uses `ListFoundationModelsCommand` Discovered models can be added individually via `POST /api/admin/config/models/add-discovered`, which merges them into the custom models list. For **LiteLLM** specifically, since models are manually configured in the LiteLLM proxy, the model IDs returned by discovery are the exact names to use -- no provider prefix is added. ### Frontend Display The model selector dropdown (present on every tab) groups models by category: - Free -- no-cost models - Fast & Cheap -- low-latency, low-cost - Smart -- balanced capability - Premium -- highest quality Each model shows its display name and cost string. The dropdown is populated from `GET /api/models` which merges built-in models, custom models, and respects the enabled/disabled list. --- ## AI Prompts ### Storage and Override - All default prompts are defined in `src/utils/prompts.js`. - Prompts can be **overridden via the database** using the `app_settings` table with keys following the pattern `prompt.{name}`. - Administrators can view and edit all prompts directly from the Admin Panel. ### Physician Memories When a physician saves corrections or preferences (referred to as "memories"), these are injected into the prompt as **low-priority style hints**. This allows the AI to adapt its output to the physician's preferred documentation style without overriding the core clinical prompt. --- ## Logging Every AI call is recorded in the `api_log` database table with the following fields: | Field | Description | |------------|-----------------------------------------------------| | `model` | The model identifier used for the request | | `tokens` | Input and output token counts | | `cost` | Estimated cost of the call | | `duration` | Wall-clock time for the request in milliseconds | Cost estimates are calculated from **hardcoded per-model rates** defined in the codebase. For OpenRouter, rates may also be fetched from the OpenRouter pricing API.