From 45b6c8e408b7afdefcbed7d61d8a87e01bee4259 Mon Sep 17 00:00:00 2001 From: Jhen-Jie Hong Date: Wed, 5 Feb 2025 16:03:21 +0800 Subject: [PATCH 1/5] feat(android): listen native logs --- .../main/java/com/rnllama/LlamaContext.java | 28 ++++++- .../src/main/java/com/rnllama/RNLlama.java | 26 +++++++ android/src/main/jni.cpp | 77 ++++++++++++++++--- .../java/com/rnllama/RNLlamaModule.java | 5 ++ .../java/com/rnllama/RNLlamaModule.java | 5 ++ example/src/App.tsx | 1 + src/NativeRNLlama.ts | 1 + src/index.ts | 25 +++++- 8 files changed, 154 insertions(+), 14 deletions(-) diff --git a/android/src/main/java/com/rnllama/LlamaContext.java b/android/src/main/java/com/rnllama/LlamaContext.java index 0cfa4b29..56ce6566 100644 --- a/android/src/main/java/com/rnllama/LlamaContext.java +++ b/android/src/main/java/com/rnllama/LlamaContext.java @@ -23,6 +23,14 @@ public class LlamaContext { private static String loadedLibrary = ""; + static void toggleNativeLog(ReactApplicationContext reactContext, boolean enabled) { + if (enabled) { + setupLog(new NativeLogCallback(reactContext)); + } else { + unsetLog(); + } + } + private int id; private ReactApplicationContext reactContext; private long context; @@ -37,8 +45,6 @@ public LlamaContext(int id, ReactApplicationContext reactContext, ReadableMap pa if (!params.hasKey("model")) { throw new IllegalArgumentException("Missing required parameter: model"); } - Log.d(NAME, "Setting log callback"); - logToAndroid(); eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); this.id = id; this.context = initContext( @@ -130,6 +136,21 @@ public String getFormattedChat(String messages, String chatTemplate) { return getFormattedChat(this.context, messages, chatTemplate == null ? "" : chatTemplate); } + private static class NativeLogCallback { + DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter; + + public NativeLogCallback(ReactApplicationContext reactContext) { + this.eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); + } + + void emitNativeLog(String level, String message) { + WritableMap event = Arguments.createMap(); + event.putString("level", level); + event.putString("message", message); + eventEmitter.emit("@RNLlama_onNativeLog", event); + } + } + private void emitLoadProgress(int progress) { WritableMap event = Arguments.createMap(); event.putInt("contextId", LlamaContext.this.id); @@ -539,5 +560,6 @@ protected static native WritableMap embedding( protected static native void removeLoraAdapters(long contextPtr); protected static native WritableArray getLoadedLoraAdapters(long contextPtr); protected static native void freeContext(long contextPtr); - protected static native void logToAndroid(); + protected static native void setupLog(NativeLogCallback logCallback); + protected static native void unsetLog(); } diff --git a/android/src/main/java/com/rnllama/RNLlama.java b/android/src/main/java/com/rnllama/RNLlama.java index aa9bda2c..29592c6f 100644 --- a/android/src/main/java/com/rnllama/RNLlama.java +++ b/android/src/main/java/com/rnllama/RNLlama.java @@ -35,6 +35,32 @@ public RNLlama(ReactApplicationContext reactContext) { private HashMap contexts = new HashMap<>(); + public void toggleNativeLog(boolean enabled, Promise promise) { + new AsyncTask() { + private Exception exception; + + @Override + protected Boolean doInBackground(Void... voids) { + try { + LlamaContext.toggleNativeLog(reactContext, enabled); + return true; + } catch (Exception e) { + exception = e; + } + return null; + } + + @Override + protected void onPostExecute(Boolean result) { + if (exception != null) { + promise.reject(exception); + return; + } + promise.resolve(result); + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + private int llamaContextLimit = -1; public void setContextLimit(double limit, Promise promise) { diff --git a/android/src/main/jni.cpp b/android/src/main/jni.cpp index 934b4b2d..0ddceba7 100644 --- a/android/src/main/jni.cpp +++ b/android/src/main/jni.cpp @@ -24,13 +24,6 @@ static inline int min(int a, int b) { return (a < b) ? a : b; } -static void log_callback(lm_ggml_log_level level, const char * fmt, void * data) { - if (level == LM_GGML_LOG_LEVEL_ERROR) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, data); - else if (level == LM_GGML_LOG_LEVEL_INFO) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, data); - else if (level == LM_GGML_LOG_LEVEL_WARN) __android_log_print(ANDROID_LOG_WARN, TAG, fmt, data); - else __android_log_print(ANDROID_LOG_DEFAULT, TAG, fmt, data); -} - extern "C" { // Method to create WritableMap @@ -1110,11 +1103,77 @@ Java_com_rnllama_LlamaContext_freeContext( delete llama; } +struct log_callback_context { + JavaVM *jvm; + jobject callback; +}; + +static void rnllama_log_callback(lm_ggml_log_level level, const char * fmt, void * data) { + auto level_c = ""; + if (level == LM_GGML_LOG_LEVEL_ERROR) { + level_c = "error"; + __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, data); + } else if (level == LM_GGML_LOG_LEVEL_INFO) { + level_c = "info"; + __android_log_print(ANDROID_LOG_INFO, TAG, fmt, data); + } else if (level == LM_GGML_LOG_LEVEL_WARN) { + level_c = "warn"; + __android_log_print(ANDROID_LOG_WARN, TAG, fmt, data); + } else { + __android_log_print(ANDROID_LOG_DEFAULT, TAG, fmt, data); + } + + log_callback_context *cb_ctx = (log_callback_context *) data; + + JNIEnv *env; + bool need_detach = false; + int getEnvResult = cb_ctx->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); + + if (getEnvResult == JNI_EDETACHED) { + if (cb_ctx->jvm->AttachCurrentThread(&env, nullptr) == JNI_OK) { + need_detach = true; + } else { + return; + } + } else if (getEnvResult != JNI_OK) { + return; + } + + jobject callback = cb_ctx->callback; + jclass cb_class = env->GetObjectClass(callback); + jmethodID emitNativeLog = env->GetMethodID(cb_class, "emitNativeLog", "(Ljava/lang/String;Ljava/lang/String;)V"); + + jstring level_str = env->NewStringUTF(level_c); + jstring fmt_str = env->NewStringUTF(fmt); + env->CallVoidMethod(callback, emitNativeLog, level_str, fmt_str); + env->DeleteLocalRef(level_str); + env->DeleteLocalRef(fmt_str); + + if (need_detach) { + cb_ctx->jvm->DetachCurrentThread(); + } +} + +JNIEXPORT void JNICALL +Java_com_rnllama_LlamaContext_setupLog(JNIEnv *env, jobject thiz, jobject logCallback) { + UNUSED(thiz); + + log_callback_context *cb_ctx = new log_callback_context; + + JavaVM *jvm; + env->GetJavaVM(&jvm); + cb_ctx->jvm = jvm; + + cb_ctx->callback = env->NewGlobalRef(logCallback); + + llama_log_set(rnllama_log_callback, cb_ctx); +} + JNIEXPORT void JNICALL -Java_com_rnllama_LlamaContext_logToAndroid(JNIEnv *env, jobject thiz) { +Java_com_rnllama_LlamaContext_unsetLog(JNIEnv *env, jobject thiz) { UNUSED(env); UNUSED(thiz); - llama_log_set(log_callback, NULL); + llama_log_set(llama_log_callback_default, NULL); } } // extern "C" diff --git a/android/src/newarch/java/com/rnllama/RNLlamaModule.java b/android/src/newarch/java/com/rnllama/RNLlamaModule.java index 1943a6d3..405100b8 100644 --- a/android/src/newarch/java/com/rnllama/RNLlamaModule.java +++ b/android/src/newarch/java/com/rnllama/RNLlamaModule.java @@ -32,6 +32,11 @@ public String getName() { return NAME; } + @ReactMethod + public void toggleNativeLog(boolean enabled, Promise promise) { + rnllama.toggleNativeLog(enabled, promise); + } + @ReactMethod public void setContextLimit(double limit, Promise promise) { rnllama.setContextLimit(limit, promise); diff --git a/android/src/oldarch/java/com/rnllama/RNLlamaModule.java b/android/src/oldarch/java/com/rnllama/RNLlamaModule.java index 68c39458..bc9873f2 100644 --- a/android/src/oldarch/java/com/rnllama/RNLlamaModule.java +++ b/android/src/oldarch/java/com/rnllama/RNLlamaModule.java @@ -33,6 +33,11 @@ public String getName() { return NAME; } + @ReactMethod + public void toggleNativeLog(boolean enabled, Promise promise) { + rnllama.toggleNativeLog(enabled, promise); + } + @ReactMethod public void setContextLimit(double limit, Promise promise) { rnllama.setContextLimit(limit, promise); diff --git a/example/src/App.tsx b/example/src/App.tsx index 6f9f11c3..ba92ae75 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -130,6 +130,7 @@ export default function App() { initLlama( { model: file.uri, + n_ctx: 200, use_mlock: true, n_gpu_layers: Platform.OS === 'ios' ? 99 : 0, // > 0: enable GPU diff --git a/src/NativeRNLlama.ts b/src/NativeRNLlama.ts index b7ba5736..8052dfc0 100644 --- a/src/NativeRNLlama.ts +++ b/src/NativeRNLlama.ts @@ -299,6 +299,7 @@ export type NativeLlamaChatMessage = { } export interface Spec extends TurboModule { + toggleNativeLog(enabled: boolean): Promise setContextLimit(limit: number): Promise modelInfo(path: string, skip?: string[]): Promise diff --git a/src/index.ts b/src/index.ts index e92b00b4..029f4545 100644 --- a/src/index.ts +++ b/src/index.ts @@ -44,6 +44,7 @@ export { SchemaGrammarConverter, convertJsonSchemaToGrammar } const EVENT_ON_INIT_CONTEXT_PROGRESS = '@RNLlama_onInitContextProgress' const EVENT_ON_TOKEN = '@RNLlama_onToken' +const EVENT_ON_NATIVE_LOG = '@RNLlama_onNativeLog' let EventEmitter: NativeEventEmitter | DeviceEventEmitterStatic if (Platform.OS === 'ios') { @@ -54,6 +55,21 @@ if (Platform.OS === 'android') { EventEmitter = DeviceEventEmitter } +// @ts-ignore +if (EventEmitter) { + EventEmitter.addListener( + EVENT_ON_NATIVE_LOG, + (evt: { level: string; message: string }) => { + console.log( + ...['[rnllama]', evt.level ? `[${evt.level}]` : '', evt.message].filter( + Boolean, + ), + ) + }, + ) + RNLlama?.toggleNativeLog?.(true) +} + export type TokenData = { token: string completion_probabilities?: Array @@ -92,7 +108,7 @@ export type ContextParams = Omit< export type EmbeddingParams = NativeEmbeddingParams export type CompletionResponseFormat = { - type: 'text' | 'json_object' | 'json_schema', + type: 'text' | 'json_object' | 'json_schema' json_schema?: { strict?: boolean schema: object @@ -114,7 +130,8 @@ export type CompletionBaseParams = { export type CompletionParams = Omit< NativeCompletionParams, 'emit_partial_completion' | 'prompt' -> & CompletionBaseParams +> & + CompletionBaseParams export type BenchResult = { modelDesc: string @@ -359,6 +376,10 @@ export class LlamaContext { } } +export async function toggleNativeLog(enabled: boolean): Promise { + return RNLlama.toggleNativeLog(enabled) +} + export async function setContextLimit(limit: number): Promise { return RNLlama.setContextLimit(limit) } From aaf9f50f6cb77ca2603954b4f838755f45c6f9cd Mon Sep 17 00:00:00 2001 From: Jhen-Jie Hong Date: Wed, 5 Feb 2025 16:49:01 +0800 Subject: [PATCH 2/5] feat(ts): add addLogListener method --- example/src/App.tsx | 9 ++++++++- src/index.ts | 19 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/example/src/App.tsx b/example/src/App.tsx index ba92ae75..ce675064 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -12,10 +12,17 @@ import type { LlamaContext } from 'llama.rn' import { initLlama, loadLlamaModelInfo, + addNativeLogListener, // eslint-disable-next-line import/no-unresolved } from 'llama.rn' import { Bubble } from './Bubble' +addNativeLogListener((level, message) => { + console.log( + ['[rnllama]', level ? `[${level}]` : '', message].filter(Boolean).join(' '), + ) +}) + const { dirs } = ReactNativeBlobUtil.fs // Example grammar for output JSON @@ -415,7 +422,7 @@ export default function App() { required: ['function', 'arguments'], }, ], - } + }, }, } // Comment to test: diff --git a/src/index.ts b/src/index.ts index 029f4545..a714fbea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -55,16 +55,14 @@ if (Platform.OS === 'android') { EventEmitter = DeviceEventEmitter } +const logListeners: Array<(level: string, message: string) => void> = [] + // @ts-ignore if (EventEmitter) { EventEmitter.addListener( EVENT_ON_NATIVE_LOG, (evt: { level: string; message: string }) => { - console.log( - ...['[rnllama]', evt.level ? `[${evt.level}]` : '', evt.message].filter( - Boolean, - ), - ) + logListeners.forEach((listener) => listener(evt.level, evt.message)) }, ) RNLlama?.toggleNativeLog?.(true) @@ -380,6 +378,17 @@ export async function toggleNativeLog(enabled: boolean): Promise { return RNLlama.toggleNativeLog(enabled) } +export function addNativeLogListener( + listener: (level: string, message: string) => void, +): { remove: () => void } { + logListeners.push(listener) + return { + remove: () => { + logListeners.splice(logListeners.indexOf(listener), 1) + }, + } +} + export async function setContextLimit(limit: number): Promise { return RNLlama.setContextLimit(limit) } From 2c097fb160d860548aba98d4ba52df3161ee2088 Mon Sep 17 00:00:00 2001 From: Jhen-Jie Hong Date: Wed, 5 Feb 2025 16:53:25 +0800 Subject: [PATCH 3/5] docs(api): build --- docs/API/README.md | 98 ++++++++++++++----- docs/API/classes/LlamaContext.md | 40 ++++---- docs/API/classes/SchemaGrammarConverter.md | 32 +++--- .../SchemaGrammarConverterBuiltinRule.md | 6 +- 4 files changed, 112 insertions(+), 64 deletions(-) diff --git a/docs/API/README.md b/docs/API/README.md index 2572148c..52908673 100644 --- a/docs/API/README.md +++ b/docs/API/README.md @@ -39,11 +39,13 @@ llama.rn ### Functions +- [addNativeLogListener](README.md#addnativeloglistener) - [convertJsonSchemaToGrammar](README.md#convertjsonschematogrammar) - [initLlama](README.md#initllama) - [loadLlamaModelInfo](README.md#loadllamamodelinfo) - [releaseAllLlama](README.md#releaseallllama) - [setContextLimit](README.md#setcontextlimit) +- [toggleNativeLog](README.md#togglenativelog) ## Type Aliases @@ -65,7 +67,7 @@ llama.rn #### Defined in -[index.ts:118](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L118) +[index.ts:134](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L134) ___ @@ -78,6 +80,7 @@ ___ | Name | Type | | :------ | :------ | | `chatTemplate?` | `string` | +| `chat_template?` | `string` | | `jinja?` | `boolean` | | `messages?` | [`RNLlamaOAICompatibleMessage`](README.md#rnllamaoaicompatiblemessage)[] | | `parallel_tool_calls?` | `object` | @@ -88,7 +91,7 @@ ___ #### Defined in -[index.ts:103](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L103) +[index.ts:117](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L117) ___ @@ -98,7 +101,7 @@ ___ #### Defined in -[index.ts:113](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L113) +[index.ts:128](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L128) ___ @@ -118,7 +121,7 @@ ___ #### Defined in -[index.ts:94](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L94) +[index.ts:108](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L108) ___ @@ -128,7 +131,7 @@ ___ #### Defined in -[index.ts:67](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L67) +[index.ts:81](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L81) ___ @@ -138,7 +141,7 @@ ___ #### Defined in -[index.ts:92](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L92) +[index.ts:106](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L106) ___ @@ -187,7 +190,7 @@ ___ #### Defined in -[NativeRNLlama.ts:61](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L61) +[NativeRNLlama.ts:66](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L66) ___ @@ -213,7 +216,7 @@ ___ #### Defined in -[NativeRNLlama.ts:220](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L220) +[NativeRNLlama.ts:225](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L225) ___ @@ -236,7 +239,7 @@ ___ #### Defined in -[NativeRNLlama.ts:209](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L209) +[NativeRNLlama.ts:214](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L214) ___ @@ -253,7 +256,7 @@ ___ #### Defined in -[NativeRNLlama.ts:204](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L204) +[NativeRNLlama.ts:209](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L209) ___ @@ -270,7 +273,7 @@ ___ #### Defined in -[NativeRNLlama.ts:199](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L199) +[NativeRNLlama.ts:204](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L204) ___ @@ -284,6 +287,7 @@ ___ | :------ | :------ | :------ | | `cache_type_k?` | `string` | KV cache data type for the K (Experimental in llama.cpp) | | `cache_type_v?` | `string` | KV cache data type for the V (Experimental in llama.cpp) | +| `chat_template?` | `string` | Chat template to override the default one from the model. | | `embd_normalize?` | `number` | - | | `embedding?` | `boolean` | - | | `flash_attn?` | `boolean` | Enable flash attention, only recommended in GPU device (Experimental in llama.cpp) | @@ -307,7 +311,7 @@ ___ #### Defined in -[NativeRNLlama.ts:8](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L8) +[NativeRNLlama.ts:8](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L8) ___ @@ -323,7 +327,7 @@ ___ #### Defined in -[NativeRNLlama.ts:4](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L4) +[NativeRNLlama.ts:4](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L4) ___ @@ -339,7 +343,7 @@ ___ #### Defined in -[NativeRNLlama.ts:240](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L240) +[NativeRNLlama.ts:245](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L245) ___ @@ -384,7 +388,7 @@ ___ #### Defined in -[NativeRNLlama.ts:244](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L244) +[NativeRNLlama.ts:249](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L249) ___ @@ -401,7 +405,7 @@ ___ #### Defined in -[NativeRNLlama.ts:285](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L285) +[NativeRNLlama.ts:291](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L291) ___ @@ -417,7 +421,7 @@ ___ #### Defined in -[NativeRNLlama.ts:236](https://github.com/mybigday/llama.rn/blob/877054a/src/NativeRNLlama.ts#L236) +[NativeRNLlama.ts:241](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/NativeRNLlama.ts#L241) ___ @@ -433,7 +437,7 @@ ___ #### Defined in -[chat.ts:3](https://github.com/mybigday/llama.rn/blob/877054a/src/chat.ts#L3) +[chat.ts:3](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/chat.ts#L3) ___ @@ -450,7 +454,7 @@ ___ #### Defined in -[chat.ts:7](https://github.com/mybigday/llama.rn/blob/877054a/src/chat.ts#L7) +[chat.ts:7](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/chat.ts#L7) ___ @@ -467,10 +471,34 @@ ___ #### Defined in -[index.ts:57](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L57) +[index.ts:71](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L71) ## Functions +### addNativeLogListener + +▸ **addNativeLogListener**(`listener`): `Object` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `listener` | (`level`: `string`, `message`: `string`) => `void` | + +#### Returns + +`Object` + +| Name | Type | +| :------ | :------ | +| `remove` | () => `void` | + +#### Defined in + +[index.ts:381](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L381) + +___ + ### convertJsonSchemaToGrammar ▸ **convertJsonSchemaToGrammar**(`«destructured»`): `string` \| `Promise`<`string`\> @@ -491,7 +519,7 @@ ___ #### Defined in -[grammar.ts:829](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L829) +[grammar.ts:829](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L829) ___ @@ -512,7 +540,7 @@ ___ #### Defined in -[index.ts:390](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L390) +[index.ts:421](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L421) ___ @@ -532,7 +560,7 @@ ___ #### Defined in -[index.ts:375](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L375) +[index.ts:406](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L406) ___ @@ -546,7 +574,7 @@ ___ #### Defined in -[index.ts:456](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L456) +[index.ts:487](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L487) ___ @@ -566,4 +594,24 @@ ___ #### Defined in -[index.ts:361](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L361) +[index.ts:392](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L392) + +___ + +### toggleNativeLog + +▸ **toggleNativeLog**(`enabled`): `Promise`<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `enabled` | `boolean` | + +#### Returns + +`Promise`<`void`\> + +#### Defined in + +[index.ts:377](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L377) diff --git a/docs/API/classes/LlamaContext.md b/docs/API/classes/LlamaContext.md index de8addea..0ece94d8 100644 --- a/docs/API/classes/LlamaContext.md +++ b/docs/API/classes/LlamaContext.md @@ -47,7 +47,7 @@ #### Defined in -[index.ts:160](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L160) +[index.ts:176](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L176) ## Properties @@ -57,7 +57,7 @@ #### Defined in -[index.ts:154](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L154) +[index.ts:170](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L170) ___ @@ -67,7 +67,7 @@ ___ #### Defined in -[index.ts:152](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L152) +[index.ts:168](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L168) ___ @@ -107,7 +107,7 @@ ___ #### Defined in -[index.ts:158](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L158) +[index.ts:174](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L174) ___ @@ -117,7 +117,7 @@ ___ #### Defined in -[index.ts:156](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L156) +[index.ts:172](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L172) ## Methods @@ -137,7 +137,7 @@ ___ #### Defined in -[index.ts:334](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L334) +[index.ts:350](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L350) ___ @@ -160,7 +160,7 @@ ___ #### Defined in -[index.ts:314](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L314) +[index.ts:330](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L330) ___ @@ -181,7 +181,7 @@ ___ #### Defined in -[index.ts:222](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L222) +[index.ts:238](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L238) ___ @@ -201,7 +201,7 @@ ___ #### Defined in -[index.ts:303](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L303) +[index.ts:319](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L319) ___ @@ -222,7 +222,7 @@ ___ #### Defined in -[index.ts:307](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L307) +[index.ts:323](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L323) ___ @@ -249,7 +249,7 @@ ___ #### Defined in -[index.ts:195](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L195) +[index.ts:211](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L211) ___ @@ -263,7 +263,7 @@ ___ #### Defined in -[index.ts:350](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L350) +[index.ts:366](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L366) ___ @@ -277,7 +277,7 @@ ___ #### Defined in -[index.ts:190](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L190) +[index.ts:206](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L206) ___ @@ -291,7 +291,7 @@ ___ #### Defined in -[index.ts:186](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L186) +[index.ts:202](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L202) ___ @@ -313,7 +313,7 @@ Load cached prompt & completion state from a file. #### Defined in -[index.ts:170](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L170) +[index.ts:186](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L186) ___ @@ -327,7 +327,7 @@ ___ #### Defined in -[index.ts:356](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L356) +[index.ts:372](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L372) ___ @@ -341,7 +341,7 @@ ___ #### Defined in -[index.ts:346](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L346) +[index.ts:362](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L362) ___ @@ -365,7 +365,7 @@ Save current cached prompt & completion state to a file. #### Defined in -[index.ts:179](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L179) +[index.ts:195](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L195) ___ @@ -379,7 +379,7 @@ ___ #### Defined in -[index.ts:295](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L295) +[index.ts:311](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L311) ___ @@ -399,4 +399,4 @@ ___ #### Defined in -[index.ts:299](https://github.com/mybigday/llama.rn/blob/877054a/src/index.ts#L299) +[index.ts:315](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/index.ts#L315) diff --git a/docs/API/classes/SchemaGrammarConverter.md b/docs/API/classes/SchemaGrammarConverter.md index dd39840e..e9a7c459 100644 --- a/docs/API/classes/SchemaGrammarConverter.md +++ b/docs/API/classes/SchemaGrammarConverter.md @@ -46,7 +46,7 @@ #### Defined in -[grammar.ts:216](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L216) +[grammar.ts:216](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L216) ## Properties @@ -56,7 +56,7 @@ #### Defined in -[grammar.ts:206](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L206) +[grammar.ts:206](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L206) ___ @@ -66,7 +66,7 @@ ___ #### Defined in -[grammar.ts:208](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L208) +[grammar.ts:208](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L208) ___ @@ -76,7 +76,7 @@ ___ #### Defined in -[grammar.ts:204](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L204) +[grammar.ts:204](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L204) ___ @@ -90,7 +90,7 @@ ___ #### Defined in -[grammar.ts:212](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L212) +[grammar.ts:212](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L212) ___ @@ -100,7 +100,7 @@ ___ #### Defined in -[grammar.ts:214](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L214) +[grammar.ts:214](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L214) ___ @@ -114,7 +114,7 @@ ___ #### Defined in -[grammar.ts:210](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L210) +[grammar.ts:210](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L210) ## Methods @@ -135,7 +135,7 @@ ___ #### Defined in -[grammar.ts:698](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L698) +[grammar.ts:698](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L698) ___ @@ -156,7 +156,7 @@ ___ #### Defined in -[grammar.ts:229](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L229) +[grammar.ts:229](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L229) ___ @@ -179,7 +179,7 @@ ___ #### Defined in -[grammar.ts:715](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L715) +[grammar.ts:715](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L715) ___ @@ -200,7 +200,7 @@ ___ #### Defined in -[grammar.ts:317](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L317) +[grammar.ts:317](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L317) ___ @@ -220,7 +220,7 @@ ___ #### Defined in -[grammar.ts:523](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L523) +[grammar.ts:523](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L523) ___ @@ -241,7 +241,7 @@ ___ #### Defined in -[grammar.ts:328](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L328) +[grammar.ts:328](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L328) ___ @@ -255,7 +255,7 @@ ___ #### Defined in -[grammar.ts:818](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L818) +[grammar.ts:818](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L818) ___ @@ -276,7 +276,7 @@ ___ #### Defined in -[grammar.ts:252](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L252) +[grammar.ts:252](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L252) ___ @@ -297,4 +297,4 @@ ___ #### Defined in -[grammar.ts:534](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L534) +[grammar.ts:534](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L534) diff --git a/docs/API/classes/SchemaGrammarConverterBuiltinRule.md b/docs/API/classes/SchemaGrammarConverterBuiltinRule.md index 46ed1636..13bc7db2 100644 --- a/docs/API/classes/SchemaGrammarConverterBuiltinRule.md +++ b/docs/API/classes/SchemaGrammarConverterBuiltinRule.md @@ -28,7 +28,7 @@ #### Defined in -[grammar.ts:85](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L85) +[grammar.ts:85](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L85) ## Properties @@ -38,7 +38,7 @@ #### Defined in -[grammar.ts:81](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L81) +[grammar.ts:81](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L81) ___ @@ -48,4 +48,4 @@ ___ #### Defined in -[grammar.ts:83](https://github.com/mybigday/llama.rn/blob/877054a/src/grammar.ts#L83) +[grammar.ts:83](https://github.com/mybigday/llama.rn/blob/aaf9f50/src/grammar.ts#L83) From ea7e945431cecddfe7d250d6fabe0ff1975eb3f7 Mon Sep 17 00:00:00 2001 From: Jhen-Jie Hong Date: Thu, 6 Feb 2025 10:58:43 +0800 Subject: [PATCH 4/5] feat(android): use default log_callback --- .../main/java/com/rnllama/LlamaContext.java | 30 +++++++++---------- android/src/main/jni.cpp | 28 ++++++++++------- example/src/App.tsx | 6 ++-- src/index.ts | 10 +++---- 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/android/src/main/java/com/rnllama/LlamaContext.java b/android/src/main/java/com/rnllama/LlamaContext.java index 56ce6566..54543120 100644 --- a/android/src/main/java/com/rnllama/LlamaContext.java +++ b/android/src/main/java/com/rnllama/LlamaContext.java @@ -23,6 +23,21 @@ public class LlamaContext { private static String loadedLibrary = ""; + private static class NativeLogCallback { + DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter; + + public NativeLogCallback(ReactApplicationContext reactContext) { + this.eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); + } + + void emitNativeLog(String level, String text) { + WritableMap event = Arguments.createMap(); + event.putString("level", level); + event.putString("text", text); + eventEmitter.emit("@RNLlama_onNativeLog", event); + } + } + static void toggleNativeLog(ReactApplicationContext reactContext, boolean enabled) { if (enabled) { setupLog(new NativeLogCallback(reactContext)); @@ -136,21 +151,6 @@ public String getFormattedChat(String messages, String chatTemplate) { return getFormattedChat(this.context, messages, chatTemplate == null ? "" : chatTemplate); } - private static class NativeLogCallback { - DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter; - - public NativeLogCallback(ReactApplicationContext reactContext) { - this.eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); - } - - void emitNativeLog(String level, String message) { - WritableMap event = Arguments.createMap(); - event.putString("level", level); - event.putString("message", message); - eventEmitter.emit("@RNLlama_onNativeLog", event); - } - } - private void emitLoadProgress(int progress) { WritableMap event = Arguments.createMap(); event.putInt("contextId", LlamaContext.this.id); diff --git a/android/src/main/jni.cpp b/android/src/main/jni.cpp index 0ddceba7..02d3abaa 100644 --- a/android/src/main/jni.cpp +++ b/android/src/main/jni.cpp @@ -24,6 +24,13 @@ static inline int min(int a, int b) { return (a < b) ? a : b; } +static void rnllama_log_callback_default(lm_ggml_log_level level, const char * fmt, void * data) { + if (level == LM_GGML_LOG_LEVEL_ERROR) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, data); + else if (level == LM_GGML_LOG_LEVEL_INFO) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, data); + else if (level == LM_GGML_LOG_LEVEL_WARN) __android_log_print(ANDROID_LOG_WARN, TAG, fmt, data); + else __android_log_print(ANDROID_LOG_DEFAULT, TAG, fmt, data); +} + extern "C" { // Method to create WritableMap @@ -1108,19 +1115,19 @@ struct log_callback_context { jobject callback; }; -static void rnllama_log_callback(lm_ggml_log_level level, const char * fmt, void * data) { +static void rnllama_log_callback_to_j(lm_ggml_log_level level, const char * text, void * data) { auto level_c = ""; if (level == LM_GGML_LOG_LEVEL_ERROR) { + __android_log_print(ANDROID_LOG_ERROR, TAG, text, nullptr); level_c = "error"; - __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, data); } else if (level == LM_GGML_LOG_LEVEL_INFO) { + __android_log_print(ANDROID_LOG_INFO, TAG, text, nullptr); level_c = "info"; - __android_log_print(ANDROID_LOG_INFO, TAG, fmt, data); } else if (level == LM_GGML_LOG_LEVEL_WARN) { + __android_log_print(ANDROID_LOG_WARN, TAG, text, nullptr); level_c = "warn"; - __android_log_print(ANDROID_LOG_WARN, TAG, fmt, data); } else { - __android_log_print(ANDROID_LOG_DEFAULT, TAG, fmt, data); + __android_log_print(ANDROID_LOG_DEFAULT, TAG, text, nullptr); } log_callback_context *cb_ctx = (log_callback_context *) data; @@ -1144,10 +1151,10 @@ static void rnllama_log_callback(lm_ggml_log_level level, const char * fmt, void jmethodID emitNativeLog = env->GetMethodID(cb_class, "emitNativeLog", "(Ljava/lang/String;Ljava/lang/String;)V"); jstring level_str = env->NewStringUTF(level_c); - jstring fmt_str = env->NewStringUTF(fmt); - env->CallVoidMethod(callback, emitNativeLog, level_str, fmt_str); + jstring text_str = env->NewStringUTF(text); + env->CallVoidMethod(callback, emitNativeLog, level_str, text_str); env->DeleteLocalRef(level_str); - env->DeleteLocalRef(fmt_str); + env->DeleteLocalRef(text_str); if (need_detach) { cb_ctx->jvm->DetachCurrentThread(); @@ -1163,17 +1170,16 @@ Java_com_rnllama_LlamaContext_setupLog(JNIEnv *env, jobject thiz, jobject logCal JavaVM *jvm; env->GetJavaVM(&jvm); cb_ctx->jvm = jvm; - cb_ctx->callback = env->NewGlobalRef(logCallback); - llama_log_set(rnllama_log_callback, cb_ctx); + llama_log_set(rnllama_log_callback_to_j, cb_ctx); } JNIEXPORT void JNICALL Java_com_rnllama_LlamaContext_unsetLog(JNIEnv *env, jobject thiz) { UNUSED(env); UNUSED(thiz); - llama_log_set(llama_log_callback_default, NULL); + llama_log_set(rnllama_log_callback_default, NULL); } } // extern "C" diff --git a/example/src/App.tsx b/example/src/App.tsx index ce675064..77205325 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -12,14 +12,16 @@ import type { LlamaContext } from 'llama.rn' import { initLlama, loadLlamaModelInfo, + toggleNativeLog, addNativeLogListener, // eslint-disable-next-line import/no-unresolved } from 'llama.rn' import { Bubble } from './Bubble' -addNativeLogListener((level, message) => { +toggleNativeLog(true) +addNativeLogListener((level, text) => { console.log( - ['[rnllama]', level ? `[${level}]` : '', message].filter(Boolean).join(' '), + ['[rnllama]', level ? `[${level}]` : '', text].filter(Boolean).join(' '), ) }) diff --git a/src/index.ts b/src/index.ts index a714fbea..f313fdd7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -55,17 +55,17 @@ if (Platform.OS === 'android') { EventEmitter = DeviceEventEmitter } -const logListeners: Array<(level: string, message: string) => void> = [] +const logListeners: Array<(level: string, text: string) => void> = [] // @ts-ignore if (EventEmitter) { EventEmitter.addListener( EVENT_ON_NATIVE_LOG, - (evt: { level: string; message: string }) => { - logListeners.forEach((listener) => listener(evt.level, evt.message)) + (evt: { level: string; text: string }) => { + logListeners.forEach((listener) => listener(evt.level, evt.text)) }, ) - RNLlama?.toggleNativeLog?.(true) + RNLlama?.toggleNativeLog?.(false) // Trigger unset to use default log callback } export type TokenData = { @@ -379,7 +379,7 @@ export async function toggleNativeLog(enabled: boolean): Promise { } export function addNativeLogListener( - listener: (level: string, message: string) => void, + listener: (level: string, text: string) => void, ): { remove: () => void } { logListeners.push(listener) return { From a9dc12bfbcc2663cc7c8c5faa6240e14bc4f8b3a Mon Sep 17 00:00:00 2001 From: Jhen-Jie Hong Date: Thu, 6 Feb 2025 11:51:25 +0800 Subject: [PATCH 5/5] feat(ios): impl toggleNativeLog --- ios/RNLlama.h | 8 -------- ios/RNLlama.mm | 13 ++++++++++++- ios/RNLlamaContext.h | 1 + ios/RNLlamaContext.mm | 27 +++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/ios/RNLlama.h b/ios/RNLlama.h index e58cf614..db735792 100644 --- a/ios/RNLlama.h +++ b/ios/RNLlama.h @@ -1,11 +1,3 @@ -#ifdef __cplusplus -#if RNLLAMA_BUILD_FROM_SOURCE -#import "rn-llama.h" -#else -#import -#endif -#endif - #import #import diff --git a/ios/RNLlama.mm b/ios/RNLlama.mm index 91de6498..cdd89b4e 100644 --- a/ios/RNLlama.mm +++ b/ios/RNLlama.mm @@ -13,6 +13,16 @@ @implementation RNLlama RCT_EXPORT_MODULE() +RCT_EXPORT_METHOD(toggleNativeLog:(BOOL)enabled) { + void (^onEmitLog)(NSString *level, NSString *text) = nil; + if (enabled) { + onEmitLog = ^(NSString *level, NSString *text) { + [self sendEventWithName:@"@RNLlama_onNativeLog" body:@{ @"level": level, @"text": text }]; + }; + } + [RNLlamaContext toggleNativeLog:enabled onEmitLog:onEmitLog]; +} + RCT_EXPORT_METHOD(setContextLimit:(double)limit withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) @@ -41,7 +51,7 @@ @implementation RNLlama } if (llamaDQueue == nil) { - llamaDQueue = dispatch_queue_create("com.rnllama", DISPATCH_QUEUE_SERIAL); + llamaDQueue = dispatch_queue_create("com.rnllama", DISPATCH_QUEUE_SERIAL); } if (llamaContexts == nil) { @@ -159,6 +169,7 @@ - (NSArray *)supportedEvents { return@[ @"@RNLlama_onInitContextProgress", @"@RNLlama_onToken", + @"@RNLlama_onNativeLog", ]; } diff --git a/ios/RNLlamaContext.h b/ios/RNLlamaContext.h index 937b6d64..63380187 100644 --- a/ios/RNLlamaContext.h +++ b/ios/RNLlamaContext.h @@ -25,6 +25,7 @@ rnllama::llama_rn_context * llama; } ++ (void)toggleNativeLog:(BOOL)enabled onEmitLog:(void (^)(NSString *level, NSString *text))onEmitLog; + (NSDictionary *)modelInfo:(NSString *)path skip:(NSArray *)skip; + (instancetype)initWithParams:(NSDictionary *)params onProgress:(void (^)(unsigned int progress))onProgress; - (void)interruptLoad; diff --git a/ios/RNLlamaContext.mm b/ios/RNLlamaContext.mm index 6d4d2294..873a2cc6 100644 --- a/ios/RNLlamaContext.mm +++ b/ios/RNLlamaContext.mm @@ -3,6 +3,33 @@ @implementation RNLlamaContext ++ (void)toggleNativeLog:(BOOL)enabled onEmitLog:(void (^)(NSString *level, NSString *text))onEmitLog { + if (enabled) { + void (^copiedBlock)(NSString *, NSString *) = [onEmitLog copy]; + llama_log_set([](lm_ggml_log_level level, const char * text, void * data) { + llama_log_callback_default(level, text, data); + NSString *levelStr = @""; + if (level == LM_GGML_LOG_LEVEL_ERROR) { + levelStr = @"error"; + } else if (level == LM_GGML_LOG_LEVEL_INFO) { + levelStr = @"info"; + } else if (level == LM_GGML_LOG_LEVEL_WARN) { + levelStr = @"warn"; + } + + NSString *textStr = [NSString stringWithUTF8String:text]; + // NOTE: Convert to UTF-8 string may fail + if (!textStr) { + return; + } + void (^block)(NSString *, NSString *) = (__bridge void (^)(NSString *, NSString *))(data); + block(levelStr, textStr); + }, copiedBlock); + } else { + llama_log_set(llama_log_callback_default, nullptr); + } +} + + (NSDictionary *)modelInfo:(NSString *)path skip:(NSArray *)skip { struct lm_gguf_init_params params = { /*.no_alloc = */ false,