├── .env.example ├── .gitignore ├── .prettierignore ├── LICENSE.md ├── README.md ├── app ├── api │ └── chat │ │ └── route.ts ├── favicon.ico ├── globals.css ├── icons.tsx ├── layout.tsx ├── opengraph-image.png └── page.tsx ├── next.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── prettier.config.js ├── public └── shooketh.png ├── scripts ├── data.jsonl └── fine-tune.ts ├── tailwind.config.js └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # Get your OpenAI API key here: https://platform.openai.com/account/api-keys 2 | OPENAI_API_KEY= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | pnpm-lock.yaml 2 | yarn.lock 3 | node_modules 4 | .next -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Steven Tey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Shooketh – AI bot fine-tuned on Shakespeare's literary works. 3 |

Shooketh

4 |
5 | 6 |

7 | An AI bot built with the Vercel AI SDK and fine-tuned on Shakespeare's literary works. 8 |

9 | 10 |

11 | Introduction · 12 | Deploy Your Own · 13 | Fine-tuning the model · 14 | Tech Stack · 15 | Contributing · 16 | License 17 |

18 |
19 | 20 | ## Introduction 21 | 22 | Shooketh is an AI bot built with the [Vercel AI SDK](https://sdk.vercel.ai/docs) and [fine-tuned](https://openai.com/blog/gpt-3-5-turbo-fine-tuning-and-api-updates) on Shakespeare's literary works. [Read the guide](https://vercel.com/guides/fine-tuning-openai-nextjs) on how you can build your own bot like me. 23 | 24 | ## Deploy your own 25 | 26 | You can deploy your own version of Shooketh with 1-click: 27 | 28 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?demo-description=An+AI+bot+built+with+the+Vercel+AI+SDK%2C+OpenAI+gpt-3.5-turbo%2C+and+fine-tuned+on+Shakespeare%27s+literary+works&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F18AaW1vWGDC6nOWYkVsYKu%2Fd18b230765c3436a9a3b3fd62bc06867%2FCleanShot_2023-08-30_at_10.07.14_2x.png&demo-title=Shooketh+%E2%80%93%C2%A0AI+bot+fine-tuned+on+Shakespeare&demo-url=https%3A%2F%2Fvercel.fyi/shooketh%2F&env=OPENAI_API_KEY&envDescription=Get+your+OpenAI+API+Key+here%3A&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&from=templates&project-name=Shooketh+%E2%80%93%C2%A0AI+bot+fine-tuned+on+Shakespeare&repository-name=shooketh&repository-url=https%3A%2F%2Fgithub.com%2Fsteven-tey%2Fshooketh) 29 | 30 | ## Fine-tuning the model 31 | 32 | [Read the guide](https://vercel.com/guides/fine-tuning-openai-nextjs) on how you can fine-tune your own AI bot with OpenAI + the Vercel AI SDK. 33 | 34 | ## Tech Stack 35 | 36 | ChatH is built on the following stack: 37 | 38 | - [Next.js](https://nextjs.org/) – framework 39 | - [OpenAI Fine-tuning](https://openai.com/blog/gpt-3-5-turbo-fine-tuning-and-api-updates) - Fine-tuning 40 | - [Vercel AI SDK](https://sdk.vercel.ai/docs) – AI completions 41 | - [Vercel](https://vercel.com) – deployments 42 | - [TailwindCSS](https://tailwindcss.com/) – styles 43 | 44 | ## Contributing 45 | 46 | Here's how you can contribute: 47 | 48 | - [Open an issue](https://github.com/steven-tey/shooketh/issues) if you believe you've encountered a bug. 49 | - Make a [pull request](https://github.com/steven-tey/shooketh/pull) to add new features/make quality-of-life improvements/fix bugs. 50 | 51 | ## Author 52 | 53 | - Steven Tey ([@steventey](https://twitter.com/steventey)) 54 | 55 | ## License 56 | 57 | Licensed under the [MIT license](https://github.com/steven-tey/shooketh/blob/main/LICENSE.md). 58 | -------------------------------------------------------------------------------- /app/api/chat/route.ts: -------------------------------------------------------------------------------- 1 | // ./app/api/chat/route.ts 2 | import OpenAI from 'openai' 3 | import { OpenAIStream, StreamingTextResponse } from 'ai' 4 | 5 | // Create an OpenAI API client (that's edge friendly!) 6 | const openai = new OpenAI({ 7 | apiKey: process.env.OPENAI_API_KEY || '' 8 | }) 9 | 10 | // IMPORTANT! Set the runtime to edge 11 | export const runtime = 'edge' 12 | 13 | export async function POST(req: Request) { 14 | // Extract the `prompt` from the body of the request 15 | const { messages } = await req.json() 16 | 17 | // Ask OpenAI for a streaming chat completion given the prompt 18 | const response = await openai.chat.completions.create({ 19 | model: 'ft:gpt-3.5-turbo-0613:vercel::7tMs6IaF', 20 | stream: true, 21 | messages: [ 22 | { 23 | role: 'system', 24 | // Note: This has to be the same system prompt as the one 25 | // used in the fine-tuning dataset 26 | content: 27 | "Shooketh is an AI bot that answers in the style of Shakespeare's literary works." 28 | }, 29 | ...messages 30 | ] 31 | }) 32 | 33 | // Convert the response into a friendly text-stream 34 | const stream = OpenAIStream(response) 35 | // Respond with the stream 36 | return new StreamingTextResponse(stream) 37 | } 38 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steven-tey/shooketh/ed533ebab72e36923b4d187ed0ba015faaad12bc/app/favicon.ico -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /app/icons.tsx: -------------------------------------------------------------------------------- 1 | export const VercelIcon = () => { 2 | return ( 3 | 9 | 10 | 11 | ) 12 | } 13 | 14 | export const GithubIcon = () => { 15 | return ( 16 | 23 | 24 | 25 | ) 26 | } 27 | 28 | export const LoadingCircle = () => { 29 | return ( 30 | 46 | ) 47 | } 48 | 49 | export const SendIcon = ({ className }: { className?: string }) => { 50 | return ( 51 | 58 | 62 | 63 | ) 64 | } 65 | 66 | export const UserIcon = () => { 67 | return ( 68 | 79 | 80 | 81 | 82 | ) 83 | } 84 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './globals.css' 2 | import { Inter } from 'next/font/google' 3 | import { Analytics } from '@vercel/analytics/react'; 4 | 5 | const inter = Inter({ subsets: ['latin'] }) 6 | 7 | export const metadata = { 8 | title: "Shooketh – AI bot fine-tuned on Shakespeare's literary works", 9 | description: 10 | "Shooketh is an AI bot built with the Vercel AI SDK and fine-tuned on Shakespeare's literary works." 11 | } 12 | 13 | export default function RootLayout({ 14 | children 15 | }: { 16 | children: React.ReactNode 17 | }) { 18 | return ( 19 | 20 | 21 | {children} 22 | 23 | 24 | 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /app/opengraph-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steven-tey/shooketh/ed533ebab72e36923b4d187ed0ba015faaad12bc/app/opengraph-image.png -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useRef } from "react"; 4 | import { useChat } from "ai/react"; 5 | import clsx from "clsx"; 6 | import { 7 | VercelIcon, 8 | GithubIcon, 9 | LoadingCircle, 10 | SendIcon, 11 | UserIcon, 12 | } from "./icons"; 13 | import Textarea from "react-textarea-autosize"; 14 | import Image from "next/image"; 15 | 16 | const examples = [ 17 | "To be or not to be", 18 | "All the world's a stage", 19 | "What is the meaning of life?", 20 | ]; 21 | 22 | export default function Chat() { 23 | const formRef = useRef(null); 24 | const inputRef = useRef(null); 25 | 26 | const { messages, input, setInput, handleSubmit, isLoading } = useChat({ 27 | onResponse: (response) => { 28 | if (response.status === 429) { 29 | window.alert("You have reached your request limit for the day."); 30 | return; 31 | } 32 | }, 33 | }); 34 | 35 | const disabled = isLoading || input.length === 0; 36 | 37 | return ( 38 |
39 |
40 | 45 | 46 | 47 | 52 | 53 | 54 |
55 | {messages.length > 0 ? ( 56 | messages.map((message, i) => ( 57 |
64 |
65 |
72 | {message.role === "user" ? ( 73 | 74 | ) : ( 75 | Shakespeare 81 | )} 82 |
83 |
84 | {message.content} 85 |
86 |
87 |
88 | )) 89 | ) : ( 90 |
91 |
92 | Shooketh 99 |

100 | Hi, I'm Shooketh! 101 |

102 |

103 | I'm an AI bot built with the{" "} 104 | 110 | Vercel AI SDK 111 | {" "} 112 | and{" "} 113 | 119 | fine-tuned 120 | {" "} 121 | on Shakespeare's literary works. 122 |
123 | 129 | Read the guide 130 | {" "} 131 | on how you can build your own bot like me. 132 |

133 |
134 |
135 | {examples.map((example, i) => ( 136 | 146 | ))} 147 |
148 |
149 | )} 150 |
151 |
156 |