mirror of
https://github.com/aljazceru/dev-gpt.git
synced 2025-12-19 22:54:21 +01:00
⚽ refactor: playground more stable generation
This commit is contained in:
@@ -27,7 +27,9 @@ FILE_AND_TAG_PAIRS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
INDICATOR_TO_IMPORT_STATEMENT = {
|
INDICATOR_TO_IMPORT_STATEMENT = {
|
||||||
|
'io.BytesIO': 'import io',
|
||||||
'BytesIO': 'from io import BytesIO',
|
'BytesIO': 'from io import BytesIO',
|
||||||
|
'base64': 'import base64',
|
||||||
}
|
}
|
||||||
|
|
||||||
FLOW_URL_PLACEHOLDER = 'jcloud.jina.ai'
|
FLOW_URL_PLACEHOLDER = 'jcloud.jina.ai'
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ Note: If you are not sure about the details, then come up with the minimal numbe
|
|||||||
|
|
||||||
generate_output_schema_prompt = '''{context_string}
|
generate_output_schema_prompt = '''{context_string}
|
||||||
Generate the lean response json schema for the Microservice.
|
Generate the lean response json schema for the Microservice.
|
||||||
Note: If you are not sure about the details, then come up with the minimal number of parameters possible.'''
|
Note: If you are not sure about the details, then come up with the minimal number of parameters possible.
|
||||||
|
Note: If you can decide to return files as URLs or as base64 encoded strings, then choose the base64 encoded strings.'''
|
||||||
|
|
||||||
summarize_description_and_schemas_prompt = '''{context_string}
|
summarize_description_and_schemas_prompt = '''{context_string}
|
||||||
Write an updated microservice description by incorporating information about the request and response parameters in a concise way without losing any information.
|
Write an updated microservice description by incorporating information about the request and response parameters in a concise way without losing any information.
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ metas:
|
|||||||
line.replace('{{APT_GET_PACKAGES}}', '').replace('{{DOCKER_BASE_IMAGE_VERSION}}', DOCKER_BASE_IMAGE_VERSION)
|
line.replace('{{APT_GET_PACKAGES}}', '').replace('{{DOCKER_BASE_IMAGE_VERSION}}', DOCKER_BASE_IMAGE_VERSION)
|
||||||
for line in docker_file_template_lines
|
for line in docker_file_template_lines
|
||||||
]
|
]
|
||||||
docker_file_content = '\n'.join(docker_file_template_lines)
|
docker_file_content = ''.join(docker_file_template_lines)
|
||||||
persist_file(docker_file_content, os.path.join(self.cur_microservice_path, 'Dockerfile'))
|
persist_file(docker_file_content, os.path.join(self.cur_microservice_path, 'Dockerfile'))
|
||||||
|
|
||||||
self.write_config_yml(self.microservice_name, self.cur_microservice_path)
|
self.write_config_yml(self.microservice_name, self.cur_microservice_path)
|
||||||
@@ -259,12 +259,16 @@ metas:
|
|||||||
|
|
||||||
|
|
||||||
def add_missing_imports_post_process_fn(self, content_dict: dict):
|
def add_missing_imports_post_process_fn(self, content_dict: dict):
|
||||||
for indicator, import_statement in INDICATOR_TO_IMPORT_STATEMENT.items():
|
for file_name, file_content in content_dict.items():
|
||||||
for file_name, file_content in content_dict.items():
|
file_content = self.add_missing_imports_for_file(file_content)
|
||||||
if indicator in file_content and import_statement not in file_content:
|
content_dict[file_name] = file_content
|
||||||
content_dict[file_name] = f'{import_statement}\n{file_content}'
|
|
||||||
return content_dict
|
return content_dict
|
||||||
|
|
||||||
|
def add_missing_imports_for_file(self, file_content):
|
||||||
|
for indicator, import_statement in INDICATOR_TO_IMPORT_STATEMENT.items():
|
||||||
|
if indicator in file_content and import_statement not in file_content:
|
||||||
|
file_content = f'{import_statement}\n{file_content}'
|
||||||
|
return file_content
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read_docker_template():
|
def read_docker_template():
|
||||||
@@ -295,12 +299,15 @@ pytest
|
|||||||
def generate_playground(self):
|
def generate_playground(self):
|
||||||
print_colored('', '\n\n############# Playground #############', 'blue')
|
print_colored('', '\n\n############# Playground #############', 'blue')
|
||||||
|
|
||||||
|
with open(os.path.join(os.path.dirname(__file__), 'static_files', 'gateway', 'app_template.py'), 'r', encoding='utf-8') as f:
|
||||||
|
playground_template = f.read()
|
||||||
file_name_to_content = get_all_microservice_files_with_content(self.cur_microservice_path)
|
file_name_to_content = get_all_microservice_files_with_content(self.cur_microservice_path)
|
||||||
conversation = self.gpt_session.get_conversation()
|
conversation = self.gpt_session.get_conversation()
|
||||||
conversation.chat(
|
conversation.chat(
|
||||||
template_generate_playground.format(
|
template_generate_playground.format(
|
||||||
code_files_wrapped=self.files_to_string(file_name_to_content, ['test_microservice.py']),
|
code_files_wrapped=self.files_to_string(file_name_to_content, ['test_microservice.py', 'microservice.py']),
|
||||||
microservice_name=self.microservice_name,
|
microservice_name=self.microservice_name,
|
||||||
|
playground_template=playground_template,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
playground_content_raw = conversation.chat(
|
playground_content_raw = conversation.chat(
|
||||||
@@ -316,6 +323,7 @@ pytest
|
|||||||
playground_content = self.extract_content_from_result(
|
playground_content = self.extract_content_from_result(
|
||||||
content_raw, 'app.py', match_single_block=True
|
content_raw, 'app.py', match_single_block=True
|
||||||
)
|
)
|
||||||
|
playground_content = self.add_missing_imports_for_file(playground_content)
|
||||||
|
|
||||||
gateway_path = os.path.join(self.cur_microservice_path, 'gateway')
|
gateway_path = os.path.join(self.cur_microservice_path, 'gateway')
|
||||||
shutil.copytree(os.path.join(os.path.dirname(__file__), 'static_files', 'gateway'), gateway_path)
|
shutil.copytree(os.path.join(os.path.dirname(__file__), 'static_files', 'gateway'), gateway_path)
|
||||||
|
|||||||
@@ -1,53 +1,53 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import base64
|
|
||||||
import streamlit as st
|
import streamlit as st
|
||||||
from jina import Client, Document, DocumentArray
|
from jina import Client, Document, DocumentArray
|
||||||
|
import io
|
||||||
|
|
||||||
st.set_page_config(
|
st.set_page_config(
|
||||||
page_title="<page title here>",
|
page_title="<page title here>",
|
||||||
page_icon="<page icon here>",
|
page_icon="<page icon here>",
|
||||||
layout="<page layout here>",
|
layout="centered",
|
||||||
initial_sidebar_state="<sidebar state here>",
|
initial_sidebar_state="auto",
|
||||||
)
|
)
|
||||||
|
|
||||||
st.title("<thematic emoji here> <header title here>")
|
st.title("<thematic emoji here> <header title here>")
|
||||||
st.markdown(
|
st.markdown(
|
||||||
"<10 word description here>"
|
"<10 word description here>"
|
||||||
"To deploy your own microservice, click [here](https://github.com/jina-ai/dev-gpt)."
|
"To generate and deploy your own microservice, click [here](https://github.com/jina-ai/dev-gpt)."
|
||||||
)
|
)
|
||||||
|
st.subheader("<a unique thematic emoji here> <sub header title here>") # only if input parameters are needed
|
||||||
st.header("<another thematic emoji here> Input Parameters") # only if input parameters are needed
|
|
||||||
with st.form(key="input_form"):
|
with st.form(key="input_form"):
|
||||||
<input parameter definition here>
|
# <input parameter definition here>
|
||||||
|
input_json_dict = {} #
|
||||||
|
|
||||||
input_data = {
|
input_json_dict_string = json.dumps(input_json_dict)
|
||||||
<input parameters here>
|
submitted = st.form_submit_button("<submit button text>")
|
||||||
}
|
|
||||||
input_json = json.dumps(input_data)
|
|
||||||
|
|
||||||
# Process input and call microservice
|
# Process input and call microservice
|
||||||
if submit_button:
|
if submitted:
|
||||||
with st.spinner("Generating collage..."):
|
with st.spinner("<spinner text here>..."):
|
||||||
|
|
||||||
|
|
||||||
client = Client(host="http://localhost:8080")
|
client = Client(host="http://localhost:8080")
|
||||||
d = Document(text=input_json)
|
d = Document(text=input_json_dict_string)
|
||||||
response = client.post("/", inputs=DocumentArray([d]))
|
response = client.post("/", inputs=DocumentArray([d]))
|
||||||
|
|
||||||
output_data = json.loads(response[0].text)
|
output_data = json.loads(response[0].text)
|
||||||
<visualization of results>
|
# <visualization of results here>
|
||||||
|
|
||||||
# Display curl command
|
# Display curl command
|
||||||
deployment_id = os.environ.get("K8S_NAMESPACE_NAME", "")
|
deployment_id = os.environ.get("K8S_NAMESPACE_NAME", "")
|
||||||
host = (
|
api_endpoint = (
|
||||||
f"https://dev-gpt-{deployment_id.split('-')[1]}.wolf.jina.ai/post"
|
f"https://dev-gpt-{deployment_id.split('-')[1]}.wolf.jina.ai/post"
|
||||||
if deployment_id
|
if deployment_id
|
||||||
else "http://localhost:8080/post"
|
else "http://localhost:8080/post"
|
||||||
)
|
)
|
||||||
|
|
||||||
with st.expander("See curl command"):
|
with st.expander("See curl command"):
|
||||||
st.markdown("You can use the following curl command to send a request to the microservice from the command line:")
|
st.markdown("You can use the following curl command to send a request to the microservice from the command line:")
|
||||||
|
escaped_input_json_dict_string = input_json_dict_string.replace('"', '\\"')
|
||||||
|
|
||||||
st.code(
|
st.code(
|
||||||
f'curl -X "POST" "{host}" -H "accept: application/json" -H "Content-Type: application/json" -d \'{{"data": [{{"text": "{input_json}"}}]}}\'',
|
f'curl -X "POST" "{api_endpoint}" -H "accept: application/json" -H "Content-Type: application/json" -d \'{{"data": [{{"text": "{escaped_input_json_dict_string}"}}]}}\'',
|
||||||
language="bash",
|
language="bash",
|
||||||
)
|
)
|
||||||
@@ -132,9 +132,10 @@ def template_generate_function_constructor(is_using_gpt_3_5_turbo, is_using_goog
|
|||||||
general_guidelines_string + f'''
|
general_guidelines_string + f'''
|
||||||
|
|
||||||
Write a python function which receives as \
|
Write a python function which receives as \
|
||||||
input json string (that can be parsed with the python function json.loads) and \
|
input json dictionary string (that can be parsed with the python function json.loads) and \
|
||||||
outputs a json string (that can be parsed with the python function json.loads). \
|
outputs a json dictionary string (that can be parsed with the python function json.loads). \
|
||||||
The function is called 'func'.
|
The function is called 'func' and has the following signature:
|
||||||
|
def func(input_json_dict_string: str) -> str:
|
||||||
The function must fulfill the following description: '{{microservice_description}}'.
|
The function must fulfill the following description: '{{microservice_description}}'.
|
||||||
It will be tested with the following scenario: '{{test_description}}'.
|
It will be tested with the following scenario: '{{test_description}}'.
|
||||||
For the implementation use the following package(s): '{{packages}}'.
|
For the implementation use the following package(s): '{{packages}}'.
|
||||||
@@ -433,13 +434,12 @@ Use the exact following syntax to wrap the code:
|
|||||||
```
|
```
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
**implementation.py**
|
**implementation.py**
|
||||||
```python
|
```python
|
||||||
import json
|
import json
|
||||||
|
|
||||||
def func(json_input: str) -> str:
|
def func(input_json_dict_string: str) -> str:
|
||||||
return json_input['img_base64']
|
return json.dumps('output_param1': input_json_dict_string['img_base64'])
|
||||||
```'''
|
```'''
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -449,50 +449,30 @@ template_generate_playground = PromptTemplate.from_template(
|
|||||||
|
|
||||||
{code_files_wrapped}
|
{code_files_wrapped}
|
||||||
|
|
||||||
Create a playground for the executor {microservice_name} using streamlit.
|
1. Write down the json request model required by microservice.py.
|
||||||
The playground must look like it was made by a professional designer.
|
2. Generate a playground for the microservice {microservice_name} using the following streamlit template by replacing all the placeholders (<...>) with the correct values:
|
||||||
All the ui elements are well thought out to make them visually appealing and easy to use.
|
**app_template.py**
|
||||||
Don't mention the word Playground in the title.
|
```python
|
||||||
The playground contains many emojis that fit the theme of the playground and has an emoji as favicon.
|
{playground_template}
|
||||||
The playground encourages the user to deploy their own microservice by clicking on this link: https://github.com/jina-ai/dev-gpt
|
|
||||||
The playground uses the following code to send a request to the microservice:
|
|
||||||
```
|
```
|
||||||
from jina import Client, Document, DocumentArray
|
Note: Don't mention the word Playground in the title.
|
||||||
client = Client(host='http://localhost:8080')
|
Most importantly: You must generate the complete app.py file using the following syntax to wrap the code:
|
||||||
d = Document(text=json.dumps(INPUT_DICTIONARY)) # fill-in dictionary which takes input
|
|
||||||
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
|
|
||||||
The playground displays a code block containing the microservice specific curl code that can be used to send the request to the microservice.
|
|
||||||
While the exact payload in the curl might change, the host and deployment ID always stay the same. Example:
|
|
||||||
```
|
|
||||||
deployment_id = os.environ.get("K8S_NAMESPACE_NAME", "")
|
|
||||||
host = f'https://dev-gpt-{{deployment_id.split("-")[1]}}.wolf.jina.ai/post' if deployment_id else "http://localhost:8080/post"
|
|
||||||
with st.expander("See curl command"):
|
|
||||||
st.code(
|
|
||||||
f'curl -X \\'POST\\' \\'host\\' -H \\'accept: application/json\\' -H \\'Content-Type: application/json\\' -d \\'{{{{"data": [{{{{"text": "hello, world!"}}}}]}}}}\\'',
|
|
||||||
language='bash'
|
|
||||||
)
|
|
||||||
```
|
|
||||||
You must provide the complete app.py file using the following syntax to wrap the code:
|
|
||||||
**app.py**
|
**app.py**
|
||||||
```python
|
```python
|
||||||
...
|
...
|
||||||
```
|
```'''
|
||||||
The playground (app.py) must always use the host on http://localhost:8080 and must not let the user configure the host on the UI.
|
|
||||||
The playground (app.py) must not import the executor.
|
|
||||||
'''
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
template_chain_of_thought = PromptTemplate.from_template(
|
template_chain_of_thought = PromptTemplate.from_template(
|
||||||
'''First, write down an extensive list of obvious and non-obvious observations about {file_name_purpose} that could need an adjustment. Explain why.
|
'''\
|
||||||
Think if all the changes are required and finally decide for the changes you want to make, but you are not allowed disregard the instructions in the previous message.
|
1. write down an extensive list (5 words per item) of obvious and non-obvious observations about {file_name_purpose} that could need an adjustment.
|
||||||
Be very hesitant to change the code. Only make a change if you are sure that it is necessary.
|
2. Explain why. (5 words per item)
|
||||||
|
3. Think if all the changes are required
|
||||||
Output only {file_name_purpose}
|
4. decide for the changes you want to make, but you are not allowed disregard the instructions in the previous message.
|
||||||
Write the whole content of {file_name_purpose} - even if you decided to change only a small thing or even nothing.
|
5. Write the whole content of {file_name_purpose} - even if you decided to change only a small thing or even nothing.
|
||||||
|
Note: Be very hesitant to change the code. Only make a change if you are sure that it is necessary.
|
||||||
|
Note: Output only {file_name_purpose}
|
||||||
''' + '\n' + template_code_wrapping_string + '''
|
''' + '\n' + template_code_wrapping_string + '''
|
||||||
|
|
||||||
Remember:
|
Remember:
|
||||||
|
|||||||
Reference in New Issue
Block a user