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