refactor: merge main

This commit is contained in:
Joschka Braun
2023-04-18 14:05:36 +02:00
parent eaac7e49b3
commit 0692976088
4 changed files with 80 additions and 53 deletions

View File

@@ -4,6 +4,7 @@ from time import sleep
from typing import List, Any
import openai
from langchain import PromptTemplate
from langchain.callbacks import CallbackManager
from langchain.chat_models import ChatOpenAI
from openai.error import RateLimitError
@@ -88,12 +89,14 @@ class _GPTConversation:
@staticmethod
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:
system_message += f'\n{executor_example}'
if 'docarray' in system_definition_examples:
system_message += f'\n{docarray_example}'
if 'client' in system_definition_examples:
system_message += f'\n{client_example}'
# create from template
return SystemMessage(content=system_message)

View File

@@ -11,7 +11,7 @@ from src.options.generate.templates import template_generate_microservice_name,
template_solve_code_issue, \
template_solve_dependency_issue, template_is_dependency_issue, template_generate_playground, \
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.string_tools import print_colored
@@ -55,8 +55,6 @@ metas:
def generate_microservice(
self,
description,
test,
path,
microservice_name,
packages,
@@ -70,9 +68,9 @@ metas:
microservice_content_raw = conversation.chat(
template_generate_executor.format(
microservice_name=microservice_name,
microservice_description=description,
test=test,
package=package,
microservice_description=self.task_description,
test=self.test_description,
packages=packages,
file_name_purpose=EXECUTOR_FILE_NAME,
tag_name=EXECUTOR_FILE_TAG,
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)
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):
print('Debugging iteration', i)
print('Trying to build the microservice. Might take a while...')
@@ -178,8 +176,7 @@ metas:
error = process_error_message(log_hubble)
if error:
print('An error occurred during the build process. Feeding the error back to the assistent...')
self.do_debug_iteration(description, error, next_microservice_path,
previous_microservice_path, test)
self.do_debug_iteration(error, next_microservice_path, previous_microservice_path)
if i == MAX_DEBUGGING_ITERATIONS - 1:
raise self.MaxDebugTimeReachedException('Could not debug the microservice.')
else:
@@ -188,8 +185,7 @@ metas:
return get_microservice_path(path, microservice_name, packages, num_approach, i)
def do_debug_iteration(self, description, error, next_microservice_path, previous_microservice_path,
test):
def do_debug_iteration(self, error, next_microservice_path, previous_microservice_path):
os.makedirs(next_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']
})
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:
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()
returned_files_raw = conversation.chat(user_query)
@@ -236,11 +232,11 @@ metas:
name = self.extract_content_from_result(name_raw, 'name.txt')
return name
def get_possible_packages(self, description):
def get_possible_packages(self):
print_colored('', '############# What packages to use? #############', 'blue')
conversation = self.gpt_session.get_conversation()
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_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):
generated_name = self.generate_microservice_name(self.task_description)
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 for packages in packages_list if len(set(packages).intersection(set(PROBLEMATIC_PACKAGES))) == 0
]
for num_approach, packages in enumerate(packages_list):
try:
self.generate_microservice(
self.task_description, self.test_description, microservice_path, microservice_name, packages, num_approach
)
self.generate_microservice(microservice_path, microservice_name, packages, num_approach)
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)
except self.MaxDebugTimeReachedException:
@@ -280,11 +274,5 @@ gptdeploy deploy --path {microservice_path}
def summarize_error(self, error):
conversation = self.gpt_session.get_conversation([])
user_query = f'''
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)
error_summary = conversation.chat(template_summarize_error.format(error=error))
return error_summary

View File

@@ -1,4 +1,5 @@
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.
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}
```
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}'

View File

@@ -57,7 +57,8 @@ b) has a stable api among different versions
c) does not have system requirements
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:
''' + not_allowed_executor_string() + '''
''' + not_allowed_executor_string + '''
When answering, just write "yes" or "no".
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:
**packages.csv**
```
package1
package2
package3
package4
package5
package1a, package1b ...
package2a, package2b, package2c
package3a ...
package4a ...
package5a ...
...
```
''')
@@ -90,7 +91,7 @@ template_generate_executor = PromptTemplate.from_template(
Write the executor called '{microservice_name}'. The name is very important to keep.
It matches the following description: '{microservice_description}'.
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:
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(
'''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:
@@ -172,15 +181,13 @@ Is this a dependency installation failure? Answer with "yes" or "no".'''
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.
The error message is:
**microservice.log**
```
{error}
```
Here is the summary of the error that occurred:
{summarized_error}
To solve this error, you should:
1. Identify the type of error by examining the stack trace.
2. Suggest how to solve it.
3. Your suggestion must include the files that need to be changed, but not files that don't need to be changed.
1. Suggest 3 to 5 possible solutions on how to solve it. You have no access to the documentation of the package.
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.
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:
''' + not_allowed_docker_string() + '''
@@ -188,6 +195,22 @@ Obey the following rules:
You are given the following files:
{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}
This is the error I encounter currently during the docker build process:
{error}
Here is the summary of the error that occurred:
{summarized_error}
Look at the stack trace of the current error. First, think about what kind of error is this?
Then think about possible reasons which might have caused it. Then suggest how to
solve it. Output all the files that need change.
To solve this error, you should:
1. Suggest 3 to 5 possible solutions on how to solve it. You have no access to the documentation of the package.
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
complete file. Use the exact same syntax to wrap the code:
complete file. Use the exact following syntax to wrap the 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
```
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 not let the user configure the host on the ui.
'''