Spaces:
Running
Running
Ved Gupta
commited on
Commit
·
8713eac
1
Parent(s):
9d9b02c
v2
Browse files- README.md +9 -0
- app/api/__init__.py +2 -1
- app/api/endpoints/__init__.py +2 -1
- app/api/endpoints/transcribe.py +22 -0
- app/api/endpoints/users.py +4 -3
- app/core/config.py +5 -1
- app/core/errors.py +10 -28
- app/core/models/AuthToken.py +8 -4
- app/core/models/Transcribe.py +1 -1
- app/core/models/User.py +12 -2
- app/main.py +3 -4
- requirements.txt +2 -1
README.md
CHANGED
@@ -80,4 +80,13 @@ uvicorn app.main:app --reload
|
|
80 |
|
81 |
```bash
|
82 |
python -m unittest
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
```
|
|
|
80 |
|
81 |
```bash
|
82 |
python -m unittest
|
83 |
+
```
|
84 |
+
|
85 |
+
# Upload File
|
86 |
+
```bash
|
87 |
+
curl -X 'POST' \
|
88 |
+
'http://localhost:8000/api/v1/transcribe/' \
|
89 |
+
-H 'accept: application/json' \
|
90 |
+
-H 'Content-Type: multipart/form-data' \
|
91 |
+
-F 'audio_file=@ElevenLabs_2023-08-10T13 53 05.000Z_VedVoice_bFrkzQsyKvReo52Q6712.mp3;type=audio/mpeg'
|
92 |
```
|
app/api/__init__.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1 |
# File: whisper.api/app/api/__init__.py
|
2 |
|
3 |
from fastapi import APIRouter
|
4 |
-
from .endpoints import items, users
|
5 |
|
6 |
api_router = APIRouter()
|
7 |
|
8 |
api_router.include_router(items.router, prefix="/items", tags=["items"])
|
9 |
api_router.include_router(users.router, prefix="/users", tags=["users"])
|
|
|
|
1 |
# File: whisper.api/app/api/__init__.py
|
2 |
|
3 |
from fastapi import APIRouter
|
4 |
+
from .endpoints import items, users, transcribe
|
5 |
|
6 |
api_router = APIRouter()
|
7 |
|
8 |
api_router.include_router(items.router, prefix="/items", tags=["items"])
|
9 |
api_router.include_router(users.router, prefix="/users", tags=["users"])
|
10 |
+
api_router.include_router(transcribe.router, prefix="/transcribe", tags=["transcribe"])
|
app/api/endpoints/__init__.py
CHANGED
@@ -2,9 +2,10 @@
|
|
2 |
|
3 |
from fastapi import APIRouter
|
4 |
|
5 |
-
from . import items, users
|
6 |
|
7 |
router = APIRouter()
|
8 |
|
9 |
router.include_router(items.router, prefix="/items", tags=["items"])
|
10 |
router.include_router(users.router, prefix="/users", tags=["users"])
|
|
|
|
2 |
|
3 |
from fastapi import APIRouter
|
4 |
|
5 |
+
from . import items, users, transcribe
|
6 |
|
7 |
router = APIRouter()
|
8 |
|
9 |
router.include_router(items.router, prefix="/items", tags=["items"])
|
10 |
router.include_router(users.router, prefix="/users", tags=["users"])
|
11 |
+
router.include_router(transcribe.router, prefix="/transcribe", tags=["transcribe"])
|
app/api/endpoints/transcribe.py
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import APIRouter, File, UploadFile, Request, Header
|
2 |
+
from pydantic import BaseModel
|
3 |
+
|
4 |
+
router = APIRouter()
|
5 |
+
|
6 |
+
|
7 |
+
class AudioFile(BaseModel):
|
8 |
+
filename: str
|
9 |
+
content_type: str
|
10 |
+
|
11 |
+
|
12 |
+
@router.post("/")
|
13 |
+
async def post_audio(
|
14 |
+
request: Request, file: UploadFile = File(...), Authorization: str = Header(...)
|
15 |
+
):
|
16 |
+
"""Receive audio file and save it to disk."""
|
17 |
+
print(f"Authorization header: {Authorization}")
|
18 |
+
|
19 |
+
with open(file.filename, "wb") as f:
|
20 |
+
f.write(file.file.read())
|
21 |
+
|
22 |
+
return AudioFile(filename=file.filename, content_type=file.content_type)
|
app/api/endpoints/users.py
CHANGED
@@ -10,7 +10,7 @@ database = SessionLocal()
|
|
10 |
users_router = router = APIRouter()
|
11 |
|
12 |
|
13 |
-
@router.post("/",
|
14 |
async def create_user(user: User):
|
15 |
db_user = UserInDB(
|
16 |
username=user.username,
|
@@ -20,7 +20,8 @@ async def create_user(user: User):
|
|
20 |
database.add(db_user)
|
21 |
database.commit()
|
22 |
database.refresh(db_user)
|
23 |
-
|
|
|
24 |
|
25 |
|
26 |
@router.get("/{user_id}/", response_model=UserResponse)
|
@@ -50,7 +51,7 @@ async def update_user(user_id: UUID, user: UpdateUser):
|
|
50 |
return {**user.dict(), "id": db_user.id, "hashed_password": None}
|
51 |
|
52 |
|
53 |
-
@router.delete("/{user_id}/"
|
54 |
async def delete_user(user_id: UUID):
|
55 |
db_user = database.query(UserInDB).filter(UserInDB.id == user_id).first()
|
56 |
database.delete(db_user)
|
|
|
10 |
users_router = router = APIRouter()
|
11 |
|
12 |
|
13 |
+
@router.post("/", status_code=201)
|
14 |
async def create_user(user: User):
|
15 |
db_user = UserInDB(
|
16 |
username=user.username,
|
|
|
20 |
database.add(db_user)
|
21 |
database.commit()
|
22 |
database.refresh(db_user)
|
23 |
+
print(db_user)
|
24 |
+
return {**db_user.data()}
|
25 |
|
26 |
|
27 |
@router.get("/{user_id}/", response_model=UserResponse)
|
|
|
51 |
return {**user.dict(), "id": db_user.id, "hashed_password": None}
|
52 |
|
53 |
|
54 |
+
@router.delete("/{user_id}/")
|
55 |
async def delete_user(user_id: UUID):
|
56 |
db_user = database.query(UserInDB).filter(UserInDB.id == user_id).first()
|
57 |
database.delete(db_user)
|
app/core/config.py
CHANGED
@@ -24,7 +24,11 @@ class Settings(BaseSettings):
|
|
24 |
POSTGRES_DATABASE_URL: str = env.get("POSTGRES_DATABASE_URL")
|
25 |
TEST_DATABASE_URL: str = env.get("POSTGRES_DATABASE_URL")
|
26 |
|
27 |
-
BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = [
|
|
|
|
|
|
|
|
|
28 |
|
29 |
@validator("SECRET_KEY", pre=True)
|
30 |
def secret_key_must_be_set(cls, v: Optional[str], values: Dict[str, Any]) -> str:
|
|
|
24 |
POSTGRES_DATABASE_URL: str = env.get("POSTGRES_DATABASE_URL")
|
25 |
TEST_DATABASE_URL: str = env.get("POSTGRES_DATABASE_URL")
|
26 |
|
27 |
+
BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = [
|
28 |
+
"http://localhost:3000",
|
29 |
+
"http://localhost:8080",
|
30 |
+
"http://localhost:8000",
|
31 |
+
]
|
32 |
|
33 |
@validator("SECRET_KEY", pre=True)
|
34 |
def secret_key_must_be_set(cls, v: Optional[str], values: Dict[str, Any]) -> str:
|
app/core/errors.py
CHANGED
@@ -1,39 +1,21 @@
|
|
1 |
-
from fastapi import Request
|
2 |
from fastapi.responses import JSONResponse
|
3 |
from fastapi.exceptions import HTTPException, RequestValidationError
|
4 |
|
5 |
|
6 |
-
async def
|
7 |
"""
|
8 |
-
|
9 |
-
"""
|
10 |
-
return JSONResponse(
|
11 |
-
status_code=exc.status_code,
|
12 |
-
content={"message": exc.detail},
|
13 |
-
)
|
14 |
|
|
|
|
|
|
|
15 |
|
16 |
-
|
|
|
17 |
"""
|
18 |
-
Exception handler for HTTP errors
|
19 |
-
"""
|
20 |
-
if isinstance(exc, HTTPException):
|
21 |
-
detail = exc.detail
|
22 |
-
status_code = exc.status_code
|
23 |
-
else:
|
24 |
-
detail = "Internal server error"
|
25 |
-
status_code = 500
|
26 |
-
return JSONResponse(
|
27 |
-
status_code=status_code,
|
28 |
-
content={"message": detail},
|
29 |
-
)
|
30 |
-
|
31 |
|
32 |
-
def http422_error_handler(request: Request, exc: RequestValidationError):
|
33 |
-
"""
|
34 |
-
Exception handler for HTTP 422 errors
|
35 |
-
"""
|
36 |
return JSONResponse(
|
37 |
-
status_code=
|
38 |
-
content={"
|
39 |
)
|
|
|
1 |
+
from fastapi import Request, Response
|
2 |
from fastapi.responses import JSONResponse
|
3 |
from fastapi.exceptions import HTTPException, RequestValidationError
|
4 |
|
5 |
|
6 |
+
async def error_handler(request: Request, exc: Exception) -> JSONResponse:
|
7 |
"""
|
8 |
+
Error handler function for FastAPI.
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
+
Args:
|
11 |
+
request: The HTTP request that caused the error.
|
12 |
+
exc: The exception that was raised.
|
13 |
|
14 |
+
Returns:
|
15 |
+
The error response.
|
16 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
|
|
|
|
|
|
|
|
18 |
return JSONResponse(
|
19 |
+
status_code=500,
|
20 |
+
content={"detail": "Error Occurs"},
|
21 |
)
|
app/core/models/AuthToken.py
CHANGED
@@ -9,7 +9,7 @@ from sqlalchemy.dialects.postgresql import UUID
|
|
9 |
from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
|
10 |
from sqlalchemy.sql import func
|
11 |
|
12 |
-
from app.core.database import Base
|
13 |
|
14 |
|
15 |
class AuthToken(Base):
|
@@ -29,10 +29,14 @@ class AuthToken(Base):
|
|
29 |
return token
|
30 |
|
31 |
def generate_bearer_token(self):
|
32 |
-
token_prefix = str(
|
33 |
-
token_suffix =
|
|
|
|
|
|
|
|
|
34 |
return f"{token_prefix}{token_suffix}"
|
35 |
|
36 |
@staticmethod
|
37 |
-
def validate_bearer_token(request_token):
|
38 |
...
|
|
|
9 |
from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
|
10 |
from sqlalchemy.sql import func
|
11 |
|
12 |
+
from app.core.database import Base
|
13 |
|
14 |
|
15 |
class AuthToken(Base):
|
|
|
29 |
return token
|
30 |
|
31 |
def generate_bearer_token(self):
|
32 |
+
token_prefix = str(uuid.uuid4()).replace("-", "")
|
33 |
+
token_suffix = "".join(
|
34 |
+
random.choices(
|
35 |
+
string.ascii_uppercase + string.ascii_lowercase + string.digits, k=32
|
36 |
+
)
|
37 |
+
)
|
38 |
return f"{token_prefix}{token_suffix}"
|
39 |
|
40 |
@staticmethod
|
41 |
+
def validate_bearer_token(request_token: str):
|
42 |
...
|
app/core/models/Transcribe.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
from datetime import datetime, timedelta
|
2 |
|
3 |
-
|
4 |
import uuid
|
5 |
from app.core.config import settings
|
6 |
|
@@ -19,3 +18,4 @@ class TranscibeInDB(Base):
|
|
19 |
text = Column(String)
|
20 |
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
|
21 |
user = relationship("UserInDB", back_populates="transcribes")
|
|
|
|
1 |
from datetime import datetime, timedelta
|
2 |
|
|
|
3 |
import uuid
|
4 |
from app.core.config import settings
|
5 |
|
|
|
18 |
text = Column(String)
|
19 |
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
|
20 |
user = relationship("UserInDB", back_populates="transcribes")
|
21 |
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
app/core/models/User.py
CHANGED
@@ -4,10 +4,11 @@ import uuid
|
|
4 |
from app.core.config import settings
|
5 |
|
6 |
from sqlalchemy.dialects.postgresql import UUID
|
7 |
-
from sqlalchemy import Column, String, Boolean
|
8 |
from sqlalchemy.orm import relationship
|
|
|
9 |
|
10 |
-
from app.core.database import Base
|
11 |
|
12 |
|
13 |
class UserInDB(Base):
|
@@ -19,8 +20,17 @@ class UserInDB(Base):
|
|
19 |
hashed_password = Column(String)
|
20 |
is_active = Column(Boolean, default=True)
|
21 |
transcribes = relationship("TranscibeInDB", back_populates="user")
|
|
|
22 |
|
23 |
def __init__(self, username: str, email: str, hashed_password: str):
|
24 |
self.username = username
|
25 |
self.email = email
|
26 |
self.hashed_password = hashed_password
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
from app.core.config import settings
|
5 |
|
6 |
from sqlalchemy.dialects.postgresql import UUID
|
7 |
+
from sqlalchemy import Column, String, Boolean, DateTime
|
8 |
from sqlalchemy.orm import relationship
|
9 |
+
from sqlalchemy.sql import func
|
10 |
|
11 |
+
from app.core.database import Base
|
12 |
|
13 |
|
14 |
class UserInDB(Base):
|
|
|
20 |
hashed_password = Column(String)
|
21 |
is_active = Column(Boolean, default=True)
|
22 |
transcribes = relationship("TranscibeInDB", back_populates="user")
|
23 |
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
24 |
|
25 |
def __init__(self, username: str, email: str, hashed_password: str):
|
26 |
self.username = username
|
27 |
self.email = email
|
28 |
self.hashed_password = hashed_password
|
29 |
+
|
30 |
+
def data(self):
|
31 |
+
return {
|
32 |
+
"id": self.id,
|
33 |
+
"username": self.username,
|
34 |
+
"email": self.email,
|
35 |
+
"created_at": self.created_at,
|
36 |
+
}
|
app/main.py
CHANGED
@@ -1,8 +1,7 @@
|
|
1 |
from fastapi import FastAPI
|
2 |
from app.api import api_router
|
3 |
from app.core.config import settings
|
4 |
-
from app.core.errors import
|
5 |
-
from app.core.errors import http422_error_handler
|
6 |
from fastapi.middleware.cors import CORSMiddleware
|
7 |
|
8 |
from app.utils import print_routes
|
@@ -25,8 +24,8 @@ if settings.BACKEND_CORS_ORIGINS:
|
|
25 |
app.include_router(api_router, prefix=settings.API_V1_STR)
|
26 |
|
27 |
# # Error handlers
|
28 |
-
app.add_exception_handler(422,
|
29 |
-
app.add_exception_handler(500,
|
30 |
|
31 |
# Print all routes
|
32 |
print_routes(app)
|
|
|
1 |
from fastapi import FastAPI
|
2 |
from app.api import api_router
|
3 |
from app.core.config import settings
|
4 |
+
from app.core.errors import error_handler
|
|
|
5 |
from fastapi.middleware.cors import CORSMiddleware
|
6 |
|
7 |
from app.utils import print_routes
|
|
|
24 |
app.include_router(api_router, prefix=settings.API_V1_STR)
|
25 |
|
26 |
# # Error handlers
|
27 |
+
app.add_exception_handler(422, error_handler)
|
28 |
+
app.add_exception_handler(500, error_handler)
|
29 |
|
30 |
# Print all routes
|
31 |
print_routes(app)
|
requirements.txt
CHANGED
@@ -9,4 +9,5 @@ faker
|
|
9 |
requests-mock
|
10 |
passlib
|
11 |
httpx
|
12 |
-
PyJWT
|
|
|
|
9 |
requests-mock
|
10 |
passlib
|
11 |
httpx
|
12 |
+
PyJWT
|
13 |
+
python-multipart
|