refactor: playground more stable generation

This commit is contained in:
Florian Hönicke
2023-05-22 11:48:28 +02:00
parent 458d5eb1a4
commit 5792225ea1
5 changed files with 60 additions and 69 deletions

View File

@@ -27,7 +27,9 @@ FILE_AND_TAG_PAIRS = [
]
INDICATOR_TO_IMPORT_STATEMENT = {
'io.BytesIO': 'import io',
'BytesIO': 'from io import BytesIO',
'base64': 'import base64',
}
FLOW_URL_PLACEHOLDER = 'jcloud.jina.ai'

View File

@@ -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 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}
Write an updated microservice description by incorporating information about the request and response parameters in a concise way without losing any information.

View File

@@ -250,7 +250,7 @@ metas:
line.replace('{{APT_GET_PACKAGES}}', '').replace('{{DOCKER_BASE_IMAGE_VERSION}}', DOCKER_BASE_IMAGE_VERSION)
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'))
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):
for indicator, import_statement in INDICATOR_TO_IMPORT_STATEMENT.items():
for file_name, file_content in content_dict.items():
if indicator in file_content and import_statement not in file_content:
content_dict[file_name] = f'{import_statement}\n{file_content}'
file_content = self.add_missing_imports_for_file(file_content)
content_dict[file_name] = file_content
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
def read_docker_template():
@@ -295,12 +299,15 @@ pytest
def generate_playground(self):
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)
conversation = self.gpt_session.get_conversation()
conversation.chat(
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,
playground_template=playground_template,
)
)
playground_content_raw = conversation.chat(
@@ -316,6 +323,7 @@ pytest
playground_content = self.extract_content_from_result(
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')
shutil.copytree(os.path.join(os.path.dirname(__file__), 'static_files', 'gateway'), gateway_path)

View File

@@ -1,53 +1,53 @@
import json
import os
import base64
import streamlit as st
from jina import Client, Document, DocumentArray
import io
st.set_page_config(
page_title="<page title here>",
page_icon="<page icon here>",
layout="<page layout here>",
initial_sidebar_state="<sidebar state here>",
layout="centered",
initial_sidebar_state="auto",
)
st.title("<thematic emoji here> <header title here>")
st.markdown(
"<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.header("<another thematic emoji here> Input Parameters") # only if input parameters are needed
st.subheader("<a unique thematic emoji here> <sub header title here>") # only if input parameters are needed
with st.form(key="input_form"):
<input parameter definition here>
# <input parameter definition here>
input_json_dict = {} #
input_data = {
<input parameters here>
}
input_json = json.dumps(input_data)
input_json_dict_string = json.dumps(input_json_dict)
submitted = st.form_submit_button("<submit button text>")
# Process input and call microservice
if submit_button:
with st.spinner("Generating collage..."):
if submitted:
with st.spinner("<spinner text here>..."):
client = Client(host="http://localhost:8080")
d = Document(text=input_json)
d = Document(text=input_json_dict_string)
response = client.post("/", inputs=DocumentArray([d]))
output_data = json.loads(response[0].text)
<visualization of results>
# <visualization of results here>
# Display curl command
deployment_id = os.environ.get("K8S_NAMESPACE_NAME", "")
host = (
api_endpoint = (
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.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(
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",
)

View File

@@ -132,9 +132,10 @@ def template_generate_function_constructor(is_using_gpt_3_5_turbo, is_using_goog
general_guidelines_string + f'''
Write a python function which receives as \
input json 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). \
The function is called 'func'.
input json dictionary string (that can be parsed with the python function json.loads) and \
outputs a json dictionary string (that can be parsed with the python function json.loads). \
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}}'.
It will be tested with the following scenario: '{{test_description}}'.
For the implementation use the following package(s): '{{packages}}'.
@@ -433,13 +434,12 @@ Use the exact following syntax to wrap the code:
```
Example:
**implementation.py**
```python
import json
def func(json_input: str) -> str:
return json_input['img_base64']
def func(input_json_dict_string: str) -> str:
return json.dumps('output_param1': input_json_dict_string['img_base64'])
```'''
)
@@ -449,50 +449,30 @@ template_generate_playground = PromptTemplate.from_template(
{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.
Don't mention the word Playground in the title.
The playground contains many emojis that fit the theme of the playground and has an emoji as favicon.
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:
1. Write down the json request model required by microservice.py.
2. Generate a playground for the microservice {microservice_name} using the following streamlit template by replacing all the placeholders (<...>) with the correct values:
**app_template.py**
```python
{playground_template}
```
from jina import Client, Document, DocumentArray
client = Client(host='http://localhost:8080')
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:
Note: Don't mention the word Playground in the title.
Most importantly: You must generate the complete app.py file using the following syntax to wrap the code:
**app.py**
```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(
'''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.
Be very hesitant to change the code. Only make a change if you are sure that it is necessary.
Output only {file_name_purpose}
Write the whole content of {file_name_purpose} - even if you decided to change only a small thing or even nothing.
'''\
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.
2. Explain why. (5 words per item)
3. Think if all the changes are required
4. decide for the changes you want to make, but you are not allowed disregard the instructions in the previous message.
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 + '''
Remember: