北京网站优化策略/怎么做公众号

北京网站优化策略,怎么做公众号,怎么做非法彩票网站吗,手机网站 焦点图文章目录 前言一、demo演示二、node.js 使用步骤1.引入库2.引入包 前端HTML调用接口和UI所有文件总结 前言 关注博主,学习每天一个小demo 今天是Ai对话网站 又到了每天一个小demo的时候咯,前面我写了多人实时对话demo、和视频转换demo,今天…

文章目录

  • 前言
  • 一、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 引入我们的第三方包 编写接口逻辑

**特别关注:

  1. baseURL: 这里大家可以替换其他的APi 比如deepseek(好像目前不能充值了),或者一些第三方的API地址。
  2. 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 lang="zh">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ChatGPT 聊天</title><style>#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>
<body><div id="chat-container"><div id="chat-messages"></div><form id="message-form"><input type="text" id="message-input" placeholder="输入消息..." required><button type="submit" id="submit-btn">发送</button></form></div><script>const 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> 

所有文件

  1. .env 存储了APi-key
  2. index.html 前端代码
  3. server.js 后段代码
    在这里插入图片描述
    在这里插入图片描述

总结

尽可能的多学习一些知识,或许以后用不到,关注我每天练习一个小demo。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unity学习42:动画状态机:混合动画状态 blend tree

目录 1 动画状态机 1.1 新建动画状态 2 混合动画状态 blend Tree 2.1 new blend Tree 2.2 blend tree state 和普通的 state的属性不同 2.3 双击blend tree 进入下一层 blend tree内部 2.3.1 blend tree 内部 2.3.2 blend type 2.3.3 参数类型默认是float&#xff0…

Mybatisplus——Mybatisplus3.5.2版本使用Page分页插件查询,records有数据但是total显示0

目录 一、问题背景 debug 执行Mybatisplus使用Page分页插件查询时&#xff0c;发现 Page 里面的records有数据但是total显示0。 二、问题产生的原因 未配置MybatisPlus的分页插件拦截器导致的或者因mybatis-plus版本3.4或3.5版本导致原先的分页插件paginationInterceptor无法…

Android10 音频参数导出合并

A10 设备录音时底噪过大&#xff0c;让音频同事校准了下&#xff0c;然后把校准好的参数需要导出来&#xff0c;集成到项目中&#xff0c;然后出包&#xff0c;导出方式在此记录 设备安装debug系统版本调试好后&#xff0c; adb root adb remount adb shell 进入设备目录 导…

C#(Winform)通过添加AForge添加并使用系统摄像机

先展示效果 AForge介绍 AForge是一个专门为开发者和研究者基于C#框架设计的, 也是NET平台下的开源计算机视觉和人工智能库 它提供了许多常用的图像处理和视频处理算法、机器学习和神经网络模型&#xff0c;并且具有高效、易用、稳定等特点。 AForge主要包括: 计算机视觉与人…

【苍穹外卖】学习

软件开发整体介绍 作为一名软件开发工程师,我们需要了解在软件开发过程中的开发流程&#xff0c; 以及软件开发过程中涉及到的岗位角色&#xff0c;角色的分工、职责&#xff0c; 并了解软件开发中涉及到的三种软件环境。那么这一小节&#xff0c;我们将从 软件开发流程、角色…

yanshee机器人初次使用说明(备注)-PyCharm

准备 需要&#xff1a; 1&#xff0c;&#xff08;优必选&#xff09;yanshee机器人Yanshee 开发者说明 2&#xff0c;手机-联网简单操控 / HDMI线与显示器和键鼠标-图形化开发环境 / 笔记本&#xff08;VNC-内置图形化开发环境/PyCharm等平台&#xff09;。 3&#xff0c;P…

#渗透测试#批量漏洞挖掘#致远互联AnalyticsCloud 分析云 任意文件读取

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

时间序列分析(四)——差分运算、延迟算子、AR(p)模型

此前篇章&#xff1a; 时间序列分析&#xff08;一&#xff09;——基础概念篇 时间序列分析&#xff08;二&#xff09;——平稳性检验 时间序列分析&#xff08;三&#xff09;——白噪声检验 一、差分运算 差分运算的定义&#xff1a;差分运算是一种将非平稳时间序列转换…

信息收集-Web应用JS架构URL提取数据匹配Fuzz接口WebPack分析自动化

知识点&#xff1a; 1、信息收集-Web应用-JS提取分析-人工&插件&项目 2、信息收集-Web应用-JS提取分析-URL&配置&逻辑 FUZZ测试 ffuf https://github.com/ffuf/ffuf 匹配插件 Hae https://github.com/gh0stkey/HaE JS提取 JSFinder https://github.com/Threez…

SQL Server 导入Excel数据

1、选中指定要导入到哪个数据库&#xff0c;右键选择 》任务 》导入数据 2、数据源 选择Excel&#xff0c;点击 下一步(Next) 3、目前 选择OLE DB Provider &#xff0c;点击 下一步&#xff08;Next&#xff09; 4、默认 &#xff0c;点击 下一步&#xff08;Next&#xff09;…

我的新书《青少年Python趣学编程(微课视频版)》出版了!

&#x1f389; 激动人心的时刻来临啦&#xff01; &#x1f389; 小伙伴们久等了&#xff0c;我的第一本新书 《青少年Python趣学编程&#xff08;微课视频版&#xff09;》 正式出版啦&#xff01; &#x1f4da;✨ 在这个AI时代&#xff0c;市面上的Python书籍常常过于枯燥&…

大模型应用开发书籍推荐

在AI原生应用的探索之路上&#xff0c;大语言模型与提示工程面临着诸多挑战。一方面&#xff0c;过度乐观的预期让开发者陷入困境&#xff1b;另一方面&#xff0c;大语言模型在效果、性能等方面的局限也限制了其应用。本书作者作为一线从业者&#xff0c;深感驾驭大模型的重要…

基于CANopen协议的同步控制和PDO消息传输

这个VI示例展示了如何通过SYNC帧触发发送和接收PDO&#xff08;Process Data Object&#xff09;消息。它涉及的步骤包括配置CANopen接口、设定通信参数、并通过SYNC信号同步多个设备的消息传输。下面是详细说明&#xff1a; ​ 1. 右键点击BatchSDO选择部署 在NI CANopen for…

vtkCamera类的Dolly函数作用及相机拉近拉远

录 1. 预备知识 1.1.相机焦点 2. vtkCamera类的Dolly函数作用 3. 附加说明 1. 预备知识 要理解vtkCamera类的Dolly函数作用,就必须先了解vtkCamera类表示的相机的各种属性。  VTK是用vtkCamera类来表示三维渲染场景中的相机。vtkCamera负责把三维场景投影到二维平面,如…

领域驱动设计(DDD)是什么?——从理论到实践的全方位解析

文章目录 一、 引言二、 核心概念与定位2.1 DDD 定义与核心理念2.2 DDD 关键元素 三、 底层原理与技术细节3.1 领域模型与普适语言3.1.1 领域模型3.1.2 普适语言&#xff08;Ubiquitous Language&#xff09; 3.2 战术设计模式详解3.2.1 实体、值对象、聚合与领域服务3.2.2 无状…

领域驱动设计叕创新,平安保险申请DDD专利

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 见下图&#xff1a; 这个名字拼得妙&#xff1a;领域驱动设计模式。 是领域驱动设计&#xff1f;还是设计模式&#xff1f;还是领域驱动设计设计模式&#xff1f;和下面这个知乎文章的…

2025冠珠瓷砖全国开门红启动大会顺利召开

新年伊始&#xff0c;战鼓催征&#xff01;2月11日上午&#xff0c;“开年焕新 家倍幸运”为主题的2025冠珠瓷砖全国开门红启动大会在品牌总部会议室成功举行。新明珠集团副总经理、冠珠瓷砖品牌总经理潘瀚&#xff0c;冠珠瓷砖品牌副总经理曾小泉等领导&#xff0c;以及冠珠瓷…

基于Qt 和微信小程序的用户管理系统:WebSocket + SQLite 实现注册与登录

目录 一. 概要 二. 技术栈 三. 系统功能设计 3.1 功能模块 3.2 数据表设计 四. 具体实现 4.1 Qt 服务端 4.1.1 初始化 WebSocket 服务器 4.1.2 用户管理界面 4.2 微信小程序端 4.2.1 注册功能 4.2.2 登录功能 五. 运行效果 六. 源码下载 一. 概要 在物联网和智能设备…

C++17中`std::map`和`std::set`的`extract`与`merge`操作

文章目录 1. extract操作使用方法内部机制 2. merge操作使用方法特点 3. 性能优势4. 实际应用场景5. 总结 在C17标准中&#xff0c; std::map和 std::set这两个关联容器引入了两个极具实用价值的新特性&#xff1a; extract和 merge。这两个操作极大地增强了关联容器在处理…

当时只道是寻常

晴&#xff0c;2025年2月16日 卸载了油管、脸书和 X 手机 app &#xff0c;太浪费我时间&#xff0c;以后再去经营吧。 教学技能大赛材料需要在明天之内搞定——《教学实施方案》。感觉玄&#xff0c;同部门有经验的老师说至少花一周时间。 只能明天早点继续接着弄&#xff…