GitHub avatar

Fox's Blog

Luna Protocol: Why I Fine-Tuned a 1.5 Billion Parameter Model on 50k Discord Samples, and Why Few-Shot Priming Changed Everything

A smaller model trained on less data can outperform a bigger model -- if you know how to prime it. Why Luna Protocol moved from a Hermes 3B to a Qwen 1.5B fine-tune, and why few-shot priming became the real progress driver.

Luna Protocol: why I fine-tuned a 1.5 billion parameter model on 50k Discord samples, and why few-shot priming changed everything

In the first article, I built a Discord bot that simulates a human being: sleep, typos, hesitations, forgetfulness, spontaneous messages. The behavioral system held up. The LLM behind it all was a 3 billion parameter Hermes model, quantized in Q8_0, consuming 3 GB of VRAM.

It worked. But it was oversized.

A Discord bot doesn't need a 3 billion parameter model to say "nm just chillin, u". What it needs is stylistic consistency: the ability to keep a precise conversational tone, message after message, without drifting into "corporate assistant" mode. And it turns out a smaller model, trained on less data and primed with a few examples, does that better than a bigger model forced through a plain system prompt.

This article covers Luna Protocol's official models: why they exist, why 1.5B instead of 3B, why 50k training samples instead of 7.3M, and why few-shot priming went from "nice bonus" to the heart of the whole approach.


The problem with the 3B model

The original setup used Discord-Micae-Hermes-3-3B.Q8_0.gguf, a 3 billion parameter model fine-tuned on Discord data. It produced good replies, but:

Metric Hermes-3-3B Q8_0 Goal
VRAM usage ~3 GB < 1 GB
Token generation ~30 tok/s ~60+ tok/s
Model file size ~3.2 GB < 1 GB
Cold start time ~8s ~3s

For a bot running 24/7 on a modest server, 3 GB of VRAM is a lot. And generation speed, fine for occasional messages, felt sluggish during burst replies or with several active channels.

The question was: can you get the same Discord-Dialogues style with half the parameters?


The fine-tuning decision: why 50k, not 7.3M

The Discord-Dialogues dataset holds 7.3M exchanges and 17M turns. It's a massive corpus of real Discord conversations. The obvious approach would have been training on the whole dataset.

I did the opposite. I trained on 50,000 samples, under 1% of the available data.

Here's why: training set size directly affects how overfitted the model gets to its training distribution.

A model trained on 7.3M examples learns a very specific statistical distribution of conversations. It gets excellent at reproducing that distribution, but it also becomes rigid: it has less room to adapt to new patterns provided at inference time.

A model trained on 50k examples learns the general tone and register of Discord conversations (informal, short, abbreviations, lowercase), but keeps enough flexibility to be steered by in-context examples. Few-shot examples don't fight a massive already-learned distribution: they complete a lighter one.

That's the core intuition: limited training data makes few-shot priming more effective.


The model: technical details

The Luna Protocol model is a QLoRA fine-tune of Qwen2.5-1.5B-Instruct:

Parameter Value
Base model unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Method QLoRA (4-bit)
LoRA rank r=16, lora_alpha=16
Targeted modules q/k/v/o_proj, gate/up/down_proj
Trainable params 18 464 768 / 1 562 179 072 (1.18%)
Training data ~50,000 samples (Discord-Dialogues subset)
Filter 8-512 tokens per sample
Epochs 2-3
Hardware Kaggle T4
Framework Unsloth

The dataset is a preprocessed fork of Discord-Dialogues, filtered to keep only clean user/assistant turns: only user and assistant exchanges, no system messages, no metadata, no bot commands. That matters for what follows.

Available quantizations

File Quantization Size Notes
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 MB Clearly degraded -- not recommended
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 MB Good size/quality tradeoff (recommended)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1.65 GB Best stylistic fidelity

The recommended model is Q4_K_M: under 1 GB, fast, and it preserves conversational style well. Q2_K degrades too much for a model that size. Q8_0 gives the best quality but consumes 68% more memory.


The few-shot priming breakthrough

Here's the part that changed everything.

The model's HuggingFace card carries a warning:

With a bare prompt and no priming, this model tends to fall back into Qwen's default "assistant" tone. A short few-shot priming makes a big difference.

That's a direct consequence of how the training data was structured.

Why system prompts alone don't work

The Discord-Dialogues training data only contains user/assistant turns. There is no system-role example in the training set. The model was never trained to follow system prompts as style directives.

When you give it a system prompt like "Your name is Luna, talk casually", it hears the instruction but has no solid learned pattern to translate it into output. So it falls back to Qwen's default behavior: helpful, structured, slightly formal.

Why few-shot examples work

When you inject conversation examples in the same ChatML format used at training (with the user/assistant turn structure), something clicks. The model recognizes the pattern from its training and aligns its output accordingly.

Here's what few-shot priming looks like in practice:

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Those examples are injected after the system prompt and before the real conversation. The model perceives them as part of the conversation history, so as a real exchange rather than as instructions. That's an essential distinction: you show it what the casual tone looks like instead of ordering it.

Before / after

No few-shot priming (bare system prompt):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

With few-shot priming (3 examples):

User: yo whats good
Bot: nm just chillin, u

The difference is stark. The model adopts the whole register: lowercase, abbreviations, casual tone, short replies. It mirrors the examples' style rather than Qwen's training data.


Memory and speed: the concrete numbers

Moving from Hermes-3-3B to Luna-Protocol-1.5B brings measurable gains:

Metric Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Improvement
VRAM usage ~3 GB ~986 MB 67% less
Model file size ~3.2 GB ~986 MB 69% smaller
Token generation ~30 tok/s ~60+ tok/s 2x faster
Cold start ~8s ~3s 62% faster
Context window 8192 8192 Identical

Why the speed gain is real

Smaller models are fundamentally faster at inference. With 1.5B parameters instead of 3B:

  • Fewer matrix multiplications per token: attention layers, FFN layers, and the output projection all scale linearly with parameter count
  • Better cache usage: the smaller model fits more of its weights in L2/L3 cache
  • Less memory bandwidth pressure: fewer bytes to read from VRAM per token

On a modest CPU-only setup (2 cores, no GPU), the 1.5B model generates tokens at about 2x the speed of the 3B model. That's the difference between "smells like a bot" and "feels like a real person typing".

Prompt cache amplifies the advantage

Luna Protocol uses llama-server with prompt cache enabled (--cache-reuse 256). That means:

  1. The first message of a session pays the full prompt-processing cost (system prompt + few-shot examples + user message)
  2. Later messages only process the new tokens, since the cached prefix is reused
  3. With 5 few-shot examples (~50-150 tokens), the overhead becomes negligible after the first request

Few-shot examples become effectively "free" after a session's first message. The model gets style guidance at near-zero marginal cost.


The implementation: how it works in code

Luna Protocol's few-shot system is clean and minimal. Three files handle everything.

1. Configuration (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

Configuration is hot-reloadable. You edit the examples, save, and the bot immediately adopts the new style, no restart.

2. Formatting and injection (src/core/few-shot.ts)

The formatFewShotExamples() function converts YAML examples into ChatML message objects:

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

The injectFewShotIntoConversation() function places them right after the system prompt:

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Integration (src/core/llm-client.ts)

Before each LLM call, few-shot examples are injected if enabled:

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

The model receives: [system_prompt] + [few_shot_examples] + [conversation_history]


Keeping the Discord-Dialogues style

The original Discord-Dialogues dataset has a very specific conversational signature:

  • Short messages: 32.8 tokens average per turn
  • Informal register: abbreviations, lowercase, no punctuation
  • Fast exchanges: several short exchanges rather than long monologues
  • Natural imperfections: typos, "lol", "fr", "ngl", "tbh"

The Luna Protocol model preserves that style through two mechanisms:

1. Fine-tuning shifts the base distribution

The 50k training samples teach the model the statistical fingerprint of Discord conversations. It learns replies are typically short, lowercase, and informal. That moves the model's default output away from Qwen's "helpful assistant" mode.

2. Few-shot priming locks the result

Few-shot examples reinforce exactly the patterns learned during fine-tuning. They act as a stylistic anchor: even if the model slightly drifts toward a more formal tone over a long conversation, the examples in context pull it back.

The combination beats each mechanism on its own:

  • Fine-tuning without few-shot: the model is globally casual but inconsistent
  • Few-shot without fine-tuning: the model tries to follow examples but keeps falling back into assistant mode
  • Fine-tuning + few-shot: the model stays consistently in character

The philosophy: smaller model, smarter prompting

Conventional wisdom in LLM deployment says "bigger is better". More parameters, more training data, more VRAM. Luna Protocol takes the opposite path:

  • 1.5B instead of 3B: half the parameters, half the memory, twice as fast
  • 50k samples instead of 7.3M: less training data, more flexibility for in-context learning
  • Few-shot priming instead of system prompts: showing the model what you want, not just telling it

That's a deliberate design choice, far more than a technical optimization. A Discord bot needs to stay a lightweight conversational companion, not a generalist assistant. It must say "nm just chillin, u" consistently, fast, and without eating the server's whole VRAM budget.

Result: a bot running on a $5/month VPS, generating tokens fast enough to feel like real-time typing, and keeping a coherent personality through a fine-tuning + few-shot priming combo worth more than the sum of its parts.


Setup

Download the model

npm run download-model
# Downloads Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

Or manually from HuggingFace.

Configure

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Launch

npm run dev                    # dev (hot reload)
npm run build && npm start     # production
./start.sh                     # PM2 (production with llama-server)

Conclusion

The Luna Protocol models prove that for style-driven conversational AI, less is more. A 1.5B model trained on 50k carefully picked samples, primed with a few examples, outperforms a 3B model trained on millions of examples, for a fraction of the memory cost and twice the generation speed.

Few-shot priming is the core mechanism for small models. It's what makes them viable for real-time conversational apps. Examples do way more than "help": they fundamentally change the model's behavior, mirroring exactly the format it trained on.

The code is open source, the model is on HuggingFace, and the dataset is public. If you want to build a conversational bot that feels human, the recipe is: small model, limited fine-tuning, solid few-shot priming.

Resource Link
GitHub repo fox3000foxy/luna-protocol-project
Model (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Dataset Discord-Dialogues
First article Luna Protocol: I built an autonomous Discord bot

Luna Protocol : pourquoi j'ai fine-tuné un modèle de 1,5 milliard de paramètres sur 50k échantillons Discord, et pourquoi le few-shot priming a tout changé

Un modèle plus petit entraîné sur moins de données peut surpasser un modèle plus gros -- à condition de savoir bien l'amorcer. Voici pourquoi Luna Protocol est passé d'un Hermes 3B à un fine-tune Qwen 1,5B, et pourquoi le few-shot priming est devenu le vrai facteur de progrès.

Luna Protocol : pourquoi j'ai fine-tuné un modèle de 1,5 milliard de paramètres sur 50k échantillons Discord, et pourquoi le few-shot priming a tout changé

Dans le premier article, j'ai construit un bot Discord qui simule un être humain : sommeil, fautes de frappe, hésitations, oublis, messages spontanés. Le système comportemental tenait la route. Le LLM derrière tout ça était un modèle Hermes de 3 milliards de paramètres, quantifié en Q8_0, consommant 3 Go de VRAM.

Ça fonctionnait. Mais c'était surdimensionné.

Un bot Discord n'a pas besoin d'un modèle de 3 milliards de paramètres pour dire « nm just chillin, u ». Ce dont il a besoin, c'est de cohérence stylistique : la capacité à conserver un ton conversationnel précis, message après message, sans dériver vers un mode « assistant corporate ». Et il s'avère qu'un modèle plus petit, entraîné sur moins de données et amorcé avec quelques exemples, y parvient mieux qu'un modèle plus gros qui force le passage via un simple prompt système.

Cet article porte sur les modèles officiels de Luna Protocol : pourquoi ils existent, pourquoi 1,5B plutôt que 3B, pourquoi 50k échantillons d'entraînement plutôt que 7,3M, et pourquoi le few-shot priming est passé du statut de « bonus sympa » à celui de cœur de toute l'approche.


Le problème avec le modèle 3B

La configuration d'origine utilisait Discord-Micae-Hermes-3-3B.Q8_0.gguf, un modèle de 3 milliards de paramètres fine-tuné sur des données Discord. Il produisait de bonnes réponses, mais :

Métrique Hermes-3-3B Q8_0 Objectif
Utilisation VRAM ~3 Go < 1 Go
Génération de tokens ~30 tok/s ~60+ tok/s
Taille du fichier modèle ~3,2 Go < 1 Go
Temps de démarrage à froid ~8s ~3s

Pour un bot tournant 24/7 sur un serveur modeste, 3 Go de VRAM, c'est beaucoup. Et la vitesse de génération, correcte pour des messages occasionnels, semblait poussive lors de réponses en rafale ou avec plusieurs canaux actifs.

La question était : peut-on obtenir le même style Discord-Dialogues avec deux fois moins de paramètres ?


La décision de fine-tuning : pourquoi 50k, pas 7,3M

Le jeu de données Discord-Dialogues contient 7,3M d'échanges et 17M de tours de parole. C'est un corpus massif de vraies conversations Discord. L'approche évidente aurait été d'entraîner sur la totalité du jeu de données.

J'ai fait l'inverse. J'ai entraîné sur 50 000 échantillons, soit moins de 1 % des données disponibles.

Voici pourquoi : la taille du jeu d'entraînement affecte directement le degré de surapprentissage du modèle vis-à-vis de sa distribution d'entraînement.

Un modèle entraîné sur 7,3M d'exemples apprend une distribution statistique très spécifique des conversations. Il devient excellent pour reproduire cette distribution, mais il devient aussi rigide : il a moins de marge pour s'adapter à de nouveaux motifs fournis au moment de l'inférence.

Un modèle entraîné sur 50k exemples apprend le ton et le registre général des conversations Discord (informel, court, abréviations, minuscules), mais il conserve assez de flexibilité pour être piloté par des exemples en contexte. Les exemples few-shot ne luttent pas contre une distribution massive déjà apprise : ils viennent compléter une distribution plus légère.

C'est l'intuition centrale : des données d'entraînement limitées rendent le few-shot priming plus efficace.


Le modèle : détails techniques

Le modèle Luna Protocol est un fine-tune QLoRA de Qwen2.5-1.5B-Instruct :

Paramètre Valeur
Modèle de base unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Méthode QLoRA (4-bit)
Rang LoRA r=16, lora_alpha=16
Modules ciblés q/k/v/o_proj, gate/up/down_proj
Paramètres entraînables 18 464 768 / 1 562 179 072 (1,18 %)
Données d'entraînement ~50 000 exemples (sous-ensemble de Discord-Dialogues)
Filtre 8-512 tokens par échantillon
Époques 2-3
Matériel Kaggle T4
Framework Unsloth

Le jeu de données est un fork prétraité de Discord-Dialogues, filtré pour ne conserver que des tours user/assistant propres : uniquement des échanges utilisateur et assistant, sans messages système ni métadonnées ni commandes de bot. C'est important pour la suite.

Quantifications disponibles

Fichier Quantification Taille Remarques
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 Mo Nettement dégradé -- déconseillé
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 Mo Bon compromis taille/qualité (recommandé)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 Go Meilleure fidélité stylistique

Le modèle recommandé est Q4_K_M : moins d'1 Go, rapide, et il préserve bien le style conversationnel. Le Q2_K se dégrade trop pour un modèle de cette taille. Le Q8_0 offre la meilleure qualité mais consomme 68 % de mémoire en plus.


La percée du few-shot priming

Voici la partie qui a tout changé.

La fiche du modèle sur HuggingFace comporte un avertissement :

Avec un prompt nu et sans amorçage, ce modèle a tendance à retomber dans le ton par défaut « assistant » de Qwen. Un court amorçage few-shot fait une grande différence.

C'est une conséquence directe de la façon dont les données d'entraînement ont été structurées.

Pourquoi les prompts système seuls ne fonctionnent pas

Les données d'entraînement Discord-Dialogues ne contiennent que des tours user/assistant. Il n'y a aucun exemple de rôle système dans le jeu d'entraînement. Le modèle n'a jamais été entraîné à suivre des prompts système comme directives de style.

Quand on lui donne un prompt système du type « Tu t'appelles Luna, parle de façon décontractée », il entend l'instruction mais n'a pas de motif appris solide pour la traduire en sortie. Il retombe alors sur le comportement par défaut de Qwen : serviable, structuré, légèrement formel.

Pourquoi les exemples few-shot fonctionnent

Quand on injecte des exemples de conversation dans le même format ChatML que celui utilisé à l'entraînement (avec la structure de tours user/assistant), quelque chose se déclenche. Le modèle reconnaît le motif issu de son entraînement et aligne sa sortie en conséquence.

Voici à quoi ressemble un amorçage few-shot en pratique :

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Ces exemples sont injectés après le prompt système et avant la vraie conversation. Le modèle les perçoit comme faisant partie de l'historique de conversation, donc comme un échange réel plutôt que comme des instructions. C'est une distinction essentielle : on lui montre à quoi ressemble le ton décontracté au lieu de le lui ordonner.

Avant / après

Sans amorçage few-shot (prompt système nu) :

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

Avec amorçage few-shot (3 exemples) :

User: yo whats good
Bot: nm just chillin, u

La différence est flagrante. Le modèle adopte tout le registre : minuscules, abréviations, ton décontracté, réponses courtes. Il calque le style des exemples plutôt que celui des données d'entraînement de Qwen.


Mémoire et vitesse : les chiffres concrets

Le passage de Hermes-3-3B à Luna-Protocol-1.5B apporte des gains mesurables :

Métrique Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Amélioration
Utilisation VRAM ~3 Go ~986 Mo 67 % de moins
Taille du fichier modèle ~3,2 Go ~986 Mo 69 % plus petit
Génération de tokens ~30 tok/s ~60+ tok/s 2x plus rapide
Démarrage à froid ~8s ~3s 62 % plus rapide
Fenêtre de contexte 8192 8192 Identique

Pourquoi le gain de vitesse est réel

Les modèles plus petits sont fondamentalement plus rapides en inférence. Avec 1,5B de paramètres au lieu de 3B :

  • Moins de multiplications matricielles par token : les couches d'attention, les couches FFN et la projection de sortie évoluent toutes linéairement avec le nombre de paramètres
  • Meilleure utilisation du cache : le modèle plus petit fait tenir davantage de ses poids dans le cache L2/L3
  • Moins de pression sur la bande passante mémoire : moins d'octets à lire depuis la VRAM par token

Sur une configuration modeste, CPU seul (2 cœurs, sans GPU), le modèle 1,5B génère des tokens à environ 2 fois la vitesse du modèle 3B. C'est la différence entre « ça sent le bot » et « on dirait une vraie personne en train de taper ».

Le cache de prompt amplifie l'avantage

Luna Protocol utilise llama-server avec le cache de prompt activé (--cache-reuse 256). Cela signifie que :

  1. Le premier message d'une session paie le coût complet du traitement du prompt (prompt système + exemples few-shot + message utilisateur)
  2. Les messages suivants ne traitent que les nouveaux tokens, car le préfixe mis en cache est réutilisé
  3. Avec 5 exemples few-shot (~50-150 tokens), le surcoût devient négligeable après la première requête

Les exemples few-shot deviennent en pratique « gratuits » après le premier message d'une session. Le modèle bénéficie d'un guidage de style à coût marginal nul.


L'implémentation : comment ça fonctionne en code

Le système few-shot de Luna Protocol est propre et minimal. Trois fichiers gèrent tout.

1. Configuration (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

La configuration est rechargeable à chaud. On modifie les exemples, on enregistre, et le bot adopte immédiatement le nouveau style, sans redémarrage.

2. Formatage et injection (src/core/few-shot.ts)

La fonction formatFewShotExamples() convertit les exemples YAML en objets de message ChatML :

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

La fonction injectFewShotIntoConversation() les place juste après le prompt système :

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Intégration (src/core/llm-client.ts)

Avant chaque appel au LLM, les exemples few-shot sont injectés s'ils sont activés :

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

Le modèle reçoit : [prompt_système] + [exemples_few_shot] + [historique_de_conversation]


Conserver le style Discord-Dialogues

Le jeu de données Discord-Dialogues d'origine a une signature conversationnelle très spécifique :

  • Messages courts : 32,8 tokens en moyenne par tour
  • Registre informel : abréviations, minuscules, absence de ponctuation
  • Échanges rapides : plusieurs échanges courts plutôt que de longs monologues
  • Imperfections naturelles : fautes de frappe, « lol », « fr », « ngl », « tbh »

Le modèle Luna Protocol préserve ce style grâce à deux mécanismes :

1. Le fine-tuning déplace la distribution de base

Les 50k échantillons d'entraînement enseignent au modèle l'empreinte statistique des conversations Discord. Il apprend que les réponses sont typiquement courtes, en minuscules et informelles. Cela éloigne la sortie par défaut du modèle du mode « assistant serviable » de Qwen.

2. Le few-shot priming verrouille le résultat

Les exemples few-shot renforcent exactement les motifs appris pendant le fine-tuning. Ils agissent comme un ancrage stylistique : même si le modèle dérive légèrement vers un ton plus formel au cours d'une longue conversation, les exemples présents dans le contexte le ramènent en arrière.

La combinaison est plus puissante que chaque mécanisme pris isolément :

  • Fine-tuning sans few-shot : le modèle est globalement décontracté mais inconsistant
  • Few-shot sans fine-tuning : le modèle essaie de suivre les exemples mais retombe sans cesse en mode assistant
  • Fine-tuning + few-shot : le modèle reste constamment dans le personnage

La philosophie : modèle plus petit, prompting plus malin

La sagesse conventionnelle en déploiement de LLM dit « plus gros, c'est mieux ». Plus de paramètres, plus de données d'entraînement, plus de VRAM. Luna Protocol prend le chemin inverse :

  • 1,5B au lieu de 3B : moitié moins de paramètres, moitié moins de mémoire, deux fois plus rapide
  • 50k échantillons au lieu de 7,3M : moins de données d'entraînement, plus de flexibilité pour l'apprentissage en contexte
  • Few-shot priming au lieu de prompts système : montrer au modèle ce qu'on veut, pas juste le lui dire

C'est un choix de conception assumé, bien plus qu'une simple optimisation technique. Un bot Discord a besoin de rester un compagnon conversationnel léger plutôt qu'un assistant généraliste. Il doit dire « nm just chillin, u » de façon cohérente, rapide, et sans engloutir tout le budget VRAM du serveur.

Résultat : un bot qui tourne sur un VPS à 5 $/mois, génère des tokens assez vite pour donner l'impression d'une frappe en temps réel, et maintient une personnalité cohérente grâce à une combinaison de fine-tuning et de few-shot priming qui vaut plus que la somme de ses parties.


Mise en place

Télécharger le modèle

npm run download-model
# Télécharge Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

Ou manuellement depuis HuggingFace.

Configurer

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Lancer

npm run dev                    # dev (rechargement à chaud)
npm run build && npm start     # production
./start.sh                     # PM2 (production avec llama-server)

Conclusion

Les modèles Luna Protocol prouvent que pour une IA conversationnelle axée sur le style, moins, c'est mieux. Un modèle de 1,5B entraîné sur 50k échantillons soigneusement choisis, amorcé avec quelques exemples, surpasse un modèle de 3B entraîné sur des millions d'exemples, pour une fraction du coût en mémoire et une vitesse de génération deux fois supérieure.

Le few-shot priming constitue le mécanisme central pour les petits modèles. C'est lui qui les rend viables pour des applications conversationnelles en temps réel. Les exemples font bien plus qu'« aider » : ils changent fondamentalement le comportement du modèle, en calquant exactement le format sur lequel il a été entraîné.

Le code est open source, le modèle est sur HuggingFace, et le jeu de données est public. Si tu veux construire un bot conversationnel qui donne l'impression d'être humain, la recette est : petit modèle, fine-tuning limité, amorçage few-shot solide.

Ressource Lien
Dépôt GitHub fox3000foxy/luna-protocol-project
Modèle (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Jeu de données Discord-Dialogues
Premier article Luna Protocol : j'ai créé un bot Discord autonome

Luna Protocol:为什么我在 5 万 Discord 样本上微调 15 亿参数模型,以及 few-shot 启动为什么改变一切

小模型少数据能赢大模型,前提是启动方式对。Luna Protocol 为什么从 Hermes 3B 换到 Qwen 1.5B 微调,few-shot 启动怎么从“加分项”变成核心。

Luna Protocol:为什么我在 5 万 Discord 样本上微调 15 亿参数模型,以及 few-shot 启动为什么改变一切

第一篇里我做了装人类的 Discord 机器人:睡觉、typo、犹豫、忘事、自发消息。行为系统立住了。后面的 LLM 是 30 亿 Hermes 模型,Q8_0 量化,吃 3G 显存。

能跑。但超配了。

Discord 机器人说"nm just chillin, u"用不着 30 亿参数。它要的是风格一致性:一句话接一句话守住 casual 语气,不滑回"企业助理"腔。而小模型少数据加几个示例,守这事比大模型硬靠系统提示词强。

这篇讲 Luna Protocol 官方模型:为什么存在,为什么 1.5B 不 3B,为什么 5 万训练样本不 730 万,few-shot 启动怎么从" bonus"变成全套打法的核心。


3B 模型的问题

原来配置用 Discord-Micae-Hermes-3-3B.Q8_0.gguf,30 亿参数 Discord 微调模型。回复质量好,但:

指标 Hermes-3-3B Q8_0 目标
显存占用 约 3G < 1G
token 生成 约 30 tok/s 约 60+ tok/s
模型文件 约 3.2G < 1G
冷启动 约 8 秒 约 3 秒

24/7 跑在小服务器的机器人,3G 显存很多。生成速度偶发消息还行,连发或多频道齐飞就肉。

问题:同样 Discord-Dialogues 味,能不能一半参数拿下?


微调决策:为什么 5 万,不 730 万

Discord-Dialogues 数据集有 730 万对话、1700 万轮。巨型真 Discord 对话库。直觉做法是全量训。

我反着来。训 5 万样本,不到数据的 1%。

为什么:训练集大小直接决定模型对训练分布的过拟合程度。

730 万样本训出的模型学到很尖的对话统计分布。复现这个分布无敌,但也僵:推理时给新模式,腾挪空间小。

5 万样本训出的模型学到 Discord 语气的大致样子(随意、短、缩写、小写),但留着被上下文示例带的余地。few-shot 示例不用和海量学死的分布打架:补轻分布刚刚好。

核心直觉:训练数据有限,few-shot 启动更有效。


模型:技术细节

Luna Protocol 模型是 Qwen2.5-1.5B-Instruct 的 QLoRA 微调:

参数 值
基座 unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
方法 QLoRA(4-bit)
LoRA 秩 r=16,lora_alpha=16
目标模块 q/k/v/o_proj、gate/up/down_proj
可训参数 18 464 768 / 1 562 179 072(1.18%)
训练数据 约 5 万样本(Discord-Dialogues 子集)
过滤 每样本 8-512 token
Epoch 2-3
硬件 Kaggle T4
框架 Unsloth

数据集是预处理的 Discord-Dialogues fork,只留干净 user/assistant 轮:只要用户和助手轮,不要系统消息、元数据、机器人命令。这点后面关键。

量化版本

文件 量化 大小 备注
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676M 掉点明显,不推荐
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986M 大小质量平衡(推荐)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1.65G 风格保真最好

推荐 Q4_K_M:不到 1G,快,聊天味保得好。Q2_K 这尺寸掉太多。Q8_0 质量最好但多 68% 内存。


few-shot 启动的突破

下面是改命的部分。

HuggingFace 模型卡上有句警告:

光秃系统提示词不加启动,这模型爱滑回 Qwen 默认"助理"腔。短 few-shot 启动效果差很大。

直接原因是训练数据的结构。

为什么纯系统提示词不行

Discord-Dialogues 训练数据只有 user/assistant 轮。训练集里没有任何 system role 示例。模型从没学过把系统提示词当风格指令跟。

给它"你叫 Luna,随意点"这类系统提示词,它听懂指令,但没有学实的映射转成输出。于是滑回 Qwen 默认:热心、结构化、偏正式。

为什么 few-shot 示例行

把同训练 ChatML 格式的对话示例注进去,开关触发。模型认出训练里的模式,对齐输出。

实际 few-shot 启动长这样:

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

示例注在系统提示词后、真对话前。模型当它们是历史对话的一部分,真聊过,而不是指令。区别关键:给它看随意长什么样,不命令它随意。

前后对比

无 few-shot 启动(光秃系统提示词):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

加 few-shot 启动(3 例):

User: yo whats good
Bot: nm just chillin, u

差天差地。整套 register 跟过去:小写、缩写、随意、短。它抄示例风格,不抄 Qwen 训练的风格。


内存和速度:具体数字

Hermes-3-3B 换 Luna-Protocol-1.5B,实测收益:

指标 Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M 提升
显存占用 约 3G 约 986M 少 67%
模型文件 约 3.2G 约 986M 小 69%
token 生成 约 30 tok/s 约 60+ tok/s 快 2 倍
冷启动 约 8 秒 约 3 秒 快 62%
上下文窗 8192 8192 一样

速度收益是真的

小模型推理本质上快。15 亿对 30 亿:

  • 每 token 矩阵乘法少:注意力层、FFN 层、输出投影全随参数线性走
  • 缓存更友好:小模型更多权重塞进 L2/L3
  • 显存带宽压力小:每 token 从显存放的字节少

丐版配置纯 CPU(2 核无 GPU),1.5B 生成速度约 3B 2 倍。"像机器人"和"像真人在敲字"的区别。

prompt 缓存放大优势

Luna Protocol 用 llama-server 开 prompt 缓存(--cache-reuse 256)。效果:

  1. session 首条消息付全 prompt 处理(系统提示词加 few-shot 示例加用户消息)
  2. 后面消息只处理新 token,缓存前缀复用
  3. 5 个 few-shot 示例(约 50-150 token)首条之后开销忽略

few-shot 示例实际首条消息之后"免费"。风格引导边际成本零。


实现:代码怎么跑

Luna Protocol 的 few-shot 系统干净极简。三个文件管全部。

1. 配置(config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

配置热重载。改示例,保存,机器人立刻换风格,不重启。

2. 格式化和注入(src/core/few-shot.ts)

formatFewShotExamples() 把 YAML 示例转 ChatML 消息:

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

injectFewShotIntoConversation() 插到系统提示词后面:

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. 接入(src/core/llm-client.ts)

每次调 LLM 前开着就注入 few-shot 示例:

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

模型收到:[系统提示词] + [few-shot 示例] + [对话历史]


守住 Discord-Dialogues 味

Discord-Dialogues 原数据集对话签名很鲜明:

  • 消息短:平均每轮 32.8 token
  • 随意 register:缩写、小写、不加标点
  • 快节奏:多短轮,不长独白
  • 自然瑕疵:typo、"lol"、"fr"、"ngl"、"tbh"

Luna Protocol 模型靠两机制守住风格:

1. 微调挪基准分布

5 万训练样本教模型 Discord 对话的统计指纹。它学到回复一般短、小写、随意。模型默认输出离 Qwen"热心助理"模式远了。

2. few-shot 启动锁死

few-shot 示例强化训练学过的模式。起风格锚作用:长对话里模型往正式滑,上下文里的示例把它拽回来。

组合比单用强:

  • 只微调不 few-shot:整体随意但不稳
  • 只 few-shot 不微调:跟着示例走但老滑回助理模式
  • 微调加 few-shot:一直在人物里

哲学:小模型,加聪明的启动

LLM 部署的传统智慧说"越大越好"。更多参数,更多训练数据,更多显存。Luna Protocol 反着走:

  • 1.5B 不 3B:一半参数,一半内存,两倍速度
  • 5 万样本不 730 万:训练数据少,上下文学习余地大
  • few-shot 启动不系统提示词:给模型看要什么,不只告诉它

这是深思熟虑的设计选择,不只是技术优化。Discord 机器人要的是轻量聊天伙伴,不是通用助理。它要稳定快速说"nm just chillin, u",不吃光服务器显存预算。

结果:5 美元/月 VPS 跑的机器人,token 生成快到像实时敲字,微调加 few-shot 组合守住一致人格,1 加 1 大于 2。


部署

下模型

npm run download-model
# 下 Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

或手动从 HuggingFace 拿。

配置

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

跑

npm run dev                    # 开发(热重载)
npm run build && npm start     # 生产
./start.sh                     # PM2(生产加 llama-server)

结语

Luna Protocol 模型证明,风格向对话 AI 少即是多。15 亿模型 5 万精挑样本训,加几个示例启动,赢 30 亿几百万样本训的,内存零头,生成快一倍。

few-shot 启动是小模型的核心机制。没有它小模型做不了实时对话。示例不只是"有帮助":它们根本改变模型行为,按训练格式原样对齐。

代码开源,模型在 HuggingFace,数据集公开。想做装人类的聊天机器人,配方是:小模型、有限微调、扎实 few-shot 启动。

Luna Protocol:Discord 50kサンプルで15億パラメータモデルを微調整した理由と、few-shot primingが全部変えた理由

少ないデータで訓練した小さいモデルの方が大きいモデルに勝てる。ただし起動の仕方を知ってればね。Luna ProtocolがHermes 3Bから微調整Qwen 1.5Bへ移った理由と、few-shot primingが真の進歩要因になった理由がここにある。

Luna Protocol:Discord 50kサンプルで15億パラメータモデルを微調整した理由と、few-shot primingが全部変えた理由

1本目の記事では人間を真似るDiscordボットを作った。睡眠、タイプミス、ためらい、忘却、自発メッセージだ。挙動システムは筋が通ってた。その裏のLLMは30億パラメータのHermesモデルで、Q8_0量子化、VRAM 3GB消費だった。

動いてた。でも大きすぎた。

Discordボットに「nm just chillin, u」って言うのに30億パラメータモデルは要らない。要るのは文体一貫性だ。正確な会話調子をメッセージごとに保つ能力で、「事務アシスタント」モードに流れないことだ。小さくて少ないデータで訓練したモデルを数例で起動した方が、単純システムプロンプトで通す大きいモデルよりうまくいくことが分かる。

この記事はLuna Protocol公式モデルについてだ。なぜ存在するか、なぜ3Bじゃなく1.5Bか、なぜ7.3Mじゃなく訓練サンプル50kか、なぜfew-shot primingが「いいおまけ」から手法全体の心臓になったかだ。


3Bモデルの問題

元の設定はDiscord-Micae-Hermes-3-3B.Q8_0.ggufを使ってた。Discordデータで微調整した30億パラメータモデルだ。良い応答を出してた。でもこうだ。

指標 Hermes-3-3B Q8_0 目標
VRAM使用 約3GB 1GB未満
トークン生成 約30トークン/秒 60+トークン/秒
モデルファイルサイズ 約3.2GB 1GB未満
コールド起動時間 約8秒 約3秒

控えめサーバーで24時間365日回るボットにVRAM 3GBは大きい。生成速度もたまのメッセージには正しいけど、連投応答や複数活性チャンネルではもっさり感じた。

問いはこうだった。Discord-Dialogues文体を半分のパラメータで出せるか。


微調整の決定:なぜ7.3Mじゃなく50kか

Discord-Dialoguesデータセットは730万やり取りと1,700万発話ターンを持つ。本物Discord会話の巨大コーパスだ。明らかな手法は全データセットで訓練することだった。

逆をやった。50,000サンプルで訓練した。利用可能データの1パーセント未満だ。

理由はこうだ。訓練データ量はモデルが訓練分布に過学習する度合いに直接影響する。

730万例で訓練したモデルは会話のとても特定の統計分布を学ぶ。この分布再現は得意になる。でも硬くもなる。推論時に渡す新模様に適応する余白が減る。

50k例で訓練したモデルはDiscord会話の一般的調子と語域を学ぶ(くだけた、短い、略語、小文字)。でも文脈内例で操縦される柔軟性は残る。few-shot例はすでに学んだ巨大分布と戦わない。軽い分布を補う。

これが中心的直観だ。限られた訓練データはfew-shot primingを効かせる。


モデル:技術詳細

Luna ProtocolモデルはQwen2.5-1.5B-InstructのQLoRA微調整だ。

パラメータ 値
ベースモデル unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
手法 QLoRA (4-bit)
LoRAランク r=16、lora_alpha=16
対象モジュール q/k/v/o_proj、gate/up/down_proj
訓練可能パラメータ 18 464 768 / 1 562 179 072 (1.18%)
訓練データ 約50,000例(Discord-Dialogues部分集合)
フィルタ 例あたり8-512トークン
エポック 2-3
機材 Kaggle T4
フレームワーク Unsloth

データセットはDiscord-Dialoguesの前処理forkで、きれいなuserやassistantターンだけ残すよう濾過した。ユーザーとアシスタントのやり取りだけで、システムメッセージもメタデータもボットコマンドもなしだ。後で大事になる。

利用可能量子化

ファイル 量子化 サイズ 備考
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676MB 明らかに劣化。非推奨
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986MB サイズと品質の良い妥協(推奨)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1.65GB 最高の文体忠実度

推奨モデルはQ4_K_Mだ。1GB未満で、速くて、会話文体をよく保つ。Q2_Kはこのサイズのモデルには劣化しすぎる。Q8_0は最高品質だがメモリ68パーセント増しだ。


few-shot primingの突破

全部変えた部分がここだ。

HuggingFaceのモデルカードに警告がある。

素のプロンプトで起動なしだと、このモデルはQwenデフォルトの「アシスタント」調子に戻りがちだ。短いfew-shot起動で大きく変わる。

訓練データをどう構造化したかの直接の帰結だ。

システムプロンプトだけでは動かない理由

Discord-Dialogues訓練データはuserやassistantターンしか含まない。訓練セットにシステム役の例はゼロだ。モデルはシステムプロンプトを文体指示として従う訓練をされたことがない。

「君はLunaで、気軽に話して」みたいなシステムプロンプトを渡すと、指示は聞くけど出力に翻訳する学んだ堅い模様がない。Qwenデフォルト挙動に戻る。助かる、構造的、少し堅い。

few-shot例が動く理由

訓練で使ったのと同じChatML形式(userやassistantターン構造)で会話例を注入すると、何かが起こる。モデルは訓練由来の模様を認識して、それに合わせて出力を整える。

実際のfew-shot起動はこんな感じだ。

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
   assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

この例はシステムプロンプトの後、本物の会話の前に注入される。モデルは指示じゃなく会話履歴の一部として捉える。本物のやり取りとしてね。これが本質的区別だ。気軽調子がどう見えるか見せてるんであって、命令してない。

前と後

few-shot起動なし(素のシステムプロンプト):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

few-shot起動あり(例3つ):

User: yo whats good
Bot: nm just chillin, u

違いは鮮やかだ。モデルは語域全部を取る。小文字、略語、気軽調子、短い応答だ。Qwen訓練データ文体じゃなく例文体をなぞる。


メモリと速度:具体的な数字

Hermes-3-3BからLuna-Protocol-1.5Bへの移行は測れる利得を運ぶ。

指標 Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M 改善
VRAM使用 約3GB 約986MB 67%減
モデルファイルサイズ 約3.2GB 約986MB 69%小
トークン生成 約30トークン/秒 60+トークン/秒 2倍速
コールド起動 約8秒 約3秒 62%速
文脈窓 8192 8192 同一

速度利得が本物な理由

小さいモデルは推論が根本から速い。30億じゃなく15億パラメータでこうだ。

  • トークンあたり行列乗算が少ない:注意層もFFN層も出力射影も全部パラメータ数に線形だ
  • キャッシュ利用が良い:小さいモデルはL2やL3キャッシュに重みが入りやすい
  • メモリ帯域圧が低い:トークンあたりVRAMから読むバイトが少ない

控えめ構成でCPUだけ(2コア、GPUなし)だと、1.5Bモデルは3Bモデルの約2倍速でトークン生成する。「ボットっぽい」と「打ってる本物っぽい」の違いだ。

プロンプトキャッシュが利点を増幅する

Luna Protocolはプロンプトキャッシュ有効のllama-serverを使う(--cache-reuse 256)。つまりこうだ。

  1. セッション初メッセージがプロンプト処理の完全コストを払う(システムプロンプトとfew-shot例とユーザーメッセージ)
  2. 後続メッセージは新しいトークンだけ処理する。キャッシュ前置きが再利用されるからだ
  3. few-shot例5つ(約50-150トークン)で、初回後の追加コストは無視できる

few-shot例はセッション初メッセージ後は実質「無料」になる。モデルは限界ゼロコストで文体誘導を受ける。


実装:コードでどう動くか

Luna Protocolのfew-shot仕組みはきれいで最小だ。3ファイルで全部やる。

1. 設定(config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

設定はホットリロード可能だ。例を変えて保存すれば、再起動なしでボットは即新文体を取る。

2. 整形と注入(src/core/few-shot.ts)

formatFewShotExamples()関数はYAML例をChatMLメッセージオブジェクトに変換する。

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

injectFewShotIntoConversation()関数はシステムプロンプト直後に置く。

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. 統合(src/core/llm-client.ts)

LLM呼び出しごとに、有効ならfew-shot例を注入する。

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

モデルが受け取るのはこうだ。[システムプロンプト] + [few-shot例] + [会話履歴]だ。


Discord-Dialogues文体を保つ

元Discord-Dialoguesデータセットはとても特定の会話署名を持つ。

  • 短いメッセージ:ターンあたり平均32.8トークン
  • くだけた語域:略語、小文字、句読点なし
  • 速いやり取り:長い独白じゃなく短い往復複数
  • 自然な不完全さ:タイプミス、「lol」、「fr」、「ngl」、「tbh」

Luna Protocolモデルは2仕組みでこの文体を保つ。

1. 微調整が基本分布をずらす

50k訓練サンプルがモデルにDiscord会話の統計指紋を教える。応答はだいたい短くて小文字でくだけたって学ぶ。これでモデルデフォルト出力がQwenの「助かるアシスタント」モードから遠ざかる。

2. few-shot primingが結果を固定する

few-shot例は微調整で学んだ模様を正確に強化する。文体錨として働く。長い会話でモデルが少し堅い調子に流れても、文脈内の例が引き戻す。

組み合わせは各単体より強い。

  • few-shotなし微調整:モデルは全体くだけてるけど一貫しない
  • 微調整なしfew-shot:モデルは例に従おうとするけどアシスタントモードに何度も戻る
  • 微調整とfew-shot:モデルは常に人物に留まる

哲学:小さいモデル、賢いprompting

LLMデプロイの常識は「大きい方が良い」って言う。パラメータ増し、訓練データ増し、VRAM増しだ。Luna Protocolは逆を行く。

  • 3Bじゃなく1.5B:半分のパラメータ、半分のメモリ、2倍速い
  • 7.3Mじゃなく50kサンプル:少ない訓練データ、文脈内学習の柔軟性増し
  • システムプロンプトじゃなくfew-shot priming:モデルに欲しいものを見せる、言うだけじゃない

これは単なる技術最適化じゃなく自覚的設計選択だ。Discordボットは汎用アシスタントじゃなく軽い会話仲間であり続ける必要がある。一貫して速く「nm just chillin, u」って言わなきゃいけない。サーバーVRAM予算を食い尽くさずにね。

結果:月5ドルVPSで回るボットだ。リアルタイム入力の感じが出る速さでトークン生成する。微調整とfew-shot primingの組み合わせで一貫した人格を保つ。各部分の合計より価値がある。


立ち上げ

モデルを落とす

npm run download-model
# Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.ggufを落とす

またはHuggingFaceから手動で。

設定する

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

起動する

npm run dev                    # dev(ホットリロード)
npm run build && npm start     # 本番
./start.sh                     # PM2(llama-server付き本番)

結論

Luna Protocolモデルが証明するのは、文体中心の会話AIには少ない方が良いってことだ。丁寧に選んだ50kサンプルで訓練した1.5Bモデルを数例で起動した方が、何百万例で訓練した3Bモデルに勝つ。メモリコストはごく一部で、生成速度は2倍だ。

few-shot primingが小モデルの中心的仕組みだ。リアルタイム会話アプリに使えるものにするのがこれだ。例は「助ける」だけじゃない。モデル挙動を根本から変える。訓練された形式そのままになぞらせる。

コードはオープンソース、モデルはHuggingFace、データセットは公開だ。人間っぽい会話ボットを作りたいなら、レシピはこうだ。小さいモデル、限られた微調整、堅いfew-shot起動だ。

リソース リンク
GitHubリポジトリ fox3000foxy/luna-protocol-project
モデル(HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
データセット Discord-Dialogues
1本目の記事 Luna Protocol:Discord自律ボットを作った

Luna Protocol: 15억 매개변수 모델을 Discord 5만 샘플로 미세 조정했고, 퓨샷 프라이밍이 모든 것을 바꾼 이유

데이터를 적게 훈련한 작은 모델이 큰 모델을 능가할 수 있어요. 제대로 시작하는 법만 알면요. Luna Protocol이 Hermes 3B에서 미세 조정 Qwen 1.5B로 넘어간 이유, 그리고 퓨샷 프라이밍이 진짜 진전 요소가 된 이유예요.

Luna Protocol: 15억 매개변수 모델을 Discord 5만 샘플로 미세 조정했고, 퓨샷 프라이밍이 모든 것을 바꾼 이유

첫 글에서는 사람을 흉내 내는 Discord 봇을 만들었어요. 수면, 오타, 망설임, 깜빡함, 자발 메시지. 행동 시스템은 버텼어요. 그 뒤 LLM은 30억 매개변수 Hermes 모델이었고 Q8_0으로 양자화되어 VRAM 3GB를 썼어요.

동작했어요. 하지만 과했어요.

Discord 봇에게 "nm just chillin, u"라고 말하려고 30억 매개변수 모델이 필요하지 않아요. 필요한 것은 문체 일관성이에요. "기업 비서" 모드로 흐르지 않고 정확한 대화 톤을 메시지마다 유지하는 능력. 알고 보니 데이터 적게 훈련하고 예시 몇 개로 시작한 작은 모델이 단순 시스템 프롬프트로 밀어붙이는 큰 모델보다 잘해요.

이 글은 Luna Protocol 공식 모델 이야기예요. 왜 존재하는지, 왜 3B가 아니라 1.5B인지, 왜 730만 개가 아니라 훈련 샘플 5만 개인지, 그리고 퓨샷 프라이밍이 "멋진 보너스"에서 접근 전체 심장이 된 이유예요.


3B 모델의 문제

원래 설정은 Discord-Micae-Hermes-3-3B.Q8_0.gguf를 썼어요. Discord 자료로 미세 조정된 30억 매개변수 모델. 좋은 답장을 냈지만요.

지표 Hermes-3-3B Q8_0 목표
VRAM 사용 ~3 Go < 1 Go
토큰 만들기 ~30 tok/s ~60+ tok/s
모델 파일 크기 ~3,2 Go < 1 Go
콜드 시작 시간 ~8s ~3s

24시간 도는 봇에 VRAM 3GB는 커요. 만들기 속도도 가끔 메시지에는 괜찮지만 버스트 답장이나 여러 활성 채널에는 느릿했어요.

질문은요. 절반 매개변수로 같은 Discord-Dialogues 문체를 얻을 수 있을까요?


미세 조정 결정: 730만이 아니라 5만인 이유

Discord-Dialogues 데이터셋에는 교환 730만 건과 발화 1,700만 턴이 있어요. 진짜 Discord 대화의 거대 말뭉치예요. 뻔한 접근은 데이터셋 전체로 훈련하는 것이었어요.

반대로 했어요. 50,000개 샘플로 훈련했어요. 가능한 자료의 1퍼센트 미만이에요.

이유는 이렇습니다. 훈련 자료 크기가 훈련 분포에 대한 모델 과적합 정도에 직접 영향을 줘요.

730만 예시로 훈련한 모델은 대화의 아주 특정한 통계 분포를 배워요. 그 분포 재현에는 훌륭해지지만 뻣뻣해져요. 추론 때 주는 새 패턴에 적응할 여지가 적어져요.

5만 예시로 훈련한 모델은 Discord 대화의 전반 톤과 레지스터(비공식, 짧음, 약어, 소문자)를 배우지만, 맥락 예시로 조종될 유연함을 충분히 유지해요. 퓨샷 예시는 이미 배운 거대 분포와 싸우지 않아요. 가벼운 분포를 보완하러 와요.

핵심 직관이에요. 제한된 훈련 자료가 퓨샷 프라이밍을 더 효과적으로 만들어요.


모델: 기술 세부 사항

Luna Protocol 모델은 Qwen2.5-1.5B-Instruct의 QLoRA 미세 조정이에요.

매개변수 값
토대 모델 unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
방법 QLoRA (4-bit)
LoRA 랭크 r=16, lora_alpha=16
대상 모듈 q/k/v/o_proj, gate/up/down_proj
훈련 가능 매개변수 18 464 768 / 1 562 179 072 (1,18 %)
훈련 자료 ~50 000개 예시 (Discord-Dialogues 부분집합)
필터 예시당 8-512 토큰
에포크 2-3
하드웨어 Kaggle T4
프레임워크 Unsloth

데이터셋은 Discord-Dialogues의 전처리된 포크예요. 깨끗한 user와 assistant 턴만 남기도록 필터링했어요. 사용자 교환과 비서 교환만 있고, 시스템 메시지도 메타데이터도 봇 명령어도 없어요. 이어지는 이야기에 중요해요.

가능한 양자화

파일 양자화 크기 비고
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 Mo 분명히 떨어져요. 비추천
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 Mo 크기와 품질 좋은 절충 (추천)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 Go 최고의 문체 충실도

추천 모델은 Q4_K_M이에요. 1GB 미만, 빠르고, 대화 문체를 잘 지켜요. Q2_K는 이 크기 모델에 너무 떨어져요. Q8_0은 품질이 가장 좋지만 메모리를 68퍼센트 더 써요.


퓨샷 프라이밍 돌파

모든 것을 바꾼 부분은 바로 여기예요.

HuggingFace 모델 카드에 경고가 있어요.

빈 프롬프트에 시작 없이 쓰면 이 모델은 Qwen 기본 "비서" 톤으로 돌아가는 경향이 있어요. 짧은 퓨샷 시작이 큰 차이를 만들어요.

훈련 자료가 어떻게 구조화됐는지의 직접 결과예요.

시스템 프롬프트만으로 안 되는 이유

Discord-Dialogues 훈련 자료에는 user와 assistant 턴만 있어요. 훈련 자료에 시스템 역할 예시가 전혀 없어요. 모델은 시스템 프롬프트를 문체 지시로 따르는 법을 배운 적이 없어요.

"너는 Luna야, 편하게 말해" 같은 시스템 프롬프트를 주면 지시는 듣지만 출력으로 바꾸는 탄탄한 학습 패턴이 없어요. 그러면 Qwen 기본 행동으로 돌아가요. 도움이 되고, 구조적이고, 살짝 격식 있어요.

퓨샷 예시가 되는 이유

훈련에 쓴 것과 같은 ChatML 형식으로 대화 예시를 주입하면 뭔가가 일어나요 (user와 assistant 턴 구조). 모델이 훈련에서 온 패턴을 알아보고 출력을 그에 맞춰요.

실제로 퓨샷 시작이 이렇게 생겼어요.

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

이 예시들은 시스템 프롬프트 뒤, 진짜 대화 앞에 주입돼요. 모델은 이를 대화 기록 일부, 즉 지시가 아니라 실제 교환으로 봐요. 본질적 구분이에요. 편한 톤이 어떤 모습인지 말해주지 않고 보여줘요.

전과 후

퓨샷 시작 없이 (빈 시스템 프롬프트):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

퓨샷 시작과 함께 (예시 3개):

User: yo whats good
Bot: nm just chillin, u

차이가 확연해요. 모델이 레지스터 전체를 가져가요. 소문자와 약어, 편한 톤, 짧은 답장. Qwen 훈련 자료 문체가 아니라 예시 문체를 따라 해요.


메모리와 속도: 구체 숫자

Hermes-3-3B에서 Luna-Protocol-1.5B로 넘어가면 측정 가능한 이득이 있어요.

지표 Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M 개선
VRAM 사용 ~3 Go ~986 Mo 67 % 감소
모델 파일 크기 ~3,2 Go ~986 Mo 69 % 작아요
토큰 만들기 ~30 tok/s ~60+ tok/s 2배 빨라요
콜드 시작 ~8s ~3s 62 % 빨라요
맥락 창 8192 8192 같아요

속도 이득이 진짜인 이유

작은 모델은 추론이 근본적으로 빨라요. 3B 대신 매개변수 1.5B라서요.

  • 토큰당 행렬 곱셈 감소: 어텐션 층과 FFN 층, 출력 투영이 모두 매개변수 수에 선형으로 커져요
  • 캐시 활용 향상: 작은 모델이 L2와 L3 캐시에 가중치를 더 많이 넣어요
  • 메모리 대역폭 압박 감소: 토큰당 VRAM에서 읽는 바이트가 적어요

보통 설정, CPU만 (코어 2개, GPU 없음)에서 1.5B 모델이 3B 모델의 약 2배 속도로 토큰을 만들어요. "봇 티가 나요"와 "진짜 사람이 치는 것 같아요"의 차이예요.

프롬프트 캐시가 이점을 키워요

Luna Protocol은 프롬프트 캐시를 켠 llama-server를 써요 (--cache-reuse 256). 뜻은요.

  1. 세션 첫 메시지가 프롬프트 처리 비용 전부를 내요 (시스템 프롬프트 + 퓨샷 예시 + 사용자 메시지)
  2. 이어지는 메시지는 캐시된 앞부분을 재사용해서 새 토큰만 처리해요
  3. 퓨샷 예시 5개(~50-150 토큰)면 첫 요청 뒤 부담이 무시할 만해져요

퓨샷 예시는 세션 첫 메시지 뒤에 사실상 "무료"가 돼요. 모델은 한계 비용 제로로 문체 안내를 받아요.


구현: 코드로 어떻게 동작하나요

Luna Protocol 퓨샷 시스템은 깔끔하고 미니멀해요. 파일 셋이 전부 다뤄요.

1. 설정 (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

설정은 핫리로드돼요. 예시를 고치고 저장하면 봇이 다시 시작 없이 바로 새 문체를 가져가요.

2. 형식화와 주입 (src/core/few-shot.ts)

formatFewShotExamples() 함수가 YAML 예시를 ChatML 메시지 객체로 바꿔요.

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

injectFewShotIntoConversation() 함수가 시스템 프롬프트 바로 뒤에 둬요.

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. 통합 (src/core/llm-client.ts)

LLM 호출마다 활성화되면 퓨샷 예시가 주입돼요.

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

모델이 받아요. [시스템_프롬프트] + [퓨샷_예시] + [대화_기록]


Discord-Dialogues 문체 유지하기

원본 Discord-Dialogues 데이터셋에는 아주 특정한 대화 서명이 있어요.

  • 짧은 메시지: 턴당 평균 32.8 토큰
  • 비공식 레지스터: 약어, 소문자, 구두점 부재
  • 빠른 교환: 긴 독백보다 짧은 교환 여러 개
  • 자연스러운 불완전함: 오타와 "lol", "fr", "ngl", "tbh"

Luna Protocol 모델은 두 구조로 이 문체를 지켜요.

1. 미세 조정이 토대 분포를 옮겨요

훈련 샘플 5만 개가 모델에게 Discord 대화의 통계 발자국을 가르쳐요. 답장이 보통 짧고 소문자이며 비공식임을 배워요. 모델 기본 출력을 Qwen의 "도움이 되는 비서" 모드에서 멀어지게 해요.

2. 퓨샷 프라이밍이 결과를 잠가요

퓨샷 예시는 미세 조정 때 배운 패턴을 정확히 강화해요. 문체 닻 구실을 해요. 긴 대화 중에 모델이 살짝 격식 톤으로 흘러도 맥락 속 예시가 뒤로 끌어와요.

조합이 각 구조 따로보다 강력해요.

  • 퓨샷 없는 미세 조정: 모델이 전반적으로 편하지만 일관 없어요
  • 미세 조정 없는 퓨샷: 모델이 예시를 따르려 하지만 계속 비서 모드로 돌아가요
  • 미세 조정 + 퓨샷: 모델이 계속 캐릭터에 머물러요

철학: 작은 모델, 영리한 프롬프팅

LLM 배포 통념은 "클수록 좋다"고 해요. 매개변수 더, 훈련 자료 더, VRAM 더. Luna Protocol은 반대 길을 가요.

  • 3B 대신 1.5B: 절반 매개변수, 절반 메모리, 2배 속도
  • 730만 대신 5만 샘플: 적은 훈련 자료, 맥락 학습의 더 큰 유연함
  • 시스템 프롬프트 대신 퓨샷 프라이밍: 원하는 것을 말만 하지 말고 모델에게 보여주기

단순 기술 최적화를 훨씬 넘는 가정한 설계 선택이에요. Discord 봇은 범용 비서가 아니라 가벼운 대화 동반자로 남아야 해요. VRAM 예산을 통째로 삼키지 않고 일관되고 빠르게 "nm just chillin, u"라고 말해야 해요.

결과: 월 5달러 VPS에서 돌고, 실시간 입력처럼 느껴질 만큼 빨리 토큰을 만들고, 각 부분 합보다 큰 미세 조정과 퓨샷 프라이밍 조합으로 일관된 개성을 유지하는 봇.


설치

모델 내려받기

npm run download-model
# Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf 내려받기

또는 HuggingFace에서 손으로.

설정

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

실행

npm run dev                    # 개발 (핫 리로드)
npm run build && npm start     # 프로덕션
./start.sh                     # PM2 (llama-server와 함께 프로덕션)

결론

Luna Protocol 모델들은 문체 중심 대화형 AI에 적을수록 좋다를 증명해요. 정성껏 고른 5만 샘플로 훈련한 1.5B 모델이 예시 몇 개로 시작해서 수백만 예시로 훈련한 3B 모델을 능가해요. 메모리 비용 일부분에 만들기 속도 2배로요.

퓨샷 프라이밍이 작은 모델의 핵심 구조예요. 실시간 대화 앱에 쓸 수 있게 만드는 것이 바로 이거예요. 예시는 "돕는" 것을 훨씬 넘어요. 훈련된 형식을 정확히 따라 하면서 모델 행동을 근본적으로 바꿔요.

코드는 오픈 소스, 모델은 HuggingFace에, 데이터셋은 공개. 사람처럼 느껴지는 대화 봇을 만들고 싶으면 레시피는요. 작은 모델, 제한된 미세 조정, 탄탄한 퓨샷 시작.

자료 링크
GitHub 저장소 fox3000foxy/luna-protocol-project
모델 (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
데이터셋 Discord-Dialogues
첫 글 Luna Protocol: 자율 Discord 봇을 만들었어요

Luna Protocol: 50 bin Discord örneğinde 1,5 milyar parametreli modeli neden ince ayarladım ve few-shot priming her şeyi neden değiştirdi

Daha az veride eğitilmiş daha küçük bir model daha büyük modeli geride bırakabilir, doğru başlatmayı bilmek koşuluyla. Luna Protocolün Hermes 3B modelinden ince ayarlı Qwen 1,5B modeline geçişi ve few-shot primingin neden ilerlemenin gerçek faktörü olduğu.

Luna Protocol: 50 bin Discord örneğinde 1,5 milyar parametreli modeli neden ince ayarladım ve few-shot priming her şeyi neden değiştirdi

İlk makalede insanı simüle eden bir Discord botu inşa ettim: uyku, yazım hataları, tereddütler, unutkanlıklar, spontan mesajlar. Davranış sistemi sağlam duruyordu. Bütün bunların arkasındaki LLM 3 milyar parametreli Hermes modeliydi, Q8_0 nicemlenmiş, 3 GB VRAM tüketiyor.

Çalışıyordu. Ama büyük geliyordu.

Bir Discord botunun "nm just chillin, u" demesi için 3 milyar parametreli modele ihtiyacı yoktur. İhtiyacı olan tarz tutarlılığıdır: "kurumsal asistan" moduna sapmadan mesaj mesaj kesin konuşma tonunu koruma yeteneği. Ve daha az veride eğitilmiş, birkaç örnekle başlatılmış daha küçük bir modelin bunu basit sistem istemiyle geçmeye zorlayan daha büyük modelden iyi yaptığı ortaya çıkar.

Bu makale Luna Protocol resmi modelleri hakkındadır: neden varlar, neden 3B yerine 1,5B, neden 7,3M yerine 50 bin eğitim örneği ve few-shot priming neden "hoş bonus" statüsünden tüm yaklaşımın kalbine geçti.


3B modeliyle ilgili sorun

Orijinal yapılandırma Discord verilerinde ince ayarlanmış 3 milyar parametreli Discord-Micae-Hermes-3-3B.Q8_0.gguf modelini kullanıyordu. İyi yanıtlar üretiyordu ama:

Metrik Hermes-3-3B Q8_0 Hedef
VRAM kullanımı ~3 GB < 1 GB
Jeton üretimi ~30 jeton/sn ~60+ jeton/sn
Model dosyası boyutu ~3,2 GB < 1 GB
Soğuk başlatma süresi ~8 sn ~3 sn

Mütevazı bir sunucuda 7/24 dönen bot için 3 GB VRAM çoktur. Ve üretim hızı ara sıra mesajlar için doğruyken patlama yanıtlar ya da birden çok aktif kanalda yavaştı.

Soru şuydu: Discord-Dialogues tarzının aynısı yarı parametreyle alınabilir mi?


İnce ayar kararı: neden 7,3M değil 50 bin

Discord-Dialogues veri kümesi 7,3M değiş tokuş ve 17M konuşma turu içerir. Gerçek Discord konuşmalarının devasa külliyatıdır. Bariz yaklaşım tüm veri kümesinde eğitmek olurdu.

Tersini yaptım. 50.000 örnekte eğittim, mevcut verilerin %1inden azı.

Nedeni şu: eğitim kümesi boyutu modelin eğitim dağılımına aşırı uyum derecesini doğrudan etkiler.

7,3M örnekte eğitilmiş model konuşmaların çok belirli istatistiksel dağılımını öğrenir. Bu dağılımı üretmede mükemmel olur ama katı da olur: çıkarım anında verilen yeni kalıplara uyum payı azalır.

50 bin örnekte eğitilmiş model Discord konuşmalarının genel ton ve kaydını öğrenir (resmi olmayan, kısa, kısaltmalar, küçük harfler) ama bağlam içi örneklerle sürülmek için yeterli esneklik korur. Few-shot örnekler zaten öğrenilmiş devasa dağılımla savaşmaz: daha hafif dağılımı tamamlamaya gelir.

Merkez sezgisi budur: sınırlı eğitim verileri few-shot priming daha etkili kılar.


Model: teknik ayrıntılar

Luna Protocol modeli Qwen2.5-1.5B-Instruct modelinin QLoRA ince ayarıdır:

Parametre Değer
Taban modeli unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Yöntem QLoRA (4-bit)
LoRA rütbesi r=16, lora_alpha=16
Hedeflenen modüller q/k/v/o_proj, gate/up/down_proj
Eğitilebilir parametreler 18 464 768 / 1 562 179 072 (%1,18)
Eğitim verileri ~50 000 örnek (Discord-Dialogues alt kümesi)
Filtre örnek başına 8-512 jeton
Dönem 2-3
Donanım Kaggle T4
Çerçeve Unsloth

Veri kümesi Discord-Dialogues önceden işlenmiş çatalıdır, yalnızca temiz user/assistant turları tutmak için filtrelenmiş: yalnızca kullanıcı ve asistan değiş tokuşları, sistem mesajı, meta veri ya da bot komutu yok. Devamı için önemlidir.

Mevcut nicemlemeler

Dosya Nicemleme Boyut Notlar
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 MB Belirgin bozulmuş: önerilmez
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 MB İyi boyut/kalite uzlaşması (önerilir)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 GB En iyi tarz sadakati

Önerilen model Q4_K_M dir: 1 GB altı, hızlı ve konuşma tarzını iyi korur. Q2_K bu boyutta model için fazla bozulur. Q8_0 en iyi kaliteyi verir ama %68 fazla bellek tüketir.


Few-shot priming atılımı

Her şeyi değiştiren kısım işte burası.

Modelin HuggingFace kartında bir uyarı vardır:

Çıplak istem ve başlatmasız bu model Qwen varsayılan "asistan" tonuna düşme eğilimindedir. Kısa few-shot başlatma büyük fark yaratır.

Bu eğitim verilerinin yapılandırılma biçiminin doğrudan sonucudur.

Neden yalnızca sistem istemleri işe yaramaz

Discord-Dialogues eğitim verileri yalnızca user/assistant turları içerir. Eğitim kümesinde sistem rolü örneği yoktur. Model stil direktifi olarak sistem istemlerini izlemeye hiç eğitilmemiştir.

"Luna adındasın, rahat konuş" türü sistem istemi verilince talimatı duyar ama çıktısına çevirmek için öğrenilmiş sağlam kalıbı yoktur. O zaman Qwen varsayılan davranışına düşer: yardımsever, yapılandırılmış, hafif resmi.

Few-shot örnekler neden işe yarar

Eğitimde kullanılan aynı ChatML formatında (user/assistant tur yapısıyla) konuşma örnekleri enjekte edilince bir şey tetiklenir. Model eğitiminden kalıbı tanır ve çıktısını ona göre hizalar.

Pratikte few-shot başlatma şuna benzer:

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Bu örnekler sistem isteminden sonra ve gerçek konuşmadan önce enjekte edilir. Model onları konuşma geçmişinin parçası, talimattan çok gerçek değiş tokuş olarak algılar. Bu esas ayrımdır: rahat tonun nasıl göründüğünü ona emretmek yerine gösteririz.

Önce / sonra

Few-shot başlatmasız (çıplak sistem istemi):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

Few-shot başlatmayla (3 örnek):

User: yo whats good
Bot: nm just chillin, u

Fark çarpıcıdır. Model tüm kaydı benimser: küçük harfler, kısaltmalar, rahat ton, kısa yanıtlar. Qwen eğitim verilerinin tarzından çok örneklerin tarzını taklit eder.


Bellek ve hız: somut sayılar

Hermes-3-3B modelinden Luna-Protocol-1.5B modeline geçiş ölçülebilir kazanımlar getirir:

Metrik Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M İyileşme
VRAM kullanımı ~3 GB ~986 MB %67 az
Model dosyası boyutu ~3,2 GB ~986 MB %69 küçük
Jeton üretimi ~30 jeton/sn ~60+ jeton/sn 2 kat hızlı
Soğuk başlatma ~8 sn ~3 sn %62 hızlı
Bağlam penceresi 8192 8192 Aynı

Hız kazancı neden gerçektir

Küçük modeller çıkarımda temelde hızlıdır. 3B yerine 1,5B parametreyle:

  • Jeton başına daha az matris çarpımı: dikkat katmanları, FFN katmanları ve çıktı projeksiyonu hepsi parametre sayısıyla doğrusal ölçeklenir
  • Daha iyi önbellek kullanımı: küçük model ağırlıklarının daha fazlasını L2/L3 önbelleğe sığdırır
  • Daha az bellek bant genişliği baskısı: jeton başına VRAMden okunacak daha az bayt

Mütevazı yapılandırmada, yalnızca CPU (2 çekirdek, GPU yok) 1,5B model jetonları 3B modelin yaklaşık 2 katı hızında üretir. "Bot kokmak" ile "yazan gerçek insan gibi" arasındaki fark budur.

İstem önbelleği avantajı büyütür

Luna Protocol önbellek etkin llama-server kullanır (--cache-reuse 256). Bu şu anlama gelir:

  1. Oturumun ilk mesajı istem işlemenin tam maliyetini öder (sistem istemi + few-shot örnekleri + kullanıcı mesajı)
  2. Sonraki mesajlar yalnızca yeni jetonları işler çünkü önbelleğe alınmış önek yeniden kullanılır
  3. 5 few-shot örnekle (~50-150 jeton) ek yük ilk istekten sonra ihmal edilir olur

Few-shot örnekler pratikte oturumun ilk mesajından sonra "bedava" olur. Model marjinal sıfır maliyetle tarz rehberliğinden yararlanır.


Uygulama: kodda nasıl çalışır

Luna Protocol few-shot sistemi temiz ve minimaldir. Her şeyi üç dosya yönetir.

1. Yapılandırma (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

Yapılandırma hot-reload yapılabilir. Örnekler değiştirilir, kaydedilir ve bot yeni tarzı yeniden başlatmadan hemen benimser.

2. Biçimleme ve enjeksiyon (src/core/few-shot.ts)

formatFewShotExamples() fonksiyonu YAML örneklerini ChatML mesaj nesnelerine dönüştürür:

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

injectFewShotIntoConversation() fonksiyonu onları sistem isteminden hemen sonra yerleştirir:

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Entegrasyon (src/core/llm-client.ts)

LLM her çağrılmadan önce few-shot örnekler etkinse enjekte edilir:

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

Model şunu alır: [sistem_istemi] + [few_shot_örnekleri] + [konuşma_geçmişi]


Discord-Dialogues tarzını korumak

Orijinal Discord-Dialogues veri kümesinin çok belirli konuşma imzası vardır:

  • Kısa mesajlar: tur başına ortalama 32,8 jeton
  • Resmi olmayan kayıt: kısaltmalar, küçük harfler, noktalama yokluğu
  • Hızlı değiş tokuşlar: uzun monologlardan çok birkaç kısa değiş tokuş
  • Doğal kusurlar: yazım hataları, "lol", "fr", "ngl", "tbh"

Luna Protocol modeli bu tarzı iki mekanizmayla korur:

1. İnce ayar taban dağılımı kaydırır

50 bin eğitim örneği modele Discord konuşmalarının istatistiksel ayak izini öğretir. Yanıtların tipik kısa, küçük harfli ve resmi olmayan olduğunu öğrenir. Bu modelin varsayılan çıktısını Qwen "yardımsever asistan" modundan uzaklaştırır.

2. Few-shot priming sonucu kilitler

Few-shot örnekler ince ayar sırasında öğrenilen kalıpları tam pekiştirir. Tarz çapası görevi görür: model uzun konuşmada hafif resmi tona sapsa bile bağlamdaki örnekler onu geri çeker.

Kombinasyon her mekanizmadan tek başına güçlüdür:

  • Few-shot olmadan ince ayar: model genelde rahat ama tutarsızdır
  • İnce ayar olmadan few-shot: model örnekleri izlemeye çalışır ama sürekli asistan moduna düşer
  • İnce ayar + few-shot: model sürekli karakterde kalır

Felsefe: daha küçük model, daha akıllı istemleme

LLM dağıtımında yaygın bilgelik "daha büyük daha iyidir" der. Daha fazla parametre, daha fazla eğitim verisi, daha fazla VRAM. Luna Protocol ters yolu alır:

  • 3B yerine 1,5B: yarı parametre, yarı bellek, iki kat hızlı
  • 7,3M yerine 50 bin örnek: daha az eğitim verisi, bağlam içi öğrenmeye daha fazla esneklik
  • Sistem istemleri yerine few-shot priming: modele ne istediğini söylemek değil göstermek

Bu basit teknik optimizasyondan çok üstlenilmiş tasarım seçimidir. Discord botunun genelci asistan değil hafif konuşma yoldaşı kalması gerekir. Tutarlı, hızlı ve sunucunun tüm VRAM bütçesini yutmadan "nm just chillin, u" demelidir.

Sonuç: ayda 5 $ VPSde dönen, gerçek zamanlı yazıyormuş izlenimi verecek kadar hızlı jeton üreten ve parçalarının toplamından değerli ince ayar ve few-shot priming kombinasyonu sayesinde tutarlı kişilik sürdüren bot.


Kurulum

Modeli indir

npm run download-model
# Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf indirir

Ya da HuggingFaceden manuel.

Yapılandır

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Çalıştır

npm run dev                    # geliştirme (hot reload)
npm run build && npm start     # üretim
./start.sh                     # PM2 (llama-server ile üretim)

Sonuç

Luna Protocol modelleri tarz odaklı konuşma yapay zekâsı için azın çok olduğunu kanıtlar. Özenle seçilmiş 50 bin örnekte eğitilmiş, birkaç örnekle başlatılmış 1,5B model, milyonlarca örnekte eğitilmiş 3B modeli geride bırakır; belleğin bir bölümü maliyet ve iki kat üretim hızıyla.

Few-shot priming küçük modeller için merkez mekanizmayı oluşturur. Onları gerçek zamanlı konuşma uygulamalarına uygun yapan odur. Örnekler "yardım etmekten" çok fazlasını yapar: modelin davranışını temel değiştirir, eğitildiği formatı tam taklit eder.

Kod açık kaynaktır, model HuggingFacededir ve veri kümesi herkese açıktır. İnsansı izlenimi veren konuşma botu inşa etmek istersen tarif: küçük model, sınırlı ince ayar, sağlam few-shot başlatma.

Kaynak Bağlantı
GitHub deposu fox3000foxy/luna-protocol-project
Model (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Veri kümesi Discord-Dialogues
İlk makale Luna Protocol: özerk bir Discord botu yarattım

Luna Protocol: perché ho fine-tunato un modello da 1,5 miliardi di parametri su 50k campioni Discord, e perché il few-shot priming ha cambiato tutto

Un modello più piccolo allenato su meno dati può superare un modello più grosso: a condizione di saperlo innescare bene. Ecco perché Luna Protocol è passato da un Hermes 3B a un fine-tune Qwen 1,5B, e perché il few-shot priming è diventato il vero fattore di progresso.

Luna Protocol: perché ho fine-tunato un modello da 1,5 miliardi di parametri su 50k campioni Discord, e perché il few-shot priming ha cambiato tutto

Nel primo articolo, ho costruito un bot Discord che simula un essere umano: sonno, refusi, esitazioni, dimenticanze, messaggi spontanei. Il sistema comportamentale teneva. L'LLM dietro tutto questo era un modello Hermes da 3 miliardi di parametri, quantizzato in Q8_0, che consumava 3 GB di VRAM.

Funzionava. Ma era sovradimensionato.

Un bot Discord non ha bisogno di un modello da 3 miliardi di parametri per dire "nm just chillin, u". Ciò di cui ha bisogno, è coerenza stilistica: la capacità di tenere un tono conversazionale preciso, messaggio dopo messaggio, senza derivare verso una modalità "assistente corporate". E si scopre che un modello più piccolo, allenato su meno dati e innescato con qualche esempio, ci riesce meglio di un modello più grosso che forza il passaggio via un semplice prompt di sistema.

Questo articolo riguarda i modelli ufficiali di Luna Protocol: perché esistono, perché 1,5B invece di 3B, perché 50k campioni di allenamento invece di 7,3M, e perché il few-shot priming è passato dallo status di "bonus simpatico" a quello di cuore di tutto l'approccio.


Il problema col modello 3B

La configurazione originale usava Discord-Micae-Hermes-3-3B.Q8_0.gguf, un modello da 3 miliardi di parametri fine-tunato su dati Discord. Produceva buone risposte, ma:

Metrica Hermes-3-3B Q8_0 Obiettivo
Uso VRAM circa 3 GB < 1 GB
Generazione di token circa 30 tok/s circa 60+ tok/s
Taglia del file modello circa 3,2 GB < 1 GB
Tempo di avvio a freddo circa 8s circa 3s

Per un bot che gira 24/7 su un server modesto, 3 GB di VRAM, sono tanti. E la velocità di generazione, corretta per messaggi occasionali, sembrava lenta durante risposte a raffica o con più canali attivi.

La domanda era: si può ottenere lo stesso stile Discord-Dialogues con metà parametri?


La decisione di fine-tuning: perché 50k, non 7,3M

Il dataset Discord-Dialogues contiene 7,3M scambi e 17M turni di parola. È un corpus enorme di vere conversazioni Discord. L'approccio ovvio sarebbe stato allenare su tutto il dataset.

Ho fatto l'inverso. Ho allenato su 50 000 campioni, cioè meno dell'1% dei dati disponibili.

Ecco perché: la taglia del set di allenamento influisce direttamente sul grado di overfitting del modello verso la sua distribuzione di allenamento.

Un modello allenato su 7,3M esempi impara una distribuzione statistica molto specifica delle conversazioni. Diventa ottimo a riprodurre questa distribuzione, ma diventa anche rigido: ha meno margine per adattarsi a nuovi pattern forniti al momento dell'inferenza.

Un modello allenato su 50k esempi impara il tono e il registro generale delle conversazioni Discord (informale, corto, abbreviazioni, minuscole), ma conserva abbastanza flessibilità per essere pilotato da esempi in contesto. Gli esempi few-shot non lottano contro una distribuzione enorme già appresa: vengono a completare una distribuzione più leggera.

È l'intuizione centrale: dati di allenamento limitati rendono il few-shot priming più efficace.


Il modello: dettagli tecnici

Il modello Luna Protocol è un fine-tune QLoRA di Qwen2.5-1.5B-Instruct:

Parametro Valore
Modello di base unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Metodo QLoRA (4-bit)
Rango LoRA r=16, lora_alpha=16
Moduli puntati q/k/v/o_proj, gate/up/down_proj
Parametri allenabili 18 464 768 / 1 562 179 072 (1,18%)
Dati di allenamento circa 50 000 esempi (sottoinsieme di Discord-Dialogues)
Filtro 8-512 token per campione
Epoche 2-3
Hardware Kaggle T4
Framework Unsloth

Il dataset è un fork pre-elaborato di Discord-Dialogues, filtrato per tenere solo turni user/assistant puliti: solo scambi utente e assistente, senza messaggi di sistema né metadati né comandi di bot. È importante per il seguito.

Quantizzazioni disponibili

File Quantizzazione Taglia Note
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 MB Nettamente degradato: sconsigliato
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 MB Buon compromesso taglia/qualità (raccomandato)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 GB Migliore fedeltà stilistica

Il modello raccomandato è Q4_K_M: meno di 1 GB, rapido, e preserva bene lo stile conversazionale. Il Q2_K si degrada troppo per un modello di questa taglia. Il Q8_0 offre la migliore qualità ma consuma il 68% di memoria in più.


La svolta del few-shot priming

Ecco la parte che ha cambiato tutto.

La scheda del modello su HuggingFace comporta un avviso:

Con un prompt nudo e senza innesco, questo modello tende a ricadere nel tono di default "assistente" di Qwen. Un corto innesco few-shot fa una grande differenza.

È una conseguenza diretta del modo in cui i dati di allenamento sono stati strutturati.

Perché i prompt di sistema da soli non funzionano

I dati di allenamento Discord-Dialogues contengono solo turni user/assistant. Non c'è alcun esempio di ruolo sistema nel set di allenamento. Il modello non è mai stato allenato a seguire prompt di sistema come direttive di stile.

Quando gli diamo un prompt di sistema tipo "Ti chiami Luna, parla in modo rilassato", sente l'istruzione ma non ha un pattern appreso solido per tradurla in uscita. Ricade allora sul comportamento di default di Qwen: servizievole, strutturato, leggermente formale.

Perché gli esempi few-shot funzionano

Quando iniettiamo esempi di conversazione nello stesso formato ChatML usato all'allenamento (con la struttura di turni user/assistant), qualcosa scatta. Il modello riconosce il pattern dal suo allenamento e allinea la sua uscita di conseguenza.

Ecco come è un innesco few-shot in pratica:

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Questi esempi sono iniettati dopo il prompt di sistema e prima della vera conversazione. Il modello li percepisce come parte dello storico di conversazione, quindi come uno scambio reale invece che come istruzioni. È una distinzione essenziale: gli mostriamo come è il tono rilassato invece di ordinarglielo.

Prima / dopo

Senza innesco few-shot (prompt di sistema nudo):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

Con innesco few-shot (3 esempi):

User: yo whats good
Bot: nm just chillin, u

La differenza è lampante. Il modello adotta tutto il registro: minuscole, abbreviazioni, tono rilassato, risposte corte. Ricalca lo stile degli esempi invece di quello dei dati di allenamento di Qwen.


Memoria e velocità: i numeri concreti

Il passaggio da Hermes-3-3B a Luna-Protocol-1.5B porta guadagni misurabili:

Metrica Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Miglioramento
Uso VRAM circa 3 GB circa 986 MB 67% in meno
Taglia del file modello circa 3,2 GB circa 986 MB 69% più piccolo
Generazione di token circa 30 tok/s circa 60+ tok/s 2x più rapido
Avvio a freddo circa 8s circa 3s 62% più rapido
Finestra di contesto 8192 8192 Identica

Perché il guadagno di velocità è reale

I modelli più piccoli sono fondamentalmente più rapidi in inferenza. Con 1,5B parametri invece di 3B:

  • Meno moltiplicazioni matriciali per token: gli strati di attention, gli strati FFN e la proiezione di uscita evolvono tutti linearmente col numero di parametri
  • Migliore uso della cache: il modello più piccolo fa stare più dei suoi pesi nella cache L2/L3
  • Meno pressione sulla banda di memoria: meno byte da leggere dalla VRAM per token

Su una configurazione modesta, solo CPU (2 core, senza GPU), il modello 1,5B genera token a circa 2 volte la velocità del modello 3B. È la differenza tra "si sente il bot" e "sembra una vera persona che digita".

La cache di prompt amplifica il vantaggio

Luna Protocol usa llama-server con la cache di prompt attivata (--cache-reuse 256). Questo significa che:

  1. Il primo messaggio di una sessione paga il costo completo dell'elaborazione del prompt (prompt di sistema + esempi few-shot + messaggio utente)
  2. I messaggi seguenti elaborano solo i nuovi token, perché il prefisso in cache è riusato
  3. Con 5 esempi few-shot (circa 50-150 token), il sovraccosto diventa trascurabile dopo la prima richiesta

Gli esempi few-shot diventano in pratica "gratis" dopo il primo messaggio di una sessione. Il modello beneficia di una guida di stile a costo marginale nullo.


L'implementazione: come funziona in codice

Il sistema few-shot di Luna Protocol è pulito e minimo. Tre file gestiscono tutto.

1. Configurazione (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

La configurazione è ricaricabile a caldo. Modifichi gli esempi, salvi, e il bot adotta subito il nuovo stile, senza riavvio.

2. Formattazione e iniezione (src/core/few-shot.ts)

La funzione formatFewShotExamples() converte gli esempi YAML in oggetti di messaggio ChatML:

// converte gli esempi YAML in messaggi ChatML
export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

La funzione injectFewShotIntoConversation() li piazza subito dopo il prompt di sistema:

// inserisce gli esempi dopo il prompt di sistema
export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Integrazione (src/core/llm-client.ts)

Prima di ogni chiamata all'LLM, gli esempi few-shot sono iniettati se attivati:

// inietta few-shot prima di ogni chiamata LLM
let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

Il modello riceve: [prompt_sistema] + [esempi_few_shot] + [storico_di_conversazione]


Conservare lo stile Discord-Dialogues

Il dataset Discord-Dialogues originale ha una firma conversazionale molto specifica:

  • Messaggi corti: 32,8 token in media per turno
  • Registro informale: abbreviazioni, minuscole, assenza di punteggiatura
  • Scambi rapidi: più scambi corti invece di lunghi monologhi
  • Imperfezioni naturali: refusi, "lol", "fr", "ngl", "tbh"

Il modello Luna Protocol preserva questo stile grazie a due meccanismi:

1. Il fine-tuning sposta la distribuzione di base

I 50k campioni di allenamento insegnano al modello l'impronta statistica delle conversazioni Discord. Impara che le risposte sono tipicamente corte, in minuscole e informali. Allontana l'uscita di default del modello dalla modalità "assistente servizievole" di Qwen.

2. Il few-shot priming blocca il risultato

Gli esempi few-shot rafforzano esattamente i pattern appresi durante il fine-tuning. Agiscono come un ancoraggio stilistico: anche se il modello deriva leggermente verso un tono più formale nel corso di una lunga conversazione, gli esempi presenti nel contesto lo riportano indietro.

La combinazione è più potente di ogni meccanismo preso isolatamente:

  • Fine-tuning senza few-shot: il modello è globalmente rilassato ma inconsistente
  • Few-shot senza fine-tuning: il modello prova a seguire gli esempi ma ricade senza sosta in modalità assistente
  • Fine-tuning + few-shot: il modello resta costantemente nel personaggio

La filosofia: modello più piccolo, prompting più furbo

La saggezza convenzionale in deploy di LLM dice "più grosso, meglio è". Più parametri, più dati di allenamento, più VRAM. Luna Protocol prende la strada inversa:

  • 1,5B invece di 3B: metà parametri, metà memoria, due volte più rapido
  • 50k campioni invece di 7,3M: meno dati di allenamento, più flessibilità per l'apprendimento in contesto
  • Few-shot priming invece di prompt di sistema: mostrare al modello ciò che vogliamo, non solo dirglielo

È una scelta di progettazione assunta, molto più di una semplice ottimizzazione tecnica. Un bot Discord deve restare un compagno conversazionale leggero invece di un assistente generalista. Deve dire "nm just chillin, u" in modo coerente, rapido, e senza ingoiare tutto il budget VRAM del server.

Risultato: un bot che gira su un VPS da 5 $/mese, genera token abbastanza in fretta da dare l'impressione di una digitazione in tempo reale, e mantiene una personalità coerente grazie a una combinazione di fine-tuning e few-shot priming che vale più della somma delle sue parti.


Setup

Scarica il modello

npm run download-model
# Scarica Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

O manualmente da HuggingFace.

Configura

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Lancia

npm run dev                    # dev (ricaricamento a caldo)
npm run build && npm start     # produzione
./start.sh                     # PM2 (produzione con llama-server)

Conclusione

I modelli Luna Protocol provano che per un'IA conversazionale incentrata sullo stile, meno, è meglio. Un modello da 1,5B allenato su 50k campioni scelti con cura, innescato con qualche esempio, supera un modello da 3B allenato su milioni di esempi, per una frazione del costo in memoria e una velocità di generazione doppia.

Il few-shot priming costituisce il meccanismo centrale per i piccoli modelli. È lui che li rende sostenibili per app conversazionali in tempo reale. Gli esempi fanno molto più che "aiutare": cambiano fondamentalmente il comportamento del modello, ricalcando esattamente il formato su cui è stato allenato.

Il codice è open source, il modello è su HuggingFace, e il dataset è pubblico. Se vuoi costruire un bot conversazionale che dà l'impressione di essere umano, la ricetta è: piccolo modello, fine-tuning limitato, innesco few-shot solido.

Risorsa Link
Deposito GitHub fox3000foxy/luna-protocol-project
Modello (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Dataset Discord-Dialogues
Primo articolo Luna Protocol: ho creato un bot Discord autonomo

Luna Protocol: warum ich ein 1,5-Milliarden-Parameter-Modell auf 50k Discord-Samples feingetunt habe, und warum Few-Shot-Priming alles geändert hat

Ein kleineres Modell trainiert auf weniger Daten kann ein größeres Modell übertreffen, vorausgesetzt man weiß, wie man es gut anstößt. Darum ist Luna Protocol von einem Hermes 3B zu einem Qwen-1,5B-Fine-Tune gewechselt, und warum Few-Shot-Priming vom 'netten Bonus' zum echten Fortschrittsfaktor wurde.

Luna Protocol: warum ich ein 1,5-Milliarden-Parameter-Modell auf 50k Discord-Samples feingetunt habe, und warum Few-Shot-Priming alles geändert hat

Im ersten Artikel habe ich einen Discord-Bot gebaut, der einen Menschen simuliert: Schlaf, Tippfehler, Zögern, Vergessen, spontane Nachrichten. Das Verhaltenssystem hielt stand. Das LLM dahinter war ein 3-Milliarden-Parameter-Hermes-Modell, quantisiert in Q8_0, 3 GB VRAM verbrauchend.

Das funktionierte. Aber es war überdimensioniert.

Ein Discord-Bot braucht kein 3-Milliarden-Parameter-Modell, um "nm just chillin, u" zu sagen. Was er braucht, ist stilistische Kohärenz: Die Fähigkeit, einen präzisen Konversationston beizubehalten, Nachricht für Nachricht, ohne in einen "Corporate-Assistent"-Modus abzudriften. Und es stellt sich heraus, dass ein kleineres Modell, trainiert auf weniger Daten und angestoßen mit ein paar Beispielen, das besser schafft als ein größeres Modell, das via simplem Systemprompt durchforciert.

Dieser Artikel handelt von den offiziellen Luna-Protocol-Modellen: Warum sie existieren, warum 1,5B statt 3B, warum 50k Trainingssamples statt 7,3M, und warum Few-Shot-Priming vom Status "netter Bonus" zum Herzen des ganzen Ansatzes wurde.


Das Problem mit dem 3B-Modell

Die Ursprungskonfiguration nutzte Discord-Micae-Hermes-3-3B.Q8_0.gguf, ein 3-Milliarden-Parameter-Modell feingetunt auf Discord-Daten. Es produzierte gute Antworten, aber:

Metrik Hermes-3-3B Q8_0 Ziel
VRAM-Nutzung ~3 Go < 1 Go
Token-Generierung ~30 tok/s ~60+ tok/s
Modelldateigröße ~3,2 Go < 1 Go
Kaltstartzeit ~8s ~3s

Für einen Bot, der 24/7 auf einem bescheidenen Server läuft, sind 3 GB VRAM viel. Und die Generierungsgeschwindigkeit, korrekt für gelegentliche Nachrichten, wirkte schleppend bei Burst-Antworten oder mehreren aktiven Channels.

Die Frage war: Kann man denselben Discord-Dialogues-Stil mit halb so vielen Parametern bekommen?


Die Fine-Tuning-Entscheidung: warum 50k, nicht 7,3M

Das Discord-Dialogues-Dataset enthält 7,3M Austausche und 17M Sprechtakte. Ein massives Korpus echter Discord-Gespräche. Der offensichtliche Ansatz wäre gewesen, auf dem gesamten Dataset zu trainieren.

Ich habe das Gegenteil getan. Ich habe auf 50.000 Samples trainiert, also weniger als 1 % der verfügbaren Daten.

Darum: Die Trainingsdatengröße beeinflusst direkt den Overfitting-Grad des Modells gegenüber seiner Trainingsverteilung.

Ein auf 7,3M Beispielen trainiertes Modell lernt eine sehr spezifische statistische Verteilung von Gesprächen. Es wird exzellent darin, diese Verteilung zu reproduzieren, wird aber auch starr: Es hat weniger Spielraum, sich an neue zur Inferencezeit gelieferte Muster anzupassen.

Ein auf 50k Beispielen trainiertes Modell lernt den allgemeinen Ton und das Register von Discord-Gesprächen (informell, kurz, Abkürzungen, Kleinschreibung), behält aber genug Flexibilität, um von Beispielen im Kontext gesteuert zu werden. Die Few-Shot-Beispiele kämpfen nicht gegen eine schon gelernte massive Verteilung: Sie ergänzen eine leichtere Verteilung.

Das ist die zentrale Intuition: Begrenzte Trainingsdaten machen Few-Shot-Priming effektiver.


Das Modell: technische Details

Das Luna-Protocol-Modell ist ein QLoRA-Fine-Tune von Qwen2.5-1.5B-Instruct:

Parameter Wert
Basismodell unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Methode QLoRA (4-bit)
LoRA-Rang r=16, lora_alpha=16
Zielmodule q/k/v/o_proj, gate/up/down_proj
Trainierbare Parameter 18 464 768 / 1 562 179 072 (1,18 %)
Trainingsdaten ~50 000 Beispiele (Teilmenge von Discord-Dialogues)
Filter 8-512 Tokens pro Sample
Epochen 2-3
Hardware Kaggle T4
Framework Unsloth

Das Dataset ist ein vorverarbeiteter Fork von Discord-Dialogues, gefiltert, um nur saubere user/assistant-Takte zu behalten: Nur Nutzer- und Assistentenaustausche, ohne Systemnachrichten, Metadaten oder Bot-Commands. Wichtig für die Fortsetzung.

Verfügbare Quantisierungen

Datei Quantisierung Größe Anmerkungen
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 Mo Deutlich degradiert, abgeraten
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 Mo Guter Größen/Qualitäts-Kompromiss (empfohlen)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 Go Beste stilistische Treue

Das empfohlene Modell ist Q4_K_M: Unter 1 GB, schnell, und es bewahrt den Konversationsstil gut. Das Q2_K degradiert zu stark für ein Modell dieser Größe. Das Q8_0 bietet die beste Qualität, verbraucht aber 68 % mehr Speicher.


Der Few-Shot-Priming-Durchbruch

Hier der Teil, der alles geändert hat.

Die Modellkarte auf HuggingFace trägt eine Warnung:

Mit nacktem Prompt und ohne Anstoß neigt dieses Modell dazu, in Qwens Standard-"Assistenten"-Ton zurückzufallen. Ein kurzer Few-Shot-Anstoß macht einen großen Unterschied.

Das ist eine direkte Folge davon, wie die Trainingsdaten strukturiert wurden.

Warum Systemprompts allein nicht funktionieren

Die Discord-Dialogues-Trainingsdaten enthalten nur user/assistant-Takte. Es gibt kein Systemrollen-Beispiel im Trainingsset. Das Modell wurde nie trainiert, Systemprompts als Stildirektiven zu folgen.

Wenn man ihm einen Systemprompt a la "Du heißt Luna, rede lässig" gibt, hört es die Instruktion, hat aber kein gelerntes solides Muster, um sie in Output zu übersetzen. Es fällt dann auf Qwens Standardverhalten zurück: Hilfsbereit, strukturiert, leicht formell.

Warum Few-Shot-Beispiele funktionieren

Wenn man Gesprächsbeispiele im selben ChatML-Format injiziert wie das zum Training genutzte (mit der user/assistant-Taktstruktur), löst sich etwas aus. Das Modell erkennt das Muster aus seinem Training und richtet seinen Output entsprechend aus.

So sieht ein Few-Shot-Anstoß in der Praxis aus:

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Diese Beispiele werden nach dem Systemprompt und vor der echten Konversation injiziert. Das Modell nimmt sie als Teil der Gesprächshistorie wahr, also als echten Austausch statt als Instruktionen. Eine essenzielle Unterscheidung: Man zeigt ihm, wie der lässige Ton aussieht, statt ihn ihm zu befehlen.

Vorher / nachher

Ohne Few-Shot-Anstoß (nackter Systemprompt):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

Mit Few-Shot-Anstoß (3 Beispiele):

User: yo whats good
Bot: nm just chillin, u

Der Unterschied ist flagrant. Das Modell übernimmt das ganze Register: Kleinschreibung, Abkürzungen, lässiger Ton, kurze Antworten. Es kopiert den Stil der Beispiele statt den der Qwen-Trainingsdaten.


Speicher und Geschwindigkeit: die konkreten Zahlen

Der Wechsel von Hermes-3-3B zu Luna-Protocol-1.5B bringt messbare Gewinne:

Metrik Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Verbesserung
VRAM-Nutzung ~3 Go ~986 Mo 67 % weniger
Modelldateigröße ~3,2 Go ~986 Mo 69 % kleiner
Token-Generierung ~30 tok/s ~60+ tok/s 2x schneller
Kaltstart ~8s ~3s 62 % schneller
Kontextfenster 8192 8192 Identisch

Warum der Geschwindigkeitsgewinn real ist

Kleinere Modelle sind in der Inference fundamental schneller. Mit 1,5B statt 3B Parametern:

  • Weniger Matrixmultiplikationen pro Token: Attention-Layer, FFN-Layer und Output-Projektion skalieren alle linear mit der Parameterzahl
  • Bessere Cache-Nutzung: Das kleinere Modell hält mehr seiner Gewichte im L2/L3-Cache
  • Weniger Speicherbandbreitendruck: Weniger Bytes pro Token aus dem VRAM zu lesen

Auf einer bescheidenen Config, nur CPU (2 Kerne, ohne GPU), generiert das 1,5B-Modell Tokens mit etwa 2-facher Geschwindigkeit des 3B-Modells. Das ist der Unterschied zwischen "riecht nach Bot" und "klingt wie eine echte tippende Person".

Der Prompt-Cache verstärkt den Vorteil

Luna Protocol nutzt llama-server mit aktiviertem Prompt-Cache (--cache-reuse 256). Das heißt:

  1. Die erste Nachricht einer Session zahlt die vollen Prompt-Verarbeitungskosten (Systemprompt + Few-Shot-Beispiele + Nutzernachricht)
  2. Folgende Nachrichten verarbeiten nur die neuen Tokens, weil der gecachte Präfix wiederverwendet wird
  3. Mit 5 Few-Shot-Beispielen (~50-150 Tokens) wird der Overhead nach der ersten Anfrage vernachlässigbar

Die Few-Shot-Beispiele werden in der Praxis nach der ersten Nachricht einer Session "gratis". Das Modell profitiert von Stilführung zu marginalen Nullkosten.


Die Implementierung: wie es im Code funktioniert

Das Few-Shot-System von Luna Protocol ist sauber und minimal. Drei Dateien handhaben alles.

1. Konfiguration (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

Die Konfiguration ist hot-reloadbar. Man ändert die Beispiele, speichert, und der Bot übernimmt sofort den neuen Stil, ohne Neustart.

2. Formatierung und Injektion (src/core/few-shot.ts)

Die Funktion formatFewShotExamples() konvertiert die YAML-Beispiele in ChatML-Nachrichtenobjekte:

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

Die Funktion injectFewShotIntoConversation() platziert sie direkt nach dem Systemprompt:

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Integration (src/core/llm-client.ts)

Vor jedem LLM-Call werden die Few-Shot-Beispiele injiziert, wenn sie aktiviert sind:

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

Das Modell empfängt: [system_prompt] + [few_shot_beispiele] + [gesprächshistorie]


Den Discord-Dialogues-Stil bewahren

Das ursprüngliche Discord-Dialogues-Dataset hat eine sehr spezifische Konversationssignatur:

  • Kurze Nachrichten: 32,8 Tokens im Schnitt pro Tak
  • Informelles Register: Abkürzungen, Kleinschreibung, fehlende Interpunktion
  • Schnelle Austausche: Mehrere kurze Austausche statt langer Monologe
  • Natürliche Imperfektionen: Tippfehler, "lol", "fr", "ngl", "tbh"

Das Luna-Protocol-Modell bewahrt diesen Stil dank zweier Mechanismen:

1. Das Fine-Tuning verschiebt die Basisverteilung

Die 50k Trainingssamples lehren dem Modell den statistischen Fingerabdruck von Discord-Gesprächen. Es lernt, dass Antworten typischerweise kurz, kleingeschrieben und informell sind. Das entfernt den Standard-Output des Modells vom "hilfsbereiten Assistenten"-Modus von Qwen.

2. Das Few-Shot-Priming verriegelt das Ergebnis

Die Few-Shot-Beispiele verstärken exakt die während des Fine-Tunings gelernten Muster. Sie wirken als stilistischer Anker: Selbst wenn das Modell im Laufe einer langen Konversation leicht zu einem formelleren Ton driftet, ziehen die im Kontext vorhandenen Beispiele es zurück.

Die Kombination ist mächtiger als jeder Mechanismus isoliert:

  • Fine-Tuning ohne Few-Shot: Das Modell ist global lässig, aber inkonsistent
  • Few-Shot ohne Fine-Tuning: Das Modell versucht, den Beispielen zu folgen, fällt aber ständig in den Assistentenmodus zurück
  • Fine-Tuning + Few-Shot: Das Modell bleibt konstant in der Rolle

Die Philosophie: kleineres Modell, smarteres Prompting

Die konventionelle Weisheit im LLM-Deployment sagt "größer ist besser". Mehr Parameter, mehr Trainingsdaten, mehr VRAM. Luna Protocol geht den umgekehrten Weg:

  • 1,5B statt 3B: Halb so viele Parameter, halb so viel Speicher, doppelt so schnell
  • 50k Samples statt 7,3M: Weniger Trainingsdaten, mehr Flexibilität für In-Context-Lernen
  • Few-Shot-Priming statt Systemprompts: Dem Modell zeigen, was man will, nicht nur sagen

Das ist eine eingestandene Designentscheidung, weit mehr als eine simple technische Optimierung. Ein Discord-Bot muss ein leichter Konversationsbegleiter bleiben statt ein generalistischer Assistent. Er muss "nm just chillin, u" kohärent sagen, schnell, und ohne das ganze VRAM-Budget des Servers zu verschlingen.

Ergebnis: Ein Bot, der auf einem 5-$/Monat-VPS läuft, Tokens schnell genug generiert, um den Eindruck von Echtzeit-Tippen zu geben, und eine kohärente Persönlichkeit dank einer Kombination aus Fine-Tuning und Few-Shot-Priming pflegt, die mehr wert ist als die Summe ihrer Teile.


Einrichtung

Das Modell herunterladen

npm run download-model
# Lädt Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf herunter

Oder manuell von HuggingFace.

Konfigurieren

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Starten

npm run dev                    # dev (Hot Reload)
npm run build && npm start     # Produktion
./start.sh                     # PM2 (Produktion mit llama-server)

Fazit

Die Luna-Protocol-Modelle beweisen, dass für stilfokussierte Konversations-KI weniger mehr ist. Ein 1,5B-Modell trainiert auf 50k sorgfältig gewählten Samples, angestoßen mit ein paar Beispielen, übertrifft ein 3B-Modell trainiert auf Millionen Beispielen, für einen Bruchteil der Speicherkosten und doppelte Generierungsgeschwindigkeit.

Few-Shot-Priming bildet den zentralen Mechanismus für kleine Modelle. Es macht sie erst viabel für Echtzeit-Konversationsanwendungen. Die Beispiele tun weit mehr als "helfen": Sie ändern das Modellverhalten fundamental, indem sie exakt das Format kopieren, auf das es trainiert wurde.

Der Code ist Open Source, das Modell liegt auf HuggingFace, und das Dataset ist öffentlich. Wenn du einen Konversationsbot bauen willst, der menschlich wirkt, lautet das Rezept: Kleines Modell, begrenztes Fine-Tuning, solides Few-Shot-Priming.

Ressource Link
GitHub-Repo fox3000foxy/luna-protocol-project
Modell (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Dataset Discord-Dialogues
Erster Artikel Luna Protocol: Ich habe einen autonomen Discord-Bot gebaut

Luna Protocol : зачем я дообучил модель на 1,5 миллиарда параметров на 50k образцах Discord, и почему few-shot priming всё изменил

Модель поменьше, обученная на меньшем количестве данных, может превзойти модель побольше -- при условии, что знаешь, как её правильно затравливать. Вот почему Luna Protocol перешёл с Hermes 3B на дообученный Qwen 1,5B, и почему few-shot priming стал настоящим фактором прогресса.

Luna Protocol : зачем я дообучил модель на 1,5 миллиарда параметров на 50k образцах Discord, и почему few-shot priming всё изменил

В первой статье я построил Discord-бота, симулирующего человека : сон, опечатки, колебания, забывчивость, спонтанные сообщения. Поведенческая система держала удар. LLM за всем этим была модель Hermes на 3 миллиарда параметров, квантованная в Q8_0, потребляющая 3 ГБ VRAM.

Это работало. Но это было избыточно.

Discord-боту не нужна модель на 3 миллиарда параметров, чтобы сказать « nm just chillin, u ». Ему нужна стилистическая связность : способность держать точный разговорный тон сообщение за сообщением, не съезжая в режим «корпоративного ассистента». И оказывается, меньшая модель, обученная на меньшем количестве данных и затравленная несколькими примерами, справляется лучше, чем большая модель, продавливаемая простым системным промптом.

Эта статья про официальные модели Luna Protocol : зачем они существуют, почему 1,5B, а не 3B, почему 50k обучающих образцов, а не 7,3M, и почему few-shot priming перешёл из статуса «приятного бонуса» в сердце всего подхода.


Проблема с моделью 3B

Исходная конфигурация использовала Discord-Micae-Hermes-3-3B.Q8_0.gguf, модель на 3 миллиарда параметров, дообученную на данных Discord. Она давала хорошие ответы, но :

Метрика Hermes-3-3B Q8_0 Цель
Utilisation VRAM ~3 Go < 1 Go
Génération de tokens ~30 tok/s ~60+ tok/s
Taille du fichier modèle ~3,2 Go < 1 Go
Temps de démarrage à froid ~8s ~3s

Для бота, крутящегося 24/7 на скромном сервере, 3 ГБ VRAM это много. А скорость генерации, нормальная для редких сообщений, казалась вялой при очередях ответов или нескольких активных каналах.

Вопрос был : можно ли получить тот же стиль Discord-Dialogues с вдвое меньшим числом параметров?


Решение о дообучении : почему 50k, а не 7,3M

Датасет Discord-Dialogues содержит 7,3M обменов и 17M реплик. Это массивный корпус настоящих разговоров Discord. Очевидным подходом было бы обучать на всём датасете.

Я сделал наоборот. Я обучил на 50 000 образцах, то есть меньше 1 % доступных данных.

Вот почему : размер обучающей выборки напрямую влияет на степень переобучения модели под её обучающее распределение.

Модель, обученная на 7,3M примеров, выучивает очень специфичное статистическое распределение разговоров. Она становится отличной в воспроизведении этого распределения, но становится и жёсткой : у неё меньше запаса адаптироваться к новым паттернам, подаваемым в момент инференса.

Модель, обученная на 50k примеров, выучивает общий тон и регистр разговоров Discord (неформально, коротко, аббревиатуры, строчные), но сохраняет достаточно гибкости, чтобы управляться примерами в контексте. Few-shot примеры не борются с массивным уже выученным распределением : они дополняют более лёгкое распределение.

Это центральная интуиция : ограниченные обучающие данные делают few-shot priming эффективнее.


Модель : технические детали

Модель Luna Protocol это QLoRA-дообучение Qwen2.5-1.5B-Instruct :

Параметр Значение
Базовая модель unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Метод QLoRA (4-bit)
Ранг LoRA r=16, lora_alpha=16
Целевые модули q/k/v/o_proj, gate/up/down_proj
Обучаемые параметры 18 464 768 / 1 562 179 072 (1,18 %)
Обучающие данные ~50 000 exemples (sous-ensemble de Discord-Dialogues)
Фильтр 8-512 tokens par échantillon
Эпохи 2-3
Железо Kaggle T4
Фреймворк Unsloth

Датасет это предобработанный форк Discord-Dialogues, отфильтрованный так, чтобы оставить только чистые ходы user/assistant : только обмены пользователя и ассистента, без системных сообщений, метаданных и команд бота. Это важно для дальнейшего.

Доступные квантования

Файл Квантование Размер Примечания
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 Mo Заметно деградирована -- не рекомендуется
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 Mo Хороший компромисс размера и качества (рекомендуется)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 Go Лучшая стилевая точность

Рекомендуемая модель Q4_K_M : меньше 1 ГБ, быстрая, и хорошо сохраняет разговорный стиль. Q2_K деградирует слишком сильно для модели такого размера. Q8_0 даёт лучшее качество, но потребляет на 68 % больше памяти.


Прорыв few-shot priming

Вот часть, изменившая всё.

В карточке модели на HuggingFace есть предупреждение :

С голым промптом и без затравки эта модель склонна скатываться в дефолтный тон «ассистента» от Qwen. Короткая few-shot затравка даёт большую разницу.

Это прямое следствие того, как были структурированы обучающие данные.

Почему одни системные промпты не работают

Обучающие данные Discord-Dialogues содержат только ходы user/assistant. В обучающей выборке нет ни одного примера системной роли. Модель никогда не обучалась следовать системным промптам как стилевым директивам.

Когда ей дают системный промпт типа «Тебя зовут Luna, говори непринуждённо», она слышит инструкцию, но не имеет прочного выученного паттерна, чтобы транслировать её в вывод. Тогда она скатывается к поведению Qwen по умолчанию : услужливому, структурированному, слегка формальному.

Почему работают few-shot примеры

Когда в том же формате ChatML, что использовался при обучении (со структурой ходов user/assistant), инжектятся примеры разговоров, что-то срабатывает. Модель узнаёт паттерн из своего обучения и выравнивает вывод соответственно.

Вот как выглядит few-shot затравка на практике :

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Эти примеры инжектятся после системного промпта и перед настоящим разговором. Модель воспринимает их как часть истории разговора, то есть как настоящий обмен, а не как инструкции. Это существенное различие : ей показывают, как выглядит непринуждённый тон, вместо того чтобы приказывать.

До / после

Без few-shot затравки (голый системный промпт) :

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

С few-shot затравкой (3 примера) :

User: yo whats good
Bot: nm just chillin, u

Разница разительная. Модель перенимает весь регистр : строчные, аббревиатуры, непринуждённый тон, короткие ответы. Она копирует стиль примеров, а не стиль обучающих данных Qwen.


Память и скорость : конкретные цифры

Переход с Hermes-3-3B на Luna-Protocol-1.5B даёт измеримые выигрыши :

Метрика Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Улучшение
Utilisation VRAM ~3 Go ~986 Mo 67 % de moins
Taille du fichier modèle ~3,2 Go ~986 Mo 69 % plus petit
Génération de tokens ~30 tok/s ~60+ tok/s 2x plus rapide
Démarrage à froid ~8s ~3s 62 % plus rapide
Окно контекста 8192 8192 Одинаково

Почему выигрыш в скорости реален

Меньшие модели фундаментально быстрее в инференсе. С 1,5B параметров вместо 3B :

  • Меньше матричных умножений на токен : слои внимания, FFN-слои и выходная проекция масштабируются линейно с числом параметров
  • Лучшее использование кэша : у меньшей модели больше весов влезает в кэш L2/L3
  • Меньше давление на пропускную способность памяти : меньше байт читать из VRAM на токен

На скромной конфигурации, только CPU (2 ядра, без GPU), модель 1,5B генерирует токены примерно в 2 раза быстрее модели 3B. Это разница между «пахнет ботом» и «похоже на настоящего человека, печатающего».

Кэш промпта усиливает преимущество

Luna Protocol использует llama-server с включённым кэшем промпта (--cache-reuse 256). Это значит, что :

  1. Первое сообщение сессии платит полную стоимость обработки промпта (системный промпт + few-shot примеры + сообщение пользователя)
  2. Следующие сообщения обрабатывают только новые токены, потому что закэшированный префикс переиспользуется
  3. С 5 few-shot примерами (~50-150 токенов) оверхед становится пренебрежимым после первого запроса

Few-shot примеры становятся на практике «бесплатными» после первого сообщения сессии. Модель получает стилевое наведение с нулевой маржинальной стоимостью.


Реализация : как это работает в коде

Few-shot система Luna Protocol чистая и минимальная. Три файла управляют всем.

1. Конфигурация (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

Конфигурация перезагружается на горячую. Меняешь примеры, сохраняешь, и бот сразу перенимает новый стиль без перезапуска.

2. Форматирование и инъекция (src/core/few-shot.ts)

Функция formatFewShotExamples() конвертирует YAML-примеры в объекты сообщений ChatML :

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

Функция injectFewShotIntoConversation() ставит их сразу после системного промпта :

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Интеграция (src/core/llm-client.ts)

Перед каждым вызовом LLM few-shot примеры инжектятся, если включены :

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

Модель получает : [prompt_système] + [exemples_few_shot] + [historique_de_conversation]


Сохранение стиля Discord-Dialogues

Исходный датасет Discord-Dialogues имеет очень специфичную разговорную сигнатуру :

  • Короткие сообщения : 32,8 токена в среднем на ход
  • Неформальный регистр : аббревиатуры, строчные, отсутствие пунктуации
  • Быстрые обмены : несколько коротких обменов вместо длинных монологов
  • Естественные imperfections : опечатки, « lol », « fr », « ngl », « tbh »

Модель Luna Protocol сохраняет этот стиль двумя механизмами :

1. Дообучение сдвигает базовое распределение

50k обучающих образцов учат модель статистическому отпечатку разговоров Discord. Она выучивает, что ответы обычно короткие, строчные и неформальные. Это уводит вывод модели по умолчанию от режима «услужливого ассистента» Qwen.

2. Few-shot priming фиксирует результат

Few-shot примеры подкрепляют ровно паттерны, выученные при дообучении. Они действуют как стилевой якорь : даже если модель слегка съедет к более формальному тону по ходу длинного разговора, примеры в контексте вернут её назад.

Комбинация мощнее, чем каждый механизм по отдельности :

  • Дообучение без few-shot : модель в целом непринуждённая, но несогласованная
  • Few-shot без дообучения : модель пытается следовать примерам, но постоянно скатывается в режим ассистента
  • Дообучение + few-shot : модель остаётся постоянно в персонаже

Философия : модель поменьше, промптинг поумнее

Конвенциональная мудрость деплоя LLM говорит «больше значит лучше». Больше параметров, больше обучающих данных, больше VRAM. Luna Protocol идёт обратным путём :

  • 1,5B вместо 3B : вдвое меньше параметров, вдвое меньше памяти, вдвое быстрее
  • 50k образцов вместо 7,3M : меньше обучающих данных, больше гибкости для обучения в контексте
  • Few-shot priming вместо системных промптов : показывать модели, чего хочешь, а не просто говорить

Это осознанный дизайнерский выбор, а не просто техническая оптимизация. Discord-боту надо оставаться лёгким разговорным компаньоном, а не ассистентом-универсалом. Он должен говорить « nm just chillin, u » связно, быстро и не съедая весь бюджет VRAM сервера.

Итог : бот, крутящийся на VPS за 5 $/мес, генерирующий токены достаточно быстро, чтобы имитировать печать в реальном времени, и держащий связную личность благодаря комбинации дообучения и few-shot priming, стоящей больше суммы частей.


Установка

Скачать модель

npm run download-model
# Télécharge Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

Или вручную с HuggingFace.

Настроить

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Запустить

npm run dev                    # dev (rechargement à chaud)
npm run build && npm start     # production
./start.sh                     # PM2 (production avec llama-server)

Заключение

Модели Luna Protocol доказывают, что для разговорного ИИ, заточенного на стиль, меньше значит лучше. Модель на 1,5B, обученная на 50k тщательно выбранных образцов и затравленная несколькими примерами, превосходит модель на 3B, обученную на миллионах примеров, за долю стоимости в памяти и с вдвое большей скоростью генерации.

Few-shot priming составляет центральный механизм для маленьких моделей. Именно он делает их жизнеспособными для разговорных приложений реального времени. Примеры делают куда больше, чем «помогают» : они фундаментально меняют поведение модели, накладывая ровно тот формат, на котором она обучалась.

Код открытый, модель на HuggingFace, датасет публичный. Если хочешь построить разговорного бота, кажущегося человеком, рецепт такой : маленькая модель, ограниченное дообучение, прочная few-shot затравка.

Ресурс Ссылка
Репозиторий GitHub fox3000foxy/luna-protocol-project
Модель (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Датасет Discord-Dialogues
Первая статья Luna Protocol : я создал автономного Discord-бота

Luna Protocol: por qué fine-tuneé un modelo de 1,5 mil millones de parámetros sobre 50k muestras Discord, y por qué el few-shot priming lo cambió todo

Un modelo más pequeño entrenado sobre menos datos puede superar un modelo más grande, a condición de saber iniciarlo bien. He aquí por qué Luna Protocol pasó de un Hermes 3B a un fine-tune Qwen 1,5B, y por qué el few-shot priming se volvió el verdadero factor de progreso.

Luna Protocol: por qué fine-tuneé un modelo de 1,5 mil millones de parámetros sobre 50k muestras Discord, y por qué el few-shot priming lo cambió todo

En el primer artículo, construí un bot Discord que simula un ser humano: sueño, erratas, vacilaciones, olvidos, mensajes espontáneos. El sistema conductual aguantaba el tipo. El LLM tras todo eso era un modelo Hermes de 3 mil millones de parámetros, cuantizado en Q8_0, consumiendo 3 GB de VRAM.

Funcionaba. Pero estaba sobredimensionado.

Un bot Discord no necesita un modelo de 3 mil millones de parámetros para decir « nm just chillin, u ». Lo que necesita es coherencia estilística: la capacidad de conservar un tono conversacional preciso, mensaje tras mensaje, sin derivar hacia un modo «asistente corporate». Y resulta que un modelo más pequeño, entrenado sobre menos datos e iniciado con unos ejemplos, lo logra mejor que un modelo más grande que fuerza el paso vía un simple prompt de sistema.

Este artículo trata de los modelos oficiales de Luna Protocol: por qué existen, por qué 1,5B en vez de 3B, por qué 50k muestras de entrenamiento en vez de 7,3M, y por qué el few-shot priming pasó del estatus de «bonus simpático» al de corazón de todo el enfoque.


El problema con el modelo 3B

La configuración original usaba Discord-Micae-Hermes-3-3B.Q8_0.gguf, un modelo de 3 mil millones de parámetros fine-tuneado sobre datos Discord. Producía buenas respuestas, pero:

Métrica Hermes-3-3B Q8_0 Objetivo
Uso VRAM ~3 GB < 1 GB
Generación de tokens ~30 tok/s ~60+ tok/s
Tamaño del archivo modelo ~3,2 GB < 1 GB
Arranque en frío ~8s ~3s

Para un bot corriendo 24/7 en un servidor modesto, 3 GB de VRAM es mucho. Y la velocidad de generación, correcta para mensajes ocasionales, parecía lenta en respuestas en ráfaga o con varios canales activos.

La pregunta era: ¿se puede obtener el mismo estilo Discord-Dialogues con la mitad de parámetros?


La decisión de fine-tuning: por qué 50k, no 7,3M

El dataset Discord-Dialogues contiene 7,3M de intercambios y 17M de turnos de palabra. Es un corpus masivo de verdaderas conversaciones Discord. El enfoque evidente habría sido entrenar sobre todo el dataset.

Hice lo inverso. Entrené sobre 50 000 muestras, o sea menos del 1% de los datos disponibles.

He aquí por qué: el tamaño del juego de entrenamiento afecta directamente el grado de sobreajuste del modelo respecto a su distribución de entrenamiento.

Un modelo entrenado sobre 7,3M de ejemplos aprende una distribución estadística muy específica de las conversaciones. Se vuelve excelente reproduciendo esa distribución, pero también se vuelve rígido: tiene menos margen para adaptarse a nuevos patrones aportados en el momento de la inferencia.

Un modelo entrenado sobre 50k ejemplos aprende el tono y el registro general de las conversaciones Discord (informal, corto, abreviaturas, minúsculas), pero conserva bastante flexibilidad para ser pilotado por ejemplos en contexto. Los ejemplos few-shot no luchan contra una distribución masiva ya aprendida: vienen a completar una distribución más ligera.

Es la intuición central: datos de entrenamiento limitados hacen el few-shot priming más eficaz.


El modelo: detalles técnicos

El modelo Luna Protocol es un fine-tune QLoRA de Qwen2.5-1.5B-Instruct:

Parámetro Valor
Modelo base unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Método QLoRA (4-bit)
Rango LoRA r=16, lora_alpha=16
Módulos objetivo q/k/v/o_proj, gate/up/down_proj
Parámetros entrenables 18 464 768 / 1 562 179 072 (1,18 %)
Datos de entrenamiento ~50 000 ejemplos (subconjunto de Discord-Dialogues)
Filtro 8-512 tokens por muestra
Épocas 2-3
Material Kaggle T4
Framework Unsloth

El dataset es un fork preprocesado de Discord-Dialogues, filtrado para conservar solo turnos user/assistant limpios: solo intercambios usuario y asistente, sin mensajes sistema ni metadatos ni comandos de bot. Es importante para lo que sigue.

Cuantizaciones disponibles

Archivo Cuantización Tamaño Notas
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 MB Claramente degradado: desaconsejado
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 MB Buen compromiso tamaño/calidad (recomendado)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 GB Mejor fidelidad estilística

El modelo recomendado es Q4_K_M: menos de 1 GB, rápido, y preserva bien el estilo conversacional. El Q2_K se degrada demasiado para un modelo de este tamaño. El Q8_0 ofrece la mejor calidad pero consume 68% de memoria más.


La ruptura del few-shot priming

Aquí la parte que lo cambió todo.

La ficha del modelo en HuggingFace lleva una advertencia:

Con un prompt desnudo y sin arranque, este modelo tiende a recaer en el tono por defecto «asistente» de Qwen. Un corto arranque few-shot marca una gran diferencia.

Es una consecuencia directa de cómo se estructuraron los datos de entrenamiento.

Por qué los prompts de sistema solos no funcionan

Los datos de entrenamiento Discord-Dialogues solo contienen turnos user/assistant. No hay ningún ejemplo de rol sistema en el juego de entrenamiento. El modelo nunca se entrenó a seguir prompts de sistema como directivas de estilo.

Cuando le das un prompt de sistema tipo «Te llamas Luna, habla de forma relajada», oye la instrucción pero no tiene un patrón aprendido sólido para traducirla en salida. Recae entonces en el comportamiento por defecto de Qwen: servicial, estructurado, ligeramente formal.

Por qué los ejemplos few-shot funcionan

Cuando inyectas ejemplos de conversación en el mismo formato ChatML que el usado en el entrenamiento (con la estructura de turnos user/assistant), algo se dispara. El modelo reconoce el patrón de su entrenamiento y alinea su salida en consecuencia.

Así se ve un arranque few-shot en la práctica:

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Esos ejemplos se inyectan tras el prompt de sistema y antes de la verdadera conversación. El modelo los percibe como parte del historial de conversación, o sea como un intercambio real más que como instrucciones. Es una distinción esencial: le muestras cómo es el tono relajado en vez de ordenárselo.

Antes / después

Sin arranque few-shot (prompt de sistema desnudo):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

Con arranque few-shot (3 ejemplos):

User: yo whats good
Bot: nm just chillin, u

La diferencia es flagrante. El modelo adopta todo el registro: minúsculas, abreviaturas, tono relajado, respuestas cortas. Calca el estilo de los ejemplos más que el de los datos de entrenamiento de Qwen.


Memoria y velocidad: las cifras concretas

El paso de Hermes-3-3B a Luna-Protocol-1.5B aporta ganancias medibles:

Métrica Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Mejora
Uso VRAM ~3 GB ~986 MB 67% menos
Tamaño del archivo modelo ~3,2 GB ~986 MB 69% más pequeño
Generación de tokens ~30 tok/s ~60+ tok/s 2x más rápido
Arranque en frío ~8s ~3s 62% más rápido
Ventana de contexto 8192 8192 Idéntica

Por qué la ganancia de velocidad es real

Los modelos más pequeños son fundamentalmente más rápidos en inferencia. Con 1,5B de parámetros en vez de 3B:

  • Menos multiplicaciones matriciales por token: las capas de atención, las capas FFN y la proyección de salida evolucionan todas linealmente con el número de parámetros
  • Mejor uso del caché: el modelo más pequeño mete más de sus pesos en el caché L2/L3
  • Menos presión sobre el ancho de banda memoria: menos bytes que leer desde la VRAM por token

En una configuración modesta, solo CPU (2 núcleos, sin GPU), el modelo 1,5B genera tokens a unas 2 veces la velocidad del modelo 3B. Es la diferencia entre «huele a bot» y «parece una persona real escribiendo».

El caché de prompt amplifica la ventaja

Luna Protocol usa llama-server con el caché de prompt activado (--cache-reuse 256). Eso significa que:

  1. El primer mensaje de una sesión paga el coste completo del procesamiento del prompt (prompt de sistema + ejemplos few-shot + mensaje usuario)
  2. Los mensajes siguientes solo procesan los nuevos tokens, porque el prefijo en caché se reutiliza
  3. Con 5 ejemplos few-shot (~50-150 tokens), el sobrecoste se vuelve despreciable tras la primera petición

Los ejemplos few-shot se vuelven en la práctica «gratis» tras el primer mensaje de una sesión. El modelo se beneficia de un guiado de estilo a coste marginal nulo.


La implementación: cómo funciona en código

El sistema few-shot de Luna Protocol es limpio y mínimo. Tres archivos lo gestionan todo.

1. Configuración (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

La configuración es recargable en caliente. Modificas los ejemplos, guardas, y el bot adopta de inmediato el nuevo estilo, sin reinicio.

2. Formateo e inyección (src/core/few-shot.ts)

La función formatFewShotExamples() convierte los ejemplos YAML en objetos de mensaje ChatML:

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

La función injectFewShotIntoConversation() los coloca justo tras el prompt de sistema:

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Integración (src/core/llm-client.ts)

Antes de cada llamada al LLM, los ejemplos few-shot se inyectan si están activados:

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

El modelo recibe: [prompt_sistema] + [ejemplos_few_shot] + [historial_de_conversación]


Conservar el estilo Discord-Dialogues

El dataset Discord-Dialogues de origen tiene una firma conversacional muy específica:

  • Mensajes cortos: 32,8 tokens de media por turno
  • Registro informal: abreviaturas, minúsculas, ausencia de puntuación
  • Intercambios rápidos: varios intercambios cortos en vez de largos monólogos
  • Imperfecciones naturales: erratas, «lol», «fr», «ngl», «tbh»

El modelo Luna Protocol preserva ese estilo gracias a dos mecanismos:

1. El fine-tuning desplaza la distribución base

Las 50k muestras de entrenamiento enseñan al modelo la huella estadística de las conversaciones Discord. Aprende que las respuestas son típicamente cortas, en minúsculas e informales. Eso aleja la salida por defecto del modelo del modo «asistente servicial» de Qwen.

2. El few-shot priming bloquea el resultado

Los ejemplos few-shot refuerzan justo los patrones aprendidos durante el fine-tuning. Actúan como un anclaje estilístico: aunque el modelo derive ligeramente hacia un tono más formal en una conversación larga, los ejemplos presentes en el contexto lo devuelven atrás.

La combinación es más potente que cada mecanismo por separado:

  • Fine-tuning sin few-shot: el modelo es globalmente relajado pero inconsistente
  • Few-shot sin fine-tuning: el modelo intenta seguir los ejemplos pero recae sin cesar en modo asistente
  • Fine-tuning + few-shot: el modelo queda constantemente en personaje

La filosofía: modelo más pequeño, prompting más listo

La sabiduría convencional en despliegue de LLM dice «más grande, mejor». Más parámetros, más datos de entrenamiento, más VRAM. Luna Protocol toma el camino inverso:

  • 1,5B en vez de 3B: mitad de parámetros, mitad de memoria, dos veces más rápido
  • 50k muestras en vez de 7,3M: menos datos de entrenamiento, más flexibilidad para el aprendizaje en contexto
  • Few-shot priming en vez de prompts de sistema: mostrar al modelo lo que queremos, no solo decírselo

Es una decisión de diseño asumida, mucho más que una simple optimización técnica. Un bot Discord necesita seguir siendo un compañero conversacional ligero más que un asistente generalista. Debe decir «nm just chillin, u» de forma coherente, rápida, y sin engullir todo el presupuesto VRAM del servidor.

Resultado: un bot que corre en un VPS a 5 $/mes, genera tokens bastante rápido para dar la impresión de una escritura en tiempo real, y mantiene una personalidad coherente gracias a una combinación de fine-tuning y few-shot priming que vale más que la suma de sus partes.


Puesta en marcha

Descargar el modelo

npm run download-model
# Descarga Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

O manualmente desde HuggingFace.

Configurar

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Lanzar

npm run dev                    # dev (recarga en caliente)
npm run build && npm start     # producción
./start.sh                     # PM2 (producción con llama-server)

Conclusión

Los modelos Luna Protocol prueban que para una IA conversacional centrada en el estilo, menos es mejor. Un modelo de 1,5B entrenado sobre 50k muestras cuidadosamente elegidas, iniciado con unos ejemplos, supera un modelo de 3B entrenado sobre millones de ejemplos, por una fracción del coste en memoria y una velocidad de generación dos veces superior.

El few-shot priming constituye el mecanismo central para los modelos pequeños. Es lo que los hace viables para aplicaciones conversacionales en tiempo real. Los ejemplos hacen mucho más que «ayudar»: cambian fundamentalmente el comportamiento del modelo, calcando justo el formato sobre el que se entrenó.

El código es open source, el modelo está en HuggingFace, y el dataset es público. Si quieres construir un bot conversacional que dé la impresión de ser humano, la receta es: modelo pequeño, fine-tuning limitado, arranque few-shot sólido.

Recurso Enlace
Repo GitHub fox3000foxy/luna-protocol-project
Modelo (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Dataset Discord-Dialogues
Primer artículo Luna Protocol: creé un bot Discord autónomo

Luna Protocol: por que eu fine-tunei um modelo de 1,5B em 50k amostras do Discord e tornei o few-shot priming a arma secreta

Um modelo menor treinado com menos dados pode superar um maior -- se você souber como prepará-lo. Veja por que o Luna Protocol trocou um Hermes 3B por um fine-tune Qwen 1,5B, e por que o few-shot priming se tornou o verdadeiro diferencial.

Luna Protocol: por que eu fine-tunei um modelo de 1,5B em 50k amostras do Discord e tornei o few-shot priming a arma secreta

No primeiro artigo, eu construí um bot do Discord que simula um ser humano -- sono, erros de digitação, hesitações, esquecimentos, mensagens espontâneas. O sistema comportamental era sólido. O LLM por trás dele era um modelo Hermes 3B, quantizado em Q8_0, consumindo 3 GB de VRAM.

Funcionava. Mas era exagero.

Um bot do Discord não precisa de um modelo de 3B de parâmetros para dizer "nm just chillin, u". O que ele precisa é de consistência de estilo -- a capacidade de manter um tom conversacional específico, mensagem após mensagem, sem derivar para o modo assistente corporativo. E acontece que um modelo menor, treinado com menos dados e preparado com alguns exemplos, faz isso melhor do que um modelo maior tentando forçar o caminho com um prompt de sistema.

Este artigo é sobre os modelos oficiais do Luna Protocol: por que eles existem, por que são 1,5B em vez de 3B, por que 50k amostras de treinamento em vez de 7,3M, e por que o few-shot priming passou de algo "bom ter" para o núcleo de toda a abordagem.


O problema com o modelo 3B

A configuração original usava Discord-Micae-Hermes-3-3B.Q8_0.gguf -- um modelo de 3B parâmetros fine-tunado em dados do Discord. Ele produzia boas respostas, mas:

Métrica Hermes-3-3B Q8_0 Alvo
Uso de VRAM ~3 GB < 1 GB
Geração de tokens ~30 tok/s ~60+ tok/s
Tamanho do arquivo do modelo ~3,2 GB < 1 GB
Tempo de inicialização a frio ~8s ~3s

Para um bot rodando 24/7 em um servidor modesto, 3 GB de VRAM é muito. E a velocidade de geração -- embora aceitável para mensagens ocasionais -- parecia lenta durante respostas em rajada ou quando vários canais estavam ativos.

A pergunta era: podemos obter o mesmo estilo Discord-Dialogues com metade dos parâmetros?


A decisão do fine-tuning: por que 50k, não 7,3M

O conjunto de dados Discord-Dialogues contém 7,3M de trocas e 17M de turnos. É um corpus massivo de conversas reais do Discord. A abordagem óbvia seria treinar no conjunto completo.

Eu fiz o oposto. Treinei em 50.000 amostras -- menos de 1% dos dados disponíveis.

Eis o porquê: o tamanho do conjunto de treinamento afeta diretamente o quanto o modelo se superajusta à sua distribuição de treinamento.

Um modelo treinado em 7,3M de exemplos aprende uma distribuição estatística muito específica de conversas. Ele se torna excelente em reproduzir essa distribuição, mas também se torna rígido -- tem menos flexibilidade para se adaptar a novos padrões fornecidos no momento da inferência.

Um modelo treinado em 50k exemplos aprende o tom geral e o registro das conversas do Discord (informal, curto, abreviações, minúsculas), mas retém flexibilidade suficiente para ser guiado por exemplos em contexto. Os exemplos few-shot não lutam contra uma distribuição massiva aprendida -- eles complementam uma distribuição mais leve.

Este é o insight central: dados de treinamento limitados tornam o few-shot priming mais eficiente.


O modelo: detalhes técnicos

O modelo Luna Protocol é um fine-tune QLoRA do Qwen2.5-1.5B-Instruct:

Parâmetro Valor
Modelo base unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Método QLoRA (4-bit)
Rank LoRA r=16, lora_alpha=16
Módulos alvo q/k/v/o_proj, gate/up/down_proj
Parâmetros treináveis 18.464.768 / 1.562.179.072 (1,18%)
Dados de treinamento ~50.000 exemplos (subconjunto do Discord-Dialogues)
Filtro 8-512 tokens por amostra
Épocas 2-3
Hardware Kaggle T4
Framework Unsloth

O conjunto de dados é um fork pré-processado do Discord-Dialogues, filtrado para conter apenas turnos user/assistant limpos -- sem mensagens de sistema, sem metadados, sem comandos de bot. Isso é importante para o que vem a seguir.

Quantizações disponíveis

Arquivo Quantização Tamanho Observações
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 MB Visivelmente degradado -- não recomendado
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 MB Bom equilíbrio tamanho/qualidade (recomendado)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 GB Melhor fidelidade de estilo

O modelo recomendado é Q4_K_M -- abaixo de 1 GB, rápido e preserva bem o estilo conversacional. O Q2_K degrada demais em um modelo tão pequeno. O Q8_0 tem a melhor qualidade, mas usa 68% mais memória.


O avanço do few-shot priming

Aqui está a parte que mudou tudo.

A ficha do modelo no HuggingFace tem um aviso:

Com um prompt simples e sem preparação, este modelo tende a recair no tom de assistente padrão do Qwen. Uma preparação curta com few-shot faz uma grande diferença.

Isso não é um bug -- é uma consequência direta de como os dados de treinamento foram estruturados.

Por que prompts de sistema sozinhos não funcionam

Os dados de treinamento do Discord-Dialogues contêm apenas turnos user/assistant. Não há exemplos de papel de sistema no conjunto de treinamento. O modelo nunca foi treinado para seguir prompts de sistema como diretrizes de estilo.

Quando você dá a ele um prompt de sistema como "Seu nome é Luna, fale casualmente", ele ouve a instrução, mas não tem um padrão forte aprendido de como traduzir isso em saída. Ele recai no padrão do Qwen: útil, estruturado, ligeiramente formal.

Por que exemplos few-shot funcionam

Quando você injeta exemplos de conversa no mesmo formato ChatML em que o modelo foi treinado (usando a estrutura de turnos user/assistant), algo se encaixa. O modelo reconhece o padrão de seus dados de treinamento e alinha sua saída para corresponder.

Aqui está como um preparo few-shot parece na prática:

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Esses exemplos são injetados após o prompt de sistema e antes da conversa real. O modelo os vê como parte do histórico da conversa, não como instruções. Essa é uma distinção crítica -- não está sendo instruído a ser casual, está sendo mostrado como é o casual.

Antes e depois

Sem preparação few-shot (apenas prompt de sistema):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

Com preparação few-shot (3 exemplos):

User: yo whats good
Bot: nm just chillin, u

A diferença é gritante. O modelo não produz apenas palavras diferentes -- ele adota todo o registro: minúsculas, abreviações, tom casual, respostas curtas. Ele corresponde ao estilo dos exemplos, não ao estilo dos dados de treinamento do Qwen.


Memória e velocidade: os números concretos

A troca do Hermes-3-3B para o Luna-Protocol-1.5B traz ganhos mensuráveis:

Métrica Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Melhoria
Uso de VRAM ~3 GB ~986 MB 67% menos
Tamanho do arquivo do modelo ~3,2 GB ~986 MB 69% menor
Geração de tokens ~30 tok/s ~60+ tok/s 2x mais rápido
Inicialização a frio ~8s ~3s 62% mais rápido
Janela de contexto 8192 8192 Mesma

Por que o ganho de velocidade é real

Modelos menores não são apenas "menos lentos" -- eles são fundamentalmente mais rápidos para inferência. Com 1,5B de parâmetros em vez de 3B:

  • Menos multiplicações de matriz por token: as camadas de atenção, camadas FFN e a projeção de saída escalam linearmente com a contagem de parâmetros
  • Melhor utilização de cache: o modelo menor consegue colocar mais de seus pesos no cache L2/L3
  • Menor pressão na largura de banda da memória: menos bytes para ler da VRAM por token

Em uma configuração modesta apenas com CPU (2 núcleos, sem GPU), o modelo de 1,5B gera tokens a aproximadamente 2x a velocidade do modelo de 3B. Esta é a diferença entre "parece um bot" e "parece uma pessoa digitando".

Cache de prompt amplifica a vantagem

O Luna Protocol usa llama-server com cache de prompt ativado (--cache-reuse 256). Isso significa que:

  1. A primeira mensagem em uma sessão paga o custo completo de processamento do prompt (prompt de sistema + exemplos few-shot + mensagem do usuário)
  2. Mensagens subsequentes processam apenas os tokens novos -- o prefixo em cache é reutilizado
  3. Com 5 exemplos few-shot (~50-150 tokens), a sobrecarga é insignificante após a primeira requisição

Os exemplos few-shot são efetivamente "gratuitos" após a primeira mensagem em uma sessão. O modelo recebe orientação de estilo com custo marginal zero.


A implementação: como funciona no código

O sistema few-shot no Luna Protocol é limpo e mínimo. Três arquivos cuidam de tudo:

1. Configuração (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

A configuração é recarregável a quente. Altere os exemplos, salve, e o bot adota o novo estilo imediatamente -- sem necessidade de reinicialização.

2. Formatação e injeção (src/core/few-shot.ts)

A função formatFewShotExamples() converte os exemplos YAML em objetos de mensagem ChatML:

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

A função injectFewShotIntoConversation() os coloca logo após o prompt de sistema:

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Integração (src/core/llm-client.ts)

Antes de cada chamada ao LLM, os exemplos few-shot são injetados se estiverem ativados:

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

O modelo recebe: [prompt_de_sistema] + [exemplos_few_shot] + [histórico_da_conversa]


Mantendo o estilo Discord-Dialogues

O conjunto de dados original Discord-Dialogues tem uma assinatura conversacional muito específica:

  • Mensagens curtas: média de 32,8 tokens por turno
  • Registro informal: abreviações, minúsculas, sem pontuação
  • Ida e volta rápido: múltiplas trocas curtas em vez de longos monólogos
  • Imperfeições naturais: erros de digitação, "lol", "fr", "ngl", "tbh"

O modelo Luna-Protocol preserva esse estilo através de dois mecanismos:

1. Fine-tuning desloca a distribuição base

Os 50k exemplos de treinamento ensinam ao modelo a impressão digital estatística das conversas do Discord. Ele aprende que as respostas são tipicamente curtas, em minúsculas e informais. Isso desloca a saída padrão do modelo para longe do modo assistente-útil do Qwen.

2. Few-shot priming consolida o resultado

Os exemplos few-shot reforçam exatamente os padrões que o modelo aprendeu durante o fine-tuning. Eles atuam como uma âncora de estilo -- mesmo que o modelo desvie ligeiramente para um tom formal durante uma conversa longa, os exemplos no contexto continuam puxando-o de volta.

A combinação é mais poderosa do que qualquer mecanismo isoladamente:

  • Fine-tuning sem few-shot: o modelo é geralmente casual, mas inconsistente
  • Few-shot sem fine-tuning: o modelo tenta seguir os exemplos, mas continua revertendo ao modo assistente
  • Fine-tuning + few-shot: o modelo fica consistentemente no personagem

A filosofia: modelo menor, prompting mais inteligente

A sabedoria convencional na implantação de LLMs é "maior é melhor". Mais parâmetros, mais dados de treinamento, mais VRAM. O Luna Protocol adota a abordagem oposta:

  • 1,5B em vez de 3B: metade dos parâmetros, metade da memória, dobro da velocidade
  • 50k amostras em vez de 7,3M: menos dados de treinamento, mais flexibilidade para aprendizado em contexto
  • Few-shot priming em vez de prompts de sistema: mostre ao modelo o que você quer, não apenas diga

Isso não é apenas uma otimização técnica -- é uma filosofia de design. Um bot do Discord não precisa ser um assistente de propósito geral. Ele precisa dizer "nm just chillin, u" de forma consistente, rápida e sem consumir todo o orçamento de VRAM do seu servidor.

O resultado: um bot que roda em um VPS de $5/mês, gera tokens rápido o suficiente para parecer digitação em tempo real e mantém uma personalidade consistente através de uma combinação de fine-tuning e few-shot priming que é maior que a soma de suas partes.


Configuração

Baixar o modelo

npm run download-model
# Baixa Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

Ou manualmente pelo HuggingFace.

Configurar

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Executar

npm run dev                    # dev (recarga a quente)
npm run build && npm start     # produção
./start.sh                     # PM2 (produção com llama-server)

Conclusão

Os modelos Luna Protocol provam que para IA conversacional focada em estilo, menos é mais. Um modelo de 1,5B treinado em 50k amostras cuidadosamente selecionadas, preparado com alguns exemplos, supera um modelo de 3B treinado em milhões de exemplos -- a uma fração do custo de memória e com o dobro da velocidade de geração.

Few-shot priming não é apenas algo "bom ter" para modelos pequenos. É o mecanismo que os torna viáveis para aplicações conversacionais em tempo real. Os exemplos não apenas "ajudam" -- eles mudam fundamentalmente como o modelo se comporta, ao corresponder exatamente ao formato em que foi treinado.

O código é open source, o modelo está no HuggingFace e o conjunto de dados é público. Se você quer construir um bot conversacional que pareça humano, a receita é: modelo pequeno, fine-tuning limitado, preparação few-shot sólida.

Recurso Link
Repositório GitHub fox3000foxy/luna-protocol-project
Modelo (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Conjunto de dados Discord-Dialogues
Primeiro artigo Luna Protocol: criei um bot autônomo para Discord

Luna Protocol : kenapa saya men fine-tune model 1,5 miliar parameter pada 50k sampel Discord, dan kenapa few-shot priming mengubah segalanya

Model lebih kecil yang dilatih pada lebih sedikit data bisa melampaui model lebih besar -- asal tahu cara meng priming dengan baik. Inilah kenapa Luna Protocol beralih dari Hermes 3B ke fine-tune Qwen 1,5B, dan kenapa few-shot priming menjadi faktor kemajuan yang sesungguhnya.

Luna Protocol : kenapa saya men fine-tune model 1,5 miliar parameter pada 50k sampel Discord, dan kenapa few-shot priming mengubah segalanya

Dalam artikel pertama, saya membangun bot Discord yang mensimulasikan manusia : tidur, salah ketik, keraguan, kelupaan, pesan spontan. Sistem perilakunya bertahan. LLM di balik semuanya adalah model Hermes 3 miliar parameter, terkuantisasi Q8_0, mengonsumsi 3 GB VRAM.

Itu berfungsi. Tapi terlalu besar.

Bot Discord tidak butuh model 3 miliar parameter untuk bilang "nm just chillin, u". Yang dibutuhkannya adalah koherensi stilistika : kemampuan menjaga nada percakapan yang tepat, pesan demi pesan, tanpa melayang ke mode "asisten korporat". Dan ternyata model lebih kecil, yang dilatih pada lebih sedikit data dan di priming dengan beberapa contoh, mencapainya lebih baik daripada model lebih besar yang dipaksa lewat prompt sistem sederhana.

Artikel ini soal model resmi Luna Protocol : kenapa mereka ada, kenapa 1,5B alih-alih 3B, kenapa 50k sampel pelatihan alih-alih 7,3 juta, dan kenapa few-shot priming beralih dari status "bonus manis" menjadi jantung seluruh pendekatan.


Masalah dengan model 3B

Konfigurasi aslinya memakai Discord-Micae-Hermes-3-3B.Q8_0.gguf, model 3 miliar parameter yang di fine-tune pada data Discord. Ia menghasilkan respons bagus, tapi :

Metrik Hermes-3-3B Q8_0 Target
Pemakaian VRAM ~3 GB < 1 GB
Pembangkitan token ~30 tok/dtk ~60+ tok/dtk
Ukuran berkas model ~3,2 GB < 1 GB
Waktu startup dingin ~8 dtk ~3 dtk

Untuk bot yang berjalan 24/7 di server sederhana, 3 GB VRAM itu banyak. Dan kecepatan pembangkitan, yang oke untuk pesan sesekali, terasa lambat saat respons beruntun atau dengan banyak kanal aktif.

Pertanyaannya adalah : bisakah kita mendapatkan gaya Discord-Dialogues yang sama dengan setengah parameter?


Keputusan fine-tuning : kenapa 50k, bukan 7,3 juta

Himpunan data Discord-Dialogues berisi 7,3 juta pertukaran dan 17 juta putaran bicara. Ini korpus masif percakapan Discord sungguhan. Pendekatan jelasnya adalah melatih pada seluruh himpunan data.

Saya melakukan kebalikannya. Saya melatih pada 50 000 sampel, kurang dari 1% data yang tersedia.

Inilah kenapanya : ukuran himpunan pelatihan langsung memengaruhi derajat overfitting model terhadap distribusi pelatihannya.

Model yang dilatih pada 7,3 juta contoh mempelajari distribusi statistik percakapan yang sangat spesifik. Ia menjadi hebat mereproduksi distribusi itu, tapi ia juga menjadi kaku : ia punya lebih sedikit ruang untuk beradaptasi pada pola baru yang diberikan saat inferensi.

Model yang dilatih pada 50k contoh mempelajari nada dan register umum percakapan Discord (informal, pendek, singkatan, huruf kecil), tapi ia menyimpan cukup fleksibilitas untuk dipandu oleh contoh dalam konteks. Contoh few-shot tidak melawan distribusi masif yang sudah dipelajari : mereka melengkapi distribusi yang lebih ringan.

Inilah intuisi sentral : data pelatihan yang terbatas membuat few-shot priming lebih efektif.


Modelnya : detail teknis

Model Luna Protocol adalah fine-tune QLoRA dari Qwen2.5-1.5B-Instruct :

Parameter Nilai
Model dasar unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Metode QLoRA (4-bit)
Peringkat LoRA r=16, lora_alpha=16
Modul yang ditarget q/k/v/o_proj, gate/up/down_proj
Parameter yang bisa dilatih 18 464 768 / 1 562 179 072 (1,18 %)
Data pelatihan ~50 000 contoh (subset Discord-Dialogues)
Filter 8-512 token per sampel
Epoch 2-3
Perangkat keras Kaggle T4
Framework Unsloth

Himpunan data adalah fork Discord-Dialogues yang diproses sebelumnya, difilter untuk hanya menyimpan putaran user/assistant yang bersih : hanya pertukaran pengguna dan asisten, tanpa pesan sistem maupun metadata maupun perintah bot. Ini penting untuk kelanjutannya.

Kuantisasi yang tersedia

Berkas Kuantisasi Ukuran Catatan
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 MB Jelas terdegradasi -- tidak disarankan
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 MB Kompromi ukuran/kualitas yang bagus (disarankan)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 GB Kesetiaan stilistika terbaik

Model yang disarankan adalah Q4_K_M : kurang dari 1 GB, cepat, dan menjaga baik gaya percakapan. Q2_K terlalu terdegradasi untuk model ukuran ini. Q8_0 menawarkan kualitas terbaik tapi mengonsumsi 68% memori lebih banyak.


Terobosan few-shot priming

Inilah bagian yang mengubah segalanya.

Lembar model di HuggingFace memuat peringatan :

Dengan prompt telanjang dan tanpa priming, model ini cenderung jatuh kembali ke nada bawaan "asisten" Qwen. Priming few-shot yang singkat membuat perbedaan besar.

Ini akibat langsung dari cara data pelatihan distrukturkan.

Kenapa prompt sistem saja tidak berhasil

Data pelatihan Discord-Dialogues hanya berisi putaran user/assistant. Tidak ada contoh peran sistem dalam himpunan pelatihan. Model tidak pernah dilatih mengikuti prompt sistem sebagai arahan gaya.

Ketika kita memberinya prompt sistem seperti "Namamu Luna, bicara santai", ia mendengar instruksinya tapi tidak punya pola kuat yang dipelajari untuk menerjemahkannya menjadi keluaran. Ia lalu jatuh kembali pada perilaku bawaan Qwen : membantu, terstruktur, sedikit formal.

Kenapa contoh few-shot berhasil

Ketika kita menyuntikkan contoh percakapan dalam format ChatML yang sama dengan yang dipakai saat pelatihan (dengan struktur putaran user/assistant), sesuatu terpicu. Model mengenali pola dari pelatihannya dan menyelaraskan keluarannya sesuai itu.

Beginilah tampilan priming few-shot dalam praktik :

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Contoh ini disuntikkan setelah prompt sistem dan sebelum percakapan sungguhan. Model memahaminya sebagai bagian dari riwayat percakapan, jadi sebagai pertukaran nyata alih-alih instruksi. Ini perbedaan esensial : kita menunjukkannya seperti apa nada santai alih-alih memerintahkannya.

Sebelum / sesudah

Tanpa priming few-shot (prompt sistem telanjang) :

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

Dengan priming few-shot (3 contoh) :

User: yo whats good
Bot: nm just chillin, u

Perbedaannya mencolok. Model mengadopsi seluruh register : huruf kecil, singkatan, nada santai, respons pendek. Ia meniru gaya contoh alih-alih gaya data pelatihan Qwen.


Memori dan kecepatan : angka konkret

Peralihan dari Hermes-3-3B ke Luna-Protocol-1.5B membawa perolehan yang terukur :

Metrik Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Peningkatan
Pemakaian VRAM ~3 GB ~986 MB 67% lebih sedikit
Ukuran berkas model ~3,2 GB ~986 MB 69% lebih kecil
Pembangkitan token ~30 tok/dtk ~60+ tok/dtk 2x lebih cepat
Startup dingin ~8 dtk ~3 dtk 62% lebih cepat
Jendela konteks 8192 8192 Sama

Kenapa perolehan kecepatan nyata

Model lebih kecil secara fundamental lebih cepat dalam inferensi. Dengan 1,5B parameter alih-alih 3B :

  • Lebih sedikit perkalian matriks per token : lapisan atensi, lapisan FFN dan proyeksi keluaran semuanya berskala linear dengan jumlah parameter
  • Pemakaian cache lebih baik : model lebih kecil lebih memuat bobotnya dalam cache L2/L3
  • Lebih sedikit tekanan pada bandwidth memori : lebih sedikit byte yang dibaca dari VRAM per token

Pada konfigurasi sederhana, CPU saja (2 core, tanpa GPU), model 1,5B membangkitkan token sekitar 2 kali kecepatan model 3B. Inilah perbedaan antara "terasa seperti bot" dan "seperti orang sungguhan sedang mengetik".

Cache prompt memperkuat keunggulan

Luna Protocol memakai llama-server dengan cache prompt aktif (--cache-reuse 256). Artinya :

  1. Pesan pertama sesi membayar biaya penuh pemrosesan prompt (prompt sistem + contoh few-shot + pesan pengguna)
  2. Pesan berikutnya hanya memproses token baru, karena awalan yang di cache dipakai ulang
  3. Dengan 5 contoh few-shot (~50-150 token), overhead menjadi bisa diabaikan setelah permintaan pertama

Contoh few-shot menjadi dalam praktik "gratis" setelah pesan pertama sesi. Model mendapat manfaat panduan gaya dengan biaya marjinal nol.


Implementasinya : cara kerjanya dalam kode

Sistem few-shot Luna Protocol bersih dan minimal. Tiga berkas menangani semuanya.

1. Konfigurasi (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

Konfigurasinya bisa di hot-reload. Kita mengubah contoh, menyimpan, dan bot segera mengadopsi gaya baru, tanpa restart.

2. Pemformatan dan penyuntikan (src/core/few-shot.ts)

Fungsi formatFewShotExamples() mengubah contoh YAML menjadi objek pesan ChatML :

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

Fungsi injectFewShotIntoConversation() menaruhnya tepat setelah prompt sistem :

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Integrasi (src/core/llm-client.ts)

Sebelum setiap panggilan ke LLM, contoh few-shot disuntikkan kalau diaktifkan :

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

Model menerima : [prompt_sistem] + [contoh_few_shot] + [riwayat_percakapan]


Menjaga gaya Discord-Dialogues

Himpunan data Discord-Dialogues asli punya ciri percakapan yang sangat spesifik :

  • Pesan pendek : 32,8 token rata-rata per putaran
  • Register informal : singkatan, huruf kecil, ketiadaan tanda baca
  • Pertukaran cepat : banyak pertukaran pendek alih-alih monolog panjang
  • Ketidaksempurnaan alami : salah ketik, "lol", "fr", "ngl", "tbh"

Model Luna Protocol menjaga gaya ini berkat dua mekanisme :

1. Fine-tuning menggeser distribusi dasar

50k sampel pelatihan mengajarkan model jejak statistik percakapan Discord. Ia belajar bahwa respons tipikalnya pendek, huruf kecil dan informal. Ini menjauhkan keluaran bawaan model dari mode "asisten membantu" Qwen.

2. Few-shot priming mengunci hasil

Contoh few-shot memperkuat tepat pola yang dipelajari selama fine-tuning. Mereka bertindak sebagai jangkar stilistika : meski model sedikit melayang ke nada lebih formal selama percakapan panjang, contoh yang ada dalam konteks menariknya kembali.

Kombinasinya lebih kuat daripada tiap mekanisme sendiri :

  • Fine-tuning tanpa few-shot : model secara umum santai tapi tidak konsisten
  • Few-shot tanpa fine-tuning : model mencoba mengikuti contoh tapi terus jatuh kembali ke mode asisten
  • Fine-tuning + few-shot : model tetap konstan dalam karakter

Filosofi : model lebih kecil, prompting lebih cerdas

Kebijaksanaan konvensional dalam deployment LLM bilang "makin besar, makin baik". Lebih banyak parameter, lebih banyak data pelatihan, lebih banyak VRAM. Luna Protocol mengambil jalan sebaliknya :

  • 1,5B alih-alih 3B : setengah parameter, setengah memori, dua kali lebih cepat
  • 50k sampel alih-alih 7,3 juta : lebih sedikit data pelatihan, lebih banyak fleksibilitas untuk pembelajaran dalam konteks
  • Few-shot priming alih-alih prompt sistem : menunjukkan pada model apa yang kita inginkan, bukan sekadar memberitahunya

Ini pilihan desain yang disadari, jauh lebih dari sekadar optimasi teknis. Bot Discord perlu tetap menjadi teman percakapan yang ringan alih-alih asisten generalis. Ia harus bilang "nm just chillin, u" secara koheren, cepat, dan tanpa melahap seluruh anggaran VRAM server.

Hasilnya : bot yang berjalan di VPS 5 $/bulan, membangkitkan token cukup cepat untuk memberi kesan pengetikan waktu nyata, dan menjaga kepribadian koheren berkat kombinasi fine-tuning dan few-shot priming yang lebih berharga daripada jumlah bagiannya.


Penyiapan

Mengunduh model

npm run download-model
# Mengunduh Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

Atau manual dari HuggingFace.

Mengonfigurasi

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Menjalankan

npm run dev                    # dev (pemuatan ulang panas)
npm run build && npm start     # produksi
./start.sh                     # PM2 (produksi dengan llama-server)

Kesimpulan

Model Luna Protocol membuktikan bahwa untuk AI percakapan yang berfokus gaya, lebih sedikit, lebih baik. Model 1,5B yang dilatih pada 50k sampel yang dipilih cermat, di priming dengan beberapa contoh, melampaui model 3B yang dilatih pada jutaan contoh, dengan sebagian kecil biaya memori dan kecepatan pembangkitan dua kali lipat.

Few-shot priming merupakan mekanisme sentral untuk model kecil. Dialah yang membuat mereka viable untuk aplikasi percakapan waktu nyata. Contoh melakukan jauh lebih dari "membantu" : mereka secara fundamental mengubah perilaku model, dengan meniru tepat format tempat ia dilatih.

Kodenya open source, modelnya ada di HuggingFace, dan himpunan datanya publik. Kalau kamu ingin membangun bot percakapan yang memberi kesan manusiawi, resepnya adalah : model kecil, fine-tuning terbatas, priming few-shot yang solid.

Sumber daya Tautan
Depot GitHub fox3000foxy/luna-protocol-project
Model (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Himpunan data Discord-Dialogues
Artikel pertama Luna Protocol : saya membuat bot Discord otonom

Luna Protocol : मैंने 50k Discord नमूनों पर 1,5 अरब पैरामीटर मॉडल fine-tune क्यों किया, और few-shot priming ने सब क्यों बदला

कम डेटा पर प्रशिक्षित छोटा मॉडल बड़े मॉडल से बेहतर हो सकता है, बशर्ते उसे अच्छी तरह शुरू करना आता हो। Luna Protocol Hermes 3B से fine-tune Qwen 1,5B पर क्यों गया, और few-shot priming प्यारा बोनस से पूरे दृष्टिकोण का हृदय क्यों बना।

Luna Protocol : मैंने 50k Discord नमूनों पर 1,5 अरब पैरामीटर मॉडल fine-tune क्यों किया, और few-shot priming ने सब क्यों बदला

पहले लेख में, मैंने Discord बॉट बनाया जो मानव का अनुकरण करता है : नींद, टाइपो, हिचकिचाहट, भूल, स्वतः संदेश। व्यवहार तंत्र चलता था। उस सबके पीछे LLM 3 अरब पैरामीटर का Hermes मॉडल था, Q8_0 में quantize, 3 Go VRAM उपभोग करता हुआ।

यह काम करता था। लेकिन यह जरूरत से बड़ा था।

Discord बॉट को "nm just chillin, u" कहने के लिए 3 अरब पैरामीटर मॉडल नहीं चाहिए। उसे शैलीगत सुसंगतता चाहिए : संदेश दर संदेश सटीक बातचीत स्वर बनाए रखने की क्षमता, बिना "corporate सहायक" मोड की ओर बहके। और पता चलता है कि कम डेटा पर प्रशिक्षित और कुछ उदाहरणों से शुरू किया छोटा मॉडल वहाँ साधारण तंत्र प्रॉम्प्ट से जबरदस्ती गुजरने वाले बड़े मॉडल से बेहतर पहुँचता है।

यह लेख Luna Protocol आधिकारिक मॉडलों पर है : वे क्यों मौजूद हैं, 3B के बजाय 1,5B क्यों, 7,3M के बजाय 50k प्रशिक्षण नमूने क्यों, और few-shot priming "प्यारा बोनस" स्थिति से पूरे दृष्टिकोण के हृदय स्थिति में क्यों गया।


3B मॉडल की समस्या

मूल कॉन्फ़िगरेशन Discord-Micae-Hermes-3-3B.Q8_0.gguf इस्तेमाल करती थी, Discord डेटा पर fine-tune 3 अरब पैरामीटर मॉडल। वह अच्छे उत्तर बनाता था, लेकिन :

मीट्रिक Hermes-3-3B Q8_0 लक्ष्य
VRAM उपयोग ~3 Go < 1 Go
token पीढ़ी ~30 tok/s ~60+ tok/s
मॉडल फाइल आकार ~3,2 Go < 1 Go
cold शुरू समय ~8s ~3s

मामूली serveur पर 24/7 चलने वाले बॉट के लिए, 3 Go VRAM बहुत है। और पीढ़ी गति, कभी कभार संदेशों के लिए सही, बौछार उत्तरों या कई सक्रिय चैनलों पर धीमी लगती थी।

प्रश्न था : क्या वही Discord-Dialogues शैली आधे पैरामीटर से पाई जा सकती है ?


fine-tuning निर्णय : 7,3M क्यों नहीं, 50k क्यों

Discord-Dialogues डेटासेट में 7,3M आदान प्रदान और 17M वाणी मोड़ हैं। यह असली Discord बातचीत का विशाल corpus है। स्पष्ट दृष्टिकोण पूरे डेटासेट पर प्रशिक्षित करना होता।

मैंने उल्टा किया। मैंने 50 000 नमूनों पर प्रशिक्षित किया, उपलब्ध डेटा के 1 % से कम।

यहाँ क्यों : प्रशिक्षण सेट आकार सीधे प्रभावित करता है कि मॉडल अपने प्रशिक्षण वितरण के प्रति कितना अति अनुकूलित है।

7,3M उदाहरणों पर प्रशिक्षित मॉडल बातचीत का बहुत विशिष्ट सांख्यिकीय वितरण सीखता है। वह इस वितरण को दोहराने में उत्कृष्ट होता है, लेकिन वह कठोर भी होता है : अनुमान समय दिए नए पैटर्न अनुकूल होने की उसके पास कम गुंजाइश होती है।

50k उदाहरणों पर प्रशिक्षित मॉडल Discord बातचीत का सामान्य स्वर और register सीखता है (अनौपचारिक, छोटा, संक्षिप्त, छोटे अक्षर), लेकिन संदर्भ में उदाहरणों से चलाए जाने के लिए पर्याप्त लचीलापन रखता है। few-shot उदाहरण पहले से सीखे विशाल वितरण से नहीं लड़ते : वे हल्के वितरण को पूरा करने आते हैं।

यही केंद्रीय अंतर्ज्ञान है : सीमित प्रशिक्षण डेटा few-shot priming को ज्यादा प्रभावी बनाता है।


मॉडल : तकनीकी विवरण

Luna Protocol मॉडल Qwen2.5-1.5B-Instruct का QLoRA fine-tune है :

पैरामीटर मान
आधार मॉडल unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
विधि QLoRA (4-bit)
LoRA rank r=16, lora_alpha=16
लक्षित मॉड्यूल q/k/v/o_proj, gate/up/down_proj
प्रशिक्षण योग्य पैरामीटर 18 464 768 / 1 562 179 072 (1,18 %)
प्रशिक्षण डेटा ~50 000 उदाहरण (Discord-Dialogues का उपसमुच्चय)
फ़िल्टर प्रति नमूना 8-512 token
युग 2-3
हार्डवेयर Kaggle T4
Framework Unsloth

डेटासेट Discord-Dialogues का पूर्व प्रोसेस fork है, सिर्फ साफ user/assistant मोड़ रखने के लिए छाँटा गया : सिर्फ उपयोगकर्ता और सहायक आदान प्रदान, बिना तंत्र संदेश या मेटाडेटा या बॉट कमांड। आगे के लिए यह महत्वपूर्ण है।

उपलब्ध quantization

फाइल Quantization आकार टिप्पणियाँ
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 Mo स्पष्ट बिगड़ा , अनुशंसित नहीं
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 Mo अच्छा आकार/गुणवत्ता समझौता (अनुशंसित)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 Go सर्वश्रेष्ठ शैलीगत निष्ठा

अनुशंसित मॉडल Q4_K_M है : 1 Go से कम, तेज, और वह बातचीत शैली अच्छी तरह संरक्षित करता है। Q2_K इस आकार के मॉडल के लिए बहुत बिगड़ता है। Q8_0 सर्वश्रेष्ठ गुणवत्ता देता है लेकिन 68 % ज्यादा स्मृति उपभोग करता है।


few-shot priming सफलता

यहाँ वह हिस्सा है जिसने सब बदला।

HuggingFace पर मॉडल कार्ड में चेतावनी है :

नंगे प्रॉम्प्ट और बिना शुरुआत के, यह मॉडल Qwen के डिफ़ॉल्ट "सहायक" स्वर में लौटता है। छोटी few-shot शुरुआत बड़ा अंतर लाती है।

यह सीधा परिणाम है कि प्रशिक्षण डेटा कैसे संरचित किए गए थे।

सिर्फ तंत्र प्रॉम्प्ट क्यों काम नहीं करते

Discord-Dialogues प्रशिक्षण डेटा में सिर्फ user/assistant मोड़ हैं। प्रशिक्षण सेट में तंत्र भूमिका का कोई उदाहरण नहीं है। मॉडल शैली निर्देश के रूप में तंत्र प्रॉम्प्ट पालन करना कभी प्रशिक्षित नहीं हुआ।

जब उसे "तुम Luna हो, शांत तरीके से बोलो" तरह का तंत्र प्रॉम्प्ट दिया जाता है, तो वह निर्देश सुनता है लेकिन उसे output में अनुवाद करने का कोई ठोस सीखा पैटर्न नहीं है। वह तब Qwen डिफ़ॉल्ट व्यवहार पर लौटता है : सहायक, संरचित, हल्का औपचारिक।

few-shot उदाहरण क्यों काम करते हैं

जब बातचीत उदाहरण प्रशिक्षण में इस्तेमाल ChatML प्रारूप (user/assistant मोड़ संरचना) में डाले जाते हैं, तो कुछ trigger होता है। मॉडल अपने प्रशिक्षण का पैटर्न पहचानता है और तदनुसार output संरेखित करता है।

व्यवहार में few-shot शुरुआत ऐसी दिखती है :

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

ये उदाहरण तंत्र प्रॉम्प्ट बाद और असली बातचीत से पहले डाले जाते हैं। मॉडल उन्हें निर्देशों के बजाय बातचीत इतिहास हिस्से के रूप में देखता है, इसलिए असली आदान प्रदान के रूप में बजाय निर्देशों के। यह जरूरी भेद है : हम उसे बताने के बजाय दिखाते हैं कि शांत स्वर कैसा दिखता है।

पहले / बाद में

few-shot शुरुआत के बिना (नंगा तंत्र प्रॉम्प्ट) :

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

few-shot शुरुआत के साथ (3 उदाहरण) :

User: yo whats good
Bot: nm just chillin, u

अंतर स्पष्ट है। मॉडल पूरा register अपनाता है : छोटे अक्षर, संक्षिप्त, शांत स्वर, छोटे उत्तर। वह Qwen प्रशिक्षण डेटा शैली के बजाय उदाहरणों की शैली नकल करता है।


स्मृति और गति : ठोस अंक

Hermes-3-3B से Luna-Protocol-1.5B जाने पर मापने योग्य लाभ लाता है :

मीट्रिक Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M सुधार
VRAM उपयोग ~3 Go ~986 Mo 67 % कम
मॉडल फाइल आकार ~3,2 Go ~986 Mo 69 % छोटा
token पीढ़ी ~30 tok/s ~60+ tok/s 2x तेज
cold शुरू ~8s ~3s 62 % तेज
संदर्भ विंडो 8192 8192 समान

गति लाभ असली क्यों है

छोटे मॉडल अनुमान में मौलिक तेज हैं। 3B के बजाय 1,5B पैरामीटर से :

  • प्रति token कम आव्यूह गुणा : attention परतें, FFN परतें और output प्रक्षेपण सभी पैरामीटर संख्या से रैखिक बढ़ते हैं
  • बेहतर cache उपयोग : छोटा मॉडल अपने ज्यादा भार L2/L3 cache में रखता है
  • स्मृति bandwidth पर कम दबाव : प्रति token VRAM से पढ़ने को कम octet

मामूली कॉन्फ़िगरेशन, सिर्फ CPU (2 core, बिना GPU) पर, 1,5B मॉडल 3B मॉडल की लगभग 2 गुना गति से token बनाता है। यही "बॉट जैसा लगता है" और "वास्तविक व्यक्ति टाइप करता लगता है" के बीच अंतर है।

prompt cache फायदा बढ़ाता है

Luna Protocol cache सक्षम (--cache-reuse 256) llama-server इस्तेमाल करता है। इसका मतलब है :

  1. सत्र का पहला संदेश prompt प्रोसेसिंग की पूरी लागत चुकाता है (तंत्र प्रॉम्प्ट + few-shot उदाहरण + उपयोगकर्ता संदेश)
  2. अगले संदेश सिर्फ नए token प्रोसेस करते हैं, क्योंकि cache उपसर्ग फिर से इस्तेमाल होता है
  3. 5 few-shot उदाहरणों (~50-150 token) से, पहली query बाद overhead नगण्य हो जाता है

few-shot उदाहरण व्यवहार में सत्र के पहले संदेश बाद "मुफ्त" हो जाते हैं। मॉडल शून्य सीमांत लागत पर शैली मार्गदर्शन पाता है।


कार्यान्वयन : कोड में यह कैसे काम करता है

Luna Protocol few-shot तंत्र साफ और न्यूनतम है। तीन फाइलें सब संभालती हैं।

1. कॉन्फ़िगरेशन (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

कॉन्फ़िगरेशन गर्म reload योग्य है। उदाहरण बदलते हैं, सहेजते हैं, और बॉट बिना पुनरारंभ तुरंत नई शैली अपनाता है।

2. स्वरूपण और इंजेक्शन (src/core/few-shot.ts)

formatFewShotExamples() फंक्शन YAML उदाहरणों को ChatML संदेश ऑब्जेक्ट में बदलता है :

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

injectFewShotIntoConversation() फंक्शन उन्हें तंत्र प्रॉम्प्ट ठीक बाद रखता है :

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. एकीकरण (src/core/llm-client.ts)

LLM के हर कॉल से पहले, few-shot उदाहरण डाले जाते हैं अगर वे सक्षम हैं :

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

मॉडल पाता है : [तंत्र_प्रॉम्प्ट] + [few_shot_उदाहरण] + [बातचीत_इतिहास]


Discord-Dialogues शैली बनाए रखना

मूल Discord-Dialogues डेटासेट की बहुत विशिष्ट बातचीत हस्ताक्षर है :

  • छोटे संदेश : प्रति मोड़ औसत 32,8 token
  • अनौपचारिक register : संक्षिप्त, छोटे अक्षर, विराम चिह्न अनुपस्थिति
  • तेज आदान प्रदान : लंबे एकालाप के बजाय कई छोटे आदान प्रदान
  • स्वाभाविक अपूर्णताएँ : टाइपो, "lol", "fr", "ngl", "tbh"

Luna Protocol मॉडल दो तंत्रों से यह शैली संरक्षित करता है :

1. fine-tuning आधार वितरण खिसकाता है

50k प्रशिक्षण नमूने मॉडल को Discord बातचीत की सांख्यिकीय छाप सिखाते हैं। वह सीखता है कि उत्तर आमतौर पर छोटे, छोटे अक्षरों और अनौपचारिक होते हैं। यह मॉडल का डिफ़ॉल्ट output Qwen के "सहायक सहायक" मोड से दूर करता है।

2. few-shot priming परिणाम lock करता है

few-shot उदाहरण ठीक fine-tuning के दौरान सीखे पैटर्न मजबूत करते हैं। वे शैलीगत लंगर की तरह काम करते हैं : भले ही मॉडल लंबी बातचीत में थोड़ा औपचारिक स्वर की ओर बहे, संदर्भ में मौजूद उदाहरण उसे पीछे लाते हैं।

संयोजन हर तंत्र अकेले से ज्यादा शक्तिशाली है :

  • few-shot के बिना fine-tuning : मॉडल वैश्विक शांत है लेकिन असंगत
  • fine-tuning के बिना few-shot : मॉडल उदाहरण पालन करने की कोशिश करता है लेकिन बार बार सहायक मोड में लौटता है
  • fine-tuning + few-shot : मॉडल लगातार पात्र में रहता है

दर्शन : छोटा मॉडल, चतुर prompting

LLM परिनियोजन में परंपरागत बुद्धि कहती है "बड़ा बेहतर है"। ज्यादा पैरामीटर, ज्यादा प्रशिक्षण डेटा, ज्यादा VRAM। Luna Protocol उल्टा रास्ता लेता है :

  • 3B के बजाय 1,5B : आधे पैरामीटर, आधी स्मृति, दो गुना तेज
  • 7,3M के बजाय 50k नमूने : कम प्रशिक्षण डेटा, संदर्भ में सीखने के लिए ज्यादा लचीलापन
  • तंत्र प्रॉम्प्ट के बजाय few-shot priming : मॉडल को सिर्फ बताने के बजाय वह दिखाना जो हम चाहते हैं

यह माना डिजाइन चुनाव है, साधारण तकनीकी अनुकूलन से कहीं ज्यादा। Discord बॉट को सामान्यवादी सहायक के बजाय हल्का बातचीत साथी रहना होगा। उसे serveur के पूरे VRAM बजट निगले बिना, सुसंगत, तेज "nm just chillin, u" कहना होगा।

परिणाम : बॉट जो 5 $/महीना VPS पर चलता है, वास्तविक समय टाइपिंग का आभास देने को काफी तेज token बनाता है, और fine-tuning और few-shot priming संयोजन से सुसंगत व्यक्तित्व बनाए रखता है जो हिस्सों योग से ज्यादा है।


स्थापना

मॉडल डाउनलोड करना

npm run download-model
# Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf डाउनलोड करता है

या HuggingFace से मैन्युअल।

कॉन्फ़िगर करना

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

चलाना

npm run dev                    # dev (गर्म reload)
npm run build && npm start     # production
./start.sh                     # PM2 (llama-server के साथ production)

निष्कर्ष

Luna Protocol मॉडल साबित करते हैं कि शैली केंद्रित संवादात्मक AI के लिए, कम बेहतर है। सावधानी से चुने 50k नमूनों पर प्रशिक्षित 1,5B मॉडल, कुछ उदाहरणों से शुरू किया, लाखों उदाहरणों पर प्रशिक्षित 3B मॉडल से बेहतर होता है, स्मृति लागत के अंश और दो गुना पीढ़ी गति के लिए।

few-shot priming छोटे मॉडलों के लिए केंद्रीय तंत्र है। यही उन्हें वास्तविक समय बातचीत application के लिए व्यवहार्य बनाता है। उदाहरण सिर्फ "मदद" से कहीं ज्यादा करते हैं : वे मौलिक मॉडल व्यवहार बदलते हैं, ठीक उस प्रारूप को नकल करके जिस पर वह प्रशिक्षित हुआ था।

कोड ओपन सोर्स है, मॉडल HuggingFace पर है, और डेटासेट सार्वजनिक है। अगर तुम बातचीत बॉट बनाना चाहते हो जो मानव लगता है, तो नुस्खा है : छोटा मॉडल, सीमित fine-tuning, ठोस few-shot शुरुआत।

संसाधन लिंक
GitHub रिपॉजिटरी fox3000foxy/luna-protocol-project
मॉडल (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
डेटासेट Discord-Dialogues
पहला लेख Luna Protocol : मैंने स्वायत्त Discord बॉट बनाया

Luna Protocol : لماذا ضبطت نموذجا من 1,5 مليار معامل على 50k عينة Discord، ولماذا غيّر التمهيد few-shot كل شيء

نموذج أصغر مدرّب على بيانات أقل يمكنه التفوق على نموذج أكبر، بشرط معرفة تمهيده جيدا. إليكم لماذا انتقل Luna Protocol من Hermes 3B إلى ضبط Qwen 1,5B، ولماذا صار التمهيد few-shot عامل التقدم الحقيقي.

Luna Protocol : لماذا ضبطت نموذجا من 1,5 مليار معامل على 50k عينة Discord، ولماذا غيّر التمهيد few-shot كل شيء

في المقال الأول، بنيت بوت Discord يحاكي إنسانا : نوم وأخطاء مطبعية وتردد ونسيان ورسائل عفوية. النظام السلوكي كان متماسكا. وكان الـLLM خلف كل ذلك نموذج Hermes من 3 مليارات معامل، مُكمَّم Q8_0، يستهلك 3 Go من VRAM.

كان يعمل. لكنه كان أكبر من اللازم.

بوت Discord لا يحتاج نموذجا من 3 مليارات معامل ليقول «nm just chillin, u». ما يحتاجه هو اتساق أسلوبي : القدرة على الحفاظ على نبرة محادثة دقيقة، رسالة بعد رسالة، دون الانحراف نحو وضع «مساعد مؤسساتي». وتبين أن نموذجا أصغر، مُدرَّبا على بيانات أقل وممهَّدا ببضعة أمثلة، ينجح في ذلك أفضل من نموذج أكبر يفرض المرور عبر prompt نظام بسيط.

هذا المقال عن نماذج Luna Protocol الرسمية : لماذا توجد، ولماذا 1,5B بدلا من 3B، ولماذا 50k عينة تدريب بدلا من 7,3M، ولماذا انتقل التمهيد few-shot من مرتبة «إضافة لطيفة» إلى قلب المقاربة كلها.


المشكلة مع نموذج 3B

كان الإعداد الأصلي يستخدم Discord-Micae-Hermes-3-3B.Q8_0.gguf، نموذجا من 3 مليارات معامل مضبوطا على بيانات Discord. كان ينتج ردودا جيدة، لكن :

المقياس Hermes-3-3B Q8_0 الهدف
استخدام VRAM ~3 Go < 1 Go
توليد الرموز ~30 tok/s ~60+ tok/s
حجم ملف النموذج ~3,2 Go < 1 Go
زمن الإقلاع البارد ~8s ~3s

لبوت يعمل 24/7 على خادم متواضع، 3 Go من VRAM كثير. وسرعة التوليد، المقبولة للرسائل العرضية، بدت متثاقلة أثناء الردود المتتابعة أو مع عدة قنوات نشطة.

وكان السؤال : هل يمكن الحصول على نفس أسلوب Discord-Dialogues بنصف المعاملات ؟


قرار الضبط : لماذا 50k، لا 7,3M

يحوي طقم البيانات Discord-Dialogues 7,3M تبادل و17M دور كلام. إنه مدونة ضخمة من محادثات Discord الحقيقية. وكانت المقاربة البديهية هي التدريب على طقم البيانات كاملا.

فعلت العكس. درّبت على 50 000 عينة، أي أقل من 1% من البيانات المتاحة.

إليكم لماذا : حجم طقم التدريب يؤثر مباشرة على درجة الإفراط في تخصيص النموذج لتوزيع تدريبه.

النموذج المدرّب على 7,3M مثال يتعلم توزيعا إحصائيا شديد الخصوصية للمحادثات. يصبح ممتازا في إعادة إنتاج هذا التوزيع، لكنه يصبح أيضا صلبا : تقل لديه الهوامش للتكيف مع أنماط جديدة تُقدَّم لحظة الاستدلال.

النموذج المدرّب على 50k مثال يتعلم النبرة والسجل العام لمحادثات Discord (غير رسمي وقصير واختصارات وحروف صغيرة)، لكنه يحتفظ بمرونة كافية ليُقاد بأمثلة في السياق. أمثلة few-shot لا تصارع توزيعا ضخما مُتعلَّما فعلا : بل تُكمّل توزيعا أخف.

إنها الحدس المركزي : بيانات تدريب محدودة تجعل التمهيد few-shot أكثر فعالية.


النموذج : تفاصيل تقنية

نموذج Luna Protocol هو ضبط QLoRA لـQwen2.5-1.5B-Instruct :

المعامل القيمة
النموذج الأساسي unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
الطريقة QLoRA (4-bit)
رتبة LoRA r=16 وlora_alpha=16
الوحدات المستهدفة q/k/v/o_proj وgate/up/down_proj
المعاملات القابلة للتدريب 18 464 768 / 1 562 179 072 (1,18 %)
بيانات التدريب ~50 000 مثال (مجموعة فرعية من Discord-Dialogues)
المرشح 8-512 tokens لكل عينة
الحقب 2-3
العتاد Kaggle T4
الإطار Unsloth

طقم البيانات fork مُعالَج مسبقا من Discord-Dialogues، مُرشَّح للاحتفاظ بأدوار user/assistant النظيفة فقط : تبادلات مستخدم ومساعد فقط، دون رسائل نظام ولا بيانات وصفية ولا أوامر بوت. وهذا مهم لما يلي.

التكميمات المتاحة

الملف التكميم الحجم ملاحظات
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 Mo متدهور بوضوح، غير موصى به
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 Mo حل وسط جيد حجم/جودة (موصى به)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 Go أفضل وفاء أسلوبي

النموذج الموصى به هو Q4_K_M : أقل من 1 Go، وسريع، ويحفظ جيدا الأسلوب المحادثي. يتدهور Q2_K أكثر من اللازم لنموذج بهذا الحجم. يقدم Q8_0 أفضل جودة لكنه يستهلك ذاكرة أكثر بـ68%.


اختراق التمهيد few-shot

إليكم الجزء الذي غيّر كل شيء.

تحمل بطاقة النموذج على HuggingFace تحذيرا :

مع prompt عارٍ ودون تمهيد، يميل هذا النموذج للسقوط في نبرة «المساعد» الافتراضية لـQwen. تمهيد few-shot قصير يصنع فرقا كبيرا.

إنها عاقبة مباشرة لطريقة هيكلة بيانات التدريب.

لماذا prompts النظام وحدها لا تعمل

لا تحوي بيانات تدريب Discord-Dialogues إلا أدوار user/assistant. لا يوجد أي مثال لدور نظام في طقم التدريب. لم يُدرَّب النموذج أبدا على اتباع prompts النظام كتوجيهات أسلوب.

وعندما نعطيه prompt نظام من نوع «اسمك Luna، تكلمي بارتياح»، يسمع التعليمات لكن لا يملك نمطا مُتعلَّما صلبا لترجمتها إلى مخرجات. فيسقط على سلوك Qwen الافتراضي : خدوم ومنظم ورسمي بعض الشيء.

لماذا تعمل أمثلة few-shot

عندما نحقن أمثلة محادثة بنفس صيغة ChatML المستخدمة في التدريب (مع بنية أدوار user/assistant)، يتحفز شيء ما. يتعرف النموذج على النمط من تدريبه ويوائم مخرجاته تبعا لذلك.

إليكم كيف يبدو تمهيد few-shot عمليا :

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

تُحقن هذه الأمثلة بعد prompt النظام وقبل المحادثة الحقيقية. يدركها النموذج كجزء من سجل المحادثة، أي كتبادل حقيقي بدلا من تعليمات. إنه تمييز أساسي : نُريه كيف تبدو النبرة المريحة بدلا من أن نأمره بها.

قبل / بعد

دون تمهيد few-shot (prompt نظام عارٍ) :

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

مع تمهيد few-shot (3 أمثلة) :

User: yo whats good
Bot: nm just chillin, u

الفرق صارخ. يتبنى النموذج السجل كله : حروف صغيرة واختصارات ونبرة مريحة وردود قصيرة. يحاكي أسلوب الأمثلة بدلا من أسلوب بيانات تدريب Qwen.


الذاكرة والسرعة : الأرقام الملموسة

يجلب الانتقال من Hermes-3-3B إلى Luna-Protocol-1.5B مكاسب قابلة للقياس :

المقياس Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M التحسن
استخدام VRAM ~3 Go ~986 Mo أقل بـ67%
حجم ملف النموذج ~3,2 Go ~986 Mo أصغر بـ69%
توليد الرموز ~30 tok/s ~60+ tok/s أسرع بمرتين
الإقلاع البارد ~8s ~3s أسرع بـ62%
نافذة السياق 8192 8192 متطابقة

لماذا مكسب السرعة حقيقي

النماذج الأصغر أسرع جوهريا في الاستدلال. مع 1,5B معامل بدلا من 3B :

  • ضرب مصفوفات أقل لكل رمز : طبقات الانتباه وطبقات FFN وإسقاط المخرجات تتدرج كلها خطيا مع عدد المعاملات
  • استخدام أفضل للكاش : النموذج الأصغر يُبقي المزيد من أوزانه في كاش L2/L3
  • ضغط أقل على عرض نطاق الذاكرة : بايتات أقل تُقرأ من VRAM لكل رمز

على إعداد متواضع، CPU وحده (نواتان، دون GPU)، يولد نموذج 1,5B الرموز بسرعة ضعفي سرعة نموذج 3B تقريبا. إنه الفرق بين «تفوح منه رائحة البوت» و«يبدو شخصا حقيقيا يكتب».

كاش الـprompt يضخّم الميزة

يستخدم Luna Protocol خادم llama-server مع تفعيل كاش الـprompt (--cache-reuse 256). وهذا يعني أن :

  1. أول رسالة في جلسة تدفع Kost الكامل لمعالجة الـprompt (prompt النظام + أمثلة few-shot + رسالة المستخدم)
  2. الرسائل التالية لا تعالج إلا الرموز الجديدة، لأن البادئة المخزنة يُعاد استخدامها
  3. مع 5 أمثلة few-shot (~50-150 token)، يصبح العبء الإضافي مهملا بعد أول طلب

تصبح أمثلة few-shot عمليا "مجانية" بعد أول رسالة في جلسة. يستفيد النموذج من توجيه أسلوبي بـkost هامشي معدوم.


التنفيذ : كيف يعمل في الكود

نظام few-shot في Luna Protocol نظيف وبسيط. ثلاثة ملفات تدير كل شيء.

1. الإعداد (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

الإعداد قابل لإعادة التحميل حيا. نعدّل الأمثلة ونسجّل، فيتبنى البوت فورا الأسلوب الجديد، دون إعادة تشغيل.

2. الصياغة والحقن (src/core/few-shot.ts)

تحوّل الدالة formatFewShotExamples() أمثلة YAML إلى كائنات رسائل ChatML :

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

وتضعها الدالة injectFewShotIntoConversation() بعد prompt النظام مباشرة :

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. التكامل (src/core/llm-client.ts)

قبل كل استدعاء للـLLM، تُحقن أمثلة few-shot إذا فُعّلت :

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

يستلم النموذج : [prompt_النظام] + [أمثلة_few_shot] + [سجل_المحادثة]


الحفاظ على أسلوب Discord-Dialogues

لطقم البيانات الأصلي Discord-Dialogues بصمة محادثية شديدة الخصوصية :

  • رسائل قصيرة : 32,8 token في المتوسط لكل دور
  • سجل غير رسمي : اختصارات وحروف صغيرة وغياب ترقيم
  • تبادلات سريعة : عدة تبادلات قصيرة بدلا من مونولوغات طويلة
  • عيوب طبيعية : أخطاء مطبعية و«lol» و«fr» و«ngl» و«tbh»

يحفظ نموذج Luna Protocol هذا الأسلوب بآليتين :

1. الضبط ينقل التوزيع الأساسي

تعلّم عينات التدريب الـ50k النموذج البصمة الإحصائية لمحادثات Discord. يتعلم أن الردود قصيرة عادة وصغيرة وغير رسمية. وهذا يبعد المخرجات الافتراضية للنموذج عن وضع «المساعد الخدوم» لـQwen.

2. التمهيد few-shot يقفل النتيجة

تعزز أمثلة few-shot بالضبط الأنماط المُتعلَّمة أثناء الضبط. تعمل كـمرساة أسلوبية : حتى لو انحرف النموذج قليلا نحو نبرة أكثر رسمية أثناء محادثة طويلة، تعيده الأمثلة الحاضرة في السياق إلى الخلف.

التركيبة أقوى من كل آلية منفردة :

  • ضبط دون few-shot : النموذج مريح عموما لكن غير متسق
  • few-shot دون ضبط : النموذج يحاول اتباع الأمثلة لكن يسقط باستمرار في وضع المساعد
  • ضبط + few-shot : النموذج يبقى باستمرار في الشخصية

الفلسفة : نموذج أصغر، prompting أذكى

تقول الحكمة التقليدية في نشر LLM "الأكبر أفضل". معاملات أكثر وبيانات تدريب أكثر وVRAM أكثر. يسلك Luna Protocol الطريق المعاكس :

  • 1,5B بدلا من 3B : نصف المعاملات، ونصف الذاكرة، وسرعة مضاعفة
  • 50k عينة بدلا من 7,3M : بيانات تدريب أقل، ومرونة أكثر للتعلم في السياق
  • تمهيد few-shot بدلا من prompts النظام : إظهار ما نريد للنموذج، لا مجرد قوله له

إنه خيار تصميم مفترض، أكثر بكثير من مجرد تحسين تقني. بوت Discord يحتاج أن يبقى رفيق محادثة خفيفا بدلا من مساعد عام. يجب أن يقول «nm just chillin, u» باتساق وسرعة، ودون ابتلاع كل ميزانية VRAM للخادم.

النتيجة : بوت يعمل على VPS بـ5 $/شهر، ويولد الرموز بسرعة كافية لإعطاء انطباع كتابة في الوقت الحقيقي، ويحافظ على شخصية متسقة بتركيبة ضبط وتمهيد few-shot تساوي أكثر من مجموع أجزائها.


الإعداد

تنزيل النموذج

npm run download-model
# تحميل Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

أو يدويا من HuggingFace.

الإعداد

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

التشغيل

npm run dev                    # تطوير (إعادة تحميل حية)
npm run build && npm start     # إنتاج
./start.sh                     # PM2 (إنتاج مع llama-server)

الخلاصة

تثبت نماذج Luna Protocol أنه لذكاء اصطناعي محادثي متمحور على الأسلوب، الأقل أفضل. نموذج 1,5B مُدرَّب على 50k عينة مختارة بعناية، وممهَّد ببضعة أمثلة، يتفوق على نموذج 3B مُدرَّب على ملايين الأمثلة، بجزء من kost الذاكرة وسرعة توليد مضاعفة.

يشكل التمهيد few-shot الآلية المركزية للنماذج الصغيرة. إنه ما يجعلها قابلة للحياة لتطبيقات محادثة في الوقت الحقيقي. تفعل الأمثلة أكثر بكثير من "المساعدة" : إنها تغير جوهريا سلوك النموذج، بمحاكاة الصيغة التي دُرّب عليها بالضبط.

الكود مفتوح المصدر، والنموذج على HuggingFace، وطقم البيانات عام. إذا أردت بناء بوت محادثي يعطي انطباع الإنسان، فالوصفة هي : نموذج صغير، وضبط محدود، وتمهيد few-shot صلب.

المورد الرابط
مستودع GitHub fox3000foxy/luna-protocol-project
النموذج (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
طقم البيانات Discord-Dialogues
المقال الأول Luna Protocol : أنشأت بوت Discord مستقلا

Luna Protocol : vì sao tôi fine-tune mô hình 1,5 tỷ tham số trên 50k mẫu Discord, và vì sao few-shot priming đổi tất cả

Mô hình nhỏ hơn huấn luyện trên ít dữ liệu hơn có thể vượt mô hình lớn hơn -- với điều kiện biết mồi nó đúng cách. Đây là lý do Luna Protocol chuyển từ Hermes 3B sang fine-tune Qwen 1,5B, và vì sao few-shot priming thành nhân tố tiến bộ thật sự.

Luna Protocol : vì sao tôi fine-tune mô hình 1,5 tỷ tham số trên 50k mẫu Discord, và vì sao few-shot priming đổi tất cả

Trong bài đầu, tôi đã xây bot Discord mô phỏng con người : giấc ngủ, lỗi gõ phím, ngập ngừng, quên lãng, tin nhắn tự phát. Hệ thống hành vi chạy tốt. LLM đằng sau tất cả là mô hình Hermes 3 tỷ tham số, lượng tử Q8_0, ngốn 3 Go VRAM.

Nó chạy. Nhưng quá khổ.

Bot Discord không cần mô hình 3 tỷ tham số để nói « nm just chillin, u ». Điều nó cần là nhất quán phong cách : khả năng giữ đúng giọng trò chuyện, tin này qua tin khác, không trôi sang chế độ « trợ lý corporate ». Và hóa ra mô hình nhỏ hơn, huấn luyện trên ít dữ liệu hơn và mồi bằng vài ví dụ, làm điều đó tốt hơn mô hình lớn hơn ép đường qua prompt hệ thống đơn thuần.

Bài này nói về các mô hình chính thức của Luna Protocol : vì sao chúng tồn tại, vì sao 1,5B thay vì 3B, vì sao 50k mẫu huấn luyện thay vì 7,3M, và vì sao few-shot priming đi từ « bonus hay » thành lõi của toàn bộ cách tiếp cận.


Vấn đề với mô hình 3B

Cấu hình gốc dùng Discord-Micae-Hermes-3-3B.Q8_0.gguf, mô hình 3 tỷ tham số fine-tune trên dữ liệu Discord. Nó cho phản hồi tốt, nhưng :

Chỉ số Hermes-3-3B Q8_0 Mục tiêu
Dùng VRAM ~3 Go < 1 Go
Sinh token ~30 tok/s ~60+ tok/s
Kích thước tệp mô hình ~3,2 Go < 1 Go
Khởi động lạnh ~8s ~3s

Với bot chạy 24/7 trên máy chủ khiêm tốn, 3 Go VRAM là nhiều. Và tốc độ sinh, ổn cho tin nhắn thỉnh thoảng, thấy ì ạch khi trả lời chùm hay nhiều kênh hoạt động.

Câu hỏi là : có thể đạt cùng phong cách Discord-Dialogues với một nửa tham số?


Quyết định fine-tuning : vì sao 50k, không phải 7,3M

Bộ dữ liệu Discord-Dialogues chứa 7,3M lượt trao đổi và 17M lượt nói. Đó là kho hội thoại Discord thật khổng lồ. Cách hiển nhiên là huấn luyện trên toàn bộ dataset.

Tôi làm ngược lại. Tôi huấn luyện trên 50 000 mẫu, tức dưới 1% dữ liệu có sẵn.

Đây là lý do : kích thước tập huấn luyện ảnh hưởng trực tiếp mức độ quá khớp của mô hình với phân bố huấn luyện của nó.

Mô hình huấn luyện trên 7,3M ví dụ học phân bố thống kê rất đặc thù của cuộc trò chuyện. Nó thành xuất sắc trong tái tạo phân bố đó, nhưng cũng thành cứng : ít dư địa thích ứng với mẫu mới đưa lúc suy luận.

Mô hình huấn luyện trên 50k ví dụ học giọng và thanh ghi chung của hội thoại Discord (thân mật, ngắn, viết tắt, chữ thường), nhưng giữ đủ linh hoạt để được dẫn dắt bằng ví dụ trong ngữ cảnh. Các ví dụ few-shot không phải chống lại phân bố khổng lồ đã học : chúng bổ sung cho phân bố nhẹ hơn.

Đó là trực giác trung tâm : dữ liệu huấn luyện hạn chế khiến few-shot priming hiệu quả hơn.


Mô hình : chi tiết kỹ thuật

Mô hình Luna Protocol là fine-tune QLoRA của Qwen2.5-1.5B-Instruct :

Tham số Giá trị
Mô hình nền unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
Phương pháp QLoRA (4-bit)
Hạng LoRA r=16, lora_alpha=16
Module nhắm q/k/v/o_proj, gate/up/down_proj
Tham số huấn luyện được 18 464 768 / 1 562 179 072 (1,18 %)
Dữ liệu huấn luyện ~50 000 ví dụ (tập con của Discord-Dialogues)
Lọc 8-512 token cho mỗi mẫu
Epoch 2-3
Phần cứng Kaggle T4
Framework Unsloth

Dataset là fork tiền xử lý của Discord-Dialogues, lọc chỉ giữ lượt user/assistant sạch : chỉ trao đổi người dùng và trợ lý, không tin nhắn hệ thống, metadata hay lệnh bot. Điều này quan trọng cho phần sau.

Lượng tử có sẵn

Tệp Lượng tử Kích thước Ghi chú
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 Mo Xuống cấp rõ -- không khuyên
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 Mo Cân bằng tốt kích thước/chất lượng (khuyên dùng)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1,65 Go Trung thực phong cách tốt nhất

Mô hình khuyên dùng là Q4_K_M : dưới 1 Go, nhanh, và giữ tốt phong cách trò chuyện. Q2_K xuống cấp quá nhiều với mô hình cỡ này. Q8_0 cho chất lượng tốt nhất nhưng ngốn thêm 68% bộ nhớ.


Đột phá few-shot priming

Đây là phần đổi tất cả.

Thẻ mô hình trên HuggingFace có cảnh báo :

Với prompt trần và không mồi, mô hình này có xu hướng rớt về giọng mặc định « trợ lý » của Qwen. Mồi few-shot ngắn tạo khác biệt lớn.

Đó là hậu quả trực tiếp của cách dữ liệu huấn luyện được cấu trúc.

Vì sao chỉ prompt hệ thống không chạy

Dữ liệu huấn luyện Discord-Dialogues chỉ chứa lượt user/assistant. Không có ví dụ vai hệ thống nào trong tập huấn luyện. Mô hình chưa bao giờ được huấn luyện để theo prompt hệ thống như chỉ dẫn phong cách.

Khi ta đưa prompt hệ thống kiểu « Bạn tên Luna, nói thoải mái », nó nghe chỉ dẫn nhưng không có mẫu đã học vững để dịch thành đầu ra. Nó bèn rớt về hành vi mặc định của Qwen : giúp ích, có cấu trúc, hơi trang trọng.

Vì sao ví dụ few-shot chạy

Khi ta bơm ví dụ hội thoại đúng định dạng ChatML dùng lúc huấn luyện (với cấu trúc lượt user/assistant), điều gì đó kích hoạt. Mô hình nhận ra mẫu từ huấn luyện và căn đầu ra theo.

Đây là dáng mồi few-shot trong thực hành :

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Các ví dụ này được bơm sau prompt hệ thống và trước cuộc trò chuyện thật. Mô hình cảm nhận chúng như phần của lịch sử trò chuyện, nên như trao đổi thật thay vì chỉ dẫn. Đó là khác biệt cốt yếu : ta cho nó thấy giọng thoải mái trông thế nào thay vì ra lệnh cho nó.

Trước / sau

Không mồi few-shot (prompt hệ thống trần) :

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

Có mồi few-shot (3 ví dụ) :

User: yo whats good
Bot: nm just chillin, u

Khác biệt rõ rệt. Mô hình nhận toàn bộ thanh ghi : chữ thường, viết tắt, giọng thoải mái, phản hồi ngắn. Nó chép phong cách của ví dụ thay vì phong cách của dữ liệu huấn luyện Qwen.


Bộ nhớ và tốc độ : con số cụ thể

Chuyển từ Hermes-3-3B sang Luna-Protocol-1.5B mang lại lợi ích đo được :

Chỉ số Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M Cải thiện
Dùng VRAM ~3 Go ~986 Mo ít hơn 67 %
Kích thước tệp mô hình ~3,2 Go ~986 Mo nhỏ hơn 69 %
Sinh token ~30 tok/s ~60+ tok/s nhanh gấp 2
Khởi động lạnh ~8s ~3s nhanh hơn 62 %
Cửa sổ ngữ cảnh 8192 8192 Giống hệt

Vì sao lợi tốc độ là thật

Mô hình nhỏ hơn về cơ bản nhanh hơn lúc suy luận. Với 1,5B tham số thay vì 3B :

  • Ít phép nhân ma trận hơn cho mỗi token : lớp attention, lớp FFN và chiếu đầu ra đều co tuyến tính theo số tham số
  • Dùng cache tốt hơn : mô hình nhỏ hơn nhét được nhiều trọng số hơn vào cache L2/L3
  • Ít áp lực băng thông bộ nhớ : ít byte đọc từ VRAM hơn cho mỗi token

Trên cấu hình khiêm tốn, chỉ CPU (2 lõi, không GPU), mô hình 1,5B sinh token với tốc độ khoảng gấp 2 mô hình 3B. Đó là khác biệt giữa « mùi bot » và « như người thật đang gõ ».

Cache prompt khuếch đại lợi thế

Luna Protocol dùng llama-server với cache prompt bật (--cache-reuse 256). Nghĩa là :

  1. Tin nhắn đầu của phiên trả đủ chi phí xử lý prompt (prompt hệ thống + ví dụ few-shot + tin nhắn người dùng)
  2. Các tin nhắn sau chỉ xử lý token mới, vì tiền tố cache được tái dùng
  3. Với 5 ví dụ few-shot (~50-150 token), chi phí thêm thành không đáng kể sau yêu cầu đầu

Các ví dụ few-shot thực tế thành « miễn phí » sau tin nhắn đầu của phiên. Mô hình hưởng dẫn dắt phong cách với chi phí biên bằng không.


Triển khai : nó chạy thế nào trong mã

Hệ thống few-shot của Luna Protocol sạch và tối thiểu. Ba tệp quản lý tất cả.

1. Cấu hình (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

Cấu hình tải nóng được. Ta sửa ví dụ, lưu, và bot nhận ngay phong cách mới, không khởi động lại.

2. Định dạng và bơm (src/core/few-shot.ts)

Hàm formatFewShotExamples() đổi ví dụ YAML thành object tin nhắn ChatML :

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

Hàm injectFewShotIntoConversation() đặt chúng ngay sau prompt hệ thống :

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. Tích hợp (src/core/llm-client.ts)

Trước mỗi gọi tới LLM, ví dụ few-shot được bơm nếu bật :

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

Mô hình nhận : [prompt_hệ_thống] + [ví_dụ_few_shot] + [lịch_sử_trò_chuyện]


Giữ phong cách Discord-Dialogues

Dataset gốc Discord-Dialogues có chữ ký trò chuyện rất đặc thù :

  • Tin nhắn ngắn : trung bình 32,8 token cho mỗi lượt
  • Thanh ghi thân mật : viết tắt, chữ thường, thiếu chấm câu
  • Trao đổi nhanh : nhiều lượt ngắn thay vì độc thoại dài
  • Không hoàn hảo tự nhiên : lỗi gõ phím, « lol », « fr », « ngl », « tbh »

Mô hình Luna Protocol giữ phong cách này nhờ hai cơ chế :

1. Fine-tuning dịch chuyển phân bố nền

50k mẫu huấn luyện dạy mô hình dấu vân thống kê của hội thoại Discord. Nó học rằng phản hồi thường ngắn, chữ thường và thân mật. Việc này kéo đầu ra mặc định của mô hình ra khỏi chế độ « trợ lý giúp ích » của Qwen.

2. Few-shot priming khóa kết quả

Ví dụ few-shot củng cố đúng mẫu học lúc fine-tuning. Chúng đóng vai neo phong cách : ngay cả khi mô hình hơi trôi sang giọng trang trọng hơn trong cuộc trò chuyện dài, các ví dụ trong ngữ cảnh kéo nó lại.

Kết hợp mạnh hơn mỗi cơ chế riêng :

  • Fine-tuning không few-shot : mô hình nhìn chung thoải mái nhưng thiếu nhất quán
  • Few-shot không fine-tuning : mô hình cố theo ví dụ nhưng cứ rớt về chế độ trợ lý
  • Fine-tuning + few-shot : mô hình giữ liên tục trong vai

Triết lý : mô hình nhỏ hơn, prompting khôn hơn

Sự khôn ngoan thông thường trong triển khai LLM nói « càng lớn càng tốt ». Nhiều tham số hơn, nhiều dữ liệu huấn luyện hơn, nhiều VRAM hơn. Luna Protocol đi đường ngược :

  • 1,5B thay vì 3B : một nửa tham số, một nửa bộ nhớ, nhanh gấp đôi
  • 50k mẫu thay vì 7,3M : ít dữ liệu huấn luyện hơn, nhiều linh hoạt hơn cho học trong ngữ cảnh
  • Few-shot priming thay vì prompt hệ thống : cho mô hình thấy điều ta muốn, không chỉ bảo nó

Đó là lựa chọn thiết kế có chủ ý, hơn nhiều tối ưu kỹ thuật đơn thuần. Bot Discord cần giữ là bạn trò chuyện nhẹ thay vì trợ lý tổng quát. Nó phải nói « nm just chillin, u » nhất quán, nhanh, và không nuốt hết ngân sách VRAM của máy chủ.

Kết quả : bot chạy trên VPS 5 $/tháng, sinh token đủ nhanh để tạo cảm giác gõ thời gian thực, và giữ cá tính nhất quán nhờ kết hợp fine-tuning và few-shot priming đáng giá hơn tổng các phần.


Cài đặt

Tải mô hình

npm run download-model
# Tải Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

Hay thủ công từ HuggingFace.

Cấu hình

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

Chạy

npm run dev                    # dev (tải nóng lại)
npm run build && npm start     # production
./start.sh                     # PM2 (production với llama-server)

Kết luận

Các mô hình Luna Protocol chứng minh rằng với AI trò chuyện thiên về phong cách, ít hơn là tốt hơn. Mô hình 1,5B huấn luyện trên 50k mẫu chọn kỹ, mồi bằng vài ví dụ, vượt mô hình 3B huấn luyện trên hàng triệu ví dụ, với một phần chi phí bộ nhớ và tốc độ sinh nhanh gấp đôi.

Few-shot priming là cơ chế trung tâm cho mô hình nhỏ. Chính nó khiến chúng khả thi cho ứng dụng trò chuyện thời gian thực. Các ví dụ làm hơn nhiều « giúp đỡ » : chúng thay đổi về nền hành vi mô hình, bằng cách chép đúng định dạng nó được huấn luyện.

Mã open source, mô hình trên HuggingFace, và dataset công khai. Nếu bạn muốn xây bot trò chuyện tạo cảm giác con người, công thức là : mô hình nhỏ, fine-tuning hạn chế, mồi few-shot chắc.

Tài nguyên Link
Repo GitHub fox3000foxy/luna-protocol-project
Mô hình (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
Dataset Discord-Dialogues
Bài đầu Luna Protocol : tôi đã tạo bot Discord tự chủ

Luna Protocol: ทำไมฉันถึง fine-tune โมเดล 1.5B บนตัวอย่าง Discord 50k ชิ้น และทำให้ few-shot priming กลายเป็นอาวุธลับ

โมเดลที่เล็กกว่าซึ่งเทรนบนข้อมูลน้อยกว่าสามารถทำงานได้ดีกว่าโมเดลที่ใหญ่กว่า -- ถ้าคุณรู้วิธี prime มัน นี่คือสาเหตุที่ Luna Protocol เปลี่ยนจาก Hermes 3B มาเป็น fine-tune Qwen 1.5B และทำไม few-shot priming ถึงกลายเป็นตัวเปลี่ยนเกมที่แท้จริง

Luna Protocol: ทำไมฉันถึง fine-tune โมเดล 1.5B บนตัวอย่าง Discord 50k ชิ้น และทำให้ few-shot priming กลายเป็นอาวุธลับ

ใน บทความแรก ฉันได้สร้างบอท Discord ที่จำลองพฤติกรรมมนุษย์ -- การนอน, การพิมพ์ผิด, การลังเล, การขี้ลืม, ข้อความที่เกิดขึ้นเอง ระบบพฤติกรรมนั้นแข็งแกร่ง LLM ที่อยู่เบื้องหลังคือโมเดล Hermes 3B ซึ่งถูก quantize เป็น Q8_0 กิน VRAM 3GB

มันใช้งานได้ แต่มันเกินความจำเป็น

บอท Discord ไม่ต้องการโมเดล 3B พารามิเตอร์เพื่อพูด "nm just chillin, u" สิ่งที่มันต้องการคือ ความสม่ำเสมอของสไตล์ -- ความสามารถในการรักษาน้ำเสียงสนทนาที่เฉพาะเจาะจง ข้อความแล้วข้อความเล่า โดยไม่ล่องลอยไปสู่โหมดผู้ช่วยองค์กร และปรากฏว่า โมเดลที่เล็กกว่าที่เทรนบนข้อมูลน้อยกว่า พร้อม prime ด้วยตัวอย่างสองสามชิ้น ทำได้ดีกว่าโมเดลที่ใหญ่กว่าที่พยายามบังคับผ่าน system prompt

บทความนี้เกี่ยวกับโมเดลทางการของ Luna Protocol: ทำไมมันถึงมีอยู่ ทำไมเป็น 1.5B แทนที่จะเป็น 3B ทำไมตัวอย่างเทรน 50k ชิ้นแทนที่จะเป็น 7.3M และทำไม few-shot priming ถึงเปลี่ยนจากสิ่งที่ดีถ้ามี กลายเป็นแกนกลางของแนวทางทั้งหมด


ปัญหากับโมเดล 3B

การตั้งค่าเดิมใช้ Discord-Micae-Hermes-3-3B.Q8_0.gguf -- โมเดล 3B พารามิเตอร์ที่ fine-tune บนข้อมูล Discord มันสร้างคำตอบที่ดี แต่:

เมตริก Hermes-3-3B Q8_0 เป้าหมาย
การใช้งาน VRAM ~3 GB < 1 GB
การสร้างโทเค็น ~30 tok/s ~60+ tok/s
ขนาดไฟล์โมเดล ~3.2 GB < 1 GB
เวลาเริ่มต้นเย็น ~8s ~3s

สำหรับบอทที่ทำงาน 24/7 บนเซิร์ฟเวอร์ธรรมดาๆ VRAM 3GB ถือว่าเยอะมาก และความเร็วในการสร้าง -- แม้จะใช้ได้สำหรับข้อความที่ไม่บ่อย -- รู้สึกช้าในช่วงที่มีการตอบกลับหลายครั้งหรือเมื่อหลายช่องทางทำงานพร้อมกัน

คำถามคือ: เราจะได้สไตล์ Discord-Dialogues เดิมด้วยพารามิเตอร์ครึ่งเดียวหรือไม่?


การตัดสินใจ fine-tune: ทำไม 50k ไม่ใช่ 7.3M

ชุดข้อมูล Discord-Dialogues มี 7.3M การแลกเปลี่ยน และ 17M เทิร์น มันเป็นคลังข้อมูลขนาดใหญ่ของการสนทนา Discord จริง วิธีการที่ชัดเจนคือการเทรนบนชุดข้อมูลทั้งหมด

ฉันทำตรงกันข้าม ฉันเทรนบน 50,000 ตัวอย่าง -- น้อยกว่า 1% ของข้อมูลที่มี

นี่คือสาเหตุ: ขนาดของชุดเทรนส่งผลโดยตรงต่อระดับที่โมเดล overfit ต่อการกระจายของชุดเทรน

โมเดลที่เทรนบน 7.3M ตัวอย่างเรียนรู้การกระจายทางสถิติที่เฉพาะเจาะจงมากของการสนทนา มันกลายเป็นเลิศในการสร้างการกระจายนั้นขึ้นมาใหม่ แต่มันก็กลายเป็น แข็งทื่อ -- มันมีความยืดหยุ่นน้อยลงในการปรับตัวกับรูปแบบใหม่ที่ให้มาที่เวลา inference

โมเดลที่เทรนบน 50k ตัวอย่างเรียนรู้น้ำเสียงและระดับภาษาทั่วไปของการสนทนา Discord (ไม่เป็นทางการ, สั้น, ตัวย่อ, ตัวพิมพ์เล็ก) แต่มันยังคงความยืดหยุ่นเพียงพอที่จะถูก นำทางโดยตัวอย่างในบริบท ตัวอย่าง few-shot ไม่ได้ต่อสู้กับการกระจายขนาดใหญ่ที่เรียนรู้มา -- มันเสริมการกระจายที่เบากว่า

นี่คือข้อมูลเชิงลึกหลัก: ข้อมูลเทรนที่จำกัดทำให้ few-shot priming มีประสิทธิภาพมากขึ้น


โมเดล: รายละเอียดทางเทคนิค

โมเดล Luna Protocol คือ fine-tune QLoRA ของ Qwen2.5-1.5B-Instruct:

พารามิเตอร์ ค่า
โมเดลฐาน unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
วิธีการ QLoRA (4-bit)
Rank LoRA r=16, lora_alpha=16
โมดูลเป้าหมาย q/k/v/o_proj, gate/up/down_proj
พารามิเตอร์ที่เทรนได้ 18,464,768 / 1,562,179,072 (1.18%)
ข้อมูลเทรน ~50,000 ตัวอย่าง (ชุดย่อยของ Discord-Dialogues)
ตัวกรอง 8-512 โทเค็นต่อตัวอย่าง
จำนวนรอบ 2-3
ฮาร์ดแวร์ Kaggle T4
เฟรมเวิร์ก Unsloth

ชุดข้อมูลเป็น fork ที่ผ่านการประมวลผลล่วงหน้าของ Discord-Dialogues กรองให้มีเฉพาะเทิร์น user/assistant ที่สะอาด -- ไม่มีข้อความระบบ ไม่มีเมตาดาต้า ไม่มีคำสั่งบอท สิ่งนี้สำคัญสำหรับตอนหลัง

การควอนไทซ์ที่มีให้เลือก

ไฟล์ การควอนไทซ์ ขนาด หมายเหตุ
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q2_K.gguf Q2_K 676 MB เสื่อมคุณภาพอย่างเห็นได้ชัด -- ไม่แนะนำ
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf Q4_K_M 986 MB สมดุลขนาด/คุณภาพดี (แนะนำ)
Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q8_0.gguf Q8_0 1.65 GB ความเที่ยงตรงของสไตล์ดีที่สุด

โมเดลที่แนะนำคือ Q4_K_M -- ต่ำกว่า 1GB, เร็ว, และรักษาสไตล์การสนทนาได้ดี Q2_K เสื่อมคุณภาพมากเกินไปบนโมเดลเล็กขนาดนี้ Q8_0 มีคุณภาพดีที่สุดแต่ใช้หน่วยความจำมากกว่า 68%


ความก้าวหน้าของ few-shot priming

นี่คือส่วนที่เปลี่ยนแปลงทุกอย่าง

การ์ดโมเดล HuggingFace มีคำเตือน:

ด้วย prompt เปล่าๆ โดยไม่มีการ priming โมเดลนี้มีแนวโน้มที่จะกลับไปใช้น้ำเสียงผู้ช่วยเริ่มต้นของ Qwen การ prime สั้นๆ ด้วยตัวอย่างสองสามชิ้นสร้างความแตกต่างอย่างมาก

นี่ไม่ใช่บั๊ก -- มันเป็นผลโดยตรงจากวิธีที่ข้อมูลเทรนถูกจัดโครงสร้าง

ทำไม system prompt เพียงอย่างเดียวไม่ทำงาน

ข้อมูลเทรน Discord-Dialogues มีเฉพาะเทิร์น user/assistant ไม่มีตัวอย่างบทบาทระบบ ในชุดเทรน โมเดลไม่เคยถูกเทรนให้ทำตาม system prompt ในฐานะคำสั่งด้านสไตล์

เมื่อคุณให้ system prompt เช่น "ชื่อคุณคือ Luna พูดแบบสบายๆ" มันได้ยินคำสั่งแต่ไม่มีรูปแบบที่เรียนรู้มาอย่างแข็งแกร่งว่าจะแปลสิ่งนั้นเป็นเอาต์พุตอย่างไร มันกลับไปที่ค่าเริ่มต้นของ Qwen: ช่วยเหลือ มีโครงสร้าง เป็นทางการเล็กน้อย

ทำไมตัวอย่าง few-shot ถึงได้ผล

เมื่อคุณใส่ตัวอย่างการสนทนาในรูปแบบ ChatML เดียวกับที่โมเดลถูกเทรน (ใช้โครงสร้างเทิร์น user/assistant) บางอย่างก็เกิดขึ้น โมเดลจำรูปแบบจากข้อมูลเทรนของมันและปรับเอาต์พุตให้ตรงกัน

นี่คือลักษณะของ few-shot prime ในทางปฏิบัติ:

few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

ตัวอย่างเหล่านี้ถูกแทรกหลังจาก system prompt และก่อนการสนทนาจริง โมเดลมองเห็นพวกมันเป็นส่วนหนึ่งของประวัติการสนทนา ไม่ใช่เป็นคำสั่ง นี่คือความแตกต่างที่สำคัญ -- มันไม่ได้ถูก บอก ให้เป็นกันเอง แต่มันถูก แสดง ให้เห็นว่าการเป็นกันเองเป็นอย่างไร

ก่อนและหลัง

โดยไม่มี few-shot priming (system prompt เปล่า):

User: yo whats good
Bot: Hello! I am doing well, thank you for asking. How can I assist you today?

ด้วย few-shot priming (3 ตัวอย่าง):

User: yo whats good
Bot: nm just chillin, u

ความแตกต่างชัดเจน โมเดลไม่เพียงแค่สร้างคำที่แตกต่าง -- มันใช้ทะเบียนภาษาทั้งหมด: ตัวพิมพ์เล็ก, ตัวย่อ, น้ำเสียงสบายๆ, คำตอบสั้น มันจับคู่สไตล์ของตัวอย่าง ไม่ใช่สไตล์ของข้อมูลเทรนของ Qwen


หน่วยความจำและความเร็ว: ตัวเลขที่เป็นรูปธรรม

การเปลี่ยนจาก Hermes-3-3B เป็น Luna-Protocol-1.5B ให้ผลลัพธ์ที่วัดได้:

เมตริก Hermes-3-3B Q8_0 Luna-Protocol Q4_K_M การปรับปรุง
การใช้งาน VRAM ~3 GB ~986 MB น้อยลง 67%
ขนาดไฟล์โมเดล ~3.2 GB ~986 MB เล็กลง 69%
การสร้างโทเค็น ~30 tok/s ~60+ tok/s เร็วขึ้น 2 เท่า
เริ่มต้นเย็น ~8s ~3s เร็วขึ้น 62%
หน้าต่างบริบท 8192 8192 เท่าเดิม

ทำไมความเร็วที่เพิ่มขึ้นถึงเป็นจริง

โมเดลที่เล็กกว่าไม่ได้แค่ "ช้าลงน้อยกว่า" -- โดยพื้นฐานแล้วมันเร็วกว่าสำหรับ inference ด้วย 1.5B พารามิเตอร์แทนที่จะเป็น 3B:

  • การคูณเมทริกซ์น้อยลง ต่อโทเค็น: เลเยอร์ attention, เลเยอร์ FFN, และ projection เอาต์พุตล้วนเพิ่มเป็นเส้นตรงตามจำนวนพารามิเตอร์
  • การใช้แคชดีขึ้น: โมเดลที่เล็กกว่าใส่น้ำหนักได้มากขึ้นในแคช L2/L3
  • แรงดันแบนด์วิดท์หน่วยความจำต่ำลง: ไบต์น้อยลงที่ต้องอ่านจาก VRAM ต่อโทเค็น

บนการตั้งค่า CPU-only ธรรมดา (2 คอร์, ไม่มี GPU) โมเดล 1.5B สร้างโทเค็นด้วยความเร็วประมาณ 2 เท่า ของโมเดล 3B นี่คือความแตกต่างระหว่าง "รู้สึกเหมือนบอท" และ "รู้สึกเหมือนคนกำลังพิมพ์"

การแคช prompt ขยายความได้เปรียบ

Luna Protocol ใช้ llama-server โดยเปิดการแคช prompt (--cache-reuse 256) ซึ่งหมายความว่า:

  1. ข้อความแรกในเซสชันจ่ายต้นทุนการประมวลผล prompt ทั้งหมด (system prompt + ตัวอย่าง few-shot + ข้อความผู้ใช้)
  2. ข้อความถัดไปประมวลผลเฉพาะโทเค็น ใหม่ -- คำนำหน้าที่ถูกแคชถูกนำกลับมาใช้ใหม่
  3. ด้วยตัวอย่าง few-shot 5 ชิ้น (~50-150 โทเค็น) ต้นทุนเพิ่มเติมนั้นเล็กน้อยหลังจากคำขอแรก

ตัวอย่าง few-shot มีประสิทธิภาพ "ฟรี" หลังจากข้อความแรกในเซสชัน โมเดลได้รับคำแนะนำด้านสไตล์โดยมีต้นทุนส่วนเพิ่มเป็นศูนย์


การนำไปใช้: ทำงานอย่างไรในโค้ด

ระบบ few-shot ใน Luna Protocol สะอาดและเรียบง่าย สามไฟล์จัดการทุกอย่าง:

1. การกำหนดค่า (config.yml)

few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"
  - user: "whats up"
    assistant: "yooo not much, what about you"
  - user: "how was your day"
    assistant: "it was alright, nothing crazy happened lol"

การกำหนดค่าสามารถโหลดซ้ำได้แบบ hot เปลี่ยนตัวอย่าง, บันทึก, และบอทจะใช้สไตล์ใหม่ทันที -- ไม่ต้องรีสตาร์ท

2. การจัดรูปแบบและการแทรก (src/core/few-shot.ts)

ฟังก์ชัน formatFewShotExamples() แปลงตัวอย่าง YAML เป็นออบเจกต์ข้อความ ChatML:

export function formatFewShotExamples(
  examples: FewShotExample[],
  username = "user"
): Array<{ role: "user" | "assistant"; content: string }> {
  const messages = [];
  for (const example of examples) {
    messages.push({ role: "user", content: `${username}: ${example.user}` });
    messages.push({ role: "assistant", content: example.assistant });
  }
  return messages;
}

ฟังก์ชัน injectFewShotIntoConversation() วางพวกมันไว้หลัง system prompt ทันที:

export function injectFewShotIntoConversation(
  messages: Message[],
  fewShotMessages: Message[]
): Message[] {
  const systemMessage = messages[0];
  const userMessages = messages.slice(1);
  return [systemMessage, ...fewShotMessages, ...userMessages];
}

3. การบูรณาการ (src/core/llm-client.ts)

ก่อนการเรียก LLM ทุกครั้ง ตัวอย่าง few-shot จะถูกแทรกถ้าเปิดใช้งาน:

let finalMessages = messages;
if (FEW_SHOT_ENABLED && FEW_SHOT_EXAMPLES.length > 0) {
  const fewShotMessages = formatFewShotExamples(FEW_SHOT_EXAMPLES);
  finalMessages = injectFewShotIntoConversation(messages, fewShotMessages);
}

โมเดลได้รับ: [system_prompt] + [few_shot_examples] + [conversation_history]


การรักษาสไตล์ Discord-Dialogues

ชุดข้อมูล Discord-Dialogues ดั้งเดิมมีลายเซ็นการสนทนาที่เฉพาะเจาะจงมาก:

  • ข้อความสั้น: เฉลี่ย 32.8 โทเค็นต่อเทิร์น
  • ระดับภาษาไม่เป็นทางการ: ตัวย่อ, ตัวพิมพ์เล็ก, ไม่มีเครื่องหมายวรรคตอน
  • การโต้ตอบเร็ว: การแลกเปลี่ยนสั้นๆ หลายครั้งแทนการพูดคนเดียวยาว
  • ความไม่สมบูรณ์แบบตามธรรมชาติ: การพิมพ์ผิด, "lol", "fr", "ngl", "tbh"

โมเดล Luna-Protocol รักษาสไตล์นี้ผ่านสองกลไก:

1. Fine-tuning เปลี่ยนการกระจายฐาน

ตัวอย่างเทรน 50k สอนโมเดล ลายนิ้วมือทางสถิติ ของการสนทนา Discord มันเรียนรู้ว่าการตอบกลับมักจะสั้น ตัวพิมพ์เล็ก และไม่เป็นทางการ สิ่งนี้เปลี่ยนเอาต์พุตเริ่มต้นของโมเดลออกจากโหมดผู้ช่วยของ Qwen

2. Few-shot priming ล็อคมันไว้

ตัวอย่าง few-shot ตอกย้ำรูปแบบที่แน่นอนที่โมเดลเรียนรู้ระหว่าง fine-tuning พวกมันทำหน้าที่เป็น สมอของสไตล์ -- ถึงแม้โมเดลจะล่องลอยไปทางน้ำเสียงทางการเล็กน้อยระหว่างการสนทนายาว ตัวอย่างในบริบทก็ยังคงดึงมันกลับมา

การรวมกันมีพลังมากกว่ากลไกใดๆ เพียงอย่างเดียว:

  • Fine-tuning โดยไม่มี few-shot: โมเดล โดยทั่วไป เป็นกันเองแต่ไม่สม่ำเสมอ
  • Few-shot โดยไม่มี fine-tuning: โมเดลพยายามทำตามตัวอย่างแต่กลับไปโหมดผู้ช่วยซ้ำแล้วซ้ำเล่า
  • Fine-tuning + few-shot: โมเดล สม่ำเสมอ อยู่ในบุคลิก

ปรัชญา: โมเดลเล็กกว่า, prompting ฉลาดกว่า

ภูมิปัญญาดั้งเดิมในการปรับใช้ LLM คือ "ยิ่งใหญ่ยิ่งดี" พารามิเตอร์มากขึ้น, ข้อมูลเทรนมากขึ้น, VRAM มากขึ้น Luna Protocol ใช้แนวทางตรงกันข้าม:

  • 1.5B แทน 3B: ครึ่งหนึ่งของพารามิเตอร์, ครึ่งหนึ่งของหน่วยความจำ, ความเร็วสองเท่า
  • 50k ตัวอย่างแทน 7.3M: ข้อมูลเทรนน้อยลง, ความยืดหยุ่นมากขึ้นสำหรับการเรียนรู้ในบริบท
  • Few-shot priming แทน system prompt: แสดงให้โมเดลเห็นสิ่งที่คุณต้องการ อย่าแค่บอกมัน

นี่ไม่ใช่แค่การเพิ่มประสิทธิภาพทางเทคนิค -- มันเป็นปรัชญาการออกแบบ บอท Discord ไม่จำเป็นต้องเป็นผู้ช่วยอเนกประสงค์ มันต้องพูด "nm just chillin, u" อย่างสม่ำเสมอ รวดเร็ว และโดยไม่กินงบ VRAM ทั้งหมดของเซิร์ฟเวอร์คุณ

ผลลัพธ์: บอทที่ทำงานบน VPS ราคา $5/เดือน, สร้างโทเค็นเร็วพอที่จะรู้สึกเหมือนกำลังพิมพ์แบบเรียลไทม์, และรักษาบุคลิกที่สม่ำเสมอผ่านการผสมผสานของ fine-tuning และ few-shot priming ที่มากกว่าผลรวมของส่วนประกอบแต่ละส่วน


การตั้งค่า

ดาวน์โหลดโมเดล

npm run download-model
# ดาวน์โหลด Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf

หรือด้วยตนเองจาก HuggingFace

กำหนดค่า

# config.yml
llama_model_path: "./models/Luna-Protocol-1.5B-Fine-Tuned-Qwen2.5.Q4_K_M.gguf"
few_shot_enabled: true
few_shot_examples:
  - user: "yo whats good"
    assistant: "nm just chillin, u"
  - user: "bored af"
    assistant: "lol same energy fr"
  - user: "hey how are you"
    assistant: "im doing pretty good tbh, just vibing"

รัน

npm run dev                    # dev (โหลดซ้ำแบบ hot)
npm run build && npm start     # production
./start.sh                     # PM2 (production กับ llama-server)

บทสรุป

โมเดล Luna Protocol พิสูจน์ว่าสำหรับ AI การสนทนาที่เน้นสไตล์ น้อยคือมากกว่า โมเดล 1.5B ที่เทรนบน 50k ตัวอย่างที่คัดสรรมาอย่างดี, ถูก prime ด้วยตัวอย่างสองสามชิ้น, ทำงานได้ดีกว่าโมเดล 3B ที่เทรนบนตัวอย่างนับล้าน -- ด้วยต้นทุนหน่วยความจำเพียงเศษเสี้ยวและความเร็วในการสร้างสองเท่า

Few-shot priming ไม่ใช่แค่สิ่งที่ดีถ้ามีสำหรับโมเดลเล็ก มันเป็นกลไกที่ทำให้โมเดลเหล่านั้นใช้งานได้สำหรับแอปพลิเคชันการสนทนาแบบเรียลไทม์ ตัวอย่างไม่ได้แค่ "ช่วย" -- มันเปลี่ยนวิธีที่โมเดลทำงานโดยพื้นฐาน โดยการจับคู่รูปแบบที่แน่นอนที่มันถูกเทรน

โค้ดเป็นโอเพนซอร์ส, โมเดลอยู่บน HuggingFace, และชุดข้อมูลเป็นสาธารณะ ถ้าคุณต้องการสร้างบอทสนทนาที่ให้ความรู้สึกเหมือนมนุษย์ สูตรคือ: โมเดลเล็ก, fine-tuning จำกัด, few-shot priming ที่แข็งแกร่ง

แหล่งข้อมูล ลิงก์
พื้นที่เก็บ GitHub fox3000foxy/luna-protocol-project
โมเดล (HuggingFace) fox3000foxy/Luna-Protocol-1.5B-Discord-Dialogues
ชุดข้อมูล Discord-Dialogues
บทความแรก Luna Protocol: ฉันสร้างบอท Discord อัตโนมัติ

Related Articles