first commit
This commit is contained in:
113
server/api/conversation.post.js
Normal file
113
server/api/conversation.post.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import ChatGPTClient from '@waylaidwanderer/chatgpt-api'
|
||||
import { PassThrough } from 'node:stream'
|
||||
import {getSetting, setSetting} from "~/utils/keyv";
|
||||
|
||||
const serializeSSEEvent = (chunk) => {
|
||||
let payload = "";
|
||||
if (chunk.id) {
|
||||
payload += `id: ${chunk.id}\n`;
|
||||
}
|
||||
if (chunk.event) {
|
||||
payload += `event: ${chunk.event}\n`;
|
||||
}
|
||||
if (chunk.data) {
|
||||
payload += `data: ${chunk.data}\n`;
|
||||
}
|
||||
if (chunk.retry) {
|
||||
payload += `retry: ${chunk.retry}\n`;
|
||||
}
|
||||
if (!payload) {
|
||||
return "";
|
||||
}
|
||||
payload += "\n";
|
||||
return payload;
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
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 = (data) => {
|
||||
tunnel.write(serializeSSEEvent(data))
|
||||
}
|
||||
setResponseHeaders(event, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Connection': 'keep-alive'
|
||||
})
|
||||
|
||||
const modelName = await getSetting('modelName')
|
||||
const apiKey = await getSetting('apiKey')
|
||||
|
||||
if (!apiKey) {
|
||||
writeToTunnel({
|
||||
event: 'error',
|
||||
data: JSON.stringify({
|
||||
code: 503,
|
||||
error: 'You haven\'t set the api key of openai',
|
||||
}),
|
||||
})
|
||||
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: modelName,
|
||||
},
|
||||
// (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' }),
|
||||
uri: 'sqlite://database.sqlite'
|
||||
};
|
||||
|
||||
const chatGptClient = new ChatGPTClient(apiKey, clientOptions, cacheOptions);
|
||||
|
||||
try {
|
||||
const response = await chatGptClient.sendMessage(body.message, {
|
||||
conversationId,
|
||||
parentMessageId,
|
||||
onProgress: (token) => {
|
||||
// console.log(token)
|
||||
writeToTunnel({ data: JSON.stringify({
|
||||
type: 'token',
|
||||
data: token
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
writeToTunnel({ data: JSON.stringify({
|
||||
type: 'done',
|
||||
data: response
|
||||
}) })
|
||||
console.log(response)
|
||||
} catch (e) {
|
||||
const code = e?.json?.data?.code || 503;
|
||||
const message = e?.json?.error?.message || 'There was an error communicating with ChatGPT.';
|
||||
writeToTunnel({
|
||||
event: 'error',
|
||||
data: JSON.stringify({
|
||||
code,
|
||||
error: message,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
return sendStream(event, tunnel)
|
||||
})
|
||||
19
server/api/settings.js
Normal file
19
server/api/settings.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import {getSetting, setSetting} from "~/utils/keyv";
|
||||
import {apiError, apiSuccess} from "~/utils/api";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const method = getMethod(event)
|
||||
if (method === 'GET') {
|
||||
const query = getQuery(event)
|
||||
let value = await getSetting(query.key)
|
||||
if (!value && query.key === 'modelName') {
|
||||
value = runtimeConfig.openaiModelName
|
||||
}
|
||||
return apiSuccess(value)
|
||||
} else if (method === 'POST') {
|
||||
const body = await readBody(event)
|
||||
await setSetting(body.key, body.value)
|
||||
return apiSuccess()
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user