Files
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

191 lines
8.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Mock LLM (OpenAI-compatible stub for CI / local processing)
Tiny local Chat Completions server that exercises Descrybes real `processing.OpenAIClient` path **without** production API keys or Green Chat.
| Item | Value |
|------|--------|
| Command | `apps/api/cmd/mock-llm` |
| Default listen | `127.0.0.1:18767` |
| Base URL | `http://127.0.0.1:18767/v1` |
| Model id | `mock-llm` |
| API key | `local-test` (placeholder; Completer requires non-empty) |
| Responses | `processing.HeuristicCompleter` (deterministic JSON for enhance) |
**Do not use the A1 tenant.** Prefer **`demo@descrybe.local`** → **Platform Demo** ([demo-user.md](demo-user.md), [safe-test-fixtures.md](safe-test-fixtures.md)).
Related: [green-chat-llm.md](green-chat-llm.md) (real local/LAN model), [local-llm-tuning.md](local-llm-tuning.md), [e2e-processing.md](e2e-processing.md).
---
## Start
```powershell
cd apps/api
go run ./cmd/mock-llm -addr 127.0.0.1:18767
# defaults: key=local-test model=mock-llm
# env overrides: MOCK_LLM_API_KEY, MOCK_LLM_MODEL
```
Health: `GET http://127.0.0.1:18767/healthz``{"status":"ok","service":"mock-llm",...}`.
Smoke:
```powershell
curl.exe -sS http://127.0.0.1:18767/v1/models -H "Authorization: Bearer local-test"
# POST /v1/chat/completions with JSON messages (same shape as OpenAI)
```
Endpoints:
| Method | Path | Notes |
|--------|------|--------|
| `GET` | `/healthz` | No auth |
| `GET` | `/v1/models` | Bearer required |
| `POST` | `/v1/chat/completions` | Bearer; assistant content from HeuristicCompleter |
| `POST` | `/v1/embeddings` | Bearer; tiny fixed vector for role probes |
Loopback is allowed by `OpenAIClient` dial policy (`localhost` / `127.0.0.1`).
---
## Config keys
Process-env platform fallback (root `.env` — restart **api** + **worker** after change):
```env
OPENAI_API_KEY=local-test
OPENAI_BASE_URL=http://127.0.0.1:18767/v1
OPENAI_MODEL=mock-llm
# optional tuning
# PROCESSING_RPM=60
# PROCESSING_MAX_RETRIES=3
```
Preferred for a single tenant: company admin → **`/integrations/ai`** → custom OpenAI-compatible:
- Base URL: `http://127.0.0.1:18767/v1`
- Model: `mock-llm`
- API key: `local-test`
`OPENAI_API_KEY` must be non-empty or the Completer stays disabled (`Enabled()`).
Unset `OPENAI_*` → worker skips AI enhance (or uses heuristic only if explicitly wired). Mock-llm is for proving the **HTTP** Completer path.
---
## How processing tests should call it
### 1. Unit / package tests (no process)
Prefer in-process stubs — already used:
- `stubCompleter` in `processing/steps_test.go`
- `HeuristicCompleter` for offline enhance shapes
- `httptest.NewServer` + `NewOpenAIClient(..., srv.URL+"/v1", ...)` as in `aiprovider/platform_role_test.go`
`go test ./cmd/mock-llm` covers health, auth, enhance JSON, and an `OpenAIClient` round-trip against the stub handlers.
### 2. Integration / E2E (worker + API)
1. Start mock-llm (above).
2. Set `OPENAI_*` **or** configure `/integrations/ai` on **Platform Demo** (not A1).
3. Ensure demo plan has `can_use_ai=true` and credits ([free-tier.md](free-tier.md)).
4. Run API + worker so the worker inherits env (or uses dashboard BYOK).
5. Enqueue `enhance_only` (or `full`) for a demo product:
```powershell
# After CSRF + login as demo@descrybe.local (cookie jar):
# POST /api/processing/jobs {"raw_product_ids":["…"],"processing_type":"enhance_only"}
# Poll GET /api/processing/jobs/{id} until completed
# Expect ai_enhance step done; gpt/step log shows OpenAI-compatible usage (not openai_not_configured)
```
Worker log should show OpenAI configured with `base=http://127.0.0.1:18767/v1 model=mock-llm`, not “platform OpenAI unset”.
### 3. CI
- Default CI: keep unit tests with `stubCompleter` / `httptest` (no long-lived process).
- Optional job: `go run ./cmd/mock-llm` in background → set `OPENAI_*` → run a narrow processing smoke. Do **not** commit real keys; use `local-test`.
---
## Translation + processing verification
Two independent axes — do not confuse them:
| Axis | What it controls | Where |
|------|------------------|--------|
| **UI locale** | Dashboard chrome strings | localStorage key descrybe-ui-locale (en es fr de it pt nl pl ja) — pps/web/src/lib/i18n/locales.ts |
| **Content language** | AI/product titles & descriptions | Company /settings → Content Language (companies.language) — allowlist in content-languages.ts / company/language.go |
### A. Translation (UI + content language)
Use **demo@descrybe.local** (not A1).
1. Web up (PUBLIC_API_URL / WEB_ORIGIN from root .env.example).
2. Login → open language switcher (or set localStorage.setItem("descrybe-ui-locale","fr") then reload) — expect French chrome, not raw
amespace.key paths; missing keys fall back to English.
3. /settings → Content Language → pick e.g. de or sl → save — company payload / GET /api/me shows the new language.
4. Optional checks: web
pm run check; Go company.ParseLanguage / IsAllowedLanguage.
Root .env.example documents both locale lists (comments only — not process-env).
### B. Processing against mock-llm
1. cd apps/api && go run ./cmd/mock-llm -addr 127.0.0.1:18767
2. Uncomment mock OPENAI_* in a **private** root .env (placeholders only — see .env.example) **or** set /integrations/ai on Platform Demo.
3. Restart **api** + **worker** if using process env.
4. Smoke stub: curl.exe -sS http://127.0.0.1:18767/v1/models -H "Authorization: Bearer local-test"
5. Package tests: go test ./cmd/mock-llm -count=1
6. Enqueue enhance (Integration / E2E section above) on a **demo** product — poll until i_enhance is done.
7. Optional: change content language, re-run enhance, confirm job still completes (heuristic mock text is language-agnostic; real Green Chat honors content language in prompts).
Checklist copy lives in root .env.example under **Locales** and **LLM test provider**.
---
## Failure modes (processing + mock-llm)
Prefer a **temporary** probe (closed port / wrong key / httptest timeout) over changing demo BYOK. If you stop mock-llm, restore it before leaving the session.
| Mode | How to induce (safe) | Completer / job behavior | User-facing note (after TruncateError) |
|------|----------------------|--------------------------|----------------------------------------|
| Provider down | Point client at closed port `127.0.0.1:18768`, **or** briefly stop mock-llm | `ai_enhance` **failed**; job item still completes with passthrough title/description | `AI provider unreachable — check base URL and that the service is running` |
| Bad API key | `OPENAI_API_KEY=wrong-key` against live mock-llm (or `/integrations/ai` test with wrong key) | Non-retryable 401; enhance fails; passthrough copy | `AI provider rejected the API key` |
| Timeout | Short `HTTPClient.Timeout` / `context.DeadlineExceeded` (unit: `TestRunSteps_enhanceViaHTTPLLMTimeout`) | Retries then fail; passthrough copy; step `failed` | `AI provider timed out — try again or check provider load` |
| Upstream 5xx | Mock returns 502 + message | Retries then fail; note keeps provider message when present | e.g. `green-chat unavailable` (retry prefix stripped) |
| Platform unset | Empty `OPENAI_API_KEY` and no company BYOK | Step **skipped** (not failed) | `ai_enhance: skipped (platform OpenAI unset; …)` |
| Free plan | `AllowAI=false` | Step **skipped** | Free-plan upgrade note |
Package coverage: `go test ./internal/processing -run 'HTTPLLM|mockLLM|TruncateError_classifies' -count=1`.
**Do not** permanently change Platform Demo `/integrations/ai` or root `.env` `OPENAI_*` for failure probes — use closed-port clients, stubs, or a short mock-llm stop.
### Restore mock-llm (after a stop)
```powershell
# Confirm down
curl.exe -sS http://127.0.0.1:18767/healthz
# Start again
cd apps/api
go run ./cmd/mock-llm -addr 127.0.0.1:18767
# Expect healthz status=ok; key/model defaults: local-test / mock-llm
curl.exe -sS http://127.0.0.1:18767/healthz
curl.exe -sS http://127.0.0.1:18767/v1/models -H "Authorization: Bearer local-test"
```
If api/worker were started with `OPENAI_BASE_URL=http://127.0.0.1:18767/v1` and `OPENAI_API_KEY=local-test`, no `.env` change is needed after restore. If you temporarily pointed a **non-demo** test company at a bad base URL, set it back to `http://127.0.0.1:18767/v1` + `local-test` (or clear BYOK to use platform env).
---
## What this is / is not
| Is | Is not |
|----|--------|
| OpenAI Chat Completions wire format for local/CI | A real GGUF / Ollama / Green Chat model |
| Deterministic enhance JSON via HeuristicCompleter | Substitute for production model quality |
| Safe placeholder key `local-test` | Something to commit as a secret |
For a real tiny local model, point the same `OPENAI_*` keys at Ollama/LM Studio/Green Chat (`OPENAI_BASE_URL=http://127.0.0.1:PORT/v1`) — see [green-chat-llm.md](green-chat-llm.md).