---
url: https://docs.nemo12.com/reference/models.md
description: >-
  Model Reference: phân biệt computed model với loại model còn lại và liệt kê
  mọi model của Nemo12 để tránh nhầm lẫn.
---

# Model Reference

Nemo12 có **hai loại "model"** và trộn lẫn chúng là nguồn gốc của rất nhiều nhầm lẫn:

| Loại | Là gì | Ví dụ | Ai sinh ra |
| --- | --- | --- | --- |
| **Computed model** | Kết quả một engine chạy trên dữ liệu thô. Có version, có hash, có lịch sử. | Learner Model, Goal Model, Readiness Model | [Engine](engines.md) |
| **Declared model** | Dữ liệu do người khai. Không có engine, không tự đổi. | Student Portrait, Parent Belief, Exam Target | Người dùng |

Computed model **không bao giờ được sửa tay**; declared model **không bao giờ bị engine ghi đè**. Đây là ranh giới cứng của SDD-002.

## 1. Bảng tổng — computed models

Danh sách chuẩn nằm ở `MODEL_KINDS` (`workers/api/src/shared/runlog.ts`) — thêm model mới phải thêm vào đây trước.

| Model | `model_kind` | Version hiện tại | Engine | Trạng thái |
| --- | --- | --- | --- | --- |
| Learner Model | `learner` | `learner-v2` | [Learner Model Engine](engines.md#3-learner-model-engine) | ✅ chạy |
| Learner Context Model | `context` | `context-v1` | [Context Engine](engines.md#4-context-engine) | ✅ chạy |
| Goal Model | `goal` | `goal-v1` | [Goal Engine](engines.md#2-goal-engine) | ✅ chạy |
| Readiness Model | `readiness` | `readiness-v1` | [Readiness Engine](engines.md#5-readiness-engine) | ✅ chạy |
| Retention Model | `retention` | `retention-v1` | [Retention Engine](engines.md#6-retention-engine) | ✅ chạy — trạng thái sống ở bảng riêng + snapshot hằng ngày qua [WF-17](workflows.md#5-wf-17--retention-refresh-scheduled). Trang riêng: [retention-model](retention-model.md) |
| Constraint Model | `constraint` | `constraint-v1` | [constraint-model](constraint-model.md) | ✅ chạy |
| Learning Plan Model | `learning_plan` | `plan-v1` | [learning-plan-model](learning-plan-model.md) | ✅ chạy |
| Recommendation Model | `recommendation` | `recommendation-v1` | [recommendation-engine](recommendation-engine.md) | ✅ chạy |

### Cơ chế versioning dùng chung

Mọi computed model đi qua `saveModelVersion()` và tuân đúng một luật:

```
content → JSON.stringify → SHA-256 → so với version active gần nhất
  hash TRÙNG   → KHÔNG tạo version mới (changed: false)
  hash KHÁC    → version += 1, bản cũ chuyển state='superseded', bản mới state='active'
```

Hệ quả quan trọng: **"engine đã chạy" và "model đã đổi" là hai câu hỏi khác nhau.** Engine chạy 100 lần mà dữ liệu không đổi thì có 100 dòng `engine_runs` nhưng vẫn chỉ 1 version. Đây là điều kiện để trả lời được "vì sao hôm nay hệ thống khuyên khác hôm qua".

Lưu tại [`learner_model_versions`](data-dictionary.md) — mỗi dòng có `content_json`, `content_hash`, `algorithm_version`, `trigger`, `engine_run_id`, `workflow_run_id`, `evidence_cutoff`.

***

## 2. Learner Model (`learner-v2`)

> "Học sinh này đang ở đâu về mặt học thuật?"

> 📄 **Trang riêng, mô tả đầy đủ: [learner-model.md](learner-model.md)** — vì sao không phải nơi lưu mastery, hai đường cập nhật (WF-04 và theo từng câu trả lời), 7 model lõi.

**Nguồn vào**: `learner_skill_state` (mọi node đã có bằng chứng) + tổng hợp `learner_evidence` + hồ sơ `learners`.

**Cấu trúc output**:

```jsonc
{
  "algorithm_version": "learner-v2",
  "computed_at": "2026-08-14T…",
  "profile": { "grade": 8, "current_school": "…", "province": "…" },
  "academic_state": {
    "nodes_tracked": 154,
    "subjects": [{
      "subject_id": "math",
      "nodes_total": 210, "coverage": 0.2,   // SRC-528: coverage ≠ mastery — mẫu số là CẢ graph
      "nodes_assessed": 42, "nodes_mastered": 18,
      "avg_mastery": 0.61, "avg_confidence": 0.72,
      "trajectory": { "improving": 12, "stable": 25, "declining": 5 },
      "strengths": [ /* top 5 node theo mastery */ ],
      "gaps":      [ /* bottom 5 node theo mastery */ ],
      "last_evidence_at": "…"
    }]
  },
  "evidence": {                          // SRC-528: State + Evidence — claim phải kèm hồ sơ bằng chứng
    "total": 318, "avg_reliability": 0.87,
    "first_evidence_at": "…", "last_evidence_at": "…",
    "distinct_sources": 3, "distinct_types": 4,
    "by_type": { "item_response": 290, "self_prediction": 28 }
  },
  "behavior": {                          // SRC-528: cách learner LÀM — chỉ đổi khi có hành vi mới
    "sessions_total": 40, "sessions_completed": 33, "sessions_abandoned": 7,
    "completion_rate": 0.83, "responses_timed": 310, "avg_response_ms": 18700
  },
  "goals_summary": { "goal_model_version": 4, /* …tóm tắt từ Goal Model */ },
  "confidence": 0.83
}
```

**Ba điều dễ hiểu sai:**

1. `confidence` ở cấp model = `1 − 0.9^(số evidence)` — **chỉ đo lượng bằng chứng**, không đo học sinh giỏi hay dốt. 0 evidence → confidence 0, và khi đó mọi con số khác đều là phỏng đoán.
2. `goals_summary` là **tham chiếu** sang Goal Model, không phải bản sao. Goal chỉ có một nguồn sự thật.
3. `strengths`/`gaps` chỉ tính trên node **đã có evidence** (`evidence_count > 0`) — node chưa đo không bao giờ bị gọi là "điểm yếu".

**Đồng bộ ngược**: khi có version mới, bảng gốc `learner_models` (từ migration 0003) cũng được cập nhật để giữ tương thích.

***

## 3. Learner Context Model (`context-v1`)

> "Bối cảnh ngắn hạn quanh học sinh này là gì?"

> 📄 **Trang riêng, mô tả đầy đủ: [learner-context-model.md](learner-context-model.md)** — ba tầng dễ nhầm, confidence = độ đầy bức tranh, hai chỗ trống (context events, capacity).

**Nguồn vào**: `learner_context_models` (row do onboarding ghi) + `school_enrollments` + `learners` + goal đang urgent nhất.

```jsonc
{
  "active_school_code": "turtle",
  "enrollments": [{ "school_code": "turtle", "status": "active" }],
  "current_grade": 8, "current_school": "…", "province": "…",
  "active_goal_ref": { "goal_id": "…", "title": "…", "kind": "…", "deadline": "…", "horizon": "operational", "urgency": 0.77 },
  "goal_blueprint_id": "…",
  "capacity": { "available_minutes_per_week": 180, "energy": "medium" },
  "context_events": []
}
```

**Luật**: goal và deadline **không phải dữ liệu gốc** ở đây — chỉ `active_goal_ref`. Nếu cần biết mục tiêu đầy đủ thì đọc Goal Model.

`capacity` đang tạm trú ở đây cho tới khi Constraint Model ra đời (Q-096). `context_events` là chỗ dành sẵn cho Context Event Registry (Phase 2).

***

## 4. Goal Model (`goal-v1`)

> "Học sinh này đang cố đạt điều gì, và cái nào gấp hơn?"

> 📄 **Trang riêng, mô tả đầy đủ: [goal-model.md](goal-model.md)** — 6 bước của engine, confidence theo nguồn gốc goal, projection idempotent, ai đọc goal.

Xem thuật toán đầy đủ tại [Goal Engine](engines.md#2-goal-engine). Model gồm `goals[]` (cây có `parent_key`), `conflicts[]`, và `summary`.

**Được phép RỖNG.** `summary.empty = true` là trạng thái hợp lệ, không phải lỗi (REQ-ONB-05, RISK-009). Hệ thống **không bịa mục tiêu** cho học sinh chưa khai.

Mỗi goal có `horizon` (`operational` ≤14 ngày · `tactical` ≤90 · `strategic` xa hơn · `undated`) và `urgency` 0–1. Xem [state machines](state-machines.md#goal).

**Projection**: model được chiếu xuống bảng `learner_goal_entries`, idempotent theo `(origin_kind, origin_id)` — goal biến mất khỏi model thì bản ghi chuyển `status='dropped'`, không xóa.

***

## 5. Readiness Model (`readiness-v1`)

> "Nếu thi **cái đích cụ thể này** hôm nay thì sao?"

> 📄 **Trang riêng, mô tả đầy đủ: [readiness-model.md](readiness-model.md)** — thuật toán, confidence có trọng số, hai đường tính readiness, study mode.

Readiness **luôn gắn với một Target** (một blueprint). Không có "readiness chung chung" — đó là mastery.

```jsonc
{
  "targets": [{
    "blueprint_id": "…", "title": "…", "subject_id": "math",
    "score": 0.68,                  // tỷ lệ trọng số đã đạt
    "estimated_score": 6.8, "cut_score": 5, "max_score": 10, "on_track": true,
    "gap_map": [{ "node_id": "…", "required": 0.8, "current": 0.35, "gap": 0.45, "severity": "critical" }],
    "largest_uncertainty": [{ "node_id": "…", "weight": 3, "confidence": 0.12 }],
    "next_assessment_priority": ["…"]
  }],
  "summary": { "targets": 2, "best": 0.68, "on_track": 1, "empty": false }
}
```

`largest_uncertainty` là điểm đặc biệt: node **quan trọng nhưng chưa đo chắc** → Readiness **sinh ra nhu cầu đo**, chứ không chỉ báo cáo. Đây là đầu vào cho việc chọn bài kiểm tra kế tiếp.

***

## 6. Retention Model (`retention-v1`)

> "Học sinh **còn nhớ** cái đã từng vững không?"

Luật gốc của SDD-017: **Mastery ≠ Retention**. Retention Engine **không bao giờ** ghi vào `learner_skill_state.mastery`. Đã học được thì mãi mãi đã học được; cái phai đi là khả năng truy xuất.

Trạng thái sống lưu ở bảng riêng `learner_retention`, tính **lazy**: decay tính lúc đọc, đường evidence chỉ ghi khi có bằng chứng mới (Q-113). Snapshot theo version do **WF-17** sinh hằng ngày qua cron.

| Trường | Ý nghĩa |
| --- | --- |
| `historical_mastery` | Đỉnh cao nhất từng đạt — chỉ tăng |
| `current_retention` | R(t), xác suất truy xuất thành công lúc này |
| `retention_confidence` | Độ tin của **ước lượng**, không phải của trí nhớ |
| `stability_days` | S — trí nhớ này bền bao lâu; retrieval thành công làm S tăng |
| `retrieval_count` / `successful_retrieval_count` | Số lần thử / số lần đúng |
| `last_exposure_at` / `last_successful_retrieval_at` / `last_strong_evidence_at` | Ba mốc thời gian tách biệt |

Node **chưa từng vững** (`historical_mastery < 0.6`) **không thuộc bức tranh trí nhớ** — nó thuộc đường học. Quên ≠ chưa học bao giờ.

***

## 7. Parent Model (declared)

> 📄 **Trang riêng, mô tả đầy đủ: [parent-model.md](parent-model.md)** — cơ chế cập nhật, đối chiếu niềm tin ↔ thực tế, WF-12 parent recommendation.

Không có engine. Gồm hai dòng dữ liệu do phụ huynh khai, giữ **toàn bộ lịch sử** để đối chiếu với ước tính hệ thống:

| Bảng | Nội dung | Vì sao giữ lịch sử |
| --- | --- | --- |
| `parent_beliefs` | Niềm tin định kỳ theo môn: `worry_level`, `perceived_state`, `predicted_score`, `will_pass` | So "bố mẹ nghĩ con được 7" với ước tính hệ thống → phát hiện lệch nhận thức |
| `interactions` (`author_role='guardian'`) | Quan sát tự do của phụ huynh | Bằng chứng ngữ cảnh mà hệ thống không tự thấy được |

Mỗi lần khai là **một dòng mới**, không update đè.

***

## 8. Student Portrait (declared)

> 📄 **Trang riêng, mô tả đầy đủ: [student-portrait.md](student-portrait.md)** — 6 bảng, quyền chặt hơn chuẩn, hai cột (bố mẹ / con), alignment.

SDD-015. Bức tranh tương lai do **phụ huynh** vẽ (tối đa 3 active/parent/learner), learner **luôn được xem** và phản ứng (`agree`/`unsure`/`disagree`).

Portrait là **aspiration input**, **không override Recommendation Engine**. Ước mơ của bố mẹ không được phép trở thành lệnh cho hệ thống dạy học.

Gồm: portrait → tracks (lộ trình dài) → milestones → external activities. Preference của parent và learner **lưu riêng**, không gộp (cũng như [Whale preferences](../architecture/sdd-011-school-models.md)).

***

## 9. Model nào đọc model nào

```
Evidence ──▶ learner_skill_state ──┬──▶ Learner Model ──▶ (views, báo cáo)
                                   ├──▶ Readiness Model ──▶ gap map, next assessment
                                   └──▶ Retention Model ──▶ review queue

Declarations (exam target, lịch thi, enrollment) ──▶ Goal Model ──┬──▶ Context Model (ref)
                                                                  ├──▶ Learner Model (summary ref)
                                                                  └──▶ Readiness Model (chọn target)
```

Thứ tự chạy **bắt buộc** là Goal → Context → Learner → Readiness, vì ba model sau đều tham chiếu Goal. Xem [WF-04](workflows.md#wf-04--evidence--model-update).

## Trace

* REQ-INT-16 (Goal), REQ-INT-23..28 (Retention), REQ-POR-01..08 (Portrait), REQ-PAR-05 (observation).
* Thiết kế: [SDD-002](../architecture/sdd-002-learner-intelligence/models-and-engines.md) §2/§3/§16/§17, [SDD-015](../architecture/sdd-015-student-portrait.md), [SDD-017](../architecture/sdd-017-retention.md).
* Kiểm chứng: QG-005.
