mirror of
https://github.com/ggerganov/whisper.cpp.git
synced 2025-06-15 05:18:07 +00:00
talk-llama : sync llama.cpp
ggml-ci
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
#include "llama-batch.h"
|
#include "llama-batch.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -281,9 +282,10 @@ llama_batch_allocr::llama_batch_allocr(struct llama_batch in_batch, llama_pos p0
|
|||||||
batch = in_batch;
|
batch = in_batch;
|
||||||
GGML_ASSERT(batch.n_tokens > 0);
|
GGML_ASSERT(batch.n_tokens > 0);
|
||||||
if (!batch.pos) {
|
if (!batch.pos) {
|
||||||
|
assert(p0 >= 0);
|
||||||
pos.resize(batch.n_tokens);
|
pos.resize(batch.n_tokens);
|
||||||
for (int32_t i = 0; i < batch.n_tokens; i++) {
|
for (int32_t i = 0; i < batch.n_tokens; i++) {
|
||||||
pos[i] = i + p0;
|
pos[i] = p0 + i;
|
||||||
}
|
}
|
||||||
batch.pos = pos.data();
|
batch.pos = pos.data();
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,11 @@ llama_context::llama_context(
|
|||||||
|
|
||||||
const auto & hparams = model.hparams;
|
const auto & hparams = model.hparams;
|
||||||
|
|
||||||
cparams.n_seq_max = std::max(1u, params.n_seq_max);
|
cparams.n_seq_max = std::max(1u, params.n_seq_max);
|
||||||
|
if (cparams.n_seq_max > LLAMA_MAX_PARALLEL_SEQUENCES) {
|
||||||
|
throw std::runtime_error("n_seq_max must be <= " + std::to_string(LLAMA_MAX_PARALLEL_SEQUENCES));
|
||||||
|
}
|
||||||
|
|
||||||
cparams.n_threads = params.n_threads;
|
cparams.n_threads = params.n_threads;
|
||||||
cparams.n_threads_batch = params.n_threads_batch;
|
cparams.n_threads_batch = params.n_threads_batch;
|
||||||
cparams.yarn_ext_factor = params.yarn_ext_factor;
|
cparams.yarn_ext_factor = params.yarn_ext_factor;
|
||||||
@ -93,6 +97,7 @@ llama_context::llama_context(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cparams.n_ubatch = std::min(cparams.n_batch, params.n_ubatch == 0 ? params.n_batch : params.n_ubatch);
|
cparams.n_ubatch = std::min(cparams.n_batch, params.n_ubatch == 0 ? params.n_batch : params.n_ubatch);
|
||||||
|
|
||||||
cparams.op_offload = params.op_offload;
|
cparams.op_offload = params.op_offload;
|
||||||
|
|
||||||
const uint32_t n_ctx_per_seq = cparams.n_ctx / cparams.n_seq_max;
|
const uint32_t n_ctx_per_seq = cparams.n_ctx / cparams.n_seq_max;
|
||||||
@ -176,8 +181,9 @@ llama_context::llama_context(
|
|||||||
// init the memory module
|
// init the memory module
|
||||||
if (!hparams.vocab_only) {
|
if (!hparams.vocab_only) {
|
||||||
llama_memory_params params_mem = {
|
llama_memory_params params_mem = {
|
||||||
/*.type_k =*/ params.type_k,
|
/*.type_k =*/ params.type_k,
|
||||||
/*.type_v =*/ params.type_v,
|
/*.type_v =*/ params.type_v,
|
||||||
|
/*.swa_full =*/ params.swa_full,
|
||||||
};
|
};
|
||||||
|
|
||||||
memory.reset(model.create_memory(params_mem, cparams));
|
memory.reset(model.create_memory(params_mem, cparams));
|
||||||
@ -687,12 +693,18 @@ int llama_context::encode(llama_batch & inp_batch) {
|
|||||||
|
|
||||||
GGML_ASSERT((!batch.token && batch.embd) || (batch.token && !batch.embd)); // NOLINT
|
GGML_ASSERT((!batch.token && batch.embd) || (batch.token && !batch.embd)); // NOLINT
|
||||||
|
|
||||||
|
// TODO: move the validation to the llama_batch_allocr
|
||||||
if (batch.token) {
|
if (batch.token) {
|
||||||
for (int32_t i = 0; i < n_tokens; ++i) {
|
for (int32_t i = 0; i < n_tokens; ++i) {
|
||||||
if (batch.token[i] < 0 || (uint32_t) batch.token[i] >= model.vocab.n_tokens()) {
|
if (batch.token[i] < 0 || (uint32_t) batch.token[i] >= model.vocab.n_tokens()) {
|
||||||
LLAMA_LOG_ERROR("%s: invalid token[%d] = %d\n", __func__, i, batch.token[i]);
|
LLAMA_LOG_ERROR("%s: invalid token[%d] = %d\n", __func__, i, batch.token[i]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (batch.seq_id && (batch.seq_id[i][0] < 0 || batch.seq_id[i][0] >= LLAMA_MAX_PARALLEL_SEQUENCES)) {
|
||||||
|
LLAMA_LOG_ERROR("%s: invalid seq_id[%d] = %d > %d\n", __func__, i, batch.seq_id[i][0], LLAMA_MAX_PARALLEL_SEQUENCES);
|
||||||
|
throw -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,7 +858,7 @@ int llama_context::encode(llama_batch & inp_batch) {
|
|||||||
|
|
||||||
int llama_context::decode(llama_batch & inp_batch) {
|
int llama_context::decode(llama_batch & inp_batch) {
|
||||||
if (!memory) {
|
if (!memory) {
|
||||||
LLAMA_LOG_WARN("%s: cannot decode batches with this context (use llama_encode() instead)\n", __func__);
|
LLAMA_LOG_DEBUG("%s: cannot decode batches with this context (calling encode() instead)\n", __func__);
|
||||||
return encode(inp_batch);
|
return encode(inp_batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -855,11 +867,17 @@ int llama_context::decode(llama_batch & inp_batch) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!inp_batch.pos) {
|
||||||
|
if (inp_batch.seq_id) {
|
||||||
|
LLAMA_LOG_ERROR("%s: pos == NULL, but seq_id != NULL\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
llama_kv_cache * kv_self = static_cast<llama_kv_cache *>(memory.get());
|
llama_kv_cache * kv_self = static_cast<llama_kv_cache *>(memory.get());
|
||||||
|
|
||||||
// temporary allocate memory for the input batch if needed
|
// temporary allocate memory for the input batch if needed
|
||||||
// TODO: this is incorrect for multiple sequences because get_pos_max() is the maximum across all sequences
|
llama_batch_allocr batch_allocr(inp_batch, inp_batch.pos ? -1 : kv_self->seq_pos_max(0) + 1);
|
||||||
llama_batch_allocr batch_allocr(inp_batch, inp_batch.pos ? -1 : kv_self->get_pos_max() + 1);
|
|
||||||
|
|
||||||
const llama_batch & batch = batch_allocr.batch;
|
const llama_batch & batch = batch_allocr.batch;
|
||||||
|
|
||||||
@ -875,11 +893,17 @@ int llama_context::decode(llama_batch & inp_batch) {
|
|||||||
|
|
||||||
GGML_ASSERT((!batch.token && batch.embd) || (batch.token && !batch.embd)); // NOLINT
|
GGML_ASSERT((!batch.token && batch.embd) || (batch.token && !batch.embd)); // NOLINT
|
||||||
|
|
||||||
|
// TODO: move the validation to the llama_batch_allocr
|
||||||
if (batch.token) {
|
if (batch.token) {
|
||||||
for (int64_t i = 0; i < n_tokens_all; ++i) {
|
for (int64_t i = 0; i < n_tokens_all; ++i) {
|
||||||
if (batch.token[i] < 0 || (uint32_t) batch.token[i] >= model.vocab.n_tokens()) {
|
if (batch.token[i] < 0 || (uint32_t) batch.token[i] >= model.vocab.n_tokens()) {
|
||||||
LLAMA_LOG_ERROR("%s: invalid token[%" PRId64 "] = %d\n", __func__, i, batch.token[i]);
|
LLAMA_LOG_ERROR("%s: invalid token[%" PRId64 "] = %d\n", __func__, i, batch.token[i]);
|
||||||
throw std::runtime_error("invalid token");
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batch.seq_id && (batch.seq_id[i][0] < 0 || batch.seq_id[i][0] >= LLAMA_MAX_PARALLEL_SEQUENCES)) {
|
||||||
|
LLAMA_LOG_ERROR("%s: invalid seq_id[%" PRId64 "] = %d >= %d\n", __func__, i, batch.seq_id[i][0], LLAMA_MAX_PARALLEL_SEQUENCES);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -947,8 +971,6 @@ int llama_context::decode(llama_batch & inp_batch) {
|
|||||||
|
|
||||||
// find KV slot
|
// find KV slot
|
||||||
if (!kv_self->find_slot(ubatch)) {
|
if (!kv_self->find_slot(ubatch)) {
|
||||||
LLAMA_LOG_WARN("%s: failed to find KV cache slot for ubatch of size %d\n", __func__, ubatch.n_tokens);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2093,6 +2115,7 @@ llama_context_params llama_context_default_params() {
|
|||||||
/*.flash_attn =*/ false,
|
/*.flash_attn =*/ false,
|
||||||
/*.no_perf =*/ true,
|
/*.no_perf =*/ true,
|
||||||
/*.op_offload =*/ true,
|
/*.op_offload =*/ true,
|
||||||
|
/*.swa_full =*/ true,
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -2287,65 +2310,51 @@ int32_t llama_apply_adapter_cvec(
|
|||||||
return res ? 0 : -1;
|
return res ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// kv cache view
|
|
||||||
//
|
|
||||||
|
|
||||||
llama_kv_cache_view llama_kv_cache_view_init(const llama_context * ctx, int32_t n_seq_max) {
|
|
||||||
const auto * kv = ctx->get_kv_self();
|
|
||||||
if (kv == nullptr) {
|
|
||||||
LLAMA_LOG_WARN("%s: the context does not have a KV cache\n", __func__);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return llama_kv_cache_view_init(*kv, n_seq_max);
|
|
||||||
}
|
|
||||||
|
|
||||||
void llama_kv_cache_view_update(const llama_context * ctx, llama_kv_cache_view * view) {
|
|
||||||
const auto * kv = ctx->get_kv_self();
|
|
||||||
if (kv == nullptr) {
|
|
||||||
LLAMA_LOG_WARN("%s: the context does not have a KV cache\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
llama_kv_cache_view_update(view, kv);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// kv cache
|
// kv cache
|
||||||
//
|
//
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
int32_t llama_get_kv_cache_token_count(const llama_context * ctx) {
|
|
||||||
return llama_kv_self_n_tokens(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t llama_kv_self_n_tokens(const llama_context * ctx) {
|
int32_t llama_kv_self_n_tokens(const llama_context * ctx) {
|
||||||
const auto * kv = ctx->get_kv_self();
|
const auto * kv = ctx->get_kv_self();
|
||||||
if (!kv) {
|
if (!kv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return kv->get_n_tokens();
|
int32_t res = 0;
|
||||||
|
|
||||||
|
for (uint32_t s = 0; s < ctx->get_cparams().n_seq_max; s++) {
|
||||||
|
const llama_pos p0 = kv->seq_pos_min(s);
|
||||||
|
const llama_pos p1 = kv->seq_pos_max(s);
|
||||||
|
|
||||||
|
if (p0 >= 0) {
|
||||||
|
res += (p1 - p0) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
int32_t llama_get_kv_cache_used_cells(const llama_context * ctx) {
|
// note: this is the same as above - will be removed anyway, so it's ok
|
||||||
return llama_kv_self_used_cells(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t llama_kv_self_used_cells(const llama_context * ctx) {
|
int32_t llama_kv_self_used_cells(const llama_context * ctx) {
|
||||||
const auto * kv = ctx->get_kv_self();
|
const auto * kv = ctx->get_kv_self();
|
||||||
if (!kv) {
|
if (!kv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return kv->get_used_cells();
|
int32_t res = 0;
|
||||||
}
|
|
||||||
|
|
||||||
// deprecated
|
for (uint32_t s = 0; s < ctx->get_cparams().n_seq_max; s++) {
|
||||||
void llama_kv_cache_clear(llama_context * ctx) {
|
const llama_pos p0 = kv->seq_pos_min(s);
|
||||||
llama_kv_self_clear(ctx);
|
const llama_pos p1 = kv->seq_pos_max(s);
|
||||||
|
|
||||||
|
if (p0 >= 0) {
|
||||||
|
res += (p1 - p0) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void llama_kv_self_clear(llama_context * ctx) {
|
void llama_kv_self_clear(llama_context * ctx) {
|
||||||
@ -2357,15 +2366,6 @@ void llama_kv_self_clear(llama_context * ctx) {
|
|||||||
kv->clear();
|
kv->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
|
||||||
bool llama_kv_cache_seq_rm(
|
|
||||||
llama_context * ctx,
|
|
||||||
llama_seq_id seq_id,
|
|
||||||
llama_pos p0,
|
|
||||||
llama_pos p1) {
|
|
||||||
return llama_kv_self_seq_rm(ctx, seq_id, p0, p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool llama_kv_self_seq_rm(
|
bool llama_kv_self_seq_rm(
|
||||||
llama_context * ctx,
|
llama_context * ctx,
|
||||||
llama_seq_id seq_id,
|
llama_seq_id seq_id,
|
||||||
@ -2379,16 +2379,6 @@ bool llama_kv_self_seq_rm(
|
|||||||
return kv->seq_rm(seq_id, p0, p1);
|
return kv->seq_rm(seq_id, p0, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
|
||||||
void llama_kv_cache_seq_cp(
|
|
||||||
llama_context * ctx,
|
|
||||||
llama_seq_id seq_id_src,
|
|
||||||
llama_seq_id seq_id_dst,
|
|
||||||
llama_pos p0,
|
|
||||||
llama_pos p1) {
|
|
||||||
llama_kv_self_seq_cp(ctx, seq_id_src, seq_id_dst, p0, p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void llama_kv_self_seq_cp(
|
void llama_kv_self_seq_cp(
|
||||||
llama_context * ctx,
|
llama_context * ctx,
|
||||||
llama_seq_id seq_id_src,
|
llama_seq_id seq_id_src,
|
||||||
@ -2403,13 +2393,6 @@ void llama_kv_self_seq_cp(
|
|||||||
kv->seq_cp(seq_id_src, seq_id_dst, p0, p1);
|
kv->seq_cp(seq_id_src, seq_id_dst, p0, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
|
||||||
void llama_kv_cache_seq_keep(
|
|
||||||
llama_context * ctx,
|
|
||||||
llama_seq_id seq_id) {
|
|
||||||
llama_kv_self_seq_keep(ctx, seq_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void llama_kv_self_seq_keep(llama_context * ctx, llama_seq_id seq_id) {
|
void llama_kv_self_seq_keep(llama_context * ctx, llama_seq_id seq_id) {
|
||||||
auto * kv = ctx->get_kv_self();
|
auto * kv = ctx->get_kv_self();
|
||||||
if (!kv) {
|
if (!kv) {
|
||||||
@ -2419,16 +2402,6 @@ void llama_kv_self_seq_keep(llama_context * ctx, llama_seq_id seq_id) {
|
|||||||
kv->seq_keep(seq_id);
|
kv->seq_keep(seq_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
|
||||||
void llama_kv_cache_seq_add(
|
|
||||||
llama_context * ctx,
|
|
||||||
llama_seq_id seq_id,
|
|
||||||
llama_pos p0,
|
|
||||||
llama_pos p1,
|
|
||||||
llama_pos delta) {
|
|
||||||
llama_kv_self_seq_add(ctx, seq_id, p0, p1, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
void llama_kv_self_seq_add(
|
void llama_kv_self_seq_add(
|
||||||
llama_context * ctx,
|
llama_context * ctx,
|
||||||
llama_seq_id seq_id,
|
llama_seq_id seq_id,
|
||||||
@ -2443,16 +2416,6 @@ void llama_kv_self_seq_add(
|
|||||||
kv->seq_add(seq_id, p0, p1, delta);
|
kv->seq_add(seq_id, p0, p1, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
|
||||||
void llama_kv_cache_seq_div(
|
|
||||||
llama_context * ctx,
|
|
||||||
llama_seq_id seq_id,
|
|
||||||
llama_pos p0,
|
|
||||||
llama_pos p1,
|
|
||||||
int d) {
|
|
||||||
llama_kv_self_seq_div(ctx, seq_id, p0, p1, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
void llama_kv_self_seq_div(
|
void llama_kv_self_seq_div(
|
||||||
llama_context * ctx,
|
llama_context * ctx,
|
||||||
llama_seq_id seq_id,
|
llama_seq_id seq_id,
|
||||||
@ -2467,25 +2430,24 @@ void llama_kv_self_seq_div(
|
|||||||
kv->seq_div(seq_id, p0, p1, d);
|
kv->seq_div(seq_id, p0, p1, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
llama_pos llama_kv_self_seq_pos_min(llama_context * ctx, llama_seq_id seq_id) {
|
||||||
llama_pos llama_kv_cache_seq_pos_max(llama_context * ctx, llama_seq_id seq_id) {
|
const auto * kv = ctx->get_kv_self();
|
||||||
return llama_kv_self_seq_pos_max(ctx, seq_id);
|
if (!kv) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kv->seq_pos_min(seq_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
llama_pos llama_kv_self_seq_pos_max(llama_context * ctx, llama_seq_id seq_id) {
|
llama_pos llama_kv_self_seq_pos_max(llama_context * ctx, llama_seq_id seq_id) {
|
||||||
const auto * kv = ctx->get_kv_self();
|
const auto * kv = ctx->get_kv_self();
|
||||||
if (!kv) {
|
if (!kv) {
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return kv->seq_pos_max(seq_id);
|
return kv->seq_pos_max(seq_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
|
||||||
void llama_kv_cache_defrag(llama_context * ctx) {
|
|
||||||
llama_kv_self_defrag(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void llama_kv_self_defrag(llama_context * ctx) {
|
void llama_kv_self_defrag(llama_context * ctx) {
|
||||||
auto * kv = ctx->get_kv_self();
|
auto * kv = ctx->get_kv_self();
|
||||||
if (!kv) {
|
if (!kv) {
|
||||||
@ -2496,11 +2458,6 @@ void llama_kv_self_defrag(llama_context * ctx) {
|
|||||||
kv->defrag_sched(-1.0f);
|
kv->defrag_sched(-1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
|
||||||
bool llama_kv_cache_can_shift(const llama_context * ctx) {
|
|
||||||
return llama_kv_self_can_shift(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool llama_kv_self_can_shift(const llama_context * ctx) {
|
bool llama_kv_self_can_shift(const llama_context * ctx) {
|
||||||
const auto * kv = ctx->get_kv_self();
|
const auto * kv = ctx->get_kv_self();
|
||||||
if (!kv) {
|
if (!kv) {
|
||||||
@ -2510,11 +2467,6 @@ bool llama_kv_self_can_shift(const llama_context * ctx) {
|
|||||||
return kv->get_can_shift();
|
return kv->get_can_shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
|
||||||
void llama_kv_cache_update(llama_context * ctx) {
|
|
||||||
llama_kv_self_update(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// llama state API
|
// llama state API
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
@ -2637,7 +2589,21 @@ int32_t llama_encode(
|
|||||||
int32_t llama_decode(
|
int32_t llama_decode(
|
||||||
llama_context * ctx,
|
llama_context * ctx,
|
||||||
llama_batch batch) {
|
llama_batch batch) {
|
||||||
const int ret = ctx->decode(batch);
|
int ret = ctx->decode(batch);
|
||||||
|
|
||||||
|
// defrag and try again
|
||||||
|
// TODO: distinguish return code when we are sure that even after defrag there is no space available
|
||||||
|
if (ret == 1) {
|
||||||
|
llama_kv_self_defrag(ctx);
|
||||||
|
ret = ctx->decode(batch);
|
||||||
|
|
||||||
|
if (ret == 1) {
|
||||||
|
LLAMA_LOG_WARN("%s: failed to find KV cache slot for batch of size %d\n", __func__, batch.n_tokens);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
LLAMA_LOG_ERROR("%s: failed to decode, ret = %d\n", __func__, ret);
|
LLAMA_LOG_ERROR("%s: failed to decode, ret = %d\n", __func__, ret);
|
||||||
}
|
}
|
||||||
|
@ -1 +1,5 @@
|
|||||||
#include "llama-cparams.h"
|
#include "llama-cparams.h"
|
||||||
|
|
||||||
|
size_t llama_max_parallel_sequences(void) {
|
||||||
|
return LLAMA_MAX_PARALLEL_SEQUENCES;
|
||||||
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#define LLAMA_MAX_PARALLEL_SEQUENCES 64
|
||||||
|
|
||||||
struct llama_cparams {
|
struct llama_cparams {
|
||||||
uint32_t n_ctx; // context size used during inference
|
uint32_t n_ctx; // context size used during inference
|
||||||
uint32_t n_batch;
|
uint32_t n_batch;
|
||||||
|
@ -1177,8 +1177,18 @@ void llama_grammar_accept_impl(struct llama_grammar & grammar, llama_token token
|
|||||||
for (const auto & trigger_pattern : grammar.trigger_patterns) {
|
for (const auto & trigger_pattern : grammar.trigger_patterns) {
|
||||||
if (std::regex_match(grammar.trigger_buffer, match, trigger_pattern.regex)) {
|
if (std::regex_match(grammar.trigger_buffer, match, trigger_pattern.regex)) {
|
||||||
grammar.awaiting_trigger = false;
|
grammar.awaiting_trigger = false;
|
||||||
// get from the first match to the end of the string
|
// get from the first matched capturing group to the end of the string
|
||||||
auto constrained_str = grammar.trigger_buffer.substr(match.position(1));
|
size_t start = std::string::npos;
|
||||||
|
for (auto i = 1u; i < match.size(); i++) {
|
||||||
|
if (match.length(i) > 0) {
|
||||||
|
start = match.position(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (start == std::string::npos) {
|
||||||
|
start = match.position(0);
|
||||||
|
}
|
||||||
|
auto constrained_str = grammar.trigger_buffer.substr(start);
|
||||||
// std::string constrained_str(match[1].first, grammar.trigger_buffer.end());
|
// std::string constrained_str(match[1].first, grammar.trigger_buffer.end());
|
||||||
grammar.trigger_buffer.clear();
|
grammar.trigger_buffer.clear();
|
||||||
llama_grammar_accept_str(grammar, constrained_str);
|
llama_grammar_accept_str(grammar, constrained_str);
|
||||||
|
@ -9,33 +9,6 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
static int32_t llama_relative_position_bucket(llama_pos x, llama_pos y, uint64_t n_buckets, bool bidirectional) {
|
|
||||||
// TODO move to hparams if a T5 variant appears that uses a different value
|
|
||||||
const int64_t max_distance = 128;
|
|
||||||
|
|
||||||
if (bidirectional) {
|
|
||||||
n_buckets >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int64_t max_exact = n_buckets >> 1;
|
|
||||||
|
|
||||||
int32_t relative_position = x - y;
|
|
||||||
int32_t relative_bucket = 0;
|
|
||||||
|
|
||||||
if (bidirectional) {
|
|
||||||
relative_bucket += (relative_position > 0) * n_buckets;
|
|
||||||
relative_position = abs(relative_position);
|
|
||||||
} else {
|
|
||||||
relative_position = -std::min<int32_t>(relative_position, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t relative_position_if_large = floorf(max_exact + logf(1.0 * relative_position / max_exact) * (n_buckets - max_exact) / log(1.0 * max_distance / max_exact));
|
|
||||||
relative_position_if_large = std::min<int32_t>(relative_position_if_large, n_buckets - 1);
|
|
||||||
relative_bucket += (relative_position < max_exact ? relative_position : relative_position_if_large);
|
|
||||||
|
|
||||||
return relative_bucket;
|
|
||||||
}
|
|
||||||
|
|
||||||
void llm_graph_input_embd::set_input(const llama_ubatch * ubatch) {
|
void llm_graph_input_embd::set_input(const llama_ubatch * ubatch) {
|
||||||
if (ubatch->token) {
|
if (ubatch->token) {
|
||||||
const int64_t n_tokens = ubatch->n_tokens;
|
const int64_t n_tokens = ubatch->n_tokens;
|
||||||
@ -110,22 +83,7 @@ void llm_graph_input_pos_bucket::set_input(const llama_ubatch * ubatch) {
|
|||||||
|
|
||||||
void llm_graph_input_pos_bucket_kv::set_input(const llama_ubatch * ubatch) {
|
void llm_graph_input_pos_bucket_kv::set_input(const llama_ubatch * ubatch) {
|
||||||
if (pos_bucket) {
|
if (pos_bucket) {
|
||||||
const int64_t n_tokens = ubatch->n_tokens;
|
kv_self->set_input_pos_bucket(pos_bucket, ubatch);
|
||||||
|
|
||||||
GGML_ASSERT(ggml_backend_buffer_is_host(pos_bucket->buffer));
|
|
||||||
GGML_ASSERT(!ubatch->equal_seqs); // TODO: use ubatch->n_seqs instead of failing
|
|
||||||
|
|
||||||
int32_t * data = (int32_t *) pos_bucket->data;
|
|
||||||
|
|
||||||
const int64_t n_kv = kv_self->n;
|
|
||||||
|
|
||||||
for (int h = 0; h < 1; ++h) {
|
|
||||||
for (int j = 0; j < n_tokens; ++j) {
|
|
||||||
for (int i = 0; i < n_kv; ++i) {
|
|
||||||
data[h*(n_kv*n_tokens) + j*n_kv + i] = llama_relative_position_bucket(kv_self->cells[i].pos, ubatch->pos[j], hparams.n_rel_attn_bkts, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,99 +361,18 @@ void llm_graph_input_attn_no_cache::set_input(const llama_ubatch * ubatch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void llm_graph_input_attn_kv_unified::set_input(const llama_ubatch * ubatch) {
|
void llm_graph_input_attn_kv_unified::set_input(const llama_ubatch * ubatch) {
|
||||||
if (self_kq_mask || self_kq_mask_swa) {
|
if (self_kq_mask) {
|
||||||
const int64_t n_kv = kv_self->n;
|
kv_self->set_input_kq_mask(self_kq_mask, ubatch, cparams.causal_attn);
|
||||||
const int64_t n_tokens = ubatch->n_tokens;
|
}
|
||||||
const int64_t n_seq_tokens = ubatch->n_seq_tokens;
|
}
|
||||||
const int64_t n_seqs = ubatch->n_seqs;
|
|
||||||
|
|
||||||
float * data = nullptr;
|
void llm_graph_input_attn_kv_unified_iswa::set_input(const llama_ubatch * ubatch) {
|
||||||
float * data_swa = nullptr;
|
if (self_kq_mask) {
|
||||||
|
kv_self->get_kv_base()->set_input_kq_mask(self_kq_mask, ubatch, cparams.causal_attn);
|
||||||
|
}
|
||||||
|
|
||||||
if (self_kq_mask) {
|
if (self_kq_mask_swa) {
|
||||||
GGML_ASSERT(ggml_backend_buffer_is_host(self_kq_mask->buffer));
|
kv_self->get_kv_swa()->set_input_kq_mask(self_kq_mask_swa, ubatch, cparams.causal_attn);
|
||||||
data = (float *) self_kq_mask->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self_kq_mask_swa) {
|
|
||||||
GGML_ASSERT(ggml_backend_buffer_is_host(self_kq_mask_swa->buffer));
|
|
||||||
data_swa = (float *) self_kq_mask_swa->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use only the previous KV cells of the correct sequence for each token of the ubatch.
|
|
||||||
// It's assumed that if a token in the batch has multiple sequences, they are equivalent.
|
|
||||||
// Example with a cache of 10 tokens, 2 tokens populated in cache and 3 tokens in batch:
|
|
||||||
// Causal mask:
|
|
||||||
// xxx-------
|
|
||||||
// xxxx------
|
|
||||||
// xxxxx-----
|
|
||||||
// Non-causal mask:
|
|
||||||
// xxxxx-----
|
|
||||||
// xxxxx-----
|
|
||||||
// xxxxx-----
|
|
||||||
// To visualize the mask, see https://github.com/ggml-org/llama.cpp/pull/12615
|
|
||||||
for (int h = 0; h < 1; ++h) {
|
|
||||||
for (int s = 0; s < n_seqs; ++s) {
|
|
||||||
const llama_seq_id seq_id = ubatch->seq_id[s][0];
|
|
||||||
|
|
||||||
for (int j = 0; j < n_seq_tokens; ++j) {
|
|
||||||
const llama_pos pos = ubatch->pos[s*n_seq_tokens + j];
|
|
||||||
for (int i = 0; i < n_kv; ++i) {
|
|
||||||
float f;
|
|
||||||
// mask the token if:
|
|
||||||
if (!kv_self->cells[i].has_seq_id(seq_id) // not the correct sequence
|
|
||||||
|| (cparams.causal_attn && kv_self->cells[i].pos > pos) // for causal, mask future tokens
|
|
||||||
) {
|
|
||||||
f = -INFINITY;
|
|
||||||
} else {
|
|
||||||
if (hparams.use_alibi) {
|
|
||||||
f = -std::abs(kv_self->cells[i].pos - pos);
|
|
||||||
} else {
|
|
||||||
f = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
data[h*(n_kv*n_tokens) + s*(n_kv*n_seq_tokens) + j*n_kv + i] = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// may need to cut off old tokens for sliding window
|
|
||||||
// TODO @ngxson : we are currently re-using the swa logic to store the chunked mask, we should rename SWA to something more generic like "aux mask"
|
|
||||||
if (data_swa) {
|
|
||||||
if (hparams.n_attn_chunk) {
|
|
||||||
llama_pos pos_chunk_start = (pos / hparams.n_attn_chunk) * hparams.n_attn_chunk;
|
|
||||||
if (kv_self->cells[i].pos < pos_chunk_start || pos < pos_chunk_start) {
|
|
||||||
f = -INFINITY;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (pos - kv_self->cells[i].pos >= (int32_t)hparams.n_swa) {
|
|
||||||
f = -INFINITY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data_swa[h*(n_kv*n_tokens) + s*(n_kv*n_seq_tokens) + j*n_kv + i] = f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mask padded tokens
|
|
||||||
if (data) {
|
|
||||||
for (int i = n_tokens; i < GGML_PAD(n_tokens, GGML_KQ_MASK_PAD); ++i) {
|
|
||||||
for (int j = 0; j < n_kv; ++j) {
|
|
||||||
data[h*(n_kv*n_tokens) + i*n_kv + j] = -INFINITY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mask padded tokens
|
|
||||||
if (data_swa) {
|
|
||||||
for (int i = n_tokens; i < GGML_PAD(n_tokens, GGML_KQ_MASK_PAD); ++i) {
|
|
||||||
for (int j = 0; j < n_kv; ++j) {
|
|
||||||
data_swa[h*(n_kv*n_tokens) + i*n_kv + j] = -INFINITY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,7 +422,6 @@ llm_graph_context::llm_graph_context(const llm_graph_params & params) :
|
|||||||
n_layer (hparams.n_layer),
|
n_layer (hparams.n_layer),
|
||||||
n_rot (hparams.n_rot),
|
n_rot (hparams.n_rot),
|
||||||
n_ctx (cparams.n_ctx),
|
n_ctx (cparams.n_ctx),
|
||||||
n_ctx_per_seq (cparams.n_ctx / cparams.n_seq_max),
|
|
||||||
n_head (hparams.n_head()),
|
n_head (hparams.n_head()),
|
||||||
n_head_kv (hparams.n_head_kv()),
|
n_head_kv (hparams.n_head_kv()),
|
||||||
n_embd_head_k (hparams.n_embd_head_k),
|
n_embd_head_k (hparams.n_embd_head_k),
|
||||||
@ -1153,7 +1029,7 @@ ggml_tensor * llm_graph_context::build_inp_pos_bucket_dec() const {
|
|||||||
|
|
||||||
auto inp = std::make_unique<llm_graph_input_pos_bucket_kv>(hparams, kv_self);
|
auto inp = std::make_unique<llm_graph_input_pos_bucket_kv>(hparams, kv_self);
|
||||||
|
|
||||||
const auto n_kv = kv_self->n;
|
const auto n_kv = kv_self->get_n();
|
||||||
|
|
||||||
auto & cur = inp->pos_bucket;
|
auto & cur = inp->pos_bucket;
|
||||||
|
|
||||||
@ -1188,16 +1064,12 @@ ggml_tensor * llm_graph_context::build_attn_mha(
|
|||||||
ggml_tensor * kq_b,
|
ggml_tensor * kq_b,
|
||||||
ggml_tensor * kq_mask,
|
ggml_tensor * kq_mask,
|
||||||
ggml_tensor * v_mla,
|
ggml_tensor * v_mla,
|
||||||
bool v_trans,
|
|
||||||
float kq_scale) const {
|
float kq_scale) const {
|
||||||
//const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il);
|
const bool v_trans = v->nb[1] > v->nb[2];
|
||||||
//const int64_t n_embd_v_gqa = hparams.n_embd_v_gqa(il);
|
|
||||||
|
|
||||||
//const int64_t n_head = hparams.n_head(il);
|
q = ggml_permute(ctx0, q, 0, 2, 1, 3);
|
||||||
//const int64_t n_head_kv = hparams.n_head_kv(il);
|
k = ggml_permute(ctx0, k, 0, 2, 1, 3);
|
||||||
|
v = ggml_permute(ctx0, v, 0, 2, 1, 3);
|
||||||
//const auto & n_embd_head_k = hparams.n_embd_head_k;
|
|
||||||
//const auto & n_embd_head_v = hparams.n_embd_head_v;
|
|
||||||
|
|
||||||
const auto n_tokens = q->ne[1];
|
const auto n_tokens = q->ne[1];
|
||||||
const auto n_head = q->ne[2];
|
const auto n_head = q->ne[2];
|
||||||
@ -1336,17 +1208,11 @@ ggml_tensor * llm_graph_context::build_attn(
|
|||||||
|
|
||||||
const auto & kq_mask = inp->get_kq_mask();
|
const auto & kq_mask = inp->get_kq_mask();
|
||||||
|
|
||||||
ggml_tensor * q = ggml_permute(ctx0, q_cur, 0, 2, 1, 3);
|
ggml_tensor * q = q_cur;
|
||||||
//cb(q, "q", il);
|
ggml_tensor * k = k_cur;
|
||||||
|
ggml_tensor * v = v_cur;
|
||||||
ggml_tensor * k = ggml_permute(ctx0, k_cur, 0, 2, 1, 3);
|
|
||||||
//cb(k, "k", il);
|
|
||||||
|
|
||||||
ggml_tensor * v = ggml_permute(ctx0, v_cur, 0, 2, 1, 3);
|
|
||||||
//cb(k, "v", il);
|
|
||||||
|
|
||||||
ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, v_mla, false, kq_scale);
|
|
||||||
|
|
||||||
|
ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, v_mla, kq_scale);
|
||||||
cb(cur, "kqv_out", il);
|
cb(cur, "kqv_out", il);
|
||||||
|
|
||||||
if (wo) {
|
if (wo) {
|
||||||
@ -1369,22 +1235,16 @@ llm_graph_input_attn_kv_unified * llm_graph_context::build_attn_inp_kv_unified()
|
|||||||
|
|
||||||
auto inp = std::make_unique<llm_graph_input_attn_kv_unified>(hparams, cparams, kv_self);
|
auto inp = std::make_unique<llm_graph_input_attn_kv_unified>(hparams, cparams, kv_self);
|
||||||
|
|
||||||
const auto n_kv = kv_self->n;
|
{
|
||||||
|
GGML_ASSERT(hparams.swa_type == LLAMA_SWA_TYPE_NONE && "Use llama_kv_cache_unified_iswa for SWA");
|
||||||
|
|
||||||
inp->self_kq_mask = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD));
|
const auto n_kv = kv_self->get_n();
|
||||||
//cb(inp->self_kq_mask, "KQ_mask", -1);
|
|
||||||
ggml_set_input(inp->self_kq_mask);
|
|
||||||
|
|
||||||
inp->self_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask, GGML_TYPE_F16) : inp->self_kq_mask;
|
inp->self_kq_mask = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD));
|
||||||
|
//cb(inp->self_kq_mask, "KQ_mask", -1);
|
||||||
|
ggml_set_input(inp->self_kq_mask);
|
||||||
|
|
||||||
if (hparams.n_swa_pattern > 1) {
|
inp->self_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask, GGML_TYPE_F16) : inp->self_kq_mask;
|
||||||
GGML_ASSERT(hparams.n_swa > 0);
|
|
||||||
|
|
||||||
inp->self_kq_mask_swa = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD));
|
|
||||||
//cb(inp->self_kq_mask_swa, "KQ_mask_swa", -1);
|
|
||||||
ggml_set_input(inp->self_kq_mask_swa);
|
|
||||||
|
|
||||||
inp->self_kq_mask_swa_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask_swa, GGML_TYPE_F16) : inp->self_kq_mask_swa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (llm_graph_input_attn_kv_unified *) res->add_input(std::move(inp));
|
return (llm_graph_input_attn_kv_unified *) res->add_input(std::move(inp));
|
||||||
@ -1409,81 +1269,104 @@ ggml_tensor * llm_graph_context::build_attn(
|
|||||||
ggml_build_forward_expand(gf, v_cur);
|
ggml_build_forward_expand(gf, v_cur);
|
||||||
|
|
||||||
const llama_kv_cache_unified * kv_self = static_cast<const llama_kv_cache_unified *>(memory);
|
const llama_kv_cache_unified * kv_self = static_cast<const llama_kv_cache_unified *>(memory);
|
||||||
const auto & n_ctx = cparams.n_ctx;
|
|
||||||
|
|
||||||
const int64_t n_embd_k_gqa = hparams.n_embd_k_gqa(il);
|
|
||||||
const int64_t n_embd_v_gqa = hparams.n_embd_v_gqa(il);
|
|
||||||
|
|
||||||
const auto n_tokens = q_cur->ne[2];
|
|
||||||
|
|
||||||
const bool v_trans = !cparams.flash_attn;
|
|
||||||
|
|
||||||
// store to KV cache
|
// store to KV cache
|
||||||
{
|
{
|
||||||
const auto kv_head = kv_self->head;
|
ggml_build_forward_expand(gf, kv_self->cpy_k(ctx0, k_cur, il));
|
||||||
|
ggml_build_forward_expand(gf, kv_self->cpy_v(ctx0, v_cur, il));
|
||||||
GGML_ASSERT(kv_self->size == n_ctx);
|
|
||||||
|
|
||||||
ggml_tensor * k_cache_view = ggml_view_1d(ctx0, kv_self->k_l[il], n_tokens*n_embd_k_gqa, ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa)*kv_head);
|
|
||||||
//cb(k_cache_view, "k_cache_view", il);
|
|
||||||
|
|
||||||
// note: storing RoPE-ed version of K in the KV cache
|
|
||||||
ggml_build_forward_expand(gf, ggml_cpy(ctx0, k_cur, k_cache_view));
|
|
||||||
|
|
||||||
v_cur = ggml_reshape_2d(ctx0, v_cur, n_embd_v_gqa, n_tokens);
|
|
||||||
|
|
||||||
ggml_tensor * v_cache_view = nullptr;
|
|
||||||
|
|
||||||
if (!v_trans) {
|
|
||||||
v_cache_view = ggml_view_1d(ctx0, kv_self->v_l[il], n_tokens*n_embd_v_gqa, ggml_row_size(kv_self->v_l[il]->type, n_embd_v_gqa)*kv_head);
|
|
||||||
} else {
|
|
||||||
// note: the V cache is transposed when not using flash attention
|
|
||||||
v_cache_view = ggml_view_2d(ctx0, kv_self->v_l[il], n_tokens, n_embd_v_gqa,
|
|
||||||
( n_ctx)*ggml_element_size(kv_self->v_l[il]),
|
|
||||||
(kv_head)*ggml_element_size(kv_self->v_l[il]));
|
|
||||||
|
|
||||||
v_cur = ggml_transpose(ctx0, v_cur);
|
|
||||||
}
|
|
||||||
//cb(v_cache_view, "v_cache_view", il);
|
|
||||||
|
|
||||||
ggml_build_forward_expand(gf, ggml_cpy(ctx0, v_cur, v_cache_view));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto & kq_mask = inp->get_kq_mask();
|
||||||
|
|
||||||
|
ggml_tensor * q = q_cur;
|
||||||
|
ggml_tensor * k = kv_self->get_k(ctx0, il);
|
||||||
|
ggml_tensor * v = kv_self->get_v(ctx0, il);
|
||||||
|
|
||||||
|
ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, v_mla, kq_scale);
|
||||||
|
cb(cur, "kqv_out", il);
|
||||||
|
|
||||||
|
if (wo) {
|
||||||
|
cur = build_lora_mm(wo, cur);
|
||||||
|
if (arch == LLM_ARCH_GLM4) {
|
||||||
|
// GLM4 seems to have numerical issues with half-precision accumulators
|
||||||
|
ggml_mul_mat_set_prec(cur, GGML_PREC_F32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wo_b) {
|
||||||
|
cur = ggml_add(ctx0, cur, wo_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
llm_graph_input_attn_kv_unified_iswa * llm_graph_context::build_attn_inp_kv_unified_iswa() const {
|
||||||
|
const llama_kv_cache_unified_iswa * kv_self = static_cast<const llama_kv_cache_unified_iswa *>(memory);
|
||||||
|
|
||||||
|
auto inp = std::make_unique<llm_graph_input_attn_kv_unified_iswa>(hparams, cparams, kv_self);
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto n_kv = kv_self->get_kv_base()->get_n();
|
||||||
|
|
||||||
|
inp->self_kq_mask = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD));
|
||||||
|
//cb(inp->self_kq_mask, "KQ_mask", -1);
|
||||||
|
ggml_set_input(inp->self_kq_mask);
|
||||||
|
|
||||||
|
inp->self_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask, GGML_TYPE_F16) : inp->self_kq_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
GGML_ASSERT(hparams.swa_type != LLAMA_SWA_TYPE_NONE && "Use llama_kv_cache_unified for non-SWA");
|
||||||
|
|
||||||
|
const auto n_kv = kv_self->get_kv_swa()->get_n();
|
||||||
|
|
||||||
|
inp->self_kq_mask_swa = ggml_new_tensor_2d(ctx0, GGML_TYPE_F32, n_kv, GGML_PAD(n_tokens, GGML_KQ_MASK_PAD));
|
||||||
|
//cb(inp->self_kq_mask_swa, "KQ_mask_swa", -1);
|
||||||
|
ggml_set_input(inp->self_kq_mask_swa);
|
||||||
|
|
||||||
|
inp->self_kq_mask_swa_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask_swa, GGML_TYPE_F16) : inp->self_kq_mask_swa;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (llm_graph_input_attn_kv_unified_iswa *) res->add_input(std::move(inp));
|
||||||
|
}
|
||||||
|
|
||||||
|
ggml_tensor * llm_graph_context::build_attn(
|
||||||
|
llm_graph_input_attn_kv_unified_iswa * inp,
|
||||||
|
ggml_cgraph * gf,
|
||||||
|
ggml_tensor * wo,
|
||||||
|
ggml_tensor * wo_b,
|
||||||
|
ggml_tensor * q_cur,
|
||||||
|
ggml_tensor * k_cur,
|
||||||
|
ggml_tensor * v_cur,
|
||||||
|
ggml_tensor * kq_b,
|
||||||
|
ggml_tensor * v_mla,
|
||||||
|
float kq_scale,
|
||||||
|
int il) const {
|
||||||
|
// these nodes are added to the graph together so that they are not reordered
|
||||||
|
// by doing so, the number of splits in the graph is reduced
|
||||||
|
ggml_build_forward_expand(gf, q_cur);
|
||||||
|
ggml_build_forward_expand(gf, k_cur);
|
||||||
|
ggml_build_forward_expand(gf, v_cur);
|
||||||
|
|
||||||
const bool is_swa = hparams.is_swa(il);
|
const bool is_swa = hparams.is_swa(il);
|
||||||
|
|
||||||
|
const llama_kv_cache_unified_iswa * kv_self = static_cast<const llama_kv_cache_unified_iswa *>(memory);
|
||||||
|
|
||||||
|
const auto * kv = is_swa ? kv_self->get_kv_swa() : kv_self->get_kv_base();
|
||||||
|
|
||||||
|
// store to KV cache
|
||||||
|
{
|
||||||
|
ggml_build_forward_expand(gf, kv->cpy_k(ctx0, k_cur, il));
|
||||||
|
ggml_build_forward_expand(gf, kv->cpy_v(ctx0, v_cur, il));
|
||||||
|
}
|
||||||
|
|
||||||
const auto & kq_mask = is_swa ? inp->get_kq_mask_swa() : inp->get_kq_mask();
|
const auto & kq_mask = is_swa ? inp->get_kq_mask_swa() : inp->get_kq_mask();
|
||||||
|
|
||||||
const auto n_kv = kv_self->n;
|
ggml_tensor * q = q_cur;
|
||||||
|
ggml_tensor * k = kv->get_k(ctx0, il);
|
||||||
|
ggml_tensor * v = kv->get_v(ctx0, il);
|
||||||
|
|
||||||
const int64_t n_head_kv = hparams.n_head_kv(il);
|
ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, v_mla, kq_scale);
|
||||||
|
|
||||||
const auto & n_embd_head_k = hparams.n_embd_head_k;
|
|
||||||
const auto & n_embd_head_v = hparams.n_embd_head_v;
|
|
||||||
|
|
||||||
ggml_tensor * q = ggml_permute(ctx0, q_cur, 0, 2, 1, 3);
|
|
||||||
//cb(q, "q", il);
|
|
||||||
|
|
||||||
ggml_tensor * k =
|
|
||||||
ggml_view_3d(ctx0, kv_self->k_l[il],
|
|
||||||
n_embd_head_k, n_kv, n_head_kv,
|
|
||||||
ggml_row_size(kv_self->k_l[il]->type, n_embd_k_gqa),
|
|
||||||
ggml_row_size(kv_self->k_l[il]->type, n_embd_head_k),
|
|
||||||
0);
|
|
||||||
//cb(k, "k", il);
|
|
||||||
|
|
||||||
ggml_tensor * v = !v_trans ?
|
|
||||||
ggml_view_3d(ctx0, kv_self->v_l[il],
|
|
||||||
n_embd_head_v, n_kv, n_head_kv,
|
|
||||||
ggml_row_size(kv_self->v_l[il]->type, n_embd_v_gqa),
|
|
||||||
ggml_row_size(kv_self->v_l[il]->type, n_embd_head_v),
|
|
||||||
0) :
|
|
||||||
ggml_view_3d(ctx0, kv_self->v_l[il],
|
|
||||||
n_kv, n_embd_head_v, n_head_kv,
|
|
||||||
ggml_element_size(kv_self->v_l[il])*n_ctx,
|
|
||||||
ggml_element_size(kv_self->v_l[il])*n_ctx*n_embd_head_v,
|
|
||||||
0);
|
|
||||||
|
|
||||||
ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, v_mla, v_trans, kq_scale);
|
|
||||||
cb(cur, "kqv_out", il);
|
cb(cur, "kqv_out", il);
|
||||||
|
|
||||||
if (wo) {
|
if (wo) {
|
||||||
@ -1534,17 +1417,11 @@ ggml_tensor * llm_graph_context::build_attn(
|
|||||||
|
|
||||||
const auto & kq_mask = inp->get_kq_mask_cross();
|
const auto & kq_mask = inp->get_kq_mask_cross();
|
||||||
|
|
||||||
ggml_tensor * q = ggml_permute(ctx0, q_cur, 0, 2, 1, 3);
|
ggml_tensor * q = q_cur;
|
||||||
//cb(q, "q", il);
|
ggml_tensor * k = k_cur;
|
||||||
|
ggml_tensor * v = v_cur;
|
||||||
ggml_tensor * k = ggml_permute(ctx0, k_cur, 0, 2, 1, 3);
|
|
||||||
//cb(k, "k", il);
|
|
||||||
|
|
||||||
ggml_tensor * v = ggml_permute(ctx0, v_cur, 0, 2, 1, 3);
|
|
||||||
//cb(k, "v", il);
|
|
||||||
|
|
||||||
ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, v_mla, false, kq_scale);
|
|
||||||
|
|
||||||
|
ggml_tensor * cur = build_attn_mha(gf, q, k, v, kq_b, kq_mask, v_mla, kq_scale);
|
||||||
cb(cur, "kqv_out", il);
|
cb(cur, "kqv_out", il);
|
||||||
|
|
||||||
if (wo) {
|
if (wo) {
|
||||||
@ -1712,3 +1589,30 @@ void llm_graph_context::build_pooling(
|
|||||||
|
|
||||||
ggml_build_forward_expand(gf, cur);
|
ggml_build_forward_expand(gf, cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t llama_relative_position_bucket(llama_pos x, llama_pos y, uint64_t n_buckets, bool bidirectional) {
|
||||||
|
// TODO move to hparams if a T5 variant appears that uses a different value
|
||||||
|
const int64_t max_distance = 128;
|
||||||
|
|
||||||
|
if (bidirectional) {
|
||||||
|
n_buckets >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int64_t max_exact = n_buckets >> 1;
|
||||||
|
|
||||||
|
int32_t relative_position = x - y;
|
||||||
|
int32_t relative_bucket = 0;
|
||||||
|
|
||||||
|
if (bidirectional) {
|
||||||
|
relative_bucket += (relative_position > 0) * n_buckets;
|
||||||
|
relative_position = abs(relative_position);
|
||||||
|
} else {
|
||||||
|
relative_position = -std::min<int32_t>(relative_position, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t relative_position_if_large = floorf(max_exact + logf(1.0 * relative_position / max_exact) * (n_buckets - max_exact) / log(1.0 * max_distance / max_exact));
|
||||||
|
relative_position_if_large = std::min<int32_t>(relative_position_if_large, n_buckets - 1);
|
||||||
|
relative_bucket += (relative_position < max_exact ? relative_position : relative_position_if_large);
|
||||||
|
|
||||||
|
return relative_bucket;
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ struct llama_cparams;
|
|||||||
|
|
||||||
class llama_memory_i;
|
class llama_memory_i;
|
||||||
class llama_kv_cache_unified;
|
class llama_kv_cache_unified;
|
||||||
|
class llama_kv_cache_unified_iswa;
|
||||||
class llama_kv_cache_recurrent;
|
class llama_kv_cache_recurrent;
|
||||||
|
|
||||||
// certain models (typically multi-modal) can produce different types of graphs
|
// certain models (typically multi-modal) can produce different types of graphs
|
||||||
@ -255,6 +256,31 @@ public:
|
|||||||
|
|
||||||
void set_input(const llama_ubatch * ubatch) override;
|
void set_input(const llama_ubatch * ubatch) override;
|
||||||
|
|
||||||
|
ggml_tensor * get_kq_mask() const { return self_kq_mask_cnv; }
|
||||||
|
|
||||||
|
ggml_tensor * self_kq_mask = nullptr; // F32 [n_kv, n_batch]
|
||||||
|
ggml_tensor * self_kq_mask_cnv = nullptr; // [n_kv, n_batch]
|
||||||
|
|
||||||
|
const llama_hparams & hparams;
|
||||||
|
const llama_cparams & cparams;
|
||||||
|
|
||||||
|
const llama_kv_cache_unified * kv_self;
|
||||||
|
};
|
||||||
|
|
||||||
|
class llm_graph_input_attn_kv_unified_iswa : public llm_graph_input_i {
|
||||||
|
public:
|
||||||
|
llm_graph_input_attn_kv_unified_iswa(
|
||||||
|
const llama_hparams & hparams,
|
||||||
|
const llama_cparams & cparams,
|
||||||
|
const llama_kv_cache_unified_iswa * kv_self) :
|
||||||
|
hparams(hparams),
|
||||||
|
cparams(cparams),
|
||||||
|
kv_self(kv_self) {
|
||||||
|
}
|
||||||
|
~llm_graph_input_attn_kv_unified_iswa() = default;
|
||||||
|
|
||||||
|
void set_input(const llama_ubatch * ubatch) override;
|
||||||
|
|
||||||
ggml_tensor * get_kq_mask() const { return self_kq_mask_cnv; }
|
ggml_tensor * get_kq_mask() const { return self_kq_mask_cnv; }
|
||||||
ggml_tensor * get_kq_mask_swa() const { return self_kq_mask_swa_cnv; }
|
ggml_tensor * get_kq_mask_swa() const { return self_kq_mask_swa_cnv; }
|
||||||
|
|
||||||
@ -266,7 +292,7 @@ public:
|
|||||||
const llama_hparams & hparams;
|
const llama_hparams & hparams;
|
||||||
const llama_cparams & cparams;
|
const llama_cparams & cparams;
|
||||||
|
|
||||||
const llama_kv_cache_unified * kv_self;
|
const llama_kv_cache_unified_iswa * kv_self;
|
||||||
};
|
};
|
||||||
|
|
||||||
class llm_graph_input_attn_cross : public llm_graph_input_i {
|
class llm_graph_input_attn_cross : public llm_graph_input_i {
|
||||||
@ -378,7 +404,6 @@ struct llm_graph_context {
|
|||||||
const int64_t n_layer;
|
const int64_t n_layer;
|
||||||
const int64_t n_rot;
|
const int64_t n_rot;
|
||||||
const int64_t n_ctx; // user-specified context size (can be different from n_ctx_train)
|
const int64_t n_ctx; // user-specified context size (can be different from n_ctx_train)
|
||||||
const int64_t n_ctx_per_seq;
|
|
||||||
const int64_t n_head;
|
const int64_t n_head;
|
||||||
const int64_t n_head_kv;
|
const int64_t n_head_kv;
|
||||||
const int64_t n_embd_head_k;
|
const int64_t n_embd_head_k;
|
||||||
@ -507,13 +532,12 @@ struct llm_graph_context {
|
|||||||
|
|
||||||
ggml_tensor * build_attn_mha(
|
ggml_tensor * build_attn_mha(
|
||||||
ggml_cgraph * gf,
|
ggml_cgraph * gf,
|
||||||
ggml_tensor * q, // [n_embd_head_q, n_tokens, n_head_q]
|
ggml_tensor * q, // [n_embd_head_q, n_head_q, n_tokens]
|
||||||
ggml_tensor * k, // [n_embd_head_k, n_tokens, n_head_k]
|
ggml_tensor * k, // [n_embd_head_k, n_head_k, n_tokens]
|
||||||
ggml_tensor * v, // [n_embd_head_v, n_tokens, n_head_v] (v_trans == false)
|
ggml_tensor * v, // [n_embd_head_v, n_head_v, n_tokens] (v_trans == false)
|
||||||
ggml_tensor * kq_b,
|
ggml_tensor * kq_b,
|
||||||
ggml_tensor * kq_mask,
|
ggml_tensor * kq_mask,
|
||||||
ggml_tensor * v_mla, // [n_embd_head_v_mla, n_embd_head_v, n_head_v]
|
ggml_tensor * v_mla, // [n_embd_head_v_mla, n_embd_head_v, n_head_v]
|
||||||
bool v_trans,
|
|
||||||
float kq_scale) const;
|
float kq_scale) const;
|
||||||
|
|
||||||
llm_graph_input_attn_no_cache * build_attn_inp_no_cache() const;
|
llm_graph_input_attn_no_cache * build_attn_inp_no_cache() const;
|
||||||
@ -546,6 +570,21 @@ struct llm_graph_context {
|
|||||||
float kq_scale,
|
float kq_scale,
|
||||||
int il) const;
|
int il) const;
|
||||||
|
|
||||||
|
llm_graph_input_attn_kv_unified_iswa * build_attn_inp_kv_unified_iswa() const;
|
||||||
|
|
||||||
|
ggml_tensor * build_attn(
|
||||||
|
llm_graph_input_attn_kv_unified_iswa * inp,
|
||||||
|
ggml_cgraph * gf,
|
||||||
|
ggml_tensor * wo,
|
||||||
|
ggml_tensor * wo_b,
|
||||||
|
ggml_tensor * q_cur, // [n_embd_head_q, n_head_q, n_tokens]
|
||||||
|
ggml_tensor * k_cur, // [n_embd_head_k, n_head_k, n_tokens]
|
||||||
|
ggml_tensor * v_cur, // [n_embd_head_v, n_head_v, n_tokens]
|
||||||
|
ggml_tensor * kq_b,
|
||||||
|
ggml_tensor * v_mla, // [n_embd_head_v_mla, n_embd_head_v, n_head_v]
|
||||||
|
float kq_scale,
|
||||||
|
int il) const;
|
||||||
|
|
||||||
llm_graph_input_attn_cross * build_attn_inp_cross() const;
|
llm_graph_input_attn_cross * build_attn_inp_cross() const;
|
||||||
|
|
||||||
ggml_tensor * build_attn(
|
ggml_tensor * build_attn(
|
||||||
@ -596,3 +635,6 @@ struct llm_graph_context {
|
|||||||
ggml_tensor * cls_out,
|
ggml_tensor * cls_out,
|
||||||
ggml_tensor * cls_out_b) const;
|
ggml_tensor * cls_out_b) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: better name
|
||||||
|
int32_t llama_relative_position_bucket(llama_pos x, llama_pos y, uint64_t n_buckets, bool bidirectional);
|
||||||
|
@ -2,6 +2,22 @@
|
|||||||
|
|
||||||
#include "ggml.h"
|
#include "ggml.h"
|
||||||
|
|
||||||
|
void llama_hparams::set_swa_pattern(uint32_t n_pattern) {
|
||||||
|
for (uint32_t il = 0; il < n_layer; ++il) {
|
||||||
|
swa_layers[il] = n_pattern == 0 || (il % n_pattern < (n_pattern - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool llama_hparams::is_swa_any() const {
|
||||||
|
for (uint32_t il = 0; il < n_layer; ++il) {
|
||||||
|
if (swa_layers[il]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t llama_hparams::n_head(uint32_t il) const {
|
uint32_t llama_hparams::n_head(uint32_t il) const {
|
||||||
if (il < n_layer) {
|
if (il < n_layer) {
|
||||||
return n_head_arr[il];
|
return n_head_arr[il];
|
||||||
@ -72,7 +88,7 @@ uint32_t llama_hparams::n_embd_v_s() const {
|
|||||||
|
|
||||||
bool llama_hparams::is_swa(uint32_t il) const {
|
bool llama_hparams::is_swa(uint32_t il) const {
|
||||||
if (il < n_layer) {
|
if (il < n_layer) {
|
||||||
return n_swa > 0 && n_swa_pattern > 0 && il % n_swa_pattern < (n_swa_pattern - 1);
|
return swa_layers[il];
|
||||||
}
|
}
|
||||||
|
|
||||||
GGML_ABORT("fatal error");
|
GGML_ABORT("fatal error");
|
||||||
|
@ -14,6 +14,12 @@ enum llama_expert_gating_func_type {
|
|||||||
LLAMA_EXPERT_GATING_FUNC_TYPE_SIGMOID = 2,
|
LLAMA_EXPERT_GATING_FUNC_TYPE_SIGMOID = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum llama_swa_type {
|
||||||
|
LLAMA_SWA_TYPE_NONE = 0,
|
||||||
|
LLAMA_SWA_TYPE_STANDARD = 1,
|
||||||
|
LLAMA_SWA_TYPE_CHUNKED = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct llama_hparams_posnet {
|
struct llama_hparams_posnet {
|
||||||
uint32_t n_embd;
|
uint32_t n_embd;
|
||||||
uint32_t n_layer;
|
uint32_t n_layer;
|
||||||
@ -35,8 +41,6 @@ struct llama_hparams {
|
|||||||
uint32_t n_embd_features = 0;
|
uint32_t n_embd_features = 0;
|
||||||
uint32_t n_layer;
|
uint32_t n_layer;
|
||||||
uint32_t n_rot;
|
uint32_t n_rot;
|
||||||
uint32_t n_swa = 0; // sliding window attention (SWA)
|
|
||||||
uint32_t n_swa_pattern = 1; // by default, all layers use non-sliding-window attention
|
|
||||||
uint32_t n_embd_head_k; // dimension of keys (d_k). d_q is assumed to be the same, but there are n_head q heads, and only n_head_kv k-v heads
|
uint32_t n_embd_head_k; // dimension of keys (d_k). d_q is assumed to be the same, but there are n_head q heads, and only n_head_kv k-v heads
|
||||||
uint32_t n_embd_head_v; // dimension of values (d_v) aka n_embd_head
|
uint32_t n_embd_head_v; // dimension of values (d_v) aka n_embd_head
|
||||||
uint32_t n_expert = 0;
|
uint32_t n_expert = 0;
|
||||||
@ -96,6 +100,15 @@ struct llama_hparams {
|
|||||||
|
|
||||||
std::array<int, 4> rope_sections;
|
std::array<int, 4> rope_sections;
|
||||||
|
|
||||||
|
// Sliding Window Attention (SWA)
|
||||||
|
llama_swa_type swa_type = LLAMA_SWA_TYPE_NONE;
|
||||||
|
// the size of the sliding window (0 - no SWA)
|
||||||
|
uint32_t n_swa = 0;
|
||||||
|
// if swa_layers[il] == true, then layer il is SWA
|
||||||
|
// if swa_layers[il] == false, then layer il is dense (i.e. non-SWA)
|
||||||
|
// by default, all layers are dense
|
||||||
|
std::array<bool, LLAMA_MAX_LAYERS> swa_layers;
|
||||||
|
|
||||||
// for State Space Models
|
// for State Space Models
|
||||||
uint32_t ssm_d_conv = 0;
|
uint32_t ssm_d_conv = 0;
|
||||||
uint32_t ssm_d_inner = 0;
|
uint32_t ssm_d_inner = 0;
|
||||||
@ -116,11 +129,10 @@ struct llama_hparams {
|
|||||||
bool causal_attn = true;
|
bool causal_attn = true;
|
||||||
bool use_alibi = false;
|
bool use_alibi = false;
|
||||||
bool attn_soft_cap = false;
|
bool attn_soft_cap = false;
|
||||||
|
bool use_kq_norm = true;
|
||||||
|
|
||||||
|
// llama4
|
||||||
uint32_t n_moe_layer_step = 0;
|
uint32_t n_moe_layer_step = 0;
|
||||||
bool use_kq_norm = true;
|
|
||||||
uint32_t n_attn_chunk = 0;
|
|
||||||
// values below seems to be fixed on llama4
|
|
||||||
uint32_t n_no_rope_layer_step = 4;
|
uint32_t n_no_rope_layer_step = 4;
|
||||||
uint32_t n_attn_temp_floor_scale = 8192;
|
uint32_t n_attn_temp_floor_scale = 8192;
|
||||||
float f_attn_temp_scale = 0.1;
|
float f_attn_temp_scale = 0.1;
|
||||||
@ -133,6 +145,23 @@ struct llama_hparams {
|
|||||||
enum llama_rope_type rope_type = LLAMA_ROPE_TYPE_NONE;
|
enum llama_rope_type rope_type = LLAMA_ROPE_TYPE_NONE;
|
||||||
enum llama_rope_scaling_type rope_scaling_type_train = LLAMA_ROPE_SCALING_TYPE_NONE;
|
enum llama_rope_scaling_type rope_scaling_type_train = LLAMA_ROPE_SCALING_TYPE_NONE;
|
||||||
|
|
||||||
|
// this value n_pattern means that every nth layer is dense (i.e. non-SWA)
|
||||||
|
// note that if n_pattern == 0, all layers are SWA
|
||||||
|
// if n_pattern == 1, all layers are dense
|
||||||
|
// example: n_pattern = 3
|
||||||
|
// il == 0: swa
|
||||||
|
// il == 1: swa
|
||||||
|
// il == 2: dense
|
||||||
|
// il == 3: swa
|
||||||
|
// il == 4: swa
|
||||||
|
// il == 5: dense
|
||||||
|
// il == 6: swa
|
||||||
|
// etc ...
|
||||||
|
void set_swa_pattern(uint32_t n_pattern);
|
||||||
|
|
||||||
|
// return true if one of the layers is SWA
|
||||||
|
bool is_swa_any() const;
|
||||||
|
|
||||||
uint32_t n_head(uint32_t il = 0) const;
|
uint32_t n_head(uint32_t il = 0) const;
|
||||||
|
|
||||||
uint32_t n_head_kv(uint32_t il = 0) const;
|
uint32_t n_head_kv(uint32_t il = 0) const;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,10 +4,12 @@
|
|||||||
#include "llama-io.h"
|
#include "llama-io.h"
|
||||||
#include "llama-graph.h"
|
#include "llama-graph.h"
|
||||||
#include "llama-memory.h"
|
#include "llama-memory.h"
|
||||||
|
#include "llama-kv-cells.h"
|
||||||
|
|
||||||
#include "ggml-cpp.h"
|
#include "ggml-cpp.h"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct llama_cparams;
|
struct llama_cparams;
|
||||||
@ -34,12 +36,16 @@ struct llama_kv_cache : public llama_memory_i {
|
|||||||
virtual void defrag_sched(float thold) = 0;
|
virtual void defrag_sched(float thold) = 0;
|
||||||
|
|
||||||
// simulate full cache, used for allocating worst-case compute buffers
|
// simulate full cache, used for allocating worst-case compute buffers
|
||||||
|
// TODO: remove
|
||||||
virtual void set_full() = 0;
|
virtual void set_full() = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// batch processing
|
// batch processing
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// =============================================================================================================
|
||||||
|
// TODO: refactor and simplify this [TAG: KV_API]
|
||||||
|
|
||||||
virtual llama_sbatch sbatch_init(const llama_batch & batch, bool logits_all) = 0;
|
virtual llama_sbatch sbatch_init(const llama_batch & batch, bool logits_all) = 0;
|
||||||
|
|
||||||
// different KV caches require different batch splitting strategies
|
// different KV caches require different batch splitting strategies
|
||||||
@ -48,11 +54,10 @@ struct llama_kv_cache : public llama_memory_i {
|
|||||||
// find an empty slot of size "n_tokens" in the cache
|
// find an empty slot of size "n_tokens" in the cache
|
||||||
virtual bool find_slot(const llama_ubatch & batch) = 0;
|
virtual bool find_slot(const llama_ubatch & batch) = 0;
|
||||||
|
|
||||||
|
// =============================================================================================================
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
virtual int32_t get_n_tokens() const = 0;
|
virtual bool get_can_shift() const = 0;
|
||||||
virtual int32_t get_used_cells() const = 0; // TODO: remove, this is too-specific to the unified cache
|
|
||||||
virtual llama_pos get_pos_max() const = 0;
|
|
||||||
virtual bool get_can_shift() const = 0;
|
|
||||||
|
|
||||||
bool get_can_edit() const override { return get_can_shift(); }
|
bool get_can_edit() const override { return get_can_shift(); }
|
||||||
|
|
||||||
@ -87,38 +92,25 @@ private:
|
|||||||
// llama_kv_cache_unified
|
// llama_kv_cache_unified
|
||||||
//
|
//
|
||||||
|
|
||||||
// TODO: add notion of max sequences
|
|
||||||
class llama_kv_cache_unified : public llama_kv_cache {
|
class llama_kv_cache_unified : public llama_kv_cache {
|
||||||
public:
|
public:
|
||||||
struct kv_cell {
|
|
||||||
llama_pos pos = -1;
|
|
||||||
llama_pos delta = 0;
|
|
||||||
|
|
||||||
std::set<llama_seq_id> seq_id;
|
|
||||||
|
|
||||||
bool has_seq_id(const llama_seq_id & id) const {
|
|
||||||
return seq_id.find(id) != seq_id.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_empty() const {
|
|
||||||
return seq_id.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_same_seq(const kv_cell & other) const {
|
|
||||||
return seq_id == other.seq_id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint32_t get_padding(const llama_cparams & cparams);
|
static uint32_t get_padding(const llama_cparams & cparams);
|
||||||
|
|
||||||
|
// this callback is used to filter out layers that should not be included in the cache
|
||||||
|
using layer_filter_cb = std::function<bool(int32_t il)>;
|
||||||
|
|
||||||
llama_kv_cache_unified(
|
llama_kv_cache_unified(
|
||||||
const llama_model & model,
|
const llama_model & model,
|
||||||
ggml_type type_k,
|
layer_filter_cb && filter,
|
||||||
ggml_type type_v,
|
ggml_type type_k,
|
||||||
bool v_trans,
|
ggml_type type_v,
|
||||||
bool offload,
|
bool v_trans,
|
||||||
uint32_t kv_size,
|
bool offload,
|
||||||
uint32_t padding);
|
uint32_t kv_size,
|
||||||
|
uint32_t n_seq_max,
|
||||||
|
uint32_t n_pad,
|
||||||
|
uint32_t n_swa,
|
||||||
|
llama_swa_type swa_type);
|
||||||
|
|
||||||
~llama_kv_cache_unified() = default;
|
~llama_kv_cache_unified() = default;
|
||||||
|
|
||||||
@ -130,10 +122,11 @@ public:
|
|||||||
|
|
||||||
bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) override;
|
bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) override;
|
||||||
void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) override;
|
void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) override;
|
||||||
void seq_keep(llama_seq_id seq_id) override;
|
void seq_keep(llama_seq_id seq_id) override;
|
||||||
void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos delta) override;
|
void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos shift) override;
|
||||||
void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) override;
|
void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) override;
|
||||||
|
|
||||||
|
llama_pos seq_pos_min(llama_seq_id seq_id) const override;
|
||||||
llama_pos seq_pos_max(llama_seq_id seq_id) const override;
|
llama_pos seq_pos_max(llama_seq_id seq_id) const override;
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -150,7 +143,6 @@ public:
|
|||||||
void set_full() override;
|
void set_full() override;
|
||||||
|
|
||||||
llama_sbatch sbatch_init(const llama_batch & batch, bool logits_all) override;
|
llama_sbatch sbatch_init(const llama_batch & batch, bool logits_all) override;
|
||||||
|
|
||||||
llama_ubatch ubatch_next(llama_sbatch & sbatch, uint32_t n_ubatch, bool embd_pooled) const override;
|
llama_ubatch ubatch_next(llama_sbatch & sbatch, uint32_t n_ubatch, bool embd_pooled) const override;
|
||||||
|
|
||||||
// updates the cache head
|
// updates the cache head
|
||||||
@ -158,50 +150,94 @@ public:
|
|||||||
// to the first cell of the slot.
|
// to the first cell of the slot.
|
||||||
bool find_slot(const llama_ubatch & batch) override;
|
bool find_slot(const llama_ubatch & batch) override;
|
||||||
|
|
||||||
int32_t get_n_tokens() const override;
|
|
||||||
int32_t get_used_cells() const override;
|
|
||||||
|
|
||||||
// TODO: better data structures to reduce the cost of this operation
|
|
||||||
llama_pos get_pos_max() const override;
|
|
||||||
|
|
||||||
bool get_can_shift() const override;
|
bool get_can_shift() const override;
|
||||||
|
|
||||||
// state write/load
|
// state write/load
|
||||||
|
|
||||||
void state_write(llama_io_write_i & io, llama_seq_id seq_id = -1) const override;
|
void state_write(llama_io_write_i & io, llama_seq_id seq_id = -1) const override;
|
||||||
void state_read (llama_io_read_i & io, llama_seq_id seq_id = -1) override;
|
void state_read (llama_io_read_i & io, llama_seq_id seq_id = -1) override;
|
||||||
|
|
||||||
uint32_t head = 0; // the location where the batch will be placed in the cache (see find_slot())
|
//
|
||||||
uint32_t size = 0; // total number of cells, shared across all sequences
|
// llama_kv_cache_unified specific API
|
||||||
uint32_t used = 0; // used cells (i.e. at least one seq_id)
|
//
|
||||||
|
|
||||||
// computed before each graph build
|
uint32_t get_n() const;
|
||||||
uint32_t n = 0;
|
uint32_t get_size() const;
|
||||||
|
|
||||||
std::vector<kv_cell> cells;
|
// get views of the current state of the cache
|
||||||
|
ggml_tensor * get_k(ggml_context * ctx, int32_t il) const;
|
||||||
|
ggml_tensor * get_v(ggml_context * ctx, int32_t il) const;
|
||||||
|
|
||||||
std::vector<ggml_tensor *> k_l; // per layer
|
// store k_cur and v_cur in the cache based on the current head location
|
||||||
std::vector<ggml_tensor *> v_l;
|
ggml_tensor * cpy_k(ggml_context * ctx, ggml_tensor * k_cur, int32_t il) const;
|
||||||
|
ggml_tensor * cpy_v(ggml_context * ctx, ggml_tensor * v_cur, int32_t il) const;
|
||||||
|
|
||||||
|
void prune_swa(llama_seq_id seq_id, llama_pos pmin, llama_pos pmax);
|
||||||
|
|
||||||
|
void set_input_kq_mask (ggml_tensor * dst, const llama_ubatch * ubatch, bool causal_attn) const;
|
||||||
|
void set_input_k_shift (ggml_tensor * dst) const;
|
||||||
|
void set_input_pos_bucket(ggml_tensor * dst, const llama_ubatch * ubatch) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const llama_model & model;
|
const llama_model & model;
|
||||||
const llama_hparams & hparams;
|
const llama_hparams & hparams;
|
||||||
|
|
||||||
bool has_shift = false;
|
struct kv_layer {
|
||||||
bool do_defrag = false;
|
// layer index in the model
|
||||||
|
// note: can be different from the layer index in the KV cache
|
||||||
|
uint32_t il;
|
||||||
|
|
||||||
|
ggml_tensor * k;
|
||||||
|
ggml_tensor * v;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool do_defrag = false;
|
||||||
bool v_trans = true; // the value tensor is transposed
|
bool v_trans = true; // the value tensor is transposed
|
||||||
bool can_shift = false;
|
|
||||||
|
uint32_t head = 0; // the location where the batch will be placed in the cache (see find_slot())
|
||||||
|
|
||||||
|
// computed before each graph build
|
||||||
|
// TODO: cells should start to maintain this value dynamically based on the edits
|
||||||
|
uint32_t n = 0;
|
||||||
|
|
||||||
|
const uint32_t n_seq_max = 1;
|
||||||
|
|
||||||
// required padding
|
// required padding
|
||||||
uint32_t padding = 1;
|
const uint32_t n_pad = 1;
|
||||||
|
|
||||||
ggml_type type_k = GGML_TYPE_F16;
|
// SWA
|
||||||
ggml_type type_v = GGML_TYPE_F16;
|
const uint32_t n_swa = 0;
|
||||||
|
|
||||||
|
const llama_swa_type swa_type = LLAMA_SWA_TYPE_NONE;
|
||||||
|
|
||||||
std::vector<ggml_context_ptr> ctxs;
|
std::vector<ggml_context_ptr> ctxs;
|
||||||
std::vector<ggml_backend_buffer_ptr> bufs;
|
std::vector<ggml_backend_buffer_ptr> bufs;
|
||||||
|
|
||||||
|
llama_kv_cells_unified cells;
|
||||||
|
|
||||||
|
std::vector<kv_layer> layers;
|
||||||
|
|
||||||
|
// model layer id -> KV cache layer id
|
||||||
|
std::unordered_map<int32_t, int32_t> map_layer_ids;
|
||||||
|
|
||||||
|
// recovery information used to restore the KV cells to their original state in case of a failure
|
||||||
|
// TODO: do not store as a state in the llama_kv_cache object, instead return upon batch preparation
|
||||||
|
// to achieve that, first need to refactor the llama_kv_cache interface [TAG: KV_API]
|
||||||
|
struct {
|
||||||
|
void clear() {
|
||||||
|
states.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct state {
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
llama_kv_cells_unified cells;
|
||||||
|
};
|
||||||
|
|
||||||
|
// stack with the partial states before each ubatch
|
||||||
|
std::vector<state> states;
|
||||||
|
} recovery;
|
||||||
|
|
||||||
// defrag
|
// defrag
|
||||||
struct {
|
struct {
|
||||||
std::vector<uint32_t> ids;
|
std::vector<uint32_t> ids;
|
||||||
@ -210,25 +246,13 @@ private:
|
|||||||
// return true if cells have been moved
|
// return true if cells have been moved
|
||||||
bool defrag_prepare(int32_t n_max_nodes);
|
bool defrag_prepare(int32_t n_max_nodes);
|
||||||
|
|
||||||
// commit/restore cache
|
|
||||||
struct slot_range {
|
|
||||||
uint32_t c0 = 0; // note: these are cell indices, not sequence positions
|
|
||||||
uint32_t c1 = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// pending cell updates that are not yet committed
|
|
||||||
struct {
|
|
||||||
std::vector<slot_range> ranges;
|
|
||||||
} pending;
|
|
||||||
|
|
||||||
// find how many cells are currently in use
|
|
||||||
uint32_t cell_max() const;
|
|
||||||
|
|
||||||
size_t total_size() const;
|
size_t total_size() const;
|
||||||
|
|
||||||
size_t size_k_bytes() const;
|
size_t size_k_bytes() const;
|
||||||
size_t size_v_bytes() const;
|
size_t size_v_bytes() const;
|
||||||
|
|
||||||
|
bool is_masked_swa(llama_pos p0, llama_pos p1) const;
|
||||||
|
|
||||||
ggml_tensor * build_rope_shift(
|
ggml_tensor * build_rope_shift(
|
||||||
const llama_cparams & cparams,
|
const llama_cparams & cparams,
|
||||||
ggml_context * ctx,
|
ggml_context * ctx,
|
||||||
@ -255,6 +279,100 @@ private:
|
|||||||
bool state_read_data(llama_io_read_i & io, uint32_t cell_count);
|
bool state_read_data(llama_io_read_i & io, uint32_t cell_count);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// llama_kv_cache_unified_iswa
|
||||||
|
//
|
||||||
|
|
||||||
|
// utilizes two instances of llama_kv_cache_unified
|
||||||
|
// the first instance is for the non-SWA layers of the model and the second instance is for the SWA layers
|
||||||
|
// upon successful commit, the SWA cache removes old tokens outside the n_swa window
|
||||||
|
|
||||||
|
class llama_kv_cache_unified_iswa : public llama_kv_cache {
|
||||||
|
public:
|
||||||
|
llama_kv_cache_unified_iswa(
|
||||||
|
const llama_model & model,
|
||||||
|
ggml_type type_k,
|
||||||
|
ggml_type type_v,
|
||||||
|
bool v_trans,
|
||||||
|
bool offload,
|
||||||
|
bool swa_full,
|
||||||
|
uint32_t kv_size,
|
||||||
|
uint32_t n_seq_max,
|
||||||
|
uint32_t n_batch,
|
||||||
|
uint32_t n_pad);
|
||||||
|
|
||||||
|
~llama_kv_cache_unified_iswa() = default;
|
||||||
|
|
||||||
|
//
|
||||||
|
// llama_memory_i
|
||||||
|
//
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
|
|
||||||
|
bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) override;
|
||||||
|
void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) override;
|
||||||
|
void seq_keep(llama_seq_id seq_id) override;
|
||||||
|
void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos shift) override;
|
||||||
|
void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) override;
|
||||||
|
|
||||||
|
llama_pos seq_pos_min(llama_seq_id seq_id) const override;
|
||||||
|
llama_pos seq_pos_max(llama_seq_id seq_id) const override;
|
||||||
|
|
||||||
|
//
|
||||||
|
// llama_kv_cache
|
||||||
|
//
|
||||||
|
|
||||||
|
void restore() override;
|
||||||
|
void commit() override;
|
||||||
|
|
||||||
|
bool update(llama_context & ctx) override;
|
||||||
|
|
||||||
|
void defrag_sched(float thold) override;
|
||||||
|
|
||||||
|
void set_full() override;
|
||||||
|
|
||||||
|
llama_sbatch sbatch_init(const llama_batch & batch, bool logits_all) override;
|
||||||
|
llama_ubatch ubatch_next(llama_sbatch & sbatch, uint32_t n_ubatch, bool embd_pooled) const override;
|
||||||
|
|
||||||
|
bool find_slot(const llama_ubatch & batch) override;
|
||||||
|
|
||||||
|
bool get_can_shift() const override;
|
||||||
|
|
||||||
|
// state write/load
|
||||||
|
|
||||||
|
void state_write(llama_io_write_i & io, llama_seq_id seq_id = -1) const override;
|
||||||
|
void state_read (llama_io_read_i & io, llama_seq_id seq_id = -1) override;
|
||||||
|
|
||||||
|
//
|
||||||
|
// llama_kv_cache_unified_iswa specific API
|
||||||
|
//
|
||||||
|
|
||||||
|
llama_kv_cache_unified * get_kv_base() const;
|
||||||
|
llama_kv_cache_unified * get_kv_swa () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const llama_hparams & hparams;
|
||||||
|
|
||||||
|
bool do_prune = true;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct entry {
|
||||||
|
llama_pos pmin;
|
||||||
|
llama_pos pmax;
|
||||||
|
};
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
pos.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// used to perform SWA pruning of old tokens
|
||||||
|
std::unordered_map<llama_seq_id, entry> pos;
|
||||||
|
} pending;
|
||||||
|
|
||||||
|
std::unique_ptr<llama_kv_cache_unified> kv_base;
|
||||||
|
std::unique_ptr<llama_kv_cache_unified> kv_swa;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// llama_kv_cache_recurrent
|
// llama_kv_cache_recurrent
|
||||||
//
|
//
|
||||||
@ -286,7 +404,8 @@ public:
|
|||||||
ggml_type type_k,
|
ggml_type type_k,
|
||||||
ggml_type type_v,
|
ggml_type type_v,
|
||||||
bool offload,
|
bool offload,
|
||||||
uint32_t kv_size);
|
uint32_t kv_size,
|
||||||
|
uint32_t n_seq_max);
|
||||||
|
|
||||||
~llama_kv_cache_recurrent() = default;
|
~llama_kv_cache_recurrent() = default;
|
||||||
|
|
||||||
@ -298,10 +417,11 @@ public:
|
|||||||
|
|
||||||
bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) override;
|
bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) override;
|
||||||
void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) override;
|
void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) override;
|
||||||
void seq_keep(llama_seq_id seq_id) override;
|
void seq_keep(llama_seq_id seq_id) override;
|
||||||
void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos delta) override;
|
void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos shift) override;
|
||||||
void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) override;
|
void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) override;
|
||||||
|
|
||||||
|
llama_pos seq_pos_min(llama_seq_id seq_id) const override;
|
||||||
llama_pos seq_pos_max(llama_seq_id seq_id) const override;
|
llama_pos seq_pos_max(llama_seq_id seq_id) const override;
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -311,24 +431,17 @@ public:
|
|||||||
void restore() override;
|
void restore() override;
|
||||||
void commit() override;
|
void commit() override;
|
||||||
|
|
||||||
bool update(llama_context & lctx) override;
|
bool update(llama_context & ctx) override;
|
||||||
|
|
||||||
void defrag_sched(float thold) override;
|
void defrag_sched(float thold) override;
|
||||||
|
|
||||||
void set_full() override;
|
void set_full() override;
|
||||||
|
|
||||||
llama_sbatch sbatch_init(const llama_batch & batch, bool logits_all) override;
|
llama_sbatch sbatch_init(const llama_batch & batch, bool logits_all) override;
|
||||||
|
|
||||||
llama_ubatch ubatch_next(llama_sbatch & sbatch, uint32_t n_ubatch, bool embd_pooled) const override;
|
llama_ubatch ubatch_next(llama_sbatch & sbatch, uint32_t n_ubatch, bool embd_pooled) const override;
|
||||||
|
|
||||||
bool find_slot(const llama_ubatch & batch) override;
|
bool find_slot(const llama_ubatch & batch) override;
|
||||||
|
|
||||||
int32_t get_n_tokens() const override;
|
|
||||||
int32_t get_used_cells() const override;
|
|
||||||
|
|
||||||
// TODO: better data structures to reduce the cost of this operation
|
|
||||||
llama_pos get_pos_max() const override;
|
|
||||||
|
|
||||||
bool get_can_shift() const override;
|
bool get_can_shift() const override;
|
||||||
|
|
||||||
// TODO: temporary methods - they are not really const as they do const_cast<>, fix this
|
// TODO: temporary methods - they are not really const as they do const_cast<>, fix this
|
||||||
@ -368,8 +481,7 @@ private:
|
|||||||
std::vector<slot_range> ranges;
|
std::vector<slot_range> ranges;
|
||||||
} pending;
|
} pending;
|
||||||
|
|
||||||
ggml_type type_k = GGML_TYPE_F16;
|
const uint32_t n_seq_max = 1;
|
||||||
ggml_type type_v = GGML_TYPE_F16;
|
|
||||||
|
|
||||||
std::vector<ggml_context_ptr> ctxs;
|
std::vector<ggml_context_ptr> ctxs;
|
||||||
std::vector<ggml_backend_buffer_ptr> bufs;
|
std::vector<ggml_backend_buffer_ptr> bufs;
|
||||||
@ -388,12 +500,3 @@ private:
|
|||||||
bool state_read_meta(llama_io_read_i & io, uint32_t cell_count, llama_seq_id dest_seq_id = -1);
|
bool state_read_meta(llama_io_read_i & io, uint32_t cell_count, llama_seq_id dest_seq_id = -1);
|
||||||
bool state_read_data(llama_io_read_i & io, uint32_t cell_count);
|
bool state_read_data(llama_io_read_i & io, uint32_t cell_count);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// kv cache view
|
|
||||||
//
|
|
||||||
|
|
||||||
llama_kv_cache_view llama_kv_cache_view_init(const llama_kv_cache & kv, int32_t n_seq_max);
|
|
||||||
|
|
||||||
void llama_kv_cache_view_update(llama_kv_cache_view * view, const llama_kv_cache * kv);
|
|
||||||
|
379
examples/talk-llama/llama-kv-cells.h
Normal file
379
examples/talk-llama/llama-kv-cells.h
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "llama.h"
|
||||||
|
#include "llama-cparams.h"
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
#include <cassert>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
// meta information about KV cells that can be part of multiple sequences at the same time
|
||||||
|
// TODO: add unit tests
|
||||||
|
class llama_kv_cells_unified {
|
||||||
|
public:
|
||||||
|
void reset() {
|
||||||
|
for (uint32_t i = 0; i < pos.size(); ++i) {
|
||||||
|
pos[i] = -1;
|
||||||
|
shift[i] = 0;
|
||||||
|
seq[i].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
has_shift = false;
|
||||||
|
|
||||||
|
used.clear();
|
||||||
|
|
||||||
|
for (uint32_t s = 0; s < LLAMA_MAX_PARALLEL_SEQUENCES; ++s) {
|
||||||
|
seq_pos[s].clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_shift() {
|
||||||
|
has_shift = false;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < shift.size(); ++i) {
|
||||||
|
shift[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t size() const {
|
||||||
|
return pos.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(uint32_t n) {
|
||||||
|
pos.resize(n);
|
||||||
|
shift.resize(n);
|
||||||
|
seq.resize(n);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_empty(uint32_t i) const {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert((pos[i] < 0 && pos[i] == -1) || pos[i] >= 0);
|
||||||
|
|
||||||
|
return pos[i] == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_used() const {
|
||||||
|
return used.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// the index of the first cell that is used
|
||||||
|
// return 0 if no cells are used
|
||||||
|
uint32_t used_min() const {
|
||||||
|
return used.empty() ? 0 : *used.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// the index of the last cell that is used + 1
|
||||||
|
// return 0 if no cells are used
|
||||||
|
uint32_t used_max_p1() const {
|
||||||
|
#if 0
|
||||||
|
if (!seq_pos[0].empty()) printf("kv_cells: min[0] = %5d, max[0] = %5d\n", *seq_pos[0].begin(), *seq_pos[0].rbegin());
|
||||||
|
if (!seq_pos[1].empty()) printf("kv_cells: min[1] = %5d, max[1] = %5d\n", *seq_pos[1].begin(), *seq_pos[1].rbegin());
|
||||||
|
if (!seq_pos[2].empty()) printf("kv_cells: min[2] = %5d, max[2] = %5d\n", *seq_pos[2].begin(), *seq_pos[2].rbegin());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return used.empty() ? 0 : *used.rbegin() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_has_shift() const {
|
||||||
|
return has_shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
// move cell isrc to idst (used during defrag)
|
||||||
|
void mv(uint32_t isrc, uint32_t idst) {
|
||||||
|
assert(isrc < pos.size());
|
||||||
|
assert(idst < pos.size());
|
||||||
|
|
||||||
|
pos [idst] = pos [isrc];
|
||||||
|
shift[idst] = shift[isrc];
|
||||||
|
seq [idst] = seq [isrc];
|
||||||
|
|
||||||
|
pos [isrc] = -1;
|
||||||
|
shift[isrc] = 0;
|
||||||
|
seq [isrc].reset();
|
||||||
|
|
||||||
|
used.erase (isrc);
|
||||||
|
used.insert(idst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the state of cells [i, i + n) (used for save/restore the state of the cells)
|
||||||
|
llama_kv_cells_unified cp(uint32_t i, uint32_t n) const {
|
||||||
|
assert(i + n <= pos.size());
|
||||||
|
|
||||||
|
llama_kv_cells_unified res;
|
||||||
|
|
||||||
|
res.resize(n);
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < n; ++j) {
|
||||||
|
res.pos[j] = pos[i + j];
|
||||||
|
res.seq[j] = seq[i + j];
|
||||||
|
|
||||||
|
assert(shift[i + j] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the state of cells [i, i + other.pos.size()) (used for save/restore the state of the cells)
|
||||||
|
void set(uint32_t i, const llama_kv_cells_unified & other) {
|
||||||
|
assert(i + other.pos.size() <= pos.size());
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < other.pos.size(); ++j) {
|
||||||
|
if (pos[i + j] == -1 && other.pos[j] != -1) {
|
||||||
|
used.insert(i + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos[i + j] != -1 && other.pos[j] == -1) {
|
||||||
|
used.erase(i + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos[i + j] != -1) {
|
||||||
|
seq_pos_rm(i + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos[i + j] = other.pos[j];
|
||||||
|
seq[i + j] = other.seq[j];
|
||||||
|
|
||||||
|
if (pos[i + j] != -1) {
|
||||||
|
seq_pos_add(i + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(shift[i + j] == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: call only if the cell has seq_id
|
||||||
|
// return true if the cell becomes empty
|
||||||
|
bool seq_rm(uint32_t i, llama_seq_id seq_id) {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert(seq[i].test(seq_id));
|
||||||
|
assert(pos[i] != -1);
|
||||||
|
assert(seq_id >= 0);
|
||||||
|
|
||||||
|
seq[i].reset(seq_id);
|
||||||
|
seq_pos[seq_id].erase(pos[i]);
|
||||||
|
|
||||||
|
if (seq[i].none()) {
|
||||||
|
pos[i] = -1;
|
||||||
|
|
||||||
|
used.erase(i);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if the cell becomes empty (i.e. it did not contain seq_id before the call)
|
||||||
|
bool seq_keep(uint32_t i, llama_seq_id seq_id) {
|
||||||
|
assert(i < pos.size());
|
||||||
|
|
||||||
|
if (seq[i].test(seq_id)) {
|
||||||
|
seq_pos_rm(i);
|
||||||
|
seq[i].reset();
|
||||||
|
|
||||||
|
seq[i].set(seq_id);
|
||||||
|
seq_pos[seq_id].insert(pos[i]);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seq[i].any()) {
|
||||||
|
seq_pos_rm(i);
|
||||||
|
seq[i].reset();
|
||||||
|
|
||||||
|
pos[i] = -1;
|
||||||
|
|
||||||
|
used.erase(i);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pos[i] == -1);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool seq_has(uint32_t i, llama_seq_id seq_id) const {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert(seq_id >= 0);
|
||||||
|
|
||||||
|
return seq[i].test(seq_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: call only if the cell is not empty and the seq_id is not in the cell
|
||||||
|
void seq_add(uint32_t i, llama_seq_id seq_id) {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert(pos[i] != -1);
|
||||||
|
assert(!seq[i].test(seq_id));
|
||||||
|
|
||||||
|
seq[i].set(seq_id);
|
||||||
|
seq_pos[seq_id].insert(pos[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the minimum position of sequence seq_id currently present in any of the cells
|
||||||
|
// return -1 if the sequence is not present
|
||||||
|
llama_pos seq_pos_min(llama_seq_id seq_id) const {
|
||||||
|
assert(seq_id >= 0);
|
||||||
|
assert(seq_id < LLAMA_MAX_PARALLEL_SEQUENCES);
|
||||||
|
|
||||||
|
if (seq_pos[seq_id].empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *seq_pos[seq_id].begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// the maximum position of sequence seq_id currently present in any of the cells
|
||||||
|
// return -1 if the sequence is not present
|
||||||
|
llama_pos seq_pos_max(llama_seq_id seq_id) const {
|
||||||
|
assert(seq_id >= 0);
|
||||||
|
assert(seq_id < LLAMA_MAX_PARALLEL_SEQUENCES);
|
||||||
|
|
||||||
|
if (seq_pos[seq_id].empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *seq_pos[seq_id].rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: call only if the cell is not empty
|
||||||
|
llama_pos pos_get(uint32_t i) const {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert(pos[i] != -1);
|
||||||
|
|
||||||
|
return pos[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: call only if the cell is not empty
|
||||||
|
llama_pos get_shift(uint32_t i) const {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert(pos[i] != -1);
|
||||||
|
|
||||||
|
return shift[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if a cell is not empty and its position is within [p0, p1)
|
||||||
|
bool pos_in(uint32_t i, llama_pos p0, llama_pos p1) const {
|
||||||
|
assert(i < pos.size());
|
||||||
|
|
||||||
|
return pos[i] >= p0 && pos[i] < p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the position of an empty cell
|
||||||
|
// does not modify "has_shift"
|
||||||
|
// note: call only if the cell is empty
|
||||||
|
void pos_set(uint32_t i, llama_pos p) {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert(pos[i] == -1);
|
||||||
|
|
||||||
|
pos[i] = p;
|
||||||
|
|
||||||
|
used.insert(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pos[i] = pos[i] + d
|
||||||
|
// sets "has_shift" to true
|
||||||
|
// note: call only if the cell is not empty
|
||||||
|
bool pos_add(uint32_t i, llama_pos d) {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert(pos[i] != -1);
|
||||||
|
|
||||||
|
seq_pos_rm(i);
|
||||||
|
|
||||||
|
pos[i] += d;
|
||||||
|
shift[i] += d;
|
||||||
|
|
||||||
|
seq_pos_add(i);
|
||||||
|
|
||||||
|
has_shift = true;
|
||||||
|
|
||||||
|
if (pos[i] < 0) {
|
||||||
|
seq_pos_rm(i);
|
||||||
|
|
||||||
|
seq[i].reset();
|
||||||
|
pos[i] = -1;
|
||||||
|
|
||||||
|
used.erase(i);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pos[i] = pos[i] / d
|
||||||
|
// sets "has_shift" to true
|
||||||
|
// note: call only if the cell is not empty
|
||||||
|
void pos_div(uint32_t i, int d) {
|
||||||
|
assert(i < pos.size());
|
||||||
|
assert(pos[i] != -1);
|
||||||
|
|
||||||
|
const llama_pos p_old = pos[i];
|
||||||
|
|
||||||
|
seq_pos_rm(i);
|
||||||
|
|
||||||
|
pos[i] /= d;
|
||||||
|
shift[i] += p_old - pos[i];
|
||||||
|
|
||||||
|
seq_pos_add(i);
|
||||||
|
|
||||||
|
has_shift = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool has_shift = false;
|
||||||
|
|
||||||
|
// set of indices of used cells (i.e. pos[i] != -1, allowed to not have any seq_id)
|
||||||
|
std::set<uint32_t> used;
|
||||||
|
|
||||||
|
std::vector<llama_pos> pos;
|
||||||
|
|
||||||
|
// this array accumulates any applied shifts to the pos array since the last reset_shift() call
|
||||||
|
// this is used to queue multiple updates to the pos array, which in the end can be applied in one go:
|
||||||
|
//
|
||||||
|
// cells.pos_add(x, shift_x);
|
||||||
|
// cells.pos_div(y, shift_y);
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// if (cells.has_shift()) {
|
||||||
|
// for (int i = 0; i < n; ++i) {
|
||||||
|
// auto shift_i = cells.get_shift(i);
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// cells.reset_shift();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
std::vector<llama_pos> shift;
|
||||||
|
|
||||||
|
using bits_t = std::bitset<LLAMA_MAX_PARALLEL_SEQUENCES>;
|
||||||
|
|
||||||
|
// the bitset seq[i] tells us which sequences are currently occupying the i-th cell
|
||||||
|
std::vector<bits_t> seq;
|
||||||
|
|
||||||
|
// the set seq_pos[s] tells us which positions are currently present for sequence s
|
||||||
|
// this way seq_pos[s].begin() and seq_pos[s].rbegin() give us the min/max positions currently in the cache
|
||||||
|
std::set<llama_pos> seq_pos[LLAMA_MAX_PARALLEL_SEQUENCES];
|
||||||
|
|
||||||
|
// helper functions for updating `seq_pos`, once cell at a time:
|
||||||
|
|
||||||
|
// remove cell i
|
||||||
|
void seq_pos_rm(uint32_t i) {
|
||||||
|
for (int s = 0; s < LLAMA_MAX_PARALLEL_SEQUENCES; ++s) {
|
||||||
|
if (seq[i].test(s)) {
|
||||||
|
seq_pos[s].erase(pos[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add cell i
|
||||||
|
void seq_pos_add(uint32_t i) {
|
||||||
|
for (int s = 0; s < LLAMA_MAX_PARALLEL_SEQUENCES; ++s) {
|
||||||
|
if (seq[i].test(s)) {
|
||||||
|
seq_pos[s].insert(pos[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -7,8 +7,8 @@ struct llama_memory_params {
|
|||||||
ggml_type type_k;
|
ggml_type type_k;
|
||||||
ggml_type type_v;
|
ggml_type type_v;
|
||||||
|
|
||||||
// parameters for other types of memory
|
// use full-size SWA cache
|
||||||
// ...
|
bool swa_full;
|
||||||
};
|
};
|
||||||
|
|
||||||
// general concept of LLM memory
|
// general concept of LLM memory
|
||||||
@ -22,9 +22,10 @@ public:
|
|||||||
virtual bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) = 0;
|
virtual bool seq_rm (llama_seq_id seq_id, llama_pos p0, llama_pos p1) = 0;
|
||||||
virtual void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) = 0;
|
virtual void seq_cp (llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) = 0;
|
||||||
virtual void seq_keep(llama_seq_id seq_id) = 0;
|
virtual void seq_keep(llama_seq_id seq_id) = 0;
|
||||||
virtual void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos delta) = 0;
|
virtual void seq_add (llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos shift) = 0;
|
||||||
virtual void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) = 0;
|
virtual void seq_div (llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) = 0;
|
||||||
|
|
||||||
|
virtual llama_pos seq_pos_min(llama_seq_id seq_id) const = 0;
|
||||||
virtual llama_pos seq_pos_max(llama_seq_id seq_id) const = 0;
|
virtual llama_pos seq_pos_max(llama_seq_id seq_id) const = 0;
|
||||||
|
|
||||||
virtual bool get_can_edit() const = 0;
|
virtual bool get_can_edit() const = 0;
|
||||||
|
@ -463,11 +463,14 @@ void llama_model::load_hparams(llama_model_loader & ml) {
|
|||||||
GGML_ASSERT(hparams.n_expert_used == 0);
|
GGML_ASSERT(hparams.n_expert_used == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// zero-out the array hparams
|
|
||||||
std::fill(hparams.n_head_arr.begin(), hparams.n_head_arr.end(), 0);
|
std::fill(hparams.n_head_arr.begin(), hparams.n_head_arr.end(), 0);
|
||||||
std::fill(hparams.n_head_kv_arr.begin(), hparams.n_head_kv_arr.end(), 0);
|
std::fill(hparams.n_head_kv_arr.begin(), hparams.n_head_kv_arr.end(), 0);
|
||||||
std::fill(hparams.n_ff_arr.begin(), hparams.n_ff_arr.end(), 0);
|
std::fill(hparams.n_ff_arr.begin(), hparams.n_ff_arr.end(), 0);
|
||||||
|
|
||||||
|
std::fill(hparams.rope_sections.begin(), hparams.rope_sections.end(), 0);
|
||||||
|
|
||||||
|
std::fill(hparams.swa_layers.begin(), hparams.swa_layers.end(), 0);
|
||||||
|
|
||||||
ml.get_key_or_arr(LLM_KV_FEED_FORWARD_LENGTH, hparams.n_ff_arr, hparams.n_layer, false);
|
ml.get_key_or_arr(LLM_KV_FEED_FORWARD_LENGTH, hparams.n_ff_arr, hparams.n_layer, false);
|
||||||
ml.get_key_or_arr(LLM_KV_ATTENTION_HEAD_COUNT, hparams.n_head_arr, hparams.n_layer, false);
|
ml.get_key_or_arr(LLM_KV_ATTENTION_HEAD_COUNT, hparams.n_head_arr, hparams.n_layer, false);
|
||||||
|
|
||||||
@ -571,9 +574,10 @@ void llama_model::load_hparams(llama_model_loader & ml) {
|
|||||||
ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps);
|
ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps);
|
||||||
ml.get_key(LLM_KV_EXPERT_FEED_FORWARD_LENGTH, hparams.n_ff_exp);
|
ml.get_key(LLM_KV_EXPERT_FEED_FORWARD_LENGTH, hparams.n_ff_exp);
|
||||||
ml.get_key(LLM_KV_INTERLEAVE_MOE_LAYER_STEP, hparams.n_moe_layer_step);
|
ml.get_key(LLM_KV_INTERLEAVE_MOE_LAYER_STEP, hparams.n_moe_layer_step);
|
||||||
hparams.n_swa_pattern = 4; // pattern: 3 chunked - 1 full
|
|
||||||
hparams.n_attn_chunk = 8192; // should this be a gguf kv? currently it's the same for Scout and Maverick
|
hparams.swa_type = LLAMA_SWA_TYPE_CHUNKED;
|
||||||
hparams.n_swa = 1; // TODO @ngxson : this is added to trigger the SWA branch (we store the chunked attn mask in the SWA tensor), will need to clean this up later
|
hparams.n_swa = 8192; // should this be a gguf kv? currently it's the same for Scout and Maverick
|
||||||
|
hparams.set_swa_pattern(4); // pattern: 3 chunked - 1 full
|
||||||
|
|
||||||
switch (hparams.n_expert) {
|
switch (hparams.n_expert) {
|
||||||
case 16: type = LLM_TYPE_17B_16E; break;
|
case 16: type = LLM_TYPE_17B_16E; break;
|
||||||
@ -852,22 +856,17 @@ void llama_model::load_hparams(llama_model_loader & ml) {
|
|||||||
default: type = LLM_TYPE_UNKNOWN;
|
default: type = LLM_TYPE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for backward compatibility ; see: https://github.com/ggerganov/llama.cpp/pull/8931
|
const bool found_swa = ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa, false);
|
||||||
if ((hparams.n_layer == 32 || hparams.n_layer == 40) && hparams.n_ctx_train == 4096) {
|
|
||||||
// default value for Phi-3-mini-4k-instruct and Phi-3-medium-4k-instruct
|
if (found_swa && hparams.n_swa > 0) {
|
||||||
hparams.n_swa = 2047;
|
LLAMA_LOG_WARN("%s: Phi SWA is currently disabled - results might be suboptimal for some models (see %s)\n",
|
||||||
} else if (hparams.n_layer == 32 && hparams.n_head_kv(0) == 32 && hparams.n_ctx_train == 131072) {
|
__func__, "https://github.com/ggml-org/llama.cpp/pull/13676");
|
||||||
// default value for Phi-3-mini-128k-instruct
|
|
||||||
// note: this seems incorrect because the window is bigger than the train context?
|
// TODO: fix conversion scripts to correctly populate `n_swa` and `n_swa_pattern`
|
||||||
hparams.n_swa = 262144;
|
hparams.swa_type = LLAMA_SWA_TYPE_NONE;
|
||||||
} else if (hparams.n_layer == 40 && hparams.n_ctx_train == 131072) {
|
|
||||||
// default value for Phi-3-medium-128k-instruct
|
hparams.n_swa = 0;
|
||||||
// note: this seems incorrect because the window is equal to the train context?
|
hparams.set_swa_pattern(1);
|
||||||
hparams.n_swa = 131072;
|
|
||||||
}
|
|
||||||
bool found_swa = ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa, false);
|
|
||||||
if (!found_swa && hparams.n_swa == 0) {
|
|
||||||
throw std::runtime_error("invalid value for sliding_window");
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_PHIMOE:
|
case LLM_ARCH_PHIMOE:
|
||||||
@ -937,8 +936,9 @@ void llama_model::load_hparams(llama_model_loader & ml) {
|
|||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_GEMMA2:
|
case LLM_ARCH_GEMMA2:
|
||||||
{
|
{
|
||||||
|
hparams.swa_type = LLAMA_SWA_TYPE_STANDARD;
|
||||||
hparams.n_swa = 4096; // default value of gemma 2
|
hparams.n_swa = 4096; // default value of gemma 2
|
||||||
hparams.n_swa_pattern = 2;
|
hparams.set_swa_pattern(2);
|
||||||
hparams.attn_soft_cap = true;
|
hparams.attn_soft_cap = true;
|
||||||
|
|
||||||
ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa, false);
|
ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa, false);
|
||||||
@ -955,7 +955,8 @@ void llama_model::load_hparams(llama_model_loader & ml) {
|
|||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_GEMMA3:
|
case LLM_ARCH_GEMMA3:
|
||||||
{
|
{
|
||||||
hparams.n_swa_pattern = 6;
|
hparams.swa_type = LLAMA_SWA_TYPE_STANDARD;
|
||||||
|
hparams.set_swa_pattern(6);
|
||||||
|
|
||||||
hparams.rope_freq_base_train_swa = 10000.0f;
|
hparams.rope_freq_base_train_swa = 10000.0f;
|
||||||
hparams.rope_freq_scale_train_swa = 1.0f;
|
hparams.rope_freq_scale_train_swa = 1.0f;
|
||||||
@ -1039,7 +1040,8 @@ void llama_model::load_hparams(llama_model_loader & ml) {
|
|||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_COHERE2:
|
case LLM_ARCH_COHERE2:
|
||||||
{
|
{
|
||||||
hparams.n_swa_pattern = 4;
|
hparams.swa_type = LLAMA_SWA_TYPE_STANDARD;
|
||||||
|
hparams.set_swa_pattern(4);
|
||||||
|
|
||||||
ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa);
|
ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa);
|
||||||
ml.get_key(LLM_KV_LOGIT_SCALE, hparams.f_logit_scale);
|
ml.get_key(LLM_KV_LOGIT_SCALE, hparams.f_logit_scale);
|
||||||
@ -2487,7 +2489,11 @@ bool llama_model::load_tensors(llama_model_loader & ml) {
|
|||||||
|
|
||||||
// output
|
// output
|
||||||
output_norm = create_tensor(tn(LLM_TENSOR_OUTPUT_NORM, "weight"), {n_embd}, 0);
|
output_norm = create_tensor(tn(LLM_TENSOR_OUTPUT_NORM, "weight"), {n_embd}, 0);
|
||||||
output = create_tensor(tn(LLM_TENSOR_OUTPUT, "weight"), {n_embd, n_vocab}, 0);
|
output = create_tensor(tn(LLM_TENSOR_OUTPUT, "weight"), {n_embd, n_vocab}, TENSOR_NOT_REQUIRED);
|
||||||
|
// if output is NULL, init from the input tok embed
|
||||||
|
if (output == NULL) {
|
||||||
|
output = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, TENSOR_DUPLICATED);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < n_layer; ++i) {
|
for (int i = 0; i < n_layer; ++i) {
|
||||||
auto & layer = layers[i];
|
auto & layer = layers[i];
|
||||||
@ -4321,7 +4327,7 @@ void llama_model::print_info() const {
|
|||||||
LLAMA_LOG_INFO("%s: n_head_kv = %s\n", __func__, print_f([&](uint32_t il) { return hparams.n_head_kv(il); }, hparams.n_layer).c_str());
|
LLAMA_LOG_INFO("%s: n_head_kv = %s\n", __func__, print_f([&](uint32_t il) { return hparams.n_head_kv(il); }, hparams.n_layer).c_str());
|
||||||
LLAMA_LOG_INFO("%s: n_rot = %u\n", __func__, hparams.n_rot);
|
LLAMA_LOG_INFO("%s: n_rot = %u\n", __func__, hparams.n_rot);
|
||||||
LLAMA_LOG_INFO("%s: n_swa = %u\n", __func__, hparams.n_swa);
|
LLAMA_LOG_INFO("%s: n_swa = %u\n", __func__, hparams.n_swa);
|
||||||
LLAMA_LOG_INFO("%s: n_swa_pattern = %u\n", __func__, hparams.n_swa_pattern);
|
LLAMA_LOG_INFO("%s: is_swa_any = %u\n", __func__, hparams.is_swa_any());
|
||||||
LLAMA_LOG_INFO("%s: n_embd_head_k = %u\n", __func__, hparams.n_embd_head_k);
|
LLAMA_LOG_INFO("%s: n_embd_head_k = %u\n", __func__, hparams.n_embd_head_k);
|
||||||
LLAMA_LOG_INFO("%s: n_embd_head_v = %u\n", __func__, hparams.n_embd_head_v);
|
LLAMA_LOG_INFO("%s: n_embd_head_v = %u\n", __func__, hparams.n_embd_head_v);
|
||||||
LLAMA_LOG_INFO("%s: n_gqa = %s\n", __func__, print_f([&](uint32_t il) { return hparams.n_gqa(il); }, hparams.n_layer).c_str());
|
LLAMA_LOG_INFO("%s: n_gqa = %s\n", __func__, print_f([&](uint32_t il) { return hparams.n_gqa(il); }, hparams.n_layer).c_str());
|
||||||
@ -4489,7 +4495,17 @@ const ggml_tensor * llama_model::get_tensor(const char * name) const {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
ggml_tensor * llama_model::get_rope_factors(uint32_t n_ctx_per_seq, int il) const {
|
float llama_model::get_rope_freq_base (const llama_cparams & cparams, int il) const {
|
||||||
|
return hparams.is_swa(il) ? hparams.rope_freq_base_train_swa : cparams.rope_freq_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
float llama_model::get_rope_freq_scale(const llama_cparams & cparams, int il) const {
|
||||||
|
return hparams.is_swa(il) ? hparams.rope_freq_scale_train_swa : cparams.rope_freq_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
ggml_tensor * llama_model::get_rope_factors(const llama_cparams & cparams, int il) const {
|
||||||
|
const uint32_t n_ctx_per_seq = cparams.n_ctx / cparams.n_seq_max;
|
||||||
|
|
||||||
// choose long/short freq factors based on the context size
|
// choose long/short freq factors based on the context size
|
||||||
if (layers[il].rope_freqs != nullptr) {
|
if (layers[il].rope_freqs != nullptr) {
|
||||||
return layers[il].rope_freqs;
|
return layers[il].rope_freqs;
|
||||||
@ -4517,22 +4533,13 @@ struct llm_build_llama : public llm_graph_context {
|
|||||||
// inp_pos - contains the positions
|
// inp_pos - contains the positions
|
||||||
ggml_tensor * inp_pos = build_inp_pos();
|
ggml_tensor * inp_pos = build_inp_pos();
|
||||||
|
|
||||||
// temperature tuning
|
|
||||||
ggml_tensor * inp_attn_scale = nullptr;
|
|
||||||
if (arch == LLM_ARCH_LLAMA4) {
|
|
||||||
inp_attn_scale = build_inp_attn_scale();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto * inp_attn = build_attn_inp_kv_unified();
|
auto * inp_attn = build_attn_inp_kv_unified();
|
||||||
|
|
||||||
const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale;
|
const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale;
|
||||||
|
|
||||||
for (int il = 0; il < n_layer; ++il) {
|
for (int il = 0; il < n_layer; ++il) {
|
||||||
ggml_tensor * inpSA = inpL;
|
ggml_tensor * inpSA = inpL;
|
||||||
|
|
||||||
bool use_rope = arch == LLM_ARCH_LLAMA4
|
|
||||||
? (il + 1) % hparams.n_no_rope_layer_step != 0
|
|
||||||
: true;
|
|
||||||
|
|
||||||
// norm
|
// norm
|
||||||
cur = build_norm(inpL,
|
cur = build_norm(inpL,
|
||||||
model.layers[il].attn_norm, NULL,
|
model.layers[il].attn_norm, NULL,
|
||||||
@ -4542,7 +4549,169 @@ struct llm_build_llama : public llm_graph_context {
|
|||||||
// self-attention
|
// self-attention
|
||||||
{
|
{
|
||||||
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
|
// compute Q and K and RoPE them
|
||||||
|
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||||
|
cb(Qcur, "Qcur", il);
|
||||||
|
if (model.layers[il].bq) {
|
||||||
|
Qcur = ggml_add(ctx0, Qcur, model.layers[il].bq);
|
||||||
|
cb(Qcur, "Qcur", il);
|
||||||
|
}
|
||||||
|
|
||||||
|
ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur);
|
||||||
|
cb(Kcur, "Kcur", il);
|
||||||
|
if (model.layers[il].bk) {
|
||||||
|
Kcur = ggml_add(ctx0, Kcur, model.layers[il].bk);
|
||||||
|
cb(Kcur, "Kcur", il);
|
||||||
|
}
|
||||||
|
|
||||||
|
ggml_tensor * Vcur = build_lora_mm(model.layers[il].wv, cur);
|
||||||
|
cb(Vcur, "Vcur", il);
|
||||||
|
if (model.layers[il].bv) {
|
||||||
|
Vcur = ggml_add(ctx0, Vcur, model.layers[il].bv);
|
||||||
|
cb(Vcur, "Vcur", il);
|
||||||
|
}
|
||||||
|
|
||||||
|
Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens);
|
||||||
|
Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens);
|
||||||
|
Vcur = ggml_reshape_3d(ctx0, Vcur, n_embd_head, n_head_kv, n_tokens);
|
||||||
|
|
||||||
|
Qcur = ggml_rope_ext(
|
||||||
|
ctx0, Qcur, inp_pos, rope_factors,
|
||||||
|
n_rot, rope_type, n_ctx_orig, freq_base, freq_scale,
|
||||||
|
ext_factor, attn_factor, beta_fast, beta_slow
|
||||||
|
);
|
||||||
|
|
||||||
|
Kcur = ggml_rope_ext(
|
||||||
|
ctx0, Kcur, inp_pos, rope_factors,
|
||||||
|
n_rot, rope_type, n_ctx_orig, freq_base, freq_scale,
|
||||||
|
ext_factor, attn_factor, beta_fast, beta_slow
|
||||||
|
);
|
||||||
|
|
||||||
|
cb(Qcur, "Qcur", il);
|
||||||
|
cb(Kcur, "Kcur", il);
|
||||||
|
cb(Vcur, "Vcur", il);
|
||||||
|
|
||||||
|
cur = build_attn(inp_attn, gf,
|
||||||
|
model.layers[il].wo, model.layers[il].bo,
|
||||||
|
Qcur, Kcur, Vcur, nullptr, nullptr, kq_scale, il);
|
||||||
|
cb(cur, "attn_out", il);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (il == n_layer - 1) {
|
||||||
|
// skip computing output for unused tokens
|
||||||
|
ggml_tensor * inp_out_ids = build_inp_out_ids();
|
||||||
|
cur = ggml_get_rows(ctx0, cur, inp_out_ids);
|
||||||
|
inpSA = ggml_get_rows(ctx0, inpSA, inp_out_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
ggml_tensor * ffn_inp = ggml_add(ctx0, cur, inpSA);
|
||||||
|
cb(ffn_inp, "ffn_inp", il);
|
||||||
|
|
||||||
|
// feed-forward network (non-MoE)
|
||||||
|
if (model.layers[il].ffn_gate_inp == nullptr) {
|
||||||
|
|
||||||
|
cur = build_norm(ffn_inp,
|
||||||
|
model.layers[il].ffn_norm, NULL,
|
||||||
|
LLM_NORM_RMS, il);
|
||||||
|
cb(cur, "ffn_norm", il);
|
||||||
|
|
||||||
|
cur = build_ffn(cur,
|
||||||
|
model.layers[il].ffn_up, model.layers[il].ffn_up_b, NULL,
|
||||||
|
model.layers[il].ffn_gate, model.layers[il].ffn_gate_b, NULL,
|
||||||
|
model.layers[il].ffn_down, model.layers[il].ffn_down_b, NULL,
|
||||||
|
NULL,
|
||||||
|
LLM_FFN_SILU, LLM_FFN_PAR, il);
|
||||||
|
cb(cur, "ffn_out", il);
|
||||||
|
} else {
|
||||||
|
// MoE branch
|
||||||
|
cur = build_norm(ffn_inp,
|
||||||
|
model.layers[il].ffn_norm, NULL,
|
||||||
|
LLM_NORM_RMS, il);
|
||||||
|
cb(cur, "ffn_norm", il);
|
||||||
|
|
||||||
|
cur = build_moe_ffn(cur,
|
||||||
|
model.layers[il].ffn_gate_inp,
|
||||||
|
model.layers[il].ffn_up_exps,
|
||||||
|
model.layers[il].ffn_gate_exps,
|
||||||
|
model.layers[il].ffn_down_exps,
|
||||||
|
nullptr,
|
||||||
|
n_expert, n_expert_used,
|
||||||
|
LLM_FFN_SILU, true,
|
||||||
|
false, 0.0,
|
||||||
|
LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX,
|
||||||
|
il);
|
||||||
|
cb(cur, "ffn_moe_out", il);
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = ggml_add(ctx0, cur, ffn_inp);
|
||||||
|
cb(cur, "ffn_out", il);
|
||||||
|
|
||||||
|
cur = build_cvec(cur, il);
|
||||||
|
cb(cur, "l_out", il);
|
||||||
|
|
||||||
|
// input for next layer
|
||||||
|
inpL = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = inpL;
|
||||||
|
|
||||||
|
cur = build_norm(cur,
|
||||||
|
model.output_norm, NULL,
|
||||||
|
LLM_NORM_RMS, -1);
|
||||||
|
|
||||||
|
cb(cur, "result_norm", -1);
|
||||||
|
res->t_embd = cur;
|
||||||
|
|
||||||
|
// lm_head
|
||||||
|
cur = build_lora_mm(model.output, cur);
|
||||||
|
|
||||||
|
cb(cur, "result_output", -1);
|
||||||
|
res->t_logits = cur;
|
||||||
|
|
||||||
|
ggml_build_forward_expand(gf, cur);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct llm_build_llama_iswa : public llm_graph_context {
|
||||||
|
llm_build_llama_iswa(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
||||||
|
const int64_t n_embd_head = hparams.n_embd_head_v;
|
||||||
|
|
||||||
|
GGML_ASSERT(n_embd_head == hparams.n_embd_head_k);
|
||||||
|
GGML_ASSERT(n_embd_head == hparams.n_rot);
|
||||||
|
|
||||||
|
ggml_tensor * cur;
|
||||||
|
ggml_tensor * inpL;
|
||||||
|
|
||||||
|
inpL = build_inp_embd(model.tok_embd);
|
||||||
|
|
||||||
|
// inp_pos - contains the positions
|
||||||
|
ggml_tensor * inp_pos = build_inp_pos();
|
||||||
|
|
||||||
|
// temperature tuning
|
||||||
|
ggml_tensor * inp_attn_scale = nullptr;
|
||||||
|
inp_attn_scale = build_inp_attn_scale();
|
||||||
|
|
||||||
|
auto * inp_attn = build_attn_inp_kv_unified_iswa();
|
||||||
|
|
||||||
|
const float kq_scale = hparams.f_attention_scale == 0.0f ? 1.0f/sqrtf(float(n_embd_head)) : hparams.f_attention_scale;
|
||||||
|
|
||||||
|
for (int il = 0; il < n_layer; ++il) {
|
||||||
|
ggml_tensor * inpSA = inpL;
|
||||||
|
|
||||||
|
const bool use_rope = (il + 1) % hparams.n_no_rope_layer_step != 0;
|
||||||
|
|
||||||
|
// norm
|
||||||
|
cur = build_norm(inpL,
|
||||||
|
model.layers[il].attn_norm, NULL,
|
||||||
|
LLM_NORM_RMS, il);
|
||||||
|
cb(cur, "attn_norm", il);
|
||||||
|
|
||||||
|
// self-attention
|
||||||
|
{
|
||||||
|
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
||||||
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
// compute Q and K and RoPE them
|
// compute Q and K and RoPE them
|
||||||
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||||
@ -4590,7 +4759,7 @@ struct llm_build_llama : public llm_graph_context {
|
|||||||
cb(Kcur, "Kcur", il);
|
cb(Kcur, "Kcur", il);
|
||||||
cb(Vcur, "Vcur", il);
|
cb(Vcur, "Vcur", il);
|
||||||
|
|
||||||
if (arch == LLM_ARCH_LLAMA4 && use_rope && hparams.use_kq_norm) {
|
if (use_rope && hparams.use_kq_norm) {
|
||||||
// Llama4TextL2Norm
|
// Llama4TextL2Norm
|
||||||
Qcur = ggml_rms_norm(ctx0, Qcur, hparams.f_norm_rms_eps);
|
Qcur = ggml_rms_norm(ctx0, Qcur, hparams.f_norm_rms_eps);
|
||||||
Kcur = ggml_rms_norm(ctx0, Kcur, hparams.f_norm_rms_eps);
|
Kcur = ggml_rms_norm(ctx0, Kcur, hparams.f_norm_rms_eps);
|
||||||
@ -4616,7 +4785,6 @@ struct llm_build_llama : public llm_graph_context {
|
|||||||
|
|
||||||
// feed-forward network (non-MoE)
|
// feed-forward network (non-MoE)
|
||||||
if (model.layers[il].ffn_gate_inp == nullptr) {
|
if (model.layers[il].ffn_gate_inp == nullptr) {
|
||||||
|
|
||||||
cur = build_norm(ffn_inp,
|
cur = build_norm(ffn_inp,
|
||||||
model.layers[il].ffn_norm, NULL,
|
model.layers[il].ffn_norm, NULL,
|
||||||
LLM_NORM_RMS, il);
|
LLM_NORM_RMS, il);
|
||||||
@ -4629,9 +4797,7 @@ struct llm_build_llama : public llm_graph_context {
|
|||||||
NULL,
|
NULL,
|
||||||
LLM_FFN_SILU, LLM_FFN_PAR, il);
|
LLM_FFN_SILU, LLM_FFN_PAR, il);
|
||||||
cb(cur, "ffn_out", il);
|
cb(cur, "ffn_out", il);
|
||||||
|
} else {
|
||||||
} else if (arch == LLM_ARCH_LLAMA4) {
|
|
||||||
// llama4 MoE
|
|
||||||
ggml_tensor * ffn_inp_normed = build_norm(ffn_inp,
|
ggml_tensor * ffn_inp_normed = build_norm(ffn_inp,
|
||||||
model.layers[il].ffn_norm, NULL,
|
model.layers[il].ffn_norm, NULL,
|
||||||
LLM_NORM_RMS, il);
|
LLM_NORM_RMS, il);
|
||||||
@ -4660,26 +4826,6 @@ struct llm_build_llama : public llm_graph_context {
|
|||||||
|
|
||||||
cur = ggml_add(ctx0, moe_out, shexp_out);
|
cur = ggml_add(ctx0, moe_out, shexp_out);
|
||||||
cb(cur, "ffn_moe_out_merged", il);
|
cb(cur, "ffn_moe_out_merged", il);
|
||||||
|
|
||||||
} else {
|
|
||||||
// MoE branch
|
|
||||||
cur = build_norm(ffn_inp,
|
|
||||||
model.layers[il].ffn_norm, NULL,
|
|
||||||
LLM_NORM_RMS, il);
|
|
||||||
cb(cur, "ffn_norm", il);
|
|
||||||
|
|
||||||
cur = build_moe_ffn(cur,
|
|
||||||
model.layers[il].ffn_gate_inp,
|
|
||||||
model.layers[il].ffn_up_exps,
|
|
||||||
model.layers[il].ffn_gate_exps,
|
|
||||||
model.layers[il].ffn_down_exps,
|
|
||||||
nullptr,
|
|
||||||
n_expert, n_expert_used,
|
|
||||||
LLM_FFN_SILU, true,
|
|
||||||
false, 0.0,
|
|
||||||
LLAMA_EXPERT_GATING_FUNC_TYPE_SOFTMAX,
|
|
||||||
il);
|
|
||||||
cb(cur, "ffn_moe_out", il);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = ggml_add(ctx0, cur, ffn_inp);
|
cur = ggml_add(ctx0, cur, ffn_inp);
|
||||||
@ -4753,7 +4899,7 @@ struct llm_build_deci : public llm_graph_context {
|
|||||||
} else if (n_head > 0) {
|
} else if (n_head > 0) {
|
||||||
// self-attention
|
// self-attention
|
||||||
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
// compute Q and K and RoPE them
|
// compute Q and K and RoPE them
|
||||||
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||||
@ -7202,6 +7348,7 @@ struct llm_build_phi2 : public llm_graph_context {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<bool iswa>
|
||||||
struct llm_build_phi3 : public llm_graph_context {
|
struct llm_build_phi3 : public llm_graph_context {
|
||||||
llm_build_phi3(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
llm_build_phi3(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
||||||
const int64_t n_embd_head = hparams.n_embd_head_v;
|
const int64_t n_embd_head = hparams.n_embd_head_v;
|
||||||
@ -7217,7 +7364,14 @@ struct llm_build_phi3 : public llm_graph_context {
|
|||||||
// inp_pos - contains the positions
|
// inp_pos - contains the positions
|
||||||
ggml_tensor * inp_pos = build_inp_pos();
|
ggml_tensor * inp_pos = build_inp_pos();
|
||||||
|
|
||||||
auto * inp_attn = build_attn_inp_kv_unified();
|
using inp_attn_type = std::conditional_t<iswa, llm_graph_input_attn_kv_unified_iswa, llm_graph_input_attn_kv_unified>;
|
||||||
|
inp_attn_type * inp_attn = nullptr;
|
||||||
|
|
||||||
|
if constexpr (iswa) {
|
||||||
|
inp_attn = build_attn_inp_kv_unified_iswa();
|
||||||
|
} else {
|
||||||
|
inp_attn = build_attn_inp_kv_unified();
|
||||||
|
}
|
||||||
|
|
||||||
for (int il = 0; il < n_layer; ++il) {
|
for (int il = 0; il < n_layer; ++il) {
|
||||||
auto * residual = inpL;
|
auto * residual = inpL;
|
||||||
@ -7225,7 +7379,7 @@ struct llm_build_phi3 : public llm_graph_context {
|
|||||||
// self-attention
|
// self-attention
|
||||||
{
|
{
|
||||||
// rope freq factors for 128k context
|
// rope freq factors for 128k context
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
ggml_tensor* attn_norm_output = build_norm(inpL,
|
ggml_tensor* attn_norm_output = build_norm(inpL,
|
||||||
model.layers[il].attn_norm,
|
model.layers[il].attn_norm,
|
||||||
@ -7977,7 +8131,7 @@ struct llm_build_minicpm3 : public llm_graph_context {
|
|||||||
for (int il = 0; il < n_layer; ++il) {
|
for (int il = 0; il < n_layer; ++il) {
|
||||||
ggml_tensor * inpSA = inpL;
|
ggml_tensor * inpSA = inpL;
|
||||||
|
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
// norm
|
// norm
|
||||||
cur = build_norm(inpL,
|
cur = build_norm(inpL,
|
||||||
@ -8277,8 +8431,8 @@ struct llm_build_gemma : public llm_graph_context {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct llm_build_gemma2 : public llm_graph_context {
|
struct llm_build_gemma2_iswa : public llm_graph_context {
|
||||||
llm_build_gemma2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
llm_build_gemma2_iswa(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
||||||
const int64_t n_embd_head = hparams.n_embd_head_k;
|
const int64_t n_embd_head = hparams.n_embd_head_k;
|
||||||
|
|
||||||
ggml_tensor * cur;
|
ggml_tensor * cur;
|
||||||
@ -8292,7 +8446,7 @@ struct llm_build_gemma2 : public llm_graph_context {
|
|||||||
// inp_pos - contains the positions
|
// inp_pos - contains the positions
|
||||||
ggml_tensor * inp_pos = build_inp_pos();
|
ggml_tensor * inp_pos = build_inp_pos();
|
||||||
|
|
||||||
auto * inp_attn = build_attn_inp_kv_unified();
|
auto * inp_attn = build_attn_inp_kv_unified_iswa();
|
||||||
|
|
||||||
for (int il = 0; il < n_layer; ++il) {
|
for (int il = 0; il < n_layer; ++il) {
|
||||||
// norm
|
// norm
|
||||||
@ -8414,8 +8568,8 @@ struct llm_build_gemma2 : public llm_graph_context {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct llm_build_gemma3 : public llm_graph_context {
|
struct llm_build_gemma3_iswa : public llm_graph_context {
|
||||||
llm_build_gemma3(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
llm_build_gemma3_iswa(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
||||||
const int64_t n_embd_head = hparams.n_embd_head_k;
|
const int64_t n_embd_head = hparams.n_embd_head_k;
|
||||||
|
|
||||||
ggml_tensor * cur;
|
ggml_tensor * cur;
|
||||||
@ -8433,13 +8587,11 @@ struct llm_build_gemma3 : public llm_graph_context {
|
|||||||
ggml_tensor * inp_pos = build_inp_pos();
|
ggml_tensor * inp_pos = build_inp_pos();
|
||||||
|
|
||||||
// TODO: is causal == true correct? might need some changes
|
// TODO: is causal == true correct? might need some changes
|
||||||
auto * inp_attn = build_attn_inp_kv_unified();
|
auto * inp_attn = build_attn_inp_kv_unified_iswa();
|
||||||
|
|
||||||
for (int il = 0; il < n_layer; ++il) {
|
for (int il = 0; il < n_layer; ++il) {
|
||||||
const bool is_swa = hparams.is_swa(il);
|
const float freq_base_l = model.get_rope_freq_base (cparams, il);
|
||||||
|
const float freq_scale_l = model.get_rope_freq_scale(cparams, il);
|
||||||
const float freq_base_l = is_swa ? hparams.rope_freq_base_train_swa : cparams.rope_freq_base;
|
|
||||||
const float freq_scale_l = is_swa ? hparams.rope_freq_scale_train_swa : cparams.rope_freq_scale;
|
|
||||||
|
|
||||||
// norm
|
// norm
|
||||||
cur = build_norm(inpL, model.layers[il].attn_norm, NULL, LLM_NORM_RMS, il);
|
cur = build_norm(inpL, model.layers[il].attn_norm, NULL, LLM_NORM_RMS, il);
|
||||||
@ -9016,8 +9168,8 @@ struct llm_build_command_r : public llm_graph_context {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct llm_build_cohere2 : public llm_graph_context {
|
struct llm_build_cohere2_iswa : public llm_graph_context {
|
||||||
llm_build_cohere2(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
llm_build_cohere2_iswa(const llama_model & model, const llm_graph_params & params, ggml_cgraph * gf) : llm_graph_context(params) {
|
||||||
const int64_t n_embd_head = hparams.n_embd_head_v;
|
const int64_t n_embd_head = hparams.n_embd_head_v;
|
||||||
|
|
||||||
GGML_ASSERT(n_embd_head == hparams.n_embd_head_k);
|
GGML_ASSERT(n_embd_head == hparams.n_embd_head_k);
|
||||||
@ -9032,7 +9184,7 @@ struct llm_build_cohere2 : public llm_graph_context {
|
|||||||
// inp_pos - contains the positions
|
// inp_pos - contains the positions
|
||||||
ggml_tensor * inp_pos = build_inp_pos();
|
ggml_tensor * inp_pos = build_inp_pos();
|
||||||
|
|
||||||
auto * inp_attn = build_attn_inp_kv_unified();
|
auto * inp_attn = build_attn_inp_kv_unified_iswa();
|
||||||
|
|
||||||
for (int il = 0; il < n_layer; ++il) {
|
for (int il = 0; il < n_layer; ++il) {
|
||||||
const bool is_swa = hparams.is_swa(il);
|
const bool is_swa = hparams.is_swa(il);
|
||||||
@ -9045,7 +9197,7 @@ struct llm_build_cohere2 : public llm_graph_context {
|
|||||||
// self-attention
|
// self-attention
|
||||||
{
|
{
|
||||||
// rope freq factors for 128k context
|
// rope freq factors for 128k context
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
// compute Q and K and RoPE them
|
// compute Q and K and RoPE them
|
||||||
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||||
@ -9983,7 +10135,7 @@ struct llm_build_deepseek : public llm_graph_context {
|
|||||||
// self-attention
|
// self-attention
|
||||||
{
|
{
|
||||||
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
// compute Q and K and RoPE them
|
// compute Q and K and RoPE them
|
||||||
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||||
@ -11347,7 +11499,7 @@ struct llm_build_exaone : public llm_graph_context {
|
|||||||
// self-attention
|
// self-attention
|
||||||
{
|
{
|
||||||
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
// compute Q and K and RoPE them
|
// compute Q and K and RoPE them
|
||||||
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||||
@ -12263,7 +12415,7 @@ struct llm_build_granite : public llm_graph_context {
|
|||||||
Vcur = ggml_reshape_3d(ctx0, Vcur, n_embd_head, n_head_kv, n_tokens);
|
Vcur = ggml_reshape_3d(ctx0, Vcur, n_embd_head, n_head_kv, n_tokens);
|
||||||
|
|
||||||
if (use_rope) {
|
if (use_rope) {
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
Qcur = ggml_rope_ext(
|
Qcur = ggml_rope_ext(
|
||||||
ctx0, Qcur, inp_pos, rope_factors,
|
ctx0, Qcur, inp_pos, rope_factors,
|
||||||
n_rot, rope_type, n_ctx_orig, freq_base, freq_scale,
|
n_rot, rope_type, n_ctx_orig, freq_base, freq_scale,
|
||||||
@ -12916,7 +13068,7 @@ struct llm_build_bailingmoe : public llm_graph_context {
|
|||||||
// self-attention
|
// self-attention
|
||||||
{
|
{
|
||||||
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
// rope freq factors for llama3; may return nullptr for llama2 and other models
|
||||||
ggml_tensor * rope_factors = model.get_rope_factors(n_ctx_per_seq, il);
|
ggml_tensor * rope_factors = model.get_rope_factors(cparams, il);
|
||||||
|
|
||||||
// compute Q and K and RoPE them
|
// compute Q and K and RoPE them
|
||||||
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||||
@ -13044,6 +13196,7 @@ llama_memory_i * llama_model::create_memory(const llama_memory_params & params,
|
|||||||
case LLM_ARCH_JINA_BERT_V2:
|
case LLM_ARCH_JINA_BERT_V2:
|
||||||
case LLM_ARCH_NOMIC_BERT:
|
case LLM_ARCH_NOMIC_BERT:
|
||||||
case LLM_ARCH_NOMIC_BERT_MOE:
|
case LLM_ARCH_NOMIC_BERT_MOE:
|
||||||
|
case LLM_ARCH_WAVTOKENIZER_DEC:
|
||||||
{
|
{
|
||||||
res = nullptr;
|
res = nullptr;
|
||||||
} break;
|
} break;
|
||||||
@ -13058,7 +13211,8 @@ llama_memory_i * llama_model::create_memory(const llama_memory_params & params,
|
|||||||
GGML_TYPE_F32,
|
GGML_TYPE_F32,
|
||||||
GGML_TYPE_F32,
|
GGML_TYPE_F32,
|
||||||
cparams.offload_kqv,
|
cparams.offload_kqv,
|
||||||
std::max((uint32_t) 1, cparams.n_seq_max));
|
std::max((uint32_t) 1, cparams.n_seq_max),
|
||||||
|
cparams.n_seq_max);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@ -13068,14 +13222,36 @@ llama_memory_i * llama_model::create_memory(const llama_memory_params & params,
|
|||||||
|
|
||||||
LLAMA_LOG_DEBUG("%s: n_ctx = %u (padded)\n", __func__, cparams.n_ctx);
|
LLAMA_LOG_DEBUG("%s: n_ctx = %u (padded)\n", __func__, cparams.n_ctx);
|
||||||
|
|
||||||
res = new llama_kv_cache_unified(
|
if (hparams.swa_type != LLAMA_SWA_TYPE_NONE) {
|
||||||
*this,
|
GGML_ASSERT(hparams.is_swa_any());
|
||||||
params.type_k,
|
|
||||||
params.type_v,
|
res = new llama_kv_cache_unified_iswa(
|
||||||
!cparams.flash_attn,
|
*this,
|
||||||
cparams.offload_kqv,
|
params.type_k,
|
||||||
cparams.n_ctx,
|
params.type_v,
|
||||||
padding);
|
!cparams.flash_attn,
|
||||||
|
cparams.offload_kqv,
|
||||||
|
params.swa_full,
|
||||||
|
cparams.n_ctx,
|
||||||
|
cparams.n_seq_max,
|
||||||
|
cparams.n_batch,
|
||||||
|
padding);
|
||||||
|
} else {
|
||||||
|
GGML_ASSERT(!hparams.is_swa_any());
|
||||||
|
|
||||||
|
res = new llama_kv_cache_unified(
|
||||||
|
*this,
|
||||||
|
nullptr,
|
||||||
|
params.type_k,
|
||||||
|
params.type_v,
|
||||||
|
!cparams.flash_attn,
|
||||||
|
cparams.offload_kqv,
|
||||||
|
cparams.n_ctx,
|
||||||
|
cparams.n_seq_max,
|
||||||
|
padding,
|
||||||
|
hparams.n_swa,
|
||||||
|
hparams.swa_type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13090,11 +13266,14 @@ llm_graph_result_ptr llama_model::build_graph(
|
|||||||
|
|
||||||
switch (arch) {
|
switch (arch) {
|
||||||
case LLM_ARCH_LLAMA:
|
case LLM_ARCH_LLAMA:
|
||||||
case LLM_ARCH_LLAMA4:
|
|
||||||
case LLM_ARCH_MINICPM:
|
case LLM_ARCH_MINICPM:
|
||||||
{
|
{
|
||||||
llm = std::make_unique<llm_build_llama>(*this, params, gf);
|
llm = std::make_unique<llm_build_llama>(*this, params, gf);
|
||||||
} break;
|
} break;
|
||||||
|
case LLM_ARCH_LLAMA4:
|
||||||
|
{
|
||||||
|
llm = std::make_unique<llm_build_llama_iswa>(*this, params, gf);
|
||||||
|
} break;
|
||||||
case LLM_ARCH_DECI:
|
case LLM_ARCH_DECI:
|
||||||
{
|
{
|
||||||
llm = std::make_unique<llm_build_deci>(*this, params, gf);
|
llm = std::make_unique<llm_build_deci>(*this, params, gf);
|
||||||
@ -13169,7 +13348,11 @@ llm_graph_result_ptr llama_model::build_graph(
|
|||||||
case LLM_ARCH_PHI3:
|
case LLM_ARCH_PHI3:
|
||||||
case LLM_ARCH_PHIMOE:
|
case LLM_ARCH_PHIMOE:
|
||||||
{
|
{
|
||||||
llm = std::make_unique<llm_build_phi3>(*this, params, gf);
|
if (hparams.swa_type != LLAMA_SWA_TYPE_NONE) {
|
||||||
|
llm = std::make_unique<llm_build_phi3<true>> (*this, params, gf);
|
||||||
|
} else {
|
||||||
|
llm = std::make_unique<llm_build_phi3<false>>(*this, params, gf);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_PLAMO:
|
case LLM_ARCH_PLAMO:
|
||||||
{
|
{
|
||||||
@ -13201,11 +13384,11 @@ llm_graph_result_ptr llama_model::build_graph(
|
|||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_GEMMA2:
|
case LLM_ARCH_GEMMA2:
|
||||||
{
|
{
|
||||||
llm = std::make_unique<llm_build_gemma2>(*this, params, gf);
|
llm = std::make_unique<llm_build_gemma2_iswa>(*this, params, gf);
|
||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_GEMMA3:
|
case LLM_ARCH_GEMMA3:
|
||||||
{
|
{
|
||||||
llm = std::make_unique<llm_build_gemma3>(*this, params, gf);
|
llm = std::make_unique<llm_build_gemma3_iswa>(*this, params, gf);
|
||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_STARCODER2:
|
case LLM_ARCH_STARCODER2:
|
||||||
{
|
{
|
||||||
@ -13225,7 +13408,7 @@ llm_graph_result_ptr llama_model::build_graph(
|
|||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_COHERE2:
|
case LLM_ARCH_COHERE2:
|
||||||
{
|
{
|
||||||
llm = std::make_unique<llm_build_cohere2>(*this, params, gf);
|
llm = std::make_unique<llm_build_cohere2_iswa>(*this, params, gf);
|
||||||
} break;
|
} break;
|
||||||
case LLM_ARCH_DBRX:
|
case LLM_ARCH_DBRX:
|
||||||
{
|
{
|
||||||
|
@ -398,7 +398,10 @@ struct llama_model {
|
|||||||
|
|
||||||
const struct ggml_tensor * get_tensor(const char * name) const;
|
const struct ggml_tensor * get_tensor(const char * name) const;
|
||||||
|
|
||||||
ggml_tensor * get_rope_factors(uint32_t n_ctx_per_seq, int il) const;
|
float get_rope_freq_base (const llama_cparams & cparams, int il) const;
|
||||||
|
float get_rope_freq_scale(const llama_cparams & cparams, int il) const;
|
||||||
|
|
||||||
|
ggml_tensor * get_rope_factors(const llama_cparams & cparams, int il) const;
|
||||||
|
|
||||||
// note: can mutate `cparams`
|
// note: can mutate `cparams`
|
||||||
// TODO: move this to new llm_arch_model_i interface
|
// TODO: move this to new llm_arch_model_i interface
|
||||||
|
@ -798,7 +798,7 @@ static void llama_sampler_min_p_apply(struct llama_sampler * smpl, llama_token_d
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if we have enough values the operation was a success
|
// if we have enough values the operation was a success
|
||||||
if (filtered_tokens.size() >= ctx->min_keep) {
|
if (!filtered_tokens.empty() && filtered_tokens.size() >= ctx->min_keep) {
|
||||||
memcpy(cur_p->data, filtered_tokens.data(), filtered_tokens.size()*sizeof(llama_token_data));
|
memcpy(cur_p->data, filtered_tokens.data(), filtered_tokens.size()*sizeof(llama_token_data));
|
||||||
cur_p->size = filtered_tokens.size();
|
cur_p->size = filtered_tokens.size();
|
||||||
min_p_applied = true;
|
min_p_applied = true;
|
||||||
@ -909,7 +909,7 @@ static void llama_sampler_typical_apply(struct llama_sampler * smpl, llama_token
|
|||||||
cum_sum += cur_p->data[idx].p;
|
cum_sum += cur_p->data[idx].p;
|
||||||
|
|
||||||
// Check if the running sum is greater than typical or if we have kept at least min_keep tokens
|
// Check if the running sum is greater than typical or if we have kept at least min_keep tokens
|
||||||
if (cum_sum > ctx->p && i >= ctx->min_keep - 1) {
|
if (cum_sum > ctx->p && (ctx->min_keep == 0 || i >= ctx->min_keep - 1)) {
|
||||||
last_idx = i + 1;
|
last_idx = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -835,7 +835,7 @@ struct llm_tokenizer_ugm_session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initialize score_sum to -FLT_MAX so it will be always lower than sums of token scores
|
// initialize score_sum to -FLT_MAX so it will be always lower than sums of token scores
|
||||||
std::vector<struct best_tokenization> tokenization_results(input_len + 1, {vocab.token_unk(), 0, -FLT_MAX});
|
std::vector<struct best_tokenization> tokenization_results(input_len + 1, {vocab.token_unk(), 0, -DBL_MAX});
|
||||||
// at the beginning tokenization score is zero
|
// at the beginning tokenization score is zero
|
||||||
tokenization_results[0] = { vocab.token_unk(), 0, 0 };
|
tokenization_results[0] = { vocab.token_unk(), 0, 0 };
|
||||||
|
|
||||||
@ -867,7 +867,7 @@ struct llm_tokenizer_ugm_session {
|
|||||||
const double challenger_score = current_best.score_sum + token_score;
|
const double challenger_score = current_best.score_sum + token_score;
|
||||||
struct best_tokenization & current_champ = tokenization_results[prefix_offset];
|
struct best_tokenization & current_champ = tokenization_results[prefix_offset];
|
||||||
if (challenger_score > current_champ.score_sum) {
|
if (challenger_score > current_champ.score_sum) {
|
||||||
struct best_tokenization challenger = { token_id, input_offset, (float) challenger_score };
|
struct best_tokenization challenger = { token_id, input_offset, challenger_score };
|
||||||
current_champ = challenger;
|
current_champ = challenger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -881,7 +881,7 @@ struct llm_tokenizer_ugm_session {
|
|||||||
prefix_offset = input_offset + n_utf8_code_units;
|
prefix_offset = input_offset + n_utf8_code_units;
|
||||||
struct best_tokenization & current_champ = tokenization_results[prefix_offset];
|
struct best_tokenization & current_champ = tokenization_results[prefix_offset];
|
||||||
if (challenger_score > current_champ.score_sum) {
|
if (challenger_score > current_champ.score_sum) {
|
||||||
struct best_tokenization challenger = { vocab.token_unk(), input_offset, (float) challenger_score };
|
struct best_tokenization challenger = { vocab.token_unk(), input_offset, challenger_score };
|
||||||
current_champ = challenger;
|
current_champ = challenger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1007,7 +1007,7 @@ private:
|
|||||||
struct best_tokenization {
|
struct best_tokenization {
|
||||||
llama_token token_id;
|
llama_token token_id;
|
||||||
size_t input_offset;
|
size_t input_offset;
|
||||||
float score_sum;
|
double score_sum;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct normalization_result normalize_prefix(const std::string & input, size_t input_offset) {
|
struct normalization_result normalize_prefix(const std::string & input, size_t input_offset) {
|
||||||
|
@ -361,10 +361,11 @@ extern "C" {
|
|||||||
|
|
||||||
// Keep the booleans together and at the end of the struct to avoid misalignment during copy-by-value.
|
// Keep the booleans together and at the end of the struct to avoid misalignment during copy-by-value.
|
||||||
bool embeddings; // if true, extract embeddings (together with logits)
|
bool embeddings; // if true, extract embeddings (together with logits)
|
||||||
bool offload_kqv; // whether to offload the KQV ops (including the KV cache) to GPU
|
bool offload_kqv; // offload the KQV ops (including the KV cache) to GPU
|
||||||
bool flash_attn; // whether to use flash attention [EXPERIMENTAL]
|
bool flash_attn; // use flash attention [EXPERIMENTAL]
|
||||||
bool no_perf; // whether to measure performance timings
|
bool no_perf; // measure performance timings
|
||||||
bool op_offload; // whether to offload host tensor operations to device
|
bool op_offload; // offload host tensor operations to device
|
||||||
|
bool swa_full; // use full-size SWA cache (https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
|
||||||
};
|
};
|
||||||
|
|
||||||
// model quantization parameters
|
// model quantization parameters
|
||||||
@ -470,6 +471,7 @@ extern "C" {
|
|||||||
LLAMA_API int64_t llama_time_us(void);
|
LLAMA_API int64_t llama_time_us(void);
|
||||||
|
|
||||||
LLAMA_API size_t llama_max_devices(void);
|
LLAMA_API size_t llama_max_devices(void);
|
||||||
|
LLAMA_API size_t llama_max_parallel_sequences(void);
|
||||||
|
|
||||||
LLAMA_API bool llama_supports_mmap (void);
|
LLAMA_API bool llama_supports_mmap (void);
|
||||||
LLAMA_API bool llama_supports_mlock (void);
|
LLAMA_API bool llama_supports_mlock (void);
|
||||||
@ -607,71 +609,14 @@ extern "C" {
|
|||||||
// KV cache
|
// KV cache
|
||||||
//
|
//
|
||||||
|
|
||||||
// TODO: start using struct llama_kv_cache
|
|
||||||
|
|
||||||
// Information associated with an individual cell in the KV cache view.
|
|
||||||
struct llama_kv_cache_view_cell {
|
|
||||||
// The position for this cell. Takes KV cache shifts into account.
|
|
||||||
// May be negative if the cell is not populated.
|
|
||||||
llama_pos pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
// An updateable view of the KV cache.
|
|
||||||
struct llama_kv_cache_view {
|
|
||||||
// Number of KV cache cells. This will be the same as the context size.
|
|
||||||
int32_t n_cells;
|
|
||||||
|
|
||||||
// Maximum number of sequences that can exist in a cell. It's not an error
|
|
||||||
// if there are more sequences in a cell than this value, however they will
|
|
||||||
// not be visible in the view cells_sequences.
|
|
||||||
int32_t n_seq_max;
|
|
||||||
|
|
||||||
// Number of tokens in the cache. For example, if there are two populated
|
|
||||||
// cells, the first with 1 sequence id in it and the second with 2 sequence
|
|
||||||
// ids then you'll have 3 tokens.
|
|
||||||
int32_t token_count;
|
|
||||||
|
|
||||||
// Number of populated cache cells.
|
|
||||||
int32_t used_cells;
|
|
||||||
|
|
||||||
// Maximum contiguous empty slots in the cache.
|
|
||||||
int32_t max_contiguous;
|
|
||||||
|
|
||||||
// Index to the start of the max_contiguous slot range. Can be negative
|
|
||||||
// when cache is full.
|
|
||||||
int32_t max_contiguous_idx;
|
|
||||||
|
|
||||||
// Information for an individual cell.
|
|
||||||
struct llama_kv_cache_view_cell * cells;
|
|
||||||
|
|
||||||
// The sequences for each cell. There will be n_seq_max items per cell.
|
|
||||||
llama_seq_id * cells_sequences;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create an empty KV cache view. (use only for debugging purposes)
|
|
||||||
LLAMA_API struct llama_kv_cache_view llama_kv_cache_view_init(const struct llama_context * ctx, int32_t n_seq_max);
|
|
||||||
|
|
||||||
// Free a KV cache view. (use only for debugging purposes)
|
|
||||||
LLAMA_API void llama_kv_cache_view_free(struct llama_kv_cache_view * view);
|
|
||||||
|
|
||||||
// Update the KV cache view structure with the current state of the KV cache. (use only for debugging purposes)
|
|
||||||
// TODO: change signature to llama_kv_cache_view_update(struct llama_kv_cache_view * view, const struct llama_context * ctx)
|
|
||||||
LLAMA_API void llama_kv_cache_view_update(const struct llama_context * ctx, struct llama_kv_cache_view * view);
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
// Returns the number of tokens in the KV cache (slow, use only for debug)
|
// Returns the number of tokens in the KV cache (slow, use only for debug)
|
||||||
// If a KV cell has multiple sequences assigned to it, it will be counted multiple times
|
// If a KV cell has multiple sequences assigned to it, it will be counted multiple times
|
||||||
LLAMA_API int32_t llama_kv_self_n_tokens(const struct llama_context * ctx);
|
DEPRECATED(LLAMA_API int32_t llama_kv_self_n_tokens(const struct llama_context * ctx),
|
||||||
|
"Use llama_kv_self_seq_pos_max() and llama_kv_self_seq_pos_min() instead (https://github.com/ggml-org/llama.cpp/issues/13793)");
|
||||||
DEPRECATED(LLAMA_API int32_t llama_get_kv_cache_token_count(const struct llama_context * ctx),
|
|
||||||
"use llama_kv_self_n_tokens instead");
|
|
||||||
|
|
||||||
// Returns the number of used KV cells (i.e. have at least one sequence assigned to them)
|
// Returns the number of used KV cells (i.e. have at least one sequence assigned to them)
|
||||||
LLAMA_API int32_t llama_kv_self_used_cells(const struct llama_context * ctx);
|
DEPRECATED(LLAMA_API int32_t llama_kv_self_used_cells(const struct llama_context * ctx),
|
||||||
|
"Use llama_kv_self_seq_pos_max() and llama_kv_self_seq_pos_min() instead (https://github.com/ggml-org/llama.cpp/issues/13793)");
|
||||||
DEPRECATED(LLAMA_API int32_t llama_get_kv_cache_used_cells(const struct llama_context * ctx),
|
|
||||||
"use llama_kv_self_used_cells instead");
|
|
||||||
|
|
||||||
// Clear the KV cache - both cell info is erased and KV data is zeroed
|
// Clear the KV cache - both cell info is erased and KV data is zeroed
|
||||||
LLAMA_API void llama_kv_self_clear(
|
LLAMA_API void llama_kv_self_clear(
|
||||||
@ -730,10 +675,18 @@ extern "C" {
|
|||||||
llama_pos p1,
|
llama_pos p1,
|
||||||
int d);
|
int d);
|
||||||
|
|
||||||
|
// Returns the smallest position present in the KV cache for the specified sequence
|
||||||
|
// This is typically non-zero only for SWA caches
|
||||||
|
// Return -1 if the sequence is empty
|
||||||
|
LLAMA_API llama_pos llama_kv_self_seq_pos_min(
|
||||||
|
struct llama_context * ctx,
|
||||||
|
llama_seq_id seq_id);
|
||||||
|
|
||||||
// Returns the largest position present in the KV cache for the specified sequence
|
// Returns the largest position present in the KV cache for the specified sequence
|
||||||
|
// Return -1 if the sequence is empty
|
||||||
LLAMA_API llama_pos llama_kv_self_seq_pos_max(
|
LLAMA_API llama_pos llama_kv_self_seq_pos_max(
|
||||||
struct llama_context * ctx,
|
struct llama_context * ctx,
|
||||||
llama_seq_id seq_id);
|
llama_seq_id seq_id);
|
||||||
|
|
||||||
// Defragment the KV cache
|
// Defragment the KV cache
|
||||||
// This will be applied:
|
// This will be applied:
|
||||||
@ -747,61 +700,6 @@ extern "C" {
|
|||||||
// Apply the KV cache updates (such as K-shifts, defragmentation, etc.)
|
// Apply the KV cache updates (such as K-shifts, defragmentation, etc.)
|
||||||
LLAMA_API void llama_kv_self_update(struct llama_context * ctx);
|
LLAMA_API void llama_kv_self_update(struct llama_context * ctx);
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API void llama_kv_cache_clear(
|
|
||||||
struct llama_context * ctx),
|
|
||||||
"use llama_kv_self_clear instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API bool llama_kv_cache_seq_rm(
|
|
||||||
struct llama_context * ctx,
|
|
||||||
llama_seq_id seq_id,
|
|
||||||
llama_pos p0,
|
|
||||||
llama_pos p1),
|
|
||||||
"use llama_kv_self_seq_rm instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API void llama_kv_cache_seq_cp(
|
|
||||||
struct llama_context * ctx,
|
|
||||||
llama_seq_id seq_id_src,
|
|
||||||
llama_seq_id seq_id_dst,
|
|
||||||
llama_pos p0,
|
|
||||||
llama_pos p1),
|
|
||||||
"use llama_kv_self_seq_cp instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API void llama_kv_cache_seq_keep(
|
|
||||||
struct llama_context * ctx,
|
|
||||||
llama_seq_id seq_id),
|
|
||||||
"use llama_kv_self_seq_keep instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API void llama_kv_cache_seq_add(
|
|
||||||
struct llama_context * ctx,
|
|
||||||
llama_seq_id seq_id,
|
|
||||||
llama_pos p0,
|
|
||||||
llama_pos p1,
|
|
||||||
llama_pos delta),
|
|
||||||
"use llama_kv_self_seq_add instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API void llama_kv_cache_seq_div(
|
|
||||||
struct llama_context * ctx,
|
|
||||||
llama_seq_id seq_id,
|
|
||||||
llama_pos p0,
|
|
||||||
llama_pos p1,
|
|
||||||
int d),
|
|
||||||
"use llama_kv_self_seq_div instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API llama_pos llama_kv_cache_seq_pos_max(
|
|
||||||
struct llama_context * ctx,
|
|
||||||
llama_seq_id seq_id),
|
|
||||||
"use llama_kv_self_seq_pos_max instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API void llama_kv_cache_defrag(struct llama_context * ctx),
|
|
||||||
"use llama_kv_self_defrag instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API bool llama_kv_cache_can_shift(const struct llama_context * ctx),
|
|
||||||
"use llama_kv_self_can_shift instead");
|
|
||||||
|
|
||||||
DEPRECATED(LLAMA_API void llama_kv_cache_update(struct llama_context * ctx),
|
|
||||||
"use llama_kv_self_update instead");
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// State / sessions
|
// State / sessions
|
||||||
//
|
//
|
||||||
@ -943,9 +841,12 @@ extern "C" {
|
|||||||
// Requires KV cache.
|
// Requires KV cache.
|
||||||
// For encode-decoder contexts, processes the batch using the decoder.
|
// For encode-decoder contexts, processes the batch using the decoder.
|
||||||
// Positive return values does not mean a fatal error, but rather a warning.
|
// Positive return values does not mean a fatal error, but rather a warning.
|
||||||
// 0 - success
|
// Upon non-zero return values, the KV cache state is restored to the state before this call
|
||||||
// 1 - could not find a KV slot for the batch (try reducing the size of the batch or increase the context)
|
// 0 - success
|
||||||
// < 0 - error. the KV cache state is restored to the state before this call
|
// 1 - could not find a KV slot for the batch (try reducing the size of the batch or increase the context)
|
||||||
|
// 2 - aborted
|
||||||
|
// -1 - invalid input batch
|
||||||
|
// < -1 - error
|
||||||
LLAMA_API int32_t llama_decode(
|
LLAMA_API int32_t llama_decode(
|
||||||
struct llama_context * ctx,
|
struct llama_context * ctx,
|
||||||
struct llama_batch batch);
|
struct llama_batch batch);
|
||||||
|
Reference in New Issue
Block a user