fixed merge conflicts
commit
51224229eb
|
@ -11,6 +11,9 @@ BROWSE_SUMMARY_MAX_TOKEN=300
|
|||
# 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)
|
||||
AI_SETTINGS_FILE=ai_settings.yaml
|
||||
# USE_WEB_BROWSER - Sets the web-browser drivers to use with selenium (defaults to chrome).
|
||||
# Note: set this to either 'chrome', 'firefox', or 'safari' depending on your current browser
|
||||
# USE_WEB_BROWSER=chrome
|
||||
|
||||
################################################################################
|
||||
### LLM PROVIDER
|
||||
|
@ -21,20 +24,11 @@ AI_SETTINGS_FILE=ai_settings.yaml
|
|||
# TEMPERATURE - Sets temperature in OpenAI (Default: 1)
|
||||
# USE_AZURE - Use Azure OpenAI or not (Default: False)
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
TEMPERATURE=1
|
||||
TEMPERATURE=0
|
||||
USE_AZURE=False
|
||||
|
||||
### AZURE
|
||||
# OPENAI_AZURE_API_BASE - OpenAI API base URL for Azure (Example: https://my-azure-openai-url.com)
|
||||
# OPENAI_AZURE_API_VERSION - OpenAI API version for Azure (Example: v1)
|
||||
# OPENAI_AZURE_DEPLOYMENT_ID - OpenAI deployment ID for Azure (Example: my-deployment-id)
|
||||
# OPENAI_AZURE_CHAT_DEPLOYMENT_ID - OpenAI deployment ID for Azure Chat (Example: my-deployment-id-for-azure-chat)
|
||||
# OPENAI_AZURE_EMBEDDINGS_DEPLOYMENT_ID - OpenAI deployment ID for Embedding (Example: my-deployment-id-for-azure-embeddigs)
|
||||
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
|
||||
# cleanup azure env as already moved to `azure.yaml.template`
|
||||
|
||||
################################################################################
|
||||
### LLM MODELS
|
||||
|
@ -120,6 +114,16 @@ IMAGE_PROVIDER=dalle
|
|||
# HUGGINGFACE_API_TOKEN - HuggingFace API token (Example: my-huggingface-api-token)
|
||||
HUGGINGFACE_API_TOKEN=your-huggingface-api-token
|
||||
|
||||
################################################################################
|
||||
### GIT Provider for repository actions
|
||||
################################################################################
|
||||
|
||||
### GITHUB
|
||||
# GITHUB_API_KEY - Github API key / PAT (Example: github_pat_123)
|
||||
# GITHUB_USERNAME - Github username
|
||||
GITHUB_API_KEY=github_pat_123
|
||||
GITHUB_USERNAME=your-github-username
|
||||
|
||||
################################################################################
|
||||
### SEARCH PROVIDER
|
||||
################################################################################
|
||||
|
|
|
@ -19,6 +19,8 @@ auto-gpt.json
|
|||
log.txt
|
||||
log-ingestion.txt
|
||||
logs
|
||||
*.log
|
||||
*.mp3
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
|
@ -152,3 +154,6 @@ dmypy.json
|
|||
.pyre/
|
||||
llama-*
|
||||
vicuna-*
|
||||
|
||||
# mac
|
||||
.DS_Store
|
||||
|
|
10
Dockerfile
10
Dockerfile
|
@ -1,6 +1,10 @@
|
|||
# Use an official Python base image from the Docker Hub
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Install git
|
||||
RUN apt-get -y update
|
||||
RUN apt-get -y install git
|
||||
|
||||
# Set environment variables
|
||||
ENV PIP_NO_CACHE_DIR=yes \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
|
@ -13,11 +17,11 @@ RUN chown appuser:appuser /home/appuser
|
|||
USER appuser
|
||||
|
||||
# Copy the requirements.txt file and install the requirements
|
||||
COPY --chown=appuser:appuser requirements.txt .
|
||||
RUN pip install --no-cache-dir --user -r requirements.txt
|
||||
COPY --chown=appuser:appuser requirements-docker.txt .
|
||||
RUN pip install --no-cache-dir --user -r requirements-docker.txt
|
||||
|
||||
# Copy the application files
|
||||
COPY --chown=appuser:appuser autogpt/ .
|
||||
COPY --chown=appuser:appuser autogpt/ ./autogpt
|
||||
|
||||
# Set the entrypoint
|
||||
ENTRYPOINT ["python", "-m", "autogpt"]
|
||||
|
|
198
README.md
198
README.md
|
@ -1,8 +1,10 @@
|
|||
# Auto-GPT: An Autonomous GPT-4 Experiment
|
||||
### 🔴 🔴 🔴 Urgent: USE `stable` not `master` 🔴 🔴 🔴
|
||||
We've improved our workflow. `master` will often be **in a broken state**.
|
||||
Download the latest `stable` release here: https://github.com/Torantulino/Auto-GPT/releases/latest
|
||||
This information SUPERCEDES any following information. Takes precedence. Do this not that.
|
||||
|
||||
> This information takes precedence over any other information provided and should be followed accordingly.
|
||||
|
||||
Our workflow has been improved, but please note that `master` branch may often in a **broken** state.
|
||||
Please download the latest `stable` release from here: https://github.com/Torantulino/Auto-GPT/releases/latest.
|
||||
|
||||
![GitHub Repo stars](https://img.shields.io/github/stars/Torantulino/auto-gpt?style=social)
|
||||
[![Twitter Follow](https://img.shields.io/twitter/follow/siggravitas?style=social)](https://twitter.com/SigGravitas)
|
||||
|
@ -91,59 +93,65 @@ Optional:
|
|||
|
||||
To install Auto-GPT, follow these steps:
|
||||
|
||||
1. Make sure you have all the **requirements** above, if not, install/get them.
|
||||
1. Make sure you have all the **requirements** listed above, if not, install/get them
|
||||
|
||||
_The following commands should be executed in a CMD, Bash or Powershell window. To do this, go to a folder on your computer, click in the folder path at the top and type CMD, then press enter._
|
||||
_To execute the following commands, open a CMD, Bash, or Powershell window by navigating to a folder on your computer and typing `CMD` in the folder path at the top, then press enter._
|
||||
|
||||
2. Clone the repository:
|
||||
For this step you need Git installed, but you can just download the zip file instead by clicking the button at the top of this page ☝️
|
||||
2. Clone the repository: For this step, you need Git installed. Alternatively, you can download the zip file by clicking the button at the top of this page ☝️
|
||||
|
||||
```
|
||||
```bash
|
||||
git clone https://github.com/Torantulino/Auto-GPT.git
|
||||
```
|
||||
|
||||
3. Navigate to the project directory:
|
||||
_(Type this into your CMD window, you're aiming to navigate the CMD window to the repository you just downloaded)_
|
||||
3. Navigate to the directory where the repository was downloaded
|
||||
|
||||
```
|
||||
cd 'Auto-GPT'
|
||||
```bash
|
||||
cd Auto-GPT
|
||||
```
|
||||
|
||||
4. Install the required dependencies:
|
||||
_(Again, type this into your CMD window)_
|
||||
4. Install the required dependencies
|
||||
|
||||
```
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
5. 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.
|
||||
- See [OpenAI API Keys Configuration](#openai-api-keys-configuration) to obtain your OpenAI API key.
|
||||
- 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 then:
|
||||
- Rename `azure.yaml.template` to `azure.yaml` and provide the relevant `azure_api_base`, `azure_api_version` and all of the deployment ids for the relevant models in the `azure_model_map` section:
|
||||
- `fast_llm_model_deployment_id` - your gpt-3.5-turbo or gpt-4 deployment id
|
||||
- `smart_llm_model_deployment_id` - your gpt-4 deployment id
|
||||
- `embedding_model_deployment_id` - your text-embedding-ada-002 v2 deployment id
|
||||
- Please specify all of these values as double quoted strings
|
||||
- details can be found here: https://pypi.org/project/openai/ in the `Microsoft Azure Endpoints` section and here: https://learn.microsoft.com/en-us/azure/cognitive-services/openai/tutorials/embeddings?tabs=command-line for the embedding model.
|
||||
- If you want to use GPT on an Azure instance, set `USE_AZURE` to `True` and then follow these steps:
|
||||
- Rename `azure.yaml.template` to `azure.yaml` and provide the relevant `azure_api_base`, `azure_api_version` and all the deployment IDs for the relevant models in the `azure_model_map` section:
|
||||
- `fast_llm_model_deployment_id` - your gpt-3.5-turbo or gpt-4 deployment ID
|
||||
- `smart_llm_model_deployment_id` - your gpt-4 deployment ID
|
||||
- `embedding_model_deployment_id` - your text-embedding-ada-002 v2 deployment ID
|
||||
- Please specify all of these values as double-quoted strings
|
||||
> Replace string in angled brackets (<>) to your own ID
|
||||
```yaml
|
||||
azure_model_map:
|
||||
fast_llm_model_deployment_id: "<my-fast-llm-deployment-id>"
|
||||
...
|
||||
```
|
||||
- Details can be found here: https://pypi.org/project/openai/ in the `Microsoft Azure Endpoints` section and here: https://learn.microsoft.com/en-us/azure/cognitive-services/openai/tutorials/embeddings?tabs=command-line for the embedding model.
|
||||
|
||||
## 🔧 Usage
|
||||
|
||||
1. Run the `autogpt` Python module in your terminal:
|
||||
_(Type this into your CMD window)_
|
||||
1. Run `autogpt` Python module in your terminal
|
||||
|
||||
```
|
||||
python -m autogpt
|
||||
```
|
||||
|
||||
2. After each of action, enter 'y' to authorise command, 'y -N' to run N continuous commands, 'n' to exit program, or enter additional feedback for the AI.
|
||||
2. After each action, choose from options to authorize command(s),
|
||||
exit the program, or provide feedback to the AI.
|
||||
1. Authorize a single command, enter `y`
|
||||
2. Authorize a series of _N_ continuous commands, enter `y -N`
|
||||
3. Exit the program, enter `n`
|
||||
|
||||
|
||||
### Logs
|
||||
|
||||
You will find activity and error logs in the folder `./output/logs`
|
||||
Activity and error logs are located in the `./output/logs`
|
||||
|
||||
To output debug logs:
|
||||
To print out debug logs:
|
||||
|
||||
```
|
||||
python -m autogpt --debug
|
||||
|
@ -165,20 +173,40 @@ docker run -it --env-file=./.env -v $PWD/auto_gpt_workspace:/app/auto_gpt_worksp
|
|||
### Command Line Arguments
|
||||
Here are some common arguments you can use when running Auto-GPT:
|
||||
> Replace anything in angled brackets (<>) to a value you want to specify
|
||||
* `python scripts/main.py --help` to see a list of all available command line arguments.
|
||||
* `python scripts/main.py --ai-settings <filename>` to run Auto-GPT with a different AI Settings file.
|
||||
* `python scripts/main.py --use-memory <memory-backend>` to specify one of 3 memory backends: `local`, `redis`, `pinecone` or 'no_memory'.
|
||||
* View all available command line arguments
|
||||
```bash
|
||||
python scripts/main.py --help
|
||||
```
|
||||
* Run Auto-GPT with a different AI Settings file
|
||||
```bash
|
||||
python scripts/main.py --ai-settings <filename>
|
||||
```
|
||||
* Specify one of 3 memory backends: `local`, `redis`, `pinecone` or `no_memory`
|
||||
```bash
|
||||
python scripts/main.py --use-memory <memory-backend>
|
||||
```
|
||||
|
||||
> **NOTE**: There are shorthands for some of these flags, for example `-m` for `--use-memory`. Use `python scripts/main.py --help` for more information
|
||||
|
||||
## 🗣️ Speech Mode
|
||||
|
||||
Use this to use TTS for Auto-GPT
|
||||
Use this to use TTS _(Text-to-Speech)_ for Auto-GPT
|
||||
|
||||
```
|
||||
```bash
|
||||
python -m autogpt --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)
|
||||
|
||||
|
||||
## 🔍 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.
|
||||
|
@ -201,59 +229,47 @@ _Remember that your free daily custom search quota allows only up to 100 searche
|
|||
|
||||
For Windows Users:
|
||||
|
||||
```
|
||||
```bash
|
||||
setx GOOGLE_API_KEY "YOUR_GOOGLE_API_KEY"
|
||||
setx CUSTOM_SEARCH_ENGINE_ID "YOUR_CUSTOM_SEARCH_ENGINE_ID"
|
||||
|
||||
```
|
||||
|
||||
For macOS and Linux users:
|
||||
|
||||
```
|
||||
```bash
|
||||
export GOOGLE_API_KEY="YOUR_GOOGLE_API_KEY"
|
||||
export CUSTOM_SEARCH_ENGINE_ID="YOUR_CUSTOM_SEARCH_ENGINE_ID"
|
||||
|
||||
```
|
||||
|
||||
## Memory Backend Setup
|
||||
|
||||
Setup any one backend to persist memory.
|
||||
|
||||
### Redis Setup
|
||||
|
||||
Install docker desktop.
|
||||
|
||||
Run:
|
||||
|
||||
```
|
||||
## Redis Setup
|
||||
> _**CAUTION**_ \
|
||||
This is not intended to be publicly accessible and lacks security measures. Therefore, avoid exposing Redis to the internet without a password or at all
|
||||
1. Install docker desktop
|
||||
```bash
|
||||
docker run -d --name redis-stack-server -p 6379:6379 redis/redis-stack-server:latest
|
||||
```
|
||||
> See https://hub.docker.com/r/redis/redis-stack-server for setting a password and additional configuration.
|
||||
|
||||
See https://hub.docker.com/r/redis/redis-stack-server for setting a password and additional configuration.
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```
|
||||
2. Set the following environment variables
|
||||
> Replace **PASSWORD** in angled brackets (<>)
|
||||
```bash
|
||||
MEMORY_BACKEND=redis
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=
|
||||
REDIS_PASSWORD=<PASSWORD>
|
||||
```
|
||||
|
||||
Note that this is not intended to be run facing the internet and is not secure, do not expose redis to the internet without a password or at all really.
|
||||
|
||||
You can optionally set
|
||||
|
||||
```
|
||||
```bash
|
||||
WIPE_REDIS_ON_START=False
|
||||
```
|
||||
|
||||
To persist memory stored in Redis.
|
||||
To persist memory stored in Redis
|
||||
|
||||
You can specify the memory index for redis using the following:
|
||||
|
||||
```
|
||||
MEMORY_INDEX=whatever
|
||||
```bash
|
||||
MEMORY_INDEX=<WHATEVER>
|
||||
```
|
||||
|
||||
### 🌲 Pinecone API Key Setup
|
||||
|
@ -280,24 +296,24 @@ Pinecone enables the storage of vast amounts of vector-based memory, allowing fo
|
|||
|
||||
In the `.env` file set:
|
||||
- `PINECONE_API_KEY`
|
||||
- `PINECONE_ENV` (something like: us-east4-gcp)
|
||||
- `PINECONE_ENV` (example: _"us-east4-gcp"_)
|
||||
- `MEMORY_BACKEND=pinecone`
|
||||
|
||||
Alternatively, you can set them from the command line (advanced):
|
||||
|
||||
For Windows Users:
|
||||
|
||||
```
|
||||
setx PINECONE_API_KEY "YOUR_PINECONE_API_KEY"
|
||||
setx PINECONE_ENV "Your pinecone region" # something like: us-east4-gcp
|
||||
```bash
|
||||
setx PINECONE_API_KEY "<YOUR_PINECONE_API_KEY>"
|
||||
setx PINECONE_ENV "<YOUR_PINECONE_REGION>" # e.g: "us-east4-gcp"
|
||||
setx MEMORY_BACKEND "pinecone"
|
||||
```
|
||||
|
||||
For macOS and Linux users:
|
||||
|
||||
```
|
||||
export PINECONE_API_KEY="YOUR_PINECONE_API_KEY"
|
||||
export PINECONE_ENV="Your pinecone region" # something like: us-east4-gcp
|
||||
```bash
|
||||
export PINECONE_API_KEY="<YOUR_PINECONE_API_KEY>"
|
||||
export PINECONE_ENV="<YOUR_PINECONE_REGION>" # e.g: "us-east4-gcp"
|
||||
export MEMORY_BACKEND="pinecone"
|
||||
```
|
||||
|
||||
|
@ -325,7 +341,7 @@ MEMORY_INDEX="Autogpt" # name of the index to create for the application
|
|||
|
||||
## Setting Your Cache Type
|
||||
|
||||
By default Auto-GPT is going to use LocalCache instead of redis or Pinecone.
|
||||
By default, Auto-GPT is going to use LocalCache instead of redis or Pinecone.
|
||||
|
||||
To switch to either, change the `MEMORY_BACKEND` env variable to the value that you want:
|
||||
|
||||
|
@ -340,7 +356,7 @@ To switch to either, change the `MEMORY_BACKEND` env variable to the value that
|
|||
|
||||
## 🧠 Memory pre-seeding
|
||||
|
||||
```
|
||||
```bash
|
||||
# python scripts/data_ingestion.py -h
|
||||
usage: data_ingestion.py [-h] (--file FILE | --dir DIR) [--init] [--overlap OVERLAP] [--max_length MAX_LENGTH]
|
||||
|
||||
|
@ -357,7 +373,7 @@ options:
|
|||
# python scripts/data_ingestion.py --dir seed_data --init --overlap 200 --max_length 1000
|
||||
```
|
||||
|
||||
This script located at scripts/data_ingestion.py, allows you to ingest files into memory and pre-seed it before running Auto-GPT.
|
||||
This script located at `scripts/data_ingestion.py`, allows you to ingest files into memory and pre-seed it before running Auto-GPT.
|
||||
|
||||
Memory pre-seeding is a technique that involves ingesting relevant documents or data into the AI's memory so that it can use this information to generate more informed and accurate responses.
|
||||
|
||||
|
@ -366,35 +382,34 @@ To pre-seed the memory, the content of each document is split into chunks of a s
|
|||
This technique is particularly useful when working with large amounts of data or when there is specific information that the AI needs to be able to access quickly.
|
||||
By pre-seeding the memory, the AI can retrieve and use this information more efficiently, saving time, API call and improving the accuracy of its responses.
|
||||
|
||||
You could for example download the documentation of an API, a Github repository, etc. and ingest it into memory before running Auto-GPT.
|
||||
You could for example download the documentation of an API, a GitHub repository, etc. and ingest it into memory before running Auto-GPT.
|
||||
|
||||
⚠️ If you use Redis as your memory, make sure to run Auto-GPT with the WIPE_REDIS_ON_START set to False in your .env file.
|
||||
⚠️ If you use Redis as your memory, make sure to run Auto-GPT with the `WIPE_REDIS_ON_START` set to `False` in your `.env` file.
|
||||
|
||||
⚠️For other memory backend, we currently forcefully wipe the memory when starting Auto-GPT. To ingest data with those memory backend, you can call the data_ingestion.py script anytime during an Auto-GPT run.
|
||||
⚠️For other memory backend, we currently forcefully wipe the memory when starting Auto-GPT. To ingest data with those memory backend, you can call the `data_ingestion.py` script anytime during an Auto-GPT run.
|
||||
|
||||
Memories will be available to the AI immediately as they are ingested, even if ingested while Auto-GPT is running.
|
||||
|
||||
In the example above, the script initializes the memory, ingests all files within the seed_data directory into memory with an overlap between chunks of 200 and a maximum length of each chunk of 4000.
|
||||
Note that you can also use the --file argument to ingest a single file into memory and that the script will only ingest files within the auto_gpt_workspace directory.
|
||||
In the example above, the script initializes the memory, ingests all files within the `/seed_data` directory into memory with an overlap between chunks of 200 and a maximum length of each chunk of 4000.
|
||||
Note that you can also use the `--file` argument to ingest a single file into memory and that the script will only ingest files within the `/auto_gpt_workspace` directory.
|
||||
|
||||
You can adjust the max_length and overlap parameters to fine-tune the way the docuents are presented to the AI when it "recall" that memory:
|
||||
You can adjust the `max_length` and overlap parameters to fine-tune the way the docuents are presented to the AI when it "recall" that memory:
|
||||
|
||||
- Adjusting the overlap value allows the AI to access more contextual information from each chunk when recalling information, but will result in more chunks being created and therefore increase memory backend usage and OpenAI API requests.
|
||||
- Reducing the max_length value will create more chunks, which can save prompt tokens by allowing for more message history in the context, but will also increase the number of chunks.
|
||||
- Increasing the max_length value will provide the AI with more contextual information from each chunk, reducing the number of chunks created and saving on OpenAI API requests. However, this may also use more prompt tokens and decrease the overall context available to the AI.
|
||||
- Reducing the `max_length` value will create more chunks, which can save prompt tokens by allowing for more message history in the context, but will also increase the number of chunks.
|
||||
- Increasing the `max_length` value will provide the AI with more contextual information from each chunk, reducing the number of chunks created and saving on OpenAI API requests. However, this may also use more prompt tokens and decrease the overall context available to the AI.
|
||||
|
||||
## 💀 Continuous Mode ⚠️
|
||||
|
||||
Run the AI **without** user authorisation, 100% automated.
|
||||
Continuous mode is not recommended.
|
||||
It is potentially dangerous and may cause your AI to run forever or carry out actions you would not usually authorise.
|
||||
Run the AI **without** user authorization, 100% automated.
|
||||
Continuous mode is NOT recommended.
|
||||
It is potentially dangerous and may cause your AI to run forever or carry out actions you would not usually authorize.
|
||||
Use at your own risk.
|
||||
|
||||
1. Run the `autogpt` python module in your terminal:
|
||||
|
||||
```
|
||||
```bash
|
||||
python -m autogpt --speak --continuous
|
||||
|
||||
```
|
||||
|
||||
2. To exit the program, press Ctrl + C
|
||||
|
@ -403,7 +418,7 @@ python -m autogpt --speak --continuous
|
|||
|
||||
If you don't have access to the GPT4 api, this mode will allow you to use Auto-GPT!
|
||||
|
||||
```
|
||||
```bash
|
||||
python -m autogpt --speak --gpt3only
|
||||
```
|
||||
|
||||
|
@ -415,15 +430,16 @@ By default, Auto-GPT uses DALL-e for image generation. To use Stable Diffusion,
|
|||
|
||||
Once you have a token, set these variables in your `.env`:
|
||||
|
||||
```
|
||||
```bash
|
||||
IMAGE_PROVIDER=sd
|
||||
HUGGINGFACE_API_TOKEN="YOUR_HUGGINGFACE_API_TOKEN"
|
||||
```
|
||||
|
||||
## Selenium
|
||||
```bash
|
||||
sudo Xvfb :10 -ac -screen 0 1024x768x24 & DISPLAY=:10 <YOUR_CLIENT>
|
||||
```
|
||||
|
||||
sudo Xvfb :10 -ac -screen 0 1024x768x24 &
|
||||
DISPLAY=:10 your-client
|
||||
## ⚠️ Limitations
|
||||
|
||||
This experiment aims to showcase the potential of GPT-4 but comes with some limitations:
|
||||
|
@ -464,13 +480,13 @@ We look forward to connecting with you and hearing your thoughts, ideas, and exp
|
|||
|
||||
To run tests, run the following command:
|
||||
|
||||
```
|
||||
```bash
|
||||
python -m unittest discover tests
|
||||
```
|
||||
|
||||
To run tests and see coverage, run the following command:
|
||||
|
||||
```
|
||||
```bash
|
||||
coverage run -m unittest discover tests
|
||||
```
|
||||
|
||||
|
@ -480,7 +496,7 @@ This project uses [flake8](https://flake8.pycqa.org/en/latest/) for linting. We
|
|||
|
||||
To run the linter, run the following command:
|
||||
|
||||
```
|
||||
```bash
|
||||
flake8 autogpt/ tests/
|
||||
|
||||
# Or, if you want to run flake8 with the same configuration as the CI:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""Main script for the autogpt package."""
|
||||
import logging
|
||||
from colorama import Fore
|
||||
from autogpt.agent.agent import Agent
|
||||
from autogpt.args import parse_arguments
|
||||
|
||||
|
@ -33,7 +34,8 @@ def main() -> None:
|
|||
# Initialize memory and make sure it is empty.
|
||||
# this is particularly important for indexing and referencing pinecone memory
|
||||
memory = get_memory(cfg, init=True)
|
||||
print(f"Using memory of type: {memory.__class__.__name__}")
|
||||
logger.typewriter_log(f"Using memory of type:", Fore.GREEN, f"{memory.__class__.__name__}")
|
||||
logger.typewriter_log(f"Using Browser:", Fore.GREEN, cfg.selenium_web_browser)
|
||||
agent = Agent(
|
||||
ai_name=ai_name,
|
||||
memory=memory,
|
||||
|
|
|
@ -14,7 +14,7 @@ class AgentManager(metaclass=Singleton):
|
|||
# Create new GPT agent
|
||||
# TODO: Centralise use of create_chat_completion() to globally enforce token limit
|
||||
|
||||
def create_agent(self, task: str, prompt: str, model: str) -> tuple[int, str]:
|
||||
def create_agent(self, task: str, prompt: str, model: str) -> Tuple[int, str]:
|
||||
"""Create a new agent and return its key
|
||||
|
||||
Args:
|
||||
|
|
|
@ -22,6 +22,7 @@ from autogpt.memory import get_memory
|
|||
from autogpt.processing.text import summarize_text
|
||||
from autogpt.speech import say_text
|
||||
from autogpt.commands.web_selenium import browse_website
|
||||
from autogpt.commands.git_operations import clone_repository
|
||||
|
||||
|
||||
CFG = Config()
|
||||
|
@ -87,6 +88,21 @@ def get_command(response: str):
|
|||
return "Error:", str(e)
|
||||
|
||||
|
||||
def map_command_synonyms(command_name: str):
|
||||
""" Takes the original command name given by the AI, and checks if the
|
||||
string matches a list of common/known hallucinations
|
||||
"""
|
||||
synonyms = [
|
||||
('write_file', 'write_to_file'),
|
||||
('create_file', 'write_to_file'),
|
||||
('search', 'google')
|
||||
]
|
||||
for seen_command, actual_command_name in synonyms:
|
||||
if command_name == seen_command:
|
||||
return actual_command_name
|
||||
return command_name
|
||||
|
||||
|
||||
def execute_command(command_name: str, arguments):
|
||||
"""Execute the command and return the result
|
||||
|
||||
|
@ -99,15 +115,18 @@ def execute_command(command_name: str, arguments):
|
|||
memory = get_memory(CFG)
|
||||
|
||||
try:
|
||||
command_name = map_command_synonyms(command_name)
|
||||
if command_name == "google":
|
||||
# Check if the Google API key is set and use the official search method
|
||||
# If the API key is not set or has only whitespaces, use the unofficial
|
||||
# search method
|
||||
key = CFG.google_api_key
|
||||
if key and key.strip() and key != "your-google-api-key":
|
||||
return google_official_search(arguments["input"])
|
||||
google_result = google_official_search(arguments["input"])
|
||||
else:
|
||||
return google_search(arguments["input"])
|
||||
google_result = google_search(arguments["input"])
|
||||
safe_message = google_result.encode('utf-8', 'ignore')
|
||||
return str(safe_message)
|
||||
elif command_name == "memory_add":
|
||||
return memory.add(arguments["string"])
|
||||
elif command_name == "start_agent":
|
||||
|
@ -124,6 +143,8 @@ def execute_command(command_name: str, arguments):
|
|||
return get_text_summary(arguments["url"], arguments["question"])
|
||||
elif command_name == "get_hyperlinks":
|
||||
return get_hyperlinks(arguments["url"])
|
||||
elif command_name == "clone_repository":
|
||||
return clone_repository(arguments["repository_url"], arguments["clone_path"])
|
||||
elif command_name == "read_file":
|
||||
return read_file(arguments["file"])
|
||||
elif command_name == "write_to_file":
|
||||
|
@ -242,11 +263,8 @@ def message_agent(key: str, message: str) -> str:
|
|||
# Check if the key is a valid integer
|
||||
if is_valid_int(key):
|
||||
agent_response = AGENT_MANAGER.message_agent(int(key), message)
|
||||
# Check if the key is a valid string
|
||||
elif isinstance(key, str):
|
||||
agent_response = AGENT_MANAGER.message_agent(key, message)
|
||||
else:
|
||||
return "Invalid key, must be an integer or a string."
|
||||
return "Invalid key, must be an integer."
|
||||
|
||||
# Speak response
|
||||
if CFG.speak_mode:
|
||||
|
@ -258,9 +276,9 @@ def list_agents():
|
|||
"""List all agents
|
||||
|
||||
Returns:
|
||||
list: A list of all agents
|
||||
str: A list of all agents
|
||||
"""
|
||||
return AGENT_MANAGER.list_agents()
|
||||
return "List of agents:\n" + "\n".join([str(x[0]) + ": " + x[1] for x in AGENT_MANAGER.list_agents()])
|
||||
|
||||
|
||||
def delete_agent(key: str) -> str:
|
||||
|
|
|
@ -50,6 +50,12 @@ def parse_arguments() -> None:
|
|||
action="store_true",
|
||||
help="Skips the re-prompting messages at the beginning of the script",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--use-browser",
|
||||
"-b",
|
||||
dest="browser_name",
|
||||
help="Specifies which web-browser to use when using selenium to scrape the web."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ai-settings",
|
||||
"-C",
|
||||
|
@ -126,3 +132,6 @@ def parse_arguments() -> None:
|
|||
logger.typewriter_log("Using AI Settings File:", Fore.GREEN, file)
|
||||
CFG.ai_settings_file = file
|
||||
CFG.skip_reprompt = True
|
||||
|
||||
if args.browser_name:
|
||||
CFG.selenium_web_browser = args.browser_name
|
||||
|
|
|
@ -100,7 +100,7 @@ def execute_shell(command_line: str) -> str:
|
|||
"""
|
||||
current_dir = os.getcwd()
|
||||
|
||||
if WORKING_DIRECTORY not in current_dir: # Change dir into workspace if necessary
|
||||
if str(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)
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ def split_file(
|
|||
Split text into chunks of a specified maximum length with a specified overlap
|
||||
between chunks.
|
||||
|
||||
:param text: The input text to be split into chunks
|
||||
:param content: The input text to be split into chunks
|
||||
:param max_length: The maximum length of each chunk,
|
||||
default is 4000 (about 1k token)
|
||||
:param overlap: The number of overlapping characters between chunks,
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import git
|
||||
from autogpt.config import Config
|
||||
|
||||
cfg = Config()
|
||||
|
||||
|
||||
def clone_repository(repo_url, clone_path):
|
||||
"""Clone a github repository locally"""
|
||||
split_url = repo_url.split("//")
|
||||
auth_repo_url = f"//{cfg.github_username}:{cfg.github_api_key}@".join(split_url)
|
||||
git.Repo.clone_from(auth_repo_url, clone_path)
|
||||
result = f"""Cloned {repo_url} to {clone_path}"""
|
||||
|
||||
return result
|
|
@ -72,7 +72,7 @@ def get_response(
|
|||
timeout (int): The timeout for the HTTP request
|
||||
|
||||
Returns:
|
||||
tuple[None, str] | tuple[Response, None]: The response and error message
|
||||
Tuple[None, str] | Tuple[Response, None]: The response and error message
|
||||
|
||||
Raises:
|
||||
ValueError: If the URL is invalid
|
||||
|
@ -192,7 +192,7 @@ def create_message(chunk, question):
|
|||
"""Create a message for the user to summarize a chunk of text"""
|
||||
return {
|
||||
"role": "user",
|
||||
"content": f'"""{chunk}""" Using the above text, please answer the following'
|
||||
"content": f'"""{chunk}""" Using the above text, answer the following'
|
||||
f' question: "{question}" -- if the question cannot be answered using the'
|
||||
" text, please summarize the text.",
|
||||
" text, summarize the text.",
|
||||
}
|
||||
|
|
|
@ -7,16 +7,20 @@ from selenium.webdriver.common.by import By
|
|||
from selenium.webdriver.support.wait import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from webdriver_manager.chrome import ChromeDriverManager
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from webdriver_manager.firefox import GeckoDriverManager
|
||||
from selenium.webdriver.chrome.options import Options as ChromeOptions
|
||||
from selenium.webdriver.firefox.options import Options as FirefoxOptions
|
||||
from selenium.webdriver.safari.options import Options as SafariOptions
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from autogpt.config import Config
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
FILE_DIR = Path(__file__).parent.parent
|
||||
CFG = Config()
|
||||
|
||||
|
||||
def browse_website(url: str, question: str) -> tuple[str, WebDriver]:
|
||||
def browse_website(url: str, question: str) -> Tuple[str, WebDriver]:
|
||||
"""Browse a website and return the answer and links to the user
|
||||
|
||||
Args:
|
||||
|
@ -24,7 +28,7 @@ def browse_website(url: str, question: str) -> tuple[str, WebDriver]:
|
|||
question (str): The question asked by the user
|
||||
|
||||
Returns:
|
||||
tuple[str, WebDriver]: The answer and links to the user and the webdriver
|
||||
Tuple[str, WebDriver]: The answer and links to the user and the webdriver
|
||||
"""
|
||||
driver, text = scrape_text_with_selenium(url)
|
||||
add_header(driver)
|
||||
|
@ -38,22 +42,33 @@ def browse_website(url: str, question: str) -> tuple[str, WebDriver]:
|
|||
return f"Answer gathered from website: {summary_text} \n \n Links: {links}", driver
|
||||
|
||||
|
||||
def scrape_text_with_selenium(url: str) -> tuple[WebDriver, str]:
|
||||
def scrape_text_with_selenium(url: str) -> Tuple[WebDriver, str]:
|
||||
"""Scrape text from a website using selenium
|
||||
|
||||
Args:
|
||||
url (str): The url of the website to scrape
|
||||
|
||||
Returns:
|
||||
tuple[WebDriver, str]: The webdriver and the text scraped from the website
|
||||
Tuple[WebDriver, str]: The webdriver and the text scraped from the website
|
||||
"""
|
||||
logging.getLogger("selenium").setLevel(logging.CRITICAL)
|
||||
|
||||
options = Options()
|
||||
options_available = {'chrome': ChromeOptions, 'safari': SafariOptions, 'firefox': FirefoxOptions}
|
||||
|
||||
options = options_available[CFG.selenium_web_browser]()
|
||||
options.add_argument(
|
||||
"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
||||
" (KHTML, like Gecko) Chrome/112.0.5615.49 Safari/537.36"
|
||||
"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.49 Safari/537.36"
|
||||
)
|
||||
|
||||
if CFG.selenium_web_browser == "firefox":
|
||||
driver = webdriver.Firefox(
|
||||
executable_path=GeckoDriverManager().install(), options=options
|
||||
)
|
||||
elif CFG.selenium_web_browser == "safari":
|
||||
# Requires a bit more setup on the users end
|
||||
# See https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari
|
||||
driver = webdriver.Safari(options=options)
|
||||
else:
|
||||
driver = webdriver.Chrome(
|
||||
executable_path=ChromeDriverManager().install(), options=options
|
||||
)
|
||||
|
@ -77,14 +92,14 @@ def scrape_text_with_selenium(url: str) -> tuple[WebDriver, str]:
|
|||
return driver, text
|
||||
|
||||
|
||||
def scrape_links_with_selenium(driver: WebDriver) -> list[str]:
|
||||
def scrape_links_with_selenium(driver: WebDriver) -> List[str]:
|
||||
"""Scrape links from a website using selenium
|
||||
|
||||
Args:
|
||||
driver (WebDriver): The webdriver to use to scrape the links
|
||||
|
||||
Returns:
|
||||
list[str]: The links scraped from the website
|
||||
List[str]: The links scraped from the website
|
||||
"""
|
||||
page_source = driver.page_source
|
||||
soup = BeautifulSoup(page_source, "html.parser")
|
||||
|
@ -109,26 +124,26 @@ def close_browser(driver: WebDriver) -> None:
|
|||
driver.quit()
|
||||
|
||||
|
||||
def extract_hyperlinks(soup: BeautifulSoup) -> list[tuple[str, str]]:
|
||||
def extract_hyperlinks(soup: BeautifulSoup) -> List[Tuple[str, str]]:
|
||||
"""Extract hyperlinks from a BeautifulSoup object
|
||||
|
||||
Args:
|
||||
soup (BeautifulSoup): The BeautifulSoup object to extract the hyperlinks from
|
||||
|
||||
Returns:
|
||||
list[tuple[str, str]]: The hyperlinks extracted from the BeautifulSoup object
|
||||
List[Tuple[str, str]]: The hyperlinks extracted from the BeautifulSoup object
|
||||
"""
|
||||
return [(link.text, link["href"]) for link in soup.find_all("a", href=True)]
|
||||
|
||||
|
||||
def format_hyperlinks(hyperlinks: list[tuple[str, str]]) -> list[str]:
|
||||
def format_hyperlinks(hyperlinks: List[Tuple[str, str]]) -> List[str]:
|
||||
"""Format hyperlinks to be displayed to the user
|
||||
|
||||
Args:
|
||||
hyperlinks (list[tuple[str, str]]): The hyperlinks to format
|
||||
hyperlinks (List[Tuple[str, str]]): The hyperlinks to format
|
||||
|
||||
Returns:
|
||||
list[str]: The formatted hyperlinks
|
||||
List[str]: The formatted hyperlinks
|
||||
"""
|
||||
return [f"{link_text} ({link_url})" for link_text, link_url in hyperlinks]
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ class Config(metaclass=Singleton):
|
|||
self.speak_mode = False
|
||||
self.skip_reprompt = False
|
||||
|
||||
self.selenium_web_browser = os.getenv("USE_WEB_BROWSER", "chrome")
|
||||
self.ai_settings_file = os.getenv("AI_SETTINGS_FILE", "ai_settings.yaml")
|
||||
self.fast_llm_model = os.getenv("FAST_LLM_MODEL", "gpt-3.5-turbo")
|
||||
self.smart_llm_model = os.getenv("SMART_LLM_MODEL", "gpt-4")
|
||||
|
@ -56,6 +57,9 @@ class Config(metaclass=Singleton):
|
|||
self.use_brian_tts = False
|
||||
self.use_brian_tts = os.getenv("USE_BRIAN_TTS")
|
||||
|
||||
self.github_api_key = os.getenv("GITHUB_API_KEY")
|
||||
self.github_username = os.getenv("GITHUB_USERNAME")
|
||||
|
||||
self.google_api_key = os.getenv("GOOGLE_API_KEY")
|
||||
self.custom_search_engine_id = os.getenv("CUSTOM_SEARCH_ENGINE_ID")
|
||||
|
||||
|
@ -141,15 +145,9 @@ class Config(metaclass=Singleton):
|
|||
config_params = yaml.load(file, Loader=yaml.FullLoader)
|
||||
except FileNotFoundError:
|
||||
config_params = {}
|
||||
self.openai_api_type = os.getenv(
|
||||
"OPENAI_API_TYPE", config_params.get("azure_api_type", "azure")
|
||||
)
|
||||
self.openai_api_base = os.getenv(
|
||||
"OPENAI_AZURE_API_BASE", config_params.get("azure_api_base", "")
|
||||
)
|
||||
self.openai_api_version = os.getenv(
|
||||
"OPENAI_AZURE_API_VERSION", config_params.get("azure_api_version", "")
|
||||
)
|
||||
self.openai_api_type = config_params.get("azure_api_type") or "azure"
|
||||
self.openai_api_base = config_params.get("azure_api_base") or ""
|
||||
self.openai_api_version = config_params.get("azure_api_version") or "2023-03-15-preview"
|
||||
self.azure_model_to_deployment_id_map = config_params.get("azure_model_map", [])
|
||||
|
||||
def set_continuous_mode(self, value: bool) -> None:
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
"""This module contains the function to fix JSON strings using GPT-3."""
|
||||
import json
|
||||
|
||||
from autogpt.llm_utils import call_ai_function
|
||||
from autogpt.logs import logger
|
||||
from autogpt.config import Config
|
||||
cfg = Config()
|
||||
|
||||
|
||||
def fix_json(json_str: str, schema: str) -> str:
|
||||
def fix_json(json_string: str, schema: str) -> str:
|
||||
"""Fix the given JSON string to make it parseable and fully compliant with the provided schema."""
|
||||
# Try to fix the JSON using GPT:
|
||||
function_string = "def fix_json(json_str: str, schema:str=None) -> str:"
|
||||
args = [f"'''{json_str}'''", f"'''{schema}'''"]
|
||||
function_string = "def fix_json(json_string: str, schema:str=None) -> str:"
|
||||
args = [f"'''{json_string}'''", f"'''{schema}'''"]
|
||||
description_string = (
|
||||
"Fixes the provided JSON string to make it parseable"
|
||||
" and fully compliant with the provided schema.\n If an object or"
|
||||
|
@ -18,13 +21,13 @@ def fix_json(json_str: str, schema: str) -> str:
|
|||
)
|
||||
|
||||
# If it doesn't already start with a "`", add one:
|
||||
if not json_str.startswith("`"):
|
||||
json_str = "```json\n" + json_str + "\n```"
|
||||
if not json_string.startswith("`"):
|
||||
json_string = "```json\n" + json_string + "\n```"
|
||||
result_string = call_ai_function(
|
||||
function_string, args, description_string, model=cfg.fast_llm_model
|
||||
)
|
||||
logger.debug("------------ JSON FIX ATTEMPT ---------------")
|
||||
logger.debug(f"Original JSON: {json_str}")
|
||||
logger.debug(f"Original JSON: {json_string}")
|
||||
logger.debug("-----------")
|
||||
logger.debug(f"Fixed JSON: {result_string}")
|
||||
logger.debug("----------- END OF FIX ATTEMPT ----------------")
|
||||
|
@ -32,9 +35,9 @@ def fix_json(json_str: str, schema: str) -> str:
|
|||
try:
|
||||
json.loads(result_string) # just check the validity
|
||||
return result_string
|
||||
except: # noqa: E722
|
||||
except json.JSONDecodeError: # noqa: E722
|
||||
# Get the call stack:
|
||||
# import traceback
|
||||
# call_stack = traceback.format_exc()
|
||||
# print(f"Failed to fix JSON: '{json_str}' "+call_stack)
|
||||
# print(f"Failed to fix JSON: '{json_string}' "+call_stack)
|
||||
return "failed"
|
||||
|
|
|
@ -59,7 +59,7 @@ def create_chat_completion(
|
|||
"""Create a chat completion using the OpenAI API
|
||||
|
||||
Args:
|
||||
messages (list[dict[str, str]]): The messages to send to the chat completion
|
||||
messages (List[Dict[str, str]]): The messages to send to the chat completion
|
||||
model (str, optional): The model to use. Defaults to None.
|
||||
temperature (float, optional): The temperature to use. Defaults to 0.9.
|
||||
max_tokens (int, optional): The max tokens to use. Defaults to None.
|
||||
|
|
|
@ -22,13 +22,13 @@ except ImportError:
|
|||
PineconeMemory = None
|
||||
|
||||
try:
|
||||
from memory.weaviate import WeaviateMemory
|
||||
from autogpt.memory.weaviate import WeaviateMemory
|
||||
except ImportError:
|
||||
print("Weaviate not installed. Skipping import.")
|
||||
WeaviateMemory = None
|
||||
|
||||
try:
|
||||
from memory.milvus import MilvusMemory
|
||||
from autogpt.memory.milvus import MilvusMemory
|
||||
except ImportError:
|
||||
print("pymilvus not installed. Skipping import.")
|
||||
MilvusMemory = None
|
||||
|
@ -60,15 +60,14 @@ def get_memory(cfg, init=False):
|
|||
" use Weaviate as a memory backend.")
|
||||
else:
|
||||
memory = WeaviateMemory(cfg)
|
||||
|
||||
elif cfg.memory_backend == "no_memory":
|
||||
memory = NoMemory(cfg)
|
||||
elif cfg.memory_backend == "milvus":
|
||||
if not MilvusMemory:
|
||||
print("Error: Milvus sdk is not installed."
|
||||
"Please install pymilvus to use Milvus as memory backend.")
|
||||
else:
|
||||
memory = MilvusMemory(cfg)
|
||||
elif cfg.memory_backend == "no_memory":
|
||||
memory = NoMemory(cfg)
|
||||
|
||||
if memory is None:
|
||||
memory = LocalCache(cfg)
|
||||
|
|
|
@ -6,7 +6,7 @@ from pymilvus import (
|
|||
Collection,
|
||||
)
|
||||
|
||||
from memory.base import MemoryProviderSingleton, get_ada_embedding
|
||||
from autogpt.memory.base import MemoryProviderSingleton, get_ada_embedding
|
||||
|
||||
|
||||
class MilvusMemory(MemoryProviderSingleton):
|
||||
|
@ -28,15 +28,16 @@ class MilvusMemory(MemoryProviderSingleton):
|
|||
]
|
||||
|
||||
# create collection if not exist and load it.
|
||||
schema = CollectionSchema(fields, "auto-gpt memory storage")
|
||||
self.collection = Collection(cfg.milvus_collection, schema)
|
||||
self.milvus_collection = cfg.milvus_collection
|
||||
self.schema = CollectionSchema(fields, "auto-gpt memory storage")
|
||||
self.collection = Collection(self.milvus_collection, self.schema)
|
||||
# create index if not exist.
|
||||
if not self.collection.has_index(index_name="embeddings"):
|
||||
if not self.collection.has_index():
|
||||
self.collection.release()
|
||||
self.collection.create_index("embeddings", {
|
||||
"index_type": "IVF_FLAT",
|
||||
"metric_type": "IP",
|
||||
"params": {"nlist": 128},
|
||||
"index_type": "HNSW",
|
||||
"params": {"M": 8, "efConstruction": 64},
|
||||
}, index_name="embeddings")
|
||||
self.collection.load()
|
||||
|
||||
|
@ -65,6 +66,13 @@ class MilvusMemory(MemoryProviderSingleton):
|
|||
""" Drop the index in memory.
|
||||
"""
|
||||
self.collection.drop()
|
||||
self.collection = Collection(self.milvus_collection, self.schema)
|
||||
self.collection.create_index("embeddings", {
|
||||
"metric_type": "IP",
|
||||
"index_type": "HNSW",
|
||||
"params": {"M": 8, "efConstruction": 64},
|
||||
}, index_name="embeddings")
|
||||
self.collection.load()
|
||||
return "Obliviated"
|
||||
|
||||
def get_relevant(self, data, num_relevant=5):
|
|
@ -1,5 +1,5 @@
|
|||
"""Text processing functions"""
|
||||
from typing import Generator, Optional
|
||||
from typing import Generator, Optional, Dict
|
||||
from selenium.webdriver.remote.webdriver import WebDriver
|
||||
from autogpt.memory import get_memory
|
||||
from autogpt.config import Config
|
||||
|
@ -114,7 +114,7 @@ def scroll_to_percentage(driver: WebDriver, ratio: float) -> None:
|
|||
driver.execute_script(f"window.scrollTo(0, document.body.scrollHeight * {ratio});")
|
||||
|
||||
|
||||
def create_message(chunk: str, question: str) -> dict[str, str]:
|
||||
def create_message(chunk: str, question: str) -> Dict[str, str]:
|
||||
"""Create a message for the chat completion
|
||||
|
||||
Args:
|
||||
|
@ -122,11 +122,11 @@ def create_message(chunk: str, question: str) -> dict[str, str]:
|
|||
question (str): The question to answer
|
||||
|
||||
Returns:
|
||||
dict[str, str]: The message to send to the chat completion
|
||||
Dict[str, str]: The message to send to the chat completion
|
||||
"""
|
||||
return {
|
||||
"role": "user",
|
||||
"content": f'"""{chunk}""" Using the above text, please answer the following'
|
||||
"content": f'"""{chunk}""" Using the above text, answer the following'
|
||||
f' question: "{question}" -- if the question cannot be answered using the text,'
|
||||
" please summarize the text.",
|
||||
" summarize the text.",
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ from autogpt.config.ai_config import AIConfig
|
|||
from autogpt.config.config import Config
|
||||
from autogpt.logs import logger
|
||||
from autogpt.promptgenerator import PromptGenerator
|
||||
from autogpt.config import Config
|
||||
from autogpt.setup import prompt_user
|
||||
from autogpt.utils import clean_input
|
||||
|
||||
|
@ -18,6 +19,9 @@ def get_prompt() -> str:
|
|||
str: The generated prompt string.
|
||||
"""
|
||||
|
||||
# Initialize the Config object
|
||||
cfg = Config()
|
||||
|
||||
# Initialize the PromptGenerator object
|
||||
prompt_generator = PromptGenerator()
|
||||
|
||||
|
@ -55,6 +59,7 @@ def get_prompt() -> str:
|
|||
),
|
||||
("List GPT Agents", "list_agents", {}),
|
||||
("Delete GPT Agent", "delete_agent", {"key": "<key>"}),
|
||||
("Clone Repository", "clone_repository", {"repository_url": "<url>", "clone_path": "<directory>"}),
|
||||
("Write to file", "write_to_file", {"file": "<file>", "text": "<text>"}),
|
||||
("Read file", "read_file", {"file": "<file>"}),
|
||||
("Append to file", "append_to_file", {"file": "<file>", "text": "<text>"}),
|
||||
|
@ -72,15 +77,26 @@ def get_prompt() -> str:
|
|||
{"code": "<full_code_string>", "focus": "<list_of_focus_areas>"},
|
||||
),
|
||||
("Execute Python File", "execute_python_file", {"file": "<file>"}),
|
||||
("Generate Image", "generate_image", {"prompt": "<prompt>"}),
|
||||
]
|
||||
|
||||
# Only add shell command to the prompt if the AI is allowed to execute it
|
||||
if cfg.execute_local_commands:
|
||||
commands.append(
|
||||
(
|
||||
"Execute Shell Command, non-interactive commands only",
|
||||
"execute_shell",
|
||||
{"command_line": "<command_line>"},
|
||||
),
|
||||
("Task Complete (Shutdown)", "task_complete", {"reason": "<reason>"}),
|
||||
("Generate Image", "generate_image", {"prompt": "<prompt>"}),
|
||||
)
|
||||
|
||||
# Add these command last.
|
||||
commands.append(
|
||||
("Do Nothing", "do_nothing", {}),
|
||||
]
|
||||
)
|
||||
commands.append(
|
||||
("Task Complete (Shutdown)", "task_complete", {"reason": "<reason>"}),
|
||||
)
|
||||
|
||||
# Add commands to the PromptGenerator object
|
||||
for command_label, command_name, args in commands:
|
||||
|
|
|
@ -27,7 +27,7 @@ def count_message_tokens(
|
|||
logger.warn("Warning: model not found. Using cl100k_base encoding.")
|
||||
encoding = tiktoken.get_encoding("cl100k_base")
|
||||
if model == "gpt-3.5-turbo":
|
||||
# !Node: gpt-3.5-turbo may change over time.
|
||||
# !Note: gpt-3.5-turbo may change over time.
|
||||
# Returning num tokens assuming gpt-3.5-turbo-0301.")
|
||||
return count_message_tokens(messages, model="gpt-3.5-turbo-0301")
|
||||
elif model == "gpt-4":
|
||||
|
|
|
@ -7,6 +7,8 @@ services:
|
|||
depends_on:
|
||||
- redis
|
||||
build: ./
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- "./autogpt:/app"
|
||||
- ".env:/app/.env"
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 309 KiB |
|
@ -0,0 +1,25 @@
|
|||
beautifulsoup4
|
||||
colorama==0.4.6
|
||||
openai==0.27.2
|
||||
playsound==1.2.2
|
||||
python-dotenv==1.0.0
|
||||
pyyaml==6.0
|
||||
readability-lxml==0.8.1
|
||||
requests
|
||||
tiktoken==0.3.3
|
||||
gTTS==2.3.1
|
||||
docker
|
||||
duckduckgo-search
|
||||
google-api-python-client #(https://developers.google.com/custom-search/v1/overview)
|
||||
pinecone-client==2.2.1
|
||||
redis
|
||||
orjson
|
||||
Pillow
|
||||
selenium
|
||||
webdriver-manager
|
||||
coverage
|
||||
flake8
|
||||
numpy
|
||||
pre-commit
|
||||
black
|
||||
isort
|
|
@ -12,7 +12,7 @@ docker
|
|||
duckduckgo-search
|
||||
google-api-python-client #(https://developers.google.com/custom-search/v1/overview)
|
||||
pinecone-client==2.2.1
|
||||
pymilvus==2.2.4
|
||||
# pymilvus==2.2.4 # Uncomment to use, but don't push uncommented to repo (causes trouble with package-installation in automated tests)
|
||||
redis
|
||||
orjson
|
||||
Pillow
|
||||
|
@ -26,3 +26,4 @@ pre-commit
|
|||
black
|
||||
sourcery
|
||||
isort
|
||||
gitpython==3.1.31
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
@echo off
|
||||
python scripts/check_requirements.py requirements.txt
|
||||
if errorlevel 1 (
|
||||
echo Installing missing packages...
|
||||
pip install -r requirements.txt
|
||||
)
|
||||
python -m autogpt %*
|
||||
pause
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
set argument=--continuous
|
||||
call run.bat %argument%
|
|
@ -0,0 +1,27 @@
|
|||
import pkg_resources
|
||||
import sys
|
||||
|
||||
def main():
|
||||
requirements_file = sys.argv[1]
|
||||
with open(requirements_file, 'r') as f:
|
||||
required_packages = [line.strip().split('#')[0].strip() for line in f.readlines()]
|
||||
|
||||
installed_packages = [package.key for package in pkg_resources.working_set]
|
||||
|
||||
missing_packages = []
|
||||
for package in required_packages:
|
||||
if not package: # Skip empty lines
|
||||
continue
|
||||
package_name = package.strip().split('==')[0]
|
||||
if package_name.lower() not in installed_packages:
|
||||
missing_packages.append(package_name)
|
||||
|
||||
if missing_packages:
|
||||
print('Missing packages:')
|
||||
print(', '.join(missing_packages))
|
||||
sys.exit(1)
|
||||
else:
|
||||
print('All packages are installed.')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
14
tests.py
14
tests.py
|
@ -1,8 +1,20 @@
|
|||
import unittest
|
||||
import coverage
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Start coverage collection
|
||||
cov = coverage.Coverage()
|
||||
cov.start()
|
||||
|
||||
# Load all tests from the 'autogpt/tests' package
|
||||
suite = unittest.defaultTestLoader.discover("autogpt/tests")
|
||||
suite = unittest.defaultTestLoader.discover("./tests")
|
||||
|
||||
# Run the tests
|
||||
unittest.TextTestRunner().run(suite)
|
||||
|
||||
# Stop coverage collection
|
||||
cov.stop()
|
||||
cov.save()
|
||||
|
||||
# Report the coverage
|
||||
cov.report(show_missing=True)
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import random
|
||||
import string
|
||||
import unittest
|
||||
|
||||
from autogpt.config import Config
|
||||
from autogpt.memory.milvus import MilvusMemory
|
||||
|
||||
|
||||
class TestMilvusMemory(unittest.TestCase):
|
||||
def random_string(self, length):
|
||||
return "".join(random.choice(string.ascii_letters) for _ in range(length))
|
||||
|
||||
def setUp(self):
|
||||
cfg = Config()
|
||||
cfg.milvus_addr = "localhost:19530"
|
||||
self.memory = MilvusMemory(cfg)
|
||||
self.memory.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.memory.add(text)
|
||||
|
||||
# Add some random strings to test noise
|
||||
for _ in range(5):
|
||||
self.memory.add(self.random_string(10))
|
||||
|
||||
def test_get_relevant(self):
|
||||
query = "I'm interested in artificial intelligence and NLP"
|
||||
k = 3
|
||||
relevant_texts = self.memory.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()
|
|
@ -0,0 +1,64 @@
|
|||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from autogpt.memory.milvus import MilvusMemory
|
||||
|
||||
|
||||
def MockConfig():
|
||||
return type(
|
||||
"MockConfig",
|
||||
(object,),
|
||||
{
|
||||
"debug_mode": False,
|
||||
"continuous_mode": False,
|
||||
"speak_mode": False,
|
||||
"milvus_collection": "autogpt",
|
||||
"milvus_addr": "localhost:19530",
|
||||
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class TestMilvusMemory(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.cfg = MockConfig()
|
||||
self.memory = MilvusMemory(self.cfg)
|
||||
|
||||
def test_add(self):
|
||||
text = "Sample text"
|
||||
self.memory.clear()
|
||||
self.memory.add(text)
|
||||
result = self.memory.get(text)
|
||||
self.assertEqual([text], result)
|
||||
|
||||
def test_clear(self):
|
||||
self.memory.clear()
|
||||
self.assertEqual(self.memory.collection.num_entities, 0)
|
||||
|
||||
def test_get(self):
|
||||
text = "Sample text"
|
||||
self.memory.clear()
|
||||
self.memory.add(text)
|
||||
result = self.memory.get(text)
|
||||
self.assertEqual(result, [text])
|
||||
|
||||
def test_get_relevant(self):
|
||||
text1 = "Sample text 1"
|
||||
text2 = "Sample text 2"
|
||||
self.memory.clear()
|
||||
self.memory.add(text1)
|
||||
self.memory.add(text2)
|
||||
result = self.memory.get_relevant(text1, 1)
|
||||
self.assertEqual(result, [text1])
|
||||
|
||||
def test_get_stats(self):
|
||||
text = "Sample text"
|
||||
self.memory.clear()
|
||||
self.memory.add(text)
|
||||
stats = self.memory.get_stats()
|
||||
self.assertEqual(15, len(stats))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -0,0 +1,60 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from autogpt.file_operations import delete_file, read_file
|
||||
|
||||
env_vars = {
|
||||
'MEMORY_BACKEND': 'no_memory',
|
||||
'TEMPERATURE': "0"
|
||||
}
|
||||
|
||||
|
||||
class TestCommands(unittest.TestCase):
|
||||
|
||||
def test_write_file(self):
|
||||
# Test case to check if the write_file command can successfully write 'Hello World' to a file
|
||||
# named 'hello_world.txt'.
|
||||
|
||||
# Read the current ai_settings.yaml file and store its content.
|
||||
ai_settings = None
|
||||
if os.path.exists('ai_settings.yaml'):
|
||||
with open('ai_settings.yaml', 'r') as f:
|
||||
ai_settings = f.read()
|
||||
os.remove('ai_settings.yaml')
|
||||
|
||||
try:
|
||||
if os.path.exists('hello_world.txt'):
|
||||
# Clean up any existing 'hello_world.txt' file before testing.
|
||||
delete_file('hello_world.txt')
|
||||
# Prepare input data for the test.
|
||||
input_data = '''write_file-GPT
|
||||
an AI designed to use the write_file command to write 'Hello World' into a file named "hello_world.txt" and then use the task_complete command to complete the task.
|
||||
Use the write_file command to write 'Hello World' into a file named "hello_world.txt".
|
||||
Use the task_complete command to complete the task.
|
||||
Do not use any other commands.
|
||||
|
||||
y -5
|
||||
EOF'''
|
||||
command = f'{sys.executable} -m autogpt'
|
||||
|
||||
# Execute the script with the input data.
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, shell=True, env={**os.environ, **env_vars})
|
||||
process.communicate(input_data.encode())
|
||||
|
||||
# Read the content of the 'hello_world.txt' file created during the test.
|
||||
content = read_file('hello_world.txt')
|
||||
finally:
|
||||
if ai_settings:
|
||||
# Restore the original ai_settings.yaml file.
|
||||
with open('ai_settings.yaml', 'w') as f:
|
||||
f.write(ai_settings)
|
||||
|
||||
# Check if the content of the 'hello_world.txt' file is equal to 'Hello World'.
|
||||
self.assertEqual(content, 'Hello World', f"Expected 'Hello World', got {content}")
|
||||
|
||||
|
||||
# Run the test case.
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -1,59 +1,84 @@
|
|||
import unittest
|
||||
from unittest import TestCase
|
||||
|
||||
from autogpt.config import Config
|
||||
|
||||
|
||||
class TestConfig(unittest.TestCase):
|
||||
class TestConfig(TestCase):
|
||||
"""
|
||||
Test cases for the Config class, which handles the configuration settings
|
||||
for the AI and ensures it behaves as a singleton.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up the test environment by creating an instance of the Config class.
|
||||
"""
|
||||
self.config = Config()
|
||||
|
||||
def test_singleton(self):
|
||||
config1 = Config()
|
||||
"""
|
||||
Test if the Config class behaves as a singleton by ensuring that two instances are the same.
|
||||
"""
|
||||
config2 = Config()
|
||||
self.assertIs(config1, config2)
|
||||
self.assertIs(self.config, config2)
|
||||
|
||||
def test_initial_values(self):
|
||||
config = Config()
|
||||
self.assertFalse(config.debug_mode)
|
||||
self.assertFalse(config.continuous_mode)
|
||||
self.assertFalse(config.speak_mode)
|
||||
self.assertEqual(config.fast_llm_model, "gpt-3.5-turbo")
|
||||
self.assertEqual(config.smart_llm_model, "gpt-4")
|
||||
self.assertEqual(config.fast_token_limit, 4000)
|
||||
self.assertEqual(config.smart_token_limit, 8000)
|
||||
"""
|
||||
Test if the initial values of the Config class attributes are set correctly.
|
||||
"""
|
||||
self.assertFalse(self.config.debug_mode)
|
||||
self.assertFalse(self.config.continuous_mode)
|
||||
self.assertFalse(self.config.speak_mode)
|
||||
self.assertEqual(self.config.fast_llm_model, "gpt-3.5-turbo")
|
||||
self.assertEqual(self.config.smart_llm_model, "gpt-4")
|
||||
self.assertEqual(self.config.fast_token_limit, 4000)
|
||||
self.assertEqual(self.config.smart_token_limit, 8000)
|
||||
|
||||
def test_set_continuous_mode(self):
|
||||
config = Config()
|
||||
config.set_continuous_mode(True)
|
||||
self.assertTrue(config.continuous_mode)
|
||||
"""
|
||||
Test if the set_continuous_mode() method updates the continuous_mode attribute.
|
||||
"""
|
||||
self.config.set_continuous_mode(True)
|
||||
self.assertTrue(self.config.continuous_mode)
|
||||
|
||||
def test_set_speak_mode(self):
|
||||
config = Config()
|
||||
config.set_speak_mode(True)
|
||||
self.assertTrue(config.speak_mode)
|
||||
"""
|
||||
Test if the set_speak_mode() method updates the speak_mode attribute.
|
||||
"""
|
||||
self.config.set_speak_mode(True)
|
||||
self.assertTrue(self.config.speak_mode)
|
||||
|
||||
def test_set_fast_llm_model(self):
|
||||
config = Config()
|
||||
config.set_fast_llm_model("gpt-3.5-turbo-test")
|
||||
self.assertEqual(config.fast_llm_model, "gpt-3.5-turbo-test")
|
||||
"""
|
||||
Test if the set_fast_llm_model() method updates the fast_llm_model attribute.
|
||||
"""
|
||||
self.config.set_fast_llm_model("gpt-3.5-turbo-test")
|
||||
self.assertEqual(self.config.fast_llm_model, "gpt-3.5-turbo-test")
|
||||
|
||||
def test_set_smart_llm_model(self):
|
||||
config = Config()
|
||||
config.set_smart_llm_model("gpt-4-test")
|
||||
self.assertEqual(config.smart_llm_model, "gpt-4-test")
|
||||
"""
|
||||
Test if the set_smart_llm_model() method updates the smart_llm_model attribute.
|
||||
"""
|
||||
self.config.set_smart_llm_model("gpt-4-test")
|
||||
self.assertEqual(self.config.smart_llm_model, "gpt-4-test")
|
||||
|
||||
def test_set_fast_token_limit(self):
|
||||
config = Config()
|
||||
config.set_fast_token_limit(5000)
|
||||
self.assertEqual(config.fast_token_limit, 5000)
|
||||
"""
|
||||
Test if the set_fast_token_limit() method updates the fast_token_limit attribute.
|
||||
"""
|
||||
self.config.set_fast_token_limit(5000)
|
||||
self.assertEqual(self.config.fast_token_limit, 5000)
|
||||
|
||||
def test_set_smart_token_limit(self):
|
||||
config = Config()
|
||||
config.set_smart_token_limit(9000)
|
||||
self.assertEqual(config.smart_token_limit, 9000)
|
||||
"""
|
||||
Test if the set_smart_token_limit() method updates the smart_token_limit attribute.
|
||||
"""
|
||||
self.config.set_smart_token_limit(9000)
|
||||
self.assertEqual(self.config.smart_token_limit, 9000)
|
||||
|
||||
def test_set_debug_mode(self):
|
||||
config = Config()
|
||||
config.set_debug_mode(True)
|
||||
self.assertTrue(config.debug_mode)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
"""
|
||||
Test if the set_debug_mode() method updates the debug_mode attribute.
|
||||
"""
|
||||
self.config.set_debug_mode(True)
|
||||
self.assertTrue(self.config.debug_mode)
|
||||
|
|
|
@ -1,25 +1,35 @@
|
|||
# Import the required libraries for unit testing
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from unittest import TestCase
|
||||
|
||||
from autogpt.promptgenerator import PromptGenerator
|
||||
|
||||
|
||||
# Create a test class for the PromptGenerator, subclassed from unittest.TestCase
|
||||
class promptgenerator_tests(unittest.TestCase):
|
||||
# Set up the initial state for each test method by creating an instance of PromptGenerator
|
||||
def setUp(self):
|
||||
self.generator = PromptGenerator()
|
||||
class TestPromptGenerator(TestCase):
|
||||
"""
|
||||
Test cases for the PromptGenerator class, which is responsible for generating
|
||||
prompts for the AI with constraints, commands, resources, and performance evaluations.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up the initial state for each test method by creating an instance of PromptGenerator.
|
||||
"""
|
||||
cls.generator = PromptGenerator()
|
||||
|
||||
# Test whether the add_constraint() method adds a constraint to the generator's constraints list
|
||||
def test_add_constraint(self):
|
||||
"""
|
||||
Test if the add_constraint() method adds a constraint to the generator's constraints list.
|
||||
"""
|
||||
constraint = "Constraint1"
|
||||
self.generator.add_constraint(constraint)
|
||||
self.assertIn(constraint, self.generator.constraints)
|
||||
|
||||
# Test whether the add_command() method adds a command to the generator's commands list
|
||||
def test_add_command(self):
|
||||
"""
|
||||
Test if the add_command() method adds a command to the generator's commands list.
|
||||
"""
|
||||
command_label = "Command Label"
|
||||
command_name = "command_name"
|
||||
args = {"arg1": "value1", "arg2": "value2"}
|
||||
|
@ -31,20 +41,29 @@ class promptgenerator_tests(unittest.TestCase):
|
|||
}
|
||||
self.assertIn(command, self.generator.commands)
|
||||
|
||||
# Test whether the add_resource() method adds a resource to the generator's resources list
|
||||
def test_add_resource(self):
|
||||
"""
|
||||
Test if the add_resource() method adds a resource to the generator's resources list.
|
||||
"""
|
||||
resource = "Resource1"
|
||||
self.generator.add_resource(resource)
|
||||
self.assertIn(resource, self.generator.resources)
|
||||
|
||||
# Test whether the add_performance_evaluation() method adds an evaluation to the generator's performance_evaluation list
|
||||
def test_add_performance_evaluation(self):
|
||||
"""
|
||||
Test if the add_performance_evaluation() method adds an evaluation to the generator's
|
||||
performance_evaluation list.
|
||||
"""
|
||||
evaluation = "Evaluation1"
|
||||
self.generator.add_performance_evaluation(evaluation)
|
||||
self.assertIn(evaluation, self.generator.performance_evaluation)
|
||||
|
||||
# Test whether the generate_prompt_string() method generates a prompt string with all the added constraints, commands, resources and evaluations
|
||||
def test_generate_prompt_string(self):
|
||||
"""
|
||||
Test if the generate_prompt_string() method generates a prompt string with all the added
|
||||
constraints, commands, resources, and evaluations.
|
||||
"""
|
||||
# Define the test data
|
||||
constraints = ["Constraint1", "Constraint2"]
|
||||
commands = [
|
||||
{
|
||||
|
@ -61,7 +80,7 @@ class promptgenerator_tests(unittest.TestCase):
|
|||
resources = ["Resource1", "Resource2"]
|
||||
evaluations = ["Evaluation1", "Evaluation2"]
|
||||
|
||||
# Add all the constraints, commands, resources, and evaluations to the generator
|
||||
# Add test data to the generator
|
||||
for constraint in constraints:
|
||||
self.generator.add_constraint(constraint)
|
||||
for command in commands:
|
||||
|
@ -76,24 +95,20 @@ class promptgenerator_tests(unittest.TestCase):
|
|||
# Generate the prompt string and verify its correctness
|
||||
prompt_string = self.generator.generate_prompt_string()
|
||||
self.assertIsNotNone(prompt_string)
|
||||
|
||||
# Check if all constraints, commands, resources, and evaluations are present in the prompt string
|
||||
for constraint in constraints:
|
||||
self.assertIn(constraint, prompt_string)
|
||||
for command in commands:
|
||||
self.assertIn(command["name"], prompt_string)
|
||||
|
||||
# Check for each key-value pair in the command args dictionary
|
||||
for key, value in command["args"].items():
|
||||
self.assertIn(f'"{key}": "{value}"', prompt_string)
|
||||
for resource in resources:
|
||||
self.assertIn(resource, prompt_string)
|
||||
for evaluation in evaluations:
|
||||
self.assertIn(evaluation, prompt_string)
|
||||
|
||||
self.assertIn("constraints", prompt_string.lower())
|
||||
self.assertIn("commands", prompt_string.lower())
|
||||
self.assertIn("resources", prompt_string.lower())
|
||||
self.assertIn("performance evaluation", prompt_string.lower())
|
||||
|
||||
|
||||
# Run the tests when this script is executed
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -0,0 +1,61 @@
|
|||
import unittest
|
||||
import tests.context
|
||||
from autogpt.token_counter import count_message_tokens, count_string_tokens
|
||||
|
||||
|
||||
class TestTokenCounter(unittest.TestCase):
|
||||
|
||||
def test_count_message_tokens(self):
|
||||
messages = [
|
||||
{"role": "user", "content": "Hello"},
|
||||
{"role": "assistant", "content": "Hi there!"}
|
||||
]
|
||||
self.assertEqual(count_message_tokens(messages), 17)
|
||||
|
||||
def test_count_message_tokens_with_name(self):
|
||||
messages = [
|
||||
{"role": "user", "content": "Hello", "name": "John"},
|
||||
{"role": "assistant", "content": "Hi there!"}
|
||||
]
|
||||
self.assertEqual(count_message_tokens(messages), 17)
|
||||
|
||||
def test_count_message_tokens_empty_input(self):
|
||||
self.assertEqual(count_message_tokens([]), 3)
|
||||
|
||||
def test_count_message_tokens_invalid_model(self):
|
||||
messages = [
|
||||
{"role": "user", "content": "Hello"},
|
||||
{"role": "assistant", "content": "Hi there!"}
|
||||
]
|
||||
with self.assertRaises(KeyError):
|
||||
count_message_tokens(messages, model="invalid_model")
|
||||
|
||||
def test_count_message_tokens_gpt_4(self):
|
||||
messages = [
|
||||
{"role": "user", "content": "Hello"},
|
||||
{"role": "assistant", "content": "Hi there!"}
|
||||
]
|
||||
self.assertEqual(count_message_tokens(messages, model="gpt-4-0314"), 15)
|
||||
|
||||
def test_count_string_tokens(self):
|
||||
string = "Hello, world!"
|
||||
self.assertEqual(count_string_tokens(string, model_name="gpt-3.5-turbo-0301"), 4)
|
||||
|
||||
def test_count_string_tokens_empty_input(self):
|
||||
self.assertEqual(count_string_tokens("", model_name="gpt-3.5-turbo-0301"), 0)
|
||||
|
||||
def test_count_message_tokens_invalid_model(self):
|
||||
messages = [
|
||||
{"role": "user", "content": "Hello"},
|
||||
{"role": "assistant", "content": "Hi there!"}
|
||||
]
|
||||
with self.assertRaises(NotImplementedError):
|
||||
count_message_tokens(messages, model="invalid_model")
|
||||
|
||||
def test_count_string_tokens_gpt_4(self):
|
||||
string = "Hello, world!"
|
||||
self.assertEqual(count_string_tokens(string, model_name="gpt-4-0314"), 4)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -0,0 +1,18 @@
|
|||
import autogpt.agent.agent_manager as agent_manager
|
||||
from autogpt.app import start_agent, list_agents
|
||||
import unittest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
||||
class TestCommands(unittest.TestCase):
|
||||
def test_make_agent(self):
|
||||
with patch("openai.ChatCompletion.create") as mock:
|
||||
obj = MagicMock()
|
||||
obj.response.choices[0].messages[0].content = "Test message"
|
||||
mock.return_value = obj
|
||||
start_agent("Test Agent", "chat", "Hello, how are you?", "gpt2")
|
||||
agents = list_agents()
|
||||
self.assertEqual("List of agents:\n0: chat", agents)
|
||||
start_agent("Test Agent 2", "write", "Hello, how are you?", "gpt2")
|
||||
agents = list_agents()
|
||||
self.assertEqual("List of agents:\n0: chat\n1: write", agents)
|
Loading…
Reference in New Issue