嘿,Java开发人员们,有个重大好消息要告诉你们:Spring如今已正式支持通过SpringAI模块来构建AI应用程序。
在本教程中,我们将使用SpringBoot、React、Docker以及OpenAI来构建一个聊天机器人的应用程序。此应用程序能够让用户与由AI驱动的聊天机器人进行交互,可以向其提出问题,并实时获取回复。
文中提到的全部源代码已在GitHub存储库中予以提供。欢迎给它加星标,然后搬运该源代码库进行尝试体验。
为了让你对所要构建的内容有个概念,最终AI应用程序的样子如下:
你感兴趣么?让我们从头开始吧!
目录
前提条件
获取OpenAI密钥
使用Spring Boot构建REST API
使用Reactjs构建Chat UI
如何将AI应用程序Docker化
运行AI应用程序
前提条件
在我们深入研究构建聊天机器人之前,你需要熟悉以下几点:
获取OpenAI密钥
首先,如果你没有Open AI账户,那么需要先注册一个,在登录之后,你会来到它的主页。
在右上角,单击“Dashboard”(控制面板)菜单。在侧边栏上,单击“APIKeys”(应用程序编程接口密钥),然后单击“Createnewsecretkey”(创建新密钥)按钮以生成你自己的密钥:
复制密钥并将其妥善保存于安全之处,因为后续你需要凭借此密钥将你的应用程序与OpenAIAPI相连接。
你可以查阅OpenAIAPI参考指南,以获取更多关于如何调用API、它所接受的请求类型以及它给出的响应内容等方面的信息。
使用SpringBoot构建REST API
让我们前往SpringInitializer(用于快速创建SpringBoot项目的基础结构的一个网络工具)来生成样板文件代码:
你可以自行选择group(反向域名)、artifact(项目唯一标识符)、name(项目名称)、description(项目描述)和package(Java包名)。我们使用Maven(Java项目的依赖管理和构建工具)作为构建工具,SpringBoot版本为3.3.3,打包选项为Jar(JavaArchive的缩写,是Java应用程序的标准打包格式),Java版本为17。(注:DependencyManagement:依赖管理)
点击生成按钮,将会下载一个zip文件。解压该文件,然后将其作为Maven项目导入到你喜欢的IDE中(我用的是Intellij)。
在Spring中配置你的OpenAI密钥
你可以使用现有的application.properties文件,或者创建一个application.yaml文件。我喜欢使用Yaml,所以创建了一个application.yaml文件,我可以在其中放置所有的SpringBoot配置。
接下来在你的application.yaml文件中添加OpenAIKey、Model和Temperature:
spring:ai:openai:chat:options:model:"gpt-3.5-turbo"temperature:"0.7"key:"PUTYOUROPEN_API_KEYHERE"
application.properties中的类似配置可能如下所示:
spring.ai.openai.chat.options.model=gpt-3.5-turbospring.ai.openai.chat.options.temperature=0.7spring.ai.openai.key="PUTYOUROPEN_API_KEYHERE"
构建ChatController
让我们创建一个URL为/ai/chat/string的GETAPI和一个处理逻辑的方法:
@RestControllerpublicclass ChatController{@Autowiredprivate final OpenAiChatModel chatModel;@GetMapping("/ai/chat/string")public Flux<String>generateString(@RequestParam(value="message",defaultValue="Tellmeajoke")Stringmessage){return chatModel.stream(message);}}
构建、运行和测试 REST API
./mvnw clean install spring-boot:run
理想情况下,它会在8080端口上运行,除非你自定义了端口。请确保该端口空闲,以成功运行应用程序。
你可以使用Postman 或Curl命令来测试你的 REST API:
curl --location 'http://localhost:8080/ai/chat/string?message=How%20are%20you%3F'
使用Reactjs构建Chat UI
我们使用useState来管理状态:
const [messages, setMessages] = useState([]);const [input, setInput] = useState('');const [loading, setLoading] = useState(false);
接下来,让我们创建一个handleSend 函数,并在用户通过点击按钮或按下回车键发送消息时进行调用:
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);}};
以下是逐步发生的过程:
让我们编写一个函数,当用户在输入字段中输入内容,对input状态进行更新:
const handleInputChange = (e) => {setInput(e.target.value);};
然后,我们创建一个函数来检查用户是否按下了 Enter 键。如果出现这种情形,它会调用 handleSend()函数来发送消息:
const handleKeyPress = (e) => {if (e.key === 'Enter') {handleSend();}};
现在让我们创建 UI 元素来呈现聊天消息:
{messages.map((message, index) => (<div key={index} className={`message-container ${message.sender}`}><imgsrc={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>)}
当 AI 处于思考状态(即 loading 为 true 时),我们显示一条加载消息(...),以便让用户知道响应即将到来。
最后,创建一个用于点击发送消息的按钮:
当此按钮被点击时,将会触发 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}`}><imgsrc={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"><inputtype="text"value={input}onChange={handleInputChange}onKeyPress={handleKeyPress}placeholder="Type your message..."/><button onClick={handleSend}><FaPaperPlane /></button></div></div>);};export default Chatbot;
在 App.js 中使用 <Chatbot/>来加载聊天机器人 UI:
function App() {return (<div className="App"><Chatbot /></div>);}
除此之外,我们还使用 CSS 来使我们的聊天机器人更加美观。你可以参考 App.css 和 Chatbot.css 文件来了解具体样式。
运行前端
使用npm命令运行应用程序:
程序会在URL上运行前端。此时应用程序已能够进行测试。
然而,分别运行后端和前端稍显繁琐。因此,让我们借助Docker来使整个构建流程更加简单。
如何将AI应用程序Docker化
让我们将整个应用程序Docker化,以便轻松打包和部署到任何地方。你可以从Docker的官方网站安装并配置Docker。
Docker化后端
聊天机器人的后端是用Spring Boot构建的,因此我们将创建一个Dockerfile,它将Spring Boot应用程序构建为可执行JAR文件并在容器中运行。
让我们为其编写Dockerfile:
# Start with an official image that has Java installedFROM openjdk:17-jdk-alpine# Set the working directory inside the containerWORKDIR /app# Copy the Maven/Gradle build file and source code into the containerCOPY target/chatbot-backend.jar /app/chatbot-backend.jar# Expose the application’s portEXPOSE 8080# Command to run the Spring Boot appCMD ["java", "-jar", "chatbot-backend.jar"]
Docker化前端
聊天机器人的前端用React构建而成,通过创建一个Dockerfile来对其进行Docker化处理,该Dockerfile会安装必要的依赖项(dependencies)、构建应用程序,并借助像NGINX这类轻量级的Web服务器来提供服务。
让我们为React前端编写Dockerfile:
# Use a Node image to build the React appFROM node:16-alpine AS build# Set the working directory inside the containerWORKDIR /app# Copy the package.json and install the dependenciesCOPY package.json package-lock.json ./RUN npm install# Copy the rest of the application code and build itCOPY . .RUN npm run build# Use a lightweight NGINX server to serve the built appFROM nginx:alpineCOPY --from=build /app/build /usr/share/nginx/html# Expose port 80 for the web trafficEXPOSE 80# Start NGINXCMD ["nginx", "-g", "daemon off;"]
使用Docker Compose同时运行前后端
现在我们已经为前端和后端分别创建了Dockerfile,我们将使用 docker-compose来协调同时运行这两个容器。
让我们在项目的根目录下编写docker-compose.yml 文件:
version: '3'services:backend:build: ./backendports:- "8080:8080"networks:- chatbot-networkfrontend:build: ./frontendports:- "3000:80"depends_on:- backendnetworks:- chatbot-networknetworks:chatbot-network:driver: bridge
运行AI应用程序
要运行整个应用程序(前端和后端),你可以使用以下命令:
docker-compose up --build
这个命令将会实现:
现在,你可以访问加载聊天机器人 UI,并开始向 AI 提问。
你已经成功使用 Spring Boot、React、Docker 和 OpenAI 构建了一个全栈聊天机器人应用。
项目中展示的源代码可在 Github 上获取,如果你觉得它有帮助,请加星标,并随意搬运该源代码库进行尝试体验。
译者介绍
刘涛,社区编辑,某大型央企系统上线检测管控负责人。
原文标题: How to Build an AI Chatbot with Spring AI, React, and Docker ,作者:Vikas Rajput