mirror of
https://github.com/aljazceru/dev-gpt.git
synced 2025-12-23 08:34:20 +01:00
refactor: merge main
This commit is contained in:
@@ -4,6 +4,7 @@ from time import sleep
|
|||||||
from typing import List, Any
|
from typing import List, Any
|
||||||
|
|
||||||
import openai
|
import openai
|
||||||
|
from langchain import PromptTemplate
|
||||||
from langchain.callbacks import CallbackManager
|
from langchain.callbacks import CallbackManager
|
||||||
from langchain.chat_models import ChatOpenAI
|
from langchain.chat_models import ChatOpenAI
|
||||||
from openai.error import RateLimitError
|
from openai.error import RateLimitError
|
||||||
@@ -88,12 +89,14 @@ class _GPTConversation:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_system_message(task_description, test_description, system_definition_examples: List[str] = []) -> SystemMessage:
|
def _create_system_message(task_description, test_description, system_definition_examples: List[str] = []) -> SystemMessage:
|
||||||
system_message = system_message_base
|
system_message = PromptTemplate.from_template(system_message_base).format(
|
||||||
|
task_description=task_description,
|
||||||
|
test_description=test_description,
|
||||||
|
)
|
||||||
if 'executor' in system_definition_examples:
|
if 'executor' in system_definition_examples:
|
||||||
system_message += f'\n{executor_example}'
|
system_message += f'\n{executor_example}'
|
||||||
if 'docarray' in system_definition_examples:
|
if 'docarray' in system_definition_examples:
|
||||||
system_message += f'\n{docarray_example}'
|
system_message += f'\n{docarray_example}'
|
||||||
if 'client' in system_definition_examples:
|
if 'client' in system_definition_examples:
|
||||||
system_message += f'\n{client_example}'
|
system_message += f'\n{client_example}'
|
||||||
# create from template
|
|
||||||
return SystemMessage(content=system_message)
|
return SystemMessage(content=system_message)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from src.options.generate.templates import template_generate_microservice_name,
|
|||||||
template_solve_code_issue, \
|
template_solve_code_issue, \
|
||||||
template_solve_dependency_issue, template_is_dependency_issue, template_generate_playground, \
|
template_solve_dependency_issue, template_is_dependency_issue, template_generate_playground, \
|
||||||
template_generate_executor, template_generate_test, template_generate_requirements, template_generate_dockerfile, \
|
template_generate_executor, template_generate_test, template_generate_requirements, template_generate_dockerfile, \
|
||||||
template_chain_of_thought
|
template_chain_of_thought, template_summarize_error
|
||||||
from src.utils.io import persist_file, get_all_microservice_files_with_content, get_microservice_path
|
from src.utils.io import persist_file, get_all_microservice_files_with_content, get_microservice_path
|
||||||
from src.utils.string_tools import print_colored
|
from src.utils.string_tools import print_colored
|
||||||
|
|
||||||
@@ -55,8 +55,6 @@ metas:
|
|||||||
|
|
||||||
def generate_microservice(
|
def generate_microservice(
|
||||||
self,
|
self,
|
||||||
description,
|
|
||||||
test,
|
|
||||||
path,
|
path,
|
||||||
microservice_name,
|
microservice_name,
|
||||||
packages,
|
packages,
|
||||||
@@ -70,9 +68,9 @@ metas:
|
|||||||
microservice_content_raw = conversation.chat(
|
microservice_content_raw = conversation.chat(
|
||||||
template_generate_executor.format(
|
template_generate_executor.format(
|
||||||
microservice_name=microservice_name,
|
microservice_name=microservice_name,
|
||||||
microservice_description=description,
|
microservice_description=self.task_description,
|
||||||
test=test,
|
test=self.test_description,
|
||||||
package=package,
|
packages=packages,
|
||||||
file_name_purpose=EXECUTOR_FILE_NAME,
|
file_name_purpose=EXECUTOR_FILE_NAME,
|
||||||
tag_name=EXECUTOR_FILE_TAG,
|
tag_name=EXECUTOR_FILE_TAG,
|
||||||
file_name=EXECUTOR_FILE_NAME,
|
file_name=EXECUTOR_FILE_NAME,
|
||||||
@@ -168,7 +166,7 @@ metas:
|
|||||||
playground_content = self.extract_content_from_result(playground_content_raw, 'app.py', match_single_block=True)
|
playground_content = self.extract_content_from_result(playground_content_raw, 'app.py', match_single_block=True)
|
||||||
persist_file(playground_content, os.path.join(microservice_path, 'app.py'))
|
persist_file(playground_content, os.path.join(microservice_path, 'app.py'))
|
||||||
|
|
||||||
def debug_microservice(self, path, microservice_name, num_approach, packages, description, test):
|
def debug_microservice(self, path, microservice_name, num_approach, packages):
|
||||||
for i in range(1, MAX_DEBUGGING_ITERATIONS):
|
for i in range(1, MAX_DEBUGGING_ITERATIONS):
|
||||||
print('Debugging iteration', i)
|
print('Debugging iteration', i)
|
||||||
print('Trying to build the microservice. Might take a while...')
|
print('Trying to build the microservice. Might take a while...')
|
||||||
@@ -178,8 +176,7 @@ metas:
|
|||||||
error = process_error_message(log_hubble)
|
error = process_error_message(log_hubble)
|
||||||
if error:
|
if error:
|
||||||
print('An error occurred during the build process. Feeding the error back to the assistent...')
|
print('An error occurred during the build process. Feeding the error back to the assistent...')
|
||||||
self.do_debug_iteration(description, error, next_microservice_path,
|
self.do_debug_iteration(error, next_microservice_path, previous_microservice_path)
|
||||||
previous_microservice_path, test)
|
|
||||||
if i == MAX_DEBUGGING_ITERATIONS - 1:
|
if i == MAX_DEBUGGING_ITERATIONS - 1:
|
||||||
raise self.MaxDebugTimeReachedException('Could not debug the microservice.')
|
raise self.MaxDebugTimeReachedException('Could not debug the microservice.')
|
||||||
else:
|
else:
|
||||||
@@ -188,8 +185,7 @@ metas:
|
|||||||
|
|
||||||
return get_microservice_path(path, microservice_name, packages, num_approach, i)
|
return get_microservice_path(path, microservice_name, packages, num_approach, i)
|
||||||
|
|
||||||
def do_debug_iteration(self, description, error, next_microservice_path, previous_microservice_path,
|
def do_debug_iteration(self, error, next_microservice_path, previous_microservice_path):
|
||||||
test):
|
|
||||||
os.makedirs(next_microservice_path)
|
os.makedirs(next_microservice_path)
|
||||||
file_name_to_content = get_all_microservice_files_with_content(previous_microservice_path)
|
file_name_to_content = get_all_microservice_files_with_content(previous_microservice_path)
|
||||||
|
|
||||||
@@ -201,11 +197,11 @@ metas:
|
|||||||
key in ['requirements.txt', 'Dockerfile']
|
key in ['requirements.txt', 'Dockerfile']
|
||||||
})
|
})
|
||||||
user_query = template_solve_dependency_issue.format(
|
user_query = template_solve_dependency_issue.format(
|
||||||
description=description, summarized_error=summarized_error, all_files_string=all_files_string,
|
description=self.task_description, summarized_error=summarized_error, all_files_string=all_files_string,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
user_query = template_solve_code_issue.format(
|
user_query = template_solve_code_issue.format(
|
||||||
description=description, summarized_error=summarized_error, all_files_string=self.files_to_string(file_name_to_content),
|
description=self.task_description, summarized_error=summarized_error, all_files_string=self.files_to_string(file_name_to_content),
|
||||||
)
|
)
|
||||||
conversation = self.gpt_session.get_conversation()
|
conversation = self.gpt_session.get_conversation()
|
||||||
returned_files_raw = conversation.chat(user_query)
|
returned_files_raw = conversation.chat(user_query)
|
||||||
@@ -236,11 +232,11 @@ metas:
|
|||||||
name = self.extract_content_from_result(name_raw, 'name.txt')
|
name = self.extract_content_from_result(name_raw, 'name.txt')
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def get_possible_packages(self, description):
|
def get_possible_packages(self):
|
||||||
print_colored('', '############# What packages to use? #############', 'blue')
|
print_colored('', '############# What packages to use? #############', 'blue')
|
||||||
conversation = self.gpt_session.get_conversation()
|
conversation = self.gpt_session.get_conversation()
|
||||||
packages_raw = conversation.chat(
|
packages_raw = conversation.chat(
|
||||||
template_generate_possible_packages.format(description=description)
|
template_generate_possible_packages.format(description=self.task_description)
|
||||||
)
|
)
|
||||||
packages_csv_string = self.extract_content_from_result(packages_raw, 'packages.csv')
|
packages_csv_string = self.extract_content_from_result(packages_raw, 'packages.csv')
|
||||||
packages_list = [[pkg.strip() for pkg in packages_string.split(',')] for packages_string in packages_csv_string.split('\n')]
|
packages_list = [[pkg.strip() for pkg in packages_string.split(',')] for packages_string in packages_csv_string.split('\n')]
|
||||||
@@ -250,17 +246,15 @@ metas:
|
|||||||
def generate(self, microservice_path):
|
def generate(self, microservice_path):
|
||||||
generated_name = self.generate_microservice_name(self.task_description)
|
generated_name = self.generate_microservice_name(self.task_description)
|
||||||
microservice_name = f'{generated_name}{random.randint(0, 10_000_000)}'
|
microservice_name = f'{generated_name}{random.randint(0, 10_000_000)}'
|
||||||
packages_list = self.get_possible_packages(description)
|
packages_list = self.get_possible_packages()
|
||||||
packages_list = [
|
packages_list = [
|
||||||
packages for packages in packages_list if len(set(packages).intersection(set(PROBLEMATIC_PACKAGES))) == 0
|
packages for packages in packages_list if len(set(packages).intersection(set(PROBLEMATIC_PACKAGES))) == 0
|
||||||
]
|
]
|
||||||
for num_approach, packages in enumerate(packages_list):
|
for num_approach, packages in enumerate(packages_list):
|
||||||
try:
|
try:
|
||||||
self.generate_microservice(
|
self.generate_microservice(microservice_path, microservice_name, packages, num_approach)
|
||||||
self.task_description, self.test_description, microservice_path, microservice_name, packages, num_approach
|
|
||||||
)
|
|
||||||
final_version_path = self.debug_microservice(
|
final_version_path = self.debug_microservice(
|
||||||
microservice_path, microservice_name, num_approach, packages, description, test
|
microservice_path, microservice_name, num_approach, packages
|
||||||
)
|
)
|
||||||
self.generate_playground(microservice_name, final_version_path)
|
self.generate_playground(microservice_name, final_version_path)
|
||||||
except self.MaxDebugTimeReachedException:
|
except self.MaxDebugTimeReachedException:
|
||||||
@@ -280,11 +274,5 @@ gptdeploy deploy --path {microservice_path}
|
|||||||
|
|
||||||
def summarize_error(self, error):
|
def summarize_error(self, error):
|
||||||
conversation = self.gpt_session.get_conversation([])
|
conversation = self.gpt_session.get_conversation([])
|
||||||
user_query = f'''
|
error_summary = conversation.chat(template_summarize_error.format(error=error))
|
||||||
Here is an error message I encountered during the docker build process:
|
|
||||||
"{error}"
|
|
||||||
Your task is to summarize the error message as compact and informative as possible while maintaining all information necessary to debug the core issue.
|
|
||||||
Warnings are not worth mentioning.
|
|
||||||
'''
|
|
||||||
error_summary = conversation.query(user_query)
|
|
||||||
return error_summary
|
return error_summary
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from src.constants import FLOW_URL_PLACEHOLDER
|
from src.constants import FLOW_URL_PLACEHOLDER
|
||||||
|
from src.options.generate.templates import not_allowed_docker_string, not_allowed_executor_string
|
||||||
|
|
||||||
executor_example = '''Using the Jina framework, users can define executors.
|
executor_example = '''Using the Jina framework, users can define executors.
|
||||||
Here is an example of how an executor can be defined. It always starts with a comment:
|
Here is an example of how an executor can be defined. It always starts with a comment:
|
||||||
@@ -83,4 +84,4 @@ and the following test scenario:
|
|||||||
{test_description}
|
{test_description}
|
||||||
```
|
```
|
||||||
|
|
||||||
You must obey the following rules:''' + f'\n{not_allowed_executor}\n{not_allowed_docker}'
|
You must obey the following rules:''' + f'\n{not_allowed_executor_string}\n{not_allowed_docker_string}'
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ b) has a stable api among different versions
|
|||||||
c) does not have system requirements
|
c) does not have system requirements
|
||||||
d) can solve the task when running in a docker container
|
d) can solve the task when running in a docker container
|
||||||
e) the implementation of the core problem using the package would obey the following rules:
|
e) the implementation of the core problem using the package would obey the following rules:
|
||||||
''' + not_allowed_executor_string() + '''
|
''' + not_allowed_executor_string + '''
|
||||||
|
|
||||||
When answering, just write "yes" or "no".
|
When answering, just write "yes" or "no".
|
||||||
|
|
||||||
5. Output the most suitable 5 python packages starting with the best one.
|
5. Output the most suitable 5 python packages starting with the best one.
|
||||||
@@ -66,11 +67,11 @@ If the package is mentioned in the description, then it is automatically the bes
|
|||||||
The output must be a list of lists wrapped into ``` and starting with **packages.csv** like this:
|
The output must be a list of lists wrapped into ``` and starting with **packages.csv** like this:
|
||||||
**packages.csv**
|
**packages.csv**
|
||||||
```
|
```
|
||||||
package1
|
package1a, package1b ...
|
||||||
package2
|
package2a, package2b, package2c
|
||||||
package3
|
package3a ...
|
||||||
package4
|
package4a ...
|
||||||
package5
|
package5a ...
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
''')
|
''')
|
||||||
@@ -90,7 +91,7 @@ template_generate_executor = PromptTemplate.from_template(
|
|||||||
Write the executor called '{microservice_name}'. The name is very important to keep.
|
Write the executor called '{microservice_name}'. The name is very important to keep.
|
||||||
It matches the following description: '{microservice_description}'.
|
It matches the following description: '{microservice_description}'.
|
||||||
It will be tested with the following scenario: '{test}'.
|
It will be tested with the following scenario: '{test}'.
|
||||||
For the implementation use the following package: '{package}'.
|
For the implementation use the following package: '{packages}'.
|
||||||
|
|
||||||
Obey the following rules:
|
Obey the following rules:
|
||||||
Have in mind that d.uri is never a path to a local file. It is always a url.
|
Have in mind that d.uri is never a path to a local file. It is always a url.
|
||||||
@@ -156,6 +157,14 @@ The Dockerfile runs the test during the build process.
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
template_summarize_error = PromptTemplate.from_template(
|
||||||
|
'''Here is an error message I encountered during the docker build process:
|
||||||
|
"{error}"
|
||||||
|
Your task is to summarize the error message as compact and informative as possible while maintaining all information necessary to debug the core issue.
|
||||||
|
Warnings are not worth mentioning.'''
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
template_is_dependency_issue = PromptTemplate.from_template(
|
template_is_dependency_issue = PromptTemplate.from_template(
|
||||||
'''Your task is to assist in identifying the root cause of a Docker build error for a python application.
|
'''Your task is to assist in identifying the root cause of a Docker build error for a python application.
|
||||||
The error message is as follows:
|
The error message is as follows:
|
||||||
@@ -172,15 +181,13 @@ Is this a dependency installation failure? Answer with "yes" or "no".'''
|
|||||||
|
|
||||||
template_solve_dependency_issue = PromptTemplate.from_template(
|
template_solve_dependency_issue = PromptTemplate.from_template(
|
||||||
'''Your task is to provide guidance on how to solve an error that occurred during the Docker build process.
|
'''Your task is to provide guidance on how to solve an error that occurred during the Docker build process.
|
||||||
The error message is:
|
Here is the summary of the error that occurred:
|
||||||
**microservice.log**
|
{summarized_error}
|
||||||
```
|
|
||||||
{error}
|
|
||||||
```
|
|
||||||
To solve this error, you should:
|
To solve this error, you should:
|
||||||
1. Identify the type of error by examining the stack trace.
|
1. Suggest 3 to 5 possible solutions on how to solve it. You have no access to the documentation of the package.
|
||||||
2. Suggest how to solve it.
|
2. Decide for the best solution and explain it in detail.
|
||||||
3. Your suggestion must include the files that need to be changed, but not files that don't need to be changed.
|
3. Write down the files that need to be changed, but not files that don't need to be changed.
|
||||||
For files that need to be changed, you must provide the complete file with the exact same syntax to wrap the code.
|
For files that need to be changed, you must provide the complete file with the exact same syntax to wrap the code.
|
||||||
Obey the following rules:
|
Obey the following rules:
|
||||||
''' + not_allowed_docker_string() + '''
|
''' + not_allowed_docker_string() + '''
|
||||||
@@ -188,6 +195,22 @@ Obey the following rules:
|
|||||||
You are given the following files:
|
You are given the following files:
|
||||||
|
|
||||||
{all_files_string}
|
{all_files_string}
|
||||||
|
|
||||||
|
Output all the files that need change.
|
||||||
|
Don't output files that don't need change. If you output a file, then write the
|
||||||
|
complete file. Use the exact following syntax to wrap the code:
|
||||||
|
|
||||||
|
**...**
|
||||||
|
```
|
||||||
|
...code...
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
**requirements.txt**
|
||||||
|
```
|
||||||
|
jina==2.0.0
|
||||||
|
```
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -205,19 +228,31 @@ Here are all the files I use:
|
|||||||
{all_files_string}
|
{all_files_string}
|
||||||
|
|
||||||
|
|
||||||
This is the error I encounter currently during the docker build process:
|
Here is the summary of the error that occurred:
|
||||||
{error}
|
{summarized_error}
|
||||||
|
|
||||||
Look at the stack trace of the current error. First, think about what kind of error is this?
|
To solve this error, you should:
|
||||||
Then think about possible reasons which might have caused it. Then suggest how to
|
1. Suggest 3 to 5 possible solutions on how to solve it. You have no access to the documentation of the package.
|
||||||
solve it. Output all the files that need change.
|
2. Decide for the best solution and explain it in detail.
|
||||||
|
3. Write down the files that need to be changed, but not files that don't need to be changed.
|
||||||
|
Obey the following rules:
|
||||||
|
''' + f'{not_allowed_executor_string}\n{not_allowed_docker_string}' + '''
|
||||||
|
|
||||||
|
Output all the files that need change.
|
||||||
Don't output files that don't need change. If you output a file, then write the
|
Don't output files that don't need change. If you output a file, then write the
|
||||||
complete file. Use the exact same syntax to wrap the code:
|
complete file. Use the exact following syntax to wrap the code:
|
||||||
|
|
||||||
**...**
|
**...**
|
||||||
```...
|
```...
|
||||||
...code...
|
...code...
|
||||||
```
|
```
|
||||||
'''
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
**microservice.py**
|
||||||
|
```python
|
||||||
|
print('hello world')
|
||||||
|
```'''
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -237,7 +272,7 @@ response = client.post('/', inputs=DocumentArray([d])) # always use '/'
|
|||||||
print(response[0].text) # can also be blob in case of image/audio..., this should be visualized in the streamlit app
|
print(response[0].text) # can also be blob in case of image/audio..., this should be visualized in the streamlit app
|
||||||
```
|
```
|
||||||
Note that the response will always be in response[0].text
|
Note that the response will always be in response[0].text
|
||||||
You must provide the complete file with the exact same syntax to wrap the code.
|
You must provide the complete app.py file with the exact same syntax to wrap the code.
|
||||||
The playground (app.py) must read the host from sys.argv because it will be started with a custom host: streamlit run app.py -- --host grpc://...
|
The playground (app.py) must read the host from sys.argv because it will be started with a custom host: streamlit run app.py -- --host grpc://...
|
||||||
The playground (app.py) must not let the user configure the host on the ui.
|
The playground (app.py) must not let the user configure the host on the ui.
|
||||||
'''
|
'''
|
||||||
|
|||||||
Reference in New Issue
Block a user