feat: support for gpt

This commit is contained in:
Florian Hönicke
2023-04-20 00:28:28 +02:00
parent 9261fa3a3d
commit db3a05771b
27 changed files with 104 additions and 27621 deletions

23
frontend/.gitignore vendored
View File

@@ -1,23 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@@ -1,70 +0,0 @@
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

17228
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +0,0 @@
{
"name": "microchain-frontend",
"version": "0.1.1",
"private": true,
"dependencies": {
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@mui/material": "^5.11.13",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.3.4",
"clipboard-copy": "^4.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"uuid": "^9.0.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -1,43 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -1,25 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@@ -1,38 +0,0 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@@ -1,196 +0,0 @@
import React, {useState} from 'react';
import axios from 'axios';
import {Box, Container, FormControl, InputLabel, MenuItem, Select, TextField, Typography,} from '@mui/material';
import copy from 'clipboard-copy';
import Button from '@mui/material/Button';
function App() {
const [executorName, setExecutorName] = useState('MyCoolOcrExecutor');
const [executorDescription, setExecutorDescription] = useState('OCR detector');
const [inputModality, setInputModality] = useState('image');
const [inputDocField, setInputDocField] = useState('uri');
const [outputModality, setOutputModality] = useState('text');
const [outputDocField, setOutputDocField] = useState('text');
const [testIn, settestIn] = useState('https://miro.medium.com/v2/resize:fit:1024/0*4ty0Adbdg4dsVBo3.png');
const [testOut, settestOut] = useState('> Hello, world!_');
const [responseText, setResponseText] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
const requestBody = {
executor_name: executorName,
executor_description: executorDescription,
input_modality: inputModality,
input_doc_field: inputDocField,
output_modality: outputModality,
output_doc_field: outputDocField,
test_in: testIn,
test_out: testOut,
};
try {
const response = await axios.post('http://0.0.0.0:8000/create', requestBody);
console.log(response.data)
setResponseText(response.data);
} catch (error) {
console.error(error);
setResponseText('An error occurred while processing the request.');
}
};
const handleCopy = (fileContent) => {
copy(fileContent);
};
return (
<Container maxWidth="md">
<Box sx={{my: 4}}>
<Typography variant="h4" component="h1" gutterBottom>
MicroChain
</Typography>
<Typography variant="body1" component="p" gutterBottom>
Magically create your microservice just by describing it.
</Typography>
<form onSubmit={handleSubmit}>
<Box sx={{my: 2}}>
<TextField
label="Executor Name"
value={executorName}
onChange={(e) => setExecutorName(e.target.value)}
fullWidth
/>
</Box>
<Box sx={{my: 2}}>
<TextField
label="Executor Description"
value={executorDescription}
onChange={(e) => setExecutorDescription(e.target.value)}
fullWidth
/>
</Box>
<Box sx={{my: 2}}>
<Typography variant="h6" component="h2" gutterBottom>
Input Interface
</Typography>
<FormControl fullWidth>
<InputLabel id="input-modality-label">Input Modality</InputLabel>
<Select
labelId="input-modality-label"
value={inputModality}
onChange={(e) => setInputModality(e.target.value)}
>
<MenuItem value="text">Text</MenuItem>
<MenuItem value="image">Image</MenuItem>
<MenuItem value="3d">3D</MenuItem>
<MenuItem value="audio">Audio</MenuItem>
<MenuItem value="video">Video</MenuItem>
<MenuItem value="pdf">PDF</MenuItem>
</Select>
</FormControl>
</Box>
<Box sx={{my: 2}}>
<FormControl fullWidth>
<InputLabel id="input-doc-field-label">Input Doc Field</InputLabel>
<Select
labelId="input-doc-field-label"
value={inputDocField}
onChange={(e) => setInputDocField(e.target.value)}
>
<MenuItem value="text">Text</MenuItem>
<MenuItem value="blob">Blob</MenuItem>
<MenuItem value="tensor">Tensor</MenuItem>
<MenuItem value="uri">URL</MenuItem>
</Select>
</FormControl>
</Box>
<Box sx={{my: 2}}>
<Typography variant="h6" component="h2" gutterBottom>
Output Interface
</Typography>
<FormControl fullWidth>
<InputLabel id="output-modality-label">Output Modality</InputLabel>
<Select
labelId="output-modality-label"
value={outputModality}
onChange={(e) => setOutputModality(e.target.value)}
>
<MenuItem value="text">Text</MenuItem>
<MenuItem value="image">Image</MenuItem>
<MenuItem value="3d">3D</MenuItem>
<MenuItem value="audio">Audio</MenuItem>
<MenuItem value="video">Video</MenuItem>
<MenuItem value="pdf">PDF</MenuItem>
</Select>
</FormControl>
</Box>
<Box sx={{my: 2}}>
<FormControl fullWidth>
<InputLabel id="output-doc-field-label">Output Doc Field</InputLabel>
<Select
labelId="output-doc-field-label"
value={outputDocField}
onChange={(e) => setOutputDocField(e.target.value)}
>
<MenuItem value="text">Text</MenuItem>
<MenuItem value="blob">Blob</MenuItem>
<MenuItem value="tensor">Tensor</MenuItem>
<MenuItem value="uri">URL</MenuItem>
</Select>
</FormControl>
</Box>
<Box sx={{my: 2}}>
<Typography variant="h6" component="h2" gutterBottom>
Test Parameters
</Typography>
<TextField
label="Input Test In"
value={testIn}
onChange={(e) => settestIn(e.target.value)}
fullWidth
/>
</Box>
<Box sx={{my: 2}}>
<TextField
label="Input Test Out"
value={testOut}
onChange={(e) => settestOut(e.target.value)}
fullWidth
/>
</Box>
<Box sx={{my: 2}}>
<Button type="submit" variant="contained" color="primary">
Submit
</Button>
</Box>
</form>
{responseText && (
<Box sx={{my: 4}}>
<Typography variant="h6" component="h2" gutterBottom>
Response
</Typography>
{Object.entries(responseText.result).map(([fileName, fileContent]) => (
<Box key={fileName} sx={{my: 2, p: 2, border: '1px solid #ddd', borderRadius: '4px'}}>
<Typography variant="subtitle1" gutterBottom>
{fileName}
</Typography>
<pre>{fileContent}</pre>
<Button
onClick={() => handleCopy(fileContent)}
variant="outlined"
color="primary"
size="small"
>
Copy Code
</Button>
</Box>
))}
</Box>
)}
</Box>
</Container>
);
}
export default App;

View File

@@ -1,8 +0,0 @@
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@@ -1,111 +0,0 @@
import React, { useState } from 'react';
function CreateExecutorForm({ onCreateExecutor }) {
const [formData, setFormData] = useState({
executor_name: '',
executor_description: '',
input_modality: '',
input_doc_field: '',
output_modality: '',
output_doc_field: '',
test_in: '',
test_out: '',
});
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
onCreateExecutor(formData);
};
return (
<form onSubmit={handleSubmit}>
<label>
Executor Name:
<input
type="text"
name="executor_name"
value={formData.executor_name}
onChange={handleChange}
required
/>
</label>
<label>
Input Executor Description:
<input
type="text"
name="executor_description"
value={formData.executor_description}
onChange={handleChange}
required
/>
</label>
<label>
Input Modality:
<input
type="text"
name="input_modality"
value={formData.input_modality}
onChange={handleChange}
required
/>
</label>
<label>
Input Doc Field:
<input
type="text"
name="input_doc_field"
value={formData.input_doc_field}
onChange={handleChange}
required
/>
</label>
<label>
Output Modality:
<input
type="text"
name="output_modality"
value={formData.output_modality}
onChange={handleChange}
required
/>
</label>
<label>
Output Doc Field:
<input
type="text"
name="output_doc_field"
value={formData.output_doc_field}
onChange={handleChange}
required
/>
</label>
<label>
Input Test URL:
<input
type="url"
name="test_in"
value={formData.test_in}
onChange={handleChange}
required
/>
</label>
<label>
Input Test Output:
<input
type="text"
name="test_out"
value={formData.test_out}
onChange={handleChange}
required
/>
</label>
<button type="submit">Create Executor</button>
</form>
);
}
export default CreateExecutorForm

View File

@@ -1,30 +0,0 @@
import React from 'react';
function ExecutorOutput({ response }) {
const { result, success, message } = response;
return (
<div>
<h2>Generated Executor Files</h2>
{success ? (
<div>
{Object.entries(result).map(([filename, content]) => (
<div key={filename}>
<h3>{filename}</h3>
<pre>
<code>{content}</code>
</pre>
</div>
))}
</div>
) : (
<div>
<h3>Error</h3>
<p>{message}</p>
</div>
)}
</div>
);
}
export default ExecutorOutput;

View File

@@ -1,13 +0,0 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

View File

@@ -1,10 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,5 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

File diff suppressed because it is too large Load Diff

View File

@@ -8,8 +8,9 @@ from langchain import PromptTemplate
from langchain.callbacks import CallbackManager
from langchain.chat_models import ChatOpenAI
from openai.error import RateLimitError
from langchain.schema import AIMessage, HumanMessage, SystemMessage, BaseMessage
from langchain.schema import HumanMessage, SystemMessage, BaseMessage
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from requests.exceptions import ConnectionError
from src.options.generate.templates_system import template_system_message_base, executor_example, docarray_example, client_example
from src.utils.string_tools import print_colored
@@ -83,7 +84,16 @@ class _GPTConversation:
if os.environ['VERBOSE'].lower() == 'true':
print_colored('user', prompt, 'blue')
print_colored('assistant', '', 'green', end='')
response = self._chat([self.system_message] + self.messages)
for i in range(10):
try:
response = self._chat([self.system_message] + self.messages)
break
except ConnectionError as e:
print('There was a connection error. Retrying...')
if i == 9:
raise e
sleep(10)
if os.environ['VERBOSE'].lower() == 'true':
print()
self.messages.append(response)

View File

@@ -73,6 +73,7 @@ def push_executor(dir_path):
'public': 'True',
'private': 'False',
'verbose': 'True',
'buildEnv': f'{{"OPENAI_API_KEY": "{os.environ["OPENAI_API_KEY"]}"}}',
'md5sum': md5_digest,
}
with suppress_stdout():
@@ -207,6 +208,7 @@ jtype: Flow
with:
name: nowapi
port: 8080
protocol: http
jcloud:
version: 3.14.2.dev18
labels:
@@ -217,6 +219,8 @@ executors:
- name: {executor_name.lower()}
uses: {prefix}://{get_user_name(DEMO_TOKEN)}/{executor_name}:latest
{"" if use_docker else "install-requirements: True"}
env:
OPENAI_API_KEY: {os.environ['OPENAI_API_KEY']}
jcloud:
resources:
instance: C2
@@ -290,3 +294,5 @@ def process_error_message(error_message):
if not response and last_line.startswith('error: '):
return last_line
return response
push_executor('/Users/florianhonicke/jina/gptdeploy/microservice/NewsArticleSummaryExecutor7754860')

View File

@@ -4,7 +4,9 @@ REQUIREMENTS_FILE_NAME = 'requirements.txt'
DOCKER_FILE_NAME = 'Dockerfile'
CLIENT_FILE_NAME = 'client.py'
STREAMLIT_FILE_NAME = 'streamlit.py'
GPT_3_5_TURBO_API_FILE_NAME = 'gpt_3_5_turbo_api.py'
GPT_3_5_TURBO_API_FILE_TAG = 'python'
EXECUTOR_FILE_TAG = 'python'
TEST_EXECUTOR_FILE_TAG = 'python'
REQUIREMENTS_FILE_TAG = ''
@@ -12,7 +14,9 @@ DOCKER_FILE_TAG = 'dockerfile'
CLIENT_FILE_TAG = 'python'
STREAMLIT_FILE_TAG = 'python'
FILE_AND_TAG_PAIRS = [
(GPT_3_5_TURBO_API_FILE_NAME, GPT_3_5_TURBO_API_FILE_NAME),
(EXECUTOR_FILE_NAME, EXECUTOR_FILE_TAG),
(TEST_EXECUTOR_FILE_NAME, TEST_EXECUTOR_FILE_TAG),
(REQUIREMENTS_FILE_NAME, REQUIREMENTS_FILE_TAG),
@@ -32,4 +36,6 @@ DEMO_TOKEN = '45372338e04f5a41af949024db929d46'
PROBLEMATIC_PACKAGES = [
# 'Pyrender', 'Trimesh',
'ModernGL', 'PyOpenGL', 'Pyglet', 'pythreejs', 'panda3d' # because they need a screen
]
]
GPT_3_5_TURBO_API_FILE_NAME = 'gpt_3_5_turbo_api.py'

View File

@@ -6,7 +6,7 @@ from src.apis import gpt
from src.apis.jina_cloud import process_error_message, push_executor
from src.constants import FILE_AND_TAG_PAIRS, NUM_IMPLEMENTATION_STRATEGIES, MAX_DEBUGGING_ITERATIONS, \
PROBLEMATIC_PACKAGES, EXECUTOR_FILE_NAME, EXECUTOR_FILE_TAG, TEST_EXECUTOR_FILE_NAME, TEST_EXECUTOR_FILE_TAG, \
REQUIREMENTS_FILE_NAME, REQUIREMENTS_FILE_TAG, DOCKER_FILE_NAME, DOCKER_FILE_TAG
REQUIREMENTS_FILE_NAME, REQUIREMENTS_FILE_TAG, DOCKER_FILE_NAME, DOCKER_FILE_TAG, GPT_3_5_TURBO_API_FILE_NAME
from src.options.generate.templates_user import template_generate_microservice_name, template_generate_possible_packages, \
template_solve_code_issue, \
template_solve_dependency_issue, template_is_dependency_issue, template_generate_playground, \
@@ -70,7 +70,7 @@ metas:
content_raw, file_name, match_single_block=True
)
persist_file(content, os.path.join(destination_folder, file_name))
return content_raw
return content
def generate_microservice(
self,
@@ -82,10 +82,13 @@ metas:
MICROSERVICE_FOLDER_v1 = get_microservice_path(path, microservice_name, packages, num_approach, 1)
os.makedirs(MICROSERVICE_FOLDER_v1)
gpt_3_5_turbo_api_content = self.write_gpt_api_file(MICROSERVICE_FOLDER_v1)
microservice_content = self.generate_and_persist_file(
'Microservice',
template_generate_executor,
MICROSERVICE_FOLDER_v1,
code_files_wrapped=self.files_to_string({'gpt_3_5_turbo_api.py': gpt_3_5_turbo_api_content}),
microservice_name=microservice_name,
microservice_description=self.task_description,
test_description=self.test_description,
@@ -99,7 +102,7 @@ metas:
'Test Microservice',
template_generate_test,
MICROSERVICE_FOLDER_v1,
code_files_wrapped=self.files_to_string({'microservice.py': microservice_content}),
code_files_wrapped=self.files_to_string({'microservice.py': microservice_content, 'gpt_3_5_turbo_api.py': gpt_3_5_turbo_api_content,}),
microservice_name=microservice_name,
microservice_description=self.task_description,
test_description=self.test_description,
@@ -114,7 +117,8 @@ metas:
MICROSERVICE_FOLDER_v1,
code_files_wrapped=self.files_to_string({
'microservice.py': microservice_content,
'test_microservice.py': test_microservice_content
'test_microservice.py': test_microservice_content,
'gpt_3_5_turbo_api.py': gpt_3_5_turbo_api_content,
}),
file_name_purpose=REQUIREMENTS_FILE_NAME,
file_name=REQUIREMENTS_FILE_NAME,
@@ -128,7 +132,8 @@ metas:
code_files_wrapped=self.files_to_string({
'microservice.py': microservice_content,
'test_microservice.py': test_microservice_content,
'requirements.txt': requirements_content
'requirements.txt': requirements_content,
'gpt_3_5_turbo_api.py': gpt_3_5_turbo_api_content,
}),
file_name_purpose=DOCKER_FILE_NAME,
file_name=DOCKER_FILE_NAME,
@@ -136,6 +141,7 @@ metas:
)
self.write_config_yml(microservice_name, MICROSERVICE_FOLDER_v1)
print('\nFirst version of the microservice generated. Start iterating on it to make the tests pass...')
def generate_playground(self, microservice_name, microservice_path):
@@ -271,3 +277,11 @@ gptdeploy deploy --path {microservice_path}
conversation = self.gpt_session.get_conversation([])
error_summary = conversation.chat(template_summarize_error.format(error=error))
return error_summary
def write_gpt_api_file(self, MICROSERVICE_FOLDER_v1):
cur_dir = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(cur_dir, GPT_3_5_TURBO_API_FILE_NAME), 'r', encoding='utf-8') as file:
GPT_3_5_Turbo_API_content = file.read()
with open(os.path.join(MICROSERVICE_FOLDER_v1, GPT_3_5_TURBO_API_FILE_NAME), 'w', encoding='utf-8') as file:
file.write(GPT_3_5_Turbo_API_content)
return GPT_3_5_Turbo_API_content

View File

@@ -0,0 +1,24 @@
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
class GPT_3_5_Turbo_API:
def __init__(self, system: str = ''):
self.system = system
def __call__(self, prompt: str) -> str:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{
"role": 'system',
"content": self.system
}, {
"role": 'user',
"content": prompt
}]
)
return response.choices[0].text

View File

@@ -1,6 +1,27 @@
from src.constants import FLOW_URL_PLACEHOLDER
from src.options.generate.templates_user import not_allowed_docker_string, not_allowed_executor_string
gpt_example = '''
# gpt_3_5_turbo is a language model that can be used to generate text.
you can use it to generate text given a system definition and a user prompt.
The system definition defines the agent the user is talking to.
The user prompt is precise question and the expected answer format.
Example:
# in the executor init:
from gpt_3_5_turbo_api import GPT_3_5_Turbo_API
gpt = GPT_3_5_Turbo_API(
system=\'\'\'
You are a tv-reporter who is specialized in C-list celebrities.
When you get asked something like 'Who was having a date with <X>?', then you answer with a json like '{"dates": ["<Y>", "<Z>"]}'.
You must not answer something else - only the json.
\'\'\')
# in the executor endpoint function:
response_string = gpt(prompt)
response = json.loads(response_string) # response is a 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:

View File

@@ -25,7 +25,9 @@ The executor and the test must not use a pre-trained model unless it is explicit
The executor and the test must not train a model.
The executor and the test must not use any attribute of Document accept Document.text.
The executor and the test must not contain prototype or placeholder implementations.
The executor and the test must run in a docker container based on debian.'''
The executor and the test must run in a docker container based on debian.
The executor and the test must use gpt_3_5_turbo_api if the task requires a language model. Other language models are not allowed.'''
template_generate_microservice_name = PromptTemplate.from_template(
@@ -88,6 +90,8 @@ You must provide the complete file with the exact same syntax to wrap the code.'
template_generate_executor = PromptTemplate.from_template(
general_guidelines_string + '''
{code_files_wrapped}
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_description}'.
@@ -99,7 +103,7 @@ Have in mind that d.uri is never a path to a local file. It is always a url.
Your approach:
1. Identify the core challenge when implementing the executor.
2. Think about solutions for these challenges.
2. Think about solutions for these challenges including the usage of gpt via "from gpt_3_5_turbo_api import GPT_3_5_Turbo_API"
3. Decide for one of the solutions.
4. Write the code for the executor. Don't write code for the test.
''' + '\n' + template_code_wrapping_string
@@ -132,7 +136,13 @@ template_generate_requirements = PromptTemplate.from_template(
{code_files_wrapped}
Write the content of the requirements.txt file. Make sure to include pytest. Make sure that jina==3.14.1. Make sure that docarray==0.21.0.
Write the content of the requirements.txt file.
Make sure to include pytest.
Make sure to include openai>=0.26.0.
Make sure that jina==3.14.1.
Make sure that docarray==0.21.0.
You must not add gpt_3_5_turbo_api to the requirements.txt file.
All versions are fixed using ~=, ==, <, >, <=, >=. The package versions must not have conflicts.
''' + '\n' + template_code_wrapping_string
)
@@ -148,7 +158,8 @@ It is important to make sure that all libs are installed that are required by th
Usually libraries are installed with apt-get.
Be aware that the machine the docker container is running on does not have a GPU - only CPU.
Add the config.yml file to the Dockerfile.
Note that the Dockerfile only has access to the files: microservice.py, requirements.txt, config.yml, test_microservice.py.
Add the gpt_3_5_turbo_api.py file to the Dockerfile.
Note that the Dockerfile only has access to the files: microservice.py, requirements.txt, config.yml, test_microservice.py and gpt_3_5_turbo_api.py.
The base image of the Dockerfile is FROM jinaai/jina:3.14.1-py39-standard.
The entrypoint is ENTRYPOINT ["jina", "executor", "--uses", "config.yml"].
Make sure the all files are in the /workdir.