Unity之使用火山引擎实现文字提问流式回复

文字提问

设置参数apiKey

调用Request方法,传入对话内容

注册事件,接收回复内容

csharp 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// 文本提问
/// </summary>
public class TextQuestions : MonoBehaviour
{
    string baseUrl = "https://ark.cn-beijing.volces.com/api/v3/chat/completions";
    string apiKey = "";

    [Header("模型")]
    [SerializeField] string model = "doubao-seed-2-0-code-preview-260215";
    [Header("深度思考")]
    [SerializeField] string thinking = "disabled";
    [Header("模型回答最大长度(单位token)")]
    [SerializeField] int maxTokens = 4096;
    [Header("思考消耗")]
    [SerializeField] string reasoningEffort = "minimal";

    public event Action<string, bool> onReceive;
    public event Action onCompleted;
    public event Action OnError;

    void OnReceive(string content)
    {
        var respone = JsonUtility.FromJson<ResponeChatMessage>(content);
        onReceive?.Invoke(respone.choices[0].delta.content,
        respone.choices[0].finish_reason == "stop");
    }

    void OnCompleted()
    {
        onCompleted?.Invoke();
    }

    public void Request(List<Message> messages)
    {
        RequestChat requestMessages = new RequestChat
        {
            messages = messages,
            model = model,
            thinking = new ThinkingType()
            {
                type = thinking,
            },
            max_tokens = maxTokens,
            reasoning_effort = reasoningEffort,
        };
        string jsonData = JsonUtility.ToJson(requestMessages);
        StartCoroutine(PostChat(jsonData));
    }

    IEnumerator PostChat(string jsonData)
    {
        using (UnityWebRequest request = new UnityWebRequest(baseUrl, UnityWebRequest.kHttpVerbPOST))
        {
            byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonData);
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);

            var tTSDownload = new TTSDownload();
            tTSDownload.OnObjectReceived += OnReceive;
            tTSDownload.OnComplete += OnCompleted;

            request.downloadHandler = tTSDownload;

            request.SetRequestHeader("Content-Type", "application/json");
            request.SetRequestHeader("Authorization", "Bearer " + apiKey);
            yield return request.SendWebRequest();
            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("请求失败:" + request.error);
                OnError?.Invoke();
            }

            tTSDownload.OnObjectReceived -= OnReceive;
            tTSDownload.OnComplete -= OnCompleted;
        }
    }
}

[Serializable]
public class RequestChat
{
    public string model;
    public List<Message> messages;
    public ThinkingType thinking;
    public int max_tokens;
    public string reasoning_effort;
    public bool stream = true;
}
[Serializable]
public class ThinkingType
{
    public string type;
}

[Serializable]
public class Message
{
    public string role;
    public string content;
    public string thinking;
}

[Serializable]
public class ResponeChatMessage
{
    public Choices[] choices;
}

[Serializable]
public class Choices
{
    public MessageDelta delta;
    public string finish_reason;
    public int index;
}

[Serializable]
public class MessageDelta
{
    public string content;
    public string role;
}

拓展DownloadHandler

csharp 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

public class TTSDownload : DownloadHandlerScript
{
    private StringBuilder buffer = new StringBuilder();
    public event Action<string> OnObjectReceived;
    public event Action OnComplete;

    public TTSDownload() : base(new byte[4096]) { }

    protected override bool ReceiveData(byte[] data, int dataLength)
    {
        string chunk = Encoding.UTF8.GetString(data, 0, dataLength);
        buffer.Append(chunk);
        ProcessBuffer();
        return true;
    }

    private void ProcessBuffer()
    {
        string content = buffer.ToString();
        int splitStartIndex = -1;
        int braceCount = 0;
        int lastProcessed = 0;
        for (int i = 0; i < content.Length; i++)
        {
            if (content[i] == '{')
            {
                if (braceCount == 0) splitStartIndex = i;
                braceCount++;
            }
            else if (content[i] == '}')
            {
                braceCount--;
                if (braceCount == 0 && splitStartIndex != -1)
                {
                    string obj = content.Substring(splitStartIndex, i - splitStartIndex + 1);
                    OnObjectReceived?.Invoke(obj);
                    splitStartIndex = -1;
                    lastProcessed = i + 1;
                }
            }
        }

        if (lastProcessed > 0)
            buffer.Remove(0, lastProcessed);
    }

    protected override void CompleteContent()
    {
        OnComplete?.Invoke();
    }
}
相关推荐
江上闲人.4 小时前
Wardogs战犬\战狗Beta测试启动报错UE崩溃卡顿?解决方法来了
游戏·游戏引擎·虚幻·战犬·战狗·wardogs
小贺儿开发8 小时前
Unity 程序员编曲花絮:汪峰《河流》细节修复
科技·学习·unity·程序员·音乐·demo·写代码
598866753@qq.com9 小时前
Unity UniText笔记
unity·unitext
杨丰玮4189 小时前
从零手写Java飞机躲障碍游戏|Swing绘图、鼠标跟随、计时器碰撞检测实战(五)
java·python·游戏·游戏引擎·图形渲染·动画·贴图
鼎艺创新科技21 小时前
不依赖 UE/Unity:我们如何从零搭建一套国产三维 GIS 渲染引擎
人工智能·算法·unity·游戏引擎·三维电子沙盘
huihui3611 天前
校友网管理软件技术选型框架:基于功能核验与系统架构的量化评估
unity·系统架构·游戏引擎
五仁烧饼1 天前
Unity性能优化系列设置篇 - URP 移动端设置基线与分档策略
unity·游戏引擎
新手unity自用笔记1 天前
unity基于Socket的网络学习
网络·网络协议·学习·unity·c#·游戏引擎
心前阳光1 天前
Unity之XR Interaction Toolkit | IPointerDownHandler问题
unity·游戏引擎·xr
帅_shuai_2 天前
unity 静态字段内存查找工具
unity·游戏引擎