最近在做Unity接入DeepSeek,流式接收DeepSeek传来的信息,因为UnityWebRequest默认是接收完消息后才响应,所以需要自定义DownloadHandler,用其中的ReceiveData()方法实时处理数据。

这是我自己写的,模版大概是这样

    /// <summary>
    /// 自定义DownloadHandler用于实时处理流式数据
    /// </summary>
    public class StreamingDownloadHandler : DownloadHandlerScript
    {
        private StringBuilder contentData = new StringBuilder();

        protected override bool ReceiveData(byte[] data, int dataLength)
        {
            if (data == null || data.Length == 0) return false;

            //实时处理接收到的每个数据块
            string chunk = Encoding.UTF8.GetString(data, 0, dataLength);
            List<string> contents = ProcessStreamChunk(chunk);          

            foreach(string content in contents)
            {
                contentData.Append(content);
            }

            //等contentData加入了一次数据,再开启显示
            if (DeepSeekManager.instance.currentStreamReceive == null)
            {
                Debug.Log("StartReceive");
                DeepSeekManager.instance.SaveReceiveData(contentData);      //Manager获取contentData地址
                DeepSeekManager.instance.StartStreamReceive();
            }
            return true;
        }

        protected override void CompleteContent()
        {
            Debug.Log("流式传输完成");
            DeepSeekManager.instance.IsReceivingStream = false;
        }

        /// <summary>`
        /// 处理流式数据
        /// </summary>
        /// <param name="streamData"></param>
        private List<string> ProcessStreamChunk(string chunk)
        {
            string[] jsonStrArray = chunk.Split("data:");
            List<string> contentList = new List<string>();

            for(int i = 0;i < jsonStrArray.Length; i++)
            {
                if (jsonStrArray[i].Contains("{") == false)
                {
                    continue;
                }
                DeepSeekResponseData data = JsonMapper.ToObject<DeepSeekResponseData>(jsonStrArray[i].Trim());
                contentList.Add(data.choices[0].delta.content);
            }
            return contentList;
        }

    }

这是ReceiveData()方法官方描述

我想实现像DeepSeek网页版那样暂停和继续生成,但是我发现ReceiveData这玩意没有api可以停止,导致我发送第二条消息的时候,第一条消息还没有接收完毕,就直接乱了。

用request.SendWebRequest(); 发送请求后,ReceiveData()会无法中断

由于DownloadHandler基类没有类似Close关闭的方法。试了DownloadHandler.Dispose() 发现没啥鸟用,后来试出来了一个方法,就是直接将request请求中断,用request.Abort()。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐