diff --git a/README.md b/README.md
index 1765597..78ebe22 100644
--- a/README.md
+++ b/README.md
@@ -111,23 +111,32 @@ Some tools requires environment variables. Set envs depend on which tools you wa
### 3. Send request to EVAL
-- `POST /api/execute`
+- Use the Web GUI to use EVAL in ease
- - `session` - session id
- - `files` - urls of file inputs
- - `prompt` - prompt
+ - Go to `http://localhost:8000` in your browser
+
-- You can send request to EVAL with `curl` or `httpie`.
+- Or you can manually send request to EVAL with APIs.
- ```bash
- curl -X POST -H "Content-Type: application/json" -d '{"session": "sessionid", "files": [], "prompt": "Hi there!"}' http://localhost:8000/api/execute
- ```
+ - `POST /api/execute`
- ```bash
- http POST http://localhost:8000/api/execute session=sessionid files:='[]' prompt="Hi there!"
- ```
+ - `session` - session id
+ - `files` - urls of file inputs
+ - `prompt` - prompt
-- We are planning to make a GUI for EVAL so you can use it without terminal.
+ - examples
+
+ ```bash
+ curl -X POST -H "Content-Type: application/json" -d '{"session": "sessionid", "files": [], "prompt": "Hi there!"}' http://localhost:8000/api/execute
+ ```
+
+ ```bash
+ http POST http://localhost:8000/api/execute session=sessionid files:='[]' prompt="Hi there!"
+ ```
+
+- It also supports asynchronous execution. You can use `POST /api/execute/async` instead of `POST /api/execute`, with same body.
+
+ - It returns `id` of the execution. Use `GET /api/execute/async/{id}` to get the result.
## TODO
diff --git a/api/container.py b/api/container.py
new file mode 100644
index 0000000..028c608
--- /dev/null
+++ b/api/container.py
@@ -0,0 +1,62 @@
+import os
+import re
+from pathlib import Path
+from typing import Dict, List
+
+from fastapi.templating import Jinja2Templates
+
+from core.agents.manager import AgentManager
+from core.handlers.base import BaseHandler, FileHandler, FileType
+from core.handlers.dataframe import CsvToDataframe
+from core.tools.base import BaseToolSet
+from core.tools.cpu import ExitConversation, RequestsGet
+from core.tools.editor import CodeEditor
+from core.tools.terminal import Terminal
+from core.upload import StaticUploader
+from env import settings
+
+BASE_DIR = Path(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+os.chdir(BASE_DIR / settings["PLAYGROUND_DIR"])
+
+
+toolsets: List[BaseToolSet] = [
+ Terminal(),
+ CodeEditor(),
+ RequestsGet(),
+ ExitConversation(),
+]
+handlers: Dict[FileType, BaseHandler] = {FileType.DATAFRAME: CsvToDataframe()}
+
+if settings["USE_GPU"]:
+ import torch
+
+ from core.handlers.image import ImageCaptioning
+ from core.tools.gpu import (
+ ImageEditing,
+ InstructPix2Pix,
+ Text2Image,
+ VisualQuestionAnswering,
+ )
+
+ if torch.cuda.is_available():
+ toolsets.extend(
+ [
+ Text2Image("cuda"),
+ ImageEditing("cuda"),
+ InstructPix2Pix("cuda"),
+ VisualQuestionAnswering("cuda"),
+ ]
+ )
+ handlers[FileType.IMAGE] = ImageCaptioning("cuda")
+
+agent_manager = AgentManager.create(toolsets=toolsets)
+
+file_handler = FileHandler(handlers=handlers, path=BASE_DIR)
+
+templates = Jinja2Templates(directory=BASE_DIR / "api" / "templates")
+
+uploader = StaticUploader.from_settings(
+ settings, path=BASE_DIR / "static", endpoint="static"
+)
+
+reload_dirs = [BASE_DIR / "core", BASE_DIR / "api"]
diff --git a/api/main.py b/api/main.py
index 5126f80..898207b 100644
--- a/api/main.py
+++ b/api/main.py
@@ -1,72 +1,22 @@
-import os
import re
-from pathlib import Path
+from multiprocessing import Process
from tempfile import NamedTemporaryFile
-from typing import Dict, List, TypedDict
+from typing import List, TypedDict
import uvicorn
from fastapi import FastAPI, Request, UploadFile
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
-from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
-from core.agents.manager import AgentManager
-from core.handlers.base import BaseHandler, FileHandler, FileType
-from core.handlers.dataframe import CsvToDataframe
-from core.tools.base import BaseToolSet
-from core.tools.cpu import ExitConversation, RequestsGet
-from core.tools.editor import CodeEditor
-from core.tools.terminal import Terminal
-from core.upload import StaticUploader
+from api.container import agent_manager, file_handler, reload_dirs, templates, uploader
+from api.worker import get_task_result, start_worker, task_execute
from env import settings
app = FastAPI()
-
-BASE_DIR = Path(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-os.chdir(BASE_DIR / settings["PLAYGROUND_DIR"])
-
-uploader = StaticUploader.from_settings(
- settings, path=BASE_DIR / "static", endpoint="static"
-)
app.mount("/static", StaticFiles(directory=uploader.path), name="static")
-templates = Jinja2Templates(directory=BASE_DIR / "api" / "templates")
-
-toolsets: List[BaseToolSet] = [
- Terminal(),
- CodeEditor(),
- RequestsGet(),
- ExitConversation(),
-]
-handlers: Dict[FileType, BaseHandler] = {FileType.DATAFRAME: CsvToDataframe()}
-
-if settings["USE_GPU"]:
- import torch
-
- from core.handlers.image import ImageCaptioning
- from core.tools.gpu import (
- ImageEditing,
- InstructPix2Pix,
- Text2Image,
- VisualQuestionAnswering,
- )
-
- if torch.cuda.is_available():
- toolsets.extend(
- [
- Text2Image("cuda"),
- ImageEditing("cuda"),
- InstructPix2Pix("cuda"),
- VisualQuestionAnswering("cuda"),
- ]
- )
- handlers[FileType.IMAGE] = ImageCaptioning("cuda")
-
-agent_manager = AgentManager.create(toolsets=toolsets)
-file_handler = FileHandler(handlers=handlers, path=BASE_DIR)
-
class ExecuteRequest(BaseModel):
session: str
@@ -107,7 +57,7 @@ async def execute(request: ExecuteRequest) -> ExecuteResponse:
files = request.files
session = request.session
- executor = agent_manager.get_or_create_executor(session)
+ executor = agent_manager.create_executor(session)
promptedQuery = "\n".join([file_handler.handle(file) for file in files])
promptedQuery += query
@@ -117,7 +67,7 @@ async def execute(request: ExecuteRequest) -> ExecuteResponse:
except Exception as e:
return {"answer": str(e), "files": []}
- files = re.findall(r"\[file/\S*\]", res["output"])
+ files = re.findall(r"\[file://\S*\]", res["output"])
files = [file[1:-1] for file in files]
return {
@@ -126,15 +76,53 @@ async def execute(request: ExecuteRequest) -> ExecuteResponse:
}
+@app.post("/api/execute/async")
+async def execute_async(request: ExecuteRequest):
+ query = request.prompt
+ files = request.files
+ session = request.session
+
+ promptedQuery = "\n".join([file_handler.handle(file) for file in files])
+ promptedQuery += query
+
+ execution = task_execute.delay(session, promptedQuery)
+ return {"id": execution.id}
+
+
+@app.get("/api/execute/async/{execution_id}")
+async def execute_async(execution_id: str):
+ execution = get_task_result(execution_id)
+
+ result = {}
+ if execution.status == "SUCCESS" and execution.result:
+ output = execution.result.get("output", "")
+ files = re.findall(r"\[file://\S*\]", output)
+ files = [file[1:-1] for file in files]
+ result = {
+ "answer": output,
+ "files": [uploader.upload(file) for file in files],
+ }
+
+ return {
+ "status": execution.status,
+ "info": execution.info,
+ "result": result,
+ }
+
+
def serve():
+ p = Process(target=start_worker, args=[])
+ p.start()
uvicorn.run("api.main:app", host="0.0.0.0", port=settings["EVAL_PORT"])
def dev():
+ p = Process(target=start_worker, args=[])
+ p.start()
uvicorn.run(
"api.main:app",
host="0.0.0.0",
port=settings["EVAL_PORT"],
reload=True,
- reload_dirs=[BASE_DIR / "core", BASE_DIR / "api"],
+ reload_dirs=reload_dirs,
)
diff --git a/api/templates/base.html b/api/templates/base.html
index d35ced7..b8f7fd6 100644
--- a/api/templates/base.html
+++ b/api/templates/base.html
@@ -44,9 +44,9 @@
-->
-