From 7822c1c879a4401b22d4c44e5ea458b3609c6e07 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Mon, 12 Aug 2024 15:04:05 -0700 Subject: [PATCH 01/29] feat: Add support for DeepSeek API base URL --- aider/sendchat.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aider/sendchat.py b/aider/sendchat.py index e767e29ce..7e12e36c9 100644 --- a/aider/sendchat.py +++ b/aider/sendchat.py @@ -1,5 +1,6 @@ import hashlib import json +import os import backoff @@ -57,6 +58,9 @@ def send_completion( temperature=temperature, stream=stream, ) + + if model_name.startswith("deepseek/") and "DEEPSEEK_API_BASE" in os.environ: + kwargs["base_url"] = os.environ["DEEPSEEK_API_BASE"] if functions is not None: kwargs["functions"] = functions if extra_headers is not None: From 2669b0c758fce89f4c90939523bb6d71e93eddca Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Mon, 12 Aug 2024 15:04:08 -0700 Subject: [PATCH 02/29] style: Apply linter edits to sendchat.py --- aider/sendchat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aider/sendchat.py b/aider/sendchat.py index 7e12e36c9..5c0977c1d 100644 --- a/aider/sendchat.py +++ b/aider/sendchat.py @@ -58,7 +58,7 @@ def send_completion( temperature=temperature, stream=stream, ) - + if model_name.startswith("deepseek/") and "DEEPSEEK_API_BASE" in os.environ: kwargs["base_url"] = os.environ["DEEPSEEK_API_BASE"] if functions is not None: From 5f8df315e453ba7f21768fc3c4e03f5c45372c1e Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Mon, 12 Aug 2024 15:05:16 -0700 Subject: [PATCH 03/29] feat: Add --deepseek option for deepseek/deepseek-coder model --- aider/args.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/aider/args.py b/aider/args.py index cd8446162..2b18fb6a0 100644 --- a/aider/args.py +++ b/aider/args.py @@ -109,6 +109,14 @@ def get_parser(default_config_files, git_root): const=gpt_3_model_name, help=f"Use {gpt_3_model_name} model for the main chat", ) + deepseek_model = "deepseek/deepseek-coder" + group.add_argument( + "--deepseek", + action="store_const", + dest="model", + const=deepseek_model, + help=f"Use {deepseek_model} model for the main chat", + ) ########## group = parser.add_argument_group("Model Settings") From 485418d917cbf8a379f638be05c68c19935bc076 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Mon, 12 Aug 2024 15:06:55 -0700 Subject: [PATCH 04/29] feat: Add --deepseek-beta bool arg to use DeepSeek Coder via the beta API endpoint --- aider/args.py | 6 ++++++ aider/sendchat.py | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/aider/args.py b/aider/args.py index 2b18fb6a0..2091a39cd 100644 --- a/aider/args.py +++ b/aider/args.py @@ -117,6 +117,12 @@ def get_parser(default_config_files, git_root): const=deepseek_model, help=f"Use {deepseek_model} model for the main chat", ) + group.add_argument( + "--deepseek-beta", + action="store_true", + help="Uses DeepSeek Coder via the beta API endpoint", + default=False, + ) ########## group = parser.add_argument_group("Model Settings") diff --git a/aider/sendchat.py b/aider/sendchat.py index 5c0977c1d..06505910c 100644 --- a/aider/sendchat.py +++ b/aider/sendchat.py @@ -59,8 +59,11 @@ def send_completion( stream=stream, ) - if model_name.startswith("deepseek/") and "DEEPSEEK_API_BASE" in os.environ: - kwargs["base_url"] = os.environ["DEEPSEEK_API_BASE"] + if model_name.startswith("deepseek/"): + if "DEEPSEEK_API_BASE" in os.environ: + kwargs["base_url"] = os.environ["DEEPSEEK_API_BASE"] + elif getattr(kwargs.get('extra_headers', {}), 'deepseek_beta', False): + kwargs["base_url"] = "https://api.deepseek.com/v1" if functions is not None: kwargs["functions"] = functions if extra_headers is not None: From 843836ea87770c5f5a726375f7e5b118672007da Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Mon, 12 Aug 2024 15:08:04 -0700 Subject: [PATCH 05/29] feat: Add --deepseek-beta bool arg and set model name and DEEPSEEK_API_BASE when used --- aider/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aider/main.py b/aider/main.py index de50dbc70..72308f7a1 100644 --- a/aider/main.py +++ b/aider/main.py @@ -461,6 +461,10 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F if os.environ.get("ANTHROPIC_API_KEY"): args.model = "claude-3-5-sonnet-20240620" + if args.deepseek_beta: + args.model = "deepseek-coder" + os.environ["DEEPSEEK_API_BASE"] = "https://api.deepseek.com/beta" + main_model = models.Model(args.model, weak_model=args.weak_model) lint_cmds = parse_lint_cmds(args.lint_cmd, io) From 888211fd48cbebd836bee2e8afc144543d3cd8ee Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 12 Aug 2024 15:10:02 -0700 Subject: [PATCH 06/29] use litellm's new supports_assistant_prefill --- aider/coders/base_coder.py | 6 ++++-- aider/main.py | 2 +- aider/models.py | 14 -------------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 7040a4b19..49a9c61c7 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -989,7 +989,7 @@ class Coder: return except FinishReasonLength: # We hit the output limit! - if not self.main_model.can_prefill: + if not self.main_model.info.get("supports_assistant_prefill"): exhausted = True break @@ -998,7 +998,9 @@ class Coder: if messages[-1]["role"] == "assistant": messages[-1]["content"] = self.multi_response_content else: - messages.append(dict(role="assistant", content=self.multi_response_content)) + messages.append( + dict(role="assistant", content=self.multi_response_content, prefix=True) + ) except Exception as err: self.io.tool_error(f"Unexpected error: {err}") traceback.print_exc() diff --git a/aider/main.py b/aider/main.py index 72308f7a1..911f09ed7 100644 --- a/aider/main.py +++ b/aider/main.py @@ -462,7 +462,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F args.model = "claude-3-5-sonnet-20240620" if args.deepseek_beta: - args.model = "deepseek-coder" + args.model = "deepseek/deepseek-coder" os.environ["DEEPSEEK_API_BASE"] = "https://api.deepseek.com/beta" main_model = models.Model(args.model, weak_model=args.weak_model) diff --git a/aider/models.py b/aider/models.py index 908404343..551d0b9a4 100644 --- a/aider/models.py +++ b/aider/models.py @@ -70,7 +70,6 @@ class ModelSettings: lazy: bool = False reminder_as_sys_msg: bool = False examples_as_sys_msg: bool = False - can_prefill: bool = False extra_headers: Optional[dict] = None max_tokens: Optional[int] = None @@ -248,7 +247,6 @@ MODEL_SETTINGS = [ weak_model_name="claude-3-haiku-20240307", use_repo_map=True, send_undo_reply=True, - can_prefill=True, ), ModelSettings( "openrouter/anthropic/claude-3-opus", @@ -256,13 +254,11 @@ MODEL_SETTINGS = [ weak_model_name="openrouter/anthropic/claude-3-haiku", use_repo_map=True, send_undo_reply=True, - can_prefill=True, ), ModelSettings( "claude-3-sonnet-20240229", "whole", weak_model_name="claude-3-haiku-20240307", - can_prefill=True, ), ModelSettings( "claude-3-5-sonnet-20240620", @@ -270,7 +266,6 @@ MODEL_SETTINGS = [ weak_model_name="claude-3-haiku-20240307", use_repo_map=True, examples_as_sys_msg=True, - can_prefill=True, accepts_images=True, max_tokens=8192, extra_headers={"anthropic-beta": "max-tokens-3-5-sonnet-2024-07-15"}, @@ -281,7 +276,6 @@ MODEL_SETTINGS = [ weak_model_name="claude-3-haiku-20240307", use_repo_map=True, examples_as_sys_msg=True, - can_prefill=True, max_tokens=8192, extra_headers={ "anthropic-beta": "max-tokens-3-5-sonnet-2024-07-15", @@ -295,7 +289,6 @@ MODEL_SETTINGS = [ weak_model_name="openrouter/anthropic/claude-3-haiku-20240307", use_repo_map=True, examples_as_sys_msg=True, - can_prefill=True, accepts_images=True, max_tokens=8192, extra_headers={ @@ -312,7 +305,6 @@ MODEL_SETTINGS = [ weak_model_name="vertex_ai/claude-3-haiku@20240307", use_repo_map=True, examples_as_sys_msg=True, - can_prefill=True, accepts_images=True, ), ModelSettings( @@ -321,13 +313,11 @@ MODEL_SETTINGS = [ weak_model_name="vertex_ai/claude-3-haiku@20240307", use_repo_map=True, send_undo_reply=True, - can_prefill=True, ), ModelSettings( "vertex_ai/claude-3-sonnet@20240229", "whole", weak_model_name="vertex_ai/claude-3-haiku@20240307", - can_prefill=True, ), # Cohere ModelSettings( @@ -486,14 +476,10 @@ class Model: if "gpt-3.5" in model or "gpt-4" in model: self.reminder_as_sys_msg = True - if "anthropic" in model: - self.can_prefill = True - if "3.5-sonnet" in model or "3-5-sonnet" in model: self.edit_format = "diff" self.use_repo_map = True self.examples_as_sys_msg = True - self.can_prefill = True # use the defaults if self.edit_format == "diff": From 73734efe8946dbfd913226747c7a18c5a80c9939 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Mon, 12 Aug 2024 15:20:05 -0700 Subject: [PATCH 07/29] feat: Add infinity symbol to edit format if model supports assistant prefill --- aider/coders/base_coder.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 49a9c61c7..f8c13b0ef 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -150,6 +150,8 @@ class Coder: weak_model = main_model.weak_model prefix = "Model:" output = f" {main_model.name} with {self.edit_format} edit format" + if main_model.info.get("supports_assistant_prefill"): + output += " ∞" if weak_model is not main_model: prefix = "Models:" output += f", weak model {weak_model.name}" From 27f92b26c6df0ced28b50b6dfe75b5d3bf9b0a2d Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 12 Aug 2024 15:33:09 -0700 Subject: [PATCH 08/29] bump versions for new litellm with prefill --- requirements.txt | 20 +++++++++++++------- requirements/requirements-browser.txt | 14 ++++++-------- requirements/requirements-help.txt | 12 ++++++------ requirements/requirements-playwright.txt | 2 +- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/requirements.txt b/requirements.txt index 84375d2af..2ec825a70 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ # aiohappyeyeballs==2.3.5 # via aiohttp -aiohttp==3.10.2 +aiohttp==3.10.3 # via litellm aiosignal==1.3.1 # via aiohttp @@ -92,7 +92,7 @@ jsonschema==4.23.0 # litellm jsonschema-specifications==2023.12.1 # via jsonschema -litellm==1.43.4 +litellm==1.43.7 # via -r requirements/requirements.in markdown-it-py==3.0.0 # via rich @@ -112,7 +112,7 @@ numpy==1.26.4 # via # -r requirements/requirements.in # scipy -openai==1.40.2 +openai==1.40.6 # via litellm packaging==24.1 # via @@ -125,7 +125,9 @@ pathspec==0.12.1 pillow==10.4.0 # via -r requirements/requirements.in prompt-toolkit==3.0.47 - # via -r requirements/requirements.in + # via + # -r requirements/requirements.in + # pypager pycodestyle==2.12.1 # via flake8 pycparser==2.22 @@ -139,7 +141,11 @@ pydantic-core==2.20.1 pyflakes==3.2.0 # via flake8 pygments==2.18.0 - # via rich + # via + # pypager + # rich +pypager==3.0.1 + # via -r requirements/requirements.in pypandoc==1.13 # via -r requirements/requirements.in pyperclip==1.9.0 @@ -176,7 +182,7 @@ sniffio==1.3.1 # anyio # httpx # openai -sounddevice==0.4.7 +sounddevice==0.5.0 # via -r requirements/requirements.in soundfile==0.12.1 # via -r requirements/requirements.in @@ -210,5 +216,5 @@ wcwidth==0.2.13 # via prompt-toolkit yarl==1.9.4 # via aiohttp -zipp==3.19.2 +zipp==3.20.0 # via importlib-metadata diff --git a/requirements/requirements-browser.txt b/requirements/requirements-browser.txt index 0718a7382..a2f82bdcd 100644 --- a/requirements/requirements-browser.txt +++ b/requirements/requirements-browser.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in # -altair==5.3.0 +altair==5.4.0 # via streamlit attrs==24.2.0 # via @@ -64,10 +64,11 @@ mdurl==0.1.2 # via # -c requirements/../requirements.txt # markdown-it-py +narwhals==1.3.0 + # via altair numpy==1.26.4 # via # -c requirements/../requirements.txt - # altair # pandas # pyarrow # pydeck @@ -78,9 +79,7 @@ packaging==24.1 # altair # streamlit pandas==2.2.2 - # via - # altair - # streamlit + # via streamlit pillow==10.4.0 # via # -c requirements/../requirements.txt @@ -129,13 +128,12 @@ tenacity==8.5.0 # via streamlit toml==0.10.2 # via streamlit -toolz==0.12.1 - # via altair tornado==6.4.1 # via streamlit typing-extensions==4.12.2 # via # -c requirements/../requirements.txt + # altair # streamlit tzdata==2024.1 # via pandas @@ -143,5 +141,5 @@ urllib3==2.2.2 # via # -c requirements/../requirements.txt # requests -watchdog==4.0.1 +watchdog==4.0.2 # via -r requirements/requirements-browser.in diff --git a/requirements/requirements-help.txt b/requirements/requirements-help.txt index 9213407c8..38c7b7504 100644 --- a/requirements/requirements-help.txt +++ b/requirements/requirements-help.txt @@ -8,7 +8,7 @@ aiohappyeyeballs==2.3.5 # via # -c requirements/../requirements.txt # aiohttp -aiohttp==3.10.2 +aiohttp==3.10.3 # via # -c requirements/../requirements.txt # huggingface-hub @@ -112,11 +112,11 @@ joblib==1.4.2 # via # nltk # scikit-learn -llama-index-core==0.10.63 +llama-index-core==0.10.65 # via # -r requirements/requirements-help.in # llama-index-embeddings-huggingface -llama-index-embeddings-huggingface==0.2.2 +llama-index-embeddings-huggingface==0.2.3 # via -r requirements/requirements-help.in markupsafe==2.1.5 # via @@ -142,7 +142,7 @@ networkx==3.2.1 # -c requirements/../requirements.txt # llama-index-core # torch -nltk==3.8.1 +nltk==3.8.2 # via llama-index-core numpy==1.26.4 # via @@ -153,7 +153,7 @@ numpy==1.26.4 # scipy # sentence-transformers # transformers -openai==1.40.2 +openai==1.40.6 # via # -c requirements/../requirements.txt # llama-index-core @@ -224,7 +224,7 @@ sqlalchemy[asyncio]==2.0.32 # via # llama-index-core # sqlalchemy -sympy==1.13.1 +sympy==1.13.2 # via torch tenacity==8.5.0 # via llama-index-core diff --git a/requirements/requirements-playwright.txt b/requirements/requirements-playwright.txt index 4be3d03b6..739bd2dae 100644 --- a/requirements/requirements-playwright.txt +++ b/requirements/requirements-playwright.txt @@ -6,7 +6,7 @@ # greenlet==3.0.3 # via playwright -playwright==1.45.1 +playwright==1.46.0 # via -r requirements/requirements-playwright.in pyee==11.1.0 # via playwright From 2a1fb7d1508d380d6ba1bcc5fc6b61bd92b56499 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 12 Aug 2024 15:35:32 -0700 Subject: [PATCH 09/29] Clean up DEEPSEEK_API_BASE --- aider/args.py | 6 ------ aider/main.py | 4 ---- aider/sendchat.py | 6 ------ 3 files changed, 16 deletions(-) diff --git a/aider/args.py b/aider/args.py index 2091a39cd..2b18fb6a0 100644 --- a/aider/args.py +++ b/aider/args.py @@ -117,12 +117,6 @@ def get_parser(default_config_files, git_root): const=deepseek_model, help=f"Use {deepseek_model} model for the main chat", ) - group.add_argument( - "--deepseek-beta", - action="store_true", - help="Uses DeepSeek Coder via the beta API endpoint", - default=False, - ) ########## group = parser.add_argument_group("Model Settings") diff --git a/aider/main.py b/aider/main.py index 911f09ed7..de50dbc70 100644 --- a/aider/main.py +++ b/aider/main.py @@ -461,10 +461,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F if os.environ.get("ANTHROPIC_API_KEY"): args.model = "claude-3-5-sonnet-20240620" - if args.deepseek_beta: - args.model = "deepseek/deepseek-coder" - os.environ["DEEPSEEK_API_BASE"] = "https://api.deepseek.com/beta" - main_model = models.Model(args.model, weak_model=args.weak_model) lint_cmds = parse_lint_cmds(args.lint_cmd, io) diff --git a/aider/sendchat.py b/aider/sendchat.py index 06505910c..29ba668ce 100644 --- a/aider/sendchat.py +++ b/aider/sendchat.py @@ -1,6 +1,5 @@ import hashlib import json -import os import backoff @@ -59,11 +58,6 @@ def send_completion( stream=stream, ) - if model_name.startswith("deepseek/"): - if "DEEPSEEK_API_BASE" in os.environ: - kwargs["base_url"] = os.environ["DEEPSEEK_API_BASE"] - elif getattr(kwargs.get('extra_headers', {}), 'deepseek_beta', False): - kwargs["base_url"] = "https://api.deepseek.com/v1" if functions is not None: kwargs["functions"] = functions if extra_headers is not None: From 2f3aa5484560ce47f83bf0566f2fd6e16a27ec2e Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 12 Aug 2024 15:36:41 -0700 Subject: [PATCH 10/29] copy --- HISTORY.md | 11 +++++++++++ aider/website/HISTORY.md | 11 +++++++++++ aider/website/assets/sample.aider.conf.yml | 3 +++ aider/website/assets/sample.env | 3 +++ aider/website/docs/config/aider_conf.md | 3 +++ aider/website/docs/config/dotenv.md | 3 +++ aider/website/docs/config/options.md | 6 +++++- 7 files changed, 39 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index d37fab09a..55698ede6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,17 @@ # Release history +### main branch + +- Infinite output for DeepSeek Coder, Mistral models in addition to Anthropic's models. +- New `--chat-mode ` switch to launch in ask/help/code modes. +- New `/code ` command request a code edit while in `ask` mode. +- Web scraper is more robust if page never idles. +- Improvements and bug fixes for `/read` only files. +- Bug fix to persist files added during `/ask`. +- Bug fix for chat history size in `/tokens`. + + ### Aider v0.49.1 - Bugfix to `/help`. diff --git a/aider/website/HISTORY.md b/aider/website/HISTORY.md index 9851d605f..703ffda6d 100644 --- a/aider/website/HISTORY.md +++ b/aider/website/HISTORY.md @@ -16,6 +16,17 @@ cog.out(text) # Release history +### main branch + +- Infinite output for DeepSeek Coder, Mistral models in addition to Anthropic's models. +- New `--chat-mode ` switch to launch in ask/help/code modes. +- New `/code ` command request a code edit while in `ask` mode. +- Web scraper is more robust if page never idles. +- Improvements and bug fixes for `/read` only files. +- Bug fix to persist files added during `/ask`. +- Bug fix for chat history size in `/tokens`. + + ### Aider v0.49.1 - Bugfix to `/help`. diff --git a/aider/website/assets/sample.aider.conf.yml b/aider/website/assets/sample.aider.conf.yml index b771f791d..5ca6131a4 100644 --- a/aider/website/assets/sample.aider.conf.yml +++ b/aider/website/assets/sample.aider.conf.yml @@ -47,6 +47,9 @@ ## Use gpt-3.5-turbo model for the main chat #35turbo: false +## Use deepseek/deepseek-coder model for the main chat +#deepseek: false + ################# # Model Settings: diff --git a/aider/website/assets/sample.env b/aider/website/assets/sample.env index a0f305388..cd1f49c44 100644 --- a/aider/website/assets/sample.env +++ b/aider/website/assets/sample.env @@ -51,6 +51,9 @@ ## Use gpt-3.5-turbo model for the main chat #AIDER_35TURBO= +## Use deepseek/deepseek-coder model for the main chat +#AIDER_DEEPSEEK= + ################# # Model Settings: diff --git a/aider/website/docs/config/aider_conf.md b/aider/website/docs/config/aider_conf.md index e45b71f54..d3dfe6887 100644 --- a/aider/website/docs/config/aider_conf.md +++ b/aider/website/docs/config/aider_conf.md @@ -86,6 +86,9 @@ cog.outl("```") ## Use gpt-3.5-turbo model for the main chat #35turbo: false +## Use deepseek/deepseek-coder model for the main chat +#deepseek: false + ################# # Model Settings: diff --git a/aider/website/docs/config/dotenv.md b/aider/website/docs/config/dotenv.md index 380d7cabd..de1434641 100644 --- a/aider/website/docs/config/dotenv.md +++ b/aider/website/docs/config/dotenv.md @@ -93,6 +93,9 @@ cog.outl("```") ## Use gpt-3.5-turbo model for the main chat #AIDER_35TURBO= +## Use deepseek/deepseek-coder model for the main chat +#AIDER_DEEPSEEK= + ################# # Model Settings: diff --git a/aider/website/docs/config/options.md b/aider/website/docs/config/options.md index 331ec13e2..bdfadbdd4 100644 --- a/aider/website/docs/config/options.md +++ b/aider/website/docs/config/options.md @@ -27,7 +27,7 @@ cog.out(get_md_help()) ``` usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model] [--opus] [--sonnet] [--4] [--4o] [--mini] [--4-turbo] - [--35turbo] [--models] [--openai-api-base] + [--35turbo] [--deepseek] [--models] [--openai-api-base] [--openai-api-type] [--openai-api-version] [--openai-api-deployment-id] [--openai-organization-id] [--model-settings-file] [--model-metadata-file] @@ -118,6 +118,10 @@ Aliases: - `--3` - `-3` +### `--deepseek` +Use deepseek/deepseek-coder model for the main chat +Environment variable: `AIDER_DEEPSEEK` + ## Model Settings: ### `--models MODEL` From 8d7927d35b34fd163495650b66deba7f97f2a6db Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 12 Aug 2024 20:55:01 -0700 Subject: [PATCH 11/29] bump deps to pickup new litellm --- requirements.txt | 2 +- requirements/requirements-dev.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 2ec825a70..906d45000 100644 --- a/requirements.txt +++ b/requirements.txt @@ -92,7 +92,7 @@ jsonschema==4.23.0 # litellm jsonschema-specifications==2023.12.1 # via jsonschema -litellm==1.43.7 +litellm==1.43.9 # via -r requirements/requirements.in markdown-it-py==3.0.0 # via rich diff --git a/requirements/requirements-dev.txt b/requirements/requirements-dev.txt index 124552e9e..0580cc4ba 100644 --- a/requirements/requirements-dev.txt +++ b/requirements/requirements-dev.txt @@ -75,7 +75,7 @@ markupsafe==2.1.5 # via # -c requirements/../requirements.txt # jinja2 -matplotlib==3.9.1.post1 +matplotlib==3.9.2 # via -r requirements/requirements-dev.in mdurl==0.1.2 # via From 124e852366bd1987f1d1519e3f3db8adfe533434 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 12 Aug 2024 20:55:10 -0700 Subject: [PATCH 12/29] infinity! --- aider/coders/base_coder.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index f8c13b0ef..ae0c7093f 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -149,9 +149,10 @@ class Coder: main_model = self.main_model weak_model = main_model.weak_model prefix = "Model:" - output = f" {main_model.name} with {self.edit_format} edit format" + output = f" {main_model.name} with" if main_model.info.get("supports_assistant_prefill"): - output += " ∞" + output += " ♾️" + output += f" {self.edit_format} edit format" if weak_model is not main_model: prefix = "Models:" output += f", weak model {weak_model.name}" From c286135eebc00441ab9c07c256e7fe66e301f6c6 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Mon, 12 Aug 2024 21:12:05 -0700 Subject: [PATCH 13/29] fix: Add new --deepseek switch and chat mode options --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index 55698ede6..855b0e616 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,7 @@ ### main branch - Infinite output for DeepSeek Coder, Mistral models in addition to Anthropic's models. +- New `--deepseek` switch to use DeepSeek Coder. - New `--chat-mode ` switch to launch in ask/help/code modes. - New `/code ` command request a code edit while in `ask` mode. - Web scraper is more robust if page never idles. From a30a27fa8ae69da0bafbb774c5393db203ce339b Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 05:25:36 -0700 Subject: [PATCH 14/29] feat: add test for main --exit that confirms version_check is called --- tests/basic/test_main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/basic/test_main.py b/tests/basic/test_main.py index f8322d2ef..b007ee35e 100644 --- a/tests/basic/test_main.py +++ b/tests/basic/test_main.py @@ -224,6 +224,11 @@ class TestMain(TestCase): main(["--yes", fname, "--encoding", "iso-8859-15"]) + def test_main_exit_calls_version_check(self): + with patch("aider.main.check_version") as mock_check_version: + main(["--exit"]) + mock_check_version.assert_called_once() + @patch("aider.main.InputOutput") @patch("aider.coders.base_coder.Coder.run") def test_main_message_adds_to_input_history(self, mock_run, MockInputOutput): From 58f06e1f56ccd239709dbe57988fbcc157f687f4 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 05:26:12 -0700 Subject: [PATCH 15/29] feat: add GitTemporaryDirectory to test_main_exit_calls_version_check --- tests/basic/test_main.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/basic/test_main.py b/tests/basic/test_main.py index b007ee35e..33bd41714 100644 --- a/tests/basic/test_main.py +++ b/tests/basic/test_main.py @@ -225,9 +225,10 @@ class TestMain(TestCase): main(["--yes", fname, "--encoding", "iso-8859-15"]) def test_main_exit_calls_version_check(self): - with patch("aider.main.check_version") as mock_check_version: - main(["--exit"]) - mock_check_version.assert_called_once() + with GitTemporaryDirectory(): + with patch("aider.main.check_version") as mock_check_version: + main(["--exit"]) + mock_check_version.assert_called_once() @patch("aider.main.InputOutput") @patch("aider.coders.base_coder.Coder.run") From fcf758527a82c498159fd95854b4a8b1f7dcfe89 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 13 Aug 2024 05:29:17 -0700 Subject: [PATCH 16/29] fix: Call check_version in main with input and output arguments --- tests/basic/test_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/basic/test_main.py b/tests/basic/test_main.py index 33bd41714..16f0fcbaa 100644 --- a/tests/basic/test_main.py +++ b/tests/basic/test_main.py @@ -227,7 +227,7 @@ class TestMain(TestCase): def test_main_exit_calls_version_check(self): with GitTemporaryDirectory(): with patch("aider.main.check_version") as mock_check_version: - main(["--exit"]) + main(["--exit"], input=DummyInput(), output=DummyOutput()) mock_check_version.assert_called_once() @patch("aider.main.InputOutput") From cef421dfc0c56a884b0bc3580233af408184dd13 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 05:29:18 -0700 Subject: [PATCH 17/29] feat: Add patch for InputOutput in test_main_exit_calls_version_check --- tests/basic/test_main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/basic/test_main.py b/tests/basic/test_main.py index 16f0fcbaa..92afe1688 100644 --- a/tests/basic/test_main.py +++ b/tests/basic/test_main.py @@ -226,9 +226,11 @@ class TestMain(TestCase): def test_main_exit_calls_version_check(self): with GitTemporaryDirectory(): - with patch("aider.main.check_version") as mock_check_version: + with patch("aider.main.check_version") as mock_check_version, \ + patch("aider.main.InputOutput") as mock_input_output: main(["--exit"], input=DummyInput(), output=DummyOutput()) mock_check_version.assert_called_once() + mock_input_output.assert_called_once() @patch("aider.main.InputOutput") @patch("aider.coders.base_coder.Coder.run") From abb375eb7306e2815784dd1cf655f9beff1d4934 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 05:29:21 -0700 Subject: [PATCH 18/29] style: Format code with linter --- tests/basic/test_main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/basic/test_main.py b/tests/basic/test_main.py index 92afe1688..1560894a0 100644 --- a/tests/basic/test_main.py +++ b/tests/basic/test_main.py @@ -226,8 +226,9 @@ class TestMain(TestCase): def test_main_exit_calls_version_check(self): with GitTemporaryDirectory(): - with patch("aider.main.check_version") as mock_check_version, \ - patch("aider.main.InputOutput") as mock_input_output: + with patch("aider.main.check_version") as mock_check_version, patch( + "aider.main.InputOutput" + ) as mock_input_output: main(["--exit"], input=DummyInput(), output=DummyOutput()) mock_check_version.assert_called_once() mock_input_output.assert_called_once() From 76a4b878b18cd4dddd23b8f6de179846551dd28a Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 05:31:04 -0700 Subject: [PATCH 19/29] feat: Add verbose argument to check_version function --- aider/main.py | 4 ++-- aider/versioncheck.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aider/main.py b/aider/main.py index de50dbc70..bb647d55d 100644 --- a/aider/main.py +++ b/aider/main.py @@ -416,11 +416,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F return main(argv, input, output, right_repo_root, return_coder=return_coder) if args.just_check_update: - update_available = check_version(io, just_check=True) + update_available = check_version(io, just_check=True, verbose=args.verbose) return 0 if not update_available else 1 if args.check_update: - check_version(io) + check_version(io, verbose=args.verbose) if args.models: models.print_matching_models(io, args.models) diff --git a/aider/versioncheck.py b/aider/versioncheck.py index e9a5f7146..76c405458 100644 --- a/aider/versioncheck.py +++ b/aider/versioncheck.py @@ -10,7 +10,7 @@ from aider import utils from aider.dump import dump # noqa: F401 -def check_version(io, just_check=False): +def check_version(io, just_check=False, verbose=False): fname = Path.home() / ".aider" / "caches" / "versioncheck" if not just_check and fname.exists(): day = 60 * 60 * 24 From ad16cc3c413f057505f8eca570f5944b88866e60 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 13 Aug 2024 05:34:53 -0700 Subject: [PATCH 20/29] fix: Add verbose output for version check --- aider/versioncheck.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/aider/versioncheck.py b/aider/versioncheck.py index 76c405458..5ce90cd35 100644 --- a/aider/versioncheck.py +++ b/aider/versioncheck.py @@ -16,6 +16,9 @@ def check_version(io, just_check=False, verbose=False): day = 60 * 60 * 24 since = time.time() - fname.stat().st_mtime if since < day: + if verbose: + hours = since / 60 / 60 + io.tool_output(f"Too soon to check version: {hours:.1f} hours") return # To keep startup fast, avoid importing this unless needed @@ -27,7 +30,7 @@ def check_version(io, just_check=False, verbose=False): latest_version = data["info"]["version"] current_version = aider.__version__ - if just_check: + if just_check or verbose: io.tool_output(f"Current version: {current_version}") io.tool_output(f"Latest version: {latest_version}") @@ -41,11 +44,13 @@ def check_version(io, just_check=False, verbose=False): fname.parent.mkdir(parents=True, exist_ok=True) fname.touch() - if just_check: + if just_check or verbose: if is_update_available: io.tool_output("Update available") else: io.tool_output("No update available") + + if just_check: return is_update_available if not is_update_available: From fb0066cbf0fb80742233f435c4bee622d4aa48c7 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 13 Aug 2024 05:54:19 -0700 Subject: [PATCH 21/29] fix: Handle KeyboardInterrupt in show_send_output_stream --- aider/coders/base_coder.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index ae0c7093f..e99276f9f 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -1259,9 +1259,9 @@ class Coder: yield from self.show_send_output_stream(completion) else: self.show_send_output(completion) - except KeyboardInterrupt: + except KeyboardInterrupt as kbi: self.keyboard_interrupt() - interrupted = True + raise kbi finally: self.io.log_llm_history( "LLM RESPONSE", @@ -1276,10 +1276,7 @@ class Coder: if args: self.io.ai_output(json.dumps(args, indent=4)) - if interrupted: - raise KeyboardInterrupt - - self.calculate_and_show_tokens_and_cost(messages, completion) + self.calculate_and_show_tokens_and_cost(messages, completion) def show_send_output(self, completion): if self.verbose: From 20341d6a43122010d72262cdea38668fe7592ffc Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 05:54:26 -0700 Subject: [PATCH 22/29] fix: remove unused variable 'interrupted' --- aider/coders/base_coder.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index e99276f9f..16d3e0d3f 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -1242,7 +1242,6 @@ class Coder: self.io.log_llm_history("TO LLM", format_messages(messages)) - interrupted = False try: hash_object, completion = send_completion( model.name, From 8cb59902a89d760457339a0364475c29d6efbd11 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 06:16:06 -0700 Subject: [PATCH 23/29] feat: Accumulate message cost and update usage report --- aider/coders/base_coder.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 16d3e0d3f..b924647b4 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -73,6 +73,7 @@ class Coder: multi_response_content = "" partial_response_content = "" commit_before_message = [] + message_cost = 0.0 @classmethod def create( @@ -1276,6 +1277,7 @@ class Coder: self.io.ai_output(json.dumps(args, indent=4)) self.calculate_and_show_tokens_and_cost(messages, completion) + self.show_usage_report() def show_send_output(self, completion): if self.verbose: @@ -1387,13 +1389,14 @@ class Coder: prompt_tokens = self.main_model.token_count(messages) completion_tokens = self.main_model.token_count(self.partial_response_content) - self.usage_report = f"Tokens: {prompt_tokens:,} sent, {completion_tokens:,} received." + tokens_report = f"Tokens: {prompt_tokens:,} sent, {completion_tokens:,} received." if self.main_model.info.get("input_cost_per_token"): cost += prompt_tokens * self.main_model.info.get("input_cost_per_token") if self.main_model.info.get("output_cost_per_token"): cost += completion_tokens * self.main_model.info.get("output_cost_per_token") self.total_cost += cost + self.message_cost += cost def format_cost(value): if value == 0: @@ -1404,9 +1407,17 @@ class Coder: else: return f"{value:.{max(2, 2 - int(math.log10(magnitude)))}f}" - self.usage_report += ( - f" Cost: ${format_cost(cost)} request, ${format_cost(self.total_cost)} session." + cost_report = ( + f" Cost: ${format_cost(self.message_cost)} message, ${format_cost(self.total_cost)} session." ) + self.usage_report = tokens_report + cost_report + else: + self.usage_report = tokens_report + + def show_usage_report(self): + if self.usage_report: + self.io.tool_output(self.usage_report) + self.message_cost = 0.0 def get_multi_response_content(self, final=False): cur = self.multi_response_content or "" From 74e85d558f7160b872a33cee4cd3e31d383ce894 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 06:16:11 -0700 Subject: [PATCH 24/29] style: Format cost report for better readability --- aider/coders/base_coder.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index b924647b4..b6c6a8d90 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -1408,7 +1408,8 @@ class Coder: return f"{value:.{max(2, 2 - int(math.log10(magnitude)))}f}" cost_report = ( - f" Cost: ${format_cost(self.message_cost)} message, ${format_cost(self.total_cost)} session." + f" Cost: ${format_cost(self.message_cost)} message," + f" ${format_cost(self.total_cost)} session." ) self.usage_report = tokens_report + cost_report else: From 89f6af94b9bc0bbba1f252694cd0e7b0d1d1e901 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 13 Aug 2024 06:18:14 -0700 Subject: [PATCH 25/29] only show usage report when prefill repeats are done, clear message-cost --- aider/coders/base_coder.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index b6c6a8d90..2e551665b 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -1019,8 +1019,7 @@ class Coder: self.io.tool_output() - if self.usage_report: - self.io.tool_output(self.usage_report) + self.show_usage_report() if exhausted: self.show_exhausted_error() @@ -1277,7 +1276,6 @@ class Coder: self.io.ai_output(json.dumps(args, indent=4)) self.calculate_and_show_tokens_and_cost(messages, completion) - self.show_usage_report() def show_send_output(self, completion): if self.verbose: From 26305a975d3a6d577ec4c9e191a765d7c47e6a13 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 13 Aug 2024 06:25:10 -0700 Subject: [PATCH 26/29] copy --- HISTORY.md | 1 + aider/website/docs/llms/deepseek.md | 8 ++------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 855b0e616..7e7b9fdae 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -8,6 +8,7 @@ - New `--chat-mode ` switch to launch in ask/help/code modes. - New `/code ` command request a code edit while in `ask` mode. - Web scraper is more robust if page never idles. +- Improved token and cost reporting for infinite output. - Improvements and bug fixes for `/read` only files. - Bug fix to persist files added during `/ask`. - Bug fix for chat history size in `/tokens`. diff --git a/aider/website/docs/llms/deepseek.md b/aider/website/docs/llms/deepseek.md index df1e3b465..1c2bc33f3 100644 --- a/aider/website/docs/llms/deepseek.md +++ b/aider/website/docs/llms/deepseek.md @@ -6,7 +6,7 @@ nav_order: 500 # DeepSeek Aider can connect to the DeepSeek.com API. -The DeepSeek Coder V2 model gets the top score on aider's code editing benchmark. +The DeepSeek Coder V2 model has a top score on aider's code editing benchmark. ``` python -m pip install aider-chat @@ -15,10 +15,6 @@ export DEEPSEEK_API_KEY= # Mac/Linux setx DEEPSEEK_API_KEY # Windows, restart shell after setx # Use DeepSeek Coder V2 -aider --model deepseek/deepseek-coder +aider --deepseek ``` -See the [model warnings](warnings.html) -section for information on warnings which will occur -when working with models that aider is not familiar with. - From 935bc2d2a67b1a771c5f44828174d74d8632db17 Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 06:42:12 -0700 Subject: [PATCH 27/29] feat: Accumulate tokens sent and received in calculate_and_show_tokens_and_cost --- aider/coders/base_coder.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 2e551665b..722b32107 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -74,6 +74,8 @@ class Coder: partial_response_content = "" commit_before_message = [] message_cost = 0.0 + message_tokens_sent = 0 + message_tokens_received = 0 @classmethod def create( @@ -1387,7 +1389,10 @@ class Coder: prompt_tokens = self.main_model.token_count(messages) completion_tokens = self.main_model.token_count(self.partial_response_content) - tokens_report = f"Tokens: {prompt_tokens:,} sent, {completion_tokens:,} received." + self.message_tokens_sent += prompt_tokens + self.message_tokens_received += completion_tokens + + tokens_report = f"Tokens: {self.message_tokens_sent:,} sent, {self.message_tokens_received:,} received." if self.main_model.info.get("input_cost_per_token"): cost += prompt_tokens * self.main_model.info.get("input_cost_per_token") @@ -1417,6 +1422,8 @@ class Coder: if self.usage_report: self.io.tool_output(self.usage_report) self.message_cost = 0.0 + self.message_tokens_sent = 0 + self.message_tokens_received = 0 def get_multi_response_content(self, final=False): cur = self.multi_response_content or "" From b1486debf81811029f9374dc236cd885ffac0c7f Mon Sep 17 00:00:00 2001 From: "Paul Gauthier (aider)" Date: Tue, 13 Aug 2024 06:42:17 -0700 Subject: [PATCH 28/29] style: Format code with line breaks for better readability --- aider/coders/base_coder.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 722b32107..da386a197 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -1392,7 +1392,9 @@ class Coder: self.message_tokens_sent += prompt_tokens self.message_tokens_received += completion_tokens - tokens_report = f"Tokens: {self.message_tokens_sent:,} sent, {self.message_tokens_received:,} received." + tokens_report = ( + f"Tokens: {self.message_tokens_sent:,} sent, {self.message_tokens_received:,} received." + ) if self.main_model.info.get("input_cost_per_token"): cost += prompt_tokens * self.main_model.info.get("input_cost_per_token") From 60a832155d69b2f4787012a13f34cd68e5cf40f7 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 13 Aug 2024 07:07:11 -0700 Subject: [PATCH 29/29] copy --- aider/website/HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aider/website/HISTORY.md b/aider/website/HISTORY.md index 703ffda6d..8eba0623f 100644 --- a/aider/website/HISTORY.md +++ b/aider/website/HISTORY.md @@ -19,9 +19,11 @@ cog.out(text) ### main branch - Infinite output for DeepSeek Coder, Mistral models in addition to Anthropic's models. +- New `--deepseek` switch to use DeepSeek Coder. - New `--chat-mode ` switch to launch in ask/help/code modes. - New `/code ` command request a code edit while in `ask` mode. - Web scraper is more robust if page never idles. +- Improved token and cost reporting for infinite output. - Improvements and bug fixes for `/read` only files. - Bug fix to persist files added during `/ask`. - Bug fix for chat history size in `/tokens`.