87 lines
3.1 KiB
JavaScript
87 lines
3.1 KiB
JavaScript
import ChatGPTClient from '@waylaidwanderer/chatgpt-api'
|
|
import { PassThrough } from 'node:stream'
|
|
import { nanoid } from 'nanoid'
|
|
|
|
const serializeSSEEvent = (event, data) => {
|
|
const id = nanoid();
|
|
const eventStr = event ? `event: ${event}\n` : '';
|
|
const dataStr = data ? `data: ${JSON.stringify(data)}\n` : '';
|
|
|
|
return `id: ${id}\n${eventStr}${dataStr}\n`;
|
|
}
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const body = await readBody(event)
|
|
const conversationId = body.conversationId ? body.conversationId.toString() : undefined
|
|
const parentMessageId = body.parentMessageId ? body.parentMessageId.toString() : undefined
|
|
const tunnel = new PassThrough()
|
|
const writeToTunnel = (event, data) => {
|
|
tunnel.write(serializeSSEEvent(event, data))
|
|
}
|
|
const endTunnel = () => {
|
|
tunnel.end()
|
|
}
|
|
|
|
setResponseHeaders(event, {
|
|
'Content-Type': 'text/event-stream',
|
|
'Cache-Control': 'no-cache',
|
|
'Connection': 'keep-alive'
|
|
})
|
|
|
|
if (!body.openaiApiKey) {
|
|
writeToTunnel('error', {
|
|
code: 503,
|
|
error: 'You haven\'t set the api key of openai',
|
|
})
|
|
endTunnel()
|
|
return sendStream(event, tunnel)
|
|
}
|
|
|
|
const clientOptions = {
|
|
// (Optional) Parameters as described in https://platform.openai.com/docs/api-reference/completions
|
|
modelOptions: {
|
|
// The model is set to text-chat-davinci-002-20221122 by default, but you can override
|
|
// it and any other parameters here
|
|
model: body.model,
|
|
},
|
|
// (Optional) Set custom instructions instead of "You are ChatGPT...".
|
|
// promptPrefix: 'You are Bob, a cowboy in Western times...',
|
|
// (Optional) Set a custom name for the user
|
|
// userLabel: 'User',
|
|
// (Optional) Set a custom name for ChatGPT
|
|
// chatGptLabel: 'ChatGPT',
|
|
// (Optional) Set to true to enable `console.debug()` logging
|
|
debug: false,
|
|
};
|
|
|
|
const cacheOptions = {
|
|
// Options for the Keyv cache, see https://www.npmjs.com/package/keyv
|
|
// This is used for storing conversations, and supports additional drivers (conversations are stored in memory by default)
|
|
// For example, to use a JSON file (`npm i keyv-file`) as a database:
|
|
// store: new KeyvFile({ filename: 'cache.json' }),
|
|
};
|
|
|
|
const chatGptClient = new ChatGPTClient(body.openaiApiKey, clientOptions, cacheOptions);
|
|
|
|
try {
|
|
const response = await chatGptClient.sendMessage(body.message, {
|
|
conversationId,
|
|
parentMessageId,
|
|
onProgress: (token) => {
|
|
// console.log(token)
|
|
writeToTunnel('message',{content: token})
|
|
}
|
|
});
|
|
writeToTunnel('done',response)
|
|
console.info(response)
|
|
} catch (e) {
|
|
const code = e?.json?.data?.code || 503;
|
|
const message = e?.json?.error?.message || 'There was an error communicating with ChatGPT.';
|
|
writeToTunnel('error', {
|
|
code,
|
|
error: message
|
|
})
|
|
}
|
|
tunnel.end()
|
|
return sendStream(event, tunnel)
|
|
}) |