一个 ChatGPT 的 Web UI 项目,搞得还不错支持语音,我小试了一下 Azure 的语音合成,效果真不错。不过这项目设计是在客户端(浏览器)向 OpenAI 发起请求,有没有人帮忙改成由服务端发起请求,类似这个项目。具体的要修改的代码可能在这里: https://github.com/hahahumble/speechgpt/blob/main/src/apis/openai.ts。
我知道代码里有个代理设置,在云端开个 Function 服务器就可以转发,但还是有些麻烦,另外还得传输 APIKey 不是很安全。
我不懂 Typescript ,虽然语言都是相通的,能看懂能小改 Typescript ,但是要用不懂的语言来表达还是有些吃力,也容易搞得低效、不合理。也有人给这项目提类似需求的 Issue (希望在服务端设置 API ),但是开发方更新有点慢。
那就自个搞一下把,希望有兴趣的开发者帮忙改下,感谢。
1
ByteCat 2023-05-26 20:27:51 +08:00
Node.js 18 开始也自带 fetch 支持了呀
|
2
a632079 2023-05-26 20:40:07 +08:00
https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#fetch
亦或者添加 node-fetch 模块。 P.S 这和 TS 无关,纯粹模块问题…… |
3
leokun 2023-05-26 20:48:23 +08:00
这个如果改成 next 的还是有一点工作量的
最简单最快的方法就是 njs 写一个转发,打成容器就好了 |
6
CLMan 2023-05-26 20:52:49 +08:00
这软件架构就是这样,服务端提供的只是一个 UI ,由本地向 OpenAI API 地址发起请求的。
你要改成服务端请求,最简单的办法是搭建一个 api 代理,将其密钥放在代理的服务端,UI 层只需要根据你的需求进行小改。 |
7
Puteulanus 2023-05-26 20:53:35 +08:00 2
你这能算自个搞一下吗哥 😂
|
8
leokun 2023-05-26 20:57:11 +08:00
|
10
zbinlin 2023-05-26 21:28:40 +08:00
这个项目不就是一个纯前端项目吗,如果你要改成从服务端发起请求,不就需要添加服务端 API 了(或者用 nginx 的 njs 来添加一个转发接口?)
|
11
AS4694lAS4808 2023-05-26 21:48:04 +08:00 via Android
|
12
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(); }); |
13
ruoxie 2023-05-26 21:58:04 +08:00
这个项目没有用流模式,体验太差了
|
14
x77 OP @Puteulanus 咱们自个儿
|