bep40 commited on
Commit
abcc4f0
·
verified ·
1 Parent(s): a4050b3

Override backend/main.py with OpenRouter patch at startup

Browse files
Files changed (1) hide show
  1. backend/main.py +126 -0
backend/main.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FastAPI application for HF Agent web interface — patched for OpenRouter."""
2
+
3
+ import logging
4
+ import os
5
+ import sys
6
+ from contextlib import asynccontextmanager
7
+ from pathlib import Path
8
+
9
+ from dotenv import load_dotenv
10
+
11
+ load_dotenv(Path(__file__).parent.parent / ".env")
12
+
13
+ # ===== OPENROUTER PATCH =====
14
+ # Patch _resolve_llm_params BEFORE importing routes
15
+ sys.path.insert(0, str(Path(__file__).parent.parent))
16
+
17
+ def _apply_openrouter_patch():
18
+ """Patch litellm routing to support OpenRouter."""
19
+ from agent.core import llm_params as lp
20
+ _original = lp._resolve_llm_params
21
+
22
+ def _patched(model_name, session_hf_token=None, reasoning_effort=None, strict=False):
23
+ openrouter_key = os.environ.get("OPENROUTER_API_KEY") or os.environ.get("OPENAI_API_KEY")
24
+ openrouter_base = os.environ.get("OPENAI_API_BASE", "")
25
+
26
+ # If OpenRouter is configured and model is not anthropic/bedrock direct
27
+ if openrouter_key and "openrouter" in openrouter_base:
28
+ if model_name.startswith("openai/"):
29
+ raw_model = model_name[len("openai/"):]
30
+ return {"model": f"openai/{raw_model}", "api_base": openrouter_base, "api_key": openrouter_key}
31
+ elif not model_name.startswith(("anthropic/", "bedrock/")):
32
+ return {"model": f"openai/{model_name}", "api_base": openrouter_base, "api_key": openrouter_key}
33
+
34
+ return _original(model_name, session_hf_token, reasoning_effort, strict)
35
+
36
+ lp._resolve_llm_params = _patched
37
+ print("[patch] ✅ OpenRouter LLM routing patched")
38
+
39
+ try:
40
+ _apply_openrouter_patch()
41
+ except Exception as e:
42
+ print(f"[patch] ⚠️ OpenRouter patch failed: {e}")
43
+ # ===== END PATCH =====
44
+
45
+ from fastapi import FastAPI
46
+ from fastapi.middleware.cors import CORSMiddleware
47
+ from fastapi.staticfiles import StaticFiles
48
+
49
+ from routes.agent import router as agent_router
50
+ from routes.auth import router as auth_router
51
+ from session_manager import session_manager
52
+
53
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
54
+ logger = logging.getLogger(__name__)
55
+
56
+
57
+ @asynccontextmanager
58
+ async def lifespan(app: FastAPI):
59
+ logger.info("Starting HF Agent backend...")
60
+ await session_manager.start()
61
+ try:
62
+ import kpis_scheduler
63
+ kpis_scheduler.start()
64
+ except Exception as e:
65
+ logger.warning("KPI scheduler failed to start: %s", e)
66
+ yield
67
+ logger.info("Shutting down HF Agent backend...")
68
+ try:
69
+ import kpis_scheduler
70
+ await kpis_scheduler.shutdown()
71
+ except Exception as e:
72
+ logger.warning("KPI scheduler shutdown failed: %s", e)
73
+ try:
74
+ for sid, agent_session in list(session_manager.sessions.items()):
75
+ sess = agent_session.session
76
+ if sess.config.save_sessions:
77
+ try:
78
+ sess.save_and_upload_detached(sess.config.session_dataset_repo)
79
+ except Exception:
80
+ pass
81
+ except Exception:
82
+ pass
83
+ await session_manager.close()
84
+
85
+
86
+ _DOCS_DISABLED = os.environ.get("SPACE_ID") is not None
87
+
88
+ app = FastAPI(
89
+ title="HF Agent", version="1.0.0", lifespan=lifespan,
90
+ docs_url=None if _DOCS_DISABLED else "/docs",
91
+ redoc_url=None if _DOCS_DISABLED else "/redoc",
92
+ openapi_url=None if _DOCS_DISABLED else "/openapi.json",
93
+ )
94
+
95
+ app.add_middleware(
96
+ CORSMiddleware,
97
+ allow_origins=["http://localhost:5173", "http://localhost:3000", "http://127.0.0.1:5173"],
98
+ allow_credentials=True, allow_methods=["*"], allow_headers=["*"],
99
+ )
100
+
101
+ app.include_router(agent_router)
102
+ app.include_router(auth_router)
103
+
104
+ # ===== PATCH AVAILABLE MODELS AFTER IMPORT =====
105
+ try:
106
+ from routes import agent as _agent_routes
107
+ _agent_routes.AVAILABLE_MODELS = [
108
+ {"id": "deepseek/deepseek-chat-v3-0324", "label": "DeepSeek V3", "provider": "openrouter", "tier": "free", "recommended": True},
109
+ {"id": "google/gemini-2.0-flash-001", "label": "Gemini 2.0 Flash", "provider": "openrouter", "tier": "free"},
110
+ {"id": "qwen/qwen3-30b-a3b", "label": "Qwen3 30B", "provider": "openrouter", "tier": "free"},
111
+ {"id": "anthropic/claude-sonnet-4", "label": "Claude Sonnet 4", "provider": "openrouter", "tier": "pro"},
112
+ ]
113
+ _agent_routes.PREMIUM_MODEL_IDS = {"anthropic/claude-sonnet-4", "anthropic/claude-opus-4"}
114
+ _agent_routes.DEFAULT_FREE_MODEL_ID = "deepseek/deepseek-chat-v3-0324"
115
+ print("[patch] ✅ Available models patched (DeepSeek V3, Gemini Flash, Qwen3)")
116
+ except Exception as e:
117
+ print(f"[patch] ⚠️ Models patch failed: {e}")
118
+ # ===== END MODELS PATCH =====
119
+
120
+ static_path = Path(__file__).parent.parent / "static"
121
+ if static_path.exists():
122
+ app.mount("/", StaticFiles(directory=str(static_path), html=True), name="static")
123
+
124
+ if __name__ == "__main__":
125
+ import uvicorn
126
+ uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))