From 7b14d77e9efdabbf59a4c0fdeb5af2e55c69ba26 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 30 Apr 2024 14:40:15 -0700 Subject: [PATCH 1/5] Don't retry on gemini RECITATION error --- aider/sendchat.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/aider/sendchat.py b/aider/sendchat.py index 2cbbfd2d9..8693cf5df 100644 --- a/aider/sendchat.py +++ b/aider/sendchat.py @@ -18,6 +18,12 @@ CACHE = None litellm.suppress_debug_info = True +def giveup_on_recitiation(ex): + if not isinstance(ex, litellm.exceptions.BadRequestError): + return + return "RECITATION" in str(ex) + + @backoff.on_exception( backoff.expo, ( @@ -27,6 +33,7 @@ litellm.suppress_debug_info = True httpx.ConnectError, litellm.exceptions.BadRequestError, ), + giveup=giveup_on_recitiation, max_tries=10, on_backoff=lambda details: print( f"{details.get('exception','Exception')}\nRetry in {details['wait']:.1f} seconds." @@ -50,6 +57,8 @@ def send_with_retries(model_name, messages, functions, stream): if not stream and CACHE is not None and key in CACHE: return hash_object, CACHE[key] + # del kwargs['stream'] + res = litellm.completion(**kwargs) if not stream and CACHE is not None: From 3469e04eb882221fe60f16bf7cab0f0b0862a494 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 30 Apr 2024 15:34:01 -0700 Subject: [PATCH 2/5] Do exp backoff for litellm.exceptions.ServiceUnavailableError #580 --- aider/sendchat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aider/sendchat.py b/aider/sendchat.py index 8693cf5df..fd6ade8a4 100644 --- a/aider/sendchat.py +++ b/aider/sendchat.py @@ -32,6 +32,7 @@ def giveup_on_recitiation(ex): APIConnectionError, httpx.ConnectError, litellm.exceptions.BadRequestError, + litellm.exceptions.ServiceUnavailableError, ), giveup=giveup_on_recitiation, max_tries=10, From a3a4d87a0ce4aa72c9e1cc33ac9ab353fbc1b83d Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 30 Apr 2024 15:40:13 -0700 Subject: [PATCH 3/5] treat litellm.exceptions.BadRequestError as a 400 error and do not retry --- aider/coders/base_coder.py | 6 ++++++ aider/sendchat.py | 8 -------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 617ac1642..007f03347 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -11,6 +11,7 @@ from json.decoder import JSONDecodeError from pathlib import Path import git +import litellm import openai from jsonschema import Draft7Validator from rich.console import Console, Text @@ -28,6 +29,8 @@ from aider.utils import is_image_file from ..dump import dump # noqa: F401 +litellm.suppress_debug_info = True + class MissingAPIKeyError(ValueError): pass @@ -572,6 +575,9 @@ class Coder: interrupted = True except ExhaustedContextWindow: exhausted = True + except litellm.exceptions.BadRequestError as err: + self.io.tool_error(f"BadRequestError: {err}") + return except openai.BadRequestError as err: if "maximum context length" in str(err): exhausted = True diff --git a/aider/sendchat.py b/aider/sendchat.py index fd6ade8a4..6c613d072 100644 --- a/aider/sendchat.py +++ b/aider/sendchat.py @@ -18,12 +18,6 @@ CACHE = None litellm.suppress_debug_info = True -def giveup_on_recitiation(ex): - if not isinstance(ex, litellm.exceptions.BadRequestError): - return - return "RECITATION" in str(ex) - - @backoff.on_exception( backoff.expo, ( @@ -31,10 +25,8 @@ def giveup_on_recitiation(ex): RateLimitError, APIConnectionError, httpx.ConnectError, - litellm.exceptions.BadRequestError, litellm.exceptions.ServiceUnavailableError, ), - giveup=giveup_on_recitiation, max_tries=10, on_backoff=lambda details: print( f"{details.get('exception','Exception')}\nRetry in {details['wait']:.1f} seconds." From e610e5bd0a5854c0a93337a57ab43d095a3dba49 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 30 Apr 2024 15:50:24 -0700 Subject: [PATCH 4/5] Handle existing dirnames with [globby] chars, with test #195 --- aider/commands.py | 10 ++++++---- tests/test_commands.py | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/aider/commands.py b/aider/commands.py index 40581b0f9..3b6f359d5 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -349,10 +349,12 @@ class Commands: self.io.tool_error(f"Skipping {fname} that matches aiderignore spec.") continue - if fname.exists() and fname.is_file(): - all_matched_files.add(str(fname)) - continue - # an existing dir will fall through and get recursed by glob + if fname.exists(): + if fname.is_file(): + all_matched_files.add(str(fname)) + continue + # an existing dir, escape any special chars so they won't be globs + word = re.sub(r"([\*\?\[\]])", r"[\1]", word) matched_files = self.glob_filtered_to_repo(word) if matched_files: diff --git a/tests/test_commands.py b/tests/test_commands.py index 1751a359d..8cc67b6d8 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -386,6 +386,23 @@ class TestCommands(TestCase): self.assertIn(str(fname.resolve()), coder.abs_fnames) + def test_cmd_add_dirname_with_special_chars(self): + with ChdirTemporaryDirectory(): + io = InputOutput(pretty=False, yes=False) + from aider.coders import Coder + + coder = Coder.create(self.GPT35, None, io) + commands = Commands(io, coder) + + dname = Path("with[brackets]") + dname.mkdir() + fname = dname / "filename.txt" + fname.touch() + + commands.cmd_add(str(dname)) + + self.assertIn(str(fname.resolve()), coder.abs_fnames) + def test_cmd_add_abs_filename(self): with ChdirTemporaryDirectory(): io = InputOutput(pretty=False, yes=False) From 22d90d70c63620d88f83e1ad5302ea735c3ebcd0 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 30 Apr 2024 20:24:53 -0700 Subject: [PATCH 5/5] prompt copy --- aider/coders/editblock_prompts.py | 4 ++-- aider/coders/udiff_prompts.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aider/coders/editblock_prompts.py b/aider/coders/editblock_prompts.py index 896670d1f..3bb882287 100644 --- a/aider/coders/editblock_prompts.py +++ b/aider/coders/editblock_prompts.py @@ -62,7 +62,7 @@ if __name__ == '__main__': ## ASSISTANT: -Do make this change we need to modify `mathweb/flask/app.py` to: +To make this change we need to modify `mathweb/flask/app.py` to: 1. Import the math package. 2. Remove the existing factorial() function. @@ -125,7 +125,7 @@ if __name__ == '__main__': ## ASSISTANT: -Do make this change we need to modify `main.py` and make a new file `hello.py`: +To make this change we need to modify `main.py` and make a new file `hello.py`: 1. Make a new hello.py file with hello() in it. 2. Remove hello() from main.py and replace it with an import. diff --git a/aider/coders/udiff_prompts.py b/aider/coders/udiff_prompts.py index 14d1a73ac..9ca7bc1db 100644 --- a/aider/coders/udiff_prompts.py +++ b/aider/coders/udiff_prompts.py @@ -109,7 +109,7 @@ You always COMPLETELY IMPLEMENT the needed code! files_no_full_files = "I am not sharing any *read-write* files yet." - repo_content_prefix = """Below here are summaries of other files present in this git repository. + repo_content_prefix = """Below here are summaries of some files present in this git repository. Do not propose changes to these files, they are *read-only*. To make a file *read-write*, ask the user to *add it to the chat*. """