Skip to content

Commit 4b756e0

Browse files
committed
Route cloud embeddings through native LiteLLM accounting
Own asynchronous embedding HTTP attempts, validate response identities before cache writes, and preserve model route families. Keep upstream provider credentials gateway-owned. @codex review
1 parent 4b70194 commit 4b756e0

53 files changed

Lines changed: 2022 additions & 340 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
# Copy this file to .env and fill in the values
33

44
# ===== API Keys =====
5-
OPENAI_API_KEY=sk-your-openai-key
65
VOYAGE_API_KEY=your-voyage-key
76
COHERE_API_KEY=your-cohere-key
87
JINA_API_KEY=your-jina-key
98
LANGTRACE_API_KEY=your-langtrace-key # Optional (UI checks presence only)
109

11-
# Ragweld generation calls only the local LiteLLM gateway. Upstream provider
12-
# secrets belong in infra/litellm.env and are never loaded into the API.
10+
# Generation and OpenAI embeddings call the local LiteLLM gateway. Their upstream
11+
# provider secrets, including OPENAI_API_KEY, belong only in infra/litellm.env.
1312
LITELLM_BASE_URL=http://127.0.0.1:54000/v1
1413
LITELLM_API_KEY=sk-ragweld-local
1514

README.md

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -229,29 +229,30 @@ Each search method compensates for the others' weaknesses. The result: **dramati
229229

230230
## Performance
231231

232-
ragweld measures real pipeline latency and throughput via **Prometheus + Grafana** (see dashboards `tribrid-overview` and `tribrid-rag-metrics`). For reproducible local benchmarking (index + search), use the built-in benchmark runner.
232+
ragweld measures pipeline latency and throughput via **Prometheus + Grafana** (see dashboards `tribrid-overview` and `tribrid-rag-metrics`). The benchmark runner measures complete HTTP search requests against a running Ragweld API, including application processing and network time. Warmup requests are excluded from measured latency and throughput.
233233

234234
### Reproducible benchmark (index + search)
235235

236236
Prereqs:
237237

238238
```bash
239-
docker compose up -d postgres neo4j
240-
# If using the docker-compose defaults:
241-
export NEO4J_PASSWORD=password
239+
# Run on LXC100 against the already running API and a registered corpus.
240+
uv run python -m scripts.benchmark_perf \
241+
--api-base-url http://127.0.0.1:58012 \
242+
--corpus-id ragweld --skip-index --iterations 5 --warmup 1 \
243+
--query 'How does the indexing run fence prevent concurrent replacement?' \
244+
--out-json /var/tmp/ragweld-benchmark.json
242245
```
243246

244-
Run:
247+
To include indexing, omit `--skip-index`. The server uses the registered corpus path unless `--corpus-path` supplies another path on that server. Indexing uses the normal run fence, validation and promotion lifecycle. `--force-reindex` permits changed embedding settings; semantic graph indexing also requires `--approved-graph-schema-hash` with the exact reviewed schema hash.
245248

246-
```bash
247-
uv run scripts/benchmark_perf.py --corpus-id ragweld --corpus-path . --force-reindex --iterations 5 --warmup 1
248-
```
249+
The runner prints Markdown and writes JSON when `--out-json` is supplied. `--request-timeout` bounds each HTTP request (default 60 seconds); `--index-timeout` bounds waiting for the accepted run (default 3,600 seconds). A failed, cancelled or unfinished index produces no success report. A wait timeout leaves the server-owned job running, so inspect that corpus's run before starting another benchmark.
249250

250-
This prints **Markdown + JSON** summary you can paste into docs/PRs.
251+
`--out-json` replaces the selected report: after input validation, the runner removes the previous report before making API requests and publishes a complete JSON file only on success. A failed rerun therefore leaves no stale metrics at that path. Concurrent invocations using the same output path are rejected without changing the active writer's report.
251252

252253
### Latest benchmark (local dev run)
253254

254-
Generated on `2026-02-01` with the command above (vector+sparse+graph enabled, `final_k=10`).
255+
Historical internal-pipeline measurement from `2026-02-01` (vector+sparse+graph enabled, `final_k=10`); these values are not directly comparable to the current HTTP benchmark.
255256

256257
| Operation | Performance | Notes |
257258
|---|---:|---|
@@ -281,7 +282,7 @@ Treat the mainline status section above as the architecture truth for modernizat
281282
- Docker & Docker Compose
282283
- Python 3.11+ with [uv](https://github.com/astral-sh/uv)
283284
- Node.js 18+
284-
- API keys for your preferred embedding provider (OpenAI, Voyage, etc.)
285+
- Provider credentials for the configured cloud workflows; OpenAI embedding credentials belong to LiteLLM
285286

286287
### 1. Clone and Configure
287288

@@ -291,17 +292,37 @@ cd ragweld
291292
cp .env.example .env
292293
```
293294

294-
Edit `.env` with your API keys:
295+
The app's `.env` configures its gateway connection with `LITELLM_BASE_URL` and
296+
`LITELLM_API_KEY`. OpenAI embeddings and generation call LiteLLM; their upstream
297+
provider credentials belong in the gateway's private `infra/litellm.env`.
298+
299+
For a new install without an existing gateway environment file:
300+
295301
```bash
296-
OPENAI_API_KEY=sk-...
297-
# or
298-
VOYAGE_API_KEY=pa-...
302+
cp infra/litellm.env.example infra/litellm.env
303+
chmod 600 infra/litellm.env
299304
```
300305

306+
Edit that private file to replace `OPENAI_API_KEY=disabled` when enabling OpenAI
307+
embeddings. Preserve existing gateway settings and Langfuse credentials when
308+
updating an installation. Do not put `OPENAI_API_KEY` in the app's `.env` or
309+
export it into the app process. Compose passes the app's `LITELLM_API_KEY` to
310+
the gateway as `LITELLM_MASTER_KEY`; this gateway client credential is separate
311+
from the upstream OpenAI key.
312+
313+
On the Proxmox deployment, `.env` points to `/etc/ragweld/runtime.env` and
314+
`infra/litellm.env` points to `/etc/ragweld/litellm.env`. Update the existing
315+
owner-only files on LXC100 instead of replacing those symlinks. After changing
316+
the gateway environment, reconcile/recreate the `litellm` service through the
317+
deployment's Compose configuration during an idle interval. Restarting only the
318+
API does not reload the gateway environment. See
319+
[gateway credentials](docs/references/generation-gateway-catalog.md#gateway-credentials)
320+
and [Proxmox activation](docs/references/native-run-accounting.md#proxmox-activation).
321+
301322
### 2. Start Infrastructure
302323

303324
```bash
304-
docker compose up -d postgres neo4j
325+
docker compose --project-name ragweld up -d postgres neo4j qdrant litellm
305326
```
306327

307328
By default, Docker volumes are stored alongside the repo. To store DB data **outside** the repo (recommended for real corpora),
@@ -317,6 +338,7 @@ This starts:
317338
- **PostgreSQL** for corpus control/state rows and caches (port 5432)
318339
- **Qdrant** vector store for dense + sparse chunk vectors (port 56333)
319340
- **Neo4j** graph database (ports 7474, 7687)
341+
- **LiteLLM** gateway for generation and OpenAI embeddings (loopback port 54000)
320342

321343
### 2a. Start The Observability Overlay For This Branch
322344

@@ -350,6 +372,9 @@ uv run uvicorn server.main:app --reload --port 58012
350372
Notes:
351373
- The backend will **auto-load** repo-root `.env` on startup (dev convenience).
352374
- If you change `.env` while the backend is running, you must **restart** the backend for changes to take effect.
375+
- `GET /api/secrets/check?keys=LITELLM_API_KEY` checks only whether the app's
376+
gateway credential is present. It does not validate the key or inspect
377+
`OPENAI_API_KEY` in LiteLLM; upstream provider keys are outside this endpoint.
353378

354379
API available at http://localhost:58012
355380
OpenAPI docs at http://localhost:58012/docs

data/models.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5952,6 +5952,8 @@
59525952
"provider": "openai",
59535953
"family": "text-embedding-3-large",
59545954
"model": "text-embedding-3-large",
5955+
"gateway_alias": "openai.text-embedding-3-large",
5956+
"gateway_upstream": "openai/text-embedding-3-large",
59555957
"components": [
59565958
"EMB"
59575959
],
@@ -5969,6 +5971,8 @@
59695971
"provider": "openai",
59705972
"family": "text-embedding-3-small",
59715973
"model": "text-embedding-3-small",
5974+
"gateway_alias": "openai.text-embedding-3-small",
5975+
"gateway_upstream": "openai/text-embedding-3-small",
59725976
"components": [
59735977
"EMB"
59745978
],

docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,10 @@ services:
258258
- LITELLM_BASE_URL=http://litellm:4000/v1
259259
- LITELLM_API_KEY=${LITELLM_API_KEY:-sk-ragweld-local}
260260
- VLLM_BASE_URL=http://host.docker.internal:58080/v1
261+
- OPENAI_API_KEY=
261262
- OPENROUTER_API_KEY=
263+
- ANTHROPIC_API_KEY=
264+
- GOOGLE_API_KEY=
262265
env_file:
263266
- .env
264267
extra_hosts:

docs/references/config-control-plane.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,21 @@ OSS-composition branch.
7272
- `GET /api/secrets/check` now uses the registry-backed secret list rather than
7373
a hardcoded allowlist.
7474
- The workbench dependency panel is the operator-facing place to confirm whether
75-
required credentials are present.
75+
required app credentials are present.
76+
77+
OpenAI embeddings and generation authenticate to LiteLLM using the app's
78+
`LITELLM_API_KEY`; Compose supplies that credential to the gateway as
79+
`LITELLM_MASTER_KEY`. Upstream keys such as `OPENAI_API_KEY` belong only in the
80+
gateway's private `infra/litellm.env`, outside the app registry and browser secret
81+
controls. See [gateway credentials](generation-gateway-catalog.md#gateway-credentials)
82+
for the Proxmox file mapping and required gateway recreation after an env change.
83+
84+
For an app-side presence check on LXC100:
85+
86+
```bash
87+
curl -sS "http://127.0.0.1:58012/api/secrets/check?keys=LITELLM_API_KEY" | jq .
88+
```
89+
90+
This returns presence only, never a credential value or proof that the gateway
91+
accepts the key. Requesting `OPENAI_API_KEY` here returns an unsupported-secret
92+
error; it cannot check the gateway's upstream key or establish provider readiness.

0 commit comments

Comments
 (0)