Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
10 KiB
Green Chat → Descrybe v2 (OpenAI-compatible)
Use LAN green-chat (systemd unit green-chat.service, binary /usr/local/bin/ge chat ser / ge chat serve) as Descrybe’s LLM the same way you would use OpenAI.
Descrybe already speaks OpenAI Chat Completions via one shared client (processing.OpenAIClient). Preferred setup: company admin → /integrations/ai (custom OpenAI-compatible base URL + key, or a popular provider). Optional process-env OPENAI_* remains a platform fallback when the company uses mode internal.
| Feature | Process | Path |
|---|---|---|
| Product AI enhance | worker | Completer → POST {base}/chat/completions |
| Campaign email AI | API | same Completer |
| SEO meta AI | API | same Completer |
| Brand voice | API/worker | Brand kit PromptBlock() injected into those Completer prompts (no separate LLM call) |
Config resolve: apps/api/internal/aiprovider (company BYOK) → optional OPENAI_* from apps/api/internal/config
Client: apps/api/internal/processing/openai.go
Wiring: cmd/worker/main.go, internal/httpapi/server.go
Do not commit real API keys, tokens, or production LAN endpoints. Use a single root .env for bootstrap secrets — do not duplicate apps/api/.env.
For CI / local processing without a real model, use the OpenAI-compatible stub: mock-llm.md (go run ./cmd/mock-llm). Prefer tenant demo@descrybe.local (not A1).
Setup (preferred: dashboard)
- Ensure root
.envhasAPP_ENCRYPTION_KEY(secrets at rest) and the API + worker are running. - Sign in as a company admin →
/integrations/ai. - Choose custom (or a popular provider), set base URL to
http://GREEN_HOST:PORT/v1, model id fromGET /v1/models, paste API key, enable, Test. - Restart is not required for dashboard-saved keys (unlike process env).
Optional env fallback (OPENAI_*)
When the company leaves AI mode internal, the platform Completer can use process env:
| Variable | Default | Role |
|---|---|---|
OPENAI_API_KEY |
(empty) | Bearer token. Must be non-empty to enable the platform fallback Completer. Use the key from green-chat drop-ins, or any placeholder (e.g. local) if the server ignores auth. |
OPENAI_BASE_URL |
https://api.openai.com/v1 |
Root including /v1. Client appends /chat/completions. |
OPENAI_MODEL |
gpt-4o-mini |
Model id from green-chat GET /v1/models (often a GGUF path/name, not gpt-4o-mini). |
PROCESSING_RPM |
60 |
Client-side spacing between calls |
PROCESSING_MAX_RETRIES |
3 |
Retries on 429 / 5xx / transport errors |
There is no OPENAI_API_BASE — use OPENAI_BASE_URL.
Typical Green Chat path:
POST http://GREEN_HOST:PORT/v1/chat/completions
└──────── OPENAI_BASE_URL ────────┘└── client appends ──┘
Also useful: GET /v1/models, and often GET /health.
Example root .env (placeholders only — optional fallback)
Put these in the repo root .env only if you need platform-env fallback. Prefer /integrations/ai. Restart both API and worker after env changes.
OPENAI_API_KEY=YOUR_GREEN_API_KEY_OR_local
OPENAI_BASE_URL=http://192.168.x.x:PORT/v1
OPENAI_MODEL=YOUR_MODEL_ID_FROM_v1_models
PowerShell (session only):
$env:OPENAI_API_KEY = "YOUR_GREEN_API_KEY_OR_local"
$env:OPENAI_BASE_URL = "http://192.168.x.x:PORT/v1"
$env:OPENAI_MODEL = "YOUR_MODEL_ID_FROM_v1_models"
Free plan blocks AI credits (can_use_ai=false). Use a paid/demo company with credits for real smoke tests — see free-tier.md and demo-user.md.
Discover IP, port, path, and API key ON THE GREEN MACHINE
Run these on the Linux host that runs green-chat (SSH as a user that can sudo where needed).
Unit + drop-ins
sudo systemctl cat green-chat
sudo systemctl cat green-chat.service.d/99-gemma4.conf
sudo systemctl cat green-chat.service.d/runtime.conf
Also useful:
sudo systemctl status green-chat --no-pager -l
ls -la /etc/systemd/system/green-chat.service.d/
sudo systemctl show green-chat -p Environment -p EnvironmentFiles -p ExecStart -p MainPID
Look for listen host/port, --model / MODEL=, and anything named API_KEY / OPENAI_* / AUTH / TOKEN. Do not paste real secrets into git or chat logs.
Listen address and LAN IP
ss -tlnp | grep -E 'ge|green|chat'
hostname -I
sudo journalctl -u green-chat -n 50 --no-pager
| Bind you see | Meaning |
|---|---|
0.0.0.0:PORT or *:PORT |
Reachable from Windows on the LAN (if firewall allows) |
127.0.0.1:PORT only |
Not reachable from other machines — rebind to 0.0.0.0 (or add a reverse proxy) |
Default Green Engine chat port is often 8767 (GE_CHAT_PORT / --port); your drop-ins may override it. Always trust ss / the unit over assumptions.
API key
# Unit environment (may include keys — redact before sharing)
sudo systemctl show green-chat -p Environment --no-pager
sudo systemctl show green-chat -p EnvironmentFiles --no-pager
# Grep drop-ins / nearby config (redact output)
grep -RInE 'API_KEY|OPENAI|BEARER|TOKEN|AUTH' \
/etc/systemd/system/green-chat.service.d/ 2>/dev/null | head -40
If green-chat does not require auth, Descrybe still needs a non-empty OPENAI_API_KEY (e.g. local) so the Completer turns on.
Model id
# From drop-ins
grep -RInE 'model|gemma|MODEL' /etc/systemd/system/green-chat.service.d/ 2>/dev/null
# Or from the running server (on the green host)
curl -sS -H "Authorization: Bearer YOUR_KEY_OR_local" \
"http://127.0.0.1:PORT/v1/models"
Use the data[].id value as OPENAI_MODEL.
Loopback smoke test (on green host)
PORT=CHANGEME
KEY='YOUR_GREEN_API_KEY_OR_local'
MODEL='CHANGEME'
curl -sS -w "\nHTTP %{http_code}\n" \
-H "Authorization: Bearer $KEY" \
"http://127.0.0.1:${PORT}/v1/models"
curl -sS -w "\nHTTP %{http_code}\n" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d "{\"model\":\"${MODEL}\",\"messages\":[{\"role\":\"user\",\"content\":\"Say hi in one word.\"}],\"temperature\":0.2}" \
"http://127.0.0.1:${PORT}/v1/chat/completions"
Expect HTTP 200 and choices[0].message.content.
Firewall (green host)
sudo ufw status || true
# Example once PORT is known (restrict to your LAN):
# sudo ufw allow from 192.168.0.0/16 to any port PORT proto tcp
If loopback works but Windows does not: fix bind (0.0.0.0) and/or firewall first.
Smoke test FROM Windows (Laragon)
Replace placeholders with values from the green host. This PC is typically on 192.168.50.x.
$GreenIP = "192.168.x.x" # from hostname -I on green machine
$Port = "PORT" # from ss / unit (often 8767)
$Key = "YOUR_GREEN_API_KEY_OR_local"
$Model = "YOUR_MODEL_ID"
Test-NetConnection -ComputerName $GreenIP -Port $Port
curl.exe -sS -w "`nHTTP %{http_code}`n" `
-H "Authorization: Bearer $Key" `
"http://${GreenIP}:${Port}/v1/models"
curl.exe -sS -w "`nHTTP %{http_code}`n" `
-H "Authorization: Bearer $Key" `
-H "Content-Type: application/json" `
-d "{\"model\":\"$Model\",\"messages\":[{\"role\":\"user\",\"content\":\"Say hi in one word.\"}],\"temperature\":0.2}" `
"http://${GreenIP}:${Port}/v1/chat/completions"
Then configure /integrations/ai (preferred) or set root .env OPENAI_* and start both processes:
cd f:\laragon\www\_MY\descrybe-v2
.\scripts\run-api.ps1 # campaigns + SEO AI
.\scripts\run-api.ps1 worker # product AI enhance (other terminal)
Root .env is loaded by loadDotEnv / scripts/run-api.ps1 — do not recreate apps/api/.env. Prefer /integrations/ai for new setups ([UNCERTAIN] env platform OpenAI fallback may be removed later).
App-level checks (after AI config + worker up)
| Surface | How |
|---|---|
| Campaign AI | POST /api/campaigns/{id}/generate with {"mode":"ai"} (paid/demo company) |
| SEO AI | POST /api/seo/apply with {"product_id":"…","mode":"ai"} |
| Processing | Worker running; start a job that runs enhance; notes must not say openai_not_configured |
| Brand | Fill brand kit; AI generate/enhance should reflect voice (same Completer) |
Email send (Resend/SMTP / EMAIL_DRY_RUN) is separate from Green Chat; AI only affects copy generation.
Reachability checklist (this workstation)
Run when Green Chat IP/port is unknown or LAN calls fail:
- On green:
sudo systemctl cat green-chat(+ drop-ins above) → port, bind, model, key env names. - On green:
ss -tlnp | grep -E 'ge|green|chat'→ confirm0.0.0.0(not only127.0.0.1). - On green:
hostname -I→ LAN IP for Windows.env. - On green: loopback
curlto/v1/modelsand/v1/chat/completions. - On green: firewall allows your Windows host (or LAN) to that TCP port.
- On Windows:
Test-NetConnection GREEN_IP -Port PORT, then the curl smoke tests. - Configure AI in
/integrations/ai(or optional root.envOPENAI_API_KEY/OPENAI_BASE_URL=http://GREEN_IP:PORT/v1/OPENAI_MODEL). - Ensure API + worker are running; retest campaign/SEO/processing on a non-Free company.
Probe notes (2026-08-04, Laragon PC 192.168.50.119)
| Target | Result |
|---|---|
Process env OPENAI_* |
Unset |
DNS green / green-chat / gemma |
No resolution |
LAN neighbors (192.168.50.39, .100, .143, .181) on default chat ports (8767, 8080, …) |
No OpenAI-compatible green-chat endpoint reachable |
| Open ports seen | .143:8443/:9000 (not chat API); .181:80/:443; .100:80 — not usable as /v1/chat/completions |
Local http://127.0.0.1:8767 (ge chat serve on this PC) |
OK — GET /v1/models 200; POST /v1/chat/completions 200 (Hello.) |
Conclusion: Descrybe wiring is ready. Remote gemma4 green-chat IP/port/key must come from the discovery commands on that host (likely loopback-bound or firewalled today).
Related
- ai-full-smoke.md — full AI feature pass/fail against LAN Green Chat
- local-llm-tuning.md — weak-model prompt/JSON/token defaults
- process-and-sell-summary.md —
OPENAI_*table - ops-runtime.md — worker / credits
- free-tier.md / demo-user.md — AI gates and demo credits