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

Unity 接入阿里的全模态大模型Qwen2.5-Omni

1 参考

根据B站up主阴沉的怪咖  开源的项目的基础上修改接入

AI二次元老婆开源项目地址(unity-AI-Chat-Toolkit):

Github地址:https://github.com/zhangliwei7758/unity-AI-Chat-Toolkit

Gitee地址:https://gitee.com/DammonSpace/unity-ai-chat-toolkit

2 官网参考

找到官网发现没C#的案例,于是参考python的脚本,改为C#

阿里全模态的官方地址:阿里云百炼

3 语音输入部分

在基类LLM里添加下属代码

  public virtual void PostMsgAudio(string base64Audio, Action<string> _callback, Action<bool> _endCallBack = null, Action<AudioClip> _AudioCallBack = null){//上下文条数设置CheckHistory();//提示词处理string message = "当前为角色的人物设定:" + m_Prompt +" 回答的语言:" + lan;//缓存发送的信息列表Content content = new Content(){type = "input_audio",input_audio = new Input_audio(){data = string.Format("data:;base64,{0}", base64Audio),format = "mp3"}};Content content2 = new Content(){type = "text",text = message};Content[] contents = new Content[] { content, content2 };m_DataAudioList.Add(new SendDataAudio("user", contents));StartCoroutine(RequestAudio(message, _callback, _endCallBack, _AudioCallBack));}public virtual IEnumerator RequestAudio(string _postWord, System.Action<string> _callback, Action<bool> _endCallBack = null, Action<AudioClip> _AudioCallBack = null){yield return new WaitForEndOfFrame();}[Serializable]public class SendDataAudio{[SerializeField] public string role;[SerializeField] public Content[] content;public SendDataAudio() { }public SendDataAudio(string _role, Content[] _content){role = _role;content = _content;}}[Serializable]public class Content{[SerializeField] public string type;[SerializeField] public Input_audio input_audio;[SerializeField] public string text;}[Serializable]public class Input_audio{[SerializeField] public string data;[SerializeField] public string format;}

4 语音解析部分

新添加一个类AliQwenOmniChat,继承LLM

using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using static ALiChat;public class AliQwenOmniChat : LLM
{public AliQwenOmniChat(){url = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";}/// <summary>/// api key/// </summary>[SerializeField] private string api_key;/// <summary>/// AI设定/// </summary>public string m_SystemSetting = string.Empty;/// <summary>/// qwen-omni-turbo-0119/// </summary>public string m_gptModel = "qwen-omni-turbo-0119";[Header("设置说话的声音")] public SpeekerRole per = SpeekerRole.Cherry;private void Start(){//运行时,添加AI设定m_DataList.Add(new SendData("system", m_SystemSetting));}/// <summary>/// 发送消息/// </summary>/// <returns></returns>public override void PostMsgAudio(string _msg, Action<string> _callback, Action<bool> endAction, Action<AudioClip> AudioAction){base.PostMsgAudio(_msg, _callback, endAction, AudioAction);}public override IEnumerator RequestAudio(string requestData, Action<string> callback, Action<bool> EndAction, Action<AudioClip> AudioAction){using (var request = new UnityWebRequest(url, "POST")){PostDataAudio _postData = new PostDataAudio{model = m_gptModel,stream = this.stream,messages = m_DataAudioList,temperature = 1,top_p = 0.7f,modalities = new string[] { "text", "audio" },audio = new Audio { voice = SetSpeeker(per), format = "wav" },stream_options = new Stream_options { include_usage = true },};string _jsonText = JsonUtility.ToJson(_postData).Trim();Debug.Log(_jsonText);byte[] data = System.Text.Encoding.UTF8.GetBytes(_jsonText);request.uploadHandler = (UploadHandler)new UploadHandlerRaw(data);request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();request.SetRequestHeader("Content-Type", "application/json");request.SetRequestHeader("Authorization", string.Format("Bearer {0}", api_key));yield return request.SendWebRequest();if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError){Debug.LogError("阿里Error: " + request.error);callback?.Invoke("阿里大模型出现点问题");yield break;}string temp = request.downloadHandler.text;var datas = temp.Split("data:");string textStr = "";string audioStr = "";foreach (var requestJson in datas){if (string.IsNullOrEmpty(requestJson))continue;Debug.Log(requestJson);var jsonP = JToken.Parse(requestJson);var item = jsonP["choices"][0];var audio = item["delta"].SelectToken("audio");if (audio != null){if (audio.SelectToken("transcript") != null){var tt = audio.SelectToken("transcript")?.ToString();//文字部分if (!string.IsNullOrEmpty(tt)){tt = tt.Trim();textStr += tt;}var finish = item.SelectToken("finish_reason");if (finish != null && finish.ToString() == "stop"){break;}}else{audioStr += audio.SelectToken("data")?.ToString();//语音部分}}}if (!string.IsNullOrEmpty(textStr)){callback.Invoke(textStr);}if (!string.IsNullOrEmpty(audioStr)){AudioAction(PlayAudio(audioStr));}EndAction.Invoke(true);}}//解析输出的Base64 编码的音频数据AudioClip PlayAudio(string audioString){if (!string.IsNullOrEmpty(audioString)){byte[] audioBytes = Convert.FromBase64String(audioString);AudioClip audioClip = WavUtility.ConvertBytesToAudioClip(audioBytes, 24000);return audioClip;}return null;}//阿里提供的四种支持的音色private string SetSpeeker(SpeekerRole _role){if (_role == SpeekerRole.Cherry) return "Cherry";if (_role == SpeekerRole.Serena) return "Serena";if (_role == SpeekerRole.Ethan) return "Ethan";if (_role == SpeekerRole.Chelsie) return "Chelsie";return "Cherry";//默认为音色Cherry}#region 数据包[Serializable]public class PostDataAudio{[SerializeField] public string model;[SerializeField] public bool stream;[SerializeField] public List<SendDataAudio> messages;[SerializeField] public float temperature = 0.7f;[SerializeField] public float top_p;[SerializeField] public string[] modalities;[SerializeField] public Audio audio;[SerializeField] public Stream_options stream_options;}[Serializable]public class Audio{public string voice;public string format;}[Serializable]public class Stream_options{public bool include_usage;}#endregionpublic enum SpeekerRole{Cherry,Serena,Ethan,Chelsie}
}

5 测试

输入需要语音输入时,找到开源项目里的录音结束处理的AcceptClip方法修改为:

  public bool AliQwenOmniChat = false;  private Queue<string> strDatas = new Queue<string>();private Queue<AudioClip> clipDatas = new Queue<AudioClip>();private bool end = true;private void AcceptClip(AudioClip _audioClip){if (m_ChatSettings.m_SpeechToText == null)return;if (AliQwenOmniChat)//阿里全模态语音输入时{byte[] _audioData = WavUtility.FromAudioClip(_audioClip);string base64String = Convert.ToBase64String(_audioData);m_ChatSettings.m_ChatModel.PostMsgAudio(base64String, CallBack, EndCallBack, AudioCallBack);//阿里语音输入m_InputWord.text = "阿里语音输入完成";}else{m_ChatSettings.m_SpeechToText.SpeechToText(_audioClip, DealingTextCallback);}}private void EndCallBack(bool isCompate){Debug.Log("是否回到结束:" + isCompate);this.end = isCompate;}private void CallBack(string _response)//文字回调{_response = _response.Trim();//m_TextBack.text = "";//Debug.Log("收到AI回复:" + _response);if (GetMesssgeIndex == 0){m_TextBack2.text = "";//切换到说话动作Debug.Log("播放声音******");m_TextBack.text = "";         SetAnimator("state", 2);}GetMesssgeIndex++;if (!string.IsNullOrEmpty(_response)){if (Ali)//阿里多模态直接返回语音  放到队列里面          strDatas.Enqueue(_response);elsem_ChatSettings.m_TextToSpeech.Speak(_response, PlayAudio);}//添加声音回调的方法private void AudioCallBack(AudioClip clip){clipDatas.Enqueue(clip);}private void Update(){if (AliQwenOmniChat){if (strDatas.Count > 0 && m_WriteState == false){StartTypeWords(strDatas.Dequeue());}if (clipDatas.Count > 0 && m_AudioSource.isPlaying == false){m_AudioSource.clip = clipDatas.Dequeue();m_AudioSource.Play();//返回的语音播放isEnd = false;}else if (m_AudioSource.isPlaying == false && this.end){if (isEnd){return;}isEnd = true;m_ChatHistory.Add(m_TextBack.text);m_AudioSource.Stop();resultDatas.Clear();GetMesssgeIndex = 0;切换到等待动作Debug.Log("切换到等待动作");             SetAnimator("state", 0);}}}

文字输入和开源项目里的原先输入一样。

语音输入测试:

我用声音问:你叫什么名字?

输入的打印:

语音输入后,返回了文字和声音,返回的打印:

相关文章:

Unity 接入阿里的全模态大模型Qwen2.5-Omni

1 参考 根据B站up主阴沉的怪咖 开源的项目的基础上修改接入 AI二次元老婆开源项目地址(unity-AI-Chat-Toolkit): Github地址&#xff1a;https://github.com/zhangliwei7758/unity-AI-Chat-Toolkit Gitee地址&#xff1a;https://gitee.com/DammonSpace/unity-ai-chat-too…...

Nginx知识点

Nginx发展历史 Nginx 是由俄罗斯程序员 Igor Sysoev 开发的高性能开源 Web 服务器、反向代理服务器和负载均衡器 &#xff0c;其历史如下&#xff1a; 起源与早期开发&#xff08;2002 - 2004 年&#xff09; 2002 年&#xff0c;当时 Igor Sysoev 在为俄罗斯门户网站 Rambl…...

NLP高频面试题(五十五)——DeepSeek系列概览与发展背景

大型模型浪潮背景 近年来,大型语言模型(Large Language Model, LLM)领域发展迅猛,从GPT-3等超大规模模型的崛起到ChatGPT的横空出世,再到GPT-4的问世,模型参数规模和训练数据量呈指数级增长。以GPT-3为例,参数高达1750亿,在570GB文本数据上训练,显示出模型规模、数据…...

详解 Unreal Engine(虚幻引擎)

详解 Unreal Engine&#xff08;虚幻引擎&#xff09; Unreal Engine&#xff08;简称 UE&#xff09;是由 Epic Games 开发的一款全球领先的实时渲染引擎&#xff0c;自 1998 年随首款游戏《Unreal》问世以来&#xff0c;已发展成为覆盖 游戏开发、影视制作、建筑可视化、汽车…...

Mysql从入门到精通day6————时间和日期函数精讲

关于Mysql的日期和时间计算函数种类非常繁多,此处我们对常用的一些函数的用法通过实例演示让读者体会他们的用法,文章末尾也给出了时间和日期计算的全部函数 函数1:curdate()和current_date()函数 作用:获取当前日期 select curdate(),current_date();运行效果:...

逻辑漏洞安全

逻辑漏洞是指由于程序逻辑不严导致一些逻辑分支处理错误造成的漏洞。 在实际开发中&#xff0c;因为开发者水平不一没有安全意识&#xff0c;而且业务发展迅速内部测试没有及时到位&#xff0c;所以常常会出现类似的漏洞。 由于开发者/设计者在开发过程中&#xff0c;由于代码…...

Github 热点项目 rowboat 一句话生成多AI智能体!5分钟搭建企业级智能工作流系统

今日高星项目推荐&#xff1a;rowboat凭借1705总星数成为智能协作工具黑马&#xff01;亮点速递&#xff1a;①自然语言秒变AI流水线——只需告诉它“帮外卖公司处理配送异常”&#xff0c;立刻生成多角色协作方案&#xff1b;②企业工具库即插即用&#xff0c;Python包HTTP接口…...

(26)VTK C++开发示例 ---将点坐标写入PLY文件

文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;VTK开发 &#x1f448; 1. 概述 本示例演示了将球体数据写入ply文件&#xff0c;并从ply文件读取显示&#xff1b; PLY 文件&#xff08;Polygon Fil…...

32BIT的SPI主机控制

SPI传输位数可参数化配置。 SPI_MASTER: timescale 1ns / 1ps module SPI_Master #(parameter CLK_FREQ 50,parameter SPI_CLK 1000,parameter CPOL 0,parameter CPHA 0 )(input clk,input rst_n,input WrRdReq, //读/写数据请求output …...

2025蓝桥省赛c++B组第二场题解

前言 这场的题目非常的简单啊&#xff0c;至于为什么有第二场&#xff0c;因为当时河北正在刮大风被迫停止了QwQ&#xff0c;个人感觉是历年来最简单的一场&#xff0c;如果有什么不足之处&#xff0c;还望补充。 试题 A: 密密摆放 【问题描述】 小蓝有一个大箱子&#xff0…...

vue3 vite打包后动态修改打包后的请求路径,无需打多个包给后端

整体思路和需求 部署多个服务器环境的时候&#xff0c;需要多次打包很麻烦&#xff0c;所以需要打包之后动态的修改 1.创建一个webconfig文件夹 2.在自己封装的接口文件中 判断是否在生产环境&#xff0c;然后将数据保存到vuex 中 代码&#xff1a; // 创建axios服务的函数 …...

Nacos-SpringBoot 配置无法自动刷新问题排查

背景 Nacos SpringBoot版本中&#xff0c;提供了NacosValue注解&#xff0c;支持控制台修改值时&#xff0c;自动刷新&#xff0c;但是今天遇见了无法自动刷新的问题。 环境 SpringBoot 2.2.x nacos-client&#xff1a;2.1.0 nacos-config-spring-boot-starter&#xff1a;0…...

【RabbitMQ消息队列】详解(一)

初识RabbitMQ RabbitMQ 是一个开源的消息代理软件&#xff0c;也被称为消息队列中间件&#xff0c;它遵循 AMQP&#xff08;高级消息队列协议&#xff09;&#xff0c;并且支持多种其他消息协议。 核心概念 生产者&#xff08;Producer&#xff09;&#xff1a;创建消息并将其…...

FFmpeg之三 录制音频并保存, API编解码从理论到实战

在学习FFmpeg的时候&#xff0c;想拿demo来练习&#xff0c;官方虽有示例&#xff0c;但更像是工具演示&#xff0c;新手不好掌握&#xff0c;在网上找不到有文章&#xff0c;能给出完整的示例和关键点的分析说明&#xff0c;一步一个错误&#xff0c;慢慢啃过来的&#xff0c;…...

Kaamel白皮书:2025版COPPA落地实操指南

COPPA简介 《儿童在线隐私保护法案》&#xff08;COPPA&#xff09;于1998年在美国颁布&#xff0c;其最初的动因源于人们日益增长的对互联网上收集儿童个人信息的担忧。为了响应这一问题&#xff0c;联邦贸易委员会&#xff08;FTC&#xff09;被授权制定并执行相关法规。COP…...

Jenkins Pipeline 构建 CI/CD 流程

文章目录 jenkins 安装jenkins 配置jenkins 快速上手在 jenkins 中创建一个新的 Pipeline 作业配置Pipeline运行 Pipeline 作业 Pipeline概述Declarative PipelineScripted Pipeline jenkins 安装 安装环境&#xff1a; Linux CentOS 10&#xff1a;Linux CentOS9安装配置Jav…...

蓝桥杯 8. 移动距离

移动距离 原题目链接 题目描述 X 星球居民小区的楼房全是一样的&#xff0c;并且按矩阵样式排列。楼房的编号为 1, 2, 3, ⋯⋯。 当排满一行时&#xff0c;从下一行相邻的楼往反方向排号。 例如&#xff0c;当小区排号宽度为 6 时&#xff0c;排列如下&#xff1a; 1 2 …...

AJAX 介绍

一、什么是AJAX ? AJAX 是 异步的 JavaScript 和 XML&#xff08;Asynchronous JavaScript And XML&#xff09; 的缩写&#xff0c;是一种实现浏览器与服务器进行数据通信的技术。其核心是通过 XMLHttpRequest 对象在不重新刷新页面的前提下&#xff0c;与服务器交换数据并更…...

硬盘损坏数据恢复后对python程序的影响

最近硬盘突然间坏掉了&#xff0c;让数据商恢复了2个月今天终于拿到了恢复后的数据。 但是一测试问题就来了&#xff1a; PS E:\geosystem> python manage.py runserver 0.0.0.0:5000 Unhandled exception in thread started by <function check_errors.<locals>.…...

promis(resolve,reject)入门级别

JavaScript Promise 的定义 Promise 是一种用于处理异步操作的对象&#xff0c;表示一个可能已经完成或者尚未完成的操作的结果。它的核心作用在于简化复杂的回调嵌套问题&#xff08;即所谓的“回调地狱”&#xff09;&#xff0c;使异步代码更加清晰易读。 Promise 的状态 …...

w~嵌入式C语言~合集6

我自己的原文哦~ https://blog.51cto.com/whaosoft/13870384 一、开源MCU简易数字示波器项目 这是一款采用STC8A8K MCU制造的简单示波器&#xff0c;只有零星组件&#xff0c;易于成型。这些功能可以涵盖简单的测量&#xff1a; 该作品主要的规格如下&#xff1a; 单片机…...

学习海康VisionMaster之路径提取

一&#xff1a;进一步学习了 今天学习下VisionMaster中的路径提取&#xff1a;可在绘制的路径上等间隔取点或查找边缘点 二&#xff1a;开始学习 1&#xff1a;什么是路径提取&#xff1f; 相当于事先指定一段路径&#xff0c;然后在对应的路径上查找边缘&#xff0c;这个也是…...

第十二章-PHP文件上传

第十二章-PHP文件上传 一&#xff0c;文件上传原理 一、HTTP协议与文件上传 1. 请求体结构 当表单设置enctype"multipart/form-data"时&#xff0c;浏览器会将表单数据编码为多部分&#xff08;multipart&#xff09;格式。 Boundary分隔符&#xff1a;随机生成的…...

第35课 常用快捷操作——用“鼠标左键”拖动图元

概述 拖动某个图元&#xff0c;是设计过程中常需要用到的操作&#xff0c;我们可以在原理图中拖动某个元器件符号&#xff0c;也可以在PCB图中拖动某个焊盘。 和常用的软件类似&#xff0c;用按住鼠标左键的方式来完成拖动操作。 用鼠标左键拖动图元 在想要拖动的图元上&…...

qt.qpa.plugin: Could not find the Qt platform plugin “cocoa“ in “ “

开发的pyqt项目在Windows运行时没啥问题&#xff0c;移植到Mac中时&#xff0c;发现一直报错qt.qpa.plugin: Could not find the Qt platform plugin “cocoa” in " "&#xff0c;一开始认为是pyqt版本问题&#xff0c;换了版本依旧不行。后续按照网上pip install o…...

二、Web服务常用的I/O操作

一、单个或者批量上传文件 前端&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>文件…...

「Mac畅玩AIGC与多模态04」开发篇01 - 创建第一个 LLM 对话应用

一、概述 本篇介绍如何在 macOS 环境下&#xff0c;基于已部署完成的 Dify 平台和本地 LLM 模型&#xff08;如 DeepSeek&#xff09;&#xff0c;创建并测试第一个基础对话应用&#xff0c;实现快速验证推理服务与平台交互功能。 二、应用创建流程 1. 通过首页创建应用 打…...

深度探究获取淘宝商品数据的途径|API接口|批量自动化采集商品数据

在电商行业竞争日益激烈的今天&#xff0c;淘宝商品数据如同蕴藏巨大价值的宝藏&#xff0c;无论是商家进行竞品分析、优化商品策略&#xff0c;还是数据分析师挖掘市场趋势&#xff0c;都离不开对这些数据的获取与分析。本文将深入探讨获取淘宝商品数据的多种途径&#xff0c;…...

马哥教育Linux云计算运维课程

课程大小&#xff1a;19.1G 课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/90640128 更多资源下载&#xff1a;关注我 你是否找了很多资料看了很多视频聊了很多群友&#xff0c;却发现自己技术仍然原地踏步&#xff1f;本教程联合BAT一线导师倾囊相授…...

FPGA与边缘AI:计算革命的前沿力量

在数字化转型浪潮中&#xff0c;边缘计算和人工智能正引领着技术革命。而FPGA&#xff08;现场可编程门阵列&#xff09;作为一种独特的硬件架构&#xff0c;正逐渐成为边缘AI领域的关键推动力。本文将探讨FPGA与边缘AI的结合如何重塑我们的数字世界&#xff0c;以及这一技术融…...