Guest User

Untitled

a guest
Dec 15th, 2025
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.47 KB | None | 0 0
  1. ---
  2. Self-Hosted Code Interpreter for LibreChat
  3.  
  4. Overview
  5.  
  6. 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.
  7.  
  8. Architecture
  9.  
  10. ┌─────────────────────────────────────────────────────────────────────┐
  11. │ LibreChat │
  12. │ (Agents use @librechat/agents which calls your code interpreter) │
  13. └───────────────────────────────┬─────────────────────────────────────┘
  14. │ HTTP API
  15. ┌─────────────────────────────────────────────────────────────────────┐
  16. │ qwen_code_api.py (FastAPI) │
  17. │ Running on port 8095 │
  18. │ │
  19. │ • Receives code execution requests │
  20. │ • Manages sessions & user isolation │
  21. │ • Spawns Docker containers for each execution │
  22. │ • Returns stdout, stderr, and output files │
  23. └───────────────────────────────┬─────────────────────────────────────┘
  24. │ Docker API
  25. ┌─────────────────────────────────────────────────────────────────────┐
  26. │ Docker Container (qwen-sandbox:latest) │
  27. │ │
  28. │ ┌───────────────────────────────────────────────────────────────┐ │
  29. │ │ SECURITY CONSTRAINTS: │ │
  30. │ │ • network_mode="none" (no internet access) │ │
  31. │ │ • mem_limit="256m" (memory cap) │ │
  32. │ │ • pids_limit=50 (prevent fork bombs) │ │
  33. │ │ • read_only=True (immutable root filesystem) │ │
  34. │ │ • no-new-privileges (no privilege escalation) │ │
  35. │ │ • 120 second timeout (execution time limit) │ │
  36. │ └───────────────────────────────────────────────────────────────┘ │
  37. │ │
  38. │ /workspace (read-write mount) ←→ Host session directory │
  39. │ │
  40. │ Pre-installed: numpy, pandas, matplotlib, seaborn, scipy, │
  41. │ scikit-learn, python-pptx, graphviz, pillow, etc. │
  42. └─────────────────────────────────────────────────────────────────────┘
  43.  
  44. Why Build This?
  45.  
  46. 1. Privacy: Code never leaves your infrastructure
  47. 2. Customization: Add any Python packages you need
  48. 3. No rate limits: Execute as much as you want
  49. 4. Cost: No per-execution fees
  50. 5. Control: Full visibility into what's running
  51.  
  52. ---
  53. API Endpoints (LibreChat Compatible)
  54.  
  55. The API matches LibreChat's @librechat/agents expectations exactly:
  56.  
  57. | Endpoint | Method | Description |
  58. |--------------------------------------|--------|------------------------------------------|
  59. | /exec | POST | Execute code, return stdout/stderr/files |
  60. | /upload | POST | Upload file to session |
  61. | /files/{session_id} | GET | List files in session |
  62. | /download/{session_id}/{file_id} | GET | Download file (browser) |
  63. | /file/{session_id}/{file_id}/content | GET | Get file as base64 (for MCP) |
  64. | /sessions/{session_id} | DELETE | Clean up session |
  65. | /health | GET | Health check |
  66.  
  67. Execute Code Request
  68.  
  69. POST /exec
  70. {
  71. "code": "import pandas as pd\ndf = pd.DataFrame({'a': [1,2,3]})\nprint(df)",
  72. "lang": "python",
  73. "session_id": "optional-session-id",
  74. "entity_id": "user-123"
  75. }
  76.  
  77. Execute Code Response
  78.  
  79. {
  80. "stdout": " a\n0 1\n1 2\n2 3\n",
  81. "stderr": "",
  82. "files": [
  83. {"name": "output.png", "id": "uuid-here"}
  84. ],
  85. "session_id": "generated-or-provided-session-id"
  86. }
  87.  
  88. ---
  89. Security Model
  90.  
  91. Container Isolation
  92.  
  93. Every code execution runs in a fresh Docker container with strict constraints:
  94.  
  95. container = client.containers.run(
  96. image="qwen-sandbox:latest",
  97. command=["python", "/workspace/_exec.py"],
  98.  
  99. # === SECURITY ===
  100. network_mode="none", # No network access AT ALL
  101. mem_limit="256m", # Max 256MB RAM
  102. memswap_limit="256m", # No swap
  103. pids_limit=50, # Prevent fork bombs
  104. read_only=True, # Read-only root filesystem
  105. security_opt=["no-new-privileges"],
  106.  
  107. # Only /workspace is writable (for output files)
  108. volumes={workspace: {"bind": "/workspace", "mode": "rw"}}
  109. )
  110.  
  111. What This Prevents
  112.  
  113. | Attack | Protection |
  114. |-------------------|-----------------------------------------------|
  115. | Data exfiltration | network_mode="none" - no outbound connections |
  116. | Crypto mining | No network + memory limits |
  117. | Fork bombs | pids_limit=50 |
  118. | Disk filling | Read-only root, limited workspace |
  119. | Container escape | no-new-privileges, non-root user |
  120. | Infinite loops | 120 second timeout |
  121. | Memory exhaustion | 256MB hard limit |
  122.  
  123. User Isolation
  124.  
  125. Each user (identified by entity_id) gets isolated file storage:
  126.  
  127. /tmp/qwen_code/
  128. ├── shared_uploads/
  129. │ ├── user-123/ # User 123's persistent files
  130. │ │ ├── template.pptx
  131. │ │ └── data.csv
  132. │ └── user-456/ # User 456's files (isolated)
  133. │ └── report.xlsx
  134. ├── {session-uuid-1}/ # Temporary session workspace
  135. ├── {session-uuid-2}/ # Another session
  136. └── ...
  137.  
  138. - Users cannot see each other's files
  139. - Files persist across sessions for the same user
  140. - Automatic cleanup removes old sessions (default: 24 hours)
  141.  
  142. ---
  143. The Docker Sandbox Image
  144.  
  145. Dockerfile
  146.  
  147. FROM python:3.11-slim
  148.  
  149. # Environment variables to prevent sandbox errors
  150. ENV MPLCONFIGDIR=/workspace
  151. ENV MPLBACKEND=Agg
  152. ENV XDG_CACHE_HOME=/workspace/.cache
  153. ENV OPENBLAS_NUM_THREADS=1
  154. ENV OMP_NUM_THREADS=1
  155. ENV PYTHONUNBUFFERED=1
  156.  
  157. # Install system dependencies
  158. RUN apt-get update && apt-get install -y --no-install-recommends \
  159. graphviz \
  160. fonts-dejavu \
  161. fonts-liberation \
  162. fontconfig \
  163. && rm -rf /var/lib/apt/lists/* \
  164. && fc-cache -f
  165.  
  166. # Install Python packages
  167. RUN pip install --no-cache-dir \
  168. numpy \
  169. pandas \
  170. matplotlib \
  171. seaborn \
  172. scipy \
  173. scikit-learn \
  174. openpyxl \
  175. xlrd \
  176. requests \
  177. beautifulsoup4 \
  178. lxml \
  179. pillow \
  180. sympy \
  181. python-pptx \
  182. graphviz
  183.  
  184. # Create /mnt/data symlink for LibreChat compatibility
  185. RUN mkdir -p /mnt && ln -s /workspace /mnt/data
  186.  
  187. # Create non-root user for extra security
  188. RUN useradd -m -s /bin/bash sandbox
  189. USER sandbox
  190.  
  191. WORKDIR /workspace
  192.  
  193. Key Design Decisions
  194.  
  195. 1. Non-root user: Container runs as sandbox user, not root
  196. 2. Professional fonts: Liberation Sans/DejaVu for clean charts and diagrams
  197. 3. Graphviz: Enables mind maps, flowcharts, org charts
  198. 4. python-pptx: PowerPoint generation with corporate templates
  199. 5. No network packages active: requests/beautifulsoup4 are installed but can't reach the internet due to network_mode="none"
  200.  
  201. ---
  202. How to Connect to LibreChat
  203.  
  204. 1. Build the Docker Image
  205.  
  206. cd services/qwen-code-interpreter
  207. docker build -t qwen-sandbox:latest .
  208.  
  209. 2. Start the API Server
  210.  
  211. pip install fastapi uvicorn docker pydantic
  212. python qwen_code_api.py --port 8095
  213.  
  214. 3. Configure LibreChat
  215.  
  216. In your LibreChat .env or configuration:
  217.  
  218. # Point to your self-hosted code interpreter
  219. LIBRECHAT_CODE_API_URL=http://localhost:8095
  220. LIBRECHAT_CODE_API_KEY=your-secret-key
  221.  
  222. Or in librechat.yaml for agents:
  223.  
  224. endpoints:
  225. agents:
  226. codeInterpreter:
  227. url: "http://localhost:8095"
  228. apiKey: "${LIBRECHAT_CODE_API_KEY}"
  229.  
  230. ---
  231. Configuration Options
  232.  
  233. All configurable via environment variables:
  234.  
  235. | Variable | Default | Description |
  236. |--------------------------|---------------------------------------------|---------------------------------------|
  237. | LIBRECHAT_CODE_API_KEY | qwen-sandbox-dev-key | API authentication key |
  238. | QWEN_CODE_WORK_DIR | /tmp/qwen_code | Base directory for sessions |
  239. | CODE_EXEC_TIMEOUT | 120 | Execution timeout in seconds |
  240. | SESSION_MAX_AGE_HOURS | 24 | Auto-cleanup sessions older than this |
  241. | CLEANUP_INTERVAL_MINUTES | 60 | How often cleanup runs |
  242. | MAX_UPLOAD_SIZE | 52428800 (50MB) | Max file upload size |
  243. | MAX_BASE64_SIZE | 26214400 (25MB) | Max file size for base64 endpoint |
  244. | CORS_ORIGINS | http://localhost:3080,http://localhost:3000 | Allowed CORS origins |
  245.  
  246. ---
  247. Advanced: MCP Integration for Email/OneDrive
  248.  
  249. The /file/{session_id}/{file_id}/content endpoint returns base64-encoded files, enabling this workflow:
  250.  
  251. 1. Agent executes code → creates PowerPoint
  252. 2. Agent calls /file/.../content → gets base64
  253. 3. Agent calls M365 MCP → uploads to user's OneDrive
  254. 4. Agent calls M365 MCP → sends email with share link
  255.  
  256. This lets each user authenticate with their own Microsoft 365 account.
  257.  
  258. ---
  259. Example Capabilities
  260.  
  261. Create Charts
  262.  
  263. import matplotlib.pyplot as plt
  264. import pandas as pd
  265.  
  266. df = pd.DataFrame({'Month': ['Jan','Feb','Mar'], 'Sales': [100, 150, 200]})
  267. plt.bar(df['Month'], df['Sales'])
  268. plt.savefig('sales_chart.png', dpi=150)
  269.  
  270. Generate PowerPoints
  271.  
  272. from pptx import Presentation
  273. from pptx.util import Inches
  274.  
  275. prs = Presentation('corporate_template.pptx') # User uploads template
  276. slide = prs.slides.add_slide(prs.slide_layouts[1])
  277. slide.shapes.title.text = "Q4 Results"
  278. prs.save('quarterly_report.pptx')
  279.  
  280. Create Mind Maps
  281.  
  282. from graphviz import Digraph
  283.  
  284. mind_map = Digraph('MindMap', format='png')
  285. mind_map.attr('node', shape='box', style='rounded,filled',
  286. fontname='Liberation Sans')
  287. mind_map.node('center', 'Main Topic', fillcolor='gold')
  288. mind_map.node('a', 'Subtopic A')
  289. mind_map.edge('center', 'a')
  290. mind_map.render('/workspace/mindmap', cleanup=True)
  291.  
  292. Data Analysis
  293.  
  294. import pandas as pd
  295. from sklearn.linear_model import LinearRegression
  296.  
  297. df = pd.read_csv('sales_data.csv') # User uploads CSV
  298. model = LinearRegression().fit(df[['marketing_spend']], df['revenue'])
  299. print(f"Revenue per $1 marketing: ${model.coef_[0]:.2f}")
  300.  
  301. ---
  302. File Structure
  303.  
  304. services/qwen-code-interpreter/
  305. ├── qwen_code_api.py # FastAPI server (680 lines)
  306. ├── Dockerfile # Sandbox image definition
  307. └── README.md # This documentation
  308.  
  309. ---
  310. Summary
  311.  
  312. This self-hosted code interpreter gives you:
  313.  
  314. - Full LibreChat compatibility - drop-in replacement
  315. - Maximum security - air-gapped containers, non-root, resource limits
  316. - User isolation - multi-tenant safe
  317. - Rich capabilities - data science, visualization, document generation
  318. - MCP integration - bridge to external services like Office 365
  319. - Zero external dependencies - runs entirely on your infrastructure
Add Comment
Please, Sign In to add comment