mirror of
https://github.com/aljazceru/dev-gpt.git
synced 2025-12-23 08:34:20 +01:00
⏪ fix: self healing response parser
This commit is contained in:
32
dev_gpt/options/generate/chains/fix_based_on_error.py
Normal file
32
dev_gpt/options/generate/chains/fix_based_on_error.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def fix_based_on_error_chain(context_string, content_type, original_content, parser):
|
||||||
|
from dev_gpt.apis.gpt import ask_gpt
|
||||||
|
current_content = original_content
|
||||||
|
for i in range(3):
|
||||||
|
try:
|
||||||
|
return parser(current_content)
|
||||||
|
except Exception:
|
||||||
|
error_message = traceback.format_exc()
|
||||||
|
current_content = ask_gpt(fix_based_on_error_prompt, context_string=context_string, content_type=content_type, current_content=current_content, error_message=error_message)
|
||||||
|
raise Exception(f'Could not fix the content:\n{original_content}')
|
||||||
|
|
||||||
|
|
||||||
|
fix_based_on_error_prompt = '''\
|
||||||
|
Context:
|
||||||
|
{context_string}
|
||||||
|
|
||||||
|
Original {content_type}:
|
||||||
|
{current_content}
|
||||||
|
|
||||||
|
Error message:
|
||||||
|
{error_message}
|
||||||
|
|
||||||
|
Your task:
|
||||||
|
You must return the fixed {content_type}.
|
||||||
|
Most importantly, you are not allowed to return something else - only the fixed {content_type}.
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ from dev_gpt.constants import FILE_AND_TAG_PAIRS, NUM_IMPLEMENTATION_STRATEGIES,
|
|||||||
IMPLEMENTATION_FILE_TAG, LANGUAGE_PACKAGES, UNNECESSARY_PACKAGES, DOCKER_BASE_IMAGE_VERSION, SEARCH_PACKAGES, \
|
IMPLEMENTATION_FILE_TAG, LANGUAGE_PACKAGES, UNNECESSARY_PACKAGES, DOCKER_BASE_IMAGE_VERSION, SEARCH_PACKAGES, \
|
||||||
INDICATOR_TO_IMPORT_STATEMENT
|
INDICATOR_TO_IMPORT_STATEMENT
|
||||||
from dev_gpt.options.generate.conversation_logger import Timer
|
from dev_gpt.options.generate.conversation_logger import Timer
|
||||||
|
from dev_gpt.options.generate.parser import json_parser
|
||||||
from dev_gpt.options.generate.pm.pm import PM
|
from dev_gpt.options.generate.pm.pm import PM
|
||||||
from dev_gpt.options.generate.templates_user import template_generate_microservice_name, \
|
from dev_gpt.options.generate.templates_user import template_generate_microservice_name, \
|
||||||
template_generate_possible_packages, \
|
template_generate_possible_packages, \
|
||||||
@@ -439,8 +440,7 @@ pytest
|
|||||||
self.previous_solutions.append(suggested_solution)
|
self.previous_solutions.append(suggested_solution)
|
||||||
|
|
||||||
def generate_solution_suggestion(self, summarized_error, all_files_string):
|
def generate_solution_suggestion(self, summarized_error, all_files_string):
|
||||||
suggested_solutions = json.loads(
|
json_string = self.generate_and_persist_file(
|
||||||
self.generate_and_persist_file(
|
|
||||||
section_title='Suggest solution for code issue',
|
section_title='Suggest solution for code issue',
|
||||||
template=template_suggest_solutions_code_issue,
|
template=template_suggest_solutions_code_issue,
|
||||||
file_name_s=['solutions.json'],
|
file_name_s=['solutions.json'],
|
||||||
@@ -449,9 +449,10 @@ pytest
|
|||||||
test_description=self.microservice_specification.test,
|
test_description=self.microservice_specification.test,
|
||||||
all_files_string=all_files_string,
|
all_files_string=all_files_string,
|
||||||
response_format_example=response_format_suggest_solutions,
|
response_format_example=response_format_suggest_solutions,
|
||||||
)['solutions.json']
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
suggested_solutions = json_parser(json_string)['solutions.json']
|
||||||
|
|
||||||
if len(self.previous_errors) > 0:
|
if len(self.previous_errors) > 0:
|
||||||
was_error_seen_before = json.loads(
|
was_error_seen_before = json.loads(
|
||||||
self.generate_and_persist_file(
|
self.generate_and_persist_file(
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from dev_gpt.options.generate.chains.fix_based_on_error import fix_based_on_error_chain
|
||||||
|
|
||||||
|
|
||||||
def identity_parser(x):
|
def identity_parser(x):
|
||||||
return x
|
return x
|
||||||
@@ -16,6 +18,10 @@ def boolean_parser(x):
|
|||||||
|
|
||||||
def json_parser(x):
|
def json_parser(x):
|
||||||
if '```' in x:
|
if '```' in x:
|
||||||
pattern = r'```(.+)```'
|
pattern = r'```(json)?(.+)```'
|
||||||
x = re.findall(pattern, x, re.DOTALL)[-1]
|
x = re.findall(pattern, x, re.DOTALL)[-1][-1]
|
||||||
return json.loads(x)
|
return json.loads(x)
|
||||||
|
|
||||||
|
def self_healing_json_parser(original_json_string):
|
||||||
|
return fix_based_on_error_chain('I want to load my JSON string using json.loads(x) but get the following error:', 'JSON',
|
||||||
|
original_json_string, parser=json_parser)
|
||||||
|
|||||||
@@ -310,14 +310,22 @@ Output the apt-get packages that need to be placed at {{APT_GET_PACKAGES}} as js
|
|||||||
```json
|
```json
|
||||||
{{"packages": ["<package1>", "<package2>"]}}
|
{{"packages": ["<package1>", "<package2>"]}}
|
||||||
```
|
```
|
||||||
Example:
|
|
||||||
Error is about missing package `libgl1-mesa-glx`.
|
Example output for an error is about missing package `libgl1-mesa-glx`:
|
||||||
The output is:
|
|
||||||
**apt-get-packages.json**
|
**apt-get-packages.json**
|
||||||
```json
|
```json
|
||||||
{{"packages": [libgl1-mesa-glx]}}
|
{{"packages": [libgl1-mesa-glx]}}
|
||||||
```
|
```
|
||||||
Only output content of the apt-get-packages.json file. Ensure the response can be parsed by Python json.loads
|
|
||||||
|
Negative example1:
|
||||||
|
```json
|
||||||
|
{{"packages": [libgl1-mesa-glx]}}
|
||||||
|
```
|
||||||
|
|
||||||
|
Negative example2:
|
||||||
|
{{"packages": [libgl1-mesa-glx]}}
|
||||||
|
|
||||||
|
Note: Only output content of the apt-get-packages.json file.
|
||||||
Note: you must not output the content of any other. Especially don't output the Dockerfile or requirements.txt.
|
Note: you must not output the content of any other. Especially don't output the Dockerfile or requirements.txt.
|
||||||
Note: the first line you output must be: **apt-get-packages.json**
|
Note: the first line you output must be: **apt-get-packages.json**
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from dev_gpt.apis.gpt import GPTSession
|
||||||
from dev_gpt.options.generate.generator import Generator
|
from dev_gpt.options.generate.generator import Generator
|
||||||
|
from dev_gpt.options.generate.parser import self_healing_json_parser
|
||||||
|
|
||||||
|
|
||||||
def create_code_block(with_backticks, asterisks, with_highlight_info, file_name, start_inline, content):
|
def create_code_block(with_backticks, asterisks, with_highlight_info, file_name, start_inline, content):
|
||||||
code_block = f'''
|
code_block = f'''
|
||||||
@@ -42,3 +47,21 @@ def test_extract_content_from_result(plain_text, expected1, expected2):
|
|||||||
parsed_result2 = Generator.extract_content_from_result(plain_text, 'test100.json', True, False)
|
parsed_result2 = Generator.extract_content_from_result(plain_text, 'test100.json', True, False)
|
||||||
assert parsed_result2 == expected2
|
assert parsed_result2 == expected2
|
||||||
|
|
||||||
|
|
||||||
|
def test_self_healing_json_parser(tmpdir):
|
||||||
|
os.environ['VERBOSE'] = 'true'
|
||||||
|
GPTSession(os.path.join(str(tmpdir), 'log.json'), model='gpt-3.5-turbo')
|
||||||
|
json_response = '''\
|
||||||
|
solutions.json
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"1": "Change line 7 of microservice.py to 'pdf_file = input_dict['pdf_file'].encode('latin-1')' to convert the bytes object to a string before passing it to PyPDF2.",
|
||||||
|
"2": "Change line 7 of microservice.py to 'pdf_file = input_dict['pdf_file'].decode('utf-8')' to decode the bytes object to a string before passing it to PyPDF2.",
|
||||||
|
"3": "Change line 13 of test_microservice.py to 'input_dict = {"pdf_file": 'Sample PDF file content'.encode('latin-1')}' to encode the string to a bytes object before passing it to func.",
|
||||||
|
"4": "Change line 13 of test_microservice.py to 'input_dict = {"pdf_file": 'Sample PDF file content'.decode('utf-8')}' to decode the string to a bytes object before passing it to func."
|
||||||
|
}
|
||||||
|
```'''
|
||||||
|
parsed_json = self_healing_json_parser(json_response)
|
||||||
|
for key in ['1', '2', '3', '4']:
|
||||||
|
assert key in parsed_json
|
||||||
|
assert 'Change' in parsed_json[key]
|
||||||
Reference in New Issue
Block a user