Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
sachin
commited on
Commit
·
9394c20
1
Parent(s):
99bc65d
update-call
Browse files- Dockerfile +1 -1
- src/server/main.py +28 -19
Dockerfile
CHANGED
@@ -9,7 +9,7 @@ COPY . .
|
|
9 |
|
10 |
# Expose port from settings
|
11 |
EXPOSE 7860
|
12 |
-
|
13 |
# Healthcheck
|
14 |
HEALTHCHECK --interval=30s --timeout=3s \
|
15 |
CMD curl -f http://localhost:7860/v1/health || exit 1
|
|
|
9 |
|
10 |
# Expose port from settings
|
11 |
EXPOSE 7860
|
12 |
+
RUN pip install dwani
|
13 |
# Healthcheck
|
14 |
HEALTHCHECK --interval=30s --timeout=3s \
|
15 |
CMD curl -f http://localhost:7860/v1/health || exit 1
|
src/server/main.py
CHANGED
@@ -3,7 +3,8 @@ import io
|
|
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, Header, Form
|
9 |
from fastapi.middleware.cors import CORSMiddleware
|
@@ -29,6 +30,10 @@ from config.logging_config import logger
|
|
29 |
|
30 |
settings = Settings()
|
31 |
|
|
|
|
|
|
|
|
|
32 |
# FastAPI app setup with enhanced docs
|
33 |
app = FastAPI(
|
34 |
title="Dhwani API",
|
@@ -278,7 +283,7 @@ async def app_register_user(
|
|
278 |
register_request: RegisterRequest,
|
279 |
x_session_key: str = Header(..., alias="X-Session-Key")
|
280 |
):
|
281 |
-
logger.
|
282 |
return await app_register(register_request, x_session_key)
|
283 |
|
284 |
@app.post("/v1/audio/speech",
|
@@ -318,7 +323,7 @@ async def generate_audio(
|
|
318 |
if len(decrypted_input) > 1000:
|
319 |
raise HTTPException(status_code=400, detail="Decrypted input cannot exceed 1000 characters")
|
320 |
|
321 |
-
logger.
|
322 |
"endpoint": "/v1/audio/speech",
|
323 |
"input_length": len(decrypted_input),
|
324 |
"client_ip": get_remote_address(request),
|
@@ -399,9 +404,13 @@ async def chat(
|
|
399 |
if len(decrypted_prompt) > 1000:
|
400 |
raise HTTPException(status_code=400, detail="Decrypted prompt cannot exceed 1000 characters")
|
401 |
|
402 |
-
logger.
|
403 |
|
404 |
try:
|
|
|
|
|
|
|
|
|
405 |
external_url = f"{settings.external_api_base_url}/v1/chat"
|
406 |
payload = {
|
407 |
"prompt": decrypted_prompt,
|
@@ -419,10 +428,10 @@ async def chat(
|
|
419 |
timeout=60
|
420 |
)
|
421 |
response.raise_for_status()
|
422 |
-
|
423 |
response_data = response.json()
|
424 |
response_text = response_data.get("response", "")
|
425 |
-
logger.
|
426 |
return ChatResponse(response=response_text)
|
427 |
|
428 |
except requests.Timeout:
|
@@ -470,7 +479,7 @@ async def process_audio(
|
|
470 |
if decrypted_language not in allowed_languages:
|
471 |
raise HTTPException(status_code=400, detail=f"Language must be one of {allowed_languages}")
|
472 |
|
473 |
-
logger.
|
474 |
"endpoint": "/v1/process_audio",
|
475 |
"filename": file.filename,
|
476 |
"language": decrypted_language,
|
@@ -493,7 +502,7 @@ async def process_audio(
|
|
493 |
response.raise_for_status()
|
494 |
|
495 |
processed_result = response.json().get("result", "")
|
496 |
-
logger.
|
497 |
return AudioProcessingResponse(result=processed_result)
|
498 |
|
499 |
except requests.Timeout:
|
@@ -551,7 +560,7 @@ async def transcribe_audio(
|
|
551 |
response.raise_for_status()
|
552 |
|
553 |
transcription = response.json().get("text", "")
|
554 |
-
logger.
|
555 |
return TranscriptionResponse(text=transcription)
|
556 |
|
557 |
except HTTPException:
|
@@ -585,7 +594,7 @@ async def chat_v2(
|
|
585 |
if not prompt:
|
586 |
raise HTTPException(status_code=400, detail="Prompt cannot be empty")
|
587 |
|
588 |
-
logger.
|
589 |
"endpoint": "/v1/chat_v2",
|
590 |
"prompt_length": len(prompt),
|
591 |
"has_image": bool(image),
|
@@ -668,7 +677,7 @@ async def translate(
|
|
668 |
logger.error(f"Unsupported language codes: src={decrypted_src_lang}, tgt={decrypted_tgt_lang}")
|
669 |
raise HTTPException(status_code=400, detail=f"Unsupported language codes: src={decrypted_src_lang}, tgt={decrypted_tgt_lang}")
|
670 |
|
671 |
-
logger.
|
672 |
|
673 |
external_url = f"{settings.external_api_base_url}/v1/translate"
|
674 |
|
@@ -697,7 +706,7 @@ async def translate(
|
|
697 |
logger.warning(f"Unexpected response format: {response_data}")
|
698 |
raise HTTPException(status_code=500, detail="Invalid response from translation service")
|
699 |
|
700 |
-
logger.
|
701 |
return TranslationResponse(translations=translations)
|
702 |
|
703 |
except requests.Timeout:
|
@@ -756,7 +765,7 @@ async def extract_text(
|
|
756 |
logger.error(f"PDF decryption failed: {str(e)}")
|
757 |
raise HTTPException(status_code=400, detail="Invalid encrypted PDF")
|
758 |
|
759 |
-
logger.
|
760 |
"endpoint": "/v1/extract-text",
|
761 |
"file_name": file.filename,
|
762 |
"page_number": page_number,
|
@@ -784,7 +793,7 @@ async def extract_text(
|
|
784 |
logger.warning("No page_content found in external API response")
|
785 |
extracted_text = ""
|
786 |
|
787 |
-
logger.
|
788 |
return PDFTextExtractionResponse(page_content=extracted_text.strip())
|
789 |
|
790 |
except requests.Timeout:
|
@@ -825,7 +834,7 @@ async def visual_query(
|
|
825 |
try:
|
826 |
import json
|
827 |
visual_query_request = VisualQueryRequest.parse_raw(data)
|
828 |
-
logger.
|
829 |
except Exception as e:
|
830 |
logger.error(f"Failed to parse JSON data: {str(e)}")
|
831 |
raise HTTPException(status_code=422, detail=f"Invalid JSON data: {str(e)}")
|
@@ -867,7 +876,7 @@ async def visual_query(
|
|
867 |
logger.error(f"Image decryption failed: {str(e)}")
|
868 |
raise HTTPException(status_code=400, detail="Invalid encrypted image")
|
869 |
|
870 |
-
logger.
|
871 |
"endpoint": "/v1/visual_query",
|
872 |
"query_length": len(decrypted_query),
|
873 |
"file_name": file.filename,
|
@@ -899,7 +908,7 @@ async def visual_query(
|
|
899 |
logger.warning(f"Empty answer received from external API: {response_data}")
|
900 |
raise HTTPException(status_code=500, detail="No answer provided by visual query service")
|
901 |
|
902 |
-
logger.
|
903 |
return VisualQueryResponse(answer=answer)
|
904 |
|
905 |
except requests.Timeout:
|
@@ -955,7 +964,7 @@ async def speech_to_speech(
|
|
955 |
if decrypted_language not in allowed_languages:
|
956 |
raise HTTPException(status_code=400, detail=f"Language must be one of {allowed_languages}")
|
957 |
|
958 |
-
logger.
|
959 |
"endpoint": "/v1/speech_to_speech",
|
960 |
"audio_filename": file.filename,
|
961 |
"language": decrypted_language,
|
@@ -1029,7 +1038,7 @@ async def speech_to_speech_v2(
|
|
1029 |
if decrypted_language not in allowed_languages:
|
1030 |
raise HTTPException(status_code=400, detail=f"Language must be one of {allowed_languages}")
|
1031 |
|
1032 |
-
logger.
|
1033 |
"endpoint": "/v1/speech_to_speech",
|
1034 |
"audio_filename": file.filename,
|
1035 |
"language": decrypted_language,
|
|
|
3 |
from time import time
|
4 |
from typing import List, Optional
|
5 |
from abc import ABC, abstractmethod
|
6 |
+
import dwani
|
7 |
+
import os
|
8 |
import uvicorn
|
9 |
from fastapi import Depends, FastAPI, File, HTTPException, Query, Request, UploadFile, Header, Form
|
10 |
from fastapi.middleware.cors import CORSMiddleware
|
|
|
30 |
|
31 |
settings = Settings()
|
32 |
|
33 |
+
|
34 |
+
dwani.api_key = os.getenv("DWANI_API_KEY")
|
35 |
+
|
36 |
+
dwani.api_base = os.getenv("DWANI_API_BASE_URL")
|
37 |
# FastAPI app setup with enhanced docs
|
38 |
app = FastAPI(
|
39 |
title="Dhwani API",
|
|
|
283 |
register_request: RegisterRequest,
|
284 |
x_session_key: str = Header(..., alias="X-Session-Key")
|
285 |
):
|
286 |
+
logger.debug(f"App registration attempt")
|
287 |
return await app_register(register_request, x_session_key)
|
288 |
|
289 |
@app.post("/v1/audio/speech",
|
|
|
323 |
if len(decrypted_input) > 1000:
|
324 |
raise HTTPException(status_code=400, detail="Decrypted input cannot exceed 1000 characters")
|
325 |
|
326 |
+
logger.debug("Processing speech request", extra={
|
327 |
"endpoint": "/v1/audio/speech",
|
328 |
"input_length": len(decrypted_input),
|
329 |
"client_ip": get_remote_address(request),
|
|
|
404 |
if len(decrypted_prompt) > 1000:
|
405 |
raise HTTPException(status_code=400, detail="Decrypted prompt cannot exceed 1000 characters")
|
406 |
|
407 |
+
logger.debug(f"Received prompt: {decrypted_prompt}, src_lang: {decrypted_src_lang}, user_id: {user_id}")
|
408 |
|
409 |
try:
|
410 |
+
|
411 |
+
|
412 |
+
response = dwani.Chat.create(prompt=decrypted_prompt, src_lang=decrypted_src_lang, tgt_lang=decrypted_tgt_lang)
|
413 |
+
'''
|
414 |
external_url = f"{settings.external_api_base_url}/v1/chat"
|
415 |
payload = {
|
416 |
"prompt": decrypted_prompt,
|
|
|
428 |
timeout=60
|
429 |
)
|
430 |
response.raise_for_status()
|
431 |
+
'''
|
432 |
response_data = response.json()
|
433 |
response_text = response_data.get("response", "")
|
434 |
+
logger.debug(f"Generated Chat response from external API: {response_text}")
|
435 |
return ChatResponse(response=response_text)
|
436 |
|
437 |
except requests.Timeout:
|
|
|
479 |
if decrypted_language not in allowed_languages:
|
480 |
raise HTTPException(status_code=400, detail=f"Language must be one of {allowed_languages}")
|
481 |
|
482 |
+
logger.debug("Processing audio processing request", extra={
|
483 |
"endpoint": "/v1/process_audio",
|
484 |
"filename": file.filename,
|
485 |
"language": decrypted_language,
|
|
|
502 |
response.raise_for_status()
|
503 |
|
504 |
processed_result = response.json().get("result", "")
|
505 |
+
logger.debug(f"Audio processing completed in {time() - start_time:.2f} seconds")
|
506 |
return AudioProcessingResponse(result=processed_result)
|
507 |
|
508 |
except requests.Timeout:
|
|
|
560 |
response.raise_for_status()
|
561 |
|
562 |
transcription = response.json().get("text", "")
|
563 |
+
logger.debug(f"Transcription completed in {time() - start_time:.2f} seconds")
|
564 |
return TranscriptionResponse(text=transcription)
|
565 |
|
566 |
except HTTPException:
|
|
|
594 |
if not prompt:
|
595 |
raise HTTPException(status_code=400, detail="Prompt cannot be empty")
|
596 |
|
597 |
+
logger.debug("Processing chat_v2 request", extra={
|
598 |
"endpoint": "/v1/chat_v2",
|
599 |
"prompt_length": len(prompt),
|
600 |
"has_image": bool(image),
|
|
|
677 |
logger.error(f"Unsupported language codes: src={decrypted_src_lang}, tgt={decrypted_tgt_lang}")
|
678 |
raise HTTPException(status_code=400, detail=f"Unsupported language codes: src={decrypted_src_lang}, tgt={decrypted_tgt_lang}")
|
679 |
|
680 |
+
logger.debug(f"Received translation request: {len(decrypted_sentences)} sentences, src_lang: {decrypted_src_lang}, tgt_lang: {decrypted_tgt_lang}, user_id: {user_id}")
|
681 |
|
682 |
external_url = f"{settings.external_api_base_url}/v1/translate"
|
683 |
|
|
|
706 |
logger.warning(f"Unexpected response format: {response_data}")
|
707 |
raise HTTPException(status_code=500, detail="Invalid response from translation service")
|
708 |
|
709 |
+
logger.debug(f"Translation successful: {translations}")
|
710 |
return TranslationResponse(translations=translations)
|
711 |
|
712 |
except requests.Timeout:
|
|
|
765 |
logger.error(f"PDF decryption failed: {str(e)}")
|
766 |
raise HTTPException(status_code=400, detail="Invalid encrypted PDF")
|
767 |
|
768 |
+
logger.debug("Processing PDF text extraction request", extra={
|
769 |
"endpoint": "/v1/extract-text",
|
770 |
"file_name": file.filename,
|
771 |
"page_number": page_number,
|
|
|
793 |
logger.warning("No page_content found in external API response")
|
794 |
extracted_text = ""
|
795 |
|
796 |
+
logger.debug(f"PDF text extraction completed in {time() - start_time:.2f} seconds")
|
797 |
return PDFTextExtractionResponse(page_content=extracted_text.strip())
|
798 |
|
799 |
except requests.Timeout:
|
|
|
834 |
try:
|
835 |
import json
|
836 |
visual_query_request = VisualQueryRequest.parse_raw(data)
|
837 |
+
logger.debug(f"Received visual query JSON: {data}")
|
838 |
except Exception as e:
|
839 |
logger.error(f"Failed to parse JSON data: {str(e)}")
|
840 |
raise HTTPException(status_code=422, detail=f"Invalid JSON data: {str(e)}")
|
|
|
876 |
logger.error(f"Image decryption failed: {str(e)}")
|
877 |
raise HTTPException(status_code=400, detail="Invalid encrypted image")
|
878 |
|
879 |
+
logger.debug("Processing visual query request", extra={
|
880 |
"endpoint": "/v1/visual_query",
|
881 |
"query_length": len(decrypted_query),
|
882 |
"file_name": file.filename,
|
|
|
908 |
logger.warning(f"Empty answer received from external API: {response_data}")
|
909 |
raise HTTPException(status_code=500, detail="No answer provided by visual query service")
|
910 |
|
911 |
+
logger.debug(f"Visual query successful: {answer}")
|
912 |
return VisualQueryResponse(answer=answer)
|
913 |
|
914 |
except requests.Timeout:
|
|
|
964 |
if decrypted_language not in allowed_languages:
|
965 |
raise HTTPException(status_code=400, detail=f"Language must be one of {allowed_languages}")
|
966 |
|
967 |
+
logger.debug("Processing speech-to-speech request", extra={
|
968 |
"endpoint": "/v1/speech_to_speech",
|
969 |
"audio_filename": file.filename,
|
970 |
"language": decrypted_language,
|
|
|
1038 |
if decrypted_language not in allowed_languages:
|
1039 |
raise HTTPException(status_code=400, detail=f"Language must be one of {allowed_languages}")
|
1040 |
|
1041 |
+
logger.debug("Processing speech-to-speech request", extra={
|
1042 |
"endpoint": "/v1/speech_to_speech",
|
1043 |
"audio_filename": file.filename,
|
1044 |
"language": decrypted_language,
|