mirror of
https://github.com/aljazceru/dev-gpt.git
synced 2025-12-30 03:44:20 +01:00
refactor: use templates
This commit is contained in:
@@ -9,6 +9,9 @@ from src.constants import FILE_AND_TAG_PAIRS, NUM_IMPLEMENTATION_STRATEGIES, MAX
|
||||
from src.options.generate.prompt_tasks import general_guidelines, executor_file_task, \
|
||||
not_allowed_executor, chain_of_thought_optimization, test_executor_file_task, requirements_file_task, \
|
||||
docker_file_task, not_allowed_docker
|
||||
from src.options.generate.templates import template_generate_microservice_name, template_generate_possible_packages, \
|
||||
template_solve_code_issue, \
|
||||
template_solve_dependency_issue, template_is_dependency_issue, template_generate_playground
|
||||
from src.utils.io import persist_file, get_all_microservice_files_with_content, get_microservice_path
|
||||
from src.utils.string_tools import print_colored
|
||||
|
||||
@@ -33,27 +36,24 @@ class Generator:
|
||||
|
||||
def write_config_yml(self, microservice_name, dest_folder):
|
||||
config_content = f'''
|
||||
jtype: {microservice_name}
|
||||
py_modules:
|
||||
- microservice.py
|
||||
metas:
|
||||
name: {microservice_name}
|
||||
'''
|
||||
jtype: {microservice_name}
|
||||
py_modules:
|
||||
- microservice.py
|
||||
metas:
|
||||
name: {microservice_name}
|
||||
'''
|
||||
with open(os.path.join(dest_folder, 'config.yml'), 'w') as f:
|
||||
f.write(config_content)
|
||||
|
||||
def files_to_string(self, file_name_to_content):
|
||||
def files_to_string(self, file_name_to_content, restrict_keys=None):
|
||||
all_microservice_files_string = ''
|
||||
for file_name, tag in FILE_AND_TAG_PAIRS:
|
||||
if file_name in file_name_to_content:
|
||||
all_microservice_files_string += f'**{file_name}**\n'
|
||||
all_microservice_files_string += f'```{tag}\n'
|
||||
all_microservice_files_string += file_name_to_content[file_name]
|
||||
all_microservice_files_string += '\n```'
|
||||
if file_name in file_name_to_content and (not restrict_keys or file_name in restrict_keys):
|
||||
all_microservice_files_string += f'**{file_name}**\n```{tag}\n{file_name_to_content[file_name]}\n```\n\n'
|
||||
return all_microservice_files_string
|
||||
|
||||
def wrap_content_in_code_block(self, microservice_content, file_name, tag):
|
||||
return f'**{file_name}**\n```{tag}\n{microservice_content}\n```\n\n'
|
||||
# def wrap_content_in_code_block(self, microservice_content, file_name, tag):
|
||||
# return f'**{file_name}**\n```{tag}\n{microservice_content}\n```\n\n'
|
||||
|
||||
def generate_microservice(
|
||||
self,
|
||||
@@ -149,30 +149,15 @@ class Generator:
|
||||
print_colored('', '############# Playground #############', 'blue')
|
||||
|
||||
file_name_to_content = get_all_microservice_files_with_content(microservice_path)
|
||||
user_query = (
|
||||
general_guidelines()
|
||||
+ self.wrap_content_in_code_block(file_name_to_content['microservice.py'], 'microservice.py', 'python')
|
||||
+ self.wrap_content_in_code_block(file_name_to_content['test_microservice.py'], 'test_microservice.py',
|
||||
'python')
|
||||
+ f'''
|
||||
Create a playground for the executor {microservice_name} using streamlit.
|
||||
The playground must look like it was made by a professional designer.
|
||||
All the ui elements are well thought out to make them visually appealing and easy to use.
|
||||
This is an example how you can connect to the executor assuming the document (d) is already defined:
|
||||
```
|
||||
from jina import Client, Document, DocumentArray
|
||||
client = Client(host=host)
|
||||
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.
|
||||
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.
|
||||
'''
|
||||
)
|
||||
conversation = self.gpt_session.get_conversation([])
|
||||
conversation.chat(user_query)
|
||||
conversation.chat(
|
||||
template_generate_playground.format(
|
||||
general_guidelines=general_guidelines(),
|
||||
code_files_wrapped=self.files_to_string(file_name_to_content, ['microservice.py', 'test_microservice.py']),
|
||||
microservice_name=microservice_name,
|
||||
|
||||
)
|
||||
)
|
||||
playground_content_raw = conversation.chat(chain_of_thought_optimization('python', 'app.py', 'the playground'))
|
||||
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'))
|
||||
@@ -208,10 +193,15 @@ The playground (app.py) must not let the user configure the host on the ui.
|
||||
key: val for key, val in file_name_to_content.items() if
|
||||
key in ['requirements.txt', 'Dockerfile']
|
||||
})
|
||||
user_query = self.get_user_query_dependency_issue(all_files_string, error)
|
||||
user_query = template_solve_dependency_issue.format(
|
||||
description=description, error=error, all_files_string=all_files_string,
|
||||
not_allowed_docker=not_allowed_docker()
|
||||
)
|
||||
else:
|
||||
user_query = self.get_user_query_code_issue(description, error, file_name_to_content,
|
||||
test)
|
||||
user_query = template_solve_code_issue.format(
|
||||
description=description, error=error, all_files_string=self.files_to_string(file_name_to_content),
|
||||
not_allowed_executor=not_allowed_executor()
|
||||
)
|
||||
conversation = self.gpt_session.get_conversation()
|
||||
returned_files_raw = conversation.chat(user_query)
|
||||
for file_name, tag in FILE_AND_TAG_PAIRS:
|
||||
@@ -221,55 +211,6 @@ The playground (app.py) must not let the user configure the host on the ui.
|
||||
for file_name, content in file_name_to_content.items():
|
||||
persist_file(content, os.path.join(next_microservice_path, file_name))
|
||||
|
||||
def get_user_query_dependency_issue(self, all_files_string, error):
|
||||
user_query = (
|
||||
f'''
|
||||
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}
|
||||
```
|
||||
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.
|
||||
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()}
|
||||
|
||||
You are given the following files:
|
||||
|
||||
{all_files_string}"
|
||||
'''
|
||||
)
|
||||
return user_query
|
||||
|
||||
def get_user_query_code_issue(self, description, error, file_name_to_content, test):
|
||||
all_files_string = self.files_to_string(file_name_to_content)
|
||||
return f'''
|
||||
General rules: {not_allowed_executor()}
|
||||
Here is the description of the task the executor must solve:
|
||||
{description}
|
||||
|
||||
Here is the test scenario the executor must pass:\n{test}
|
||||
Here are all the files I use:
|
||||
{all_files_string}
|
||||
|
||||
|
||||
This is the error I encounter currently during the docker build process:
|
||||
{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.
|
||||
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:
|
||||
**...**
|
||||
```...
|
||||
...code...
|
||||
```
|
||||
'''
|
||||
|
||||
class MaxDebugTimeReachedException(BaseException):
|
||||
pass
|
||||
|
||||
@@ -280,68 +221,21 @@ complete file. Use the exact same syntax to wrap the code:
|
||||
|
||||
print_colored('', 'Is it a dependency issue?', 'blue')
|
||||
conversation = self.gpt_session.get_conversation([])
|
||||
answer = conversation.chat(
|
||||
f'Your task is to assist in identifying the root cause of a Docker build error for a python application. '
|
||||
f'The error message is as follows::\n\n{error}\n\n'
|
||||
f'The docker file is as follows:\n\n{docker_file}\n\n'
|
||||
f'Is this a dependency installation failure? Answer with "yes" or "no".'
|
||||
)
|
||||
answer = conversation.chat(template_is_dependency_issue.format(error=error, docker_file=docker_file))
|
||||
return 'yes' in answer.lower()
|
||||
|
||||
def generate_microservice_name(self, description):
|
||||
conversation = self.gpt_session.get_conversation()
|
||||
user_query = f'''
|
||||
Generate a name for the executor matching the description:
|
||||
"{description}"
|
||||
The executor name must fulfill the following criteria:
|
||||
- camel case
|
||||
- start with a capital letter
|
||||
- only consists of lower and upper case characters
|
||||
- end with Executor.
|
||||
|
||||
The output is a the raw string wrapped into ``` and starting with **name.txt** like this:
|
||||
**name.txt**
|
||||
```
|
||||
PDFParserExecutor
|
||||
```
|
||||
'''
|
||||
name_raw = conversation.chat(user_query)
|
||||
name_raw = conversation.chat(template_generate_microservice_name.format(description=description))
|
||||
name = self.extract_content_from_result(name_raw, 'name.txt')
|
||||
return name
|
||||
|
||||
def get_possible_packages(self, description):
|
||||
print_colored('', '############# What packages to use? #############', 'blue')
|
||||
user_query = f'''
|
||||
Here is the task description of the problem you need to solve:
|
||||
"{description}"
|
||||
1. Write down all the non-trivial subtasks you need to solve.
|
||||
2. Find out what is the core problem to solve.
|
||||
3. List up to 15 Python packages that are specifically designed or have functionalities to solve the complete core problem.
|
||||
4. For each of the 15 package think if it fulfills the following requirements:
|
||||
a) specifically designed or have functionalities to solve the complete core problem.
|
||||
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()}
|
||||
When answering, just write "yes" or "no".
|
||||
|
||||
5. Output the most suitable 5 python packages starting with the best one.
|
||||
If the package is mentioned in the description, then it is automatically the best one.
|
||||
|
||||
The output must be a list of lists wrapped into ``` and starting with **packages.csv** like this:
|
||||
**packages.csv**
|
||||
```
|
||||
package1
|
||||
package2
|
||||
package3
|
||||
package4
|
||||
package5
|
||||
...
|
||||
```
|
||||
'''
|
||||
conversation = self.gpt_session.get_conversation()
|
||||
packages_raw = conversation.chat(user_query)
|
||||
packages_raw = conversation.chat(
|
||||
template_generate_possible_packages.format(description=description, not_allowed_executor=not_allowed_executor())
|
||||
)
|
||||
packages_csv_string = self.extract_content_from_result(packages_raw, 'packages.csv')
|
||||
packages = [package.split(',') for package in packages_csv_string.split('\n')]
|
||||
packages = packages[:NUM_IMPLEMENTATION_STRATEGIES]
|
||||
|
||||
@@ -71,8 +71,7 @@ print(response[0].text)
|
||||
```'''
|
||||
|
||||
|
||||
system_message_base = f'''
|
||||
It is the year 2021.
|
||||
system_message_base = '''It is the year 2021.
|
||||
You are a principal engineer working at Jina - an open source company.
|
||||
You accurately satisfy all of the user's requirements.
|
||||
'''
|
||||
Your goal is to build a microservice that: {description}'''
|
||||
132
src/options/generate/templates.py
Normal file
132
src/options/generate/templates.py
Normal file
@@ -0,0 +1,132 @@
|
||||
from langchain import PromptTemplate
|
||||
|
||||
template_generate_microservice_name = PromptTemplate.from_template(
|
||||
'''Generate a name for the executor matching the description:
|
||||
"{description}"
|
||||
The executor name must fulfill the following criteria:
|
||||
- camel case
|
||||
- start with a capital letter
|
||||
- only consists of lower and upper case characters
|
||||
- end with Executor.
|
||||
|
||||
The output is a the raw string wrapped into ``` and starting with **name.txt** like this:
|
||||
**name.txt**
|
||||
```
|
||||
PDFParserExecutor
|
||||
```'''
|
||||
)
|
||||
|
||||
|
||||
template_generate_possible_packages = PromptTemplate.from_template(
|
||||
'''Here is the task description of the problem you need to solve:
|
||||
"{description}"
|
||||
1. Write down all the non-trivial subtasks you need to solve.
|
||||
2. Find out what is the core problem to solve.
|
||||
3. List up to 15 Python packages that are specifically designed or have functionalities to solve the complete core problem.
|
||||
4. For each of the 15 package think if it fulfills the following requirements:
|
||||
a) specifically designed or have functionalities to solve the complete core problem.
|
||||
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}
|
||||
When answering, just write "yes" or "no".
|
||||
|
||||
5. Output the most suitable 5 python packages starting with the best one.
|
||||
If the package is mentioned in the description, then it is automatically the best one.
|
||||
|
||||
The output must be a list of lists wrapped into ``` and starting with **packages.csv** like this:
|
||||
**packages.csv**
|
||||
```
|
||||
package1
|
||||
package2
|
||||
package3
|
||||
package4
|
||||
package5
|
||||
...
|
||||
```
|
||||
''')
|
||||
|
||||
|
||||
template_solve_code_issue = PromptTemplate.from_template(
|
||||
'''General rules: {not_allowed_executor}
|
||||
Here is the description of the task the executor must solve:
|
||||
{description}
|
||||
|
||||
Here is the test scenario the executor must pass:\n{test}
|
||||
Here are all the files I use:
|
||||
{all_files_string}
|
||||
|
||||
|
||||
This is the error I encounter currently during the docker build process:
|
||||
{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.
|
||||
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:
|
||||
**...**
|
||||
```...
|
||||
...code...
|
||||
```
|
||||
'''
|
||||
)
|
||||
|
||||
|
||||
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}
|
||||
```
|
||||
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.
|
||||
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}
|
||||
|
||||
You are given the following files:
|
||||
|
||||
{all_files_string}
|
||||
'''
|
||||
)
|
||||
|
||||
|
||||
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:
|
||||
|
||||
{error}
|
||||
|
||||
The docker file is as follows:
|
||||
|
||||
{docker_file}
|
||||
|
||||
Is this a dependency installation failure? Answer with "yes" or "no".'''
|
||||
)
|
||||
|
||||
|
||||
template_generate_playground = PromptTemplate.from_template(
|
||||
'''{general_guidelines}
|
||||
|
||||
{code_files_wrapped}
|
||||
|
||||
Create a playground for the executor {microservice_name} using streamlit.
|
||||
The playground must look like it was made by a professional designer.
|
||||
All the ui elements are well thought out to make them visually appealing and easy to use.
|
||||
This is an example how you can connect to the executor assuming the document (d) is already defined:
|
||||
```
|
||||
from jina import Client, Document, DocumentArray
|
||||
client = Client(host=host)
|
||||
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.
|
||||
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.
|
||||
'''
|
||||
)
|
||||
Reference in New Issue
Block a user