Implement preview token for oss (#23)
This commit is contained in:
commit
36a1861d01
3 changed files with 93 additions and 20 deletions
|
|
@ -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
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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<string | null>(
|
||||
'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 (
|
||||
<>
|
||||
<div className={cn('pb-[200px] pt-4 md:pt-10', className)}>
|
||||
|
|
@ -45,6 +64,42 @@ export function Chat({ id, initialMessages, className }: ChatProps) {
|
|||
input={input}
|
||||
setInput={setInput}
|
||||
/>
|
||||
|
||||
<Dialog open={previewTokenDialog} onOpenChange={setPreviewTokenDialog}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Enter your OpenAI Key</DialogTitle>
|
||||
<DialogDescription>
|
||||
If you have not obtained your OpenAI API key, you can do so by{' '}
|
||||
<a
|
||||
href="https://platform.openai.com/signup/"
|
||||
className="underline"
|
||||
>
|
||||
signing up
|
||||
</a>{' '}
|
||||
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 <code className="font-mono">ai-token</code>.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<Input
|
||||
value={previewTokenInput}
|
||||
placeholder="OpenAI API key"
|
||||
onChange={e => setPreviewTokenInput(e.target.value)}
|
||||
/>
|
||||
<DialogFooter className="items-center">
|
||||
<Button
|
||||
onClick={() => {
|
||||
setPreviewToken(previewTokenInput)
|
||||
setPreviewTokenDialog(false)
|
||||
}}
|
||||
>
|
||||
Save Token
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
24
lib/hooks/use-local-storage.ts
Normal file
24
lib/hooks/use-local-storage.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
|
||||
export const useLocalStorage = <T>(
|
||||
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]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue