initial commit
This commit is contained in:
commit
69416eb896
133
.gitignore
vendored
Normal file
133
.gitignore
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.env.*
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
.idea/
|
||||
|
||||
.vercel
|
0
__init__.py
Normal file
0
__init__.py
Normal file
18
app.py
Normal file
18
app.py
Normal file
@ -0,0 +1,18 @@
|
||||
from fastapi import FastAPI
|
||||
|
||||
from config.config import initiate_database
|
||||
from routes.request import router as RequestRouter
|
||||
from routes.admin import router as AdminRouter
|
||||
from config import Settings
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.on_event("startup")
|
||||
async def start_database():
|
||||
await initiate_database()
|
||||
|
||||
|
||||
app.include_router(RequestRouter, tags=["Requests"])
|
||||
|
||||
if Settings().ENV == "dev":
|
||||
app.include_router(AdminRouter, tags=["Admin"])
|
1
azure/__init__.py
Normal file
1
azure/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .functions import translate
|
27
azure/functions.py
Normal file
27
azure/functions.py
Normal file
@ -0,0 +1,27 @@
|
||||
import requests
|
||||
import uuid
|
||||
from config import Settings
|
||||
|
||||
|
||||
def translate(data):
|
||||
constructed_url = Settings().AZURE_ENDPOINT + '/translate'
|
||||
|
||||
params = {
|
||||
'api-version': '3.0',
|
||||
'from': data.language_from,
|
||||
'to': [data.language_to]
|
||||
}
|
||||
|
||||
headers = {
|
||||
'Ocp-Apim-Subscription-Key': Settings().AZURE_KEY,
|
||||
'Ocp-Apim-Subscription-Region': Settings().AZURE_LOCATION,
|
||||
'Content-type': 'application/json',
|
||||
'X-ClientTraceId': str(uuid.uuid4())
|
||||
}
|
||||
|
||||
body = [{
|
||||
'text': data.requested_text
|
||||
}]
|
||||
|
||||
request = requests.post(constructed_url, params=params, headers=headers, json=body)
|
||||
return request.json()
|
1
config/__init__.py
Normal file
1
config/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .config import Settings
|
23
config/config.py
Normal file
23
config/config.py
Normal file
@ -0,0 +1,23 @@
|
||||
from beanie import init_beanie
|
||||
from motor.motor_asyncio import AsyncIOMotorClient
|
||||
from pydantic import BaseSettings
|
||||
from typing import Literal
|
||||
|
||||
from models.request import Request
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
DATABASE_URL: str
|
||||
AZURE_KEY: str
|
||||
AZURE_ENDPOINT: str
|
||||
AZURE_LOCATION: str
|
||||
ENV: Literal["dev", "prod"]
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
orm_mode = True
|
||||
|
||||
|
||||
async def initiate_database():
|
||||
client = AsyncIOMotorClient(Settings().DATABASE_URL)
|
||||
await init_beanie(database=client.get_default_database(), document_models=[Request])
|
18
database/database.py
Normal file
18
database/database.py
Normal file
@ -0,0 +1,18 @@
|
||||
from typing import List
|
||||
from models.request import Request
|
||||
|
||||
|
||||
request_collection = Request
|
||||
|
||||
|
||||
async def add_request(item: Request) -> Request:
|
||||
return await item.create()
|
||||
|
||||
async def retrieve_requests() -> List[Request]:
|
||||
return await request_collection.all().to_list()
|
||||
|
||||
async def retrieve_request(text: str, language_from: str, language_to: str) -> List[Request]:
|
||||
return await request_collection.find({"requested_text": text, "language_from": language_from, "language_to": language_to}).to_list()
|
||||
|
||||
async def clear_requests() -> None:
|
||||
return await request_collection.delete_all()
|
40
models/request.py
Normal file
40
models/request.py
Normal file
@ -0,0 +1,40 @@
|
||||
from beanie import Document
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Request(Document):
|
||||
id: str
|
||||
requested_text: str
|
||||
response_text: str
|
||||
language_from: str
|
||||
language_to: str
|
||||
unixdate: int
|
||||
|
||||
class Settings:
|
||||
name = "request"
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"id": "9e90b529-05d0-4b0e-a8f8-de17e72e553c",
|
||||
"requested_text": "I would really like to drive your car around the block a few times!",
|
||||
"response_text": "Ich würde wirklich gerne mit Ihrem Auto ein paar Mal um den Block fahren!",
|
||||
"language_from": "en",
|
||||
"language_to": "de",
|
||||
"date": 1678225669
|
||||
}
|
||||
}
|
||||
|
||||
class RequestData(BaseModel):
|
||||
requested_text: str
|
||||
language_from: str
|
||||
language_to: str
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"requested_text": "I would really like to drive your car around the block a few times!",
|
||||
"language_from": "en",
|
||||
"language_to": "de",
|
||||
}
|
||||
}
|
9
requirements.txt
Normal file
9
requirements.txt
Normal file
@ -0,0 +1,9 @@
|
||||
requests==2.28.2
|
||||
uuid==1.30
|
||||
motor==3.1.1
|
||||
uvicorn==0.20.0
|
||||
pymongo==4.3.3
|
||||
fastapi==0.93.0
|
||||
pydantic==1.10.5
|
||||
passlib==1.7.4
|
||||
beanie==1.17.0
|
14
routes/admin.py
Normal file
14
routes/admin.py
Normal file
@ -0,0 +1,14 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
from database.database import *
|
||||
from models.request import *
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/cleardb", response_description="Clears database cache")
|
||||
async def cleardb():
|
||||
await clear_requests()
|
||||
|
||||
@router.get("/dbcache", response_description="Show database contents", response_model=List[Request])
|
||||
async def showcache():
|
||||
return await retrieve_requests()
|
37
routes/request.py
Normal file
37
routes/request.py
Normal file
@ -0,0 +1,37 @@
|
||||
from fastapi import APIRouter
|
||||
import uuid
|
||||
import time
|
||||
|
||||
from azure import translate as azure_translate
|
||||
from database.database import *
|
||||
from models.request import *
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/translate", response_description="Translate text", response_model=Request)
|
||||
async def translate(data: RequestData):
|
||||
# Check if this request is saved in the database
|
||||
check_db = await retrieve_request(data.requested_text, data.language_from, data.language_to)
|
||||
|
||||
if len(check_db) == 0: # Not in database, use azure api
|
||||
print("Not in database, use Azure api")
|
||||
# Make api request
|
||||
response = azure_translate(data)
|
||||
print(response)
|
||||
|
||||
# Create object
|
||||
item = Request(
|
||||
id=str(uuid.uuid4()),
|
||||
requested_text=data.requested_text,
|
||||
response_text=response[0]['translations'][0]['text'],
|
||||
language_from=data.language_from,
|
||||
language_to=data.language_to,
|
||||
unixdate=int(time.time())
|
||||
)
|
||||
|
||||
# Save it to the database and return it
|
||||
return await add_request(item=item)
|
||||
else:
|
||||
print("Already in database, serving the cached result")
|
||||
return check_db[0]
|
Loading…
Reference in New Issue
Block a user