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

直接上代码:

解决步骤1:引入vue+elementUi

  <head>
    <meta charset="UTF-8" />
    <title>Fetch Stream Example</title>
  </head>
  <script src="./vue.js"></script>
  <!-- 引入样式 -->
  <link
    rel="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">
            <img
              src="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-input
          type="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的内容,所以没有实现最终的效果。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部