Abrarul8541 commited on
Commit
7f3c389
·
verified ·
1 Parent(s): 77afceb

Phase 3: JNI bridge to llama.cpp (load, streaming generate, free)

Browse files
Files changed (1) hide show
  1. app/src/main/cpp/llama_jni.cpp +94 -0
app/src/main/cpp/llama_jni.cpp ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <jni.h>
2
+ #include <string>
3
+ #include <vector>
4
+ #include "llama.h"
5
+
6
+ struct State {
7
+ llama_model *model;
8
+ llama_context *ctx;
9
+ };
10
+
11
+ extern "C" JNIEXPORT jlong JNICALL
12
+ Java_io_github_abrarul_modularai_engine_LlamaEngine_nativeLoad(JNIEnv *env, jobject, jstring path,
13
+ jint nCtx, jint threads) {
14
+ llama_backend_init();
15
+ const char *p = env->GetStringUTFChars(path, nullptr);
16
+ llama_model_params mp = llama_model_default_params();
17
+ llama_model *m = llama_model_load_from_file(p, mp);
18
+ env->ReleaseStringUTFChars(path, p);
19
+ if (!m) return 0;
20
+
21
+ llama_context_params cp = llama_context_default_params();
22
+ cp.n_ctx = nCtx;
23
+ cp.n_batch = nCtx;
24
+ cp.n_ubatch = 512;
25
+ cp.n_threads = threads;
26
+ cp.n_threads_batch = threads;
27
+ llama_context *c = llama_init_from_model(m, cp);
28
+ if (!c) {
29
+ llama_model_free(m);
30
+ return 0;
31
+ }
32
+ return reinterpret_cast<jlong>(new State{m, c});
33
+ }
34
+
35
+ extern "C" JNIEXPORT void JNICALL
36
+ Java_io_github_abrarul_modularai_engine_LlamaEngine_nativeGenerate(JNIEnv *env, jobject, jlong h,
37
+ jstring prompt, jint maxTokens,
38
+ jfloat temp, jobject sink) {
39
+ auto *s = reinterpret_cast<State *>(h);
40
+ if (!s) return;
41
+ const llama_vocab *vocab = llama_model_get_vocab(s->model);
42
+
43
+ const char *pr = env->GetStringUTFChars(prompt, nullptr);
44
+ std::string text(pr);
45
+ env->ReleaseStringUTFChars(prompt, pr);
46
+
47
+ llama_memory_clear(llama_get_memory(s->ctx), true);
48
+
49
+ int n = -llama_tokenize(vocab, text.c_str(), (int) text.size(), nullptr, 0, true, true);
50
+ if (n <= 0 || n >= (int) llama_n_ctx(s->ctx)) return; // empty or does not fit the context
51
+ std::vector<llama_token> toks(n);
52
+ if (llama_tokenize(vocab, text.c_str(), (int) text.size(), toks.data(), n, true, true) < 0) return;
53
+
54
+ llama_sampler *smpl = llama_sampler_chain_init(llama_sampler_chain_default_params());
55
+ if (temp > 0.0f) {
56
+ llama_sampler_chain_add(smpl, llama_sampler_init_top_p(0.9f, 1));
57
+ llama_sampler_chain_add(smpl, llama_sampler_init_temp(temp));
58
+ llama_sampler_chain_add(smpl, llama_sampler_init_dist(LLAMA_DEFAULT_SEED));
59
+ } else {
60
+ llama_sampler_chain_add(smpl, llama_sampler_init_greedy());
61
+ }
62
+
63
+ jclass cls = env->GetObjectClass(sink);
64
+ jmethodID mid = env->GetMethodID(cls, "onToken", "([B)Z");
65
+
66
+ llama_token tok; // must outlive the loop body: the batch points at it
67
+ llama_batch batch = llama_batch_get_one(toks.data(), (int) toks.size());
68
+ for (int i = 0; i < maxTokens; i++) {
69
+ if (llama_decode(s->ctx, batch) != 0) break;
70
+ tok = llama_sampler_sample(smpl, s->ctx, -1);
71
+ if (llama_vocab_is_eog(vocab, tok)) break;
72
+
73
+ char buf[256];
74
+ int len = llama_token_to_piece(vocab, tok, buf, sizeof(buf), 0, true);
75
+ if (len < 0) break;
76
+ jbyteArray arr = env->NewByteArray(len);
77
+ env->SetByteArrayRegion(arr, 0, len, reinterpret_cast<const jbyte *>(buf));
78
+ jboolean cont = env->CallBooleanMethod(sink, mid, arr);
79
+ env->DeleteLocalRef(arr);
80
+ if (!cont || env->ExceptionCheck()) break;
81
+
82
+ batch = llama_batch_get_one(&tok, 1);
83
+ }
84
+ llama_sampler_free(smpl);
85
+ }
86
+
87
+ extern "C" JNIEXPORT void JNICALL
88
+ Java_io_github_abrarul_modularai_engine_LlamaEngine_nativeFree(JNIEnv *, jobject, jlong h) {
89
+ auto *s = reinterpret_cast<State *>(h);
90
+ if (!s) return;
91
+ llama_free(s->ctx);
92
+ llama_model_free(s->model);
93
+ delete s;
94
+ }