diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index d2ead0a..4f63d1e 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -7,33 +7,27 @@ import { nanoid } from '@/lib/utils' export const runtime = 'edge' -const configuration = new Configuration({ - apiKey: process.env.OPENAI_API_KEY -}) - -const openai = new OpenAIApi(configuration) - -if (!process.env.OPENAI_API_KEY) { - throw new Error('Missing env var from OpenAI') -} - export async function POST(req: Request) { + const json = await req.json() + const { messages, previewToken } = json const session = await auth() - if (session == null) { - return new Response('Unauthorized', { status: 401 }) + + if (process.env.VERCEL_ENV !== 'preview') { + if (session == null) { + return new Response('Unauthorized', { status: 401 }) + } } - const json = await req.json() - const { messages } = json + const configuration = new Configuration({ + apiKey: previewToken || process.env.OPENAI_API_KEY + }) + + const openai = new OpenAIApi(configuration) const res = await openai.createChatCompletion({ model: 'gpt-3.5-turbo', messages, temperature: 0.7, - top_p: 1, - frequency_penalty: 1, - max_tokens: 500, - n: 1, stream: true }) diff --git a/components/chat.tsx b/components/chat.tsx index bc2ffda..b3a8394 100644 --- a/components/chat.tsx +++ b/components/chat.tsx @@ -7,22 +7,41 @@ import { ChatList } from '@/components/chat-list' import { ChatPanel } from '@/components/chat-panel' import { EmptyScreen } from '@/components/empty-screen' import { ChatScrollAnchor } from '@/components/chat-scroll-anchor' +import { useLocalStorage } from '@/lib/hooks/use-local-storage' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog' +import { useState } from 'react' +import { Button } from './ui/button' +import { Input } from './ui/input' +const IS_PREVIEW = process.env.VERCEL_ENV === 'preview' export interface ChatProps extends React.ComponentProps<'div'> { initialMessages?: Message[] id?: string } export function Chat({ id, initialMessages, className }: ChatProps) { + const [previewToken, setPreviewToken] = useLocalStorage( + 'ai-token', + null + ) + const [previewTokenDialog, setPreviewTokenDialog] = useState(IS_PREVIEW) + const [previewTokenInput, setPreviewTokenInput] = useState(previewToken ?? '') const { messages, append, reload, stop, isLoading, input, setInput } = useChat({ initialMessages, id, body: { - id + id, + previewToken } }) - return ( <>
@@ -45,6 +64,42 @@ export function Chat({ id, initialMessages, className }: ChatProps) { input={input} setInput={setInput} /> + + + + + Enter your OpenAI Key + + If you have not obtained your OpenAI API key, you can do so by{' '} + + signing up + {' '} + on the OpenAI website. This is only necessary for preview + environments so that the open source community can test the app. + The token will be saved to your browser's local storage under + the name ai-token. + + + setPreviewTokenInput(e.target.value)} + /> + + + + + ) } diff --git a/lib/hooks/use-local-storage.ts b/lib/hooks/use-local-storage.ts new file mode 100644 index 0000000..19f6b7e --- /dev/null +++ b/lib/hooks/use-local-storage.ts @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react' + +export const useLocalStorage = ( + key: string, + initialValue: T +): [T, (value: T) => void] => { + const [storedValue, setStoredValue] = useState(initialValue) + + useEffect(() => { + // Retrieve from localStorage + const item = window.localStorage.getItem(key) + if (item) { + setStoredValue(JSON.parse(item)) + } + }, [key]) + + const setValue = (value: T) => { + // Save state + setStoredValue(value) + // Save to localStorage + window.localStorage.setItem(key, JSON.stringify(value)) + } + return [storedValue, setValue] +}