Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理

Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理

目录

Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理

一、简单介绍

二、实现原理

三、注意实现

四、简单实现步骤

五、关键代码

六、附加

创建新的 .NET Core ,获取 Azure.AI.OpenAI dll 包

检索密钥和终结点


一、简单介绍

Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。

本节介绍,这里在使用微软的Azure 把Azue.AI.OpenAI 接入到Unity中,在Unity中直接调用 Azue.AI.OpenAI 接口函数,实现简单聊天功能,这里简单说明,如果你有更好的方法,欢迎留言交流。

二、实现原理

1、官网申请得到Azure OpenAI 对应的 AZURE_OPENAI_ENDPOINT 和 AZURE_OPENAI_KEY,以及对应的模型名 DeploymentOrModelName

2、把相关的 dll 引入进来,主要有 Azure.AI.OpenAI、 Azure.Core 等等

3、创建客户端 OpenAIClient = new(new Uri(AZURE_OPENAI_ENDPOINT ), new AzureKeyCredential(AZURE_OPENAI_KEY));

OpenAIClient .GetChatCompletionsXXAsync (DeploymentOrModelName,prompt)

来发起请求

三、注意实现

1、这里使用 Async 来异步获取数据,避免发起请求时卡顿

2、由于使用 Async ,各种对应的数据事件进行必要的 Loom.QueueOnMainThread 处理,不然可能会报入的错误: Net.WebException : Error: NameResolutionFailure

3、使用 CancellationTokenSource 来终止 Async 造成的 Task 任务

4、ChatCompletionsOptions 的 MaxTokens 可能可以控制Stream的速度和接收的内容

四、简单实现步骤

1、根据 Azure OpenAI 的 官网的操作下载 Azure.AI.OpenAI 相关 dll 包,然后导入到Unity Plugins (目前对应的是当前最新版的 netstandard2.0 或者 netstandard2.1 的dll 包,根据需要选择,dll (dotnet add package)下载默认路径为 C:\Users\YOUR_USER_NAME\.nuget\packages)

快速入门 - 开始通过 Azure OpenAI 服务使用 ChatGPT 和 GPT-4 - Azure OpenAI Service | Microsoft Learn

2、 简单的搭建场景

3、简单的封装一下AzureOpenAIQueryHandler接口

 4、添加测试脚本 TestAzureOpenAI

5、对应挂载脚本TestAzureOpenAI 到场景中,并对应赋值

 6、运行场景、效果如下

五、关键代码

1、AzureOpenAIQueryHandler


using Azure.AI.OpenAI;
using Azure;
using System;
using UnityEngine;
using System.Threading.Tasks;
using System.Threading;

public class AzureOpenAIQueryHandler 
{
    const string END_POINT = "AZURE_OPENAI_ENDPOINT ";
    const string KEY = "AZURE_OPENAI_KEY";
    const string DeploymentOrModelName = "DeploymentOrModelName";

    OpenAIClient m_Client;
    StreamingChatCompletions m_StreamingChatCompletions;

    private CancellationTokenSource m_CancellationTokenSource;
    private CancellationTokenSource m_StreamCancellationTokenSource;

    public AzureOpenAIQueryHandler() {
        m_Client = new(new Uri(END_POINT), new AzureKeyCredential(KEY));
    }
    ~AzureOpenAIQueryHandler() {
        m_StreamingChatCompletions?.Dispose();
        m_StreamingChatCompletions = null;
        m_Client = null;
    }

    /// <summary>
    /// 正常聊天
    /// </summary>
    /// <param name="prompt">聊天的内容</param>
    /// <param name="onStartAction">发起聊天开始事件</param>
    /// <param name="onGettedDataEndAction">聊天接收内容数据事件</param>
    public async Task SendChat(string prompt, Action onStartAction, Action<string> onGettedDataEndAction) {
        StopChat();
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        m_CancellationTokenSource = cancellationTokenSource;
        Loom.QueueOnMainThread(() =>
        {
            onStartAction?.Invoke();
        });
        if (cancellationTokenSource?.IsCancellationRequested == false) {
            Response<ChatCompletions>  response = await m_Client.GetChatCompletionsAsync(
            deploymentOrModelName: DeploymentOrModelName,
            PromptDataHandler(prompt));

            if (cancellationTokenSource?.IsCancellationRequested == false)
            {
                string content = response.Value.Choices[0].Message.Content;
                Loom.QueueOnMainThread(() =>
                {
                    onGettedDataEndAction?.Invoke(content);
                });
            }
        }
    }

    /// <summary>
    /// 停止访问
    /// </summary>
    public void StopChat() {
        if (m_CancellationTokenSource != null)
        {
            m_CancellationTokenSource.Cancel();
            m_CancellationTokenSource.Dispose();
            m_CancellationTokenSource = null;
        }
    }

    /// <summary>
    /// 流式聊天
    /// </summary>
    /// <param name="prompt">聊天的内容</param>
    /// <param name="onStartAction">发起聊天开始事件</param>
    /// <param name="gettingDataAction">流式正在接收数据</param>
    /// <param name="onGettedDataEndAction">流式数据结束事件</param>
    /// <returns></returns>
    public async Task SendStreamChat(string prompt, Action onStartAction, Action<string> gettingDataAction,Action onGettedDataEndAction) {

        StopStreamChat();
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        m_StreamCancellationTokenSource = cancellationTokenSource;
        Debug.Log(" Start ");
        Loom.QueueOnMainThread(() =>
        {
            onStartAction?.Invoke();
        });

        if (m_StreamingChatCompletions != null) { Debug.Log(" streamingChatCompletions.Dispose "); m_StreamingChatCompletions.Dispose(); }
        Response<StreamingChatCompletions> response = await m_Client.GetChatCompletionsStreamingAsync(
            deploymentOrModelName: DeploymentOrModelName,
            PromptDataHandler(prompt));
        if (cancellationTokenSource?.IsCancellationRequested==false)
        {
            using (m_StreamingChatCompletions = response.Value)
            {

                await foreach (StreamingChatChoice choice in m_StreamingChatCompletions.GetChoicesStreaming())
                {
                    await foreach (ChatMessage message in choice.GetMessageStreaming())
                    {
                        if (cancellationTokenSource?.IsCancellationRequested == false) {
                            Loom.QueueOnMainThread(() =>
                            {
                                //Debug.Log(message.Content);
                                gettingDataAction?.Invoke(message.Content);
                            });
                        }
                    }
                }
            }
        }

        if (cancellationTokenSource?.IsCancellationRequested == false) { 
            Debug.Log(" End ");
            Loom.QueueOnMainThread(() => {
                onGettedDataEndAction?.Invoke();
            });
        }
    }

    /// <summary>
    /// 停止流式访问
    /// </summary>
    public void StopStreamChat()
    {
        if (m_StreamCancellationTokenSource != null)
        {
            m_StreamCancellationTokenSource.Cancel();
            m_StreamCancellationTokenSource.Dispose();
            m_StreamCancellationTokenSource = null;
        }
    }

    /// <summary>
    /// 根据需要做数据处理
    /// </summary>
    /// <param name="prompt"></param>
    /// <returns></returns>
    protected virtual ChatCompletionsOptions PromptDataHandler(string prompt) {
        ChatCompletionsOptions chatCompletionsOptions = new ChatCompletionsOptions()
        {
            Messages =
            {
                new ChatMessage(ChatRole.System, "你是聊天高手,可以聊天说地"),
                new ChatMessage(ChatRole.User, prompt),
            },
            MaxTokens = 200, //速度和内容显示

        };

        return chatCompletionsOptions;
    }
}

2、TestAzureOpenAI


using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;

public class TestAzureOpenAI : MonoBehaviour
{
    AzureOpenAIQueryHandler m_AzureGptQueryHandler;

    public Button Btn;
    public InputField IptFld;
    public Text Txt;

    string getEndContent;
    Task m_Task;
    // Start is called before the first frame update
    void Start()
    {
        m_AzureGptQueryHandler = new AzureOpenAIQueryHandler();
        //Btn.onClick.AddListener(OnClick);
        Btn.onClick.AddListener(OnClickStream);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q)) {
            OnClick();
        }

        Debug.Log($"m_Task?.Id = {m_Task?.Id}, m_Task?.Status = {m_Task?.Status} ");
    }

    private void OnDestroy()
    {
        Btn.onClick.RemoveAllListeners();
    }

    void OnClick() {
        Debug.Log(" m_AzureGptQueryHandler Request");

        string ask = string.IsNullOrEmpty(IptFld.text) == false ? IptFld.text : "你是谁";
        m_Task = m_AzureGptQueryHandler.SendChat(ask, () => {
            getEndContent = "";
            Txt.text = "";
        },
        (str) => {
            getEndContent += str;
            Txt.text += str;
            TaskDispose();
        }
        );
    }

    void OnClickStream() {
        Debug.Log(" m_AzureGptQueryHandler Request");
        string ask = string.IsNullOrEmpty(IptFld.text) == false ? IptFld.text : "你是谁";
        //ask =HandleAskContent(ask);
        m_Task = m_AzureGptQueryHandler.SendStreamChat(ask, () => {
            getEndContent = "";
            Txt.text = "";
        },
        (str) => {
            getEndContent += str;
            Txt.text += str;
        },
        () => {
            Debug.Log(getEndContent);
            TaskDispose();
        }
        );

    }

    void TaskDispose() {
        m_Task?.Dispose();
        m_Task = null;
    }

   
}

六、附加

案例工程项目源码:https://download.csdn.net/download/u014361280/87950232

创建新的 .NET Core ,获取 Azure.AI.OpenAI dll 包

1、在控制台窗口(例如 cmd、PowerShell 或 Bash)中,使用 dotnet new 命令创建名为 azure-openai-quickstart 的新控制台应用。 此命令将创建包含单个 C# 源文件的简单“Hello World”项目:Program.cs

命令:dotnet new console -n azure-openai-quickstart

 2、将目录更改为新创建的应用文件夹。 可使用以下代码生成应用程序:

命令:dotnet build

3、使用以下项安装 OpenAI .NET 客户端库

命令:dotnet add package Azure.AI.OpenAI --prerelease

dll 默认下载到如下路径文件夹

检索密钥和终结点

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Unity Azure Kinect 是一组示例和脚本,用于在Unity使用Azure Kinect(也称为'Kinect for Azure',K4A)。这些示例提供了一些主要脚本,以及与Azure.AI.OpenAIAzure.Core等相关的dll文件。 要在Unity配置Azure Kinect环境,您需要下载并导入Azure Kinect Sensor SDK和Azure Kinect Body Tracking SDK。然后,您可以启动Demo场景来测试和使用Azure Kinect功能。 总结来说,Unity Azure Kinect是一个用于在Unity使用Azure Kinect的工具集,提供了示例和脚本来帮助您使用Azure Kinect的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Azure Kinect Examples for Unity.unitypackage](https://download.csdn.net/download/xiaolishaobinchen/16066812)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Unity 工具Azure OpenAI 功能接入Unity 简单整理](https://blog.csdn.net/u014361280/article/details/131395601)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Unity 配置AzureKinect环境](https://blog.csdn.net/a71468293a/article/details/118970226)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仙魁XAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值