LLM for Unity  v2.4.1
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
371#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
372
373 public LLMLib(string arch){}
374
375#if UNITY_ANDROID
376 public const string LibraryName = "libundreamai_android";
377#else
378 public const string LibraryName = "__Internal";
379#endif
380
381 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="Logging")]
382 public static extern void LoggingStatic(IntPtr stringWrapper);
383 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StopLogging")]
384 public static extern void StopLoggingStatic();
385 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Construct")]
386 public static extern IntPtr LLM_ConstructStatic(string command);
387 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Delete")]
388 public static extern void LLM_DeleteStatic(IntPtr LLMObject);
389 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_StartServer")]
390 public static extern void LLM_StartServerStatic(IntPtr LLMObject);
391 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_StopServer")]
392 public static extern void LLM_StopServerStatic(IntPtr LLMObject);
393 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Start")]
394 public static extern void LLM_StartStatic(IntPtr LLMObject);
395 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Started")]
396 public static extern bool LLM_StartedStatic(IntPtr LLMObject);
397 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Stop")]
398 public static extern void LLM_StopStatic(IntPtr LLMObject);
399 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_SetTemplate")]
400 public static extern void LLM_SetTemplateStatic(IntPtr LLMObject, string chatTemplate);
401 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_SetSSL")]
402 public static extern void LLM_SetSSLStatic(IntPtr LLMObject, string SSLCert, string SSLKey);
403 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Tokenize")]
404 public static extern void LLM_TokenizeStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
405 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Detokenize")]
406 public static extern void LLM_DetokenizeStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
407 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Embeddings")]
408 public static extern void LLM_EmbeddingsStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
409 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Lora_Weight")]
410 public static extern void LLM_LoraWeightStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
411 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Lora_List")]
412 public static extern void LLM_LoraListStatic(IntPtr LLMObject, IntPtr stringWrapper);
413 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Completion")]
414 public static extern void LLM_CompletionStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
415 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Slot")]
416 public static extern void LLM_SlotStatic(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
417 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Cancel")]
418 public static extern void LLM_CancelStatic(IntPtr LLMObject, int idSlot);
419 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="LLM_Status")]
420 public static extern int LLM_StatusStatic(IntPtr LLMObject, IntPtr stringWrapper);
421 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StringWrapper_Construct")]
422 public static extern IntPtr StringWrapper_ConstructStatic();
423 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StringWrapper_Delete")]
424 public static extern void StringWrapper_DeleteStatic(IntPtr instance);
425 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StringWrapper_GetStringSize")]
426 public static extern int StringWrapper_GetStringSizeStatic(IntPtr instance);
427 [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint="StringWrapper_GetString")]
428 public static extern void StringWrapper_GetStringStatic(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false);
429
430 public void Logging(IntPtr stringWrapper){ LoggingStatic(stringWrapper); }
431 public void StopLogging(){ StopLoggingStatic(); }
432 public IntPtr LLM_Construct(string command){ return LLM_ConstructStatic(command); }
433 public void LLM_Delete(IntPtr LLMObject){ LLM_DeleteStatic(LLMObject); }
434 public void LLM_StartServer(IntPtr LLMObject){ LLM_StartServerStatic(LLMObject); }
435 public void LLM_StopServer(IntPtr LLMObject){ LLM_StopServerStatic(LLMObject); }
436 public void LLM_Start(IntPtr LLMObject){ LLM_StartStatic(LLMObject); }
437 public bool LLM_Started(IntPtr LLMObject){ return LLM_StartedStatic(LLMObject); }
438 public void LLM_Stop(IntPtr LLMObject){ LLM_StopStatic(LLMObject); }
439 public void LLM_SetTemplate(IntPtr LLMObject, string chatTemplate){ LLM_SetTemplateStatic(LLMObject, chatTemplate); }
440 public void LLM_SetSSL(IntPtr LLMObject, string SSLCert, string SSLKey){ LLM_SetSSLStatic(LLMObject, SSLCert, SSLKey); }
441 public void LLM_Tokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_TokenizeStatic(LLMObject, jsonData, stringWrapper); }
442 public void LLM_Detokenize(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_DetokenizeStatic(LLMObject, jsonData, stringWrapper); }
443 public void LLM_Embeddings(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_EmbeddingsStatic(LLMObject, jsonData, stringWrapper); }
444 public void LLM_LoraWeight(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_LoraWeightStatic(LLMObject, jsonData, stringWrapper); }
445 public void LLM_LoraList(IntPtr LLMObject, IntPtr stringWrapper){ LLM_LoraListStatic(LLMObject, stringWrapper); }
446 public void LLM_Completion(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_CompletionStatic(LLMObject, jsonData, stringWrapper); }
447 public void LLM_Slot(IntPtr LLMObject, string jsonData, IntPtr stringWrapper){ LLM_SlotStatic(LLMObject, jsonData, stringWrapper); }
448 public void LLM_Cancel(IntPtr LLMObject, int idSlot){ LLM_CancelStatic(LLMObject, idSlot); }
449 public int LLM_Status(IntPtr LLMObject, IntPtr stringWrapper){ return LLM_StatusStatic(LLMObject, stringWrapper); }
450 public IntPtr StringWrapper_Construct(){ return StringWrapper_ConstructStatic(); }
451 public void StringWrapper_Delete(IntPtr instance){ StringWrapper_DeleteStatic(instance); }
452 public int StringWrapper_GetStringSize(IntPtr instance){ return StringWrapper_GetStringSizeStatic(instance); }
453 public void StringWrapper_GetString(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false){ StringWrapper_GetStringStatic(instance, buffer, bufferSize, clear); }
454
455#else
456
457 static bool has_avx_set = false;
458 static readonly object staticLock = new object();
459
460 static LLMLib()
461 {
462 lock (staticLock)
463 {
464 if (has_avx_set) return;
465 string archCheckerPath = GetArchitectureCheckerPath();
466 if (archCheckerPath != null)
467 {
468 IntPtr archCheckerHandle = LibraryLoader.LoadLibrary(archCheckerPath);
469 if (archCheckerHandle == IntPtr.Zero)
470 {
471 LLMUnitySetup.LogError($"Failed to load library {archCheckerPath}.");
472 }
473 else
474 {
475 try
476 {
477 has_avx = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx")();
478 has_avx2 = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx2")();
479 has_avx512 = LibraryLoader.GetSymbolDelegate<HasArchDelegate>(archCheckerHandle, "has_avx512")();
480 LibraryLoader.FreeLibrary(archCheckerHandle);
481 }
482 catch (Exception e)
483 {
484 LLMUnitySetup.LogError($"{e.GetType()}: {e.Message}");
485 }
486 }
487 }
488 has_avx_set = true;
489 }
490 }
491
497 public LLMLib(string arch)
498 {
499 libraryHandle = LibraryLoader.LoadLibrary(GetArchitecturePath(arch));
500 if (libraryHandle == IntPtr.Zero)
501 {
502 throw new Exception($"Failed to load library {arch}.");
503 }
504
505 LLM_Construct = LibraryLoader.GetSymbolDelegate<LLM_ConstructDelegate>(libraryHandle, "LLM_Construct");
506 LLM_Delete = LibraryLoader.GetSymbolDelegate<LLM_DeleteDelegate>(libraryHandle, "LLM_Delete");
507 LLM_StartServer = LibraryLoader.GetSymbolDelegate<LLM_StartServerDelegate>(libraryHandle, "LLM_StartServer");
508 LLM_StopServer = LibraryLoader.GetSymbolDelegate<LLM_StopServerDelegate>(libraryHandle, "LLM_StopServer");
509 LLM_Start = LibraryLoader.GetSymbolDelegate<LLM_StartDelegate>(libraryHandle, "LLM_Start");
510 LLM_Started = LibraryLoader.GetSymbolDelegate<LLM_StartedDelegate>(libraryHandle, "LLM_Started");
511 LLM_Stop = LibraryLoader.GetSymbolDelegate<LLM_StopDelegate>(libraryHandle, "LLM_Stop");
512 LLM_SetTemplate = LibraryLoader.GetSymbolDelegate<LLM_SetTemplateDelegate>(libraryHandle, "LLM_SetTemplate");
513 LLM_SetSSL = LibraryLoader.GetSymbolDelegate<LLM_SetSSLDelegate>(libraryHandle, "LLM_SetSSL");
514 LLM_Tokenize = LibraryLoader.GetSymbolDelegate<LLM_TokenizeDelegate>(libraryHandle, "LLM_Tokenize");
515 LLM_Detokenize = LibraryLoader.GetSymbolDelegate<LLM_DetokenizeDelegate>(libraryHandle, "LLM_Detokenize");
516 LLM_Embeddings = LibraryLoader.GetSymbolDelegate<LLM_EmbeddingsDelegate>(libraryHandle, "LLM_Embeddings");
517 LLM_LoraWeight = LibraryLoader.GetSymbolDelegate<LLM_LoraWeightDelegate>(libraryHandle, "LLM_Lora_Weight");
518 LLM_LoraList = LibraryLoader.GetSymbolDelegate<LLM_LoraListDelegate>(libraryHandle, "LLM_Lora_List");
519 LLM_Completion = LibraryLoader.GetSymbolDelegate<LLM_CompletionDelegate>(libraryHandle, "LLM_Completion");
520 LLM_Slot = LibraryLoader.GetSymbolDelegate<LLM_SlotDelegate>(libraryHandle, "LLM_Slot");
521 LLM_Cancel = LibraryLoader.GetSymbolDelegate<LLM_CancelDelegate>(libraryHandle, "LLM_Cancel");
522 LLM_Status = LibraryLoader.GetSymbolDelegate<LLM_StatusDelegate>(libraryHandle, "LLM_Status");
523 StringWrapper_Construct = LibraryLoader.GetSymbolDelegate<StringWrapper_ConstructDelegate>(libraryHandle, "StringWrapper_Construct");
524 StringWrapper_Delete = LibraryLoader.GetSymbolDelegate<StringWrapper_DeleteDelegate>(libraryHandle, "StringWrapper_Delete");
525 StringWrapper_GetStringSize = LibraryLoader.GetSymbolDelegate<StringWrapper_GetStringSizeDelegate>(libraryHandle, "StringWrapper_GetStringSize");
526 StringWrapper_GetString = LibraryLoader.GetSymbolDelegate<StringWrapper_GetStringDelegate>(libraryHandle, "StringWrapper_GetString");
527 Logging = LibraryLoader.GetSymbolDelegate<LoggingDelegate>(libraryHandle, "Logging");
528 StopLogging = LibraryLoader.GetSymbolDelegate<StopLoggingDelegate>(libraryHandle, "StopLogging");
529 }
530
535 public static string GetArchitectureCheckerPath()
536 {
537 string filename;
538 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
539 {
540 filename = $"windows-archchecker/archchecker.dll";
541 }
542 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
543 {
544 filename = $"linux-archchecker/libarchchecker.so";
545 }
546 else
547 {
548 return null;
549 }
550 return Path.Combine(LLMUnitySetup.libraryPath, filename);
551 }
552
558 public static string GetArchitecturePath(string arch)
559 {
560 string filename;
561 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer)
562 {
563 filename = $"windows-{arch}/undreamai_windows-{arch}.dll";
564 }
565 else if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
566 {
567 filename = $"linux-{arch}/libundreamai_linux-{arch}.so";
568 }
569 else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXServer)
570 {
571 filename = $"macos-{arch}/libundreamai_macos-{arch}.dylib";
572 }
573 else
574 {
575 string error = "Unknown OS";
576 LLMUnitySetup.LogError(error);
577 throw new Exception(error);
578 }
579 return Path.Combine(LLMUnitySetup.libraryPath, filename);
580 }
581
582 public delegate bool HasArchDelegate();
583 public delegate void LoggingDelegate(IntPtr stringWrapper);
584 public delegate void StopLoggingDelegate();
585 public delegate IntPtr LLM_ConstructDelegate(string command);
586 public delegate void LLM_DeleteDelegate(IntPtr LLMObject);
587 public delegate void LLM_StartServerDelegate(IntPtr LLMObject);
588 public delegate void LLM_StopServerDelegate(IntPtr LLMObject);
589 public delegate void LLM_StartDelegate(IntPtr LLMObject);
590 public delegate bool LLM_StartedDelegate(IntPtr LLMObject);
591 public delegate void LLM_StopDelegate(IntPtr LLMObject);
592 public delegate void LLM_SetTemplateDelegate(IntPtr LLMObject, string chatTemplate);
593 public delegate void LLM_SetSSLDelegate(IntPtr LLMObject, string SSLCert, string SSLKey);
594 public delegate void LLM_TokenizeDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
595 public delegate void LLM_DetokenizeDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
596 public delegate void LLM_EmbeddingsDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
597 public delegate void LLM_LoraWeightDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
598 public delegate void LLM_LoraListDelegate(IntPtr LLMObject, IntPtr stringWrapper);
599 public delegate void LLM_CompletionDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
600 public delegate void LLM_SlotDelegate(IntPtr LLMObject, string jsonData, IntPtr stringWrapper);
601 public delegate void LLM_CancelDelegate(IntPtr LLMObject, int idSlot);
602 public delegate int LLM_StatusDelegate(IntPtr LLMObject, IntPtr stringWrapper);
603 public delegate IntPtr StringWrapper_ConstructDelegate();
604 public delegate void StringWrapper_DeleteDelegate(IntPtr instance);
605 public delegate int StringWrapper_GetStringSizeDelegate(IntPtr instance);
606 public delegate void StringWrapper_GetStringDelegate(IntPtr instance, IntPtr buffer, int bufferSize, bool clear = false);
607
608 public LoggingDelegate Logging;
609 public StopLoggingDelegate StopLogging;
610 public LLM_ConstructDelegate LLM_Construct;
611 public LLM_DeleteDelegate LLM_Delete;
612 public LLM_StartServerDelegate LLM_StartServer;
613 public LLM_StopServerDelegate LLM_StopServer;
614 public LLM_StartDelegate LLM_Start;
615 public LLM_StartedDelegate LLM_Started;
616 public LLM_StopDelegate LLM_Stop;
617 public LLM_SetTemplateDelegate LLM_SetTemplate;
618 public LLM_SetSSLDelegate LLM_SetSSL;
619 public LLM_TokenizeDelegate LLM_Tokenize;
620 public LLM_DetokenizeDelegate LLM_Detokenize;
621 public LLM_CompletionDelegate LLM_Completion;
622 public LLM_EmbeddingsDelegate LLM_Embeddings;
623 public LLM_LoraWeightDelegate LLM_LoraWeight;
624 public LLM_LoraListDelegate LLM_LoraList;
625 public LLM_SlotDelegate LLM_Slot;
626 public LLM_CancelDelegate LLM_Cancel;
627 public LLM_StatusDelegate LLM_Status;
628 public StringWrapper_ConstructDelegate StringWrapper_Construct;
629 public StringWrapper_DeleteDelegate StringWrapper_Delete;
630 public StringWrapper_GetStringSizeDelegate StringWrapper_GetStringSize;
631 public StringWrapper_GetStringDelegate StringWrapper_GetString;
632
633#endif
634
640 public static List<string> PossibleArchitectures(bool gpu = false)
641 {
642 List<string> architectures = new List<string>();
643 if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsServer ||
644 Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxServer)
645 {
646 if (gpu)
647 {
648 if (LLMUnitySetup.FullLlamaLib)
649 {
650 architectures.Add("cuda-cu12.2.0-full");
651 architectures.Add("cuda-cu11.7.1-full");
652 }
653 else
654 {
655 architectures.Add("cuda-cu12.2.0");
656 architectures.Add("cuda-cu11.7.1");
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
690 {
691 string error = "Unknown OS";
692 LLMUnitySetup.LogError(error);
693 throw new Exception(error);
694 }
695 return architectures;
696 }
697
703 public string GetStringWrapperResult(IntPtr stringWrapper)
704 {
705 string result = "";
706 int bufferSize = StringWrapper_GetStringSize(stringWrapper);
707 if (bufferSize > 1)
708 {
709 IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
710 try
711 {
712 StringWrapper_GetString(stringWrapper, buffer, bufferSize);
713 result = Marshal.PtrToStringAnsi(buffer);
714 }
715 finally
716 {
717 Marshal.FreeHGlobal(buffer);
718 }
719 }
720 return result;
721 }
722
726 public void Destroy()
727 {
728 if (libraryHandle != IntPtr.Zero) LibraryLoader.FreeLibrary(libraryHandle);
729 }
730 }
731
732}