* 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>
185 lines
5.1 KiB
Python
185 lines
5.1 KiB
Python
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)
|