{"id":23947383,"url":"https://github.com/singhdivyank/voice-assistant","last_synced_at":"2026-06-20T14:32:42.291Z","repository":{"id":216035691,"uuid":"740304627","full_name":"singhdivyank/voice-assistant","owner":"singhdivyank","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-03T02:11:39.000Z","size":349,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-03T04:13:47.786Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/singhdivyank.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-01-08T04:19:43.000Z","updated_at":"2026-05-03T02:09:47.000Z","dependencies_parsed_at":"2024-01-08T05:46:53.136Z","dependency_job_id":"86daa6f0-6bc2-4178-a969-aa0eaad9d25e","html_url":"https://github.com/singhdivyank/voice-assistant","commit_stats":null,"previous_names":["singhdivyank/voice-assistant"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/singhdivyank/voice-assistant","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singhdivyank%2Fvoice-assistant","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singhdivyank%2Fvoice-assistant/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singhdivyank%2Fvoice-assistant/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singhdivyank%2Fvoice-assistant/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/singhdivyank","download_url":"https://codeload.github.com/singhdivyank/voice-assistant/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singhdivyank%2Fvoice-assistant/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34573729,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gemini-pro","generative-ai","langchain-python"],"created_at":"2025-01-06T09:17:40.725Z","updated_at":"2026-06-20T14:32:42.283Z","avatar_url":"https://github.com/singhdivyank.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DocJarvis- AI Medical Assistant\n\n\u003e **Medical Disclaimer:** DocJarvis is an AI-assisted tool for **educational (informational) purposes only**. It does not constitute medical advice, diagnosis, or treatment. Always consult qualified healthcare professional.\n\nDocJarvis is a multilingual, voice-first medical consultation assistant built on **CrewAI mulit-agent architecture**. It takes a patient through symptom collection, AI-driven diagnosis, medical recommendations, and prescription generation- with a **Human-In-The-Loop** (HITL) doctor review step implemented via GMail MCP (Model Context Protocol) before any prescription is finalised.\n\n## Table of Contents\n\n- [Architecture Overview](#architecture-overview)\n- [Multi-Agent System](#multi-agent-system)\n- [Tech Stack](#tech-stack)\n- [Project Structure](#project-structure)\n- [API Reference](#api-reference)\n- [Getting Started](#getting-started)\n  - [Prerequisites](#prerequisites)\n  - [Environment Variables](#environment-variables)\n  - [Local Development](#local-development)\n  - [Docker Compose](#docker-compose)\n- [Workflow: End-to-End Flow](#workflow-end-to-end-flow)\n- [MCP Integration](#mcp-integration)\n- [Monitoring \u0026 Observability](#monitoring--observability)\n- [CI/CD](#cicd)\n- [Configuration Reference](#configuration-reference)\n- [Deployment](#deployment-steps)\n\n## Architecture Overview\n\n![](./diagrams/architecture_diagram.png)\n\nThe system has two parallel API tracks:\n\n- **V1**- single-agent, stateless endpoints for simple integrations and the legacy frontend flow\n- **V2**- the full multi-agent workflow. All new development targets V2.\n\n## Multi-agent System\n\nThe V2 pipeline uses five **CrewAI agents**, each with a dedicated tool set and a scoped role:\n\n| Agent                     | Role                                                      | Tools                                                      | Step(s) |\n| ------------------------- | --------------------------------------------------------- | ---------------------------------------------------------- | ------- |\n| `speech_processor`        | Transcribes audio and synthesises TTS responses           | `TextToSpeechTool`                                         | 2, 8    |\n| `translator`              | Translates between patient language and English           | `TranslationTool`                                          | 3, 4    |\n| `qna_generator`           | Generates exactly 3 focused diagnostic questions          | `QuestionGenerationTool`                                   | 4       |\n| `medication`              | Produces evidence-based medication recommendations        | `MedicationTool`                                           | 7       |\n| `prescription_specialist` | Generates prescriptions and manages Gmail MCP review loop | `PrescriptionTool`, `GMailMCPSendTool`, `GMailMCPReadTool` | 9, 10   |\n\nAgents are pre-inistantiated module-level singletons (`medical_agents.py`) and loaded into `MedicalCrew` at startup. The crew validates configuration during the FastAPI lifespan and logs a warning (without blocking startup) if initialisation fails.\n\n**Agent Tools**\n\nAll agent tools inherit from CrewAI's `BaseTool` because FastAPI runs in an async event loop and CrewAI tools call `_run()` synchronously, async service calls (LLMs, TTS) are dispatched to a dedicated `ThreadPoolExecutor` via a `_run_async()` helper to avoid `RuntimeError: This event loop is already running`\n\n## Tech Stack\n\n**Backend**\n\n| Component            | Technology                                           |\n| -------------------- | ---------------------------------------------------- |\n| Framework            | FastAPI 0.100+ with async lifespan                   |\n| LLM                  | Google Gemini 2.5 Flash via `langchain-google-genai` |\n| Agent orchestration  | CrewAI                                               |\n| STT                  | Google Speech Recognition (`speech_recognition`)     |\n| TTS                  | Google TTS (`gTTS`) + `pydub` for format conversion  |\n| Translation          | `deep-translator` (GoogleTranslator) + `langdetect`  |\n| Session store (dev)  | In-memory dict                                       |\n| Session store (prod) | Redis (`redis-py` async)                             |\n| Tracing              | OpenTelemetry (OTLP gRPC exporter)                   |\n| LLM tracing          | LangSmith                                            |\n| MCP                  | Gmail MCP server (custom `GMailMCPClient`)           |\n| Config               | Pydantic Settings v2                                 |\n| Runtime              | Python 3.11, Uvicorn                                 |\n\n**Frontend**\n\n| Component       | Technology                                       |\n| --------------- | ------------------------------------------------ |\n| Framework       | React 19 + TypeScript 5.5                        |\n| Build           | Vite 7                                           |\n| State           | Zustand 5 with `devtools` + `persist` middleware |\n| Styling         | Tailwind CSS 3.4                                 |\n| Audio capture   | `MediaRecorder` API (WebM/Opus → server STT)     |\n| STT (Q\u0026A phase) | Web Speech Recognition API                       |\n| TTS (intro)     | Web Speech Synthesis API                         |\n| HTTP            | Fetch API (custom `V1ApiClient` / `V2ApiClient`) |\n| Testing         | Vitest + Testing Library                         |\n\n## Infrastructure\n\n| Component        | Technology                               |\n| ---------------- | ---------------------------------------- |\n| Reverse proxy    | Nginx (TLS 1.2/1.3, HTTP/2, SSE support) |\n| Containerisation | Docker + Docker Compose                  |\n| CI               | GitHub Actions                           |\n| Metrics / traces | OpenTelemetry Collector → OTLP endpoint  |\n\n## Project Structure\n\n```\ndocjarvis/\n├── backend/                      # Python FastAPI backend\n│   ├── src/\n│   │   ├── api/\n│   │   │   ├── __init__.py\n│   │   │   ├── main.py          # FastAPI app (artifact above)\n│   │   │   ├── schemas.py\n│   │   │   ├── routes/\n│   │   │   │   ├── __init__.py\n│   │   │   │   ├── diagnosis.py\n│   │   │   │   ├── health_checks.py\n│   │   │   │   ├── helpers.py\n│   │   │   │   ├── monitoring.py\n│   │   │   │   ├── prescription.py\n│   │   │   │   ├── sessions.py\n│   │   │   │   ├── workflow_routes.py\n│   │   │   └── middleware/\n│   │   │   │   ├── __init__.py\n│   │   │   │   ├── error_handler.py\n│   │   │   │   └── logging.py\n│   │   ├── config/\n│   │   │   ├── __init__.py\n│   │   │   ├── monitoring.py\n│   │   │   ├── settings.py\n│   │   ├── core/\n│   │   │   ├── __init__.py\n│   │   │   ├── diagnosis.py\n│   │   │   ├── llm_manager.py\n│   │   │   ├── mcp_client.py\n│   │   │   ├── prescription.py\n│   │   │   ├── crew_ai/\n│   │   │   │   ├── tools/\n│   │   │   │   │   ├── __init__.py\n│   │   │   │   │   ├── gmail_mcp_tools.py\n│   │   │   │   │   ├── medical_tools.py\n│   │   │   │   ├── workflows/\n│   │   │   │   │   ├── __init__.py\n│   │   │   │   │   ├── mcp_workflow.py\n│   │   │   │   │   └── session_workflow.py\n│   │   │   │   ├── __init__.py\n│   │   │   │   ├── constants.py\n│   │   │   │   ├── medical_agents.py\n│   │   │   │   └── medical_crew.py\n│   │   ├── monitoring/\n│   │   │   ├── __init__.py\n│   │   │   ├── cache_manager.py\n│   │   │   ├── dashboard.py\n│   │   │   ├── load_balancer.py\n│   │   │   ├── performance_monitor.py\n│   │   ├── services/\n│   │   │   ├── __init__.py\n│   │   │   ├── session_store.py\n│   │   │   ├── speech.py\n│   │   │   ├── translation.py\n│   │   ├── utils/\n│   │   │   ├── __init__.py\n│   │   │   ├── backstories.py\n│   │   │   ├── consts.py\n│   │   │   ├── exceptions.py\n│   │   │   ├── file_handler.py\n│   │   │   ├── helpers.py\n│   │   │   └── task_descriptions.py\n│   ├── tests/\n│   │   ├── conftest.py\n│   │   ├── integration/\n│   │   │   ├── test_monitoring_health.py\n│   │   │   ├── test_session_lifecycle.py\n│   │   │   ├── test_sessions_api.py\n│   │   │   └── test_workflow_routes.py\n│   │   └── unit/\n│   │   │   ├── test_cache_manager.py\n│   │   │   ├── test_consts.py\n│   │   │   ├── test_diagnosis.py\n│   │   │   ├── test_helpers.py\n│   │   │   ├── test_mcp_workflow.py\n│   │   │   ├── test_monitoring.py\n│   │   │   ├── test_session_store.py\n│   │   │   └── test_session_workflow.py\n│   ├── pyproject.toml\n│   ├── requirements.txt\n│   └── Dockerfile\n├── frontend/                     # React TypeScript frontend\n│   ├── src/\n│   │   ├── api/\n│   │   │   ├── client.ts        # API client\n│   │   ├── components/\n│   │   │   ├── consultation/\n│   │   │   │   ├── index.ts\n│   │   │   │   ├── ConversationDisplay.tsx\n│   │   │   │   ├── ConversationPane.tsx\n│   │   │   │   ├── PatientForm.tsx\n│   │   │   │   ├── PrescriptionPane.tsx\n│   │   │   │   ├── PrescriptionReview.tsx\n│   │   │   │   ├── VoiceConsultation.tsx\n│   │   │   ├── layout/\n│   │   │   │   ├── index.ts\n│   │   │   │   ├── Header.tsx\n│   │   │   │   ├── Footer.tsx\n│   │   │   ├── speech/\n│   │   │   │   ├── index.ts\n│   │   │   │   ├── SpeechControls.tsx\n│   │   │   │   ├── VoiceInput.tsx\n│   │   │   └── ui/ # Reusable UI components\n│   │   │   │   ├── index.ts\n│   │   │   │   ├── Alert.tsx\n│   │   │   │   ├── Button.tsx\n│   │   │   │   ├── Card.tsx\n│   │   │   │   ├── Input.tsx\n│   │   │   │   ├── ProgressBar.tsx\n│   │   │   │   ├── Select.tsx\n│   │   │   │   ├── Spinner.tsx\n│   │   │   │   └── TextArea.tsx\n│   │   ├── hooks/\n│   │   │   ├── index.ts\n│   │   │   ├── useAudioRecording.ts\n│   │   │   ├── useLocalStorage.ts\n│   │   │   ├── useSpeechRecognition.ts\n│   │   │   ├── useSpeechSynthesis.ts\n│   │   ├── utils/\n│   │   │   ├── constants.ts\n│   │   │   ├── consultationStore.ts\n│   │   │   └── index.ts\n│   │   ├── App.tsx\n│   │   ├── main.tsx\n│   │   └── index.css\n│   ├── public/\n│   ├── Dockerfile\n│   ├── env.d.ts\n│   ├── index.html\n│   ├── nginx.conf\n│   ├── package.json\n|   ├── package-lock.json\n│   ├── tailwind.config.js\n│   ├── tsconfig.json\n│   ├── tsconfig.node.json\n│   └── vite.config.ts\n├── .github/\n│   └── workflows/\n│       ├── ci.yml\n│       └── deploy.yml\n├── .gitignore\n├── .pylintrc\n├── Pytest.ini\n├── docker-compose.yml\n├── otel-config.yml\n├── package.json\n└── README.md\n```\n\n## API Reference\n\nFull interactive docs are available at `http://localhost:8000/docs` in debug mode.\n\n### V1 — Legacy Single-Agent\n\n| Method   | Endpoint                                | Description                            |\n| -------- | --------------------------------------- | -------------------------------------- |\n| `POST`   | `/api/v1/sessions/`                     | Create a session                       |\n| `GET`    | `/api/v1/sessions/{id}`                 | Get full session state                 |\n| `POST`   | `/api/v1/sessions/{id}/answer`          | Submit a text answer                   |\n| `POST`   | `/api/v1/sessions/{id}/transcribe`      | Submit audio (STT + next question)     |\n| `POST`   | `/api/v1/sessions/{id}/complete`        | Complete session and get medication    |\n| `POST`   | `/api/v1/sessions/{id}/complete/stream` | Streaming medication (SSE)             |\n| `DELETE` | `/api/v1/sessions/{id}`                 | Delete session                         |\n| `POST`   | `/api/v1/diagnosis/questions`           | Generate questions from complaint text |\n| `POST`   | `/api/v1/prescription/{id}/generate`    | Generate prescription document         |\n| `GET`    | `/api/v1/prescription/{id}/download`    | Download prescription file             |\n\n### V2 — CrewAI Multi-Agent Workflow\n\nAll V2 workflow endpoints accept `multipart/form-data` (FastAPI `Form` parameters).\n\n| Method   | Endpoint                                         | Step | Description                                |\n| -------- | ------------------------------------------------ | ---- | ------------------------------------------ |\n| `POST`   | `/api/v2/workflow/welcome-audio`                 | 1    | Generate TTS welcome audio                 |\n| `POST`   | `/api/v2/workflow/process-initial-symptom`       | 2–4  | STT → translation → 3 diagnostic questions |\n| `POST`   | `/api/v2/workflow/answer-question/{id}`          | 5–6  | Record a Q\u0026A answer                        |\n| `POST`   | `/api/v2/workflow/generate-recommendations/{id}` | 7    | CrewAI diagnosis + pharmacist agents       |\n| `POST`   | `/api/v2/workflow/recommendations-audio`         | 8    | TTS of recommendations                     |\n| `POST`   | `/api/v2/workflow/generate-prescription/{id}`    | 9–10 | Generate PDF + Gmail MCP send              |\n| `POST`   | `/api/v2/workflow/doctor-response`               | MCP  | Parse doctor's APPROVE/MODIFY/REJECT reply |\n| `GET`    | `/api/v2/workflow/session/{id}/status`           | —    | Poll session progress                      |\n| `DELETE` | `/api/v2/workflow/session/{id}`                  | —    | Delete session                             |\n| `GET`    | `/api/v2/workflow/health`                        | —    | Crew health check                          |\n\n### V2 — Monitoring\n\n| Method | Endpoint                                 | Description                             |\n| ------ | ---------------------------------------- | --------------------------------------- |\n| `GET`  | `/api/v2/monitoring/dashboard`           | Full metrics dashboard                  |\n| `GET`  | `/api/v2/monitoring/performance`         | Agent P50/P95/P99 latency + error rates |\n| `GET`  | `/api/v2/monitoring/cache`               | Cache hit rate and per-agent config     |\n| `POST` | `/api/v2/monitoring/cache/clear`         | Clear all agent caches                  |\n| `POST` | `/api/v2/monitoring/cache/clear/{agent}` | Clear single agent cache                |\n| `GET`  | `/api/v2/monitoring/load-balancing`      | Concurrency load per agent              |\n| `GET`  | `/api/v2/monitoring/agents`              | Per-agent health status                 |\n| `GET`  | `/api/v2/monitoring/health`              | Overall system health score             |\n\n### V2 — Health\n\n| Method | Endpoint                 | Description                                                  |\n| ------ | ------------------------ | ------------------------------------------------------------ |\n| `GET`  | `/api/v2/health/ready`   | Kubernetes readiness probe (LLM, crew, cache, load balancer) |\n| `GET`  | `/api/v2/health/deep`    | Full diagnostic: agents, resources, MCP                      |\n| `GET`  | `/api/v2/health/startup` | Post-init startup check                                      |\n| `GET`  | `/health`                | Root health (used by load balancer)                          |\n| `GET`  | `/ready`                 | Root readiness (used by load balancer)                       |\n\n## Getting Started\n\n### Prerequisites\n\n| Requirement             | Version |\n| ----------------------- | ------- |\n| Python                  | 3.11+   |\n| Node.js                 | 20+     |\n| Docker + Docker Compose | 24+     |\n| Google Cloud account    | —       |\n| Gmail account (for MCP) | —       |\n\n### Environment Variables\n\nCreate `.env` in project root from the template below:\n\n```env\n# -- LLM -------------------------\nGOOGLE_API_KEY=your_google_api_key\n# -- Application -------------------------\nENVIRONMENT=dev # dev | staging | prod\n# -- Session Store -------------------------\n# Leave blank to use in-memory store (dev).\n# Set to redis://... for production\nREDIS_URL=\n# -- MCP / GMail -------------------------\n# Gmail MCP server endpoint (e.g. a locally running MCP server or hosted URL)\nGMAIL_SERVER=http://localhost:3001\n# -- Doctor's email address for prescription review -------------------------\nDOCTOR_EMAIL = doctor@hospital.com\n# -- LangSmith (optional) -------------------------\nLANGSMITH_API_KEY=\nLANGSMITH_PROJECT=docjarvis\nLANGSMITH_TRACING=false\n# -- OpenTelemetry (optional) -------------------------\nOTEL_ENABLED=false\nOTEL_EXPORTER_ENDPOINT=http://local-host:4317\nOTEL_SERVICE_NAME=docjarvis-backend\nVITE_API_URL_v1=http://localhost:8000/api/v1\nVITE_API_URL_v2=http://localhost:8000/api/v2\n```\n\n### Local Development\n\n**Backend**:\n\n```bash\ncd backend\npython -m venv .venv\nsource .venv/bin/activate          # Windows: .venv\\Scripts\\activate\npip install -r requirements.txt\nuvicorn src.api.main:app --reload --host 0.0.0.0 --port 8000\n```\n\nThe API will be live at `http://localhost:8000`. Swagger UI is available at `http://localhost:8000/docs` (debug mode only).\n\n**Frontend**:\n\nThe Vite dev server requires a local TLS certificate because `MediaRecorder` and Web Speech APIs require HTTPS (even on localhost in some browsers). Generate one with [mkcert](https://github.com/FiloSottile/mkcert):\n\n```bash\nmkcert -install\nmkcert localhost\n# Moves the generated files into the frontend directory:\nmv localhost.pem localhost-key.pem frontend/\ncd frontend\nnpm install\nnpm run dev\n```\n\n### Docker Compose\n\n```bash\n# Build and start all services\ndocker compose up --build\n\n# Backend only\ndocker compose up backend\n\n# With Redis session store\nREDIS_URL=redis://redis:6379 docker compose up\n```\n\nServices:\n\n| Service    | Port   | Description                  |\n| ---------- | ------ | ---------------------------- |\n| `backend`  | `8000` | FastAPI app                  |\n| `frontend` | `443`  | Nginx + React (HTTPS)        |\n| `redis`    | `6379` | Session store (prod profile) |\n\n## Workflow: End-to-End Flow\n\n![](./diagrams/workflow.png)\n\n## MCP Integration\n\nDocJarvis implements a HITL review step using the Gmail MCP server. No prescription is finalised without explicit doctor approval.\n\n**How it works**\n\n1. The `prescription_specialist` CrewAI agent calls `GMailMCPSendTool` to send a formatted HTML email to `DOCTOR_EMAIL` containing the prescription and review instructions.\n2. The email body contains structured commands the doctor replies with:\n   - `APPROVE #\u003creview_id\u003e`- approve as written\n   - `MODIFY #\u003creview_id\u003e - \u003cchanges\u003e`- approve with modifications\n   - `REJECT #\u003creview_id\u003e - \u003creason\u003e`- reject\n3. The `MCPWorkflowManager` polls GMail via `GMailMCPReadTool` every 10 seconds for replies (configure via `POLL_INTERVAL_SECONDS`).\n4. On receipt, `_parse_action()` uses regex matching to extract the command and routes to appropriate outcome handlers.\n5. The frontend `PrescriptionReview` component lets users paste the doctor's reply directly as a fallback for environments where polling is unavailable.\n\n**MCP server setup**\n\nThe GMail MCP server must be running and accessible at `GMAIL_SERVER`. Refer to MCP server's own documentation for OAuth2 credential setup. The `GMailMCPClient` connects on first use and reconnects if disconnected.\n\n## Monitoring and Observability\n\n### OpenTelemetry\n\nWhen `OTEL_ENABLED=true`, the backend exports traces and metrics via OTLP gRPC to `OTEL_EXPORTER_ENDPOINT`. FastAPI and HTTPX are auto-instrumented via `FastAPIInstrumentor` and `HTTPXClientInstrumentor`. Custom metrics recorded:\n\n| Metric                        | Type           | Description                 |\n| ----------------------------- | -------------- | --------------------------- |\n| `docjarvis.session.created`   | Counter        | Sessions created            |\n| `docjarvis.session.completed` | Counter        | Sessions completed          |\n| `docjarvis.llm.requests`      | Counter        | LLM API calls               |\n| `docjarvis.llm.errors`        | Counter        | LLM API errors              |\n| `docjarvis.llm.latency`       | Histogram (ms) | LLM request latency         |\n| `docjarvis.session.duration`  | Histogram (s)  | Consultation duration       |\n| `agent_execution_duration`    | Histogram (ms) | Per-agent execution time    |\n| `cache_operations`            | Counter        | Cache hits / misses / sets  |\n| `agent_concurrent_load`       | Histogram      | Real-time agent concurrency |\n\n### LangSmith\n\nSet `LANGSMITH_TRACING=true` and provide `LANGSMITH_API_KEY` + `LANGSMITH_PROJECT` to trace all LangChain/LLM calls in the LangSmith dashboard.\n\n### Monitoring Dashboard\n\nThe V2 dashboard endpoint (`GET /api/v2/monitoring/dashboard`) returns a comprehensive JSON payload covering:\n\n- Per-agent performance (P50/P95/P99, success rate, error count)\n- Cache statistics (hit rate, LRU eviction count, per-agent TTL config)\n- Load balancer state (current concurrency, queue depth per agent)\n- System metrics (CPU, memory, disk via `psutil`)\n\n### Per-Agent Thresholds\n\n| Agent          | Latency threshold | Error rate threshold |\n| -------------- | ----------------- | -------------------- |\n| `stt`          | 3,000 ms          | 3%                   |\n| `translation`  | 2,000 ms          | 2%                   |\n| `qa`           | 4,000 ms          | 5%                   |\n| `diagnosis`    | 6,000 ms          | 5%                   |\n| `prescription` | 5,000 ms          | 5%                   |\n| `tts`          | 4,000 ms          | 3%                   |\n\nBreaches trigger a `performance_alerts` counter increment and a `WARNING` log entry.\n\n## CI/CD\n\nThe pipeline is defined in `.github/workflows/ci.yml` and runs on every push to `main` and on pull requests targetting `main`.\n\n```\nbackend-test ──┐\n               ├──▶ docker-build\nfrontend-test ─┘\n```\n\n**`backend-test`:**\n\n1. Python 3.11 setup with pip cache\n2. Install `requirements.txt` + `pytest pytest-asyncio pytest-cov pylint httpx`\n3. Pylint lint (non-blocking)\n4. `pytest --cov=src --cov-report=xml`\n5. Upload coverage to Codecov\n   **`frontend-test`:**\n6. Node 20 setup with npm cache\n7. `npm ci`\n8. ESLint + TypeScript typecheck\n9. Vitest with coverage\n10. `vite build` (validates the production bundle)\n    **`docker-build`** (runs only after both test jobs pass):\n11. `docker build ./backend`\n12. `docker build ./frontend`\n\n## Configuration Reference\n\nAll backend configuration is managed through `src/config/settings.py` (Pydantic Settings v2). Values are read from environment variables or `.env`\n\n| Variable                 | Default            | Description                                       |\n| ------------------------ | ------------------ | ------------------------------------------------- |\n| `GOOGLE_API_KEY`         | —                  | **Required.** Google Generative AI API key        |\n| `ENVIRONMENT`            | `dev`              | `dev` \\| `staging` \\| `prod`                      |\n| `DEBUG`                  | `true`             | Enables Swagger UI at `/docs`                     |\n| `HOST`                   | `0.0.0.0`          | Bind address                                      |\n| `PORT`                   | `8000`             | Bind port                                         |\n| `WORKERS`                | `4`                | Uvicorn workers (ignored in debug mode)           |\n| `GEMINI_MODEL`           | `gemini-2.5-flash` | Model identifier                                  |\n| `LLM_TEMPERATURE`        | `0.2`              | Generation temperature                            |\n| `LLM_MAX_TOKENS`         | `2048`             | Max output tokens                                 |\n| `REDIS_URL`              | `\"\"`               | Redis connection string (empty = in-memory store) |\n| `SESSION_TTL`            | `3600`             | Redis session TTL in seconds                      |\n| `GMAIL_SERVER`           | `\"\"`               | Gmail MCP server endpoint                         |\n| `DOCTOR_EMAIL`           | `\"\"`               | Recipient for prescription review emails          |\n| `LANGSMITH_API_KEY`      | `\"\"`               | LangSmith API key                                 |\n| `LANGSMITH_PROJECT`      | `\"\"`               | LangSmith project name                            |\n| `LANGSMITH_TRACING`      | `false`            | Enable LangSmith tracing                          |\n| `OTEL_ENABLED`           | `false`            | Enable OpenTelemetry export                       |\n| `OTEL_SERVICE_NAME`      | `\"\"`               | OTel service name                                 |\n| `OTEL_EXPORTER_ENDPOINT` | `\"\"`               | OTLP gRPC endpoint                                |\n\n## Deployment\n\n### Tech Stack\n\n| Layer                  | Technology                                              |\n| ---------------------- | ------------------------------------------------------- |\n| **Frontend**           | React 19, TypeScript, Vite, Zustand, Tailwind CSS       |\n| **Backend**            | FastAPI, Python 3.11, CrewAI, Gemini 2.5 Flash          |\n| **AI / LLM**           | Google Gemini via LangChain, CrewAI multi-agent         |\n| **Speech**             | Web Speech API (STT), Web Speech Synthesis + gTTS (TTS) |\n| **Email**              | Gmail API (OAuth 2.0) for prescription review           |\n| **Frontend Hosting**   | Vercel                                                  |\n| **Backend Hosting**    | Google Cloud Run                                        |\n| **Container Registry** | Google Artifact Registry                                |\n| **CI**                 | GitHub Actions                                          |\n| **CD**                 | GitHub Actions → Cloud Run + Vercel                     |\n\n### CI/CD Deployment Flow\n\n![](./diagrams/deployment_flow.png)\n\n### Environment Variables\n\n| Variable                   | Description                             |\n| -------------------------- | --------------------------------------- |\n| `GOOGLE_API_KEY`           | Gemini API key                          |\n| `DOCTOR_EMAIL`             | Recipient email for prescription review |\n| `GMAIL_CREDENTIALS_B64`    | Base64-encoded `credentials.json`       |\n| `GMAIL_TOKEN_B64`          | Base64-encoded `token.json`             |\n| `ENVIRONMENT`              | `prod`                                  |\n| `CREWAI_TRACING_ENABLED`   | `false`                                 |\n| `CREWAI_DISABLE_TELEMETRY` | `true`                                  |\n| `VITE_API_URL_V1`          | `https://your-backend.run.app/api/v1`   |\n| `VITE_API_URL_V2`          | `https://your-backend.run.app/api/v2`   |\n\n### GitHUb Secrets Required\n\n```\nGCP_SA_KEY                 — GCP service account JSON key\nGCP_PROJECT_ID             — GCP project ID\nGOOGLE_API_KEY             — Gemini API key\nDOCTOR_EMAIL               — Doctor email for prescription review\nGMAIL_CREDENTIALS_B64      — base64 -i credentials.json | tr -d '\\n'\nGMAIL_TOKEN_B64            — base64 -i token.json | tr -d '\\n'\nVERCEL_TOKEN               — Vercel API token\nVITE_API_URL_V1            — Cloud Run backend URL /api/v1\nVITE_API_URL_V2            — Cloud Run backend URL /api/v2\n```\n\n## Manual First Deploy (one-time, before CD is active)\n\n```bash\n# 1. Authenticate\ngcloud auth login\ngcloud config set project YOUR_PROJECT_ID\n\n# 2. Enable APIs\ngcloud services enable run.googleapis.com artifactregistry.googleapis.com\n\n# 3. Create Artifact Registry repository\ngcloud artifacts repositories create docjarvis \\\n  --repository-format=docker \\\n  --location=us-central1\n\n# 4. Build and push\ngcloud auth configure-docker us-central1-docker.pkg.dev\ndocker buildx build \\\n  --platform linux/amd64 \\\n  -t us-central1-docker.pkg.dev/YOUR_PROJECT_ID/docjarvis/backend:latest \\\n  --push ./backend\n\n# 5. Deploy\ngcloud run deploy docjarvis-backend \\\n  --image us-central1-docker.pkg.dev/YOUR_PROJECT_ID/docjarvis/backend:latest \\\n  --platform managed \\\n  --region us-central1 \\\n  --allow-unauthenticated \\\n  --memory 2Gi --cpu 2 --timeout 300 \\\n  --port 8080 --startup-cpu-boost\n\n# 6. Get URL\ngcloud run services describe docjarvis-backend \\\n  --region us-central1 \\\n  --format 'value(status.url)'\n```\n\nAfter this, all subsequent deploys happen automatically via the CD pipeline on every push to `main`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinghdivyank%2Fvoice-assistant","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsinghdivyank%2Fvoice-assistant","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinghdivyank%2Fvoice-assistant/lists"}