GPT聊天功能,逐字返回数据

news2024/11/27 16:29:38

目录

  • 前言
  • 一、前端
  • 二、后端
    • 1.接收前端请求的api
      • `如下是继续向其他接口请求的api`
      • `如下是直接返回前端数据的api`
      • `甚至可以返回图片`
    • 2.模拟GPT的接口


前言

我们在和GPT交流的时候发现GPT总是逐字的显示,因为GPT是一种基于神经网络的自然语言处理模型,它的训练数据是从大量的文本语料库中获取的。在训练过程中,GPT会学习到文本的语法、语义和上下文信息,并尝试预测下一个单词或字符。因此,当GPT接收到一段文本时,它会根据之前学习到的知识,逐字分析并返回相应的数据。这种逐字返回数据的行为是GPT模型的自然表现,也是它能够生成连贯、流畅文本的重要原因之一。
但当我们想研发一个套壳网站时,因为GPT会逐字返回数据,那么我们也需要逐字为前端提供数据,我们可以使用WebsocketSSE长轮询的方式来实现,这些网络上有太多例子,这次用.net 丰富的对异步支持,编写异步流式返回数据。


一、前端

通过fetch的方式向后端请求数据,并通过时时读取异步流的方式将数据渲染在页面中

<div>   
    <input type="button" id="getdata" value="获取数据" />
    <br />
    <textarea cols="100" rows="50" id="data" style="width: 500px;"></textarea>    
</div>
<script>
    $(document).ready(function () {
        $("#getdata").click(async function fetchText() {
            fetch('/Data/GetText')
                .then(response => {
                    const reader = response.body.getReader();
                    let result = '';
                    return reader.read().then(function processResult({ done, value }) {
                        if (done) {
                            return result;
                        }
                        result += new TextDecoder('utf-8').decode(value);
                        // 将result显示在页面上
                        $('#data').html(result);
                        return reader.read().then(processResult);
                    });
                })
                .catch(error => {
                    console.error(error);
                });
        })
    });

</script>

二、后端

1.接收前端请求的api

如下是继续向其他接口请求的api

		/// <summary>
        /// 向模拟的GPT后端发送请求
        /// </summary>
        /// <returns></returns>
        public async Task GetText()
        {
            var url = "http://localhost:5041/Data/GetStreamData";
            var client = new HttpClient();
            using HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
            var response = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead);
            await using var stream = await response.Content.ReadAsStreamAsync();
            var streamReader = new StreamReader(stream);
            var buffer = new Memory<char>(new char[5]);
            int writeLength = 0;
            while ((writeLength = await streamReader.ReadBlockAsync(buffer)) > 0)
            {
                if (writeLength < buffer.Length)
                {
                    buffer = buffer[..writeLength];
                }
                await Response.WriteAsync(buffer.ToString());
            }
        }

HttpCompletionOption枚举有两个值,默认情况下使用的是ResponseContentRead

  1. ResponseContentRead:等到整个响应完成才完成操作
  2. ResponseHeadersRead:一旦获取到响应头即完成操作,不用等到整个内容响应
    在这里插入图片描述

如下是直接返回前端数据的api

		/// <summary>
        /// 不需要转发可以使用这个接口,也可以实现逐字返回数据
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task GetData(string value)
        {
            List<string> strings = new List<string>() { "兰", "叶", "春", "葳", "蕤", ",", "桂", "华", "秋", "皎", "洁", "。",
"欣", "欣", "此", "生", "意", ",", "自", "尔", "为", "佳", "节", "。",
"谁", "知", "林", "栖", "者", ",", "闻", "风", "坐", "相", "悦", "。",
"草", "木", "有", "本", "心", ",", "何", "求", "美", "人", "折", "!"  };
            string result = string.Empty;
            for (int i = 0; i < strings.Count; i++)
            {
                result = strings[i];
                await Response.WriteAsync(result);
                await Task.Delay(100);
            }
        }

在这里插入图片描述

甚至可以返回图片

   <input type="button" id="getimg" value="获取图片" />
   <img id="img" style="width: 500px;" />
<script>
    $(document).ready(function () {
        $('#getimg').click(async function () {
            const streamingImage = document.getElementById('img');
            fetch('/Data/Stream', {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/octet-stream'
                }
            }).then(response => {
                // 将响应体转换为可读流
                const reader = response.body.getReader();
                // 创建一个Blob对象来存储图像数据
                let chunks = [];
                let blob = new Blob(chunks, { type: 'image/jpeg' });
                // 定义一个函数来处理每个数据块
                function handleDataChunk(chunk) {
                    chunks.push(chunk);
                    blob = new Blob(chunks, { type: 'image/jpeg' });
                    streamingImage.src = URL.createObjectURL(blob);
                }
                // 定义一个函数来处理可读流的数据
                function readStream() {
                    reader.read().then(({ done, value }) => {
                        if (done) {
                            console.log('Stream finished');
                            return;
                        }
                        handleDataChunk(value);
                        readStream();
                    });
                }
                // 开始读取可读流的数据
                readStream();
            }).catch(error => {
                console.error('Fetch error:', error);
            });
        })
    });

</script>
public async Task Stream()
{
    string filePath = "pixelcity.png";
    new FileExtensionContentTypeProvider().TryGetContentType(filePath, out string contentType);
    Response.ContentType = contentType ?? "application/octet-stream";
    var fileStream = System.IO.File.OpenRead(filePath);
    var bytes = new byte[1024];
    int writeLength = 0;
    while ((writeLength = fileStream.Read(bytes, 0, bytes.Length)) > 0)
    {
        await Response.Body.WriteAsync(bytes, 0, writeLength);
        await Task.Delay(100);
    }
}

在这里插入图片描述

2.模拟GPT的接口

代码如下(示例):


        /// <summary>
        /// 模拟GPT接口
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>	
        public async Task GetStreamData()
        {
            string filePath = "文档.txt";
            Response.ContentType = "application/octet-stream";
            var reader = new StreamReader(filePath);
            var buffer = new Memory<char>(new char[5]);
            int writeLength = 0;
            //每次读取5个字符写入到流中
            while ((writeLength = await reader.ReadBlockAsync(buffer)) > 0)
            {
                if (writeLength < buffer.Length)
                {
                    buffer = buffer[..writeLength];
                }
                await Response.WriteAsync(buffer.ToString());
                await Task.Delay(100);
            }
        }

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

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

相关文章

王道考研计算机网络第一章知识点汇总

以上内容为1.1概念与功能的重点知识点 以下为1.2组成与分类&#xff1a; P2P模式下每台主机既可以是客户也可以是服务器&#xff0c;主机越多资源分享速度越快。 1.3标准化工作及相关组织 1.4性能指标 带宽只是指的是从主机内部往传输链路上投送数据的最大能力(从入口端放入数…

棱镜七彩中标浦发银行项目 助力金融行业开源治理

近日&#xff0c;棱镜七彩凭借出色的研发实力和优秀的产品服务能力在众多竞标企业中脱颖而出&#xff0c;成功中标上海浦东发展银行创新实验室“开源治理扫描工具信创改造课题”项目。棱镜七彩将为浦发银行在开源软件治理、软件安全可靠性等方面提供全方位支持。 在数字经济发…

odoo from 表单自定义按钮 执行JS代码 并调用websoket

业务场景&#xff1a; 集成串口读取RFID数据。由于串口是需要在客户端本地电脑执行才可以拿到数据 但是系统 部署在服务器 不能直接调用串口。 解决方案&#xff1a; 利用websoket通信 调用串口 传输 读取到的串口数据&#xff0c;解决服务器与本地之间的通信 本场景是基于odo…

深度解析:2023年软件测试的10个新趋势和挑战

随着技术的飞速发展&#xff0c;软件测试的角色和责任也在经历重大转变。我们在2023年目前所面临的一些新趋势和挑战值得所有从业人员关注。以下是这些主要趋势和挑战的深度分析。 趋势一&#xff1a;人工智能和机器学习在测试中的应用 AI和ML正在越来越多地应用于软件测试&am…

给httprunnermanager接口自动化测试平台演示参数化(五)

文章目录 一、背景1.1、前情回顾 二、参数化实现三、总结 一、背景 参数化&#xff0c;在使用httprunner框架的时候&#xff0c;参数话说实在的不是很实用&#xff0c;因为更多是场景化的用例编写&#xff0c;不用过多的去参数化批量执行&#xff0c;无非也就是登录注册查询啥的…

数据库系统概论 ---知识点大全(期末复习版)

&#xff08;一&#xff09;绪论 数据(Data)&#xff1a;是数据库中存储的基本对象 数据的定义&#xff1a;描述事物的符号记录 数据的种类&#xff1a;文字、图形、图象、声音等 数据的特点&#xff1a;数据与其语义是不可分的 数据库(Database,简称DB)&#xff1a;是长期…

数据结构与算法-跳表详解

我们知道如果一个数组是有序的&#xff0c;查询的时候可以使用二分法进行查询&#xff0c;时间复杂度可以降到 O(logn) &#xff0c;但如果链表是有序的&#xff0c;我们仍然是从前往后一个个查找&#xff0c;这样显然很慢&#xff0c;这个时候我们可以使用跳表&#xff08;Ski…

chatgpt赋能python:Python如何依次取字符——一种简单有效的方法

Python如何依次取字符——一种简单有效的方法 1. 介绍 Python 常常被用于编写文本处理脚本&#xff0c;而文本处理中的一个常见任务就是依次取字符。本文将介绍一种简单高效的方法&#xff0c;让您可以在 Python 中便捷地完成此操作。 2. 如何依次取字符 Python 中的字符串…

黑客入门必备指南

在探讨黑客如何入门之前&#xff0c;首先我们的思想要端正。 作为一名黑客&#xff0c;必须要有正直善良的价值观。 或许你听过这么一句话“能力越大&#xff0c;责任越大”作为一名黑客就是如此&#xff0c;黑客的技术越精湛&#xff0c;能力就越大&#xff0c;就越不能去干…

spark入门 Linux模式 Local模式 (二)

一、下载对应的spark包 https://archive.apache.org/dist/spark/spark-3.0.0/ 我这里下载的是spark-3.0.0-bin-hadoop3.2.tgz 二、解压 tar -zvxf spark-3.0.0-bin-hadoop3.2.tgz三、启动 再解压路径的bin目录执行下 ./spark-shell 四、测试 WordCount代码例子 sc.textFil…

接口测试-使用mock生产随机数据

在做接口测试的时候&#xff0c;有的接口需要进行大量的数据进行测试&#xff0c;还不能是重复的数据&#xff0c;这个时候就需要随机生产数据进行测试了。这里教导大家使用mock.js生成各种随机数据。 一、什么是mock.js mock.js是用于生成随*机数据&#xff0c;拦截 Ajax 请…

uniapp引入uView正确步骤及误区

1.导入uview组件库 2.导入成功后在main.js里引入 import uView from /uni_modules/uview-ui Vue.use(uView)3.在App.vue里引入样式文件 import "/uni_modules/uview-ui/index.scss";4.在pages.json里添加配置 "easycom": {"^u-(.*)": "/…

大聪明教你学Java | parallelStream().forEach() 的踩坑日记

前言 &#x1f34a;作者简介&#xff1a; 不肯过江东丶&#xff0c;一个来自二线城市的程序员&#xff0c;致力于用“猥琐”办法解决繁琐问题&#xff0c;让复杂的问题变得通俗易懂。 &#x1f34a;支持作者&#xff1a; 点赞&#x1f44d;、关注&#x1f496;、留言&#x1f4…

springboot学生管理系统(含源码+数据库)

本次系统开发所用到的Java语言、Spring框架、SpringMVC框架、MyBatis框架、SpringBoot框架以及MySQL。 1.系统分析 &#xff08;1&#xff09;教师管理需求&#xff0c;学校想轻松的查阅指定教师的信息&#xff0c;学校对教师进行一个基本的信息管理&#xff0c;学校可以方便…

【python】脚本编写

这里写自定义目录标题 欢迎使用python来编写脚本环境搭建 欢迎使用python来编写脚本 测试方向&#xff0c;测试报告&#xff0c;单元测试 环境搭建 python环境搭建 下载地址 https://www.python.org/ 文档 https://docs.python.org/3/ pycharm的环境 使用chatgpt来实现代码功…

【安全架构】

概念 安全是产品的属性&#xff0c;安全的目标是保障产品里信息资产的保密性&#xff08;Confidentiality&#xff09;、完整性&#xff08;Integrity&#xff09;和可用性&#xff08;Availability&#xff09;&#xff0c;简记为CIA。 保密性&#xff1a; 保障信息资产不被未…

通过Visual Studio诊断工具定位软件CPU瓶颈

通过VS诊断工具定位软件CPU瓶颈 前情提示&#xff1a;正常情况下我们使用调试模式会看不到诊断工具窗口&#xff0c;控制台会报“无法启动标准收集器。请尝试修复 Visual Studio 的安装。 (HRESULT: 0xe1110002)”这样的错误。 解决方式&#xff1a;通过[Downloads - Visual St…

00后是太恐怖了,工作没两年,跳槽到我们公司起薪20K都快接近我了

在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反感的&#xff0c;是技术平平&…

【JAVA】---逆波兰表达式

一. 逆波兰表达式的介绍 逆波兰表达式又称为后缀表达式&#xff0c;代表的含义是操作数在前&#xff0c;运算符在后。 比如&#xff1a;12&#xff0c;用逆波兰表达式来写的话&#xff0c;就是12。 而12这种写法称为中缀表达式&#xff0c;即运算符在两个操作数之间&#xff0c…