Skip to content

Commit

Permalink
feat: further simplify setup flow (#673)
Browse files Browse the repository at this point in the history
* made quickstart to openai or memgpt the default option when the user doesn't have a config set

* modified formatting + message styles

* revised quickstart guides in docs to talk about quickstart command

* make message consistent

---------

Co-authored-by: Sarah Wooders <sarahwooders@gmail.com>
  • Loading branch information
cpacker and sarahwooders authored Dec 22, 2023
1 parent a880635 commit 7d3e5b2
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 39 deletions.
34 changes: 21 additions & 13 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,44 @@ category: 6580d34ee5e4d00068bf2a1d
### Installation

To install MemGPT, make sure you have Python installed on your computer, then run:

```sh
pip install pymemgpt
```

If you already have MemGPT installed, you can update to the latest version with:

```sh
pip install pymemgpt -U
```

### Running MemGPT using the OpenAI API

Add your OpenAI API key to your environment:
### Running MemGPT

Now, you can run MemGPT and start chatting with a MemGPT agent with:
```sh
export OPENAI_API_KEY=YOUR_API_KEY # on Linux/Mac
set OPENAI_API_KEY=YOUR_API_KEY # on Windows
$Env:OPENAI_API_KEY = "YOUR_API_KEY" # on Windows (PowerShell)
memgpt run
```
Configure default settings for MemGPT by running:

If you're running MemGPT for the first time, you'll see two quickstart options:

1. **OpenAI**: select this if you'd like to run MemGPT with OpenAI models like GPT-4 (requires an OpenAI API key)
2. **MemGPT Free Endpoint**: select this if you'd like to try MemGPT on a top open LLM for free (currently variants of Mixtral 8x7b!)

Neither of these options require you to have an LLM running on your own machine. If you'd like to run MemGPT with your custom LLM setup (or on OpenAI Azure), select **Other** to proceed to the advanced setup.

### Quickstart

If you'd ever like to quickly switch back to the default **OpenAI** or **MemGPT Free Endpoint** options, you can use the `quickstart` command:
```sh
memgpt configure
# this will set you up on the MemGPT Free Endpoint
memgpt quickstart
```
Now, you can run MemGPT with:
```sh
memgpt run
# this will set you up on the default OpenAI settings
memgpt quickstart --backend openai
```

In this example we use the OpenAI API, but you can run MemGPT with other backends! See:
### Advanced setup

MemGPT supports a large number of LLM backends! See:

* [Running MemGPT on OpenAI Azure and custom OpenAI endpoints](endpoints)
* [Running MemGPT with your own LLMs (Llama 2, Mistral 7B, etc.)](local_llm)
Expand Down
95 changes: 69 additions & 26 deletions memgpt/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class QuickstartChoice(Enum):
memgpt_hosted = "memgpt"


def set_config_with_dict(new_config: dict):
def set_config_with_dict(new_config: dict) -> bool:
"""Set the base config using a dict"""
from memgpt.utils import printd

Expand All @@ -51,25 +51,30 @@ def set_config_with_dict(new_config: dict):
if modified:
printd(f"Saving new config file.")
old_config.save()
typer.secho(f"\nMemGPT configuration file updated!", fg=typer.colors.GREEN)
typer.secho('Run "memgpt run" to create an agent with the new config.', fg=typer.colors.YELLOW)
typer.secho(f"📖 MemGPT configuration file updated!", fg=typer.colors.GREEN)
typer.secho(f"🧠 model\t-> {old_config.model}\n🖥️ endpoint\t-> {old_config.model_endpoint}", fg=typer.colors.GREEN)
return True
else:
typer.secho(f"\nMemGPT configuration file unchanged.", fg=typer.colors.GREEN)
typer.secho('Run "memgpt run" to create an agent.', fg=typer.colors.YELLOW)
typer.secho(f"📖 MemGPT configuration file unchanged.", fg=typer.colors.WHITE)
typer.secho(f"🧠 model\t-> {old_config.model}\n🖥️ endpoint\t-> {old_config.model_endpoint}", fg=typer.colors.WHITE)
return False


def quickstart(
backend: QuickstartChoice = typer.Option("memgpt", help="Quickstart setup backend"),
latest: bool = typer.Option(False, "--latest", help="Use --latest to pull the latest config from online"),
debug: bool = typer.Option(False, "--debug", help="Use --debug to enable debugging output"),
terminal: bool = True,
):
"""Set the base config file with a single command"""

# setup logger
utils.DEBUG = debug
logging.getLogger().setLevel(logging.CRITICAL)
if debug:
logging.getLogger().setLevel(logging.DEBUG)

config_was_modified = False
if backend == QuickstartChoice.memgpt_hosted:
# if latest, try to pull the config from the repo
# fallback to using local
Expand All @@ -83,32 +88,34 @@ def quickstart(
# Parse the response content as JSON
config = response.json()
# Output a success message and the first few items in the dictionary as a sample
print("JSON config file downloaded successfully.")
set_config_with_dict(config)
printd("JSON config file downloaded successfully.")
config_was_modified = set_config_with_dict(config)
else:
print(f"Failed to download config from {url}. Status code:", response.status_code)
typer.secho(f"Failed to download config from {url}. Status code: {response.status_code}", fg=typer.colors.RED)

# Load the file from the relative path
script_dir = os.path.dirname(__file__) # Get the directory where the script is located
backup_config_path = os.path.join(script_dir, "..", "..", "configs", "memgpt_hosted.json")
try:
with open(backup_config_path, "r") as file:
backup_config = json.load(file)
print("Loaded backup config file successfully.")
set_config_with_dict(backup_config)
printd("Loaded backup config file successfully.")
config_was_modified = set_config_with_dict(backup_config)
except FileNotFoundError:
print(f"Backup config file not found at {backup_config_path}")
typer.secho(f"Backup config file not found at {backup_config_path}", fg=typer.colors.RED)
return
else:
# Load the file from the relative path
script_dir = os.path.dirname(__file__) # Get the directory where the script is located
backup_config_path = os.path.join(script_dir, "..", "..", "configs", "memgpt_hosted.json")
try:
with open(backup_config_path, "r") as file:
backup_config = json.load(file)
print("Loaded config file successfully.")
set_config_with_dict(backup_config)
printd("Loaded config file successfully.")
config_was_modified = set_config_with_dict(backup_config)
except FileNotFoundError:
print(f"Config file not found at {backup_config_path}")
typer.secho(f"Config file not found at {backup_config_path}", fg=typer.colors.RED)
return

elif backend == QuickstartChoice.openai:
# Make sure we have an API key
Expand All @@ -131,9 +138,9 @@ def quickstart(
print("JSON config file downloaded successfully.")
# Add the API key
config["openai_key"] = api_key
set_config_with_dict(config)
config_was_modified = set_config_with_dict(config)
else:
print(f"Failed to download config from {url}. Status code:", response.status_code)
typer.secho(f"Failed to download config from {url}. Status code: {response.status_code}", fg=typer.colors.RED)

# Load the file from the relative path
script_dir = os.path.dirname(__file__) # Get the directory where the script is located
Expand All @@ -142,10 +149,11 @@ def quickstart(
with open(backup_config_path, "r") as file:
backup_config = json.load(file)
backup_config["openai_key"] = api_key
print("Loaded backup config file successfully.")
set_config_with_dict(backup_config)
printd("Loaded backup config file successfully.")
config_was_modified = set_config_with_dict(backup_config)
except FileNotFoundError:
print(f"Backup config file not found at {backup_config_path}")
typer.secho(f"Backup config file not found at {backup_config_path}", fg=typer.colors.RED)
return
else:
# Load the file from the relative path
script_dir = os.path.dirname(__file__) # Get the directory where the script is located
Expand All @@ -154,14 +162,22 @@ def quickstart(
with open(backup_config_path, "r") as file:
backup_config = json.load(file)
backup_config["openai_key"] = api_key
print("Loaded config file successfully.")
set_config_with_dict(backup_config)
printd("Loaded config file successfully.")
config_was_modified = set_config_with_dict(backup_config)
except FileNotFoundError:
print(f"Config file not found at {backup_config_path}")
typer.secho(f"Config file not found at {backup_config_path}", fg=typer.colors.RED)
return

else:
raise NotImplementedError(backend)

# 'terminal' = quickstart was run alone, in which case we should guide the user on the next command
if terminal:
if config_was_modified:
typer.secho('⚡ Run "memgpt run" to create an agent with the new config.', fg=typer.colors.YELLOW)
else:
typer.secho('⚡ Run "memgpt run" to create an agent.', fg=typer.colors.YELLOW)


def open_folder():
"""Open a folder viewer of the MemGPT home directory"""
Expand Down Expand Up @@ -281,14 +297,41 @@ def run(
if debug:
logging.getLogger().setLevel(logging.DEBUG)

if not MemGPTConfig.exists(): # if no config, run configure
if not MemGPTConfig.exists():
# if no config, ask about quickstart
# do you want to do:
# - openai (run quickstart)
# - memgpt hosted (run quickstart)
# - other (run configure)
if yes:
# use defaults
# if user is passing '-y' to bypass all inputs, use memgpt hosted
# since it can't fail out if you don't have an API key
quickstart(backend=QuickstartChoice.memgpt_hosted)
config = MemGPTConfig()

else:
# use input
configure()
config_choices = {
"memgpt": "Use the free MemGPT endpoints",
"openai": "Use OpenAI (requires an OpenAI API key)",
"other": "Other (OpenAI Azure, custom LLM endpoint, etc)",
}
config_selection = questionary.select(
"How would you like to set up MemGPT?",
choices=list(config_choices.values()),
default=config_choices["memgpt"],
).ask()

if config_selection == config_choices["memgpt"]:
quickstart(backend=QuickstartChoice.memgpt_hosted, debug=debug, terminal=False)
elif config_selection == config_choices["openai"]:
quickstart(backend=QuickstartChoice.openai, debug=debug, terminal=False)
elif config_selection == config_choices["other"]:
configure()
else:
raise ValueError(config_selection)

config = MemGPTConfig.load()

else: # load config
config = MemGPTConfig.load()

Expand Down

0 comments on commit 7d3e5b2

Please sign in to comment.