Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
sachin
commited on
Commit
·
0b7d0b0
1
Parent(s):
445a506
add-swage docs
Browse files- src/server/main.py +34 -13
src/server/main.py
CHANGED
@@ -3,14 +3,13 @@ import io
|
|
3 |
from time import time
|
4 |
from typing import List, Optional
|
5 |
from abc import ABC, abstractmethod
|
6 |
-
from pydantic import BaseModel, Field
|
7 |
-
|
8 |
|
9 |
import uvicorn
|
10 |
-
from fastapi import Depends, FastAPI, File, HTTPException, Query, Request, UploadFile, Form
|
11 |
from fastapi.middleware.cors import CORSMiddleware
|
12 |
from fastapi.responses import JSONResponse, RedirectResponse, StreamingResponse
|
13 |
-
from
|
|
|
14 |
from slowapi import Limiter
|
15 |
from slowapi.util import get_remote_address
|
16 |
import requests
|
@@ -25,12 +24,28 @@ from config.logging_config import logger
|
|
25 |
|
26 |
settings = Settings()
|
27 |
|
|
|
|
|
|
|
28 |
# FastAPI app setup with enhanced docs
|
29 |
app = FastAPI(
|
30 |
title="Dhwani API",
|
31 |
-
description="A multilingual AI-powered API supporting Indian languages for chat, text-to-speech, audio processing, and transcription."
|
|
|
|
|
|
|
|
|
|
|
32 |
version="1.0.0",
|
33 |
redirect_slashes=False,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
)
|
35 |
|
36 |
app.add_middleware(
|
@@ -137,7 +152,7 @@ async def home():
|
|
137 |
@app.post("/v1/token",
|
138 |
response_model=TokenResponse,
|
139 |
summary="User Login",
|
140 |
-
description="Authenticate a user with username and password to obtain an access token.",
|
141 |
tags=["Authentication"],
|
142 |
responses={
|
143 |
200: {"description": "Successful login", "model": TokenResponse},
|
@@ -161,7 +176,7 @@ async def refresh(token_response: TokenResponse = Depends(refresh_token)):
|
|
161 |
@app.post("/v1/register",
|
162 |
response_model=TokenResponse,
|
163 |
summary="Register New User",
|
164 |
-
description="Create a new user account and return an access token.",
|
165 |
tags=["Authentication"],
|
166 |
responses={
|
167 |
200: {"description": "User registered successfully", "model": TokenResponse},
|
@@ -172,11 +187,12 @@ async def register_user(register_request: RegisterRequest):
|
|
172 |
|
173 |
@app.post("/v1/audio/speech",
|
174 |
summary="Generate Speech from Text",
|
175 |
-
description="Convert text to speech in the specified format using an external TTS service. Rate limited to 5 requests per minute per user.",
|
176 |
tags=["Audio"],
|
177 |
responses={
|
178 |
200: {"description": "Audio stream", "content": {"audio/mp3": {"example": "Binary audio data"}}},
|
179 |
400: {"description": "Invalid input"},
|
|
|
180 |
429: {"description": "Rate limit exceeded"},
|
181 |
504: {"description": "TTS service timeout"}
|
182 |
})
|
@@ -247,11 +263,12 @@ class ChatResponse(BaseModel):
|
|
247 |
@app.post("/v1/chat",
|
248 |
response_model=ChatResponse,
|
249 |
summary="Chat with AI",
|
250 |
-
description="Generate a chat response from a prompt in the specified language. Rate limited to 100 requests per minute per user.",
|
251 |
tags=["Chat"],
|
252 |
responses={
|
253 |
200: {"description": "Chat response", "model": ChatResponse},
|
254 |
400: {"description": "Invalid prompt"},
|
|
|
255 |
429: {"description": "Rate limit exceeded"},
|
256 |
504: {"description": "Chat service timeout"}
|
257 |
})
|
@@ -302,10 +319,11 @@ async def chat(
|
|
302 |
@app.post("/v1/process_audio/",
|
303 |
response_model=AudioProcessingResponse,
|
304 |
summary="Process Audio File",
|
305 |
-
description="Process an uploaded audio file in the specified language. Rate limited to 100 requests per minute per user.",
|
306 |
tags=["Audio"],
|
307 |
responses={
|
308 |
200: {"description": "Processed result", "model": AudioProcessingResponse},
|
|
|
309 |
429: {"description": "Rate limit exceeded"},
|
310 |
504: {"description": "Audio processing timeout"}
|
311 |
})
|
@@ -350,10 +368,11 @@ async def process_audio(
|
|
350 |
@app.post("/v1/transcribe/",
|
351 |
response_model=TranscriptionResponse,
|
352 |
summary="Transcribe Audio File",
|
353 |
-
description="Transcribe an uploaded audio file into text in the specified language.",
|
354 |
tags=["Audio"],
|
355 |
responses={
|
356 |
200: {"description": "Transcription result", "model": TranscriptionResponse},
|
|
|
357 |
504: {"description": "Transcription service timeout"}
|
358 |
})
|
359 |
async def transcribe_audio(
|
@@ -387,11 +406,12 @@ async def transcribe_audio(
|
|
387 |
@app.post("/v1/chat_v2",
|
388 |
response_model=TranscriptionResponse,
|
389 |
summary="Chat with Image (V2)",
|
390 |
-
description="Generate a response from a text prompt and optional image. Rate limited to 100 requests per minute per user.",
|
391 |
tags=["Chat"],
|
392 |
responses={
|
393 |
200: {"description": "Chat response", "model": TranscriptionResponse},
|
394 |
400: {"description": "Invalid prompt"},
|
|
|
395 |
429: {"description": "Rate limit exceeded"}
|
396 |
})
|
397 |
@limiter.limit(settings.chat_rate_limit)
|
@@ -443,10 +463,11 @@ class TranslationResponse(BaseModel):
|
|
443 |
@app.post("/v1/translate",
|
444 |
response_model=TranslationResponse,
|
445 |
summary="Translate Text",
|
446 |
-
description="Translate a list of sentences from source to target language.",
|
447 |
tags=["Translation"],
|
448 |
responses={
|
449 |
200: {"description": "Translation result", "model": TranslationResponse},
|
|
|
450 |
500: {"description": "Translation service error"},
|
451 |
504: {"description": "Translation service timeout"}
|
452 |
})
|
|
|
3 |
from time import time
|
4 |
from typing import List, Optional
|
5 |
from abc import ABC, abstractmethod
|
|
|
|
|
6 |
|
7 |
import uvicorn
|
8 |
+
from fastapi import Depends, FastAPI, File, HTTPException, Query, Request, UploadFile, Form, Security
|
9 |
from fastapi.middleware.cors import CORSMiddleware
|
10 |
from fastapi.responses import JSONResponse, RedirectResponse, StreamingResponse
|
11 |
+
from fastapi.security import OAuth2PasswordBearer
|
12 |
+
from pydantic import BaseModel, field_validator, Field
|
13 |
from slowapi import Limiter
|
14 |
from slowapi.util import get_remote_address
|
15 |
import requests
|
|
|
24 |
|
25 |
settings = Settings()
|
26 |
|
27 |
+
# Define OAuth2 scheme explicitly for Swagger
|
28 |
+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/v1/token")
|
29 |
+
|
30 |
# FastAPI app setup with enhanced docs
|
31 |
app = FastAPI(
|
32 |
title="Dhwani API",
|
33 |
+
description="A multilingual AI-powered API supporting Indian languages for chat, text-to-speech, audio processing, and transcription. "
|
34 |
+
"**Authentication Guide:** \n"
|
35 |
+
"1. Register a new user via `/v1/register` with a POST request containing `username` and `password`. \n"
|
36 |
+
"2. Obtain an access token by sending a POST request to `/v1/token` with `username` and `password`. \n"
|
37 |
+
"3. Click the 'Authorize' button (top-right), enter `Bearer <your_access_token>` in the 'bearerAuth' field, and click 'Authorize'. \n"
|
38 |
+
"All protected endpoints require this token for access.",
|
39 |
version="1.0.0",
|
40 |
redirect_slashes=False,
|
41 |
+
openapi_tags=[
|
42 |
+
{"name": "Utility", "description": "General utility endpoints"},
|
43 |
+
{"name": "Authentication", "description": "User authentication and registration"},
|
44 |
+
{"name": "Chat", "description": "Chat-related endpoints"},
|
45 |
+
{"name": "Audio", "description": "Audio processing and TTS endpoints"},
|
46 |
+
{"name": "Translation", "description": "Text translation endpoints"}
|
47 |
+
],
|
48 |
+
swagger_ui_oauth2_redirect_url="/docs/oauth2-redirect",
|
49 |
)
|
50 |
|
51 |
app.add_middleware(
|
|
|
152 |
@app.post("/v1/token",
|
153 |
response_model=TokenResponse,
|
154 |
summary="User Login",
|
155 |
+
description="Authenticate a user with username and password to obtain an access token. Copy the token and use it in the 'Authorize' button above.",
|
156 |
tags=["Authentication"],
|
157 |
responses={
|
158 |
200: {"description": "Successful login", "model": TokenResponse},
|
|
|
176 |
@app.post("/v1/register",
|
177 |
response_model=TokenResponse,
|
178 |
summary="Register New User",
|
179 |
+
description="Create a new user account and return an access token. Use this token for subsequent requests.",
|
180 |
tags=["Authentication"],
|
181 |
responses={
|
182 |
200: {"description": "User registered successfully", "model": TokenResponse},
|
|
|
187 |
|
188 |
@app.post("/v1/audio/speech",
|
189 |
summary="Generate Speech from Text",
|
190 |
+
description="Convert text to speech in the specified format using an external TTS service. Rate limited to 5 requests per minute per user. Requires authentication.",
|
191 |
tags=["Audio"],
|
192 |
responses={
|
193 |
200: {"description": "Audio stream", "content": {"audio/mp3": {"example": "Binary audio data"}}},
|
194 |
400: {"description": "Invalid input"},
|
195 |
+
401: {"description": "Unauthorized - Token required"},
|
196 |
429: {"description": "Rate limit exceeded"},
|
197 |
504: {"description": "TTS service timeout"}
|
198 |
})
|
|
|
263 |
@app.post("/v1/chat",
|
264 |
response_model=ChatResponse,
|
265 |
summary="Chat with AI",
|
266 |
+
description="Generate a chat response from a prompt in the specified language. Rate limited to 100 requests per minute per user. Requires authentication.",
|
267 |
tags=["Chat"],
|
268 |
responses={
|
269 |
200: {"description": "Chat response", "model": ChatResponse},
|
270 |
400: {"description": "Invalid prompt"},
|
271 |
+
401: {"description": "Unauthorized - Token required"},
|
272 |
429: {"description": "Rate limit exceeded"},
|
273 |
504: {"description": "Chat service timeout"}
|
274 |
})
|
|
|
319 |
@app.post("/v1/process_audio/",
|
320 |
response_model=AudioProcessingResponse,
|
321 |
summary="Process Audio File",
|
322 |
+
description="Process an uploaded audio file in the specified language. Rate limited to 100 requests per minute per user. Requires authentication.",
|
323 |
tags=["Audio"],
|
324 |
responses={
|
325 |
200: {"description": "Processed result", "model": AudioProcessingResponse},
|
326 |
+
401: {"description": "Unauthorized - Token required"},
|
327 |
429: {"description": "Rate limit exceeded"},
|
328 |
504: {"description": "Audio processing timeout"}
|
329 |
})
|
|
|
368 |
@app.post("/v1/transcribe/",
|
369 |
response_model=TranscriptionResponse,
|
370 |
summary="Transcribe Audio File",
|
371 |
+
description="Transcribe an uploaded audio file into text in the specified language. Requires authentication.",
|
372 |
tags=["Audio"],
|
373 |
responses={
|
374 |
200: {"description": "Transcription result", "model": TranscriptionResponse},
|
375 |
+
401: {"description": "Unauthorized - Token required"},
|
376 |
504: {"description": "Transcription service timeout"}
|
377 |
})
|
378 |
async def transcribe_audio(
|
|
|
406 |
@app.post("/v1/chat_v2",
|
407 |
response_model=TranscriptionResponse,
|
408 |
summary="Chat with Image (V2)",
|
409 |
+
description="Generate a response from a text prompt and optional image. Rate limited to 100 requests per minute per user. Requires authentication.",
|
410 |
tags=["Chat"],
|
411 |
responses={
|
412 |
200: {"description": "Chat response", "model": TranscriptionResponse},
|
413 |
400: {"description": "Invalid prompt"},
|
414 |
+
401: {"description": "Unauthorized - Token required"},
|
415 |
429: {"description": "Rate limit exceeded"}
|
416 |
})
|
417 |
@limiter.limit(settings.chat_rate_limit)
|
|
|
463 |
@app.post("/v1/translate",
|
464 |
response_model=TranslationResponse,
|
465 |
summary="Translate Text",
|
466 |
+
description="Translate a list of sentences from source to target language. Requires authentication.",
|
467 |
tags=["Translation"],
|
468 |
responses={
|
469 |
200: {"description": "Translation result", "model": TranslationResponse},
|
470 |
+
401: {"description": "Unauthorized - Token required"},
|
471 |
500: {"description": "Translation service error"},
|
472 |
504: {"description": "Translation service timeout"}
|
473 |
})
|