Merge branch 'main' into json-coders

This commit is contained in:
Paul Gauthier 2024-08-14 10:50:23 -07:00
commit 5c24a06dc8
15 changed files with 902 additions and 259 deletions

View file

@ -1,6 +1,10 @@
# Release history
### Aider v0.50.1
- Bugfix for provider API exceptions.
### Aider v0.50.0
- Infinite output for DeepSeek Coder, Mistral models in addition to Anthropic's models.

View file

@ -1 +1 @@
__version__ = "0.50.1-dev"
__version__ = "0.50.2-dev"

View file

@ -1244,6 +1244,7 @@ class Coder:
self.io.log_llm_history("TO LLM", format_messages(messages))
completion = None
try:
hash_object, completion = send_completion(
model.name,
@ -1263,6 +1264,8 @@ class Coder:
except KeyboardInterrupt as kbi:
self.keyboard_interrupt()
raise kbi
except Exception as e:
self.io.tool_error(f"Error during API call: {str(e)}")
finally:
self.io.log_llm_history(
"LLM RESPONSE",

View file

@ -125,8 +125,8 @@ Every *SEARCH/REPLACE block* must use this format:
7. The end of the replace block: >>>>>>> REPLACE
8. The closing fence: {fence[1]}
Every *SEARCH* section must *EXACTLY MATCH* the existing source code, character for character, including all comments, docstrings, etc.
Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.
If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup.
*SEARCH/REPLACE* blocks will replace *all* matching occurrences.
Include enough lines to make the SEARCH blocks uniquely match the lines to change.

View file

@ -724,7 +724,7 @@ class Commands:
add = result.returncode != 0
else:
response = self.io.prompt_ask(
"Add the output to the chat?\n(y/n/instructions)", default=""
"Add the output to the chat?\n(Y/n/instructions)", default=""
).strip()
if response.lower() in ["yes", "y"]:

View file

@ -327,6 +327,17 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
parser = get_parser(default_config_files, git_root)
args, unknown = parser.parse_known_args(argv)
if args.verbose:
print("Config files search order, if no --config:")
for file in default_config_files:
exists = "(exists)" if Path(file).exists() else ""
print(f" - {file} {exists}")
default_config_files.reverse()
parser = get_parser(default_config_files, git_root)
args, unknown = parser.parse_known_args(argv)
# Load the .env file specified in the arguments
loaded_dotenvs = load_dotenv_files(git_root, args.env_file)

View file

@ -16,6 +16,10 @@ cog.out(text)
# Release history
### Aider v0.50.1
- Bugfix for provider API exceptions.
### Aider v0.50.0
- Infinite output for DeepSeek Coder, Mistral models in addition to Anthropic's models.

View file

@ -577,6 +577,7 @@
pass_rate_2: 77.4
percent_cases_well_formed: 99.2
error_outputs: 23
released: 2024-06-20
num_malformed_responses: 4
num_with_malformed_responses: 1
user_asks: 2
@ -603,6 +604,7 @@
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 0
released: 2024-03-13
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
@ -644,6 +646,7 @@
commit_hash: d31eef3-dirty
pass_rate_1: 40.6
pass_rate_2: 55.6
released: 2024-07-18
percent_cases_well_formed: 100.0
error_outputs: 1
num_malformed_responses: 0
@ -668,6 +671,7 @@
pass_rate_1: 60.9
pass_rate_2: 69.9
percent_cases_well_formed: 97.7
released: 2024-06-28
error_outputs: 58
num_malformed_responses: 13
num_with_malformed_responses: 3
@ -690,6 +694,7 @@
commit_hash: f7ce78b-dirty
pass_rate_1: 46.6
pass_rate_2: 63.9
released: 2024-07-23
percent_cases_well_formed: 92.5
error_outputs: 84
num_malformed_responses: 19
@ -716,6 +721,7 @@
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
released: 2024-07-23
num_with_malformed_responses: 0
user_asks: 0
lazy_comments: 0
@ -738,6 +744,7 @@
pass_rate_2: 72.9
percent_cases_well_formed: 97.7
error_outputs: 13
released: 2024-07-24
num_malformed_responses: 3
num_with_malformed_responses: 3
user_asks: 1
@ -763,6 +770,7 @@
error_outputs: 3
num_malformed_responses: 0
num_with_malformed_responses: 0
released: 2024-07-24
user_asks: 3
lazy_comments: 0
syntax_errors: 1
@ -785,6 +793,7 @@
percent_cases_well_formed: 100.0
error_outputs: 27
num_malformed_responses: 0
released: 2024-07-23
num_with_malformed_responses: 0
user_asks: 23
lazy_comments: 8
@ -810,6 +819,7 @@
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 0
released: 2024-07-23
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
@ -838,9 +848,34 @@
indentation_errors: 2
exhausted_context_windows: 0
test_timeouts: 5
released: 2024-08-06
command: aider --model openai/gpt-4o-2024-08-06
date: 2024-08-06
versions: 0.48.1-dev
seconds_per_case: 6.5
total_cost: 0.0000
- dirname: 2024-08-14-13-07-12--chatgpt-4o-latest-diff
test_cases: 133
model: chatgpt-4o-latest
edit_format: diff
commit_hash: b1c3769
pass_rate_1: 53.4
pass_rate_2: 69.2
percent_cases_well_formed: 97.7
error_outputs: 27
num_malformed_responses: 5
num_with_malformed_responses: 3
user_asks: 7
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model openai/chatgpt-4o-latest
date: 2024-08-14
released: 2024-08-08
versions: 0.50.2-dev
seconds_per_case: 26.3
total_cost: 3.6113

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Before After
Before After

View file

@ -28,7 +28,7 @@ Using a `.aider.conf.yml` file:
dark-mode: true
```
By setting an environgment variable:
By setting an environment variable:
```
export AIDER_DARK_MODE=true

View file

@ -321,6 +321,6 @@ mod_dates = [get_last_modified_date(file) for file in files]
latest_mod_date = max(mod_dates)
cog.out(f"{latest_mod_date.strftime('%B %d, %Y.')}")
]]]-->
August 10, 2024.
August 14, 2024.
<!--[[[end]]]-->
</p>

View file

@ -23,7 +23,7 @@ You can add images to the chat just like you would
add any other file:
- Use `/add <image-filename>` from within the chat
- Use `/add-clipboard-image` to paste an image from your clipboard into the chat.
- Use `/clipboard` to paste an image from your clipboard into the chat.
- Launch aider with image filenames on the command line: `aider <image-filename>` along with any other command line arguments you need.
## Web pages

View file

@ -28,8 +28,6 @@ from aider.coders import Coder
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
load_dotenv()
BENCHMARK_DNAME = Path(os.environ.get("AIDER_BENCHMARK_DIR", "tmp.benchmarks"))
EXERCISES_DIR_DEFAULT = "exercism-python"
@ -39,6 +37,8 @@ app = typer.Typer(add_completion=False, pretty_exceptions_enable=False)
NUM_TESTS = (89, 133)
load_dotenv(override=True)
def show_stats(dirnames, graphs):
raw_rows = []
@ -378,7 +378,7 @@ def summarize_results(dirname):
pass_rate = 100 * passed_tests[i] / res.completed_tests
percents[i] = pass_rate
# console.print(f"{pass_rate:.1f}% correct after try {i+1}")
setattr(res, f"pass_rate_{i+1}", f"{pass_rate:.1f}")
setattr(res, f"pass_rate_{i + 1}", f"{pass_rate:.1f}")
print(f"- dirname: {dirname.name}")
style = None if res.completed_tests in NUM_TESTS else "red"
@ -393,10 +393,10 @@ def summarize_results(dirname):
console.print(f" {key}: {val}", style=style)
for i in range(tries):
print(f" pass_rate_{i+1}: {percents[i]:.1f}")
print(f" pass_rate_{i + 1}: {percents[i]:.1f}")
pct_well_formed = 1.0 - res.num_with_malformed_responses / res.completed_tests
print(f" percent_cases_well_formed: {pct_well_formed*100:.1f}")
print(f" percent_cases_well_formed: {pct_well_formed * 100:.1f}")
show("error_outputs")
show("num_malformed_responses")
@ -564,7 +564,6 @@ def run_test_real(
fnames=fnames,
use_git=False,
stream=False,
pretty=False,
verbose=verbose,
)
coder.max_apply_update_errors = max_apply_update_errors
@ -591,7 +590,7 @@ def run_test_real(
coder.apply_updates()
else:
response = coder.run(with_message=instructions)
response = coder.run(with_message=instructions, preproc=False)
dur += time.time() - start
if not no_aider:

View file

@ -3,6 +3,8 @@ import yaml
from imgcat import imgcat
from matplotlib import rc
from aider.dump import dump # noqa: 401
def plot_over_time(yaml_file):
with open(yaml_file, "r") as file:
@ -12,49 +14,97 @@ def plot_over_time(yaml_file):
pass_rates = []
models = []
print("Debug: Raw data from YAML file:")
print(data)
for entry in data:
if "released" in entry and "pass_rate_2" in entry:
dates.append(entry["released"])
pass_rates.append(entry["pass_rate_2"])
models.append(entry["model"].split("(")[0].strip())
print("Debug: Processed data:")
print("Dates:", dates)
print("Pass rates:", pass_rates)
print("Models:", models)
if not dates or not pass_rates:
print(
"Error: No data to plot. Check if the YAML file is empty or if the data is in the"
" expected format."
)
return
plt.rcParams["hatch.linewidth"] = 0.5
plt.rcParams["hatch.color"] = "#444444"
rc("font", **{"family": "sans-serif", "sans-serif": ["Helvetica"], "size": 10})
plt.rcParams["text.color"] = "#444444"
fig, ax = plt.subplots(figsize=(10, 5))
fig, ax = plt.subplots(figsize=(12, 6)) # Increase figure size for better visibility
print("Debug: Figure created. Plotting data...")
ax.grid(axis="y", zorder=0, lw=0.2)
for spine in ax.spines.values():
spine.set_edgecolor("#DDDDDD")
spine.set_linewidth(0.5)
colors = [
"red" if "gpt-4" in model else "green" if "gpt-3.5" in model else "blue" for model in models
(
"purple"
if "-4o" in model and "gpt-4o-mini" not in model
else "red" if "gpt-4" in model else "green" if "gpt-3.5" in model else "lightblue"
)
for model in models
]
# Separate data points by color
purple_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "purple"]
red_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "red"]
green_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "green"]
# Plot lines for purple, red, and green points
if purple_points:
purple_dates, purple_rates = zip(*sorted(purple_points))
ax.plot(purple_dates, purple_rates, c="purple", alpha=0.5, linewidth=1)
if red_points:
red_dates, red_rates = zip(*sorted(red_points))
ax.plot(red_dates, red_rates, c="red", alpha=0.5, linewidth=1)
if green_points:
green_dates, green_rates = zip(*sorted(green_points))
ax.plot(green_dates, green_rates, c="green", alpha=0.5, linewidth=1)
# Plot all points
ax.scatter(dates, pass_rates, c=colors, alpha=0.5, s=120)
for i, model in enumerate(models):
ax.annotate(
model,
(dates[i], pass_rates[i]),
fontsize=12,
fontsize=8,
alpha=0.75,
xytext=(5, 5),
textcoords="offset points",
)
ax.set_xlabel("Model release date", fontsize=18, color="#555")
ax.set_ylabel("Aider code editing benchmark,\npercent completed correctly", fontsize=18, color="#555")
ax.set_ylabel(
"Aider code editing benchmark,\npercent completed correctly", fontsize=18, color="#555"
)
ax.set_title("LLM code editing skill by model release date", fontsize=20)
ax.set_ylim(0, 30)
plt.xticks(fontsize=14)
ax.set_ylim(0, 100) # Adjust y-axis limit to accommodate higher values
plt.xticks(fontsize=14, rotation=45, ha="right") # Rotate x-axis labels for better readability
plt.tight_layout(pad=3.0)
print("Debug: Saving figures...")
plt.savefig("tmp_over_time.png")
plt.savefig("tmp_over_time.svg")
print("Debug: Displaying figure with imgcat...")
imgcat(fig)
print("Debug: Figure generation complete.")
# Example usage
plot_over_time("_data/edit_leaderboard.yml")
plot_over_time("aider/website/_data/edit_leaderboard.yml")

View file

@ -226,9 +226,10 @@ 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()
@ -373,6 +374,67 @@ class TestMain(TestCase):
self.assertRegex(relevant_output, r"AIDER_DARK_MODE:\s+on")
self.assertRegex(relevant_output, r"dark_mode:\s+True")
def test_yaml_config_file_loading(self):
with GitTemporaryDirectory() as git_dir:
git_dir = Path(git_dir)
# Create fake home directory
fake_home = git_dir / "fake_home"
fake_home.mkdir()
os.environ["HOME"] = str(fake_home)
# Create subdirectory as current working directory
cwd = git_dir / "subdir"
cwd.mkdir()
os.chdir(cwd)
# Create .aider.conf.yml files in different locations
home_config = fake_home / ".aider.conf.yml"
git_config = git_dir / ".aider.conf.yml"
cwd_config = cwd / ".aider.conf.yml"
named_config = git_dir / "named.aider.conf.yml"
cwd_config.write_text("model: gpt-4-32k\nmap-tokens: 4096\n")
git_config.write_text("model: gpt-4\nmap-tokens: 2048\n")
home_config.write_text("model: gpt-3.5-turbo\nmap-tokens: 1024\n")
named_config.write_text("model: gpt-4-1106-preview\nmap-tokens: 8192\n")
with (
patch("pathlib.Path.home", return_value=fake_home),
patch("aider.coders.Coder.create") as MockCoder,
):
# Test loading from specified config file
main(
["--yes", "--exit", "--config", str(named_config)],
input=DummyInput(),
output=DummyOutput(),
)
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["main_model"].name, "gpt-4-1106-preview")
self.assertEqual(kwargs["map_tokens"], 8192)
# Test loading from current working directory
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
_, kwargs = MockCoder.call_args
print("kwargs:", kwargs) # Add this line for debugging
self.assertIn("main_model", kwargs, "main_model key not found in kwargs")
self.assertEqual(kwargs["main_model"].name, "gpt-4-32k")
self.assertEqual(kwargs["map_tokens"], 4096)
# Test loading from git root
cwd_config.unlink()
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["main_model"].name, "gpt-4")
self.assertEqual(kwargs["map_tokens"], 2048)
# Test loading from home directory
git_config.unlink()
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["main_model"].name, "gpt-3.5-turbo")
self.assertEqual(kwargs["map_tokens"], 1024)
def test_map_tokens_option(self):
with GitTemporaryDirectory():
with patch("aider.coders.base_coder.RepoMap") as MockRepoMap: