Merge 8ff1bf1976 into 9f732c4f5d
This commit is contained in:
commit
7a3661ab0f
98
backend/prompts.py
Normal file
98
backend/prompts.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
from typing import List, Union
|
||||||
|
|
||||||
|
from openai.types.chat import ChatCompletionMessageParam, ChatCompletionContentPartParam
|
||||||
|
|
||||||
|
from imported_code_prompts import (
|
||||||
|
IMPORTED_CODE_BOOTSTRAP_SYSTEM_PROMPT,
|
||||||
|
IMPORTED_CODE_IONIC_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
IMPORTED_CODE_REACT_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
IMPORTED_CODE_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
)
|
||||||
|
from screenshot_system_prompts import (
|
||||||
|
BOOTSTRAP_SYSTEM_PROMPT,
|
||||||
|
IONIC_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
REACT_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
TAILWIND_SYSTEM_PROMPT,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
USER_PROMPT = """
|
||||||
|
Generate code for a web page that looks exactly like these images. Seperate them into different sectionsif multiple images are provided.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def assemble_imported_code_prompt(
|
||||||
|
code: str, stack: str, result_image_data_url: Union[str, None] = None
|
||||||
|
) -> List[ChatCompletionMessageParam]:
|
||||||
|
system_content = IMPORTED_CODE_TAILWIND_SYSTEM_PROMPT
|
||||||
|
if stack == "html_tailwind":
|
||||||
|
system_content = IMPORTED_CODE_TAILWIND_SYSTEM_PROMPT
|
||||||
|
elif stack == "react_tailwind":
|
||||||
|
system_content = IMPORTED_CODE_REACT_TAILWIND_SYSTEM_PROMPT
|
||||||
|
elif stack == "bootstrap":
|
||||||
|
system_content = IMPORTED_CODE_BOOTSTRAP_SYSTEM_PROMPT
|
||||||
|
elif stack == "ionic_tailwind":
|
||||||
|
system_content = IMPORTED_CODE_IONIC_TAILWIND_SYSTEM_PROMPT
|
||||||
|
else:
|
||||||
|
raise Exception("Code config is not one of available options")
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": system_content,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "Here is the code of the app: " + code,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
# TODO: Use result_image_data_url
|
||||||
|
|
||||||
|
|
||||||
|
def assemble_prompt(
|
||||||
|
images: List[str],
|
||||||
|
generated_code_config: str,
|
||||||
|
result_image_data_url: Union[str, None] = None,
|
||||||
|
) -> List[ChatCompletionMessageParam]:
|
||||||
|
# Set the system prompt based on the output settings
|
||||||
|
system_content = TAILWIND_SYSTEM_PROMPT
|
||||||
|
if generated_code_config == "html_tailwind":
|
||||||
|
system_content = TAILWIND_SYSTEM_PROMPT
|
||||||
|
elif generated_code_config == "react_tailwind":
|
||||||
|
system_content = REACT_TAILWIND_SYSTEM_PROMPT
|
||||||
|
elif generated_code_config == "bootstrap":
|
||||||
|
system_content = BOOTSTRAP_SYSTEM_PROMPT
|
||||||
|
elif generated_code_config == "ionic_tailwind":
|
||||||
|
system_content = IONIC_TAILWIND_SYSTEM_PROMPT
|
||||||
|
else:
|
||||||
|
raise Exception("Code config is not one of available options")
|
||||||
|
|
||||||
|
user_content: List[ChatCompletionContentPartParam]= []
|
||||||
|
for image_data_url in images:
|
||||||
|
user_content.append(
|
||||||
|
{
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": {"url": image_data_url, "detail": "high"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if result_image_data_url:
|
||||||
|
user_content.insert(1, {
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": {"url": result_image_data_url, "detail": "high"},
|
||||||
|
})
|
||||||
|
|
||||||
|
user_content.append(
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": USER_PROMPT,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return [
|
||||||
|
{"role": "system", "content": system_content},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": user_content,
|
||||||
|
},
|
||||||
|
]
|
||||||
@ -200,10 +200,12 @@ async def stream_code(websocket: WebSocket):
|
|||||||
try:
|
try:
|
||||||
if params.get("resultImage") and params["resultImage"]:
|
if params.get("resultImage") and params["resultImage"]:
|
||||||
prompt_messages = assemble_prompt(
|
prompt_messages = assemble_prompt(
|
||||||
params["image"], valid_stack, params["resultImage"]
|
params["images"], generated_code_config, params["resultImage"]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
prompt_messages = assemble_prompt(params["image"], valid_stack)
|
prompt_messages = assemble_prompt(
|
||||||
|
params["images"], generated_code_config
|
||||||
|
)
|
||||||
except:
|
except:
|
||||||
await websocket.send_json(
|
await websocket.send_json(
|
||||||
{
|
{
|
||||||
|
|||||||
@ -288,8 +288,7 @@ function App() {
|
|||||||
doGenerateCode(
|
doGenerateCode(
|
||||||
{
|
{
|
||||||
generationType: "create",
|
generationType: "create",
|
||||||
image: referenceImages[0],
|
images: referenceImages,
|
||||||
inputMode,
|
|
||||||
},
|
},
|
||||||
currentVersion
|
currentVersion
|
||||||
);
|
);
|
||||||
@ -340,8 +339,7 @@ function App() {
|
|||||||
doGenerateCode(
|
doGenerateCode(
|
||||||
{
|
{
|
||||||
generationType: "update",
|
generationType: "update",
|
||||||
inputMode,
|
images: referenceImages,
|
||||||
image: referenceImages[0],
|
|
||||||
resultImage: resultImage,
|
resultImage: resultImage,
|
||||||
history: updatedHistory,
|
history: updatedHistory,
|
||||||
isImportedFromCode,
|
isImportedFromCode,
|
||||||
@ -352,8 +350,7 @@ function App() {
|
|||||||
doGenerateCode(
|
doGenerateCode(
|
||||||
{
|
{
|
||||||
generationType: "update",
|
generationType: "update",
|
||||||
inputMode,
|
images: referenceImages,
|
||||||
image: referenceImages[0],
|
|
||||||
history: updatedHistory,
|
history: updatedHistory,
|
||||||
isImportedFromCode,
|
isImportedFromCode,
|
||||||
},
|
},
|
||||||
@ -556,37 +553,34 @@ function App() {
|
|||||||
|
|
||||||
{/* Reference image display */}
|
{/* Reference image display */}
|
||||||
<div className="flex gap-x-2 mt-2">
|
<div className="flex gap-x-2 mt-2">
|
||||||
{referenceImages.length > 0 && (
|
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
"scanning relative": appState === AppState.CODING,
|
"scanning relative": appState === AppState.CODING,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{inputMode === "image" && (
|
{referenceImages.length > 1 ? (
|
||||||
|
<div className="grid grid-cols-2 gap-2">
|
||||||
|
{referenceImages.map((image, i) => (
|
||||||
|
<img
|
||||||
|
className="border max-h-40 w-full h-full object-contain border-gray-200 rounded-md"
|
||||||
|
src={image}
|
||||||
|
alt={`Reference image: ${i}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
<img
|
<img
|
||||||
className="w-[340px] border border-gray-200 rounded-md"
|
className="w-[340px] border border-gray-200 rounded-md"
|
||||||
src={referenceImages[0]}
|
src={referenceImages[0]}
|
||||||
alt="Reference"
|
alt-="Reference Image"
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{inputMode === "video" && (
|
|
||||||
<video
|
|
||||||
muted
|
|
||||||
autoPlay
|
|
||||||
loop
|
|
||||||
className="w-[340px] border border-gray-200 rounded-md"
|
|
||||||
src={referenceImages[0]}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-400 uppercase text-sm text-center mt-1">
|
<div className="text-gray-400 uppercase text-sm text-center mt-1">
|
||||||
{inputMode === "video"
|
Original Screenshot{referenceImages.length > 1 ? "s" : ""}
|
||||||
? "Original Video"
|
|
||||||
: "Original Screenshot"}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
<div className="bg-gray-400 px-4 py-2 rounded text-sm hidden">
|
<div className="bg-gray-400 px-4 py-2 rounded text-sm hidden">
|
||||||
<h2 className="text-lg mb-4 border-b border-gray-800">
|
<h2 className="text-lg mb-4 border-b border-gray-800">
|
||||||
Console
|
Console
|
||||||
|
|||||||
@ -69,8 +69,7 @@ function ImageUpload({ setReferenceImages }: Props) {
|
|||||||
|
|
||||||
const { getRootProps, getInputProps, isFocused, isDragAccept, isDragReject } =
|
const { getRootProps, getInputProps, isFocused, isDragAccept, isDragReject } =
|
||||||
useDropzone({
|
useDropzone({
|
||||||
maxFiles: 1,
|
maxSize: 1024 * 1024 * 5, // 5 MB
|
||||||
maxSize: 1024 * 1024 * 20, // 20 MB
|
|
||||||
accept: {
|
accept: {
|
||||||
// Image formats
|
// Image formats
|
||||||
"image/png": [".png"],
|
"image/png": [".png"],
|
||||||
|
|||||||
@ -33,8 +33,7 @@ export enum ScreenRecorderState {
|
|||||||
|
|
||||||
export interface CodeGenerationParams {
|
export interface CodeGenerationParams {
|
||||||
generationType: "create" | "update";
|
generationType: "create" | "update";
|
||||||
inputMode: "image" | "video";
|
images: string[];
|
||||||
image: string;
|
|
||||||
resultImage?: string;
|
resultImage?: string;
|
||||||
history?: string[];
|
history?: string[];
|
||||||
isImportedFromCode?: boolean;
|
isImportedFromCode?: boolean;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user