实现一个简单的聊天应用,用户可以通过输入问题或点击“Surprise me”按钮获取随机问题,并从后端API获取回答。
import { useState } from "react";
function App() {const [ value, setValue] = useState(""); // 存储用户输入的问题。const [error, setError] = useState(""); // 存储错误信息。const [chatHistory, setChatHistory] = useState([]); // 存储聊天记录,格式为一个数组,每个元素是一个包含 role(用户或模型)和 parts(消息内容)的对象。const surpriseOptions = ['Who won the latest Nobel Peace Prize?','Where does pizza come from?','Who do you make a sandwich?'] // 一个包含随机问题的数组const surprise = () => {const randomValue = surpriseOptions[Math.floor(Math.random() * surpriseOptions.length)];setValue(randomValue);} // 从 surpriseOptions 中随机选择一个问题,并将其设置为 value// getResponse 是一个异步函数,用于向后端API发送请求并获取回答const getResponse = async () => {if (!value){setError("Please enter a question");return;} // 如果 value 为空,设置错误信息并返回。try {const options = {method: 'POST',body: JSON.stringify({history: chatHistory,message: value}), // 转换为 JSON 字符串headers: {'Content-Type': 'application/json'}}const response = await fetch('http://localhost:8000/gemini', options); // 使用 fetch 发送POST请求,请求体包含 chatHistory 和用户输入的 valueconst data = await response.text();console.log(data);setChatHistory(oldChatHistory => [...oldChatHistory, {role: "user",parts: [{text: value}],},{role: "model",parts: [{text: data}],}]) // 将API返回的回答添加到 chatHistory 中setValue("") // 清空输入框}catch (error) {console.error(error);setError("Something went wrong! Please try again later.");} // 如果发生错误,设置错误信息}const clear = () => {setValue("")setError("")setChatHistory([])} // 清空输入框、错误信息和聊天记录。return (<div className="app"><p>What do you want to know?<button className="surprise" onClick={surprise} disabled={!chatHistory}>Surprise me</button></p><!-- 如果 disabled 为 true,按钮不可点击;如果 disabled 为 false,按钮可点击。 如果 chatHistory 为空([]),它仍然是一个对象,而所有对象在布尔上下文中都被视为 true,!chatHistory 返回 false。
--><div className="input-container"><inputvalue={value}placeholder="When is Christmas...?"onChange={(e) => setValue(e.target.value)}/><!-- e.target.value 用于获取事件目标(通常是输入框、下拉框等表单元素)的当前值。它通常与 onChange 事件一起使用,以便在用户输入时实时获取输入内容。 -->{!error && <button onClick={getResponse}>Ask me</button>}{error && <button onClick={clear}>Clear</button>}</div>{error && <p>{error}</p>}<div className="search-result">{chatHistory.map((chatItem, _index) => <div key={_index}><p className="answer">{chatItem.role}: {chatItem.parts.map(part => part.text).join(" ")}</p></div>)}</div></div>);
}export default App;
渲染一个包含以下内容的界面:
- 一个标题和“Surprise me”按钮(仅在 chatHistory 不为空时可用)。
- 一个输入框和“Ask me”按钮(如果无错误)或“Clear”按钮(如果有错误)。
- 错误信息(如果有)。
- 聊天记录,每条记录显示用户问题和模型回答。
实现一个基于 Express 的 Node.js 服务器,用于与 Google 的 Generative AI 模型(Gemini)进行交互
const PORT = 8000
const express = require('express') // Node.js 的 Web 框架,用于构建服务器。
const cors = require('cors') // 用于处理跨域资源共享(CORS),允许前端与后端跨域通信。const app = express()
app.use(cors()) // 启用 CORS 中间件,允许跨域请求。
app.use(express.json()) // 启用 JSON 解析中间件,以便服务器可以解析请求体中的 JSON 数据。require('dotenv').config()const { GoogleGenerativeAI } = require('@google/generative-ai') // Google 提供的 Generative AI SDK,用于与 Gemini 模型交互。const genAI = new GoogleGenerativeAI(process.env.GOOGLE_GEN_AI_KEY)// 定义一个 POST 路由 /gemini,用于接收前端发送的请求。
app.post('/gemini', async (req, res) => {const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });// 使用聊天历史记录初始化一个 Gemini 聊天会话。const chat = model.startChat({history: req.body.history}) // 从请求体中获取聊天历史记录。const msg = req.body.message // 从请求体中获取用户发送的消息。const result = await chat.sendMessage(msg) // 向 Gemini 模型发送用户的消息。const response = await result.responseconst text = response.text()res.send(text) // 将模型的响应文本发送回前端。
}
)// 启动服务器,监听指定的端口(PORT)。
app.listen(PORT, () => console.log(`Server running on port ${PORT}`))