ruoxie
2023-05-26 21:52:27 +08:00
代码直接给你了
import * as https from 'https';
import { TextDecoder } from 'util';
export const createChatCompletion = (options: {
host: string;
apiKey: string;
model: string;
text: string;
context?: string;
maxTokens: number;
handleChunk?: (data: { text?: string; hasMore: boolean }) => void;
}) =>
new Promise<string>((resolve, reject) => {
let combinedResult = '';
const request = https.request(
{
hostname: options.host,
port: 443,
path: '/v1/chat/completions',
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${options.apiKey}`,
},
},
(res) => {
res.on('data', async (chunk) => {
const text = new TextDecoder('utf-8').decode(chunk);
const data = text.split('\n\n').filter((s) => s);
for (let i = 0; i < data.length; i++) {
try {
let element = data[i];
if (element.includes('data: ')) {
if (element.trim() === 'data:') {
// 处理只返回了 data: 的情况
return;
}
} else if (element.includes('delta')) {
// 处理没有 data 开头
element = `data: ${element}`;
}
if (element.includes('data: ')) {
if (element.includes('[DONE]')) {
options.handleChunk &&
options.handleChunk({ hasMore: false, text: '' });
return;
}
// remove 'data: '
const data = JSON.parse(element.replace('data: ', ''));
if (data.finish_reason === 'stop') {
options.handleChunk &&
options.handleChunk({ hasMore: false, text: '' });
return;
}
const openaiRes = data.choices[0].delta.content;
if (openaiRes) {
options.handleChunk &&
options.handleChunk({
text: openaiRes.replaceAll('\\n', '\n'),
hasMore: true,
});
combinedResult += openaiRes;
}
} else {
options.handleChunk &&
options.handleChunk({ hasMore: false, text: element });
return;
}
} catch (e) {
console.error({
e,
element: data[i],
});
}
}
});
res.on('error', (e) => {
options.handleChunk &&
options.handleChunk({ hasMore: false, text: e.toString() });
reject(e);
});
res.on('end', () => {
resolve(combinedResult);
});
},
);
const body = {
model: options.model,
messages: [
{
role: 'system',
content: options.context || '',
},
{
role: 'user',
content: options.text,
},
],
stream: true,
max_tokens: options.maxTokens,
};
request.write(JSON.stringify(body));
request.end();
});