mirror of
https://github.com/Aider-AI/aider.git
synced 2025-06-01 10:14:59 +00:00
Merge branch 'main' into watch
This commit is contained in:
commit
139d89d817
78 changed files with 5012 additions and 2667 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -13,3 +13,4 @@ _site
|
|||
aider/__version__.py
|
||||
.venv/
|
||||
.#*
|
||||
.gitattributes
|
||||
|
|
|
@ -187,8 +187,8 @@ pytest
|
|||
You can also run specific test files or test cases by providing the file path or test name:
|
||||
|
||||
```
|
||||
pytest aider/tests/test_coder.py
|
||||
pytest aider/tests/test_coder.py::TestCoder::test_specific_case
|
||||
pytest tests/basic/test_coder.py
|
||||
pytest tests/basic/test_coder.py::TestCoder::test_specific_case
|
||||
```
|
||||
|
||||
#### Continuous Integration
|
||||
|
|
50
HISTORY.md
50
HISTORY.md
|
@ -1,6 +1,54 @@
|
|||
|
||||
# Release history
|
||||
|
||||
### Aider v0.65.0
|
||||
|
||||
- Added `--alias` config to define [custom model aliases](https://aider.chat/docs/config/model-aliases.html).
|
||||
- Added `--[no-]detect-urls` flag to disable detecting and offering to scrape URLs found in the chat.
|
||||
- Ollama models now default to an 8k context window.
|
||||
- Added [RepoMap support for Dart language](https://aider.chat/docs/languages.html) by @malkoG.
|
||||
- Ask 2.5% of users if they want to opt-in to [analytics](https://aider.chat/docs/more/analytics.html).
|
||||
- Skip suggesting files that share names with files already in chat.
|
||||
- `/editor` returns and prefill the file content into the prompt, so you can use `/editor` to compose messages that start with `/commands`, etc.
|
||||
- Enhanced error handling for analytics.
|
||||
- Improved handling of UnknownEditFormat exceptions with helpful documentation links.
|
||||
- Bumped dependencies to pick up grep-ast 0.4.0 for Dart language support.
|
||||
- Aider wrote 81% of the code in this release.
|
||||
|
||||
### Aider v0.64.1
|
||||
|
||||
- Disable streaming for o1 on OpenRouter.
|
||||
|
||||
### Aider v0.64.0
|
||||
|
||||
- Added [`/editor` command](https://aider.chat/docs/usage/commands.html) to open system editor for writing prompts, by @thehunmonkgroup.
|
||||
- Full support for `gpt-4o-2024-11-20`.
|
||||
- Stream o1 models by default.
|
||||
- `/run` and suggested shell commands are less mysterious and now confirm that they "Added XX lines of output to the chat."
|
||||
- Ask 1% of users if they want to opt-in to [analytics](https://aider.chat/docs/more/analytics.html).
|
||||
- Added support for [optional multiline input tags](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) with matching closing tags.
|
||||
- Improved [model settings configuration](https://aider.chat/docs/config/adv-model-settings.html#global-extra-params) with support for global `extra_params` for `litellm.completion()`.
|
||||
- Architect mode now asks to add files suggested by the LLM.
|
||||
- Fixed bug in fuzzy model name matching.
|
||||
- Added Timeout exception to handle API provider timeouts.
|
||||
- Added `--show-release-notes` to control release notes display on first run of new version.
|
||||
- Save empty dict to cache file on model metadata download failure, to delay retry.
|
||||
- Improved error handling and code formatting.
|
||||
- Aider wrote 74% of the code in this release.
|
||||
|
||||
### Aider v0.63.2
|
||||
|
||||
- Fixed bug in fuzzy model name matching when litellm provider info is missing.
|
||||
- Modified model metadata file loading to allow override of resource file.
|
||||
- Allow recursive loading of dirs using `--read`.
|
||||
- Updated dependency versions to pick up litellm fix for ollama models.
|
||||
- Added exponential backoff retry when writing files to handle editor file locks.
|
||||
- Updated Qwen 2.5 Coder 32B model configuration.
|
||||
|
||||
### Aider v0.63.1
|
||||
|
||||
- Fixed bug in git ignored file handling.
|
||||
- Improved error handling for git operations.
|
||||
|
||||
### Aider v0.63.0
|
||||
|
||||
- Support for Qwen 2.5 Coder 32B.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
try:
|
||||
from aider.__version__ import __version__
|
||||
except Exception:
|
||||
__version__ = "0.63.1.dev"
|
||||
__version__ = "0.65.1.dev"
|
||||
|
||||
__all__ = [__version__]
|
||||
|
|
|
@ -5,7 +5,7 @@ import time
|
|||
import uuid
|
||||
from pathlib import Path
|
||||
|
||||
from mixpanel import Mixpanel
|
||||
from mixpanel import Mixpanel, MixpanelException
|
||||
from posthog import Posthog
|
||||
|
||||
from aider import __version__
|
||||
|
@ -62,8 +62,47 @@ class Analytics:
|
|||
self.permanently_disable = True
|
||||
self.save_data()
|
||||
|
||||
def need_to_ask(self):
|
||||
return not self.asked_opt_in and not self.permanently_disable
|
||||
def need_to_ask(self, args_analytics):
|
||||
if args_analytics is False:
|
||||
return False
|
||||
|
||||
could_ask = not self.asked_opt_in and not self.permanently_disable
|
||||
if not could_ask:
|
||||
return False
|
||||
|
||||
if args_analytics is True:
|
||||
return True
|
||||
|
||||
assert args_analytics is None, args_analytics
|
||||
|
||||
if not self.user_id:
|
||||
return False
|
||||
|
||||
PERCENT = 2.5
|
||||
return self.is_uuid_in_percentage(self.user_id, PERCENT)
|
||||
|
||||
def is_uuid_in_percentage(self, uuid_str, percent):
|
||||
"""Check if a UUID string falls within the first X percent of the UUID space.
|
||||
|
||||
Args:
|
||||
uuid_str: UUID string to test
|
||||
percent: Percentage threshold (0-100)
|
||||
|
||||
Returns:
|
||||
bool: True if UUID falls within the first X percent
|
||||
"""
|
||||
if not (0 <= percent <= 100):
|
||||
raise ValueError("Percentage must be between 0 and 100")
|
||||
|
||||
if not uuid_str:
|
||||
return False
|
||||
|
||||
# Convert percentage to hex threshold (1% = "04...", 10% = "1a...", etc)
|
||||
# Using first 6 hex digits
|
||||
if percent == 0:
|
||||
return False
|
||||
threshold = format(int(0xFFFFFF * percent / 100), "06x")
|
||||
return uuid_str[:6] <= threshold
|
||||
|
||||
def get_data_file_path(self):
|
||||
data_file = Path.home() / ".aider" / "analytics.json"
|
||||
|
@ -120,7 +159,7 @@ class Analytics:
|
|||
return None
|
||||
|
||||
def event(self, event_name, main_model=None, **kwargs):
|
||||
if not (self.mp or self.ph) and not self.logfile:
|
||||
if not self.mp and not self.ph and not self.logfile:
|
||||
return
|
||||
|
||||
properties = {}
|
||||
|
@ -143,7 +182,10 @@ class Analytics:
|
|||
properties["aider_version"] = __version__
|
||||
|
||||
if self.mp:
|
||||
try:
|
||||
self.mp.track(self.user_id, event_name, dict(properties))
|
||||
except MixpanelException:
|
||||
self.mp = None # Disable mixpanel on connection errors
|
||||
|
||||
if self.ph:
|
||||
self.ph.capture(self.user_id, event_name, dict(properties))
|
||||
|
|
|
@ -193,6 +193,12 @@ def get_parser(default_config_files, git_root):
|
|||
default=".aider.model.metadata.json",
|
||||
help="Specify a file with context window and costs for unknown models",
|
||||
)
|
||||
group.add_argument(
|
||||
"--alias",
|
||||
action="append",
|
||||
metavar="ALIAS:MODEL",
|
||||
help="Add a model alias (can be used multiple times)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--verify-ssl",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
|
@ -562,8 +568,8 @@ def get_parser(default_config_files, git_root):
|
|||
group.add_argument(
|
||||
"--analytics",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=False,
|
||||
help="Enable/disable analytics for one session (default: False)",
|
||||
default=None,
|
||||
help="Enable/disable analytics for current session (default: random)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--analytics-log",
|
||||
|
@ -620,6 +626,12 @@ def get_parser(default_config_files, git_root):
|
|||
help="Check for new aider versions on launch",
|
||||
default=True,
|
||||
)
|
||||
group.add_argument(
|
||||
"--show-release-notes",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Show release notes on first run of new version (default: None, ask user)",
|
||||
default=None,
|
||||
)
|
||||
group.add_argument(
|
||||
"--install-main-branch",
|
||||
action="store_true",
|
||||
|
@ -732,6 +744,16 @@ def get_parser(default_config_files, git_root):
|
|||
default=True,
|
||||
help="Enable/disable fancy input with history and completion (default: True)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--detect-urls",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=True,
|
||||
help="Enable/disable detection and offering to add URLs to chat (default: True)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--editor",
|
||||
help="Specify which editor to use for the /editor command",
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Voice Settings")
|
||||
|
|
|
@ -37,6 +37,15 @@ from ..dump import dump # noqa: F401
|
|||
from .chat_chunks import ChatChunks
|
||||
|
||||
|
||||
class UnknownEditFormat(ValueError):
|
||||
def __init__(self, edit_format, valid_formats):
|
||||
self.edit_format = edit_format
|
||||
self.valid_formats = valid_formats
|
||||
super().__init__(
|
||||
f"Unknown edit format {edit_format}. Valid formats are: {', '.join(valid_formats)}"
|
||||
)
|
||||
|
||||
|
||||
class MissingAPIKeyError(ValueError):
|
||||
pass
|
||||
|
||||
|
@ -91,6 +100,7 @@ class Coder:
|
|||
cache_warming_thread = None
|
||||
num_cache_warming_pings = 0
|
||||
suggest_shell_commands = True
|
||||
detect_urls = True
|
||||
ignore_mentions = None
|
||||
chat_language = None
|
||||
|
||||
|
@ -156,7 +166,12 @@ class Coder:
|
|||
res.original_kwargs = dict(kwargs)
|
||||
return res
|
||||
|
||||
raise ValueError(f"Unknown edit format {edit_format}")
|
||||
valid_formats = [
|
||||
str(c.edit_format)
|
||||
for c in coders.__all__
|
||||
if hasattr(c, "edit_format") and c.edit_format is not None
|
||||
]
|
||||
raise UnknownEditFormat(edit_format, valid_formats)
|
||||
|
||||
def clone(self, **kwargs):
|
||||
new_coder = Coder.create(from_coder=self, **kwargs)
|
||||
|
@ -267,6 +282,7 @@ class Coder:
|
|||
num_cache_warming_pings=0,
|
||||
suggest_shell_commands=True,
|
||||
chat_language=None,
|
||||
detect_urls=True,
|
||||
):
|
||||
# Fill in a dummy Analytics if needed, but it is never .enable()'d
|
||||
self.analytics = analytics if analytics is not None else Analytics()
|
||||
|
@ -280,6 +296,7 @@ class Coder:
|
|||
self.ignore_mentions = set()
|
||||
|
||||
self.suggest_shell_commands = suggest_shell_commands
|
||||
self.detect_urls = detect_urls
|
||||
|
||||
self.num_cache_warming_pings = num_cache_warming_pings
|
||||
|
||||
|
@ -812,6 +829,9 @@ class Coder:
|
|||
|
||||
def check_for_urls(self, inp: str) -> List[str]:
|
||||
"""Check input for URLs and offer to add them to the chat."""
|
||||
if not self.detect_urls:
|
||||
return []
|
||||
|
||||
url_pattern = re.compile(r"(https?://[^\s/$.?#].[^\s]*[^\s,.])")
|
||||
urls = list(set(url_pattern.findall(inp))) # Use set to remove duplicates
|
||||
added_urls = []
|
||||
|
@ -962,7 +982,7 @@ class Coder:
|
|||
if self.chat_language:
|
||||
language = self.chat_language
|
||||
else:
|
||||
language = "in the same language they are using"
|
||||
language = "the same language they are using"
|
||||
|
||||
prompt = prompt.format(
|
||||
fence=self.fence,
|
||||
|
@ -1059,7 +1079,7 @@ class Coder:
|
|||
max_input_tokens = self.main_model.info.get("max_input_tokens") or 0
|
||||
# Add the reminder prompt if we still have room to include it.
|
||||
if (
|
||||
max_input_tokens is None
|
||||
not max_input_tokens
|
||||
or total_tokens < max_input_tokens
|
||||
and self.gpt_prompts.system_reminder
|
||||
):
|
||||
|
@ -1405,9 +1425,18 @@ class Coder:
|
|||
|
||||
addable_rel_fnames = self.get_addable_relative_files()
|
||||
|
||||
# Get basenames of files already in chat or read-only
|
||||
existing_basenames = {os.path.basename(f) for f in self.get_inchat_relative_files()} | {
|
||||
os.path.basename(self.get_rel_fname(f)) for f in self.abs_read_only_fnames
|
||||
}
|
||||
|
||||
mentioned_rel_fnames = set()
|
||||
fname_to_rel_fnames = {}
|
||||
for rel_fname in addable_rel_fnames:
|
||||
# Skip files that share a basename with files already in chat
|
||||
if os.path.basename(rel_fname) in existing_basenames:
|
||||
continue
|
||||
|
||||
normalized_rel_fname = rel_fname.replace("\\", "/")
|
||||
normalized_words = set(word.replace("\\", "/") for word in words)
|
||||
if normalized_rel_fname in normalized_words:
|
||||
|
@ -2061,9 +2090,10 @@ class Coder:
|
|||
if output:
|
||||
accumulated_output += f"Output from {command}\n{output}\n"
|
||||
|
||||
if accumulated_output.strip() and not self.io.confirm_ask(
|
||||
if accumulated_output.strip() and self.io.confirm_ask(
|
||||
"Add command output to the chat?", allow_never=True
|
||||
):
|
||||
accumulated_output = ""
|
||||
|
||||
num_lines = len(accumulated_output.strip().splitlines())
|
||||
line_plural = "line" if num_lines == 1 else "lines"
|
||||
self.io.tool_output(f"Added {num_lines} {line_plural} of output to the chat.")
|
||||
return accumulated_output
|
||||
|
|
|
@ -14,6 +14,7 @@ from prompt_toolkit.completion import Completion, PathCompleter
|
|||
from prompt_toolkit.document import Document
|
||||
|
||||
from aider import models, prompts, voice
|
||||
from aider.editor import pipe_editor
|
||||
from aider.format_settings import format_settings
|
||||
from aider.help import Help, install_help_extra
|
||||
from aider.llm import litellm
|
||||
|
@ -45,7 +46,15 @@ class Commands:
|
|||
)
|
||||
|
||||
def __init__(
|
||||
self, io, coder, voice_language=None, verify_ssl=True, args=None, parser=None, verbose=False
|
||||
self,
|
||||
io,
|
||||
coder,
|
||||
voice_language=None,
|
||||
verify_ssl=True,
|
||||
args=None,
|
||||
parser=None,
|
||||
verbose=False,
|
||||
editor=None,
|
||||
):
|
||||
self.io = io
|
||||
self.coder = coder
|
||||
|
@ -60,6 +69,7 @@ class Commands:
|
|||
self.voice_language = voice_language
|
||||
|
||||
self.help = None
|
||||
self.editor = editor
|
||||
|
||||
def cmd_model(self, args):
|
||||
"Switch to a new LLM"
|
||||
|
@ -868,7 +878,6 @@ class Commands:
|
|||
exit_status, combined_output = run_cmd(
|
||||
args, verbose=self.verbose, error_print=self.io.tool_error
|
||||
)
|
||||
instructions = None
|
||||
|
||||
if combined_output is None:
|
||||
return
|
||||
|
@ -876,36 +885,22 @@ class Commands:
|
|||
if add_on_nonzero_exit:
|
||||
add = exit_status != 0
|
||||
else:
|
||||
self.io.tool_output()
|
||||
response = self.io.prompt_ask(
|
||||
"Add the output to the chat?\n(Y)es/(n)o/message with instructions:",
|
||||
).strip()
|
||||
self.io.tool_output()
|
||||
|
||||
if response.lower() in ["yes", "y"]:
|
||||
add = True
|
||||
elif response.lower() in ["no", "n"]:
|
||||
add = False
|
||||
else:
|
||||
add = True
|
||||
instructions = response
|
||||
if response.strip():
|
||||
self.io.user_input(response, log_only=True)
|
||||
self.io.add_to_input_history(response)
|
||||
add = self.io.confirm_ask("Add command output to the chat?")
|
||||
|
||||
if add:
|
||||
for line in combined_output.splitlines():
|
||||
self.io.tool_output(line, log_only=True)
|
||||
num_lines = len(combined_output.strip().splitlines())
|
||||
line_plural = "line" if num_lines == 1 else "lines"
|
||||
self.io.tool_output(f"Added {num_lines} {line_plural} of output to the chat.")
|
||||
|
||||
msg = prompts.run_output.format(
|
||||
command=args,
|
||||
output=combined_output,
|
||||
)
|
||||
|
||||
if instructions:
|
||||
msg = instructions + "\n\n" + msg
|
||||
|
||||
return msg
|
||||
self.coder.cur_messages += [
|
||||
dict(role="user", content=msg),
|
||||
dict(role="assistant", content="Ok."),
|
||||
]
|
||||
|
||||
def cmd_exit(self, args):
|
||||
"Exit the application"
|
||||
|
@ -1366,6 +1361,13 @@ class Commands:
|
|||
|
||||
report_github_issue(issue_text, title=title, confirm=False)
|
||||
|
||||
def cmd_editor(self, initial_content=""):
|
||||
"Open an editor to write a prompt"
|
||||
|
||||
user_input = pipe_editor(initial_content, suffix="md", editor=self.editor)
|
||||
if user_input.strip():
|
||||
self.io.set_placeholder(user_input.rstrip())
|
||||
|
||||
|
||||
def expand_subdir(file_path):
|
||||
if file_path.is_file():
|
||||
|
|
|
@ -50,7 +50,6 @@ def diff_partial_update(lines_orig, lines_updated, final=False, fname=None):
|
|||
# dump(lines_orig)
|
||||
# dump(lines_updated)
|
||||
|
||||
assert_newlines(lines_orig)
|
||||
assert_newlines(lines_orig)
|
||||
|
||||
num_orig_lines = len(lines_orig)
|
||||
|
|
146
aider/editor.py
Normal file
146
aider/editor.py
Normal file
|
@ -0,0 +1,146 @@
|
|||
"""
|
||||
Editor module for handling system text editor interactions.
|
||||
|
||||
This module provides functionality to:
|
||||
- Discover and launch the system's configured text editor
|
||||
- Create and manage temporary files for editing
|
||||
- Handle editor preferences from environment variables
|
||||
- Support cross-platform editor operations
|
||||
"""
|
||||
|
||||
import os
|
||||
import platform
|
||||
import shlex
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
DEFAULT_EDITOR_NIX = "vi"
|
||||
DEFAULT_EDITOR_OS_X = "vim"
|
||||
DEFAULT_EDITOR_WINDOWS = "notepad"
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def print_status_message(success, message, style=None):
|
||||
"""
|
||||
Print a status message with appropriate styling.
|
||||
|
||||
:param success: Whether the operation was successful
|
||||
:param message: The message to display
|
||||
:param style: Optional style override. If None, uses green for success and red for failure
|
||||
"""
|
||||
if style is None:
|
||||
style = "bold green" if success else "bold red"
|
||||
console.print(message, style=style)
|
||||
print("")
|
||||
|
||||
|
||||
def write_temp_file(
|
||||
input_data="",
|
||||
suffix=None,
|
||||
prefix=None,
|
||||
dir=None,
|
||||
):
|
||||
"""
|
||||
Create a temporary file with the given input data.
|
||||
|
||||
:param input_data: Content to write to the temporary file
|
||||
:param suffix: Optional file extension (without the dot)
|
||||
:param prefix: Optional prefix for the temporary filename
|
||||
:param dir: Optional directory to create the file in
|
||||
:return: Path to the created temporary file
|
||||
:raises: OSError if file creation or writing fails
|
||||
"""
|
||||
kwargs = {"prefix": prefix, "dir": dir}
|
||||
if suffix:
|
||||
kwargs["suffix"] = f".{suffix}"
|
||||
fd, filepath = tempfile.mkstemp(**kwargs)
|
||||
try:
|
||||
with os.fdopen(fd, "w") as f:
|
||||
f.write(input_data)
|
||||
except Exception:
|
||||
os.close(fd)
|
||||
raise
|
||||
return filepath
|
||||
|
||||
|
||||
def get_environment_editor(default=None):
|
||||
"""
|
||||
Fetches the preferred editor from the environment variables.
|
||||
|
||||
This function checks the following environment variables in order to
|
||||
determine the user's preferred editor:
|
||||
|
||||
- VISUAL
|
||||
- EDITOR
|
||||
|
||||
:param default: The default editor to return if no environment variable is set.
|
||||
:type default: str or None
|
||||
:return: The preferred editor as specified by environment variables or the default value.
|
||||
:rtype: str or None
|
||||
"""
|
||||
editor = os.environ.get("VISUAL", os.environ.get("EDITOR", default))
|
||||
return editor
|
||||
|
||||
|
||||
def discover_editor(editor_override=None):
|
||||
"""
|
||||
Discovers and returns the appropriate editor command as a list of arguments.
|
||||
|
||||
Handles cases where the editor command includes arguments, including quoted arguments
|
||||
with spaces (e.g. 'vim -c "set noswapfile"').
|
||||
|
||||
:return: A list of command parts ready for subprocess execution
|
||||
:rtype: list[str]
|
||||
"""
|
||||
system = platform.system()
|
||||
if system == "Windows":
|
||||
default_editor = DEFAULT_EDITOR_WINDOWS
|
||||
elif system == "Darwin":
|
||||
default_editor = DEFAULT_EDITOR_OS_X
|
||||
else:
|
||||
default_editor = DEFAULT_EDITOR_NIX
|
||||
if editor_override:
|
||||
editor = editor_override
|
||||
else:
|
||||
editor = get_environment_editor(default_editor)
|
||||
try:
|
||||
return shlex.split(editor)
|
||||
except ValueError as e:
|
||||
raise RuntimeError(f"Invalid editor command format '{editor}': {e}")
|
||||
|
||||
|
||||
def pipe_editor(input_data="", suffix=None, editor=None):
|
||||
"""
|
||||
Opens the system editor with optional input data and returns the edited content.
|
||||
|
||||
This function creates a temporary file with the provided input data, opens it in
|
||||
the system editor, waits for the user to make changes and close the editor, then
|
||||
reads and returns the modified content. The temporary file is deleted afterwards.
|
||||
|
||||
:param input_data: Initial content to populate the editor with
|
||||
:type input_data: str
|
||||
:param suffix: Optional file extension for the temporary file (e.g. '.txt', '.md')
|
||||
:type suffix: str or None
|
||||
:return: The edited content after the editor is closed
|
||||
:rtype: str
|
||||
"""
|
||||
filepath = write_temp_file(input_data, suffix)
|
||||
command_parts = discover_editor(editor)
|
||||
command_parts.append(filepath)
|
||||
subprocess.call(command_parts)
|
||||
with open(filepath, "r") as f:
|
||||
output_data = f.read()
|
||||
try:
|
||||
os.remove(filepath)
|
||||
except PermissionError:
|
||||
print_status_message(
|
||||
False,
|
||||
(
|
||||
f"WARNING: Unable to delete temporary file {filepath!r}. You may need to delete it"
|
||||
" manually."
|
||||
),
|
||||
)
|
||||
return output_data
|
|
@ -40,6 +40,11 @@ EXCEPTIONS = [
|
|||
ExInfo("ServiceUnavailableError", True, "The API provider's servers are down or overloaded."),
|
||||
ExInfo("UnprocessableEntityError", True, None),
|
||||
ExInfo("UnsupportedParamsError", True, None),
|
||||
ExInfo(
|
||||
"Timeout",
|
||||
True,
|
||||
"The API provider timed out without returning a response. They may be down or overloaded.",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -7,4 +7,5 @@ exclude_website_pats = [
|
|||
"docs/unified-diffs.md",
|
||||
"docs/leaderboards/index.md",
|
||||
"assets/**",
|
||||
"**/.DS_Store",
|
||||
]
|
||||
|
|
87
aider/io.py
87
aider/io.py
|
@ -1,6 +1,7 @@
|
|||
import base64
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
import webbrowser
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
@ -199,6 +200,7 @@ class InputOutput:
|
|||
editingmode=EditingMode.EMACS,
|
||||
fancy_input=True,
|
||||
):
|
||||
self.placeholder = None
|
||||
self.never_prompts = set()
|
||||
self.interrupted_partial_input = None
|
||||
self.editingmode = editingmode
|
||||
|
@ -336,14 +338,36 @@ class InputOutput:
|
|||
self.tool_error("Use --encoding to set the unicode encoding.")
|
||||
return
|
||||
|
||||
def write_text(self, filename, content):
|
||||
def write_text(self, filename, content, max_retries=5, initial_delay=0.1):
|
||||
"""
|
||||
Writes content to a file, retrying with progressive backoff if the file is locked.
|
||||
|
||||
:param filename: Path to the file to write.
|
||||
:param content: Content to write to the file.
|
||||
:param max_retries: Maximum number of retries if a file lock is encountered.
|
||||
:param initial_delay: Initial delay (in seconds) before the first retry.
|
||||
"""
|
||||
if self.dry_run:
|
||||
return
|
||||
|
||||
delay = initial_delay
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
with open(str(filename), "w", encoding=self.encoding) as f:
|
||||
f.write(content)
|
||||
return # Successfully wrote the file
|
||||
except PermissionError as err:
|
||||
if attempt < max_retries - 1:
|
||||
time.sleep(delay)
|
||||
delay *= 2 # Exponential backoff
|
||||
else:
|
||||
self.tool_error(
|
||||
f"Unable to write file {filename} after {max_retries} attempts: {err}"
|
||||
)
|
||||
raise
|
||||
except OSError as err:
|
||||
self.tool_error(f"Unable to write file {filename}: {err}")
|
||||
raise
|
||||
|
||||
def rule(self):
|
||||
if self.pretty:
|
||||
|
@ -433,11 +457,15 @@ class InputOutput:
|
|||
if multiline_input:
|
||||
show = ". "
|
||||
|
||||
try:
|
||||
try:
|
||||
if self.prompt_session:
|
||||
# Use placeholder if set, then clear it
|
||||
default = self.placeholder or ""
|
||||
self.placeholder = None
|
||||
|
||||
line = self.prompt_session.prompt(
|
||||
show,
|
||||
default=default,
|
||||
completer=completer_instance,
|
||||
reserve_space_for_menu=4,
|
||||
complete_style=CompleteStyle.MULTI_COLUMN,
|
||||
|
@ -457,7 +485,6 @@ class InputOutput:
|
|||
return ""
|
||||
except Exception as err:
|
||||
dump(err)
|
||||
|
||||
except UnicodeEncodeError as err:
|
||||
self.tool_error(str(err))
|
||||
return ""
|
||||
|
@ -466,13 +493,38 @@ class InputOutput:
|
|||
stop_event.set()
|
||||
watcher.join() # Thread should exit quickly due to stop_event
|
||||
|
||||
if line and line[0] == "{" and not multiline_input:
|
||||
if line.strip("\r\n") and not multiline_input:
|
||||
stripped = line.strip("\r\n")
|
||||
if stripped == "{":
|
||||
multiline_input = True
|
||||
inp += line[1:] + "\n"
|
||||
continue
|
||||
elif line and line[-1] == "}" and multiline_input:
|
||||
inp += line[:-1] + "\n"
|
||||
multiline_tag = None
|
||||
inp += ""
|
||||
elif stripped[0] == "{":
|
||||
# Extract tag if it exists (only alphanumeric chars)
|
||||
tag = "".join(c for c in stripped[1:] if c.isalnum())
|
||||
if stripped == "{" + tag:
|
||||
multiline_input = True
|
||||
multiline_tag = tag
|
||||
inp += ""
|
||||
else:
|
||||
inp = line
|
||||
break
|
||||
else:
|
||||
inp = line
|
||||
break
|
||||
continue
|
||||
elif multiline_input and line.strip():
|
||||
if multiline_tag:
|
||||
# Check if line is exactly "tag}"
|
||||
if line.strip("\r\n") == f"{multiline_tag}}}":
|
||||
break
|
||||
else:
|
||||
inp += line + "\n"
|
||||
# Check if line is exactly "}"
|
||||
elif line.strip("\r\n") == "}":
|
||||
break
|
||||
else:
|
||||
inp += line + "\n"
|
||||
elif multiline_input:
|
||||
inp += line + "\n"
|
||||
else:
|
||||
|
@ -488,8 +540,8 @@ class InputOutput:
|
|||
return
|
||||
FileHistory(self.input_history_file).append_string(inp)
|
||||
# Also add to the in-memory history if it exists
|
||||
if hasattr(self, "session") and hasattr(self.session, "history"):
|
||||
self.session.history.append_string(inp)
|
||||
if self.prompt_session and self.prompt_session.history:
|
||||
self.prompt_session.history.append_string(inp)
|
||||
|
||||
def get_input_history(self):
|
||||
if not self.input_history_file:
|
||||
|
@ -506,8 +558,7 @@ class InputOutput:
|
|||
log_file.write(f"{role.upper()} {timestamp}\n")
|
||||
log_file.write(content + "\n")
|
||||
|
||||
def user_input(self, inp, log_only=True):
|
||||
if not log_only:
|
||||
def display_user_input(self, inp):
|
||||
if self.pretty and self.user_input_color:
|
||||
style = dict(style=self.user_input_color)
|
||||
else:
|
||||
|
@ -515,6 +566,10 @@ class InputOutput:
|
|||
|
||||
self.console.print(Text(inp), **style)
|
||||
|
||||
def user_input(self, inp, log_only=True):
|
||||
if not log_only:
|
||||
self.display_user_input(inp)
|
||||
|
||||
prefix = "####"
|
||||
if inp:
|
||||
hist = inp.splitlines()
|
||||
|
@ -533,11 +588,11 @@ class InputOutput:
|
|||
hist = "\n" + content.strip() + "\n\n"
|
||||
self.append_chat_history(hist)
|
||||
|
||||
def offer_url(self, url, prompt="Open URL for more info?"):
|
||||
def offer_url(self, url, prompt="Open URL for more info?", allow_never=True):
|
||||
"""Offer to open a URL in the browser, returns True if opened."""
|
||||
if url in self.never_prompts:
|
||||
return False
|
||||
if self.confirm_ask(prompt, subject=url, allow_never=True):
|
||||
if self.confirm_ask(prompt, subject=url, allow_never=allow_never):
|
||||
webbrowser.open(url)
|
||||
return True
|
||||
return False
|
||||
|
@ -736,6 +791,10 @@ class InputOutput:
|
|||
|
||||
self.console.print(show_resp)
|
||||
|
||||
def set_placeholder(self, placeholder):
|
||||
"""Set a one-time placeholder text for the next input prompt."""
|
||||
self.placeholder = placeholder
|
||||
|
||||
def print(self, message=""):
|
||||
print(message)
|
||||
|
||||
|
|
105
aider/main.py
105
aider/main.py
|
@ -5,6 +5,8 @@ import re
|
|||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
import webbrowser
|
||||
from dataclasses import fields
|
||||
from pathlib import Path
|
||||
|
||||
import git
|
||||
|
@ -16,11 +18,13 @@ from aider import __version__, models, urls, utils
|
|||
from aider.analytics import Analytics
|
||||
from aider.args import get_parser
|
||||
from aider.coders import Coder
|
||||
from aider.coders.base_coder import UnknownEditFormat
|
||||
from aider.commands import Commands, SwitchCoder
|
||||
from aider.format_settings import format_settings, scrub_sensitive_info
|
||||
from aider.history import ChatSummary
|
||||
from aider.io import InputOutput
|
||||
from aider.llm import litellm # noqa: F401; properly init litellm on launch
|
||||
from aider.models import ModelSettings
|
||||
from aider.repo import ANY_GIT_ERROR, GitRepo
|
||||
from aider.report import report_uncaught_exceptions
|
||||
from aider.versioncheck import check_version, install_from_main_branch, install_upgrade
|
||||
|
@ -332,14 +336,16 @@ def load_dotenv_files(git_root, dotenv_fname, encoding="utf-8"):
|
|||
|
||||
|
||||
def register_litellm_models(git_root, model_metadata_fname, io, verbose=False):
|
||||
model_metatdata_files = generate_search_path_list(
|
||||
".aider.model.metadata.json", git_root, model_metadata_fname
|
||||
)
|
||||
model_metatdata_files = []
|
||||
|
||||
# Add the resource file path
|
||||
resource_metadata = importlib_resources.files("aider.resources").joinpath("model-metadata.json")
|
||||
model_metatdata_files.append(str(resource_metadata))
|
||||
|
||||
model_metatdata_files += generate_search_path_list(
|
||||
".aider.model.metadata.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 and verbose:
|
||||
|
@ -503,8 +509,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
io.tool_warning("Terminal does not support pretty output (UnicodeDecodeError)")
|
||||
|
||||
analytics = Analytics(logfile=args.analytics_log, permanently_disable=args.analytics_disable)
|
||||
if args.analytics:
|
||||
if analytics.need_to_ask():
|
||||
if args.analytics is not False:
|
||||
if analytics.need_to_ask(args.analytics):
|
||||
io.tool_output(
|
||||
"Aider respects your privacy and never collects your code, chat messages, keys or"
|
||||
" personal info."
|
||||
|
@ -540,7 +546,14 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
|
||||
all_files = args.files + (args.file or [])
|
||||
fnames = [str(Path(fn).resolve()) for fn in all_files]
|
||||
read_only_fnames = [str(Path(fn).resolve()) for fn in (args.read or [])]
|
||||
read_only_fnames = []
|
||||
for fn in args.read or []:
|
||||
path = Path(fn).resolve()
|
||||
if path.is_dir():
|
||||
read_only_fnames.extend(str(f) for f in path.rglob("*") if f.is_file())
|
||||
else:
|
||||
read_only_fnames.append(str(path))
|
||||
|
||||
if len(all_files) > 1:
|
||||
good = True
|
||||
for fname in all_files:
|
||||
|
@ -603,7 +616,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
cmd_line = scrub_sensitive_info(args, cmd_line)
|
||||
io.tool_output(cmd_line, log_only=True)
|
||||
|
||||
check_and_load_imports(io, verbose=args.verbose)
|
||||
is_first_run = is_first_run_of_new_version(io, verbose=args.verbose)
|
||||
check_and_load_imports(io, is_first_run, verbose=args.verbose)
|
||||
|
||||
if args.anthropic_api_key:
|
||||
os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key
|
||||
|
@ -622,6 +636,18 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
register_models(git_root, args.model_settings_file, io, verbose=args.verbose)
|
||||
register_litellm_models(git_root, args.model_metadata_file, io, verbose=args.verbose)
|
||||
|
||||
# Process any command line aliases
|
||||
if args.alias:
|
||||
for alias_def in args.alias:
|
||||
# Split on first colon only
|
||||
parts = alias_def.split(":", 1)
|
||||
if len(parts) != 2:
|
||||
io.tool_error(f"Invalid alias format: {alias_def}")
|
||||
io.tool_output("Format should be: alias:model-name")
|
||||
return 1
|
||||
alias, model = parts
|
||||
models.MODEL_ALIASES[alias.strip()] = model.strip()
|
||||
|
||||
if not args.model:
|
||||
args.model = "gpt-4o-2024-08-06"
|
||||
if os.environ.get("ANTHROPIC_API_KEY"):
|
||||
|
@ -635,9 +661,15 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
)
|
||||
|
||||
if args.verbose:
|
||||
io.tool_output("Model info:")
|
||||
io.tool_output("Model metadata:")
|
||||
io.tool_output(json.dumps(main_model.info, indent=4))
|
||||
|
||||
io.tool_output("Model settings:")
|
||||
for attr in sorted(fields(ModelSettings), key=lambda x: x.name):
|
||||
val = getattr(main_model, attr.name)
|
||||
val = json.dumps(val, indent=4)
|
||||
io.tool_output(f"{attr.name}: {val}")
|
||||
|
||||
lint_cmds = parse_lint_cmds(args.lint_cmd, io)
|
||||
if lint_cmds is None:
|
||||
return 1
|
||||
|
@ -678,7 +710,13 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
return 1
|
||||
|
||||
commands = Commands(
|
||||
io, None, verify_ssl=args.verify_ssl, args=args, parser=parser, verbose=args.verbose
|
||||
io,
|
||||
None,
|
||||
verify_ssl=args.verify_ssl,
|
||||
args=args,
|
||||
parser=parser,
|
||||
verbose=args.verbose,
|
||||
editor=args.editor,
|
||||
)
|
||||
|
||||
summarizer = ChatSummary(
|
||||
|
@ -726,7 +764,12 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
num_cache_warming_pings=args.cache_keepalive_pings,
|
||||
suggest_shell_commands=args.suggest_shell_commands,
|
||||
chat_language=args.chat_language,
|
||||
detect_urls=args.detect_urls,
|
||||
)
|
||||
except UnknownEditFormat as err:
|
||||
io.tool_error(str(err))
|
||||
io.offer_url(urls.edit_formats, "Open documentation about edit formats?")
|
||||
return 1
|
||||
except ValueError as err:
|
||||
io.tool_error(str(err))
|
||||
return 1
|
||||
|
@ -788,6 +831,18 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
|
||||
io.tool_output('Use /help <question> for help, run "aider --help" to see cmd line args')
|
||||
|
||||
if args.show_release_notes is True:
|
||||
io.tool_output(f"Opening release notes: {urls.release_notes}")
|
||||
io.tool_output()
|
||||
webbrowser.open(urls.release_notes)
|
||||
elif args.show_release_notes is None and is_first_run:
|
||||
io.tool_output()
|
||||
io.offer_url(
|
||||
urls.release_notes,
|
||||
"Would you like to see what's new in this version?",
|
||||
allow_never=False,
|
||||
)
|
||||
|
||||
if git_root and Path.cwd().resolve() != Path(git_root).resolve():
|
||||
io.tool_warning(
|
||||
"Note: in-chat filenames are always relative to the git working dir, not the current"
|
||||
|
@ -843,7 +898,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||
coder.show_announcements()
|
||||
|
||||
|
||||
def check_and_load_imports(io, verbose=False):
|
||||
def is_first_run_of_new_version(io, verbose=False):
|
||||
"""Check if this is the first run of a new version/executable combination"""
|
||||
installs_file = Path.home() / ".aider" / "installs.json"
|
||||
key = (__version__, sys.executable)
|
||||
|
||||
|
@ -864,7 +920,26 @@ def check_and_load_imports(io, verbose=False):
|
|||
if verbose:
|
||||
io.tool_output("Installs file does not exist, creating new dictionary")
|
||||
|
||||
if str(key) not in installs:
|
||||
is_first_run = str(key) not in installs
|
||||
|
||||
if is_first_run:
|
||||
installs[str(key)] = True
|
||||
installs_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(installs_file, "w") as f:
|
||||
json.dump(installs, f, indent=4)
|
||||
|
||||
return is_first_run
|
||||
|
||||
except Exception as e:
|
||||
io.tool_warning(f"Error checking version: {e}")
|
||||
if verbose:
|
||||
io.tool_output(f"Full exception details: {traceback.format_exc()}")
|
||||
return True # Safer to assume it's a first run if we hit an error
|
||||
|
||||
|
||||
def check_and_load_imports(io, is_first_run, verbose=False):
|
||||
try:
|
||||
if is_first_run:
|
||||
if verbose:
|
||||
io.tool_output(
|
||||
"First run for this version and executable, loading imports synchronously"
|
||||
|
@ -875,13 +950,8 @@ def check_and_load_imports(io, verbose=False):
|
|||
io.tool_error(str(err))
|
||||
io.tool_output("Error loading required imports. Did you install aider properly?")
|
||||
io.offer_url(urls.install_properly, "Open documentation url for more info?")
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
installs[str(key)] = True
|
||||
installs_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(installs_file, "w") as f:
|
||||
json.dump(installs, f, indent=4)
|
||||
if verbose:
|
||||
io.tool_output("Imports loaded and installs file updated")
|
||||
else:
|
||||
|
@ -890,8 +960,9 @@ def check_and_load_imports(io, verbose=False):
|
|||
thread = threading.Thread(target=load_slow_imports)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
except Exception as e:
|
||||
io.tool_warning(f"Error in checking imports: {e}")
|
||||
io.tool_warning(f"Error in loading imports: {e}")
|
||||
if verbose:
|
||||
io.tool_output(f"Full exception details: {traceback.format_exc()}")
|
||||
|
||||
|
|
104
aider/models.py
104
aider/models.py
|
@ -61,6 +61,23 @@ claude-3-5-sonnet-20241022
|
|||
|
||||
ANTHROPIC_MODELS = [ln.strip() for ln in ANTHROPIC_MODELS.splitlines() if ln.strip()]
|
||||
|
||||
# Mapping of model aliases to their canonical names
|
||||
MODEL_ALIASES = {
|
||||
# Claude models
|
||||
"sonnet": "claude-3-sonnet-20241022",
|
||||
"haiku": "claude-3-haiku-20241022",
|
||||
"opus": "claude-3-opus-20240229",
|
||||
# GPT models
|
||||
"4": "gpt-4-0613",
|
||||
"4o": "gpt-4o-2024-08-06",
|
||||
"4-turbo": "gpt-4-1106-preview",
|
||||
"35turbo": "gpt-3.5-turbo",
|
||||
"35-turbo": "gpt-3.5-turbo",
|
||||
"3": "gpt-3.5-turbo",
|
||||
# Other models
|
||||
"deepseek": "deepseek/deepseek-coder",
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class ModelSettings:
|
||||
|
@ -161,6 +178,22 @@ MODEL_SETTINGS = [
|
|||
lazy=True,
|
||||
reminder="sys",
|
||||
),
|
||||
ModelSettings(
|
||||
"gpt-4o-2024-11-20",
|
||||
"diff",
|
||||
weak_model_name="gpt-4o-mini",
|
||||
use_repo_map=True,
|
||||
lazy=True,
|
||||
reminder="sys",
|
||||
),
|
||||
ModelSettings(
|
||||
"openai/gpt-4o-2024-11-20",
|
||||
"diff",
|
||||
weak_model_name="gpt-4o-mini",
|
||||
use_repo_map=True,
|
||||
lazy=True,
|
||||
reminder="sys",
|
||||
),
|
||||
ModelSettings(
|
||||
"gpt-4o",
|
||||
"diff",
|
||||
|
@ -629,7 +662,6 @@ MODEL_SETTINGS = [
|
|||
reminder="user",
|
||||
use_system_prompt=False,
|
||||
use_temperature=False,
|
||||
streaming=False,
|
||||
),
|
||||
ModelSettings(
|
||||
"azure/o1-mini",
|
||||
|
@ -641,7 +673,6 @@ MODEL_SETTINGS = [
|
|||
reminder="user",
|
||||
use_system_prompt=False,
|
||||
use_temperature=False,
|
||||
streaming=False,
|
||||
),
|
||||
ModelSettings(
|
||||
"o1-mini",
|
||||
|
@ -653,7 +684,6 @@ MODEL_SETTINGS = [
|
|||
reminder="user",
|
||||
use_system_prompt=False,
|
||||
use_temperature=False,
|
||||
streaming=False,
|
||||
),
|
||||
ModelSettings(
|
||||
"openai/o1-preview",
|
||||
|
@ -665,7 +695,6 @@ MODEL_SETTINGS = [
|
|||
reminder="user",
|
||||
use_system_prompt=False,
|
||||
use_temperature=False,
|
||||
streaming=False,
|
||||
),
|
||||
ModelSettings(
|
||||
"azure/o1-preview",
|
||||
|
@ -677,7 +706,6 @@ MODEL_SETTINGS = [
|
|||
reminder="user",
|
||||
use_system_prompt=False,
|
||||
use_temperature=False,
|
||||
streaming=False,
|
||||
),
|
||||
ModelSettings(
|
||||
"o1-preview",
|
||||
|
@ -689,7 +717,6 @@ MODEL_SETTINGS = [
|
|||
reminder="user",
|
||||
use_system_prompt=False,
|
||||
use_temperature=False,
|
||||
streaming=False,
|
||||
),
|
||||
ModelSettings(
|
||||
"openrouter/openai/o1-mini",
|
||||
|
@ -762,6 +789,11 @@ class ModelInfoManager:
|
|||
pass
|
||||
except Exception as ex:
|
||||
print(str(ex))
|
||||
try:
|
||||
# Save empty dict to cache file on failure
|
||||
self.cache_file.write_text("{}")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def get_model_from_cached_json_db(self, model):
|
||||
if not self.content:
|
||||
|
@ -804,11 +836,17 @@ model_info_manager = ModelInfoManager()
|
|||
|
||||
class Model(ModelSettings):
|
||||
def __init__(self, model, weak_model=None, editor_model=None, editor_edit_format=None):
|
||||
self.name = model
|
||||
# Map any alias to its canonical name
|
||||
self.name = MODEL_ALIASES.get(model, model)
|
||||
self.max_chat_history_tokens = 1024
|
||||
self.weak_model = None
|
||||
self.editor_model = None
|
||||
|
||||
# Find the extra settings
|
||||
self.extra_model_settings = next(
|
||||
(ms for ms in MODEL_SETTINGS if ms.name == "aider/extra_params"), None
|
||||
)
|
||||
|
||||
self.info = self.get_model_info(model)
|
||||
|
||||
# Are all needed keys/params available?
|
||||
|
@ -836,17 +874,44 @@ class Model(ModelSettings):
|
|||
def get_model_info(self, model):
|
||||
return model_info_manager.get_model_info(model)
|
||||
|
||||
def _copy_fields(self, source):
|
||||
"""Helper to copy fields from a ModelSettings instance to self"""
|
||||
for field in fields(ModelSettings):
|
||||
val = getattr(source, field.name)
|
||||
setattr(self, field.name, val)
|
||||
|
||||
def configure_model_settings(self, model):
|
||||
# Look for exact model match
|
||||
exact_match = False
|
||||
for ms in MODEL_SETTINGS:
|
||||
# direct match, or match "provider/<model>"
|
||||
if model == ms.name:
|
||||
for field in fields(ModelSettings):
|
||||
val = getattr(ms, field.name)
|
||||
setattr(self, field.name, val)
|
||||
return # <--
|
||||
self._copy_fields(ms)
|
||||
exact_match = True
|
||||
break # Continue to apply overrides
|
||||
|
||||
model = model.lower()
|
||||
|
||||
# If no exact match, try generic settings
|
||||
if not exact_match:
|
||||
self.apply_generic_model_settings(model)
|
||||
|
||||
# Apply override settings last if they exist
|
||||
if self.extra_model_settings and self.extra_model_settings.extra_params:
|
||||
# Initialize extra_params if it doesn't exist
|
||||
if not self.extra_params:
|
||||
self.extra_params = {}
|
||||
|
||||
# Deep merge the extra_params dicts
|
||||
for key, value in self.extra_model_settings.extra_params.items():
|
||||
if isinstance(value, dict) and isinstance(self.extra_params.get(key), dict):
|
||||
# For nested dicts, merge recursively
|
||||
self.extra_params[key] = {**self.extra_params[key], **value}
|
||||
else:
|
||||
# For non-dict values, simply update
|
||||
self.extra_params[key] = value
|
||||
|
||||
def apply_generic_model_settings(self, model):
|
||||
if ("llama3" in model or "llama-3" in model) and "70b" in model:
|
||||
self.edit_format = "diff"
|
||||
self.use_repo_map = True
|
||||
|
@ -868,17 +933,19 @@ class Model(ModelSettings):
|
|||
|
||||
if "gpt-3.5" in model or "gpt-4" in model:
|
||||
self.reminder = "sys"
|
||||
return # <--
|
||||
|
||||
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.reminder = "user"
|
||||
return # <--
|
||||
|
||||
if model.startswith("o1-") or "/o1-" in model:
|
||||
self.use_system_prompt = False
|
||||
self.use_temperature = False
|
||||
self.streaming = False
|
||||
return # <--
|
||||
|
||||
if (
|
||||
"qwen" in model
|
||||
|
@ -886,14 +953,17 @@ class Model(ModelSettings):
|
|||
and ("2.5" in model or "2-5" in model)
|
||||
and "32b" in model
|
||||
):
|
||||
"openrouter/qwen/qwen-2.5-coder-32b-instruct",
|
||||
self.edit_format = "diff"
|
||||
self.editor_edit_format = "editor-diff"
|
||||
self.use_repo_map = True
|
||||
if model.startswith("ollama/") or model.startswith("ollama_chat/"):
|
||||
self.extra_params = dict(num_ctx=8 * 1024)
|
||||
return # <--
|
||||
|
||||
# use the defaults
|
||||
if self.edit_format == "diff":
|
||||
self.use_repo_map = True
|
||||
return # <--
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
@ -1050,6 +1120,9 @@ def register_models(model_settings_fnames):
|
|||
if not os.path.exists(model_settings_fname):
|
||||
continue
|
||||
|
||||
if not Path(model_settings_fname).read_text().strip():
|
||||
continue
|
||||
|
||||
try:
|
||||
with open(model_settings_fname, "r") as model_settings_file:
|
||||
model_settings_list = yaml.safe_load(model_settings_file)
|
||||
|
@ -1167,7 +1240,10 @@ def fuzzy_match_models(name):
|
|||
model = model.lower()
|
||||
if attrs.get("mode") != "chat":
|
||||
continue
|
||||
provider = (attrs["litellm_provider"] + "/").lower()
|
||||
provider = attrs.get("litellm_provider", "").lower()
|
||||
if not provider:
|
||||
continue
|
||||
provider += "/"
|
||||
|
||||
if model.startswith(provider):
|
||||
fq_model = model
|
||||
|
|
91
aider/queries/tree-sitter-dart-tags.scm
Normal file
91
aider/queries/tree-sitter-dart-tags.scm
Normal file
|
@ -0,0 +1,91 @@
|
|||
(class_definition
|
||||
name: (identifier) @name.definition.class) @definition.class
|
||||
|
||||
(method_signature
|
||||
(function_signature)) @definition.method
|
||||
|
||||
(type_alias
|
||||
(type_identifier) @name.definition.type) @definition.type
|
||||
|
||||
(method_signature
|
||||
(getter_signature
|
||||
name: (identifier) @name.definition.method)) @definition.method
|
||||
|
||||
(method_signature
|
||||
(setter_signature
|
||||
name: (identifier) @name.definition.method)) @definition.method
|
||||
|
||||
(method_signature
|
||||
(function_signature
|
||||
name: (identifier) @name.definition.method)) @definition.method
|
||||
|
||||
(method_signature
|
||||
(factory_constructor_signature
|
||||
(identifier) @name.definition.method)) @definition.method
|
||||
|
||||
(method_signature
|
||||
(constructor_signature
|
||||
name: (identifier) @name.definition.method)) @definition.method
|
||||
|
||||
(method_signature
|
||||
(operator_signature)) @definition.method
|
||||
|
||||
(method_signature) @definition.method
|
||||
|
||||
(mixin_declaration
|
||||
(mixin)
|
||||
(identifier) @name.definition.mixin) @definition.mixin
|
||||
|
||||
(extension_declaration
|
||||
name: (identifier) @name.definition.extension) @definition.extension
|
||||
|
||||
(enum_declaration
|
||||
name: (identifier) @name.definition.enum) @definition.enum
|
||||
|
||||
(function_signature
|
||||
name: (identifier) @name.definition.function) @definition.function
|
||||
|
||||
(new_expression
|
||||
(type_identifier) @name.reference.class) @reference.class
|
||||
|
||||
(initialized_variable_definition
|
||||
name: (identifier)
|
||||
value: (identifier) @name.reference.class
|
||||
value: (selector
|
||||
"!"?
|
||||
(argument_part
|
||||
(arguments
|
||||
(argument)*))?)?) @reference.class
|
||||
|
||||
(assignment_expression
|
||||
left: (assignable_expression
|
||||
(identifier)
|
||||
(unconditional_assignable_selector
|
||||
"."
|
||||
(identifier) @name.reference.call))) @reference.call
|
||||
|
||||
(assignment_expression
|
||||
left: (assignable_expression
|
||||
(identifier)
|
||||
(conditional_assignable_selector
|
||||
"?."
|
||||
(identifier) @name.reference.call))) @reference.call
|
||||
|
||||
((identifier) @name
|
||||
(selector
|
||||
"!"?
|
||||
(conditional_assignable_selector
|
||||
"?." (identifier) @name.reference.call)?
|
||||
(unconditional_assignable_selector
|
||||
"."? (identifier) @name.reference.call)?
|
||||
(argument_part
|
||||
(arguments
|
||||
(argument)*))?)*
|
||||
(cascade_section
|
||||
(cascade_selector
|
||||
(identifier)) @name.reference.call
|
||||
(argument_part
|
||||
(arguments
|
||||
(argument)*))?)?) @reference.call
|
||||
|
||||
|
|
@ -334,8 +334,11 @@ class GitRepo:
|
|||
def git_ignored_file(self, path):
|
||||
if not self.repo:
|
||||
return
|
||||
try:
|
||||
if self.repo.ignored(path):
|
||||
return True
|
||||
except ANY_GIT_ERROR:
|
||||
return False
|
||||
|
||||
def ignored_file(self, fname):
|
||||
self.refresh_aider_ignore()
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"openrouter/qwen/qwen-2.5-coder-32b-instruct": {
|
||||
"max_tokens": 33792,
|
||||
"max_input_tokens": 33792,
|
||||
"max_output_tokens": 33792,
|
||||
"input_cost_per_token": 0.00000018,
|
||||
"output_cost_per_token": 0.00000018,
|
||||
"litellm_provider": "openrouter",
|
||||
"mode": "chat",
|
||||
},
|
||||
}
|
|
@ -12,3 +12,5 @@ github_issues = "https://github.com/Aider-AI/aider/issues/new"
|
|||
git_index_version = "https://github.com/Aider-AI/aider/issues/211"
|
||||
install_properly = "https://aider.chat/docs/troubleshooting/imports.html"
|
||||
analytics = "https://aider.chat/docs/more/analytics.html"
|
||||
release_notes = "https://aider.chat/HISTORY.html#release-notes"
|
||||
edit_formats = "https://aider.chat/docs/more/edit-formats.html"
|
||||
|
|
|
@ -12,7 +12,9 @@ description: Release notes and stats on aider writing its own code.
|
|||
|
||||
The above
|
||||
[stats are based on the git commit history](/docs/faq.html#how-are-the-aider-wrote-xx-of-code-stats-computed)
|
||||
in the aider repo.
|
||||
of the aider repo.
|
||||
|
||||
## Release notes
|
||||
|
||||
<!--[[[cog
|
||||
# This page is a copy of HISTORY.md, adding the front matter above.
|
||||
|
@ -22,6 +24,54 @@ cog.out(text)
|
|||
]]]-->
|
||||
|
||||
|
||||
### Aider v0.65.0
|
||||
|
||||
- Added `--alias` config to define [custom model aliases](https://aider.chat/docs/config/model-aliases.html).
|
||||
- Added `--[no-]detect-urls` flag to disable detecting and offering to scrape URLs found in the chat.
|
||||
- Ollama models now default to an 8k context window.
|
||||
- Added [RepoMap support for Dart language](https://aider.chat/docs/languages.html) by @malkoG.
|
||||
- Ask 2.5% of users if they want to opt-in to [analytics](https://aider.chat/docs/more/analytics.html).
|
||||
- Skip suggesting files that share names with files already in chat.
|
||||
- `/editor` returns and prefill the file content into the prompt, so you can use `/editor` to compose messages that start with `/commands`, etc.
|
||||
- Enhanced error handling for analytics.
|
||||
- Improved handling of UnknownEditFormat exceptions with helpful documentation links.
|
||||
- Bumped dependencies to pick up grep-ast 0.4.0 for Dart language support.
|
||||
- Aider wrote 81% of the code in this release.
|
||||
|
||||
### Aider v0.64.1
|
||||
|
||||
- Disable streaming for o1 on OpenRouter.
|
||||
|
||||
### Aider v0.64.0
|
||||
|
||||
- Added [`/editor` command](https://aider.chat/docs/usage/commands.html) to open system editor for writing prompts, by @thehunmonkgroup.
|
||||
- Full support for `gpt-4o-2024-11-20`.
|
||||
- Stream o1 models by default.
|
||||
- `/run` and suggested shell commands are less mysterious and now confirm that they "Added XX lines of output to the chat."
|
||||
- Ask 1% of users if they want to opt-in to [analytics](https://aider.chat/docs/more/analytics.html).
|
||||
- Added support for [optional multiline input tags](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) with matching closing tags.
|
||||
- Improved [model settings configuration](https://aider.chat/docs/config/adv-model-settings.html#global-extra-params) with support for global `extra_params` for `litellm.completion()`.
|
||||
- Architect mode now asks to add files suggested by the LLM.
|
||||
- Fixed bug in fuzzy model name matching.
|
||||
- Added Timeout exception to handle API provider timeouts.
|
||||
- Added `--show-release-notes` to control release notes display on first run of new version.
|
||||
- Save empty dict to cache file on model metadata download failure, to delay retry.
|
||||
- Improved error handling and code formatting.
|
||||
- Aider wrote 74% of the code in this release.
|
||||
|
||||
### Aider v0.63.2
|
||||
|
||||
- Fixed bug in fuzzy model name matching when litellm provider info is missing.
|
||||
- Modified model metadata file loading to allow override of resource file.
|
||||
- Allow recursive loading of dirs using `--read`.
|
||||
- Updated dependency versions to pick up litellm fix for ollama models.
|
||||
- Added exponential backoff retry when writing files to handle editor file locks.
|
||||
- Updated Qwen 2.5 Coder 32B model configuration.
|
||||
|
||||
### Aider v0.63.1
|
||||
|
||||
- Fixed bug in git ignored file handling.
|
||||
- Improved error handling for git operations.
|
||||
|
||||
### Aider v0.63.0
|
||||
|
||||
|
|
|
@ -1801,8 +1801,8 @@
|
|||
Paul Gauthier (aider): 113
|
||||
start_tag: v0.44.0
|
||||
total_lines: 266
|
||||
- aider_percentage: 47.04
|
||||
aider_total: 254
|
||||
- aider_percentage: 53.3
|
||||
aider_total: 339
|
||||
end_date: '2024-07-29'
|
||||
end_tag: v0.46.0
|
||||
file_counts:
|
||||
|
@ -1853,6 +1853,9 @@
|
|||
aider/scrape.py:
|
||||
Paul Gauthier: 3
|
||||
Paul Gauthier (aider): 32
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 11
|
||||
Paul Gauthier (aider): 85
|
||||
benchmark/Dockerfile:
|
||||
Your Name: 1
|
||||
tests/basic/test_coder.py:
|
||||
|
@ -1868,13 +1871,13 @@
|
|||
Paul Gauthier (aider): 73
|
||||
grand_total:
|
||||
Charles Joachim: 4
|
||||
Paul Gauthier: 209
|
||||
Paul Gauthier (aider): 204
|
||||
Paul Gauthier: 220
|
||||
Paul Gauthier (aider): 289
|
||||
Your Name: 73
|
||||
Your Name (aider): 50
|
||||
start_tag: v0.45.0
|
||||
total_lines: 540
|
||||
- aider_percentage: 59.12
|
||||
total_lines: 636
|
||||
- aider_percentage: 57.16
|
||||
aider_total: 415
|
||||
end_date: '2024-07-31'
|
||||
end_tag: v0.47.0
|
||||
|
@ -1920,6 +1923,8 @@
|
|||
Paul Gauthier (aider): 2
|
||||
aider/utils.py:
|
||||
Paul Gauthier: 7
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 24
|
||||
docker/Dockerfile:
|
||||
Paul Gauthier: 19
|
||||
Paul Gauthier (aider): 21
|
||||
|
@ -1944,10 +1949,10 @@
|
|||
tests/basic/test_repomap.py:
|
||||
Paul Gauthier: 1
|
||||
grand_total:
|
||||
Paul Gauthier: 287
|
||||
Paul Gauthier: 311
|
||||
Paul Gauthier (aider): 415
|
||||
start_tag: v0.46.0
|
||||
total_lines: 702
|
||||
total_lines: 726
|
||||
- aider_percentage: 44.44
|
||||
aider_total: 276
|
||||
end_date: '2024-08-06'
|
||||
|
@ -2011,8 +2016,8 @@
|
|||
paul-gauthier: 1
|
||||
start_tag: v0.47.0
|
||||
total_lines: 621
|
||||
- aider_percentage: 61.52
|
||||
aider_total: 478
|
||||
- aider_percentage: 61.2
|
||||
aider_total: 489
|
||||
end_date: '2024-08-10'
|
||||
end_tag: v0.49.0
|
||||
file_counts:
|
||||
|
@ -2055,6 +2060,9 @@
|
|||
aider/versioncheck.py:
|
||||
Paul Gauthier: 3
|
||||
Paul Gauthier (aider): 11
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 11
|
||||
Paul Gauthier (aider): 11
|
||||
docker/Dockerfile:
|
||||
Paul Gauthier: 5
|
||||
Paul Gauthier (aider): 2
|
||||
|
@ -2075,10 +2083,10 @@
|
|||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 49
|
||||
grand_total:
|
||||
Paul Gauthier: 299
|
||||
Paul Gauthier (aider): 478
|
||||
Paul Gauthier: 310
|
||||
Paul Gauthier (aider): 489
|
||||
start_tag: v0.48.0
|
||||
total_lines: 777
|
||||
total_lines: 799
|
||||
- aider_percentage: 66.05
|
||||
aider_total: 214
|
||||
end_date: '2024-08-13'
|
||||
|
@ -2135,8 +2143,8 @@
|
|||
Paul Gauthier (aider): 201
|
||||
start_tag: v0.49.0
|
||||
total_lines: 324
|
||||
- aider_percentage: 56.25
|
||||
aider_total: 450
|
||||
- aider_percentage: 52.49
|
||||
aider_total: 580
|
||||
end_date: '2024-08-20'
|
||||
end_tag: v0.51.0
|
||||
file_counts:
|
||||
|
@ -2170,6 +2178,14 @@
|
|||
Paul Gauthier: 3
|
||||
aider/utils.py:
|
||||
Paul Gauthier (aider): 6
|
||||
aider/website/_includes/code-in-json-benchmark.js:
|
||||
Paul Gauthier: 101
|
||||
Paul Gauthier (aider): 64
|
||||
aider/website/_includes/code-in-json-syntax.js:
|
||||
Paul Gauthier: 73
|
||||
Paul Gauthier (aider): 66
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
benchmark/benchmark.py:
|
||||
Paul Gauthier: 7
|
||||
benchmark/over_time.py:
|
||||
|
@ -2188,11 +2204,11 @@
|
|||
Paul Gauthier: 15
|
||||
Paul Gauthier (aider): 104
|
||||
grand_total:
|
||||
Paul Gauthier: 350
|
||||
Paul Gauthier (aider): 450
|
||||
Paul Gauthier: 525
|
||||
Paul Gauthier (aider): 580
|
||||
start_tag: v0.50.0
|
||||
total_lines: 800
|
||||
- aider_percentage: 68.19
|
||||
total_lines: 1105
|
||||
- aider_percentage: 68.1
|
||||
aider_total: 521
|
||||
end_date: '2024-08-23'
|
||||
end_tag: v0.52.0
|
||||
|
@ -2231,6 +2247,8 @@
|
|||
Paul Gauthier (aider): 9
|
||||
aider/versioncheck.py:
|
||||
Paul Gauthier: 2
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
benchmark/benchmark.py:
|
||||
Paul Gauthier: 1
|
||||
scripts/blame.py:
|
||||
|
@ -2250,13 +2268,13 @@
|
|||
tests/basic/test_wholefile.py:
|
||||
Paul Gauthier: 8
|
||||
grand_total:
|
||||
Paul Gauthier: 242
|
||||
Paul Gauthier: 243
|
||||
Paul Gauthier (aider): 521
|
||||
pcamp: 1
|
||||
start_tag: v0.51.0
|
||||
total_lines: 764
|
||||
- aider_percentage: 58.61
|
||||
aider_total: 405
|
||||
total_lines: 765
|
||||
- aider_percentage: 61.4
|
||||
aider_total: 455
|
||||
end_date: '2024-08-27'
|
||||
end_tag: v0.53.0
|
||||
file_counts:
|
||||
|
@ -2321,14 +2339,16 @@
|
|||
tests/basic/test_repomap.py:
|
||||
Paul Gauthier: 4
|
||||
Paul Gauthier (aider): 63
|
||||
tests/fixtures/sample-code-base/sample.js:
|
||||
Paul Gauthier (aider): 50
|
||||
tests/fixtures/sample-code-base/sample.py:
|
||||
Paul Gauthier (aider): 68
|
||||
grand_total:
|
||||
Paul Gauthier: 286
|
||||
Paul Gauthier (aider): 405
|
||||
Paul Gauthier (aider): 455
|
||||
start_tag: v0.52.0
|
||||
total_lines: 691
|
||||
- aider_percentage: 63.95
|
||||
total_lines: 741
|
||||
- aider_percentage: 63.75
|
||||
aider_total: 204
|
||||
end_date: '2024-08-28'
|
||||
end_tag: v0.54.0
|
||||
|
@ -2364,6 +2384,8 @@
|
|||
aider/versioncheck.py:
|
||||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 13
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
tests/basic/test_coder.py:
|
||||
Paul Gauthier: 36
|
||||
Paul Gauthier (aider): 27
|
||||
|
@ -2376,11 +2398,11 @@
|
|||
Paul Gauthier: 1
|
||||
grand_total:
|
||||
Antti Kaihola: 4
|
||||
Paul Gauthier: 111
|
||||
Paul Gauthier: 112
|
||||
Paul Gauthier (aider): 204
|
||||
start_tag: v0.53.0
|
||||
total_lines: 319
|
||||
- aider_percentage: 52.9
|
||||
total_lines: 320
|
||||
- aider_percentage: 52.87
|
||||
aider_total: 811
|
||||
end_date: '2024-09-04'
|
||||
end_tag: v0.55.0
|
||||
|
@ -2450,6 +2472,8 @@
|
|||
aider/voice.py:
|
||||
Paul Gauthier: 7
|
||||
Paul Gauthier (aider): 9
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
scripts/versionbump.py:
|
||||
Paul Gauthier: 9
|
||||
tests/basic/test_coder.py:
|
||||
|
@ -2478,11 +2502,11 @@
|
|||
grand_total:
|
||||
Antti Kaihola: 12
|
||||
Nikolay Sedelnikov: 45
|
||||
Paul Gauthier: 665
|
||||
Paul Gauthier: 666
|
||||
Paul Gauthier (aider): 811
|
||||
start_tag: v0.54.0
|
||||
total_lines: 1533
|
||||
- aider_percentage: 55.6
|
||||
total_lines: 1534
|
||||
- aider_percentage: 55.4
|
||||
aider_total: 154
|
||||
end_date: '2024-09-09'
|
||||
end_tag: v0.56.0
|
||||
|
@ -2517,6 +2541,8 @@
|
|||
aider/report.py:
|
||||
Paul Gauthier: 2
|
||||
Paul Gauthier (aider): 20
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
benchmark/benchmark.py:
|
||||
Paul Gauthier: 1
|
||||
tests/basic/test_linter.py:
|
||||
|
@ -2526,13 +2552,13 @@
|
|||
Paul Gauthier: 2
|
||||
Paul Gauthier (aider): 9
|
||||
grand_total:
|
||||
Paul Gauthier: 108
|
||||
Paul Gauthier: 109
|
||||
Paul Gauthier (aider): 154
|
||||
fry69: 15
|
||||
start_tag: v0.55.0
|
||||
total_lines: 277
|
||||
- aider_percentage: 69.98
|
||||
aider_total: 394
|
||||
total_lines: 278
|
||||
- aider_percentage: 70.36
|
||||
aider_total: 406
|
||||
end_date: '2024-09-21'
|
||||
end_tag: v0.57.0
|
||||
file_counts:
|
||||
|
@ -2575,6 +2601,10 @@
|
|||
Paul Gauthier: 3
|
||||
aider/utils.py:
|
||||
Paul Gauthier: 2
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Anjor Kanekar: 1
|
||||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 12
|
||||
benchmark/benchmark.py:
|
||||
Paul Gauthier: 4
|
||||
scripts/issues.py:
|
||||
|
@ -2592,15 +2622,16 @@
|
|||
Paul Gauthier: 18
|
||||
Paul Gauthier (aider): 20
|
||||
grand_total:
|
||||
Anjor Kanekar: 1
|
||||
Christian Clauss: 2
|
||||
Jay Alammar: 1
|
||||
Jay Alammar (aider): 13
|
||||
Krazer: 33
|
||||
Paul Gauthier: 133
|
||||
Paul Gauthier (aider): 381
|
||||
Paul Gauthier: 134
|
||||
Paul Gauthier (aider): 393
|
||||
start_tag: v0.56.0
|
||||
total_lines: 563
|
||||
- aider_percentage: 53.45
|
||||
total_lines: 577
|
||||
- aider_percentage: 47.95
|
||||
aider_total: 712
|
||||
end_date: '2024-09-29'
|
||||
end_tag: v0.58.0
|
||||
|
@ -2677,6 +2708,8 @@
|
|||
Mike Bailey: 17
|
||||
Paul Gauthier: 2
|
||||
Paul Gauthier (aider): 10
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 153
|
||||
benchmark/benchmark.py:
|
||||
Paul Gauthier: 25
|
||||
Paul Gauthier (aider): 29
|
||||
|
@ -2705,14 +2738,14 @@
|
|||
grand_total:
|
||||
Jonathan Ellis: 2
|
||||
Mike Bailey: 18
|
||||
Paul Gauthier: 376
|
||||
Paul Gauthier: 529
|
||||
Paul Gauthier (aider): 712
|
||||
Stein Martin Hustad: 26
|
||||
fry69: 197
|
||||
rti: 1
|
||||
start_tag: v0.57.0
|
||||
total_lines: 1332
|
||||
- aider_percentage: 76.79
|
||||
total_lines: 1485
|
||||
- aider_percentage: 75.44
|
||||
aider_total: 172
|
||||
end_date: '2024-10-04'
|
||||
end_tag: v0.59.0
|
||||
|
@ -2747,6 +2780,8 @@
|
|||
Paul Gauthier: 2
|
||||
aider/versioncheck.py:
|
||||
Paul Gauthier: 1
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 4
|
||||
scripts/issues.py:
|
||||
Paul Gauthier: 1
|
||||
scripts/update-docs.sh:
|
||||
|
@ -2762,11 +2797,11 @@
|
|||
tests/help/test_help.py:
|
||||
Paul Gauthier: 1
|
||||
grand_total:
|
||||
Paul Gauthier: 52
|
||||
Paul Gauthier: 56
|
||||
Paul Gauthier (aider): 172
|
||||
start_tag: v0.58.0
|
||||
total_lines: 224
|
||||
- aider_percentage: 49.12
|
||||
total_lines: 228
|
||||
- aider_percentage: 48.95
|
||||
aider_total: 140
|
||||
end_date: '2024-10-22'
|
||||
end_tag: v0.60.0
|
||||
|
@ -2804,6 +2839,8 @@
|
|||
Paul Gauthier: 3
|
||||
aider/sendchat.py:
|
||||
Paul Gauthier: 3
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
tests/basic/test_editblock.py:
|
||||
Paul Gauthier: 23
|
||||
tests/basic/test_main.py:
|
||||
|
@ -2813,12 +2850,12 @@
|
|||
Paul Gauthier (aider): 46
|
||||
grand_total:
|
||||
Jonathan Ellis: 10
|
||||
Paul Gauthier: 93
|
||||
Paul Gauthier: 94
|
||||
Paul Gauthier (aider): 140
|
||||
Sven Grunewaldt: 24
|
||||
fry69: 18
|
||||
start_tag: v0.59.0
|
||||
total_lines: 285
|
||||
total_lines: 286
|
||||
- aider_percentage: 67.61
|
||||
aider_total: 860
|
||||
end_date: '2024-11-01'
|
||||
|
@ -2895,8 +2932,8 @@
|
|||
kAIto47802: 4
|
||||
start_tag: v0.60.0
|
||||
total_lines: 1272
|
||||
- aider_percentage: 84.0
|
||||
aider_total: 63
|
||||
- aider_percentage: 82.42
|
||||
aider_total: 75
|
||||
end_date: '2024-11-04'
|
||||
end_tag: v0.62.0
|
||||
file_counts:
|
||||
|
@ -2911,12 +2948,15 @@
|
|||
aider/models.py:
|
||||
Paul Gauthier: 5
|
||||
Paul Gauthier (aider): 45
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 4
|
||||
Paul Gauthier (aider): 12
|
||||
grand_total:
|
||||
Paul Gauthier: 12
|
||||
Paul Gauthier (aider): 63
|
||||
Paul Gauthier: 16
|
||||
Paul Gauthier (aider): 75
|
||||
start_tag: v0.61.0
|
||||
total_lines: 75
|
||||
- aider_percentage: 55.16
|
||||
total_lines: 91
|
||||
- aider_percentage: 55.08
|
||||
aider_total: 385
|
||||
end_date: '2024-11-13'
|
||||
end_tag: v0.63.0
|
||||
|
@ -2952,6 +2992,8 @@
|
|||
aider/sendchat.py:
|
||||
Paul Gauthier: 17
|
||||
Paul Gauthier (aider): 4
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
scripts/issues.py:
|
||||
Paul Gauthier: 4
|
||||
Paul Gauthier (aider): 195
|
||||
|
@ -2975,7 +3017,155 @@
|
|||
Paul Gauthier: 1
|
||||
grand_total:
|
||||
Logan Attwood: 29
|
||||
Paul Gauthier: 284
|
||||
Paul Gauthier: 285
|
||||
Paul Gauthier (aider): 385
|
||||
start_tag: v0.62.0
|
||||
total_lines: 698
|
||||
total_lines: 699
|
||||
- aider_percentage: 73.15
|
||||
aider_total: 880
|
||||
end_date: '2024-11-21'
|
||||
end_tag: v0.64.0
|
||||
file_counts:
|
||||
aider/__init__.py:
|
||||
Paul Gauthier: 1
|
||||
aider/analytics.py:
|
||||
Paul Gauthier: 20
|
||||
Paul Gauthier (aider): 21
|
||||
aider/args.py:
|
||||
Paul Gauthier: 2
|
||||
Paul Gauthier (aider): 10
|
||||
aider/coders/base_coder.py:
|
||||
Paul Gauthier: 15
|
||||
Paul Gauthier (aider): 3
|
||||
caetanominuzzo: 1
|
||||
aider/commands.py:
|
||||
Chad Phillips: 4
|
||||
Paul Gauthier: 5
|
||||
Paul Gauthier (aider): 19
|
||||
aider/editor.py:
|
||||
Chad Phillips: 133
|
||||
Paul Gauthier (aider): 13
|
||||
aider/exceptions.py:
|
||||
Paul Gauthier: 5
|
||||
aider/help_pats.py:
|
||||
Paul Gauthier: 1
|
||||
aider/io.py:
|
||||
Chad Phillips: 9
|
||||
Paul Gauthier (aider): 41
|
||||
mw: 21
|
||||
aider/main.py:
|
||||
Paul Gauthier: 21
|
||||
Paul Gauthier (aider): 41
|
||||
aider/models.py:
|
||||
Paul Gauthier: 41
|
||||
Paul Gauthier (aider): 33
|
||||
aider/repo.py:
|
||||
Paul Gauthier (aider): 5
|
||||
aider/urls.py:
|
||||
Paul Gauthier: 1
|
||||
aider/website/_includes/edit-leaderboard.js:
|
||||
Paul Gauthier (aider): 97
|
||||
aider/website/_includes/quant-chart.js:
|
||||
Paul Gauthier: 3
|
||||
Paul Gauthier (aider): 66
|
||||
aider/website/_includes/refactor-leaderboard.js:
|
||||
Paul Gauthier (aider): 90
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 10
|
||||
aider/website/share/index.md:
|
||||
Paul Gauthier (aider): 29
|
||||
benchmark/over_time.py:
|
||||
Paul Gauthier: 11
|
||||
Paul Gauthier (aider): 162
|
||||
scripts/blame.py:
|
||||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 2
|
||||
scripts/issues.py:
|
||||
Paul Gauthier: 5
|
||||
Paul Gauthier (aider): 12
|
||||
scripts/versionbump.py:
|
||||
Paul Gauthier: 7
|
||||
tests/basic/test_analytics.py:
|
||||
Paul Gauthier: 12
|
||||
Paul Gauthier (aider): 30
|
||||
tests/basic/test_commands.py:
|
||||
Paul Gauthier (aider): 4
|
||||
tests/basic/test_editor.py:
|
||||
Paul Gauthier (aider): 129
|
||||
tests/basic/test_main.py:
|
||||
Paul Gauthier (aider): 8
|
||||
tests/basic/test_models.py:
|
||||
Paul Gauthier: 3
|
||||
Paul Gauthier (aider): 55
|
||||
grand_total:
|
||||
Chad Phillips: 146
|
||||
Paul Gauthier: 155
|
||||
Paul Gauthier (aider): 880
|
||||
caetanominuzzo: 1
|
||||
mw: 21
|
||||
start_tag: v0.63.0
|
||||
total_lines: 1203
|
||||
- aider_percentage: 81.11
|
||||
aider_total: 584
|
||||
end_date: '2024-11-26'
|
||||
end_tag: v0.65.0
|
||||
file_counts:
|
||||
aider/__init__.py:
|
||||
Paul Gauthier: 1
|
||||
aider/analytics.py:
|
||||
Paul Gauthier: 2
|
||||
Paul Gauthier (aider): 5
|
||||
aider/args.py:
|
||||
Paul Gauthier (aider): 12
|
||||
aider/coders/base_coder.py:
|
||||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 31
|
||||
aider/commands.py:
|
||||
Paul Gauthier: 2
|
||||
aider/io.py:
|
||||
Paul Gauthier: 3
|
||||
Paul Gauthier (aider): 9
|
||||
aider/main.py:
|
||||
Paul Gauthier: 15
|
||||
Paul Gauthier (aider): 19
|
||||
aider/models.py:
|
||||
Paul Gauthier: 9
|
||||
Paul Gauthier (aider): 17
|
||||
aider/queries/tree-sitter-dart-tags.scm:
|
||||
malkoG: 91
|
||||
aider/urls.py:
|
||||
Paul Gauthier (aider): 1
|
||||
aider/website/_includes/quant-chart.js:
|
||||
Paul Gauthier (aider): 76
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
benchmark/benchmark.py:
|
||||
Paul Gauthier (aider): 10
|
||||
benchmark/docker.sh:
|
||||
Paul Gauthier (aider): 1
|
||||
benchmark/over_time.py:
|
||||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 157
|
||||
scripts/update-docs.sh:
|
||||
Paul Gauthier: 1
|
||||
scripts/update-history.py:
|
||||
Paul Gauthier: 8
|
||||
Paul Gauthier (aider): 64
|
||||
tests/basic/test_coder.py:
|
||||
Paul Gauthier (aider): 81
|
||||
tests/basic/test_editor.py:
|
||||
Paul Gauthier (aider): 16
|
||||
tests/basic/test_main.py:
|
||||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 42
|
||||
tests/basic/test_models.py:
|
||||
Paul Gauthier (aider): 30
|
||||
tests/basic/test_repomap.py:
|
||||
Paul Gauthier (aider): 13
|
||||
grand_total:
|
||||
Paul Gauthier: 45
|
||||
Paul Gauthier (aider): 584
|
||||
malkoG: 91
|
||||
start_tag: v0.64.0
|
||||
total_lines: 720
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- dirname: 2024-05-01-20-05-59--direct-opus-filenames-outside-fence
|
||||
test_cases: 133
|
||||
model: claude-3-opus-20240229
|
||||
released: 2024-02-29
|
||||
_released: 2024-02-29
|
||||
edit_format: diff
|
||||
commit_hash: f4b1797-dirty, f4b1797
|
||||
pass_rate_1: 53.4
|
||||
|
@ -46,7 +46,8 @@
|
|||
|
||||
- dirname: 2024-05-03-20-47-24--gemini-1.5-pro-diff-fenced
|
||||
test_cases: 133
|
||||
model: gemini-1.5-pro-latest
|
||||
released: 2024-05-03
|
||||
model: gemini-1.5-pro-001
|
||||
edit_format: diff-fenced
|
||||
commit_hash: 3a48dfb, 5d32dd7
|
||||
pass_rate_1: 45.9
|
||||
|
@ -274,7 +275,7 @@
|
|||
- dirname: 2024-05-03-22-24-48--openrouter--llama3-diff-examples-sys-msg
|
||||
test_cases: 132
|
||||
model: llama3-70b-8192
|
||||
released: 2024-04-18
|
||||
_released: 2024-04-18
|
||||
edit_format: diff
|
||||
commit_hash: b5bb453
|
||||
pass_rate_1: 38.6
|
||||
|
@ -297,7 +298,7 @@
|
|||
- dirname: 2024-05-06-18-31-08--command-r-plus-whole-final
|
||||
test_cases: 133
|
||||
model: command-r-plus
|
||||
released: 2024-04-04
|
||||
_released: 2024-04-04
|
||||
edit_format: whole
|
||||
commit_hash: fc3a43e-dirty
|
||||
pass_rate_1: 21.8
|
||||
|
@ -410,6 +411,7 @@
|
|||
- dirname: 2024-06-08-22-37-55--qwen2-72b-instruct-whole
|
||||
test_cases: 133
|
||||
model: Qwen2 72B Instruct
|
||||
released: 2024-06-08
|
||||
edit_format: whole
|
||||
commit_hash: 02c7335-dirty, 1a97498-dirty
|
||||
pass_rate_1: 44.4
|
||||
|
@ -623,7 +625,7 @@
|
|||
commit_hash: d31eef3-dirty
|
||||
pass_rate_1: 40.6
|
||||
pass_rate_2: 55.6
|
||||
released: 2024-07-18
|
||||
_released: 2024-07-18
|
||||
percent_cases_well_formed: 100.0
|
||||
error_outputs: 1
|
||||
num_malformed_responses: 0
|
||||
|
@ -671,7 +673,7 @@
|
|||
commit_hash: f7ce78b-dirty
|
||||
pass_rate_1: 46.6
|
||||
pass_rate_2: 63.9
|
||||
released: 2024-07-23
|
||||
_released: 2024-07-23
|
||||
percent_cases_well_formed: 92.5
|
||||
error_outputs: 84
|
||||
num_malformed_responses: 19
|
||||
|
@ -691,6 +693,7 @@
|
|||
- dirname: 2024-07-24-06-30-29--llama-405b-whole
|
||||
test_cases: 133
|
||||
model: llama-3.1-405b-instruct (whole)
|
||||
_released: 2024-07-23
|
||||
edit_format: whole
|
||||
commit_hash: a362dea-dirty
|
||||
pass_rate_1: 48.9
|
||||
|
@ -698,7 +701,6 @@
|
|||
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
|
||||
|
@ -770,7 +772,7 @@
|
|||
percent_cases_well_formed: 100.0
|
||||
error_outputs: 27
|
||||
num_malformed_responses: 0
|
||||
released: 2024-07-23
|
||||
_released: 2024-07-23
|
||||
num_with_malformed_responses: 0
|
||||
user_asks: 23
|
||||
lazy_comments: 8
|
||||
|
@ -796,7 +798,7 @@
|
|||
num_malformed_responses: 0
|
||||
num_with_malformed_responses: 0
|
||||
user_asks: 0
|
||||
released: 2024-07-23
|
||||
_released: 2024-07-23
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
|
@ -835,6 +837,7 @@
|
|||
- dirname: 2024-08-28-07-10-50--gemini-1.5-pro-exp-0827-diff-fenced
|
||||
test_cases: 133
|
||||
model: gemini-1.5-pro-exp-0827
|
||||
released: 2024-08-27
|
||||
edit_format: diff-fenced
|
||||
commit_hash: d8adc75
|
||||
pass_rate_1: 54.9
|
||||
|
@ -946,7 +949,7 @@
|
|||
versions: 0.54.13.dev
|
||||
seconds_per_case: 8.3
|
||||
total_cost: 0.0000
|
||||
released: 2024-09-04
|
||||
_released: 2024-09-04
|
||||
|
||||
- dirname: 2024-09-04-16-17-33--yi-coder-9b-chat-q4_0-whole
|
||||
test_cases: 133
|
||||
|
@ -973,6 +976,7 @@
|
|||
|
||||
- dirname: 2024-09-05-14-50-11--deepseek-sep5-no-shell
|
||||
test_cases: 133
|
||||
released: 2024-09-05
|
||||
model: DeepSeek V2.5
|
||||
edit_format: diff
|
||||
commit_hash: 1279c86
|
||||
|
@ -1112,6 +1116,7 @@
|
|||
- dirname: 2024-09-21-16-45-11--o1-preview-flex-sr-markers
|
||||
test_cases: 133
|
||||
model: o1-preview
|
||||
_released: 2024-09-12
|
||||
edit_format: diff
|
||||
commit_hash: 5493654-dirty
|
||||
pass_rate_1: 57.9
|
||||
|
@ -1204,6 +1209,7 @@
|
|||
- dirname: 2024-09-24-16-26-45--gemini-1.5-pro-002-diff-fenced
|
||||
test_cases: 133
|
||||
model: gemini-1.5-pro-002
|
||||
released: 2024-09-24
|
||||
edit_format: diff-fenced
|
||||
commit_hash: 6b5fe9b, 3edcd71
|
||||
pass_rate_1: 49.6
|
||||
|
@ -1477,6 +1483,7 @@
|
|||
- dirname: 2024-10-04-16-30-08--chatgpt-4o-latest-diff-oct4
|
||||
test_cases: 133
|
||||
model: openai/chatgpt-4o-latest
|
||||
released: 2024-10-04
|
||||
edit_format: diff
|
||||
commit_hash: af10953
|
||||
pass_rate_1: 56.4
|
||||
|
@ -1592,6 +1599,7 @@
|
|||
- dirname: 2024-10-22-17-45-28--sonnet-1022-diff-fixed-model-settings
|
||||
test_cases: 133
|
||||
model: claude-3-5-sonnet-20241022
|
||||
released: 2024-10-22
|
||||
edit_format: diff
|
||||
commit_hash: 3b14eb9
|
||||
pass_rate_1: 69.2
|
||||
|
@ -1615,6 +1623,7 @@
|
|||
- dirname: 2024-11-04-19-19-32--haiku35-diff-ex-as-sys-false
|
||||
test_cases: 133
|
||||
model: claude-3-5-haiku-20241022
|
||||
released: 2024-10-22
|
||||
edit_format: diff
|
||||
commit_hash: 03bbdb0-dirty
|
||||
pass_rate_1: 61.7
|
||||
|
@ -1773,32 +1782,10 @@
|
|||
seconds_per_case: 18.3
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-09-10-57-11--Qwen2.5-Coder-32B-Instruct
|
||||
test_cases: 133
|
||||
model: Qwen2.5-Coder-32B-Instruct (whole)
|
||||
edit_format: whole
|
||||
commit_hash: ec9982a
|
||||
pass_rate_1: 60.9
|
||||
pass_rate_2: 73.7
|
||||
percent_cases_well_formed: 100.0
|
||||
error_outputs: 1
|
||||
num_malformed_responses: 0
|
||||
num_with_malformed_responses: 0
|
||||
user_asks: 1
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 1
|
||||
test_timeouts: 1
|
||||
command: aider --model openai/Qwen2.5-Coder-32B-Instruct
|
||||
date: 2024-11-09
|
||||
versions: 0.59.2.dev
|
||||
seconds_per_case: 26.6
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-09-11-09-15--Qwen2.5-Coder-32B-Instruct
|
||||
test_cases: 133
|
||||
model: Qwen2.5-Coder-32B-Instruct (diff)
|
||||
model: Qwen2.5-Coder-32B-Instruct
|
||||
released: 2024-11-12
|
||||
edit_format: diff
|
||||
commit_hash: ec9982a
|
||||
pass_rate_1: 59.4
|
||||
|
@ -1813,8 +1800,149 @@
|
|||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 3
|
||||
command: aider --model openai/Qwen2.5-Coder-32B-Instruct
|
||||
command: aider --model openai/hf:Qwen/Qwen2.5-Coder-32B-Instruct --openai-api-base https://glhf.chat/api/openai/v1
|
||||
date: 2024-11-09
|
||||
versions: 0.59.2.dev
|
||||
seconds_per_case: 22.5
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-20-14-57-11--mistral-2411-direct-diff
|
||||
test_cases: 133
|
||||
model: Mistral Large (2411)
|
||||
released: 2024-11-18
|
||||
edit_format: diff
|
||||
commit_hash: dba844c
|
||||
pass_rate_1: 46.6
|
||||
pass_rate_2: 65.4
|
||||
percent_cases_well_formed: 96.2
|
||||
error_outputs: 8
|
||||
num_malformed_responses: 8
|
||||
num_with_malformed_responses: 5
|
||||
user_asks: 5
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 1
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 1
|
||||
command: aider --model mistral/mistral-large-latest
|
||||
date: 2024-11-20
|
||||
versions: 0.63.3.dev
|
||||
seconds_per_case: 24.9
|
||||
total_cost: 3.2334
|
||||
|
||||
- dirname: 2024-11-20-19-28-30--gpt-4o-2024-11-20
|
||||
test_cases: 133
|
||||
model: gpt-4o-2024-11-20
|
||||
released: 2024-11-20
|
||||
edit_format: diff
|
||||
commit_hash: 2ac0776-dirty
|
||||
pass_rate_1: 58.6
|
||||
pass_rate_2: 71.4
|
||||
percent_cases_well_formed: 99.2
|
||||
error_outputs: 1
|
||||
num_malformed_responses: 1
|
||||
num_with_malformed_responses: 1
|
||||
user_asks: 4
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 5
|
||||
command: aider --model openai/gpt-4o-2024-11-20
|
||||
date: 2024-11-20
|
||||
versions: 0.63.3.dev
|
||||
seconds_per_case: 6.0
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-09-20-21-47-17--qwen2.5-32b-instruct-q8_0-whole
|
||||
test_cases: 133
|
||||
model: ollama/qwen2.5:32b-instruct-q8_0
|
||||
edit_format: whole
|
||||
commit_hash: 2753ac6
|
||||
pass_rate_1: 46.6
|
||||
pass_rate_2: 58.6
|
||||
percent_cases_well_formed: 100.0
|
||||
error_outputs: 0
|
||||
num_malformed_responses: 0
|
||||
num_with_malformed_responses: 0
|
||||
user_asks: 1
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 2
|
||||
command: aider --model ollama/qwen2.5:32b-instruct-q8_0
|
||||
date: 2024-09-20
|
||||
versions: 0.56.1.dev
|
||||
seconds_per_case: 1763.7
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-20-15-17-37--qwen25-32b-or-diff
|
||||
test_cases: 133
|
||||
model: openrouter/qwen/qwen-2.5-coder-32b-instruct
|
||||
edit_format: diff
|
||||
commit_hash: e917424
|
||||
pass_rate_1: 49.6
|
||||
pass_rate_2: 65.4
|
||||
percent_cases_well_formed: 84.2
|
||||
error_outputs: 43
|
||||
num_malformed_responses: 31
|
||||
num_with_malformed_responses: 21
|
||||
user_asks: 43
|
||||
lazy_comments: 0
|
||||
syntax_errors: 2
|
||||
indentation_errors: 2
|
||||
exhausted_context_windows: 12
|
||||
test_timeouts: 2
|
||||
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
|
||||
date: 2024-11-20
|
||||
versions: 0.63.3.dev
|
||||
seconds_per_case: 40.7
|
||||
total_cost: 0.1497
|
||||
|
||||
- dirname: 2024-11-21-17-46-36--gemini-exp-1121-diff
|
||||
test_cases: 133
|
||||
model: gemini-exp-1121
|
||||
released: 2024-11-21
|
||||
edit_format: diff
|
||||
commit_hash: e94961a
|
||||
pass_rate_1: 46.6
|
||||
pass_rate_2: 57.9
|
||||
percent_cases_well_formed: 83.5
|
||||
error_outputs: 101
|
||||
num_malformed_responses: 101
|
||||
num_with_malformed_responses: 22
|
||||
user_asks: 5
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 2
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 3
|
||||
command: aider --model gemini/gemini-exp-1121
|
||||
date: 2024-11-21
|
||||
versions: 0.63.3.dev
|
||||
seconds_per_case: 60.3
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-15-20-33-31--gemini-exp-1114-diff
|
||||
test_cases: 133
|
||||
model: gemini-exp-1114
|
||||
released: 2024-11-14
|
||||
edit_format: diff
|
||||
commit_hash: 0bf17a4
|
||||
pass_rate_1: 50.4
|
||||
pass_rate_2: 60.9
|
||||
percent_cases_well_formed: 85.7
|
||||
error_outputs: 70
|
||||
num_malformed_responses: 70
|
||||
num_with_malformed_responses: 19
|
||||
user_asks: 2
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 4
|
||||
command: aider --model gemini/gemini-exp-1114
|
||||
date: 2024-11-15
|
||||
versions: 0.63.2.dev
|
||||
seconds_per_case: 38.6
|
299
aider/website/_data/quant.yml
Normal file
299
aider/website/_data/quant.yml
Normal file
|
@ -0,0 +1,299 @@
|
|||
- dirname: 2024-11-09-11-09-15--Qwen2.5-Coder-32B-Instruct
|
||||
test_cases: 133
|
||||
model: "HuggingFace via GLHF: BF16"
|
||||
released: 2024-11-12
|
||||
edit_format: diff
|
||||
commit_hash: ec9982a
|
||||
pass_rate_1: 59.4
|
||||
pass_rate_2: 71.4
|
||||
percent_cases_well_formed: 94.7
|
||||
error_outputs: 17
|
||||
num_malformed_responses: 17
|
||||
num_with_malformed_responses: 7
|
||||
user_asks: 1
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 3
|
||||
command: aider --model openai/hf:Qwen/Qwen2.5-Coder-32B-Instruct --openai-api-base https://glhf.chat/api/openai/v1
|
||||
date: 2024-11-09
|
||||
versions: 0.59.2.dev
|
||||
seconds_per_case: 22.5
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-22-18-56-13--ollama-qwen2.5-coder:32b-instruct-fp16
|
||||
test_cases: 132
|
||||
model: "Ollama: fp16"
|
||||
edit_format: diff
|
||||
commit_hash: f06452c-dirty, 6a0a97c-dirty, 4e9ae16-dirty, 5506d0f-dirty
|
||||
pass_rate_1: 58.3
|
||||
pass_rate_2: 71.4
|
||||
percent_cases_well_formed: 90.2
|
||||
error_outputs: 27
|
||||
num_malformed_responses: 26
|
||||
num_with_malformed_responses: 13
|
||||
user_asks: 2
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 0
|
||||
command: aider --model ollama/qwen2.5-coder:32b-instruct-fp16
|
||||
date: 2024-11-22
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 119.6
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-22-14-53-26--hyperbolic-qwen25coder32binstruct
|
||||
test_cases: 133
|
||||
model: "Hyperbolic: BF16"
|
||||
edit_format: diff
|
||||
commit_hash: f9ef161, 17aef7b-dirty
|
||||
pass_rate_1: 57.9
|
||||
pass_rate_2: 69.2
|
||||
percent_cases_well_formed: 91.7
|
||||
error_outputs: 30
|
||||
num_malformed_responses: 29
|
||||
num_with_malformed_responses: 11
|
||||
user_asks: 9
|
||||
lazy_comments: 0
|
||||
syntax_errors: 4
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 2
|
||||
command: aider --model openai/Qwen/Qwen2.5-Coder-32B-Instruct --openai-api-base https://api.hyperbolic.xyz/v1/
|
||||
date: 2024-11-22
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 33.2
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-22-17-53-35--qwen25-coder-32b-Instruct-4bit
|
||||
test_cases: 133
|
||||
model: "mlx-community: 4bit"
|
||||
edit_format: diff
|
||||
commit_hash: a16dcab-dirty
|
||||
pass_rate_1: 60.2
|
||||
pass_rate_2: 72.2
|
||||
percent_cases_well_formed: 88.7
|
||||
error_outputs: 31
|
||||
num_malformed_responses: 30
|
||||
num_with_malformed_responses: 15
|
||||
user_asks: 6
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 1
|
||||
test_timeouts: 0
|
||||
command: aider --model openai/mlx-community/Qwen2.5-Coder-32B-Instruct-4bit
|
||||
date: 2024-11-23
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 53.4
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-23-15-07-20--qwen25-coder-32b-Instruct-8bit
|
||||
test_cases: 133
|
||||
model: "mlx-community: 8bit"
|
||||
edit_format: diff
|
||||
commit_hash: a16dcab-dirty
|
||||
pass_rate_1: 59.4
|
||||
pass_rate_2: 72.2
|
||||
percent_cases_well_formed: 92.5
|
||||
error_outputs: 20
|
||||
num_malformed_responses: 15
|
||||
num_with_malformed_responses: 10
|
||||
user_asks: 7
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 5
|
||||
test_timeouts: 2
|
||||
command: aider --model openai/mlx-community/Qwen2.5-Coder-32B-Instruct-8bit
|
||||
date: 2024-11-23
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 98.4
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-24-22-18-18--or-all-or-fixed-blank-messages2
|
||||
test_cases: 133
|
||||
model: "OpenRouter: multiple"
|
||||
edit_format: diff
|
||||
commit_hash: 0c59d32
|
||||
pass_rate_1: 57.1
|
||||
pass_rate_2: 67.7
|
||||
percent_cases_well_formed: 95.5
|
||||
error_outputs: 56
|
||||
num_malformed_responses: 10
|
||||
num_with_malformed_responses: 6
|
||||
user_asks: 14
|
||||
lazy_comments: 0
|
||||
syntax_errors: 6
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 3
|
||||
test_timeouts: 1
|
||||
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
|
||||
date: 2024-11-24
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 21.2
|
||||
total_cost: 0.1420
|
||||
|
||||
- dirname: 2024-11-23-21-08-53--ollama-qwen2.5-coder:32b-instruct-q4_K_M-8kctx
|
||||
test_cases: 133
|
||||
model: "Ollama: q4_K_M"
|
||||
edit_format: diff
|
||||
commit_hash: baa1335-dirty, e63df83-dirty, ff8c1aa-dirty
|
||||
pass_rate_1: 54.9
|
||||
pass_rate_2: 66.9
|
||||
percent_cases_well_formed: 94.0
|
||||
error_outputs: 21
|
||||
num_malformed_responses: 21
|
||||
num_with_malformed_responses: 8
|
||||
user_asks: 5
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 3
|
||||
command: aider --model ollama/qwen2.5-coder:32b-instruct-q4_K_M
|
||||
date: 2024-11-23
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 35.7
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-24-02-23-32--deepinfra-qwen-diff
|
||||
test_cases: 133
|
||||
model: "Deepinfra: BF16"
|
||||
edit_format: diff
|
||||
commit_hash: bb78e2f
|
||||
pass_rate_1: 58.6
|
||||
pass_rate_2: 72.2
|
||||
percent_cases_well_formed: 94.7
|
||||
error_outputs: 15
|
||||
num_malformed_responses: 13
|
||||
num_with_malformed_responses: 7
|
||||
user_asks: 3
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 2
|
||||
test_timeouts: 3
|
||||
command: aider --model deepinfra/Qwen/Qwen2.5-Coder-32B-Instruct
|
||||
date: 2024-11-24
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 17.5
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-24-04-12-58--fireworks-qwen-diff
|
||||
test_cases: 133
|
||||
model: "Fireworks: unknown"
|
||||
edit_format: diff
|
||||
commit_hash: 757eac0
|
||||
pass_rate_1: 57.9
|
||||
pass_rate_2: 72.2
|
||||
percent_cases_well_formed: 94.0
|
||||
error_outputs: 23
|
||||
num_malformed_responses: 19
|
||||
num_with_malformed_responses: 8
|
||||
user_asks: 8
|
||||
lazy_comments: 0
|
||||
syntax_errors: 6
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 4
|
||||
test_timeouts: 1
|
||||
command: aider --model fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct
|
||||
date: 2024-11-24
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 10.4
|
||||
total_cost: 0.5759
|
||||
|
||||
- dirname: 2024-11-24-02-04-59--ollama-qwen2.5-coder:32b-instruct-q2_K-8kctx
|
||||
test_cases: 133
|
||||
model: "Ollama: q2_K"
|
||||
edit_format: diff
|
||||
commit_hash: 757eac0, bb78e2f, 8d0ba40-dirty, 1d09e96
|
||||
pass_rate_1: 48.9
|
||||
pass_rate_2: 61.7
|
||||
percent_cases_well_formed: 91.7
|
||||
error_outputs: 32
|
||||
num_malformed_responses: 32
|
||||
num_with_malformed_responses: 11
|
||||
user_asks: 8
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 1
|
||||
command: aider --model ollama/qwen2.5-coder:32b-instruct-q2_K
|
||||
date: 2024-11-24
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 97.8
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-11-24-14-56-49--qwen25-32b-or-fireworks
|
||||
test_cases: 133
|
||||
model: "Fireworks via OpenRouter: unknown"
|
||||
edit_format: diff
|
||||
commit_hash: c2f184f
|
||||
pass_rate_1: 55.6
|
||||
pass_rate_2: 67.7
|
||||
percent_cases_well_formed: 94.0
|
||||
error_outputs: 39
|
||||
num_malformed_responses: 24
|
||||
num_with_malformed_responses: 8
|
||||
user_asks: 13
|
||||
lazy_comments: 0
|
||||
syntax_errors: 1
|
||||
indentation_errors: 1
|
||||
exhausted_context_windows: 7
|
||||
test_timeouts: 4
|
||||
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
|
||||
date: 2024-11-24
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 16.1
|
||||
total_cost: 0.1391
|
||||
|
||||
- dirname: 2024-11-24-22-03-19--or-hyperbolic-or-fixed-blank-messages2
|
||||
test_cases: 133
|
||||
model: "Hyperbolic via OpenRouter: BF16"
|
||||
edit_format: diff
|
||||
commit_hash: 0c59d32
|
||||
pass_rate_1: 55.6
|
||||
pass_rate_2: 68.4
|
||||
percent_cases_well_formed: 89.5
|
||||
error_outputs: 28
|
||||
num_malformed_responses: 24
|
||||
num_with_malformed_responses: 14
|
||||
user_asks: 29
|
||||
lazy_comments: 0
|
||||
syntax_errors: 1
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 4
|
||||
test_timeouts: 1
|
||||
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
|
||||
date: 2024-11-24
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 41.5
|
||||
total_cost: 0.1402
|
||||
|
||||
- dirname: 2024-11-24-15-00-50--qwen25-32b-or-deepinfra
|
||||
test_cases: 133
|
||||
model: "Deepinfra via OpenRouter: BF16"
|
||||
edit_format: diff
|
||||
commit_hash: c2f184f
|
||||
pass_rate_1: 57.1
|
||||
pass_rate_2: 69.9
|
||||
percent_cases_well_formed: 89.5
|
||||
error_outputs: 35
|
||||
num_malformed_responses: 31
|
||||
num_with_malformed_responses: 14
|
||||
user_asks: 11
|
||||
lazy_comments: 0
|
||||
syntax_errors: 1
|
||||
indentation_errors: 1
|
||||
exhausted_context_windows: 4
|
||||
test_timeouts: 1
|
||||
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
|
||||
date: 2024-11-24
|
||||
versions: 0.64.2.dev
|
||||
seconds_per_case: 28.5
|
||||
total_cost: 0.1390
|
97
aider/website/_includes/edit-leaderboard.js
Normal file
97
aider/website/_includes/edit-leaderboard.js
Normal file
|
@ -0,0 +1,97 @@
|
|||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var ctx = document.getElementById('editChart').getContext('2d');
|
||||
const HIGHTLIGHT_MODEL = 'no no no no';
|
||||
var leaderboardData = {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Percent completed correctly',
|
||||
data: [],
|
||||
backgroundColor: function(context) {
|
||||
const label = context.chart.data.labels[context.dataIndex] || '';
|
||||
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)';
|
||||
},
|
||||
borderColor: function(context) {
|
||||
const label = context.chart.data.labels[context.dataIndex] || '';
|
||||
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)';
|
||||
},
|
||||
borderWidth: 1
|
||||
}]
|
||||
};
|
||||
|
||||
var allData = [];
|
||||
{% for row in edit_sorted %}
|
||||
allData.push({
|
||||
model: '{{ row.model }}',
|
||||
pass_rate_2: {{ row.pass_rate_2 }},
|
||||
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
function updateChart() {
|
||||
var selectedRows = document.querySelectorAll('tr.selected');
|
||||
var showAll = selectedRows.length === 0;
|
||||
|
||||
leaderboardData.labels = [];
|
||||
leaderboardData.datasets[0].data = [];
|
||||
|
||||
allData.forEach(function(row, index) {
|
||||
var rowElement = document.getElementById('edit-row-' + index);
|
||||
if (showAll) {
|
||||
rowElement.classList.remove('selected');
|
||||
}
|
||||
if (showAll || rowElement.classList.contains('selected')) {
|
||||
leaderboardData.labels.push(row.model);
|
||||
leaderboardData.datasets[0].data.push(row.pass_rate_2);
|
||||
}
|
||||
});
|
||||
|
||||
leaderboardChart.update();
|
||||
}
|
||||
|
||||
var tableBody = document.querySelector('table tbody');
|
||||
allData.forEach(function(row, index) {
|
||||
var tr = tableBody.children[index];
|
||||
tr.id = 'edit-row-' + index;
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.onclick = function() {
|
||||
this.classList.toggle('selected');
|
||||
updateChart();
|
||||
};
|
||||
});
|
||||
|
||||
var leaderboardChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: leaderboardData,
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateChart();
|
||||
|
||||
// Add search functionality for edit table
|
||||
document.getElementById('editSearchInput').addEventListener('keyup', function() {
|
||||
var searchWords = this.value.toLowerCase().split(' ').filter(word => word.length > 0);
|
||||
var tableBody = document.querySelector('table:first-of-type tbody');
|
||||
var rows = tableBody.getElementsByTagName('tr');
|
||||
|
||||
leaderboardData.labels = [];
|
||||
leaderboardData.datasets[0].data = [];
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var rowText = rows[i].textContent;
|
||||
if (searchWords.every(word => rowText.toLowerCase().includes(word))) {
|
||||
rows[i].style.display = '';
|
||||
leaderboardData.labels.push(allData[i].model);
|
||||
leaderboardData.datasets[0].data.push(allData[i].pass_rate_2);
|
||||
} else {
|
||||
rows[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
leaderboardChart.update();
|
||||
});
|
||||
});
|
0
aider/website/_includes/leaderboard.js
Normal file
0
aider/website/_includes/leaderboard.js
Normal file
|
@ -1,5 +1,15 @@
|
|||
You can send long, multi-line messages in the chat in a few ways:
|
||||
- Paste a multi-line message directly into the chat.
|
||||
- Enter `{` alone on the first line to start a multiline message and `}` alone on the last line to end it.
|
||||
- Or, start with `{tag` (where "tag" is any sequence of letters/numbers) and end with `tag}`. This is useful when you need to include closing braces `}` in your message.
|
||||
- Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments).
|
||||
- Use `/paste` to paste text from the clipboard into the chat.
|
||||
- Use the `/editor` command to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
|
||||
|
||||
Example with a tag:
|
||||
```
|
||||
{python
|
||||
def hello():
|
||||
print("Hello}") # Note: contains a brace
|
||||
python}
|
||||
```
|
||||
|
|
95
aider/website/_includes/quant-chart.js
Normal file
95
aider/website/_includes/quant-chart.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var ctx = document.getElementById('quantChart').getContext('2d');
|
||||
var allData = [];
|
||||
{% for row in site.data.quant %}
|
||||
allData.push({
|
||||
model: '{{ row.model }}',
|
||||
pass_rate_2: {{ row.pass_rate_2 }}
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
// Sort data by pass_rate_2 in descending order
|
||||
allData.sort((a, b) => b.pass_rate_2 - a.pass_rate_2);
|
||||
|
||||
var chart;
|
||||
|
||||
function updateChart(filterText) {
|
||||
var filteredData = allData.filter(row =>
|
||||
row.model.toLowerCase().includes(filterText.toLowerCase())
|
||||
);
|
||||
|
||||
var chartData = {
|
||||
labels: filteredData.map(row => row.model),
|
||||
datasets: [{
|
||||
label: 'Percent completed correctly',
|
||||
data: filteredData.map(row => row.pass_rate_2),
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
||||
borderColor: 'rgba(54, 162, 235, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
};
|
||||
|
||||
if (chart) {
|
||||
chart.data = chartData;
|
||||
chart.update();
|
||||
} else {
|
||||
chart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: chartData,
|
||||
options: {
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Aider code editing benchmark',
|
||||
font: {
|
||||
size: 16
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Percent completed correctly',
|
||||
font: {
|
||||
size: 14
|
||||
}
|
||||
},
|
||||
ticks: {
|
||||
font: {
|
||||
size: 16
|
||||
}
|
||||
}
|
||||
},
|
||||
x: {
|
||||
ticks: {
|
||||
font: {
|
||||
size: 16
|
||||
}
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Provider: quantization',
|
||||
font: {
|
||||
size: 14
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initial chart render
|
||||
updateChart('');
|
||||
|
||||
// Connect search input to chart filtering
|
||||
document.getElementById('quantSearchInput').addEventListener('keyup', function() {
|
||||
updateChart(this.value);
|
||||
});
|
||||
});
|
90
aider/website/_includes/refactor-leaderboard.js
Normal file
90
aider/website/_includes/refactor-leaderboard.js
Normal file
|
@ -0,0 +1,90 @@
|
|||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var ctx = document.getElementById('refacChart').getContext('2d');
|
||||
var leaderboardData = {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Percent completed correctly',
|
||||
data: [],
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
||||
borderColor: 'rgba(54, 162, 235, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
};
|
||||
|
||||
var allData = [];
|
||||
{% for row in refac_sorted %}
|
||||
allData.push({
|
||||
model: '{{ row.model }}',
|
||||
pass_rate_1: {{ row.pass_rate_1 }},
|
||||
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
function updateChart() {
|
||||
var selectedRows = document.querySelectorAll('tr.selected');
|
||||
var showAll = selectedRows.length === 0;
|
||||
|
||||
leaderboardData.labels = [];
|
||||
leaderboardData.datasets[0].data = [];
|
||||
|
||||
allData.forEach(function(row, index) {
|
||||
var rowElement = document.getElementById('refac-row-' + index);
|
||||
if (showAll) {
|
||||
rowElement.classList.remove('selected');
|
||||
}
|
||||
if (showAll || rowElement.classList.contains('selected')) {
|
||||
leaderboardData.labels.push(row.model);
|
||||
leaderboardData.datasets[0].data.push(row.pass_rate_1);
|
||||
}
|
||||
});
|
||||
|
||||
leaderboardChart.update();
|
||||
}
|
||||
|
||||
var tableBody = document.querySelectorAll('table tbody')[1];
|
||||
allData.forEach(function(row, index) {
|
||||
var tr = tableBody.children[index];
|
||||
tr.id = 'refac-row-' + index;
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.onclick = function() {
|
||||
this.classList.toggle('selected');
|
||||
updateChart();
|
||||
};
|
||||
});
|
||||
|
||||
var leaderboardChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: leaderboardData,
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateChart();
|
||||
|
||||
// Add search functionality for refactoring table
|
||||
document.getElementById('refacSearchInput').addEventListener('keyup', function() {
|
||||
var searchWords = this.value.toLowerCase().split(' ').filter(word => word.length > 0);
|
||||
var tableBody = document.querySelectorAll('table tbody')[1];
|
||||
var rows = tableBody.getElementsByTagName('tr');
|
||||
|
||||
leaderboardData.labels = [];
|
||||
leaderboardData.datasets[0].data = [];
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var rowText = rows[i].textContent;
|
||||
if (searchWords.every(word => rowText.toLowerCase().includes(word))) {
|
||||
rows[i].style.display = '';
|
||||
leaderboardData.labels.push(allData[i].model);
|
||||
leaderboardData.datasets[0].data.push(allData[i].pass_rate_1);
|
||||
} else {
|
||||
rows[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
leaderboardChart.update();
|
||||
});
|
||||
});
|
169
aider/website/_posts/2024-11-21-quantization.md
Normal file
169
aider/website/_posts/2024-11-21-quantization.md
Normal file
|
@ -0,0 +1,169 @@
|
|||
---
|
||||
title: Details matter with open source models
|
||||
excerpt: Open source LLMs are becoming very powerful, but pay attention to how you (or your provider) are serving the model. It can affect code editing skill.
|
||||
highlight_image: /assets/quantization.jpg
|
||||
draft: false
|
||||
nav_exclude: true
|
||||
---
|
||||
{% if page.date %}
|
||||
<p class="post-date">{{ page.date | date: "%B %d, %Y" }}</p>
|
||||
{% endif %}
|
||||
|
||||
# Details matter with open source models
|
||||
{: .no_toc }
|
||||
|
||||
Open source models like Qwen 2.5 32B Instruct are performing very well on
|
||||
aider's code editing benchmark, rivaling closed source frontier models.
|
||||
|
||||
But pay attention to how your model is being served and quantized,
|
||||
as it can impact code editing skill.
|
||||
Open source models are often available at a variety of quantizations,
|
||||
and can be served with different token limits.
|
||||
These details matter when working with code.
|
||||
|
||||
The graph and table below compares different versions of the Qwen 2.5 Coder 32B Instruct model,
|
||||
served both locally and from a variety of cloud providers.
|
||||
|
||||
- The [HuggingFace BF16 weights](https://huggingface.co/Qwen/Qwen2.5-Coder-32B-Instruct) served via [glhf.chat](https://glhf.chat).
|
||||
- [4bit and 8bit quants for mlx](https://t.co/cwX3DYX35D).
|
||||
- The results from [OpenRouter's mix of providers](https://openrouter.ai/qwen/qwen-2.5-coder-32b-instruct/providers) which serve the model with different levels of quantization.
|
||||
- Results from individual providers served via OpenRouter and directly to their own APIs.
|
||||
- Ollama locally serving different quantizations from the [Ollama model library](https://ollama.com/library/qwen2.5-coder:32b-instruct-q4_K_M).
|
||||
|
||||
The best versions of the model rival GPT-4o, while the worst performer
|
||||
is more like the older GPT-4 Turbo.
|
||||
Suboptimal choices in quantization and token limits can
|
||||
easily produce far worse results.
|
||||
|
||||
This benchmarking effort highlighted a number of pitfalls and details which
|
||||
can have a significant impact on the model's ability to correctly edit code:
|
||||
|
||||
- Quantization -- Open source models are often available at dozens of different quantizations.
|
||||
- Context window -- Cloud providers can decide how large a context window to accept,
|
||||
and they often choose differently. Ollama defaults to a tiny 2k context window,
|
||||
and silently discards data that exceeds it.
|
||||
- Output token limits -- Open source models are often served with wildly
|
||||
differing output token limits. This has a direct impact on how much code the
|
||||
model can write or edit in a response.
|
||||
- Buggy cloud providers -- Between Qwen and DeepSeep, there were
|
||||
multiple cloud providers with broken or buggy API endpoints that seemed
|
||||
to be returning result different from expected based on the advertised
|
||||
quantization and context sizes.
|
||||
|
||||
|
||||
### Sections
|
||||
{: .no_toc }
|
||||
|
||||
- TOC
|
||||
{:toc}
|
||||
|
||||
## Benchmark results
|
||||
|
||||
<canvas id="quantChart" width="800" height="600" style="margin: 20px 0"></canvas>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
{% include quant-chart.js %}
|
||||
</script>
|
||||
|
||||
<input type="text" id="quantSearchInput" placeholder="Search..." style="width: 100%; max-width: 800px; margin: 10px auto; padding: 8px; display: block; border: 1px solid #ddd; border-radius: 4px;">
|
||||
|
||||
<table style="width: 100%; max-width: 800px; margin: auto; border-collapse: collapse; box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 14px;">
|
||||
<thead style="background-color: #f2f2f2;">
|
||||
<tr>
|
||||
<th style="padding: 8px; text-align: left;">Model</th>
|
||||
<th style="padding: 8px; text-align: center;">Percent completed correctly</th>
|
||||
<th style="padding: 8px; text-align: center;">Percent using correct edit format</th>
|
||||
<th style="padding: 8px; text-align: left;">Command</th>
|
||||
<th style="padding: 8px; text-align: center;">Edit format</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% assign quant_sorted = site.data.quant | sort: 'pass_rate_2' | reverse %}
|
||||
{% for row in quant_sorted %}
|
||||
<tr style="border-bottom: 1px solid #ddd;">
|
||||
<td style="padding: 8px;">{{ row.model }}</td>
|
||||
<td style="padding: 8px; text-align: center;">{{ row.pass_rate_2 }}%</td>
|
||||
<td style="padding: 8px; text-align: center;">{{ row.percent_cases_well_formed }}%</td>
|
||||
<td style="padding: 8px;"><code>{{ row.command }}</code></td>
|
||||
<td style="padding: 8px; text-align: center;">{{ row.edit_format }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
tr.selected {
|
||||
color: #0056b3;
|
||||
}
|
||||
table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
td, th {
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
td:nth-child(3), td:nth-child(4) {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
document.getElementById('quantSearchInput').addEventListener('keyup', function() {
|
||||
var input = this.value.toLowerCase();
|
||||
var rows = document.querySelectorAll('tbody tr');
|
||||
|
||||
rows.forEach(function(row) {
|
||||
var text = row.textContent.toLowerCase();
|
||||
if(text.includes(input)) {
|
||||
row.style.display = '';
|
||||
row.classList.add('selected');
|
||||
} else {
|
||||
row.style.display = 'none';
|
||||
row.classList.remove('selected');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
## Setting Ollama's context window size
|
||||
|
||||
[Ollama uses a 2k context window by default](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-specify-the-context-window-size),
|
||||
which is very small for working with aider.
|
||||
Unlike most other LLM servers, Ollama does not throw an error if you submit
|
||||
a request that exceeds the context window.
|
||||
Instead, it just silently truncates the request by discarding the "oldest" messages
|
||||
in the chat to make it fit within the context window.
|
||||
|
||||
All of the Ollama results above were collected with at least an 8k context window, which
|
||||
is large enough to attempt all the coding problems in the benchmark.
|
||||
Aider sets Ollama's context window to 8k by default.
|
||||
|
||||
You can change the Ollama server's context window with a
|
||||
[`.aider.model.settings.yml` file](https://aider.chat/docs/config/adv-model-settings.html#model-settings)
|
||||
like this:
|
||||
|
||||
```
|
||||
- name: ollama/qwen2.5-coder:32b-instruct-fp16
|
||||
extra_params:
|
||||
num_ctx: 8192
|
||||
```
|
||||
|
||||
## Choosing providers with OpenRouter
|
||||
|
||||
OpenRouter allows you to ignore specific providers in your
|
||||
[preferences](https://openrouter.ai/settings/preferences).
|
||||
This can be used to limit your OpenRouter requests to be
|
||||
served by only your preferred providers.
|
||||
|
||||
## Notes
|
||||
|
||||
This article went through many revisions as I received feedback from
|
||||
numerous members of the community.
|
||||
Here are some of the noteworthy learnings and changes:
|
||||
|
||||
- The first version of this article included incorrect Ollama models.
|
||||
- Earlier Ollama results used the too small default 2k context window,
|
||||
artificially harming the benchmark results.
|
||||
- The benchmark results appear to have uncovered a problem in the way
|
||||
OpenRouter was communicating with Hyperbolic.
|
||||
They fixed the issue 11/24/24, shortly after it was pointed out.
|
Binary file not shown.
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 103 KiB |
File diff suppressed because it is too large
Load diff
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 59 KiB |
BIN
aider/website/assets/quantization.jpg
Normal file
BIN
aider/website/assets/quantization.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 KiB |
File diff suppressed because it is too large
Load diff
|
@ -86,6 +86,14 @@
|
|||
## Specify a file with context window and costs for unknown models
|
||||
#model-metadata-file: .aider.model.metadata.json
|
||||
|
||||
## Add a model alias (can be used multiple times)
|
||||
#alias: xxx
|
||||
## Specify multiple values like this:
|
||||
#alias:
|
||||
# - xxx
|
||||
# - yyy
|
||||
# - zzz
|
||||
|
||||
## Verify the SSL cert when connecting to models (default: True)
|
||||
#verify-ssl: true
|
||||
|
||||
|
@ -271,8 +279,8 @@
|
|||
############
|
||||
# Analytics:
|
||||
|
||||
## Enable/disable analytics for one session (default: False)
|
||||
#analytics: false
|
||||
## Enable/disable analytics for current session (default: random)
|
||||
#analytics: xxx
|
||||
|
||||
## Specify a file to log analytics events
|
||||
#analytics-log: xxx
|
||||
|
@ -314,6 +322,9 @@
|
|||
## Check for new aider versions on launch
|
||||
#check-update: true
|
||||
|
||||
## Show release notes on first run of new version (default: None, ask user)
|
||||
#show-release-notes: xxx
|
||||
|
||||
## Install the latest version from the main branch
|
||||
#install-main-branch: false
|
||||
|
||||
|
@ -365,6 +376,12 @@
|
|||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#fancy-input: true
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#detect-urls: true
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#editor: xxx
|
||||
|
||||
#################
|
||||
# Voice Settings:
|
||||
|
||||
|
|
|
@ -90,6 +90,9 @@
|
|||
## Specify a file with context window and costs for unknown models
|
||||
#AIDER_MODEL_METADATA_FILE=.aider.model.metadata.json
|
||||
|
||||
## Add a model alias (can be used multiple times)
|
||||
#AIDER_ALIAS=
|
||||
|
||||
## Verify the SSL cert when connecting to models (default: True)
|
||||
#AIDER_VERIFY_SSL=true
|
||||
|
||||
|
@ -270,8 +273,8 @@
|
|||
############
|
||||
# Analytics:
|
||||
|
||||
## Enable/disable analytics for one session (default: False)
|
||||
#AIDER_ANALYTICS=false
|
||||
## Enable/disable analytics for current session (default: random)
|
||||
#AIDER_ANALYTICS=
|
||||
|
||||
## Specify a file to log analytics events
|
||||
#AIDER_ANALYTICS_LOG=
|
||||
|
@ -300,6 +303,9 @@
|
|||
## Check for new aider versions on launch
|
||||
#AIDER_CHECK_UPDATE=true
|
||||
|
||||
## Show release notes on first run of new version (default: None, ask user)
|
||||
#AIDER_SHOW_RELEASE_NOTES=
|
||||
|
||||
## Install the latest version from the main branch
|
||||
#AIDER_INSTALL_MAIN_BRANCH=false
|
||||
|
||||
|
@ -348,6 +354,12 @@
|
|||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#AIDER_FANCY_INPUT=true
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#AIDER_DETECT_URLS=true
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#AIDER_EDITOR=
|
||||
|
||||
#################
|
||||
# Voice Settings:
|
||||
|
||||
|
|
|
@ -11,6 +11,13 @@ description: Configuring advanced settings for LLMs.
|
|||
In most cases, you can safely ignore aider's warning about unknown context
|
||||
window size and model costs.
|
||||
|
||||
{: .note }
|
||||
Aider never *enforces* token limits, it only *reports* token limit errors
|
||||
from the API provider.
|
||||
You probably don't need to
|
||||
configure aider with the proper token limits
|
||||
for unusual models.
|
||||
|
||||
But, you can register context window limits and costs for models that aren't known
|
||||
to aider. Create a `.aider.model.metadata.json` file in one of these locations:
|
||||
|
||||
|
@ -55,8 +62,10 @@ These model settings are pre-configured for most popular models.
|
|||
But it can sometimes be helpful to override them or add settings for
|
||||
a model that aider doesn't know about.
|
||||
|
||||
To do that,
|
||||
create a `.aider.model.settings.yml` file in one of these locations:
|
||||
|
||||
### Configuration file locations
|
||||
|
||||
You can override or add settings for any model by creating a `.aider.model.settings.yml` file in one of these locations:
|
||||
|
||||
- Your home directory.
|
||||
- The root if your git repo.
|
||||
|
@ -66,9 +75,31 @@ create a `.aider.model.settings.yml` file in one of these locations:
|
|||
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.
|
||||
For example, below are all the pre-configured model settings
|
||||
to give a sense for the settings which are supported.
|
||||
The yaml file should be a list of dictionary objects for each model.
|
||||
|
||||
|
||||
### Global extra params
|
||||
|
||||
You can use the special model name `aider/extra_params` to define
|
||||
`extra_params` that will be passed to `litellm.completion()` for all models.
|
||||
Only the `extra_params` dict is used from this special model name.
|
||||
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
- name: aider/extra_params
|
||||
extra_params:
|
||||
extra_headers:
|
||||
Custom-Header: value
|
||||
max_tokens: 8192
|
||||
```
|
||||
|
||||
These settings will be merged with any model-specific settings, with the
|
||||
`aider/extra_params` settings taking precedence for any direct conflicts.
|
||||
|
||||
### Example model settings
|
||||
|
||||
Below are all the pre-configured model settings to give a sense for the settings which are supported.
|
||||
|
||||
You can also look at the `ModelSettings` class in
|
||||
[models.py](https://github.com/Aider-AI/aider/blob/main/aider/models.py)
|
||||
|
@ -241,6 +272,38 @@ cog.out("```\n")
|
|||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: gpt-4o-mini
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff
|
||||
editor_edit_format: null
|
||||
editor_model_name: null
|
||||
examples_as_sys_msg: false
|
||||
extra_params: null
|
||||
lazy: true
|
||||
name: gpt-4o-2024-11-20
|
||||
reminder: sys
|
||||
send_undo_reply: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: gpt-4o-mini
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff
|
||||
editor_edit_format: null
|
||||
editor_model_name: null
|
||||
examples_as_sys_msg: false
|
||||
extra_params: null
|
||||
lazy: true
|
||||
name: openai/gpt-4o-2024-11-20
|
||||
reminder: sys
|
||||
send_undo_reply: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: gpt-4o-mini
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff
|
||||
|
@ -1057,7 +1120,7 @@ cog.out("```\n")
|
|||
name: openai/o1-mini
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: false
|
||||
use_temperature: false
|
||||
|
@ -1073,7 +1136,7 @@ cog.out("```\n")
|
|||
name: azure/o1-mini
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: false
|
||||
use_temperature: false
|
||||
|
@ -1089,7 +1152,7 @@ cog.out("```\n")
|
|||
name: o1-mini
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: false
|
||||
use_temperature: false
|
||||
|
@ -1105,7 +1168,7 @@ cog.out("```\n")
|
|||
name: openai/o1-preview
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: false
|
||||
use_temperature: false
|
||||
|
@ -1121,7 +1184,7 @@ cog.out("```\n")
|
|||
name: azure/o1-preview
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: false
|
||||
use_temperature: false
|
||||
|
@ -1137,7 +1200,7 @@ cog.out("```\n")
|
|||
name: o1-preview
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: false
|
||||
use_temperature: false
|
||||
|
|
|
@ -142,6 +142,14 @@ cog.outl("```")
|
|||
## Specify a file with context window and costs for unknown models
|
||||
#model-metadata-file: .aider.model.metadata.json
|
||||
|
||||
## Add a model alias (can be used multiple times)
|
||||
#alias: xxx
|
||||
## Specify multiple values like this:
|
||||
#alias:
|
||||
# - xxx
|
||||
# - yyy
|
||||
# - zzz
|
||||
|
||||
## Verify the SSL cert when connecting to models (default: True)
|
||||
#verify-ssl: true
|
||||
|
||||
|
@ -327,8 +335,8 @@ cog.outl("```")
|
|||
############
|
||||
# Analytics:
|
||||
|
||||
## Enable/disable analytics for one session (default: False)
|
||||
#analytics: false
|
||||
## Enable/disable analytics for current session (default: random)
|
||||
#analytics: xxx
|
||||
|
||||
## Specify a file to log analytics events
|
||||
#analytics-log: xxx
|
||||
|
@ -370,6 +378,9 @@ cog.outl("```")
|
|||
## Check for new aider versions on launch
|
||||
#check-update: true
|
||||
|
||||
## Show release notes on first run of new version (default: None, ask user)
|
||||
#show-release-notes: xxx
|
||||
|
||||
## Install the latest version from the main branch
|
||||
#install-main-branch: false
|
||||
|
||||
|
@ -421,6 +432,12 @@ cog.outl("```")
|
|||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#fancy-input: true
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#detect-urls: true
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#editor: xxx
|
||||
|
||||
#################
|
||||
# Voice Settings:
|
||||
|
||||
|
|
|
@ -132,6 +132,9 @@ cog.outl("```")
|
|||
## Specify a file with context window and costs for unknown models
|
||||
#AIDER_MODEL_METADATA_FILE=.aider.model.metadata.json
|
||||
|
||||
## Add a model alias (can be used multiple times)
|
||||
#AIDER_ALIAS=
|
||||
|
||||
## Verify the SSL cert when connecting to models (default: True)
|
||||
#AIDER_VERIFY_SSL=true
|
||||
|
||||
|
@ -312,8 +315,8 @@ cog.outl("```")
|
|||
############
|
||||
# Analytics:
|
||||
|
||||
## Enable/disable analytics for one session (default: False)
|
||||
#AIDER_ANALYTICS=false
|
||||
## Enable/disable analytics for current session (default: random)
|
||||
#AIDER_ANALYTICS=
|
||||
|
||||
## Specify a file to log analytics events
|
||||
#AIDER_ANALYTICS_LOG=
|
||||
|
@ -342,6 +345,9 @@ cog.outl("```")
|
|||
## Check for new aider versions on launch
|
||||
#AIDER_CHECK_UPDATE=true
|
||||
|
||||
## Show release notes on first run of new version (default: None, ask user)
|
||||
#AIDER_SHOW_RELEASE_NOTES=
|
||||
|
||||
## Install the latest version from the main branch
|
||||
#AIDER_INSTALL_MAIN_BRANCH=false
|
||||
|
||||
|
@ -390,6 +396,12 @@ cog.outl("```")
|
|||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#AIDER_FANCY_INPUT=true
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#AIDER_DETECT_URLS=true
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#AIDER_EDITOR=
|
||||
|
||||
#################
|
||||
# Voice Settings:
|
||||
|
||||
|
|
127
aider/website/docs/config/editor.md
Normal file
127
aider/website/docs/config/editor.md
Normal file
|
@ -0,0 +1,127 @@
|
|||
---
|
||||
parent: Configuration
|
||||
nav_order: 15
|
||||
description: How to configure a custom editor for aider's /editor command
|
||||
---
|
||||
|
||||
# Editor configuration
|
||||
|
||||
Aider allows you to configure your preferred text editor for use with the `/editor` command. The editor must be capable of running in "blocking mode", meaning the command line will wait until you close the editor before proceeding.
|
||||
|
||||
## Using `--editor`
|
||||
|
||||
You can specify the text editor with the `--editor` switch or using
|
||||
`editor:` in aider's
|
||||
[yaml config file](https://aider.chat/docs/config/aider_conf.html).
|
||||
|
||||
## Environment variables
|
||||
|
||||
Aider checks the following environment variables in order to determine which editor to use:
|
||||
|
||||
1. `AIDER_EDITOR`
|
||||
2. `VISUAL`
|
||||
3. `EDITOR`
|
||||
|
||||
## Default behavior
|
||||
|
||||
If no editor is configured, aider will use these platform-specific defaults:
|
||||
|
||||
- Windows: `notepad`
|
||||
- macOS: `vim`
|
||||
- Linux/Unix: `vi`
|
||||
|
||||
## Using a custom editor
|
||||
|
||||
You can set your preferred editor in your shell's configuration file (e.g., `.bashrc`, `.zshrc`):
|
||||
|
||||
```bash
|
||||
export AIDER_EDITOR=vim
|
||||
```
|
||||
|
||||
## Popular Editors by Platform
|
||||
|
||||
### macOS
|
||||
|
||||
1. **vim**
|
||||
```bash
|
||||
export AIDER_EDITOR=vim
|
||||
```
|
||||
|
||||
2. **Emacs**
|
||||
```bash
|
||||
export AIDER_EDITOR=emacs
|
||||
```
|
||||
|
||||
3. **VSCode**
|
||||
```bash
|
||||
export AIDER_EDITOR="code --wait"
|
||||
```
|
||||
|
||||
4. **Sublime Text**
|
||||
```bash
|
||||
export AIDER_EDITOR="subl --wait"
|
||||
```
|
||||
|
||||
5. **BBEdit**
|
||||
```bash
|
||||
export AIDER_EDITOR="bbedit --wait"
|
||||
```
|
||||
|
||||
### Linux
|
||||
|
||||
1. **vim**
|
||||
```bash
|
||||
export AIDER_EDITOR=vim
|
||||
```
|
||||
|
||||
2. **Emacs**
|
||||
```bash
|
||||
export AIDER_EDITOR=emacs
|
||||
```
|
||||
|
||||
3. **nano**
|
||||
```bash
|
||||
export AIDER_EDITOR=nano
|
||||
```
|
||||
|
||||
4. **VSCode**
|
||||
```bash
|
||||
export AIDER_EDITOR="code --wait"
|
||||
```
|
||||
|
||||
5. **Sublime Text**
|
||||
```bash
|
||||
export AIDER_EDITOR="subl --wait"
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
1. **Notepad**
|
||||
```bat
|
||||
set AIDER_EDITOR=notepad
|
||||
```
|
||||
|
||||
2. **VSCode**
|
||||
```bat
|
||||
set AIDER_EDITOR="code --wait"
|
||||
```
|
||||
|
||||
3. **Notepad++**
|
||||
```bat
|
||||
set AIDER_EDITOR="notepad++ -multiInst -notabbar -nosession -noPlugin -waitForClose"
|
||||
```
|
||||
|
||||
## Editor command arguments
|
||||
|
||||
Some editors require specific command-line arguments to operate in blocking mode. The `--wait` flag (or equivalent) is commonly used to make the editor block until the file is closed.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encounter issues with your editor not blocking (returning to the prompt immediately), verify that:
|
||||
|
||||
1. Your editor supports blocking mode
|
||||
2. You've included the necessary command-line arguments for blocking mode
|
||||
3. The editor command is properly quoted if it contains spaces or special characters, e.g.:
|
||||
```bash
|
||||
export AIDER_EDITOR="code --wait"
|
||||
```
|
72
aider/website/docs/config/model-aliases.md
Normal file
72
aider/website/docs/config/model-aliases.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
parent: Configuration
|
||||
nav_order: 1000
|
||||
description: Assign convenient short names to models.
|
||||
---
|
||||
|
||||
# Model Aliases
|
||||
|
||||
Model aliases allow you to create shorthand names for models you frequently use. This is particularly useful for models with long names or when you want to standardize model usage across your team.
|
||||
|
||||
## Command Line Usage
|
||||
|
||||
You can define aliases when launching aider using the `--alias` option:
|
||||
|
||||
```bash
|
||||
aider --alias "fast:gpt-3.5-turbo" --alias "smart:gpt-4"
|
||||
```
|
||||
|
||||
Multiple aliases can be defined by using the `--alias` option multiple times. Each alias definition should be in the format `alias:model-name`.
|
||||
|
||||
## Configuration File
|
||||
|
||||
You can also define aliases in your [`.aider.conf.yml` file](https://aider.chat/docs/config/aider_conf.html):
|
||||
|
||||
```yaml
|
||||
alias:
|
||||
- "fast:gpt-3.5-turbo"
|
||||
- "smart:gpt-4"
|
||||
- "hacker:claude-3-sonnet-20240229"
|
||||
```
|
||||
|
||||
## Using Aliases
|
||||
|
||||
Once defined, you can use the alias instead of the full model name:
|
||||
|
||||
```bash
|
||||
aider --model fast # Uses gpt-3.5-turbo
|
||||
aider --model smart # Uses gpt-4
|
||||
```
|
||||
|
||||
## Built-in Aliases
|
||||
|
||||
Aider includes some built-in aliases for convenience:
|
||||
|
||||
<!--[[[cog
|
||||
import cog
|
||||
from aider.models import MODEL_ALIASES
|
||||
|
||||
for alias, model in sorted(MODEL_ALIASES.items()):
|
||||
cog.outl(f"- `{alias}`: {model}")
|
||||
]]]-->
|
||||
- `3`: gpt-3.5-turbo
|
||||
- `35-turbo`: gpt-3.5-turbo
|
||||
- `35turbo`: gpt-3.5-turbo
|
||||
- `4`: gpt-4-0613
|
||||
- `4-turbo`: gpt-4-1106-preview
|
||||
- `4o`: gpt-4o-2024-08-06
|
||||
- `deepseek`: deepseek/deepseek-coder
|
||||
- `haiku`: claude-3-haiku-20241022
|
||||
- `opus`: claude-3-opus-20240229
|
||||
- `sonnet`: claude-3-sonnet-20241022
|
||||
<!--[[[end]]]-->
|
||||
|
||||
## Priority
|
||||
|
||||
If the same alias is defined in multiple places, the priority is:
|
||||
|
||||
1. Command line aliases (highest priority)
|
||||
2. Configuration file aliases
|
||||
3. Built-in aliases (lowest priority)
|
||||
|
||||
This allows you to override built-in aliases with your own preferences.
|
|
@ -32,9 +32,9 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
|
|||
[--openai-api-type] [--openai-api-version]
|
||||
[--openai-api-deployment-id] [--openai-organization-id]
|
||||
[--model-settings-file] [--model-metadata-file]
|
||||
[--verify-ssl | --no-verify-ssl] [--edit-format]
|
||||
[--architect] [--weak-model] [--editor-model]
|
||||
[--editor-edit-format]
|
||||
[--alias] [--verify-ssl | --no-verify-ssl]
|
||||
[--edit-format] [--architect] [--weak-model]
|
||||
[--editor-model] [--editor-edit-format]
|
||||
[--show-model-warnings | --no-show-model-warnings]
|
||||
[--max-chat-history-tokens] [--env-file]
|
||||
[--cache-prompts | --no-cache-prompts]
|
||||
|
@ -66,14 +66,16 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
|
|||
[--analytics-disable] [--file] [--read] [--vim]
|
||||
[--chat-language] [--version] [--just-check-update]
|
||||
[--check-update | --no-check-update]
|
||||
[--show-release-notes | --no-show-release-notes]
|
||||
[--install-main-branch] [--upgrade] [--apply]
|
||||
[--apply-clipboard-edits] [--yes-always] [-v]
|
||||
[--show-repo-map] [--show-prompts] [--exit] [--message]
|
||||
[--message-file] [--load] [--encoding] [-c]
|
||||
[--gui | --no-gui | --browser | --no-browser]
|
||||
[--suggest-shell-commands | --no-suggest-shell-commands]
|
||||
[--fancy-input | --no-fancy-input] [--voice-format]
|
||||
[--voice-language]
|
||||
[--fancy-input | --no-fancy-input]
|
||||
[--detect-urls | --no-detect-urls] [--editor]
|
||||
[--voice-format] [--voice-language]
|
||||
|
||||
```
|
||||
|
||||
|
@ -190,6 +192,10 @@ Specify a file with context window and costs for unknown models
|
|||
Default: .aider.model.metadata.json
|
||||
Environment variable: `AIDER_MODEL_METADATA_FILE`
|
||||
|
||||
### `--alias ALIAS:MODEL`
|
||||
Add a model alias (can be used multiple times)
|
||||
Environment variable: `AIDER_ALIAS`
|
||||
|
||||
### `--verify-ssl`
|
||||
Verify the SSL cert when connecting to models (default: True)
|
||||
Default: True
|
||||
|
@ -510,8 +516,7 @@ Environment variable: `AIDER_TEST`
|
|||
## Analytics:
|
||||
|
||||
### `--analytics`
|
||||
Enable/disable analytics for one session (default: False)
|
||||
Default: False
|
||||
Enable/disable analytics for current session (default: random)
|
||||
Environment variable: `AIDER_ANALYTICS`
|
||||
Aliases:
|
||||
- `--analytics`
|
||||
|
@ -561,6 +566,13 @@ Aliases:
|
|||
- `--check-update`
|
||||
- `--no-check-update`
|
||||
|
||||
### `--show-release-notes`
|
||||
Show release notes on first run of new version (default: None, ask user)
|
||||
Environment variable: `AIDER_SHOW_RELEASE_NOTES`
|
||||
Aliases:
|
||||
- `--show-release-notes`
|
||||
- `--no-show-release-notes`
|
||||
|
||||
### `--install-main-branch`
|
||||
Install the latest version from the main branch
|
||||
Default: False
|
||||
|
@ -666,6 +678,18 @@ Aliases:
|
|||
- `--fancy-input`
|
||||
- `--no-fancy-input`
|
||||
|
||||
### `--detect-urls`
|
||||
Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
Default: True
|
||||
Environment variable: `AIDER_DETECT_URLS`
|
||||
Aliases:
|
||||
- `--detect-urls`
|
||||
- `--no-detect-urls`
|
||||
|
||||
### `--editor VALUE`
|
||||
Specify which editor to use for the /editor command
|
||||
Environment variable: `AIDER_EDITOR`
|
||||
|
||||
## Voice Settings:
|
||||
|
||||
### `--voice-format VOICE_FORMAT`
|
||||
|
|
|
@ -60,6 +60,23 @@ directory you start in.
|
|||
You can also create a `.aiderignore` file to tell aider
|
||||
to ignore parts of the repo that aren't relevant to your task.
|
||||
This file conforms to `.gitignore` syntax and conventions.
|
||||
For example, to focus only on specific directories in a monorepo,
|
||||
you could create a `.aiderignore` file with:
|
||||
|
||||
```
|
||||
# Ignore everything
|
||||
/*
|
||||
|
||||
# Allow specific directories and their contents
|
||||
!foo/
|
||||
!bar/
|
||||
!baz/
|
||||
|
||||
# Allow nested files under these directories
|
||||
!foo/**
|
||||
!bar/**
|
||||
!baz/**
|
||||
```
|
||||
|
||||
You can use `--aiderignore <filename>` to name a specific file
|
||||
to use for ignore patterns.
|
||||
|
@ -193,7 +210,7 @@ You can also refer to the
|
|||
## How are the "aider wrote xx% of code" stats computed?
|
||||
|
||||
[Aider is tightly integrated with git](/docs/git.html) so all
|
||||
one of aider's code changes are committed to the repo with proper attribution.
|
||||
of aider's code changes are committed to the repo with proper attribution.
|
||||
The
|
||||
[stats are computed](https://github.com/Aider-AI/aider/blob/main/scripts/blame.py)
|
||||
by doing something like `git blame` on the repo,
|
||||
|
|
|
@ -62,6 +62,7 @@ cog.out(get_supported_languages_md())
|
|||
| cpp | .cc | ✓ | ✓ |
|
||||
| cpp | .cpp | ✓ | ✓ |
|
||||
| css | .css | | ✓ |
|
||||
| dart | .dart | ✓ | ✓ |
|
||||
| dockerfile | .dockerfile | | ✓ |
|
||||
| dot | .dot | | ✓ |
|
||||
| elisp | .el | ✓ | ✓ |
|
||||
|
|
|
@ -31,6 +31,8 @@ This measures the LLM's coding ability, and whether it can
|
|||
write new code that integrates into existing code.
|
||||
The model also has to successfully apply all its changes to the source file without human intervention.
|
||||
|
||||
<input type="text" id="editSearchInput" placeholder="Search..." style="width: 100%; max-width: 800px; margin: 10px auto; padding: 8px; display: block; border: 1px solid #ddd; border-radius: 4px;">
|
||||
|
||||
<table style="width: 100%; max-width: 800px; margin: auto; border-collapse: collapse; box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 14px;">
|
||||
<thead style="background-color: #f2f2f2;">
|
||||
<tr>
|
||||
|
@ -58,81 +60,7 @@ The model also has to successfully apply all its changes to the source file with
|
|||
<canvas id="editChart" width="800" height="450" style="margin-top: 20px"></canvas>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var ctx = document.getElementById('editChart').getContext('2d');
|
||||
const HIGHTLIGHT_MODEL = 'no no no no';
|
||||
var leaderboardData = {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Percent completed correctly',
|
||||
data: [],
|
||||
backgroundColor: function(context) {
|
||||
const label = context.chart.data.labels[context.dataIndex] || '';
|
||||
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)';
|
||||
},
|
||||
borderColor: function(context) {
|
||||
const label = context.chart.data.labels[context.dataIndex] || '';
|
||||
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)';
|
||||
},
|
||||
borderWidth: 1
|
||||
}]
|
||||
};
|
||||
|
||||
var allData = [];
|
||||
{% for row in edit_sorted %}
|
||||
allData.push({
|
||||
model: '{{ row.model }}',
|
||||
pass_rate_2: {{ row.pass_rate_2 }},
|
||||
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
function updateChart() {
|
||||
var selectedRows = document.querySelectorAll('tr.selected');
|
||||
var showAll = selectedRows.length === 0;
|
||||
|
||||
leaderboardData.labels = [];
|
||||
leaderboardData.datasets[0].data = [];
|
||||
|
||||
allData.forEach(function(row, index) {
|
||||
var rowElement = document.getElementById('edit-row-' + index);
|
||||
if (showAll) {
|
||||
rowElement.classList.remove('selected');
|
||||
}
|
||||
if (showAll || rowElement.classList.contains('selected')) {
|
||||
leaderboardData.labels.push(row.model);
|
||||
leaderboardData.datasets[0].data.push(row.pass_rate_2);
|
||||
}
|
||||
});
|
||||
|
||||
leaderboardChart.update();
|
||||
}
|
||||
|
||||
var tableBody = document.querySelector('table tbody');
|
||||
allData.forEach(function(row, index) {
|
||||
var tr = tableBody.children[index];
|
||||
tr.id = 'edit-row-' + index;
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.onclick = function() {
|
||||
this.classList.toggle('selected');
|
||||
updateChart();
|
||||
};
|
||||
});
|
||||
|
||||
var leaderboardChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: leaderboardData,
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateChart();
|
||||
});
|
||||
{% include edit-leaderboard.js %}
|
||||
</script>
|
||||
<style>
|
||||
tr.selected {
|
||||
|
@ -158,6 +86,8 @@ The refactoring benchmark requires a large context window to
|
|||
work with large source files.
|
||||
Therefore, results are available for fewer models.
|
||||
|
||||
<input type="text" id="refacSearchInput" placeholder="Search..." style="width: 100%; max-width: 800px; margin: 10px auto; padding: 8px; display: block; border: 1px solid #ddd; border-radius: 4px;">
|
||||
|
||||
<table style="width: 100%; max-width: 800px; margin: auto; border-collapse: collapse; box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 14px;">
|
||||
<thead style="background-color: #f2f2f2;">
|
||||
<tr>
|
||||
|
@ -185,74 +115,7 @@ Therefore, results are available for fewer models.
|
|||
<canvas id="refacChart" width="800" height="450" style="margin-top: 20px"></canvas>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var ctx = document.getElementById('refacChart').getContext('2d');
|
||||
var leaderboardData = {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Percent completed correctly',
|
||||
data: [],
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
||||
borderColor: 'rgba(54, 162, 235, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
};
|
||||
|
||||
var allData = [];
|
||||
{% for row in refac_sorted %}
|
||||
allData.push({
|
||||
model: '{{ row.model }}',
|
||||
pass_rate_1: {{ row.pass_rate_1 }},
|
||||
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
function updateChart() {
|
||||
var selectedRows = document.querySelectorAll('tr.selected');
|
||||
var showAll = selectedRows.length === 0;
|
||||
|
||||
leaderboardData.labels = [];
|
||||
leaderboardData.datasets[0].data = [];
|
||||
|
||||
allData.forEach(function(row, index) {
|
||||
var rowElement = document.getElementById('refac-row-' + index);
|
||||
if (showAll) {
|
||||
rowElement.classList.remove('selected');
|
||||
}
|
||||
if (showAll || rowElement.classList.contains('selected')) {
|
||||
leaderboardData.labels.push(row.model);
|
||||
leaderboardData.datasets[0].data.push(row.pass_rate_1);
|
||||
}
|
||||
});
|
||||
|
||||
leaderboardChart.update();
|
||||
}
|
||||
|
||||
var tableBody = document.querySelectorAll('table tbody')[1];
|
||||
allData.forEach(function(row, index) {
|
||||
var tr = tableBody.children[index];
|
||||
tr.id = 'refac-row-' + index;
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.onclick = function() {
|
||||
this.classList.toggle('selected');
|
||||
updateChart();
|
||||
};
|
||||
});
|
||||
|
||||
var leaderboardChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: leaderboardData,
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateChart();
|
||||
});
|
||||
{% include refactor-leaderboard.js %}
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -318,6 +181,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.')}")
|
||||
]]]-->
|
||||
November 11, 2024.
|
||||
November 24, 2024.
|
||||
<!--[[[end]]]-->
|
||||
</p>
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
parent: Connecting to LLMs
|
||||
nav_order: 850
|
||||
---
|
||||
|
||||
# Editing format
|
||||
|
||||
Aider uses different "edit formats" to collect code edits from different LLMs.
|
||||
The "whole" format is the easiest for an LLM to use, but it uses a lot of tokens
|
||||
and may limit how large a file can be edited.
|
||||
Models which can use one of the diff formats are much more efficient,
|
||||
using far fewer tokens.
|
||||
Models that use a diff-like format are able to
|
||||
edit larger files with less cost and without hitting token limits.
|
||||
|
||||
Aider is configured to use the best edit format for the popular OpenAI and Anthropic models
|
||||
and the [other models recommended on the LLM page](https://aider.chat/docs/llms.html).
|
||||
For lesser known models aider will default to using the "whole" editing format
|
||||
since it is the easiest format for an LLM to use.
|
||||
|
||||
If you would like to experiment with the more advanced formats, you can
|
||||
use these switches: `--edit-format diff` or `--edit-format udiff`.
|
26
aider/website/docs/llms/lm-studio.md
Normal file
26
aider/website/docs/llms/lm-studio.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
parent: Connecting to LLMs
|
||||
nav_order: 400
|
||||
---
|
||||
|
||||
# LM Studio
|
||||
|
||||
To use LM Studio:
|
||||
|
||||
```
|
||||
python -m pip install -U aider-chat
|
||||
|
||||
export LM_STUDIO_API_KEY=<key> # Mac/Linux
|
||||
setx LM_STUDIO_API_KEY <key> # Windows, restart shell after setx
|
||||
|
||||
export LM_STUDIO_API_BASE=<url> # Mac/Linux
|
||||
setx LM_STUDIO_API_BASE <url> # Windows, restart shell after setx
|
||||
|
||||
aider --model lm_studio/<your-model-name>
|
||||
```
|
||||
|
||||
|
||||
|
||||
See the [model warnings](warnings.html)
|
||||
section for information on warnings which will occur
|
||||
when working with models that aider is not familiar with.
|
|
@ -20,24 +20,49 @@ python -m pip install -U aider-chat
|
|||
export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux
|
||||
setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx
|
||||
|
||||
aider --model ollama/<model>
|
||||
aider --model ollama_chat/<model>
|
||||
```
|
||||
|
||||
In particular, `llama3:70b` works well with aider:
|
||||
{: .note }
|
||||
Using `ollama_chat/` is recommended over `ollama/`.
|
||||
|
||||
|
||||
```
|
||||
ollama pull llama3:70b
|
||||
ollama serve
|
||||
|
||||
# In another terminal window...
|
||||
export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux
|
||||
setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx
|
||||
|
||||
aider --model ollama/llama3:70b
|
||||
```
|
||||
|
||||
See the [model warnings](warnings.html)
|
||||
section for information on warnings which will occur
|
||||
when working with models that aider is not familiar with.
|
||||
|
||||
## API Key
|
||||
|
||||
If you are using an ollama that requires an API key you can set `OLLAMA_API_KEY`:
|
||||
|
||||
```
|
||||
export OLLAMA_API_KEY=<api-key> # Mac/Linux
|
||||
setx OLLAMA_API_KEY <api-key> # Windows, restart shell after setx
|
||||
```
|
||||
|
||||
## Setting the context window size
|
||||
|
||||
[Ollama uses a 2k context window by default](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-specify-the-context-window-size),
|
||||
which is very small for working with aider.
|
||||
|
||||
Aider sets Ollama's context window to 8k by default.
|
||||
If you would like
|
||||
a larger context window
|
||||
you can use a
|
||||
[`.aider.model.settings.yml` file](https://aider.chat/docs/config/adv-model-settings.html#model-settings)
|
||||
like this:
|
||||
|
||||
```
|
||||
- name: ollama/qwen2.5-coder:32b-instruct-fp16
|
||||
extra_params:
|
||||
num_ctx: 8192
|
||||
```
|
||||
|
||||
Unlike most other LLM servers, Ollama does not throw an error if you submit
|
||||
a request that exceeds the context window.
|
||||
Instead, it just silently truncates the request by discarding the "oldest" messages
|
||||
in the chat to make it fit within the context window.
|
||||
So if your context window is too small, you won't get an error.
|
||||
Aider will probably just fail to work well and experience
|
||||
a lot of
|
||||
[file editing problems](https://aider.chat/docs/troubleshooting/edit-errors.html).
|
||||
|
|
24
aider/website/docs/llms/xai.md
Normal file
24
aider/website/docs/llms/xai.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
parent: Connecting to LLMs
|
||||
nav_order: 400
|
||||
---
|
||||
|
||||
# xAI
|
||||
|
||||
You'll need a [xAI API key](https://console.x.ai.).
|
||||
|
||||
To use xAI:
|
||||
|
||||
```
|
||||
python -m pip install -U aider-chat
|
||||
|
||||
export XAI_API_KEY=<key> # Mac/Linux
|
||||
setx XAI_API_KEY <key> # Windows, restart shell after setx
|
||||
|
||||
aider --model xai/grok-beta
|
||||
|
||||
# List models available from xAI
|
||||
aider --list-models xai/
|
||||
```
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ features and commands are most used.
|
|||
It also helps uncover bugs that users are experiencing, so that they can be fixed
|
||||
in upcoming releases.
|
||||
|
||||
## Enabling & disabling analytics
|
||||
## Disabling analytics
|
||||
|
||||
You can opt out of analytics forever by running this command one time:
|
||||
|
||||
|
@ -39,10 +39,27 @@ You can opt out of analytics forever by running this command one time:
|
|||
aider --analytics-disable
|
||||
```
|
||||
|
||||
To enable analytics for a single session, you can run aider with `--analytics`.
|
||||
This will *not* have any effect if you have permanently disabled analytics with the previous command.
|
||||
## Enabling analytics
|
||||
|
||||
The first time, you will need to agree to opt-in.
|
||||
The `--[no-]analytics` switch controls whether analytics are enabled for the
|
||||
current session:
|
||||
|
||||
- `--analytics` will turn on analytics for the current session.
|
||||
This will *not* have any effect if you have permanently disabled analytics
|
||||
with `--analytics-disable`.
|
||||
If this is the first time you have enabled analytics, aider
|
||||
will confirm you wish to opt-in to analytics.
|
||||
- `--no-analytics` will turn off analytics for the current session.
|
||||
- By default, if you don't provide `--analytics` or `--no-analytics`,
|
||||
aider will enable analytics for a random subset of users.
|
||||
This will never happen if you have permanently disabled analytics
|
||||
with `--analytics-disable`.
|
||||
Randomly selected users will be asked if they wish to opt-in to analytics.
|
||||
|
||||
|
||||
## Opting in
|
||||
|
||||
The first time analytics are enabled, you will need to agree to opt-in.
|
||||
|
||||
```
|
||||
aider --analytics
|
||||
|
@ -53,13 +70,8 @@ For more info: https://aider.chat/docs/more/analytics.html
|
|||
Allow collection of anonymous analytics to help improve aider? (Y)es/(N)o [Yes]:
|
||||
```
|
||||
|
||||
If you've added `analytics: true` to your
|
||||
[yaml config file](/docs/config/aider_conf.html),
|
||||
you can disable analytics for a single session, you can run:
|
||||
If you say "no", analytics will be permanently disabled.
|
||||
|
||||
```
|
||||
aider --no-analytics
|
||||
```
|
||||
|
||||
## Details about data being collected
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ cog.out(model_list)
|
|||
]]]-->
|
||||
- anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
- anthropic.claude-3-5-sonnet-20241022-v2:0
|
||||
- anthropic/claude-3-5-sonnet-20241022
|
||||
- claude-3-5-haiku-20241022
|
||||
- claude-3-5-sonnet-20240620
|
||||
- claude-3-5-sonnet-20241022
|
||||
|
@ -91,11 +90,17 @@ cog.out(model_list)
|
|||
- openrouter/anthropic/claude-3.5-sonnet
|
||||
- us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
- us.anthropic.claude-3-5-sonnet-20241022-v2:0
|
||||
- vertex_ai/claude-3-5-haiku
|
||||
- vertex_ai/claude-3-5-haiku@20241022
|
||||
- vertex_ai/claude-3-5-sonnet
|
||||
- vertex_ai/claude-3-5-sonnet-v2
|
||||
- vertex_ai/claude-3-5-sonnet-v2@20241022
|
||||
- vertex_ai/claude-3-5-sonnet@20240620
|
||||
- vertex_ai/claude-3-haiku
|
||||
- vertex_ai/claude-3-haiku@20240307
|
||||
- vertex_ai/claude-3-opus
|
||||
- vertex_ai/claude-3-opus@20240229
|
||||
- vertex_ai/claude-3-sonnet
|
||||
- vertex_ai/claude-3-sonnet@20240229
|
||||
<!--[[[end]]]-->
|
||||
|
||||
|
|
|
@ -95,3 +95,6 @@ io = InputOutput(yes=True)
|
|||
coder = Coder.create(model=model, fnames=fnames, io=io)
|
||||
```
|
||||
|
||||
{: .note }
|
||||
The scripting API is not officially supported or documented and may
|
||||
change without warning.
|
||||
|
|
|
@ -19,31 +19,7 @@ LLM edits that are "almost" correctly formatted.
|
|||
But sometimes the LLM just won't cooperate.
|
||||
In these cases, here are some things you might try.
|
||||
|
||||
## Use a capable model
|
||||
|
||||
If possible try using GPT-4o, Claude 3.5 Sonnet or Claude 3 Opus,
|
||||
as they are the strongest and most capable models.
|
||||
|
||||
Weaker models
|
||||
are more prone to
|
||||
disobeying the system prompt instructions.
|
||||
Most local models are just barely capable of working with aider,
|
||||
so editing errors are probably unavoidable.
|
||||
|
||||
Local models which have been quantized are even more likely to have problems
|
||||
because they are not capable enough to follow aider's system prompts.
|
||||
|
||||
## Try the whole format
|
||||
|
||||
Run aider with `--edit-format whole` if the model is using a different edit format.
|
||||
You can see which edit format it is using in the announce lines:
|
||||
|
||||
```
|
||||
Aider v0.50.2-dev
|
||||
Models: claude-3-5-sonnet-20240620 with ♾️ diff edit format
|
||||
```
|
||||
|
||||
## Reduce distractions
|
||||
## Don't add too many files
|
||||
|
||||
Many LLMs now have very large context windows,
|
||||
but filling them with irrelevant code or conversation
|
||||
|
@ -55,6 +31,38 @@ Aider also sends the LLM a [map of your entire git repo](https://aider.chat/docs
|
|||
- Use `/clear` to remove the conversation history, again to help the LLM focus.
|
||||
- Use `/tokens` to see how many tokens you are using for each message.
|
||||
|
||||
## Use a more capable model
|
||||
|
||||
If possible try using GPT-4o, Claude 3.5 Sonnet or Claude 3 Opus,
|
||||
as they are the strongest and most capable models.
|
||||
|
||||
Weaker models
|
||||
are more prone to
|
||||
disobeying the system prompt instructions.
|
||||
Most local models are just barely capable of working with aider,
|
||||
so editing errors are probably unavoidable.
|
||||
|
||||
## Local models: context window and quantization
|
||||
|
||||
Be especially careful about the
|
||||
[Ollama context window](https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size)
|
||||
when working with local models.
|
||||
It defaults to be very small and silently discards data if you exceed it.
|
||||
|
||||
Local models which have been quantized are more likely to have editing problems
|
||||
because they are not capable enough to follow aider's system prompts.
|
||||
|
||||
## Try the whole edit format
|
||||
|
||||
Run aider with `--edit-format whole` if were using a different edit format.
|
||||
You can see which edit format it is using in the announce lines:
|
||||
|
||||
```
|
||||
Aider v0.50.2-dev
|
||||
Models: claude-3-5-sonnet-20240620 with ♾️ diff edit format
|
||||
```
|
||||
|
||||
|
||||
## More help
|
||||
|
||||
{% include help.md %}
|
||||
|
|
|
@ -33,6 +33,13 @@ To reduce output tokens:
|
|||
For more info: https://aider.chat/docs/token-limits.html
|
||||
```
|
||||
|
||||
{: .note }
|
||||
Aider never *enforces* token limits, it only *reports* token limit errors
|
||||
from the API provider.
|
||||
You probably don't need to
|
||||
[configure aider with the proper token limits](http://0.0.0.0:4000/docs/config/adv-model-settings.html#context-window-size-and-token-costs)
|
||||
for unusual models.
|
||||
|
||||
## Input tokens & context window size
|
||||
|
||||
The most common problem is trying to send too much data to a
|
||||
|
|
|
@ -3,7 +3,14 @@ parent: Usage
|
|||
nav_order: 50
|
||||
description: Control aider with in-chat commands like /add, /model, etc.
|
||||
---
|
||||
|
||||
# In-chat commands
|
||||
{: .no_toc }
|
||||
|
||||
- TOC
|
||||
{:toc}
|
||||
|
||||
## Slash commands
|
||||
|
||||
Aider supports commands from within the chat, which all start with `/`.
|
||||
|
||||
|
@ -24,6 +31,7 @@ cog.out(get_help_md())
|
|||
| **/copy** | Copy the last assistant message to the clipboard |
|
||||
| **/diff** | Display the diff of changes since the last message |
|
||||
| **/drop** | Remove files from the chat session to free up context space |
|
||||
| **/editor** | Open an editor to write a prompt |
|
||||
| **/exit** | Exit the application |
|
||||
| **/git** | Run a git command (output excluded from chat) |
|
||||
| **/help** | Ask questions about aider |
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
parent: Usage
|
||||
nav_order: 60
|
||||
description: Using the chat, ask and help chat modes.
|
||||
description: Using the code, architect, ask and help chat modes.
|
||||
---
|
||||
|
||||
# Chat modes
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
nav_exclude: true
|
||||
---
|
||||
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self';
|
||||
script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com;
|
||||
connect-src http: https:;
|
||||
style-src 'self' 'unsafe-inline';">
|
||||
|
||||
# Shared aider chat transcript
|
||||
|
||||
A user has shared the following transcript of a pair programming chat session
|
||||
|
@ -37,11 +43,29 @@ print("goodbye")
|
|||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.6/purify.min.js"></script>
|
||||
<script>
|
||||
function isValidUrl(url) {
|
||||
try {
|
||||
const urlObj = new URL(url);
|
||||
return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Configure marked with secure defaults
|
||||
marked.setOptions({
|
||||
headerIds: false,
|
||||
mangle: false
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var urlParams = new URLSearchParams(window.location.search);
|
||||
var conv = urlParams.get('mdurl');
|
||||
if (!conv) {
|
||||
if (!conv || !isValidUrl(conv)) {
|
||||
document.querySelector('#shared-transcript').innerHTML =
|
||||
'<div style="color: red; padding: 1em;">Error: Invalid or missing URL provided</div>';
|
||||
return;
|
||||
}
|
||||
document.getElementById('mdurl').href = conv;
|
||||
|
@ -63,11 +87,14 @@ window.onload = function() {
|
|||
return line;
|
||||
}).join('\n');
|
||||
var html = marked.parse(markdown);
|
||||
var sanitizedHtml = DOMPurify.sanitize(html);
|
||||
var divElement = document.querySelector('#shared-transcript');
|
||||
divElement.innerHTML = html;
|
||||
divElement.innerHTML = sanitizedHtml;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching markdown:', error);
|
||||
document.querySelector('#shared-transcript').innerHTML =
|
||||
'<div style="color: red; padding: 1em;">Error: Failed to load chat transcript</div>';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -155,6 +155,9 @@ def main(
|
|||
tries: int = typer.Option(2, "--tries", "-r", help="Number of tries for running tests"),
|
||||
threads: int = typer.Option(1, "--threads", "-t", help="Number of threads to run in parallel"),
|
||||
num_tests: int = typer.Option(-1, "--num-tests", "-n", help="Number of tests to run"),
|
||||
num_ctx: Optional[int] = typer.Option(
|
||||
None, "--num-ctx", help="Override model context window size"
|
||||
),
|
||||
exercises_dir: str = typer.Option(
|
||||
EXERCISES_DIR_DEFAULT, "--exercises-dir", help="Directory with exercise files"
|
||||
),
|
||||
|
@ -247,6 +250,7 @@ def main(
|
|||
max_apply_update_errors,
|
||||
editor_model,
|
||||
editor_edit_format,
|
||||
num_ctx,
|
||||
)
|
||||
|
||||
all_results.append(results)
|
||||
|
@ -526,6 +530,7 @@ def run_test_real(
|
|||
max_apply_update_errors,
|
||||
editor_model,
|
||||
editor_edit_format,
|
||||
num_ctx=None,
|
||||
):
|
||||
if not os.path.isdir(testdir):
|
||||
print("Not a dir:", testdir)
|
||||
|
@ -588,6 +593,11 @@ def run_test_real(
|
|||
editor_model=editor_model,
|
||||
editor_edit_format=editor_edit_format,
|
||||
)
|
||||
|
||||
if num_ctx:
|
||||
if not main_model.extra_params:
|
||||
main_model.extra_params = {}
|
||||
main_model.extra_params["num_ctx"] = num_ctx
|
||||
edit_format = edit_format or main_model.edit_format
|
||||
|
||||
dump(main_model)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
docker run \
|
||||
-it --rm \
|
||||
--add-host=host.docker.internal:host-gateway \
|
||||
-v `pwd`:/aider \
|
||||
-v `pwd`/tmp.benchmarks/.:/benchmarks \
|
||||
-e OPENAI_API_KEY=$OPENAI_API_KEY \
|
||||
|
|
|
@ -1,121 +1,168 @@
|
|||
from dataclasses import dataclass
|
||||
from datetime import date
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import yaml
|
||||
from imgcat import imgcat
|
||||
from matplotlib import rc
|
||||
|
||||
from aider.dump import dump # noqa: 401
|
||||
|
||||
@dataclass
|
||||
class ModelData:
|
||||
name: str
|
||||
release_date: date
|
||||
pass_rate: float
|
||||
|
||||
def get_model_color(model):
|
||||
default = "lightblue"
|
||||
|
||||
if model == "gpt-4o-mini":
|
||||
return default
|
||||
|
||||
@property
|
||||
def color(self) -> str:
|
||||
model = self.name.lower()
|
||||
if "gemini" in model and "pro" in model:
|
||||
return "magenta"
|
||||
if "qwen" in model:
|
||||
return "darkblue"
|
||||
if "mistral" in model:
|
||||
return "cyan"
|
||||
if "haiku" in model:
|
||||
return "pink"
|
||||
if "deepseek" in model:
|
||||
return "brown"
|
||||
if "sonnet" in model:
|
||||
return "orange"
|
||||
if "-4o" in model:
|
||||
return "purple"
|
||||
|
||||
if "gpt-4" in model:
|
||||
return "red"
|
||||
|
||||
if "gpt-3.5" in model:
|
||||
return "green"
|
||||
return "lightblue"
|
||||
|
||||
return default
|
||||
@property
|
||||
def legend_label(self) -> str:
|
||||
model = self.name.lower()
|
||||
if "gemini" in model and "pro" in model:
|
||||
return "Gemini 1.5 Pro"
|
||||
if "claude-3-sonnet" in model:
|
||||
return "Sonnet"
|
||||
if "o1-preview" in model:
|
||||
return "O1 Preview"
|
||||
if "gpt-3.5" in model:
|
||||
return "GPT-3.5 Turbo"
|
||||
if "gpt-4-" in model and "-4o" not in model:
|
||||
return "GPT-4"
|
||||
if "qwen" in model:
|
||||
return "Qwen"
|
||||
if "-4o" in model:
|
||||
return "GPT-4o"
|
||||
if "haiku" in model:
|
||||
return "Haiku"
|
||||
if "deepseek" in model:
|
||||
return "DeepSeek"
|
||||
if "mistral" in model:
|
||||
return "Mistral"
|
||||
return model
|
||||
|
||||
|
||||
def plot_over_time(yaml_file):
|
||||
with open(yaml_file, "r") as file:
|
||||
data = yaml.safe_load(file)
|
||||
class BenchmarkPlotter:
|
||||
LABEL_FONT_SIZE = 16
|
||||
|
||||
dates = []
|
||||
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
|
||||
def __init__(self):
|
||||
self.setup_plot_style()
|
||||
|
||||
def setup_plot_style(self):
|
||||
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=(12, 6)) # Increase figure size for better visibility
|
||||
def load_data(self, yaml_file: str) -> List[ModelData]:
|
||||
with open(yaml_file, "r") as file:
|
||||
data = yaml.safe_load(file)
|
||||
|
||||
print("Debug: Figure created. Plotting data...")
|
||||
models = []
|
||||
for entry in data:
|
||||
if "released" in entry and "pass_rate_2" in entry:
|
||||
model = ModelData(
|
||||
name=entry["model"].split("(")[0].strip(),
|
||||
release_date=entry["released"],
|
||||
pass_rate=entry["pass_rate_2"],
|
||||
)
|
||||
models.append(model)
|
||||
return models
|
||||
|
||||
def create_figure(self) -> Tuple[plt.Figure, plt.Axes]:
|
||||
fig, ax = plt.subplots(figsize=(12, 8))
|
||||
ax.grid(axis="y", zorder=0, lw=0.2)
|
||||
for spine in ax.spines.values():
|
||||
spine.set_edgecolor("#DDDDDD")
|
||||
spine.set_linewidth(0.5)
|
||||
return fig, ax
|
||||
|
||||
colors = [get_model_color(model) for model in models]
|
||||
def plot_model_series(self, ax: plt.Axes, models: List[ModelData]):
|
||||
# Group models by color
|
||||
color_groups: Dict[str, List[ModelData]] = {}
|
||||
for model in models:
|
||||
if model.color not in color_groups:
|
||||
color_groups[model.color] = []
|
||||
color_groups[model.color].append(model)
|
||||
|
||||
# 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 each color group
|
||||
for color, group in color_groups.items():
|
||||
sorted_group = sorted(group, key=lambda x: x.release_date)
|
||||
dates = [m.release_date for m in sorted_group]
|
||||
rates = [m.pass_rate for m in sorted_group]
|
||||
|
||||
# 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 line
|
||||
ax.plot(dates, rates, c=color, alpha=0.5, linewidth=1)
|
||||
|
||||
# Plot all points
|
||||
ax.scatter(dates, pass_rates, c=colors, alpha=0.5, s=120)
|
||||
# Plot points
|
||||
ax.scatter(dates, rates, c=color, alpha=0.5, s=120)
|
||||
|
||||
for i, model in enumerate(models):
|
||||
# Add label for first point
|
||||
first_model = sorted_group[0]
|
||||
ax.annotate(
|
||||
model,
|
||||
(dates[i], pass_rates[i]),
|
||||
fontsize=8,
|
||||
alpha=0.75,
|
||||
xytext=(5, 5),
|
||||
first_model.legend_label,
|
||||
(first_model.release_date, first_model.pass_rate),
|
||||
xytext=(10, 5),
|
||||
textcoords="offset points",
|
||||
color=color,
|
||||
alpha=0.8,
|
||||
fontsize=self.LABEL_FONT_SIZE,
|
||||
)
|
||||
|
||||
def set_labels_and_style(self, ax: plt.Axes):
|
||||
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_title("LLM code editing skill by model release date", fontsize=20)
|
||||
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)
|
||||
ax.set_ylim(30, 90)
|
||||
plt.xticks(fontsize=14, rotation=45, ha="right")
|
||||
plt.tight_layout(pad=1.0)
|
||||
|
||||
print("Debug: Saving figures...")
|
||||
plt.savefig("tmp_over_time.png")
|
||||
plt.savefig("tmp_over_time.svg")
|
||||
|
||||
print("Debug: Displaying figure with imgcat...")
|
||||
def save_and_display(self, fig: plt.Figure):
|
||||
plt.savefig("aider/website/assets/models-over-time.png")
|
||||
plt.savefig("aider/website/assets/models-over-time.svg")
|
||||
imgcat(fig)
|
||||
|
||||
print("Debug: Figure generation complete.")
|
||||
def plot(self, yaml_file: str):
|
||||
models = self.load_data(yaml_file)
|
||||
fig, ax = self.create_figure()
|
||||
self.plot_model_series(ax, models)
|
||||
self.set_labels_and_style(ax)
|
||||
self.save_and_display(fig)
|
||||
|
||||
|
||||
# Example usage
|
||||
plot_over_time("aider/website/_data/edit_leaderboard.yml")
|
||||
def main():
|
||||
plotter = BenchmarkPlotter()
|
||||
models = plotter.load_data("aider/website/_data/edit_leaderboard.yml")
|
||||
|
||||
# Print release dates and model names
|
||||
for model in sorted(models, key=lambda x: x.release_date):
|
||||
print(f"{model.release_date}: {model.name}")
|
||||
|
||||
plotter.plot("aider/website/_data/edit_leaderboard.yml")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -58,6 +58,7 @@ include = ["aider*", "aider.website"]
|
|||
"docs/unified-diffs.md",
|
||||
"docs/leaderboards/index.md",
|
||||
"assets/**",
|
||||
"**/.DS_Store",
|
||||
# [[[end]]]
|
||||
]
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#
|
||||
aiohappyeyeballs==2.4.3
|
||||
# via aiohttp
|
||||
aiohttp==3.10.10
|
||||
aiohttp==3.11.7
|
||||
# via litellm
|
||||
aiosignal==1.3.1
|
||||
# via aiohttp
|
||||
|
@ -62,11 +62,11 @@ gitdb==4.0.11
|
|||
# via gitpython
|
||||
gitpython==3.1.43
|
||||
# via -r requirements/requirements.in
|
||||
grep-ast==0.3.3
|
||||
grep-ast==0.4.0
|
||||
# via -r requirements/requirements.in
|
||||
h11==0.14.0
|
||||
# via httpcore
|
||||
httpcore==1.0.6
|
||||
httpcore==1.0.7
|
||||
# via httpx
|
||||
httpx==0.27.2
|
||||
# via openai
|
||||
|
@ -86,9 +86,9 @@ importlib-resources==6.4.5
|
|||
# via -r requirements/requirements.in
|
||||
jinja2==3.1.4
|
||||
# via litellm
|
||||
jiter==0.7.0
|
||||
jiter==0.7.1
|
||||
# via openai
|
||||
json5==0.9.25
|
||||
json5==0.9.28
|
||||
# via -r requirements/requirements.in
|
||||
jsonschema==4.23.0
|
||||
# via
|
||||
|
@ -96,7 +96,7 @@ jsonschema==4.23.0
|
|||
# litellm
|
||||
jsonschema-specifications==2024.10.1
|
||||
# via jsonschema
|
||||
litellm==1.51.2
|
||||
litellm==1.52.16
|
||||
# via -r requirements/requirements.in
|
||||
markdown-it-py==3.0.0
|
||||
# via rich
|
||||
|
@ -120,9 +120,9 @@ numpy==1.26.4
|
|||
# via
|
||||
# -r requirements/requirements.in
|
||||
# scipy
|
||||
openai==1.53.0
|
||||
openai==1.55.1
|
||||
# via litellm
|
||||
packaging==24.1
|
||||
packaging==24.2
|
||||
# via
|
||||
# -r requirements/requirements.in
|
||||
# huggingface-hub
|
||||
|
@ -134,12 +134,14 @@ pexpect==4.9.0
|
|||
# via -r requirements/requirements.in
|
||||
pillow==10.4.0
|
||||
# via -r requirements/requirements.in
|
||||
posthog==3.7.0
|
||||
posthog==3.7.3
|
||||
# via -r requirements/requirements.in
|
||||
prompt-toolkit==3.0.48
|
||||
# via -r requirements/requirements.in
|
||||
propcache==0.2.0
|
||||
# via yarl
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
psutil==6.1.0
|
||||
# via -r requirements/requirements.in
|
||||
ptyprocess==0.7.0
|
||||
|
@ -148,11 +150,11 @@ pycodestyle==2.12.1
|
|||
# via flake8
|
||||
pycparser==2.22
|
||||
# via cffi
|
||||
pydantic==2.9.2
|
||||
pydantic==2.10.2
|
||||
# via
|
||||
# litellm
|
||||
# openai
|
||||
pydantic-core==2.23.4
|
||||
pydantic-core==2.27.1
|
||||
# via pydantic
|
||||
pydub==0.25.1
|
||||
# via -r requirements/requirements.in
|
||||
|
@ -176,7 +178,7 @@ referencing==0.35.1
|
|||
# via
|
||||
# jsonschema
|
||||
# jsonschema-specifications
|
||||
regex==2024.9.11
|
||||
regex==2024.11.6
|
||||
# via tiktoken
|
||||
requests==2.32.3
|
||||
# via
|
||||
|
@ -185,9 +187,9 @@ requests==2.32.3
|
|||
# mixpanel
|
||||
# posthog
|
||||
# tiktoken
|
||||
rich==13.9.3
|
||||
rich==13.9.4
|
||||
# via -r requirements/requirements.in
|
||||
rpds-py==0.20.1
|
||||
rpds-py==0.21.0
|
||||
# via
|
||||
# jsonschema
|
||||
# referencing
|
||||
|
@ -217,7 +219,7 @@ tokenizers==0.19.1
|
|||
# via
|
||||
# -r requirements/requirements.in
|
||||
# litellm
|
||||
tqdm==4.66.6
|
||||
tqdm==4.67.1
|
||||
# via
|
||||
# huggingface-hub
|
||||
# openai
|
||||
|
@ -239,7 +241,7 @@ urllib3==2.2.3
|
|||
# requests
|
||||
wcwidth==0.2.13
|
||||
# via prompt-toolkit
|
||||
yarl==1.17.1
|
||||
yarl==1.18.0
|
||||
# via aiohttp
|
||||
zipp==3.20.2
|
||||
zipp==3.21.0
|
||||
# via importlib-metadata
|
||||
|
|
|
@ -4,109 +4,109 @@
|
|||
#
|
||||
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in
|
||||
#
|
||||
altair==5.4.1
|
||||
altair==5.5.0
|
||||
# via streamlit
|
||||
attrs==24.2.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# jsonschema
|
||||
# referencing
|
||||
blinker==1.8.2
|
||||
blinker==1.9.0
|
||||
# via streamlit
|
||||
cachetools==5.5.0
|
||||
# via streamlit
|
||||
certifi==2024.8.30
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# requests
|
||||
charset-normalizer==3.4.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# requests
|
||||
click==8.1.7
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# streamlit
|
||||
gitdb==4.0.11
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# gitpython
|
||||
gitpython==3.1.43
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# streamlit
|
||||
idna==3.10
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# requests
|
||||
jinja2==3.1.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# altair
|
||||
# pydeck
|
||||
jsonschema==4.23.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# altair
|
||||
jsonschema-specifications==2024.10.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# jsonschema
|
||||
markdown-it-py==3.0.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# rich
|
||||
markupsafe==3.0.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# jinja2
|
||||
mdurl==0.1.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# markdown-it-py
|
||||
narwhals==1.12.1
|
||||
narwhals==1.14.2
|
||||
# via altair
|
||||
numpy==1.26.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# pandas
|
||||
# pydeck
|
||||
# streamlit
|
||||
packaging==24.1
|
||||
packaging==24.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# altair
|
||||
|
@ -117,27 +117,27 @@ pandas==2.2.3
|
|||
# streamlit
|
||||
pillow==10.4.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# streamlit
|
||||
protobuf==5.28.3
|
||||
# via streamlit
|
||||
pyarrow==18.0.0
|
||||
pyarrow==18.1.0
|
||||
# via streamlit
|
||||
pydeck==0.9.1
|
||||
# via streamlit
|
||||
pygments==2.18.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# rich
|
||||
python-dateutil==2.9.0.post0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# pandas
|
||||
pytz==2024.2
|
||||
|
@ -146,41 +146,41 @@ pytz==2024.2
|
|||
# pandas
|
||||
referencing==0.35.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# jsonschema
|
||||
# jsonschema-specifications
|
||||
requests==2.32.3
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# streamlit
|
||||
rich==13.9.3
|
||||
rich==13.9.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# streamlit
|
||||
rpds-py==0.20.1
|
||||
rpds-py==0.21.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# jsonschema
|
||||
# referencing
|
||||
six==1.16.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# python-dateutil
|
||||
smmap==5.0.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# gitdb
|
||||
streamlit==1.39.0
|
||||
streamlit==1.40.2
|
||||
# via -r requirements/requirements-browser.in
|
||||
tenacity==8.5.0
|
||||
# via
|
||||
|
@ -188,12 +188,12 @@ tenacity==8.5.0
|
|||
# streamlit
|
||||
toml==0.10.2
|
||||
# via streamlit
|
||||
tornado==6.4.1
|
||||
tornado==6.4.2
|
||||
# via streamlit
|
||||
typing-extensions==4.12.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# altair
|
||||
|
@ -204,8 +204,8 @@ tzdata==2024.2
|
|||
# pandas
|
||||
urllib3==2.2.3
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
# requests
|
||||
|
|
|
@ -12,27 +12,27 @@ build==1.2.2.post1
|
|||
# via pip-tools
|
||||
certifi==2024.8.30
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# requests
|
||||
cfgv==3.4.0
|
||||
# via pre-commit
|
||||
charset-normalizer==3.4.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# requests
|
||||
click==8.1.7
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# pip-tools
|
||||
# typer
|
||||
codespell==2.3.0
|
||||
# via -r requirements/requirements-dev.in
|
||||
cogapp==3.4.1
|
||||
# via -r requirements/requirements-dev.in
|
||||
contourpy==1.3.0
|
||||
contourpy==1.3.1
|
||||
# via matplotlib
|
||||
cycler==0.12.1
|
||||
# via matplotlib
|
||||
|
@ -48,28 +48,28 @@ docutils==0.21.2
|
|||
# sphinx-rtd-theme
|
||||
filelock==3.16.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# virtualenv
|
||||
fonttools==4.54.1
|
||||
fonttools==4.55.0
|
||||
# via matplotlib
|
||||
identify==2.6.1
|
||||
identify==2.6.3
|
||||
# via pre-commit
|
||||
idna==3.10
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# requests
|
||||
imagesize==1.4.1
|
||||
# via sphinx
|
||||
imgcat==0.5.0
|
||||
imgcat==0.6.0
|
||||
# via -r requirements/requirements-dev.in
|
||||
iniconfig==2.0.0
|
||||
# via pytest
|
||||
jinja2==3.1.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# sphinx
|
||||
kiwisolver==1.4.7
|
||||
# via matplotlib
|
||||
|
@ -77,20 +77,20 @@ lox==0.12.0
|
|||
# via -r requirements/requirements-dev.in
|
||||
markdown-it-py==3.0.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# rich
|
||||
markupsafe==3.0.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# jinja2
|
||||
matplotlib==3.9.2
|
||||
# via -r requirements/requirements-dev.in
|
||||
mdurl==0.1.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# markdown-it-py
|
||||
multiprocess==0.70.17
|
||||
# via pathos
|
||||
|
@ -98,15 +98,15 @@ nodeenv==1.9.1
|
|||
# via pre-commit
|
||||
numpy==1.26.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# contourpy
|
||||
# matplotlib
|
||||
# pandas
|
||||
packaging==24.1
|
||||
packaging==24.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# build
|
||||
# matplotlib
|
||||
# pytest
|
||||
|
@ -117,8 +117,8 @@ pathos==0.3.3
|
|||
# via lox
|
||||
pillow==10.4.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# matplotlib
|
||||
pip-tools==7.4.1
|
||||
# via -r requirements/requirements-dev.in
|
||||
|
@ -134,8 +134,8 @@ pre-commit==4.0.1
|
|||
# via -r requirements/requirements-dev.in
|
||||
pygments==2.18.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# rich
|
||||
# sphinx
|
||||
pyparsing==3.2.0
|
||||
|
@ -148,26 +148,26 @@ pytest==8.3.3
|
|||
# via -r requirements/requirements-dev.in
|
||||
python-dateutil==2.9.0.post0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# matplotlib
|
||||
# pandas
|
||||
pytz==2024.2
|
||||
# via pandas
|
||||
pyyaml==6.0.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# pre-commit
|
||||
requests==2.32.3
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# sphinx
|
||||
rich==13.9.3
|
||||
rich==13.9.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# typer
|
||||
semver==3.0.2
|
||||
# via -r requirements/requirements-dev.in
|
||||
|
@ -175,8 +175,8 @@ shellingham==1.5.4
|
|||
# via typer
|
||||
six==1.16.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# python-dateutil
|
||||
snowballstemmer==2.2.0
|
||||
# via sphinx
|
||||
|
@ -184,7 +184,7 @@ sphinx==8.1.3
|
|||
# via
|
||||
# sphinx-rtd-theme
|
||||
# sphinxcontrib-jquery
|
||||
sphinx-rtd-theme==3.0.1
|
||||
sphinx-rtd-theme==3.0.2
|
||||
# via lox
|
||||
sphinxcontrib-applehelp==2.0.0
|
||||
# via sphinx
|
||||
|
@ -200,23 +200,23 @@ sphinxcontrib-qthelp==2.0.0
|
|||
# via sphinx
|
||||
sphinxcontrib-serializinghtml==2.0.0
|
||||
# via sphinx
|
||||
typer==0.12.5
|
||||
typer==0.13.1
|
||||
# via -r requirements/requirements-dev.in
|
||||
typing-extensions==4.12.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# typer
|
||||
tzdata==2024.2
|
||||
# via pandas
|
||||
urllib3==2.2.3
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# requests
|
||||
virtualenv==20.27.1
|
||||
virtualenv==20.28.0
|
||||
# via pre-commit
|
||||
wheel==0.44.0
|
||||
wheel==0.45.1
|
||||
# via pip-tools
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
|
|
|
@ -6,79 +6,81 @@
|
|||
#
|
||||
aiohappyeyeballs==2.4.3
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# aiohttp
|
||||
aiohttp==3.10.10
|
||||
aiohttp==3.11.7
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# huggingface-hub
|
||||
# llama-index-core
|
||||
aiosignal==1.3.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# aiohttp
|
||||
annotated-types==0.7.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# pydantic
|
||||
anyio==4.6.2.post1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# httpx
|
||||
attrs==24.2.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# aiohttp
|
||||
certifi==2024.8.30
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# httpcore
|
||||
# httpx
|
||||
# requests
|
||||
charset-normalizer==3.4.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# requests
|
||||
click==8.1.7
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# nltk
|
||||
dataclasses-json==0.6.7
|
||||
# via llama-index-core
|
||||
deprecated==1.2.14
|
||||
deprecated==1.2.15
|
||||
# via llama-index-core
|
||||
dirtyjson==1.0.8
|
||||
# via llama-index-core
|
||||
filelock==3.16.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# huggingface-hub
|
||||
# torch
|
||||
# transformers
|
||||
filetype==1.2.0
|
||||
# via llama-index-core
|
||||
frozenlist==1.5.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# aiohttp
|
||||
# aiosignal
|
||||
fsspec==2024.10.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# huggingface-hub
|
||||
# llama-index-core
|
||||
# torch
|
||||
|
@ -88,31 +90,31 @@ greenlet==3.0.3
|
|||
# sqlalchemy
|
||||
h11==0.14.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# httpcore
|
||||
httpcore==1.0.6
|
||||
httpcore==1.0.7
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# httpx
|
||||
httpx==0.27.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# llama-index-core
|
||||
huggingface-hub[inference]==0.26.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# llama-index-embeddings-huggingface
|
||||
# sentence-transformers
|
||||
# tokenizers
|
||||
# transformers
|
||||
idna==3.10
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# anyio
|
||||
# httpx
|
||||
|
@ -120,34 +122,34 @@ idna==3.10
|
|||
# yarl
|
||||
jinja2==3.1.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# torch
|
||||
joblib==1.4.2
|
||||
# via
|
||||
# nltk
|
||||
# scikit-learn
|
||||
llama-index-core==0.11.21
|
||||
llama-index-core==0.12.0
|
||||
# via
|
||||
# -r requirements/requirements-help.in
|
||||
# llama-index-embeddings-huggingface
|
||||
llama-index-embeddings-huggingface==0.3.1
|
||||
llama-index-embeddings-huggingface==0.4.0
|
||||
# via -r requirements/requirements-help.in
|
||||
markupsafe==3.0.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# jinja2
|
||||
marshmallow==3.23.0
|
||||
marshmallow==3.23.1
|
||||
# via dataclasses-json
|
||||
mpmath==1.3.0
|
||||
# via sympy
|
||||
multidict==6.1.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# aiohttp
|
||||
# yarl
|
||||
mypy-extensions==1.0.0
|
||||
|
@ -156,70 +158,71 @@ nest-asyncio==1.6.0
|
|||
# via llama-index-core
|
||||
networkx==3.2.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# llama-index-core
|
||||
# torch
|
||||
nltk==3.9.1
|
||||
# via llama-index-core
|
||||
numpy==1.26.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# llama-index-core
|
||||
# scikit-learn
|
||||
# scipy
|
||||
# transformers
|
||||
packaging==24.1
|
||||
packaging==24.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# huggingface-hub
|
||||
# marshmallow
|
||||
# transformers
|
||||
pillow==10.4.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# llama-index-core
|
||||
# sentence-transformers
|
||||
propcache==0.2.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# aiohttp
|
||||
# yarl
|
||||
pydantic==2.9.2
|
||||
pydantic==2.10.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# llama-index-core
|
||||
pydantic-core==2.23.4
|
||||
pydantic-core==2.27.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# pydantic
|
||||
pyyaml==6.0.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# huggingface-hub
|
||||
# llama-index-core
|
||||
# transformers
|
||||
regex==2024.9.11
|
||||
regex==2024.11.6
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# nltk
|
||||
# tiktoken
|
||||
# transformers
|
||||
requests==2.32.3
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# huggingface-hub
|
||||
# llama-index-core
|
||||
|
@ -231,16 +234,16 @@ scikit-learn==1.5.2
|
|||
# via sentence-transformers
|
||||
scipy==1.13.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# scikit-learn
|
||||
# sentence-transformers
|
||||
sentence-transformers==3.2.1
|
||||
sentence-transformers==3.3.1
|
||||
# via llama-index-embeddings-huggingface
|
||||
sniffio==1.3.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# anyio
|
||||
# httpx
|
||||
sqlalchemy[asyncio]==2.0.36
|
||||
|
@ -255,20 +258,20 @@ threadpoolctl==3.5.0
|
|||
# via scikit-learn
|
||||
tiktoken==0.8.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# llama-index-core
|
||||
tokenizers==0.19.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# transformers
|
||||
torch==2.2.2
|
||||
# via sentence-transformers
|
||||
tqdm==4.66.6
|
||||
tqdm==4.67.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# huggingface-hub
|
||||
# llama-index-core
|
||||
# nltk
|
||||
|
@ -278,8 +281,8 @@ transformers==4.44.2
|
|||
# via sentence-transformers
|
||||
typing-extensions==4.12.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# huggingface-hub
|
||||
# llama-index-core
|
||||
|
@ -294,16 +297,16 @@ typing-inspect==0.9.0
|
|||
# llama-index-core
|
||||
urllib3==2.2.3
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# requests
|
||||
wrapt==1.16.0
|
||||
wrapt==1.17.0
|
||||
# via
|
||||
# deprecated
|
||||
# llama-index-core
|
||||
yarl==1.17.1
|
||||
yarl==1.18.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# aiohttp
|
||||
|
|
|
@ -15,8 +15,8 @@ pyee==12.0.0
|
|||
# via playwright
|
||||
typing-extensions==4.12.2
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/../requirements.txt
|
||||
# -c requirements/requirements-browser.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# -c requirements/requirements-help.txt
|
||||
|
|
|
@ -15,6 +15,6 @@ RUN bundle install --retry 5 --jobs 20
|
|||
ENTRYPOINT [ "docker-entrypoint.sh" ]
|
||||
|
||||
# bundle exec jekyll serve --force_polling -H 0.0.0.0 -P 4000
|
||||
CMD [ "bundle", "exec", "jekyll", "serve", "--force_polling", "-H", "0.0.0.0", "-P", "4000" ]
|
||||
CMD [ "bundle", "exec", "jekyll", "serve", "--verbose", "--trace", "--force_polling", "-H", "0.0.0.0", "-P", "4000" ]
|
||||
|
||||
|
||||
|
|
|
@ -23,8 +23,10 @@ def blame(start_tag, end_tag=None):
|
|||
files = [
|
||||
f
|
||||
for f in files
|
||||
if f.endswith((".py", ".scm", ".sh", "Dockerfile", "Gemfile"))
|
||||
if f.endswith((".js", ".py", ".scm", ".sh", "Dockerfile", "Gemfile"))
|
||||
or (f.startswith(".github/workflows/") and f.endswith(".yml"))
|
||||
or f == "aider/website/share/index.md"
|
||||
or f == "aider/website/docs/leaderboards/index.md"
|
||||
]
|
||||
files = [f for f in files if not f.endswith("prompts.py")]
|
||||
|
||||
|
|
|
@ -22,15 +22,27 @@ def has_been_reopened(issue_number):
|
|||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
DUPLICATE_COMMENT = """Thanks for trying aider and filing this issue.
|
||||
BOT_SUFFIX = """Note: A [bot script](https://github.com/Aider-AI/aider/blob/main/scripts/issues.py) made these updates to the issue.
|
||||
""" # noqa
|
||||
|
||||
DUPLICATE_COMMENT = (
|
||||
"""Thanks for trying aider and filing this issue.
|
||||
|
||||
This looks like a duplicate of #{oldest_issue_number}. Please see the comments there for more information, and feel free to continue the discussion within that issue.
|
||||
|
||||
I'm going to close this issue for now. But please let me know if you think this is actually a distinct issue and I will reopen this issue.""" # noqa
|
||||
+ BOT_SUFFIX
|
||||
)
|
||||
|
||||
STALE_COMMENT = """I'm labeling this issue as stale because it has been open for 2 weeks with no activity. If there are no additional comments, it will be closed in 7 days.""" # noqa
|
||||
STALE_COMMENT = (
|
||||
"""I'm labeling this issue as stale because it has been open for 2 weeks with no activity. If there are no additional comments, I will close it in 7 days.""" # noqa
|
||||
+ BOT_SUFFIX
|
||||
)
|
||||
|
||||
CLOSE_STALE_COMMENT = """I'm closing this issue because it has been stalled for 3 weeks with no activity. Feel free to add a comment here and we can re-open it. Or feel free to file a new issue at any time.""" # noqa
|
||||
CLOSE_STALE_COMMENT = (
|
||||
"""I'm closing this issue because it has been stalled for 3 weeks with no activity. Feel free to add a comment here and we can re-open it. Or feel free to file a new issue at any time.""" # noqa
|
||||
+ BOT_SUFFIX
|
||||
)
|
||||
|
||||
# GitHub API configuration
|
||||
GITHUB_API_URL = "https://api.github.com"
|
||||
|
@ -279,7 +291,7 @@ def handle_stale_closing(all_issues, auto_yes):
|
|||
continue
|
||||
|
||||
# Add closing comment
|
||||
comment_url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments"
|
||||
comment_url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments" # noqa
|
||||
response = requests.post(
|
||||
comment_url, headers=headers, json={"body": CLOSE_STALE_COMMENT}
|
||||
)
|
||||
|
|
|
@ -24,6 +24,7 @@ cog $ARG \
|
|||
aider/website/docs/config/options.md \
|
||||
aider/website/docs/config/aider_conf.md \
|
||||
aider/website/docs/config/adv-model-settings.md \
|
||||
aider/website/docs/config/model-aliases.md \
|
||||
aider/website/docs/leaderboards/index.md \
|
||||
aider/website/docs/llms/other.md \
|
||||
aider/website/docs/more/infinite-output.md \
|
||||
|
|
72
scripts/update-history.py
Executable file
72
scripts/update-history.py
Executable file
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
from aider import __version__
|
||||
|
||||
|
||||
def get_base_version():
|
||||
# Parse current version like "0.64.2.dev" to get major.minor
|
||||
match = re.match(r"(\d+\.\d+)", __version__)
|
||||
if not match:
|
||||
raise ValueError(f"Could not parse version: {__version__}")
|
||||
return match.group(1) + ".0"
|
||||
|
||||
|
||||
def run_git_log():
|
||||
base_ver = get_base_version()
|
||||
cmd = [
|
||||
"git",
|
||||
"log",
|
||||
"-p",
|
||||
f"v{base_ver}..HEAD",
|
||||
"--",
|
||||
"aider/",
|
||||
":!aider/website/",
|
||||
":!scripts/",
|
||||
":!HISTORY.md",
|
||||
]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
return result.stdout
|
||||
|
||||
|
||||
def main():
|
||||
# Get the git log output
|
||||
diff_content = run_git_log()
|
||||
|
||||
# Save to temporary file
|
||||
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".diff") as tmp:
|
||||
tmp.write(diff_content)
|
||||
tmp_path = tmp.name
|
||||
|
||||
# Run blame to get aider percentage
|
||||
blame_result = subprocess.run(["python3", "scripts/blame.py"], capture_output=True, text=True)
|
||||
aider_line = blame_result.stdout.strip().split("\n")[-1] # Get last line with percentage
|
||||
|
||||
# Construct and run the aider command
|
||||
message = f"""
|
||||
Update the history with changes shown in the diffs.
|
||||
Describe actual user-facing changes, not every single commit that was made implementing them.
|
||||
Don't edit or duplicate changes that have existing history entries, just add any new items not already listed.
|
||||
Be sure to attribute changes to the proper .x version.
|
||||
Changes in the .x-dev version should be listed under a "### main branch" heading
|
||||
|
||||
Also, add this as the last bullet under the "### main branch" section:
|
||||
{aider_line}
|
||||
""" # noqa
|
||||
|
||||
cmd = ["aider", "HISTORY.md", "--read", tmp_path, "--msg", message, "--no-auto-commit"]
|
||||
subprocess.run(cmd)
|
||||
|
||||
# Run update-docs.sh after aider
|
||||
subprocess.run(["scripts/update-docs.sh"])
|
||||
|
||||
# Cleanup
|
||||
os.unlink(tmp_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -124,7 +124,10 @@ def main():
|
|||
for cmd in git_commands:
|
||||
print(f"Running: {' '.join(cmd)}")
|
||||
if not dry_run:
|
||||
subprocess.run(cmd, check=True)
|
||||
subprocess.run(
|
||||
cmd,
|
||||
check=True,
|
||||
)
|
||||
|
||||
new_dev_version = f"{incremented_version}.dev"
|
||||
updated_dev_content = re.sub(
|
||||
|
|
|
@ -91,10 +91,49 @@ def test_system_info(temp_data_dir):
|
|||
|
||||
def test_need_to_ask(temp_data_dir):
|
||||
analytics = Analytics()
|
||||
assert analytics.need_to_ask() is True
|
||||
assert analytics.need_to_ask(True) is True
|
||||
assert analytics.need_to_ask(False) is False
|
||||
|
||||
analytics.user_id = "111"
|
||||
assert analytics.need_to_ask(None) is False
|
||||
|
||||
analytics.user_id = "000"
|
||||
assert analytics.need_to_ask(None) is True
|
||||
|
||||
analytics.asked_opt_in = True
|
||||
assert analytics.need_to_ask() is False
|
||||
assert analytics.need_to_ask(True) is False
|
||||
|
||||
analytics.permanently_disable = True
|
||||
assert analytics.need_to_ask() is False
|
||||
assert analytics.need_to_ask(True) is False
|
||||
|
||||
|
||||
def test_is_uuid_in_percentage():
|
||||
analytics = Analytics()
|
||||
|
||||
# Test basic percentage thresholds
|
||||
assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 1) is True
|
||||
assert analytics.is_uuid_in_percentage("01999000000000000000000000000000", 1) is True
|
||||
assert analytics.is_uuid_in_percentage("02000000000000000000000000000000", 1) is True
|
||||
assert analytics.is_uuid_in_percentage("02910000000000000000000000000001", 1) is False
|
||||
assert analytics.is_uuid_in_percentage("03000000000000000000000000000000", 1) is False
|
||||
assert analytics.is_uuid_in_percentage("ff000000000000000000000000000000", 1) is False
|
||||
|
||||
assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 10) is True
|
||||
assert analytics.is_uuid_in_percentage("19000000000000000000000000000000", 10) is True
|
||||
assert analytics.is_uuid_in_percentage("1a000000000000000000000000000000", 10) is False
|
||||
assert analytics.is_uuid_in_percentage("ff000000000000000000000000000000", 10) is False
|
||||
|
||||
# Test edge cases
|
||||
assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 0) is False
|
||||
assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 100) is True
|
||||
assert analytics.is_uuid_in_percentage("ffffffffffffffffffffffffffffffff", 100) is True
|
||||
|
||||
# Test invalid inputs
|
||||
with pytest.raises(ValueError):
|
||||
analytics.is_uuid_in_percentage("00000000000000000000000000000000", -1)
|
||||
with pytest.raises(ValueError):
|
||||
analytics.is_uuid_in_percentage("00000000000000000000000000000000", 101)
|
||||
|
||||
# Test empty/None UUID
|
||||
assert analytics.is_uuid_in_percentage("", 50) is False
|
||||
assert analytics.is_uuid_in_percentage(None, 50) is False
|
||||
|
|
|
@ -7,6 +7,7 @@ from unittest.mock import MagicMock, patch
|
|||
import git
|
||||
|
||||
from aider.coders import Coder
|
||||
from aider.coders.base_coder import UnknownEditFormat
|
||||
from aider.dump import dump # noqa: F401
|
||||
from aider.io import InputOutput
|
||||
from aider.models import Model
|
||||
|
@ -168,6 +169,37 @@ class TestCoder(unittest.TestCase):
|
|||
|
||||
self.assertEqual(coder.abs_fnames, set([str(fname.resolve())]))
|
||||
|
||||
def test_skip_duplicate_basename_mentions(self):
|
||||
with GitTemporaryDirectory():
|
||||
io = InputOutput(pretty=False, yes=True)
|
||||
coder = Coder.create(self.GPT35, None, io)
|
||||
|
||||
# Create files with same basename in different directories
|
||||
fname1 = Path("dir1") / "file.txt"
|
||||
fname2 = Path("dir2") / "file.txt"
|
||||
fname3 = Path("dir3") / "unique.txt"
|
||||
|
||||
for fname in [fname1, fname2, fname3]:
|
||||
fname.parent.mkdir(parents=True, exist_ok=True)
|
||||
fname.touch()
|
||||
|
||||
# Add one file to chat
|
||||
coder.add_rel_fname(str(fname1))
|
||||
|
||||
# Mock get_tracked_files to return all files
|
||||
mock = MagicMock()
|
||||
mock.return_value = set([str(fname1), str(fname2), str(fname3)])
|
||||
coder.repo.get_tracked_files = mock
|
||||
|
||||
# Check that file mentions skip files with duplicate basenames
|
||||
mentioned = coder.get_file_mentions(f"Check {fname2} and {fname3}")
|
||||
self.assertEqual(mentioned, {str(fname3)})
|
||||
|
||||
# Add a read-only file with same basename
|
||||
coder.abs_read_only_fnames.add(str(fname2.resolve()))
|
||||
mentioned = coder.get_file_mentions(f"Check {fname1} and {fname3}")
|
||||
self.assertEqual(mentioned, {str(fname3)})
|
||||
|
||||
def test_check_for_file_mentions_read_only(self):
|
||||
with GitTemporaryDirectory():
|
||||
io = InputOutput(
|
||||
|
@ -821,32 +853,55 @@ This command will print 'Hello, World!' to the console."""
|
|||
with GitTemporaryDirectory():
|
||||
io = InputOutput(yes=True)
|
||||
coder = Coder.create(self.GPT35, "diff", io=io, suggest_shell_commands=False)
|
||||
self.assertFalse(coder.suggest_shell_commands)
|
||||
|
||||
def mock_send(*args, **kwargs):
|
||||
coder.partial_response_content = """Here's a shell command to run:
|
||||
def test_detect_urls_enabled(self):
|
||||
with GitTemporaryDirectory():
|
||||
io = InputOutput(yes=True)
|
||||
coder = Coder.create(self.GPT35, "diff", io=io, detect_urls=True)
|
||||
coder.commands.scraper = MagicMock()
|
||||
coder.commands.scraper.scrape = MagicMock(return_value="some content")
|
||||
|
||||
```bash
|
||||
echo "Hello, World!"
|
||||
```
|
||||
# Test with a message containing a URL
|
||||
message = "Check out https://example.com"
|
||||
coder.check_for_urls(message)
|
||||
coder.commands.scraper.scrape.assert_called_once_with("https://example.com")
|
||||
|
||||
This command will print 'Hello, World!' to the console."""
|
||||
coder.partial_response_function_call = dict()
|
||||
return []
|
||||
def test_detect_urls_disabled(self):
|
||||
with GitTemporaryDirectory():
|
||||
io = InputOutput(yes=True)
|
||||
coder = Coder.create(self.GPT35, "diff", io=io, detect_urls=False)
|
||||
coder.commands.scraper = MagicMock()
|
||||
coder.commands.scraper.scrape = MagicMock(return_value="some content")
|
||||
|
||||
coder.send = mock_send
|
||||
# Test with a message containing a URL
|
||||
message = "Check out https://example.com"
|
||||
result = coder.check_for_urls(message)
|
||||
self.assertEqual(result, [])
|
||||
coder.commands.scraper.scrape.assert_not_called()
|
||||
|
||||
# Mock the handle_shell_commands method to check if it's called
|
||||
coder.handle_shell_commands = MagicMock()
|
||||
def test_unknown_edit_format_exception(self):
|
||||
# Test the exception message format
|
||||
invalid_format = "invalid_format"
|
||||
valid_formats = ["diff", "whole", "map"]
|
||||
exc = UnknownEditFormat(invalid_format, valid_formats)
|
||||
expected_msg = (
|
||||
f"Unknown edit format {invalid_format}. Valid formats are: {', '.join(valid_formats)}"
|
||||
)
|
||||
self.assertEqual(str(exc), expected_msg)
|
||||
|
||||
# Run the coder with a message
|
||||
coder.run(with_message="Suggest a shell command")
|
||||
def test_unknown_edit_format_creation(self):
|
||||
# Test that creating a Coder with invalid edit format raises the exception
|
||||
io = InputOutput(yes=True)
|
||||
invalid_format = "invalid_format"
|
||||
|
||||
# Check if the shell command was added to the list
|
||||
self.assertEqual(len(coder.shell_commands), 1)
|
||||
self.assertEqual(coder.shell_commands[0].strip(), 'echo "Hello, World!"')
|
||||
with self.assertRaises(UnknownEditFormat) as cm:
|
||||
Coder.create(self.GPT35, invalid_format, io=io)
|
||||
|
||||
# Check if handle_shell_commands was called with the correct argument
|
||||
coder.handle_shell_commands.assert_not_called()
|
||||
exc = cm.exception
|
||||
self.assertEqual(exc.edit_format, invalid_format)
|
||||
self.assertIsInstance(exc.valid_formats, list)
|
||||
self.assertTrue(len(exc.valid_formats) > 0)
|
||||
|
||||
def test_coder_create_with_new_file_oserror(self):
|
||||
with GitTemporaryDirectory():
|
||||
|
|
|
@ -1068,8 +1068,10 @@ class TestCommands(TestCase):
|
|||
io.prompt_ask = lambda *args, **kwargs: "y"
|
||||
|
||||
# Test the cmd_run method with a command that should not raise an error
|
||||
result = commands.cmd_run("exit 1", add_on_nonzero_exit=True)
|
||||
self.assertIn("I ran this command", result)
|
||||
commands.cmd_run("exit 1", add_on_nonzero_exit=True)
|
||||
|
||||
# Check that the output was added to cur_messages
|
||||
self.assertTrue(any("exit 1" in msg["content"] for msg in coder.cur_messages))
|
||||
|
||||
def test_cmd_add_drop_untracked_files(self):
|
||||
with GitTemporaryDirectory():
|
||||
|
|
129
tests/basic/test_editor.py
Normal file
129
tests/basic/test_editor.py
Normal file
|
@ -0,0 +1,129 @@
|
|||
import os
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from aider.editor import (
|
||||
DEFAULT_EDITOR_NIX,
|
||||
DEFAULT_EDITOR_OS_X,
|
||||
DEFAULT_EDITOR_WINDOWS,
|
||||
discover_editor,
|
||||
get_environment_editor,
|
||||
pipe_editor,
|
||||
print_status_message,
|
||||
write_temp_file,
|
||||
)
|
||||
|
||||
|
||||
def test_get_environment_editor():
|
||||
# Test with no environment variables set
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
assert get_environment_editor("default") == "default"
|
||||
|
||||
# Test EDITOR precedence
|
||||
with patch.dict(os.environ, {"EDITOR": "vim"}):
|
||||
assert get_environment_editor() == "vim"
|
||||
|
||||
# Test VISUAL overrides EDITOR
|
||||
with patch.dict(os.environ, {"EDITOR": "vim", "VISUAL": "code"}):
|
||||
assert get_environment_editor() == "code"
|
||||
|
||||
|
||||
def test_discover_editor_defaults():
|
||||
with patch("platform.system") as mock_system:
|
||||
# Test Windows default
|
||||
mock_system.return_value = "Windows"
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
assert discover_editor() == [DEFAULT_EDITOR_WINDOWS]
|
||||
|
||||
# Test macOS default
|
||||
mock_system.return_value = "Darwin"
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
assert discover_editor() == [DEFAULT_EDITOR_OS_X]
|
||||
|
||||
# Test Linux default
|
||||
mock_system.return_value = "Linux"
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
assert discover_editor() == [DEFAULT_EDITOR_NIX]
|
||||
|
||||
|
||||
def test_write_temp_file():
|
||||
# Test basic file creation
|
||||
content = "test content"
|
||||
filepath = write_temp_file(content)
|
||||
assert os.path.exists(filepath)
|
||||
with open(filepath, "r") as f:
|
||||
assert f.read() == content
|
||||
os.remove(filepath)
|
||||
|
||||
# Test with suffix
|
||||
filepath = write_temp_file("content", suffix="txt")
|
||||
assert filepath.endswith(".txt")
|
||||
os.remove(filepath)
|
||||
|
||||
# Test with prefix
|
||||
filepath = write_temp_file("content", prefix="test_")
|
||||
assert os.path.basename(filepath).startswith("test_")
|
||||
os.remove(filepath)
|
||||
|
||||
|
||||
def test_print_status_message(capsys):
|
||||
# Test success message
|
||||
print_status_message(True, "Success!")
|
||||
captured = capsys.readouterr()
|
||||
assert "Success!" in captured.out
|
||||
|
||||
# Test failure message
|
||||
print_status_message(False, "Failed!")
|
||||
captured = capsys.readouterr()
|
||||
assert "Failed!" in captured.out
|
||||
|
||||
|
||||
def test_discover_editor_override():
|
||||
# Test editor override
|
||||
assert discover_editor("code") == ["code"]
|
||||
assert discover_editor('vim -c "set noswapfile"') == ["vim", "-c", "set noswapfile"]
|
||||
|
||||
# Test invalid editor command
|
||||
with pytest.raises(RuntimeError):
|
||||
discover_editor('vim "unclosed quote')
|
||||
|
||||
|
||||
def test_pipe_editor():
|
||||
# Test with default editor
|
||||
test_content = "Initial content"
|
||||
modified_content = "Modified content"
|
||||
|
||||
# Mock the file operations and editor call
|
||||
with (
|
||||
patch("aider.editor.write_temp_file") as mock_write,
|
||||
patch("builtins.open") as mock_open,
|
||||
patch("os.remove") as mock_remove,
|
||||
patch("subprocess.call") as mock_subprocess,
|
||||
):
|
||||
# Setup mocks
|
||||
mock_write.return_value = "temp.txt"
|
||||
mock_file = MagicMock()
|
||||
mock_file.__enter__.return_value.read.return_value = modified_content
|
||||
mock_open.return_value = mock_file
|
||||
|
||||
# Test with default editor
|
||||
result = pipe_editor(test_content)
|
||||
assert result == modified_content
|
||||
mock_write.assert_called_with(test_content, None)
|
||||
mock_subprocess.assert_called()
|
||||
|
||||
# Test with custom editor
|
||||
result = pipe_editor(test_content, editor="code")
|
||||
assert result == modified_content
|
||||
mock_subprocess.assert_called()
|
||||
|
||||
# Test with suffix
|
||||
result = pipe_editor(test_content, suffix="md")
|
||||
assert result == modified_content
|
||||
mock_write.assert_called_with(test_content, "md")
|
||||
|
||||
# Test cleanup on permission error
|
||||
mock_remove.side_effect = PermissionError
|
||||
result = pipe_editor(test_content)
|
||||
assert result == modified_content
|
|
@ -45,7 +45,7 @@ class TestMain(TestCase):
|
|||
self.webbrowser_patcher.stop()
|
||||
|
||||
def test_main_with_empty_dir_no_files_on_command(self):
|
||||
main(["--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
|
||||
main(["--no-git", "--exit", "--yes"], input=DummyInput(), output=DummyOutput())
|
||||
|
||||
def test_main_with_emptqy_dir_new_file(self):
|
||||
main(["foo.txt", "--yes", "--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
|
||||
|
@ -332,7 +332,7 @@ class TestMain(TestCase):
|
|||
def test_false_vals_in_env_file(self):
|
||||
self.create_env_file(".env", "AIDER_SHOW_DIFFS=off")
|
||||
with patch("aider.coders.Coder.create") as MockCoder:
|
||||
main(["--no-git"], input=DummyInput(), output=DummyOutput())
|
||||
main(["--no-git", "--yes"], input=DummyInput(), output=DummyOutput())
|
||||
MockCoder.assert_called_once()
|
||||
_, kwargs = MockCoder.call_args
|
||||
self.assertEqual(kwargs["show_diffs"], False)
|
||||
|
@ -340,7 +340,7 @@ class TestMain(TestCase):
|
|||
def test_true_vals_in_env_file(self):
|
||||
self.create_env_file(".env", "AIDER_SHOW_DIFFS=on")
|
||||
with patch("aider.coders.Coder.create") as MockCoder:
|
||||
main(["--no-git"], input=DummyInput(), output=DummyOutput())
|
||||
main(["--no-git", "--yes"], input=DummyInput(), output=DummyOutput())
|
||||
MockCoder.assert_called_once()
|
||||
_, kwargs = MockCoder.call_args
|
||||
self.assertEqual(kwargs["show_diffs"], True)
|
||||
|
@ -381,7 +381,11 @@ class TestMain(TestCase):
|
|||
def test_verbose_mode_lists_env_vars(self):
|
||||
self.create_env_file(".env", "AIDER_DARK_MODE=on")
|
||||
with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
|
||||
main(["--no-git", "--verbose", "--exit"], input=DummyInput(), output=DummyOutput())
|
||||
main(
|
||||
["--no-git", "--verbose", "--exit", "--yes"],
|
||||
input=DummyInput(),
|
||||
output=DummyOutput(),
|
||||
)
|
||||
output = mock_stdout.getvalue()
|
||||
relevant_output = "\n".join(
|
||||
line
|
||||
|
@ -633,6 +637,49 @@ class TestMain(TestCase):
|
|||
)
|
||||
self.assertTrue(coder.suggest_shell_commands)
|
||||
|
||||
def test_detect_urls_default(self):
|
||||
with GitTemporaryDirectory():
|
||||
coder = main(
|
||||
["--exit", "--yes"],
|
||||
input=DummyInput(),
|
||||
output=DummyOutput(),
|
||||
return_coder=True,
|
||||
)
|
||||
self.assertTrue(coder.detect_urls)
|
||||
|
||||
def test_detect_urls_disabled(self):
|
||||
with GitTemporaryDirectory():
|
||||
coder = main(
|
||||
["--no-detect-urls", "--exit", "--yes"],
|
||||
input=DummyInput(),
|
||||
output=DummyOutput(),
|
||||
return_coder=True,
|
||||
)
|
||||
self.assertFalse(coder.detect_urls)
|
||||
|
||||
def test_detect_urls_enabled(self):
|
||||
with GitTemporaryDirectory():
|
||||
coder = main(
|
||||
["--detect-urls", "--exit", "--yes"],
|
||||
input=DummyInput(),
|
||||
output=DummyOutput(),
|
||||
return_coder=True,
|
||||
)
|
||||
self.assertTrue(coder.detect_urls)
|
||||
|
||||
def test_invalid_edit_format(self):
|
||||
with GitTemporaryDirectory():
|
||||
with patch("aider.io.InputOutput.offer_url") as mock_offer_url:
|
||||
result = main(
|
||||
["--edit-format", "not-a-real-format", "--exit", "--yes"],
|
||||
input=DummyInput(),
|
||||
output=DummyOutput(),
|
||||
)
|
||||
self.assertEqual(result, 1) # main() should return 1 on error
|
||||
mock_offer_url.assert_called_once()
|
||||
args, _ = mock_offer_url.call_args
|
||||
self.assertEqual(args[0], "https://aider.chat/docs/more/edit-formats.html")
|
||||
|
||||
def test_chat_language_spanish(self):
|
||||
with GitTemporaryDirectory():
|
||||
coder = main(
|
||||
|
|
|
@ -2,8 +2,10 @@ import unittest
|
|||
from unittest.mock import ANY, MagicMock, patch
|
||||
|
||||
from aider.models import (
|
||||
ANTHROPIC_BETA_HEADER,
|
||||
Model,
|
||||
ModelInfoManager,
|
||||
register_models,
|
||||
sanity_check_model,
|
||||
sanity_check_models,
|
||||
)
|
||||
|
@ -80,7 +82,9 @@ class TestModels(unittest.TestCase):
|
|||
) # Should return True because there's a problem with the editor model
|
||||
mock_io.tool_warning.assert_called_with(ANY) # Ensure a warning was issued
|
||||
|
||||
warning_messages = [call.args[0] for call in mock_io.tool_warning.call_args_list]
|
||||
warning_messages = [
|
||||
warning_call.args[0] for warning_call in mock_io.tool_warning.call_args_list
|
||||
]
|
||||
print("Warning messages:", warning_messages) # Add this line
|
||||
|
||||
self.assertGreaterEqual(mock_io.tool_warning.call_count, 1) # Expect two warnings
|
||||
|
@ -88,6 +92,87 @@ class TestModels(unittest.TestCase):
|
|||
any("bogus-model" in msg for msg in warning_messages)
|
||||
) # Check that one of the warnings mentions the bogus model
|
||||
|
||||
def test_model_aliases(self):
|
||||
# Test common aliases
|
||||
model = Model("4")
|
||||
self.assertEqual(model.name, "gpt-4-0613")
|
||||
|
||||
model = Model("4o")
|
||||
self.assertEqual(model.name, "gpt-4o-2024-08-06")
|
||||
|
||||
model = Model("35turbo")
|
||||
self.assertEqual(model.name, "gpt-3.5-turbo")
|
||||
|
||||
model = Model("35-turbo")
|
||||
self.assertEqual(model.name, "gpt-3.5-turbo")
|
||||
|
||||
model = Model("3")
|
||||
self.assertEqual(model.name, "gpt-3.5-turbo")
|
||||
|
||||
model = Model("sonnet")
|
||||
self.assertEqual(model.name, "claude-3-sonnet-20241022")
|
||||
|
||||
model = Model("haiku")
|
||||
self.assertEqual(model.name, "claude-3-haiku-20241022")
|
||||
|
||||
model = Model("opus")
|
||||
self.assertEqual(model.name, "claude-3-opus-20240229")
|
||||
|
||||
# Test non-alias passes through unchanged
|
||||
model = Model("gpt-4")
|
||||
self.assertEqual(model.name, "gpt-4")
|
||||
|
||||
def test_aider_extra_model_settings(self):
|
||||
import tempfile
|
||||
|
||||
import yaml
|
||||
|
||||
# Create temporary YAML file with test settings
|
||||
test_settings = [
|
||||
{
|
||||
"name": "aider/extra_params",
|
||||
"extra_params": {
|
||||
"extra_headers": {"Foo": "bar"},
|
||||
"some_param": "some value",
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
# Write to a regular file instead of NamedTemporaryFile
|
||||
# for better cross-platform compatibility
|
||||
tmp = tempfile.mktemp(suffix=".yml")
|
||||
try:
|
||||
with open(tmp, "w") as f:
|
||||
yaml.dump(test_settings, f)
|
||||
|
||||
# Register the test settings
|
||||
register_models([tmp])
|
||||
|
||||
# Test that defaults are applied when no exact match
|
||||
model = Model("claude-3-5-sonnet-20240620")
|
||||
# Test that both the override and existing headers are present
|
||||
model = Model("claude-3-5-sonnet-20240620")
|
||||
self.assertEqual(model.extra_params["extra_headers"]["Foo"], "bar")
|
||||
self.assertEqual(
|
||||
model.extra_params["extra_headers"]["anthropic-beta"],
|
||||
ANTHROPIC_BETA_HEADER,
|
||||
)
|
||||
self.assertEqual(model.extra_params["some_param"], "some value")
|
||||
self.assertEqual(model.extra_params["max_tokens"], 8192)
|
||||
|
||||
# Test that exact match overrides defaults but not overrides
|
||||
model = Model("gpt-4")
|
||||
self.assertEqual(model.extra_params["extra_headers"]["Foo"], "bar")
|
||||
self.assertEqual(model.extra_params["some_param"], "some value")
|
||||
finally:
|
||||
# Clean up the temporary file
|
||||
import os
|
||||
|
||||
try:
|
||||
os.unlink(tmp)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -373,6 +373,19 @@ class TestRepoMapAllLanguages(unittest.TestCase):
|
|||
|
||||
def test_get_repo_map_all_languages(self):
|
||||
language_files = {
|
||||
"dart": (
|
||||
"test.dart",
|
||||
"""void main() {
|
||||
print('Hello, World!');
|
||||
}
|
||||
|
||||
class Greeter {
|
||||
String sayHello(String name) {
|
||||
return 'Hello, $name!';
|
||||
}
|
||||
}
|
||||
""",
|
||||
),
|
||||
"c": (
|
||||
"test.c",
|
||||
(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue