Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ---
- Self-Hosted Code Interpreter for LibreChat
- Overview
- This is a drop-in replacement for LibreChat's hosted code interpreter (code.librechat.ai). Instead of sending code to an external service, you run a local FastAPI server that executes Python code in secure Docker containers.
- Architecture
- ┌─────────────────────────────────────────────────────────────────────┐
- │ LibreChat │
- │ (Agents use @librechat/agents which calls your code interpreter) │
- └───────────────────────────────┬─────────────────────────────────────┘
- │ HTTP API
- ▼
- ┌─────────────────────────────────────────────────────────────────────┐
- │ qwen_code_api.py (FastAPI) │
- │ Running on port 8095 │
- │ │
- │ • Receives code execution requests │
- │ • Manages sessions & user isolation │
- │ • Spawns Docker containers for each execution │
- │ • Returns stdout, stderr, and output files │
- └───────────────────────────────┬─────────────────────────────────────┘
- │ Docker API
- ▼
- ┌─────────────────────────────────────────────────────────────────────┐
- │ Docker Container (qwen-sandbox:latest) │
- │ │
- │ ┌───────────────────────────────────────────────────────────────┐ │
- │ │ SECURITY CONSTRAINTS: │ │
- │ │ • network_mode="none" (no internet access) │ │
- │ │ • mem_limit="256m" (memory cap) │ │
- │ │ • pids_limit=50 (prevent fork bombs) │ │
- │ │ • read_only=True (immutable root filesystem) │ │
- │ │ • no-new-privileges (no privilege escalation) │ │
- │ │ • 120 second timeout (execution time limit) │ │
- │ └───────────────────────────────────────────────────────────────┘ │
- │ │
- │ /workspace (read-write mount) ←→ Host session directory │
- │ │
- │ Pre-installed: numpy, pandas, matplotlib, seaborn, scipy, │
- │ scikit-learn, python-pptx, graphviz, pillow, etc. │
- └─────────────────────────────────────────────────────────────────────┘
- Why Build This?
- 1. Privacy: Code never leaves your infrastructure
- 2. Customization: Add any Python packages you need
- 3. No rate limits: Execute as much as you want
- 4. Cost: No per-execution fees
- 5. Control: Full visibility into what's running
- ---
- API Endpoints (LibreChat Compatible)
- The API matches LibreChat's @librechat/agents expectations exactly:
- | Endpoint | Method | Description |
- |--------------------------------------|--------|------------------------------------------|
- | /exec | POST | Execute code, return stdout/stderr/files |
- | /upload | POST | Upload file to session |
- | /files/{session_id} | GET | List files in session |
- | /download/{session_id}/{file_id} | GET | Download file (browser) |
- | /file/{session_id}/{file_id}/content | GET | Get file as base64 (for MCP) |
- | /sessions/{session_id} | DELETE | Clean up session |
- | /health | GET | Health check |
- Execute Code Request
- POST /exec
- {
- "code": "import pandas as pd\ndf = pd.DataFrame({'a': [1,2,3]})\nprint(df)",
- "lang": "python",
- "session_id": "optional-session-id",
- "entity_id": "user-123"
- }
- Execute Code Response
- {
- "stdout": " a\n0 1\n1 2\n2 3\n",
- "stderr": "",
- "files": [
- {"name": "output.png", "id": "uuid-here"}
- ],
- "session_id": "generated-or-provided-session-id"
- }
- ---
- Security Model
- Container Isolation
- Every code execution runs in a fresh Docker container with strict constraints:
- container = client.containers.run(
- image="qwen-sandbox:latest",
- command=["python", "/workspace/_exec.py"],
- # === SECURITY ===
- network_mode="none", # No network access AT ALL
- mem_limit="256m", # Max 256MB RAM
- memswap_limit="256m", # No swap
- pids_limit=50, # Prevent fork bombs
- read_only=True, # Read-only root filesystem
- security_opt=["no-new-privileges"],
- # Only /workspace is writable (for output files)
- volumes={workspace: {"bind": "/workspace", "mode": "rw"}}
- )
- What This Prevents
- | Attack | Protection |
- |-------------------|-----------------------------------------------|
- | Data exfiltration | network_mode="none" - no outbound connections |
- | Crypto mining | No network + memory limits |
- | Fork bombs | pids_limit=50 |
- | Disk filling | Read-only root, limited workspace |
- | Container escape | no-new-privileges, non-root user |
- | Infinite loops | 120 second timeout |
- | Memory exhaustion | 256MB hard limit |
- User Isolation
- Each user (identified by entity_id) gets isolated file storage:
- /tmp/qwen_code/
- ├── shared_uploads/
- │ ├── user-123/ # User 123's persistent files
- │ │ ├── template.pptx
- │ │ └── data.csv
- │ └── user-456/ # User 456's files (isolated)
- │ └── report.xlsx
- ├── {session-uuid-1}/ # Temporary session workspace
- ├── {session-uuid-2}/ # Another session
- └── ...
- - Users cannot see each other's files
- - Files persist across sessions for the same user
- - Automatic cleanup removes old sessions (default: 24 hours)
- ---
- The Docker Sandbox Image
- Dockerfile
- FROM python:3.11-slim
- # Environment variables to prevent sandbox errors
- ENV MPLCONFIGDIR=/workspace
- ENV MPLBACKEND=Agg
- ENV XDG_CACHE_HOME=/workspace/.cache
- ENV OPENBLAS_NUM_THREADS=1
- ENV OMP_NUM_THREADS=1
- ENV PYTHONUNBUFFERED=1
- # Install system dependencies
- RUN apt-get update && apt-get install -y --no-install-recommends \
- graphviz \
- fonts-dejavu \
- fonts-liberation \
- fontconfig \
- && rm -rf /var/lib/apt/lists/* \
- && fc-cache -f
- # Install Python packages
- RUN pip install --no-cache-dir \
- numpy \
- pandas \
- matplotlib \
- seaborn \
- scipy \
- scikit-learn \
- openpyxl \
- xlrd \
- requests \
- beautifulsoup4 \
- lxml \
- pillow \
- sympy \
- python-pptx \
- graphviz
- # Create /mnt/data symlink for LibreChat compatibility
- RUN mkdir -p /mnt && ln -s /workspace /mnt/data
- # Create non-root user for extra security
- RUN useradd -m -s /bin/bash sandbox
- USER sandbox
- WORKDIR /workspace
- Key Design Decisions
- 1. Non-root user: Container runs as sandbox user, not root
- 2. Professional fonts: Liberation Sans/DejaVu for clean charts and diagrams
- 3. Graphviz: Enables mind maps, flowcharts, org charts
- 4. python-pptx: PowerPoint generation with corporate templates
- 5. No network packages active: requests/beautifulsoup4 are installed but can't reach the internet due to network_mode="none"
- ---
- How to Connect to LibreChat
- 1. Build the Docker Image
- cd services/qwen-code-interpreter
- docker build -t qwen-sandbox:latest .
- 2. Start the API Server
- pip install fastapi uvicorn docker pydantic
- python qwen_code_api.py --port 8095
- 3. Configure LibreChat
- In your LibreChat .env or configuration:
- # Point to your self-hosted code interpreter
- LIBRECHAT_CODE_API_URL=http://localhost:8095
- LIBRECHAT_CODE_API_KEY=your-secret-key
- Or in librechat.yaml for agents:
- endpoints:
- agents:
- codeInterpreter:
- url: "http://localhost:8095"
- apiKey: "${LIBRECHAT_CODE_API_KEY}"
- ---
- Configuration Options
- All configurable via environment variables:
- | Variable | Default | Description |
- |--------------------------|---------------------------------------------|---------------------------------------|
- | LIBRECHAT_CODE_API_KEY | qwen-sandbox-dev-key | API authentication key |
- | QWEN_CODE_WORK_DIR | /tmp/qwen_code | Base directory for sessions |
- | CODE_EXEC_TIMEOUT | 120 | Execution timeout in seconds |
- | SESSION_MAX_AGE_HOURS | 24 | Auto-cleanup sessions older than this |
- | CLEANUP_INTERVAL_MINUTES | 60 | How often cleanup runs |
- | MAX_UPLOAD_SIZE | 52428800 (50MB) | Max file upload size |
- | MAX_BASE64_SIZE | 26214400 (25MB) | Max file size for base64 endpoint |
- | CORS_ORIGINS | http://localhost:3080,http://localhost:3000 | Allowed CORS origins |
- ---
- Advanced: MCP Integration for Email/OneDrive
- The /file/{session_id}/{file_id}/content endpoint returns base64-encoded files, enabling this workflow:
- 1. Agent executes code → creates PowerPoint
- 2. Agent calls /file/.../content → gets base64
- 3. Agent calls M365 MCP → uploads to user's OneDrive
- 4. Agent calls M365 MCP → sends email with share link
- This lets each user authenticate with their own Microsoft 365 account.
- ---
- Example Capabilities
- Create Charts
- import matplotlib.pyplot as plt
- import pandas as pd
- df = pd.DataFrame({'Month': ['Jan','Feb','Mar'], 'Sales': [100, 150, 200]})
- plt.bar(df['Month'], df['Sales'])
- plt.savefig('sales_chart.png', dpi=150)
- Generate PowerPoints
- from pptx import Presentation
- from pptx.util import Inches
- prs = Presentation('corporate_template.pptx') # User uploads template
- slide = prs.slides.add_slide(prs.slide_layouts[1])
- slide.shapes.title.text = "Q4 Results"
- prs.save('quarterly_report.pptx')
- Create Mind Maps
- from graphviz import Digraph
- mind_map = Digraph('MindMap', format='png')
- mind_map.attr('node', shape='box', style='rounded,filled',
- fontname='Liberation Sans')
- mind_map.node('center', 'Main Topic', fillcolor='gold')
- mind_map.node('a', 'Subtopic A')
- mind_map.edge('center', 'a')
- mind_map.render('/workspace/mindmap', cleanup=True)
- Data Analysis
- import pandas as pd
- from sklearn.linear_model import LinearRegression
- df = pd.read_csv('sales_data.csv') # User uploads CSV
- model = LinearRegression().fit(df[['marketing_spend']], df['revenue'])
- print(f"Revenue per $1 marketing: ${model.coef_[0]:.2f}")
- ---
- File Structure
- services/qwen-code-interpreter/
- ├── qwen_code_api.py # FastAPI server (680 lines)
- ├── Dockerfile # Sandbox image definition
- └── README.md # This documentation
- ---
- Summary
- This self-hosted code interpreter gives you:
- - Full LibreChat compatibility - drop-in replacement
- - Maximum security - air-gapped containers, non-root, resource limits
- - User isolation - multi-tenant safe
- - Rich capabilities - data science, visualization, document generation
- - MCP integration - bridge to external services like Office 365
- - Zero external dependencies - runs entirely on your infrastructure
Add Comment
Please, Sign In to add comment