Skip to main content

OpenAI-compatible LLM proxy with SQLite request capture, observability, and an admin UI.

Project description

LLM Observe Proxy

llm-observe-proxy is an OpenAI-compatible, record-only proxy for inspecting LLM traffic. It forwards requests to an upstream /v1 API, stores requests and responses in SQLite, and provides a polished local admin UI for browsing, pretty-printing, trimming, and changing runtime settings.

It is useful when you want LiteLLM-style observability without introducing a full gateway or external database.

Published package: https://pypi.org/project/llm-observe-proxy/

Features

  • OpenAI-compatible passthrough route: ANY /v1/{path:path}.
  • SQLite capture for request/response headers, bodies, status, timing, model, endpoint, streaming state, tool-call signals, image assets, and errors.
  • Admin UI for searching and browsing captured traffic.
  • Detail pages with response render modes for JSON, plain text, Markdown, tool calls, and raw SSE streams.
  • Request image gallery for data URL and remote image references.
  • Settings UI for upstream URL, incoming host/port preferences, all-IPs exposure, and retention trimming.
  • No authentication by default, intended for local or trusted development networks.

Install

From PyPI with pip:

python -m pip install llm-observe-proxy
llm-observe-proxy

From PyPI with uv:

uv tool install llm-observe-proxy
llm-observe-proxy

Run it once without installing:

uvx llm-observe-proxy

For local development from this repository:

C:\Python\Python313\python.exe -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e .[dev]
.\.venv\Scripts\llm-observe-proxy.exe

By default, the proxy listens on:

http://localhost:8080

and forwards requests to:

http://localhost:8000/v1

Open the admin UI:

http://localhost:8080/admin

Usage

Point an OpenAI-compatible client at the proxy:

from openai import OpenAI

client = OpenAI(
    api_key="local-dev-key",
    base_url="http://localhost:8080/v1",
)

response = client.chat.completions.create(
    model="gpt-demo",
    messages=[{"role": "user", "content": "Hello through the proxy"}],
)
print(response.choices[0].message.content)

Run on a different port:

llm-observe-proxy --port 8090

Expose on all interfaces:

llm-observe-proxy --expose-all-ips

Set the upstream from the CLI:

llm-observe-proxy --upstream-url http://localhost:8000/v1

You can also change the upstream URL and next-start incoming host/port settings from /admin/settings.

Screenshots

Screenshots are generated from a seeded demo database and stored in docs/screenshots.

Request browser Tool calls
Request browser Tool-call detail
Images Settings
Image request detail Settings

Additional screenshots:

Regenerate screenshots:

.\.venv\Scripts\python.exe scripts\seed_demo_db.py .tmp\screenshots.sqlite3
.\.venv\Scripts\python.exe scripts\capture_screenshots.py --database .tmp\screenshots.sqlite3 --output docs\screenshots

Routes

  • ANY /v1/{path:path}: OpenAI-compatible pass-through proxy.
  • GET /admin: request browser.
  • GET /admin/requests/{id}: request/response detail view.
  • GET /admin/settings: upstream settings and retention tools.
  • POST /admin/settings/incoming: update incoming host/port settings for next startup.
  • POST /admin/settings/upstream: update upstream URL.
  • POST /admin/trim: delete records older than N days.
  • GET /healthz: health check.

Configuration

Environment variables:

Variable Default Purpose
LLM_OBSERVE_DATABASE_URL sqlite:///./llm_observe_proxy.sqlite3 SQLite SQLAlchemy URL.
LLM_OBSERVE_INCOMING_HOST localhost Bind host when not exposing all IPs.
LLM_OBSERVE_INCOMING_PORT 8080 Bind port.
LLM_OBSERVE_EXPOSE_ALL_IPS false Bind to 0.0.0.0 when true.
LLM_OBSERVE_UPSTREAM_URL http://localhost:8000/v1 Upstream OpenAI-compatible /v1 base URL.
LLM_OBSERVE_LOG_LEVEL INFO Uvicorn log level.

Incoming host/port settings saved in the UI are used on the next process startup; they do not rebind a currently running process.

Tests

.\.venv\Scripts\ruff.exe check src tests
.\.venv\Scripts\python.exe -m compileall -q src tests
.\.venv\Scripts\pytest.exe -q

The test suite starts a fake upstream on localhost:8080/v1, so stop any local process using port 8080 before running tests. See docs/tests/README.md for the full coverage matrix.

Publishing

See docs/publishing.md for name checks, build commands, and the pre-publish checklist.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

llm_observe_proxy-0.1.1.tar.gz (454.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

llm_observe_proxy-0.1.1-py3-none-any.whl (28.0 kB view details)

Uploaded Python 3

File details

Details for the file llm_observe_proxy-0.1.1.tar.gz.

File metadata

  • Download URL: llm_observe_proxy-0.1.1.tar.gz
  • Upload date:
  • Size: 454.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for llm_observe_proxy-0.1.1.tar.gz
Algorithm Hash digest
SHA256 7200aca32f6e9f541e0068cb69dc8414df28fa890d87a2ae361a34cd98b57ccb
MD5 8ff6d10314572885d027c62fe0396996
BLAKE2b-256 92ac3c635d3c66f834fb698c81d86d3299da3f8c45b8c87545dbc2066e449f85

See more details on using hashes here.

File details

Details for the file llm_observe_proxy-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for llm_observe_proxy-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9bc63668806181b49d4b23b49213f8f7cb528383154dae2a611c29934f3e36e8
MD5 1445044d574e02d9c6613841cc2f79ac
BLAKE2b-256 930e410c8d135b795577a0be9ba4f731c724192c7f40df602e679a078786b456

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page