Skip to content

Commit 8729378

Browse files
authored
Merge pull request #3 from JamesVorder/cleaup-1
Cleanup PR
2 parents 63370bd + 8d58333 commit 8729378

File tree

6 files changed

+129
-138
lines changed

6 files changed

+129
-138
lines changed

TestRunner/GenericTestRunner.py

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import pytest
21
import subprocess
32
from lib.utils import CodeGenSandbox
43
from abc import ABCMeta, abstractmethod
5-
from pytest_plugins import ResultsCollector, SessionStartPlugin
64

75

86
class GenericTestRunner(metaclass=ABCMeta):
@@ -11,6 +9,7 @@ def run(self, *args, **kwargs) -> (int, str): pass
119

1210

1311
class SubProcessTestRunner(GenericTestRunner):
12+
1413
sandbox: CodeGenSandbox
1514

1615
def __init__(self, sandbox: CodeGenSandbox) -> None:
@@ -24,25 +23,3 @@ def run(self, *args, **kwargs) -> (int, str):
2423
universal_newlines=True
2524
)
2625
return proc.returncode, proc.stdout
27-
28-
29-
# TODO: This implementation is currently defunct
30-
# class InlineTestRunner(GenericTestRunner):
31-
#
32-
# def __init__(self, sandbox) -> None:
33-
# self.test_dir = sandbox.get_sandboxed_test_path()
34-
#
35-
# def run(self, *args, **kwargs) -> (int, str):
36-
# collector = ResultsCollector()
37-
# setup = SessionStartPlugin()
38-
# # TODO: Remove the ExampleClass reference here.
39-
# pytest.main(args=["-k", "ExampleClass"], plugins=[collector, setup])
40-
# _out = ""
41-
#
42-
# if collector.exitcode > 0:
43-
# for report in collector.reports:
44-
# _out += f"{report.outcome.upper()} {report.nodeid} ... Outcome: - {report.longrepr.reprcrash.message}"
45-
# _out += "\n"
46-
# _out += report.longreprtext
47-
# _out += "\n"
48-
# return collector.exitcode, _out

generated/__init__.py

Whitespace-only changes.

generated/test_class.py

Whitespace-only changes.

lib/agents.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from abc import ABCMeta, abstractmethod
2+
3+
from langroid import ChatAgent, ChatAgentConfig
4+
5+
from lib.utils import CodeGenSandbox
6+
7+
8+
class GenericAgent(metaclass=ABCMeta):
9+
@abstractmethod
10+
def respond(self, prompt: str, *args, **kwargs) -> str: pass
11+
12+
13+
class CodeGenAgent(GenericAgent):
14+
15+
sandbox: CodeGenSandbox
16+
agent: ChatAgent
17+
class_skeleton: str
18+
previous_code_attempt: str
19+
latest_test_result: str
20+
latest_test_result_interpretation: str
21+
22+
def __init__(self, sandbox: CodeGenSandbox, config: ChatAgentConfig):
23+
self.sandbox = sandbox
24+
25+
with open(self.sandbox.get_sandboxed_class_path(), "r") as f:
26+
self.class_skeleton = f.read()
27+
28+
self.agent = ChatAgent(config)
29+
30+
def respond(self, prompt: str, *args, **kwargs) -> str:
31+
response = self.agent.llm_response(prompt)
32+
with open(self.sandbox.get_sandboxed_class_path(), "w+") as _out:
33+
_out.write(response.content)
34+
35+
return response.content
36+
37+
def set_previous_code_attempt(self, attempt: str) -> None:
38+
self.previous_code_attempt = attempt
39+
40+
def set_latest_test_result(self, tr: str) -> None:
41+
self.latest_test_result = tr
42+
43+
def set_latest_test_result_interpretation(self, interpretation: str) -> None:
44+
self.latest_test_result_interpretation = interpretation
45+
46+
47+
class TestInterpreterAgent(GenericAgent):
48+
49+
sandbox: CodeGenSandbox
50+
agent: ChatAgent
51+
latest_test_results: str
52+
latest_test_exit_code: int
53+
54+
def __init__(self, sandbox: CodeGenSandbox, config: ChatAgentConfig) -> None:
55+
self.sandbox = sandbox
56+
self.agent = ChatAgent(config)
57+
58+
def set_latest_test_results(self, results: str) -> None:
59+
self.latest_test_results = results
60+
61+
def set_latest_test_exit_code(self, code: int) -> None:
62+
self.latest_test_exit_code = code
63+
64+
def respond(self, prompt: str, *args, **kwargs) -> str:
65+
return self.agent.llm_response(prompt)

main.py

Lines changed: 63 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import os
2+
3+
from langroid import ChatAgentConfig
4+
25
from lib.utils import CodeGenSandbox
6+
from lib.agents import CodeGenAgent, TestInterpreterAgent, GenericAgent
37
import typer
48

59
import langroid as lr
@@ -12,104 +16,25 @@
1216
setup_colored_logging()
1317

1418

15-
def generate_first_attempt(sandbox: CodeGenSandbox) -> str:
16-
with open(sandbox.get_sandboxed_class_path(), "r") as f:
17-
class_skeleton = f.read()
18-
19-
cfg = lr.ChatAgentConfig(
20-
llm=lr.language_models.OpenAIGPTConfig(
21-
chat_model="ollama/llama3:latest",
22-
),
23-
vecdb=None
24-
)
25-
main_agent = lr.ChatAgent(cfg)
26-
response = main_agent.llm_response(f"You are an expert at writing Python code."
27-
f"Fill in the following class skeleton."
28-
f"Do NOT add any other methods or commentary."
29-
f"Your response should be ONLY the python code."
30-
f"Do not say 'here is the python code'"
31-
f"Do not surround your response with quotes or backticks."
32-
f"DO NOT EVER USE ``` in your output."
33-
f"Your output MUST be valid, runnable python code and NOTHING else."
34-
f"{class_skeleton}")
35-
with open(sandbox.get_sandboxed_class_path(), "w+") as _out:
36-
_out.write(response.content)
37-
38-
return response.content
39-
40-
41-
def generate_next_attempt(sandbox: CodeGenSandbox, test_results: str, test_results_insights: str) -> str:
42-
cfg = lr.ChatAgentConfig(
43-
llm=lr.language_models.OpenAIGPTConfig(
44-
chat_model="ollama/llama3:latest",
45-
),
46-
vecdb=None
47-
)
48-
agent = lr.ChatAgent(cfg)
49-
with open(sandbox.get_sandboxed_class_path(), "r") as f:
50-
code_snippet = f.read()
51-
52-
prompt = f"""
19+
def chat(
20+
code_gen_agent: GenericAgent,
21+
test_interpreter: GenericAgent,
22+
test_runner: GenericTestRunner,
23+
max_epochs: int = 5
24+
) -> None:
25+
code_attempt = code_gen_agent.respond(
26+
prompt=f"""
5327
You are an expert at writing Python code.
54-
Consider the following code, and test results.
55-
Here is the code:
56-
{code_snippet}
57-
Here are the test results:
58-
{test_results}
59-
In addition, you may consider these insights about the test results when coming up with your solution:
60-
{test_results_insights}
61-
Update the code so that the tests will pass.
62-
Your output MUST contain all the same classes and methods as the input code.
28+
Fill in the following class skeleton.
6329
Do NOT add any other methods or commentary.
6430
Your response should be ONLY the python code.
6531
Do not say 'here is the python code'
6632
Do not surround your response with quotes or backticks.
6733
DO NOT EVER USE ``` in your output.
68-
Your response should NEVER start or end with ```
6934
Your output MUST be valid, runnable python code and NOTHING else.
35+
{code_gen_agent.class_skeleton}
7036
"""
71-
response = agent.llm_response(prompt)
72-
with open(sandbox.get_sandboxed_class_path(), "w") as _out:
73-
_out.write(response.content)
74-
75-
return response.content
76-
77-
78-
def interpret_test_results(results: str, code: str) -> str:
79-
cfg = lr.ChatAgentConfig(
80-
llm=lr.language_models.OpenAIGPTConfig(
81-
chat_model="ollama/llama3:latest",
82-
),
83-
vecdb=None
8437
)
85-
agent = lr.ChatAgent(cfg)
86-
prompt = f"""
87-
You are an expert at interpreting the results of unit tests, and providing insight into what they mean.
88-
You should be descriptive about what variables are incorrect, and in what way.
89-
You should include information about which methods should be modified, and in what way.
90-
You should generally not provide code.
91-
Please provide insights about the following test results:
92-
{results}
93-
Those results were produced by the following code:
94-
{code}
95-
"""
96-
response = agent.llm_response(prompt)
97-
return response.content
98-
99-
100-
def teardown() -> None:
101-
codegen_path = os.path.join(".", "generated")
102-
build_path = os.path.join(".", "build")
103-
if not os.path.exists(build_path):
104-
os.makedirs(build_path)
105-
with open(os.path.join(codegen_path, "test_class.py"), "r+") as generated_file:
106-
with open(os.path.join(build_path, "test_class.py"), "w+") as _out:
107-
_out.write(generated_file.read())
108-
generated_file.truncate(0)
109-
110-
111-
def chat(sandbox: CodeGenSandbox, test_runner: GenericTestRunner, max_epochs: int=5) -> None:
112-
code_attempt = generate_first_attempt(sandbox)
11338
solved = False
11439
for _ in range(max_epochs):
11540
# test_exit_code, test_result(s = get_test_results()
@@ -120,13 +45,44 @@ def chat(sandbox: CodeGenSandbox, test_runner: GenericTestRunner, max_epochs: in
12045
print("Done!")
12146
break
12247
else:
123-
results_insights = interpret_test_results(test_results, code_attempt)
124-
code_attempt = generate_next_attempt(sandbox, test_results, results_insights)
125-
# else:
126-
# solved = True
127-
# print("There is some problem with the test suite itself.")
128-
# break
129-
# teardown()
48+
test_interpreter.set_latest_test_results(test_results)
49+
test_interpreter.set_latest_test_exit_code(test_exit_code)
50+
results_insights = test_interpreter.respond(
51+
prompt=f"""
52+
You are an expert at interpreting the results of unit tests, and providing insight into what they mean.
53+
You should be descriptive about what variables are incorrect, and in what way.
54+
You should include information about which methods should be modified, and in what way.
55+
You should generally not provide code.
56+
Please provide insights about the following test results:
57+
{test_interpreter.latest_test_results}
58+
Those results were produced by the following code:
59+
{test_interpreter.latest_test_exit_code}
60+
"""
61+
)
62+
code_gen_agent.set_previous_code_attempt(code_attempt)
63+
code_gen_agent.set_latest_test_result(test_results)
64+
code_gen_agent.set_latest_test_result_interpretation(results_insights)
65+
code_attempt = code_gen_agent.respond(
66+
prompt=f"""
67+
You are an expert at writing Python code.
68+
Consider the following code, and test results.
69+
Here is the code:
70+
{code_gen_agent.previous_code_attempt}
71+
Here are the test results:
72+
{code_gen_agent.latest_test_result}
73+
In addition, you may consider these insights about the test results when coming up with your solution:
74+
{code_gen_agent.latest_test_result_interpretation}
75+
Update the code so that the tests will pass.
76+
Your output MUST contain all the same classes and methods as the input code.
77+
Do NOT add any other methods or commentary.
78+
Your response should be ONLY the python code.
79+
Do not say 'here is the python code'
80+
Do not surround your response with quotes or backticks.
81+
DO NOT EVER USE ``` in your output.
82+
Your response should NEVER start or end with ```
83+
Your output MUST be valid, runnable python code and NOTHING else.
84+
"""
85+
)
13086
if not solved:
13187
print(f"Reached the end of epoch {max_epochs} without finding a solution :(")
13288

@@ -168,10 +124,19 @@ def main(
168124
)
169125
)
170126

127+
llama3 = ChatAgentConfig(
128+
llm=lr.language_models.OpenAIGPTConfig(
129+
chat_model="ollama/llama3:latest",
130+
),
131+
vecdb=None
132+
)
133+
171134
sandbox = CodeGenSandbox(project_dir, class_skeleton_path, test_path, sandbox_path)
172135
sandbox.init_sandbox()
173-
tr: GenericTestRunner = SubProcessTestRunner(sandbox)
174-
chat(sandbox, tr, max_epochs=max_epochs)
136+
code_generator: GenericAgent = CodeGenAgent(sandbox, llama3)
137+
test_interpreter: GenericAgent = TestInterpreterAgent(sandbox, llama3)
138+
test_runner: GenericTestRunner = SubProcessTestRunner(sandbox)
139+
chat(sandbox, code_generator, test_interpreter, test_runner, max_epochs=max_epochs)
175140

176141

177142
if __name__ == "__main__":

test/test_ExampleClass.py

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)