-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🚀 RELEASE: Version bump to 1.1.0. Added a basic REST-API wrapper. #2
* 📦 NEW: Wrapped REST API endpoint around Meeseeks core. * 📦 NEW: Docker image for API & Build action update
- Loading branch information
Showing
7 changed files
with
246 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# syntax=docker/dockerfile:1 | ||
|
||
# Dockerfile.api | ||
ARG BASE_IMAGE="ghcr.io/bearlike/meeseeks-base:latest" | ||
FROM $BASE_IMAGE | ||
|
||
ARG TITLE="Meeseeks API: Personal Assistant" | ||
|
||
LABEL title=$TITLE | ||
|
||
# Install the meeseeks-api dependencies | ||
WORKDIR /app/meeseeks-api | ||
RUN poetry install | ||
|
||
# Set API specific environment variable | ||
ENV MASTER_API_TOKEN='msk-strong-password' | ||
|
||
# Expose port 5123 for the API | ||
EXPOSE 5123 | ||
|
||
# Run the API application | ||
ENTRYPOINT ["poetry", "run", "python", "backend.py"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# syntax=docker/dockerfile:1 | ||
|
||
# Dockerfile.chat | ||
ARG BASE_IMAGE="ghcr.io/bearlike/meeseeks-base:latest" | ||
FROM $BASE_IMAGE | ||
|
||
ARG TITLE="Meeseeks Chat: Personal Assistant" | ||
|
||
LABEL title=$TITLE | ||
|
||
# Install the meeseeks-chat dependencies | ||
WORKDIR /app/meeseeks-chat | ||
RUN poetry install | ||
|
||
# Expose port 8502 for Streamlit | ||
EXPOSE 8502 | ||
|
||
# Healthcheck to ensure the Streamlit server is running | ||
HEALTHCHECK CMD curl --fail http://localhost:8502/_stcore/health | ||
|
||
# Run the Streamlit application | ||
ENTRYPOINT ["poetry", "run", "python", "-m", "streamlit", "run", "chat_master.py", "--server.port=8502", "--server.address=0.0.0.0"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# meeseeks-api | ||
|
||
REST API Engine wrapped around the meeseeks-core | ||
- REST API Engine wrapped around the meeseeks-core. | ||
- No components are explicitly tested for safety or security. Use with caution in a production environment. | ||
|
||
[Link to GitHub Repository](https://github.com/bearlike/Personal-Assistant/edit/main/README.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,128 @@ | ||
#!/usr/bin/env python3 | ||
# TODO: Complete the API submodule by wrapping around the Meeseeks core. | ||
""" | ||
Meeseeks API | ||
This module implements a REST API for Meeseeks using Flask-RESTX. | ||
It provides a single endpoint to interact with the Meeseeks core, | ||
allowing users to submit queries and receive the executed action plan | ||
as a JSON response. | ||
""" | ||
# TODO: API key authentication and rate limiting not implemented yet. | ||
# Standard library modules | ||
import os | ||
import sys | ||
from flask import Flask, request | ||
from flask_restx import Api, Resource | ||
# TODO: Need to package the application and import it as module | ||
from typing import Dict | ||
|
||
# Third-party modules | ||
from flask import Flask, request, jsonify | ||
from flask_restx import Api, Resource, fields | ||
from dotenv import load_dotenv | ||
|
||
# Adding the parent directory to the path before importing the custom modules | ||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) | ||
|
||
# Custom imports - Meeseeks core modules | ||
from core.task_master import generate_action_plan, run_action_plan | ||
if True: | ||
from core.task_master import generate_action_plan, run_action_plan | ||
from core.classes import TaskQueue | ||
from core.common import get_logger | ||
|
||
# Load environment variables | ||
load_dotenv() | ||
# Get the API token from the environment variables | ||
# The default API token is "msk-strong-password" | ||
MASTER_API_TOKEN = os.getenv("MASTER_API_TOKEN", "msk-strong-password") | ||
|
||
# Initialize logger | ||
logging = get_logger(name="meeseeks-api") | ||
logging.debug("Starting API server with API token: %s", MASTER_API_TOKEN) | ||
# Create Flask application | ||
app = Flask(__name__) | ||
api = Api(app) | ||
|
||
authorizations = { | ||
'apikey': { | ||
'type': 'apiKey', | ||
'in': 'header', | ||
'name': 'X-API-KEY' | ||
} | ||
} | ||
VERSION = os.getenv("VERSION", "(Dev)") | ||
# Create API instance with Swagger documentation | ||
api = Api(app, version=VERSION, title='Meeseeks API', | ||
description='Interact with Meeseeks through a REST API', | ||
doc='/swagger-ui/', authorizations=authorizations, security='apikey') | ||
|
||
# Define API namespace | ||
ns = api.namespace('api', description='Meeseeks operations') | ||
|
||
# Define API model for request and response | ||
task_queue_model = api.model('TaskQueue', { | ||
'human_message': fields.String( | ||
required=True, description='The original user query'), | ||
'action_steps': fields.List(fields.Nested(api.model('ActionStep', { | ||
'action_consumer': fields.String( | ||
required=True, | ||
description='The tool responsible for executing the action'), | ||
'action_type': fields.String( | ||
required=True, | ||
description='The type of action to be performed (get/set)'), | ||
'action_argument': fields.String( | ||
required=True, | ||
description='The specific argument for the action'), | ||
'result': fields.String( | ||
description='The result of the executed action') | ||
}))), | ||
}) | ||
|
||
|
||
@ns.route('/query') | ||
class MeeseeksQuery(Resource): | ||
""" | ||
Endpoint to submit a query to Meeseeks and receive the executed | ||
action plan as a JSON response. | ||
""" | ||
|
||
@api.doc(security='apikey') | ||
@api.expect(api.model('Query', {'query': fields.String( | ||
required=True, description='The user query')})) | ||
@api.response(200, 'Success', task_queue_model) | ||
@api.response(400, 'Invalid input') | ||
@api.response(401, 'Unauthorized') | ||
def post(self) -> Dict: | ||
""" | ||
Process a user query, generate and execute the action plan, | ||
and return the result as a JSON. | ||
Requires a valid API token for authorization. | ||
""" | ||
# Get API token from headers | ||
api_token = request.headers.get('X-API-Key', None) | ||
|
||
# Validate API token | ||
if api_token is None: | ||
return {"message": "API token is not provided."}, 401 | ||
if api_token != MASTER_API_TOKEN: | ||
logging.warning( | ||
"Unauthorized API call attempt with token: %s", api_token) | ||
return {"message": "Unauthorized"}, 401 | ||
|
||
# Get user query from request data | ||
user_query = request.json.get('query') | ||
if not user_query: | ||
return {"message": "Invalid input: 'query' is required"}, 400 | ||
|
||
logging.info("Received user query: %s", user_query) | ||
|
||
@api.route('/generate_action_plan') | ||
class GenerateActionPlanResource(Resource): | ||
def post(self): | ||
user_input = request.json.get('user_input') | ||
action_plan_list, task_queue = generate_action_plan(user_input) | ||
return {'action_plan_list': action_plan_list, 'task_queue': task_queue} | ||
# Generate action plan from user query | ||
task_queue: TaskQueue = generate_action_plan(user_query=user_query) | ||
|
||
# Execute action plan | ||
task_queue = run_action_plan(task_queue) | ||
|
||
@api.route('/run_action_plan') | ||
class RunActionPlanResource(Resource): | ||
def post(self): | ||
task_queue = request.json.get('task_queue') | ||
ai_response = run_action_plan(task_queue) | ||
return {'ai_response': ai_response} | ||
# Return TaskQueue as JSON | ||
logging.info("Returning executed action plan.") | ||
return task_queue.dict(), 200 | ||
|
||
|
||
if __name__ == '__main__': | ||
app.run(debug=True) | ||
app.run(debug=True, host='0.0.0.0', port=5123) |