Unity3D 交互式AI桌面宠物开发系列【四】大模型语言交互技术,支持讯飞星火大模型、百度文心一言、ChatGPT4、DeepSeek等各大平台
该系列主要介绍怎么制作AI桌面宠物的流程,我会从项目开始创建初期到最终可以和AI宠物进行交互为止,项目已经开发完成,我会仔细梳理一下流程,分步讲解。 这篇文章主要讲关于讯飞星火大模型API接入的方法。
提示:内容纯个人编写,欢迎评论点赞,来指正我。
前言
本篇内容主要讲Unity开发桌面宠物的大模型交互功能,大家感兴趣也可以了解一下这个开发方向,目前还是挺有前景的。
下面让我们出发吧 ————>—————–>
一、AI 模型交互 (LLM) 概述
LLM大模型交互技术是一种基于大型语言模型(Large Language Model,LLM)的交互技术。LLM 是一种使用机器学习技术训练而成的大规模语言模型,能够处理和生成自然语言文本。LLM 大模型交互技术利用这种模型的强大语言理解和生成能力,为用户提供更加智能和自然的交互方式。
通过LLM大模型交互技术,用户可以与系统进行更加自然语言的对话和交流,实现更加智能、灵活和个性化的服务。这种技术可以应用在各个领域,如智能助手、客服机器人、智能问答系统等,使得用户与系统之间的交互更加高效和流畅。

二、Unity开发准备阶段
1.Unity平台
- 该系列全部使用Unity2021.3.44开发;
- 该系列前后文章存在关联,不懂的可以看前面文章;
- 该系列完成之后我会上传源码工程,着急的小伙伴可以自己写框架,我就先编写各模块的独立功能。
2.示例:讯飞平台
- 注册讯飞账户,已注册的直接登录;
- 创建大模型交互应用,然后 领取 星火认知大模型 Spark4.0 Ultra 免费测试服务量绑定该应用,或者付费购买服务量;(个人认证可以领取免费服务量)
- 前两步我就不贴流程图了,该系列在之前的文章中提到过注册和领取相关功能免费服务量的流程;
- 我这里就先贴出来讯飞平台的,其他平台的也做好了,有需求的话后期再拓展一下。
- 上述操作很简单
- 重点来了,科大讯飞平台的星火大模型接口怎么接入,下面来看一下吧
三、科大讯飞 星火大模型
1. 创建应用



- 点击用户下面的 “我的应用” 然后创建应用,命名大模型交互的应用,创建成功后会生成一个APPKey或者APPID 保存好。(名字随便起,记住APPID,后续要用到)
2. 查看免费测试服务量

- 创建成功之后可以在控制台查看赠送的Tokens。
- 个人测试的话领取免费开发测试服务量就可以了,商用的话就购买相应的服务量。
3. 查看 WebSocket 接口信息

- 记录保存该各项数据,后续在WebSocket连接的时候要用到这些。
4. API 开发文档查看

- 这里有开发文档可以自行查看并学习,当然我是看过的,那么接下来就到了开发阶段了!
- ps: 记住这个接口地址,这是WebSocket的API 地址 (调用的网址),接下来会用到。
四、功能开发阶段
1. Unity界面开发

- ① 用于显示AI回复内容的 Text 文本
- ② 用于点击发送消息的 Button 按钮
- ③ 用于用户输入提问词的 InputField 输入框
- ④ 用于挂载LLM模型交互 脚本 的空物体
2. 代码分析

- 参数:用于定义变量和UI组件的可视化配置;
- 生命周期函数:Unity自带Awake、Start等函数
- 收发消息处理:用于处理发送的消息和收到消息的UI处理以及聊天记录的存储;
- 数据配置:配置星火大模型的版本
- 获取鉴权Url:用于鉴权加密的API地址;
- WebSocket连接:用于实现基于WebSocket通信协议进行收发消息;
- 数据定义:用于定义发送数据和接收数据的数据结构,根据第三方平台的参数。
3. 代码片段
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;
using Debug = UnityEngine.Debug;
public class XunFeiChatSpark : MonoBehaviour
{
#region 参数
///
/// 选择星火大模型版本
///
[Header("选择星火大模型版本")]
[SerializeField] private ModelType m_SparkModel = ModelType.星火大模型4_Ultra;
///
/// api地址
///
[SerializeField] private string url;
///
/// 讯飞的AppID
///
[Header("填写APP ID")]
[SerializeField] private string m_AppID = "讯飞的AppID";
///
/// 讯飞的APIKey
///
[Header("填写Api Key")]
[SerializeField] private string m_APIKey = "讯飞的APIKey";
///
/// 讯飞的APISecret
///
[Header("填写Secret Key")]
[SerializeField] private string m_APISecret = "讯飞的APISecret";
///
/// 提示词,与消息一起发送
///
[Header("发送的提示词设定")]
[SerializeField] protected string m_Prompt = string.Empty;
///
/// 语言
///
protected string lan = "中文";
///
/// 上下文保留条数
///
[Header("上下文保留条数")]
[SerializeField] protected int m_HistoryKeepCount = 15;
///
/// 缓存对话
///
[SerializeField] public ListSendData> m_DataList = new ListSendData>();
///
/// 计算方法调用的时间
///
[SerializeField] protected Stopwatch stopwatch = new Stopwatch();
///
/// 获取用户输入内容
///
[Header("UI配置")]
[SerializeField]
private InputField m_InputContent;
///
/// 发送内容按钮
///
[SerializeField]
private Button m_SendMesBtn;
///
/// 显示文本内容
///
[SerializeField]
private Text m_TextBack;
#endregion
#region 生命周期函数
private void Awake()
{
url = "wss://spark-api.xf-yun.com/v4.0/chat";
}
private void Start()
{
//绑定发送按钮的方法
m_SendMesBtn.onClick.AddListener(delegate
{
if (!string.IsNullOrEmpty(m_InputContent.text))
{
SendMessage(m_InputContent.text, CallBack);
}
});
}
#endregion
#region 收发消息处理
///
/// 设置保留的上下文条数,防止太长
///
public virtual void CheckHistory()
{
if (m_DataList.Count > m_HistoryKeepCount)
{
m_DataList.RemoveAt(0);
}
}
///
/// 发送消息
///
public void SendMessage(string _msg, Actionstring> _callback)
{
//上下文条数设置
CheckHistory();
//提示词处理
string message = "当前为角色的人物设定:" + m_Prompt +
" 回答的语言:" + lan +
" 接下来是我的提问:" + _msg;
//缓存发送的信息列表
m_DataList.Add(new SendData("user", message));
StartCoroutine(Request(_callback));
}
///
/// 请求数据
///
///
///
///
public IEnumerator Request(Actionstring> _callback)
{
yield return null;
//处理发送数据
RequestData requestData = new RequestData();
requestData.header.app_id = m_AppID;
//判断大模型的版本
requestData.parameter.chat.domain = GetDomain();
//添加对话列表
ListPostMsgData> _tempList = new ListPostMsgData>();
for (int i = 0; i m_DataList.Count; i++)
{
PostMsgData _msg = new PostMsgData()
{
role = m_DataList[i].role,
content = m_DataList[i].content
};
_tempList.Add(_msg);
}
requestData.payload.message.text = _tempList;
string _json = JsonUtility.ToJson(requestData);
//Websocket连接
ConnectHost(_json, _callback);
}
///
/// AI 回复信息的回调
///
///
private void CallBack(string _response)
{
_response = _response.Trim();
m_TextBack.text = "";
//文字处理 去除换行符和特殊字符
_response = _response.Replace(@"n", "").Replace(@"r", "").Replace(@"", "");
Debug.Log("收到 AI 回复:" + _response);
m_TextBack.text = _response;
}
#endregion
#region 数据配置
///
/// 指定访问的版本
/// 星火大模型API当前有Lite、Pro、Pro-128K、Max、Max-32K和4.0 Ultra六个版本,各版本独立计量tokens。
///
///
private string GetDomain()
{
//这里可以自行扩展其他版本的大模型
string label = "";
switch (m_SparkModel)
{
case ModelType.星火大模型Pro:
label = "Pro";
break;
case ModelType.星火大模型Max:
label = "Max";
break;
case ModelType.星火大模型4_Ultra:
label = "4.0Ultra";
break;
default:
label = "4.0Ultra";
break;
}
return label;
}
///
/// 用来区分不同的模型版本
///
private enum ModelType
{
星火大模型Pro,
星火大模型Max,
星火大模型4_Ultra
}
#endregion
#region 获取鉴权Url
///
/// 获取鉴权url
///
///
private string GetAuthUrl()
{
string date = DateTime.UtcNow.ToString("r");
Uri uri = new Uri(url);
StringBuilder builder = new StringBuilder("host: ").Append(uri.Host).Append("n").//
Append("date: ").Append(date).Append("n").//
Append("GET ").Append(uri.LocalPath).Append(" HTTP/1.1");
string sha = HMACsha256(m_APISecret, builder.ToString());
string authorization = string.Format("api_key="{0}", algorithm="{1}", headers="{2}", signature="{3}"", m_APIKey, "hmac-sha256", "host date request-line", sha);
string NewUrl = "https://" + uri.Host + uri.LocalPath;
string path1 = "authorization" + "=" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(authorization));
date = date.Replace(" ", "%20").Replace(":", "%3A").Replace(",", "%2C");
string path2 = "date" + "=" + date;
string path3 = "host" + "=" + uri.Host;
NewUrl = NewUrl + "?" + path1 + "&" + path2 + "&" + path3;
return NewUrl;
}
public string HMACsha256(string apiSecretIsKey, string buider)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(apiSecretIsKey);
System.Security.Cryptography.HMACSHA256 hMACSHA256 = new System.Security.Cryptography.HMACSHA256(bytes);
byte[] date = System.Text.Encoding.UTF8.GetBytes(buider);
date = hMACSHA256.ComputeHash(date);
hMACSHA256.Clear();
return Convert.ToBase64String(date);
}
#endregion
#region WebSocket连接
private ClientWebSocket m_WebSocket;
private CancellationToken m_CancellationToken;
///
/// 连接服务器
///
///
///
private async void ConnectHost(string text, Actionstring> _callback)
{
try
{
stopwatch.Restart();
m_WebSocket = new ClientWebSocket();
m_CancellationToken = new CancellationToken();
string authUrl = GetAuthUrl();
string url = authUrl.Replace("http://", "ws://").Replace("https://", "wss://");
Uri uri = new Uri(url);
await m_WebSocket.ConnectAsync(uri, m_CancellationToken);
await m_WebSocket.SendAsync(new ArraySegmentbyte>(Encoding.UTF8.GetBytes(text)), WebSocketMessageType.Binary, true, m_CancellationToken);
StringBuilder sb = new StringBuilder();
//用于拼接返回的答复
string _callBackMessage = "";
while (m_WebSocket.State == WebSocketState.Open)
{
var result = new byte[1024];
await m_WebSocket.ReceiveAsync(new ArraySegmentbyte>(result), m_CancellationToken);//接受数据
Listbyte> list = new Listbyte>(result); while (list[list.Count - 1] == 0x00) list.RemoveAt(list.Count - 1);//去除空字节
var str = Encoding.UTF8.GetString(list.ToArray());
sb.Append(str);
if (str.EndsWith("}"))
{
//获取返回的数据
ResponseData _responseData = JsonUtility.FromJsonResponseData>(sb.ToString());
sb.Clear();
if (_responseData.header.code != 0)
{
//返回错误
Debug.Log("错误码:" + _responseData.header.code);
m_WebSocket.Abort();
break;
}
//没有回复数据
if (_responseData.payload.choices.text.Count == 0)
{
Debug.LogError("没有获取到回复的信息!");
m_WebSocket.Abort();
break;
}
//拼接回复的数据
_callBackMessage += _responseData.payload.choices.text[0].content;
if (_responseData.payload.choices.status == 2)
{
stopwatch.Stop();
Debug.Log("ChatSpark耗时:" + stopwatch.Elapsed.TotalSeconds);
//添加记录
m_DataList.Add(new SendData("assistant", _callBackMessage));
//回调
_callback(_callBackMessage);
m_WebSocket.Abort();
break;
}
}
}
}
catch (Exception ex)
{
Debug.LogError("报错信息: " + ex.Message);
m_WebSocket.Dispose();
}
}
#endregion
#region 数据定义
///
/// 发送的数据结构
///
[Serializable]
private class RequestData
{
public HeaderData header = new HeaderData();
public ParameterData parameter = new ParameterData();
public MessageData payload = new MessageData();
}
[Serializable]
private class HeaderData
{
//必填项
public string app_id = string.Empty;
//选填,用户的ID ,只要不为空就可以
public string uid = "123456";
}
[Serializable]
private class ParameterData
{
public ChatParameter chat = new ChatParameter();
}
[Serializable]
private class ChatParameter
{
public string domain = "4.0Ultra";
public float temperature = 0.5f;
public int max_tokens = 1024;
}
[Serializable]
private class MessageData
{
public TextData message = new TextData();
}
[Serializable]
private class TextData
{
public ListPostMsgData> text = new ListPostMsgData>();
}
[Serializable]
private class PostMsgData
{
public string role = string.Empty;
public string content = string.Empty;
}
///
/// 接收的数据结构
///
[Serializable]
private class ResponseData
{
public ReHeaderData header = new ReHeaderData();
public PayloadData payload = new PayloadData();
}
[Serializable]
private class ReHeaderData
{
//错误码,0表示正常,非0表示出错
public int code;
//会话是否成功的描述信息
public string message = string.Empty;
public string sid = string.Empty;
//会话状态,取值为[0,1,2];0代表首次结果;1代表中间结果;2代表最后一个结果
public int status;
}
[Serializable]
private class PayloadData
{
public ChoicesData choices = new ChoicesData();
}
[Serializable]
private class ChoicesData
{
public int status;
public int seq;
public ListReTextData> text = new ListReTextData>();
}
[Serializable]
private class ReTextData
{
public string content = string.Empty;
public string role = string.Empty;
public int index;
}
///
/// 用于聊天记录存储的结构
///
[Serializable]
public class SendData
{
[SerializeField] public string role;
[SerializeField] public string content;
public SendData() { }
public SendData(string _role, string _content)
{
role = _role;
content = _content;
}
}
#endregion
}
4. 数据配置

- 将APPid、ApiKey、SecretKey替换成自己讯飞平台上的 WebSocket 信息数据
- 变量对应UI进行配置
5. 效果展示
Unity3D实现大模型交互讯飞星火大模型视频演示
- 输入内容,点击发送,返回的结果会显示在UI界面上,就代表成功了。

- 控制台会有打印结果的,也一样代表 API 接入成功。
- 注意这是非流式的,有需要可以出一期流式的通信,响应速度更快。
6. 问题反馈
- 运行后有任何问题都可以在评论区进行讨论~
- 代码写的不是很工整,多多指点,后续会进行整个系列的框架搭建
- 下一期更新暂定:
① 其他平台LLM接入功能,例如:百度文心一言、ChatGPT、DeepSeek等
② 语音合成效果,例如:讯飞、百度等
二选一哦!- 评论告诉我,下一期更新什么
然后就,大功告成了!!!

比心啦 ❥(^_-)

总结
- 提示: 大家根据需求来做功能,后续继续其他功能啦,不懂的快喊我。
- 大家可以在评论区讨论其他系列下一期出什么内容,这个系列会继续更新的
- 点赞收藏加关注哦~ 蟹蟹
文章来源于互联网:Unity3D开发AI桌面精灵/宠物系列 【四】 大模型语言交互技术、基于WebSocket通信 – 支持讯飞星火大模型、百度文心一言、ChatGPT4、DeepSeek等 C# 开发
5bei.cn大模型教程网










