初始化项目,由ModelHub XC社区提供模型
Model: xxrickyxx/Ailo152m-v2 Source: Original Platform
This commit is contained in:
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.gguf filter=lfs diff=lfs merge=lfs -text
|
||||
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
||||
251
README.md
Normal file
251
README.md
Normal file
@@ -0,0 +1,251 @@
|
||||
---
|
||||
license: cc-by-nc-sa-4.0
|
||||
language:
|
||||
- en
|
||||
tags:
|
||||
- text-generation
|
||||
- transformer
|
||||
- instruction-tuned
|
||||
- reasoning
|
||||
- web-search
|
||||
- rag
|
||||
- small-language-model
|
||||
- edge-ai
|
||||
- on-device
|
||||
- cpu-inference
|
||||
- ollama
|
||||
- gguf
|
||||
- causal-lm
|
||||
- conversational
|
||||
pipeline_tag: text-generation
|
||||
library_name: gguf
|
||||
model-index:
|
||||
- name: AILO-152M-v2
|
||||
results: []
|
||||
---
|
||||
|
||||
# AILO-152M-v2 Tiny LLM with Chat, Reasoning & Web Search ⚡
|
||||
|
||||
> **A 152M-parameter language model that runs on almost anything** laptops, old PCs, even a Raspberry Pi yet does instruction-following chat, step-by-step reasoning, and **web search** for fresh facts.
|
||||
|
||||
**AILO** (Artificial Intelligence Language Operator) is a compact, fast, from-scratch transformer. v2 turns the original base model into a real assistant: it answers questions, thinks before answering, and can use **live web results** to answer about things it was never trained on.
|
||||
|
||||
```bash
|
||||
ollama run Alieno/ailo-152m-v2
|
||||
```
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| 🧠 **Parameters** | 151.9M |
|
||||
| ⚡ **Speed** | up to **384 tok/s** (GPU), runs on **CPU & edge** |
|
||||
| 📦 **Size** | 97 MB (q4_k_m) – 305 MB (f16) |
|
||||
| 🌐 **Web search** | yes (context-following) |
|
||||
| 💭 **Reasoning** | yes (`<think>`) |
|
||||
| 🪶 **Min RAM** | ~300 MB |
|
||||
|
||||
---
|
||||
|
||||
## ✨ Why AILO-152M-v2?
|
||||
|
||||
- **Runs anywhere** 97 MB quantized, ~300 MB RAM. Old laptops, mini-PCs, Raspberry Pi, phones.
|
||||
- **Fast** fastest in its class (see benchmarks). Real-time chat even on modest hardware.
|
||||
- **Web-aware** trained for *context-following*, so it answers from fresh search results instead of stale memory.
|
||||
- **Distilled from a bigger model** answers learned from **Gemma 3 4B** (knowledge distillation): richer, better-structured replies than its size suggests.
|
||||
- **Honest small model** strong at concise factual Q&A and conversation; pairs with tools for exact math.
|
||||
- **Open & local** no cloud, full privacy, drop-in for Ollama.
|
||||
|
||||
**Great for:** edge/on-device AI, offline assistants, learning how LLMs work, fast prototyping, low-power servers, privacy-first chatbots.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick start
|
||||
|
||||
### Ollama (recommended)
|
||||
```bash
|
||||
ollama run Alieno/ailo-152m-v2
|
||||
>>> What is the capital of Italy?
|
||||
The capital city of Italy is Rome.
|
||||
```
|
||||
|
||||
Tags: `:latest` / `:q8_0` (best quality, 156 MB) · `:q4_k_m` (smallest, 97 MB) · `:f16` (full precision, 305 MB)
|
||||
|
||||
### API
|
||||
```bash
|
||||
curl http://localhost:11434/api/chat -d '{
|
||||
"model": "Alieno/ailo-152m-v2",
|
||||
"messages": [{"role": "user", "content": "Explain what gravity is."}]
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏆 Benchmarks
|
||||
|
||||
Evaluated via Ollama `/api/chat` on factual QA, reasoning and coherence vs comparable and **larger** models:
|
||||
|
||||
| Model | Params | Factual | Reasoning | Coherence | Speed (tok/s) |
|
||||
|-------|--------|---------|-----------|-----------|---------------|
|
||||
| **AILO-152M-v2** | **152M** | **7/8** | 1–2/5 | **100%** | **384** 🥇 |
|
||||
| SmolLM2 | 135M | 8/8 | 1/5 | 98% | 403 |
|
||||
| Qwen2.5 | 500M | 8/8 | 3–4/5 | 96% | 213 |
|
||||
| TinyLlama | 1.1B | 8/8 | 1–2/5 | 97% | 260 |
|
||||
|
||||
- 🥇 **Top coherence** (100% virtually no repetition) and among the **fastest**.
|
||||
- Competitive on factual accuracy with models its size and **larger**.
|
||||
- Trails only bigger instruction-tuned models on multi-step reasoning expected for the smallest, from-scratch model here.
|
||||
|
||||
> Measured on an NVIDIA RTX 5060 Ti. Reasoning has run-to-run variance on an 8/5-question micro-suite.
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Hardware & performance
|
||||
|
||||
AILO-152M is tiny, so it runs **far beyond high-end GPUs** including old and low-power hardware. Approximate generation speed (q4_k_m, ~97 MB):
|
||||
|
||||
| Hardware | Type | Est. speed (tok/s) | Notes |
|
||||
|----------|------|--------------------|-------|
|
||||
| RTX 5060 Ti / 4070+ | Modern GPU | **350–450** | ✅ measured: 384 (q8_0) |
|
||||
| RTX 3060 / 2070 | Mid GPU | ~250–350 | smooth real-time |
|
||||
| GTX 1660 / 1060 | **Older GPU** | ~150–220 | still real-time |
|
||||
| GTX 1050 / MX150 | **Old laptop GPU** | ~90–140 | very usable |
|
||||
| Ryzen 7 / Core i7 (recent) | Modern CPU | ~45–80 | no GPU needed |
|
||||
| Core i5 ~2015 | **Old CPU** | ~18–30 | usable for chat |
|
||||
| Raspberry Pi 5 | **SBC / edge** | ~10–16 | runs offline |
|
||||
| Raspberry Pi 4 | **Low-power SBC** | ~5–9 | runs offline |
|
||||
| Recent smartphone | **Mobile** | ~15–35 | via llama.cpp/Termux |
|
||||
|
||||
*Estimates except the measured RTX 5060 Ti; real numbers vary with quantization, RAM bandwidth and build flags. The takeaway: **AILO runs even where larger models can't load at all.***
|
||||
|
||||
**Minimum requirements:** ~300 MB RAM (q4_k_m), any x86-64 / ARM CPU. No GPU required.
|
||||
|
||||
---
|
||||
|
||||
## 💬 Chat format
|
||||
|
||||
Trained on this template (tags are plain GPT-2 BPE sequences no vocab extension):
|
||||
```
|
||||
<|user|>
|
||||
{question}
|
||||
<|assistant|>
|
||||
<think>{optional reasoning}</think>
|
||||
{answer}<|end|>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Web search (fresh facts)
|
||||
|
||||
AILO v2 is trained for **context-following with override**: give it search results and it answers from them **even when they contradict its training-time knowledge**, so it can use *up-to-date* facts. When no context is given, it falls back to its own (true) knowledge.
|
||||
|
||||
A ready pipeline is included (`ailo_web.py`): DuckDuckGo → instant-answer + **semantic re-ranking** (MiniLM) with language/relevance filters → short clean context (fits the 512-token window) → AILO answers.
|
||||
|
||||
```bash
|
||||
python ailo_web.py "What is the tallest mountain in the world?"
|
||||
# -> "Mount Everest, at 8,848 meters."
|
||||
```
|
||||
|
||||
*This is how a 152M model can answer about events it never saw in training.*
|
||||
|
||||
---
|
||||
|
||||
## 💭 Reasoning (thinking)
|
||||
|
||||
The model declares the **`thinking` capability**: set `"think": true` and the reasoning trace is returned in `message.thinking`, separate from the answer (shown in a dedicated box in the Ollama desktop app). Best on reasoning-style prompts; for exact math, pair with a calculator tool.
|
||||
|
||||
---
|
||||
|
||||
## 🐍 Python (Transformers)
|
||||
```python
|
||||
from huggingface_hub import hf_hub_download
|
||||
import torch, tiktoken, sys
|
||||
repo = "xxrickyxx/ailo-152m-v2"
|
||||
for f in ["config.json","configuration_ailo.py","modeling_ailo.py","pytorch_model.bin"]:
|
||||
hf_hub_download(repo_id=repo, filename=f, local_dir="ailo_v2")
|
||||
sys.path.insert(0, "ailo_v2")
|
||||
from modeling_ailo import AILOForCausalLM
|
||||
from configuration_ailo import AILOConfig
|
||||
model = AILOForCausalLM(AILOConfig())
|
||||
model.load_state_dict(torch.load("ailo_v2/pytorch_model.bin", map_location="cpu"), strict=False)
|
||||
model.eval()
|
||||
tok = tiktoken.get_encoding("gpt2")
|
||||
ids = torch.tensor([tok.encode_ordinary("<|user|>\nWhat is the capital of Italy?\n<|assistant|>\n")])
|
||||
print(tok.decode(model.generate(ids, max_new_tokens=40, temperature=0.3)[0].tolist()))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📐 Model details
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Parameters | 151.9M |
|
||||
| Architecture | Decoder-only Transformer (LayerNorm · RoPE · SwiGLU) |
|
||||
| Layers / Hidden / Heads | 12 / 768 / 12 |
|
||||
| Context length | 512 tokens |
|
||||
| Vocabulary | 50,257 (GPT-2 BPE) |
|
||||
| Base | AILO-152M (FineWeb-Edu, 182k steps) |
|
||||
| Fine-tuning | SFT + **distillation from Gemma 3 4B**: instruction + reasoning (GSM8K) + context-following (SQuAD) + context-override + tool-use |
|
||||
| Formats | GGUF (q4_k_m, q8_0, f16) + PyTorch |
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Limitations
|
||||
- 152M params: limited world knowledge and multi-step reasoning vs larger models.
|
||||
- 512-token context: best with short, focused prompts; not for long documents.
|
||||
- Web-search quality depends on search-result quality; best for well-defined factual questions.
|
||||
- For exact arithmetic, use the tool/agent layer (the calculator does the math).
|
||||
- Primarily English.
|
||||
|
||||
---
|
||||
|
||||
## 📜 License
|
||||
|
||||
This project uses a **dual-license** model.
|
||||
|
||||
### 🆓 Non-Commercial License
|
||||
Released under **Creative Commons Attribution-NonCommercial-ShareAlike 4.0 (CC BY-NC-SA 4.0)**.
|
||||
|
||||
You are free to:
|
||||
- Use the model for **research, education, and personal projects**
|
||||
- **Modify and fine-tune** the model
|
||||
- **Redistribute derivatives** under the same license
|
||||
|
||||
You must:
|
||||
- Provide **attribution**
|
||||
- Keep the **same license** for derivative works
|
||||
- **Not** use the model for **commercial purposes**
|
||||
|
||||
### 💼 Commercial License
|
||||
Commercial use of AILO-152M is **not permitted** under the free license. Commercial use includes:
|
||||
- Integration into paid products or services
|
||||
- Use in SaaS platforms, APIs, or enterprise systems
|
||||
- Any application that generates revenue directly or indirectly
|
||||
|
||||
For commercial licensing, a separate paid agreement (royalty or license fee) is required. Please contact the author.
|
||||
|
||||
---
|
||||
|
||||
## 📬 Contact
|
||||
|
||||
For research collaboration or commercial licensing inquiries, contact the project maintainer:
|
||||
|
||||
**Riccardo Sparacino** [LinkedIn](https://www.linkedin.com/in/riccardo-sparacino-developer-php-javascript-mysql-app-ios-android/)
|
||||
|
||||
---
|
||||
|
||||
## 📑 Citation
|
||||
```bibtex
|
||||
@misc{ailo152m_v2_2026,
|
||||
title = {AILO-152M-v2: A Tiny Instruction-Tuned LLM with Reasoning and Web Search},
|
||||
author = {Sparacino, Riccardo},
|
||||
year = {2026},
|
||||
note = {Dual-licensed CC BY-NC-SA 4.0 / commercial}
|
||||
}
|
||||
```
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
Built with [Ollama](https://ollama.com) and [llama.cpp](https://github.com/ggerganov/llama.cpp). Fine-tuning data: Alpaca-cleaned, GSM8K, SQuAD. Knowledge-distillation teacher: **Gemma 3 4B**. Embeddings for web re-ranking: sentence-transformers MiniLM.
|
||||
|
||||
---
|
||||
|
||||
*Keywords: small language model, tiny LLM, 152M, efficient LLM, edge AI, on-device LLM, CPU inference, Raspberry Pi LLM, Ollama model, GGUF, instruction-tuned, reasoning model, web search LLM, RAG, offline assistant, low-resource, fast inference.*
|
||||
3
ailo-152m-v2-f16.gguf
Normal file
3
ailo-152m-v2-f16.gguf
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2a3fd5dc78a687b98b822a714dd2d593513819b0d08d4f8531a3afbe3bc21d8b
|
||||
size 305537696
|
||||
3
ailo-152m-v2-q4_k_m.gguf
Normal file
3
ailo-152m-v2-q4_k_m.gguf
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d4413fc146577c6756747e885f55703773d9baaf6fb7708d2b2e95b11f20d273
|
||||
size 101775424
|
||||
3
ailo-152m-v2-q8_0.gguf
Normal file
3
ailo-152m-v2-q8_0.gguf
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6cec6db0bf707d5a62263c570a24cfc7ff4a1dfe7465020966078f776fa84833
|
||||
size 163184416
|
||||
23
config.json
Normal file
23
config.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"architectures": [
|
||||
"AILOForCausalLM"
|
||||
],
|
||||
"model_type": "ailo",
|
||||
"vocab_size": 50257,
|
||||
"hidden_size": 768,
|
||||
"num_hidden_layers": 12,
|
||||
"num_attention_heads": 12,
|
||||
"intermediate_size": 3072,
|
||||
"max_position_embeddings": 512,
|
||||
"hidden_dropout_prob": 0.1,
|
||||
"attention_probs_dropout_prob": 0.1,
|
||||
"bos_token_id": 50256,
|
||||
"eos_token_id": 50256,
|
||||
"pad_token_id": 50256,
|
||||
"torch_dtype": "float32",
|
||||
"transformers_version": "4.57.0",
|
||||
"auto_map": {
|
||||
"AutoConfig": "configuration_ailo.AILOConfig",
|
||||
"AutoModelForCausalLM": "modeling_ailo.AILOForCausalLM"
|
||||
}
|
||||
}
|
||||
41
configuration_ailo.py
Normal file
41
configuration_ailo.py
Normal file
@@ -0,0 +1,41 @@
|
||||
"""
|
||||
AILO Configuration for HuggingFace Transformers
|
||||
"""
|
||||
|
||||
from transformers import PretrainedConfig
|
||||
|
||||
|
||||
class AILOConfig(PretrainedConfig):
|
||||
"""Configuration class for AILO model."""
|
||||
|
||||
model_type = "ailo"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
vocab_size: int = 50257,
|
||||
hidden_size: int = 768,
|
||||
num_hidden_layers: int = 12,
|
||||
num_attention_heads: int = 12,
|
||||
intermediate_size: int = 3072,
|
||||
max_position_embeddings: int = 512,
|
||||
hidden_dropout_prob: float = 0.1,
|
||||
attention_probs_dropout_prob: float = 0.1,
|
||||
bos_token_id: int = 50256,
|
||||
eos_token_id: int = 50256,
|
||||
pad_token_id: int = 50256,
|
||||
**kwargs
|
||||
):
|
||||
super().__init__(
|
||||
bos_token_id=bos_token_id,
|
||||
eos_token_id=eos_token_id,
|
||||
pad_token_id=pad_token_id,
|
||||
**kwargs
|
||||
)
|
||||
self.vocab_size = vocab_size
|
||||
self.hidden_size = hidden_size
|
||||
self.num_hidden_layers = num_hidden_layers
|
||||
self.num_attention_heads = num_attention_heads
|
||||
self.intermediate_size = intermediate_size
|
||||
self.max_position_embeddings = max_position_embeddings
|
||||
self.hidden_dropout_prob = hidden_dropout_prob
|
||||
self.attention_probs_dropout_prob = attention_probs_dropout_prob
|
||||
50001
merges.txt
Normal file
50001
merges.txt
Normal file
File diff suppressed because it is too large
Load Diff
216
modeling_ailo.py
Normal file
216
modeling_ailo.py
Normal file
@@ -0,0 +1,216 @@
|
||||
"""
|
||||
AILO Model for HuggingFace Transformers - Matching original architecture
|
||||
"""
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
import math
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
from transformers import PreTrainedModel
|
||||
from transformers.generation import GenerationMixin
|
||||
from transformers.modeling_outputs import CausalLMOutputWithPast
|
||||
|
||||
try:
|
||||
from .configuration_ailo import AILOConfig
|
||||
except ImportError:
|
||||
from configuration_ailo import AILOConfig
|
||||
|
||||
|
||||
class RotaryPositionalEmbedding(nn.Module):
|
||||
"""Rotary Position Embedding (RoPE)."""
|
||||
|
||||
def __init__(self, dim: int, max_seq_len: int = 512, base: int = 10000):
|
||||
super().__init__()
|
||||
inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
|
||||
self.register_buffer("inv_freq", inv_freq)
|
||||
self.max_seq_len = max_seq_len
|
||||
|
||||
def forward(self, x: torch.Tensor, seq_len: int) -> Tuple[torch.Tensor, torch.Tensor]:
|
||||
t = torch.arange(seq_len, device=x.device).type_as(self.inv_freq)
|
||||
freqs = torch.einsum("i,j->ij", t, self.inv_freq)
|
||||
emb = torch.cat((freqs, freqs), dim=-1)
|
||||
return emb.cos(), emb.sin()
|
||||
|
||||
|
||||
def apply_rotary_pos_emb(q, k, cos, sin):
|
||||
"""Apply rotary position embedding."""
|
||||
def rotate_half(x):
|
||||
x1, x2 = x[..., :x.shape[-1]//2], x[..., x.shape[-1]//2:]
|
||||
return torch.cat((-x2, x1), dim=-1)
|
||||
|
||||
q_embed = (q * cos) + (rotate_half(q) * sin)
|
||||
k_embed = (k * cos) + (rotate_half(k) * sin)
|
||||
return q_embed, k_embed
|
||||
|
||||
|
||||
class AILOAttention(nn.Module):
|
||||
"""Multi-head attention matching original structure."""
|
||||
|
||||
def __init__(self, config: AILOConfig):
|
||||
super().__init__()
|
||||
self.n_heads = config.num_attention_heads
|
||||
self.head_dim = config.hidden_size // config.num_attention_heads
|
||||
self.scale = self.head_dim ** -0.5
|
||||
|
||||
# Match original: separate q, k, v projections
|
||||
self.q_proj = nn.Linear(config.hidden_size, config.hidden_size, bias=False)
|
||||
self.k_proj = nn.Linear(config.hidden_size, config.hidden_size, bias=False)
|
||||
self.v_proj = nn.Linear(config.hidden_size, config.hidden_size, bias=False)
|
||||
self.out_proj = nn.Linear(config.hidden_size, config.hidden_size, bias=False)
|
||||
|
||||
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
|
||||
self.rotary = RotaryPositionalEmbedding(self.head_dim, config.max_position_embeddings)
|
||||
|
||||
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
||||
B, T, C = x.shape
|
||||
|
||||
q = self.q_proj(x).view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
|
||||
k = self.k_proj(x).view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
|
||||
v = self.v_proj(x).view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
|
||||
|
||||
cos, sin = self.rotary(x, T)
|
||||
cos, sin = cos.unsqueeze(0).unsqueeze(0), sin.unsqueeze(0).unsqueeze(0)
|
||||
q, k = apply_rotary_pos_emb(q, k, cos, sin)
|
||||
|
||||
attn = (q @ k.transpose(-2, -1)) * self.scale
|
||||
|
||||
# Causal mask
|
||||
causal_mask = torch.triu(torch.ones(T, T, device=x.device), diagonal=1).bool()
|
||||
attn = attn.masked_fill(causal_mask.unsqueeze(0).unsqueeze(0), float('-inf'))
|
||||
|
||||
attn = F.softmax(attn, dim=-1)
|
||||
attn = self.dropout(attn)
|
||||
|
||||
out = (attn @ v).transpose(1, 2).reshape(B, T, C)
|
||||
return self.out_proj(out)
|
||||
|
||||
|
||||
class AILOMLP(nn.Module):
|
||||
"""Feed-forward with SwiGLU - matching original w1, w2, w3 structure."""
|
||||
|
||||
def __init__(self, config: AILOConfig):
|
||||
super().__init__()
|
||||
# Match original: w1 [3072, 768], w2 [768, 3072], w3 [3072, 768]
|
||||
self.w1 = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
|
||||
self.w2 = nn.Linear(config.intermediate_size, config.hidden_size, bias=False)
|
||||
self.w3 = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
|
||||
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
||||
|
||||
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
||||
# SwiGLU: w2(silu(w1(x)) * w3(x))
|
||||
return self.dropout(self.w2(F.silu(self.w1(x)) * self.w3(x)))
|
||||
|
||||
|
||||
class AILOBlock(nn.Module):
|
||||
"""Transformer block matching original structure."""
|
||||
|
||||
def __init__(self, config: AILOConfig):
|
||||
super().__init__()
|
||||
self.ln1 = nn.LayerNorm(config.hidden_size, elementwise_affine=True, bias=False)
|
||||
self.attn = AILOAttention(config)
|
||||
self.ln2 = nn.LayerNorm(config.hidden_size, elementwise_affine=True, bias=False)
|
||||
self.ff = AILOMLP(config)
|
||||
|
||||
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
||||
x = x + self.attn(self.ln1(x))
|
||||
x = x + self.ff(self.ln2(x))
|
||||
return x
|
||||
|
||||
|
||||
class AILOPreTrainedModel(PreTrainedModel):
|
||||
"""Base class for AILO models."""
|
||||
|
||||
config_class = AILOConfig
|
||||
base_model_prefix = "ailo"
|
||||
|
||||
def _init_weights(self, module):
|
||||
if isinstance(module, nn.Linear):
|
||||
nn.init.normal_(module.weight, mean=0.0, std=0.02)
|
||||
elif isinstance(module, nn.Embedding):
|
||||
nn.init.normal_(module.weight, mean=0.0, std=0.02)
|
||||
|
||||
|
||||
class AILOForCausalLM(AILOPreTrainedModel, GenerationMixin):
|
||||
"""AILO model for causal language modeling - matching original structure."""
|
||||
|
||||
def __init__(self, config: AILOConfig):
|
||||
super().__init__(config)
|
||||
|
||||
# Match original naming: tok_emb, blocks, ln_f, head
|
||||
self.tok_emb = nn.Embedding(config.vocab_size, config.hidden_size)
|
||||
self.blocks = nn.ModuleList([AILOBlock(config) for _ in range(config.num_hidden_layers)])
|
||||
self.ln_f = nn.LayerNorm(config.hidden_size, elementwise_affine=True, bias=False)
|
||||
self.head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
||||
|
||||
# Weight tying
|
||||
self.head.weight = self.tok_emb.weight
|
||||
|
||||
self.post_init()
|
||||
|
||||
def forward(
|
||||
self,
|
||||
input_ids: torch.LongTensor,
|
||||
attention_mask: Optional[torch.Tensor] = None,
|
||||
labels: Optional[torch.LongTensor] = None,
|
||||
**kwargs
|
||||
) -> CausalLMOutputWithPast:
|
||||
x = self.tok_emb(input_ids)
|
||||
|
||||
for block in self.blocks:
|
||||
x = block(x)
|
||||
|
||||
x = self.ln_f(x)
|
||||
logits = self.head(x)
|
||||
|
||||
loss = None
|
||||
if labels is not None:
|
||||
shift_logits = logits[..., :-1, :].contiguous()
|
||||
shift_labels = labels[..., 1:].contiguous()
|
||||
loss = F.cross_entropy(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
|
||||
|
||||
return CausalLMOutputWithPast(loss=loss, logits=logits)
|
||||
|
||||
def prepare_inputs_for_generation(self, input_ids, **kwargs):
|
||||
return {"input_ids": input_ids}
|
||||
|
||||
@torch.no_grad()
|
||||
def generate(
|
||||
self,
|
||||
input_ids: torch.LongTensor,
|
||||
max_new_tokens: int = 100,
|
||||
temperature: float = 0.8,
|
||||
top_k: int = 50,
|
||||
top_p: float = 0.95,
|
||||
**kwargs
|
||||
) -> torch.LongTensor:
|
||||
"""Generate text tokens."""
|
||||
for _ in range(max_new_tokens):
|
||||
idx_cond = input_ids[:, -512:] # Max context
|
||||
outputs = self(idx_cond)
|
||||
logits = outputs.logits[:, -1, :] / temperature
|
||||
|
||||
# Top-k
|
||||
if top_k > 0:
|
||||
v, _ = torch.topk(logits, min(top_k, logits.size(-1)))
|
||||
logits[logits < v[:, [-1]]] = float('-inf')
|
||||
|
||||
# Top-p
|
||||
if top_p < 1.0:
|
||||
sorted_logits, sorted_indices = torch.sort(logits, descending=True)
|
||||
cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)
|
||||
sorted_indices_to_remove = cumulative_probs > top_p
|
||||
sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
|
||||
sorted_indices_to_remove[..., 0] = 0
|
||||
indices_to_remove = sorted_indices_to_remove.scatter(1, sorted_indices, sorted_indices_to_remove)
|
||||
logits[indices_to_remove] = float('-inf')
|
||||
|
||||
probs = F.softmax(logits, dim=-1)
|
||||
next_token = torch.multinomial(probs, num_samples=1)
|
||||
input_ids = torch.cat([input_ids, next_token], dim=1)
|
||||
|
||||
if next_token.item() == self.config.eos_token_id:
|
||||
break
|
||||
|
||||
return input_ids
|
||||
3
pytorch_model.bin
Normal file
3
pytorch_model.bin
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e34544bc0274b2c58cf254ad1f86e919e075db28586cf70d2a128ff9152e280c
|
||||
size 607493595
|
||||
1
vocab.json
Normal file
1
vocab.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user