GraesonB / ChatGPT-Wrapper-For-Unity

A ChatGPT API wrapper for Unity
MIT License
263 stars 36 forks source link

Version Compatability #3

Closed etriantafyllidis closed 1 year ago

etriantafyllidis commented 1 year ago

Hi there!

Thanks for a very useful wrapper :)

I managed to get it working with Unity v2021.3.3f1+.

My question was regarding older version compatibility, say 2019.3.0f6? Out of curiosity mostly, do you think it would be plausible to downgrade the project to such a version?

I attempted to downgrade the wrapper and stumbled across numerous issues. I managed to fix some straightforward APIs such as: https://stackoverflow.com/questions/74906471/unitywebrequest-does-not-contain-a-definition-for-result

Yet I have a few more hurdles to go through as it seems. Just wondering if it is at all possible to use the wrapper for the aforementioned version (or older ones), thanks again 👍

GraesonB commented 1 year ago

Hi there,

I'm glad you find it useful :-). I would like to add support for older versions of Unity, so if you could screenshot all of the issues you're having and include them in this issue I will resolve them.

etriantafyllidis commented 1 year ago

I managed to get things working.

The main issue was actually the link I attached above. There were other errors such as UI and Visual Scripting related, but if anyone would like to get started with the basic wrapper that @GraesonB kindly wrote, I found the following to work with Unity 2019.3.0f6 versions and lower.

The requests.cs script, will not be compatible with Unity 2020.3 versions and lower. More specifically, UnityWebRequestwill not have a definition for result, which was added at 2020.3+ A quick workaround is to use Conditional Compilation as suggested by the above link.

In the requests.cs script, the following small modifications worked for me:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

namespace ChatGPTWrapper
{
    public class Requests
    {
        private void SetHeaders(ref UnityWebRequest req, List<(string, string)> headers)
        {
            for (int i = 0; i < headers.Count; i++)
            {
                req.SetRequestHeader(headers[i].Item1, headers[i].Item2);
            }
        }

        public IEnumerator GetReq<T>(string uri, System.Action<T> callback, List<(string, string)> headers = null)
        {
            UnityWebRequest webRequest = new UnityWebRequest(uri, "GET");
            if (headers != null) SetHeaders(ref webRequest, headers);
            webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
            webRequest.disposeUploadHandlerOnDispose = true;
            webRequest.disposeDownloadHandlerOnDispose = true;

            yield return webRequest.SendWebRequest();

            #if UNITY_2020_3_OR_NEWER
            switch (webRequest.result)
            {
                case UnityWebRequest.Result.ConnectionError:
                case UnityWebRequest.Result.DataProcessingError:
                    Debug.LogError("Error: " + webRequest.error);
                    break;
                case UnityWebRequest.Result.ProtocolError:
                    Debug.LogError(": HTTP Error: " + webRequest.error);
                    break;
                case UnityWebRequest.Result.Success:
                    var responseJson = JsonUtility.FromJson<T>(webRequest.downloadHandler.text);
                    callback(responseJson);
                    break;
            }
            #else
            if(!string.IsNullOrWhiteSpace(webRequest.error))
            {
                Debug.LogError($"Error {webRequest.responseCode} - {webRequest.error}");
                yield break;
            }
            else
            {
                var responseJson = JsonUtility.FromJson<T>(webRequest.downloadHandler.text);
                callback(responseJson);
            }
            #endif
            webRequest.Dispose();
        }

        public IEnumerator PostReq<T>(string uri, string json, System.Action<T> callback, List<(string, string)> headers = null)
        {
            UnityWebRequest webRequest = new UnityWebRequest(uri, "POST");
            if (headers != null) SetHeaders(ref webRequest, headers);

            byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json);
            webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend);
            webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
            webRequest.disposeDownloadHandlerOnDispose = true;
            webRequest.disposeUploadHandlerOnDispose = true;

            yield return webRequest.SendWebRequest();

            #if UNITY_2020_3_OR_NEWER
            switch (webRequest.result)
            {
                case UnityWebRequest.Result.ConnectionError:
                case UnityWebRequest.Result.DataProcessingError:
                    Debug.LogError("Error: " + webRequest.error);
                    break;
                case UnityWebRequest.Result.ProtocolError:
                    Debug.LogError(": HTTP Error: " + webRequest.error);
                    break;
                case UnityWebRequest.Result.Success:
                    var responseJson = JsonUtility.FromJson<T>(webRequest.downloadHandler.text);
                    callback(responseJson);
                    break;
            }
            #else
            if(!string.IsNullOrWhiteSpace(webRequest.error))
            {
                Debug.LogError($"Error {webRequest.responseCode} - {webRequest.error}");
                yield break;
            }
            else
            {
                var responseJson = JsonUtility.FromJson<T>(webRequest.downloadHandler.text);
                    callback(responseJson);
            }
            #endif
            webRequest.Dispose();
        }
    }
}

I hope this helps :)

GraesonB commented 1 year ago

@DeathByCh0c0 I Didn't have time to get around to it yesterday, I appreciate you posting your fix :-). I'll update the repo tonight

GraesonB commented 1 year ago

@DeathByCh0c0 not sure if you noticed or not but I added your changes to the repo. Also, the official API just launched today and its 10x cheaper than Davinci! I've added support for the new API, so feel free to test it out and leave feedback.

Seeing as you're studying human-computer-interaction and ML, if you're hoping to run some models on data that's generated from user interactions with ChatGPT in your use case, I can add a feature to pipe that conversation data into a NoSQL DB for you since that's not far off from my own plans. Let me know if you're interested

etriantafyllidis commented 1 year ago

@GraesonB Hey! I did see the changes, glad to see these were somewhat helpful regarding compatibility with lower Unity3D versions :)

I actually just checked the changes you made today and it seems that the gpt-3.5-turbo works for me! Good job! 👍 From your message I gather you are referring to querying past history chat(-s)? As far as I can tell, if you terminate the active scene in play mode and restart it, past chat cannot be accessed, unless I guess you parse that as part of the initial prompt when restarting the scene. Sorry if I misunderstood your message.

GraesonB commented 1 year ago

@DeathByCh0c0 Haha no worries at all! My fault for being unclear. I plan on making a server for my own use case that will store conversations in a database that could be accessed later down the road in Unity by a fetch request. I'm not sure what your use case is, but if you're interested in saving conversation history in your own database, let me know :-)