[经验分享]gpt-3.5-Turbo|unity中实现http接口调用gpt新接口以及信息处理的实现案例分享
Posted 阴沉的怪咖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[经验分享]gpt-3.5-Turbo|unity中实现http接口调用gpt新接口以及信息处理的实现案例分享相关的知识,希望对你有一定的参考价值。
最近openAI发布了目前chatGPT所使用的模型gpt-3.5-Turbo,之前使用了text-davinci-003模型做了一个galgame的AI女友对话的demo。这次趁着新接口的发布,对这个demo也同步更新了模型调用的代码。本篇文章将分享一下,如何在unity里使用UnityWebRequest实现与openAI的接口调用以及信息处理的示例,希望能够帮助到有需要的朋友。
一、gpt-3.5-Turbo官方示例分析
①首先我们需要知道turbo接口api的调用地址,从官方文档中查询,找到了调用连接,如下:
api调用地址:https://api.openai.com/v1/chat/completions
②调用api所需要发送的报文
1)Header:
①ContentType:application/json
②Authorization:Bearer 你的apikey
2)发送的报文主体
从openAI官方网站查询了一下Turbo的调用示例,官方展示了一个Python的代码示例:
# Note: you need to be using OpenAI Python v0.27.0 for the code below to work
import openai
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
"role": "system", "content": "You are a helpful assistant.",
"role": "user", "content": "Who won the world series in 2020?",
"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020.",
"role": "user", "content": "Where was it played?"
]
)
从官方示例可以发现,我们需要发送的报文,应该包含model的名称以及需要发送的messages,实际上从官方文档里看,可以发送的字段会更多,需要的话请大家自行查询吧。
我们可以发现,发送的报文里,包含有role角色定义,以及角色所发送的消息。
这里我们注意一下,role的可选值,必须是
口 system:在初始化的时候,设置AI的角色设定,可以理解为是人设。
口 user:我们发送的信息,放在这里
口 assistant:模型返回的信息,放在这里
需要注意的是,观察官方示例,可以发现,所有发送的信息以及反馈信息均被放置在报文里,这样可以让模型回答的时候,关联前文。
3)返回的报文
模型返回的报文格式如下所示,返回的信息以Json格式反馈。
"id": "chatcmpl-6pWU3qzNuTBLU7U0tUw6Nqa0oQhWbHF",
"object": "chat.completion",
"created": 1677737615,
"model": "gpt-3.5-turbo-0301",
"usage":
"prompt_tokens": 39,
"completion_tokens": 35,
"total_tokens": 74
,
"choices": [
"message":
"role": "assistant",
"content": "你好,我是AI助手!"
,
"finish_reason": "stop",
"index": 0
]
二、unity发送的报文格式
因为我们需要使用unity来访问api,所以需要修改一下报文主体。这里我们将需要发送的报文写成Json格式:
"model":"gpt-3.5-turbo",
"messages":[
"role": "system", "content": "你是一个经验丰富的AI助手,能帮我处理很多计算机事务",
"role": "user", "content": "你好",
"role": "assistant", "content": "你好,我是一个语言模型AI"
]
三、Unity中调用api的代码示例
本节内容将介绍一下如何使用UnityWebRequest实现调用gpt-3.5-Turbo的代码实现。
1)首先定义一下数据发送的类,用作保存待发送的报文信息。
[Serializable]public class PostData
public string model;
public List<SendData> messages;
[Serializable]
public class SendData
public string role;
public string content;
public SendData()
public SendData(string _role,string _content)
role = _role;
content = _content;
2)定义一下返回数据的类,用于保存模型返回的数据信息
[Serializable]
public class MessageBack
public string id;
public string created;
public string model;
public List<MessageBody> choices;
[Serializable]
public class MessageBody
public Message message;
public string finish_reason;
public string index;
[Serializable]
public class Message
public string role;
public string content;
3)unity使用UnityWebRequest调用api的代码示例
调用api的功能写成一个方法,输入的参数包含待发送的文本、openAI的密钥以及回调函数,方法里需要用的一些变量,我放在脚本里做了定义。
以下是完整的代码示例:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class GptTurboScript : MonoBehaviour
/// <summary>
/// api地址
/// </summary>
public string m_ApiUrl = "https://api.openai.com/v1/chat/completions";
/// <summary>
/// gpt-3.5-turbo
/// </summary>
public string m_gptModel = "gpt-3.5-turbo";
/// <summary>
/// 缓存对话
/// </summary>
[SerializeField]public List<SendData> m_DataList = new List<SendData>();
/// <summary>
/// AI人设
/// </summary>
public string Prompt;
private void Start()
//运行时,添加人设
m_DataList.Add(new SendData("system", Prompt));
/// <summary>
/// 调用接口
/// </summary>
/// <param name="_postWord"></param>
/// <param name="_openAI_Key"></param>
/// <param name="_callback"></param>
/// <returns></returns>
public IEnumerator GetPostData(string _postWord,string _openAI_Key, System.Action<string> _callback)
//缓存发送的信息列表
m_DataList.Add(new SendData("user", _postWord));
using (UnityWebRequest request = new UnityWebRequest(m_ApiUrl, "POST"))
PostData _postData = new PostData
model = m_gptModel,
messages = m_DataList
;
string _jsonText = JsonUtility.ToJson(_postData);
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", _openAI_Key));
yield return request.SendWebRequest();
if (request.responseCode == 200)
string _msg = request.downloadHandler.text;
MessageBack _textback = JsonUtility.FromJson<MessageBack>(_msg);
if (_textback != null && _textback.choices.Count > 0)
string _backMsg = _textback.choices[0].message.content;
//添加记录
m_DataList.Add(new SendData("assistant", _backMsg));
_callback(_backMsg);
#region 数据包
[Serializable]public class PostData
public string model;
public List<SendData> messages;
[Serializable]
public class SendData
public string role;
public string content;
public SendData()
public SendData(string _role,string _content)
role = _role;
content = _content;
[Serializable]
public class MessageBack
public string id;
public string created;
public string model;
public List<MessageBody> choices;
[Serializable]
public class MessageBody
public Message message;
public string finish_reason;
public string index;
[Serializable]
public class Message
public string role;
public string content;
#endregion
本文的代码示例是基于我前段时间做的一个使用chatGPT实现的二次元AI女友galgame的demo提取的,源码包提供了text-davinci-003以及gpt-3.5-Turbo两个模型的demo示例,源码已经发布在Gitee上,需要使用的朋友,可以自行下载参考。
Gitee地址:chatGPTAIGirlFrienchatGPTAIGirlFriendSample: 使用chatGPT+unity+Azure+VRoid制作的简单的AI女友(老婆)对话机器人的demo。
Unity性能优化专题—腾讯牛人分享经验 (难度1 推荐3)
原文地址:
之前因为老大要求,要把unity最终发布的包压缩到至少之前大小的一半,这可难倒我了,不过最终还是在问了很多大神后解决了,主要是在本文章中讲的“二”。 tag: unity素材压缩、unity资源压缩、unity压缩包大小、unity怎么节省空间
这里从三个纬度来分享下内存的优化经验:代码层面、贴图层面、框架设计层面。
一.代码层面。
1.foreach。
Mono下的foreach使用需谨慎。频繁调用容易触及堆上限,导致GC过早触发,出现卡顿现象。
特别注意的是在Update中如果非必要,不要使用foreach。尽可能用for来代替foreach。会产生GC Alloc,说明foreach调用GetEnumerator()时候有堆内存上的操作,new和dispose。
2.string修改。
如果熟悉C++的话,就会了解,每次使用string的时候,都要在内存中创建一个新的字符串对象,就需要为该新对象分配新的空间。 特别是在循环中需要修改string对象,就会频繁的分配新的空间,这时候推荐使用StringBuilder.Append等操作来处理。C++中通常也是通过分配一个固定的字符内存来处理字符串的操作。
3.gameObject.tag
gameObject.tag 会在内部循环调用对象分配的标签属性以及拷贝额外的内存,推荐使用gameObject.CompareTag("XXX")来代替.tag。
4.使用ObjectPool对象池来管理对象,避免频繁的Instance,Destroy。
二.贴图层面。
代码上的内存优化,很大层面上都不及贴图上的优化。有时候改一张图就帮你省了大几兆的内存。
1.巧妙通过调整纹理资源,来调整图的大小。比如:通过9宫格、部分缩小后Unity里在拉大等方式。
比如:(主要调整了两个小元素)就省了一半的内存。
优化前:
优化后:
2.Ios平台使用PVRT压缩纹理。Adroid平台使用ETC1格式压缩。均可以减至1/4的内存大小。优化非常明显。
目前主流的Android机型基本都支持ETC1格式压缩。但ETC1只能支持非Alpha通道的图片压缩。所以一般把Alpha通道图分离出来,绘制到GPU显存时,a值从Alpha图里获取,无Alpha通道的图就可以使用ETC1压缩。
而ETC2以上的格式压缩虽然支持含Alpha通道的图片,但是支持的机型还比较少。目前不推荐使用。
未使用ETC1压缩前的内存占用大小1024*1024的png图占用10.7M( 包含了Editor中的内存占用,以及mip map内存占用 )。
mipMap是摄像机离得远近用不同的图片,3D游戏中用内存换性能的一种有效方式。它会将大图变成若干小图,存储内存中,当摄像机离的比较远的时候,只需使用小图。
UI、2D场景可以把Texure这个设置去掉。
这样实际游戏中未压缩纹理1024×1024的图在内存中占用是 4M。(Unity Profiler下看应该是8M)
使用ETC1压缩后,场景图片一张大小只有1.3MB,加上通道图2.6M。几乎是用来的1/4。
甚至文件的大小也小了1/4。
3.通过减色的方式减少图片大小。很多UI其实使用的色彩很少,用不到256色。这类图片就可以进行减色压缩。
三.框架设计层面。
一个相对中大型的游戏,系统非常的多。这时候合理的适时的释放内存有助于游戏的正常体验,甚至可以防止内存快速到达峰值,导致设备Crash。
目前主流平台机型可用内存:
Android平台:在客户端最低配置以上,均需满足以下内存消耗指标(PSS):
1)内存1G以下机型:最高PSS<=150MB
2)内存2G的机型:最高PSS<=200MB
iOS平台:在iPhone4S下运行,消耗内存(real mem)不大于150MB
1.场景切换时避开峰值。
当前一个场景还未释放的时候,切换到新的场景。这时候由于两个内存叠加很容易达到内存峰值。解决方案是,在屏幕中间遮盖一个Loading场景。在旧的释放完,并且新的初始化结束后,隐藏Loading场景,使之有效的避开内存大量叠加超过峰值。
2.GUI模块加入生命周期管理。
主角、强化、技能、商城、进化、背包、任务等等。通常一个游戏都少不了这些系统。但要是全部都打开,或者这个时候再点世界地图,外加一些逻辑数据内存的占用等等。你会发现,内存也很快就达到峰值。
这时候有效的管理系统模块生命周期就非常有必要。首先将模块进行划分:
1)经常打开 Cache_10;
2)偶尔打开 Cache_5;
3)只打开一次 Cache_0。
创建一个ModuleMananger 类,内部Render方法每分钟轮询一次。如果是“Cache_0”这个类型,一关闭就直接Destroy释放内存;“Cache_10”这个类型为10分钟后自动释放内存;" Cache_5"这种类型为5分钟后自动释放内存。每次打开模块,该模块就会重新计时。这样就可以有效合理的分配内存。
转载自: 腾讯游戏开发者平台
以上是关于[经验分享]gpt-3.5-Turbo|unity中实现http接口调用gpt新接口以及信息处理的实现案例分享的主要内容,如果未能解决你的问题,请参考以下文章
ChatGPT(GPT3.5) OpenAI官方API正式发布
ChatGPT开放API,上来就干到最低价,可以人手一个ChatGPT了