feat: AI proxy via papa-app (Anthropic from RU), env and docker-compose
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
25be90de7b
commit
9d49c9bb6b
@ -7,3 +7,9 @@ NODE_ENV=development
|
||||
# AI — Anthropic Claude (единственный AI-провайдер). Бэкенд: ANTHROPIC_API_KEY
|
||||
# OPENAI_API_KEY не используется
|
||||
ANTHROPIC_API_KEY=
|
||||
|
||||
# Прокси Anthropic через papa-app на Railway (если Anthropic блокирует с РФ IP)
|
||||
# AI_PROXY_URL=https://papa-app-production.up.railway.app/api/proxy/anthropic
|
||||
# AI_PROXY_SECRET=klg-refly-proxy-2026
|
||||
AI_PROXY_URL=
|
||||
AI_PROXY_SECRET=
|
||||
|
||||
@ -21,8 +21,11 @@ class ChatResponse(BaseModel):
|
||||
@router.post("/chat", response_model=ChatResponse)
|
||||
async def ai_chat(req: ChatRequest, user=Depends(get_current_user)):
|
||||
api_key = getattr(settings, "ANTHROPIC_API_KEY", None) or ""
|
||||
if not api_key or api_key == "":
|
||||
raise HTTPException(400, "AI assistant not configured")
|
||||
proxy_url = getattr(settings, "AI_PROXY_URL", "") or ""
|
||||
proxy_secret = getattr(settings, "AI_PROXY_SECRET", "") or ""
|
||||
if not proxy_url or not proxy_secret:
|
||||
if not api_key or api_key == "":
|
||||
raise HTTPException(400, "AI assistant not configured (set ANTHROPIC_API_KEY or AI_PROXY_URL+AI_PROXY_SECRET)")
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
@ -52,21 +55,33 @@ async def ai_chat(req: ChatRequest, user=Depends(get_current_user)):
|
||||
Отвечай на русском языке. Будь конкретным и профессиональным.
|
||||
Используй авиационную терминологию где уместно."""
|
||||
|
||||
payload = {
|
||||
"model": getattr(settings, "ANTHROPIC_MODEL", "claude-sonnet-4-20250514"),
|
||||
"max_tokens": 1024,
|
||||
"system": system_prompt,
|
||||
"messages": [{"role": "user", "content": req.message}],
|
||||
}
|
||||
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
resp = await client.post(
|
||||
"https://api.anthropic.com/v1/messages",
|
||||
headers={
|
||||
"x-api-key": api_key,
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json",
|
||||
},
|
||||
json={
|
||||
"model": getattr(settings, "ANTHROPIC_MODEL", "claude-sonnet-4-20250514"),
|
||||
"max_tokens": 1024,
|
||||
"system": system_prompt,
|
||||
"messages": [{"role": "user", "content": req.message}],
|
||||
},
|
||||
)
|
||||
if proxy_url and proxy_secret:
|
||||
resp = await client.post(
|
||||
proxy_url,
|
||||
headers={
|
||||
"x-proxy-secret": proxy_secret,
|
||||
"content-type": "application/json",
|
||||
},
|
||||
json=payload,
|
||||
)
|
||||
else:
|
||||
resp = await client.post(
|
||||
"https://api.anthropic.com/v1/messages",
|
||||
headers={
|
||||
"x-api-key": api_key,
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json",
|
||||
},
|
||||
json=payload,
|
||||
)
|
||||
|
||||
if resp.status_code != 200:
|
||||
raise HTTPException(502, f"AI service error: {resp.status_code}")
|
||||
|
||||
@ -67,6 +67,9 @@ class Settings(BaseSettings):
|
||||
# AI (Anthropic Claude)
|
||||
ANTHROPIC_API_KEY: str = ""
|
||||
ANTHROPIC_MODEL: str = "claude-sonnet-4-20250514"
|
||||
# Прокси Anthropic через papa-app (Railway) — для обхода блокировки с российских IP
|
||||
AI_PROXY_URL: str = ""
|
||||
AI_PROXY_SECRET: str = ""
|
||||
|
||||
@property
|
||||
def database_url(self) -> str:
|
||||
|
||||
@ -95,6 +95,9 @@ services:
|
||||
FGIS_ORG_ID: ${FGIS_ORG_ID:-}
|
||||
FGIS_API_KEY: ${FGIS_API_KEY:-}
|
||||
FGIS_CERT_PATH: /etc/ssl/fgis/client.pem
|
||||
# Прокси Anthropic через papa-app (Railway) — обход блокировки с российских IP
|
||||
AI_PROXY_URL: ${AI_PROXY_URL:-}
|
||||
AI_PROXY_SECRET: ${AI_PROXY_SECRET:-}
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user