Skip to content

Commit

Permalink
Merge branch 'master' into add-unit-tests-workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
richbeales authored Apr 12, 2023
2 parents 5265d81 + 9c9758c commit 364e2a4
Show file tree
Hide file tree
Showing 14 changed files with 235 additions and 24 deletions.
2 changes: 2 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ USE_AZURE=False
OPENAI_AZURE_API_BASE=your-base-url-for-azure
OPENAI_AZURE_API_VERSION=api-version-for-azure
OPENAI_AZURE_DEPLOYMENT_ID=deployment-id-for-azure
OPENAI_AZURE_CHAT_DEPLOYMENT_ID=deployment-id-for-azure-chat
OPENAI_AZURE_EMBEDDINGS_DEPLOYMENT_ID=deployment-id-for-azure-embeddigs
IMAGE_PROVIDER=dalle
HUGGINGFACE_API_TOKEN=
USE_MAC_OS_TTS=False
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ package-lock.json
auto_gpt_workspace/*
*.mpeg
.env
venv/*
*venv/*
outputs/*
ai_settings.yaml
.vscode
.idea/*
auto-gpt.json
log.txt

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ To contribute to this GitHub project, you can follow these steps:
2. Clone the repository to your local machine using the following command:

```
git clone https://github.com/Torantulino/Auto-GPT
git clone https://github.com/<YOUR-GITHUB-USERNAME>/Auto-GPT
```
3. Create a new branch for your changes using the following command:

Expand Down
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Your support is greatly appreciated
## 📋 Requirements

- [Python 3.8 or later](https://www.tutorialspoint.com/how-to-install-python-in-windows)
- OpenAI API key
- [OpenAI API key](https://platform.openai.com/account/api-keys)
- [PINECONE API key](https://www.pinecone.io/)

Optional:
Expand Down Expand Up @@ -96,10 +96,9 @@ pip install -r requirements.txt
```

4. Rename `.env.template` to `.env` and fill in your `OPENAI_API_KEY`. If you plan to use Speech Mode, fill in your `ELEVEN_LABS_API_KEY` as well.

- Obtain your OpenAI API key from: https://platform.openai.com/account/api-keys.
- Obtain your ElevenLabs API key from: https://elevenlabs.io. You can view your xi-api-key using the "Profile" tab on the website.
- If you want to use GPT on an Azure instance, set `USE_AZURE` to `True` and provide the `OPENAI_AZURE_API_BASE`, `OPENAI_AZURE_API_VERSION` and `OPENAI_AZURE_DEPLOYMENT_ID` values as explained here: https://pypi.org/project/openai/ in the `Microsoft Azure Endpoints` section
- Obtain your OpenAI API key from: https://platform.openai.com/account/api-keys.
- Obtain your ElevenLabs API key from: https://elevenlabs.io. You can view your xi-api-key using the "Profile" tab on the website.
- If you want to use GPT on an Azure instance, set `USE_AZURE` to `True` and provide the `OPENAI_AZURE_API_BASE`, `OPENAI_AZURE_API_VERSION` and `OPENAI_AZURE_DEPLOYMENT_ID` values as explained here: https://pypi.org/project/openai/ in the `Microsoft Azure Endpoints` section. Additionally you need separate deployments for both embeddings and chat. Add their ID values to `OPENAI_AZURE_CHAT_DEPLOYMENT_ID` and `OPENAI_AZURE_EMBEDDINGS_DEPLOYMENT_ID` respectively

## 🔧 Usage

Expand Down
4 changes: 2 additions & 2 deletions scripts/agent_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def create_agent(task, prompt, model):

messages = [{"role": "user", "content": prompt}, ]

# Start GTP3 instance
# Start GPT instance
agent_reply = create_chat_completion(
model=model,
messages=messages,
Expand Down Expand Up @@ -41,7 +41,7 @@ def message_agent(key, message):
# Add user message to message history before sending to agent
messages.append({"role": "user", "content": message})

# Start GTP3 instance
# Start GPT instance
agent_reply = create_chat_completion(
model=model,
messages=messages,
Expand Down
45 changes: 37 additions & 8 deletions scripts/browse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,61 @@
from bs4 import BeautifulSoup
from config import Config
from llm_utils import create_chat_completion
from urllib.parse import urlparse, urljoin

cfg = Config()

# Function to check if the URL is valid
def is_valid_url(url):
try:
result = urlparse(url)
return all([result.scheme, result.netloc])
except ValueError:
return False

# Function to sanitize the URL
def sanitize_url(url):
return urljoin(url, urlparse(url).path)

# Function to make a request with a specified timeout and handle exceptions
def make_request(url, timeout=10):
try:
response = requests.get(url, headers=cfg.user_agent_header, timeout=timeout)
response.raise_for_status()
return response
except requests.exceptions.RequestException as e:
return "Error: " + str(e)

# Define and check for local file address prefixes
def check_local_file_access(url):
local_prefixes = ['file:///', 'file://localhost', 'http://localhost', 'https://localhost']
return any(url.startswith(prefix) for prefix in local_prefixes)

def scrape_text(url):
"""Scrape text from a webpage"""
# Most basic check if the URL is valid:
# Basic check if the URL is valid
if not url.startswith('http'):
return "Error: Invalid URL"

# Restrict access to local files
if check_local_file_access(url):
return "Error: Access to local files is restricted"

try:
response = requests.get(url, headers=cfg.user_agent_header)
except requests.exceptions.RequestException as e:
return "Error: " + str(e)
# Validate the input URL
if not is_valid_url(url):
# Sanitize the input URL
sanitized_url = sanitize_url(url)

# Check if the response contains an HTTP error
if response.status_code >= 400:
return "Error: HTTP " + str(response.status_code) + " error"
# Make the request with a timeout and handle exceptions
response = make_request(sanitized_url)

if isinstance(response, str):
return response
else:
# Sanitize the input URL
sanitized_url = sanitize_url(url)

response = requests.get(sanitized_url, headers=cfg.user_agent_header)

soup = BeautifulSoup(response.text, "html.parser")

Expand Down
2 changes: 2 additions & 0 deletions scripts/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def __init__(self):
self.openai_api_base = os.getenv("OPENAI_AZURE_API_BASE")
self.openai_api_version = os.getenv("OPENAI_AZURE_API_VERSION")
self.openai_deployment_id = os.getenv("OPENAI_AZURE_DEPLOYMENT_ID")
self.azure_chat_deployment_id = os.getenv("OPENAI_AZURE_CHAT_DEPLOYMENT_ID")
self.azure_embeddigs_deployment_id = os.getenv("OPENAI_AZURE_EMBEDDINGS_DEPLOYMENT_ID")
openai.api_type = "azure"
openai.api_base = self.openai_api_base
openai.api_version = self.openai_api_version
Expand Down
5 changes: 3 additions & 2 deletions scripts/json_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"""


def fix_and_parse_json(
def fix_and_parse_json(
json_str: str,
try_to_fix_with_gpt: bool = True
) -> Union[str, Dict[Any, Any]]:
Expand All @@ -35,8 +35,8 @@ def fix_and_parse_json(
json_str = json_str.replace('\t', '')
return json.loads(json_str)
except json.JSONDecodeError as _: # noqa: F841
json_str = correct_json(json_str)
try:
json_str = correct_json(json_str)
return json.loads(json_str)
except json.JSONDecodeError as _: # noqa: F841
pass
Expand All @@ -53,6 +53,7 @@ def fix_and_parse_json(
last_brace_index = json_str.rindex("}")
json_str = json_str[:last_brace_index+1]
return json.loads(json_str)
# Can throw a ValueError if there is no "{" or "}" in the json_str
except (json.JSONDecodeError, ValueError) as e: # noqa: F841
if try_to_fix_with_gpt:
print("Warning: Failed to parse AI output, attempting to fix."
Expand Down
2 changes: 1 addition & 1 deletion scripts/llm_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def create_chat_completion(messages, model=None, temperature=None, max_tokens=No
"""Create a chat completion using the OpenAI API"""
if cfg.use_azure:
response = openai.ChatCompletion.create(
deployment_id=cfg.openai_deployment_id,
deployment_id=cfg.azure_chat_deployment_id,
model=model,
messages=messages,
temperature=temperature,
Expand Down
11 changes: 10 additions & 1 deletion scripts/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ def prompt_user():
def parse_arguments():
"""Parses the arguments passed to the script"""
global cfg
cfg.set_debug_mode(False)
cfg.set_continuous_mode(False)
cfg.set_speak_mode(False)

Expand All @@ -274,6 +275,7 @@ def parse_arguments():
parser.add_argument('--speak', action='store_true', help='Enable Speak Mode')
parser.add_argument('--debug', action='store_true', help='Enable Debug Mode')
parser.add_argument('--gpt3only', action='store_true', help='Enable GPT3.5 Only Mode')
parser.add_argument('--gpt4only', action='store_true', help='Enable GPT4 Only Mode')
args = parser.parse_args()

if args.continuous:
Expand All @@ -291,7 +293,14 @@ def parse_arguments():
if args.gpt3only:
print_to_console("GPT3.5 Only Mode: ", Fore.GREEN, "ENABLED")
cfg.set_smart_llm_model(cfg.fast_llm_model)

if args.gpt4only:
print_to_console("GPT4 Only Mode: ", Fore.GREEN, "ENABLED")
cfg.set_fast_llm_model(cfg.smart_llm_model)

if args.debug:
print_to_console("Debug Mode: ", Fore.GREEN, "ENABLED")
cfg.set_debug_mode(True)


# TODO: fill in llm values here
Expand Down Expand Up @@ -383,7 +392,7 @@ def parse_arguments():
f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}")

# Execute command
if command_name.lower().startswith( "error" ):
if command_name is not None and command_name.lower().startswith( "error" ):
result = f"Command {command_name} threw the following error: " + arguments
elif command_name == "human_feedback":
result = f"Human feedback: {user_input}"
Expand Down
8 changes: 6 additions & 2 deletions scripts/memory/base.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
"""Base class for memory providers."""
import abc
from config import AbstractSingleton
from config import AbstractSingleton, Config
import openai
cfg = Config()


def get_ada_embedding(text):
text = text.replace("\n", " ")
return openai.Embedding.create(input=[text], model="text-embedding-ada-002")["data"][0]["embedding"]
if cfg.use_azure:
return openai.Embedding.create(input=[text], engine=cfg.azure_embeddigs_deployment_id, model="text-embedding-ada-002")["data"][0]["embedding"]
else:
return openai.Embedding.create(input=[text], model="text-embedding-ada-002")["data"][0]["embedding"]


class MemoryProviderSingleton(AbstractSingleton):
Expand Down
2 changes: 1 addition & 1 deletion scripts/memory/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ def add(self, text: str):
vector = vector[np.newaxis, :]
self.data.embeddings = np.concatenate(
[
vector,
self.data.embeddings,
vector,
],
axis=0,
)
Expand Down
49 changes: 49 additions & 0 deletions tests/integration/memory_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import unittest
import random
import string
import sys
from pathlib import Path
# Add the parent directory of the 'scripts' folder to the Python path
sys.path.append(str(Path(__file__).resolve().parent.parent.parent / 'scripts'))
from config import Config
from memory.local import LocalCache

class TestLocalCache(unittest.TestCase):

def random_string(self, length):
return ''.join(random.choice(string.ascii_letters) for _ in range(length))

def setUp(self):
cfg = cfg = Config()
self.cache = LocalCache(cfg)
self.cache.clear()

# Add example texts to the cache
self.example_texts = [
'The quick brown fox jumps over the lazy dog',
'I love machine learning and natural language processing',
'The cake is a lie, but the pie is always true',
'ChatGPT is an advanced AI model for conversation'
]

for text in self.example_texts:
self.cache.add(text)

# Add some random strings to test noise
for _ in range(5):
self.cache.add(self.random_string(10))

def test_get_relevant(self):
query = "I'm interested in artificial intelligence and NLP"
k = 3
relevant_texts = self.cache.get_relevant(query, k)

print(f"Top {k} relevant texts for the query '{query}':")
for i, text in enumerate(relevant_texts, start=1):
print(f"{i}. {text}")

self.assertEqual(len(relevant_texts), k)
self.assertIn(self.example_texts[1], relevant_texts)

if __name__ == '__main__':
unittest.main()
Loading

0 comments on commit 364e2a4

Please sign in to comment.