A FastAPI-based proxy for LLM API calls designed to clean and normalize outputs from models like LM Studio. It strips reasoning/thinking tags from model responses while preserving the actual content.
Version: 1.0.5
Status: Stable
- Chat Completions Proxy — Full OpenAI-compatible
/v1/chat/completionsendpoint with streaming support - Reasoning Tag Removal — Automatically removes
<reasoning>,<thinking>, and<thought>tags (case-insensitive, multiline) from model outputs - Markdown Code Block Cleanup — Strips markdown code fences that break JSON parsers in streaming responses
- Smart Streaming Buffering — Accumulates raw content during reasoning tag blocks, then yields only clean tokens once actual output appears
- Reasoning Content Promotion — If main
contentis empty butreasoning_contenthas output, promotes it to the primary response field - Embeddings Passthrough — Raw
/v1/embeddingsendpoint with no transformation - Models Listing —
/v1/modelsendpoint reflecting upstream model catalog - Health Check —
/healthendpoint for load balancers and monitoring (includes version and timestamp)
- Python 3.10+
- Docker & Docker Compose (recommended)
docker compose up --build -dThe proxy will be available at http://localhost:9090.
| Environment Variable | Default Value | Description |
|---|---|---|
LM_STUDIO_URL |
http://host.docker.internal:1234/v1 |
Upstream LLM API endpoint |
SOURCE_DATE_EPOCH |
Current timestamp | Fixed epoch for reproducible builds (optional) |
curl -X POST http://localhost:9090/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [
{"role": "user", "content": "What is 2+2?"}
],
"stream": false
}'curl -X POST http://localhost:9090/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [
{"role": "user", "content": "Write a poem about cats."}
],
"stream": true
}'curl -X POST http://localhost:9090/v1/embeddings \
-H "Content-Type: application/json" \
-d '{
"model": "text-embedding-3-large",
"input": "Hello world"
}'curl http://localhost:9090/v1/modelscurl http://localhost:9090/health
# Returns:
# {"status": "ok", "version": "1.0.5", "timestamp": "..."}The proxy applies the following transformations in order:
- Tag Removal — Strips all
<reasoning>,<thinking>, and<thought>tags (case-insensitive, handles multiline content) - Markdown Fence Removal — Removes leading/trailing
json orblocks that may appear in streaming responses - Whitespace Normalization — Trims leading/trailing whitespace from final output
# Install dependencies
pip install fastapi httpx uvicorn[standard]
# Run locally
uvicorn proxy:app --host 0.0.0.0 --port 8080--
- Added structured logging: Replaced
print()statements with proper Pythonloggingmodule for production-ready diagnostics - Improved error handling: Added validation and graceful degradation on malformed JSON requests
- Enhanced observability: All errors, warnings, and info events now include timestamps and log levels
- Fixed
/v1/embeddingspassthrough: Switched to raw request/response forwarding to prevent local JSON parsing errors (400 Bad Request) and ensure data integrity for large payloads. - Updated documentation to reflect raw passthrough behavior.
- Increased request timeouts from 60s to 300s (5 minutes) to prevent
ReadTimeouterrors with slower local models or large context windows - Improved stream error logging to display actual exception types for easier debugging
- Added passthrough support for
/v1/embeddingsendpoint (embedding models)
- Core proxy functionality with tag removal
- Streaming and non-streaming support
- Smart buffering for streaming responses
- Content promotion from reasoning_content
- Docker containerization with compose setup
MIT