0% found this document useful (0 votes)
3 views66 pages

Methodology File

The frontend is a React SPA built with Vite, utilizing Tailwind for styling and Zustand with Context API for state management, while making API calls using the native fetch API. The backend is a Python FastAPI application that communicates with a cloud LLM via the OpenAI SDK and includes various middleware for authentication, logging, and rate limiting. Key features include a chat interface, mood insights, and cognitive distortion detection, with real-time capabilities through SSE for chat responses.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views66 pages

Methodology File

The frontend is a React SPA built with Vite, utilizing Tailwind for styling and Zustand with Context API for state management, while making API calls using the native fetch API. The backend is a Python FastAPI application that communicates with a cloud LLM via the OpenAI SDK and includes various middleware for authentication, logging, and rate limiting. Key features include a chat interface, mood insights, and cognitive distortion detection, with real-time capabilities through SSE for chat responses.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

3.

1 Technologies and Tools Used


3.1.1 Frontend Framework
Questions;
Analyze the entire frontend codebase and tell me:
1. Is this project using [Link], [Link], or both? What version (check [Link])?
2. Is it using App Router or Pages Router ([Link])?
3. List all major UI libraries and component libraries in use (e.g., Tailwind, shadcn/ui, MUI,
Framer Motion).
4. What state management approach is used — Context API, Redux, Zustand, or other?
5. How are API calls made from the frontend — fetch, axios, React Query, SWR?
6. List the key pages/routes and what each one does in the context of the mental health app.
7. Are there any real-time features (WebSockets, SSE) on the frontend?
Give output as a structured technical summary suitable for a methodology chapter.

Solution:

Here is a concise technical summary grounded in `[Link]`, `[Link]`, `src/[Link]`,


`src/services/[Link]`, and the main views/stores.

---

## Frontend stack and architecture (methodology-oriented summary)

### 1. Framework: React vs [Link] and versions

The client is a **Vite single-page application (SPA)** using **React only** — **[Link] is not
used** (no `next` dependency, build script is `vite`).

From `[Link]`:

| Package | Declared version |


|----------------|------------------|
| **react** | `^19.2.0` |
| **react-dom** | `^19.2.0` |
| **vite** | `^7.3.1` (dev) |
| **typescript** | `^5.9.3` (dev) |

The repo mixes **JavaScript (`.jsx`)** and **TypeScript (`.tsx`/`.ts`)** under `src/`.

### 2. [Link] routing: App Router vs Pages Router

**Not applicable.** There is no [Link] file-based routing. Navigation is **in-app tab state**
(`activeTab` in `[Link]`) with five primary “screens” rendered as siblings and shown/hidden
with CSS (`hidden` vs full height), not URL routes.
### 3. Major UI and component-related libraries

| Library / layer | Role in this project |


|------------------|----------------------|
| **Tailwind CSS** (`tailwindcss` `^4.2.1`, `@tailwindcss/vite` `^4.2.1`) | Utility-first styling;
integrated via Vite plugin; `src/[Link]` uses `@import "tailwindcss"`. |
| **Framer Motion** (`framer-motion` `^12.35.1`) | Layout/enter-exit animations across sidebar,
chat, toolkit, modals, widgets. |
| **Radix UI** (`@radix-ui/react-popover` `^1.1.15`) | Headless popover primitive (e.g.
`[Link]`). This is **one Radix primitive**, not a full shadcn/ui kit. |
| **Recharts** (`recharts` `^3.8.0`) | Charts on the insights dashboard (mood trends, bars, etc.). |
| **canvas-confetti** (`canvas-confetti` `^1.9.4`) | Lightweight celebration / feedback effects (e.g.
widget completion). |

There is **no MUI**, **no full shadcn/ui package set**, and **no React Router** in
dependencies.

### 4. State management

A **hybrid** approach:

- **Zustand** (`zustand` `^5.0.12`): global client state for **chat messages** (`[Link]`)
and **audio/atmosphere** (`[Link]`).
- **React Context API**: **`MoodProvider`** (current mood + light/dark theme synced to `data-
mood` / `data-theme` on `[Link]`) and **`AudioProvider`** (thin wrapper
exposing mute/volume controls backed by the audio Zustand store).

**Redux / RTK, MobX, Jotai, Recoil** are **not** direct application dependencies in
`[Link]`; the application code does not import them.

### 5. How API calls are made

All HTTP traffic is centralized in **`src/services/[Link]`** and uses the **native `fetch` API** only.
There is **no axios**, **no TanStack React Query**, and **no SWR** in `[Link]` or
typical usage patterns from the scanned files.

The backend base URL is fixed as `[Link] in that module, with JWT-style
handling via `Authorization: Bearer` after guest registration/login.

**Streaming:** assistant replies use **`fetch` to `POST /api/chat/stream`** with manual


**`ReadableStream` + `TextDecoder`** processing of **Server-Sent Events (SSE)**-style `data:
…` lines (`streamChat` in `[Link]`), not a third-party streaming client.
### 6. Key “pages” / areas and mental-health app role

These are **logical sections** (tabs), not [Link] routes:

| Tab id (`Sidebar`) | User-facing label | Role in the mental-health / CBT app |


|--------------------|-------------------|-------------------------------------|
| `chat` | Chat | Primary **therapeutic dialogue**: streaming LLM chat, crisis handling, voice
modal, session sidebar, mood-linked widgets in the feed, history sync with the API. |
| `dashboard` | Insights | **Mood and usage insights**: pulls mood history from the API,
visualizes patterns (Recharts), badges/interventions from local logging. |
| `toolkit` | Toolkit | **Self-guided CBT / wellness tools** (thought journal, grounding, gratitude,
behavioral activation, etc.); can hand off a prompt to chat for guided exercises. |
| `music` | Music | **Music / playlist discovery** (external links) and integration with the app’s
**ambient / soundscape** experience (Zustand-driven audio). |
| `exercises` | Exercises | **Cognitive distortion work**: user text analyzed via
**`detectDistortions`** API; educational UI around identified thinking patterns. |

### 7. Real-time features on the frontend

- **WebSockets:** No `WebSocket` usage was found in `src/` for client connectivity to the
backend.
- **SSE / streaming:** Yes — **token streaming for chat** is implemented over HTTP using
**`fetch` + stream reading** and parsing of SSE-formatted payloads (`streamChat` in `[Link]`).
This provides **incremental assistant output** and metadata/crisis signals in the stream
contract, but it is **not** a separate `EventSource` long-poll API in the code inspected; it is
**fetch-based SSE consumption**.

---

**Bottom line for a methodology chapter:** This study’s web client is a **React 19 SPA built with
Vite 7**, styled primarily with **Tailwind 4**, with **Zustand + Context** for state, **fetch**
(including **SSE-style streaming** for chat) toward a **FastAPI** backend, and **no [Link] or
file-based App/Pages routing**.

3.1.2 backend and API Layer


Analyze the backend codebase and answer:
1. What backend framework is used — [Link]/Express, FastAPI, or both? List versions from
[Link] or [Link].
2. What is the folder/module structure of the backend? List major directories and their roles.
3. How are API routes organized? List all major REST endpoints with their HTTP method, path,
and purpose.
4. Is there middleware for auth, logging, rate limiting, or error handling? List them.
5. How does the backend communicate with the LLM API — direct HTTP calls, SDK,
streaming?
6. Are there any background jobs, queues, or scheduled tasks?
Give output as a structured technical summary for a methodology chapter.
Here is a structured backend summary based on `cbt-backend/[Link]`, `[Link]`,
`[Link]`, `middleware/*`, and all routers under `cbt-backend/routers/`.

---

## Backend technical summary (methodology-oriented)

### 1. Framework stack and versions

The backend is **Python-only**. There is **no [Link] / Express** layer and **no
`[Link]`** under `cbt-backend/`.

| Component | Role | Pinned / constrained version (`[Link]`) |


|-----------|------|-----------------------------------------------------|
| **FastAPI** | HTTP API framework | `0.135.1` |
| **Uvicorn** | ASGI server | `0.41.0` |
| **SQLAlchemy** | Async ORM / DB access | `2.0.48` |
| **aiosqlite** | Async SQLite driver | `0.22.1` |
| **Pydantic** | Request/response models | `2.12.5` |
| **python-jose** | JWT encode/decode | `3.5.0` |
| **passlib + bcrypt** | Password hashing | `1.7.4`, `4.0.1` |
| **slowapi** | Rate limiting | `0.1.9` |
| **OpenAI Python SDK** | Groq-compatible chat client | `openai>=1.40.0` |
| **transformers + torch** | Local HF models (mood, distortions) | `5.3.0`, `2.10.0` |
| **openai-whisper** | Local STT | `20250625` |
| **gTTS, pydub** | TTS / audio handling | `2.5.4`, `0.25.1` |

**Conclusion:** Single backend stack — **FastAPI on Uvicorn**, with **local ML**


(Transformers, Whisper) and **cloud LLM** (Groq via OpenAI-compatible API).

---

### 2. Folder / module structure

| Path | Role |
|------|------|
| `[Link]` | App factory, **lifespan** (DB init, model loading, background `asyncio` tasks),
**CORS**, middleware wiring, router registration, **health** and demo routes. |
| `[Link]` | Async SQLAlchemy engine, sessions, `get_db` dependency. |
| `[Link]` | JWT creation/validation, **OAuth2 bearer** dependency `get_current_user`. |
| `logging_config.py` | Root logging, file handlers, **JSONL structured** events
(`log_structured`). |
| `routers/` | HTTP route modules (`auth`, `mood`, `distortion`, `chat`, `voice`, `voice_chat`,
`crisis`, `history`). |
| `models/` | Domain logic: `[Link]` (LLM), `mood_classifier.py`, `distortion_detector.py`,
`[Link]`, `crisis_handler.py`, `[Link]`, `db_models.py`, `inference_cache.py`, etc. |
| `middleware/` | `rate_limiter.py` (SlowAPI), `error_handler.py` (global exception handlers). |
| `scripts/` | Utilities (e.g. `check_env.py`). |

---

### 3. API route organization and major REST endpoints

Routers are mounted from `[Link]` with path prefixes shown below. **Method — path —
purpose:**

**Application root (`[Link]`, not under `/api`)**

| Method | Path | Purpose |


|--------|------|---------|
| GET | `/` | Lightweight “server up” JSON with high-level model labels. |
| GET | `/health` | JSON health snapshot (model load state, devices, uptime). |
| GET | `/health/ui` | HTML dashboard for demos (polls `/health`). |
| POST | `/health/test-stream` | Benchmarks **Groq streaming** (`Therapist.chat_stream`)
without JWT/DB. |

**Auth — `routers/[Link]` → prefix `/api/auth`**

| Method | Path | Purpose |


|--------|------|---------|
| POST | `/api/auth/register` | Create user (bcrypt), return access + refresh JWTs. |
| POST | `/api/auth/login` | Verify credentials, return JWT pair. |
| POST | `/api/auth/refresh` | Exchange refresh token for new access + refresh tokens. |

**Mood — `routers/[Link]` → `/api`**

| Method | Path | Purpose |


|--------|------|---------|
| POST | `/api/classify-mood` | BERT-based text → app mood + emotion scores
(cached). |

**Distortions — `routers/[Link]` → `/api`**

| Method | Path | Purpose |


|--------|------|---------|
| POST | `/api/detect-distortions` | DistilBART-MNLI zero-shot cognitive distortions (cached). |
**Chat — `routers/[Link]` → `/api`**

| Method | Path | Purpose |


|--------|------|---------|
| POST | `/api/chat` | Non-streaming CBT-style reply; persists messages/mood logs; **JWT**. |
| POST | `/api/chat/stream` | **SSE** stream of tokens + final metadata; persists
user/assistant/mood metadata; **JWT**. |

**Voice (STT/TTS) — `routers/[Link]` → `/api`**

| Method | Path | Purpose |


|--------|------|---------|
| POST | `/api/transcribe` | Upload audio → Whisper text; **JWT**. |
| POST | `/api/synthesize` | Text → gTTS MP3 stream; **JWT**. |

**Voice pipeline — `routers/voice_chat.py` → `/api`**

| Method | Path | Purpose |


|--------|------|---------|
| POST | `/api/voice-chat` | Single request: transcribe → mood → therapist → TTS
base64; **JWT**. |

**Crisis — `routers/[Link]` → `/api/crisis`**

| Method | Path | Purpose |


|--------|------|---------|
| POST | `/api/crisis/response` | Static / rule-based crisis copy + resources metadata from
`CrisisHandler`. |
| GET | `/api/crisis/resources` | Curated crisis resource list for clients. |

**History / sessions — `routers/[Link]` → `/api`**

| Method | Path | Purpose |


|--------|------|---------|
| GET | `/api/history/{session_id}` | Chronological chat messages for a session; **JWT**. |
| GET | `/api/mood-history/{session_id}` | Mood log timeline for insights; **JWT**. |
| DELETE | `/api/session/{session_id}` | Delete session and cascaded data; **JWT**. |

---

### 4. Middleware and cross-cutting concerns

| Concern | Implementation |
|---------|----------------|
| **CORS** | `CORSMiddleware` in `[Link]` — allows configured localhost origins (Vite/React
ports), credentials, all methods/headers. |
| **Authentication** | Not Starlette “auth middleware”; **route-level**
`Depends(get_current_user)` with **OAuth2 password bearer** (`[Link]`) for protected `/api/*`
routes. Public: e.g. `/api/classify-mood`, `/api/detect-distortions`, `/api/crisis/*`, auth
register/login/refresh, and root/health routes. |
| **Rate limiting** | **SlowAPI** (`middleware/rate_limiter.py`): default **60/minute** per IP;
stricter limits on selected routes via `@[Link](...)` (e.g. chat **20/minute**, voice-chat
**10/minute**, classify-mood **30/minute**, etc.). |
| **Error handling** | `middleware/error_handler.py`: handlers for `HTTPException`,
`RequestValidationError`, and a catch-all **500** handler that logs stack traces and returns
JSON without exposing internals arbitrarily. |
| **Logging** | `logging_config.configure_logging()` at import time in `[Link]`; structured
`log_structured` used in chat streaming and therapist calls. |

---

### 5. Backend ↔ LLM communication

- **Mechanism:** The **`openai` Python SDK** (`OpenAI` client) pointed at **Groq’s OpenAI-
compatible base URL** (`[Link] by default), with `GROQ_API_KEY`
and optional `GROQ_MODEL` from environment (`models/[Link]`).
- **Non-streaming:** `[Link](..., stream=False)` inside `[Link]()`,
wrapped with a **thread pool + timeout** (`LLM_CHAT_TIMEOUT_SEC`).
- **Streaming:** `Therapist.chat_stream()` uses **`stream=True`** and **iterates completion
chunks**, yielding text deltas; `routers/[Link]` wraps that in a **`StreamingResponse`** with
**`text/event-stream`** (SSE) for the client.
- **Not** raw `httpx`/`requests` for the therapist path — it is **SDK-based** HTTP under the
hood.

---

### 6. Background jobs, queues, and scheduled tasks

- **No** Celery, RQ, Dramatiq, APScheduler, or similar appears in the codebase.


- **Startup-only asynchronous work:** In `[Link]` **lifespan**, `asyncio.create_task` runs
**background loading** for DistilBART and Whisper so the API can respond while models finish
loading.
- **Per-request concurrency:** `routers/[Link]` uses a **`ThreadPoolExecutor`** to run
mood/distortion inference in parallel with streaming; this is **in-process** work, not a durable job
queue.

---
**Bottom line for a methodology chapter:** The study backend is a **FastAPI 0.135** service on
**Uvicorn**, using **SQLite + SQLAlchemy 2** for persistence, **JWT authentication** on
sensitive routes, **SlowAPI** rate limits, centralized **logging and JSON error responses**,
**local Transformers/Whisper** inference, and **Groq-hosted LLM access** via the **OpenAI
Python SDK** with both **blocking** and **streaming** chat completions, exposed to the client
as **REST + SSE** where applicable.

3.1.3 LLM API Integration


Search the entire codebase for all LLM/AI API integrations and tell me:
1. Which LLM provider(s) are used — OpenAI, Anthropic, Gemini, or others? Which models
specifically (e.g., gpt-4o, claude-3-5-sonnet)?
2. Show me how the API is called — include the SDK/client initialization pattern and a
representative API call structure.
3. What parameters are configured — temperature, max_tokens, top_p, stop sequences?
4. Is streaming used? If yes, how is the streamed response handled and sent to the frontend?
5. Where are system prompts defined? Show the full content of all system prompts related to
CBT or therapy.
6. How is conversation history/context passed to the LLM across turns?
7. Are there any prompt chaining or multi-step LLM call patterns?
Give output as a structured technical summary for a methodology chapter.

## LLM/AI Integration Summary

### 1) Providers and models used

**LLM provider (chat therapist):**


- **Groq** (via OpenAI-compatible endpoint), initialized with OpenAI Python SDK client.
- Model: **`llama-3.3-70b-versatile`** (configurable via `GROQ_MODEL`).

**Other AI/ML integrations (non-LLM but relevant):**


- **Hugging Face Transformers**
- Mood model: `bhadresh-savani/bert-base-uncased-emotion`
- Distortion model: `valhalla/distilbart-mnli-12-3` (zero-shot classification)
- **OpenAI Whisper** (local STT): `WHISPER_MODEL_NAME` default `base`
- **gTTS** (Google text-to-speech endpoint; no API key in code)

**Not found in codebase:**


- Anthropic Claude SDK/API
- Gemini SDK/API
- Direct OpenAI-hosted GPT usage (OpenAI SDK is used as a client wrapper against Groq base
URL)

---
### 2) API call pattern (client init + representative calls)

**LLM client initialization (Groq via OpenAI SDK):**

```116:124:cbt-backend/models/[Link]
[Link] = OpenAI(api_key=api_key, base_url=self.GROQ_BASE_URL)

try:
[Link](
model=self.MODEL_NAME,
messages=[{"role": "user", "content": "ping"}],
max_tokens=1,
temperature=0,
)
```

**Non-streaming chat call:**

```397:402:cbt-backend/models/[Link]
return [Link](
model=self.MODEL_NAME,
messages=messages,
stream=False,
**params,
)
```

**Streaming chat call:**

```483:488:cbt-backend/models/[Link]
stream = [Link](
model=self.MODEL_NAME,
messages=messages,
stream=True,
**params,
)
```

---

### 3) Configured generation parameters

In `Therapist._completion_params()`:
- `temperature` = env `LLM_TEMPERATURE` (default `0.7`)
- `max_tokens` = env `LLM_MAX_TOKENS` (default `1024`)
- `top_p` = env `LLM_TOP_P` (default `0.95`)

Also configured:
- `LLM_CHAT_TIMEOUT_SEC` default `90` (timeout wrapper for non-streaming call)

Not configured in current calls:


- `stop` / stop sequences
- `presence_penalty`
- `frequency_penalty`

---

### 4) Streaming usage and frontend delivery

Yes, streaming is used end-to-end.

**Backend streaming path:**


- LLM stream from `Therapist.chat_stream()` yields token deltas.
- `routers/[Link]` wraps this into FastAPI `StreamingResponse` with `media_type="text/event-
stream"`.
- Emits SSE frames:
- token chunks: `{"token": "...", "is_crisis": bool, "done": false}`
- metadata event: `{"type":"metadata","mood":...,"distortions":[...],"done":false}`
- completion event: `{"token":"","done":true}`

**Frontend streaming handling:**


- `src/services/[Link]` calls `fetch('/api/chat/stream')`, reads `[Link]()`, decodes
with `TextDecoder`, buffers by newline, parses `data: {json}` lines, and invokes callbacks
`onToken/onMetadata/onDone`.

This is effectively **SSE over fetch stream** (not EventSource).

---

### 5) System prompts (full CBT/therapy prompt content)

Primary therapy system prompt is in `Therapist.SYSTEM_PROMPT`:

```45:95:cbt-backend/models/[Link]
SYSTEM_PROMPT = '''You are a warm, compassionate CBT therapist AI. You can render
interactive UI widgets in chat when they truly help — most of the time, conversation alone is
enough.
CLINICAL PACING RULES — FOLLOW STRICTLY:

PHASE 1 — RAPPORT (first 2 exchanges):


- Just listen and reflect. No widgets. No exercises.
- Use open questions: "Tell me more about that."
- Validate the emotion without rushing to fix it.
- Example: "That sounds really exhausting. How long have you been carrying this?"

PHASE 2 — EXPLORATION (exchanges 3-5):


- Dig deeper into the specific situation.
- Identify the core thought or belief driving the distress.
- ONE widget maximum if clearly needed.
- Do not stack exercises.

PHASE 3 — INTERVENTION (exchange 6+):


- Now introduce structured CBT tools if appropriate.
- Still maximum 1 widget per response.
- Always debrief after an exercise before moving on.
- If user just completed a widget, ask about their experience BEFORE offering another one.

ABSOLUTE RULES:
- Never show a widget in two consecutive responses
- Never show more than 3 widgets in one full session
- If the user seems frustrated or disengaged, stop exercises and just talk
- Always finish the session with reflection, not an exercise

CONVERSATIONAL STYLE RULES — FOLLOW STRICTLY:


- Ask only ONE question per response. Never ask two or more questions in the same message.
- Always put the question at the END of your response, never at the beginning or middle.
- Lead with acknowledgement and validation first, then gently explore with a single focused
question.
- Use simple, warm, plain language. Avoid clinical or technical therapy terms.
- Keep responses concise — 3 to 5 sentences maximum unless the situation genuinely requires
more.
- Mirror the emotional weight of the user's message. If they are in deep distress, be gentle and
slow. Do not rush to problem-solving.
- Never give a list of suggestions or coping strategies in one message. Introduce one idea at a
time.

WIDGET JSON PROTOCOL (only when appropriate under the rules above):
Output widgets using a fenced code block with the language tag exactly `widget` (three
backticks, then the word widget, newline), then a single JSON object, then closing three
backticks on their own line.
Schema:
```widget
{"type":"TASK_BOARD"|"BREATHING_CIRCLE"|"EMOTION_WHEEL"|"DISTORTION_CARD"|
"MUSIC_CARD"|"MUSIC_SUGGESTION"|"GRATITUDE_PROMPT"|"THOUGHT_RECORD","p
ayload":{...}}
```

RULES:
- Never render more than 1 widget per response
- Always include a warm short text message BEFORE the widget
- Always include a brief follow-up text message AFTER the widget
- Keep your text SHORT when a widget is present — the widget does the work
- Never put markdown inside JSON string values. Use valid JSON only.'''
```

Additional system-level injected prompt strings:


- Dynamic context wrapper:
- `"[System Context: The user is currently feeling {mood}. Tailor your CBT intervention
specifically to this emotional state. ...]"`
- Optional distortion augmentation:
- `"Possible cognitive distortion patterns to consider for this message: ... Draw on relevant CBT
frameworks without labeling or shaming the user."`
- Optional widget directives appended into system-context (breathing/task-board/distortion-
card/music-suggestion directives).

---

### 6) Conversation history/context across turns

For text chat:


- Frontend keeps `conversationHistory` as `{role, content}` list.
- On each send, frontend passes **prior turns only** (`slice(0, -1)`) and current message
separately.
- Backend `ChatRequest` includes:
- `conversation_history`
- `message` (current turn)
- `mood`
- optional `emotion_scores`, `detected_distortions`, `mood_context`,
`one_turn_system_instruction`
- `session_message_count`
- `Therapist._build_messages()` composes:
1. base system prompt
2. optional extra system messages (`mood_context`, `one_turn_system_instruction`)
3. full prior conversation history
4. final current user message prefixed by generated system context.

For voice chat:


- `conversation_history=[]` (explicitly stateless per turn in current implementation).

---

### 7) Prompt chaining / multi-step patterns

Yes, there are multi-step orchestration patterns:

- **Parallel inference + streaming response** (`/api/chat/stream`):


- Step A: Start LLM token stream.
- Step B (parallel): run mood + distortion inference in executor.
- Step C: stream tokens immediately to client.
- Step D: after stream, emit metadata event with mood/distortion output and persist.
- **Crisis short-circuit path**:
- If crisis keywords detected, skip normal LLM generation and return crisis-safe response flow.
- **Voice pipeline** (`/api/voice-chat`):
- STT (Whisper) → mood classification (BERT) → therapist LLM response (Groq) →
TTS (gTTS), returned as JSON + base64 audio.

---

## Methodology-ready conclusion

The codebase uses a **single cloud LLM provider: Groq**, accessed through the **OpenAI
Python SDK compatibility layer**, with configurable `temperature`, `max_tokens`, and `top_p`,
and supports both **blocking and streaming** generation. Therapy behavior is governed by an
explicit CBT system prompt plus dynamic per-turn system context injections. Context
persistence is handled by passing structured prior turns every request (text mode), while voice
mode is currently stateless. The backend also composes multi-model pipelines (LLM + local
classifiers + STT/TTS), including parallel post-hoc inference metadata during streaming.

3.1.4 Database and Session Management


Analyze the database and session layer of this project and answer:
1. What database(s) are used — PostgreSQL, MongoDB, Firebase, Redis, SQLite? Show
evidence from config files or schema files.
2. What ORM or query library is used — Prisma, Drizzle, SQLAlchemy, Mongoose, raw SQL?
3. Show the full database schema — all tables/collections with field names, types, and
relationships.
4. How are user sessions managed — JWT, cookie-based sessions, NextAuth, [Link],
Redis sessions?
5. What data is persisted per user — messages, mood logs, session history, progress data?
6. Is Redis or any cache layer used? What is cached and for how long?
7. How is session continuity maintained across conversations with the AI?
Give output as a structured technical summary for a methodology chapter.

## Database and Session Layer Summary

### 1) Database technology in use (with evidence)

- **Primary database: SQLite**


- Evidence: `cbt-backend/[Link]` sets
`SQLALCHEMY_DATABASE_URL = "sqlite+aiosqlite:///./cbt_backend.db"`.
- Engine created with async SQLite driver (`aiosqlite`) and `check_same_thread=False`.
- No evidence of PostgreSQL, MongoDB, Firebase, or Redis as a persistent datastore.

Additionally:
- On startup, schema is auto-created via SQLAlchemy metadata:
- `[Link]` runs `await conn.run_sync([Link].create_all)`.

---

### 2) ORM/query library

- **ORM:** SQLAlchemy (async ORM layer)


- Declarative models in `cbt-backend/models/db_models.py`
- Async session factory via `async_sessionmaker` in `[Link]`
- Queries performed through SQLAlchemy `select(...)` in routers.
- Not Prisma / Drizzle / Mongoose / raw-SQL-centric architecture.

---

### 3) Full database schema (tables, fields, relationships)

From `cbt-backend/models/db_models.py`:

#### `users`
- `id: String` (PK, UUID string, indexed)
- `username: String` (unique, indexed, not null)
- `password_hash: String` (not null)
- `created_at: DateTime`
- Relationship:
- `users (1) -> (many) sessions`
#### `sessions`
- `id: String` (PK, UUID string, indexed)
- `user_id: String` (FK -> `[Link]`, `ondelete="SET NULL"`, nullable, indexed)
- `created_at: DateTime`
- `last_active: DateTime` (auto-updated on update)
- `metadata_json: JSON` (default `{}`)
- Relationships:
- `(many) messages` with cascade delete-orphan
- `(many) mood_logs` with cascade delete-orphan
- `(many) cbt_interventions` with cascade delete-orphan

#### `messages`
- `id: String` (PK, UUID string, indexed)
- `session_id: String` (FK -> `[Link]`, `ondelete="CASCADE"`, indexed, not null)
- `role: String` (`user` / `assistant`)
- `content: String`
- `timestamp: DateTime`
- `mood_at_time: String` (nullable)
- `is_crisis: Boolean` (default `False`)
- Widget-related optional fields:
- `widget_type: String` (nullable)
- `widget_state: String` (nullable)
- `widget_response_json: JSON` (nullable)
- Index:
- `ix_messages_session_timestamp(session_id, timestamp)`

#### `mood_logs`
- `id: String` (PK, UUID string, indexed)
- `session_id: String` (FK -> `[Link]`, `ondelete="CASCADE"`, indexed, not null)
- `mood: String` (not null)
- `confidence: Float` (not null)
- `timestamp: DateTime`
- `trigger_message: String` (nullable)
- Index:
- `ix_mood_logs_session_timestamp(session_id, timestamp)`

#### `cbt_interventions`
- `id: String` (PK, UUID string)
- `session_id: String` (FK -> `[Link]`, `ondelete="CASCADE"`, indexed, not null)
- `intervention_type: String` (not null)
- `metadata_json: JSON` (default `{}`)
- `timestamp: DateTime`
- Index:
- `ix_interventions_session_timestamp(session_id, timestamp)`

**Relational summary:**
- `users 1—N sessions`
- `sessions 1—N messages`
- `sessions 1—N mood_logs`
- `sessions 1—N cbt_interventions`

---

### 4) Session/auth management approach

- **Auth/session security model:** JWT bearer tokens (not cookie sessions)


- `[Link]` uses:
- `OAuth2PasswordBearer(tokenUrl="/api/auth/login")`
- Access token + refresh token creation via `python-jose`.
- Token characteristics:
- Access token: type `"access"`, expiry from `ACCESS_TOKEN_EXPIRE_MINUTES` (default
30).
- Refresh token: type `"refresh"`, expiry from `REFRESH_TOKEN_EXPIRE_DAYS` (default 7).
- Password storage:
- Hashed with `passlib` + bcrypt (`password_hash` in `users` table).
- No NextAuth / [Link] / server-side cookie store.

---

### 5) Persisted data per user

Per authenticated user (via linked `sessions.user_id`), the backend persists:

- **Conversation messages** (`messages`)


- User and assistant turns, timestamps, crisis flag, optional mood-at-message, optional widget
state fields.
- **Mood history** (`mood_logs`)
- Mood label, confidence, trigger message, timestamp.
- **Session metadata** (`sessions.metadata_json`)
- e.g., latest stream metadata (`mood`, `distortions`) written during streaming path.
- **CBT intervention analytics** (`cbt_interventions`)
- Intervention type + metadata payload for widgets/exercises.

Operationally, chat endpoints explicitly write:


- Session row (if missing)
- User message
- Assistant message
- Mood log

---

### 6) Redis/cache layer usage

- **Redis:** not used.


- **Cache layer:** in-process memory caches:
- `cbt-backend/models/inference_cache.py`:
- `MOOD_CACHE = LRUCache(maxsize=200)`
- `DISTORTION_CACHE = LRUCache(maxsize=200)`
- key: MD5 of normalized text prefix.
- Additional per-model LRU caches via `functools.lru_cache` in model classes.
- **TTL/expiry:** none configured; eviction is size-based (LRU), process-memory lifetime only.

---

### 7) Session continuity across AI conversations

Continuity is maintained through a combined frontend+backend pattern:

1. **Frontend thread identity**


- `src/utils/[Link]` stores active `session_id` in `localStorage` (`cbt_chat_session_id`).
- If absent, it migrates from `cbt_device_id` or creates a UUID.
- Sidebar thread list is also persisted in localStorage.

2. **Per-request continuity payload**


- Frontend sends `session_id` on each chat request (`/api/chat`, `/api/chat/stream`).
- It also sends `conversation_history` (prior turns) and `session_message_count`.

3. **Backend persistence and retrieval**


- `ensure_session_exists(...)` creates `sessions` row when first seen.
- Messages/mood logs are appended to DB under that `session_id`.
- History endpoints (`/api/history/{session_id}`, `/api/mood-history/{session_id}`) repopulate UI
when reopening a thread.

4. **Auth linkage**
- Since chat/history routes require JWT, continuity is tied to authenticated guest user +
session id.

---

## Methodology-ready conclusion
This project uses an **async SQLAlchemy + SQLite** persistence layer, with a normalized
relational schema centered on `users` and `sessions`, and longitudinal storage for `messages`,
`mood_logs`, and `cbt_interventions`. Session security is **token-based (JWT access/refresh)**
rather than cookie session middleware. Conversation continuity is preserved by a frontend-
persisted `session_id` plus backend relational session records and history replay APIs. Caching
is limited to **in-memory LRU inference caches** (no Redis, no distributed cache, no TTL
policy).

3.1.5 Development and Collaboration Tools


Based on the project configuration files, tell me:
1. What is the version control setup — Git branching strategy, .gitignore contents, any GitHub
Actions or CI/CD workflows?
2. What is the deployment setup — Vercel, Railway, Render, AWS, Docker? Show evidence
from config files ([Link], Dockerfile, [Link], etc.).
3. What environment variables are used (list keys only from .[Link] or README, not
values)?
4. What development tools are configured — ESLint, Prettier, Husky, TypeScript, Jest, Vitest?
5. Is there a README with setup instructions? Summarize it.
6. What package manager is used — npm, yarn, pnpm, bun?
Give output as a structured technical summary for a methodology chapter.

## Project Configuration Summary (Methodology-Oriented)

### 1) Version control setup (Git strategy, ignore rules, CI/CD)

**Git strategy**
- No explicit branching strategy is documented in repository config/docs (no
`[Link]`, no branch policy file found).
- Repository is Git-based (normal `.gitignore` present).

**`.gitignore` coverage**
- Root `.gitignore` excludes:
- Node artifacts: `node_modules`, `dist`, `dist-ssr`
- Logs: `*.log`, npm/yarn/pnpm debug logs
- Local/editor files: `.vscode/*` (except extensions), `.idea`, `.DS_Store`, etc.
- Backend `cbt-backend/.gitignore` excludes:
- Python/venv/build artifacts
- `.env`
- SQLite files (`*.db`, `*.sqlite3`)
- Backend logs

**CI/CD / GitHub Actions**


- No GitHub Actions workflows found (`.github/workflows` absent).
- No CI pipeline config detected in the repo.
---

### 2) Deployment setup (Vercel/Railway/Render/AWS/Docker)

No deployment target is explicitly configured in codebase-level deployment files.

**Evidence:**
- No `Dockerfile`, `[Link]`, `[Link]`, `[Link]`, `[Link]`, `Procfile`,
`[Link]`, or similar.
- README focuses on **local development** via:
- Backend: `uvicorn main:app --reload --port 8000`
- Frontend: `npm run dev`
- Convenience scripts: `[Link]`, `[Link]`, `setup_windows.bat`,
`run_windows.bat`

**Conclusion:** Current repo is configured primarily for local/dev execution, not an explicitly
codified cloud deployment pipeline.

---

### 3) Environment variables (keys only)

From `cbt-backend/.[Link]`:

- `JWT_SECRET_KEY`
- `JWT_ALGORITHM`
- `ACCESS_TOKEN_EXPIRE_MINUTES`
- `REFRESH_TOKEN_EXPIRE_DAYS`
- `GROQ_API_KEY`
- `GROQ_MODEL`
- `GROQ_BASE_URL` (commented optional)
- `LLM_TEMPERATURE` (commented optional)
- `LLM_MAX_TOKENS` (commented optional)
- `LLM_TOP_P` (commented optional)
- `LLM_CHAT_TIMEOUT_SEC` (commented optional)
- `WHISPER_MODEL_NAME`
- `HEALTH_TTS_MODE` (commented optional)
- `LOG_DIR` (commented optional)
- `LOG_LEVEL` (commented optional)
- `APP_LOG_FILE` (commented optional)
- `ERROR_LOG_FILE` (commented optional)
- `VERBOSE_STREAM_LOG` (commented optional)
---

### 4) Development tools configured

**Configured**
- **ESLint** (flat config): `[Link]`
- **TypeScript** compiler config: `[Link]`
- **Vite** build/dev tooling
- Python dependency tooling via `[Link]`

**Not configured/found**
- **Prettier** (no config/dependency found)
- **Husky** (no config/dependency found)
- **Jest** (no config/dependency found)
- **Vitest** (no config/dependency found)

---

### 5) README presence and setup summary

Yes — a substantive `[Link]` exists and includes setup/run instructions.

**README summary:**
- Describes app scope: AI-assisted CBT chat, widgets, mood adaptation, voice, music
suggestions, crisis flow.
- Documents stack: React+Vite frontend, FastAPI backend, SQLAlchemy+SQLite, local ML
models + Groq LLM.
- Provides backend setup:
- create venv
- `pip install -r [Link]`
- copy `.[Link]` to `.env`
- run `uvicorn`
- Provides frontend setup:
- `npm install`
- `npm run dev`
- Provides all-in-one launch scripts for macOS/Linux/Windows.
- Lists core frontend scripts (`dev`, `build`, `preview`, `lint`).
- Includes optional backend env preflight check (`python scripts/check_env.py`).

---

### 6) Package manager

- **Frontend package manager:** **npm**


- Evidence: `[Link]` present; README uses `npm install` and `npm run ...`.
- No `[Link]`, `[Link]`, or `[Link]` found.

---

## Methodology-ready conclusion

The repository uses a straightforward Git setup with practical ignore rules for Node/Python/local
artifacts, but does not encode a formal branching policy or CI/CD workflow. Deployment is
presently local-first (Vite + Uvicorn with helper scripts), with no explicit container or cloud
platform manifest files. Environment configuration is centralized in a backend `.[Link]`
covering auth, LLM, model/runtime, and logging controls. Development tooling includes ESLint,
TypeScript, and Vite, while Prettier/Husky/Jest/Vitest are not configured in the current project
state.

3.2 System Design and Work Flow


3.2.1 Requirement Analysis & CBT Framework Mapping
Search the codebase for all references to CBT (Cognitive Behavioral Therapy) techniques,
therapeutic concepts, or mental health logic and tell me:
1. Which specific CBT techniques are implemented — thought records, cognitive restructuring,
behavioral activation, psychoeducation, journaling, grounding exercises, etc.?
2. Where in the code are CBT concepts mapped to system behavior? (Check system prompts,
constants files, config files, or comment blocks.)
3. Are there any predefined CBT exercise templates, structured response formats, or
therapeutic scripts hardcoded in the project?
4. How does the system decide which CBT technique to apply to a given user input?
5. Is there a defined scope of mental health conditions addressed — anxiety, depression,
stress, OCD, etc.?
Give output as a structured technical summary for a methodology chapter.

## CBT and Therapeutic Logic Summary

### 1) Implemented CBT techniques and therapeutic methods

The project implements a **multi-technique CBT toolkit** through structured chat widgets and
dedicated views.

**Directly implemented techniques**


- **Thought record / cognitive restructuring**
- `THOUGHT_RECORD` widget (`ThoughtRecordWidget`) captures:
- situation
- automatic thought
- balanced thought
- **Cognitive distortion identification + reframe**
- Distortion detector (DistilBART zero-shot) identifies common distortions.
- `DISTORTION_CARD` widget asks user to rewrite a flagged thought.
- **Behavioral activation / task breakdown**
- `TASK_BOARD` widget decomposes overwhelm into sub-tasks and tracks completion.
- **Breathing-based regulation / grounding**
- `BREATHING_CIRCLE` widget implements paced box breathing (6-2-6-2 cycle).
- **Emotion labeling / affect identification**
- `EMOTION_WHEEL` widget and `MoodCheckIn` collect core emotion, sub-emotion, and
intensity.
- **Gratitude journaling / positive data logging**
- `GRATITUDE_PROMPT` widget stores gratitude entries locally.
- **Psychoeducation-like content**
- Distortion descriptions and explanations are hardcoded in detector/widget views.

**Additional supportive therapeutic features**


- Crisis escalation and safety prompts/resources (`CrisisHandler` + SOS flow).
- Mood-adaptive atmosphere/audio behavior.

---

### 2) Where CBT concepts are mapped to system behavior

**Core mapping points**


- **Therapeutic policy and pacing:** `cbt-backend/models/[Link]`
- `SYSTEM_PROMPT` defines rapport → exploration → intervention phases,
constraints, Socratic style.
- **Technique dispatch rules:** `[Link]::_widget_directive`
- Maps user text + emotion signals + session stage to specific widget directives.
- **Emotion-to-app-state mapping:** `cbt-backend/models/mood_classifier.py`
- `EMOTION_TO_MOOD` maps model emotions to app moods (`anxious`, `low-energy`,
`overwhelmed`, `neutral`).
- **Distortion taxonomy:** `cbt-backend/models/distortion_detector.py`
- `DISTORTIONS` constant defines 10 named cognitive distortions plus explanations.
- **Frontend widget system binding:** `src/components/[Link]`
- Maps widget type tokens to concrete therapeutic UI components.
- **Post-exercise conversational summaries:** `src/lib/[Link]`
- Converts completed exercise data into natural-language follow-up injected back into chat.
- **Mood-triggered side effects:** `src/lib/[Link]`
- Adds one-turn breathing nudge for high fear; routes mood scores to atmosphere switching
logic.

---

### 3) Hardcoded templates, structured formats, and scripts


Yes—substantial structure is hardcoded.

**Structured response/exercise formats**


- Mandatory ` ```widget ` JSON protocol in system prompt with strict schema:
- `TASK_BOARD`, `BREATHING_CIRCLE`, `EMOTION_WHEEL`, `DISTORTION_CARD`,
`MUSIC_CARD`, `MUSIC_SUGGESTION`, `GRATITUDE_PROMPT`, `THOUGHT_RECORD`.
- Thought record template fields (`situation`, `automaticThought`, `balancedThought`).
- Distortion detector’s hardcoded canonical list of 10 distortions and descriptions.
- Mood check-in structure: core emotion + sub-emotion + 1–10 intensity.
- Crisis response templates:
- tiered `safe_message`
- `safety_plan_prompt`
- curated hotline/resource list.

---

### 4) How the system chooses which CBT technique to apply

Technique selection is **hybrid rule-based + model-guided**:

1. **Primary orchestration in backend therapist rules (`_widget_directive`)**


- Inputs:
- current user message text
- emotion scores (especially fear/sadness)
- session message count and cooldown since last widget
- crisis keyword checks
- Decision examples:
- high fear + panic language -> breathing widget
- overwhelm/task-load language -> task board
- absolutist self-judgment -> distortion card
- sadness/anxiety + music-seeking language -> music suggestion
- Guardrails:
- no widgets in early rapport turns
- cooldown between widgets
- max widgets per session.

2. **Distortion signal path**


- Distortion model provides labels used in context and dedicated exercises.

3. **Mood inference path**


- Mood classifier outputs emotion probabilities that influence prompts/rules and UI/audio
adaptations.
4. **User-directed path**
- Toolkit lets users manually start named CBT exercises.

---

### 5) Scope of mental health conditions/themes addressed

The implemented scope is **broad emotional distress support**, with explicit emphasis on:

- **Anxiety** (fear mapping, breathing/grounding, panic cues)


- **Low mood / depressive energy states** (`low-energy` mapping, behavioral activation
framing, gratitude)
- **Overwhelm / stress burden** (`overwhelmed` mapping, task breakdown)
- **Cognitive distortions / maladaptive thinking patterns** (10-class distortion framework)
- **Crisis and suicidality risk language** (high/moderate concern tiers + safety resources)

Not explicitly modeled as diagnostic modules:


- OCD, PTSD, bipolar, psychosis, etc. are not separately represented as dedicated clinical
condition pathways in the code; logic is framed as CBT-style support and crisis triage rather
than diagnosis.

---

## Methodology-ready conclusion

The codebase operationalizes CBT through a rule-constrained conversational therapist,


structured widget protocols, and deterministic mappings from emotion/distortion signals to
intervention type. It combines model-driven inference (emotion/distortion detection), session-
aware rule logic (clinical pacing and widget cooldown), and predefined exercise templates
(thought record, reframe, breathing, task decomposition, gratitude, emotion labeling). The
mental-health scope targets anxiety, low mood, overwhelm, distortion patterns, and crisis safety
support, with non-diagnostic therapeutic guidance.

3.2.2 Conversational Flow Design & Prompt Engineering


Do a deep analysis of all prompt engineering in this project and tell me:
1. Show the full text of every system prompt, instruction block, or LLM persona definition in the
codebase.
2. How is the conversation flow structured — single-turn, multi-turn, goal-directed dialogue, or
branching paths?
3. Are there different prompt templates for different phases (e.g., intake, assessment,
intervention, closure)? Show each one.
4. How is user context injected into prompts — what variables are interpolated and from where?
5. Are there any chain-of-thought instructions, output format constraints (JSON, structured text),
or persona instructions given to the LLM?
6. Is there a fallback or reprompting mechanism if the LLM gives an unsafe or off-topic
response?
Give output as a structured technical summary for a methodology chapter.

## Prompt Engineering Deep Analysis

### 1) Full text of every LLM-facing system prompt / instruction block

I found one primary persona prompt plus several dynamic instruction templates injected as extra
system/user context.

### A) Primary persona/system prompt (`cbt-backend/models/[Link]`)

```text
You are a warm, compassionate CBT therapist AI. You can render interactive UI widgets in chat
when they truly help — most of the time, conversation alone is enough.

CLINICAL PACING RULES — FOLLOW STRICTLY:

PHASE 1 — RAPPORT (first 2 exchanges):


- Just listen and reflect. No widgets. No exercises.
- Use open questions: "Tell me more about that."
- Validate the emotion without rushing to fix it.
- Example: "That sounds really exhausting. How long have you been carrying this?"

PHASE 2 — EXPLORATION (exchanges 3-5):


- Dig deeper into the specific situation.
- Identify the core thought or belief driving the distress.
- ONE widget maximum if clearly needed.
- Do not stack exercises.

PHASE 3 — INTERVENTION (exchange 6+):


- Now introduce structured CBT tools if appropriate.
- Still maximum 1 widget per response.
- Always debrief after an exercise before moving on.
- If user just completed a widget, ask about their experience BEFORE offering another one.

ABSOLUTE RULES:
- Never show a widget in two consecutive responses
- Never show more than 3 widgets in one full session
- If the user seems frustrated or disengaged, stop exercises and just talk
- Always finish the session with reflection, not an exercise

CONVERSATIONAL STYLE RULES — FOLLOW STRICTLY:


- Ask only ONE question per response. Never ask two or more questions in the same message.
- Always put the question at the END of your response, never at the beginning or middle.
- Lead with acknowledgement and validation first, then gently explore with a single focused
question.
- Use simple, warm, plain language. Avoid clinical or technical therapy terms.
- Keep responses concise — 3 to 5 sentences maximum unless the situation genuinely requires
more.
- Mirror the emotional weight of the user's message. If they are in deep distress, be gentle and
slow. Do not rush to problem-solving.
- Never give a list of suggestions or coping strategies in one message. Introduce one idea at a
time.

WIDGET JSON PROTOCOL (only when appropriate under the rules above):
Output widgets using a fenced code block with the language tag exactly `widget` (three
backticks, then the word widget, newline), then a single JSON object, then closing three
backticks on their own line.

Schema:
```widget
{"type":"TASK_BOARD"|"BREATHING_CIRCLE"|"EMOTION_WHEEL"|"DISTORTION_CARD"|
"MUSIC_CARD"|"MUSIC_SUGGESTION"|"GRATITUDE_PROMPT"|"THOUGHT_RECORD","p
ayload":{...}}
```

RULES:
- Never render more than 1 widget per response
- Always include a warm short text message BEFORE the widget
- Always include a brief follow-up text message AFTER the widget
- Keep your text SHORT when a widget is present — the widget does the work
- Never put markdown inside JSON string values. Use valid JSON only.
```

### B) Dynamic context template added to current user turn


(`therapist._format_system_context`)

```text
[System Context: The user is currently feeling {mood}. Tailor your CBT intervention specifically
to this emotional state. Possible cognitive distortion patterns to consider for this message:
{listed_distortions}. Draw on relevant CBT frameworks without labeling or shaming the user.]
```

(Second sentence appears only if distortion labels are provided.)

### C) Rule-triggered directive templates (`therapist._widget_directive`)


These are appended into the context when rules match:

1. **Acute anxiety directive**


```text
WIDGET_DIRECTIVE: You MUST start your reply with a ```widget``` JSON block with
{"type":"BREATHING_CIRCLE","payload":{"technique":"4-7-8","cycles":2}} because both the
user's words and emotion signal strong acute anxiety. Then add a short validating sentence.
```

2. **Overwhelm/task directive**
```text
WIDGET_DIRECTIVE: You MUST start your reply with a ```widget``` JSON block with
{"type":"TASK_BOARD","payload":{"title":"Break down what feels overwhelming"}} tailor the title
to their situation. Then add one supportive sentence.
```

3. **Cognitive reframe directive**


```text
WIDGET_DIRECTIVE: You MUST start your reply with a ```widget``` JSON block with
{"type":"DISTORTION_CARD","payload":{"flaggedText":"<short exact phrase from user>"}} use
their wording in flaggedText. Then add one gentle reflective sentence.
```

4. **Music regulation directive**


```text
WIDGET_DIRECTIVE: You MUST include a ```widget``` JSON block with
{"type":"MUSIC_SUGGESTION","payload":{"mood":"anxious|low-energy"}} in your reply. Add a
short gentle sentence before and after the widget.
```

### D) Optional one-turn system nudge from frontend helper (`src/lib/[Link]`)

```text
Start your response with a ```widget``` JSON block using type BREATHING_CIRCLE (e.g.
technique 4-7-8, cycles 2). Include warm text before and after the widget per your rules.
```

Note: `[Link]` currently sets `oneTurnExtra = null`, so this appears implemented but not
actively passed in current flow.

---

### 2) Conversation flow structure


The chat is **multi-turn, session-based, and partially goal-directed**:

- Multi-turn context is sent every request via `conversation_history`.


- The prompt enforces phased progression: **rapport -> exploration -> intervention**.
- Widget interventions are **branching**, triggered by rule-based conditions (fear keywords,
overwhelm language, absolute self-judgment, sadness/music cues).
- Streaming mode (`/api/chat/stream`) delivers token-by-token output + post-stream metadata.

So this is not single-turn QA; it is a **stateful therapeutic dialogue with phase-aware


branching**.

---

### 3) Different prompt templates by phase

Yes, phases exist inside one master system prompt (not separate files/templates):

- **Phase 1: Rapport** (first 2 exchanges)


- **Phase 2: Exploration** (exchanges 3-5)
- **Phase 3: Intervention** (exchange 6+)

Additionally, operational sub-templates:


- dynamic mood/distortion context line
- widget directives selected by rules
- optional one-turn system instruction
- optional mood_context system message from client

---

### 4) User context injection: variables and sources

Prompt context is built in `therapist._build_messages()` from:

- `conversation_history` (prior `{role, content}` turns) from frontend state / DB history


- `mood` (current app mood)
- `distortions` (detected distortion names)
- `emotion_scores` (BERT probabilities, e.g., fear/sadness) for directive logic
- `session_message_count` (used for phase gating / cooldown)
- `mood_context` (optional hidden system note from frontend)
- `one_turn_system_instruction` (optional temporary system nudge)

Assembly order:
1. base `SYSTEM_PROMPT`
2. optional `mood_context` as `role=system`
3. optional `one_turn_system_instruction` as `role=system`
4. prior conversation history
5. current user message prefixed with generated system context (+ optional
`WIDGET_DIRECTIVE`)

---

### 5) Chain-of-thought, output constraints, persona instructions

**Persona instructions:** strong and explicit (warm CBT therapist, Socratic style, pacing, safety
tone).

**Output constraints:** very explicit:


- one question max
- sentence-length/style constraints
- no widget overuse constraints
- strict fenced widget JSON protocol with fixed `type` enum
- include short text before and after widget
- valid JSON only in widget block

**Chain-of-thought:** no explicit “show reasoning” instructions.


Model is guided behaviorally but not asked to reveal internal reasoning.

---

### 6) Fallback / reprompting for unsafe or off-topic outputs

There is **safety and robustness handling**, but **no explicit reprompt loop**:

- **Crisis short-circuit**: if crisis keywords match, therapist call is bypassed and crisis-safe
response is used.
- **Widget JSON sanitization**: invalid widget JSON fences are stripped
(`_validate_widget_json`), preventing malformed structured output.
- **Low-quality/empty output fallback**: if reply is empty/too short, backend substitutes a generic
supportive sentence.
- **Timeout fallback**: returns “taking longer than usual” message.
- **Frontend network/stream failures**: frontend inserts fallback supportive responses.

What is *not* present:


- no separate moderation model pass
- no automatic “reprompt model with stricter instruction” retry for off-topic content
- no structured unsafe-response classifier beyond crisis keyword logic and prompt guardrails
---

## Methodology conclusion

This project uses a **single, highly constrained CBT persona prompt** plus **dynamic context
and rule-triggered directive injection** to shape intervention selection. Dialogue management is
**multi-turn and phase-aware**, with deterministic gating (message count, cooldown, crisis
checks, emotion-score thresholds) layered on top of LLM generation. Output format control is
strong for widget rendering (fenced JSON contract), while safety control is primarily prompt/rule-
based with crisis short-circuiting and fallback messaging rather than iterative reprompting or
external moderation orchestration.

3.2.3 Mood Assesment & Cognitive Distortion Detection via LLM


Analyze the codebase for all mood tracking, sentiment analysis, and cognitive distortion
detection logic and tell me:
1. How is the user's mood assessed — through explicit user input (scales, sliders), LLM
inference from text, or both?
2. Is there a mood scoring mechanism? What scale or schema is used?
3. Does the system detect cognitive distortions (e.g., catastrophizing, black-and-white thinking,
mind reading)? Where and how is this done?
4. Is the LLM prompted to classify mood or distortions? Show the exact prompt used for this
classification.
5. How are mood assessment results stored and used downstream in the conversation?
6. Are there any structured output formats (JSON) returned by the LLM for mood/distortion
data? Show the schema.
Give output as a structured technical summary for a methodology chapter.

## Mood, Sentiment, and Distortion Analysis Summary

### 1) How mood is assessed

The system uses **both explicit user input and model inference**.

- **Explicit input (self-report):**


- `MoodCheckIn` + emotion wheel collects:
- `coreId` / `coreLabel`
- `subEmotion`
- `intensity` (slider 1–10)
- **Model inference from text/audio:**
- Backend `MoodClassifier` (BERT model: `bhadresh-savani/bert-base-uncased-emotion`)
classifies text to emotion probabilities and mapped app mood.
- In voice flow, transcription is passed to same classifier (`voice_chat.py`).

So mood tracking is hybrid: **self-reported affect + automated NLP inference**.


---

### 2) Mood scoring mechanism (scale/schema)

There are multiple mood schemas:

- **Classifier schema (backend):**


- `mood` (categorical app mood: `neutral | anxious | low-energy | overwhelmed`)
- `emotion` (raw BERT top emotion)
- `confidence` (0.0–1.0)
- `all_scores` (probability distribution over model emotions)

- **User intensity scale (frontend):**


- Slider `1..10` with labels `Mild`, `Moderate`, `Intense`.

- **Dashboard derived numeric mood score (frontend analytics):**


- `neutral: 7`, `anxious: 4`, `low-energy: 3`, `overwhelmed: 2`
- Used for trend visualization and score aggregation, not as backend clinical ground truth.

---

### 3) Cognitive distortion detection (where/how)

Yes, distortion detection is implemented explicitly.

- **Where:**
- Model logic: `cbt-backend/models/distortion_detector.py`
- Endpoint: `POST /api/detect-distortions` in `cbt-backend/routers/[Link]`
- UI exercise: `src/views/[Link]`
- **How:**
- Hugging Face zero-shot classifier (`valhalla/distilbart-mnli-12-3`)
- Candidate label set is a hardcoded list of 10 CBT distortions:
- catastrophizing
- all-or-nothing thinking
- overgeneralization
- mind reading
- fortune telling
- emotional reasoning
- should statements
- labeling
- personalization
- discounting the positive
- Multi-label scoring with confidence threshold (`CONFIDENCE_THRESHOLD = 0.45` in model
class; router comments mention 0.5, but code threshold lives in model).

---

### 4) Is LLM prompted to classify mood/distortions? Exact prompt?

**No.** Mood and distortion classification are **not performed by the LLM** in this codebase.

- Mood classification uses BERT classifier directly.


- Distortion detection uses DistilBART zero-shot classifier directly.
- There is **no explicit natural-language prompt string** sent to an LLM for classification.

Effective classifier input for distortion detector is:


- premise = user text
- candidate labels = the 10 distortion names above
- `multi_label=True`

(Template/hypothesis formatting is internal to Hugging Face zero-shot pipeline and not custom-
defined in project code.)

---

### 5) How results are stored and used downstream

**Storage**
- `mood_logs` table stores:
- `session_id`, `mood`, `confidence`, `timestamp`, `trigger_message`
- `messages.mood_at_time` is set for user messages (and updated with inferred mood in
streaming path)
- Session metadata (`sessions.metadata_json`) stores:
- `last_stream_metadata: { mood, distortions }`

**Downstream use**
- Chat UI:
- Receives streaming metadata event (`type: "metadata"`) with `mood` + `distortions`
- Updates message metadata and app mood state when confidence is sufficient.
- Therapist behavior:
- Chat requests include optional `emotion_scores`, `detected_distortions`, `mood_context`
- These influence intervention/widget choice in backend prompt construction.
- Dashboard:
- Reads `/api/mood-history/{session_id}` and visualizes trends/heatmap.

---
### 6) Structured output formats (JSON) returned by LLM for mood/distortion data

For **mood/distortion data specifically**:


- **Not from LLM**. These are returned by backend model endpoints / metadata pipeline.

**Schemas used:**

- `MoodResponse`:
- `mood: str`
- `emotion: str`
- `confidence: float`
- `all_scores: dict`
- `message: str`

- `DistortionResponse`:
- `distortions: List[{ name: str, description: str, confidence: float }]`
- `count: int`
- `message: str`

- Stream metadata event (`/api/chat/stream`):


- `{ type: "metadata", mood: object|null, distortions: string[], done: false }`

Note: The LLM does have a separate JSON protocol for chat widgets (` ```widget { ... } ``` `), but
that is **intervention UI control**, not mood/distortion classification output.

3.2.4 Therapeutic Response Generation & CBT Exercise Delivery


Analyze how the system generates therapeutic responses and delivers CBT exercises and tell
me:
1. What is the pipeline from user input to therapeutic response? Trace the full call chain.
2. How does the system select and deliver a CBT exercise — rule-based, LLM-decided, or user-
initiated?
3. Are CBT exercises structured as multi-step interactions? Show any exercise templates or
flows.
4. How does the LLM know to stay therapeutic and not give generic responses? What
instructions enforce this?
5. Is there psychoeducational content delivered to the user? Where is it stored or generated?
6. How does the system handle user responses during an exercise — does it adapt based on
replies?
Give output as a structured technical summary for a methodology chapter.

## Therapeutic Response & CBT Delivery Methodology


### 1) Pipeline: user input → therapeutic response (full call chain)

**Client-side (text chat path)**


1. User submits text in `ChatInputWithHighlights`, handled by `[Link]`.
2. `ChatView` appends the user message locally, builds `conversationHistory`, and calls
`streamChat(...)` (SSE).
3. `streamChat` posts to `/api/chat/stream` with `message`, `mood`, `session_id`,
`conversation_history`, and optional context fields.
4. SSE tokens stream back; frontend incrementally parses assistant output and converts widget
fences into structured widget messages.
5. `TherapeuticFeed` renders text bubbles and widget components from parsed assistant
segments.

```366:430:src/views/[Link]
const sendUserMessage = useCallback(
async (userText) => {
const trimmed = [Link]();
if (!trimmed || isStreaming) return;
// ...
await streamChat(
trimmed,
moodForChat,
sessionId || getActiveChatSessionId(),
historyForApi,
emotionScores,
moodContextPayload,
oneTurnExtra,
```

```172:203:src/services/[Link]
export async function streamChat(
message,
mood,
sessionId,
conversationHistory,
emotion_scores,
mood_context,
one_turn_system_instruction,
onToken,
onCrisis,
onDone,
onMetadata,
onError
){
try {
const body = {
message,
mood,
session_id: sessionId,
conversation_history: conversationHistory,
session_message_count: conversationHistory?.length ?? 0,
};
```

**Server-side (streaming endpoint)**


1. `POST /api/chat/stream` in `[Link]` authenticates and deserializes `ChatRequest`.
2. Crisis pre-check via `therapist._check_crisis([Link])`.
3. Non-crisis: calls `therapist.chat_stream(...)`; crisis: bypasses LLM and emits crisis-safe
content.
4. Persists user message + mood log pre-stream; assistant message and metadata post-
stream.
5. Returns SSE with token events + metadata + done.

```156:188:cbt-backend/routers/[Link]
@[Link]("/chat/stream")
@[Link]("20/minute")
async def chat_stream(
request: Request,
payload: ChatRequest,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)
):
# ...
is_crisis = therapist._check_crisis([Link])
history = [{"role": [Link], "content": [Link]} for m in payload.conversation_history]
```

**LLM invocation layer**


- `[Link]()` / `Therapist.chat_stream()` build message stack and call Groq OpenAI-
compatible chat completions.
- System prompt + optional dynamic system context + history + current user turn are assembled
in `_build_messages`.

```297:337:cbt-backend/models/[Link]
def _build_messages(
self,
user_message: str,
mood: str,
conversation_history: list[dict],
distortions: list[str] | None = None,
emotion_scores: dict[str, float] | None = None,
mood_context: str | None = None,
one_turn_system_instruction: str | None = None,
session_message_count: int = 0,
) -> list[dict]:
system_msg = {"role": "system", "content": self.SYSTEM_PROMPT}
messages: list[dict] = [system_msg]
# ... append optional system nudges + history ...
[Link]({"role": "user", "content": f"{ctx}\n\n{user_message}"})
```

---

### 2) CBT exercise selection/delivery: rule-based, LLM-decided, or user-initiated?

**Hybrid architecture (rule + model + UI trigger):**

- **Rule-based backend gating/directives:** `_widget_directive()` in `[Link]` applies


deterministic rules (session stage, cooldown, emotion thresholds, keywords, crisis exclusion)
and injects `WIDGET_DIRECTIVE`.
- **LLM-decided content formatting:** model still generates final therapeutic text + widget JSON
block.
- **Frontend delivery is declarative:** frontend does not choose intervention heuristically at
render time; it parses ` ```widget ... ``` ` and dispatches to registered widget component.
- **User-initiated path exists:** `injectBreathing` can explicitly add a breathing widget from UI
flow.

```185:227:cbt-backend/models/[Link]
def _widget_directive(
self,
user_message: str,
emotion_scores: dict[str, float] | None,
session_message_count: int = 0,
messages_since_last_widget: int = 99,
) -> str:
if session_message_count < 4:
return ""
if messages_since_last_widget < 6:
return ""
# ...
if fear > 0.75 and anxiety_keywords:
return (
"WIDGET_DIRECTIVE: You MUST start your reply with a ```widget``` JSON block with "
'{"type":"BREATHING_CIRCLE","payload":{"technique":"4-7-8","cycles":2}} '
```

```13:26:src/components/[Link]
export const WIDGET_REGISTRY: Record<
WidgetType,
FC<WidgetProps> | undefined
>={
TASK_BOARD: TaskBoardWidget,
BREATHING_CIRCLE: BreathingWidget,
BREATHING_EXERCISE: BreathingWidget,
EMOTION_WHEEL: EmotionWheelWidget,
DISTORTION_CARD: DistortionCardWidget,
MUSIC_CARD: MusicCardWidget,
MUSIC_SUGGESTION: MusicSuggestionWidget,
GRATITUDE_PROMPT: GratitudeWidget,
THOUGHT_RECORD: ThoughtRecordWidget,
};
```

---

### 3) Are CBT exercises multi-step interactions? Templates/flows

Yes. Exercises are implemented as interactive stateful widgets (not one-shot static cards).
Examples:

- `BreathingWidget`: duration selection → guided timed breathing phases →


completion callback.
- `TaskBoardWidget`: compose tasks/subtasks and mark completion.
- `EmotionWheelWidget`: choose emotion/subemotion/intensity flow.
- `DistortionCardWidget`: cognitive reframe entry and save.
- `ThoughtRecordWidget` and `GratitudeWidget`: structured form-based completion.
- `MusicSuggestionWidget` / `MusicCardWidget`: action-triggered completion.

```8:13:src/components/widgets/[Link]
const PHASES = [
{ label: 'Inhale slowly...', side: 'top', duration: 6 },
{ label: 'Hold...', side: 'right', duration: 2 },
{ label: 'Exhale gently...', side: 'bottom', duration: 6 },
{ label: 'Hold...', side: 'left', duration: 2 },
] as const;
```
```113:127:src/components/widgets/[Link]
useEffect(() => {
if (finished && ![Link]) {
[Link] = true;
logCBTIntervention('BREATHING', {
technique: 'box-6-2-6-2',
rounds: totalRounds,
durationSeconds: selectedDuration,
});
onComplete({
technique: 'box-6-2-6-2',
cyclesCompleted: totalRounds,
durationSeconds: selectedDuration,
});
}
}, [finished, totalRounds, selectedDuration, onComplete]);
```

---

### 4) How the LLM is constrained to remain therapeutic (vs generic)

Primary control is prompt governance in `Therapist.SYSTEM_PROMPT`, which includes:

- Phase-based clinical pacing (rapport → exploration → intervention).


- Hard limits on exercise frequency and sequencing.
- Conversational behavior constraints (one question max, ask at end, concise, empathic style).
- Widget protocol constraints (single widget per response, valid JSON, text before/after widget).

```45:76:cbt-backend/models/[Link]
SYSTEM_PROMPT = '''You are a warm, compassionate CBT therapist AI...
CLINICAL PACING RULES — FOLLOW STRICTLY:
PHASE 1 — RAPPORT (first 2 exchanges):
- Just listen and reflect. No widgets. No exercises.
...
ABSOLUTE RULES:
- Never show a widget in two consecutive responses
- Never show more than 3 widgets in one full session
...
CONVERSATIONAL STYLE RULES — FOLLOW STRICTLY:
- Ask only ONE question per response.
- Always put the question at the END of your response
```
Additional non-prompt controls:
- Crisis keyword short-circuit in `Therapist._check_crisis`.
- Crisis-safe response override from `CrisisHandler` when needed.

---

### 5) Psychoeducational content: stored or generated?

- **Mostly generated dynamically** by the LLM under therapeutic system instructions; no


dedicated psychoeducation content repository/template bank was found.
- **Static curated content does exist for crisis resources** in `[Link]`,
delivered via crisis handling and crisis endpoints.

```15:24:cbt-backend/models/crisis_handler.py
[Link] = [
{
"name": "iCall (India) - Tata Institute of Social Sciences",
"phone": "9152987821",
"text": "N/A",
"website": "[Link]
"available_hours": "Mon–Sat, 8am–10pm IST",
"description": "Free, confidential psychosocial support for individuals in distress across
India.",
},
```

---

### 6) Handling user replies during exercise and adaptation behavior

**Current behavior is adaptive, but mostly through text/history, not structured exercise state on
backend.**

- Widget completion callback chain: widget `onComplete` → `TherapeuticFeed` →


`[Link]`.
- `handleWidgetComplete` stores widget completion in local state and **converts completion
into a synthetic natural-language user message** via `summarizeWidgetCompletion(...)`, then
sends that text to backend as next turn.
- Backend adapts via conversation history + emotion/distortion context + widget pacing counters
inferred from assistant content.
- `ChatRequest.widget_response` exists in schema but is not consumed in chat route/model
path (no active structured backend handling observed).
```514:523:src/views/[Link]
const handleWidgetComplete = useCallback(
(messageId, response) => {
const msg = [Link]().[Link]((m) => [Link] === messageId);
if (!msg?.widget) return;
const wType = [Link];
updateMessageWidget(messageId, { state: 'completed', response });
logCBTIntervention(interventionLogType(wType), { response, widgetType: wType });
const summary = summarizeWidgetCompletion(wType, response);
void sendUserMessage(summary);
},
```

```68:87:cbt-backend/models/[Link]
class ChatRequest(BaseModel):
message: str
mood: str = "neutral"
conversation_history: List[HistoryMessage] = []
# ...
one_turn_system_instruction: Optional[str] = None
# Completed widget data to pass back as context for the next model turn
widget_response: Optional[dict] = None
```

---

## Methodological Conclusion

- The system uses a **prompt-governed therapeutic LLM pipeline with deterministic


safety/intervention scaffolding**.
- CBT exercises are delivered through a **widget protocol embedded in assistant output**, then
rendered by frontend registry dispatch.
- Exercise selection is **hybrid**: backend rule heuristics + model realization + occasional UI-
triggered insertion.
- Interaction is **multi-step at UI level** with rich widget state, but backend adaptation currently
relies primarily on **textual summaries and conversation history**, not a fully structured
exercise-state feedback loop.

3.2.5 User Authentication, Session Continuity & Progress Tracking


Analyze the authentication and user progress system and tell me:
1. How is user authentication implemented — email/password, OAuth (Google, GitHub), magic
link, or other? Which library handles it?
2. What happens when a new user registers — what data is collected and stored?
3. How are therapy sessions defined and stored — by date, by conversation ID, by topic?
4. What progress metrics are tracked per user — mood trends, session count, exercise
completion, distortion frequency?
5. Is there a dashboard or profile page showing user progress? What data does it display?
6. How is session state maintained during an active conversation — localStorage, server-side
session, DB?
7. What happens when a user returns after a gap — does the system recall previous context?
Give output as a structured technical summary for a methodology chapter.

## Authentication and User Progress System (Methodology Summary)

### 1) Authentication model and library stack

- **Auth type:** custom `username + password` with JWT bearer tokens; no OAuth, no magic
link, no email-based identity in current schema.
- **Backend security stack:** `passlib` (`CryptContext` + bcrypt) for password hashing, `python-
jose` for JWT signing/verification, FastAPI `OAuth2PasswordBearer` for bearer extraction.
- **Token model:** short-lived access token + longer refresh token; both JWTs contain `sub`
and `type` claims.

```245:257:cbt-backend/models/[Link]
class UserCreate(BaseModel):
username: str
password: str

class UserLogin(BaseModel):
username: str
password: str

class TokenResponse(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
```

```23:27:cbt-backend/[Link]
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/login")
```

---

### 2) New-user registration flow: collected and stored data


- **API:** `POST /api/auth/register`.
- **Input collected:** `username`, `password`.
- **Storage behavior:**
- checks username uniqueness,
- hashes password,
- stores `User(username, password_hash)`.
- **DB fields in `users`:** `id`, `username`, `password_hash`, `created_at`.
- **Post-registration response:** returns access + refresh JWTs (no profile enrichment at
registration).

```22:41:cbt-backend/routers/[Link]
@[Link]("/register", response_model=TokenResponse)
async def register_user(user_in: UserCreate, db: AsyncSession = Depends(get_db)):
result = await [Link](select(User).where([Link] == user_in.username))
# ...
hashed_password = get_password_hash(user_in.password)
new_user = User(username=user_in.username, password_hash=hashed_password)
```

---

### 3) Therapy session definition and storage

- **Session identity:** conversation-level `session_id` (UUID/string), not topic-based.


- **Persistence entity:** `Session` table with `id`, `user_id`, `created_at`, `last_active`,
`metadata_json`.
- **Message linkage:** each message row references `session_id`; sessions hold chronological
chat logs.
- **Temporal dimension:** timestamps on session, message, mood logs; history APIs sort by
timestamp.
- **Session semantics:** effectively “chat thread / conversation ID.”

```30:45:cbt-backend/models/db_models.py
class Session(Base):
__tablename__ = "sessions"
id = Column(String, primary_key=True, index=True, default=lambda: str(uuid.uuid4()))
user_id = Column(String, ForeignKey("[Link]", ondelete="SET NULL"), nullable=True,
index=True)
created_at = Column(DateTime, default=_utc_now)
last_active = Column(DateTime, default=_utc_now, onupdate=_utc_now)
metadata_json = Column(JSON, default={})
```

---
### 4) Progress metrics tracked per user

**Tracked in backend DB**


- **Messages:** role/content/timestamp, mood-at-time, crisis flag.
- **Mood trajectory:** `MoodLog` rows with mood, confidence, timestamp, trigger_message.
- **CBT activity model present:** `CBTIntervention` table (`intervention_type`, `metadata_json`,
timestamp).

**Tracked/derived in frontend analytics**


- **Intervention counts and badges:** from local `cbt_interventions` log (`logIntervention` path),
used for weekly wins and stacked intervention chart.
- **Mood trend chart:** from backend mood logs.
- **Energy/anxiety:** derived proxies from mood class in dashboard transform functions (not
separate backend measures).
- **Distortion frequency:** no dedicated longitudinal distortion table; distortion output appears in
stream metadata/session metadata, not exposed as first-class trend API.

```57:83:cbt-backend/models/db_models.py
class Message(Base):
role = Column(String, nullable=False)
content = Column(String, nullable=False)
timestamp = Column(DateTime, default=_utc_now)
mood_at_time = Column(String, nullable=True)
is_crisis = Column(Boolean, default=False)
widget_type = Column(String, nullable=True)
widget_state = Column(String, nullable=True)
widget_response_json = Column(JSON, nullable=True)
```

```93:107:cbt-backend/models/db_models.py
class MoodLog(Base):
mood = Column(String, nullable=False)
confidence = Column(Float, nullable=False)
timestamp = Column(DateTime, default=_utc_now)
```

---

### 5) Dashboard/profile surfaces and displayed progress data

- **User-facing progress page exists:** `DashboardView` (“Insights” tab).


- **Displayed content:**
- weekly wins summary (reframes, breathing, task breakdown counts),
- milestone badges,
- interventions chart (last 7 days),
- 7-day mood trend (mood/energy/anxiety),
- 30-day check-in heatmap,
- stats cards (`Current Streak`, `Sessions This Week`, `Exercises Done`, `Avg. Mood Score`).
- **Important methodological note:** `STATS` values are currently hardcoded constants, while
charts and weekly summaries are data-driven.

```224:229:src/views/[Link]
const STATS = [
{ label: 'Current Streak', value: '5 days', icon: '🔥', change: '+2' },
{ label: 'Sessions This Week', value: '12', icon: '💬', change: '+4' },
{ label: 'Exercises Done', value: '8', icon: '🧘', change: '+3' },
{ label: 'Avg. Mood Score', value: '6.8', icon: '📊', change: '+1.2' },
];
```

---

### 6) Active conversation session-state maintenance

- **Frontend local state:** active chat session ID in `localStorage` (`cbt_chat_session_id`),


saved session list in `cbt_saved_chat_sessions`.
- **Auth persistence:** persistent device ID (`cbt_device_id`) in `localStorage`; token itself kept
in-memory and reissued on app load via anonymous register/login strategy.
- **Server-side persistence:** chat and mood history in DB tables keyed by `session_id`.
- **In-turn context:** frontend sends `conversation_history` with each chat request; backend
does not hold opaque server-side conversation memory per token session.

```5:14:src/utils/[Link]
export const CHAT_SESSION_STORAGE_KEY = 'cbt_chat_session_id';
export function getActiveChatSessionId() {
let sid = [Link](CHAT_SESSION_STORAGE_KEY);
if (sid) return sid;
const deviceId = [Link]('cbt_device_id');
if (deviceId) {
[Link](CHAT_SESSION_STORAGE_KEY, deviceId);
return deviceId;
}
```

---

### 7) Return-after-gap behavior (context recall)


- **Yes, context is recalled** for text chat sessions when returning:
- frontend resolves prior `session_id` from local storage,
- calls `GET /api/history/{session_id}` and `GET /api/mood-history/{session_id}`,
- rehydrates chat feed and dashboard visualizations.
- **Recall scope:** by selected session/thread, not a global user memory profile.
- **Voice caveat:** voice endpoint currently uses stateless per-turn processing
(`conversation_history=[]` in voice route), so it does not carry historical dialogue context.

```14:30:cbt-backend/routers/[Link]
@[Link]("/history/{session_id}", response_model=HistoryResponse)
async def get_session_history(...):
result = await [Link](
select(Message)
.where(Message.session_id == session_id)
.order_by([Link]())
)
```

---

## Methodological interpretation

The system implements **thread-centric therapeutic continuity** rather than identity-rich account
continuity. Authentication is minimal (username/password JWT), while longitudinal therapeutic
state is primarily reconstructed from persisted session artifacts (`messages`, `mood_logs`) and
supplemented by client-side intervention analytics. This yields reliable within-thread recall and
usable progress visualizations, but cross-session/cross-device personalization and fully server-
side aggregated progress remain partial in the current architecture.

3.2.6 Frontend UI/UX Design for empathetic engagement


Analyze the frontend UI/UX design decisions in this project and tell me:
1. What is the overall visual design language — color palette, typography, spacing system?
(Check Tailwind config, CSS variables, or theme files.)
2. What design choices were made to create an empathetic, calming interface (e.g., soft colors,
gentle animations, non-clinical language)?
3. How is the chat interface structured — show the main chat component's structure and key
props/state.
4. Are there any animated or interactive elements designed to reduce user anxiety or build
rapport?
5. How is the app made accessible — ARIA labels, keyboard navigation, screen reader
support?
6. Is the app responsive/mobile-friendly? What breakpoints or responsive strategies are used?
7. Are there any loading states, typing indicators, or feedback mechanisms during AI response
generation?
Give output as a structured technical summary for a methodology chapter.

## Frontend UI/UX Methodology Analysis

### 1) Visual design language (palette, typography, spacing)

- **Theme architecture:** tokenized design system in `src/[Link]` using CSS variables (`--
color-bg`, `--color-accent`, `--color-text-*`, etc.), with mood/theme variants via `[data-mood="..."]`
and `[data-theme="dark"]`.
- **Mood-adaptive palette:** distinct semantic palettes for `neutral`, `anxious` (cool cyan), `low-
energy` (warm amber), and `overwhelmed` (soft violet), all mapped to reusable utility tokens.
- **Typography:** Inter is the global typeface (`body { font-family: 'Inter'... }`), with consistent
hierarchy (`text-2xl` titles, `text-sm` section labels, `text-xs` supportive/meta copy).
- **Spacing system:** consistent utility rhythm (`p-4/5/6`, `gap-2/3/4`, `space-y-*`), rounded card
language (`rounded-xl/2xl`), and restrained borders/shadows for a soft interface.

---

### 2) Empathetic/calming UI decisions

- **Soft visual tone:** translucent surfaces, gentle gradients, rounded geometry, low-contrast
borders, and non-harsh color contrast.
- **Non-clinical language:** copy in widgets and views uses supportive everyday phrasing (“one
step at a time”, affirming reframing feedback) instead of technical therapeutic jargon.
- **Mood-sensitive theming:** `MoodContext` sets `data-mood`/`data-theme` on document root
so the whole interface shifts tone based on emotional context.
- **Crisis-aware UX:** dedicated crisis path (`SOSModal`) with high-visibility but controlled
danger styling and clear support actions.

---

### 3) Chat interface structure (main components, props/state)

- **Orchestrator component:** `ChatView` manages chat lifecycle, sessions, streaming state,


crisis flow, and modal state.
- **Rendering layer:** `TherapeuticFeed` displays text bubbles, widgets, completion chips, and
typing indicators.
- **Input layer:** `ChatInputWithHighlights` handles message input, distortion highlighting, send
behavior, and keyboard interaction.
- **Dynamic exercise composition:** widgets are resolved through `WidgetRegistry` by backend-
provided widget type.
- **Core state in `ChatView`:** `sessionId`, `savedSessions`, `input`, `isTyping`, `isStreaming`,
`thinkingHint`, `sidebarOpen`, `showVoice`, `showSOS`, `crisisData`.

---

### 4) Animated/interactive rapport/anxiety-reducing elements

- **Breathing intervention UX:** guided timed breathing with phase progression, countdown,
start/pause/resume/restart, and supportive completion feedback (`BreathingWidget`).
- **Motion language:** framer-motion is used across feed/cards/modals with short, gentle easing
and spring transitions.
- **Streaming reassurance cues:** typing dots, “Thinking...” hint, and streaming cursor reduce
perceived silence during model latency.
- **Interactive therapeutic widgets:** task breakdown, emotion wheel, thought reframing,
gratitude/thought record, and music suggestions provide actionable regulation tools.
- **Reduced-motion support:** `prefers-reduced-motion` handling exists globally, plus widget-
level checks in breathing flow.

---

### 5) Accessibility implementation

- **Positive patterns:**
- ARIA labels on key controls (e.g., close panel, close widget).
- Keyboard handling for send (`Enter`), multiline (`Shift+Enter`), and panel escape (`Escape`).
- Some visible focus treatments (`focus-visible:ring-*`).
- `role="alert"` used for error communication in voice flow.
- **Gaps observed:**
- Some icon-only controls appear to rely on icon/title without consistent `aria-label`.
- Chat textarea lacks explicit programmatic label in places (placeholder-only guidance).
- Global transition rules may affect perceived accessibility for some users.

---

### 6) Responsiveness/mobile strategy

- **Responsive shell:** `ChatView` uses breakpoint-aware sidebar behavior (desktop persistent,


mobile off-canvas with overlay and slide-in/out).
- **Utility breakpoint usage:** `sm`, `md`, `lg` classes across spacing/layout grids (`px-4 sm:px-
6`, responsive column grids, mobile toggles).
- **Mobile chat ergonomics:** overlay dismiss behavior, compact control layout, and bounded
input auto-resize improve small-screen usability.
- **Feed ergonomics:** message bubble widths capped differently across breakpoints for
readable line length.
---

### 7) Loading/typing/feedback during AI generation

- **Authentication startup feedback:** “Securing connection...” loading state and connection-


failure fallback UI in `App`.
- **Chat generation feedback:** `isTyping`, `isStreaming`, delayed `thinkingHint`, animated
typing dots, streaming cursor, and disabled send controls during active stream.
- **Voice flow feedback:** explicit state machine (`listening`, `processing`, `speaking`, `error`)
with visual and textual status updates.
- **Widget completion feedback:** completion chips and supportive messages reinforce task
closure.
- **Crisis feedback:** escalation messaging and resource surface when crisis signals are
detected.

---

## Methodological conclusion

The frontend applies a **therapeutic, mood-adaptive design system** with strong emotional UX
intent: soft visual language, guided interventions, and continuous conversational feedback.
Structurally, chat is modular (`ChatView` orchestration + `TherapeuticFeed` rendering +
registry-driven widgets), which supports extension and consistent behavior. Accessibility and
responsiveness are broadly implemented, with clear strengths in keyboard flow and mobile chat
layout, though there are incremental opportunities in ARIA coverage consistency and control
labeling.

3.2.7 End-to-End Integration, Testing & Safety Guardrails


Analyze the integration, testing, and safety systems in this project and tell me:
1. How do the frontend, backend, and LLM API connect end-to-end? Trace a full user message
from browser to LLM and back.
2. What testing is in place — unit tests, integration tests, E2E tests? Which frameworks (Jest,
Vitest, Playwright, Cypress)?
3. What safety guardrails are implemented for crisis detection — keywords, LLM-based
detection, or rule-based filters?
4. If a user expresses suicidal ideation or crisis, what does the system do — what is the exact
response or escalation path?
5. Are there content moderation filters, profanity filters, or topic restriction mechanisms?
6. How does the system prevent the LLM from giving harmful medical advice or acting outside
its therapeutic scope?
7. Are there rate limits, abuse prevention, or session timeout mechanisms?
Give output as a structured technical summary for a methodology chapter.
## Integration, Testing, and Safety Systems (Methodology Summary)

### 1) End-to-end integration: browser -> backend -> LLM -> browser

**Primary runtime path is streaming (`/api/chat/stream`) with SSE.**

1. **User sends message in frontend**


- `[Link]()` creates local user message and builds prior history.
- Frontend calls `streamChat(...)` in `src/services/[Link]`.

2. **Frontend sends authenticated request**


- `POST /api/chat/stream` with JWT bearer header and JSON payload:
- `message`, `mood`, `session_id`, `conversation_history`, `session_message_count` (+
optional context fields).

3. **Backend route orchestration**


- `cbt-backend/routers/[Link]::chat_stream()` validates `ChatRequest`, checks auth
(`get_current_user`), crisis pre-checks, starts background mood/distortion inference, and
persists the user-side turn.

4. **LLM invocation**
- `chat_stream()` calls `therapist.chat_stream(...)`.
- `cbt-backend/models/[Link]` builds system + context + history + user messages, then
calls Groq through OpenAI-compatible SDK:
- `[Link](stream=True, ...)`.

5. **Streaming back to frontend**


- Backend yields SSE `data:` JSON events with `token`, crisis flags, final `metadata`, and
`done`.
- Frontend `parseSseDataLine()` appends tokens and updates UI progressively.

6. **Frontend final render**


- Full response is parsed into text + widget segments (`parseCompleteAssistantText`,
`segmentsToAssistantMessages`) and shown in `TherapeuticFeed`.

---

### 2) Testing in place (frameworks + scope)

- **No formal JS test framework configured** (`Jest`, `Vitest`, `Playwright`, `Cypress` not found
in scripts/deps).
- **No formal Python test suite framework found** (`pytest` not present in requirements; no test
runner config).
- Found **one manual smoke test script** at project root:
- `test_therapist.py` (directly instantiates `Therapist`, calls `chat`, prints behavior checks).
- Net: testing is **ad-hoc/manual**, not full unit/integration/E2E automation.

---

### 3) Crisis safety guardrails: detection approach

Safety is **rule-based**, not LLM-based moderation.

- `Therapist` has hardcoded `CRISIS_KEYWORDS` and `_check_crisis(...)`.


- `CrisisHandler` uses regex pattern tiers:
- `high_severity_patterns`
- `moderate_severity_patterns`
- Crisis logic is local deterministic Python (offline classification), then returns curated response
package.

So detection = **keyword + regex rule engine**, not model classifier moderation.

---

### 4) Exact crisis/escalation behavior

If crisis is detected:

1. **Backend short-circuits normal therapy response path**.


2. Calls `crisis_handler.get_response(...)` to return:
- `safe_message`
- `safety_plan_prompt`
- `resources`
- `escalation_level` (`high` / `moderate` / `concern`)
3. In stream mode, backend emits crisis token content and sets `is_crisis`.
4. Frontend `onCrisis` triggers `triggerCrisisFlow(...)`:
- fetches crisis response data,
- opens `SOSModal`,
- appends crisis-priority assistant message:
- `🆘 Priority: <LEVEL> — Opening safety resources...`
5. `SOSModal` displays safety text + action links (`[Link] `[Link] from resource list.

Example high-risk wording in code:


- `"I hear how much pain you are in right now..."` + prompt to contact one listed resource
immediately.
---

### 5) Content moderation / profanity / topic restriction

- **No dedicated profanity filter** found.


- **No generic moderation API** (e.g., toxicity classifier/mod endpoint) found.
- **No broad topic-restriction engine** found.
- Practical restrictions are mostly:
- crisis short-circuit rules,
- therapeutic system prompt constraints,
- widget JSON validation/parsing safety behavior.

---

### 6) Preventing harmful/over-scope therapeutic output

Control mechanisms are prompt and flow constraints, plus crisis overrides:

- `SYSTEM_PROMPT` enforces therapeutic style and pacing:


- warm CBT role
- strict conversational rules
- constrained intervention cadence
- no exercise stacking
- Crisis paths bypass or override normal LLM output with deterministic safe templates.
- In non-stream mode, widget JSON is post-validated (`_validate_widget_json`) to drop
malformed widget blocks.
- There is **no separate clinical policy engine** or medical-advice classifier layer beyond prompt
+ crisis rules.

---

### 7) Rate limits, abuse prevention, session timeout

**Rate limiting present**


- Global default via SlowAPI limiter: `60/minute`.
- Endpoint overrides:
- chat/chat-stream: `20/minute`
- mood: `30/minute`
- voice-chat: `10/minute`
- history/session ops: `60/minute`

**Auth/session security controls**


- JWT access + refresh token issuance in backend (`[Link]`, `/auth/refresh` route).
- Access/refresh expiries configurable via env.

**Important implementation caveat**


- Frontend currently stores and uses access token in memory and does not implement
automatic refresh flow.
- No explicit user-idle session timeout UX found client-side.
- Abuse controls are mainly request-rate caps + auth; no advanced anti-bot/challenge controls
observed.

---

## Methodological conclusion

The system is tightly integrated and functionally safe for baseline CBT chat via **rule-based
crisis interception + therapeutic prompting + per-route rate limits**. However, testing maturity is
low (manual smoke test only), and moderation coverage is narrow (no profanity/toxicity
moderation layer). Safety is strongest around explicit crisis language; non-crisis harmful-content
prevention depends primarily on prompt governance rather than multi-layer policy enforcement.

3.2.8 Scalability Provisions & Future AI Model Upgrade Path


Analyze the architecture of this project for scalability and extensibility and tell me:
1. Is the LLM provider abstracted in a way that allows easy model switching (e.g., a model
config variable or provider interface)?
2. How would the system handle 1000+ concurrent users — what would need to change in the
current architecture?
3. Is the database schema designed for growth — are there indexes, pagination, or archiving
strategies?
4. Is the backend stateless and horizontally scalable, or does it rely on in-memory state?
5. Are there any feature flags, config-driven behaviors, or plugin-style modules that make the
system extensible?
6. What infrastructure changes would be needed to move from development to production at
scale (caching, CDN, load balancer)?
Give output as a structured technical summary for a methodology chapter.

## Scalability & Extensibility Architecture Assessment

### 1) LLM provider abstraction and model switching

- **Partially abstracted (config-level), not provider-abstracted.**


- Model selection is env-driven via `GROQ_MODEL`; generation params are env-driven
(`LLM_MAX_TOKENS`, `LLM_TEMPERATURE`, `LLM_TOP_P`).
- Current implementation is still a **single concrete provider path**: `Therapist` instantiates
`OpenAI(...)` against Groq-compatible base URL; no provider interface/strategy layer.

```28:32:cbt-backend/models/[Link]
GROQ_BASE_URL = [Link]("GROQ_BASE_URL", "[Link]
MODEL_NAME = [Link]("GROQ_MODEL", "llama-3.3-70b-versatile")
MAX_TOKENS = int([Link]("LLM_MAX_TOKENS", "1024"))
LLM_TEMPERATURE = float([Link]("LLM_TEMPERATURE", "0.7"))
LLM_TOP_P = float([Link]("LLM_TOP_P", "0.95"))
```

**Methodological conclusion:** easy model swap *within Groq/OpenAI-compatible path*, but not
plug-and-play multi-provider extensibility yet.

---

### 2) 1000+ concurrent users: what must change

Current bottlenecks suggest this architecture will saturate before 1000 active concurrent users
without redesign:

- SQLite write contention under heavy chat/message logging.


- Local inference + voice workloads in-process.
- Small fixed executor (`ThreadPoolExecutor(max_workers=2)`).
- In-memory limiter/cache not shared across instances.
- Unbounded history fetches (`.all()`).

```29:29:cbt-backend/routers/[Link]
ml_executor = ThreadPoolExecutor(max_workers=2)
```

**Required changes for 1000+ users**


- Migrate DB to PostgreSQL (managed) + proper pool tuning + migrations.
- Introduce Redis for distributed rate limiting and shared cache.
- Split heavy inference/voice into worker services/queues.
- Add autoscaled multi-worker API deployment behind LB.
- Add pagination + retention rules for history endpoints.
- Add provider failover/retry/circuit-breaker for LLM and TTS dependencies.

---

### 3) Database growth readiness (indexes, pagination, archiving)


- **Strengths:** schema has sensible entities (`User`, `Session`, `Message`, `MoodLog`,
`CBTIntervention`) and key compound indexes by session/time.
- **Gaps:** no pagination in history APIs; no archival/TTL strategy; no soft-delete/data tiering.

```89:90:cbt-backend/models/db_models.py
Index("ix_messages_session_timestamp", "session_id", "timestamp"),
```

```119:120:cbt-backend/models/db_models.py
Index("ix_mood_logs_session_timestamp", "session_id", "timestamp"),
```

```146:147:cbt-backend/models/db_models.py
Index("ix_interventions_session_timestamp", "session_id", "timestamp"),
```

```26:31:cbt-backend/routers/[Link]
result = await [Link](
select(Message)
.where(Message.session_id == session_id)
.order_by([Link]())
)
messages = [Link]().all()
```

---

### 4) Stateless/horizontal scalability assessment

- **Partially stateless, not fully horizontally safe yet.**


- Auth is JWT-based (good for stateless auth), and core chat/session state is DB-backed.
- But app behavior relies on process-local state:
- in-memory caches (`MOOD_CACHE`, `DISTORTION_CACHE`),
- in-memory rate limiting,
- singleton-like model objects initialized at startup per process.

```6:7:cbt-backend/models/inference_cache.py
MOOD_CACHE = LRUCache(maxsize=200)
DISTORTION_CACHE = LRUCache(maxsize=200)
```

```8:8:cbt-backend/middleware/rate_limiter.py
limiter = Limiter(key_func=get_remote_address, default_limits=["60/minute"])
```
**Implication:** horizontal scaling works functionally, but with inconsistent limits/cache behavior
unless externalized.

---

### 5) Extensibility mechanisms (flags/config/plugins)

- **Config-driven behavior:** strong use of env variables for LLM/auth/logging parameters.


- **Feature flags:** no dedicated flag framework (no runtime targeting, staged rollout controls).
- **Plugin-style modules:** frontend widget architecture is good (central registry + typed widget
contract), making CBT UI extensions straightforward.
- **Backend plugin architecture:** limited; routers call concrete services directly (no formal
provider interface for LLM/mood/distortion engines).

---

### 6) Dev → production infrastructure changes needed

Current repo and scripts are dev-centric (`uvicorn --reload`, local API base, localhost CORS).

```17:17:[Link]
uvicorn main:app --reload --port 8000 &
```

```6:6:src/services/[Link]
const API_BASE = '[Link]
```

**Production-scale infrastructure blueprint**


- **Compute:** containerize API/frontend; run API with multiple workers behind load balancer.
- **Data:** PostgreSQL + backups + read replicas (as needed).
- **Cache/control plane:** Redis (rate limiting, shared cache, queue broker).
- **Async pipeline:** job queue for voice/inference-heavy operations.
- **Edge:** CDN for frontend static assets; gzip/brotli + cache headers.
- **Networking/security:** production CORS/origin config, TLS termination, secrets manager.
- **Observability:** centralized logs, metrics, traces, SLO alerts, cost/token monitoring.
- **Resilience:** retries/timeouts/circuit breakers for LLM/TTS calls.

---

## Overall methodological judgment


The project is **functionally modular and extensible at the feature level** (especially UI widgets
and configurable LLM parameters), but **operationally pre-scale**: SQLite, in-memory
limiter/cache, and monolithic in-process inference are the primary blockers. For 1000+
concurrency, the key transition is from “single-node intelligent app” to “distributed API +
managed data + workerized inference” architecture.

3.3 System Architecture Overview


3.3.1 High-Level Architecture Diagram
Based on the entire codebase, describe the high-level system architecture of this application in
detail:
1. List every major system component (Frontend, Backend, LLM API, Database, Auth Service,
etc.) and its technology.
2. Describe how each component connects to the others — what calls what, over what protocol
(REST, WebSocket, SDK).
3. Are there any third-party services integrated (email service, analytics, monitoring)?
4. Is there a separate AI/ML service layer, or is LLM logic embedded in the main backend?
5. Describe the hosting/deployment architecture — where does each component live?
6. Provide a textual description detailed enough for me to draw a professional architecture
diagram (boxes and arrows style), labeling every connection and data flow.

## High-Level System Architecture (Codebase-Derived)

### 1) Major system components and technology

- **Frontend SPA**
- Tech: React + Vite + JS/TS, Zustand, Framer Motion, Tailwind-style utility classes.
- Key role: chat UI, widget rendering, dashboard, audio UX, session switching.
- **Backend API**
- Tech: FastAPI (Python), async SQLAlchemy, SlowAPI rate limiter.
- Key role: auth, chat orchestration, streaming responses, mood/distortion endpoints,
history/session APIs, crisis APIs, voice pipeline.
- **LLM integration (inside backend)**
- Tech: `openai` Python client pointed at Groq OpenAI-compatible endpoint.
- Key role: therapeutic response generation (`chat` and `chat_stream`) with CBT prompt/rules.
- **Database**
- Tech: SQLite via `sqlite+aiosqlite` (current).
- Entities: `users`, `sessions`, `messages`, `mood_logs`, `cbt_interventions`.
- **Auth subsystem (inside backend)**
- Tech: JWT (`python-jose`), password hashing (`passlib` + bcrypt), FastAPI OAuth2 bearer
dependency.
- **Classical ML/NLP models (inside backend process)**
- Mood classifier, distortion detector, crisis classifier/handler, voice processor.
- Includes in-memory caches and thread-pool execution for selected inference calls.
- **External third-party APIs/services**
- Groq LLM API (primary AI inference).
- gTTS for text-to-speech in voice flow.
- Google Fonts CDN (frontend styling asset).
- **Local/session persistence in browser**
- `localStorage` keys for device ID, active chat session ID, saved session list, local intervention
logs.

---

### 2) How components connect (what calls what, protocol)

- **Frontend -> Backend**: HTTPS/HTTP REST + SSE (streaming)


- `POST /api/auth/register`, `/api/auth/login`, `/api/auth/refresh`
- `POST /api/chat` (non-stream), `POST /api/chat/stream` (SSE token stream)
- `POST /api/classify-mood`, `POST /api/detect-distortions`
- `GET /api/history/{session_id}`, `GET /api/mood-history/{session_id}`, `DELETE
/api/session/{session_id}`
- `POST /api/voice-chat`, crisis endpoints
- **Backend -> LLM provider (Groq)**: OpenAI-compatible SDK over HTTPS
- `[Link](...)` (stream=false/true)
- **Backend -> DB**: SQLAlchemy async ORM over SQLite driver
- Persists users, sessions, messages, mood logs, interventions metadata.
- **Backend internal service calls**: in-process Python function calls
- Router -> therapist/mood/distortion/crisis/voice modules.
- **Frontend internal flow**: parsed streamed assistant text -> widget JSON blocks -> widget
registry -> component rendering.
- **No WebSocket transport** observed; real-time path uses **SSE**.

---

### 3) Third-party services integrated

- **Groq API** (LLM inference)


- **gTTS** (text-to-speech)
- **Google Fonts** (UI font loading)
- No clear integration found for: Stripe, Segment/GA, Sentry, Datadog, email/SMS providers, or
external monitoring platforms (beyond app-internal health/logging).

---

### 4) AI/ML service layer separation

- **No separate AI microservice layer currently.**


- LLM and ML logic are **embedded in the main FastAPI backend process**:
- `Therapist` class handles prompting + LLM calls.
- Mood/distortion/crisis/voice are loaded and invoked in backend lifespan/router modules.
- Architecture is modular in code, but runtime is monolithic API + embedded inference
components.

---

### 5) Hosting/deployment architecture (as implemented now)

- Current codebase is **development-oriented local deployment**:


- Backend starts with `uvicorn ... --reload --port 8000`
- Frontend runs Vite dev server (`localhost:5173`)
- API base in frontend points to `[Link]
- No first-class production infra manifests detected (e.g., Docker/K8s/Terraform/managed
deployment configs).
- So “where each component lives” in current form:
- Frontend dev server: local machine
- Backend API + AI modules: same local machine process space
- SQLite DB file: local filesystem
- LLM/TTS providers: external cloud endpoints over internet

---

### 6) Diagram-ready “boxes and arrows” textual architecture

Use these boxes and labeled arrows directly:

1. **[User Browser / React SPA]**


- Sub-boxes: Chat UI, TherapeuticFeed, WidgetRegistry, Dashboard, localStorage.
2. **[FastAPI Backend]**
- Sub-boxes: Auth Router, Chat Router, Stream SSE Handler, History Router, Voice Router,
Crisis Router.
3. **[AI Modules (in Backend Process)]**
- Sub-boxes: Therapist (LLM orchestrator), Mood Classifier, Distortion Detector, Crisis
Handler, Voice Processor.
4. **[SQLite DB]**
- Tables: Users, Sessions, Messages, MoodLogs, CBTInterventions.
5. **[Groq LLM API]**
6. **[gTTS API]**
7. **[Google Fonts CDN]**

**Arrows/data flows:**
- `User Browser -> FastAPI Backend`
**REST JSON** for auth/chat/history/mood/session APIs.
- `User Browser -> FastAPI Backend`
**SSE stream** for `/api/chat/stream` token-by-token assistant output.
- `FastAPI Chat Router -> Therapist`
in-process call with user text, mood context, history, distortions, pacing metadata.
- `Therapist -> Groq LLM API`
HTTPS SDK call (`[Link]`, streaming or non-streaming).
- `FastAPI Routers -> SQLite DB`
async ORM reads/writes for users, sessions, messages, mood logs.
- `Voice Router -> Voice Processor -> gTTS API`
transcribe/classify/respond/synthesize pipeline.
- `Browser localStorage <-> React SPA`
device ID, active session ID, saved sessions, local intervention logs.
- `React SPA -> Google Fonts CDN`
stylesheet/font asset fetch.

If you want, I can also provide this as a Mermaid `flowchart` block so you can paste it directly
into docs.

3.3.2 Data Flow & Conversation Pipeline

Trace and document the complete data flow of a single therapy conversation in this application:
1. Step-by-step: what happens from the moment a user types a message to when they see the
AI response?
2. What data transformations happen at each stage — how is raw user input processed before
reaching the LLM?
3. How is conversation history retrieved, formatted, and included in the LLM request?
4. How is the LLM's response processed before being sent to the frontend — any post-
processing, filtering, or formatting?
5. What is written to the database during a conversation and at what points?
6. If streaming is used, how does the data flow differ — how is the stream piped from LLM to
frontend?
7. Provide a numbered sequential pipeline (Step 1 → Step 2 → ...) I can use as the
basis for a data flow diagram.

## Single-Turn Therapy Conversation Data Flow (Diagram-Ready)

Below is the **end-to-end pipeline for one user message** in the current app (primary path =
streaming chat).

### Step 1 -> User enters message in UI


- User types in chat input and submits.
- `[Link]()` trims text, rejects empty input, and blocks if already
streaming.
- A local user message object is created and appended to the chat store for immediate UI
feedback.

---

### Step 2 -> Frontend builds request context


- Frontend appends `{ role: "user", content: <trimmed text> }` to in-memory
`conversationHistory`.
- It computes `historyForApi = [Link](0, -1)` so the just-sent message is **not
duplicated** in history.
- Request body for `streamChat(...)` includes:
- `message` (current user text),
- `mood`,
- `session_id`,
- `conversation_history` (prior turns only),
- `session_message_count`,
- optional `emotion_scores`, `mood_context`, `one_turn_system_instruction` (currently often
null in this flow).

---

### Step 3 -> Frontend sends streaming API request


- `streamChat()` sends `POST /api/chat/stream` with JSON body.
- Transport is HTTP with SSE response expected.

---

### Step 4 -> Backend receives and validates


- `chat_stream()` route is entered (JWT-authenticated via `get_current_user`, DB session
injected).
- `ChatRequest` is parsed/validated by Pydantic.
- Backend checks that therapist model is loaded.

---

### Step 5 -> Early backend pre-processing


- Crisis pre-check: `therapist._check_crisis([Link])`.
- `conversation_history` Pydantic objects are transformed to plain dicts:
- `[{role, content}, ...]`.
- Two async inference tasks are launched in executor for metadata enrichment:
- mood classification (`_classify_mood_cached`),
- distortion detection (`_detect_distortions_cached`).
---

### Step 6 -> Pre-stream DB writes (user-side persistence)


Before any assistant tokens are streamed, backend persists:
- `Message` row for user turn (`role="user"`, `content=[Link]`,
`mood_at_time=[Link]`),
- `MoodLog` row (`mood`, `confidence=1.0`, `trigger_message`).
- Also ensures session row exists (`ensure_session_exists`).

---

### Step 7 -> LLM request construction (raw input -> LLM-ready prompt)
In `Therapist._build_messages(...)`, backend transforms inputs into final LLM message list:

1. Base `system` prompt (`SYSTEM_PROMPT`) with CBT/therapeutic rules.


2. Optional extra system messages:
- `mood_context`,
- `one_turn_system_instruction`.
3. Prior `conversation_history` turns.
4. Current user turn rewritten as:
- `[System Context: mood + optional distortion context + optional widget directive]`
- then actual user text.

Additional transformation:
- Rule-based `_widget_directive(...)` may inject a forced widget instruction based on session
pacing, keywords, and emotion scores.

---

### Step 8 -> LLM call and stream generation


- `Therapist.chat_stream()` calls Groq via OpenAI-compatible SDK
(`[Link](stream=True)`).
- Tokens are yielded incrementally from backend generator.

If crisis was detected:


- LLM stream is bypassed.
- Backend emits crisis-safe message from `CrisisHandler`.

---

### Step 9 -> Backend SSE emission to frontend


Backend emits SSE frames like:
- token events (`{"token": "...", "done": false, ...}`),
- optional crisis marker,
- final metadata event (mood/distortion results),
- done event.

After stream completes, backend persists assistant reply and session metadata.

---

### Step 10 -> Frontend consumes stream incrementally


`parseSseDataLine(...)` handles each line:
- `onToken`: appends token to `fullText`.
- UI uses `parseStreamingAssistantText(...)` + `displayableStreamingText(...)` to render partial
text while hiding incomplete widget fences.
- `onMetadata`: attaches mood/distortion metadata to the triggering user message.

---

### Step 11 -> Final response parse and render


On `done`:
- Frontend runs `parseCompleteAssistantText(fullText)`.
- It splits text by fenced ` ```widget ... ``` ` blocks.
- `segmentsToAssistantMessages(...)` converts parsed segments into chat messages:
- plain assistant text messages,
- assistant widget messages (`type: "widget"`, `state: "active"`).
- `TherapeuticFeed` renders text and maps widget types via `WidgetRegistry`.

---

### Step 12 -> Post-turn state updates


- Final assistant raw content is pushed into `conversationHistory` as `{ role: "assistant", content:
finalRaw }`.
- Streaming flags are cleared.
- UI is now ready for next user turn.

---

## Data Transformations Summary (Raw -> Structured)

1. **User input text** -> trimmed string.


2. **Store message object** -> normalized `ChatMessage`.
3. **History objects** -> API payload (`conversation_history` prior turns only).
4. **Backend Pydantic models** -> plain dict history for LLM.
5. **Mood/distortion/context + user text** -> composite LLM user prompt.
6. **LLM raw output text** -> widget-validated/parsed segments.
7. **Parsed segments** -> renderable chat messages + interactive widgets.

---

## Conversation History Handling

- Retrieved on session load via `GET /api/history/{session_id}`.


- Backend returns chronological messages from DB.
- Frontend rehydrates with `backendHistoryToChatMessages(...)`:
- assistant content is reparsed into text/widget segments.
- historical widget messages are marked `state: "completed"`.

For new turns, frontend sends prior turns in `conversation_history` each request.

---

## LLM Response Post-processing / Filtering

- Non-stream path explicitly applies `_validate_widget_json(...)` (removes malformed widget


JSON fences).
- Streaming path tokenizes directly but frontend parser safely treats malformed widget blocks as
text if JSON parse fails.
- Crisis path can override LLM content with curated safety response.

---

## Database Writes During a Conversation

### At turn start (streaming path)


- Ensure/create `Session`.
- Insert user `Message`.
- Insert `MoodLog`.
- Commit.

### At turn end


- Insert assistant `Message` (full assembled reply).
- Update `Session.metadata_json.last_stream_metadata` with inferred mood/distortions.
- Commit.

---

## Streaming vs Non-Streaming Difference


- **Non-stream (`/api/chat`)**: one blocking LLM call, one final response payload, then DB writes
for both user and assistant in same request flow.
- **Streaming (`/api/chat/stream`)**: pre-write user data, emit tokens live via SSE, finalize
assistant persistence after stream completion, plus emit metadata event.

---

## Compact numbered pipeline for your diagram

1. User submits message in chat UI.


2. Frontend creates local user message + updates in-memory history.
3. Frontend sends `POST /api/chat/stream` with message + prior history + session context.
4. Backend authenticates request and parses `ChatRequest`.
5. Backend runs crisis pre-check and starts mood/distortion inference tasks.
6. Backend ensures session and persists user message + mood log.
7. Backend builds LLM message stack (system prompt + optional system context + history +
contextualized user turn).
8. Backend calls Groq streaming completion (or crisis fallback path).
9. Backend pipes tokens to frontend via SSE; emits final metadata and done events.
10. Frontend appends tokens to live UI and incrementally parses text/widget boundaries.
11. On done, frontend fully parses assistant output into text + widget messages and renders
them.
12. Backend persists assistant message and stream metadata; frontend stores final assistant
turn in conversation history.

Backend Model Evaluation:


This is a comprehensive and well-structured evaluation script for the machine learning pipeline
of the "MindBridge CBT App," conducted by the CSIR-CSIO Lab. As a researcher analyzing this
notebook, it is clear that the authors have set up a multi-modal evaluation framework testing
three distinct natural language and speech models.

Here is a detailed, researcher-level breakdown of the methodologies, models, and analytical


choices present in the notebook.

1. BERT Emotion Classifier Evaluation


The first section evaluates a fine-tuned BERT model for multi-class emotion classification, which
serves as the foundational mood-tracking component.

● Model Selected: bhadresh-savani/bert-base-uncased-emotion.


● Evaluation Dataset: The researchers constructed a synthetic, balanced test set of 60
utterances mapped to six core emotions: sadness, joy, love, anger, fear, and surprise
(10 samples per class).
● Metrics Analyzed: Standard classification metrics including Overall Accuracy, Macro
and Weighted $F_1$ scores, and a Confusion Matrix. Furthermore, the code calculates
per-class $F_1$ scores and charts the distribution of prediction confidence for correct
versus incorrect classifications.
● Clinical Application (Mood Mapping): The researchers map these 6 raw emotions into
4 "App Moods" (low-energy, neutral, overwhelmed, anxious) to match the app's UI,
evaluating the overall mapping accuracy.

2. Cognitive Distortion Detection (Zero-Shot)


The second section addresses a more complex, specialized NLP task: identifying cognitive
distortions (a core tenet of Cognitive Behavioral Therapy) from user input.

● Model Selected: valhalla/distilbart-mnli-12-3, utilized as a zero-shot classifier.


● Evaluation Dataset: A synthetic dataset of 50 phrases distributed across 10 specific
cognitive distortions (e.g., "catastrophizing", "all-or-nothing thinking", "mind reading").
● Clinical Rationale for Metrics: The researchers calculate both $Top\text{-}1$ and
$Top\text{-}3$accuracy. They provide an excellent clinical justification for this: in real-
world CBT, multiple cognitive distortions frequently co-occur in a single thought (e.g., a
statement can be both an "overgeneralization" and "all-or-nothing thinking"). Therefore,
surfacing the true primary distortion within the $Top\text{-}3$predictions is highly
relevant for therapeutic logic.
● Threshold Tuning: A trade-off analysis curve is plotted to evaluate Precision and Recall
proxies across different confidence thresholds, specifically highlighting the app's chosen
operational threshold of 0.45.

3. Speech-to-Text (STT) Transcription


The final model evaluated handles voice journaling or spoken input, converting user audio to
text before passing it to the NLP models.

● Model Selected: openai/whisper-base.


● Evaluation Dataset: Evaluated against 20 test samples streamed from the clean test
split of the widely used librispeech_asr dataset.
● Metrics Analyzed: The code calculates the Word Error Rate (WER) using the jiwer
library, formatting the output into a DataFrame that compares the reference text, the
transcribed hypothesis, and the individual WER. Transcription Accuracy is derived as $1
- WER$.

4. Executive Summary & Dashboard Generation


The notebook concludes by generating a comprehensive executive summary.

● Reporting: It outputs a console-based summary of the critical metrics (Accuracy, $F_1$,


$Top\text{-}k$metrics, and WER) attributed to the "CSIR-CSIO Lab".
● Visualization: It generates a 2x2 Matplotlib visualization dashboard
(mindbridge_evaluation_complete.png) combining the BERT Confusion Matrix, BERT
Confidence Distribution, DistilBART Threshold Trade-offs, and Whisper STT Metrics into
a single, presentation-ready graphic.

Researcher's Critique:

The methodology is sound for a proof-of-concept or preliminary app evaluation. The code
elegantly bridges raw machine learning metrics with product-specific constraints (e.g., the 4-
state mood mapping and the 0.45 distortion threshold). However, from a rigorous research
perspective, the sample sizes for the BERT ($N=60$) and DistilBART ($N=50$) evaluations are
entirely synthetic and quite small; scaling this evaluation to a larger, diverse corpus of real
clinical data would be the necessary next step to validate generalization.

You might also like