Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
8.7 KiB
Mock LLM (OpenAI-compatible stub for CI / local processing)
Tiny local Chat Completions server that exercises Descrybe’s 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, safe-test-fixtures.md).
Related: green-chat-llm.md (real local/LAN model), local-llm-tuning.md, e2e-processing.md.
Start
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:
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):
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:
stubCompleterinprocessing/steps_test.goHeuristicCompleterfor offline enhance shapeshttptest.NewServer+NewOpenAIClient(..., srv.URL+"/v1", ...)as inaiprovider/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)
- Start mock-llm (above).
- Set
OPENAI_*or configure/integrations/aion Platform Demo (not A1). - Ensure demo plan has
can_use_ai=trueand credits (free-tier.md). - Run API + worker so the worker inherits env (or uses dashboard BYOK).
- Enqueue
enhance_only(orfull) for a demo product:
# 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-llmin background → setOPENAI_*→ run a narrow processing smoke. Do not commit real keys; uselocal-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).
- Web up (PUBLIC_API_URL / WEB_ORIGIN from root .env.example).
- 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.
- /settings → Content Language → pick e.g. de or sl → save — company payload / GET /api/me shows the new language.
- 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
- cd apps/api && go run ./cmd/mock-llm -addr 127.0.0.1:18767
- Uncomment mock OPENAI_* in a private root .env (placeholders only — see .env.example) or set /integrations/ai on Platform Demo.
- Restart api + worker if using process env.
- Smoke stub: curl.exe -sS http://127.0.0.1:18767/v1/models -H "Authorization: Bearer local-test"
- Package tests: go test ./cmd/mock-llm -count=1
- Enqueue enhance (Integration / E2E section above) on a demo product — poll until i_enhance is done.
- 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)
# 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.