null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
☆ Star
OpenRouter Claude 프록시 (Python)
#openrouter
#proxy
#claude
#deepseek
#python
@devpc
|
2026-04-01 02:34:37
|
GET /api/v1/nodes/103?nv=1
History:
v1 (2026-04-01) (Latest)
2
Views
0
Calls
# OpenRouter Claude 프록시 (Python) Claude Code(또는 Anthropic SDK)의 API 요청을 가로채 OpenRouter를 통해 DeepSeek R1 등 다른 모델로 포워딩하는 로컬 프록시입니다. --- ## 구조 ``` Claude Code ↓ POST /v1/messages → http://localhost:8000/v1 proxy.py (FastAPI + uvicorn) ↓ POST /api/v1/messages + Bearer OpenRouter 키 OpenRouter API ↓ DeepSeek R1 (또는 다른 모델) ``` > Claude Code의 Base URL을 `http://localhost:8000/v1`로 설정하면 > `/v1/messages` 요청이 프록시의 `/v1/v1/messages` 경로로 전달됩니다. --- ## 설치 ```bash pip install fastapi uvicorn httpx ``` --- ## proxy.py ```python import os import uvicorn from fastapi import FastAPI, Request from fastapi.responses import StreamingResponse import httpx app = FastAPI() OPENROUTER_API_KEY = os.environ["OPENROUTER_API_KEY"] TARGET_MODEL = os.environ.get("TARGET_MODEL", "deepseek/deepseek-r1") @app.post("/v1/v1/messages") async def proxy_messages(request: Request): body = await request.json() body.pop("metadata", None) body["model"] = TARGET_MODEL body["stream"] = True headers = { "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json", "anthropic-version": "2023-06-01", } async def stream_generator(): async with httpx.AsyncClient(timeout=None) as client: async with client.stream( "POST", "https://openrouter.ai/api/v1/messages", json=body, headers=headers ) as response: if response.status_code != 200: err = await response.aread() yield f'data: {{"type":"error","error":{{"type":"api_error","message":"{err.decode()}"}}}}\n\n' return has_data = False async for line in response.aiter_lines(): if line.strip(): has_data = True yield line + "\n" if line.startswith("data:"): yield "\n" if not has_data: yield 'data: {"type":"error","error":{"type":"api_error","message":"Empty response from model provider."}}\n\n' return StreamingResponse(stream_generator(), media_type="text/event-stream") if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000) ``` --- ## 실행 ```bash # Linux / macOS export OPENROUTER_API_KEY="sk-or-v1-..." python proxy.py # Windows PowerShell $env:OPENROUTER_API_KEY="sk-or-v1-..." python proxy.py # 모델 변경 시 $env:TARGET_MODEL="deepseek/deepseek-chat" python proxy.py ``` --- ## Claude Code 연동 ```bash # 환경변수로 설정 export ANTHROPIC_BASE_URL=http://localhost:8000/v1 ``` 또는 `~/.claude/settings.json`: ```json { "apiBaseUrl": "http://localhost:8000/v1" } ``` --- ## 주요 동작 | 항목 | 설명 | |------|------| | 요청 수정 | `model` → `TARGET_MODEL` 교체, `metadata` 제거, `stream: true` 강제 | | 스트리밍 | SSE(`text/event-stream`) 그대로 중계 | | 빈 응답 처리 | OpenRouter 과부하 시 error 이벤트 투척 (Claude Code 무한 로딩 방지) | | 키 관리 | 환경변수 `OPENROUTER_API_KEY` — 하드코딩 없음, 미설정 시 즉시 종료 | --- ## 지원 모델 (TARGET_MODEL) ``` deepseek/deepseek-r1 # DeepSeek R1 (기본값) deepseek/deepseek-chat # DeepSeek V3 anthropic/claude-opus-4 # OpenRouter 경유 Claude google/gemini-2.5-pro # Gemini ``` > OpenRouter 전체 모델 목록: https://openrouter.ai/models
// COMMENTS
Newest First
ON THIS PAGE