coze的ai生成图标是怎么实现的(AI全栈)

1,154 阅读8分钟

前言

在coze创建bot中,有一个有意思的功能是自动生成机器人图标,那么这个图标是怎么生成的?

image.png

毋庸置疑,根据用户输入的bot名称功能介绍生成,那么接下来我们就来实现一下这个功能。调用多模态模型gpt4/gpt4o/专业绘图模型dalle-3

整体思路

  1. 前端通过bootstrap快速搭建一个页面,通过form表单收集bot名称、bot功能介绍
  2. ajax发送post请求,向后端服务器发送数据(提交表单)
  3. 后端,通过koa搭建服务器,后端端口号3000,前端端口号5500,调用openai dalle3多模态模型
  4. ai,安装openai,dotenv管理key,调用接口,选择模型...
  • 具体详情后面将详细描述。

frontend(前端)

前端主要就是提供页面的交互、美观,接收用户输入,然后post发送给后端,最后大模型处理了这个信息后得到的图片再在前端展示出来

image.png 利用bootstrap快速搭建页面,优点如下:

  1. 响应式设计:能使网页在不同的设备(如桌面、平板、手机等)上自动适应,提供良好的用户体验。
  2. 丰富的组件:包含了各种常用的 UI 组件,如导航栏、按钮、表单、模态框等,方便快速开发界面。
  3. 简洁的样式:提供了一套统一且美观的样式风格,无需过多手动设计样式。
  4. 文档完善:有详细的文档和丰富的示例,易于学习和使用。
  5. 社区活跃:拥有庞大的社区,能及时获得支持和更新。
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">
    <style>
        #logo img {
            display: block;
            width: 200px;
            height: 200px;
        }
    </style>
</head>

<body>
    <!-- bootstrap 好快 PC 框架 -->
    <!-- 网页布局 -->
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <form name="logoForm">
                    <div class="form-group">
                        <label for="titleInput">Bot名称:</label>
                        <input type="text" class="form-control" id="titleInput" name="title" placeholder="Bot名称"
                            requried>
                    </div>
                    <div class="form-group">
                        <label for="descInput">Bot介绍:</label>
                        <textarea class="form-control" name="desc" id="descInput" placeholder="请输入Bot介绍">
                        </textarea>
                    </div>
                    <div class="form-group">
                        <button type="submit" class="btn btn-primary">生成图标</button>
                    </div>
                </form>
            </div>
            <div class="row" id="logo">

            </div>
        </div>
    </div>
  
</body>

</html>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">
  • 引入bootstrap
  • container中放第一个row,row中放form表单,表单中放一个input用于收集bot名称,一个放textarea用收集bot介绍,然后来一个button提交按钮
  • 注意与label连用for..id
  • 最后放第二个row用于展示ai生成的logo(提前挖好坑)

JavaScript

<script>
        const oForm = document.forms['logoForm']
        const oLogo = document.getElementById('logo')
        oForm.addEventListener('submit', function (e) {
            e.preventDefault()
            const title = this["title"].value.trim()
            const desc = this["desc"].value.trim()
            // console.log(title, desc);
            if (title) {
                const data = {
                    title,
                    desc
                }
                // post 提交表单 
                fetch('http://localhost:3000/logo', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    // 请求体 字符串或文件二进制
                    body: JSON.stringify(data)
                })
                    .then(res => res.json())
                    .then(data => {
                        console.log(data);
                        if (data.code == 200) {
                            const { url } = data
                            const oImg = document.createElement('img')
                            oImg.src = url
                            oImg.onload = function () {
                                document.getElementById('logo').appendChild(oImg)
                            }
                        } else {
                            console.log('出错了');
                        }
                    })
            }
        })
    </script>

DOM元素获取:

  1. const oForm = document.forms['logoForm']:从页面中获取名为logoForm的表单元素。
  2. const oLogo = document.getElementById('logo'):获取ID为logo的元素,这个元素将用于展示生成的图标。

事件监听器:

oForm.addEventListener('submit', function (e) { ... }):添加事件监听器到表单的提交事件。当表单被提交时,会执行函数体内的代码。

阻止默认行为:

e.preventDefault():防止表单提交的默认行为,即刷新页面。这使得我们可以使用AJAX(异步JavaScript和XML)进行后台数据处理,而不会中断用户的当前浏览状态。

数据获取与处理:

const title = this["title"].value.trim() 和 const desc = this["desc"].value.trim():从表单中获取用户输入的Bot名称和介绍,并去除首尾空白字符。由于绑定了监听器,this指向绑定的元素,然后通过name属性直接获取道dom响应的dom结构

发送请求:

  1. 使用fetch API 发送一个POST请求到http://localhost:3000/logo,其中请求头设置为Content-Type: application/json,并将用户输入的数据作为JSON字符串放入请求体。设置请求头是必要的,相当于告诉浏览器需要解析的是什么样的东西。
  2. body: JSON.stringify(data):将JavaScript对象转换成JSON格式的字符串。

响应处理:

  1. .then(res => res.json()):等待服务器响应,将响应体解析为JSON格式。 .then(data => { ... }):进一步处理解析后的JSON数据。 如果服务器返回的状态码code为200,说明请求成功,从中提取图标URL。 使用document.createElement('img')创建一个新的<img>元素,并设置其src属性为从服务器获取的图标URL。
  2. 当图片加载完成时(找到最佳的时间点(素养)),oImg.onload,将图片元素追加到oLogo元素中,从而在页面上显示图标。如果服务器返回的状态码不是200,或者请求过程中出现错误,控制台将输出错误信息。整个流程实现了用户输入数据,通过Ajax请求服务器生成图标,并在页面上动态展示图标的功能。

backend(后端)

项目初始化

npm init -y

安装模块

npm i koa
npm i koa-router
npm i @koa/cors
npm i -g nodemon
npm i @koa/bodyparser
npm i openai
npm i dotenv

模块的引入 这里我们创建的是mjs文件而不是js文件,mjs文件支持es6后的新的模块化写法,不需要通过require进行导入了,可以像其他语言一样import xx from xx,替代了CommonJS

import Koa from 'koa';
import Router from 'koa-router';
import cors from '@koa/cors';
import { bodyParser } from '@koa/bodyparser';
import OpenAI from 'openai';
import dotenv from 'dotenv';
  • koa可以用于创建一个服务器
const app = new koa();
app.listen(3000, () => {
    console.log('server is running at http://localhost:3000');
})
  • 通过app.use(接收函数)注册中间件。中间件函数可以在请求处理的不同阶段进行一些通用的操作,比如对请求进行预处理、执行权限验证、处理错误、修改请求或响应对象等。 通过将一个或多个函数作为参数传递给 app.use() ,这些函数就会按照添加的顺序依次被执行,形成一个处理请求的链条。
  • koa-router可以方便地定义不同的 HTTP 方法(如 GET、POST 等)与特定路径的映射关系,并关联相应的处理函数。简单说就是定义路由。
  • @koa/cors 主要是用于处理跨域资源共享(CORS)。如果不做跨域处理,浏览器会报错,因为js有同源策略,前端端口与后端端口不一。
  • @koa/bodyparser:用于解析HTTP请求体,会将请求体解析为JavaScript可操作的对象,并挂在ctx.request.body上。
  • dotenv:将一些敏感信息进行集中存储在一个 .env 文件(自己创建),然后在应用启动时加载这些环境变量到 process.env 中,从而使得配置更加灵活和安全。

接下来我们想利用多模态模型对名称、描述分析一下之后,帮助我们生成对应的图标logo,但是首先我们需要有gpt的key。

API Key获取传送门——WildCard | 一分钟注册,轻松订阅海外软件服务

image.png

image.png

  • 我们已经安装过dotenv了
dotenv.config({
    path: '.env'
});
  • 创建一个.env文件,用于管理我们的敏感信息,比如password,比如key。

image.png

  • 创建openai实例
const client = new OpenAI({
    apiKey: process.env.OPENAI_KEY,
    baseURL: 'https://api.gptsapi.net/v1'
});

完整后台,调用dall-e-3

定义处理/logo路径的post请求的路由处理函数。它接收前端向后端发送的post请求体中的title 和 desc,并且用这些信息构建一个提示指令,然后调用 DALL·E-3的接口生成图片。

// es6 module 模块化,引入koa框架
// 不用require commonjs
// 启动 后端服务
// 引入最火的一个简单的node框架
import koa from 'koa';
import Router from 'koa-router'; // 添加路由
import cors from '@koa/cors'; // 跨域
import { bodyParser } from '@koa/bodyparser'; // 解析post请求体
import OpenAI from 'openai'
import dotenv from 'dotenv';

dotenv.config({
    path: '.env'
});
// console.log(process.env.OPENAI_KEY);

const client = new OpenAI({
    apiKey: process.env.OPENAI_KEY,
    baseURL: 'https://api.gptsapi.net/v1'
})

// 网站就是一个app
const app = new koa();
const router = new Router();
// 挂载跨域功能
app.use(cors());
// 挂在post 请求体解析功能
app.use(bodyParser());
router.post('/logo', async (ctx) => {
    console.log(ctx.request.body);
    const { title, desc } = ctx.request.body;
    // const prompt = `我要开发${title}的一款App,
    //             功能细节是 ${desc},请告诉我找你做外包要多少钱`
    let response;
    try {
        const prompt = `
            你是一位互联网大厂设计师,
            请为应用名为${title},
            功能细节为${desc}的移动端App
            设计一个高端、大气、上档次的logo
        `
        response = await client.images.generate({
            model: 'dall-e-3',
            prompt: prompt,
            n: 1,
            size: "1024x1024"

        })
        ctx.body = {
            code: 200,
            url: response.data[0].url
        }
        // console.log(url);

        // const response = await client.chat.completions.create({
        //     model: 'gpt-3.5-turbo',
        //     messages: [
        //         {
        //             role: 'admin',
        //             content: '你是一位抖音年薪200w的技术经理,请回答以下内容'
        //         },
        //         {
        //             role: 'user',
        //             content: prompt
        //         }
        //     ],
        //     n: 1
        // })
    } catch (err) {
        console.log(err);
        ctx.body = {
            code: 500,
            msg: '出错了'
        }
    }

    console.log(response, '///////////');
    // ctx.body = {
    //     title,
    //     desc
    // }
    // ctx.body = 'logo';
})
router.get('/', (ctx) => {
    ctx.body = 'index page';
})
// use 加一个什么服务
// 用户通过http请求进来,use里面的函数会被执行
// 请求  中间件  响应 
// app.use((ctx) => {
//     // ctx 上下文对象
//     // 上下文对象中包含了很多属性,比如body
//     // 响应体
//     ctx.body = 'hello';
// })
// router.routes 路由上所有的路由声明加上去
app.use(router.routes())
// 启动http服务 3000端口
app.listen(3000, () => {
    console.log('server is running at http://localhost:3000');
})

  1. 使用 import 语句引入了 koa 框架、Router 路由模块、cors 跨域模块、bodyParser 请求体解析模块以及 OpenAI 并配置了环境变量。
  2. 创建了一个 OpenAI 客户端实例并进行了相关配置。
  3. 创建了 koa 应用实例和路由实例。
  4. 为应用挂载了跨域功能和请求体解析功能。
  5. 在路由中定义了 /logo 的 post 路由处理函数,用于接收请求并与 OpenAI 交互来生成内容并返回响应,同时处理了可能出现的错误。还定义了 / 的 get 路由处理函数。
  6. 通过 app.use(router.routes()) 将路由添加到应用中。
  7. 启动了一个在 3000 端口运行的 HTTP 服务,并在控制台输出相关提示信息。

效果

image.png

传统前后端项目,如何引入openai成为AI全栈项目?传统前后端如何引入AI成为AI全栈项目?一个demo让你彻底理解 - 掘金 (juejin.cn)