
掌握ChatGPT插件与自定义GPT
嘿,Java开发者们,我有个好消息:Spring 现在正式支持使用 Spring AI 模块构建 AI 应用程序。
在本教程中,我们将使用 Spring Boot、React、Docker 和 OpenAI 构建一个聊天机器人应用程序。此应用程序将允许用户与 AI 驱动的聊天机器人互动、提出问题并实时接收回复。
本文中提到的整个源代码已经在 GitHub 存储库中提供。
为了让你对我们将要构建的内容有个概念,最终应用程序将如下所示:
你兴奋吗?让我们从头开始构建它!
在开始构建聊天机器人之前,你需要了解一些基础知识:
首先,如果您没有 OpenAI 帐户,则需要注册一个 OpenAI 帐户。登录后,您将被带到主页。
在右上角,单击 “Dashboard” 菜单。在侧边栏上,单击“API Keys”,然后单击“Create new secret key”按钮以生成您的密钥:
复制密钥并将其保存在安全的地方,因为您稍后需要它来将您的应用程序连接到 OpenAI API。
您可以浏览 OpenAI API 参考指南,了解更多关于如何调用API、它接受哪些请求以及它给出的响应的更多信息。
让我们转到 spring initializer 以生成样板代码:
您可以提供您选择的组、构件、名称、描述和包。我们使用 Maven 作为构建工具,使用 Spring Boot 版本 3.3.3,使用 Jar 作为打包选项,并使用 Java 版本 17。
点击生成按钮,将下载 zip。解压缩文件并将它们作为 Maven 项目导入到您最喜欢的 IDE 中(我的是 Intellij)。
你可以使用现有的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"
让我们创建一个带有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);
}
}
使用 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的最佳实践。
我们将使用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);
}
};
以下是逐步发生的事情:
现在,我们来编写一个函数,以便用户在输入字段中输入内容时更新输入状态:
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
的形式显示出来。接下来,让我们创建一些逻辑,根据一个标志(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。
我们的聊天机器人的后端是用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文件。我们的聊天机器人的前端是使用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应用的服务。现在我们已经分别为前端和后端创建了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
此命令将:
现在,你可以访问 http://localhost:3000
来加载聊天机器人的用户界面,并开始向AI提问。
您已成功使用 Spring Boot、React、Docker 和 OpenAI 构建了一个全栈聊天机器人应用程序。
原文链接:https://www.freecodecamp.org/news/ai-chatbot-with-spring-react-docker/