网页设计与网站建设课程总结,东营网站seo外包,天天网站,万网域名注册商文章目录 前言一、demo演示二、node.js 使用步骤1.引入库2.引入包 前端HTML调用接口和UI所有文件总结 前言
关注博主#xff0c;学习每天一个小demo 今天是Ai对话网站
又到了每天一个小demo的时候咯#xff0c;前面我写了多人实时对话demo、和视频转换demo#xff0c;今天… 文章目录 前言一、demo演示二、node.js 使用步骤1.引入库2.引入包 前端HTML调用接口和UI所有文件总结 前言
关注博主学习每天一个小demo 今天是Ai对话网站
又到了每天一个小demo的时候咯前面我写了多人实时对话demo、和视频转换demo今天我来使用 node.js html 调用chatGpt Api实现一个Ai 流式对话小demo,当然现在主流的各种APi调用方式一致你也可以接入deepseek或者第三方的接口效果一样 一、demo演示
下面是一个简单的demo演示并且是支持流式的
二、node.js 使用步骤
1.引入库
代码如下
先初始化一个package.js 文件。
npm init -y我们需要安装 express、cors、openAi、dotenv三方库
{name: web,version: 1.0.0,main: server.js,scripts: {test: echo \Error: no test specified\ exit 1,start: node server.js},keywords: [],author: ,license: ISC,description: ,dependencies: {axios: ^1.7.9,cors: ^2.8.5,dotenv: ^16.0.3,express: ^4.18.2,openai: ^4.0.0}
}2.引入包
创建server.js 引入我们的第三方包 编写接口逻辑
**特别关注:
baseURL: 这里大家可以替换其他的APi 比如deepseek(好像目前不能充值了)或者一些第三方的API地址。apiKey 这里大家把key可以直接填写上我这里为了学习知识新建了一个.env 文件。**
const express require(express);
const cors require(cors);
const OpenAI require(openai);
require(dotenv).config();const app express();
app.use(express.json());
app.use(cors());// 初始化OpenAI客户端
const openai new OpenAI({apiKey: process.env.DEEPSEEK_API_KEY, baseURL: https://api.openai.com/v1 // 使用OpenAI官方API地址 这里可以可以使用别的Api地址// 比如 deepseek 或者其他的第三方的一些// baseURL: https://api.deepseek.com/v1
});let conversationHistory [];app.post(/chat, async (req, res) {try {const { message } req.body;// 设置响应头支持流式输出res.setHeader(Content-Type, text/event-stream);res.setHeader(Cache-Control, no-cache);res.setHeader(Connection, keep-alive);res.setHeader(Access-Control-Allow-Origin, *); // 添加CORS支持// 添加用户消息到历史记录conversationHistory.push({ role: user, content: message });const stream await openai.chat.completions.create({model: gpt-3.5-turbo,messages: [{ role: system, content: You are a helpful assistant. },...conversationHistory],temperature: 0.7,max_tokens: 1000,stream: true,});let fullResponse ;// 确保每次写入后立即刷新缓冲区for await (const chunk of stream) {const content chunk.choices[0]?.delta?.content || ;if (content) {fullResponse content;const dataToSend JSON.stringify({ content });console.log(Sending to client:, dataToSend);res.write(data: ${dataToSend}\n\n);// 强制刷新缓冲区if (res.flush) {res.flush();}}}// 将完整回复添加到对话历史conversationHistory.push({ role: assistant, content: fullResponse });if (conversationHistory.length 10) {conversationHistory conversationHistory.slice(-10);}res.write(data: [DONE]\n\n);if (res.flush) {res.flush();}res.end();} catch (error) {console.error(Error:, error);res.write(data: ${JSON.stringify({ error: 服务器错误 })}\n\n);res.end();}
});const PORT 3000;
app.listen(PORT, () {console.log(服务器运行在端口 ${PORT});
}); 在根目录执行 node server.js 启动服务
前端HTML调用接口和UI
不墨迹哈直接把所有代码贴过来 大家好直接研究代码我就不用一行一行解读了没啥东西难处就是对流式数据的一个处理
特别注意 不要直接点击html打开页面在vscode里面安装扩展Live Server然后点击右下角 Go live启动一个微服务。
!DOCTYPE html
html langzh
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleChatGPT 聊天/titlestyle#chat-container {width: 80%;max-width: 800px;margin: 20px auto;padding: 20px;border: 1px solid #ccc;border-radius: 5px;}#chat-messages {height: 400px;overflow-y: auto;margin-bottom: 20px;padding: 10px;border: 1px solid #eee;}.message {margin: 10px 0;padding: 10px;border-radius: 5px;}.user-message {background-color: #e3f2fd;margin-left: 20%;}.bot-message {background-color: #f5f5f5;margin-right: 20%;}#message-form {display: flex;gap: 10px;}#message-input {flex: 1;padding: 8px;}.typing {opacity: 0.5;}.cursor {display: inline-block;width: 2px;height: 15px;background: #000;margin-left: 2px;animation: blink 1s infinite;}keyframes blink {0%, 100% { opacity: 1; }50% { opacity: 0; }}/style
/head
bodydiv idchat-containerdiv idchat-messages/divform idmessage-forminput typetext idmessage-input placeholder输入消息... requiredbutton typesubmit idsubmit-btn发送/button/form/divscriptconst messageForm document.getElementById(message-form);const messageInput document.getElementById(message-input);const chatMessages document.getElementById(chat-messages);const submitBtn document.getElementById(submit-btn);messageForm.addEventListener(submit, async (e) {e.preventDefault();const message messageInput.value.trim();if (!message) return;// 禁用输入和发送按钮messageInput.disabled true;submitBtn.disabled true;// 显示用户消息addMessage(message, user);messageInput.value ;// 创建机器人回复的消息框const botMessageDiv document.createElement(div);botMessageDiv.className message bot-message typing;chatMessages.appendChild(botMessageDiv);// 添加光标const cursor document.createElement(span);cursor.className cursor;botMessageDiv.appendChild(cursor);try {const response await fetch(http://localhost:3000/chat, {method: POST,headers: {Content-Type: application/json,Accept: text/event-stream},body: JSON.stringify({ message })});if (!response.ok) {throw new Error(HTTP error! status: ${response.status});}const reader response.body.getReader();const decoder new TextDecoder();let botResponse ;let buffer ;try {while (true) {const { value, done } await reader.read();// 如果流结束了就退出循环if (done) {console.log(Stream complete);break;}// 确保有值才处理if (value) {buffer decoder.decode(value, { stream: true });const lines buffer.split(\n);// 保留最后一个不完整的行buffer lines.pop() || ;for (const line of lines) {if (line.trim() ) continue;if (!line.startsWith(data: )) continue;const data line.slice(6).trim();if (data [DONE]) {botMessageDiv.classList.remove(typing);cursor.remove();continue;}try {const parsedData JSON.parse(data);if (parsedData.content) {botResponse parsedData.content;botMessageDiv.textContent botResponse;botMessageDiv.appendChild(cursor);chatMessages.scrollTop chatMessages.scrollHeight;}} catch (e) {console.error(JSON解析错误:, e, Raw data:, data);}}}}// 处理最后可能残留的数据if (buffer.trim()) {const finalText decoder.decode(); // 完成流的解码if (finalText) {buffer finalText;const lines buffer.split(\n);for (const line of lines) {if (line.trim() || !line.startsWith(data: )) continue;const data line.slice(6).trim();if (data [DONE]) continue;try {const parsedData JSON.parse(data);if (parsedData.content) {botResponse parsedData.content;botMessageDiv.textContent botResponse;}} catch (e) {console.error(最终解析错误:, e, Raw data:, data);}}}}} catch (streamError) {console.error(Stream processing error:, streamError);throw streamError;}} catch (error) {console.error(Error:, error);botMessageDiv.textContent 抱歉发生错误。;botMessageDiv.classList.remove(typing);cursor.remove();} finally {messageInput.disabled false;submitBtn.disabled false;messageInput.focus();}});function addMessage(text, sender) {const messageDiv document.createElement(div);messageDiv.className message ${sender}-message;messageDiv.textContent text;chatMessages.appendChild(messageDiv);chatMessages.scrollTop chatMessages.scrollHeight;}/script
/body
/html 所有文件
.env 存储了APi-keyindex.html 前端代码server.js 后段代码
总结
尽可能的多学习一些知识或许以后用不到关注我每天练习一个小demo。