Skip to content

Commit

Permalink
cr
Browse files Browse the repository at this point in the history
  • Loading branch information
jerryjliu committed Apr 17, 2023
2 parents 537bac0 + 9dea8b1 commit 7b244af
Show file tree
Hide file tree
Showing 20 changed files with 169 additions and 70 deletions.
3 changes: 1 addition & 2 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
EXECUTE_LOCAL_COMMANDS=False
# BROWSE_CHUNK_MAX_LENGTH - When browsing website, define the length of chunk stored in memory
BROWSE_CHUNK_MAX_LENGTH=8192
# BROWSE_SUMMARY_MAX_TOKEN - Define the maximum length of the summary generated by GPT agent when browsing website
BROWSE_SUMMARY_MAX_TOKEN=300
# USER_AGENT - Define the user-agent used by the requests library to browse website (string)
# USER_AGENT="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"
# AI_SETTINGS_FILE - Specifies which AI Settings file to use (defaults to ai_settings.yaml)
Expand Down Expand Up @@ -54,6 +52,7 @@ SMART_TOKEN_LIMIT=8000
# local - Default
# pinecone - Pinecone (if configured)
# redis - Redis (if configured)
# milvus - Milvus (if configured)
MEMORY_BACKEND=local

### PINECONE
Expand Down
4 changes: 4 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Upon entering directory, direnv requests user permission once to automatically load project dependencies onwards.
# Eliminating the need of running "nix develop github:superherointj/nix-auto-gpt" for Nix users to develop/use Auto-GPT.

[[ -z $IN_NIX_SHELL ]] && use flake github:superherointj/nix-auto-gpt
28 changes: 28 additions & 0 deletions .github/workflows/pr-label.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: "Pull Request auto-label"
on:
# So that PRs touching the same files as the push are updated
push:
# So that the `dirtyLabel` is removed if conflicts are resolve
# We recommend `pull_request_target` so that github secrets are available.
# In `pull_request` we wouldn't be able to change labels of fork PRs
pull_request_target:
types: [opened, synchronize]
concurrency:
group: ${{ github.event_name == 'pull_request_target' && format('pr-label-{0}', github.event.pull_request.number) || '' }}
cancel-in-progress: ${{ github.event_name == 'pull_request_target' || '' }}

jobs:
conflicts:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Update PRs with conflict labels
uses: eps1lon/actions-label-merge-conflict@releases/2.x
with:
dirtyLabel: "conflicts"
#removeOnDirtyLabel: "PR: ready to ship"
repoToken: "${{ secrets.GITHUB_TOKEN }}"
commentOnDirty: "This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request."
commentOnClean: "Conflicts have been resolved! 🎉 A maintainer will review the pull request shortly."
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ celerybeat.pid
*.sage.py

# Environments
.direnv/
.env
.venv
env/
Expand Down
15 changes: 13 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ FROM python:3.11-slim
RUN apt-get -y update
RUN apt-get -y install git chromium-driver

# Install Xvfb and other dependencies for headless browser testing
RUN apt-get update \
&& apt-get install -y wget gnupg2 libgtk-3-0 libdbus-glib-1-2 dbus-x11 xvfb ca-certificates

# Install Firefox / Chromium
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
&& apt-get update \
&& apt-get install -y chromium firefox-esr

# Set environment variables
ENV PIP_NO_CACHE_DIR=yes \
PYTHONUNBUFFERED=1 \
Expand All @@ -17,8 +27,9 @@ RUN chown appuser:appuser /home/appuser
USER appuser

# Copy the requirements.txt file and install the requirements
COPY --chown=appuser:appuser requirements-docker.txt .
RUN pip install --no-cache-dir --user -r requirements-docker.txt
COPY --chown=appuser:appuser requirements.txt .
RUN sed -i '/Items below this point will not be included in the Docker Image/,$d' requirements.txt && \
pip install --no-cache-dir --user -r requirements.txt

# Copy the application files
COPY --chown=appuser:appuser autogpt/ ./autogpt
Expand Down
33 changes: 21 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,21 @@ Development of this free, open-source project is made possible by all the <a hre
- [Milvus](https://milvus.io/)
- [Redis](https://redis.io)
- [LlamaIndex](https://github.com/jerryjliu/llama_index)
- [Weaviate](https://weaviate.io)
- ElevenLabs Key (If you want the AI to speak)

## ⚠️ OpenAI API Keys Configuration ⚠️

Obtain your OpenAI API key from: https://platform.openai.com/account/api-keys.

To use OpenAI API key for Auto-GPT, you **NEED** to have billing set up (AKA paid account).

You can set up paid account at https://platform.openai.com/account/billing/overview.

![For OpenAI API key to work, set up paid account at OpenAI API > Billing](./docs/imgs/openai-api-key-billing-paid-account.png)

#### **PLEASE ENSURE YOU HAVE DONE THIS STEP BEFORE PROCEEDING, OTHERWISE NOTHING WILL WORK!**

## 💾 Installation

To install Auto-GPT, follow these steps:
Expand Down Expand Up @@ -208,18 +221,6 @@ python -m autogpt --speak
- Adam : pNInz6obpgDQGcFmaJgB
- Sam : yoZ06aMxZJJ28mfd3POQ


## OpenAI API Keys Configuration

Obtain your OpenAI API key from: https://platform.openai.com/account/api-keys.

To use OpenAI API key for Auto-GPT, you NEED to have billing set up (AKA paid account).

You can set up paid account at https://platform.openai.com/account/billing/overview.

![For OpenAI API key to work, set up paid account at OpenAI API > Billing](./docs/imgs/openai-api-key-billing-paid-account.png)


## 🔍 Google API Keys Configuration

This section is optional, use the official google api if you are having issues with error 429 when running a google search.
Expand Down Expand Up @@ -343,6 +344,14 @@ export MEMORY_BACKEND="pinecone"
[Weaviate](https://weaviate.io/) is an open-source vector database. It allows to store data objects and vector embeddings from ML-models and scales seamlessly to billion of data objects. [An instance of Weaviate can be created locally (using Docker), on Kubernetes or using Weaviate Cloud Services](https://weaviate.io/developers/weaviate/quickstart).
Although still experimental, [Embedded Weaviate](https://weaviate.io/developers/weaviate/installation/embedded) is supported which allows the Auto-GPT process itself to start a Weaviate instance. To enable it, set `USE_WEAVIATE_EMBEDDED` to `True` and make sure you `pip install "weaviate-client>=3.15.4"`.

#### Install the Weaviate client

Install the Weaviate client before usage.

```
$ pip install weaviate-client
```


### LlamaIndex Setup

Expand Down
15 changes: 14 additions & 1 deletion autogpt/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
from autogpt.commands.image_gen import generate_image
from autogpt.commands.audio_text import read_audio_from_file
from autogpt.commands.web_requests import scrape_links, scrape_text
from autogpt.commands.execute_code import execute_python_file, execute_shell
from autogpt.commands.execute_code import (
execute_python_file,
execute_shell,
execute_shell_popen,
)
from autogpt.commands.file_operations import (
append_to_file,
delete_file,
Expand Down Expand Up @@ -191,6 +195,15 @@ def execute_command(command_name: str, arguments):
" shell commands, EXECUTE_LOCAL_COMMANDS must be set to 'True' "
"in your config. Do not attempt to bypass the restriction."
)
elif command_name == "execute_shell_popen":
if CFG.execute_local_commands:
return execute_shell_popen(arguments["command_line"])
else:
return (
"You are not allowed to run local shell commands. To execute"
" shell commands, EXECUTE_LOCAL_COMMANDS must be set to 'True' "
"in your config. Do not attempt to bypass the restriction."
)
elif command_name == "read_audio_from_file":
return read_audio_from_file(arguments["file"])
elif command_name == "generate_image":
Expand Down
38 changes: 34 additions & 4 deletions autogpt/commands/execute_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ def execute_python_file(file: str):
try:
client = docker.from_env()

image_name = "python:3.10"
# You can replace this with the desired Python image/version
# You can find available Python images on Docker Hub:
# https://hub.docker.com/_/python
image_name = "python:3-alpine"
try:
client.images.get(image_name)
print(f"Image '{image_name}' found locally")
Expand All @@ -57,9 +60,6 @@ def execute_python_file(file: str):
elif status:
print(status)

# You can replace 'python:3.8' with the desired Python image/version
# You can find available Python images on Docker Hub:
# https://hub.docker.com/_/python
container = client.containers.run(
image_name,
f"python {file}",
Expand Down Expand Up @@ -114,6 +114,36 @@ def execute_shell(command_line: str) -> str:
return output


def execute_shell_popen(command_line):
"""Execute a shell command with Popen and returns an english description
of the event and the process id
Args:
command_line (str): The command line to execute
Returns:
str: Description of the fact that the process started and its id
"""
current_dir = os.getcwd()

if WORKING_DIRECTORY not in current_dir: # Change dir into workspace if necessary
work_dir = os.path.join(os.getcwd(), WORKING_DIRECTORY)
os.chdir(work_dir)

print(f"Executing command '{command_line}' in working directory '{os.getcwd()}'")

do_not_show_output = subprocess.DEVNULL
process = subprocess.Popen(
command_line, shell=True, stdout=do_not_show_output, stderr=do_not_show_output
)

# Change back to whatever the prior working dir was

os.chdir(current_dir)

return f"Subprocess started with PID:'{str(process.pid)}'"


def we_are_running_in_a_docker_container() -> bool:
"""Check if we are running in a Docker container
Expand Down
7 changes: 6 additions & 1 deletion autogpt/commands/file_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,14 @@ def split_file(
while start < content_length:
end = start + max_length
if end + overlap < content_length:
chunk = content[start : end + overlap]
chunk = content[start : end + overlap - 1]
else:
chunk = content[start:content_length]

# Account for the case where the last chunk is shorter than the overlap, so it has already been consumed
if len(chunk) <= overlap:
break

yield chunk
start += max_length - overlap

Expand Down
19 changes: 19 additions & 0 deletions autogpt/commands/web_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,28 @@ def check_local_file_access(url: str) -> bool:
"""
local_prefixes = [
"file:///",
"file://localhost/",
"file://localhost",
"http://localhost",
"http://localhost/",
"https://localhost",
"https://localhost/",
"http://2130706433",
"http://2130706433/",
"https://2130706433",
"https://2130706433/",
"http://127.0.0.1/",
"http://127.0.0.1",
"https://127.0.0.1/",
"https://127.0.0.1",
"https://0.0.0.0/",
"https://0.0.0.0",
"http://0.0.0.0/",
"http://0.0.0.0",
"http://0000",
"http://0000/",
"https://0000",
"https://0000/"
]
return any(url.startswith(prefix) for prefix in local_prefixes)

Expand Down
20 changes: 8 additions & 12 deletions autogpt/config/config.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
"""Configuration class to store the state of bools for different scripts access."""
import os
from colorama import Fore

from autogpt.config.singleton import Singleton

import openai
import yaml

from colorama import Fore
from dotenv import load_dotenv

from autogpt.config.singleton import Singleton

load_dotenv(verbose=True)


Expand All @@ -33,7 +32,6 @@ def __init__(self) -> None:
self.fast_token_limit = int(os.getenv("FAST_TOKEN_LIMIT", 4000))
self.smart_token_limit = int(os.getenv("SMART_TOKEN_LIMIT", 8000))
self.browse_chunk_max_length = int(os.getenv("BROWSE_CHUNK_MAX_LENGTH", 8192))
self.browse_summary_max_token = int(os.getenv("BROWSE_SUMMARY_MAX_TOKEN", 300))

self.openai_api_key = os.getenv("OPENAI_API_KEY")
self.temperature = float(os.getenv("TEMPERATURE", "1"))
Expand Down Expand Up @@ -67,15 +65,17 @@ def __init__(self) -> None:
self.pinecone_api_key = os.getenv("PINECONE_API_KEY")
self.pinecone_region = os.getenv("PINECONE_ENV")

self.weaviate_host = os.getenv("WEAVIATE_HOST")
self.weaviate_host = os.getenv("WEAVIATE_HOST")
self.weaviate_port = os.getenv("WEAVIATE_PORT")
self.weaviate_protocol = os.getenv("WEAVIATE_PROTOCOL", "http")
self.weaviate_username = os.getenv("WEAVIATE_USERNAME", None)
self.weaviate_password = os.getenv("WEAVIATE_PASSWORD", None)
self.weaviate_scopes = os.getenv("WEAVIATE_SCOPES", None)
self.weaviate_embedded_path = os.getenv("WEAVIATE_EMBEDDED_PATH")
self.weaviate_api_key = os.getenv("WEAVIATE_API_KEY", None)
self.use_weaviate_embedded = os.getenv("USE_WEAVIATE_EMBEDDED", "False") == "True"
self.use_weaviate_embedded = (
os.getenv("USE_WEAVIATE_EMBEDDED", "False") == "True"
)

# milvus configuration, e.g., localhost:19530.
self.milvus_addr = os.getenv("MILVUS_ADDR", "localhost:19530")
Expand Down Expand Up @@ -193,10 +193,6 @@ def set_browse_chunk_max_length(self, value: int) -> None:
"""Set the browse_website command chunk max length value."""
self.browse_chunk_max_length = value

def set_browse_summary_max_token(self, value: int) -> None:
"""Set the browse_website command summary max token value."""
self.browse_summary_max_token = value

def set_openai_api_key(self, value: str) -> None:
"""Set the OpenAI API key value."""
self.openai_api_key = value
Expand Down Expand Up @@ -242,5 +238,5 @@ def check_openai_api_key() -> None:
Fore.RED
+ "Please set your OpenAI API key in .env or as an environment variable."
)
print("You can get your key from https://beta.openai.com/account/api-keys")
print("You can get your key from https://platform.openai.com/account/api-keys")
exit(1)
2 changes: 1 addition & 1 deletion autogpt/json_fixes/auto_fix.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def fix_json(json_string: str, schema: str) -> str:
try:
json.loads(result_string) # just check the validity
return result_string
except json.JSONDecodeError: # noqa: E722
except json.JSONDecodeError:
# Get the call stack:
# import traceback
# call_stack = traceback.format_exc()
Expand Down
4 changes: 2 additions & 2 deletions autogpt/memory/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import dataclasses
import os
from typing import Any
from typing import Any, List

import numpy as np
import orjson

from autogpt.memory.base import MemoryProviderSingleton
from autogpt.llm_utils import create_embedding_with_ada
from autogpt.memory.base import MemoryProviderSingleton

EMBED_DIM = 1536
SAVE_OPTIONS = orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_SERIALIZE_DATACLASS
Expand Down
2 changes: 0 additions & 2 deletions autogpt/processing/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ def summarize_text(
summary = create_chat_completion(
model=CFG.fast_llm_model,
messages=messages,
max_tokens=CFG.browse_summary_max_token,
)
summaries.append(summary)
print(f"Added chunk {i + 1} summary to memory")
Expand All @@ -95,7 +94,6 @@ def summarize_text(
return create_chat_completion(
model=CFG.fast_llm_model,
messages=messages,
max_tokens=CFG.browse_summary_max_token,
)


Expand Down
Loading

0 comments on commit 7b244af

Please sign in to comment.