Files
descrybe/docs/green-chat-llm.md
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

10 KiB
Raw Permalink Blame History

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 Descrybes 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)

  1. Ensure root .env has APP_ENCRYPTION_KEY (secrets at rest) and the API + worker are running.
  2. Sign in as a company admin/integrations/ai.
  3. Choose custom (or a popular provider), set base URL to http://GREEN_HOST:PORT/v1, model id from GET /v1/models, paste API key, enable, Test.
  4. 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:

  1. On green: sudo systemctl cat green-chat (+ drop-ins above) → port, bind, model, key env names.
  2. On green: ss -tlnp | grep -E 'ge|green|chat' → confirm 0.0.0.0 (not only 127.0.0.1).
  3. On green: hostname -I → LAN IP for Windows .env.
  4. On green: loopback curl to /v1/models and /v1/chat/completions.
  5. On green: firewall allows your Windows host (or LAN) to that TCP port.
  6. On Windows: Test-NetConnection GREEN_IP -Port PORT, then the curl smoke tests.
  7. Configure AI in /integrations/ai (or optional root .env OPENAI_API_KEY / OPENAI_BASE_URL=http://GREEN_IP:PORT/v1 / OPENAI_MODEL).
  8. 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) OKGET /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).