using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
public class ChatGLM_Turbo : LLM
{
#region 参数
///
/// 选择的模型
///
[SerializeField] private ModelType m_Type= ModelType.chatglm_turbo;
///
/// 调用方式 invoke/async-invoke/sse-invoke 先实现同步模式
///
[SerializeField] private string m_InvokeMethod = "invoke";
///
/// 智普AI的apikey
///
[Header("填写智普AI的apikey")]
[SerializeField] private string m_Key = string.Empty;
//api key
[SerializeField] private string m_ApiKey = string.Empty;
//secret key
[SerializeField] private string m_SecretKey = string.Empty;
#endregion
private void Awake()
{
OnInit();
}
///
/// 发送消息
///
///
public override void PostMsg(string _msg, Action _callback)
{
base.PostMsg(_msg, _callback);
}
///
/// 发送数据
///
///
///
///
public override IEnumerator Request(string _postWord, System.Action _callback)
{
stopwatch.Restart();
string jsonPayload = JsonConvert.SerializeObject(new RequestData
{
model=m_Type.ToString(),
prompt = m_DataList
});
using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
{
byte[] data = System.Text.Encoding.UTF8.GetBytes(jsonPayload);
request.uploadHandler = (UploadHandler)new UploadHandlerRaw(data);
request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Authorization", GetToken());
yield return request.SendWebRequest();
if (request.responseCode == 200)
{
string _msg = request.downloadHandler.text;
ResponseData response = JsonConvert.DeserializeObject(_msg);
if (response.data.choices.Count > 0)
{
string _msgBack = response.data.choices[0].content;
//添加记录
m_DataList.Add(new SendData("assistant", _msgBack));
//回调
_callback(_msgBack);
}
else
{
Debug.Log(_msg);
}
}
}
stopwatch.Stop();
Debug.Log("chatGLM Turbo耗时:" + stopwatch.Elapsed.TotalSeconds);
}
///
/// 初始化
///
private void OnInit()
{
SplitKey();
GetEndPointUrl();
}
///
/// 获取资源路径
///
private void GetEndPointUrl()
{
url = String.Format("https://open.bigmodel.cn/api/paas/v3/model-api/{0}/{1}", m_Type, m_InvokeMethod);
}
///
/// 处理key
///
private void SplitKey()
{
try {
if (m_Key == "")
return;
string[] _split = m_Key.Split('.');
m_ApiKey = _split[0];
m_SecretKey = _split[1];
}
catch { }
}
#region 生成api鉴权token
///
/// 生成api鉴权 token
///
///
private string GetToken()
{
long expirationMilliseconds = DateTimeOffset.Now.AddHours(1).ToUnixTimeMilliseconds();
long timestampMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
string jwtToken = GenerateJwtToken(m_ApiKey, expirationMilliseconds, timestampMilliseconds);
return jwtToken;
}
//获取token
private string GenerateJwtToken(string apiKeyId, long expirationMilliseconds, long timestampMilliseconds)
{
// 构建Header
string _headerJson = "{\"alg\":\"HS256\",\"sign_type\":\"SIGN\"}";
string encodedHeader = Base64UrlEncode(_headerJson);
// 构建Payload
string _playLoadJson = string.Format("{{\"api_key\":\"{0}\",\"exp\":{1}, \"timestamp\":{2}}}", apiKeyId, expirationMilliseconds, timestampMilliseconds);
string encodedPayload = Base64UrlEncode(_playLoadJson);
// 构建签名
string signature = HMACsha256(m_SecretKey, $"{encodedHeader}.{encodedPayload}");
// 组合Header、Payload和Signature生成JWT令牌
string jwtToken = $"{encodedHeader}.{encodedPayload}.{signature}";
return jwtToken;
}
// Base64 URL编码
private string Base64UrlEncode(string input)
{
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
string base64 = Convert.ToBase64String(inputBytes);
return base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
}
// 使用HMAC SHA256生成签名
private string HMACsha256(string apiSecretIsKey, string buider)
{
byte[] bytes = Encoding.UTF8.GetBytes(apiSecretIsKey);
HMACSHA256 hMACSHA256 = new System.Security.Cryptography.HMACSHA256(bytes);
byte[] date = Encoding.UTF8.GetBytes(buider);
date = hMACSHA256.ComputeHash(date);
hMACSHA256.Clear();
return Convert.ToBase64String(date);
}
#endregion
#region 数据定义
///
/// 模型类型
///
public enum ModelType
{
chatglm_turbo,
characterglm
}
[Serializable]
private class RequestData
{
[SerializeField] public string model;
[SerializeField] public List prompt;
[SerializeField] public float temperature = 0.7f;
}
[Serializable]
private class ResponseData
{
[SerializeField] public int code;
[SerializeField] public string msg = string.Empty;
[SerializeField] public string success = string.Empty;
[SerializeField] public ReData data=new ReData();
}
[Serializable]
private class ReData
{
[SerializeField] public string task_id = string.Empty;
[SerializeField] public string request_id = string.Empty;
[SerializeField] public string task_status = string.Empty;
[SerializeField] public List choices=new List();
}
#endregion
}