127 lines
3.4 KiB
TypeScript
127 lines
3.4 KiB
TypeScript
import { kv } from '@vercel/kv'
|
|
// import { Message, OpenAIStream, StreamingTextResponse } from '@aigxion/isdk'
|
|
import OpenAI from 'openai'
|
|
import { ChatCompletionMessageParam } from 'openai/resources/chat/completions'
|
|
|
|
import { auth } from '@/auth'
|
|
import { nanoid } from '@/lib/utils'
|
|
import { Message, OpenAIStream, StreamingTextResponse } from '@aigxion/isdk'
|
|
|
|
export const runtime = 'edge'
|
|
|
|
const openai = new OpenAI({
|
|
// baseURL: "https://api.openai.com/v1",
|
|
baseURL: "https://filefast.io/chatgpt/v1",
|
|
apiKey: process.env.OPENAI_API_KEY
|
|
})
|
|
|
|
export async function POST(req: Request) {
|
|
const json = await req.json()
|
|
const { messages, functions } = json
|
|
const session = await auth()
|
|
const { id: userId, image: avatarUrl } = session?.user ?? {}
|
|
|
|
// Limit the number of messages to 30, removing from the middle of the array
|
|
function limitedMessagesArray(messages: ChatCompletionMessageParam[]) {
|
|
const messageLimit = 30
|
|
|
|
if (messages.length > messageLimit) {
|
|
const numberOfElementsToRemove = messages.length - messageLimit
|
|
const startIndex = Math.floor(
|
|
(messages.length - numberOfElementsToRemove) / 2
|
|
)
|
|
messages.splice(startIndex, numberOfElementsToRemove)
|
|
}
|
|
|
|
return messages
|
|
}
|
|
|
|
|
|
|
|
|
|
// curl https://api.openai.com/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer sk-" -d '{"model": "gpt-4-turbo-preview", "prompt": "给我创建一个BTC钱包", "temperature": 0, "max_tokens": 127}'
|
|
|
|
// curl https://api.openai.com/v1/chat/completions \
|
|
// -H "Content-Type: application/json" \
|
|
// -H "Authorization: Bearer sk-" \
|
|
// -d '{
|
|
// "model": "gpt-4-0125-preview",
|
|
// "messages": [
|
|
// {
|
|
// "role": "system",
|
|
// "content": "You are a helpful assistant."
|
|
// },
|
|
// {
|
|
// "role": "user",
|
|
// "content": "给我创建一个BTC钱包"
|
|
// }
|
|
// ]
|
|
// }'
|
|
|
|
// curl "https://api.openai.com/v1/assistants" \
|
|
// -H "Content-Type: application/json" \
|
|
// -H "Authorization: Bearer sk-" \
|
|
// -H "OpenAI-Beta: assistants=v1" \
|
|
// -d '{
|
|
// "instructions": "给我创建一个BTC钱包",
|
|
// "name": "Math Tutor",
|
|
// "tools": [{"type": "code_interpreter"}],
|
|
// "model": "gpt-4-turbo-preview"
|
|
// }'
|
|
|
|
// curl https://api.openai.com/v1/models \
|
|
// -H "Authorization: Bearer sk-"
|
|
|
|
|
|
|
|
const res = await openai.chat.completions.create({
|
|
// model: userId ? 'gpt-4-turbo-preview' : 'gpt-3.5-turbo-0125',
|
|
model: 'gpt-4-turbo-preview',
|
|
stream: true,
|
|
messages: limitedMessagesArray(messages),
|
|
functions
|
|
})
|
|
|
|
// openai.beta.assistants.create()
|
|
|
|
const stream = OpenAIStream(res, {
|
|
|
|
|
|
async onCompletion(completion) {
|
|
if (userId) {
|
|
const title = messages
|
|
.find((m: Message) => m.role !== 'system')
|
|
?.content.substring(0, 100)
|
|
const id = String(json.id ?? nanoid())
|
|
const createdAt = Date.now()
|
|
const path = `/chat/${id}`
|
|
const payload = {
|
|
id,
|
|
title,
|
|
userId,
|
|
createdAt,
|
|
avatarUrl,
|
|
path,
|
|
messages: [
|
|
...messages,
|
|
{
|
|
content: completion,
|
|
role: 'assistant'
|
|
}
|
|
]
|
|
}
|
|
await kv.hmset(`chat:${id}`, payload)
|
|
await kv.zadd(`user:chat:${userId}`, {
|
|
score: createdAt,
|
|
member: `chat:${id}`
|
|
})
|
|
}
|
|
}
|
|
})
|
|
|
|
return new StreamingTextResponse(stream)
|
|
}
|
|
|
|
|
|
|