feat(frontend): generate scripts in the flow and app builders (#1886)

* feat: add inline code gen flow

* feat(frontend): add script gen to flow and app builders

* fix(backend): allow all users to use openai

* Fix build

* Fix build

* Fix build

---------

Co-authored-by: Faton Ramadani <faton.ramadani14@gmail.com>
This commit is contained in:
HugoCasa
2023-07-18 12:55:35 +02:00
committed by GitHub
parent 7baaa0b713
commit 2416805629
28 changed files with 1483 additions and 117 deletions
-2
View File
@@ -27,8 +27,6 @@ async fn proxy(
Path((w_id, openai_path)): Path<(String, String)>,
body: Bytes,
) -> impl IntoResponse {
tracing::info!("reached openai endpoint");
let mut tx = db.begin().await?;
let settings = sqlx::query_as!(
OpenAIKey,
-2
View File
@@ -707,9 +707,7 @@ async fn edit_openai_key(
async fn exists_openai_key(
Extension(db): Extension<DB>,
Path(w_id): Path<String>,
Authed { is_admin, username, .. }: Authed,
) -> JsonResult<bool> {
require_admin(is_admin, &username)?;
let mut tx = db.begin().await?;
let openai_key = sqlx::query_scalar!(
+98
View File
@@ -46,6 +46,7 @@
},
"devDependencies": {
"@floating-ui/core": "^1.3.1",
"@modyfi/vite-plugin-yaml": "^1.0.4",
"@playwright/test": "^1.34.3",
"@rgossiaux/svelte-headlessui": "^1.0.2",
"@sveltejs/adapter-static": "^2.0.2",
@@ -703,6 +704,20 @@
"integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==",
"dev": true
},
"node_modules/@modyfi/vite-plugin-yaml": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@modyfi/vite-plugin-yaml/-/vite-plugin-yaml-1.0.4.tgz",
"integrity": "sha512-qkT0KiR3AQQRfUvDzLv4+1rYAzXj+QmGhAbyUd0Ordf9xynK76i758lk5GiEfxuQxbvdqDaJ9oXkH/KacbSjQQ==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "5.0.2",
"js-yaml": "4.1.0",
"tosource": "2.0.0-alpha.3"
},
"peerDependencies": {
"vite": "^2.6.0 || ^3.0.0 || ^4.0.0"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -792,6 +807,28 @@
"svelte": "^3.44.0"
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
"integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@sveltejs/adapter-static": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-2.0.2.tgz",
@@ -1219,6 +1256,12 @@
"@types/d3-selection": "*"
}
},
"node_modules/@types/estree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==",
"dev": true
},
"node_modules/@types/geojson": {
"version": "7946.0.10",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
@@ -3383,6 +3426,12 @@
"node": ">=4.0"
}
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -7844,6 +7893,15 @@
"node": ">=8.0"
}
},
"node_modules/tosource": {
"version": "2.0.0-alpha.3",
"resolved": "https://registry.npmjs.org/tosource/-/tosource-2.0.0-alpha.3.tgz",
"integrity": "sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/totalist": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz",
@@ -8861,6 +8919,17 @@
"integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==",
"dev": true
},
"@modyfi/vite-plugin-yaml": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@modyfi/vite-plugin-yaml/-/vite-plugin-yaml-1.0.4.tgz",
"integrity": "sha512-qkT0KiR3AQQRfUvDzLv4+1rYAzXj+QmGhAbyUd0Ordf9xynK76i758lk5GiEfxuQxbvdqDaJ9oXkH/KacbSjQQ==",
"dev": true,
"requires": {
"@rollup/pluginutils": "5.0.2",
"js-yaml": "4.1.0",
"tosource": "2.0.0-alpha.3"
}
},
"@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -8927,6 +8996,17 @@
"dev": true,
"requires": {}
},
"@rollup/pluginutils": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
"integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
"dev": true,
"requires": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
}
},
"@sveltejs/adapter-static": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-2.0.2.tgz",
@@ -9291,6 +9371,12 @@
"@types/d3-selection": "*"
}
},
"@types/estree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==",
"dev": true
},
"@types/geojson": {
"version": "7946.0.10",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
@@ -10812,6 +10898,12 @@
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
"estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -14040,6 +14132,12 @@
"is-number": "^7.0.0"
}
},
"tosource": {
"version": "2.0.0-alpha.3",
"resolved": "https://registry.npmjs.org/tosource/-/tosource-2.0.0-alpha.3.tgz",
"integrity": "sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug==",
"dev": true
},
"totalist": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz",
+1
View File
@@ -17,6 +17,7 @@
},
"devDependencies": {
"@floating-ui/core": "^1.3.1",
"@modyfi/vite-plugin-yaml": "^1.0.4",
"@playwright/test": "^1.34.3",
"@rgossiaux/svelte-headlessui": "^1.0.2",
"@sveltejs/adapter-static": "^2.0.2",
+14 -13
View File
@@ -10,7 +10,6 @@
import 'monaco-editor/esm/vs/basic-languages/typescript/typescript.contribution'
import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution'
import 'monaco-editor/esm/vs/language/typescript/monaco.contribution'
import { Breakpoints } from './apps/gridUtils'
meditor.defineTheme('myTheme', {
base: 'vs',
@@ -23,17 +22,19 @@
})
meditor.setTheme('myTheme')
const SIDE_BY_SIDE_MIN_WIDTH = 650
export let automaticLayout = true
export let fixedOverflowWidgets = true
export let sideBySideMinWidth = Breakpoints.lg
let diffEditor: meditor.IStandaloneDiffEditor
let diffEditor: meditor.IStandaloneDiffEditor | undefined
let diffDivEl: HTMLDivElement | null = null
let editorWidth: number = SIDE_BY_SIDE_MIN_WIDTH
function loadDiffEditor() {
diffEditor = meditor.createDiffEditor(diffDivEl!, {
automaticLayout,
renderSideBySide: window.innerWidth >= sideBySideMinWidth,
renderSideBySide: editorWidth >= SIDE_BY_SIDE_MIN_WIDTH,
domReadOnly: true,
readOnly: true,
minimap: {
@@ -51,9 +52,9 @@
export function setDiff(
original: string,
modified: string,
lang: 'typescript' | 'python' | 'go' | 'shell' | 'sql' | 'graphql'
lang: 'typescript' | 'python' | 'go' | 'shell' | 'sql' | 'graphql' | 'javascript'
): void {
diffEditor.setModel({
diffEditor?.setModel({
original: meditor.createModel(original, lang),
modified: meditor.createModel(modified, lang)
})
@@ -64,11 +65,11 @@
}
export function getOriginal(): string {
return diffEditor.getModel()?.original.getValue() ?? ''
return diffEditor?.getModel()?.original.getValue() ?? ''
}
export function getModified(): string {
return diffEditor.getModel()?.modified.getValue() ?? ''
return diffEditor?.getModel()?.modified.getValue() ?? ''
}
export function show(): void {
@@ -78,20 +79,20 @@
diffDivEl?.classList.add('hidden')
}
function onResize() {
diffEditor.updateOptions({ renderSideBySide: window.innerWidth >= sideBySideMinWidth })
function onWidthChange(editorWidth: number) {
diffEditor?.updateOptions({ renderSideBySide: editorWidth >= SIDE_BY_SIDE_MIN_WIDTH })
}
$: onWidthChange(editorWidth)
onMount(() => {
if (BROWSER) {
loadDiffEditor()
window.addEventListener('resize', onResize)
return () => {
diffEditor?.dispose()
window.removeEventListener('resize', onResize)
}
}
})
</script>
<div bind:this={diffDivEl} class="{$$props.class} editor" />
<div bind:this={diffDivEl} class="{$$props.class} editor" bind:clientWidth={editorWidth} />
@@ -1,6 +1,6 @@
<script lang="ts">
import type { Schema } from '$lib/common'
import { ScriptService, type FlowModule, type Job } from '$lib/gen'
import { ScriptService, type FlowModule, type Job, Script } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import { getModifierKey } from '$lib/utils'
import { getScriptByPath } from '$lib/scripts'
@@ -17,10 +17,15 @@
import { Kbd } from './common'
import { evalValue } from './flows/utils'
import type { PickableProperties } from './flows/previousResults'
import type DiffEditor from './DiffEditor.svelte'
import type Editor from './Editor.svelte'
export let mod: FlowModule
export let schema: Schema
export let pickableProperties: PickableProperties | undefined
export let lang: Script.language
export let editor: Editor
export let diffEditor: DiffEditor
const { flowStore, flowStateStore, testStepStore } =
getContext<FlowEditorContext>('FlowEditorContext')
@@ -112,7 +117,14 @@
<Pane size={50} minSize={10} class="text-sm text-gray-600">
{#if testJob != undefined && 'result' in testJob && testJob.result != undefined}
<pre class="overflow-x-auto break-words relative h-full px-2">
<DisplayResult workspaceId={testJob?.workspace_id} jobId={testJob?.id} result={testJob.result} />
<DisplayResult
workspaceId={testJob?.workspace_id}
jobId={testJob?.id}
result={testJob.result}
{editor}
{diffEditor}
{lang}
/>
</pre>
{:else}
<div class="p-2">
@@ -303,7 +303,7 @@
bind:this={diffEditor}
automaticLayout
{fixedOverflowWidgets}
class="hidden flex-1 h-full !overflow-visible"
class="hidden h-full"
/>
{/key}
</div>
@@ -8,7 +8,8 @@
KeyCode,
KeyMod,
Uri as mUri,
languages
languages,
type IRange
} from 'monaco-editor/esm/vs/editor/editor.api'
import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution'
import 'monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution'
@@ -100,6 +101,35 @@
editor?.focus()
}
export function getSelectedLines(): string | undefined {
if (editor) {
const selection = editor.getSelection()
if (selection) {
const range: IRange = {
startLineNumber: selection.startLineNumber,
startColumn: 1,
endLineNumber: selection.endLineNumber + 1,
endColumn: 1
}
return editor.getModel()?.getValueInRange(range)
}
}
}
export function onDidChangeCursorSelection(f: (e: meditor.ICursorSelectionChangedEvent) => void) {
if (editor) {
return editor.onDidChangeCursorSelection(f)
}
}
export function show(): void {
divEl?.classList.remove('hidden')
}
export function hide(): void {
divEl?.classList.add('hidden')
}
let width = 0
async function loadMonaco() {
model = meditor.createModel(code, lang, mUri.parse(uri))
@@ -18,6 +18,8 @@
import { buildExtraLib } from '../../utils'
import RunButton from './RunButton.svelte'
import { scriptLangToEditorLang } from '$lib/scripts'
import ScriptGen from '$lib/components/codeGen/ScriptGen.svelte'
import DiffEditor from '$lib/components/DiffEditor.svelte'
let inlineScriptEditorDrawer: InlineScriptEditorDrawer
@@ -33,7 +35,8 @@
const { runnableComponents, stateId, worldStore, state, appPath, app } =
getContext<AppViewerContext>('AppViewerContext')
let editor: Editor
export let editor: Editor | undefined = undefined
let diffEditor: DiffEditor
let simpleEditor: SimpleEditor
let validCode = true
@@ -152,6 +155,13 @@
<Badge color="red" baseClass="!text-2xs">Invalid</Badge>
{/if}
<ScriptGen
lang={inlineScript?.language}
editor={inlineScript?.language === 'frontend' ? simpleEditor : editor}
{diffEditor}
inlineScript
/>
<Button
title="Delete"
size="xs"
@@ -252,6 +262,13 @@
}}
/>
{/if}
<DiffEditor
bind:this={diffEditor}
class="hidden h-full"
automaticLayout
fixedOverflowWidgets
/>
</div>
</div>
{/if}
@@ -13,12 +13,14 @@
import type DiffEditor from '../DiffEditor.svelte'
import { scriptLangToEditorLang } from '$lib/scripts'
import type { Selection } from 'monaco-editor/esm/vs/editor/editor.api'
import type SimpleEditor from '../SimpleEditor.svelte'
// props
export let iconOnly: boolean = false
export let lang: SupportedLanguage
export let editor: Editor | undefined
export let lang: SupportedLanguage | 'frontend'
export let editor: Editor | SimpleEditor | undefined
export let diffEditor: DiffEditor | undefined
export let inlineScript = false
// state
let funcDesc: string = ''
@@ -73,7 +75,7 @@
generatedCode = ''
}
async function checkIfOpenAIAvailable(lang: SupportedLanguage) {
async function checkIfOpenAIAvailable(lang: SupportedLanguage | 'frontend') {
try {
const exists = $existsOpenaiKeyStore
openAIAvailable = exists && SUPPORTED_LANGUAGES.has(lang)
@@ -84,7 +86,11 @@
}
function showDiff() {
diffEditor?.setDiff(editor?.getCode() || '', generatedCode, scriptLangToEditorLang(lang))
diffEditor?.setDiff(
editor?.getCode() || '',
generatedCode,
lang === 'frontend' ? 'javascript' : scriptLangToEditorLang(lang)
)
diffEditor?.show()
editor?.hide()
}
@@ -114,32 +120,63 @@
{#if openAIAvailable}
{#if generatedCode}
<div class="flex gap-1 px-2">
<Button
title="Discard generated code"
btnClasses="!font-medium"
size="xs"
color="red"
spacingSize="xs2"
on:click={rejectDiff}
variant="contained"
startIcon={{ icon: faClose }}
{iconOnly}
>
Discard
</Button><Button
title="Accept generated code"
btnClasses="!font-medium"
size="xs"
color="green"
spacingSize="xs2"
on:click={acceptDiff}
startIcon={{ icon: faCheck }}
{iconOnly}
>
Accept
</Button>
</div>
{#if inlineScript}
<div class="flex gap-1">
<Button
title="Discard generated code"
btnClasses="!font-medium px-2 w-7"
size="xs"
color="red"
on:click={rejectDiff}
variant="contained"
>
<Icon data={faClose} />
</Button><Button
title="Accept generated code"
btnClasses="!font-medium px-2 w-7"
size="xs"
color="green"
on:click={acceptDiff}
>
<Icon data={faCheck} /></Button
>
</div>
{:else}
<div class="flex gap-1 px-2">
<Button
title="Discard generated code"
btnClasses="!font-medium px-2"
size="xs"
color="red"
on:click={rejectDiff}
variant="contained"
startIcon={{ icon: faClose }}
{iconOnly}
>
Discard
</Button><Button
title="Accept generated code"
btnClasses="!font-medium px-2"
size="xs"
color="green"
on:click={acceptDiff}
startIcon={{ icon: faCheck }}
{iconOnly}
>
Accept
</Button>
</div>
{/if}
{:else if inlineScript}
<Button
size="lg"
bind:element={button}
color="light"
btnClasses="!px-2 !bg-gray-100 hover:!bg-gray-200"
loading={genLoading}
>
<Icon scale={0.8} data={faMagicWandSparkles} />
</Button>
{:else}
<Button
title="Generate code from prompt"
@@ -155,7 +192,7 @@
{isEdit ? 'AI Edit' : 'AI Gen'}
</Button>
{/if}
{#if !generatedCode}
{#if !generatedCode && !genLoading}
<Popup
ref={button}
options={{ placement: 'top-start' }}
+34 -62
View File
@@ -6,6 +6,8 @@ import { existsOpenaiKeyStore, workspaceStore } from '$lib/stores'
import { formatResourceTypes } from './utils'
import { scriptLangToEditorLang } from '$lib/scripts'
import { EDIT_CONFIG, FIX_CONFIG, GEN_CONFIG } from './prompts'
const WARNING_MSG =
'WARNING: this code was generated by OpenAI, it might not be accurate. Use at your own risk.'
@@ -17,64 +19,25 @@ const COMMENT_TYPES = {
[Script.language.POSTGRESQL]: '--',
[Script.language.MYSQL]: '--',
[Script.language.NATIVETS]: '//',
[Script.language.BUN]: '//'
[Script.language.BUN]: '//',
frontend: '//'
}
const PROMPTS = {
[Script.language
.PYTHON3]: `Write a function in python called "main". The function should {description}. Specify the parameter types. Do not call the main function.
You have access to the following resource types, if you need them, you have to define the TypedDict exactly as specified (class name has to be IN LOWERCASE) and add them as parameters: {resourceTypes}
If the TypedDict name conflicts with the imported object, rename the imported object NOT THE TYPE.`,
[Script.language
.DENO]: `Write a function in typescript called "main". The function should {description}. Specify the parameter types. You are in a Deno environment. You can import deno libraries or you can also import npm libraries like that: "import ... from "npm:{package}";". Export the "main" function like this: "export function main(...)". Do not call the main function.
You have access to the following resource types, if you need them, you have to define the type exactly as specified and add them as parameters: {resourceTypes}
If the type name conflicts with the imported object, rename the imported object NOT THE TYPE.`,
[Script.language.GO]:
'Write a function in go called "main". The function should {description}. Import the packages you need. The return type of the function has to be ({return_type}, error). The file package has to be "inner".',
[Script.language.BASH]:
'Write bash code that should {description}. Do not include "#!/bin/bash". Arguments are always string and can only be obtained with "var1="$1"", "var2="$2"", etc... You do not need to check if the arguments are present.',
[Script.language.POSTGRESQL]:
'Write SQL code for a PostgreSQL that should {description}. Arguments can be obtained directly in the statement with $1::{type}, $2::{type}, etc... Name the parameters by adding comments before the command like that: -- $1 name1 (one per row, do not include the type)',
[Script.language.MYSQL]:
'Write SQL code for MySQL that should {description}. Arguments can be obtained directly in the statement with ?. Name the parameters by adding comments before the command like that: -- ? name1 ({type}) (one per row)',
[Script.language
.NATIVETS]: `Write a function in typescript called "main". The function should {description}. Specify the parameter types. You should use fetch and are not allowed to import any libraries. Export the "main" function like this: "export function main(...)". Do not call the main function.
You have access to the following resource types, if you need them, you have to define the type exactly as specified and add them as parameters: {resourceTypes}
If the type name conflicts with the imported object, rename the imported object NOT THE TYPE.`,
[Script.language
.BUN]: `Write a function in typescript called "main". The function should {description}. Specify the parameter types. You are in a Node.js environment. You can import npm libraries. Export the "main" function like this: "export function main(...)". Do not call the main function.
You have access to the following resource types, if you need them, you have to define the type exactly as specified and add them as parameters: {resourceTypes}
If the type name conflicts with the imported object, rename the imported object NOT THE TYPE.`
}
function scriptLangToEnvironment(lang: Script.language) {
function scriptLangToEnvironment(lang: Script.language | 'frontend') {
if (lang === Script.language.DENO) {
return 'typescript in a deno running environment'
} else if (lang === Script.language.BUN) {
return 'typescript in a node.js running environment'
} else if (lang === Script.language.NATIVETS) {
return 'typescript where you should use fetch and are not allowed to import any libraries'
} else if (lang === 'frontend') {
return 'client-side javascript'
} else {
return lang
}
}
const SYSTEM_PROMPT =
'You write code as queried by the user. Only output code. Wrap the code like that: ```language\n{code}\n```. Put any explanation directly in the code as comments.'
const EDIT_SYSTEM_PROMPT =
'You edit the code as queried by the user. Only output code. Wrap the code like that: ```language\n{code}\n```. Put any explanation directly in the code as comments.'
const EDIT_PROMPT =
"Here's my environement: {environment}\nHere's my code: ```{lang}\n{code}\n```\nMy instructions: {description}"
const FIX_PROMPT =
"Here's my environement: {environment}\nHere's my code: ```{lang}\n{code}\n```\nI get the following error: {error}\nFix it for me."
const FIX_SYSTEM_PROMPT =
'You fix the code shared by the user. Only output code. Wrap the code like that: ```language\n{code}\n```. Put explanations directly in the code as comments.'
export const SUPPORTED_LANGUAGES = new Set(Object.keys(PROMPTS))
export const SUPPORTED_LANGUAGES = new Set(Object.keys(GEN_CONFIG.prompts))
let workspace: string | undefined = undefined
@@ -91,11 +54,10 @@ workspaceStore.subscribe(async (value) => {
})
interface BaseOptions {
language: Script.language
language: Script.language | 'frontend'
}
interface ScriptGenerationOptions extends BaseOptions {
language: Script.language
description: string
}
@@ -122,18 +84,16 @@ export async function generateScript(scriptOptions: ScriptGenerationOptions): Pr
}
})
let prompt = PROMPTS[scriptOptions.language].replace('{description}', scriptOptions.description)
let prompt = GEN_CONFIG.prompts[scriptOptions.language].prompt.replace(
'{description}',
scriptOptions.description
)
if (
[Script.language.DENO, Script.language.BUN, Script.language.NATIVETS].includes(
scriptOptions.language
)
) {
if (['deno', 'bun', 'nativets'].includes(scriptOptions.language)) {
const resourceTypes = await ResourceService.listResourceType({ workspace })
const resourceTypesText = formatResourceTypes(resourceTypes, 'typescript')
prompt = prompt.replace('{resourceTypes}', resourceTypesText)
} else if (scriptOptions.language == Script.language.PYTHON3) {
} else if (scriptOptions.language === 'python3') {
const resourceTypes = await ResourceService.listResourceType({ workspace })
const resourceTypesText = formatResourceTypes(resourceTypes, 'python3')
prompt = prompt.replace('{resourceTypes}', resourceTypesText)
@@ -145,7 +105,7 @@ export async function generateScript(scriptOptions: ScriptGenerationOptions): Pr
messages: [
{
role: 'system',
content: SYSTEM_PROMPT
content: GEN_CONFIG.system
},
{
role: 'user',
@@ -200,18 +160,24 @@ export async function editScript(scriptOptions: EditScriptOptions): Promise<stri
}
})
let prompt = EDIT_PROMPT.replace('{lang}', scriptLangToEditorLang(scriptOptions.language))
let prompt = EDIT_CONFIG.prompt
.replace(
'{lang}',
scriptOptions.language === 'frontend'
? 'javascript'
: scriptLangToEditorLang(scriptOptions.language)
)
.replace('{code}', scriptOptions.selectedCode)
.replace('{description}', scriptOptions.description)
.replace('{environment}', scriptLangToEnvironment(scriptOptions.language))
const completion = await openai.chat.completions.create({
model: 'gpt-4',
max_tokens: 512,
max_tokens: 2048,
messages: [
{
role: 'system',
content: EDIT_SYSTEM_PROMPT
content: EDIT_CONFIG.system
},
{
role: 'user',
@@ -252,18 +218,24 @@ export async function fixScript(scriptOptions: FixScriptOpions) {
}
})
let prompt = FIX_PROMPT.replace('{lang}', scriptLangToEditorLang(scriptOptions.language))
let prompt = FIX_CONFIG.prompt
.replace(
'{lang}',
scriptOptions.language === 'frontend'
? 'javascript'
: scriptLangToEditorLang(scriptOptions.language)
)
.replace('{code}', scriptOptions.code)
.replace('{error}', scriptOptions.error)
.replace('{environment}', scriptLangToEnvironment(scriptOptions.language))
const completion = await openai.chat.completions.create({
model: 'gpt-4',
max_tokens: 512,
max_tokens: 2048,
messages: [
{
role: 'system',
content: FIX_SYSTEM_PROMPT
content: FIX_CONFIG.system
},
{
role: 'user',
@@ -0,0 +1,13 @@
system: |-
You write code as queried by the user. Only output code. Wrap the code like that:
```language
{code}
```
Put explanations directly in the code as comments.
prompt: |-
Here's my environement: {environment}
Here's my code:
```{lang}
{code}
```
My instructions: {description}
@@ -0,0 +1,14 @@
system: |-
You fix the code shared by the user. Only output code. Wrap the code like that:
```language
{code}
```
Put explanations directly in the code as comments.
prompt: |-
Here's my environement: {environment}
Here's my code:
```{lang}
{code}
```
I get the following error: {error}
Fix it for me.
@@ -0,0 +1,49 @@
system: |-
You write code as queried by the user. Only output code. Wrap the code like that:
```language
{code}
```
Put explanations directly in the code as comments.
prompts:
python3:
prompt: |-
Write a function in python called "main". The function should {description}. Specify the parameter types. Do not call the main function.
You have access to the following resource types, if you need them, you have to define the TypedDict exactly as specified (class name has to be IN LOWERCASE) and add them as parameters: {resourceTypes}
If the TypedDict name conflicts with the imported object, rename the imported object NOT THE TYPE.
deno:
prompt: |-
Write a function in typescript called "main". The function should {description}. Specify the parameter types. You are in a Deno environment. You can import deno libraries or you can also import npm libraries like that: "import ... from "npm:{package}";". Export the "main" function like this: "export async function main(...)". Do not call the main function.
You have access to the following resource types, if you need them, you have to define the type exactly as specified and add them as parameters: {resourceTypes}
If the type name conflicts with the imported object, rename the imported object NOT THE TYPE.
go:
prompt: |-
Write a function in go called "main". The function should {description}. Import the packages you need. The return type of the function has to be ({return_type}, error). The file package has to be "inner".
bash:
prompt: |-
Write bash code that should {description}. Do not include "#!/bin/bash". Arguments are always string and can only be obtained with "var1="$1"", "var2="$2"", etc... You do not need to check if the arguments are present.
postgresql:
prompt: |-
Write SQL code for a PostgreSQL that should {description}. Arguments can be obtained directly in the statement with $1::{type}, $2::{type}, etc... Name the parameters by adding comments before the command like that: -- $1 name1 (one per row, do not include the type)
mysql:
prompt: |-
Write SQL code for MySQL that should {description}. Arguments can be obtained directly in the statement with ?. Name the parameters by adding comments before the command like that: -- ? name1 ({type}) (one per row)
nativets:
prompt: |-
Write a function in typescript called "main". The function should {description}. Specify the parameter types. You should use fetch and are not allowed to import any libraries. Export the "main" function like this: "export async function main(...)". Do not call the main function.
You have access to the following resource types, if you need them, you have to define the type exactly as specified and add them as parameters: {resourceTypes}
If the type name conflicts with the imported object, rename the imported object NOT THE TYPE.
bun:
prompt: |-
Write a function in typescript called "main". The function should {description}. Specify the parameter types. You are in a Node.js environment. You can import npm libraries. Export the "main" function like this: "export async function main(...)". Do not call the main function.
You have access to the following resource types, if you need them, you have to define the type exactly as specified and add them as parameters: {resourceTypes}
If the type name conflicts with the imported object, rename the imported object NOT THE TYPE.
frontend:
prompt: |-
Write client-side javascript code that should {description}. You have access to a few helpers:
You can access the context object with the ctx global variable.
The app state is a store that can be used to store data. You can access and update the state object with the state global variable like this: state.foo = 'bar'
You can use the goto function to navigate to a specific URL: goto(path: string, newTab?: boolean)
Use the setTab function to manually set the tab of a Tab component: setTab(id: string, index: string)
Use the recompute function to recompute a component: recompute(id: string)
Use the getAgGrid function to get the ag-grid instance of a table: getAgGrid(id: string)
The setValue function is meant to set or force the value of a component: setValue(id: string, value: any).
@@ -0,0 +1,25 @@
import editObj from './edit.yaml'
import fixObj from './fix.yaml'
import genObj from './gen.yaml'
interface CommonConfig {
system: string
prompt: string
}
interface GenConfig {
system: string
prompts: {
[key: string]: {
prompt: string
}
}
}
const EDIT_CONFIG = editObj as CommonConfig
const FIX_CONFIG = fixObj as CommonConfig
const GEN_CONFIG = genObj as GenConfig
export { EDIT_CONFIG, FIX_CONFIG, GEN_CONFIG }
@@ -32,6 +32,7 @@
import FlowModuleMock from './FlowModuleMock.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import { SecondsInput } from '$lib/components/common'
import DiffEditor from '$lib/components/DiffEditor.svelte'
const { selectedId, previewArgs, flowStateStore, flowStore, saveDraft } =
getContext<FlowEditorContext>('FlowEditorContext')
@@ -43,6 +44,7 @@
export let previousModule: FlowModule | undefined
let editor: Editor
let diffEditor: DiffEditor
let modulePreview: ModulePreview
let websocketAlive = {
pyright: false,
@@ -174,6 +176,7 @@
<EditorBar
{validCode}
{editor}
{diffEditor}
lang={flowModule.value['language'] ?? 'deno'}
{websocketAlive}
iconOnly={width < 850}
@@ -222,6 +225,12 @@
}}
fixedOverflowWidgets={true}
/>
<DiffEditor
bind:this={diffEditor}
automaticLayout
fixedOverflowWidgets
class="hidden h-full"
/>
{/key}
{:else if flowModule.value.type === 'script'}
<div class="border-t border-gray-200">
@@ -260,6 +269,9 @@
pickableProperties={stepPropPicker.pickableProperties}
bind:this={modulePreview}
mod={flowModule}
{editor}
{diffEditor}
lang={flowModule.value['language'] ?? 'deno'}
schema={$flowStateStore[$selectedId]?.schema ?? {}}
/>
{:else if selected === 'advanced'}
@@ -56,6 +56,7 @@
selectAll,
pointer
}
let d3Zoom = determineD3Instance(
boundary,
d3,
@@ -89,6 +90,7 @@
d3.select(`#zoom_in_${canvasId}`).on('click', function () {
try {
// @ts-ignore
d3Zoom.scaleBy(nodes.transition().duration(250), 1.4)
} catch (e) {
console.log('error', e)
@@ -96,6 +98,7 @@
})
d3.select(`#zoom_out_${canvasId}`).on('click', function () {
try {
// @ts-ignore
d3Zoom.scaleBy(nodes.transition().duration(250), 0.714)
} catch (e) {
console.log('error', e)
+2 -1
View File
@@ -35,7 +35,8 @@
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"types": ["@modyfi/vite-plugin-yaml/modules"]
},
"include": ["src/**/*.js", "src/**/*.ts", "src/**/*.d.ts", "src/**/*.svelte"],
"extends": "./.svelte-kit/tsconfig.json"
+2 -1
View File
@@ -1,6 +1,7 @@
import { sveltekit } from '@sveltejs/kit/vite'
import { readFileSync } from 'fs'
import { fileURLToPath } from 'url'
import ViteYaml from '@modyfi/vite-plugin-yaml'
const file = fileURLToPath(new URL('package.json', import.meta.url))
const json = readFileSync(file, 'utf8')
@@ -31,7 +32,7 @@ const config = {
preview: {
port: 3000
},
plugins: [sveltekit()],
plugins: [sveltekit(), ViteYaml()],
define: {
__pkg__: version
},
+3
View File
@@ -0,0 +1,3 @@
.venv
.env
**/__pycache__
+42
View File
@@ -0,0 +1,42 @@
# Test sample queries of the AI feature
## Setup
Create a virtual environment `python -m venv .venv`, activate it `source .venv/bin/activate` and install the requirements `pip install -r requirements.txt`. Put your `OPENAI_API_KEY` in `.env`.
## Run
Run the script `python src/gen_samples.py` and check the results in `sample_answers.yaml`.
## Add queries
You can add more queries in `sample_queries.yaml`. There are three types of queries:
### Generate code from a prompt
```yaml
- type: gen
description: hello world
lang: python3
```
### Modifiy code according to a prompt
```yaml
- type: edit
description: comment
lang: python3
code: |-
print("hello world")
```
### Fix code given an error
```yaml
- type: fix
lang: python3
code: |-
def main():
return 3 / 0
error: division by zero
```
+4
View File
@@ -0,0 +1,4 @@
openai==0.27.8
python-dotenv==1.0.0
pyyaml==6.0
tqdm==4.65.0
+312
View File
@@ -0,0 +1,312 @@
- answer: |-
```python
import psycopg2
from typing import TypedDict
class postgresql(TypedDict):
host: str
port: int
user: str
dbname: str
sslmode: str
password: str
def main(postgres_config: postgresql):
# Connect to the PostgreSQL server
conn = psycopg2.connect(
host=postgres_config['host'],
port=postgres_config['port'],
user=postgres_config['user'],
password=postgres_config['password'],
dbname=postgres_config['dbname'],
sslmode=postgres_config['sslmode']
)
# Create a cursor object
cur = conn.cursor()
# Execute a query
cur.execute("SELECT * FROM orders")
# Fetch all the rows
rows = cur.fetchall()
# Print all the rows
for row in rows:
print(row)
# Close the cursor and connection
cur.close()
conn.close()
```
description: Connect to postgres and list the rows in the orders table
lang: python3
type: gen
- answer: |-
Sure, here's the corrected code. I've added a check to ensure that the number passed to the function is not zero to prevent a division by zero error.
```python
def main(num: int) -> int:
if num == 0:
raise ValueError("The input number should not be zero") # raise an error if num is zero
return 3 / num
```
This code will raise a ValueError if the input number is zero.
code: |-
def main(num: int) -> int:
return 3 / num
error: division by zero
lang: python3
type: fix
- answer: |-
Sure, here's your code with comments:
```python
# This is a Python function that takes an integer as input.
def main(num: int) -> int:
# The function divides the input number by 16.
# The result of this division is then returned by the function.
return num / 16
```
code: |-
def main(num: int) -> int:
return num / 16
description: Comment my code
lang: python3
type: edit
- answer: |-
```go
package inner
import (
"errors"
"fmt"
)
// Function to divide a number by 16
func main(num float64) (float64, error) {
if num == 0 {
return 0, errors.New("Division by zero is not allowed")
}
result := num / 16
return result, nil
}
```
In this code, we define a function called `main` that takes a float64 number as an input. It then divides the number by 16 and returns the result. If the number is 0, it returns an error.
description: Divide a number by 16
lang: go
type: gen
- answer: |-
```typescript
import { toWords } from "npm:number-to-words"; // Importing the "number-to-words" npm package.
export async function main(number: number): Promise<string> {
// Convert the number to words.
const words = toWords(number);
// Return the words.
return words;
}
```
In this function, we are using the "number-to-words" npm package to convert a number to words. The function takes a number as an argument and returns a Promise that resolves to a string. The string is the word representation of the number.
description: Convert a number to a word
lang: deno
type: gen
- answer: |-
```typescript
// Importing the required libraries
import { Client } from "npm:https://deno.land/x/postgres@v0.13.0/mod.ts";
type Postgresql = {
host: string,
port: number,
user: string,
dbname: string,
sslmode: string,
password: string
}
// Exporting the main function
export async function main(postgres: Postgresql) {
// Creating a new client with the provided configuration
const client = new Client({
hostname: postgres.host,
port: postgres.port,
user: postgres.user,
password: postgres.password,
database: postgres.dbname,
tls: {
enforce: postgres.sslmode === "require",
},
});
// Connecting to the database
await client.connect();
// Querying the "orders" table
const result = await client.queryArray("SELECT * FROM orders;");
// Closing the connection
await client.end();
// Returning the rows of the "orders" table
return result.rows;
}
```
In this function, we first import the `Client` class from the `postgres` library. We then define a function `main` that takes a `Postgresql` object as argument. This object contains the information needed to connect to the PostgreSQL database.
In the function, we first create a new `Client` instance with the provided configuration. We then connect to the database, query the "orders" table, and close the connection. Finally, we return the rows of the "orders" table.
description: Connect to postgres and list the rows in the orders table
lang: deno
type: gen
- answer: |-
```typescript
// Importing the npm library "number-to-words" to convert numbers to words
import * as numberToWords from 'number-to-words';
type Airtable = {
apiKey: string
}
type AirtableTable = {
baseId: string,
tableName: string
}
// ... all the other types here ...
type Toggl = {
token: string
}
// Defining the main function
export async function main(number: number): Promise<string> {
// Converting the number to a word using the numberToWords library
const word = numberToWords.toWords(number);
// Returning the word
return word;
}
```
Note: This code assumes that you have installed the `number-to-words` npm package in your project. If not, you can install it by running `npm install --save number-to-words` in your project directory.
description: Convert a number to a word
lang: bun
type: gen
- answer: |-
```sql
-- $1::text as name
-- $2::text as email
INSERT INTO users (name, email)
VALUES ($1::text, $2::text);
```
description: Insert an email and a name in the users table
lang: postgresql
type: gen
- answer: |-
```sql
-- ? email (VARCHAR)
-- ? name (VARCHAR)
INSERT INTO users (email, name) VALUES (?, ?)
```
description: Insert an email and a name in the users table
lang: mysql
type: gen
- answer: |-
```bash
var1="$1" # Get the first argument
result=$(echo "scale=2; $var1 / 16" | bc) # Divide the number by 16 using bc command. Scale is used to get the decimal values up to 2 places
echo $result # Print the result
```
description: Divide a number by 16
lang: bash
type: gen
- answer: |-
Here is a simple Dockerfile for a Python application. It assumes that your application is using Flask and Gunicorn, but you can replace these with your actual dependencies.
```dockerfile
# Use an official Python runtime as a parent image
FROM python:3.7-slim
# Set the working directory in the container to /app
WORKDIR /app
# Add the current directory contents into the container at /app
ADD . /app
# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["gunicorn", "app:app"]
```
This Dockerfile does the following:
- `FROM python:3.7-slim` starts with the 3.7-slim Python image.
- `WORKDIR /app` sets the working directory inside the container to /app.
- `ADD . /app` copies the current directory (i.e., the directory containing the Dockerfile) into the container at /app.
- `RUN pip install --trusted-host pypi.python.org -r requirements.txt` installs the Python dependencies.
- `EXPOSE 80` makes port 80 available outside the container.
- `ENV NAME World` sets an environment variable.
- `CMD ["gunicorn", "app:app"]` runs your application with Gunicorn when the container starts.
description: Write a docker image for a python app
lang: bash
type: gen
- answer: |-
```typescript
// Define the Github type
type Github = {
token: string
}
// Define the main function
export async function main(github: Github, owner: string, repo: string): Promise<number> {
// Define the url for the Github API
const url = `https://api.github.com/repos/${owner}/${repo}`;
// Define the headers for the request
const headers = {
'Authorization': `token ${github.token}`,
'Accept': 'application/vnd.github.v3+json'
};
// Fetch the data from the Github API
const response = await fetch(url, { headers });
// Check if the response is ok
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Parse the response as JSON
const data = await response.json();
// Return the number of stars
return data.stargazers_count;
}
```
This function takes a Github object and the owner and repo as strings. It constructs the URL for the Github API and defines the headers for the request. It then fetches the data from the Github API and checks if the response is ok. If it is, it parses the response as JSON and returns the number of stars. If the response is not ok, it throws an error.
description: Query the github api and return the number of stars of a repo
lang: nativets
type: gen
- answer: |-
```javascript
// Access the email from the context object
let email = ctx.email;
// Set the value of the input with id 'my_field' to the email
setValue('my_field', email);
```
description: set the value of the input with id 'my_field' to the context variable
email
lang: frontend
type: gen
+45
View File
@@ -0,0 +1,45 @@
- lang: python3
type: gen
description: Connect to postgres and list the rows in the orders table
- lang: python3
type: fix
code: |-
def main(num: int) -> int:
return 3 / num
error: division by zero
- lang: python3
type: edit
code: |-
def main(num: int) -> int:
return num / 16
description: Comment my code
- lang: go
type: gen
description: Divide a number by 16
- lang: deno
type: gen
description: Convert a number to a word
- lang: deno
type: gen
description: Connect to postgres and list the rows in the orders table
- lang: bun
type: gen
description: Convert a number to a word
- lang: postgresql
type: gen
description: Insert an email and a name in the users table
- lang: mysql
type: gen
description: Insert an email and a name in the users table
- lang: bash
type: gen
description: Divide a number by 16
- lang: bash
type: gen
description: Write a docker image for a python app
- lang: nativets
type: gen
description: Query the github api and return the number of stars of a repo
- lang: frontend
type: gen
description: set the value of the input with id 'my_field' to the context variable email
View File
+184
View File
@@ -0,0 +1,184 @@
import argparse
import yaml
from dotenv import load_dotenv
from tqdm import tqdm
from resources import RESOURCE_TYPES
load_dotenv()
import openai
import re
from typing import TypedDict, Tuple
class Literal(str):
pass
def literal_presenter(dumper, data):
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
yaml.add_representer(Literal, literal_presenter)
class GenPrompt(TypedDict):
prompt: str
class GenConfig(TypedDict):
prompts: dict[str, GenPrompt]
system: str
class CommonConfig(TypedDict):
system: str
prompt: str
class Query(TypedDict):
description: str
type: str
lang: str
code: str
error: str
def scriptLangToCodeLang(lang: str):
if lang in ["deno", "bun", "nativets"]:
return "typescript"
elif lang in ["postgresql", "mysql"]:
return "sql"
elif lang == "python3":
return "python"
elif lang == "bash":
return "shell"
elif lang == "frontend":
return "javascript"
else:
return lang
def scriptLangToEnvironment(lang: str):
if lang == "deno":
return "typescript in a deno running environment"
elif lang == "bun":
return "typescript in a node.js running environment"
elif lang == "nativets":
return "typescript where you should use fetch and are not allowed to import any libraries"
elif lang == "frontend":
return "client-side javascript"
else:
return lang
def get_prompts(prompts_path: str) -> Tuple[GenConfig, CommonConfig, CommonConfig]:
GEN_CONFIG = None
EDIT_CONFIG = None
FIX_CONFIG = None
with open(prompts_path + "/gen.yaml") as f:
GEN_CONFIG = yaml.safe_load(f)
with open(prompts_path + "/edit.yaml") as f:
EDIT_CONFIG = yaml.safe_load(f)
with open(prompts_path + "/fix.yaml") as f:
FIX_CONFIG = yaml.safe_load(f)
return GEN_CONFIG, EDIT_CONFIG, FIX_CONFIG
def get_queries(queries_path: str) -> list[Query]:
with open(queries_path) as f:
return yaml.safe_load(f)
def prepare_prompt(
query: Query,
GEN_CONFIG: GenConfig,
EDIT_CONFIG: CommonConfig,
FIX_CONFIG: CommonConfig,
):
system = ""
prompt = ""
if query["type"] == "gen":
system = GEN_CONFIG["system"]
prompt = GEN_CONFIG["prompts"][query["lang"]]["prompt"]
prompt = prompt.replace("{description}", query["description"])
if query["lang"] in ["deno", "bun", "nativets"]:
prompt = prompt.replace("{resourceTypes}", RESOURCE_TYPES["typescript"])
elif query["lang"] in ["python3"]:
prompt = prompt.replace("{resourceTypes}", RESOURCE_TYPES["python"])
elif query["type"] == "edit":
system = EDIT_CONFIG["system"]
prompt = EDIT_CONFIG["prompt"]
lang = scriptLangToCodeLang(query["lang"])
environment = scriptLangToEnvironment(query["lang"])
prompt = (
prompt.replace("{description}", query["description"])
.replace("{lang}", lang)
.replace("{environment}", environment)
.replace("{code}", query["code"])
)
elif query["type"] == "fix":
system = FIX_CONFIG["system"]
prompt = FIX_CONFIG["prompt"]
lang = scriptLangToCodeLang(query["lang"])
environment = scriptLangToEnvironment(query["lang"])
prompt = (
prompt.replace("{lang}", lang)
.replace("{environment}", environment)
.replace("{error}", query["error"])
.replace("{code}", query["code"])
)
return system, prompt
def format_answer(answer: str):
return re.sub("[^\\S\n]+\n", "\n", answer).replace("\t", " ")
def gen_samples(queries_path: str, answers_path: str, prompts_path: str):
GEN_CONFIG, EDIT_CONFIG, FIX_CONFIG = get_prompts(prompts_path)
queries = get_queries(queries_path)
answers = []
for query in tqdm(queries):
system, prompt = prepare_prompt(query, GEN_CONFIG, EDIT_CONFIG, FIX_CONFIG)
chat_completion = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": prompt},
],
temperature=0.5,
max_tokens=2048,
)
answer = {
**query,
"answer": Literal(format_answer(chat_completion["choices"][0]["message"]["content"])), # type: ignore
}
if "code" in query:
answer["code"] = Literal(query["code"])
answers.append(answer)
with open(answers_path, "w") as f:
yaml.dump(answers, f)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Process some integers.")
parser.add_argument("--queries_path", type=str, default="./sample_queries.yaml")
parser.add_argument("--answers_path", type=str, default="./sample_answers.yaml")
parser.add_argument(
"--prompts_path",
type=str,
default="../frontend/src/lib/components/codeGen/prompts",
)
args = parser.parse_args()
gen_samples(args.queries_path, args.answers_path, args.prompts_path)
+493
View File
@@ -0,0 +1,493 @@
RESOURCE_TYPES = {
"typescript": """type Airtable = {
apiKey: string
}
type AirtableTable = {
baseId: string,
tableName: string
}
type Appwrite = {
key: string,
project: string,
endpoint: string,
self_signed: boolean
}
type Aws = {
region: string,
awsAccessKeyId: string,
awsSecretAccessKey: string
}
type Azure = {
azureClientId: string,
azureTenantId: string,
azureClientSecret: string
}
type Clickhouse = {
host: string,
password: string,
username: string
}
type CMyResourceType = {
name: string
}
type CSolarFlar = {
a: number,
b: number,
c: boolean,
d: string,
e: any,
f: any[],
g: any,
h: any
}
type Datadog = {
apiKey: string,
appKey: string,
apiBase: string
}
type DiscordBotConfiguration = {
public_key: string,
application_id: string
}
type DiscordWebhook = {
webhook_url: string
}
type Dynatrace = {
accessToken: string,
environmentId: string,
environmentUrl: string
}
type Faunadb = {
region: string,
secret: string
}
type Firebase = {
appId: string,
apiKey: string,
projectId: string,
authDomain: string,
measurementId: string,
storageBucket: string,
messagingSenderId: string
}
type Funkwhale = {
token: string,
baseUrl: string
}
type Gcal = {
token: string
}
type GcpServiceAccount = {
type: string,
auth_uri: string,
client_id: string,
token_uri: string,
project_id: string,
private_key: string,
client_email: string,
private_key_id: string,
client_x509_cert_url: string,
auth_provider_x509_cert_url: string
}
type Gdrive = {
token: string
}
type Github = {
token: string
}
type Gitlab = {
token: string,
baseUrl: string
}
type Gmail = {
token: string
}
type Gsheets = {
token: string
}
type Hubspot = {
token: string
}
type Ipinfo = {
token: string
}
type Linkding = {
token: string,
baseUrl: string
}
type Linkedin = {
token: string
}
type Mailchimp = {
server: string,
api_key: string
}
type Mailgun = {
api_key: string
}
type Mastodon = {
token: string,
baseUrl: string
}
type Matrix = {
token: string,
baseUrl: string
}
type Mongodb = {
db: string,
tls: boolean,
servers: any,
credential: any
}
type MongodbRest = {
api_key: string,
endpoint: string
}
type Mysql = {
host: string,
port: number,
user: string,
database: string,
password: string
}
type Nocodb = {
table: string,
apiUrl: string,
xc_token: string,
workspace: string
}
type Notion = {
token: string
}
type Openai = {
api_key: string,
organization_id: string
}
type Pinecone = {
apiKey: string,
environment: string
}
type Postgresql = {
host: string,
port: number,
user: string,
dbname: string,
sslmode: string,
password: string
}
type Rss = {
url: string
}
type S3 = {
port: number,
bucket: string,
region: string,
useSSL: boolean,
endPoint: string,
accessKey: string,
pathStyle: boolean,
secretKey: string
}
type Sendgrid = {
token: string
}
type Slack = {
token: string
}
type Smtp = {
host: string,
port: number,
user: string,
password: string
}
type Square = {
token: string
}
type Stripe = {
token: string
}
type Supabase = {
key: string,
url: string
}
type Surrealdb = {
url: string,
token: string
}
type Telegram = {
token: string
}
type Toggl = {
token: string
}
""",
"python": """class airtable(TypedDict):
apiKey: str
class airtable_table(TypedDict):
baseId: str
tableName: str
class appwrite(TypedDict):
key: str
project: str
endpoint: str
self_signed: bool
class aws(TypedDict):
region: str
awsAccessKeyId: str
awsSecretAccessKey: str
class azure(TypedDict):
azureClientId: str
azureTenantId: str
azureClientSecret: str
class clickhouse(TypedDict):
host: str
password: str
username: str
class c_my_resource_type(TypedDict):
name: str
class c_solar_flar(TypedDict):
a: int
b: float
c: bool
d: str
e: dict
f: list
g: dict
h: dict
class datadog(TypedDict):
apiKey: str
appKey: str
apiBase: str
class discord_bot_configuration(TypedDict):
public_key: str
application_id: str
class discord_webhook(TypedDict):
webhook_url: str
class dynatrace(TypedDict):
accessToken: str
environmentId: str
environmentUrl: str
class faunadb(TypedDict):
region: str
secret: str
class firebase(TypedDict):
appId: str
apiKey: str
projectId: str
authDomain: str
measurementId: str
storageBucket: str
messagingSenderId: str
class funkwhale(TypedDict):
token: str
baseUrl: str
class gcal(TypedDict):
token: str
class gcp_service_account(TypedDict):
type: str
auth_uri: str
client_id: str
token_uri: str
project_id: str
private_key: str
client_email: str
private_key_id: str
client_x509_cert_url: str
auth_provider_x509_cert_url: str
class gdrive(TypedDict):
token: str
class github(TypedDict):
token: str
class gitlab(TypedDict):
token: str
baseUrl: str
class gmail(TypedDict):
token: str
class gsheets(TypedDict):
token: str
class hubspot(TypedDict):
token: str
class ipinfo(TypedDict):
token: str
class linkding(TypedDict):
token: str
baseUrl: str
class linkedin(TypedDict):
token: str
class mailchimp(TypedDict):
server: str
api_key: str
class mailgun(TypedDict):
api_key: str
class mastodon(TypedDict):
token: str
baseUrl: str
class matrix(TypedDict):
token: str
baseUrl: str
class mongodb(TypedDict):
db: str
tls: bool
servers: dict
credential: dict
class mongodb_rest(TypedDict):
api_key: str
endpoint: str
class mysql(TypedDict):
host: str
port: float
user: str
database: str
password: str
class nocodb(TypedDict):
table: str
apiUrl: str
xc_token: str
workspace: str
class notion(TypedDict):
token: str
class openai(TypedDict):
api_key: str
organization_id: str
class pinecone(TypedDict):
apiKey: str
environment: str
class postgresql(TypedDict):
host: str
port: int
user: str
dbname: str
sslmode: str
password: str
class rss(TypedDict):
url: str
class s3(TypedDict):
port: float
bucket: str
region: str
useSSL: bool
endPoint: str
accessKey: str
pathStyle: bool
secretKey: str
class sendgrid(TypedDict):
token: str
class slack(TypedDict):
token: str
class smtp(TypedDict):
host: str
port: int
user: str
password: str
class square(TypedDict):
token: str
class stripe(TypedDict):
token: str
class supabase(TypedDict):
key: str
url: str
class surrealdb(TypedDict):
url: str
token: str
class telegram(TypedDict):
token: str
class toggl(TypedDict):
token: str
""",
}
+1
View File
@@ -0,0 +1 @@
3.10.4