Merge pull request #667 from caseymcc/register_settings

Add support to load/override model settings
This commit is contained in:
paul-gauthier 2024-06-21 16:57:41 -07:00 committed by GitHub
commit cf451d5e9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 142 additions and 41 deletions

View file

@ -158,18 +158,23 @@ def get_parser(default_config_files, git_root):
env_var="OPENAI_ORGANIZATION_ID", env_var="OPENAI_ORGANIZATION_ID",
help="Specify the OpenAI organization ID", help="Specify the OpenAI organization ID",
) )
group.add_argument(
"--model-settings-file",
metavar="MODEL_SETTINGS_FILE",
default=None,
help="Specify a file with aider model settings for unknown models",
group.add_argument(
"--model-metadata-file",
metavar="MODEL_METADATA_FILE",
default=None,
help="Specify a file with context window and costs for unknown models",
)
group.add_argument( group.add_argument(
"--verify-ssl", "--verify-ssl",
action=argparse.BooleanOptionalAction, action=argparse.BooleanOptionalAction,
default=True, default=True,
help="Verify the SSL cert when connecting to models (default: True)", help="Verify the SSL cert when connecting to models (default: True)",
) )
group.add_argument(
"--model-metadata-file",
metavar="MODEL_FILE",
default=None,
help="Specify a file with context window and costs for unknown models",
)
group.add_argument( group.add_argument(
"--edit-format", "--edit-format",
metavar="EDIT_FORMAT", metavar="EDIT_FORMAT",

View file

@ -212,7 +212,48 @@ def parse_lint_cmds(lint_cmds, io):
return return
return res return res
def generate_search_path_list(default_fname, git_root, command_line_file):
files = []
default_file = Path(default_fname)
files.append(Path.home() / default_file) # homedir
if git_root:
files.append(Path(git_root) / default_file) # git root
if command_line_file:
files.append(command_line_file)
files.append(default_file.resolve())
files = list(map(str, files))
files = list(dict.fromkeys(files))
return files
def register_models(git_root, model_settings_fname, io):
model_settings_files = generate_search_path_list(".aider.models.yml", git_root, model_settings_fname)
try:
files_loaded = models.register_models(model_settings_files)
if len(files_loaded) > 0:
io.tool_output(f"Loaded {len(files_loaded)} model settings file(s)")
for file_loaded in files_loaded:
io.tool_output(f" - {file_loaded}")
except Exception as e:
io.tool_error(f"Error loading aider model settings: {e}")
return 1
return None
def register_litellm_models(git_root, model_metadata_fname, io):
model_metatdata_files = generate_search_path_list(".aider.litellm.models.json", git_root, model_metadata_fname)
try:
model_metadata_files_loaded = models.register_litellm_models(model_metatdata_files)
if len(model_metadata_files_loaded) > 0:
io.tool_output(f"Loaded {len(model_metadata_files_loaded)} litellm model file(s)")
for model_metadata_file in model_metadata_files_loaded:
io.tool_output(f" - {model_metadata_file}")
except Exception as e:
io.tool_error(f"Error loading litellm models: {e}")
return 1
def main(argv=None, input=None, output=None, force_git_root=None, return_coder=False): def main(argv=None, input=None, output=None, force_git_root=None, return_coder=False):
if argv is None: if argv is None:
argv = sys.argv[1:] argv = sys.argv[1:]
@ -350,26 +391,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.openai_organization_id: if args.openai_organization_id:
os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id
model_def_files = [] register_models(git_root, args.model_settings_file, io)
model_def_fname = Path(".aider.models.json") register_litellm_models(git_root, args.model_metadata_file, io)
model_def_files.append(Path.home() / model_def_fname) # homedir
if git_root:
model_def_files.append(Path(git_root) / model_def_fname) # git root
if args.model_metadata_file:
model_def_files.append(args.model_metadata_file)
model_def_files.append(model_def_fname.resolve())
model_def_files = list(map(str, model_def_files))
model_def_files = list(dict.fromkeys(model_def_files))
try:
model_metadata_files_loaded = models.register_models(model_def_files)
if len(model_metadata_files_loaded) > 0:
io.tool_output(f"Loaded {len(model_metadata_files_loaded)} model file(s)")
for model_metadata_file in model_metadata_files_loaded:
io.tool_output(f" - {model_metadata_file}")
except Exception as e:
io.tool_error(f"Error loading model info/cost: {e}")
return 1
main_model = models.Model(args.model, weak_model=args.weak_model) main_model = models.Model(args.model, weak_model=args.weak_model)
lint_cmds = parse_lint_cmds(args.lint_cmd, io) lint_cmds = parse_lint_cmds(args.lint_cmd, io)

View file

@ -1,5 +1,6 @@
import difflib import difflib
import json import json
import yaml
import math import math
import os import os
import sys import sys
@ -470,23 +471,47 @@ class Model:
return validate_variables(["GROQ_API_KEY"]) return validate_variables(["GROQ_API_KEY"])
return res return res
def register_models(model_settings_fnames):
def register_models(model_def_fnames): files_loaded = []
model_metadata_files_loaded = [] for model_settings_fname in model_settings_fnames:
for model_def_fname in model_def_fnames: if not os.path.exists(model_settings_fname):
if not os.path.exists(model_def_fname):
continue continue
model_metadata_files_loaded.append(model_def_fname)
try: try:
with open(model_def_fname, "r") as model_def_file: with open(model_settings_fname, "r") as model_settings_file:
model_settings_list = yaml.safe_load(model_settings_file)
for model_settings_dict in model_settings_list:
model_settings = ModelSettings(**model_settings_dict)
existing_model_settings = next((ms for ms in MODEL_SETTINGS if ms.name == model_settings.name), None)
if existing_model_settings:
MODEL_SETTINGS.remove(existing_model_settings)
MODEL_SETTINGS.append(model_settings)
except Exception as e:
raise Exception(f"Error loading model settings from {model_settings_fname}: {e}")
files_loaded.append(model_settings_fname)
return files_loaded
def register_litellm_models(model_fnames):
files_loaded = []
for model_fname in model_fnames:
if not os.path.exists(model_fname):
continue
try:
with open(model_fname, "r") as model_def_file:
model_def = json.load(model_def_file) model_def = json.load(model_def_file)
except json.JSONDecodeError as e: litellm.register_model(model_def)
raise Exception(f"Error loading model definition from {model_def_fname}: {e}") except Exception as e:
raise Exception(f"Error loading model definition from {model_fname}: {e}")
files_loaded.append(model_fname)
litellm.register_model(model_def) return files_loaded
return model_metadata_files_loaded
def validate_variables(vars): def validate_variables(vars):

View file

@ -8,10 +8,45 @@ nav_order: 900
{% include model-warnings.md %} {% include model-warnings.md %}
## Adding settings for missing models
You can register model settings used by aider for unknown models.
Create a `.aider.models.yml` file in one of these locations:
- Your home directory.
- The root if your git repo.
- The current directory where you launch aider.
- Or specify a specific file with the `--model-settings-file <filename>` switch.
If the files above exist, they will be loaded in that order.
Files loaded last will take priority.
The yaml file should be a a list of dictionary objects for each model, as follows:
```
- name: "gpt-3.5-turbo"
edit_format: "whole"
weak_model_name: "gpt-3.5-turbo"
use_repo_map: false
send_undo_reply: false
accepts_images: false
lazy: false
reminder_as_sys_msg: true
examples_as_sys_msg: false
- name: "gpt-4-turbo-2024-04-09"
edit_format: "udiff"
weak_model_name: "gpt-3.5-turbo"
use_repo_map: true
send_undo_reply: true
accepts_images: true
lazy: true
reminder_as_sys_msg: true
examples_as_sys_msg: false
```
## Specifying context window size and token costs ## Specifying context window size and token costs
You can register context window limits and costs for models that aren't known You can register context window limits and costs for models that aren't known
to aider. Create a `.aider.models.json` file in one of these locations: to aider. Create a `.aider.litellm.models.json` file in one of these locations:
- Your home directory. - Your home directory.
- The root if your git repo. - The root if your git repo.

View file

@ -14,6 +14,14 @@ from aider.args import get_md_help
cog.out(get_md_help()) cog.out(get_md_help())
]]]--> ]]]-->
``` ```
usage: aider [-h] [--vim] [--openai-api-key] [--anthropic-api-key]
[--model] [--opus] [--sonnet] [--4] [--4o] [--4-turbo]
[--35turbo] [--models] [--openai-api-base]
[--openai-api-type] [--openai-api-version]
[--openai-api-deployment-id] [--openai-organization-id]
[--model-settings-file] [--model-metadata-file]
[--edit-format] [--weak-model]
=======
usage: aider [-h] [--llm-history-file] [--openai-api-key] usage: aider [-h] [--llm-history-file] [--openai-api-key]
[--anthropic-api-key] [--model] [--opus] [--sonnet] [--anthropic-api-key] [--model] [--opus] [--sonnet]
[--4] [--4o] [--4-turbo] [--35turbo] [--models] [--4] [--4o] [--4-turbo] [--35turbo] [--models]
@ -129,6 +137,10 @@ Environment variable: `OPENAI_API_DEPLOYMENT_ID`
Specify the OpenAI organization ID Specify the OpenAI organization ID
Environment variable: `OPENAI_ORGANIZATION_ID` Environment variable: `OPENAI_ORGANIZATION_ID`
### `--model-settings-file MODEL_FILE`
Specify a file with aider model settings for unknown models
Environment variable: `AIDER_MODEL_SETTINGS_FILE`
=======
### `--verify-ssl` ### `--verify-ssl`
Verify the SSL cert when connecting to models (default: True) Verify the SSL cert when connecting to models (default: True)
Default: True Default: True