在充满活力的技术领域中,创新不断塑造着可能的边界,而人工智能(AI)从未停止过吸引我们的想象力。
人工智能是指计算机系统对人类智能过程的模拟。这些过程包括学习、推理、解决问题、感知、语言理解和决策等任务。
如今,个人和公司已经开发并训练出了多个人工智能模型,可以比人类更好地实时执行某些任务。在人工智能的无数应用中,一个特别引人关注的领域是人工智能驱动的图像生成。
您正在构建的内容
本指南介绍如何构建一个 React 应用程序,通过 Node.js 后端与 OpenAI DALL-E API 无缝集成,并根据文本提示生成图像。
运行中的人工智能图像生成器,使用 DALL-E API 生成生动而富有创意的图像。
要参与本项目,您应具备以下条件
- 对 HTML、CSS 和 JavaScript 有基本了解
- React 和 Node.js 的基础知识
- 计算机上安装了 Node.js 和 npm(Node 包管理器)或 yarn
什么是 OpenAI DALL-E API?
OpenAI API 是一个基于云的平台,它允许开发者访问 OpenAI 预先训练好的人工智能模型,如 DALL-E 和 GPT-3(我们使用该模型在此 Git 仓库中的代码构建了 ChatGPT 克隆版)。它允许开发人员在程序中添加摘要、翻译、图像生成和修改等人工智能功能,而无需开发和训练自己的模型。
要使用 OpenAI API,请使用 Google 账户或电子邮件在 OpenAI 网站上创建一个账户,并获取一个 API 密钥。要生成 API 密钥,请单击网站右上角的 “Personal“,然后选择 “View API keys“。
创建 OpenAI API 密钥的过程。
单击 “Create new secret key” 按钮,并将密匙保存在某处。您将在本应用程序中使用它与 OpenAI 的 DALL-E API 进行交互。
设置开发环境
您可以从头开始创建 React 应用程序并开发自己的界面,也可以按照以下步骤获取我们的 Git 启动模板:
- 访问本项目的 GitHub 仓库。
- 选择 “Use this template“>”Create a new repository“,将启动代码复制到 GitHub 账户中的仓库(选中复选框以包含所有分支)。
- 将仓库拉到本地电脑,然后使用命令切换到 starter-files 分支:
git checkout starter-files
。 - 运行
npm install
命令安装必要的依赖项。
安装完成后,就可以在本地电脑上使用 npm run start
启动项目。这样,项目就可以在 http://localhost:3000/ 上运行了。
AI 图像生成器应用程序的用户界面,展示了人工智能在图像创建方面的强大功能。
在本项目中,我们为 React 应用程序添加了所有必要的依赖项。以下是已安装内容的概览:
- file-server:该实用库简化了下载生成图片的过程。它与下载按钮相连,确保了流畅的用户体验。
- uuid:该库为每张图片分配一个唯一标识。这可以防止图像共享相同的默认文件名,从而保持秩序和清晰度。
- react-icons:该库集成到项目中,可以毫不费力地整合图标,增强应用程序的视觉吸引力。
React 应用程序的核心是 src 文件夹。这里存放着 Webpack 的基本 JavaScript 代码。让我们来了解一下 src 文件夹中的文件和文件夹:
- assets:在此目录中,您可以找到整个项目中使用的图片和加载器 gif。
- data:该文件夹包含一个 index.js 文件,可导出 30 个提示数组。这些提示可用于生成各种随机图片。请随意编辑。
- index.css:这里存储了本项目中使用的样式。
了解 Utils 文件夹
在该文件夹中,index.js 文件定义了两个可重复使用的函数。第一个函数会随机选择描述可生成的各种图像的提示。
import { randomPrompts } from '../data'; export const getRandomPrompt = () => { const randomIndex = Math.floor(Math.random() * randomPrompts.length); const randomPrompt = randomPrompts[randomIndex]; return randomPrompt; }
第二个函数利用 file-saver 依赖关系处理生成图像的下载。这两个函数的创建都是为了提供模块化和高效性,在需要时可以方便地导入到组件中。
import FileSaver from 'file-saver'; import { v4 as uuidv4 } from 'uuid'; export async function downloadImage(photo) { const _id = uuidv4(); FileSaver.saveAs(photo, `download-${_id}.jpg`); }
在上面的代码中,uuid 属性为每个生成的图像文件提供了一个唯一的 ID,因此它们不会有相同的文件名。
了解组件
组件是分隔开来的小代码块,使代码易于维护和理解。本项目创建了三个组件: Header.jsx、Footer.jsx 和 Form.jsx。主要组件是表单组件,在该组件中,输入被接收并传递到 App.jsx 文件,generateImage
函数被添加为 Generate Image 按钮的 onClick
事件。
在表单组件中,创建了一个状态来存储和更新提示。此外,您还可以通过点击随机图标来生成随机提示。这是通过 handleRandomPrompt
函数实现的,该函数使用了已设置的 getRandomPrompt
函数。当你点击图标时,它会获取随机提示并更新状态:
const handleRandomPrompt = () => { const randomPrompt = getRandomPrompt(); setPrompt(randomPrompt) }
了解 App.jsx 文件
大部分代码都在这里。所有组件都集中在这里。还有一个指定区域用于显示生成的图片。如果尚未生成图像,则会显示一个占位符图像(预览图像)。
在该文件中,有两种状态需要管理:
isGenerating
: 用于跟踪图像当前是否正在生成。默认设置为 false。generatedImage
: 该状态存储已生成图像的相关信息。
此外,还导入了 downloadImage
实用程序函数,使您可以在单击 Download 按钮时触发生成图像的下载:
<button className="btn" onClick={() => downloadImage(generatedImage.photo)} >
现在,您已经了解了启动文件并设置了项目。让我们开始处理这个应用程序的逻辑。
使用 OpenAI 的 DALL-E API 生成图像
要利用 OpenAI 的 DALL-E API 功能,您需要使用 Node.js 建立一个服务器。在该服务器中,您将创建一个 POST 路由。该路由将负责接收从 React 应用程序发送的提示文本,然后利用它生成图像。
要开始工作,请运行以下命令在项目目录中安装必要的依赖项:
npm i express cors openai
此外,将以下依赖项安装为开发依赖项。这些工具将帮助您设置 Node.js 服务器:
npm i -D dotenv nodemon
已安装的依赖项说明如下:
- express: 该库有助于在 Node.js 中创建服务器。
- cors: CORS 可促进不同域之间的安全通信。
- openai: 通过该依赖关系,您可以访问 OpenAI 的 DALL-E API。
- dotenv: dotenv 协助管理环境变量。
- nodemon: nodemon 是一种开发工具,可监控文件的变化并自动重启服务器。
安装成功后,在项目根目录下创建 server.js 文件。所有服务器代码都将存放在这里。
在 server.js 文件中,导入刚安装的库并将其实例化:
// Import the necessary libraries const express = require('express'); const cors = require('cors'); require('dotenv').config(); const OpenAI = require('openai'); // Create an instance of the Express application const app = express(); // Enable Cross-Origin Resource Sharing (CORS) app.use(cors()); // Configure Express to parse JSON data and set a data limit app.use(express.json({ limit: '50mb' })); // Create an instance of the OpenAI class and provide your API key const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); // Define a function to start the server const startServer = async () => { app.listen(8080, () => console.log('Server started on port 8080')); }; // Call the startServer function to begin listening on the specified port startServer();
在上面的代码中,你需要导入必要的库。然后,使用 const app = express();
建立一个 Express 应用程序实例。然后,启用 CORS。接下来,配置 Express 以处理传入的 JSON 数据,并指定数据大小限制为 50MB
。
随后,使用 OpenAI API 密钥创建 OpenAI 类实例。在项目根目录下创建 .env 文件,并使用 OPENAI_API_KEY
变量添加 API 密钥。最后,定义异步 startServer
函数并调用它来启动服务器。
现在你已经配置好了 server.js 文件。让我们创建一个 POST 路由,您可以在 React 应用程序中使用该路由与服务器交互:
app.post('/api', async (req, res) => { try { const { prompt } = req.body; const response = await openai.images.generate({ prompt, n: 1, size: '1024x1024', response_format: 'b64_json', }); const image = response.data[0].b64_json; res.status(200).json({ photo: image }); } catch (error) { console.error(error); } });
在这段代码中,路由设置为 /api
,旨在处理传入的 POST 请求。在路由的回调函数中,您将使用 req.body
接收到从 React 应用程序发送的数据,特别是 prompt
值。
随后,会调用 OpenAI 库的 images.generate
方法。该方法接收所提供的提示并生成图像作为响应。n
等参数决定了要生成的图片数量(这里只有一张),size
指定了图片的尺寸,response_format
则指示了应提供的响应格式(本例中为 b64_json
)。
生成图片后,从响应中提取图片数据并存储到 image
变量中。然后,使用 res.status(200).json({ photo: image })
向 React 应用程序发送包含生成的图像数据的 JSON 响应,并将 HTTP 状态设置为 200
(表示成功)。
如果在此过程中出现任何错误,将执行 catch
代码块中的代码,并将错误记录到控制台以便调试。
现在服务器已经准备就绪!让我们在 package.json 文件 scripts
对象中指定用于运行服务器的命令:
"scripts": { "dev:frontend": "react-scripts start", "dev:backend": "nodemon server.js", "build": "react-scripts build", },
现在运行 npm run dev:backend
时,服务器将在 http://localhost:8080/ 上启动,而运行 npm run dev:frontend
时,React 应用程序将在 http://localhost:3000/ 上启动。确保两者在不同的终端运行。
从 React 向 Node.js 服务器发出 HTTP 请求
在 App.jsx 文件中,您将创建一个 generateImage
函数,当点击 Form.jsx 组件中的 Generate Image(生成图片)按钮时触发该函数。该函数接受两个参数:来自 Form.jsx 组件的 prompt
和 setPrompt
。
在 generateImage
函数中,向 Node.js 服务器发出 HTTP POST 请求:
const generateImage = async (prompt, setPrompt) => { if (prompt) { try { setIsGenerating(true); const response = await fetch( 'http://localhost:8080/api', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ prompt, }), } ); const data = await response.json(); setGeneratedImage({ photo: `data:image/jpeg;base64,${data.photo}`, altText: prompt, }); } catch (err) { alert(err); } finally { setPrompt(''); setIsGenerating(false); } } else { alert('Please provide proper prompt'); } };
在上面的代码中,您要检查 prompt
参数是否有值,然后将 isGenerating
状态设为 true
,因为操作正在开始。这将使加载器显示在屏幕上,因为在 App.jsx 文件中,我们有这段代码控制加载器的显示:
{isGenerating && ( <div> className="loader-comp"> <img src={Loader} alt="" className='loader-img' /> </div> )}
接下来,使用 fetch()
方法,使用 http://localhost:8080/api 向服务器发出 POST 请求–这就是我们安装 CORS 的原因,因为我们正在与另一个 URL 上的 API 交互。我们使用提示作为消息正文。然后,提取 Node.js 服务器返回的响应,并将其设置为 generatedImage
状态。
一旦 generatedImage
状态有了值,图片就会显示出来:
{generatedImage.photo ? ( <img src={generatedImage.photo} alt={generatedImage.altText} className="imgg ai-img" /> ) : ( <img src={preview} alt="preview" className="imgg preview-img" /> )}
这就是 App.jsx 文件的完整内容:
import { Form, Footer, Header } from './components'; import preview from './assets/preview.png'; import Loader from './assets/loader-3.gif' import { downloadImage } from './utils'; import { useState } from 'react'; const App = () => { const [isGenerating, setIsGenerating] = useState(false); const [generatedImage, setGeneratedImage] = useState({ photo: null, altText: null, }); const generateImage = async (prompt, setPrompt) => { if (prompt) { try { setIsGenerating(true); const response = await fetch( 'http://localhost:8080/api', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ prompt, }), } ); const data = await response.json(); setGeneratedImage({ photo: `data:image/jpeg;base64,${data.photo}`, altText: prompt, }); } catch (err) { alert(err); } finally { setPrompt(''); setIsGenerating(false); } } else { alert('Please provide proper prompt'); } }; return ( <div className='container'> <Header /> <main className="flex-container"> <Form generateImage={generateImage} prompt={prompt} /> <div className="image-container"> {generatedImage.photo ? ( <img src={generatedImage.photo} alt={generatedImage.altText} className="imgg ai-img" /> ) : ( <img src={preview} alt="preview" className="imgg preview-img" /> )} {isGenerating && ( <div className="loader-comp"> <img src={Loader} alt="" className='loader-img' /> </div> )} <button className="btn" onClick={() => downloadImage(generatedImage.photo)} > Download </button> </div> </main> <Footer /> </div> ); }; export default App;
将您的全栈应用程序部署到 Kinsta
到目前为止,您已经成功构建了一个能与 Node.js 交互的 React 应用程序,这使它成为一个全栈应用程序。现在让我们将此应用程序部署到 Kinsta。
首先,配置服务器,以便为 React 应用程序构建过程中生成的静态文件提供服务。这可以通过导入 path
模块并使用它来提供静态文件来实现:
const path = require('path'); app.use(express.static(path.resolve(__dirname, './build')));
当您执行 npm run build && npm run dev:backend
命令时,您的全栈 React 应用程序将加载到 http://localhost:8080/。这是因为 React 应用程序已编译成 build 文件夹中的静态文件。然后,这些文件将作为静态目录并入 Node.js 服务器。因此,当您运行 Node 服务器时,就可以访问应用程序。
在将代码部署到您选择的 Git 提供商(Bitbucket、GitHub 或 GitLab)之前,请记住修改 App.jsx 文件中的 HTTP 请求 URL。将 http://localhost:8080/api
改为 /api
,因为 URL 将被预输入。
最后,在 package.json
文件中,为用于部署的 Node.js 服务器添加一个脚本命令:
"scripts": { // … "start": "node server.js", },
接下来,按照以下步骤将代码推送到您首选的 Git 提供商,并将您的仓库部署到 Kinsta:
- 在 MyKinsta 面板上登录您的 Kinsta 账户。
- 选择左侧边栏上的 Application ,然后单击 “Add Application” 按钮。
- 在出现的模态中,选择要部署的版本库。如果有多个分支,可以选择所需的分支并为应用程序命名。
- 从可用的数据中心位置中选择一个。
- 将
OPENAI_API_KEY
添加为环境变量。Kinsta 会自动为你设置一个 Dockerfile。 - 最后,在启动命令字段中添加
npm run build && npm run start
。Kinsta 会从 package.json 安装应用程序的依赖项,然后构建并部署应用程序。
小结
小结在本指南中,您将学习如何利用 OpenAI 的 DALL-E API 的强大功能来生成图像。您还学会了如何使用 React 和 Node.js 构建基本的全栈应用程序。
人工智能的可能性是无限的,因为每天都有新的模型问世,您可以创建令人惊叹的项目,并将其部署到应用程序托管中。
评论留言