当前位置: 首页 > news >正文

手写chatGPT——fetch解析text/event-stream会话流并逐字回显到页面——js技能提升

直接上效果图:
在这里插入图片描述
页面分上下两部分,上面是会话界面,底部是提交框。

直接上代码:

解决步骤1:引入vue+elementUi

  <head><meta charset="UTF-8" /><title>Fetch Stream Example</title></head><script src="./vue.js"></script><!-- 引入样式 --><linkrel="stylesheet"href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"/><!-- 引入组件库 --><script src="https://unpkg.com/element-ui/lib/index.js"></script>

解决步骤2:搭建静态页面——使用vue

<div id="bodyWrap"><div class="wrapCon"><div class="wrapCls" v-for="(item,index) in historyList" :key="index"><div class="questionWrap"><imgsrc="https://img2.baidu.com/it/u=2125727497,3458875842&fm=253&fmt=auto&app=138&f=JPEG"alt=""/><div class="question">{{item.message}}</div></div><div class="output">{{item.content}}</div></div></div><div id="footerId"><el-inputtype="textarea":rows="3"ref="textearaRef"placeholder="请输入内容"v-model="textarea"></el-input><el-button size="small" type="primary" @click="handleSubmit">提交</el-button></div></div>

解决步骤3:css部分

 <style>* {margin: 0;padding: 0;}body {font-size: 14px;padding: 10px;}#bodyWrap {height: 100vh;border: 1px solid #efefef;border-radius: 10px;padding: 10px;}.wrapCon {height: calc(100vh - 60px);overflow: auto;}#footerId {position: fixed;bottom: 10px;display: flex;left: 30px;right: 30px;}#footerId .el-textarea {margin-right: 10px;flex: 1;}.wrapCls {margin: 10px;padding: 10px;border: 1px solid #efefef;border-radius: 5px;}.questionWrap {display: flex;width: 60%;}.questionWrap img {border-radius: 50%;margin-right: 10px;width: 40px;height: 40px;}.output {margin-top: 10px;background-color: #d9ecff;border: 1px solid #409eff;padding: 10px;border-radius: 4px;margin-left: 50px;min-height: 20px;}.question {background-color: #f0f9eb;border: 1px solid #67c23a;padding: 10px;border-radius: 4px;}</style>

解决步骤4:js部分

<script>new Vue({el: '#bodyWrap',data() {return {textarea:'我的元器件参数是: 100Ω±1%-1/10W 帮我选择一个国巨型号,精简一下话术20字之内,只要给我一个型号就可以',historyList: [],};},mounted() {this.$refs.textearaRef.focus();},methods: {handleSubmit() {if (!this.textarea) {return;}this.render();},render() {let that = this;let params = {message: that.textarea,content: '',};that.historyList.push(params);// 假设你要获取的数据是一个文本流//下面的接口地址是我局域网后端同事提供的,需要换成你们自己的才可以fetch('http://192.168.35.3:11434/api/chat', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({model: 'llama3.1',messages: [{role: 'user',content: this.textarea,},],stream: true,}),dataType: 'text/event-stream',}).then((response) => response.body) // 获取响应体.then((body) => {// 创建一个读取流const reader = body.getReader();// 使用循环来读取数据流const p = document.createElement('p');const output = document.createElement('div');(function read() {reader.read().then(({ done, value }) => {let con = '';if (done) {return;}let json = new TextDecoder('utf-8').decode(value);if (json) {let obj = JSON.parse(json);p.appendChild(document.createTextNode(obj.message.content));output.appendChild(p);that.historyList[that.historyList.length - 1].content +=obj.message.content;}// 递归调用read函数以继续读取数据流read();});})();});},},});
</script>

最开始其实是想用eventSource的方式来处理的。但是onMessage一直收不到后端的数据,所以后面就放弃了,转而用了fetch。下面也记录一下eventSource的用法:

下面使用eventSource来处理,但是效果没有实现

解决步骤1:在h5中使用fetchEventSource,需要用到webpack

1.初始化包管理文件
npm install
2.安装webpackwebpack-cli编译器
npm install webpack --save-dev
npm install webpack-cli --save-dev
3.新建webpack.config.js文件,文件内容如下:
const path = require('path');
module.exports = {entry: './test.js', //打包入口output: {//打包文件输出路径path: path.resolve(__dirname, 'dist'),filename: 'index.js',},
};
4.新建test.js文件,文件内容如下:
import { fetchEventSource } from '@microsoft/fetch-event-source';
fetchEventSource('http://192.168.35.3:11434/api/chat', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({model: 'llama3.1',messages: [{ role: 'user', content: '你好啊' }],stream: true,}),onmessage: (ev) => {console.log('ev', ev, JSON.parse(ev.data));// document.getElementById('output').textContent += ev.data;console.log(111);},onopen() {console.log('Connection opened');},onclose() {console.log('Connection closed');},onerror(err) {console.error('Error:', err);},
});

感觉上面的代码没问题,但是onmessage方法中就是收不到ev的内容,所以没有实现最终的效果。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【C++BFS算法】2998. 使 X 和 Y 相等的最少操作次数
  • Redis作为缓存,如何与MySql的数据进行同步?
  • 7 postgresql 10版本 分区表使用场景、创建删除、注意事项
  • 熟悉简单测试面经
  • 代码随想录第二十一天|动态规划(5)
  • 3.2.2 最短路径 堆优化版Djkstra算法
  • 快速解密哈希算法利器Hasher:解密MD5、SHA256、SHA512、RIPEMD160等最佳工具
  • ChatTTS文本转语音本地部署结合内网穿透实现远程使用生成AI音频
  • sql注入安全作业
  • LearnOpenGL-入门章节学习笔记
  • C语言程序设计-[5] 输入输出语句
  • ShardingSphere 内核工作原理
  • 极简聊天室-websocket版(双向通信)
  • 数据科学家必须掌握的12个Python功能
  • pxe自动安装linux
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • android 一些 utils
  • css布局,左右固定中间自适应实现
  • CSS实用技巧
  • DOM的那些事
  • ES6--对象的扩展
  • Objective-C 中关联引用的概念
  • sessionStorage和localStorage
  • Spring-boot 启动时碰到的错误
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • VUE es6技巧写法(持续更新中~~~)
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 不上全站https的网站你们就等着被恶心死吧
  • 分布式事物理论与实践
  • 如何选择开源的机器学习框架?
  • 数据科学 第 3 章 11 字符串处理
  • 优化 Vue 项目编译文件大小
  • 阿里云移动端播放器高级功能介绍
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • #Datawhale AI夏令营第4期#多模态大模型复盘
  • #stm32整理(一)flash读写
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (floyd+补集) poj 3275
  • (八十八)VFL语言初步 - 实现布局
  • (二)c52学习之旅-简单了解单片机
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (四)js前端开发中设计模式之工厂方法模式
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • .NET Core 2.1路线图
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .Net Redis的秒杀Dome和异步执行
  • .NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • .NET企业级应用架构设计系列之开场白
  • .NET中统一的存储过程调用方法(收藏)
  • [100天算法】-目标和(day 79)
  • [ANT] 项目中应用ANT
  • [BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析