diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6a61899 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,29 @@ +# Ignore environment files +.env +.env.example + +# Ignore git files +.gitattributes +.gitignore + +# Ignore build scripts +build-install.sh + +# Ignore Python cache files +**/__pycache__/ + +# Ignore documentation +docs/ + +# Ignore specific application directories +# meeseeks-api/ + +# (when needed) Ignore poetry lock files +poetry.lock + + +# Ignore codemod scripts +repo-to-prompt.codemod.js + +# Ignore requirements file (if any) +requirements.txt diff --git a/.env.example b/.env.example index cfc4200..8267d1d 100644 --- a/.env.example +++ b/.env.example @@ -7,7 +7,7 @@ # * Meeseeks Settings # - VERSION: Version of your application (There is no need to change these value) # - ENVMODE: Environment mode of your application (valid options: dev, prod) -VERSION=0.0.1 +VERSION=1.0.0 ENVMODE=dev LOG_LEVEL=DEBUG CACHE_DIR='/path/to/cache/directory' diff --git a/.github/workflows/docker-buildx.yml b/.github/workflows/docker-buildx.yml new file mode 100644 index 0000000..9048b0b --- /dev/null +++ b/.github/workflows/docker-buildx.yml @@ -0,0 +1,72 @@ +#@doc +# * This GitHub Actions workflow builds and pushes a Docker image to GitHub Container Registry. +# * It is triggered when a branch is created with the name syntax "release/[version]-[channel]". +# +# The workflow does the following: +# 1. Checks out the code, sets up Docker buildx, Login to the registry. +# 2. Extracts the branch name from the GITHUB_REF environment variable. +# 3. Splits the branch name to get the version and channel. +# 4. Builds and pushes the Docker image. + +# Examples: +# If the branch name is 'release/1.0.0-latest', the image is tagged as '1.0.0' and 'latest'. +# If the branch name is 'release/1.0.1-stable', the image is tagged as '1.0.1' and 'stable'. +# If the branch name is 'release/1.0.2-dev', the image is tagged as '1.0.2-dev'. +# +# * The 'latest' and 'stable' tags allow us to easily switch between different versions. +# * The 'dev' tag allows you to have a separate version for development. + +name: Build Meseeks Chat Docker Image + +on: + workflow_dispatch: + push: + branches: + - "release/*" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract branch name + id: extract_branch + shell: bash + run: | + BRANCH_NAME=$(echo ${{ github.ref }} | sed 's/refs\/heads\///') + echo "branch=$BRANCH_NAME" >> $GITHUB_ENV + echo "Extracted branch name: $BRANCH_NAME" + + - name: Set version and channel + id: version_channel + run: | + BRANCH_NAME=${{ env.branch }} + VERSION=$(echo $BRANCH_NAME | cut -d'/' -f 2 | cut -d'-' -f 1) + CHANNEL=$(echo $BRANCH_NAME | cut -d'/' -f 2 | cut -d'-' -f 2) + echo "version=$VERSION" >> $GITHUB_ENV + echo "channel=$CHANNEL" >> $GITHUB_ENV + echo "Extracted version: $VERSION" + echo "Extracted channel: $CHANNEL" + echo "Extracted branch name: $BRANCH_NAME" + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + push: true + tags: | + ghcr.io/bearlike/meeseeks-chat:${{ env.version }}${{ env.channel == 'dev' && '-dev' || '' }} + ghcr.io/bearlike/meeseeks-chat:${{ env.channel == 'latest' && 'latest' || env.channel == 'stable' && 'stable' || 'dev' }} + platforms: linux/amd64,linux/arm64 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0a9fc6b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,68 @@ +# Dockerfile to build meeseeks-chat with core dependencies. + +FROM python:3.11-buster + +# Set the title, GitHub repo URL, version, and author +ARG TITLE="Meeseeks Chat: Personal Assistant" \ + VERSION="1.0.0" \ + AUTHOR="Krishnakanth Alagiri" + +LABEL org.opencontainers.image.source="https://github.com/bearlike/Personal-Assistant" \ + org.opencontainers.image.version=$VERSION \ + org.opencontainers.image.vendor=$AUTHOR \ + org.opencontainers.image.licenses="mail@kanth.tech" \ + org.opencontainers.image.licenses="MIT" + +LABEL maintainer=$AUTHOR \ + title=$TITLE \ + url=$GITHUB_REPO_URL \ + version=$VERSION + +# Virtualens are redundant for Dockerfile. +ENV POETRY_NO_INTERACTION=1 \ + POETRY_CACHE_DIR=/tmp/poetry_cache \ + POETRY_VIRTUALENVS_CREATE=false + +# Update and install necessary software +RUN apt-get update && apt-get install -y \ + build-essential \ + curl \ + software-properties-common \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Set the working directory to /app (assuming project root) +WORKDIR /app + +# Copy the repo contents to the Docker image +COPY . /app + +# Install Poetry +RUN pip install 'poetry>=1.8,<1.9' + +# Install the core dependencies +RUN poetry install + +# Install the meeseeks-chat dependencies +WORKDIR /app/meeseeks-chat +RUN poetry install + +# Set default environment variablesfor Meeseeks +ENV CACHE_DIR='/tmp/meeseeks_cache' \ + DEFAULT_MODEL='gpt-3.5-turbo' \ + LOG_LEVEL=DEBUG \ + ENVMODE=dev \ + VERSION=${VERSION} \ + COLOREDLOGS_FIELD_STYLES='asctime=color=240;name=45,inverse' \ + COLOREDLOGS_LEVEL_STYLES='info=220;spam=22;debug=34;verbose=34;notice=220;warning=202;success=118,bold;error=124;critical=background=red' \ + COLOREDLOGS_LOG_FORMAT='%(asctime)s [%(name)s] %(levelname)s %(message)s' + + +# Expose port 8501 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"] diff --git a/README.md b/README.md index cc2a3ef..e15c726 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,16 @@ The project takes advantage of various models through OpenAI-compatible endpoint Meeseeks builds upon recent advancements in LLM-based multi-agent systems, which have shown promising results in collaborative problem-solving, RAG, consensus-seeking, and theory of mind inference in cooperative settings. By harnessing the planning and decision-making capabilities of LLMs, Meeseeks should provide an efficient and effective solution for handling complex tasks across various tools. ## Features 🔥 +
+Legends (Expand to View) + | Completed | In-Progress | Planned | Scoping | | :-------: | :---------: | :-----: | :-----: | | ✅ | 🚧 | 📅 | 🧐 | +
+ + | Status | Feature | | :----: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -34,9 +40,9 @@ Meeseeks builds upon recent advancements in LLM-based multi-agent systems, which ### Integrations 📦 -| Status | Integration Name | Description | -| :----: | :--------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------- | -| ✅ | Home Assistant API | Control devices and retrieve sensor data via `request` | +| Status | Integration Name | Description | +| :----: | :--------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------- | +| ✅ | [Home Assistant](https://github.com/home-assistant/core) | Control devices and retrieve sensor data via `request` | | 📅 | Gmail | Access Gmail functionality via `llama_index.tools.google.GmailToolSpec` | | 🚧 | Google Calendar | Access Google Calendar functionality via `llama_index.tools.google.GoogleCalendarToolSpec` | | 📅 | Google Search | Perform Google search via `llama_index.tools.google.GoogleSearchToolSpec` | @@ -46,6 +52,19 @@ Meeseeks builds upon recent advancements in LLM-based multi-agent systems, which | 🧐 | Android Debugging Shell | Use Home Assistant ADB Integrations to perform actions on Android TV Variants via `integrations.HomeAssistant`. | +## Running Meeseeks with Docker 🐳 (Recommended) + +1. **Install Docker**: If you haven't already, [install Docker on your machine](https://docs.docker.com/get-docker/). + +2. **Environment Variables**: Copy the [`.env.example`](".env.example") file to a new file named ``docker-meeseeks.env`` and modify the necessary environment variables. + +3. **Run the Docker Container**: Default port is `8502`. Run the Docker container with the following command. + +```bash +docker run --env-file docker-meeseeks.env -p 8502:8502 ghcr.io/bearlike/meeseeks-chat:latest +``` +4. Now, you should be able to access the Meeseeks chat interface at `http://hostname-or-ip:8502` in your web browser. Enjoy chatting with Meeseeks! + ## Project Setup 🛠️ This project is composed of multiple modules, each with its own set of dependencies. Follow the steps below to set up the project on your local machine. @@ -57,7 +76,7 @@ This project is composed of multiple modules, each with its own set of dependenc > [!NOTE] -> **Quick Installation for Mac and Linux Users:** Clone the repository, navigate to the project root and run the below script: +> **Installation script for Mac and Linux Users:** Clone the repository, navigate to the project root and run the below script: > ```bash > chmod +x build-install.sh > ./build-install.sh fallback-install @@ -87,18 +106,19 @@ This project is composed of multiple modules, each with its own set of dependenc poetry install cd ../meeseeks-chat poetry install + cd .. ``` 4. **Environment Variables**: Copy the [``.env.example``](.env.example) file to a new file named ``.env`` and modify in the necessary environment variables. - ## Running the Meeseeks Chat Interface 🤖 After installing the dependencies, you can run the application with the following command: ```bash -streamlit run main.py +cd ./meeseeks-chat +streamlit run chat_master.py ``` diff --git a/build-install.sh b/build-install.sh index 435a5da..88d28c1 100644 --- a/build-install.sh +++ b/build-install.sh @@ -31,7 +31,7 @@ function build_and_install() { mv dist/*.whl ../ # Install the package - if ! pip install ../$1-0.1.0-py3-none-any.whl; then + if ! pip install ../$1-1.0.0-py3-none-any.whl; then echo "Error: Failed to install the $1 package" exit 1 fi diff --git a/meeseeks-api/pyproject.toml b/meeseeks-api/pyproject.toml index 1a477fd..32b0a69 100644 --- a/meeseeks-api/pyproject.toml +++ b/meeseeks-api/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "meeseeks-api" -version = "0.1.0" +version = "1.0.0" description = "REST API Engine wrapped around the meeseeks-core" authors = ["Krishnakanth Alagiri "] license = "MIT" diff --git a/meeseeks-chat/pyproject.toml b/meeseeks-chat/pyproject.toml index 647540a..0ec230c 100644 --- a/meeseeks-chat/pyproject.toml +++ b/meeseeks-chat/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "meeseeks-chat" -version = "0.1.0" +version = "1.0.0" description = "Chat Interface wrapped around the meeseeks-core. Powered by Streamlit." authors = ["Krishnakanth Alagiri "] license = "MIT" diff --git a/pyproject.toml b/pyproject.toml index f6aefaa..13db417 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "meeseeks" -version = "0.1.0" +version = "1.0.0" description = "Core module for Meeseeks - A powerful multi-LLM-agent assistant for complex tasks with support for tools integration." authors = ["Krishnakanth Alagiri "] license = "MIT" diff --git a/tools/integration/homeassistant.py b/tools/integration/homeassistant.py index dc72e4f..1a3a524 100644 --- a/tools/integration/homeassistant.py +++ b/tools/integration/homeassistant.py @@ -19,6 +19,9 @@ logging = get_logger(name="tools.integration.homeassistant") load_dotenv() +# ! BUG: Error correction for model parsing errors is not implemented yet. +# ! Currently, if there are parsing errors, the tool is allowed to fail. +# TODO: Implement OutputFixingParser for error correction. def cache_monitor(func): """Decorator to monitor and update the cache.""" @@ -331,7 +334,14 @@ def _invoke_service_and_set_state( return MockSpeaker(content=tmp_return_message) def set_state(self, action_step: ActionStep) -> "MockSpeaker": - """Perform the action defined by this service.""" + """ Predict and call a service for a given action step based + on sensor information. + Args: + action_step (ActionStep): The natural language action + step to be performed. + Returns: + Response from the chain. + """ self.update_cache() rag_documents = self._load_rag_documents([ "entities.json", "services.json" @@ -345,11 +355,19 @@ def set_state(self, action_step: ActionStep) -> "MockSpeaker": logging.info("Invoking `set` action chain using `%s` for `%s`.", self.model_name, action_step) + # TODO: Interpret the response from call service. return self._invoke_service_and_set_state( chain, rag_documents, action_step) def get_state(self, action_step: ActionStep) -> "MockSpeaker": - """Perform the action defined by this service.""" + """ Generate response for a given action step based + on sensor information. + Args: + action_step (ActionStep): The natural language action + step to be performed. + Returns: + Response from the chain. + """ self.update_cache() rag_documents = self._load_rag_documents(["sensors.json"])