Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🦀 Small Language Model

Một mô hình ngôn ngữ nhỏ (SLM) xây dựng từ đầu bằng Rust, không dùng framework ML nào. Dự án triển khai đầy đủ vòng lặp forward pass → backpropagation → gradient descent theo kiến trúc MLP 2 lớp với embedding ký tự — được điều khiển qua một giao diện CLI tương tác.


Mục lục


Tổng quan

Dự án xây dựng một mô hình ngôn ngữ cấp độ ký tự (character-level) theo kiến trúc MLP (Multi-Layer Perceptron). Mô hình học xác suất của ký tự tiếp theo dựa trên mem ký tự trước đó, sử dụng embedding véc-tơ cho mỗi ký tự.

Khác với phiên bản trước (script chạy một lần), phiên bản hiện tại cung cấp một REPL tương tác — người dùng có thể nhập lệnh để cấu hình, huấn luyện, sinh văn bản và lưu/tải mô hình mà không cần sửa code.


Kiến trúc mô hình

Input (mem ký tự)
        │
        ▼
  Embedding Lookup
  [vocab_size × dim]
        │
        ▼ (context_length = mem × dim)
  Layer 1: Linear + Tanh
  [layer_node × context_length]
        │
        ▼
  Layer 2: Linear + Softmax
  [vocab_size × layer_node]
        │
        ▼
  Probability Distribution → Sample next char

Giá trị mặc định (có thể thay đổi qua CLI):

Tham số Mặc định Ý nghĩa
mem 4 Số ký tự ngữ cảnh đầu vào
dim 4 Số chiều embedding mỗi ký tự
context_length 16 Tổng chiều input layer (mem × dim, tự tính)
layer 64 Số neuron lớp ẩn
scale 0.1 Hệ số khởi tạo trọng số ngẫu nhiên
rate 0.01 Tốc độ học (learning rate)
respond_length 100 Số ký tự tối đa khi sinh văn bản

Cấu trúc dự án

small_language_model/
├── Cargo.toml              # Manifest Rust, dependency: rand
├── Cargo.lock
├── .gitignore
│
├── src/
│   ├── main.rs             # Entry point: khởi tạo Owl & Sea, vòng lặp CLI
│   ├── lib.rs              # Khai báo các module public
│   ├── interfaces.rs       # Type aliases dùng chung
│   ├── config.rs           # Struct Config — cấu hình siêu tham số
│   ├── sea.rs              # Struct Sea — orchestrator trung tâm
│   │
│   ├── animal/
│   │   ├── crab.rs         # Tokenizer ký tự (char ↔ Endu)
│   │   ├── beaver.rs       # Model builder — build model từ Config & Crab
│   │   ├── owl/            # CLI controller (REPL)
│   │   │   ├── mod.rs      # Struct Owl — vòng lặp lệnh
│   │   │   ├── eyes.rs     # Đọc input từ stdin
│   │   │   ├── fur.rs      # Hằng số màu ANSI
│   │   │   ├── guide.rs    # In hướng dẫn help
│   │   │   └── owl_action.rs # Enum OwlC — các lệnh CLI
│   │   └── shrimp/         # Serialize / Deserialize (lưu tải model)
│   │       ├── mod.rs
│   │       ├── writer.rs   # ShrimpW — ghi binary
│   │       └── reader.rs   # ShrimpR — đọc binary
│   │
│   ├── slm/
│   │   ├── decoder.rs      # Hàm tiện ích lấy context/label từ chuỗi
│   │   ├── tensor_math.rs  # Các phép toán tensor: softmax, tanh, one-hot, ...
│   │   └── jelly_fish/     # Struct Model — mô hình ngôn ngữ
│   │       ├── mod.rs      # Định nghĩa Model, active_a_layer
│   │       ├── default.rs  # Khởi tạo Model & embedding ngẫu nhiên
│   │       ├── generate.rs # Sinh văn bản
│   │       ├── train.rs    # Huấn luyện (forward + backward + update)
│   │       ├── vocab_update.rs # Cập nhật embedding theo gradient
│   │       └── config.rs   # Giao tiếp Model ↔ Config
│   │
│   └── utils/
│       ├── matrix.rs       # Các phép toán ma trận thuần túy
│       └── file_reader.rs  # Đọc file văn bản
│
├── tests/
│   ├── crab_test.rs        # Unit tests cho Crab tokenizer
│   ├── decode_test.rs      # Unit tests cho decoder
│   ├── matrix_test.rs      # Unit tests cho matrix operations
│   └── saveload_test.rs    # Integration tests cho Shrimp save/load
│
└── resources/
    └── note.txt            # Văn bản tiếng Việt mẫu (lịch sử / mèo)

Các module

interfaces.rs

Định nghĩa tất cả type aliases dùng chung xuyên suốt dự án.

pub type Prof       = f32;               // Kiểu số thực (xác suất, trọng số)
pub type Endu       = u16;               // Mã số nguyên của một ký tự
pub type Data       = Vec<char>;         // Chuỗi ký tự thô
pub type EncodedVec = Vec<Endu>;         // Chuỗi đã mã hóa
pub type Tensor1D   = Vec<Prof>;         // Vector 1 chiều
pub type Matrix     = Vec<Tensor1D>;     // Ma trận 2D
pub type Layer      = (Matrix, Matrix);  // (trọng số W, bias B) của 1 lớp
pub type Dpcontext  = (Layer, Layer, Matrix, Matrix); // Gradient backward pass

Nguyên tắc: Tất cả module chỉ giao tiếp qua các type này — không phụ thuộc trực tiếp vào cấu trúc nội bộ của nhau.


config.rs

Config chứa toàn bộ siêu tham số của mô hình. Được tạo với giá trị mặc định và có thể điều chỉnh qua lệnh set của CLI trước khi build.

Trường Mặc định Setter
layer_node 64 set_layer_node
mem_ctx_char 4 set_mem_ctx_char
dimention 4 set_dimention
scale 0.1 set_scale
learning_rate 0.01 set_learning_rate
context_length 16 (tự tính: mem × dim)
respond_length 100 set_respond_length

sea.rs — Orchestrator

Sea là trung tâm điều phối — nắm giữ Crab, ModelBeaver, đồng thời cung cấp các API cấp cao cho Owl gọi tới.

Method Mô tả
Sea::new() Khởi tạo Sea với Crab rỗng và chưa có model
crab_eating(text) Nạp văn bản vào Crab (cập nhật từ điển)
build() Tạo Model từ cấu hình Beaver và từ điển Crab hiện tại
jelly_thinking(s) Sinh văn bản từ chuỗi đầu vào
jelly_learning(s) Huấn luyện model trên chuỗi văn bản
save(path) Lưu Crab + Model ra file nhị phân qua ShrimpW
load(path) Tải Crab + Model từ file nhị phân qua ShrimpR

animal/crab — Tokenizer

File: src/animal/crab.rs

Crab là tokenizer cấp ký tự. Duy trì bảng tra hai chiều char ↔ Endu với Endu tự tăng theo thứ tự gặp lần đầu.

Method Mô tả
Crab::new() Tạo tokenizer rỗng
eat_one(char) Thêm 1 ký tự vào từ điển (idempotent)
eat_all(&str) -> EncodedVec Tokenize toàn bộ chuỗi, trả về chuỗi mã số
to_endu(&char) -> Option<Endu> Chuyển ký tự → mã số
to_char(&Endu) -> Option<char> Chuyển mã số → ký tự
display(EncodedVec) In chuỗi mã số ra văn bản gốc
size() -> usize Số ký tự duy nhất trong từ điển

animal/beaver — Model Builder

File: src/animal/beaver.rs

Beaver giữ Config và tạo Model khi được lệnh. Nhận các lệnh set từ CLI để cập nhật cấu hình trước khi build.

Method Mô tả
Beaver::new() Tạo builder với Config mặc định
build(&Crab) -> Model Tạo Model mới (embedding + 2 lớp MLP ngẫu nhiên)
beaverf(key, f32) Đặt tham số float (scale, rate)
beavern(key, usize) Đặt tham số nguyên (dim, mem, layer)
display() In cấu hình hiện tại ra console

animal/owl — CLI Controller

Owl là vòng lặp REPL với 2 trạng thái: SETUP (chưa có model) và MODEL (đã có model).

Enum OwlC — các lệnh trả về từ vòng lặp:

BeaverDisplay          // show — hiển thị cấu hình
CfgF(key, f32)         // set scale/rate <value>
CfgN(key, usize)       // set dim/mem/layer <value>
Eat(text)              // import <path> — nạp văn bản
Load(path)             // load <path> — tải model
Build                  // build — tạo model mới
Input(text)            // gen <text> — sinh văn bản
Train(text)            // train <path> — huấn luyện
Save(path)             // save <path> — lưu model
Exit                   // exit

Sub-modules:

  • eyes.rsEyes<R>: wrapper đọc token/dòng từ stdin
  • fur.rs — Hằng số màu ANSI (RED, GREEN, CYAN, ...)
  • guide.rs — In hướng dẫn help cho từng trạng thái

animal/shrimp — Save / Load

Serialize/Deserialize mô hình ra file nhị phân tùy chỉnh (không dùng thư viện ngoài).

ShrimpW (Writer):

Method Mô tả
ShrimpW::new(path) Mở file để ghi
crab(&Crab) Ghi từ điển Crab
model(&Model) Ghi toàn bộ Model (emb + 2 lớp + config)
tensor(&Tensor1D) Ghi một vector
matrix(&Matrix) Ghi một ma trận
config(&Config) Ghi cấu hình

ShrimpR (Reader):

Method Mô tả
ShrimpR::new(path) Mở file để đọc
crab() Đọc và phục hồi Crab
model() Đọc và phục hồi Model
tensor() Đọc một vector
matrix() Đọc một ma trận
config() Đọc cấu hình

slm/jelly_fish — Model

Trái tim của dự án. Chứa embedding matrix và 2 lớp MLP.

pub struct Model {
    embedding : Matrix,  // [vocab_size × dim]
    layer1    : Layer,   // (W1, B1) — lớp ẩn
    layer2    : Layer,   // (W2, B2) — lớp output
    cfg       : Config,  // siêu tham số
}

Sub-modules:

File Chức năng
generate.rs generate(&ctx) -> EncodedVec — sinh respond_length ký tự
train.rs train(&data) -> Prof — 1 epoch, trả về loss trung bình
vocab_update.rs update_embedding(ctx, d_x) — cập nhật embedding
default.rs Model::new(emb, cfg), make_emb_mtx(size, dim, scale)
config.rs Wrapper getter Config từ Model

Backward pass:

z1 = W1·x + b1
h  = tanh(z1)
y  = W2·h + b2
p  = softmax(y)

dL/dy = p - one_hot(correct)
dW2   = hᵀ · dL/dy
dh    = dL/dy · W2ᵀ
dz1   = dh ⊙ tanh'(h)       (Hadamard product)
dW1   = xᵀ · dz1
dx    = dz1 · W1ᵀ           (dùng để update embedding)

utils — Tiện ích

matrix.rs

Thư viện ma trận thuần Rust, không dependency ngoài.

Hàm Mô tả
new_matrix(w, h, val) Tạo ma trận h×w với giá trị val
plus(A, B) -> Matrix Cộng từng phần tử
minus(A, B) -> Matrix Trừ từng phần tử
mul_n(A, n) -> Matrix Nhân vô hướng
hada(A, B) -> Matrix Tích Hadamard
multi(A, B) -> Matrix Nhân ma trận (cache-friendly: i→k→j)
transpose(A) -> Matrix Chuyển vị
lookup(m, row) Lấy 1 hàng của ma trận
tanh_deriv(h) -> Matrix Đạo hàm tanh: 1 - h²
shape(m) -> (usize, usize) Trả về (height, width)

file_reader.rs

Hàm Mô tả
file_reader(path) -> Option<String> Đọc file text, chuẩn hóa \r\n\n

CLI — Giao diện dòng lệnh

Chương trình chạy ở 2 trạng thái, được hiển thị trên prompt:

Trạng thái [SETUP] — chưa có model

Lệnh Mô tả
help In danh sách lệnh
show Hiển thị cấu hình hiện tại
set scale <float> Đặt hệ số khởi tạo trọng số
set rate <float> Đặt learning rate
set dim <int> Đặt số chiều embedding
set mem <int> Đặt số ký tự ngữ cảnh
set layer <int> Đặt số neuron lớp ẩn
import <path> Nạp file văn bản vào từ điển (có thể gọi nhiều lần)
build Tạo model mới → chuyển sang trạng thái MODEL
load <path> Tải model từ file → chuyển sang trạng thái MODEL
exit Thoát chương trình

Trạng thái [MODEL] — đã có model

Lệnh Mô tả
help In danh sách lệnh
gen <text> Sinh văn bản tiếp nối từ chuỗi đầu vào
train <path> Huấn luyện model trên file văn bản, in loss
save <path> Lưu model + từ điển ra file nhị phân
exit Quay về trạng thái SETUP

Ví dụ phiên làm việc:

WELCOME USER
type "help" to see more!

:: [SETUP] show
|---Current config:--*
|> Node's number layer 1: 64
|> Char's length memory : 4
|> Dimention per char   : 4
|> Scale when creating  : 0.1
|> Learning rate        : 0.01
|-------------------*

:: [SETUP] set layer 128
:: [SETUP] set rate 0.005
:: [SETUP] import resources/note.txt
:: [SETUP] build
**
Model created
**
:: [MODEL] gen Mèo là
Mèo là ...(sinh tiếp 100 ký tự)
:: [MODEL] train resources/note.txt
 Trained , new expected LOSS: 2.3417
:: [MODEL] save mymodel
:: [MODEL] exit
:: [SETUP] exit

Luồng hoạt động

main()
 │
 ├─ Owl::new()                     ← khởi tạo CLI controller
 ├─ Sea::new()                     ← khởi tạo orchestrator
 │
 └─ loop:
      cmd = owl.big_loop()         ← đọc & parse lệnh từ stdin
      │
      ├─ [SETUP] show    → sea.beaver.display()
      ├─ [SETUP] set     → sea.beaver.beaverf/beavern(k, v)
      ├─ [SETUP] import  → sea.crab_eating(text)
      ├─ [SETUP] build   → sea.build() → owl.set_state(true)
      ├─ [SETUP] load    → sea.load(path) → owl.set_state(true)
      │
      ├─ [MODEL] gen     → sea.jelly_thinking(text)
      ├─ [MODEL] train   → sea.jelly_learning(text)
      ├─ [MODEL] save    → sea.save(path)
      └─ [MODEL] exit    → owl.set_state(false) → quay về SETUP

Cài đặt và chạy

Yêu cầu: Rust toolchain (1.85+ do dùng edition = "2024")

# Clone dự án
git clone <repo-url>
cd small_language_model

# Chạy (debug)
cargo run

# Chạy tối ưu tốc độ (khuyến nghị khi huấn luyện)
cargo run --release

Chạy Tests

# Chạy toàn bộ tests
cargo test

## Cấu hình siêu tham số

Tất cả siêu tham số được quản lý trong `src/config.rs` và có thể chỉnh qua CLI lệnh `set` **trước khi** `build`. Sau khi build, cần tải lại model để thay đổi cấu hình.

```rust
Config::new() {
    layer_node:     64,   // Số neuron lớp ẩn
    mem_ctx_char:   4,    // Số ký tự ngữ cảnh
    dimention:      4,    // Chiều embedding
    context_length: 16,   // = mem × dim (tự tính)
    scale:          0.1,  // Hệ số khởi tạo trọng số
    learning_rate:  0.01, // Learning rate SGD
    respond_length: 100,  // Độ dài văn bản sinh ra
}

Dự án được xây dựng tại EIU — mục tiêu học thuật, tự hiện thực hóa backprop từ đầu.

About

A tool allow train Ai from blank without depdencies.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages