Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
@@ -12,17 +12,7 @@ async def startup():
|
|
12 |
|
13 |
from pydantic import BaseModel
|
14 |
from typing import List, Dict, Any
|
15 |
-
from helper_functions_api import md_to_html, search_brave, fetch_and_extract_content, limit_tokens, together_response, insert_data
|
16 |
-
import os
|
17 |
-
from dotenv import load_dotenv, find_dotenv
|
18 |
-
from datetime import datetime, timedelta
|
19 |
-
import asyncio
|
20 |
-
import re
|
21 |
-
# Load environment variables from .env file
|
22 |
-
#load_dotenv("keys.env")
|
23 |
-
|
24 |
|
25 |
-
|
26 |
TOGETHER_API_KEY = os.getenv('TOGETHER_API_KEY')
|
27 |
BRAVE_API_KEY = os.getenv('BRAVE_API_KEY')
|
28 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
@@ -30,95 +20,103 @@ HELICON_API_KEY = os.getenv("HELICON_API_KEY")
|
|
30 |
SUPABASE_USER = os.environ['SUPABASE_USER']
|
31 |
SUPABASE_PASSWORD = os.environ['SUPABASE_PASSWORD']
|
32 |
|
33 |
-
# Groq model names
|
34 |
-
llm_default_small = "llama3-8b-8192"
|
35 |
-
llm_default_medium = "llama3-70b-8192"
|
36 |
-
|
37 |
-
# Together Model names (fallback)
|
38 |
-
llm_fallback_small = "meta-llama/Llama-3-8b-chat-hf"
|
39 |
-
llm_fallback_medium = "meta-llama/Llama-3-70b-chat-hf"
|
40 |
-
|
41 |
-
SysPromptJson = "You are now in the role of an expert AI who can extract structured information from user request. Both key and value pairs must be in double quotes. You must respond ONLY with a valid JSON file. Do not add any additional comments."
|
42 |
-
SysPromptList = "You are now in the role of an expert AI who can extract structured information from user request. All elements must be in double quotes. You must respond ONLY with a valid python List. Do not add any additional comments."
|
43 |
-
SysPromptDefault = "You are an expert AI, complete the given task. Do not add any additional comments."
|
44 |
-
SysPromptMd = "You are an expert AI who can create a structured report using information provided in the context from user request.The report should be in markdown format consists of markdown tables structured into subtopics. Do not add any additional comments."
|
45 |
-
|
46 |
-
sys_prompts = {
|
47 |
-
"offline": {
|
48 |
-
"Chat": "You are an expert AI, complete the given task. Do not add any additional comments.",
|
49 |
-
"Full Text Report": "You are an expert AI who can create a detailed report from user request. The report should be in markdown format. Do not add any additional comments.",
|
50 |
-
"Tabular Report": "You are an expert AI who can create a structured report from user request.The report should be in markdown format structured into subtopics/tables/lists. Do not add any additional comments.",
|
51 |
-
"Tables only": "You are an expert AI who can create a structured tabular report from user request.The report should be in markdown format consists of only markdown tables. Do not add any additional comments.",
|
52 |
-
},
|
53 |
-
"online": {
|
54 |
-
"Chat": "You are an expert AI, complete the given task using the provided context. Do not add any additional comments.",
|
55 |
-
"Full Text Report": "You are an expert AI who can create a detailed report using information scraped from the internet. You should decide which information is relevant to the given task and use it to create a report. The report should be in markdown format. Do not add any additional comments.",
|
56 |
-
"Tabular Report": """You are an expert AI who can provide answers using internet search results.
|
57 |
-
1 filter and summarize relevant information, if there are conflicting information, use the latest source.
|
58 |
-
2. use it to construct a clear and factual answer.
|
59 |
-
Your response should be properly formatted and well readable using markdown formatting. """,
|
60 |
-
"Tables only": "You are an expert AI who can create a structured tabular report using information scraped from the internet. You should decide which information is relevant to the given task. The report should be in markdown format consists of only markdown tables. Do not add any additional comments.",
|
61 |
-
},
|
62 |
-
}
|
63 |
-
|
64 |
-
class QueryModel(BaseModel):
|
65 |
-
topic: str = Query(default="", description="input query to generate Report")
|
66 |
-
description: str = Query(default="", description="additional context for report")
|
67 |
-
user_id: str = Query(default="", description="unique user id")
|
68 |
-
user_name: str = Query(default="", description="user name")
|
69 |
-
internet: bool = Query(default=True, description="Enable Internet search")
|
70 |
-
output_format: str = Query(default="Tabular Report", description="Output format for the report",
|
71 |
-
enum=["Chat", "Full Text Report", "Tabular Report", "Tables only"])
|
72 |
-
data_format: str = Query(default="Structured data", description="Type of data to extract from the internet",
|
73 |
-
enum=["No presets", "Structured data", "Quantitative data"])
|
74 |
-
|
75 |
-
#@cache(expire=604800)
|
76 |
-
async def generate_report(query: QueryModel):
|
77 |
-
query_str = query.topic
|
78 |
-
description = query.description
|
79 |
-
user_id = query.user_id
|
80 |
-
internet = "online" if query.internet else "offline"
|
81 |
-
sys_prompt_output_format = sys_prompts[internet][query.output_format]
|
82 |
-
data_format = query.data_format
|
83 |
-
optimized_search_query = ""
|
84 |
-
all_text_with_urls = [("", "")]
|
85 |
-
|
86 |
-
if query.internet:
|
87 |
-
search_query = re.sub(r'[^\w\s]', '', description).strip()
|
88 |
-
try:
|
89 |
-
urls, optimized_search_query = await search_brave(search_query, num_results=8)
|
90 |
-
all_text_with_urls = fetch_and_extract_content(data_format, urls, description)
|
91 |
-
additional_context = limit_tokens(str(all_text_with_urls))
|
92 |
-
prompt = f"Write a factual answer to the query:: {description} #### , refer the provided internet search results reference:{additional_context}"
|
93 |
-
except Exception as e:
|
94 |
-
print(e)
|
95 |
-
query.internet = False
|
96 |
-
print("failed to search/scrape results, falling back to LLM response")
|
97 |
-
|
98 |
-
if not query.internet:
|
99 |
-
prompt = f"#### COMPLETE THE TASK: {description} #### IN THE CONTEXT OF ### CONTEXT: {query_str}"
|
100 |
-
|
101 |
-
md_report = together_response(prompt, model=llm_default_medium, SysPrompt=sys_prompt_output_format)
|
102 |
-
|
103 |
-
if user_id != "test":
|
104 |
-
insert_data(user_id, query_str, description, str(all_text_with_urls), md_report)
|
105 |
-
references_html = {}
|
106 |
-
for text, url in all_text_with_urls:
|
107 |
-
references_html[url] = str(md_to_html(text))
|
108 |
-
|
109 |
-
return {
|
110 |
-
"report": md_to_html(md_report),
|
111 |
-
"references": references_html,
|
112 |
-
"search_query": optimized_search_query
|
113 |
-
}
|
114 |
-
|
115 |
-
@app.post("/generate_report")
|
116 |
-
async def api_generate_report(request: Request, query: QueryModel):
|
117 |
-
return await generate_report(query)
|
118 |
-
|
119 |
app.add_middleware(
|
120 |
CORSMiddleware,
|
121 |
allow_origins=["*"],
|
122 |
allow_credentials=True,
|
123 |
allow_methods=["*"],
|
124 |
-
allow_headers=["*"],)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
from pydantic import BaseModel
|
14 |
from typing import List, Dict, Any
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
|
|
16 |
TOGETHER_API_KEY = os.getenv('TOGETHER_API_KEY')
|
17 |
BRAVE_API_KEY = os.getenv('BRAVE_API_KEY')
|
18 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
|
|
20 |
SUPABASE_USER = os.environ['SUPABASE_USER']
|
21 |
SUPABASE_PASSWORD = os.environ['SUPABASE_PASSWORD']
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
app.add_middleware(
|
24 |
CORSMiddleware,
|
25 |
allow_origins=["*"],
|
26 |
allow_credentials=True,
|
27 |
allow_methods=["*"],
|
28 |
+
allow_headers=["*"],)
|
29 |
+
|
30 |
+
import asyncio
|
31 |
+
import uvicorn
|
32 |
+
from fastapi import FastAPI, HTTPException
|
33 |
+
from pydantic import BaseModel
|
34 |
+
from jupyter_client import KernelManager
|
35 |
+
from typing import Dict
|
36 |
+
from datetime import datetime, timedelta
|
37 |
+
import psutil
|
38 |
+
|
39 |
+
app = FastAPI()
|
40 |
+
|
41 |
+
# Model for input data
|
42 |
+
class CodeExecutionRequest(BaseModel):
|
43 |
+
session_token: str
|
44 |
+
code: str
|
45 |
+
|
46 |
+
# Store kernel managers and last access times
|
47 |
+
kernel_managers: Dict[str, KernelManager] = {}
|
48 |
+
last_access_times: Dict[str, datetime] = {}
|
49 |
+
|
50 |
+
# Timeout duration in seconds
|
51 |
+
TIMEOUT_DURATION = 600 # 10 minutes
|
52 |
+
|
53 |
+
# Function to create a new kernel
|
54 |
+
async def create_kernel(session_token: str):
|
55 |
+
km = KernelManager()
|
56 |
+
km.start_kernel()
|
57 |
+
kernel_managers[session_token] = km
|
58 |
+
last_access_times[session_token] = datetime.now()
|
59 |
+
|
60 |
+
# Function to kill a kernel
|
61 |
+
async def kill_kernel(session_token: str):
|
62 |
+
km = kernel_managers.pop(session_token, None)
|
63 |
+
if km:
|
64 |
+
km.shutdown_kernel(now=True)
|
65 |
+
last_access_times.pop(session_token, None)
|
66 |
+
|
67 |
+
# Function to execute code in a kernel
|
68 |
+
async def execute_code(session_token: str, code: str):
|
69 |
+
if session_token not in kernel_managers:
|
70 |
+
await create_kernel(session_token)
|
71 |
+
|
72 |
+
km = kernel_managers[session_token]
|
73 |
+
kc = km.client()
|
74 |
+
kc.start_channels()
|
75 |
+
|
76 |
+
try:
|
77 |
+
kc.execute(code)
|
78 |
+
reply = kc.get_shell_msg(timeout=5)
|
79 |
+
result = reply['content']
|
80 |
+
except Exception as e:
|
81 |
+
result = {'status': 'error', 'ename': type(e).__name__, 'evalue': str(e)}
|
82 |
+
|
83 |
+
kc.stop_channels()
|
84 |
+
last_access_times[session_token] = datetime.now()
|
85 |
+
return result
|
86 |
+
|
87 |
+
# Background task to check for idle kernels
|
88 |
+
async def check_idle_kernels():
|
89 |
+
while True:
|
90 |
+
now = datetime.now()
|
91 |
+
for session_token, last_access in list(last_access_times.items()):
|
92 |
+
if now - last_access > timedelta(seconds=TIMEOUT_DURATION):
|
93 |
+
await kill_kernel(session_token)
|
94 |
+
await asyncio.sleep(60) # Check every minute
|
95 |
+
|
96 |
+
@app.on_event("startup")
|
97 |
+
async def startup_event():
|
98 |
+
asyncio.create_task(check_idle_kernels())
|
99 |
+
|
100 |
+
@app.post("/execute")
|
101 |
+
async def execute(request: CodeExecutionRequest):
|
102 |
+
result = await execute_code(request.session_token, request.code)
|
103 |
+
return result
|
104 |
+
|
105 |
+
@app.get("/info")
|
106 |
+
async def get_info():
|
107 |
+
# Get the number of active kernels
|
108 |
+
active_kernels = len(kernel_managers)
|
109 |
+
|
110 |
+
# Get system resource usage
|
111 |
+
cpu_usage = psutil.cpu_percent(interval=1)
|
112 |
+
ram_usage = psutil.virtual_memory().percent
|
113 |
+
|
114 |
+
# Return the information
|
115 |
+
return {
|
116 |
+
"active_kernels": active_kernels,
|
117 |
+
"cpu_usage_percent": cpu_usage,
|
118 |
+
"ram_usage_percent": ram_usage
|
119 |
+
}
|
120 |
+
|
121 |
+
if __name__ == "__main__":
|
122 |
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|