view release on metacpan or search on metacpan
lib/Lugh.xs view on Meta::CPAN
int
backend_device_count()
CODE:
/* Return count of available devices */
RETVAL = (int)ggml_backend_dev_count();
OUTPUT:
RETVAL
void
available_backends()
PPCODE:
{
size_t i, count;
/* Always include "auto" option */
count = ggml_backend_reg_count();
EXTEND(SP, count + 1);
/* List all registered backends by name */
for (i = 0; i < count; i++) {
ggml_backend_reg_t reg = ggml_backend_reg_get(i);
const char *name = ggml_backend_reg_name(reg);
lib/Lugh.xs view on Meta::CPAN
RETVAL
void
forward(self, ...)
SV *self
PREINIT:
HV *hv;
LughForwardOpts opts;
LughForwardResult result;
int i, j;
PPCODE:
hv = (HV*)SvRV(self);
Zero(&opts, 1, LughForwardOpts);
/* Parse named parameters: forward(tokens => \@t, lora => $l, ...) */
parse_forward_options(aTHX_ &opts, &ST(0), 1, items);
if (!opts.tokens && !opts.all_tokens) {
croak("forward() requires tokens => \\@tokens");
}
lib/Lugh.xs view on Meta::CPAN
void
forward_simple(self, tokens_ref)
SV *self
SV *tokens_ref
PREINIT:
HV *hv;
LughForwardOpts opts;
LughForwardResult result;
int j;
PPCODE:
if (!SvROK(tokens_ref) || SvTYPE(SvRV(tokens_ref)) != SVt_PVAV) {
croak("forward_simple() requires an array reference");
}
hv = (HV*)SvRV(self);
Zero(&opts, 1, LughForwardOpts);
opts.tokens = parse_tokens_av(aTHX_ (AV*)SvRV(tokens_ref), &opts.n_tokens);
if (!do_forward_unified(aTHX_ hv, &opts, &result)) {
char *err = result.error ? result.error : "Forward pass failed";
lib/Lugh.xs view on Meta::CPAN
free_forward_result(&result);
void
forward_cache(self, ...)
SV *self
PREINIT:
HV *hv;
LughForwardOpts opts;
LughForwardResult result;
int j;
PPCODE:
hv = (HV*)SvRV(self);
Zero(&opts, 1, LughForwardOpts);
/* Detect positional: forward_cache($cache, \@tokens, ...) */
if (items >= 3 && sv_isobject(ST(1)) && SvROK(ST(2)) && SvTYPE(SvRV(ST(2))) == SVt_PVAV) {
opts.cache = get_lugh_kvcache(aTHX_ ST(1));
opts.tokens = parse_tokens_av(aTHX_ (AV*)SvRV(ST(2)), &opts.n_tokens);
/* Parse remaining as named params */
parse_forward_options(aTHX_ &opts, &ST(0), 3, items);
} else {
lib/Lugh.xs view on Meta::CPAN
void
forward_pool(self, ...)
SV *self
PREINIT:
HV *hv;
LughForwardOpts opts;
LughForwardResult result;
int j;
SV **svp;
PPCODE:
hv = (HV*)SvRV(self);
Zero(&opts, 1, LughForwardOpts);
/* Detect positional: forward_pool($pool, \@tokens, ...) */
if (items >= 3 && sv_isobject(ST(1)) && SvROK(ST(2)) && SvTYPE(SvRV(ST(2))) == SVt_PVAV) {
SV *pool_sv = ST(1);
if (SvROK(pool_sv) && SvTYPE(SvRV(pool_sv)) == SVt_PVHV) {
HV *pool_hv = (HV*)SvRV(pool_sv);
svp = hv_fetch(pool_hv, "_pool_id", 8, 0);
if (svp && *svp) opts.pool = get_mempool_by_id(SvIV(*svp));
lib/Lugh.xs view on Meta::CPAN
free_forward_result(&result);
void
forward_batch(self, ...)
SV *self
PREINIT:
HV *hv;
LughForwardOpts opts;
LughForwardResult result;
int i, j;
PPCODE:
hv = (HV*)SvRV(self);
Zero(&opts, 1, LughForwardOpts);
/* Detect positional: forward_batch(\@sequences, ...) */
if (items >= 2 && SvROK(ST(1)) && SvTYPE(SvRV(ST(1))) == SVt_PVAV) {
if (!parse_sequences_av(aTHX_ (AV*)SvRV(ST(1)), &opts.all_tokens, &opts.seq_lengths, &opts.n_sequences)) {
croak("Invalid sequences format");
}
/* Parse remaining as named params */
parse_forward_options(aTHX_ &opts, &ST(0), 2, items);
lib/Lugh.xs view on Meta::CPAN
void
forward_cache_pool(self, ...)
SV *self
PREINIT:
HV *hv;
LughForwardOpts opts;
LughForwardResult result;
int j;
SV **svp;
PPCODE:
hv = (HV*)SvRV(self);
Zero(&opts, 1, LughForwardOpts);
/* Detect positional: forward_cache_pool($cache, $pool, \@tokens, ...) */
if (items >= 4 && sv_isobject(ST(1)) && sv_isobject(ST(2)) &&
SvROK(ST(3)) && SvTYPE(SvRV(ST(3))) == SVt_PVAV) {
opts.cache = get_lugh_kvcache(aTHX_ ST(1));
SV *pool_sv = ST(2);
if (SvROK(pool_sv) && SvTYPE(SvRV(pool_sv)) == SVt_PVHV) {
HV *pool_hv = (HV*)SvRV(pool_sv);
lib/Lugh.xs view on Meta::CPAN
void
forward_batch_pool(self, ...)
SV *self
PREINIT:
HV *hv;
LughForwardOpts opts;
LughForwardResult result;
int i, j;
SV **svp;
PPCODE:
hv = (HV*)SvRV(self);
Zero(&opts, 1, LughForwardOpts);
/* Detect positional: forward_batch_pool($pool, \@sequences, ...) */
if (items >= 3 && sv_isobject(ST(1)) && SvROK(ST(2)) && SvTYPE(SvRV(ST(2))) == SVt_PVAV) {
SV *pool_sv = ST(1);
if (SvROK(pool_sv) && SvTYPE(SvRV(pool_sv)) == SVt_PVHV) {
HV *pool_hv = (HV*)SvRV(pool_sv);
svp = hv_fetch(pool_hv, "_pool_id", 8, 0);
if (svp && *svp) opts.pool = get_mempool_by_id(SvIV(*svp));
lib/Lugh.xs view on Meta::CPAN
int max_tokens = 128;
float temperature = 0.8f;
float top_p = 0.95f;
int top_k = 40;
int eos_token = 2;
int greedy = 0;
SV *callback = NULL;
int i;
int n_result;
SV **orig_sp;
PPCODE:
orig_sp = SP; /* Save original stack pointer */
/* Get model */
hv = (HV*)SvRV(self);
svp = hv_fetch(hv, "_model", 6, 0);
if (!svp || !*svp) croak("No model in inference object");
model = get_lugh_model(aTHX_ *svp);
if (!model) croak("Invalid model");
/* Parse input tokens */
lib/Lugh.xs view on Meta::CPAN
SV **svp;
HV *token_to_id;
AV *id_to_token;
const char *str;
STRLEN len;
AV *tokens;
int add_bos = 1;
int bos_id, eos_id, unk_id;
size_t pos;
int i;
PPCODE:
hv = (HV*)SvRV(self);
svp = hv_fetch(hv, "_token_to_id", 12, 0);
if (!svp || !SvROK(*svp)) croak("Tokenizer not initialized");
token_to_id = (HV*)SvRV(*svp);
svp = hv_fetch(hv, "_id_to_token", 12, 0);
if (!svp || !SvROK(*svp)) croak("Tokenizer not initialized");
id_to_token = (AV*)SvRV(*svp);
lib/Lugh.xs view on Meta::CPAN
for (i = 0; i < n_elements; i++) {
ggml_set_f32_1d(tensor, i, SvNV(ST(i + 1)));
}
void
get_f32(self)
SV *self
PREINIT:
struct ggml_tensor *tensor;
int64_t i, n_elements;
PPCODE:
tensor = INT2PTR(struct ggml_tensor *, SvIV(SvRV(self)));
n_elements = ggml_nelements(tensor);
EXTEND(SP, n_elements);
for (i = 0; i < n_elements; i++) {
mPUSHn(ggml_get_f32_1d(tensor, i));
}
int64_t
nelements(self)
lib/Lugh.xs view on Meta::CPAN
RETVAL = ggml_n_dims(tensor);
OUTPUT:
RETVAL
void
shape(self)
SV *self
PREINIT:
struct ggml_tensor *tensor;
int i, n_dims;
PPCODE:
tensor = INT2PTR(struct ggml_tensor *, SvIV(SvRV(self)));
n_dims = ggml_n_dims(tensor);
EXTEND(SP, n_dims);
for (i = 0; i < n_dims; i++) {
mPUSHi(tensor->ne[i]);
}
int
type(self)
lib/Lugh.xs view on Meta::CPAN
OUTPUT:
RETVAL
void
tensor_info(self, name)
SV *self
const char *name
PREINIT:
LughModel *lm;
struct ggml_tensor *t;
PPCODE:
lm = get_lugh_model(aTHX_ self);
t = ggml_get_tensor(lm->ctx, name);
if (t) {
/* Return: type, n_dims, ne[0], ne[1], ne[2], ne[3] */
EXTEND(SP, 6);
mPUSHi(t->type);
mPUSHi(ggml_n_dims(t));
mPUSHi(t->ne[0]);
mPUSHi(t->ne[1]);
mPUSHi(t->ne[2]);
mPUSHi(t->ne[3]);
}
void
tensor_names(self)
SV *self
PREINIT:
LughModel *lm;
int64_t i;
PPCODE:
lm = get_lugh_model(aTHX_ self);
EXTEND(SP, lm->n_tensors);
for (i = 0; i < lm->n_tensors; i++) {
mPUSHs(newSVpv(gguf_get_tensor_name(lm->gguf, i), 0));
}
void
kv_keys(self)
SV *self
PREINIT:
LughModel *lm;
int64_t i;
PPCODE:
lm = get_lugh_model(aTHX_ self);
EXTEND(SP, lm->n_kv);
for (i = 0; i < lm->n_kv; i++) {
mPUSHs(newSVpv(gguf_get_key(lm->gguf, i), 0));
}
SV *
get_kv(self, key)
SV *self
const char *key
lib/Lugh.xs view on Meta::CPAN
OUTPUT:
RETVAL
void
weight_names(self)
SV *self
PREINIT:
LughLoRAAdapter *lora;
MAGIC *mg;
int i;
PPCODE:
if (!SvROK(self)) croak("Not a reference");
mg = mg_findext(SvRV(self), PERL_MAGIC_ext, &lugh_lora_vtbl);
if (!mg) croak("Invalid LoRA object");
lora = get_lora_by_id((int)(IV)mg->mg_ptr);
if (!lora) croak("LoRA adapter not found");
EXTEND(SP, lora->n_weights);
for (i = 0; i < lora->n_weights; i++) {
mPUSHp(lora->weights[i].name, strlen(lora->weights[i].name));
}
lib/Lugh.xs view on Meta::CPAN
void
trainable_parameters(self)
SV *self
PREINIT:
LughLoRAAdapter *lora;
LughTensor *lt;
MAGIC *mg;
int i, count = 0;
HV *result_hv;
PPCODE:
if (!SvROK(self)) croak("Not a reference");
mg = mg_findext(SvRV(self), PERL_MAGIC_ext, &lugh_lora_vtbl);
if (!mg) croak("Invalid LoRA object");
lora = get_lora_by_id((int)(IV)mg->mg_ptr);
if (!lora) croak("LoRA adapter not found");
if (!lora->trainable) {
croak("trainable_parameters() only available for trainable LoRA adapters (created with create())");
}
lib/Lugh.xs view on Meta::CPAN
SV *self
SV *input_tokens_ref
int n_draft
PREINIT:
HV *hv;
SV **svp;
LughSpeculative *spec;
AV *input_av, *draft_av;
int i, n_input;
int *input_tokens;
PPCODE:
if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVHV)
croak("Invalid Lugh::Speculative object");
hv = (HV*)SvRV(self);
svp = hv_fetch(hv, "_spec_id", 8, 0);
if (!svp) croak("Invalid Lugh::Speculative object");
spec = get_speculative_by_id(SvIV(*svp));
if (!spec) croak("Speculative decoder has been destroyed");
if (!SvROK(input_tokens_ref) || SvTYPE(SvRV(input_tokens_ref)) != SVt_PVAV)
lib/Lugh.xs view on Meta::CPAN
SV *self
SV *input_tokens_ref
SV *draft_tokens_ref
PREINIT:
HV *hv;
SV **svp;
LughSpeculative *spec;
AV *input_av, *draft_av_in, *accepted_av;
int i, n_input, n_draft;
int *input_tokens, *draft_tokens;
PPCODE:
if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVHV)
croak("Invalid Lugh::Speculative object");
hv = (HV*)SvRV(self);
svp = hv_fetch(hv, "_spec_id", 8, 0);
if (!svp) croak("Invalid Lugh::Speculative object");
spec = get_speculative_by_id(SvIV(*svp));
if (!spec) croak("Speculative decoder has been destroyed");
if (!SvROK(input_tokens_ref) || SvTYPE(SvRV(input_tokens_ref)) != SVt_PVAV)
lib/Lugh.xs view on Meta::CPAN
step(self, input_tokens_ref)
SV *self
SV *input_tokens_ref
PREINIT:
HV *hv;
SV **svp;
LughSpeculative *spec;
AV *input_av, *accepted_av;
int *input_tokens;
int n_input, i;
PPCODE:
if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVHV)
croak("Invalid Lugh::Speculative object");
hv = (HV*)SvRV(self);
svp = hv_fetch(hv, "_spec_id", 8, 0);
if (!svp) croak("Invalid Lugh::Speculative object");
spec = get_speculative_by_id(SvIV(*svp));
if (!spec) croak("Speculative decoder has been destroyed");
if (!SvROK(input_tokens_ref) || SvTYPE(SvRV(input_tokens_ref)) != SVt_PVAV)
lib/Lugh.xs view on Meta::CPAN
SV *input_tokens_ref
int max_tokens
PREINIT:
HV *hv;
SV **svp;
LughSpeculative *spec;
AV *input_av, *output_av, *accepted_av;
int *current_tokens;
int n_current, n_generated;
int i;
PPCODE:
if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVHV)
croak("Invalid Lugh::Speculative object");
hv = (HV*)SvRV(self);
svp = hv_fetch(hv, "_spec_id", 8, 0);
if (!svp) croak("Invalid Lugh::Speculative object");
spec = get_speculative_by_id(SvIV(*svp));
if (!spec) croak("Speculative decoder has been destroyed");
if (!SvROK(input_tokens_ref) || SvTYPE(SvRV(input_tokens_ref)) != SVt_PVAV)
lib/Lugh.xs view on Meta::CPAN
}
void
get_data(self)
SV *self
PREINIT:
HV *hv;
SV **svp;
LughTensor *lt;
int64_t i, n_elements;
PPCODE:
if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVHV)
croak("Invalid Lugh::Autograd::Tensor object");
hv = (HV*)SvRV(self);
svp = hv_fetch(hv, "_tensor_id", 10, 0);
if (!svp) croak("Invalid tensor object");
lt = get_tensor_by_id(SvIV(*svp));
if (!lt) croak("Tensor has been freed");
n_elements = ggml_nelements(lt->tensor);
EXTEND(SP, n_elements);
lib/Lugh.xs view on Meta::CPAN
RETVAL
void
shape(self)
SV *self
PREINIT:
HV *hv;
SV **svp;
LughTensor *lt;
int i, n_dims;
PPCODE:
if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVHV)
croak("Invalid Lugh::Autograd::Tensor object");
hv = (HV*)SvRV(self);
svp = hv_fetch(hv, "_tensor_id", 10, 0);
if (!svp) croak("Invalid tensor object");
lt = get_tensor_by_id(SvIV(*svp));
if (!lt) croak("Tensor has been freed");
n_dims = ggml_n_dims(lt->tensor);
EXTEND(SP, n_dims);
lib/Lugh.xs view on Meta::CPAN
void
batch_data(class, data_av, ...)
SV* class
AV* data_av
PREINIT:
STRLEN batch_size = 32;
int shuffle = 0;
STRLEN data_len, i, j;
STRLEN *indices = NULL;
AV *result_av;
PPCODE:
PERL_UNUSED_VAR(class);
/* Parse optional args - items includes class and data_av, so remaining must be even */
if (items > 2) {
if ((items - 2) % 2 != 0) croak("Expected key-value pairs after data");
for (i = 2; i < (STRLEN)items; i += 2) {
const char *key = SvPV_nolen(ST(i));
SV *val = ST(i + 1);
if (strEQ(key, "batch_size")) {
batch_size = SvIV(val);
lib/Lugh.xs view on Meta::CPAN
tokenize_batch(class, tokenizer, texts_av, ...)
SV* class
SV* tokenizer
AV* texts_av
PREINIT:
STRLEN max_length = 512;
STRLEN i, n_texts;
AV *all_input_ids;
AV *all_targets;
AV *result;
PPCODE:
PERL_UNUSED_VAR(class);
if (!tokenizer || !SvOK(tokenizer)) {
croak("tokenizer required");
}
/* Parse optional args */
if (items > 3) {
for (i = 3; i < (STRLEN)items; i += 2) {
const char *key = SvPV_nolen(ST(i));
lib/Lugh.xs view on Meta::CPAN
/* Return (\@all_input_ids, \@all_targets) */
EXTEND(SP, 2);
PUSHs(sv_2mortal(newRV_noinc((SV*)all_input_ids)));
PUSHs(sv_2mortal(newRV_noinc((SV*)all_targets)));
void
zero_grad(class, ...)
SV* class
PREINIT:
STRLEN i;
PPCODE:
PERL_UNUSED_VAR(class);
for (i = 1; i < (STRLEN)items; i++) {
SV *tensor_sv = ST(i);
if (!SvOK(tensor_sv)) continue;
dSP;
ENTER;
SAVETMPS;
lib/Lugh.xs view on Meta::CPAN
void
clip_grad_norm(class, max_norm, ...)
SV* class
float max_norm
PREINIT:
float total_norm = 0.0f;
float clip_coef;
STRLEN i;
AV* tensors_av = NULL;
AV* all_grads = NULL;
PPCODE:
PERL_UNUSED_VAR(class);
if (max_norm <= 0) {
croak("max_norm must be positive");
}
/* Collect all gradient data */
all_grads = newAV();
for (i = 2; i < (STRLEN)items; i++) {
lib/Lugh.xs view on Meta::CPAN
/* Return total norm (before clipping) */
EXTEND(SP, 1);
mPUSHn(total_norm);
void
clip_grad_value(class, max_value, ...)
SV* class
float max_value
PREINIT:
STRLEN i;
PPCODE:
PERL_UNUSED_VAR(class);
if (max_value <= 0) {
croak("max_value must be positive");
}
for (i = 2; i < (STRLEN)items; i++) {
SV *tensor_sv = ST(i);
if (!SvOK(tensor_sv)) continue;
if (!SvROK(tensor_sv) || SvTYPE(SvRV(tensor_sv)) != SVt_PVHV) continue;
lib/Lugh/Prompt.xs view on Meta::CPAN
}
RETVAL = newSVpv(buf.data, buf.len);
strbuf_free(&buf);
OUTPUT:
RETVAL
# Return list of available format names
void
available_formats(...)
PPCODE:
int i;
for (i = 0; FORMATS[i].name != NULL; i++) {
mXPUSHs(newSVpv(FORMATS[i].name, 0));
}
# Get format name for architecture
SV*
format_for_architecture(...)
CODE:
const char* arch_str = NULL;
lib/Lugh/Quant.xs view on Meta::CPAN
type_count()
CODE:
RETVAL = GGML_TYPE_COUNT;
OUTPUT:
RETVAL
void
all_types()
PREINIT:
int i;
PPCODE:
EXTEND(SP, GGML_TYPE_COUNT);
for (i = 0; i < GGML_TYPE_COUNT; i++) {
const char *name = ggml_type_name((enum ggml_type)i);
if (name && strlen(name) > 0) {
mPUSHi(i);
}
}
void
all_quantized_types()
PREINIT:
int i;
PPCODE:
for (i = 0; i < GGML_TYPE_COUNT; i++) {
if (ggml_is_quantized((enum ggml_type)i)) {
XPUSHs(sv_2mortal(newSViv(i)));
}
}
int
type_from_name(name)
const char *name
CODE: