diff --git a/Editor/LLMBuildProcessor.cs b/Editor/LLMBuildProcessor.cs index 96d0f3a8..12ec976f 100644 --- a/Editor/LLMBuildProcessor.cs +++ b/Editor/LLMBuildProcessor.cs @@ -2,7 +2,7 @@ using UnityEditor.Build; using UnityEditor.Build.Reporting; using UnityEngine; -#if UNITY_IOS +#if UNITY_IOS || UNITY_VISIONOS using UnityEditor.iOS.Xcode; #endif @@ -16,28 +16,14 @@ public class LLMBuildProcessor : IPreprocessBuildWithReport, IPostprocessBuildWi public void OnPreprocessBuild(BuildReport report) { Application.logMessageReceived += OnBuildError; - string platform = null; - switch (report.summary.platform) - { - case BuildTarget.StandaloneWindows: - case BuildTarget.StandaloneWindows64: - platform = "windows"; - break; - case BuildTarget.StandaloneLinux64: - platform = "linux"; - break; - case BuildTarget.StandaloneOSX: - platform = "macos"; - break; - case BuildTarget.Android: - platform = "android"; - break; - case BuildTarget.iOS: - platform = "ios"; - break; - } - LLMBuilder.Build(platform); + LLMBuilder.Build(report.summary.platform); AssetDatabase.Refresh(); +#if UNITY_IOS || UNITY_VISIONOS + EditorApplication.delayCall += () => + { + ModifyXCodeBuild(report.summary.platform, report.summary.outputPath); + }; +#endif } // called during build to check for errors @@ -46,38 +32,64 @@ private void OnBuildError(string condition, string stacktrace, LogType type) if (type == LogType.Error) BuildCompleted(); } -#if UNITY_IOS +#if UNITY_IOS || UNITY_VISIONOS /// - /// Adds the Accelerate framework (for ios) + /// Postprocess the iOS Build /// - public static void AddAccelerate(string outputPath) + public static void ModifyXCodeBuild(BuildTarget buildTarget, string outputPath) { string projPath = PBXProject.GetPBXProjectPath(outputPath); - PBXProject proj = new PBXProject(); - proj.ReadFromFile(projPath); - proj.AddFrameworkToProject(proj.GetUnityMainTargetGuid(), "Accelerate.framework", false); - proj.AddFrameworkToProject(proj.GetUnityFrameworkTargetGuid(), "Accelerate.framework", false); - proj.WriteToFile(projPath); +#if UNITY_VISIONOS + projPath = projPath.Replace("Unity-iPhone", "Unity-VisionOS"); +#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); + + // Add Accelerate framework + project.AddFrameworkToProject(unityMainTargetGuid, "Accelerate.framework", false); + project.AddFrameworkToProject(targetGuid, "Accelerate.framework", false); + + 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"); + 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.WriteToFile(projPath); } + #endif // called after the build public void OnPostprocessBuild(BuildReport report) { -#if UNITY_IOS - AddAccelerate(report.summary.outputPath); -#endif - BuildCompleted(); + EditorApplication.delayCall += () => + { + BuildCompleted(); + }; } public void BuildCompleted() { - // Delay the reset operation to ensure Unity is no longer in the build process - EditorApplication.delayCall += () => - { - Application.logMessageReceived -= OnBuildError; - LLMBuilder.Reset(); - }; + Application.logMessageReceived -= OnBuildError; + LLMBuilder.Reset(); } } } diff --git a/Runtime/LLMBuilder.cs b/Runtime/LLMBuilder.cs index e8a6dd2f..1e577323 100644 --- a/Runtime/LLMBuilder.cs +++ b/Runtime/LLMBuilder.cs @@ -12,12 +12,10 @@ namespace LLMUnity /// /// Class implementing the LLMUnity builder. /// - public class LLMBuilder + public class LLMBuilder : AssetPostprocessor { static List movedPairs = new List(); public static string BuildTempDir = Path.Combine(Application.temporaryCachePath, "LLMUnityBuild"); - public static string androidPluginDir = Path.Combine(Application.dataPath, "Plugins", "Android", "LLMUnity"); - public static string iOSPluginDir = Path.Combine(Application.dataPath, "Plugins", "iOS", "LLMUnity"); static string movedCache = Path.Combine(BuildTempDir, "moved.json"); [InitializeOnLoadMethod] @@ -26,6 +24,18 @@ private static void InitializeOnLoad() Reset(); } + public static string PluginDir(string platform, bool relative = false) + { + string pluginDir = Path.Combine("Plugins", platform, "LLMUnity"); + if (!relative) pluginDir = Path.Combine(Application.dataPath, pluginDir); + return pluginDir; + } + + public static string PluginLibraryDir(string platform, bool relative = false) + { + return Path.Combine(PluginDir(platform, relative), LLMUnitySetup.libraryName); + } + /// /// Performs an action for a file or a directory recursively /// @@ -88,7 +98,7 @@ public static void MovePath(string source, string target) /// path public static bool DeletePath(string path) { - string[] allowedDirs = new string[] { LLMUnitySetup.GetAssetPath(), BuildTempDir, androidPluginDir, iOSPluginDir}; + string[] allowedDirs = new string[] { LLMUnitySetup.GetAssetPath(), BuildTempDir, PluginDir("Android"), PluginDir("iOS"), PluginDir("VisionOS")}; bool deleteOK = false; foreach (string allowedDir in allowedDirs) deleteOK = deleteOK || LLMUnitySetup.IsSubPath(path, allowedDir); if (!deleteOK) @@ -152,38 +162,75 @@ static void AddActionAddMeta(string target) /// Moves libraries in the correct place for building /// /// target platform - public static void BuildLibraryPlatforms(string platform) + public static void BuildLibraryPlatforms(BuildTarget buildTarget) { - List platforms = new List(){ "windows", "macos", "linux", "android", "ios", "setup" }; - platforms.Remove(platform); + string platform = ""; + switch (buildTarget) + { + case BuildTarget.StandaloneWindows: + case BuildTarget.StandaloneWindows64: + platform = "windows"; + break; + case BuildTarget.StandaloneLinux64: + platform = "linux"; + break; + case BuildTarget.StandaloneOSX: + platform = "macos"; + break; + case BuildTarget.Android: + platform = "android"; + break; + case BuildTarget.iOS: + platform = "ios"; + break; + case BuildTarget.VisionOS: + platform = "visionos"; + break; + } + foreach (string source in Directory.GetDirectories(LLMUnitySetup.libraryPath)) { string sourceName = Path.GetFileName(source); - foreach (string platformPrefix in platforms) + bool move = !sourceName.StartsWith(platform); + move = move || (sourceName.Contains("cuda") && !sourceName.Contains("full") && LLMUnitySetup.FullLlamaLib); + move = move || (sourceName.Contains("cuda") && sourceName.Contains("full") && !LLMUnitySetup.FullLlamaLib); + if (move) { - bool move = sourceName.StartsWith(platformPrefix); - move = move || (sourceName.Contains("cuda") && !sourceName.Contains("full") && LLMUnitySetup.FullLlamaLib); - move = move || (sourceName.Contains("cuda") && sourceName.Contains("full") && !LLMUnitySetup.FullLlamaLib); - if (move) - { - string target = Path.Combine(BuildTempDir, sourceName); - MoveAction(source, target); - MoveAction(source + ".meta", target + ".meta"); - } + string target = Path.Combine(BuildTempDir, sourceName); + MoveAction(source, target); + MoveAction(source + ".meta", target + ".meta"); } } - if (platform == "android" || platform == "ios") + if (buildTarget == BuildTarget.Android || buildTarget == BuildTarget.iOS || buildTarget == BuildTarget.VisionOS) { - string pluginDir = platform == "android"? androidPluginDir: iOSPluginDir; string source = Path.Combine(LLMUnitySetup.libraryPath, platform); - string target = Path.Combine(pluginDir, LLMUnitySetup.libraryName); + string target = PluginLibraryDir(buildTarget.ToString()); + string pluginDir = PluginDir(buildTarget.ToString()); MoveAction(source, target); MoveAction(source + ".meta", target + ".meta"); AddActionAddMeta(pluginDir); } } + + static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload) + { + string pathToPlugin = Path.Combine("Assets", PluginLibraryDir(BuildTarget.VisionOS.ToString(), true), "libundreamai_visionos.a"); + for (int i = 0; i < movedAssets.Length; i++) + { + if(movedAssets[i] == pathToPlugin) + { + var importer = AssetImporter.GetAtPath(pathToPlugin) as PluginImporter; + if (importer != null && importer.isNativePlugin) { + importer.SetCompatibleWithPlatform(BuildTarget.VisionOS, true); + importer.SetPlatformData(BuildTarget.VisionOS, "CPU", "ARM64"); + AssetDatabase.ImportAsset(pathToPlugin); + } + } + } + } + /// /// Bundles the model information /// @@ -196,11 +243,11 @@ public static void BuildModels() /// /// Bundles the models and libraries /// - public static void Build(string platform) + public static void Build(BuildTarget buildTarget) { DeletePath(BuildTempDir); Directory.CreateDirectory(BuildTempDir); - BuildLibraryPlatforms(platform); + BuildLibraryPlatforms(buildTarget); BuildModels(); } diff --git a/Runtime/LLMLib.cs b/Runtime/LLMLib.cs index 98dcc78c..767ab35c 100644 --- a/Runtime/LLMLib.cs +++ b/Runtime/LLMLib.cs @@ -139,10 +139,8 @@ public static IntPtr LoadLibrary(string libraryName) handle = Linux.dlopen(libraryName); else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer) handle = Mac.dlopen(libraryName); - else if (Application.platform == RuntimePlatform.Android) - handle = Android.dlopen(libraryName); - else if (Application.platform == RuntimePlatform.IPhonePlayer) - handle = iOS.dlopen(libraryName); + else if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.VisionOS) + handle = Mobile.dlopen(libraryName); else throw new PlatformNotSupportedException($"Current platform is unknown, unable to load library '{libraryName}'."); @@ -167,10 +165,8 @@ public static IntPtr GetSymbol(IntPtr library, string symbolName) handle = Linux.dlsym(library, symbolName); else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer) handle = Mac.dlsym(library, symbolName); - else if (Application.platform == RuntimePlatform.Android) - handle = Android.dlsym(library, symbolName); - else if (Application.platform == RuntimePlatform.IPhonePlayer) - handle = iOS.dlsym(library, symbolName); + else if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.VisionOS) + handle = Mobile.dlsym(library, symbolName); else throw new PlatformNotSupportedException($"Current platform is unknown, unable to load symbol '{symbolName}' from library {library}."); @@ -192,10 +188,8 @@ public static void FreeLibrary(IntPtr library) Linux.dlclose(library); else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer) Mac.dlclose(library); - else if (Application.platform == RuntimePlatform.Android) - Android.dlclose(library); - else if (Application.platform == RuntimePlatform.IPhonePlayer) - iOS.dlclose(library); + else if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.VisionOS) + Mobile.dlclose(library); else throw new PlatformNotSupportedException($"Current platform is unknown, unable to close library '{library}'."); } @@ -289,11 +283,11 @@ private static class Win32 public static extern void FreeLibrary(IntPtr hModule); } - private static class Android + private static class Mobile { public static IntPtr dlopen(string path) => dlopen(path, 1); -#if UNITY_ANDROID +#if UNITY_ANDROID || UNITY_IOS || UNITY_VISIONOS [DllImport("__Internal")] public static extern IntPtr dlopen(string filename, int flags); @@ -318,41 +312,6 @@ public static int dlclose(IntPtr handle) return default; } -#endif - } - - private static class iOS - { - public static IntPtr dlopen(string path) => dlopen(path, 1); - -#if UNITY_IOS - // LoadLibrary for iOS - [DllImport("__Internal")] - public static extern IntPtr dlopen(string filename, int flags); - - // GetSymbol for iOS - [DllImport("__Internal")] - public static extern IntPtr dlsym(IntPtr handle, string symbol); - - // FreeLibrary for iOS - [DllImport("__Internal")] - public static extern int dlclose(IntPtr handle); -#else - public static IntPtr dlopen(string filename, int flags) - { - return default; - } - - public static IntPtr dlsym(IntPtr handle, string symbol) - { - return default; - } - - public static int dlclose(IntPtr handle) - { - return default; - } - #endif } } @@ -368,9 +327,9 @@ public class LLMLib static bool has_avx2 = false; static bool has_avx512 = false; -#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR +#if (UNITY_ANDROID || UNITY_IOS || UNITY_VISIONOS) && !UNITY_EDITOR - public LLMLib(string arch){} + public LLMLib(string arch) {} #if UNITY_ANDROID public const string LibraryName = "libundreamai_android"; @@ -378,79 +337,79 @@ public LLMLib(string arch){} public const string LibraryName = "__Internal"; #endif - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="Logging")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Logging")] public static extern void LoggingStatic(IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StopLogging")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StopLogging")] public static extern void StopLoggingStatic(); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Construct")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Construct")] public static extern IntPtr LLM_ConstructStatic(string command); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Delete")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Delete")] public static extern void LLM_DeleteStatic(IntPtr LLMObject); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_StartServer")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_StartServer")] public static extern void LLM_StartServerStatic(IntPtr LLMObject); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_StopServer")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_StopServer")] public static extern void LLM_StopServerStatic(IntPtr LLMObject); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Start")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Start")] public static extern void LLM_StartStatic(IntPtr LLMObject); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Started")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Started")] public static extern bool LLM_StartedStatic(IntPtr LLMObject); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Stop")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Stop")] public static extern void LLM_StopStatic(IntPtr LLMObject); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_SetTemplate")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_SetTemplate")] public static extern void LLM_SetTemplateStatic(IntPtr LLMObject, string chatTemplate); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_SetSSL")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_SetSSL")] public static extern void LLM_SetSSLStatic(IntPtr LLMObject, string SSLCert, string SSLKey); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Tokenize")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Tokenize")] public static extern void LLM_TokenizeStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Detokenize")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Detokenize")] public static extern void LLM_DetokenizeStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Embeddings")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Embeddings")] public static extern void LLM_EmbeddingsStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Lora_Weight")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Lora_Weight")] public static extern void LLM_LoraWeightStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Lora_List")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Lora_List")] public static extern void LLM_LoraListStatic(IntPtr LLMObject, IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Completion")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Completion")] public static extern void LLM_CompletionStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Slot")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Slot")] public static extern void LLM_SlotStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Cancel")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Cancel")] public static extern void LLM_CancelStatic(IntPtr LLMObject, int idSlot); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Status")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Status")] public static extern int LLM_StatusStatic(IntPtr LLMObject, IntPtr stringWrapper); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StringWrapper_Construct")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_Construct")] public static extern IntPtr StringWrapper_ConstructStatic(); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StringWrapper_Delete")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_Delete")] public static extern void StringWrapper_DeleteStatic(IntPtr instance); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StringWrapper_GetStringSize")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_GetStringSize")] public static extern int StringWrapper_GetStringSizeStatic(IntPtr instance); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StringWrapper_GetString")] + [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_GetString")] public static extern void StringWrapper_GetStringStatic(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false); - public void Logging(IntPtr stringWrapper){ LoggingStatic(stringWrapper); } - public void StopLogging(){ StopLoggingStatic(); } - public IntPtr LLM_Construct(string command){ return LLM_ConstructStatic(command); } - public void LLM_Delete(IntPtr LLMObject){ LLM_DeleteStatic(LLMObject); } - public void LLM_StartServer(IntPtr LLMObject){ LLM_StartServerStatic(LLMObject); } - public void LLM_StopServer(IntPtr LLMObject){ LLM_StopServerStatic(LLMObject); } - public void LLM_Start(IntPtr LLMObject){ LLM_StartStatic(LLMObject); } - public bool LLM_Started(IntPtr LLMObject){ return LLM_StartedStatic(LLMObject); } - public void LLM_Stop(IntPtr LLMObject){ LLM_StopStatic(LLMObject); } - public void LLM_SetTemplate(IntPtr LLMObject, string chatTemplate){ LLM_SetTemplateStatic(LLMObject, chatTemplate); } - public void LLM_SetSSL(IntPtr LLMObject, string SSLCert, string SSLKey){ LLM_SetSSLStatic(LLMObject, SSLCert, SSLKey); } - public void LLM_Tokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_TokenizeStatic(LLMObject, jsonData, stringWrapper); } - public void LLM_Detokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_DetokenizeStatic(LLMObject, jsonData, stringWrapper); } - public void LLM_Embeddings(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_EmbeddingsStatic(LLMObject, jsonData, stringWrapper); } - public void LLM_LoraWeight(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_LoraWeightStatic(LLMObject, jsonData, stringWrapper); } - public void LLM_LoraList(IntPtr LLMObject, IntPtr stringWrapper){ LLM_LoraListStatic(LLMObject, stringWrapper); } - public void LLM_Completion(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_CompletionStatic(LLMObject, jsonData, stringWrapper); } - public void LLM_Slot(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_SlotStatic(LLMObject, jsonData, stringWrapper); } - public void LLM_Cancel(IntPtr LLMObject, int idSlot){ LLM_CancelStatic(LLMObject, idSlot); } - public int LLM_Status(IntPtr LLMObject, IntPtr stringWrapper){ return LLM_StatusStatic(LLMObject, stringWrapper); } - public IntPtr StringWrapper_Construct(){ return StringWrapper_ConstructStatic(); } - public void StringWrapper_Delete(IntPtr instance){ StringWrapper_DeleteStatic(instance); } - public int StringWrapper_GetStringSize(IntPtr instance){ return StringWrapper_GetStringSizeStatic(instance); } - public void StringWrapper_GetString(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false){ StringWrapper_GetStringStatic(instance, buffer, bufferSize, clear); } + public void Logging(IntPtr stringWrapper) { LoggingStatic(stringWrapper); } + public void StopLogging() { StopLoggingStatic(); } + public IntPtr LLM_Construct(string command) { return LLM_ConstructStatic(command); } + public void LLM_Delete(IntPtr LLMObject) { LLM_DeleteStatic(LLMObject); } + public void LLM_StartServer(IntPtr LLMObject) { LLM_StartServerStatic(LLMObject); } + public void LLM_StopServer(IntPtr LLMObject) { LLM_StopServerStatic(LLMObject); } + public void LLM_Start(IntPtr LLMObject) { LLM_StartStatic(LLMObject); } + public bool LLM_Started(IntPtr LLMObject) { return LLM_StartedStatic(LLMObject); } + public void LLM_Stop(IntPtr LLMObject) { LLM_StopStatic(LLMObject); } + public void LLM_SetTemplate(IntPtr LLMObject, string chatTemplate) { LLM_SetTemplateStatic(LLMObject, chatTemplate); } + public void LLM_SetSSL(IntPtr LLMObject, string SSLCert, string SSLKey) { LLM_SetSSLStatic(LLMObject, SSLCert, SSLKey); } + public void LLM_Tokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_TokenizeStatic(LLMObject, jsonData, stringWrapper); } + public void LLM_Detokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_DetokenizeStatic(LLMObject, jsonData, stringWrapper); } + public void LLM_Embeddings(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_EmbeddingsStatic(LLMObject, jsonData, stringWrapper); } + public void LLM_LoraWeight(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_LoraWeightStatic(LLMObject, jsonData, stringWrapper); } + public void LLM_LoraList(IntPtr LLMObject, IntPtr stringWrapper) { LLM_LoraListStatic(LLMObject, stringWrapper); } + public void LLM_Completion(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_CompletionStatic(LLMObject, jsonData, stringWrapper); } + public void LLM_Slot(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_SlotStatic(LLMObject, jsonData, stringWrapper); } + public void LLM_Cancel(IntPtr LLMObject, int idSlot) { LLM_CancelStatic(LLMObject, idSlot); } + public int LLM_Status(IntPtr LLMObject, IntPtr stringWrapper) { return LLM_StatusStatic(LLMObject, stringWrapper); } + public IntPtr StringWrapper_Construct() { return StringWrapper_ConstructStatic(); } + public void StringWrapper_Delete(IntPtr instance) { StringWrapper_DeleteStatic(instance); } + public int StringWrapper_GetStringSize(IntPtr instance) { return StringWrapper_GetStringSizeStatic(instance); } + public void StringWrapper_GetString(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false) { StringWrapper_GetStringStatic(instance, buffer, bufferSize, clear); } #else @@ -686,6 +645,10 @@ public static List PossibleArchitectures(bool gpu = false) { architectures.Add("ios"); } + else if (Application.platform == RuntimePlatform.VisionOS) + { + architectures.Add("visionos"); + } else { string error = "Unknown OS"; @@ -694,7 +657,7 @@ public static List PossibleArchitectures(bool gpu = false) } return architectures; } - + /// /// Allows to retrieve a string from the library (Unity only allows marshalling of chars) /// @@ -728,6 +691,5 @@ public void Destroy() if (libraryHandle != IntPtr.Zero) LibraryLoader.FreeLibrary(libraryHandle); } } - } /// \endcond diff --git a/Runtime/LLMUnitySetup.cs b/Runtime/LLMUnitySetup.cs index 0d50e7ff..931a688d 100644 --- a/Runtime/LLMUnitySetup.cs +++ b/Runtime/LLMUnitySetup.cs @@ -103,7 +103,7 @@ public class LLMUnitySetup /// LLM for Unity version public static string Version = "v2.4.1"; /// LlamaLib version - public static string LlamaLibVersion = "v1.2.1"; + public static string LlamaLibVersion = "v1.2.2"; /// LlamaLib release url public static string LlamaLibReleaseURL = $"https://github.com/undreamai/LlamaLib/releases/download/{LlamaLibVersion}"; /// LlamaLib name @@ -219,13 +219,13 @@ public static string GetLibraryName(string version) public static string GetAssetPath(string relPath = "") { - string assetsDir = Application.platform == RuntimePlatform.Android? Application.persistentDataPath : Application.streamingAssetsPath; + string assetsDir = Application.platform == RuntimePlatform.Android ? Application.persistentDataPath : Application.streamingAssetsPath; return Path.Combine(assetsDir, relPath).Replace('\\', '/'); } public static string GetDownloadAssetPath(string relPath = "") { - string assetsDir = (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)? Application.persistentDataPath : Application.streamingAssetsPath; + string assetsDir = (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.VisionOS) ? Application.persistentDataPath : Application.streamingAssetsPath; return Path.Combine(assetsDir, relPath).Replace('\\', '/'); } @@ -374,6 +374,19 @@ public static string RelativePath(string fullPath, string basePath) return relativePath; } + public static string SearchDirectory(string directory, string targetFileName) + { + string[] files = Directory.GetFiles(directory, targetFileName); + if (files.Length > 0) return files[0]; + string[] subdirectories = Directory.GetDirectories(directory); + foreach (var subdirectory in subdirectories) + { + string result = SearchDirectory(subdirectory, targetFileName); + if (result != null) return result; + } + return null; + } + #if UNITY_EDITOR [HideInInspector] public static float libraryProgress = 1; @@ -414,13 +427,12 @@ static async Task DownloadAndExtractInsideDirectory(string url, string path, str File.Delete(zipPath); } - static void DeleteEarlierVersions() { List assetPathSubDirs = new List(); - foreach (string dir in new string[]{GetAssetPath(), Path.Combine(Application.dataPath, "Plugins", "Android")}) + foreach (string dir in new string[] {GetAssetPath(), Path.Combine(Application.dataPath, "Plugins", "Android")}) { - if(Directory.Exists(dir)) assetPathSubDirs.AddRange(Directory.GetDirectories(dir)); + if (Directory.Exists(dir)) assetPathSubDirs.AddRange(Directory.GetDirectories(dir)); } Regex regex = new Regex(GetLibraryName("(.+)"));