前言
在coze创建bot中,有一个有意思的功能是自动生成机器人图标,那么这个图标是怎么生成的?
毋庸置疑,根据用户输入的bot名称
、功能介绍
生成,那么接下来我们就来实现一下这个功能。调用多模态模型gpt4/gpt4o/专业绘图模型dalle-3
整体思路
前端
通过bootstrap
快速搭建一个页面,通过form表单
收集bot名称、bot功能介绍ajax
发送post
请求,向后端服务器发送数据(提交表单)
后端
,通过koa
搭建服务器,后端端口号3000,前端端口号5500,调用openai dalle3多模态模型
。ai
,安装openai,dotenv管理key,调用接口,选择模型...
- 具体详情后面将详细描述。
frontend(前端)
前端主要就是提供页面的交互、美观,接收用户输入,然后post发送给后端,最后大模型处理了这个信息后得到的图片再在前端展示出来
利用bootstrap快速搭建页面,优点如下:
- 响应式设计:能使网页在不同的设备(如桌面、平板、手机等)上自动适应,提供良好的用户体验。
- 丰富的组件:包含了各种常用的 UI 组件,如导航栏、按钮、表单、模态框等,方便快速开发界面。
- 简洁的样式:提供了一套统一且美观的样式风格,无需过多手动设计样式。
- 文档完善:有详细的文档和丰富的示例,易于学习和使用。
- 社区活跃:拥有庞大的社区,能及时获得支持和更新。
<!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元素获取:
const oForm = document.forms['logoForm']
:从页面中获取名为logoForm
的表单元素。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结构
发送请求:
- 使用
fetch
API 发送一个POST请求到http://localhost:3000/logo
,其中请求头设置为Content-Type: application/json
,并将用户输入的数据作为JSON字符串放入请求体。设置请求头是必要的,相当于告诉浏览器需要解析的是什么样的东西。 body: JSON.stringify(data)
:将JavaScript对象转换成JSON格式的字符串。
响应处理:
.then(res => res.json())
:等待服务器响应,将响应体解析为JSON格式。.then(data => { ... })
:进一步处理解析后的JSON数据。 如果服务器返回的状态码code
为200,说明请求成功,从中提取图标URL。 使用document.createElement('img')
创建一个新的<img>
元素,并设置其src
属性为从服务器获取的图标URL。- 当图片加载完成时(找到最佳的时间点(素养)),
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 | 一分钟注册,轻松订阅海外软件服务
- 我们已经安装过dotenv了
dotenv.config({
path: '.env'
});
- 创建一个.env文件,用于管理我们的敏感信息,比如password,比如key。
- 创建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');
})
- 使用
import
语句引入了koa
框架、Router
路由模块、cors
跨域模块、bodyParser
请求体解析模块以及OpenAI
并配置了环境变量。 - 创建了一个
OpenAI
客户端实例并进行了相关配置。 - 创建了
koa
应用实例和路由实例。 - 为应用挂载了跨域功能和请求体解析功能。
- 在路由中定义了
/logo
的post
路由处理函数,用于接收请求并与OpenAI
交互来生成内容并返回响应,同时处理了可能出现的错误。还定义了/
的get
路由处理函数。 - 通过
app.use(router.routes())
将路由添加到应用中。 - 启动了一个在 3000 端口运行的 HTTP 服务,并在控制台输出相关提示信息。
效果
传统前后端项目,如何引入openai成为AI全栈项目?传统前后端如何引入AI成为AI全栈项目?一个demo让你彻底理解 - 掘金 (juejin.cn)