LLM for Unity  v2.5.0
Create characters in Unity with LLMs!
Loading...
Searching...
No Matches
LLMLib.cs
Go to the documentation of this file.
1
4using System;
5using System.Collections.Generic;
6using System.IO;
7using System.Runtime.InteropServices;
8using UnityEngine;
9
10namespace LLMUnity
11{
16 public class StreamWrapper
17 {
18 LLMLib llmlib;
19 Callback<string> callback;
20 IntPtr stringWrapper;
21 string previousString = "";
22 string previousCalledString = "";
23 int previousBufferSize = 0;
24 bool clearOnUpdate;
25
26 public StreamWrapper(LLMLib llmlib, Callback<string> callback, bool clearOnUpdate = false)
27 {
28 this.llmlib = llmlib;
29 this.callback = callback;
30 this.clearOnUpdate = clearOnUpdate;
31 stringWrapper = (llmlib?.StringWrapper_Construct()).GetValueOrDefault();
32 }
33
39 public string GetString(bool clear = false)
40 {
41 string result;
42 int bufferSize = (llmlib?.StringWrapper_GetStringSize(stringWrapper)).GetValueOrDefault();
43 if (bufferSize <= 1)
44 {
45 result = "";
46 }
47 else if (previousBufferSize != bufferSize)
48 {
49 IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
50 try
51 {
52 llmlib?.StringWrapper_GetString(stringWrapper, buffer, bufferSize, clear);
53 result = Marshal.PtrToStringAnsi(buffer);
54 }
55 finally
56 {
57 Marshal.FreeHGlobal(buffer);
58 }
59 previousString = result;
60 }
61 else
62 {
63 result = previousString;
64 }
65 previousBufferSize = bufferSize;
66 return result;
67 }
68
72 public void Update()
73 {
74 if (stringWrapper == IntPtr.Zero) return;
75 string result = GetString(clearOnUpdate);
76 if (result != "" && previousCalledString != result)
77 {
78 callback?.Invoke(result);
79 previousCalledString = result;
80 }
81 }
82
87 public IntPtr GetStringWrapper()
88 {
89 return stringWrapper;
90 }
91
95 public void Destroy()
96 {
97 if (stringWrapper != IntPtr.Zero) llmlib?.StringWrapper_Delete(stringWrapper);
98 }
99 }
100
107 static class LibraryLoader
108 {
116 public static T GetSymbolDelegate<T>(IntPtr library, string name) where T : Delegate
117 {
118 var symbol = GetSymbol(library, name);
119 if (symbol == IntPtr.Zero)
120 throw new EntryPointNotFoundException($"Unable to load symbol '{name}'.");
121
122 return Marshal.GetDelegateForFunctionPointer<T>(symbol);
123 }
124
130 public static IntPtr LoadLibrary(string libraryName)
131 {
132 if (string.IsNullOrEmpty(libraryName))
133 throw new ArgumentNullException(nameof(libraryName));
134
135 IntPtr handle;
136 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
137 handle = Win32.LoadLibrary(libraryName);
138 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
139 handle = Linux.dlopen(libraryName);
140 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer)
141 handle = Mac.dlopen(libraryName);
142 else if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.VisionOS)
143 handle = Mobile.dlopen(libraryName);
144 else
145 throw new PlatformNotSupportedException($"Current platform is unknown, unable to load library '{libraryName}'.");
146
147 return handle;
148 }
149
156 public static IntPtr GetSymbol(IntPtr library, string symbolName)
157 {
158 if (string.IsNullOrEmpty(symbolName))
159 throw new ArgumentNullException(nameof(symbolName));
160
161 IntPtr handle;
162 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
163 handle = Win32.GetProcAddress(library, symbolName);
164 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
165 handle = Linux.dlsym(library, symbolName);
166 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer)
167 handle = Mac.dlsym(library, symbolName);
168 else if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.VisionOS)
169 handle = Mobile.dlsym(library, symbolName);
170 else
171 throw new PlatformNotSupportedException($"Current platform is unknown, unable to load symbol '{symbolName}' from library {library}.");
172
173 return handle;
174 }
175
180 public static void FreeLibrary(IntPtr library)
181 {
182 if (library == IntPtr.Zero)
183 return;
184
185 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
186 Win32.FreeLibrary(library);
187 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
188 Linux.dlclose(library);
189 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer)
190 Mac.dlclose(library);
191 else if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.VisionOS)
192 Mobile.dlclose(library);
193 else
194 throw new PlatformNotSupportedException($"Current platform is unknown, unable to close library '{library}'.");
195 }
196
197 private static class Mac
198 {
199 private const string SystemLibrary = "/usr/lib/libSystem.dylib";
200
201 private const int RTLD_LAZY = 1;
202 private const int RTLD_NOW = 2;
203
204 public static IntPtr dlopen(string path, bool lazy = true) =>
205 dlopen(path, lazy ? RTLD_LAZY : RTLD_NOW);
206
207 [DllImport(SystemLibrary)]
208 public static extern IntPtr dlopen(string path, int mode);
209
210 [DllImport(SystemLibrary)]
211 public static extern IntPtr dlsym(IntPtr handle, string symbol);
212
213 [DllImport(SystemLibrary)]
214 public static extern void dlclose(IntPtr handle);
215 }
216
217 private static class Linux
218 {
219 private const string SystemLibrary = "libdl.so";
220 private const string SystemLibrary2 = "libdl.so.2"; // newer Linux distros use this
221
222 private const int RTLD_LAZY = 1;
223 private const int RTLD_NOW = 2;
224
225 private static bool UseSystemLibrary2 = true;
226
227 public static IntPtr dlopen(string path, bool lazy = true)
228 {
229 try
230 {
231 return dlopen2(path, lazy ? RTLD_LAZY : RTLD_NOW);
232 }
233 catch (DllNotFoundException)
234 {
235 UseSystemLibrary2 = false;
236 return dlopen1(path, lazy ? RTLD_LAZY : RTLD_NOW);
237 }
238 }
239
240 public static IntPtr dlsym(IntPtr handle, string symbol)
241 {
242 return UseSystemLibrary2 ? dlsym2(handle, symbol) : dlsym1(handle, symbol);
243 }
244
245 public static void dlclose(IntPtr handle)
246 {
247 if (UseSystemLibrary2)
248 dlclose2(handle);
249 else
250 dlclose1(handle);
251 }
252
253 [DllImport(SystemLibrary, EntryPoint = "dlopen")]
254 private static extern IntPtr dlopen1(string path, int mode);
255
256 [DllImport(SystemLibrary, EntryPoint = "dlsym")]
257 private static extern IntPtr dlsym1(IntPtr handle, string symbol);
258
259 [DllImport(SystemLibrary, EntryPoint = "dlclose")]
260 private static extern void dlclose1(IntPtr handle);
261
262 [DllImport(SystemLibrary2, EntryPoint = "dlopen")]
263 private static extern IntPtr dlopen2(string path, int mode);
264
265 [DllImport(SystemLibrary2, EntryPoint = "dlsym")]
266 private static extern IntPtr dlsym2(IntPtr handle, string symbol);
267
268 [DllImport(SystemLibrary2, EntryPoint = "dlclose")]
269 private static extern void dlclose2(IntPtr handle);
270 }
271
272 private static class Win32
273 {
274 private const string SystemLibrary = "Kernel32.dll";
275
276 [DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
277 public static extern IntPtr LoadLibrary(string lpFileName);
278
279 [DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
280 public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
281
282 [DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
283 public static extern void FreeLibrary(IntPtr hModule);
284 }
285
286 private static class Mobile
287 {
288 public static IntPtr dlopen(string path) => dlopen(path, 1);
289
290#if UNITY_ANDROID || UNITY_IOS || UNITY_VISIONOS
291 [DllImport("__Internal")]
292 public static extern IntPtr dlopen(string filename, int flags);
293
294 [DllImport("__Internal")]
295 public static extern IntPtr dlsym(IntPtr handle, string symbol);
296
297 [DllImport("__Internal")]
298 public static extern int dlclose(IntPtr handle);
299#else
300 public static IntPtr dlopen(string filename, int flags)
301 {
302 return default;
303 }
304
305 public static IntPtr dlsym(IntPtr handle, string symbol)
306 {
307 return default;
308 }
309
310 public static int dlclose(IntPtr handle)
311 {
312 return default;
313 }
314
315#endif
316 }
317 }
318
323 public class LLMLib
324 {
325 public string architecture { get; private set; }
326 IntPtr libraryHandle = IntPtr.Zero;
327 static bool has_avx = false;
328 static bool has_avx2 = false;
329 static bool has_avx512 = false;
330 List<IntPtr> dependencyHandles = new List<IntPtr>();
331
332#if (UNITY_ANDROID || UNITY_IOS || UNITY_VISIONOS) && !UNITY_EDITOR
333
334 public LLMLib(string arch)
335 {
336 architecture = arch;
337 }
338
339#if UNITY_ANDROID
340 public const string LibraryName = "libundreamai_android";
341#else
342 public const string LibraryName = "__Internal";
343#endif
344
345 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Logging")]
346 public static extern void LoggingStatic(IntPtr stringWrapper);
347 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StopLogging")]
348 public static extern void StopLoggingStatic();
349 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Construct")]
350 public static extern IntPtr LLM_ConstructStatic(string command);
351 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Delete")]
352 public static extern void LLM_DeleteStatic(IntPtr LLMObject);
353 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_StartServer")]
354 public static extern void LLM_StartServerStatic(IntPtr LLMObject);
355 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_StopServer")]
356 public static extern void LLM_StopServerStatic(IntPtr LLMObject);
357 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Start")]
358 public static extern void LLM_StartStatic(IntPtr LLMObject);
359 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Started")]
360 public static extern bool LLM_StartedStatic(IntPtr LLMObject);
361 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Stop")]
362 public static extern void LLM_StopStatic(IntPtr LLMObject);
363 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_SetTemplate")]
364 public static extern void LLM_SetTemplateStatic(IntPtr LLMObject, string chatTemplate);
365 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_SetSSL")]
366 public static extern void LLM_SetSSLStatic(IntPtr LLMObject, string SSLCert, string SSLKey);
367 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Tokenize")]
368 public static extern void LLM_TokenizeStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
369 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Detokenize")]
370 public static extern void LLM_DetokenizeStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
371 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Embeddings")]
372 public static extern void LLM_EmbeddingsStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
373 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Lora_Weight")]
374 public static extern void LLM_LoraWeightStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
375 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Lora_List")]
376 public static extern void LLM_LoraListStatic(IntPtr LLMObject, IntPtr stringWrapper);
377 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Completion")]
378 public static extern void LLM_CompletionStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
379 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Slot")]
380 public static extern void LLM_SlotStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
381 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Cancel")]
382 public static extern void LLM_CancelStatic(IntPtr LLMObject, int idSlot);
383 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Status")]
384 public static extern int LLM_StatusStatic(IntPtr LLMObject, IntPtr stringWrapper);
385 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_Construct")]
386 public static extern IntPtr StringWrapper_ConstructStatic();
387 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_Delete")]
388 public static extern void StringWrapper_DeleteStatic(IntPtr instance);
389 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_GetStringSize")]
390 public static extern int StringWrapper_GetStringSizeStatic(IntPtr instance);
391 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_GetString")]
392 public static extern void StringWrapper_GetStringStatic(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false);
393
394 public void Logging(IntPtr stringWrapper) { LoggingStatic(stringWrapper); }
395 public void StopLogging() { StopLoggingStatic(); }
396 public IntPtr LLM_Construct(string command) { return LLM_ConstructStatic(command); }
397 public void LLM_Delete(IntPtr LLMObject) { LLM_DeleteStatic(LLMObject); }
398 public void LLM_StartServer(IntPtr LLMObject) { LLM_StartServerStatic(LLMObject); }
399 public void LLM_StopServer(IntPtr LLMObject) { LLM_StopServerStatic(LLMObject); }
400 public void LLM_Start(IntPtr LLMObject) { LLM_StartStatic(LLMObject); }
401 public bool LLM_Started(IntPtr LLMObject) { return LLM_StartedStatic(LLMObject); }
402 public void LLM_Stop(IntPtr LLMObject) { LLM_StopStatic(LLMObject); }
403 public void LLM_SetTemplate(IntPtr LLMObject, string chatTemplate) { LLM_SetTemplateStatic(LLMObject, chatTemplate); }
404 public void LLM_SetSSL(IntPtr LLMObject, string SSLCert, string SSLKey) { LLM_SetSSLStatic(LLMObject, SSLCert, SSLKey); }
405 public void LLM_Tokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_TokenizeStatic(LLMObject, jsonData, stringWrapper); }
406 public void LLM_Detokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_DetokenizeStatic(LLMObject, jsonData, stringWrapper); }
407 public void LLM_Embeddings(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_EmbeddingsStatic(LLMObject, jsonData, stringWrapper); }
408 public void LLM_LoraWeight(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_LoraWeightStatic(LLMObject, jsonData, stringWrapper); }
409 public void LLM_LoraList(IntPtr LLMObject, IntPtr stringWrapper) { LLM_LoraListStatic(LLMObject, stringWrapper); }
410 public void LLM_Completion(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_CompletionStatic(LLMObject, jsonData, stringWrapper); }
411 public void LLM_Slot(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_SlotStatic(LLMObject, jsonData, stringWrapper); }
412 public void LLM_Cancel(IntPtr LLMObject, int idSlot) { LLM_CancelStatic(LLMObject, idSlot); }
413 public int LLM_Status(IntPtr LLMObject, IntPtr stringWrapper) { return LLM_StatusStatic(LLMObject, stringWrapper); }
414 public IntPtr StringWrapper_Construct() { return StringWrapper_ConstructStatic(); }
415 public void StringWrapper_Delete(IntPtr instance) { StringWrapper_DeleteStatic(instance); }
416 public int StringWrapper_GetStringSize(IntPtr instance) { return StringWrapper_GetStringSizeStatic(instance); }
417 public void StringWrapper_GetString(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false) { StringWrapper_GetStringStatic(instance, buffer, bufferSize, clear); }
418
419#else
420
421 static bool has_avx_set = false;
422 static readonly object staticLock = new object();
423
424 static LLMLib()
425 {
426 lock (staticLock)
427 {
428 if (has_avx_set) return;
429 string archCheckerPath = GetArchitectureCheckerPath();
430 if (archCheckerPath != null)
431 {
432 IntPtr archCheckerHandle = LibraryLoader.LoadLibrary(archCheckerPath);
433 if (archCheckerHandle == IntPtr.Zero)
434 {
435 LLMUnitySetup.LogError($"Failed to load library {archCheckerPath}.");
436 }
437 else
438 {
439 try
440 {
441 has_avx = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx")();
442 has_avx2 = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx2")();
443 has_avx512 = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx512")();
444 LibraryLoader.FreeLibrary(archCheckerHandle);
445 }
446 catch (Exception e)
447 {
448 LLMUnitySetup.LogError($"{e.GetType()}: {e.Message}");
449 }
450 }
451 }
452 has_avx_set = true;
453 }
454 }
455
461 public LLMLib(string arch)
462 {
463 architecture = arch;
464 foreach (string dependency in GetArchitectureDependencies(arch))
465 {
466 LLMUnitySetup.Log($"Loading {dependency}");
467 dependencyHandles.Add(LibraryLoader.LoadLibrary(dependency));
468 }
469
470 libraryHandle = LibraryLoader.LoadLibrary(GetArchitecturePath(arch));
471 if (libraryHandle == IntPtr.Zero)
472 {
473 throw new Exception($"Failed to load library {arch}.");
474 }
475
476 LLM_Construct = LibraryLoader.GetSymbolDelegate<LLM_ConstructDelegate>(libraryHandle, "LLM_Construct");
477 LLM_Delete = LibraryLoader.GetSymbolDelegate<LLM_DeleteDelegate>(libraryHandle, "LLM_Delete");
478 LLM_StartServer = LibraryLoader.GetSymbolDelegate<LLM_StartServerDelegate>(libraryHandle, "LLM_StartServer");
479 LLM_StopServer = LibraryLoader.GetSymbolDelegate<LLM_StopServerDelegate>(libraryHandle, "LLM_StopServer");
480 LLM_Start = LibraryLoader.GetSymbolDelegate<LLM_StartDelegate>(libraryHandle, "LLM_Start");
481 LLM_Started = LibraryLoader.GetSymbolDelegate<LLM_StartedDelegate>(libraryHandle, "LLM_Started");
482 LLM_Stop = LibraryLoader.GetSymbolDelegate<LLM_StopDelegate>(libraryHandle, "LLM_Stop");
483 LLM_SetTemplate = LibraryLoader.GetSymbolDelegate<LLM_SetTemplateDelegate>(libraryHandle, "LLM_SetTemplate");
484 LLM_SetSSL = LibraryLoader.GetSymbolDelegate<LLM_SetSSLDelegate>(libraryHandle, "LLM_SetSSL");
485 LLM_Tokenize = LibraryLoader.GetSymbolDelegate<LLM_TokenizeDelegate>(libraryHandle, "LLM_Tokenize");
486 LLM_Detokenize = LibraryLoader.GetSymbolDelegate<LLM_DetokenizeDelegate>(libraryHandle, "LLM_Detokenize");
487 LLM_Embeddings = LibraryLoader.GetSymbolDelegate<LLM_EmbeddingsDelegate>(libraryHandle, "LLM_Embeddings");
488 LLM_LoraWeight = LibraryLoader.GetSymbolDelegate<LLM_LoraWeightDelegate>(libraryHandle, "LLM_Lora_Weight");
489 LLM_LoraList = LibraryLoader.GetSymbolDelegate<LLM_LoraListDelegate>(libraryHandle, "LLM_Lora_List");
490 LLM_Completion = LibraryLoader.GetSymbolDelegate<LLM_CompletionDelegate>(libraryHandle, "LLM_Completion");
491 LLM_Slot = LibraryLoader.GetSymbolDelegate<LLM_SlotDelegate>(libraryHandle, "LLM_Slot");
492 LLM_Cancel = LibraryLoader.GetSymbolDelegate<LLM_CancelDelegate>(libraryHandle, "LLM_Cancel");
493 LLM_Status = LibraryLoader.GetSymbolDelegate<LLM_StatusDelegate>(libraryHandle, "LLM_Status");
494 StringWrapper_Construct = LibraryLoader.GetSymbolDelegate<StringWrapper_ConstructDelegate>(libraryHandle, "StringWrapper_Construct");
495 StringWrapper_Delete = LibraryLoader.GetSymbolDelegate<StringWrapper_DeleteDelegate>(libraryHandle, "StringWrapper_Delete");
496 StringWrapper_GetStringSize = LibraryLoader.GetSymbolDelegate<StringWrapper_GetStringSizeDelegate>(libraryHandle, "StringWrapper_GetStringSize");
497 StringWrapper_GetString = LibraryLoader.GetSymbolDelegate<StringWrapper_GetStringDelegate>(libraryHandle, "StringWrapper_GetString");
498 Logging = LibraryLoader.GetSymbolDelegate<LoggingDelegate>(libraryHandle, "Logging");
499 StopLogging = LibraryLoader.GetSymbolDelegate<StopLoggingDelegate>(libraryHandle, "StopLogging");
500 }
501
506 public static string GetArchitectureCheckerPath()
507 {
508 string filename;
509 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
510 {
511 filename = $"windows-archchecker/archchecker.dll";
512 }
513 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
514 {
515 filename = $"linux-archchecker/libarchchecker.so";
516 }
517 else
518 {
519 return null;
520 }
521 return Path.Combine(LLMUnitySetup.libraryPath, filename);
522 }
523
529 public static List<string> GetArchitectureDependencies(string arch)
530 {
531 List<string> dependencies = new List<string>();
532 if (arch == "cuda-cu12.2.0-full")
533 {
534 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
535 {
536 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"windows-{arch}/cudart64_12.dll"));
537 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"windows-{arch}/cublasLt64_12.dll"));
538 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"windows-{arch}/cublas64_12.dll"));
539 }
540 }
541 else if (arch == "vulkan")
542 {
543 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
544 {
545 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"windows-{arch}/vulkan-1.dll"));
546 }
547 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
548 {
549 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"linux-{arch}/libvulkan.so.1"));
550 }
551 }
552 return dependencies;
553 }
554
560 public static string GetArchitecturePath(string arch)
561 {
562 string filename;
563 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
564 {
565 filename = $"windows-{arch}/undreamai_windows-{arch}.dll";
566 }
567 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
568 {
569 filename = $"linux-{arch}/libundreamai_linux-{arch}.so";
570 }
571 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer)
572 {
573 filename = $"macos-{arch}/libundreamai_macos-{arch}.dylib";
574 }
575 else
576 {
577 string error = "Unknown OS";
578 LLMUnitySetup.LogError(error);
579 throw new Exception(error);
580 }
581 return Path.Combine(LLMUnitySetup.libraryPath, filename);
582 }
583
584 public delegate bool HasArchDelegate();
585 public delegate void LoggingDelegate(IntPtr stringWrapper);
586 public delegate void StopLoggingDelegate();
587 public delegate IntPtr LLM_ConstructDelegate(string command);
588 public delegate void LLM_DeleteDelegate(IntPtr LLMObject);
589 public delegate void LLM_StartServerDelegate(IntPtr LLMObject);
590 public delegate void LLM_StopServerDelegate(IntPtr LLMObject);
591 public delegate void LLM_StartDelegate(IntPtr LLMObject);
592 public delegate bool LLM_StartedDelegate(IntPtr LLMObject);
593 public delegate void LLM_StopDelegate(IntPtr LLMObject);
594 public delegate void LLM_SetTemplateDelegate(IntPtr LLMObject, string chatTemplate);
595 public delegate void LLM_SetSSLDelegate(IntPtr LLMObject, string SSLCert, string SSLKey);
596 public delegate void LLM_TokenizeDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
597 public delegate void LLM_DetokenizeDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
598 public delegate void LLM_EmbeddingsDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
599 public delegate void LLM_LoraWeightDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
600 public delegate void LLM_LoraListDelegate(IntPtr LLMObject, IntPtr stringWrapper);
601 public delegate void LLM_CompletionDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
602 public delegate void LLM_SlotDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
603 public delegate void LLM_CancelDelegate(IntPtr LLMObject, int idSlot);
604 public delegate int LLM_StatusDelegate(IntPtr LLMObject, IntPtr stringWrapper);
605 public delegate IntPtr StringWrapper_ConstructDelegate();
606 public delegate void StringWrapper_DeleteDelegate(IntPtr instance);
607 public delegate int StringWrapper_GetStringSizeDelegate(IntPtr instance);
608 public delegate void StringWrapper_GetStringDelegate(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false);
609
610 public LoggingDelegate Logging;
611 public StopLoggingDelegate StopLogging;
612 public LLM_ConstructDelegate LLM_Construct;
613 public LLM_DeleteDelegate LLM_Delete;
614 public LLM_StartServerDelegate LLM_StartServer;
615 public LLM_StopServerDelegate LLM_StopServer;
616 public LLM_StartDelegate LLM_Start;
617 public LLM_StartedDelegate LLM_Started;
618 public LLM_StopDelegate LLM_Stop;
619 public LLM_SetTemplateDelegate LLM_SetTemplate;
620 public LLM_SetSSLDelegate LLM_SetSSL;
621 public LLM_TokenizeDelegate LLM_Tokenize;
622 public LLM_DetokenizeDelegate LLM_Detokenize;
623 public LLM_CompletionDelegate LLM_Completion;
624 public LLM_EmbeddingsDelegate LLM_Embeddings;
625 public LLM_LoraWeightDelegate LLM_LoraWeight;
626 public LLM_LoraListDelegate LLM_LoraList;
627 public LLM_SlotDelegate LLM_Slot;
628 public LLM_CancelDelegate LLM_Cancel;
629 public LLM_StatusDelegate LLM_Status;
630 public StringWrapper_ConstructDelegate StringWrapper_Construct;
631 public StringWrapper_DeleteDelegate StringWrapper_Delete;
632 public StringWrapper_GetStringSizeDelegate StringWrapper_GetStringSize;
633 public StringWrapper_GetStringDelegate StringWrapper_GetString;
634
635#endif
636
642 public static List<string> PossibleArchitectures(bool gpu = false)
643 {
644 List<string> architectures = new List<string>();
645 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer ||
646 Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
647 {
648 if (gpu)
649 {
650 if (LLMUnitySetup.FullLlamaLib)
651 {
652 architectures.Add("cuda-cu12.2.0-full");
653 }
654 else
655 {
656 architectures.Add("cuda-cu12.2.0");
657 }
658 architectures.Add("hip");
659 architectures.Add("vulkan");
660 }
661 if (has_avx512) architectures.Add("avx512");
662 if (has_avx2) architectures.Add("avx2");
663 if (has_avx) architectures.Add("avx");
664 architectures.Add("noavx");
665 }
666 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer)
667 {
668 string arch = RuntimeInformation.ProcessArchitecture.ToString().ToLower();
669 if (arch.Contains("arm"))
670 {
671 architectures.Add("arm64-acc");
672 architectures.Add("arm64-no_acc");
673 }
674 else
675 {
676 if (arch != "x86" && arch != "x64") LLMUnitySetup.LogWarning($"Unknown architecture of processor {arch}! Falling back to x86_64");
677 architectures.Add("x64-acc");
678 architectures.Add("x64-no_acc");
679 }
680 }
681 else if (Application.platform == RuntimePlatform.Android)
682 {
683 architectures.Add("android");
684 }
685 else if (Application.platform == RuntimePlatform.IPhonePlayer)
686 {
687 architectures.Add("ios");
688 }
689 else if (Application.platform == RuntimePlatform.VisionOS)
690 {
691 architectures.Add("visionos");
692 }
693 else
694 {
695 string error = "Unknown OS";
696 LLMUnitySetup.LogError(error);
697 throw new Exception(error);
698 }
699 return architectures;
700 }
701
707 public string GetStringWrapperResult(IntPtr stringWrapper)
708 {
709 string result = "";
710 int bufferSize = StringWrapper_GetStringSize(stringWrapper);
711 if (bufferSize > 1)
712 {
713 IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
714 try
715 {
716 StringWrapper_GetString(stringWrapper, buffer, bufferSize);
717 result = Marshal.PtrToStringAnsi(buffer);
718 }
719 finally
720 {
721 Marshal.FreeHGlobal(buffer);
722 }
723 }
724 return result;
725 }
726
730 public void Destroy()
731 {
732 if (libraryHandle != IntPtr.Zero) LibraryLoader.FreeLibrary(libraryHandle);
733 foreach (IntPtr dependencyHandle in dependencyHandles) LibraryLoader.FreeLibrary(dependencyHandle);
734 }
735 }
736}