Why is fine tuning with JSONL no where near as impactful as uploading JSONL file directly to custom created GPT

Goal

  • Create a Discord bot that answers questions about developing games on ZEPETO.
    (ZEPETO is an online metaverse platform where users can create games using Unity and the ZEPETO Unity plugin)

  • Developing games for ZEPETO requires you use TypeScript instead of C# as the scripting language.

Issue

  • (Example B in the attached pic) When fine tuning using a JSONL file that contains questions and answers, the training data does not seem to have any effect on the responses from the fine tuned model.
  • (Example A in the attached pic) If I use that exact same JSONL file and upload that to a custom GPT, then I get answers that I would expect.

Questions

  1. Am I doing something wrong with fine-tuning?
  2. Would fine tuning be the correct way to train a custom model to answer coding questions about using ZEPETO’s custom TypeScript API?

Take a look at this image for reference:

Here is the JSONL file for reference:

{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "What programming language do I use to make ZEPETO games?"}, {"role": "assistant", "content": "You can use TypeScript to make ZEPETO games with Unity."}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "Can I code ZEPETO games using C#?"}, {"role": "assistant", "content": "You can not use C# to developer ZEPETO games with Unity. C# will only work in the Unity editor. Once you build your Unity ZEPETO game project, C# will be ignored by the compiler. You can only use TypeScript to make ZEPETO games with Unity."}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "What does a ZEPETO client side TypeScript file look like?"}, {"role": "assistant", "content": "import {ZepetoScriptBehaviour} from \"ZEPETO.Script\";\n\nexport default class HelloWorld extends ZepetoScriptBehaviour {\n    \n    Start() \n    {\n \n    }\n\n    Update()\n    {\n    \n    }\n}"}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "Give me an example of a ZEPETO TypeScript file that is using imports."}, {"role": "assistant", "content": "import {ZepetoScriptBehaviour} from \"ZEPETO.Script\";\nimport {Text} from \"UnityEngine.UI\";\n\n// import custom script from path\nimport ExtraComponent from \"./lib/ExtraComponent\"\n\nexport default class Properties extends ZepetoScriptBehaviour {\n    \n    public resultUi:Text;\n    private extComponent:ExtraComponent;\n    \n    Start() \n    {\n        // add script component\n        this.gameObject.AddComponent<ExtraComponent>();\n        this.extComponent = this.gameObject.GetComponent<ExtraComponent>();\n    }\n   \n    Update() \n    {\n        // get value by method call\n        var count = this.extComponent.GetCount();\n        \n        if(count > 10)\n        {\n            // set value by method call \n            this.extComponent.SetCount(0);\n        }\n        \n        // get public property\n        var resultString = this.extComponent.stringProperty;\n        \n        // print result\n        console.log(`result : ${resultString}`);\n        this.resultUi.text = resultString;\n    }\n}"}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "Show me an example ZEPETO TypeScript code for creating properties."}, {"role": "assistant", "content": "import {ZepetoScriptBehaviour} from \"ZEPETO.Script\";\nimport {Vector3, GameObject, Transform} from \"UnityEngine\";\n\nexport default class Properties extends ZepetoScriptBehaviour {\n    \n    public floatValue: float;\n    public floatValues: float[];\n    \n    @NonSerialized()\n    public strValue:string;\n    \n    @HideInInspector()\n    public strValue2:string;\n    \n    public gameOject:GameObject;\n    public transformValue:Transform;\n    \n    // private collider:Collider;\n    private vectorValue: Vector3;\n    \n    Start() \n    {\n        console.log(typeof(this.floatValues));\n        console.log(`floatValue : ${this.floatValue}`);\n        console.log(`strValue : ${this.strValue}`);\n        \n        console.log(`${this.floatValues.length}`)\n\n        // console.log(`type ${typeof extraComponent}`);\n    }\n\n    Update() \n    {\n        // rotate cube a\n        var transform = this.gameOject.GetComponent<Transform>();\n        transform.Rotate(this.vectorValue);\n\n        // rotate cube b\n        this.transformValue.Rotate(this.vectorValue);\n    }\n}"}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "Show me an example ZEPETO TypeScript file that uses Unity's life cycle events."}, {"role": "assistant", "content": "import { ZepetoScriptBehaviour } from 'ZEPETO.Script'\n\nexport default class MonoBehaviour_LifeCycle extends  ZepetoScriptBehaviour {\n\n    // All Unity MonoBehaviour events are available.\n    // https://docs.unity3d.com/ScriptReference/MonoBehaviour.html\n    /*\n    Awake() { }\n    OnEnable() { }\n    Start() { }\n    Update() { }\n    ...\n    */\n    Awake() {\n        console.log('Awake.');\n    }\n\n    OnEnable() {\n        console.log('OnEnable.');\n    }\n\n    Start() {\n        console.log('Start.');\n    }\n\n    Update() {\n        console.log('OnUpdate.');\n    }\n\n    FixedUpdate() {\n        console.log('FixedUpdate.');\n    }\n\n    LateUpdate() {\n        console.log('LateUpdate.');\n    }\n\n    OnDisable() {\n        console.log('OnDisable.');\n    }\n\n    OnDestroy() {\n        console.log('OnDestroy.');\n    }\n\n    OnTriggerEnter() {\n        console.log('OnTriggerEnter.');\n    }\n\n    OnTriggerExit() {\n        console.log('OnTriggerExit.');\n    }\n\n    OnTriggerStay() {\n        console.log('OnTriggerStay.');\n    }\n\n    OnTriggerEnter2D() {\n        console.log('OnTriggerEnter2D.');\n    }\n\n    OnTriggerExit2D() {\n        console.log('OnTriggerExit2D.');\n    }\n\n    OnTriggerStay2D() {\n        console.log('OnTriggerStay2D.');\n    }\n\n    OnGUI() {\n        console.log('OnGUI.');\n    }\n\n    OnApplicationFocus() {\n        console.log('OnApplicationFocus.');\n    }\n\n    OnApplicationPause() {\n        console.log('OnApplicationPause.');\n    }\n\n    OnApplicationQuit() {\n        console.log('OnApplicationQuit.');\n    }\n}"}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "Show me an example ZEPETO TypeScript file that uses Transforms."}, {"role": "assistant", "content": "import { ZepetoScriptBehaviour } from 'ZEPETO.Script'\n\nexport default class MonoBehaviour_Transform extends ZepetoScriptBehaviour {\n    // All Unity MonoBehaviour events are available.\n    // https://docs.unity3d.com/ScriptReference/MonoBehaviour.html\n    /*\n    Awake() { }\n    Start() { }\n    OnEnable() { }\n    Update() { }\n    */\n\n    Start() {\n        console.warn(`My name is ${this.gameObject.name}`);\n    }\n\n    Update() {\n        this.transform.Rotate(0, 1, 0);\n    }\n}"}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "Show me an example ZEPETO TypeScript file that uses Coroutines."}, {"role": "assistant", "content": "import {ZepetoScriptBehaviour} from \"ZEPETO.Script\";\nimport {WaitForSeconds} from \"UnityEngine\";\nexport default class Coroutine extends ZepetoScriptBehaviour {\n    private curent: number;\n    Start()\n    {\n        this.curent = 0;\n        console.log(`start routine`);\n        this.StartCoroutine(this.DoRoutine());\n    }\n\n    *DoRoutine() {\n        while(true) {\n            console.log(`[${this.curent++}] Wait to next routine..`);\n            yield new WaitForSeconds(1);\n        }\n    }\n}"}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "Show me an example ZEPETO TypeScript file that uses Unity Events."}, {"role": "assistant", "content": "import { ZepetoScriptBehaviour } from 'ZEPETO.Script'\nimport {UnityEvent} from \"UnityEngine.Events\";\n\nexport default class Event extends ZepetoScriptBehaviour {\n    private mEvent:UnityEvent;\n\n    Start() {    \n        this.mEvent = new UnityEvent();\n        this.mEvent.AddListener( ()=> this.Ping() );\n    }\n\n    Update() {\n        if(this.mEvent != null) {\n            this.mEvent.Invoke();\n        }\n    }\n     \n    Ping(){\n        console.log('Ping');\n    }\n\n}"}]}
{"messages": [{"role": "system", "content": "You are a friendly bot that answers questions about developing games in ZEPETO using TypeScript."}, {"role": "user", "content": "Show me an example ZEPETO TypeScript file that uses UI Events."}, {"role": "assistant", "content": "export  default  class  UIEvent extends  ZepetoScriptBehaviour{\n  //Slider Code\n  public cubeTransform:Transform;\n  public sliderUI:Slider;\n\n  //InputField & Button Code\n  public cubePrefab:GameObject;\n  public inputFieldUI:InputField;\n  public createBtn:Button;\n  public deleteBtn:Button;\n  public cubeArray:Object[];\n  \n  Start(){\n      //Slider Code\n      this.sliderUI.maxValue = 180;\n      this.sliderUI.onValueChanged.AddListener( (v) => {\n          this.cubeTransform.rotation = Quaternion.Euler(0, v, 0);\n      });\n      \n      //InputField & Button Code\n      this.cubeArray = [];\n      this.createBtn.onClick.AddListener(()=>{\n          this.CubeCreate();\n      });\n      this.deleteBtn.onClick.AddListener(()=>{\n          this.CubeDeleteAll();\n      });\n  }\n\n  CubeCreate(){\n      var createCnt = Number(this.inputFieldUI.text);\n\n      //Exception handling\n      if(isNaN(createCnt) ||\n          createCnt == 0) {\n          return;\n      }\n\n      //Delete Cube\n      this.CubeDeleteAll();\n\n      //Create Cube\n      for (var i = 0; i < createCnt; ++i)\n      {\n          var cubeObj = GameObject.Instantiate(this.cubePrefab, new Vector3(i * 1.5, -3.5, 0), Quaternion.identity);\n          this.cubeArray.push(cubeObj);\n      }\n  }\n\n  CubeDeleteAll(){\n      //Delete Cube\n      for (var i = 0; i < this.cubeArray.length; ++i) {\n          GameObject.Destroy(this.cubeArray[i]);\n      }\n      this.cubeArray = [];\n  }\n}"}]}
2 Likes

This is straightforward to answer: Fine-tuning is not intended to inject new knowledge into the model. Instead it is meant to steer the model towards producing output in a certain style and/or format or training it to perform a task in a specific way.

You can read more about fine-tune use cases here.

2 Likes

Hi! Thanks for this answer! I will look more into the fine-tune use cases that you linked above!

I have a follow up question about this. If fine-tuning is not how I inject new knowledge into the model, then what method should I be using to inject new knowledge into the model?

2 Likes