从零实现一个GPT 【React + Express】--- 【5】实现网页生成能力

摘要

经过前面的四篇文章,我们已经实现了。文本对话,文生图的两个功能。其实我觉得这个系列这四篇文章就已经够用了。后续,我会继续提供一些额外模型能力的教程。这里读者如果有感兴趣的功能,也可以在评论区留下建议我们一起实现。

网页生成思路

那本篇文章主要来实现一下网页生成的能力,简单描述一下:就是用户输入一段query,然后给用户输出一个网页。那这个功能模型肯定不能支持,不能像文生图一样,给模型一个query,然后他给你部署好一个网页,然后通过url输出给你,这肯定是不行的。

那模型不支持,我们就无法做到了嘛,当然不。作为一个前端开发,我们肯定知道,一个网页代表的就是一个html。那模型有输出html的功能啊,那能不能经过我们的处理,实现这个网页生成的功能呢?

首先我们要给模型一个system,告诉模型你就是个只会写html的助手 。然后,当用户发来一个query之后,我们在query之后拼上请以html的格式输出。 哎,这样模型输出的不就是一个html了吗。

那在后端我们拿到了html的输出,只需要将其通过fs模型写到对应的目录下,再把html对应的目录返回给前端,这不就实现了吗。多么简单。

实现接口

现在,我们来到后端项目中,我们的chat接口要修改一下,我们要区分一下是走之前的对话链路,还是走生成网页的链路:

js 复制代码
//routes/chat.js


router.post('/chat', function(req, res) {
    res.set('Content-Type', 'text/event-stream;charset=utf-8');
    res.set('Access-Control-Allow-Origin', '*');
    res.set('X-Accel-Buffering', 'no');
    res.set('Cache-Control', 'no-cache, no-transform');
    const { message, sessionId, type } = req.body;

    if (type === 'html') {
        getHtml(message, sessionId, res);
        return;
    }

    getChat(message, sessionId, res);
});

直接通过前端传过来的参数来判断,如果type === html,那么就走新的链路。

现在我们来实现一下getHtml方法,首先我们要修改一下模型的system。

js 复制代码
const stream = await client.chat.completions.create({
    messages: [
        { role: 'system', content: '你是一个擅长编写html的代码助手' },
        ...historyList,
        { role: 'user', content: message + ',请以html的格式输出 ,请确保生成的HTML代码是合法的,并且包含基本的结构和语义' },
    ],
    model: 'gpt-3.5-turbo',
    stream: true,
    max_tokens: 5000, // 控制生成的 token 数
});

这样我们就限制了模型的输出一定是以html输出。但是模型输出html的同时,肯定也会输出一些文本,所以我们要把文本中的html部分截断出来,然后再通过fs写入对应的目录下:

js 复制代码
//routes/chat.js

const startIndex = answer.indexOf('<html');
const endIndex = answer.lastIndexOf('</html>');
const html = answer.slice(startIndex, endIndex + 7);

const folderPath = path.join(__dirname, '../public/html');
const fileName = Date.now() + '.html';
const filePath = path.join(folderPath, fileName);

fs.writeFileSync(filePath, html, 'utf8');

最后,我们把文件所在的目录返回给前端,即可。这里肯定要定义一个新的类型事件:

js 复制代码
//routes/chat.js

eventName = 'source';
res.write(`event: ${eventName}\n`);
res.write(`data: ${JSON.stringify({html: `http://localhost:3002/html/${fileName}`})}\n\n`)

后端部分的提交记录如下:

github.com/TeacherXin/...

实现前端部分

node端的部分实现完了,我们来实现前端的部分。

首先我们在SkillList里增加一个技能,对应的类型也添加好。当我们选中这个类型之后,我们的sendData方法就要携带type参数,发送给后端,现在我们修改一下sendData方法:

js 复制代码
//src/page/components/DialogInput/index.tsx

const callbackMap: CallBackMap = {
    message: messageCallback,
    major: majorCallback,
    close: closeCallback,
}

if (skillStore.selectedSkill === 'html') {
    data.type = 'html';
    callbackMap.source = (source) => {
        changeLastHtmlUrl(source.html);
    };
}

connectSSE(url, data, callbackMap);

这里记得我们要对source的事件类型也进行处理一下。

最后修改一下视图层前端部分就实现了,是不是非常简单。

更多的提交内容可以查看:

github.com/TeacherXin/...

最后我们来看一下效果吧:

相关推荐
小喷友18 分钟前
第 6 章:API 路由(后端能力)
前端·react.js·next.js
闻道且行之1 小时前
TTS语音合成|GPT-SoVITS语音合成服务器部署,实现http访问
服务器·gpt·http
代码的余温2 小时前
React核心:组件化与虚拟DOM揭秘
前端·react.js·前端框架
小螺号dididi吹2 小时前
【React】状态管理
前端·javascript·react.js
代码的余温2 小时前
React Refs:直接操作DOM的终极指南
前端·javascript·react.js
前端小咸鱼一条6 小时前
React组件化的封装
前端·javascript·react.js
南方kenny6 小时前
TypeScript + React:让前端开发更可靠的黄金组合
前端·react.js·typescript
CF14年老兵7 小时前
✅ Next.js 渲染速查表
前端·react.js·next.js
dyb7 小时前
开箱即用的Next.js SSR企业级开发模板
前端·react.js·next.js
zzywxc7878 小时前
在处理大数据列表渲染时,React 虚拟列表是提升性能的关键技术,但在实际实现中常遇到渲染抖动和滚动定位偏移等问题。
前端·javascript·人工智能·深度学习·react.js·重构·ecmascript