From a8c79d17e3f689e6ddbd281b019633b289d0e9fe Mon Sep 17 00:00:00 2001 From: amirrr <6696894+amirrr@users.noreply.github.com> Date: Sat, 13 Jul 2024 16:11:45 +0200 Subject: [PATCH] add working assistant --- .vscode/launch.json | 10 +++---- Dockerfile | 1 - client/src/pages/Login/Galaxy.tsx | 2 +- client/src/pages/Login/stars-render.ts | 8 +++--- server/api.py | 28 +++----------------- server/assistant.py | 36 ++++++++++++++++---------- server/config/app_config.py | 4 ++- server/controllers/assisstant.py | 29 +++++++-------------- 8 files changed, 46 insertions(+), 72 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index dcbddc1..8f1b0ba 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,14 +5,12 @@ "version": "0.2.0", "configurations": [ { - "name": "Python Debugger: Flask", + "name": "Python: Debug Atlas server ", "type": "debugpy", "request": "launch", - "module": "flask", - "env": { "FLASK_APP": "server/api.py", "FLASK_DEBUG": "1" }, - "args": ["run", "--no-debugger", "--no-reload", "--port", "8000"], - "jinja": true, - "autoStartBrowser": false + "program": "${workspaceFolder}/server/api.py", + "console": "integratedTerminal", + "args": ["--port", "8000", "--dev", "true"] } ] } diff --git a/Dockerfile b/Dockerfile index 4ea2cf1..30332ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,6 @@ RUN mkdir ./api COPY server ./api RUN pip install --upgrade pip RUN pip install -r ./api/requirements.txt -RUN pip install gunicorn eventlet ENV FLASK_ENV production EXPOSE 80 diff --git a/client/src/pages/Login/Galaxy.tsx b/client/src/pages/Login/Galaxy.tsx index 68ac694..4312b01 100644 --- a/client/src/pages/Login/Galaxy.tsx +++ b/client/src/pages/Login/Galaxy.tsx @@ -20,7 +20,7 @@ const Galaxy = ({ loggingIn }: { loggingIn?: boolean }) => { useEffect(() => { const starDensity = 0.216 - const speedCoeff = 0.05 + const speedCoeff = 0.03 const giantColor = '180,184,240' const starColor = '226,225,142' const cometColor = '226,225,224' diff --git a/client/src/pages/Login/stars-render.ts b/client/src/pages/Login/stars-render.ts index f27514e..e2d072e 100644 --- a/client/src/pages/Login/stars-render.ts +++ b/client/src/pages/Login/stars-render.ts @@ -23,8 +23,8 @@ export class Star { reset() { const { getRandInterval, getProbability } = this.constructor as typeof Star - this.giant = getProbability(3) - this.comet = this.giant || this.first ? false : getProbability(10) + this.giant = getProbability(5) + this.comet = this.giant || this.first ? false : getProbability(3) this.x = getRandInterval(0, this.width - 10) this.y = getRandInterval(0, this.height) this.r = getRandInterval(1.1, 2.6) @@ -67,10 +67,10 @@ export class Star { if (this.giant) { universe.fillStyle = `rgba(${this.colors.giantColor},${this.opacity})` - universe.arc(this.x, this.y, 2, 0, 2 * Math.PI, false) + universe.arc(this.x, this.y, 3, 0, 2 * Math.PI, false) } else if (this.comet) { universe.fillStyle = `rgba(${this.colors.cometColor},${this.opacity})` - universe.arc(this.x, this.y, 1.5, 0, 2 * Math.PI, false) + universe.arc(this.x, this.y, 2.5, 0, 2 * Math.PI, false) for (let i = 0; i < 30; i++) { universe.fillStyle = `rgba(${this.colors.cometColor},${this.opacity - (this.opacity / 20) * i})` diff --git a/server/api.py b/server/api.py index 27f295b..16ad9af 100644 --- a/server/api.py +++ b/server/api.py @@ -4,7 +4,6 @@ import os from sanic import Sanic, response from sanic.request import Request -from sanic_jwt import Initialize from sanic_cors import CORS import socketio from config.app_config import AppConfig @@ -32,27 +31,6 @@ async def attach_db(_app, _loop): await init_db() -# Define JWT authentication -async def authenticate(request): - """ - Authenticate the user. - """ - email = request.json.get("email", None) - print(email) - if email: - user = await login_user(email) - return user - return None - - -Initialize(app, authenticate=authenticate) - -# # Define API resources -# app.add_route(GetFeatures.as_view(), "/api/features") -# app.add_route(RunAssistant.as_view(), "/api/run_assistant") - - -# TODO: add login rate limiter @app.route("/api/login", methods=["POST"]) async def login(request: Request): """ @@ -82,7 +60,7 @@ async def run_assistant_endpoint(request: Request): Handles the POST request for running the assistant. """ if request.method == "POST": - file = request.form.get("file") + file = request.files.get("file") sid = request.form.get("sid") return await run_assistant(sid=sid, file=file, sio=sio) @@ -136,11 +114,11 @@ def parse_args(): "-p", "--port", help="Port for the server.", type=int, default=80 ) parser.add_argument( - "-d", "--debug", help="Debug mode on or off.", type=bool, default=False + "-d", "--dev", help="Dev mode on or off.", type=bool, default=False ) return parser.parse_args() if __name__ == "__main__": args = parse_args() - app.run(host="0.0.0.0", port=args.port, debug=args.debug) + app.run(host="0.0.0.0", port=args.port, dev=args.dev) diff --git a/server/assistant.py b/server/assistant.py index a1b4c11..e3f8f06 100644 --- a/server/assistant.py +++ b/server/assistant.py @@ -8,6 +8,8 @@ from typing import Dict, List, Union from openai import OpenAI from dotenv import load_dotenv +from sanic.request.form import File +import socketio load_dotenv() @@ -221,7 +223,7 @@ def build_feature_functions( return experiments_function_call -def upload_file_to_vector_store(client: OpenAI, file_path: str) -> str: +def upload_file_to_vector_store(client: OpenAI, file: File, sid: str) -> str: """ Uploads a file to the vector store. @@ -232,6 +234,12 @@ def upload_file_to_vector_store(client: OpenAI, file_path: str) -> str: - URL to the uploaded file. """ + file_path = f"paper/{sid}{file.name}" + + with open(file_path, "wb") as f: + f.write(file.body) + f.close() + file_info = client.files.create(file=open(file_path, "rb"), purpose="assistants") now = datetime.now() @@ -311,12 +319,12 @@ def create_temporary_assistant(client: OpenAI): return my_temporary_assistant -def call_asssistant_api(file_path: str, sid: str, sio): +async def call_asssistant_api(file: File, sid: str, sio: socketio.AsyncServer): client = OpenAI() try: - sio.emit( + await sio.emit( "status", {"status": "Fetching all features...", "progress": 0}, to=sid, @@ -324,7 +332,7 @@ def call_asssistant_api(file_path: str, sid: str, sio): ) feature_list = get_all_features() - sio.emit( + await sio.emit( "status", {"status": "Building feature functions...", "progress": 5}, to=sid, @@ -332,15 +340,15 @@ def call_asssistant_api(file_path: str, sid: str, sio): ) functions = build_feature_functions(feature_list) - sio.emit( + await sio.emit( "status", {"status": "Uploading file to vector store...", "progress": 10}, to=sid, namespace="/home", ) - vector_store = upload_file_to_vector_store(client, file_path) + vector_store = upload_file_to_vector_store(client=client, file=file, sid=sid) - sio.emit( + await sio.emit( "status", {"status": "Creating an assistant for your task...", "progress": 12}, to=sid, @@ -348,7 +356,7 @@ def call_asssistant_api(file_path: str, sid: str, sio): ) my_temporary_assistant = create_temporary_assistant(client) - sio.emit( + await sio.emit( "status", {"status": "Updating assistant...", "progress": 15}, to=sid, @@ -358,7 +366,7 @@ def call_asssistant_api(file_path: str, sid: str, sio): client, my_temporary_assistant.id, vector_store, functions ) - sio.emit( + await sio.emit( "status", {"status": "Creating thread message...", "progress": 30}, to=sid, @@ -368,12 +376,12 @@ def call_asssistant_api(file_path: str, sid: str, sio): messages=[ { "role": "user", - "content": "define_experiments_conditions_and_behaviors", + "content": "run function define_experiments_conditions_and_behaviors", } ], ) - sio.emit( + await sio.emit( "status", {"status": "Running assistant...", "progress": 40}, to=sid, @@ -384,7 +392,7 @@ def call_asssistant_api(file_path: str, sid: str, sio): thread_id=thread_message.id, assistant_id=updated_assistant.id ) - sio.emit( + await sio.emit( "status", {"status": "Getting tool outputs...", "progress": 50}, to=sid, @@ -395,7 +403,7 @@ def call_asssistant_api(file_path: str, sid: str, sio): run.required_action.submit_tool_outputs.tool_calls[0].function.arguments ) - sio.emit( + await sio.emit( "status", {"status": "Checking output format...", "progress": 60}, to=sid, @@ -413,7 +421,7 @@ def call_asssistant_api(file_path: str, sid: str, sio): print(e) raise AssistantException("Assistant run failed") from e finally: - sio.emit( + await sio.emit( "status", {"status": "Cleaning up resources...", "progress": 70}, to=sid, diff --git a/server/config/app_config.py b/server/config/app_config.py index 30e50ec..9a488e0 100644 --- a/server/config/app_config.py +++ b/server/config/app_config.py @@ -21,7 +21,9 @@ class AppConfig(Config): JWT_EXP_DELTA_SECONDS (int): The expiration time for JWT tokens in seconds. """ - BASE_URL = os.getenv("BASE_URL") + BASE_URL = os.getenv( + "FLASK_ENV" == "development" and "BASE_URL_DEV" or "BASE_URL_PROD" + ) SECRET = os.getenv("SOCKET_SECRET") JWT_SECRET = os.getenv("JWT_SECRET") JWT_ALGORITHM = "HS256" diff --git a/server/controllers/assisstant.py b/server/controllers/assisstant.py index 164254c..62cdc48 100644 --- a/server/controllers/assisstant.py +++ b/server/controllers/assisstant.py @@ -4,9 +4,9 @@ import os from sanic import json as json_response +from sanic.request.form import File import socketio - from assistant import AssistantException, call_asssistant_api @@ -16,41 +16,30 @@ os.makedirs(UPLOAD_DIRECTORY) -def run_assistant(sid, file, sio: socketio.AsyncServer): +async def run_assistant(sid: str, file: File, sio: socketio.AsyncServer): """ Run the assistant with the uploaded file """ + + print("Running assistant", sid, file.name) if file: - file_path = os.path.join(UPLOAD_DIRECTORY, file.filename) - file.save(file_path) try: - result = call_asssistant_api(file_path, sid, sio) - - # print("result : ", json.dumps(result)) - sio.emit( - "status", - {"status": "Fetching all features...", "progress": 0}, - to=sid, - ) + result = await call_asssistant_api(file=file, sid=sid, sio=sio) response_data = { "message": "File successfully uploaded", - "file_name": file.filename, + "file_name": file.name, "experiments": result["experiments"], } - # Delete the uploaded - if os.path.isfile(file_path): - os.remove(file_path) + if os.path.isfile(f"paper/{sid}{file.name}"): + os.remove(f"paper/{sid}{file.name}") print("File removed from local storage successfully") else: # If it fails, inform the user. - print(f"Error: {file_path} file not found") + print(f"Error: {f"paper/{sid}{file.name}"} file not found") return json_response(body=response_data, status=200) except AssistantException as e: response_data = {"error": str(e)} return json_response(body=response_data, status=500) - else: - response_data = {"error": "File upload failed"} - return json_response(body=response_data, status=400)