---
url: https://docs.nemo12.com/reference/learner-context-model.md
description: >-
  Learner Context Model: bối cảnh quanh học sinh gồm trường, school, thời gian
  và mục tiêu, cơ chế cập nhật và cách dùng.
---

# Learner Context Model

> "Bối cảnh quanh học sinh này là gì?" — em đang học trường nào, ở school nào, có bao nhiêu thời gian, đang nhắm mục tiêu nào.

Thiết kế: [SDD-002](../architecture/sdd-002-learner-intelligence/models-and-engines.md) §3, [SDD-007](../architecture/sdd-007-learner-orchestration.md) §6 · Code: `modules/models/service.ts` → `runContextEngine()` · Bảng nguồn: `learner_context_models` (0003) · Snapshot: `learner_model_versions` (`model_kind='context'`)

***

## 1. Context trả lời câu mà Learner Model không trả lời

[Learner Model](learner-model.md) biết đứa trẻ **học tới đâu**. Context Model biết đứa trẻ **đang sống trong hoàn cảnh nào**.

Cùng một mastery 0.6 ở Đại số nghĩa hoàn toàn khác nhau nếu:

* em học lớp 8 vs lớp 10,
* em vào Turtle (nền tảng) vs Shark (thi chuyên),
* em có 300 phút/tuần vs 60 phút/tuần.

Không có Context, mọi khuyến nghị đều là lời khuyên chung chung cho một học sinh trung bình không tồn tại.

## 2. Ba tầng dễ nhầm nhau

| Tên | Là gì | Có version |
| --- | --- | --- |
| `learner_context_models` | **Bảng** — dữ liệu thô do onboarding ghi. 1 dòng/learner | ❌ |
| **Context Model** | **Snapshot** do Context Engine sinh, gom thêm enrollment + goal ref | ✅ |
| `learner_context_events` | **Lời khai theo thời điểm** — "con ốm", "tuần này bận" (migration 0030) | ❌ |

Bảng chứa cái **ổn định** (lớp, trường, school). Context event chứa cái **nhất thời** (ốm, bận, sắp thi). Model là bức ảnh gộp lại.

***

## 3. Model chứa gì

```jsonc
{
  "algorithm_version": "context-v1",
  "computed_at": "2026-08-15T…",
  "confidence": 0.83,
  "active_school_code": "turtle",
  "enrollments": [{ "school_code": "turtle", "status": "active" }],
  "current_grade": 8,
  "current_school": "THCS …",
  "province": "Hà Nội",
  "active_goal_ref": {
    "goal_id": "…", "title": "Thi học kỳ 1 — Toán",
    "kind": "semester_exam", "deadline": "2026-09-20",
    "horizon": "operational", "urgency": 0.77
  },
  "goal_blueprint_id": "…",
  "capacity": { "available_minutes_per_week": 180, "energy": "medium" },
  "context_events": []
}
```

### `active_goal_ref` — tham chiếu, không phải dữ liệu gốc

```sql
SELECT id, title, kind, deadline, horizon, urgency FROM learner_goal_entries
WHERE learner_id=?1 AND status='active' ORDER BY urgency DESC, priority ASC LIMIT 1
```

Đúng một goal — goal **gấp nhất**. Và đây chỉ là **con trỏ**: SDD-002 §3 cấm goal/deadline làm dữ liệu gốc ở đây. Cần mục tiêu đầy đủ thì đọc [Goal Model](goal-model.md).

Vì sao cứng rắn: deadline xuất hiện ở hai bảng là bảo đảm sẽ có ngày chúng lệch nhau, và không ai biết bên nào đúng. Một nguồn sự thật, mọi nơi khác trỏ về.

### Fallback hai tầng

```ts
current_grade:  row?.current_grade  ?? learner?.grade  ?? null
current_school: row?.current_school ?? learner?.current_school ?? null
```

Ưu tiên bảng context (do onboarding ghi cho **school đang active**), rồi mới tới hồ sơ chung. Một đứa trẻ có thể học lớp 8 ở trường nhưng vào Shark để luyện đề lớp 9 — context của school thắng.

### Confidence = tỷ lệ ô đã biết

```ts
const known = [grade, school, province, activeGoal, available_minutes_per_week, có enrollment];
confidence = số ô != null / 6
```

Không phải xác suất — là **độ đầy của bức tranh** (AS-05.5.4). Context toàn ô trống thì Planning **không được** coi nó như sự thật.

| confidence | Nghĩa |
| --- | --- |
| 1.0 | Biết đủ 6 ô — kế hoạch cá nhân hoá được |
| 0.5 | Biết một nửa — kế hoạch còn đoán |
| 0.17 | Gần như chỉ biết em tồn tại |

***

## 4. Cơ chế CẬP NHẬT

### 4.1 Ai ghi bảng nguồn

Chỉ **một** chỗ: `modules/onboarding/routes.ts` (~341), khi learner chọn school / khai hồ sơ. Không engine nào ghi vào `learner_context_models` — engine chỉ **đọc**.

`available_minutes_per_week` và `energy` cũng nằm ở bảng này, nhưng đó là **chỗ trú tạm** cho tới khi [Constraint Model](models.md) nhận (Q-096) — xem §6.

### 4.2 Engine chạy khi nào

[WF-04 step 2](workflows.md#4-step-thứ-tự-bắt-buộc) — **sau Goal, trước Learner Model**. Thứ tự bắt buộc vì Context cần goal urgent nhất để dựng `active_goal_ref`.

Trigger: `AssessmentCompleted`, `GoalChanged`, `EXAM_RESCHEDULED`, `admin_recompute`.

::: warning Context **không** nằm trong đường cập nhật nhẹ
[Đường theo từng câu trả lời](learner-model.md#32-đường-nhẹ-cập-nhật-theo-từng-câu-trả-lời-src-130) chỉ chạy Learner Model + Readiness. Context không đổi vì một câu trả lời — trường học, lớp, school, quỹ thời gian đều không phụ thuộc vào việc em vừa làm đúng hay sai.

Nhưng `active_goal_ref.urgency` và `horizon` **phụ thuộc thời gian** (tính trong Goal Engine). Một goal `tactical` hôm nay thành `operational` sau vài tuần mà không có gì kích hoạt tính lại — cùng khoảng trống với [Goal Model](goal-model.md#5-trigger--khi-nào-model-được-tính-lại).
:::

***

## 5. Cách DÙNG

| Nơi | Đọc gì | Để làm gì |
| --- | --- | --- |
| [Readiness Engine](readiness-model.md#blueprint-nào-được-chấm--ba-nguồn) | `goal_blueprint_id` | một trong 3 nguồn chọn target |
| [Goal Engine](goal-model.md) | `goal_blueprint_id` | dựng goal nền từ enrollment |
| Planning Engine | `available_minutes_per_week`, `energy` | chia việc vừa quỹ thời gian |
| Constraint Engine | capacity | tách thành model riêng |
| Onboarding | `active_school_code` | biết learner đang ở school nào |

Vòng phụ thuộc đáng chú ý: Goal Engine đọc `goal_blueprint_id` **từ bảng**, còn Context Model đọc goal **từ `learner_goal_entries`**. Không phải vòng lặp vô hạn vì hai bên đọc hai nguồn khác nhau — nhưng đó là lý do thứ tự Goal → Context trong WF-04 không được đảo.

***

## 6. Hai chỗ trống trong model

### 6.1 `context_events: []` — luôn rỗng

```ts
context_events: [] as unknown[], // Context Event Registry (§5b) — Phase 2.
```

Nhưng bảng `learner_context_events` (migration 0030) **đã có và đang chạy thật**: `POST/GET /v1/learners/{id}/context-events`, 8 loại (`time_budget`, `illness`, `exam_soon`, `busy`, `stress`, `motivation`, `focus_subject`, `other`), và **Planning Engine đọc trực tiếp** qua `activeContextEvents()`.

Nghĩa là: context event **đang được dùng**, nhưng **chưa được gộp vào Context Model snapshot**. Hệ quả thực tế — đọc lại một version cũ của Context Model sẽ **không** thấy "hôm đó con đang ốm", dù thông tin ấy có ảnh hưởng tới kế hoạch hôm đó.

Đây là khoảng trống có thật, ghi ra để không ai tưởng model đã đầy đủ.

### 6.2 `capacity` đang trú tạm

`available_minutes_per_week` và `energy` nằm trong Context Model, nhưng **Constraint Model đã tồn tại** (`modules/models/constraint.ts`, `constraint-v1`) và đó mới là chỗ đúng của chúng (Q-096).

Constraint Model có `capacity.source` phân biệt `learner_declaration` vs `unknown` — chính là thứ Context Model không có. Hôm nay hai model cùng nói về quỹ thời gian; hợp nhất là việc còn lại.

***

## 7. Bất biến — vi phạm là bug

1. Goal/deadline **không** là dữ liệu gốc ở đây — chỉ `active_goal_ref`.
2. Engine **chỉ đọc** `learner_context_models`; chỉ onboarding được ghi.
3. Chạy **sau Goal**, **trước Learner Model** trong WF-04.
4. `confidence` phản ánh **độ đầy** của bức tranh, không phải chất lượng học sinh.
5. Context **không** nằm trong đường cập nhật theo từng câu trả lời.
6. Fallback hai tầng: context của school thắng hồ sơ chung.

## 8. Khoảng trống đã biết

| Việc | Trạng thái |
| --- | --- |
| Gộp `learner_context_events` vào snapshot | ⏳ §6.1 — hiện Planning đọc thẳng bảng |
| Chuyển `capacity` sang Constraint Model | ⏳ §6.2 — Constraint Model đã chạy |
| Cron tính lại `active_goal_ref.horizon` theo thời gian | ⏳ chung với [Goal Model](goal-model.md#5-trigger--khi-nào-model-được-tính-lại) |
| `deadline` trong bảng `learner_context_models` | ⚠️ cột còn tồn tại nhưng engine **không đọc** — di sản, dễ gây hiểu nhầm là nguồn deadline |

## Trace

* REQ-PAR-14 (khai tự nhiên → Context Event), REQ-INT-29.
* Nguồn: SRC-032, SRC-105, SRC-130 · Q-096 (tách Constraint Model).
* Thiết kế: [SDD-002](../architecture/sdd-002-learner-intelligence/models-and-engines.md) §3/§5b, [SDD-007](../architecture/sdd-007-learner-orchestration.md) §6.
* Kiểm chứng: QG-005.
* Liên quan: [Learner Model](learner-model.md) · [Goal Model](goal-model.md) · [Readiness](readiness-model.md) · [Engines §4](engines.md#4-context-engine).
