From eb65e9d408b610fff0bc1e6ca71528a27f8f65d3 Mon Sep 17 00:00:00 2001 From: Michael Ryaboy Date: Wed, 18 Jan 2023 18:38:06 -0800 Subject: [PATCH 01/16] actually works --- components/DropDownNew.tsx | 113 ++++++++ package-lock.json | 4 +- package.json | 2 +- pages/api/generate.ts | 172 +++++++++-- pages/tools/[tool].tsx | 350 +++++++++++++++++++++++ public/1-icon.png | Bin 0 -> 7929 bytes public/2-icon.png | Bin 0 -> 9564 bytes public/3-icon.png | Bin 0 -> 9643 bytes public/4-icon.png | Bin 0 -> 8663 bytes public/5-icon.png | Bin 0 -> 9688 bytes public/6-icon.png | Bin 0 -> 10420 bytes public/7-icon.png | Bin 0 -> 8160 bytes public/number_circle_one_icon_173687.png | Bin 0 -> 7929 bytes 13 files changed, 618 insertions(+), 23 deletions(-) create mode 100644 components/DropDownNew.tsx create mode 100644 pages/tools/[tool].tsx create mode 100644 public/1-icon.png create mode 100644 public/2-icon.png create mode 100644 public/3-icon.png create mode 100644 public/4-icon.png create mode 100644 public/5-icon.png create mode 100644 public/6-icon.png create mode 100644 public/7-icon.png create mode 100644 public/number_circle_one_icon_173687.png diff --git a/components/DropDownNew.tsx b/components/DropDownNew.tsx new file mode 100644 index 00000000..0a77c028 --- /dev/null +++ b/components/DropDownNew.tsx @@ -0,0 +1,113 @@ +// interface DropDownProps { +// value: string | undefined; +// options: { value: string; label: string }[] | undefined; +// onChange: (event: React.ChangeEvent) => void; +// } + +// export default function DropDownNew({ value, options, onChange }: DropDownProps) { +// return ( + +// +// ); +// }; + + +import { Menu, Transition } from "@headlessui/react"; +import { + CheckIcon, + ChevronDownIcon, + ChevronUpIcon, +} from "@heroicons/react/20/solid"; +import { Fragment } from "react"; + +function classNames(...classes: string[]) { + return classes.filter(Boolean).join(" "); +} + +// type vibeType = "Professional" | "Casual" | "Funny"; + +// interface DropDownProps { +// vibe: "Professional" | "Casual" | "Funny"; +// setVibe: (vibe: vibeType) => void; +// } + +// let vibes: vibeType[] = ["Professional", "Casual", "Funny"]; + +interface FormData { + [key: string]: string | undefined; + } + + +interface DropDownProps { + value: string | undefined; + name: string; + options: { value: string; label: string }[] | undefined; + formData: FormData + setFormData: (newFormData: FormData) => void; +} + +export default function DropDown({ value, name, options, formData, setFormData }: DropDownProps) { + return ( + +
+ + {value} + +
+ + + +
+ {options && options.map((option) => ( + + {({ active }) => ( + + )} + + ))} +
+
+
+
+ ); +} + + diff --git a/package-lock.json b/package-lock.json index 49f2d05f..95408f17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "twitter-bio-generator", + "name": "aitools", "lockfileVersion": 2, "requires": true, "packages": { @@ -11,7 +11,7 @@ "@tailwindcss/forms": "^0.5.3", "@vercel/analytics": "^0.1.8", "framer-motion": "^8.4.3", - "next": "latest", + "next": "^13.1.2", "react": "18.2.0", "react-dom": "18.2.0", "react-hook-form": "^7.42.0", diff --git a/package.json b/package.json index 8c2eebac..c84e3c34 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@tailwindcss/forms": "^0.5.3", "@vercel/analytics": "^0.1.8", "framer-motion": "^8.4.3", - "next": "latest", + "next": "^13.1.2", "react": "18.2.0", "react-dom": "18.2.0", "react-hook-form": "^7.42.0", diff --git a/pages/api/generate.ts b/pages/api/generate.ts index 7fa89eec..0ed039b4 100644 --- a/pages/api/generate.ts +++ b/pages/api/generate.ts @@ -1,3 +1,113 @@ +// import type { NextRequest } from "next/server"; + +// if (!process.env.OPENAI_API_KEY) { +// throw new Error("Missing env var from OpenAI"); +// } + +// export const config = { +// runtime: "edge", +// }; + +// const handler = async (req: NextRequest): Promise => { +// const { toolName, formData } = (await req.json()) as { +// toolName: string; +// formData: { [key: string]: string }; +// }; + +// if (!prompt) { +// return new Response("No prompt in the request", { status: 400 }); +// } + +// // const payload = { +// // model: "text-davinci-003", +// // prompt, +// // temperature: 0.7, +// // top_p: 1, +// // frequency_penalty: 0, +// // presence_penalty: 0, +// // max_tokens: 200, +// // stream: true, +// // n: 1, +// // }; + +// const payload = await fetch('http://localhost:5001/toolModel', { +// method: 'POST', +// headers: { +// 'Content-Type': 'application/json' +// }, +// body: JSON.stringify({ +// toolName: toolName, +// formValues: formData +// }) +// }); +// const response = await payload.json(); +// console.log("response", response) +// if (response.error) { +// throw new Error(response.error); +// } + +// const res = await fetch("https://api.openai.com/v1/completions", { +// headers: { +// "Content-Type": "application/json", +// Authorization: `Bearer ${process.env.OPENAI_API_KEY ?? ""}`, +// }, +// method: "POST", +// body: JSON.stringify(payload), +// }); + +// const data = res.body; + +// return new Response(data, { +// headers: { "Content-Type": "application/json; charset=utf-8" }, +// }); +// }; + +// export default handler; + + +// const handler = async (req: NextRequest): Promise => { +// req.json().then(async (body) => { +// const { toolName, formData } = body; + +// if (!toolName) { +// return new Response("No toolName in the request", { status: 400 }); +// } + +// await fetch('http://localhost:5001/toolModel', { +// method: 'POST', +// headers: { +// 'Content-Type': 'application/json' +// }, +// body: JSON.stringify({ +// toolName: toolName, +// formValues: formData +// }) +// }).then(payloadResponse => payloadResponse.json()) +// .then(async payload => { +// if (payload.error) { +// return new Response(payload.error, { status: 500 }); +// } + +// const res = await fetch("https://api.openai.com/v1/completions", { +// headers: { +// "Content-Type": "application/json", +// Authorization: `Bearer ${process.env.OPENAI_API_KEY ?? ""}`, +// }, +// method: "POST", +// body: JSON.stringify(payload), +// }); +// }) +// .catch((error) => { +// console.log(error) +// return new Response(error.message, { status: 500 }); +// }); +// }); +// }; + + +// export default handler; + + import type { NextRequest } from "next/server"; if (!process.env.OPENAI_API_KEY) { @@ -9,25 +119,45 @@ export const config = { }; const handler = async (req: NextRequest): Promise => { - const { prompt } = (await req.json()) as { - prompt?: string; - }; - - if (!prompt) { - return new Response("No prompt in the request", { status: 400 }); - } - - const payload = { - model: "text-davinci-003", - prompt, - temperature: 0.7, - top_p: 1, - frequency_penalty: 0, - presence_penalty: 0, - max_tokens: 200, - stream: true, - n: 1, - }; + const { toolName, formData } = (await req.json()) as { + toolName: string; + formData: { [key: string]: string }; +}; + + // if (!prompt) { + // return new Response("No prompt in the request", { status: 400 }); + // } + const prompt = "test" + + // const payload = { + // model: "text-davinci-003", + // prompt, + // temperature: 0.7, + // top_p: 1, + // frequency_penalty: 0, + // presence_penalty: 0, + // max_tokens: 200, + // stream: true, + // n: 1, + // }; + + + const payload = await fetch('http://localhost:5001/toolModel', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + toolName, + formData + }) + }) + .then(res => res.json()) + .then(data => data) + .catch(err => console.log(err)) + + console.log("payload is ", payload) + const res = await fetch("https://api.openai.com/v1/completions", { headers: { @@ -38,11 +168,13 @@ const handler = async (req: NextRequest): Promise => { body: JSON.stringify(payload), }); + const data = res.body; + // const data = "e" return new Response(data, { headers: { "Content-Type": "application/json; charset=utf-8" }, }); }; -export default handler; +export default handler; \ No newline at end of file diff --git a/pages/tools/[tool].tsx b/pages/tools/[tool].tsx new file mode 100644 index 00000000..72ca95d5 --- /dev/null +++ b/pages/tools/[tool].tsx @@ -0,0 +1,350 @@ +import { AnimatePresence, motion } from "framer-motion"; +import type { NextPage } from "next"; +import Head from "next/head"; +import Image from "next/image"; +import { SetStateAction, useState } from "react"; +import { GetStaticProps, GetStaticPaths } from "next"; +import { Toaster, toast } from "react-hot-toast"; +import DropDown from "../../components/DropDown"; +import DropDownNew from "../../components/DropDownNew"; +import Footer from "../../components/Footer"; +import Github from "../../components/GitHub"; +import Header from "../../components/Header"; +import LoadingDots from "../../components/LoadingDots"; +import ResizablePanel from "../../components/ResizablePanel"; + +interface Props { + schema: ToolSchema; +} + +interface FormData { + [key: string]: string | undefined; +} + +const Tool: NextPage = ({ schema }) => { + const [loading, setLoading] = useState(false); + const [bio, setBio] = useState(""); + const [vibe, setVibe] = useState<"Professional" | "Casual" | "Funny">( + "Professional" + ); + const [generatedBios, setGeneratedBios] = useState(""); + const initialFormData = schema.fields.reduce((formData, field) => { + formData[field.name] = field.type === "select" && field.options ? field.options[0].value : ""; + return formData; + }, {} as FormData); + + const [formData, setFormData] = useState(initialFormData); + + console.log("Streamed response: ", generatedBios); + + const prompt = + vibe === "Funny" + ? `Generate 2 funny twitter bios with no hashtags and clearly labeled "1." and "2.". Make sure there is a joke in there and it's a little ridiculous. Make sure each generated bio is at max 20 words and base it on this context: ${bio}${bio.slice(-1) === "." ? "" : "." + }` + : `Generate 2 ${vibe} twitter bios with no hashtags and clearly labeled "1." and "2.". Make sure each generated bio is at least 14 words and at max 20 words and base them on this context: ${bio}${bio.slice(-1) === "." ? "" : "." + }`; + + const handleSelect = (event: React.ChangeEvent, formDataName: string) => { + const { name, value } = event.target; + setFormData({ ...formData, [formDataName]: value }); + }; + + const handleChange = (event: React.ChangeEvent, formDataName: string) => { + const { value } = event.target; + setFormData({ ...formData, [formDataName]: value }); + }; + + // console.log("schema", schema); + console.log("formData", formData) + + const formFields = schema.fields.map((field, index) => { + let input; + if (field.type === "select") { + input = ( + <> +
+ {`${index+1} +

Select your vibe.

+
+
+ ) => setFormData(newFormData)} + /> + {/* handleSelect(event, field.name)} + /> */} +
+ + ); + } else { + input = ( + <> +
+ {`${index+1} +

+ Copy your current bio{" "} + + (or write a few sentences about yourself) + + . +

+
+