AI:想要什么logo,我给你生成一个

1,517 阅读5分钟

随着AI技术的发展,特别是2024年中国AI行业的持续升温,AI全栈开发成为了非常热门且高薪的职业方向。在这个领域,开发者不仅需要掌握传统的Web开发技术,还要具备AI相关的能力;今天我们就来实现一下coze中一个高级的AI功能:AI图标生成,再次提升我们对AI的理解。

AI图标生成

coze(主页 - 扣子 (coze.cn)),国内知名AI应用,今天我们就来学习一下它里面的图标生成功能;效果如下图:

chrome-capture-2024-7-20.gif

当我们点击“AI生成”时,AI会根据用户输入的“Bot功能介绍”,去调用大模型帮助我们生成相关的图标;AI图标生成的功能不仅让我们可以快速地拿到一个相关的Logo,而且更是颠覆了传统的上传图标的方式。

AI功能的实现

在实现上述功能之前,我们可以先来了解一下,AI全栈式的开发,它不仅集前端、后端和AI服务为一体,更是要做到前后端的一个分离;前端(frontend)、后端(backend)

前端 frontend

在前端部分,我们可以引入一个比较早期的前端框架库(bootstrap);通过link标签去引入:

<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">

虽然 bootstrap 框架,我们在实际开发中用的并不多,但利用它的CSS框架依然可以快速完成PC项目页面的开发。

<!DOCTYPE html>
<html lang="en">

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

<body>
    <!-- 布局 -->
    <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" id="titleInput" name="title" class="form-control" placeholder="请输入名称"
                            required>
                    </div>
                    <div class="form-group">
                        <label for="descInput">Bot功能介绍:</label>
                        <textarea name="desc" class="form-control" row="3" id="descInput">
                    </textarea>
                    </div>
                    <div class="form-group">
                        <button name="loginButton" type="primary" class="btn btn-primary">生成LOGO</button>
                    </div>
                </form>
                <div class="col-md-6" id="result"></div>
            </div>
        </div>
    </div>
</body>

</html>

HTML 结构

<div class="col-md-6 col-md-offset-3">:在 Bootstrap 的栅格系统中,每个行默认被分为 12 个等宽的列;"col-md-6" 表示该列将占据 6 个栅格单位,"col-md-offset-3" 表示该列将相对于行的起始位置向右偏移 3 个栅格单位;因此该 div在页面上居中显示

QQ图片20240823011149.png

HTML5 中的表单增强

<input type="text" placeholder="请输入名称" required>HTML5 对表单进行了显著的增强,引入了许多新的功能和特性,其中 placeholderrequired 都是html5中表单增强的新特性,placeholder: 显示提示文本,当用户开始输入时消失;required: 指定字段是否为必填项

屏幕截图 2024-08-23 020138.png

script 脚本

再来看,在这个AI功能中,前端页面需要进行哪些交互呢?当我们点击按钮时,我们需要把表单的内容进行收集,然后提交给后端进行处理,再拿到后端生成的图片进行展示

    <script>
        // forms 是所有表单的集合,可以按名字来获取
        const oForm = document.forms["logoForm"]
        oForm.addEventListener('submit', function (event) {
            event.preventDefault() // 阻止默认提交
            const title = this["title"].value.trim()
            if (!title) return // html5 有的不支持,两套方案
            const btn = this["loginButton"];
            btn.disabled = true;
            const desc = this["desc"].value.trim()
            // console.log(title);

            // HTTP 协议
            // 请求行 localhost:3000/logo POST
            // 请求头 
            // 请求体 title desc
            // 前后端数据交付的格式是json
            // 输出是二进制或字符串
            // es6 key value 一样的,可以省略

            let data = {
                title,
                desc
            }
            console.log(JSON.stringify(data));
            fetch('http://localhost:3000/logo', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data)
            })
                // 响应 JSON
                .then(res => res.json())
                .then(data => {
                    btn.disabled = false;
                    console.log(data);
                    if (data.status == 200) {
                        let url = data.url;
                        document.getElementById('result').innerHTML +=
                            `<img src="${url}" alt="">`
                    }
                })
        })
    </script>

在上面的代码中,我们有几个需要注意的点;

  • 阻止表单的默认提交:在处理表单提交时,通常我们需要阻止表单的默认提交行为,以便我们可以执行自定义的操作;event.preventDefault() 就可以阻止表单的默认提交行为。
  • 事件监听中的this:在事件处理器函数中,this 关键字通常指向触发事件的对象。这是因为事件处理器函数是在某个 DOM 元素上注册的,当事件发生时,该函数会被调用,并且 this 关键字会自动绑定到触发该事件的 DOM 元素
  • .trim()trim() 方法用于去除字符串两端的空白字符(包括空格、制表符、换行符等)。这意味着即使用户在输入前后添加了空格,trim() 方法也会去除这些空格,确保实际使用的值没有多余的空白。
  • fetch 向后端发送请求'Content-Type': 'application/json' 表明我们将发送的数据格式是 JSON前后端数据交付的格式通常都是 json,又因为 HTTP 协议传输的数据是以文本形式的,而不是原生的 JavaScript 对象,所以 JSON.stringify(data) 被用来将 data 对象转换为 JSON 字符串,然后作为请求体发送给服务器。
  • HTTP 通信:一个完整的请求通常由请求行、请求头和请求体三部分组成;请求行包含三部分,Method(方法)、URL(资源的位置) 和 HTTP版本请求头则包含了一系列键值对,用于提供客户端和服务端之间通信所需的额外信息,如 Content-Type 表示实体对象(请求体)的数据类型Cookie 存储客户端状态信息,通常用于会话管理,Authorization 用于身份认证,通常包含一个token请求体的话包含了要发送给服务器的具体数据,对于GET请求,通常没有请求体;而对于POST、PUT等请求,则可以有请求体。
  • fetch 请求返回的Promise对象:当你使用 fetch API 发起一个网络请求时,它会返回一个 Promise 对象,可以用 .then() 方法处理 fetch 返回的 Response 对象,response.json() 是一个异步方法,用于从 fetch 请求返回的 Response 对象中解析 JSON 数据;然后我们就可以拿到JSON对象进行操作。

后端 backend

前端页面设计完之后,接下来我们要对后端进行接口(/logo)的开发;我们可以引入 node 中一个流行的后端框架 KOA

npm init -y      // 初始化后端项目
npm i koa       // 安装 koa

在这里,我们把单点入口文件设为 main.mjs.mjs 文件和 .js 文件之间的主要区别在于它们如何处理模块系统.mjs 文件 默认使用 ECMAScript 模块(ES Modules),使用 import 和 export 关键字来导入和导出模块,而 .js 文件 默认使用 CommonJS 模块系统,在 Node.js 中使用 require 函数来导入模块,并使用 module.exports 来导出模块

//导入koa框架
import Koa from 'koa' 
//导入koa-router模块,用于创建路由
import Router from 'koa-router' 
// koa-bodyparser 中间件,用于解析 POST 请求的 body 部分
import {bodyParser} from '@koa/bodyparser'
// koa-cors 中间件,用于处理跨域资源共享 (CORS)
import cors from '@koa/cors'
// openai 库,用于与 openai 的 api 进行交互
import OpenAI from 'openai'

// 创建一个 openai 的客户端实例,设置密钥和请求基础 URL
const client = new OpenAI({
    apiKey: 'xxxxxxxxxxxxxxx',
    // gptsapi 会帮我们做openai的请求转发
    baseURL: 'https://api.302.ai/v1'
})
// 创建一个 Koa 应用实例
const app = new Koa()
// 创建一个路由对象的实例
const router = new Router() 

// 使用 koa-bodyparser 中间件来解析请求体
app.use(bodyParser())
// 使用 koa-cors 中间件来处理跨域请求
app.use(cors())

// 定义一个 POST 路由 '/logo', 用于处理图片生成请求
router.post('/logo',async ctx => {
    // console.log(ctx.request.body,'////');
    // 从请求体中解构出标题和描述
    let {title, desc} = ctx.request.body;
    
    const prompt = `
    你是一位资深设计师,
    请为标题为${title},功能为${desc}
    的移动app应用设计一款logo,
    要求 高端大气上档次。
    `
    
    // console.log(title, desc);

    try {
        // 使用 OpenAI 的图像生成 API 生成图片
        const response = await client.images.generate({
            model: 'dall-e-3',
            prompt,
            n: 1
        })
        // 响应成功,构造一个包含图片 URL 的响应体
        ctx.body = {
            url: response.data[0].url,
        }
    } catch (error) {
        // 异常捕获,构造一个错误响应体
        ctx.body = {
            status: 500,
            error: error.message
        }
    }

    // console.log(response.data[0].url);
    
})

// 定义一个 GET 路由 '/', 用于返回一个简单的文本响应
router.get('/',ctx => {
    ctx.body = '首页'
})

// 将路由对象的路由配置到 Koa 应用上
app.use(router.routes())

// 启动 Koa 服务器并监听 3000 端口
app.listen(3000,() => {
    console.log('server is running at http://localhost:3000');
})

来看我们对上面代码的分析:

  • 搭建一个后端服务new Koa() 创建一个 Koa 应用实例,它的实例就是一个后端服务器,它可以用来定义路由、中间件和其他功能,最终用于处理 HTTP 请求并发送响应。

路由 koa-router

  • 服务器端引入路由koa-router 模块,用于创建一个路由实例,路由定义了特定的 URL 路径与处理该路径的函数之间的映射关系,主要分三部分,method(方法),path(路径)和函数(ctx参数),最后通过 app.use(router.routes()) 去进行使用。

ctx 上下文对象

  • 上下文对象 ctx:它是对 Node.js 的原生 requestresponse 对象的一种封装ctx.request 包含了请求信息的对象ctx.response 用于构造响应的对象ctx.body 设置响应体的内容

JSON字符串的解析

  • 中间件 bodyParser ;它用于处理 HTTP 请求的主体部分;因为前端给我们传过来的是一串JSON对象字符串,所以我们要把请求体解析成一个JSON对象拿到数据

CORS

  • CORS 解决同源策略:因为前端跑在5500的端口上,而后端又是在3000端口上,这就导致当前端给后端发接口请求后,后端想要给前端返回响应的数据时,会触发浏览器的同源策略,数据安全保护机制,这就会导致后端响应的数据返回不到前端;因此我们可以通过CORS这样一个手段去解决这个问题。

AI生成效果如下

image.png

小结

为什么前端开发者需要学习AI?答案很简单:AI是大势所趋。AI不仅是技术发展的必然结果,更是前端用户体验的革命性变化。2024年,随着AI的普及,前端开发将不仅仅局限于传统的用户交互,还将涉及到AI生成内容(AIGC)的领域。以生成Logo为例,传统的方法可能需要用户上传文件,然后通过设计工具进行调整。而在AI全栈开发中,前端可以直接通过调用AI模型(如DALL-E 3),实现基于文本生成图像的功能。这种多模态模型不仅支持文本,还可以处理图片、视频和音频,从而为用户提供更加丰富和多样的交互体验