如何获取文心一言API密钥(分步指南)
如何使用Spring AI、React和Docker构建AI聊天机器人
嘿,Java开发者们,我有个好消息:Spring 现在正式支持使用 Spring AI 模块构建 AI 应用程序。
在本教程中,我们将使用 Spring Boot、React、Docker 和 OpenAI 构建一个聊天机器人应用程序。此应用程序将允许用户与 AI 驱动的聊天机器人互动、提出问题并实时接收回复。
本文中提到的整个源代码已经在 GitHub 存储库中提供。
为了让你对我们将要构建的内容有个概念,最终应用程序将如下所示:
你兴奋吗?让我们从头开始构建它!
先决条件
在开始构建聊天机器人之前,你需要了解一些基础知识:
- 对 Java 和 Spring Boot 有基本的了解。
- 对 React 和 CSS 有基本的了解。
- 将 JDK、Node Package Manager 和 Docker 安装到您的计算机上。
获取您的 OpenAI 密钥
首先,如果您没有 OpenAI 帐户,则需要注册一个 OpenAI 帐户。登录后,您将被带到主页。
在右上角,单击 “Dashboard” 菜单。在侧边栏上,单击“API Keys”,然后单击“Create new secret key”按钮以生成您的密钥:
复制密钥并将其保存在安全的地方,因为您稍后需要它来将您的应用程序连接到 OpenAI API。
您可以浏览 OpenAI API 参考指南,了解更多关于如何调用API、它接受哪些请求以及它给出的响应的更多信息。
在 Spring Boot 中构建 REST API
让我们转到 spring initializer 以生成样板代码:
您可以提供您选择的组、构件、名称、描述和包。我们使用 Maven 作为构建工具,使用 Spring Boot 版本 3.3.3,使用 Jar 作为打包选项,并使用 Java 版本 17。
点击生成按钮,将下载 zip。解压缩文件并将它们作为 Maven 项目导入到您最喜欢的 IDE 中(我的是 Intellij)。
在 Spring 中配置您的 OpenAI 密钥
你可以使用现有的application.properties文件或创建一个application.yaml文件。我喜欢使用 Yaml,所以我创建了一个application.yaml文件,我可以在其中放置我所有的 Spring Boot 配置。
将OpenAIKey、Model和Temperature添加到你的application.yaml文件中:
spring:
ai:
openai:
chat:
options:
model: "gpt-3.5-turbo"
temperature: "0.7"
key: "PUT YOUR OPEN_API_KEY HERE"
在application.properties中的类似配置可能如下所示:
spring.ai.openai.chat.options.model=gpt-3.5-turbo
spring.ai.openai.chat.options.temperature=0.7
spring.ai.openai.key="PUT YOUR OPEN_API_KEY HERE"
构建 ChatController
让我们创建一个带有URL /ai/chat/string的GET API和一个处理逻辑的方法:
@RestController
public class ChatController {
@Autowired
private final OpenAiChatModel chatModel;
@GetMapping("/ai/chat/string")
public Flux<String> generateString(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return chatModel.stream(message);
}
}
- 首先,我们在ChatController类上添加@RestController注解以将其标记为我们Spring控制器。
- 然后,我们注入了OpenAiChatModel类的依赖项。然后,我们注入了OpenAiChatModel类的依赖项。它作为Spring AI依赖项的一部分可以立即使用。
- OpenAiChatModel类有一个stream(message)方法,该方法接受提示作为字符串并返回一个字符串响应(技术上讲,它是一个Flux,因为我们使用了相同的方法的响应式版本)。
- 在内部,OpenAiChatModel.stream(message)将调用OpenAI API并从那里获取响应。OpenAI调用将使用你在application.yaml文件中提到的配置文件,因此请确保使用有效的OpenAI密钥。
- 我们已经创建了一个方法来处理GET API调用,该方法接受消息并返回Flux作为响应。
构建、运行和测试 REST API
使用 maven 命令构建并运行 Spring Boot 应用程序:
./mvnw clean install spring-boot:run
理想情况下,它会在8080端口上运行,除非你已自定义端口。确保该端口空闲以便成功运行应用程序。
你可以使用Postman或Curl命令来测试你的REST API:
curl --location 'http://localhost:8080/ai/chat/string?message=How%20are%20you%3F'
使用 React.js 构建 ChatUI
为了本教程,我们将使它非常简单和容易,所以请原谅我没有遵循任何React的最佳实践。
创建App.js来管理ChatUI表单
我们将使用useState来管理状态:
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [loading, setLoading] = useState(false);
messages
:它将存储聊天中的所有消息。每条消息都有文本内容和发送者(要么是’user’(用户),要么是’ai’(人工智能))。input
:用于存储用户在文本框中输入的内容。loading
:当聊天机器人正在等待AI的响应时,此状态设置为true,收到响应后设置为false。
创建handleSend函数:当用户点击按钮或按下Enter键发送消息时调用此函数。
const handleSend = async () => {
if (input.trim() === '') return;
const newMessage = { text: input, sender: 'user' };
setMessages([...messages, newMessage]);
setInput('');
setLoading(true);
try {
const response = await axios.get('http://localhost:8080/ai/chat/string?message=' + input);
const aiMessage = { text: response.data, sender: 'ai' };
setMessages([...messages, newMessage, aiMessage]);
} catch (error) {
console.error("Error fetching AI response", error);
} finally {
setLoading(false);
}
};
以下是逐步发生的事情:
- 检查空输入:如果输入字段为空,则函数会提前返回(不发送任何内容)。
- 用户发送新消息:一条新消息会被添加到消息数组中。这条消息包含用户输入的文本,并被标记为由’user’(用户)发送。
- 重置输入:发送消息后,输入字段将被清除。
- 开始加载:在等待AI响应的过程中,加载状态被设置为true,以显示加载指示器。
- 发起API请求:代码使用axios来请求AI聊天机器人API,并传递用户的消息。当收到响应时,AI的一条新消息会被添加到聊天中。
- 错误处理:如果获取AI响应时出现问题,则会在控制台记录一个错误。
- 停止加载:最后,加载状态被关闭。
现在,我们来编写一个函数,以便用户在输入字段中输入内容时更新输入状态:
const handleInputChange = (e) => {
setInput(e.target.value);
};
这个函数会监听输入字段的变化,并将新的输入值存储到状态中,以便后续使用。每当用户在输入框中输入或删除字符时,这个函数都会被调用。
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
handleSend();
}
};
现在让我们创建 UI 元素来呈现聊天消息:
{messages.map((message, index) => (
<div key={index} className={`message-container ${message.sender}`}>
<img
src={message.sender === 'user' ? 'user-icon.png' : 'ai-assistant.png'}
alt={`${message.sender} avatar`}
className="avatar"
/>
<div className={`message ${message.sender}`}>
{message.text}
</div>
</div>
))}
此区块呈现聊天中的所有消息:
- 通过消息映射:使用
.map()
方法遍历消息数组,将每条消息以div
的形式显示出来。 - 消息样式:根据发送者(用户或AI)的不同,为消息设置不同的类名,从而清晰地表明消息的发送者。
- 头像图像:每条消息都显示一个小头像,用户和AI的头像图片不同。
接下来,让我们创建一些逻辑,根据一个标志(flag)来显示加载器:
{loading && (
<div className="message-container ai">
<img src="ai-assistant.png" alt="AI avatar" className="avatar" />
<div className="message ai">...</div>
</div>
)}
当AI正在思考(即加载状态为true时),我们显示一个加载消息(例如“…”),以便用户知道响应很快就会到来。...
最后,创建一个按钮来触发发送消息的操作:
<button onClick={handleSend}>
<FaPaperPlane />
</button>
这个按钮在被点击时会触发handleSend()
函数。这里使用的图标是一张纸飞机,它是“发送”按钮的常见图标。
完整的Chatbot.js
文件如下所示:
import React, { useState } from 'react';
import axios from 'axios';
import { FaPaperPlane } from 'react-icons/fa';
import './Chatbot.css';
const Chatbot = () => {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [loading, setLoading] = useState(false);
const handleSend = async () => {
if (input.trim() === '') return;
const newMessage = { text: input, sender: 'user' };
setMessages([...messages, newMessage]);
setInput('');
setLoading(true);
try {
const response = await axios.get('http://localhost:8080/ai/chat/string?message=' + input);
const aiMessage = { text: response.data, sender: 'ai' };
setMessages([...messages, newMessage, aiMessage]);
} catch (error) {
console.error("Error fetching AI response", error);
} finally {
setLoading(false);
}
};
const handleInputChange = (e) => {
setInput(e.target.value);
};
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
handleSend();
}
};
return (
<div className="chatbot-container">
<div className="chat-header">
<img src="ChatBot.png" alt="Chatbot Logo" className="chat-logo" />
<div className="breadcrumb">Home > Chat</div>
</div>
<div className="chatbox">
{messages.map((message, index) => (
<div key={index} className={`message-container ${message.sender}`}>
<img
src={message.sender === 'user' ? 'user-icon.png' : 'ai-assistant.png'}
alt={`${message.sender} avatar`}
className="avatar"
/>
<div className={`message ${message.sender}`}>
{message.text}
</div>
</div>
))}
{loading && (
<div className="message-container ai">
<img src="ai-assistant.png" alt="AI avatar" className="avatar" />
<div className="message ai">...</div>
</div>
)}
</div>
<div className="input-container">
<input
type="text"
value={input}
onChange={handleInputChange}
onKeyPress={handleKeyPress}
placeholder="Type your message..."
/>
<button onClick={handleSend}>
<FaPaperPlane />
</button>
</div>
</div>
);
};
export default Chatbot;
在App.js
中使用<Chatbot/>
来加载聊天机器人用户界面:
function App() {
return (
<div className="App">
<Chatbot />
</div>
);
}
除此之外,我们还使用CSS来让我们的聊天机器人看起来更美观一些。您可以参考App.css
和Chatbot.css
文件。
运行前端
使用npm命令来运行应用程序:
npm start
这应该在http://localhost:3000
上运行前端。现在,应用程序已经准备好进行测试了。
但是分别运行后端和前端有点麻烦。所以,让我们使用Docker来让整个构建过程变得更简单。
如何 Docker 化应用程序
让我们将整个应用程序Docker化,以便能够轻松地将其打包并部署到任何地方。您可以从Docker官方网站安装和配置Docker。
Docker 化后端
我们的聊天机器人的后端是用Spring Boot构建的,因此我们将创建一个Dockerfile,它将Spring Boot应用程序构建成一个可执行的JAR文件,并在容器中运行它。
让我们来编写它的Dockerfile:
# Start with an official image that has Java installed
FROM openjdk:17-jdk-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy the Maven/Gradle build file and source code into the container
COPY target/chatbot-backend.jar /app/chatbot-backend.jar
# Expose the application’s port
EXPOSE 8080
# Command to run the Spring Boot app
CMD ["java", "-jar", "chatbot-backend.jar"]
FROM openjdk:17-jdk-alpine
:这指定容器应基于包含 JDK 17 的轻量级 Alpine Linux 映像,这是运行 Spring Boot 所必需的。WORKDIR /app
:这行设置了容器内部的工作目录为/app
,我们的应用程序文件将存放在这里。COPY target/chatbot-backend.jar /app/chatbot-backend.jar
:这行将构建好的JAR文件从本地机器(通常在使用Maven或Gradle构建项目后的target
文件夹中)复制到容器中。EXPOSE 8080
:这行告诉Docker应用程序将在8080端口监听请求。CMD ["java", "-jar", "chatbot-backend.jar"]
:这行指定了容器启动时将运行的命令。它运行启动Spring Boot应用程序的JAR文件。
Docker 化前端
我们的聊天机器人的前端是使用React构建的,我们可以通过创建一个Dockerfile来将其Docker化,这个Dockerfile将安装必要的依赖项,构建应用程序,并使用像NGINX这样的轻量级Web服务器来提供服务。
让我们来编写React前端的Dockerfile:
# Use a Node image to build the React app
FROM node:16-alpine AS build
# Set the working directory inside the container
WORKDIR /app
# Copy the package.json and install the dependencies
COPY package.json package-lock.json ./
RUN npm install
# Copy the rest of the application code and build it
COPY . .
RUN npm run build
# Use a lightweight NGINX server to serve the built app
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
# Expose port 80 for the web traffic
EXPOSE 80
# Start NGINX
CMD ["nginx", "-g", "daemon off;"]
FROM node:16-alpine AS build
:这行指定了使用轻量级的Node.js镜像(版本16,基于Alpine Linux)来构建React应用。在这个容器中,我们将安装所有依赖并构建应用。WORKDIR /app
:这行设置了容器内部的工作目录为/app
。COPY package.json package-lock.json ./
:这行将package.json
和package-lock.json
文件复制到容器中,以便安装依赖。RUN npm install
:这行在容器中运行npm install
命令,安装package.json
中列出的依赖。COPY . .
:这行将前端源代码的所有文件复制到容器中。RUN npm run build
:这行在容器中运行npm run build
命令,构建React应用。构建后的文件将位于build
文件夹中。FROM nginx:alpine
:在应用构建完成后,这行指定了基于nginx Web服务器的轻量级Alpine Linux镜像来启动一个新的容器。COPY --from=build /app/build /usr/share/nginx/html
:这行将第一个容器中构建的React应用复制到nginx容器中,并将其放置在nginx默认的服务文件夹中。EXPOSE 80
:这行将公开端口 80,NGINX 使用它来提供 Web 流量。CMD ["nginx", "-g", "daemon off;"]
:这行以前台模式启动nginx服务器,以提供React应用的服务。
Docker Compose 来运行两者
现在我们已经分别为前端和后端创建了Dockerfile,接下来我们将使用docker-compose来协调同时运行这两个容器。
让我们在项目根目录下编写docker-compose.yml
文件:
version: '3'
services:
backend:
build: ./backend
ports:
- "8080:8080"
networks:
- chatbot-network
frontend:
build: ./frontend
ports:
- "3000:80"
depends_on:
- backend
networks:
- chatbot-network
networks:
chatbot-network:
driver: bridge
version: '3'
:这行定义了所使用的Docker Compose的版本。services:
:这行开始定义了想要运行的服务。backend
:这个服务使用位于./backend
目录的Dockerfile来构建后端,并暴露8080端口。frontend
:这个服务使用位于./frontend
目录的Dockerfile来构建前端。它将主机的3000端口映射到容器内的80端口
depends_on:
:这行确保前端服务在启动之前等待后端服务准备就绪。networks:
:这个部分定义了一个共享网络,以便后端和前端可以相互通信。
运行应用程序
要运行整个应用程序(前端和后端),您可以使用以下命令:
docker-compose up --build
此命令将:
- 构建前端和后端映像。
- 启动两个容器(后端在8080端口,前端通常映射到主机的3000端口,但由Nginx在容器内80端口提供服务)。
- 设置网络,以便两个服务可以相互通信。
现在,你可以访问 http://localhost:3000
来加载聊天机器人的用户界面,并开始向AI提问。
祝贺 🎉
您已成功使用 Spring Boot、React、Docker 和 OpenAI 构建了一个全栈聊天机器人应用程序。
原文链接:https://www.freecodecamp.org/news/ai-chatbot-with-spring-react-docker/