2024-06-22 12:31:53 +00:00
|
|
|
import uuid
|
2023-10-15 20:04:58 +00:00
|
|
|
import transformers
|
2024-06-23 18:23:15 +00:00
|
|
|
import asyncio
|
2024-06-28 11:14:49 +00:00
|
|
|
import os
|
2024-06-19 13:06:23 +00:00
|
|
|
import torch
|
2024-06-28 11:14:49 +00:00
|
|
|
import aiohttp
|
2023-10-16 10:45:15 +00:00
|
|
|
from fastapi import FastAPI
|
|
|
|
from pydantic import BaseModel
|
2024-06-20 09:26:16 +00:00
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
from apscheduler.schedulers.background import BackgroundScheduler
|
2023-10-16 10:45:15 +00:00
|
|
|
|
2024-06-28 11:14:49 +00:00
|
|
|
# ENV VARS
|
|
|
|
ONEUPTIME_URL = os.getenv("ONEUPTIME_URL")
|
|
|
|
|
|
|
|
if not ONEUPTIME_URL:
|
|
|
|
ONEUPTIME_URL = "https://oneuptime.com"
|
|
|
|
|
|
|
|
print(f"ONEUPTIME_URL: {ONEUPTIME_URL}")
|
|
|
|
|
2024-06-19 20:58:08 +00:00
|
|
|
# TODO: Store this in redis down the line.
|
|
|
|
items_pending = {}
|
|
|
|
items_processed = {}
|
2024-06-27 13:57:05 +00:00
|
|
|
errors = {}
|
2023-10-16 10:45:15 +00:00
|
|
|
|
2024-06-28 11:14:49 +00:00
|
|
|
async def validateSecretKey(secretKey):
|
|
|
|
try:
|
|
|
|
|
|
|
|
# If no secret key then return false
|
|
|
|
if not secretKey:
|
|
|
|
return False
|
|
|
|
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
|
|
url = f"{ONEUPTIME_URL}/api/code-repository/is-valid/{secretKey}"
|
|
|
|
async with session.get(url) as response:
|
|
|
|
if response.status == 200:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
print(repr(e))
|
|
|
|
return False
|
|
|
|
|
2024-06-27 14:56:22 +00:00
|
|
|
async def job(queue):
|
2024-06-20 09:26:16 +00:00
|
|
|
print("Processing queue...")
|
|
|
|
|
2024-06-27 14:56:22 +00:00
|
|
|
model_path = "/app/Models/Meta-Llama-3-8B-Instruct"
|
2024-06-23 18:40:38 +00:00
|
|
|
|
2024-06-27 14:56:22 +00:00
|
|
|
pipe = transformers.pipeline(
|
|
|
|
"text-generation",
|
|
|
|
model=model_path,
|
|
|
|
# use gpu if available
|
|
|
|
device="cuda" if torch.cuda.is_available() else "cpu",
|
|
|
|
)
|
2024-06-23 20:31:43 +00:00
|
|
|
|
2024-06-27 14:56:22 +00:00
|
|
|
while True:
|
|
|
|
|
|
|
|
random_id = None
|
|
|
|
|
|
|
|
try:
|
2024-06-23 20:31:43 +00:00
|
|
|
# process this item.
|
2024-06-27 14:56:22 +00:00
|
|
|
random_id = await queue.get()
|
2024-06-23 20:31:43 +00:00
|
|
|
print(f"Processing item {random_id}")
|
|
|
|
messages = items_pending[random_id]
|
|
|
|
print(f"Messages:")
|
|
|
|
print(messages)
|
|
|
|
outputs = pipe(messages)
|
|
|
|
items_processed[random_id] = outputs
|
|
|
|
del items_pending[random_id]
|
|
|
|
print(f"Processed item {random_id}")
|
|
|
|
except Exception as e:
|
|
|
|
print(f"Error processing item {random_id}")
|
2024-06-27 13:57:05 +00:00
|
|
|
# store error
|
2024-06-27 14:56:22 +00:00
|
|
|
errors[random_id] = repr(e)
|
2024-06-23 20:31:43 +00:00
|
|
|
# delete from items_pending
|
|
|
|
if random_id in items_pending:
|
|
|
|
del items_pending[random_id]
|
|
|
|
print(e)
|
2024-06-20 09:26:16 +00:00
|
|
|
|
2024-06-23 18:23:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2024-06-20 09:26:16 +00:00
|
|
|
@asynccontextmanager
|
|
|
|
async def lifespan(app:FastAPI):
|
2024-06-27 14:56:22 +00:00
|
|
|
queue = asyncio.Queue()
|
|
|
|
app.model_queue = queue
|
|
|
|
asyncio.create_task(job(queue))
|
2024-06-20 09:26:16 +00:00
|
|
|
yield
|
|
|
|
|
2023-10-16 10:45:15 +00:00
|
|
|
# Declare a Pydantic model for the request body
|
|
|
|
class Prompt(BaseModel):
|
2024-06-27 20:11:57 +00:00
|
|
|
messages: list
|
2024-06-28 11:14:49 +00:00
|
|
|
secretkey: str
|
2023-10-16 10:45:15 +00:00
|
|
|
|
2024-06-19 20:58:08 +00:00
|
|
|
# Declare a Pydantic model for the request body
|
|
|
|
class PromptResult(BaseModel):
|
|
|
|
id: str
|
2024-06-28 11:14:49 +00:00
|
|
|
secretkey: str
|
2024-06-19 20:58:08 +00:00
|
|
|
|
2024-06-20 09:26:16 +00:00
|
|
|
app = FastAPI(lifespan=lifespan)
|
2023-10-16 10:45:15 +00:00
|
|
|
|
2024-06-19 13:06:23 +00:00
|
|
|
@app.get("/")
|
|
|
|
async def root():
|
2024-06-22 12:31:53 +00:00
|
|
|
return {"status": "ok"}
|
2024-06-19 13:06:23 +00:00
|
|
|
|
2023-10-16 10:45:15 +00:00
|
|
|
@app.post("/prompt/")
|
|
|
|
async def create_item(prompt: Prompt):
|
|
|
|
|
2024-06-27 20:19:44 +00:00
|
|
|
try:
|
|
|
|
# If not prompt then return bad request error
|
|
|
|
if not prompt:
|
|
|
|
return {"error": "Prompt is required"}
|
|
|
|
|
2024-06-28 11:14:49 +00:00
|
|
|
# Validate the secret key
|
|
|
|
is_valid = await validateSecretKey(prompt_status.secretkey)
|
|
|
|
|
|
|
|
if not is_valid:
|
|
|
|
print("Invalid secret key")
|
|
|
|
return {"error": "Invalid secret key"}
|
|
|
|
|
2024-06-27 20:19:44 +00:00
|
|
|
# messages are in str format. We need to convert them fron json [] to list
|
|
|
|
messages = prompt.messages
|
2023-10-16 10:45:15 +00:00
|
|
|
|
2024-06-27 20:19:44 +00:00
|
|
|
# Log prompt to console
|
|
|
|
print(messages)
|
2024-06-18 17:42:11 +00:00
|
|
|
|
2024-06-27 20:19:44 +00:00
|
|
|
# Generate UUID
|
|
|
|
random_id = str(uuid.uuid4())
|
2024-06-19 20:58:08 +00:00
|
|
|
|
2024-06-27 20:19:44 +00:00
|
|
|
# add to queue
|
2024-06-19 20:58:08 +00:00
|
|
|
|
2024-06-27 20:19:44 +00:00
|
|
|
items_pending[random_id] = messages
|
|
|
|
await app.model_queue.put(random_id)
|
2024-06-19 20:58:08 +00:00
|
|
|
|
2024-06-27 20:19:44 +00:00
|
|
|
# Return response
|
|
|
|
return {
|
|
|
|
"id": random_id,
|
|
|
|
"status": "queued"
|
|
|
|
}
|
|
|
|
except Exception as e:
|
2024-06-27 20:23:24 +00:00
|
|
|
print(e)
|
2024-06-27 20:19:44 +00:00
|
|
|
return {"error": repr(e)}
|
2024-06-19 20:58:08 +00:00
|
|
|
|
2024-06-28 11:14:49 +00:00
|
|
|
# Disable this API in production
|
2024-06-22 12:31:53 +00:00
|
|
|
@app.get("/queue-status/")
|
|
|
|
async def queue_status():
|
2024-06-27 20:19:44 +00:00
|
|
|
try:
|
|
|
|
return {"pending": items_pending, "processed": items_processed, "queue": app.model_queue.qsize(), "errors": errors}
|
|
|
|
except Exception as e:
|
2024-06-27 20:23:24 +00:00
|
|
|
print(e)
|
2024-06-27 20:19:44 +00:00
|
|
|
return {"error": repr(e)}
|
2024-06-22 12:31:53 +00:00
|
|
|
|
2024-06-19 20:58:08 +00:00
|
|
|
@app.post("/prompt-result/")
|
|
|
|
async def prompt_status(prompt_status: PromptResult):
|
2024-06-27 20:19:44 +00:00
|
|
|
try:
|
2024-06-19 20:58:08 +00:00
|
|
|
# Log prompt status to console
|
|
|
|
print(prompt_status)
|
2024-06-28 11:14:49 +00:00
|
|
|
|
|
|
|
# Validate the secret key
|
|
|
|
is_valid = await validateSecretKey(prompt_status.secretkey)
|
|
|
|
|
|
|
|
if not is_valid:
|
|
|
|
print("Invalid secret key")
|
|
|
|
return {"error": "Invalid secret key"}
|
|
|
|
|
2024-06-19 20:58:08 +00:00
|
|
|
# If not prompt status then return bad request error
|
|
|
|
if not prompt_status:
|
|
|
|
return {"error": "Prompt status is required"}
|
|
|
|
|
|
|
|
# check if item is processed.
|
|
|
|
if prompt_status.id in items_processed:
|
|
|
|
|
|
|
|
|
|
|
|
return_value = {
|
|
|
|
"id": prompt_status.id,
|
|
|
|
"status": "processed",
|
|
|
|
"output": items_processed[prompt_status.id]
|
|
|
|
}
|
|
|
|
|
|
|
|
# delete from item_processed
|
|
|
|
del items_processed[prompt_status.id]
|
|
|
|
|
|
|
|
return return_value
|
|
|
|
else:
|
2024-06-20 10:00:07 +00:00
|
|
|
|
|
|
|
status = "not found"
|
|
|
|
|
|
|
|
if prompt_status.id in items_pending:
|
|
|
|
status = "pending"
|
|
|
|
|
2024-06-19 20:58:08 +00:00
|
|
|
return {
|
|
|
|
"id": prompt_status.id,
|
2024-06-20 10:00:07 +00:00
|
|
|
"status": status
|
2024-06-19 20:58:08 +00:00
|
|
|
}
|
2024-06-27 20:19:44 +00:00
|
|
|
except Exception as e:
|
2024-06-27 20:23:24 +00:00
|
|
|
print(e)
|
2024-06-27 20:19:44 +00:00
|
|
|
return {"error": repr(e)}
|
2024-06-19 20:58:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|