Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: decrease number of saves to MemGPTConfig #943

Merged
merged 1 commit into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 45 additions & 35 deletions memgpt/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,15 @@ def str_to_quickstart_choice(choice_str: str) -> QuickstartChoice:
raise ValueError(f"{choice_str} is not a valid QuickstartChoice. Valid options are: {valid_options}")


def set_config_with_dict(new_config: dict) -> bool:
"""Set the base config using a dict"""
def set_config_with_dict(new_config: dict) -> (MemGPTConfig, bool):
"""_summary_

Args:
new_config (dict): Dict of new config values

Returns:
new_config MemGPTConfig, modified (bool): Returns the new config and a boolean indicating if the config was modified
"""
from memgpt.utils import printd

old_config = MemGPTConfig.load()
Expand Down Expand Up @@ -93,32 +100,7 @@ def set_config_with_dict(new_config: dict) -> bool:
else:
printd(f"Skipping new config {k}: {v} == {new_config[k]}")

if modified:
printd(f"Saving new config file.")
old_config.save()
typer.secho(f"📖 MemGPT configuration file updated!", fg=typer.colors.GREEN)
typer.secho(
"\n".join(
[
f"🧠 model\t-> {old_config.default_llm_config.model}",
f"🖥️ endpoint\t-> {old_config.default_llm_config.model_endpoint}",
]
),
fg=typer.colors.GREEN,
)
return True
else:
typer.secho(f"📖 MemGPT configuration file unchanged.", fg=typer.colors.WHITE)
typer.secho(
"\n".join(
[
f"🧠 model\t-> {old_config.default_llm_config.model}",
f"🖥️ endpoint\t-> {old_config.default_llm_config.model_endpoint}",
]
),
fg=typer.colors.WHITE,
)
return False
return (old_config, modified)


def quickstart(
Expand All @@ -127,7 +109,10 @@ def quickstart(
debug: Annotated[bool, typer.Option(help="Use --debug to enable debugging output")] = False,
terminal: bool = True,
):
"""Set the base config file with a single command"""
"""Set the base config file with a single command

This function and `configure` should be the ONLY places where MemGPTConfig.save() is called.
"""

# setup logger
utils.DEBUG = debug
Expand All @@ -154,7 +139,7 @@ def quickstart(
config = response.json()
# Output a success message and the first few items in the dictionary as a sample
printd("JSON config file downloaded successfully.")
config_was_modified = set_config_with_dict(config)
new_config, config_was_modified = set_config_with_dict(config)
else:
typer.secho(f"Failed to download config from {url}. Status code: {response.status_code}", fg=typer.colors.RED)

Expand All @@ -165,7 +150,7 @@ def quickstart(
with open(backup_config_path, "r", encoding="utf-8") as file:
backup_config = json.load(file)
printd("Loaded backup config file successfully.")
config_was_modified = set_config_with_dict(backup_config)
new_config, config_was_modified = set_config_with_dict(backup_config)
except FileNotFoundError:
typer.secho(f"Backup config file not found at {backup_config_path}", fg=typer.colors.RED)
return
Expand All @@ -177,7 +162,7 @@ def quickstart(
with open(backup_config_path, "r", encoding="utf-8") as file:
backup_config = json.load(file)
printd("Loaded config file successfully.")
config_was_modified = set_config_with_dict(backup_config)
new_config, config_was_modified = set_config_with_dict(backup_config)
except FileNotFoundError:
typer.secho(f"Config file not found at {backup_config_path}", fg=typer.colors.RED)
return
Expand All @@ -203,7 +188,7 @@ def quickstart(
config = response.json()
# Output a success message and the first few items in the dictionary as a sample
print("JSON config file downloaded successfully.")
config_was_modified = set_config_with_dict(config)
new_config, config_was_modified = set_config_with_dict(config)
else:
typer.secho(f"Failed to download config from {url}. Status code: {response.status_code}", fg=typer.colors.RED)

Expand All @@ -214,7 +199,7 @@ def quickstart(
with open(backup_config_path, "r", encoding="utf-8") as file:
backup_config = json.load(file)
printd("Loaded backup config file successfully.")
config_was_modified = set_config_with_dict(backup_config)
new_config, config_was_modified = set_config_with_dict(backup_config)
except FileNotFoundError:
typer.secho(f"Backup config file not found at {backup_config_path}", fg=typer.colors.RED)
return
Expand All @@ -226,14 +211,39 @@ def quickstart(
with open(backup_config_path, "r", encoding="utf-8") as file:
backup_config = json.load(file)
printd("Loaded config file successfully.")
config_was_modified = set_config_with_dict(backup_config)
new_config, config_was_modified = set_config_with_dict(backup_config)
except FileNotFoundError:
typer.secho(f"Config file not found at {backup_config_path}", fg=typer.colors.RED)
return

else:
raise NotImplementedError(backend)

if config_was_modified:
cpacker marked this conversation as resolved.
Show resolved Hide resolved
printd(f"Saving new config file.")
new_config.save()
typer.secho(f"📖 MemGPT configuration file updated!", fg=typer.colors.GREEN)
typer.secho(
"\n".join(
[
f"🧠 model\t-> {new_config.default_llm_config.model}",
f"🖥️ endpoint\t-> {new_config.default_llm_config.model_endpoint}",
]
),
fg=typer.colors.GREEN,
)
else:
typer.secho(f"📖 MemGPT configuration file unchanged.", fg=typer.colors.WHITE)
typer.secho(
"\n".join(
[
f"🧠 model\t-> {new_config.default_llm_config.model}",
f"🖥️ endpoint\t-> {new_config.default_llm_config.model_endpoint}",
]
),
fg=typer.colors.WHITE,
)

# 'terminal' = quickstart was run alone, in which case we should guide the user on the next command
if terminal:
if config_was_modified:
Expand Down
5 changes: 4 additions & 1 deletion memgpt/cli/cli_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,10 @@ def configure_recall_storage(config: MemGPTConfig, credentials: MemGPTCredential

@app.command()
def configure():
"""Updates default MemGPT configurations"""
"""Updates default MemGPT configurations

This function and quickstart should be the ONLY place where MemGPTConfig.save() is called
"""

# check credentials
credentials = MemGPTCredentials.load()
Expand Down
1 change: 0 additions & 1 deletion memgpt/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
@dataclass
class MemGPTConfig:
config_path: str = os.path.join(MEMGPT_DIR, "config")
anon_clientid: str = None

Check failure on line 42 in memgpt/config.py

View workflow job for this annotation

GitHub Actions / Pyright types check (3.11)

Expression of type "None" cannot be assigned to declared type "str"   "None" is incompatible with "str" (reportAssignmentType)

# preset
preset: str = DEFAULT_PRESET
Expand All @@ -57,22 +57,22 @@
# database configs: archival
archival_storage_type: str = "chroma" # local, db
archival_storage_path: str = os.path.join(MEMGPT_DIR, "chroma")
archival_storage_uri: str = None # TODO: eventually allow external vector DB

Check failure on line 60 in memgpt/config.py

View workflow job for this annotation

GitHub Actions / Pyright types check (3.11)

Expression of type "None" cannot be assigned to declared type "str"   "None" is incompatible with "str" (reportAssignmentType)

# database configs: recall
recall_storage_type: str = "sqlite" # local, db
recall_storage_path: str = MEMGPT_DIR
recall_storage_uri: str = None # TODO: eventually allow external vector DB

Check failure on line 65 in memgpt/config.py

View workflow job for this annotation

GitHub Actions / Pyright types check (3.11)

Expression of type "None" cannot be assigned to declared type "str"   "None" is incompatible with "str" (reportAssignmentType)

# database configs: metadata storage (sources, agents, data sources)
metadata_storage_type: str = "sqlite"
metadata_storage_path: str = MEMGPT_DIR
metadata_storage_uri: str = None

Check failure on line 70 in memgpt/config.py

View workflow job for this annotation

GitHub Actions / Pyright types check (3.11)

Expression of type "None" cannot be assigned to declared type "str"   "None" is incompatible with "str" (reportAssignmentType)

# database configs: agent state
persistence_manager_type: str = None # in-memory, db

Check failure on line 73 in memgpt/config.py

View workflow job for this annotation

GitHub Actions / Pyright types check (3.11)

Expression of type "None" cannot be assigned to declared type "str"   "None" is incompatible with "str" (reportAssignmentType)
persistence_manager_save_file: str = None # local file

Check failure on line 74 in memgpt/config.py

View workflow job for this annotation

GitHub Actions / Pyright types check (3.11)

Expression of type "None" cannot be assigned to declared type "str"   "None" is incompatible with "str" (reportAssignmentType)
persistence_manager_uri: str = None # db URI

Check failure on line 75 in memgpt/config.py

View workflow job for this annotation

GitHub Actions / Pyright types check (3.11)

Expression of type "None" cannot be assigned to declared type "str"   "None" is incompatible with "str" (reportAssignmentType)

# version (for backcompat)
memgpt_version: str = memgpt.__version__
Expand Down Expand Up @@ -115,7 +115,7 @@

# insure all configuration directories exist
cls.create_config_dir()
if os.path.exists(config_path):

Check failure on line 118 in memgpt/config.py

View workflow job for this annotation

GitHub Actions / Pyright types check (3.11)

Argument of type "str | None" cannot be assigned to parameter "path" of type "FileDescriptorOrPath" in function "exists" (reportArgumentType)
# read existing config
config.read(config_path)

Expand Down Expand Up @@ -185,7 +185,6 @@
anon_clientid = MemGPTConfig.generate_uuid()
config = cls(anon_clientid=anon_clientid, config_path=config_path)
config.create_config_dir() # create dirs
config.save() # save updated config

return config

Expand Down
Loading