-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathagents.py
More file actions
143 lines (121 loc) · 4.04 KB
/
Copy pathagents.py
File metadata and controls
143 lines (121 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import sys
from abc import ABC, abstractmethod
from pathlib import Path
import logging
from aider.coders import Coder
from aider.models import Model
from aider.io import InputOutput
import re
def handle_logging(logging_name: str, log_file: Path) -> None:
"""Handle logging for agent"""
logger = logging.getLogger(logging_name)
logger.setLevel(logging.INFO)
logger.propagate = False
logger_handler = logging.FileHandler(log_file)
logger_handler.setFormatter(
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
)
logger.addHandler(logger_handler)
class AgentReturn(ABC):
def __init__(self, log_file: Path):
self.log_file = log_file
self.last_cost = self.get_money_cost()
def get_money_cost(self) -> float:
"""Get accumulated money cost from log file"""
last_cost = 0.0
with open(self.log_file, "r") as file:
for line in file:
if "Tokens:" in line and "Cost:" in line:
match = re.search(
r"Cost: \$\d+\.\d+ message, \$(\d+\.\d+) session", line
)
if match:
last_cost = float(match.group(1))
return last_cost
class Agents(ABC):
def __init__(self, max_iteration: int):
self.max_iteration = max_iteration
@abstractmethod
def run(self) -> AgentReturn:
"""Start agent"""
raise NotImplementedError
class AiderAgents(Agents):
def __init__(self, max_iteration: int, model_name: str):
super().__init__(max_iteration)
self.model = Model(model_name)
def run(
self,
message: str,
test_cmd: str,
lint_cmd: str,
fnames: list[str],
log_dir: Path,
test_first: bool = False,
) -> AgentReturn:
"""Start aider agent"""
if test_cmd:
auto_test = True
else:
auto_test = False
if lint_cmd:
auto_lint = True
else:
auto_lint = False
log_dir = log_dir.resolve()
log_dir.mkdir(parents=True, exist_ok=True)
input_history_file = log_dir / ".aider.input.history"
chat_history_file = log_dir / ".aider.chat.history.md"
# Set up logging
log_file = log_dir / "aider.log"
logging.basicConfig(
filename=log_file,
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
# Redirect print statements to the log file
sys.stdout = open(log_file, "a")
sys.stderr = open(log_file, "a")
# Configure httpx and backoff logging
handle_logging("httpx", log_file)
handle_logging("backoff", log_file)
io = InputOutput(
yes=True,
input_history_file=input_history_file,
chat_history_file=chat_history_file,
)
coder = Coder.create(
main_model=self.model,
fnames=fnames,
auto_lint=auto_lint,
auto_test=auto_test,
lint_cmds={"python": lint_cmd},
test_cmd=test_cmd,
io=io,
)
coder.max_reflection = self.max_iteration
coder.stream = True
# Run the agent
if test_first:
test_errors = coder.commands.cmd_test(test_cmd)
if test_errors:
coder.run(test_errors)
else:
coder.run(message)
# #### TMP
# #### TMP
# import time
# import random
# time.sleep(random.random() * 5)
# n = random.random() / 10
# with open(log_file, "a") as f:
# f.write(
# f"> Tokens: 33k sent, 1.3k received. Cost: $0.12 message, ${n} session. \n"
# )
# #### TMP
# Close redirected stdout and stderr
sys.stdout.close()
sys.stderr.close()
# Restore original stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
return AgentReturn(log_file)