邀请懂 TypeScript 的程序员帮忙改代码 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
x77
V2EX    程序员

邀请懂 TypeScript 的程序员帮忙改代码

  •  
  •   x77 2023-05-26 20:20:32 +08:00 1943 次点击
    这是一个创建于 937 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一个 ChatGPT 的 Web UI 项目,搞得还不错支持语音,我小试了一下 Azure 的语音合成,效果真不错。不过这项目设计是在客户端(浏览器)向 OpenAI 发起请求,有没有人帮忙改成由服务端发起请求,类似这个项目。具体的要修改的代码可能在这里: https://github.com/hahahumble/speechgpt/blob/main/src/apis/openai.ts

    我知道代码里有个代理设置,在云端开个 Function 服务器就可以转发,但还是有些麻烦,另外还得传输 APIKey 不是很安全。

    我不懂 Typescript ,虽然语言都是相通的,能看懂能小改 Typescript ,但是要用不懂的语言来表达还是有些吃力,也容易搞得低效、不合理。也有人给这项目提类似需求的 Issue (希望在服务端设置 API ),但是开发方更新有点慢。

    那就自个搞一下把,希望有兴趣的开发者帮忙改下,感谢。

    15 条回复    2023-05-27 19:24:32 +08:00
    ByteCat
        1
    ByteCat  
       2023-05-26 20:27:51 +08:00
    Node.js 18 开始也自带 fetch 支持了呀
    a632079
        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 无关,纯粹模块问题……
    leokun
        3
    leokun  
       2023-05-26 20:48:23 +08:00
    这个如果改成 next 的还是有一点工作量的
    最简单最快的方法就是 njs 写一个转发,打成容器就好了
    x77
        4
    x77  
    OP
       2023-05-26 20:48:23 +08:00
    @ByteCat
    @a632079
    我 nodejs 开发环境都没折腾啊
    Aloento
        5
    Aloento  
       2023-05-26 20:52:35 +08:00
    @x77 #4 他们应该听不懂你在说什么
    CLMan
        6
    CLMan  
       2023-05-26 20:52:49 +08:00
    这软件架构就是这样,服务端提的只是一个 UI ,由本地向 OpenAI API 地址发起请求的。

    你要改成服务端请求,最简单的办法是搭建一个 api 代理,将其密钥放在代理的服务端,UI 层只需要根据你的需求进行小改。
    Puteulanus
        7
    Puteulanus  
       2023-05-26 20:53:35 +08:00   2
    你这能算自个搞一下吗哥
    leokun
        8
    leokun  
       2023-05-26 20:57:11 +08:00
    a632079
        9
    a632079  
       2023-05-26 21:18:46 +08:00
    @Aloento 他说服务端,也没提什么框架,什么 Runtime 。只提了一嘴小改 TS ,那不就默认 node 了嘛
    zbinlin
        10
    zbinlin  
       2023-05-26 21:28:40 +08:00
    这个项目不就是一个纯前端项目吗,如果你要改成从服务端发起请求,不就需要添加服务端 API 了(或者用 nginx 的 njs 来添加一个转发接口?)
    AS4694lAS4808
        11
    AS4694lAS4808  
       2023-05-26 21:48:04 +08:00 via Android
    代码只需要加一行,把 base_url 改成你机器的。

    然后在对应的机器上开一个 nginx ,后端代理到 api.openai.com ,location 里添加密钥头,完事。
    ruoxie
        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();
    });
    ruoxie
        13
    ruoxie  
       2023-05-26 21:58:04 +08:00
    这个项目没有用流模式,体验太差了
    x77
        14
    x77  
    OP
       2023-05-27 19:19:06 +08:00
    @Puteulanus 咱们自个儿
    x77
        15
    x77  
    OP
       2023-05-27 19:24:32 +08:00
    @ruoxie 感谢。
    我这边只能编译 docker 镜像,把您的代码替换掉 openai.ts 文件就可以了吗?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1106 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 23:27 PVG 07:27 LAX 15:27 JFK 18:27
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86