Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
fdc53bf
WIP
amakropoulos Aug 13, 2025
bda6dff
Merge fdc53bf9e7b72d3ed871bf9d9a4fae8a09e50340 into 891497bf8ad6d10f9…
amakropoulos Aug 13, 2025
0f94f6f
update VERSION
amakropoulos Aug 13, 2025
728babc
working setup
amakropoulos Aug 15, 2025
ddc67c6
fix platform paths on postprocess
amakropoulos Aug 15, 2025
ff1afde
initial working LLM with LlamaLib
amakropoulos Aug 15, 2025
00a76ec
add NewtonSoft JSON dependency
amakropoulos Aug 15, 2025
bd1ec6d
add LlamaLib
amakropoulos Aug 15, 2025
bc74831
implementation of LLMAgent methods (untested)
amakropoulos Aug 15, 2025
8118aa5
allow empty templates
amakropoulos Aug 17, 2025
05caeea
small fixes mainly on the ChatAsync
amakropoulos Aug 17, 2025
23282d4
use ChatAsync instead of Chat
amakropoulos Aug 17, 2025
8762162
move completion parameters to LLMCaller
amakropoulos Aug 18, 2025
42ae20f
rename LLMCaller to LLMClient
amakropoulos Aug 18, 2025
5c62cec
simplify grammar by keeping the grammar value instead of the file
amakropoulos Aug 18, 2025
f778fb9
remove unused completion parameters
amakropoulos Aug 18, 2025
567ad3f
getters/setters for variables needing more actions
amakropoulos Aug 18, 2025
958f8b9
remove not needed classes
amakropoulos Aug 18, 2025
2614d20
general improvements and small fixes
amakropoulos Aug 19, 2025
18d1d1b
more changes
amakropoulos Aug 19, 2025
8f7f869
more improvements
amakropoulos Aug 19, 2025
c715ccf
check callback target for destruction
amakropoulos Aug 20, 2025
b9e9464
initial pass of basic unit test
amakropoulos Nov 11, 2025
116e41e
update to latest LlamaLib (remote changes)
amakropoulos Nov 13, 2025
548820b
simplify library finding
amakropoulos Nov 13, 2025
1425189
small fixes
amakropoulos Nov 13, 2025
9d75920
fix llmagent save test
amakropoulos Nov 17, 2025
6be3137
autosave history
amakropoulos Nov 18, 2025
7d27df9
fix blas selection with exclusion list
amakropoulos Nov 18, 2025
68412f6
adapt for chat history removal of system prompt
amakropoulos Nov 18, 2025
ea13827
functionality to return and show the service command
amakropoulos Nov 18, 2025
35804a6
remove chat template tests
amakropoulos Nov 18, 2025
84ecfc1
remove template functionality
amakropoulos Dec 2, 2025
f11d0ba
Option to debug the LLM prompts
amakropoulos Dec 2, 2025
2cf2e41
show grammar with box
amakropoulos Dec 2, 2025
556e63e
comment typo
amakropoulos Dec 2, 2025
9250efd
remove save cache functionality
amakropoulos Dec 2, 2025
7726186
adapt tests to recent changes
amakropoulos Dec 2, 2025
ed276ca
update Samples to v3
amakropoulos Dec 2, 2025
84efdf7
fix setting up of functions dependent on caller object
amakropoulos Dec 2, 2025
f08e89a
Add undream libraries in macOS Xcode
amakropoulos Dec 5, 2025
1c4c701
update tooltips
amakropoulos Dec 5, 2025
ec01c69
fix: Bypasses the issue where errors occur due to antivirus program d…
Nov 21, 2025
750c06a
Add migration guide
amakropoulos Dec 8, 2025
5613738
await rag.Add
amakropoulos Dec 8, 2025
7328049
retain loras in Editor
amakropoulos Dec 9, 2025
73a8556
work around async warning
amakropoulos Dec 9, 2025
9db50a4
use LLMUnity exceptions alongside an error log
amakropoulos Dec 10, 2025
a24c721
update Readme
amakropoulos Dec 10, 2025
12924ff
fix typos
amakropoulos Dec 10, 2025
c6b1647
update LlamaLib
amakropoulos Dec 11, 2025
2930ddd
try-catch in Chat
amakropoulos Dec 11, 2025
95f000d
update LlamaLib
amakropoulos Dec 11, 2025
bcd67aa
remove user and assistant roles
amakropoulos Dec 11, 2025
7857ebd
fix usearch for iOS
amakropoulos Jul 17, 2025
1e4aa40
update tooltips
amakropoulos Dec 12, 2025
b5900c8
update tests
amakropoulos Dec 12, 2025
c536a62
implement changes for IL2CPP
amakropoulos Dec 16, 2025
60dd270
fix build location for Android
amakropoulos Dec 16, 2025
cf2bcb7
adapt Readme
amakropoulos Dec 16, 2025
e58836d
update LlamaLib
amakropoulos Dec 16, 2025
73ad540
update LlamaLib
amakropoulos Dec 16, 2025
09a1728
set debug level before creating LlamaLib
amakropoulos Dec 16, 2025
e2e66c8
build usearch for Android 16kb support
amakropoulos Dec 16, 2025
3ce0451
serialize embedding fields
amakropoulos Dec 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
github: [amakropoulos]
ko_fi: amakropoulos
2 changes: 1 addition & 1 deletion .github/doxygen/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = "LLM for Unity"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = v2.5.2
PROJECT_NUMBER = v3.0.0

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
68 changes: 48 additions & 20 deletions Editor/LLMBuildProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
#if UNITY_IOS || UNITY_VISIONOS
using System.Collections.Generic;
#if UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_VISIONOS
using System.IO;
using UnityEditor.iOS.Xcode;
#endif
Expand All @@ -27,56 +28,83 @@ private void OnBuildError(string condition, string stacktrace, LogType type)
if (type == LogType.Error) BuildCompleted();
}

#if UNITY_IOS || UNITY_VISIONOS
#if UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_VISIONOS
/// <summary>
/// Postprocess the iOS Build
/// </summary>
public static void PostprocessIOSBuild(BuildTarget buildTarget, string outputPath)
{
List<string> libraryFileNames = new List<string>();
#if UNITY_IOS
string projPath = PBXProject.GetPBXProjectPath(outputPath);
#if UNITY_VISIONOS
projPath = projPath.Replace("Unity-iPhone", "Unity-VisionOS");
libraryFileNames.Add("libllamalib_ios-arm64.a");
#elif UNITY_VISIONOS
string projPath = PBXProject.GetPBXProjectPath(outputPath).Replace("Unity-iPhone", "Unity-VisionOS");
libraryFileNames.Add("libllamalib_visionos-arm64.a");
#else
string projPath = Path.Combine(outputPath, Path.GetFileName(outputPath) + ".xcodeproj", "project.pbxproj");
if (!File.Exists(projPath)) return;
libraryFileNames.Add("libllamalib_osx-universal_acc.dylib");
libraryFileNames.Add("libllamalib_osx-universal_no-acc.dylib");
#endif

PBXProject project = new PBXProject();
project.ReadFromFile(projPath);

string targetGuid = project.GetUnityFrameworkTargetGuid();
string frameworkTargetGuid = project.GetUnityFrameworkTargetGuid();
string unityMainTargetGuid = project.GetUnityMainTargetGuid();
string embedFrameworksGuid = project.GetResourcesBuildPhaseByTarget(frameworkTargetGuid);
string targetGuid = project.GetUnityFrameworkTargetGuid();

// Add Accelerate framework
project.AddFrameworkToProject(unityMainTargetGuid, "Accelerate.framework", false);
project.AddFrameworkToProject(targetGuid, "Accelerate.framework", false);
if (targetGuid != null) project.AddFrameworkToProject(targetGuid, "Accelerate.framework", false);

List<string> libraryFiles = new List<string>();
foreach (string libraryFileName in libraryFileNames)
{
string lib = LLMUnitySetup.SearchDirectory(outputPath, libraryFileName);
if (lib != null) libraryFiles.Add(lib);
}

string libraryFile = LLMUnitySetup.RelativePath(LLMUnitySetup.SearchDirectory(outputPath, $"libundreamai_{buildTarget.ToString().ToLower()}.a"), outputPath);
string fileGuid = project.FindFileGuidByProjectPath(libraryFile);
if (string.IsNullOrEmpty(fileGuid)) Debug.LogError($"Library file {libraryFile} not found in project");
if (libraryFiles.Count == 0)
{
Debug.LogError($"No library files found for the build");
}
else
{
foreach (var phaseGuid in project.GetAllBuildPhasesForTarget(unityMainTargetGuid))
foreach (string libraryFile in libraryFiles)
{
if (project.GetBuildPhaseName(phaseGuid) == "Embed Frameworks")
string relLibraryFile = LLMUnitySetup.RelativePath(libraryFile, outputPath);
string fileGuid = project.FindFileGuidByProjectPath(relLibraryFile);
if (string.IsNullOrEmpty(fileGuid))
{
project.RemoveFileFromBuild(phaseGuid, fileGuid);
break;
Debug.LogError($"Library file {relLibraryFile} not found in project");
}
}
else
{
foreach (var phaseGuid in project.GetAllBuildPhasesForTarget(unityMainTargetGuid))
{
if (project.GetBuildPhaseName(phaseGuid) == "Embed Frameworks")
{
project.RemoveFileFromBuild(phaseGuid, fileGuid);
break;
}
}

project.AddFileToBuild(unityMainTargetGuid, fileGuid);
project.AddFileToBuild(targetGuid, fileGuid);
project.AddFileToBuild(unityMainTargetGuid, fileGuid);
if (targetGuid != null) project.AddFileToBuild(targetGuid, fileGuid);
}
}
}

project.WriteToFile(projPath);
AssetDatabase.ImportAsset(projPath);
}

#endif

// called after the build
public void OnPostprocessBuild(BuildReport report)
{
#if UNITY_IOS || UNITY_VISIONOS
#if UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_VISIONOS
PostprocessIOSBuild(report.summary.platform, report.summary.outputPath);
#endif
EditorApplication.delayCall += () =>
Expand Down
22 changes: 5 additions & 17 deletions Editor/LLMCallerEditor.cs → Editor/LLMClientEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

namespace LLMUnity
{
[CustomEditor(typeof(LLMCaller), true)]
[CustomEditor(typeof(LLMClient), true)]
public class LLMCallerEditor : PropertyEditor {}

[CustomEditor(typeof(LLMCharacter), true)]
public class LLMCharacterEditor : LLMCallerEditor
[CustomEditor(typeof(LLMAgent), true)]
public class LLMAgentEditor : LLMCallerEditor
{
public override void AddModelSettings(SerializedObject llmScriptSO)
{
Expand All @@ -23,26 +23,14 @@ public override void AddModelSettings(SerializedObject llmScriptSO)
ShowPropertiesOfClass("", llmScriptSO, new List<Type> { typeof(ModelAttribute) }, false);

EditorGUILayout.BeginHorizontal();
GUILayout.Label("Grammar", GUILayout.Width(EditorGUIUtility.labelWidth));
if (GUILayout.Button("Load grammar", GUILayout.Width(buttonWidth)))
{
EditorApplication.delayCall += () =>
{
string path = EditorUtility.OpenFilePanelWithFilters("Select a gbnf grammar file", "", new string[] { "Grammar Files", "gbnf" });
string path = EditorUtility.OpenFilePanelWithFilters("Select a grammar file", "", new string[] { "Grammar Files", "json,gbnf" });
if (!string.IsNullOrEmpty(path))
{
((LLMCharacter)target).SetGrammar(path);
}
};
}
if (GUILayout.Button("Load JSON grammar", GUILayout.Width(buttonWidth)))
{
EditorApplication.delayCall += () =>
{
string path = EditorUtility.OpenFilePanelWithFilters("Select a json schema grammar file", "", new string[] { "Grammar Files", "json" });
if (!string.IsNullOrEmpty(path))
{
((LLMCharacter)target).SetJSONGrammar(path);
((LLMAgent)target).LoadGrammar(path);
}
};
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 17 additions & 45 deletions Editor/LLMEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public class LLMEditor : PropertyEditor
{
private ReorderableList modelList;
static float nameColumnWidth = 150f;
static float templateColumnWidth = 150f;
static float textColumnWidth = 150f;
static float includeInBuildColumnWidth = 30f;
static float actionColumnWidth = 20f;
Expand All @@ -32,7 +31,7 @@ public class LLMEditor : PropertyEditor

public void AddSecuritySettings(SerializedObject llmScriptSO, LLM llmScript)
{
void AddSSLLoad(string type, Callback<string> setterCallback)
void AddSSLLoad(string type, Action<string> setterCallback)
{
if (GUILayout.Button("Load SSL " + type, GUILayout.Width(buttonWidth)))
{
Expand All @@ -44,29 +43,17 @@ void AddSSLLoad(string type, Callback<string> setterCallback)
}
}

void AddSSLInfo(string propertyName, string type, Callback<string> setterCallback)
{
string path = llmScriptSO.FindProperty(propertyName).stringValue;
if (path != "")
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("SSL " + type + " path", path);
if (GUILayout.Button(trashIcon, GUILayout.Height(actionColumnWidth), GUILayout.Width(actionColumnWidth))) setterCallback("");
EditorGUILayout.EndHorizontal();
}
}

EditorGUILayout.LabelField("Server Security Settings", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(llmScriptSO.FindProperty("APIKey"));
EditorGUILayout.PropertyField(llmScriptSO.FindProperty("_APIKey"));

if (llmScriptSO.FindProperty("advancedOptions").boolValue)
{
EditorGUILayout.BeginHorizontal();
AddSSLLoad("certificate", llmScript.SetSSLCert);
AddSSLLoad("key", llmScript.SetSSLKey);
AddSSLLoad("certificate", llmScript.SetSSLCertFromFile);
AddSSLLoad("key", llmScript.SetSSLKeyFromFile);
EditorGUILayout.EndHorizontal();
AddSSLInfo("SSLCertPath", "certificate", llmScript.SetSSLCert);
AddSSLInfo("SSLKeyPath", "key", llmScript.SetSSLKey);
EditorGUILayout.PropertyField(llmScriptSO.FindProperty("_SSLCert"));
EditorGUILayout.PropertyField(llmScriptSO.FindProperty("_SSLKey"));
}
Space();
}
Expand Down Expand Up @@ -111,7 +98,7 @@ public override void AddModelSettings(SerializedObject llmScriptSO)
if (llmScriptSO.FindProperty("advancedOptions").boolValue)
{
attributeClasses.Add(typeof(ModelAdvancedAttribute));
if (LLMUnitySetup.FullLlamaLib) attributeClasses.Add(typeof(ModelExtrasAttribute));
attributeClasses.Add(typeof(ModelExtrasAttribute));
}
ShowPropertiesOfClass("", llmScriptSO, attributeClasses, false);
Space();
Expand All @@ -126,10 +113,10 @@ static void ResetModelOptions()
{
List<string> existingOptions = new List<string>();
foreach (ModelEntry entry in LLMManager.modelEntries) existingOptions.Add(entry.url);
modelOptions = new List<string>(){"Download model", "Custom URL"};
modelNames = new List<string>(){null, null};
modelURLs = new List<string>(){null, null};
modelLicenses = new List<string>(){null, null};
modelOptions = new List<string>() { "Download model", "Custom URL" };
modelNames = new List<string>() { null, null };
modelURLs = new List<string>() { null, null };
modelLicenses = new List<string>() { null, null };
foreach (var entry in LLMUnitySetup.modelOptions)
{
string category = entry.Key;
Expand All @@ -146,9 +133,9 @@ static void ResetModelOptions()

float[] GetColumnWidths(bool expandedView)
{
List<float> widths = new List<float>(){actionColumnWidth, nameColumnWidth, templateColumnWidth};
if (expandedView) widths.AddRange(new List<float>(){textColumnWidth, textColumnWidth});
widths.AddRange(new List<float>(){includeInBuildColumnWidth, actionColumnWidth});
List<float> widths = new List<float>() { actionColumnWidth, nameColumnWidth };
if (expandedView) widths.AddRange(new List<float>() { textColumnWidth, textColumnWidth });
widths.AddRange(new List<float>() { includeInBuildColumnWidth, actionColumnWidth });
return widths.ToArray();
}

Expand Down Expand Up @@ -320,7 +307,6 @@ void OnEnable()
int col = 0;
Rect selectRect = rects[col++];
Rect nameRect = rects[col++];
Rect templateRect = rects[col++];
Rect urlRect = new Rect();
Rect pathRect = new Rect();
if (expandedView)
Expand Down Expand Up @@ -351,19 +337,6 @@ void OnEnable()

DrawCopyableLabel(nameRect, entry.label, entry.filename);

if (!entry.lora)
{
string[] templateDescriptions = ChatTemplate.templatesDescription.Keys.ToList().ToArray();
string[] templates = ChatTemplate.templatesDescription.Values.ToList().ToArray();
int templateIndex = Array.IndexOf(templates, entry.chatTemplate);
int newTemplateIndex = EditorGUI.Popup(templateRect, templateIndex, templateDescriptions);
if (newTemplateIndex != templateIndex)
{
LLMManager.SetTemplate(entry.filename, templates[newTemplateIndex]);
UpdateModels();
}
}

if (expandedView)
{
if (hasURL)
Expand Down Expand Up @@ -411,7 +384,6 @@ void OnEnable()
int col = 0;
EditorGUI.LabelField(rects[col++], "");
EditorGUI.LabelField(rects[col++], "Model");
EditorGUI.LabelField(rects[col++], "Chat template");
if (expandedView)
{
EditorGUI.LabelField(rects[col++], "URL");
Expand Down Expand Up @@ -440,14 +412,14 @@ private void DrawCopyableLabel(Rect rect, string label, string text = "")

private void CopyToClipboard(string text)
{
TextEditor te = new TextEditor {text = text};
TextEditor te = new TextEditor { text = text };
te.SelectAll();
te.Copy();
}

public void AddExtrasToggle()
{
if (ToggleButton("Use extras", LLMUnitySetup.FullLlamaLib)) LLMUnitySetup.SetFullLlamaLib(!LLMUnitySetup.FullLlamaLib);
if (ToggleButton("Use cuBLAS", LLMUnitySetup.CUBLAS)) LLMUnitySetup.SetCUBLAS(!LLMUnitySetup.CUBLAS);
}

public override void AddOptionsToggles(SerializedObject llmScriptSO)
Expand Down Expand Up @@ -481,7 +453,7 @@ public override void OnInspectorGUI()

AddOptionsToggles(llmScriptSO);
AddSetupSettings(llmScriptSO);
if (llmScriptSO.FindProperty("remote").boolValue) AddSecuritySettings(llmScriptSO, llmScript);
if (llmScriptSO.FindProperty("_remote").boolValue) AddSecuritySettings(llmScriptSO, llmScript);
AddModelLoadersSettings(llmScriptSO, llmScript);
AddChatSettings(llmScriptSO);

Expand Down
2 changes: 1 addition & 1 deletion Editor/PropertyEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public virtual bool ToggleButton(string text, bool activated)
public virtual void AddSetupSettings(SerializedObject llmScriptSO)
{
List<Type> attributeClasses = new List<Type>(){typeof(LocalRemoteAttribute)};
SerializedProperty remoteProperty = llmScriptSO.FindProperty("remote");
SerializedProperty remoteProperty = llmScriptSO.FindProperty("_remote");
if (remoteProperty != null) attributeClasses.Add(remoteProperty.boolValue ? typeof(RemoteAttribute) : typeof(LocalAttribute));
attributeClasses.Add(typeof(LLMAttribute));
if (llmScriptSO.FindProperty("advancedOptions").boolValue)
Expand Down
Loading