LLM for Unity  v2.4.2
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)
143 handle = Android.dlopen(libraryName);
144 else if (Application.platform == RuntimePlatform.IPhonePlayer)
145 handle = iOS.dlopen(libraryName);
146 else
147 throw new PlatformNotSupportedException($"Current platform is unknown, unable to load library '{libraryName}'.");
148
149 return handle;
150 }
151
158 public static IntPtr GetSymbol(IntPtr library, string symbolName)
159 {
160 if (string.IsNullOrEmpty(symbolName))
161 throw new ArgumentNullException(nameof(symbolName));
162
163 IntPtr handle;
164 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
165 handle = Win32.GetProcAddress(library, symbolName);
166 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
167 handle = Linux.dlsym(library, symbolName);
168 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer)
169 handle = Mac.dlsym(library, symbolName);
170 else if (Application.platform == RuntimePlatform.Android)
171 handle = Android.dlsym(library, symbolName);
172 else if (Application.platform == RuntimePlatform.IPhonePlayer)
173 handle = iOS.dlsym(library, symbolName);
174 else
175 throw new PlatformNotSupportedException($"Current platform is unknown, unable to load symbol '{symbolName}' from library {library}.");
176
177 return handle;
178 }
179
184 public static void FreeLibrary(IntPtr library)
185 {
186 if (library == IntPtr.Zero)
187 return;
188
189 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
190 Win32.FreeLibrary(library);
191 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
192 Linux.dlclose(library);
193 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer)
194 Mac.dlclose(library);
195 else if (Application.platform == RuntimePlatform.Android)
196 Android.dlclose(library);
197 else if (Application.platform == RuntimePlatform.IPhonePlayer)
198 iOS.dlclose(library);
199 else
200 throw new PlatformNotSupportedException($"Current platform is unknown, unable to close library '{library}'.");
201 }
202
203 private static class Mac
204 {
205 private const string SystemLibrary = "/usr/lib/libSystem.dylib";
206
207 private const int RTLD_LAZY = 1;
208 private const int RTLD_NOW = 2;
209
210 public static IntPtr dlopen(string path, bool lazy = true) =>
211 dlopen(path, lazy ? RTLD_LAZY : RTLD_NOW);
212
213 [DllImport(SystemLibrary)]
214 public static extern IntPtr dlopen(string path, int mode);
215
216 [DllImport(SystemLibrary)]
217 public static extern IntPtr dlsym(IntPtr handle, string symbol);
218
219 [DllImport(SystemLibrary)]
220 public static extern void dlclose(IntPtr handle);
221 }
222
223 private static class Linux
224 {
225 private const string SystemLibrary = "libdl.so";
226 private const string SystemLibrary2 = "libdl.so.2"; // newer Linux distros use this
227
228 private const int RTLD_LAZY = 1;
229 private const int RTLD_NOW = 2;
230
231 private static bool UseSystemLibrary2 = true;
232
233 public static IntPtr dlopen(string path, bool lazy = true)
234 {
235 try
236 {
237 return dlopen2(path, lazy ? RTLD_LAZY : RTLD_NOW);
238 }
239 catch (DllNotFoundException)
240 {
241 UseSystemLibrary2 = false;
242 return dlopen1(path, lazy ? RTLD_LAZY : RTLD_NOW);
243 }
244 }
245
246 public static IntPtr dlsym(IntPtr handle, string symbol)
247 {
248 return UseSystemLibrary2 ? dlsym2(handle, symbol) : dlsym1(handle, symbol);
249 }
250
251 public static void dlclose(IntPtr handle)
252 {
253 if (UseSystemLibrary2)
254 dlclose2(handle);
255 else
256 dlclose1(handle);
257 }
258
259 [DllImport(SystemLibrary, EntryPoint = "dlopen")]
260 private static extern IntPtr dlopen1(string path, int mode);
261
262 [DllImport(SystemLibrary, EntryPoint = "dlsym")]
263 private static extern IntPtr dlsym1(IntPtr handle, string symbol);
264
265 [DllImport(SystemLibrary, EntryPoint = "dlclose")]
266 private static extern void dlclose1(IntPtr handle);
267
268 [DllImport(SystemLibrary2, EntryPoint = "dlopen")]
269 private static extern IntPtr dlopen2(string path, int mode);
270
271 [DllImport(SystemLibrary2, EntryPoint = "dlsym")]
272 private static extern IntPtr dlsym2(IntPtr handle, string symbol);
273
274 [DllImport(SystemLibrary2, EntryPoint = "dlclose")]
275 private static extern void dlclose2(IntPtr handle);
276 }
277
278 private static class Win32
279 {
280 private const string SystemLibrary = "Kernel32.dll";
281
282 [DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
283 public static extern IntPtr LoadLibrary(string lpFileName);
284
285 [DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
286 public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
287
288 [DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
289 public static extern void FreeLibrary(IntPtr hModule);
290 }
291
292 private static class Android
293 {
294 public static IntPtr dlopen(string path) => dlopen(path, 1);
295
296#if UNITY_ANDROID
297 [DllImport("__Internal")]
298 public static extern IntPtr dlopen(string filename, int flags);
299
300 [DllImport("__Internal")]
301 public static extern IntPtr dlsym(IntPtr handle, string symbol);
302
303 [DllImport("__Internal")]
304 public static extern int dlclose(IntPtr handle);
305#else
306 public static IntPtr dlopen(string filename, int flags)
307 {
308 return default;
309 }
310
311 public static IntPtr dlsym(IntPtr handle, string symbol)
312 {
313 return default;
314 }
315
316 public static int dlclose(IntPtr handle)
317 {
318 return default;
319 }
320
321#endif
322 }
323
324 private static class iOS
325 {
326 public static IntPtr dlopen(string path) => dlopen(path, 1);
327
328#if UNITY_IOS
329 // LoadLibrary for iOS
330 [DllImport("__Internal")]
331 public static extern IntPtr dlopen(string filename, int flags);
332
333 // GetSymbol for iOS
334 [DllImport("__Internal")]
335 public static extern IntPtr dlsym(IntPtr handle, string symbol);
336
337 // FreeLibrary for iOS
338 [DllImport("__Internal")]
339 public static extern int dlclose(IntPtr handle);
340#else
341 public static IntPtr dlopen(string filename, int flags)
342 {
343 return default;
344 }
345
346 public static IntPtr dlsym(IntPtr handle, string symbol)
347 {
348 return default;
349 }
350
351 public static int dlclose(IntPtr handle)
352 {
353 return default;
354 }
355
356#endif
357 }
358 }
359
364 public class LLMLib
365 {
366 IntPtr libraryHandle = IntPtr.Zero;
367 static bool has_avx = false;
368 static bool has_avx2 = false;
369 static bool has_avx512 = false;
370 List<IntPtr> dependencyHandles = new List<IntPtr>();
371
372#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
373
374 public LLMLib(string arch) {}
375
376#if UNITY_ANDROID
377 public const string LibraryName = "libundreamai_android";
378#else
379 public const string LibraryName = "__Internal";
380#endif
381
382 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Logging")]
383 public static extern void LoggingStatic(IntPtr stringWrapper);
384 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StopLogging")]
385 public static extern void StopLoggingStatic();
386 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Construct")]
387 public static extern IntPtr LLM_ConstructStatic(string command);
388 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Delete")]
389 public static extern void LLM_DeleteStatic(IntPtr LLMObject);
390 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_StartServer")]
391 public static extern void LLM_StartServerStatic(IntPtr LLMObject);
392 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_StopServer")]
393 public static extern void LLM_StopServerStatic(IntPtr LLMObject);
394 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Start")]
395 public static extern void LLM_StartStatic(IntPtr LLMObject);
396 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Started")]
397 public static extern bool LLM_StartedStatic(IntPtr LLMObject);
398 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Stop")]
399 public static extern void LLM_StopStatic(IntPtr LLMObject);
400 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_SetTemplate")]
401 public static extern void LLM_SetTemplateStatic(IntPtr LLMObject, string chatTemplate);
402 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_SetSSL")]
403 public static extern void LLM_SetSSLStatic(IntPtr LLMObject, string SSLCert, string SSLKey);
404 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Tokenize")]
405 public static extern void LLM_TokenizeStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
406 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Detokenize")]
407 public static extern void LLM_DetokenizeStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
408 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Embeddings")]
409 public static extern void LLM_EmbeddingsStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
410 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Lora_Weight")]
411 public static extern void LLM_LoraWeightStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
412 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Lora_List")]
413 public static extern void LLM_LoraListStatic(IntPtr LLMObject, IntPtr stringWrapper);
414 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Completion")]
415 public static extern void LLM_CompletionStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
416 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Slot")]
417 public static extern void LLM_SlotStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
418 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Cancel")]
419 public static extern void LLM_CancelStatic(IntPtr LLMObject, int idSlot);
420 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLM_Status")]
421 public static extern int LLM_StatusStatic(IntPtr LLMObject, IntPtr stringWrapper);
422 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_Construct")]
423 public static extern IntPtr StringWrapper_ConstructStatic();
424 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_Delete")]
425 public static extern void StringWrapper_DeleteStatic(IntPtr instance);
426 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_GetStringSize")]
427 public static extern int StringWrapper_GetStringSizeStatic(IntPtr instance);
428 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StringWrapper_GetString")]
429 public static extern void StringWrapper_GetStringStatic(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false);
430
431 public void Logging(IntPtr stringWrapper) { LoggingStatic(stringWrapper); }
432 public void StopLogging() { StopLoggingStatic(); }
433 public IntPtr LLM_Construct(string command) { return LLM_ConstructStatic(command); }
434 public void LLM_Delete(IntPtr LLMObject) { LLM_DeleteStatic(LLMObject); }
435 public void LLM_StartServer(IntPtr LLMObject) { LLM_StartServerStatic(LLMObject); }
436 public void LLM_StopServer(IntPtr LLMObject) { LLM_StopServerStatic(LLMObject); }
437 public void LLM_Start(IntPtr LLMObject) { LLM_StartStatic(LLMObject); }
438 public bool LLM_Started(IntPtr LLMObject) { return LLM_StartedStatic(LLMObject); }
439 public void LLM_Stop(IntPtr LLMObject) { LLM_StopStatic(LLMObject); }
440 public void LLM_SetTemplate(IntPtr LLMObject, string chatTemplate) { LLM_SetTemplateStatic(LLMObject, chatTemplate); }
441 public void LLM_SetSSL(IntPtr LLMObject, string SSLCert, string SSLKey) { LLM_SetSSLStatic(LLMObject, SSLCert, SSLKey); }
442 public void LLM_Tokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_TokenizeStatic(LLMObject, jsonData, stringWrapper); }
443 public void LLM_Detokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_DetokenizeStatic(LLMObject, jsonData, stringWrapper); }
444 public void LLM_Embeddings(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_EmbeddingsStatic(LLMObject, jsonData, stringWrapper); }
445 public void LLM_LoraWeight(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_LoraWeightStatic(LLMObject, jsonData, stringWrapper); }
446 public void LLM_LoraList(IntPtr LLMObject, IntPtr stringWrapper) { LLM_LoraListStatic(LLMObject, stringWrapper); }
447 public void LLM_Completion(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_CompletionStatic(LLMObject, jsonData, stringWrapper); }
448 public void LLM_Slot(IntPtr LLMObject, string jsonData, IntPtr stringWrapper) { LLM_SlotStatic(LLMObject, jsonData, stringWrapper); }
449 public void LLM_Cancel(IntPtr LLMObject, int idSlot) { LLM_CancelStatic(LLMObject, idSlot); }
450 public int LLM_Status(IntPtr LLMObject, IntPtr stringWrapper) { return LLM_StatusStatic(LLMObject, stringWrapper); }
451 public IntPtr StringWrapper_Construct() { return StringWrapper_ConstructStatic(); }
452 public void StringWrapper_Delete(IntPtr instance) { StringWrapper_DeleteStatic(instance); }
453 public int StringWrapper_GetStringSize(IntPtr instance) { return StringWrapper_GetStringSizeStatic(instance); }
454 public void StringWrapper_GetString(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false) { StringWrapper_GetStringStatic(instance, buffer, bufferSize, clear); }
455
456#else
457
458 static bool has_avx_set = false;
459 static readonly object staticLock = new object();
460
461 static LLMLib()
462 {
463 lock (staticLock)
464 {
465 if (has_avx_set) return;
466 string archCheckerPath = GetArchitectureCheckerPath();
467 if (archCheckerPath != null)
468 {
469 IntPtr archCheckerHandle = LibraryLoader.LoadLibrary(archCheckerPath);
470 if (archCheckerHandle == IntPtr.Zero)
471 {
472 LLMUnitySetup.LogError($"Failed to load library {archCheckerPath}.");
473 }
474 else
475 {
476 try
477 {
478 has_avx = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx")();
479 has_avx2 = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx2")();
480 has_avx512 = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx512")();
481 LibraryLoader.FreeLibrary(archCheckerHandle);
482 }
483 catch (Exception e)
484 {
485 LLMUnitySetup.LogError($"{e.GetType()}: {e.Message}");
486 }
487 }
488 }
489 has_avx_set = true;
490 }
491 }
492
498 public LLMLib(string arch)
499 {
500 foreach (string dependency in GetArchitectureDependencies(arch))
501 {
502 LLMUnitySetup.Log($"Loading {dependency}");
503 dependencyHandles.Add(LibraryLoader.LoadLibrary(dependency));
504 }
505
506 libraryHandle = LibraryLoader.LoadLibrary(GetArchitecturePath(arch));
507 if (libraryHandle == IntPtr.Zero)
508 {
509 throw new Exception($"Failed to load library {arch}.");
510 }
511
512 LLM_Construct = LibraryLoader.GetSymbolDelegate<LLM_ConstructDelegate>(libraryHandle, "LLM_Construct");
513 LLM_Delete = LibraryLoader.GetSymbolDelegate<LLM_DeleteDelegate>(libraryHandle, "LLM_Delete");
514 LLM_StartServer = LibraryLoader.GetSymbolDelegate<LLM_StartServerDelegate>(libraryHandle, "LLM_StartServer");
515 LLM_StopServer = LibraryLoader.GetSymbolDelegate<LLM_StopServerDelegate>(libraryHandle, "LLM_StopServer");
516 LLM_Start = LibraryLoader.GetSymbolDelegate<LLM_StartDelegate>(libraryHandle, "LLM_Start");
517 LLM_Started = LibraryLoader.GetSymbolDelegate<LLM_StartedDelegate>(libraryHandle, "LLM_Started");
518 LLM_Stop = LibraryLoader.GetSymbolDelegate<LLM_StopDelegate>(libraryHandle, "LLM_Stop");
519 LLM_SetTemplate = LibraryLoader.GetSymbolDelegate<LLM_SetTemplateDelegate>(libraryHandle, "LLM_SetTemplate");
520 LLM_SetSSL = LibraryLoader.GetSymbolDelegate<LLM_SetSSLDelegate>(libraryHandle, "LLM_SetSSL");
521 LLM_Tokenize = LibraryLoader.GetSymbolDelegate<LLM_TokenizeDelegate>(libraryHandle, "LLM_Tokenize");
522 LLM_Detokenize = LibraryLoader.GetSymbolDelegate<LLM_DetokenizeDelegate>(libraryHandle, "LLM_Detokenize");
523 LLM_Embeddings = LibraryLoader.GetSymbolDelegate<LLM_EmbeddingsDelegate>(libraryHandle, "LLM_Embeddings");
524 LLM_LoraWeight = LibraryLoader.GetSymbolDelegate<LLM_LoraWeightDelegate>(libraryHandle, "LLM_Lora_Weight");
525 LLM_LoraList = LibraryLoader.GetSymbolDelegate<LLM_LoraListDelegate>(libraryHandle, "LLM_Lora_List");
526 LLM_Completion = LibraryLoader.GetSymbolDelegate<LLM_CompletionDelegate>(libraryHandle, "LLM_Completion");
527 LLM_Slot = LibraryLoader.GetSymbolDelegate<LLM_SlotDelegate>(libraryHandle, "LLM_Slot");
528 LLM_Cancel = LibraryLoader.GetSymbolDelegate<LLM_CancelDelegate>(libraryHandle, "LLM_Cancel");
529 LLM_Status = LibraryLoader.GetSymbolDelegate<LLM_StatusDelegate>(libraryHandle, "LLM_Status");
530 StringWrapper_Construct = LibraryLoader.GetSymbolDelegate<StringWrapper_ConstructDelegate>(libraryHandle, "StringWrapper_Construct");
531 StringWrapper_Delete = LibraryLoader.GetSymbolDelegate<StringWrapper_DeleteDelegate>(libraryHandle, "StringWrapper_Delete");
532 StringWrapper_GetStringSize = LibraryLoader.GetSymbolDelegate<StringWrapper_GetStringSizeDelegate>(libraryHandle, "StringWrapper_GetStringSize");
533 StringWrapper_GetString = LibraryLoader.GetSymbolDelegate<StringWrapper_GetStringDelegate>(libraryHandle, "StringWrapper_GetString");
534 Logging = LibraryLoader.GetSymbolDelegate<LoggingDelegate>(libraryHandle, "Logging");
535 StopLogging = LibraryLoader.GetSymbolDelegate<StopLoggingDelegate>(libraryHandle, "StopLogging");
536 }
537
542 public static string GetArchitectureCheckerPath()
543 {
544 string filename;
545 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
546 {
547 filename = $"windows-archchecker/archchecker.dll";
548 }
549 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
550 {
551 filename = $"linux-archchecker/libarchchecker.so";
552 }
553 else
554 {
555 return null;
556 }
557 return Path.Combine(LLMUnitySetup.libraryPath, filename);
558 }
559
565 public static List<string> GetArchitectureDependencies(string arch)
566 {
567 List<string> dependencies = new List<string>();
568 if (arch == "cuda-cu12.2.0-full")
569 {
570 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
571 {
572 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"windows-{arch}/cudart64_12.dll"));
573 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"windows-{arch}/cublasLt64_12.dll"));
574 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"windows-{arch}/cublas64_12.dll"));
575 }
576 } else if (arch == "vulkan") {
577 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
578 {
579 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"windows-{arch}/vulkan-1.dll"));
580 }
581 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
582 {
583 dependencies.Add(Path.Combine(LLMUnitySetup.libraryPath, $"linux-{arch}/libvulkan.so.1"));
584 }
585 }
586 return dependencies;
587 }
588
594 public static string GetArchitecturePath(string arch)
595 {
596 string filename;
597 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
598 {
599 filename = $"windows-{arch}/undreamai_windows-{arch}.dll";
600 }
601 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
602 {
603 filename = $"linux-{arch}/libundreamai_linux-{arch}.so";
604 }
605 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer)
606 {
607 filename = $"macos-{arch}/libundreamai_macos-{arch}.dylib";
608 }
609 else
610 {
611 string error = "Unknown OS";
612 LLMUnitySetup.LogError(error);
613 throw new Exception(error);
614 }
615 return Path.Combine(LLMUnitySetup.libraryPath, filename);
616 }
617
618 public delegate bool HasArchDelegate();
619 public delegate void LoggingDelegate(IntPtr stringWrapper);
620 public delegate void StopLoggingDelegate();
621 public delegate IntPtr LLM_ConstructDelegate(string command);
622 public delegate void LLM_DeleteDelegate(IntPtr LLMObject);
623 public delegate void LLM_StartServerDelegate(IntPtr LLMObject);
624 public delegate void LLM_StopServerDelegate(IntPtr LLMObject);
625 public delegate void LLM_StartDelegate(IntPtr LLMObject);
626 public delegate bool LLM_StartedDelegate(IntPtr LLMObject);
627 public delegate void LLM_StopDelegate(IntPtr LLMObject);
628 public delegate void LLM_SetTemplateDelegate(IntPtr LLMObject, string chatTemplate);
629 public delegate void LLM_SetSSLDelegate(IntPtr LLMObject, string SSLCert, string SSLKey);
630 public delegate void LLM_TokenizeDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
631 public delegate void LLM_DetokenizeDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
632 public delegate void LLM_EmbeddingsDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
633 public delegate void LLM_LoraWeightDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
634 public delegate void LLM_LoraListDelegate(IntPtr LLMObject, IntPtr stringWrapper);
635 public delegate void LLM_CompletionDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
636 public delegate void LLM_SlotDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
637 public delegate void LLM_CancelDelegate(IntPtr LLMObject, int idSlot);
638 public delegate int LLM_StatusDelegate(IntPtr LLMObject, IntPtr stringWrapper);
639 public delegate IntPtr StringWrapper_ConstructDelegate();
640 public delegate void StringWrapper_DeleteDelegate(IntPtr instance);
641 public delegate int StringWrapper_GetStringSizeDelegate(IntPtr instance);
642 public delegate void StringWrapper_GetStringDelegate(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false);
643
644 public LoggingDelegate Logging;
645 public StopLoggingDelegate StopLogging;
646 public LLM_ConstructDelegate LLM_Construct;
647 public LLM_DeleteDelegate LLM_Delete;
648 public LLM_StartServerDelegate LLM_StartServer;
649 public LLM_StopServerDelegate LLM_StopServer;
650 public LLM_StartDelegate LLM_Start;
651 public LLM_StartedDelegate LLM_Started;
652 public LLM_StopDelegate LLM_Stop;
653 public LLM_SetTemplateDelegate LLM_SetTemplate;
654 public LLM_SetSSLDelegate LLM_SetSSL;
655 public LLM_TokenizeDelegate LLM_Tokenize;
656 public LLM_DetokenizeDelegate LLM_Detokenize;
657 public LLM_CompletionDelegate LLM_Completion;
658 public LLM_EmbeddingsDelegate LLM_Embeddings;
659 public LLM_LoraWeightDelegate LLM_LoraWeight;
660 public LLM_LoraListDelegate LLM_LoraList;
661 public LLM_SlotDelegate LLM_Slot;
662 public LLM_CancelDelegate LLM_Cancel;
663 public LLM_StatusDelegate LLM_Status;
664 public StringWrapper_ConstructDelegate StringWrapper_Construct;
665 public StringWrapper_DeleteDelegate StringWrapper_Delete;
666 public StringWrapper_GetStringSizeDelegate StringWrapper_GetStringSize;
667 public StringWrapper_GetStringDelegate StringWrapper_GetString;
668
669#endif
670
676 public static List<string> PossibleArchitectures(bool gpu = false)
677 {
678 List<string> architectures = new List<string>();
679 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer ||
680 Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
681 {
682 if (gpu)
683 {
684 if (LLMUnitySetup.FullLlamaLib)
685 {
686 architectures.Add("cuda-cu12.2.0-full");
687 }
688 else
689 {
690 architectures.Add("cuda-cu12.2.0");
691 }
692 architectures.Add("hip");
693 architectures.Add("vulkan");
694 }
695 if (has_avx512) architectures.Add("avx512");
696 if (has_avx2) architectures.Add("avx2");
697 if (has_avx) architectures.Add("avx");
698 architectures.Add("noavx");
699 }
700 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer)
701 {
702 string arch = RuntimeInformation.ProcessArchitecture.ToString().ToLower();
703 if (arch.Contains("arm"))
704 {
705 architectures.Add("arm64-acc");
706 architectures.Add("arm64-no_acc");
707 }
708 else
709 {
710 if (arch != "x86" && arch != "x64") LLMUnitySetup.LogWarning($"Unknown architecture of processor {arch}! Falling back to x86_64");
711 architectures.Add("x64-acc");
712 architectures.Add("x64-no_acc");
713 }
714 }
715 else if (Application.platform == RuntimePlatform.Android)
716 {
717 architectures.Add("android");
718 }
719 else if (Application.platform == RuntimePlatform.IPhonePlayer)
720 {
721 architectures.Add("ios");
722 }
723 else
724 {
725 string error = "Unknown OS";
726 LLMUnitySetup.LogError(error);
727 throw new Exception(error);
728 }
729 return architectures;
730 }
731
737 public string GetStringWrapperResult(IntPtr stringWrapper)
738 {
739 string result = "";
740 int bufferSize = StringWrapper_GetStringSize(stringWrapper);
741 if (bufferSize > 1)
742 {
743 IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
744 try
745 {
746 StringWrapper_GetString(stringWrapper, buffer, bufferSize);
747 result = Marshal.PtrToStringAnsi(buffer);
748 }
749 finally
750 {
751 Marshal.FreeHGlobal(buffer);
752 }
753 }
754 return result;
755 }
756
760 public void Destroy()
761 {
762 if (libraryHandle != IntPtr.Zero) LibraryLoader.FreeLibrary(libraryHandle);
763 foreach (IntPtr dependencyHandle in dependencyHandles) LibraryLoader.FreeLibrary(dependencyHandle);
764 }
765 }
766}