NeerajCodz commited on
Commit
1226a86
·
1 Parent(s): e5b4f8d

feat: add providers API endpoints with model and cost tracking

Browse files
backend/app/api/routes/providers.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Provider management API routes."""
2
+
3
+ from typing import Any
4
+
5
+ from fastapi import APIRouter, Depends
6
+ from pydantic import BaseModel, Field
7
+
8
+ from app.api.deps import get_model_router
9
+ from app.models.router import SmartModelRouter
10
+
11
+ router = APIRouter(prefix="/providers", tags=["providers"])
12
+
13
+
14
+ class ProviderInfo(BaseModel):
15
+ """Provider information."""
16
+
17
+ id: str
18
+ name: str
19
+ available: bool
20
+ models_count: int
21
+ features: list[str]
22
+
23
+
24
+ class ModelInfo(BaseModel):
25
+ """Model information."""
26
+
27
+ id: str
28
+ name: str
29
+ provider: str
30
+ context_window: int
31
+ max_output_tokens: int
32
+ supports_functions: bool
33
+ supports_vision: bool
34
+ supports_streaming: bool
35
+ cost_per_1k_input: float
36
+ cost_per_1k_output: float
37
+
38
+
39
+ @router.get("")
40
+ @router.get("/")
41
+ async def list_providers(router: SmartModelRouter = Depends(get_model_router)) -> dict[str, Any]:
42
+ """
43
+ List all initialized AI providers.
44
+
45
+ Returns:
46
+ Dictionary with providers list and summary statistics
47
+ """
48
+ providers_list = []
49
+
50
+ for provider_name in router.list_providers():
51
+ provider_obj = router.providers.get(provider_name)
52
+ if provider_obj:
53
+ models = provider_obj.list_models()
54
+ features = []
55
+
56
+ # Check provider capabilities
57
+ if any(m.supports_functions for m in models):
58
+ features.append("functions")
59
+ if any(m.supports_vision for m in models):
60
+ features.append("vision")
61
+ if any(m.supports_streaming for m in models):
62
+ features.append("streaming")
63
+
64
+ providers_list.append(ProviderInfo(
65
+ id=provider_name,
66
+ name=provider_obj.PROVIDER_NAME.title(),
67
+ available=True,
68
+ models_count=len(models),
69
+ features=features,
70
+ ))
71
+
72
+ return {
73
+ "providers": [p.model_dump() for p in providers_list],
74
+ "count": len(providers_list),
75
+ "available_models_count": sum(p.models_count for p in providers_list),
76
+ }
77
+
78
+
79
+ @router.get("/{provider_name}")
80
+ async def get_provider_details(
81
+ provider_name: str,
82
+ router: SmartModelRouter = Depends(get_model_router),
83
+ ) -> dict[str, Any]:
84
+ """
85
+ Get detailed information about a specific provider.
86
+
87
+ Args:
88
+ provider_name: Provider identifier (openai, google, anthropic, groq, nvidia)
89
+
90
+ Returns:
91
+ Provider details including all available models
92
+ """
93
+ provider_obj = router.providers.get(provider_name)
94
+ if not provider_obj:
95
+ return {
96
+ "error": f"Provider '{provider_name}' not initialized",
97
+ "available_providers": router.list_providers(),
98
+ }
99
+
100
+ models = provider_obj.list_models()
101
+
102
+ return {
103
+ "id": provider_name,
104
+ "name": provider_obj.PROVIDER_NAME.title(),
105
+ "available": True,
106
+ "models": [ModelInfo(
107
+ id=m.id,
108
+ name=m.name,
109
+ provider=m.provider,
110
+ context_window=m.context_window,
111
+ max_output_tokens=m.max_output_tokens,
112
+ supports_functions=m.supports_functions,
113
+ supports_vision=m.supports_vision,
114
+ supports_streaming=m.supports_streaming,
115
+ cost_per_1k_input=m.cost_per_1k_input,
116
+ cost_per_1k_output=m.cost_per_1k_output,
117
+ ).model_dump() for m in models],
118
+ "models_count": len(models),
119
+ }
120
+
121
+
122
+ @router.get("/models/all")
123
+ async def list_all_models(
124
+ router: SmartModelRouter = Depends(get_model_router),
125
+ ) -> dict[str, Any]:
126
+ """
127
+ List all available models across all providers.
128
+
129
+ Returns:
130
+ List of all models with their details
131
+ """
132
+ all_models = router.get_available_models()
133
+
134
+ return {
135
+ "models": [ModelInfo(
136
+ id=m.id,
137
+ name=m.name,
138
+ provider=m.provider,
139
+ context_window=m.context_window,
140
+ max_output_tokens=m.max_output_tokens,
141
+ supports_functions=m.supports_functions,
142
+ supports_vision=m.supports_vision,
143
+ supports_streaming=m.supports_streaming,
144
+ cost_per_1k_input=m.cost_per_1k_input,
145
+ cost_per_1k_output=m.cost_per_1k_output,
146
+ ).model_dump() for m in all_models],
147
+ "count": len(all_models),
148
+ "by_provider": {
149
+ provider: len([m for m in all_models if m.provider == provider])
150
+ for provider in router.list_providers()
151
+ },
152
+ }
153
+
154
+
155
+ @router.get("/costs/summary")
156
+ async def get_cost_summary(
157
+ router: SmartModelRouter = Depends(get_model_router),
158
+ ) -> dict[str, Any]:
159
+ """
160
+ Get cost tracking summary.
161
+
162
+ Returns:
163
+ Cost statistics across all providers and models
164
+ """
165
+ return router.get_cost_summary()
166
+
167
+
168
+ @router.post("/costs/reset")
169
+ async def reset_cost_tracking(
170
+ router: SmartModelRouter = Depends(get_model_router),
171
+ ) -> dict[str, str]:
172
+ """
173
+ Reset cost tracking counters.
174
+
175
+ Returns:
176
+ Confirmation message
177
+ """
178
+ router.reset_cost_tracking()
179
+ return {"status": "success", "message": "Cost tracking reset"}
backend/app/main.py CHANGED
@@ -74,6 +74,12 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
74
  logger.info("Initializing tool registry...")
75
  _tool_registry = MCPToolRegistry()
76
  await _tool_registry.initialize()
 
 
 
 
 
 
77
 
78
  logger.info("Application startup complete")
79
 
@@ -127,6 +133,10 @@ def create_app() -> FastAPI:
127
  app.include_router(memory.router, prefix=api_prefix, tags=["Memory"])
128
  app.include_router(settings_routes.router, prefix=api_prefix, tags=["Settings"])
129
  app.include_router(plugins.router, prefix=api_prefix, tags=["Plugins"])
 
 
 
 
130
 
131
  # Serve static files (frontend build)
132
  static_dir = Path(__file__).parent.parent / "static"
 
74
  logger.info("Initializing tool registry...")
75
  _tool_registry = MCPToolRegistry()
76
  await _tool_registry.initialize()
77
+
78
+ # Update dependency container
79
+ from app.api import deps
80
+ deps.container.set_memory_manager(_memory_manager)
81
+ deps.container.set_model_router(_model_router)
82
+ deps.container.set_tool_registry(_tool_registry)
83
 
84
  logger.info("Application startup complete")
85
 
 
133
  app.include_router(memory.router, prefix=api_prefix, tags=["Memory"])
134
  app.include_router(settings_routes.router, prefix=api_prefix, tags=["Settings"])
135
  app.include_router(plugins.router, prefix=api_prefix, tags=["Plugins"])
136
+
137
+ # Import and include providers router
138
+ from app.api.routes import providers
139
+ app.include_router(providers.router, prefix=api_prefix, tags=["Providers"])
140
 
141
  # Serve static files (frontend build)
142
  static_dir = Path(__file__).parent.parent / "static"