本文译者为360奇舞团前端开发工程师
原文标题:Building a website gallery with ChatGPT, Stable Diffusion, React and NodeJS
原文作者:Nevo David
原文地址:https://javascript.plainenglish.io/building-a-website-gallery-with-chatgpt-stable-diffusion-react-and-nodejs-afe8cdd9567a
摘要
在本文中,您将学习如何构建一个 Web 应用程序,该应用程序根据你提供的网站描述,使用 ChatGPT 和 Stable Diffusion ,生成图标和合适的域名。
简介
人工智能正在接管世界。这些技术每天都在震撼着我们的世界:ChatGPT 和 Stable Diffusion。
ChatGPT 使用其 GPT3.5 模型回答世界上的任何问题。
Stable Diffusion是一个文本转图片的模型,可以将任何文本转换为图片。
结合使用这两种技术是人工智能的未来。
在本文中,我将向您展示如何通过结合两者来创建整个网站品牌。
我真的很兴奋关于这个技术🤩
什么是 Stable Diffusion?
Stable Diffusion 是一种文本到图像的潜在扩散模型,使用户能够根据给定的文本输入在几秒钟内生成图像。它还用于诸如图像修复和生成图像到图像的等过程。
ChatGPT也是OpenAI训练的一个AI语言模型,用于生成文本以类似人类的对话方式与用户互动。用户可以在几秒钟内提交请求,并从历史、科学、数学和当前事件等广泛的主题中获得信息或问题的答案。
在本文的最后,你将学到如何使用 Stable Diffusion WebUI从文本创建图像,以及如何使用Node.js应用程序向ChatGPT发送消息。
安装和运行稳定版的 Diffusion Web UI
你可以在Windows、Linux、Apple Silicon上下载Stable Diffusion Web UI。在这里,我将指导你在Apple Silicon上完成安装。
前提条件: 确保你的电脑上已经安装了Homebrew,这是一个安装包,可以让你安装Apple未提供的各种应用程序。
打开一个命令行终端,然后输入下面的命令用于下载WebUI的依赖。
MAC:
brew install cmake protobuf rust python@3.10 git wget
Debian-based:
sudo apt install wget git python3 python3-venv
Red Hat-based:
sudo dnf install wget git python3
Arch-based:
sudo pacman -S wget git python3
通过运行以下命令克隆 Web UI 库
git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui
我们需要下载稳定版本的Stable Diffusion 模型(大文件),然后cd进入到
stable-diffusion-webui/models/Stable-diffusion
文件夹。
cd stable-diffusion-webui/models/Stable-diffusion
下载此模型-对于本次的示例我们使用的是Stable Diffusion版本,但是你可以随意下载你想要的其他版本。
wget https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.ckpt
将模型从v1–5-pruned-emaonly.ckpt 重命名为model.ckpt
mv v1–5-pruned-emaonly.ckpt model.ckpt
进入到
stable-diffusion-webui
文件夹并且运行web UI工程,创建虚拟环境并安装依赖项。
cd stable-diffusion-webui
./webui.sh
访问本地URL—
http://127.0.0.1:7860
以通过其用户界面与Web UI交互。在之后要重新启动 Web UI 进程,请进入到终端上的
stable-diffusion-webui
文件夹并运行命令./webui.sh
。如果要使用Web UI API,需要在命令中添加API标志./webui.sh --api
。
构建web应用程序
在本节中,我将指导你创建web应用程序的项目环境,我们将使用React.js做前端,Node.js做后端服务器。
使用下面的代码为web应用程序创建项目的文件夹:
mkdir stable-diffusion-app
cd stable-diffusion-app
mkdir client server
设置 React 应用程序
通过命令进入到client文件夹,然后创建一个新的React.js项目。
cd client
npx create-react-app ./
从React程序中删除冗余的文件,比如logo和测试文件,并且更新App.js
文件以显示”Hello World“,如下所示:
function App() {
return (
<div>
<p>Hello World!</p>
</div>
);
}
export default App;
进入到src/index.css
文件然后拷贝下面的代码,这里面包含此项目需要的所有css样式。
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap");
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: "Space Grotesk", sans-serif;
}
.app,
.loading,
.result__container > div {
display: flex;
align-items: center;
justify-content: center;
}
.app {
width: 100%;
margin: 50px auto;
flex-direction: column;
}
.app > h1 {
margin-bottom: 30px;
color: #2b3467;
}
form {
display: flex;
flex-direction: column;
width: 80%;
}
textarea {
padding: 20px;
border: 1px solid #ddd;
outline: none;
border-radius: 5px;
margin: 5px 0px;
box-shadow: 0 2px 8px 0 rgba(99, 99, 99, 0.2);
}
button {
margin-top: 15px;
display: inline-block;
width: 200px;
padding: 20px;
cursor: pointer;
font-weight: bold;
border: none;
border-radius: 5px;
outline: none;
font-size: 18px;
background-color: #f0dbdb;
}
.loading {
width: 100%;
height: 100vh;
background-color: #fefcf3;
}
.result__container {
display: flex;
align-items: center;
flex-wrap: wrap;
margin-top: 30px;
}
.result__container > div {
margin: 5px;
flex-direction: column;
}
.image {
width: 400px;
height: 300px;
margin-bottom: 15px;
}
更新App.js
文件,显示一个输入字框,允许你输入建议的网站描述。
import React, { useState } from "react";
const App = () => {
const [description, setDescription] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
console.log({ description });
setDescription("");
};
return (
<div className='app'>
<h1>Website Idea Generator</h1>
<form method='POST' onSubmit={handleSubmit}>
<label htmlFor='description'>Enter the description</label>
<textarea
name='description'
rows={6}
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
<button>GENERATE</button>
</form>
</div>
);
};
export default App;
设置Node.js服务器
使用命令行终端进入到server文件夹创建一个package.json
文件
cd server & npm init -y
安装 Express、Nodemon、CORS 库。
npm install express cors nodemon
ExpressJS 是一个快速、极简的框架,在 Node.js 中构建 Web 应用程序它提供了多项功能。CORS是一个Node.js包,允许在不同域之间的通信,Nodemon是一个Node.js工具,可以检测到文件改变的时候重启服务。
创建一个index.js
文件-web服务器的入口
touch index.js
使用ExpressJS设置Node.js服务器,当在浏览器中访问http://localhost:4000/api
时,下面的代码会返回一个json对象
//👇🏻index.js
const express = require("express");
const cors = require("cors");
const app = express();
const PORT = 4000;
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cors());
app.get("/api", (req, res) => {
res.json({
message: "Hello world",
});
});
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
安装 Axios、 非官方 ChatGPT API library、 Puppeteer。ChatGPT API使用Puppeteer作为一个可选的对等依赖,以自动绕过Cloudflare的保护。
npm install chatgpt puppeteer axios
要在 server/index.js
文件中使用 ChatGPT API,您需要对该文件进行配置,以使用require
和 import
关键词来导入库。 因此,更新 server/package.json
文件以包含 type
关键字。
{ "type": "module" }
在 server/index.js
的文件顶部加入下面的代码。
import { createRequire } from "module";
const require = createRequire(import.meta.url);
//...other code statements
完成最后两个步骤之后,你现在可以在index.js
文件中使用ChatGPT
通过在package.json
文件的脚本列表中添加start
命令来配置Nodemon。下面的代码片段使用Nodemon启动服务器。
//In server/package.json
"scripts": {
"test": "echo \\"Error: no test specified\\" && exit 1",
"start": "nodemon index.js"
},
恭喜你!现在你可以通过下面的命令来启动服务器
npm start
如何在 Node.js 应用程序中与 ChatGPT 通信
在本节中,你将学习如何通过非官方的ChatGPT库从Node.js服务器与ChatGPT通信。
该库使用了一个完全自动化的基于浏览器的解决方案,使我们能够爬取我们的方法-这意味着它执行了完全的浏览器自动化,使我们能够登录到OpenAI网站,解决验证码,并通过OpenAI的cookies发送消息。
你在一节中已经安装了库,接下来在index.js
文件中导入ChatGPT API 库如下所示,ChatGPT API使用Puppeteer作为一个可选的对等依赖,以自动绕过Cloudflare的保护。
import { ChatGPTAPIBrowser } from "chatgpt"
我们需要ChatGPT,根据用户指定的任何描述生成一个域名,并为Stable Diffusion API创建一个提示符。
因此,在服务器上创建一个路由,接受来自React应用程序的描述。
app.post("/api", async (req, res) => {
const { prompt } = req.body;
console.log(prompt);
});
在React 应用程序中创建一个函数,当用户提交表单,就将描述信息发到服务器上的/api
端点。
async function sendDescription() {
try {
const request = await fetch("http://localhost:4000/api", {
method: "POST",
body: JSON.stringify({
prompt: description,
}),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
const res = await request.json();
console.log(res);
} catch (err) {
console.error(err);
}
}
在React 应用程序中添加一个加载状态,用于保存请求状态,并在提交表单后调用async函数。
const [description, setDescription] = useState("");
const [loading, setLoading] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
//👇🏻 calls the async function
sendDescription();
setDescription("");
setLoading(true);
};
更新/api
端点以将描述发送给ChatGPT,并生成一个域名并给Stable Diffusion提示。
async function chatgptFunction(content) {
try {
const api = new ChatGPTAPIBrowser({
email: "YOUR_CHATGPT_EMAIL_ADDRESS",
password: "YOUR_CHATGPT_PASSWORD",
});
await api.initSession();
//👇🏻 sends the instruction for the domain name to ChatGPT
const getDomainName = await api.sendMessage(
`Can you generate a domain name for a website about: ${content}`
);
let domainName = getDomainName.response;
//👇🏻 sends the instruction for the prompt to ChatGPT
const generatePrompt = await api.sendMessage(
`I have a website for ${content}, and I want to generate a logo for it, can you generate a prompt for dall-e for me? make it long like 50 words, you don't need to tell me why you generated the prompt`
);
const diffusionPrompt = generatePrompt.response;
console.log({ domainName, diffusionPrompt });
} catch (err) {
console.error(err);
}
}
app.post("/api", async (req, res) => {
const { prompt } = req.body;
const result = await chatgptFunction(prompt);
res.json({ message: "Retrieved successfully!" });
});
在上面的代码中使用Puppeteer 启动浏览器,并自动登录你的ChatGPT账号,验证完成后,ChatGPT 处理请求并返回响应信息。
在下面的部分,我将指导你如何将ChatGPT生成的提示发送到Stable Diffusion API。
如何与 Stable Diffusion API 交互
要与Stable Diffusion API进行交互,请通过下面的命令重启web UI 进程。
cd stable-diffusion-webui
./webui.sh --api
你可以在http://127.0.0.1:7860/docs
,查看可用的API端点。 我们将利用/sdapi/v1/txt2img
端点进行文本到图像的转换。
使用生成的提示作为payload向 /sdapi/v1/txt2img
端点发送POST请求。
async function chatgptFunction(content) {
try {
const api = new ChatGPTAPIBrowser({
email: "asaoludavid234@yahoo.com",
password: "davidasaolu",
});
await api.initSession();
const getDomainName = await api.sendMessage(
`Can you generate a domain name for a website about: ${content}`
);
let domainName = getDomainName.response;
const generatePrompt = await api.sendMessage(
`I have a website for ${content}, and I want to generate a logo for it, can you generate a prompt for dall-e for me? make it long like 50 words, you don't need to tell me why you generated the prompt`
);
const diffusionPrompt = generatePrompt.response;
//👇🏻 Makes a POST request via Axios with the prompt as the payload
const request = await axios.post("http://127.0.0.1:7860/sdapi/v1/txt2img", {
prompt: diffusionPrompt,
});
//👇🏻 returns the generated logo and the domain name
let logoImage = await request.data.images;
return { logoImage, domainName };
} catch (err) {
console.error(err);
}
}
从上面的代码中, /sdapi/v1/txt2img
端点接收一个名为prompt的必须参数 - 要生成图片的文本描述。
更新 Node.js 服务器上的 /api 端点并保存结果,将其发送到 React.js 应用程序。
使用React 程序展示结果
更新 sendDescription
函数,以接收服务器返回的响应结果。
//👇🏻 React state that holds the result
const [result, setResult] = useState([]);
async function sendDescription() {
try {
const request = await fetch("http://localhost:4000/api", {
method: "POST",
body: JSON.stringify({
prompt: description,
}),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
const res = await request.json();
if (res.message) {
//👇🏻 update the loading and result states
setLoading(false);
setResult(res.result);
}
} catch (err) {
console.error(err);
}
}
创建一个Loading组件,在请求等待的过程中显示给用户。
import React from "react";
const Loading = () => {
return (
<div className='loading'>
<h1>Loading, please wait...</h1>
</div>
);
};
export default Loading;
添加下面的代码当请求等待的过程中展示组件。
if (loading) return <Loading />;
更新组件以渲染生成的结果,如下所示。
return (
<div className='app'>
<h1>Website Idea Generator</h1>
<form method='POST' onSubmit={handleSubmit}>
<label htmlFor='description'>Enter the description</label>
<textarea
name='description'
rows={6}
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
<button>GENERATE</button>
</form>
<div className='result__container'>
{result.length > 0 &&
result.map((item, index) => (
<div key={index}>
<img
src={`data:image/png;base64,${item.logoImage}`}
alt={item.domainName}
className='image'
/>
<p>Domain: {item.domainName}</p>
</div>
))}
</div>
</div>
);
上面的代码展示为各样的请求生成图标和域名,恭喜!🎉 你完成了本项目的教程。
以下是鸡尾酒网站获得的结果示例:
结论:
到目前为止,你已经学会了:
什么是Stable Diffusion,
如何在你的电脑上安装和配置Stable Diffusion
如何从Node.js 应用发送消息给ChatGPT
如何通过Stable Diffusion API 从文本生成图像。
本教程带领你完成一个应用程序示例,你可以使用Stable Diffusion和ChatGPT构建应用程序,这些AI技术可以被应用在各个领域创建强大的应用程序。
这个教程的源代码在这里:
https://github.com/novuhq/blog/tree/main/webapp-with-stable-diffusion-and-chatgpt
感谢你的阅读!
- END -
关于奇舞团
奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。