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);}}}

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

语音输入测试:

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

输入的打印:

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

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

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

相关文章

第十五届蓝桥杯 2024 C/C++组 合法密码

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; substr函数&#xff1a; 思路详解&#xff1a; 代码&#xff1a; 代码详解; 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; P10906 [蓝桥杯 2024 国 B] 合法密码 -…

NoSQL 简单讲解

目录 1. NoSQL 的背景与意义 1.1 数据库的演变 1.2 NoSQL 的兴起 2. NoSQL 数据库的分类 2.1 键值存储&#xff08;Key-Value Stores&#xff09; 2.2 文档数据库&#xff08;Document Stores&#xff09; 2.3 列族存储&#xff08;Column-Family Stores&#xff09; 2.…

122.在 Vue3 中使用 OpenLayers 实现图层层级控制(zIndex)显示与设置详解

📅 作者:彭麒 📫 邮箱:1062470959@qq.com 📌 声明:本文源码归吉檀迦俐所有,欢迎学习借鉴,如用于商业项目请注明出处 🙌 🔧 技术栈:Vue 3 + Composition API + OpenLayers 6+ + Element Plus + Tailwind CSS 🧠 一、什么是 zIndex(图层层级)? 在地图开发中…

车载测试用例开发-如何平衡用例覆盖度和测试效率的方法论

1 摘要 在进行车载测试用例编写时&#xff0c;会遇到多个条件导致用例排列组合爆炸的情况&#xff0c;但是为了产品测试质量&#xff0c;我们又不得不保证用例设计的需求覆盖度&#xff0c;这样又会使得测试周期非常长。我们如何平衡效率和测试质量&#xff1f;本文进行了一些…

AI——神经网络以及TensorFlow使用

文章目录 一、TensorFlow安装二、张量、变量及其操作1、张量Tensor2、变量 三、tf.keras介绍1、使用tf.keras构建我们的模型2、激活函数1、sigmoid/logistics函数2、tanh函数3、RELU函数4、LeakReLu5、SoftMax6、如何选择激活函数 3、参数初始化1、bias偏置初始化2、weight权重…

Kubernetes (k8s) 日常运维命令总结

一、资源查看 查看所有命名空间的 Pod kubectl get pod --all-namespaces查看指定命名空间的 Pod kubectl get pod --namespace <命名空间>查看所有部署&#xff08;Deployments&#xff09; kubectl get deployments.apps --all-namespaces查看所有守护进程集&#xff0…

【PostgreSQL教程】PostgreSQL 特别篇之 语言接口连接Perl

博主介绍:✌全网粉丝22W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

07-IDEA企业开发工具-开发入门程序

1. IDEA创建Java项目的代码结构 项目结构: IDEA中的Java项目包含四种主要结构&#xff1a;工程(Project)、模块(Module)、包(Package)、类(Class)。 工程(Project): 代表整个项目&#xff0c;通常是一个磁盘目录或文件夹。模块(Module): 工程下的子单元&#xff0c;用于划分项…

深度解析云计算:概念、优势与分类全览

以下是对云计算概念、优点和分类更详细的介绍&#xff1a; 一、云计算的概念 云计算是一种通过互联网提供计算服务的模式&#xff0c;它基于虚拟化、分布式计算、网络存储等一系列先进技术&#xff0c;将计算资源进行整合和管理&#xff0c;形成一个庞大的资源池。这些资源包…

高并发系统的通用设计方法是什么?

背景 高并发系统的通用设计方法是解决系统在面对大量用户访问时的性能瓶颈问题。当系统遇到性能瓶颈时&#xff0c;通常是因为某个单点资源&#xff08;如数据库、后端云服务器、网络带宽等&#xff09;达到了极限。 为了提升整个系统的容量&#xff0c;需要找到这个瓶颈资源…

【手机】vivo手机应用声音分离方案

文章目录 前言方案 前言 尝试分离vivo手机音乐与其他应用的声音 方案 最佳方案&#xff1a;网易云音乐设置内关闭音量均衡 上传不同的白噪音&#xff0c;成功 goodlock&#xff0c;主要适用于三星手机&#xff0c;vivo不一定适用 app volume control &#xff0c;可行

一个报错说函数为私有函数

你遇到的警告信息&#xff1a; warning: declaration of struct Zero2TenVDrv will not be visible outside of this function [-Wvisibility]这是编译器提示你在某个函数内部声明了一个结构体 struct Zero2TenVDrv&#xff0c;但这个结构体的声明作用域仅限于该函数内部&…

3.2 Agent核心能力:感知、规划、决策与执行

智能代理&#xff08;Agent&#xff09;是一种能够在复杂环境中自主运作的计算实体&#xff0c;其智能行为依赖于四大核心能力&#xff1a;感知&#xff08;Perception&#xff09;、规划&#xff08;Planning&#xff09;、决策&#xff08;Decision-making&#xff09;和执行…

图解Mysql原理:深入理解事务的特性以及它的实现机制

前言 大家好&#xff0c;我是程序蛇玩编程。 Mysql中事务大家不陌生吧&#xff0c;事务就是要保证一组数据库操作&#xff0c;要么全部成功&#xff0c;要么全部失败。那它具有哪些特性&#xff0c;如何实现的呢?接着往下看。 正文 事务的特性: 事务的基本特性主要为四种…

进行网页开发时,怎样把function()中变量值在控制台输出,查看?

在网页开发过程中&#xff0c;为了及时了解JavaScript中的function函数中的变量值&#xff0c;可以用控制台命令console.log()把变量的值在控制台输出&#xff0c;方便调试时对函数变量值进行了解。 看下面的一段示例&#xff1a; <!DOCTYPE html> <html> &l…

linux内核进程管理(1)——创建,退出

linux源码阅读——进程管理&#xff08;1&#xff09; 1. 进程的基本介绍1.1 linux中进程和线程的区别1.2 task_struct中的基本内容1.3 命名空间ns(namespace)命名空间结构图Linux 中的命名空间类型 1.4 进程标识符 2. 创建一个进程的流程2.1 CLONE宏2.2 创建进程系统调用1. do…

人像面部关键点检测

此工作为本人近期做人脸情绪识别&#xff0c;CBAM模块前是否能加人脸关键点检测而做的尝试。由于创新点不是在于检测点的标注&#xff0c;而是CBAM的改进&#xff0c;因此&#xff0c;只是借用了现成库Dilb与cv2进行。 首先&#xff0c;下载人脸关键点预测模型:Index of /file…

【Python】每隔一段时间自动清除网站上cookies的方法

我在写爬虫的时候&#xff0c;经常会因为点击浏览太多的页面&#xff0c;而导致很多的cookies累积。 虽然单个Cookie很小&#xff0c;但长期积累可能占用浏览器存储空间&#xff0c;导致浏览器运行变慢&#xff08;尤其对老旧设备&#xff09;。 而且Cookies&#xff08;尤其…

非隔离电源芯片WT5104

非隔离电源芯片WT5104 非隔离电源芯片 WT5104 介绍 WT5104 是一款超高效且高精度的非隔离降压开关电源恒压控制驱动芯片&#xff0c;在各类电源转换场景中提供5V辅助电源供电发挥着重要作用。 一、芯片特点 高集成度&#xff1a;内部集成 800V 功率 MOSFET&#xff0c;极大减…

基于 Python 的自然语言处理系列(83):InstructGPT 原理与实现

&#x1f4cc; 论文地址&#xff1a;Training language models to follow instructions with human feedback &#x1f4bb; 参考项目&#xff1a;instructGOOSE &#x1f4f7; 模型架构图&#xff1a; 一、引言&#xff1a;为什么需要 InstructGPT&#xff1f; 传统的语言模型…