# AI Features — DeepSeek Integration

spq-v2 mirrors v1's AI integration exactly: all calls go to `/deepseek/v1/chat/completions` with `deepseek-v4-flash`.

## Architecture

All AI functions live in `src/lib/ai.ts` and use a shared `callDeepSeek()` helper:

```
fetch('/deepseek/v1/chat/completions', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    model: 'deepseek-v4-flash',
    messages: [{role:'system', content}, {role:'user', content}],
    temperature: 0,
    thinking: { type: 'disabled' },
    max_tokens: 500,
  }),
})
```

The endpoint works through the Python proxy server (`/deepseek/*` is forwarded by nginx in production, not the Python proxy — the proxy only handles `/pb/*`; ensure nginx has the `/deepseek` location block).

## Exported Functions

### 1. `getPriorityAnalysis(services)` — Generate Priorities
- Input: `ServiceItem[]` (name, recommendation)
- Output: `PriorityResult[]` (name, rank, priority_reason)
- Sends services to AI for safety-first ranking: CRITICAL_SAFETY > SAFETY_CONCERN > RECOMMENDED > MAINTENANCE > OPTIONAL
- Strips markdown code blocks from response before JSON parsing

### 2. `aiWriteExplanation(params)` — AI Write
- Input: `ExplanationParams` (serviceName, recommendation, technicianNotes?, vehicleInfo?, mileage?, maintenanceInterval?)
- Output: `ExplanationResult` (level, explanation) or null
- Generates professional customer-facing explanation
- Incorporates vehicle context, mileage, interval data
- Parses `LEVEL:` and `EXPLANATION:` tagged response format
- Level is one of: CRITICAL, RECOMMENDED, OPTIONAL, PREVENTIVE, MAINTENANCE

### 3. `aiSuggestServices(vehicle, selectedServices, catalog)` — AI Suggest
- Input: `SuggestVehicle`, `string[]`, `CatalogItem[]`
- Output: `SuggestResult[]` (name, reason) or null
- Recommends services from catalog based on mileage + vehicle info
- Cross-references AI output against catalog names — only returns catalog matches
- Never invents services; only suggests from the provided catalog

### 4. Screenshot OCR + Extraction (in Appointments.tsx)
- Uses Tesseract.js (dynamic CDN import: `cdn.jsdelivr.net/npm/tesseract.js@5`)
- Canvas preprocessing: 2-3x upscale + mild contrast enhancement
- OCR text sent to `/deepseek/v1/chat/completions` with `max_tokens: 2000` for structured JSON extraction
- Extracted appointments reviewed before batch import

## Pitfalls

- **Tesseract.js not in package.json** — the screenshot import feature loads it dynamically from CDN. If offline or CDN blocked, the feature silently fails.
- **Model must be `deepseek-v4-flash`** — other models may not follow the strict JSON-only response format.
- **AI functions return `null` on failure** — UI must handle null gracefully (show toast, don't crash).
- **`temperature: 0` is intentional** — structured extraction needs deterministic output.
