在最近的学习中,我学会了JavaScript加上大模型的开发。相信这肯定是未来发展的趋势。我将围绕"Logo随机生成"这一主题,深入浅出地介绍AI全栈开发的基本概念、关键技术点,以及如何通过实战项目融合前端、后端以及AI技术,创造一个既富有创新又具有实用价值的应用实例。
AI全栈开发概述
AI全栈开发是指开发者不仅要掌握前端(如网页或移动应用界面)和后端(如服务器逻辑与数据库交互)的技术,还要具备运用AI算法和框架的能力,从而在项目中实现智能化的功能。这一过程涵盖了数据处理、模型训练、API设计、用户界面构建等多个环节,要求开发者具备全方位的技术栈和跨领域的协作能力。
前端技术基础
在项目的前端部分,我使用了Bootstrap CSS框架来快速搭建响应式页面。通过编写HTML和JavaScript代码,我实现了表单的布局和交互功能。以下是我在前端开发中的一些亮点:
- 我使用了.container、.row、.col类来实现灵活的网格布局,使得页面在不同设备上都能保持良好的展示效果。
- 通过设置placeholder和required属性,我提高了表单的易用性和数据的有效性。
- 我编写了JavaScript代码,使用fetch API向后端发送数据,并在页面上动态显示生成的Logo,实现了无刷新的页面更新。
代码示例:
- html
html
<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="请输入名称"
required>
</div>
<div class="form-group">
<label for="titleInput">Bot功能介绍</label>
<textarea name="desc" class="form-control" row='3' id="descInoput"></textarea>
</div>
<div class="form-group">
<button name="logoBtn" type="submit" class="btn btn-primary">生成LOGO</button>
</div>
</form>
<div class="col-md-6" id="result">
</div>
</div>
</div>
</div>
代码亮点
-
表单结构清晰: 表单使用了.form-group包裹每个输入元素,保持了代码的组织性和可读性。这对于维护和后续开发非常有利。
-
用户友好: 输入框设置了placeholder提示信息,帮助用户理解需要输入的内容。同时,对Bot名称的输入框应用了required属性,确保数据的有效性,减少了后台处理无效数据的可能性。
-
动态内容预留:
这一部分没有直接填充内容,而是预留了一个ID为"result"的div,通过JavaScript动态地在这个区域显示生成的Logo。这样的做法有利于页面的性能优化和内容的实时更新,提升了页面的动态交互能力。
- js
js
<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['logoBtn'];
btn.disabled = true;
const desc = this['desc'].value.trim();
// HTTP协议
// 请求行 localhost:3000/logo POST
// 请求头 Content-Type: application/json;charset=UTF-8
// 请求体
// 前后端交互的数据格式是json
// 输出的是二进制或字符串
let data = {
title,
desc
};
fetch('http://localhost:3000/logo', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
body: JSON.stringify(data)
}).then(res => {
console.log(2);
return res.json()
})
.then(data => {
btn.disabled = false;
console.log(1);
if(data.status == 200){
let url = data.url
document.getElementById("result").innerHTML += `<img src="${url}" alt="">`;
}
})
});
</script>
代码亮点
-
数据验证 :在提交表单前,通过
this['title'].value.trim()
获取并清理标题输入值,然后检查是否为空,这是一种基本但重要的前端验证,有助于减少不必要的服务器请求。 -
按钮状态管理 :在发起请求前后改变按钮的
disabled
状态,防止用户重复点击提交,这是提升用户体验的一个小细节,也保证了数据的一致性。 -
Fetch API使用 :采用现代化的
fetch
函数进行HTTP请求,替代了老旧的XMLHttpRequest,代码更简洁易读。通过设置请求方法(method: 'POST'
)、请求头(headers
)以及请求体(body
),向服务器发送JSON格式的数据,符合现代Web开发的最佳实践。 -
动态内容更新 :根据服务器响应动态地在页面上插入图片(
<img src="${url}" alt="">
),使用模板字符串方便地构造HTML片段并插入到DOM中,实现了无刷新的页面更新效果。
后端技术与架构
在后端部分,我使用了Node.js和Koa框架来构建服务。我学习了如何定义API路径、处理跨域问题,并且与AI模型进行交互。以下是我在后端开发中的一些关键步骤:
我定义了一个/logo的POST接口,用于接收前端传来的Logo生成请求。 使用OpenAI的API,我根据用户输入的信息生成了Logo图像,并将图像的URL返回给前端。 我还处理了可能出现的错误,确保了服务的稳定性。
代码示例:
js
router.post('/logo', async (ctx) => {
try {
let { title, desc } = ctx.request.body
console.log(title, desc);
const prompt = `
你是一位资深的设计师,
请你为标题为${title},功能为${desc}的移动端app应用设计一款logo,
要求,高端大气上档次。
`
const response = await client.images.generate({
model: 'dall-e-3',
prompt,
n: 1
})
ctx.body = {
status: 200,
url: response.data[0].url
}
console.log(response.data[0].url);
} catch (error) {
ctx.body = {
status: 500,
msg: '服务器错误'
}
}
})
-
构造提示文本(prompt): 使用解构出来的title和desc,构造一个描述性的字符串(prompt),这个字符串作为指令给到AI模型,告诉它要设计一个怎样的Logo。例如,如果title是"智能助手",desc是"提供日常信息查询服务",那么生成的prompt就会是要求设计一个针对名为"智能助手",具有日常信息查询功能的高端大气上档次的移动端APP Logo。
-
调用OpenAI API生成图片: 接下来,使用之前初始化的OpenAI客户端(client)调用images.generate方法。这个方法需要几个参数,其中model指定了要使用的模型(这里是'dall-e-3',OpenAI的一个图像生成模型),prompt就是前面构造的描述文本,而n: 1表示只需要生成一张图片。
-
处理响应并返回结果: 当从OpenAI API得到响应后,从中提取第一个生成的图片的URL(response.data[0].url),然后把这个URL连同HTTP状态码200一起作为响应体(ctx.body)返回给前端。这意味着前端将会收到一个成功的响应,其中包含新生成Logo的直接链接。
实战项目
在这个项目中,前端用户通过一个简洁的表单提交Logo的名称和功能介绍,表单提交后通过JavaScript的fetch
API向后端发送POST请求,携带JSON格式的数据。后端Koa应用接收到请求后,使用OpenAI客户端根据用户提供的信息生成Logo图像,并以JSON格式返回图像的URL。前端接收到这个URL后,在页面上动态加载显示生成的Logo。
完整代码如下:
- html
js
<!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;
}
</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" class="form-control" id="titleInput" name="title" placeholder="请输入名称"
required>
</div>
<div class="form-group">
<label for="titleInput">Bot功能介绍</label>
<textarea name="desc" class="form-control" row='3' id="descInoput"></textarea>
</div>
<div class="form-group">
<button name="logoBtn" type="submit" class="btn btn-primary">生成LOGO</button>
</div>
</form>
<div class="col-md-6" id="result">
</div>
</div>
</div>
</div>
<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['logoBtn'];
btn.disabled = true;
const desc = this['desc'].value.trim();
// HTTP协议
// 请求行 localhost:3000/logo POST
// 请求头 Content-Type: application/json;charset=UTF-8
// 请求体
// 前后端交互的数据格式是json
// 输出的是二进制或字符串
let data = {
title,
desc
};
fetch('http://localhost:3000/logo', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
body: JSON.stringify(data)
}).then(res => {
console.log(2);
return res.json()
})
.then(data => {
btn.disabled = false;
console.log(1);
if(data.status == 200){
let url = data.url
document.getElementById("result").innerHTML += `<img src="${url}" alt="">`;
}
})
});
</script>
</body>
</html>
- node后端
js
import Koa from 'koa' // 后端极简框架
import Router from 'koa-router'
import cor from '@koa/cors'
import { bodyParser } from '@koa/bodyparser'
import OpenAI from "openai";
const client = new OpenAI({
apiKey: 'your-api-key',
baseURL: 'https://api.302.ai/v1'
})
// web 服务就是一个app
const app = new Koa()
const router = new Router()
app.use(cor())
app.use(bodyParser())
router.get('/', (ctx) => {
ctx.body = '首页'
})
router.post('/logo', async (ctx) => {
try {
let { title, desc } = ctx.request.body
console.log(title, desc);
const prompt = `
你是一位资深的设计师,
请你为标题为${title},功能为${desc}的移动端app应用设计一款logo,
要求,高端大气上档次。
`
const response = await client.images.generate({
model: 'dall-e-3',
prompt,
n: 1
})
ctx.body = {
status: 200,
url: response.data[0].url
}
console.log(response.data[0].url);
} catch (error) {
ctx.body = {
status: 500,
msg: '服务器错误'
}
}
})
app.use(router.routes())
app.listen(3000, () =>
console.log('server listen on port http://localhost:3000')
)
运行成果:
总结
本项目"手写Logo随机生成"充分展示了AI全栈开发的魅力,通过整合前端、后端与AI技术,创造了一个既富有趣味性的应用实例。