Text Generation
GGUF
llama.cpp
ripple
ricursive
dense
imatrix
long-context
rtx-pro-6000
blackwell
tool-use
reasoning
conversational
Instructions to use prometheusAIR/Ripple-65B-Preview-GGUF with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use prometheusAIR/Ripple-65B-Preview-GGUF with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S # Run inference directly in the terminal: llama cli -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S # Run inference directly in the terminal: llama cli -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S # Run inference directly in the terminal: ./build/bin/llama cli -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
Use Docker
docker model run hf.co/prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
- Llama new
- LM Studio
- Jan
- vLLM
How to use prometheusAIR/Ripple-65B-Preview-GGUF with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "prometheusAIR/Ripple-65B-Preview-GGUF" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "prometheusAIR/Ripple-65B-Preview-GGUF", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
- Ollama
How to use prometheusAIR/Ripple-65B-Preview-GGUF with Ollama:
ollama run hf.co/prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
- Unsloth Desktop
- Pi
How to use prometheusAIR/Ripple-65B-Preview-GGUF with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use prometheusAIR/Ripple-65B-Preview-GGUF with Docker Model Runner:
docker model run hf.co/prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
- Lemonade
How to use prometheusAIR/Ripple-65B-Preview-GGUF with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
Run and chat with the model
lemonade run user.Ripple-65B-Preview-GGUF-IQ3_S
List all available models
lemonade list
- Hermes Agent
How to use prometheusAIR/Ripple-65B-Preview-GGUF with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use prometheusAIR/Ripple-65B-Preview-GGUF with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "prometheusAIR/Ripple-65B-Preview-GGUF:IQ3_S" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Download patches/llama.cpp-ricursive.patch from prometheusAIR/Ripple-65B-Preview-GGUF: direct link, hf CLI and curl.
- Browser
- Download file 23.1 kB
-
https://huggingface.co/prometheusAIR/Ripple-65B-Preview-GGUF/resolve/main/patches/llama.cpp-ricursive.patch
- Command line
-
hf download hf://prometheusAIR/Ripple-65B-Preview-GGUF/patches/llama.cpp-ricursive.patch
-
curl -L -o llama.cpp-ricursive.patch https://huggingface.co/prometheusAIR/Ripple-65B-Preview-GGUF/resolve/main/patches/llama.cpp-ricursive.patch
23.1 kB
| diff --git a/conversion/__init__.py b/conversion/__init__.py | |
| index 0c6204b87..5bd957bd1 100644 | |
| --- a/conversion/__init__.py | |
| +++ b/conversion/__init__.py | |
| __all__ = [ | |
| TEXT_MODEL_MAP: dict[str, str] = { | |
| "NEOChatModel": "sensenova_u1", | |
| "AfmoeForCausalLM": "afmoe", | |
| + "RicursiveForCausalLM": "ricursive", | |
| "LagunaForCausalLM": "laguna", | |
| "FlintForCausalLM": "flint", | |
| "ApertusForCausalLM": "llama", | |
| diff --git a/conversion/ricursive.py b/conversion/ricursive.py | |
| new file mode 100644 | |
| index 000000000..e4ab321c0 | |
| --- /dev/null | |
| +++ b/conversion/ricursive.py | |
| +from __future__ import annotations | |
| + | |
| +from typing import Iterable, TYPE_CHECKING | |
| + | |
| +if TYPE_CHECKING: | |
| + from torch import Tensor | |
| + | |
| +from .base import ModelBase, TextModel, gguf | |
| + | |
| + | |
| +@ModelBase.register("RicursiveForCausalLM") | |
| +class RicursiveModel(TextModel): | |
| + model_arch = gguf.MODEL_ARCH.RICURSIVE | |
| + | |
| + def set_vocab(self): | |
| + tokens, toktypes, tokpre = self.get_vocab_base() | |
| + self.gguf_writer.add_tokenizer_model("gpt2") | |
| + self.gguf_writer.add_tokenizer_pre(tokpre) | |
| + self.gguf_writer.add_token_list(tokens) | |
| + self.gguf_writer.add_token_types(toktypes) | |
| + | |
| + special_vocab = gguf.SpecialVocab(self.dir_model, load_merges=True) | |
| + # tokenizer_config.json carries a plain ChatML stub; the vendor serves the tools-aware | |
| + # repo-root chat_template.jinja, which SpecialVocab would otherwise lose to the stub | |
| + if (template := self.dir_model / "chat_template.jinja").is_file(): | |
| + special_vocab.chat_template = template.read_text(encoding="utf-8") | |
| + special_vocab.add_to_gguf(self.gguf_writer) | |
| + | |
| + # tokenizer.json has no post_processor: the HF tokenizer never prepends <|endoftext|> | |
| + self.gguf_writer.add_add_bos_token(False) | |
| + | |
| + def set_gguf_parameters(self): | |
| + super().set_gguf_parameters() | |
| + hparams = self.hparams | |
| + | |
| + head_dim = hparams["head_dim"] # 128, while hidden_size / num_attention_heads is 64 | |
| + self.gguf_writer.add_key_length(head_dim) | |
| + self.gguf_writer.add_value_length(head_dim) | |
| + self.gguf_writer.add_rope_dimension_count(head_dim) | |
| + | |
| + # sliding_attention layers use RoPE, full_attention layers use no positional encoding | |
| + self.gguf_writer.add_sliding_window(hparams["sliding_window"]) | |
| + self.gguf_writer.add_sliding_window_pattern([t == "sliding_attention" for t in hparams["layer_types"]]) | |
| + | |
| + if (embed_scale := hparams.get("embed_scale")) is not None: | |
| + self.gguf_writer.add_embedding_scale(embed_scale) | |
| + if (clamp := hparams.get("ffn_clamp_threshold")) is not None: | |
| + self.gguf_writer.add_swiglu_clamp(clamp) | |
| + | |
| + assert hparams.get("use_gated_attention", True), "only gated-attention checkpoints are supported" | |
| + assert hparams.get("use_valres", False), "only value-residual checkpoints are supported" | |
| + | |
| + def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]: | |
| + if name.endswith("self_attn.value_res_lambda"): | |
| + assert bid is not None | |
| + yield (self.format_tensor_name(gguf.MODEL_TENSOR.ATTN_VALUE_RES, bid), data_torch) | |
| + return | |
| + if name.endswith("self_attn.g_proj.weight"): | |
| + assert bid is not None | |
| + yield (self.format_tensor_name(gguf.MODEL_TENSOR.ATTN_GATE, bid), data_torch) | |
| + return | |
| + | |
| + yield from super().modify_tensors(data_torch, name, bid) | |
| diff --git a/gguf-py/gguf/constants.py b/gguf-py/gguf/constants.py | |
| index 930714f30..bc18372eb 100644 | |
| --- a/gguf-py/gguf/constants.py | |
| +++ b/gguf-py/gguf/constants.py | |
| class Keys: | |
| EMBD_LENGTH_PER_LAYER_INP = "{arch}.embedding_length_per_layer_input" | |
| SWIGLU_CLAMP_EXP = "{arch}.swiglu_clamp_exp" | |
| SWIGLU_CLAMP_SHEXP = "{arch}.swiglu_clamp_shexp" | |
| + SWIGLU_CLAMP = "{arch}.swiglu_clamp" | |
| HIDDEN_ACT = "{arch}.hidden_activation" | |
| DENSE_FEAT_IN_SIZE = "{arch}.{dense}_feat_in" | |
| DENSE_FEAT_OUT_SIZE = "{arch}.{dense}_feat_out" | |
| class MODEL_ARCH(IntEnum): | |
| DOTS3NOTE = auto() | |
| ARCEE = auto() | |
| AFMOE = auto() | |
| + RICURSIVE = auto() | |
| LAGUNA = auto() | |
| ERNIE4_5 = auto() | |
| ERNIE4_5_MOE = auto() | |
| class MODEL_TENSOR(IntEnum): | |
| ATTN_SINKS = auto() | |
| ATTN_SSMAX = auto() | |
| ATTN_GATE = auto() | |
| + ATTN_VALUE_RES = auto() # ricursive: per-layer value-residual mix logit | |
| ATTN_RESID_ALPHA = auto() | |
| ATTN_RESID_BETA = auto() | |
| FFN_GATE_INP = auto() | |
| MODEL_ARCH_NAMES: dict[MODEL_ARCH, str] = { | |
| MODEL_ARCH.DOTS3NOTE: "dots3note", | |
| MODEL_ARCH.ARCEE: "arcee", | |
| MODEL_ARCH.AFMOE: "afmoe", | |
| + MODEL_ARCH.RICURSIVE: "ricursive", | |
| MODEL_ARCH.LAGUNA: "laguna", | |
| MODEL_ARCH.ERNIE4_5: "ernie4_5", | |
| MODEL_ARCH.ERNIE4_5_MOE: "ernie4_5-moe", | |
| TENSOR_NAMES: dict[MODEL_TENSOR, str] = { | |
| MODEL_TENSOR.ATTN_SINKS: "blk.{bid}.attn_sinks", | |
| MODEL_TENSOR.ATTN_SSMAX: "blk.{bid}.attn_ssmax", | |
| MODEL_TENSOR.ATTN_GATE: "blk.{bid}.attn_gate", | |
| + MODEL_TENSOR.ATTN_VALUE_RES: "blk.{bid}.attn_value_res", | |
| MODEL_TENSOR.ATTN_RESID_ALPHA: "blk.{bid}.attn_resid_alpha", | |
| MODEL_TENSOR.ATTN_RESID_BETA: "blk.{bid}.attn_resid_beta", | |
| MODEL_TENSOR.ATTN_Q_NORM: "blk.{bid}.attn_q_norm", | |
| MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = { | |
| MODEL_TENSOR.FFN_DOWN, | |
| MODEL_TENSOR.FFN_UP, | |
| ], | |
| + MODEL_ARCH.RICURSIVE: [ | |
| + MODEL_TENSOR.TOKEN_EMBD, | |
| + MODEL_TENSOR.OUTPUT_NORM, | |
| + MODEL_TENSOR.OUTPUT, | |
| + MODEL_TENSOR.ATTN_NORM, | |
| + MODEL_TENSOR.ATTN_POST_NORM, | |
| + MODEL_TENSOR.ATTN_Q, | |
| + MODEL_TENSOR.ATTN_K, | |
| + MODEL_TENSOR.ATTN_V, | |
| + MODEL_TENSOR.ATTN_OUT, | |
| + MODEL_TENSOR.ATTN_Q_NORM, | |
| + MODEL_TENSOR.ATTN_K_NORM, | |
| + MODEL_TENSOR.ATTN_GATE, | |
| + MODEL_TENSOR.ATTN_VALUE_RES, | |
| + MODEL_TENSOR.FFN_PRE_NORM, | |
| + MODEL_TENSOR.FFN_POST_NORM, | |
| + MODEL_TENSOR.FFN_GATE, | |
| + MODEL_TENSOR.FFN_DOWN, | |
| + MODEL_TENSOR.FFN_UP, | |
| + ], | |
| MODEL_ARCH.AFMOE: [ | |
| MODEL_TENSOR.TOKEN_EMBD, | |
| MODEL_TENSOR.OUTPUT_NORM, | |
| diff --git a/gguf-py/gguf/gguf_writer.py b/gguf-py/gguf/gguf_writer.py | |
| index 0e7aa5012..a2e646c84 100644 | |
| --- a/gguf-py/gguf/gguf_writer.py | |
| +++ b/gguf-py/gguf/gguf_writer.py | |
| class GGUFWriter: | |
| def add_swiglu_clamp_shexp(self, values: Sequence[float]) -> None: | |
| self.add_array(Keys.LLM.SWIGLU_CLAMP_SHEXP.format(arch=self.arch), values) | |
| + def add_swiglu_clamp(self, value: float) -> None: | |
| + self.add_float32(Keys.LLM.SWIGLU_CLAMP.format(arch=self.arch), value) | |
| + | |
| def add_hidden_act(self, value: str) -> None: | |
| self.add_string(Keys.LLM.HIDDEN_ACT.format(arch=self.arch), value) | |
| diff --git a/src/llama-arch.cpp b/src/llama-arch.cpp | |
| index 92a13e985..3b53ec39a 100644 | |
| --- a/src/llama-arch.cpp | |
| +++ b/src/llama-arch.cpp | |
| static const std::map<llm_arch, const char *> LLM_ARCH_NAMES = { | |
| { LLM_ARCH_DOTS3NOTE, "dots3note" }, | |
| { LLM_ARCH_ARCEE, "arcee" }, | |
| { LLM_ARCH_AFMOE, "afmoe" }, | |
| + { LLM_ARCH_RICURSIVE, "ricursive" }, | |
| { LLM_ARCH_LAGUNA, "laguna" }, | |
| { LLM_ARCH_ERNIE4_5, "ernie4_5" }, | |
| { LLM_ARCH_ERNIE4_5_MOE, "ernie4_5-moe" }, | |
| static const std::map<llm_kv, const char *> LLM_KV_NAMES = { | |
| { LLM_KV_EXPERT_CHUNK_FEED_FORWARD_LENGTH, "%s.expert_chunk_feed_forward_length" }, | |
| { LLM_KV_SWIGLU_CLAMP_EXP, "%s.swiglu_clamp_exp" }, | |
| { LLM_KV_SWIGLU_CLAMP_SHEXP, "%s.swiglu_clamp_shexp" }, | |
| + { LLM_KV_SWIGLU_CLAMP, "%s.swiglu_clamp" }, | |
| { LLM_KV_USE_PARALLEL_RESIDUAL, "%s.use_parallel_residual" }, | |
| { LLM_KV_TENSOR_DATA_LAYOUT, "%s.tensor_data_layout" }, | |
| { LLM_KV_EXPERT_COUNT, "%s.expert_count" }, | |
| static const std::map<llm_tensor, const char *> LLM_TENSOR_NAMES = { | |
| { LLM_TENSOR_ATTN_Q_NORM, "blk.%d.attn_q_norm" }, | |
| { LLM_TENSOR_ATTN_K_NORM, "blk.%d.attn_k_norm" }, | |
| { LLM_TENSOR_ATTN_GATE, "blk.%d.attn_gate" }, | |
| + { LLM_TENSOR_ATTN_VALUE_RES, "blk.%d.attn_value_res" }, | |
| { LLM_TENSOR_ATTN_RESID_ALPHA, "blk.%d.attn_resid_alpha" }, | |
| { LLM_TENSOR_ATTN_RESID_BETA, "blk.%d.attn_resid_beta" }, | |
| { LLM_TENSOR_FFN_POST_NORM, "blk.%d.post_ffw_norm" }, | |
| static const std::map<llm_tensor, llm_tensor_info> LLM_TENSOR_INFOS = { | |
| {LLM_TENSOR_ATTN_QKV, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}}, | |
| {LLM_TENSOR_ATTN_OUT, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}}, | |
| {LLM_TENSOR_ATTN_GATE, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}}, | |
| + {LLM_TENSOR_ATTN_VALUE_RES, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL}}, | |
| {LLM_TENSOR_ATTN_RESID_ALPHA, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL}}, | |
| {LLM_TENSOR_ATTN_RESID_BETA, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL}}, | |
| {LLM_TENSOR_FFN_GATE, {LLM_TENSOR_LAYER_REPEATING, GGML_OP_MUL_MAT}}, | |
| diff --git a/src/llama-arch.h b/src/llama-arch.h | |
| index f811607b6..5a2d8272d 100644 | |
| --- a/src/llama-arch.h | |
| +++ b/src/llama-arch.h | |
| enum llm_arch { | |
| LLM_ARCH_DOTS3NOTE, | |
| LLM_ARCH_ARCEE, | |
| LLM_ARCH_AFMOE, | |
| + LLM_ARCH_RICURSIVE, | |
| LLM_ARCH_LAGUNA, | |
| LLM_ARCH_ERNIE4_5, | |
| LLM_ARCH_ERNIE4_5_MOE, | |
| enum llm_kv { | |
| LLM_KV_EXPERT_CHUNK_FEED_FORWARD_LENGTH, | |
| LLM_KV_SWIGLU_CLAMP_EXP, | |
| LLM_KV_SWIGLU_CLAMP_SHEXP, | |
| + LLM_KV_SWIGLU_CLAMP, | |
| LLM_KV_USE_PARALLEL_RESIDUAL, | |
| LLM_KV_TENSOR_DATA_LAYOUT, | |
| LLM_KV_EXPERT_COUNT, | |
| enum llm_tensor { | |
| LLM_TENSOR_ATTN_SINKS, | |
| LLM_TENSOR_ATTN_SSMAX, | |
| LLM_TENSOR_ATTN_GATE, | |
| + LLM_TENSOR_ATTN_VALUE_RES, | |
| LLM_TENSOR_ATTN_RESID_ALPHA, | |
| LLM_TENSOR_ATTN_RESID_BETA, | |
| LLM_TENSOR_FFN_GATE_INP, | |
| diff --git a/src/llama-hparams.h b/src/llama-hparams.h | |
| index 95daf482d..4a9a2cf75 100644 | |
| --- a/src/llama-hparams.h | |
| +++ b/src/llama-hparams.h | |
| struct llama_hparams { | |
| // Additional scale factors (Granite/Granite MoE) | |
| float f_residual_scale = 0.0f; | |
| float f_embedding_scale = 0.0f; | |
| + float f_swiglu_clamp = 0.0f; // dense FFN: silu(min(gate, c)) * clamp(up, -c, c) | |
| float f_attention_scale = 0.0f; | |
| // grok-2 | |
| diff --git a/src/llama-model.cpp b/src/llama-model.cpp | |
| index 3c4e598f1..ed395b0b2 100644 | |
| --- a/src/llama-model.cpp | |
| +++ b/src/llama-model.cpp | |
| static llama_model * llama_model_mapping(llm_arch arch, const llama_model_params | |
| return new llama_model_arcee(params); | |
| case LLM_ARCH_AFMOE: | |
| return new llama_model_afmoe(params); | |
| + case LLM_ARCH_RICURSIVE: | |
| + return new llama_model_ricursive(params); | |
| case LLM_ARCH_LAGUNA: | |
| return new llama_model_laguna(params); | |
| case LLM_ARCH_ERNIE4_5: | |
| llama_rope_type llama_model_rope_type(const llama_model * model) { | |
| case LLM_ARCH_COGVLM: | |
| case LLM_ARCH_PANGU_EMBED: | |
| case LLM_ARCH_AFMOE: | |
| + case LLM_ARCH_RICURSIVE: | |
| case LLM_ARCH_LAGUNA: | |
| case LLM_ARCH_QWEN3NEXT: | |
| case LLM_ARCH_CLOVER_MOE: | |
| diff --git a/src/llama-model.h b/src/llama-model.h | |
| index 45d2b8666..2c3d6b15d 100644 | |
| --- a/src/llama-model.h | |
| +++ b/src/llama-model.h | |
| struct llama_layer { | |
| struct ggml_tensor * wv_enc = nullptr; | |
| struct ggml_tensor * wo_enc = nullptr; | |
| struct ggml_tensor * wqkv_gate = nullptr; | |
| + struct ggml_tensor * attn_value_res = nullptr; // ricursive: value-residual mix logit, [1] | |
| struct ggml_tensor * wqkv_gate_b = nullptr; | |
| // K2 Horizon MoVA | |
| struct ggml_tensor * attn_v_gate = nullptr; | |
| diff --git a/src/models/models.h b/src/models/models.h | |
| index dd3b7b1ed..449ac3c37 100644 | |
| --- a/src/models/models.h | |
| +++ b/src/models/models.h | |
| struct llama_model_afmoe : public llama_model_base { | |
| }; | |
| +struct llama_model_ricursive : public llama_model_base { | |
| + llama_model_ricursive(const struct llama_model_params & params) : llama_model_base(params) {} | |
| + void load_arch_hparams(llama_model_loader & ml) override; | |
| + void load_arch_tensors(llama_model_loader & ml) override; | |
| + | |
| + struct graph : public llm_graph_context { | |
| + graph(const llama_model & model, const llm_graph_params & params); | |
| + }; | |
| + | |
| + std::unique_ptr<llm_graph_context> build_arch_graph(const llm_graph_params & params) const override; | |
| +}; | |
| + | |
| + | |
| struct llama_model_beam : public llama_model_base { | |
| llama_model_beam(const struct llama_model_params & params) : llama_model_base(params) {} | |
| void load_arch_hparams(llama_model_loader & ml) override; | |
| diff --git a/src/models/ricursive.cpp b/src/models/ricursive.cpp | |
| new file mode 100644 | |
| index 000000000..d11255d8f | |
| --- /dev/null | |
| +++ b/src/models/ricursive.cpp | |
| +#include "models.h" | |
| + | |
| +void llama_model_ricursive::load_arch_hparams(llama_model_loader & ml) { | |
| + ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps); | |
| + ml.get_key(LLM_KV_EMBEDDING_SCALE, hparams.f_embedding_scale, false); | |
| + ml.get_key(LLM_KV_SWIGLU_CLAMP, hparams.f_swiglu_clamp, false); | |
| + | |
| + // 4 sliding (RoPE) : 1 full (NoPE), the window includes the current token | |
| + ml.get_key(LLM_KV_ATTENTION_SLIDING_WINDOW, hparams.n_swa); | |
| + hparams.swa_type = LLAMA_SWA_TYPE_STANDARD; | |
| + load_swa_pattern(ml, 5); | |
| + | |
| + hparams.rope_freq_base_train_swa = hparams.rope_freq_base_train; | |
| + hparams.rope_freq_scale_train_swa = hparams.rope_freq_scale_train; | |
| + ml.get_key(LLM_KV_ROPE_FREQ_BASE_SWA, hparams.rope_freq_base_train_swa, false); | |
| + | |
| + switch (hparams.n_layer()) { | |
| + case 80: type = LLM_TYPE_65B; break; | |
| + default: type = LLM_TYPE_UNKNOWN; | |
| + } | |
| +} | |
| + | |
| +void llama_model_ricursive::load_arch_tensors(llama_model_loader &) { | |
| + LLAMA_LOAD_LOCALS; | |
| + | |
| + tok_embd = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, 0); | |
| + | |
| + // output | |
| + 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}, 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) { | |
| + auto & layer = layers[i]; | |
| + | |
| + // sandwich attention normalization | |
| + layer.attn_norm = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "weight", i), {n_embd}, 0); | |
| + layer.attn_post_norm = create_tensor(tn(LLM_TENSOR_ATTN_POST_NORM, "weight", i), {n_embd}, 0); | |
| + | |
| + create_tensor_qkv(layer, i, n_embd, n_embd_head_k * n_head, n_embd_k_gqa, n_embd_v_gqa, 0); | |
| + layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd_head_k * n_head, n_embd}, 0); | |
| + | |
| + layer.attn_q_norm = create_tensor(tn(LLM_TENSOR_ATTN_Q_NORM, "weight", i), {n_embd_head_k}, 0); | |
| + layer.attn_k_norm = create_tensor(tn(LLM_TENSOR_ATTN_K_NORM, "weight", i), {n_embd_head_k}, 0); | |
| + | |
| + // elementwise sigmoid gate on the attention output | |
| + layer.wqkv_gate = create_tensor(tn(LLM_TENSOR_ATTN_GATE, "weight", i), {n_embd, n_embd_head_k * n_head}, 0); | |
| + | |
| + // value residual: v_proj sees lerp(scaled token embeddings, attn_norm output, sigmoid(lambda)) | |
| + layer.attn_value_res = create_tensor(tn(LLM_TENSOR_ATTN_VALUE_RES, "weight", i), {1}, 0); | |
| + | |
| + // sandwich ffn normalization | |
| + layer.ffn_norm = create_tensor(tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, 0); | |
| + layer.ffn_post_norm = create_tensor(tn(LLM_TENSOR_FFN_POST_NORM, "weight", i), {n_embd}, 0); | |
| + | |
| + layer.ffn_gate = create_tensor(tn(LLM_TENSOR_FFN_GATE, "weight", i), {n_embd, n_ff}, 0); | |
| + layer.ffn_down = create_tensor(tn(LLM_TENSOR_FFN_DOWN, "weight", i), {n_ff, n_embd}, 0); | |
| + layer.ffn_up = create_tensor(tn(LLM_TENSOR_FFN_UP, "weight", i), {n_embd, n_ff}, 0); | |
| + } | |
| +} | |
| + | |
| +std::unique_ptr<llm_graph_context> llama_model_ricursive::build_arch_graph(const llm_graph_params & params) const { | |
| + return std::make_unique<graph>(*this, params); | |
| +} | |
| + | |
| +llama_model_ricursive::graph::graph(const llama_model & model, const llm_graph_params & params) : 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 == n_rot); | |
| + | |
| + ggml_tensor * cur; | |
| + ggml_tensor * inpL; | |
| + | |
| + // build_inp_embd applies hparams.f_embedding_scale (sqrt(n_embd) here) itself | |
| + inpL = build_inp_embd(model.tok_embd); | |
| + cb(inpL, "inp_scaled", -1); | |
| + | |
| + // the value-residual source for every layer, including layer 0 | |
| + ggml_tensor * inp_embd = inpL; | |
| + | |
| + // inp_pos - contains the positions | |
| + ggml_tensor * inp_pos = build_inp_pos(); | |
| + auto * inp_attn = build_attn_inp_kv_iswa(); | |
| + ggml_tensor * inp_out_ids = build_inp_out_ids(); | |
| + | |
| + const float kq_scale = 1.0f/sqrtf(float(n_embd_head)); | |
| + | |
| + for (int il = 0; il < n_layer; ++il) { | |
| + res->t_layer_inp[il] = inpL; | |
| + | |
| + const auto & layer = model.layers[il]; | |
| + | |
| + const bool is_swa = hparams.is_swa(il); | |
| + | |
| + ggml_tensor * inpSA = inpL; | |
| + | |
| + cur = build_norm(inpL, layer.attn_norm, NULL, LLM_NORM_RMS, il); | |
| + cb(cur, "attn_norm", il); | |
| + | |
| + // self-attention | |
| + { | |
| + ggml_tensor * attn_inp = cur; | |
| + | |
| + ggml_tensor * Qcur = build_lora_mm(layer.wq, cur, layer.wq_s); | |
| + cb(Qcur, "Qcur", il); | |
| + ggml_tensor * Kcur = build_lora_mm(layer.wk, cur, layer.wk_s); | |
| + cb(Kcur, "Kcur", il); | |
| + | |
| + ggml_tensor * mix = ggml_sigmoid(ctx0, layer.attn_value_res); | |
| + ggml_tensor * vinp = ggml_add(ctx0, inp_embd, ggml_mul(ctx0, ggml_sub(ctx0, cur, inp_embd), mix)); | |
| + cb(vinp, "vres_inp", il); | |
| + ggml_tensor * Vcur = build_lora_mm(layer.wv, vinp, layer.wv_s); | |
| + 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 = build_norm(Qcur, layer.attn_q_norm, NULL, LLM_NORM_RMS, il); | |
| + Kcur = build_norm(Kcur, layer.attn_k_norm, NULL, LLM_NORM_RMS, il); | |
| + cb(Qcur, "Qcur_normed", il); | |
| + cb(Kcur, "Kcur_normed", il); | |
| + | |
| + // full-attention layers carry no positional encoding | |
| + if (is_swa) { | |
| + const float freq_base_l = model.get_rope_freq_base (cparams, il); | |
| + const float freq_scale_l = model.get_rope_freq_scale(cparams, il); | |
| + | |
| + Qcur = ggml_rope_ext( | |
| + ctx0, Qcur, inp_pos, nullptr, | |
| + n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, | |
| + ext_factor, attn_factor, beta_fast, beta_slow); | |
| + Kcur = ggml_rope_ext( | |
| + ctx0, Kcur, inp_pos, nullptr, | |
| + n_rot, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, | |
| + ext_factor, attn_factor, beta_fast, beta_slow); | |
| + cb(Qcur, "Qcur_rope", il); | |
| + cb(Kcur, "Kcur_rope", il); | |
| + } | |
| + | |
| + cur = build_attn(inp_attn, | |
| + NULL, NULL, NULL, // wo is applied after gating | |
| + Qcur, Kcur, Vcur, nullptr, nullptr, nullptr, kq_scale, il); | |
| + cb(cur, "attn_out", il); | |
| + | |
| + // attention gating: attn_out * sigmoid(g_proj(attn_norm)) BEFORE o_proj | |
| + ggml_tensor * gate = build_lora_mm(layer.wqkv_gate, attn_inp); | |
| + gate = ggml_sigmoid(ctx0, gate); | |
| + cb(gate, "attn_gate_sig", il); | |
| + cur = ggml_mul(ctx0, cur, gate); | |
| + cb(cur, "attn_gated", il); | |
| + | |
| + cur = build_lora_mm(layer.wo, cur, layer.wo_s); | |
| + cb(cur, "attn_o_proj", il); | |
| + } | |
| + | |
| + cur = build_norm(cur, layer.attn_post_norm, NULL, LLM_NORM_RMS, il); | |
| + cb(cur, "attn_post_norm", il); | |
| + | |
| + if (il == n_layer - 1 && 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); | |
| + | |
| + cur = build_norm(ffn_inp, layer.ffn_norm, NULL, LLM_NORM_RMS, il); | |
| + cb(cur, "ffn_norm", il); | |
| + | |
| + // dense SwiGLU with pre-activation clamping | |
| + { | |
| + ggml_tensor * up = build_lora_mm(layer.ffn_up, cur, layer.ffn_up_s); | |
| + cb(up, "ffn_up", il); | |
| + ggml_tensor * gate = build_lora_mm(layer.ffn_gate, cur, layer.ffn_gate_s); | |
| + cb(gate, "ffn_gate", il); | |
| + | |
| + if (hparams.f_swiglu_clamp > 0.0f) { | |
| + cur = ggml_swiglu_clamp(ctx0, gate, up, hparams.f_swiglu_clamp); | |
| + } else { | |
| + cur = ggml_swiglu_split(ctx0, gate, up); | |
| + } | |
| + cb(cur, "ffn_swiglu", il); | |
| + | |
| + cur = build_lora_mm(layer.ffn_down, cur, layer.ffn_down_s); | |
| + cb(cur, "ffn_out", il); | |
| + } | |
| + | |
| + cur = build_norm(cur, layer.ffn_post_norm, NULL, LLM_NORM_RMS, il); | |
| + cb(cur, "ffn_post_norm", il); | |
| + | |
| + cur = ggml_add(ctx0, cur, ffn_inp); | |
| + 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, model.output_s); | |
| + cb(cur, "result_output", -1); | |
| + res->t_logits = cur; | |
| +} | |