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 |
| 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 | ✅ chạy |
| Learner Context Model | context | context-v1 | Context Engine | ✅ chạy |
| Goal Model | goal | goal-v1 | Goal Engine | ✅ chạy |
| Readiness Model | readiness | readiness-v1 | Readiness Engine | ✅ chạy |
| Retention Model | retention | retention-v1 | Retention Engine | ✅ chạy — trạng thái sống ở bảng riêng + snapshot hằng ngày qua WF-17. Trang riêng: retention-model |
| Constraint Model | constraint | constraint-v1 | constraint-model | ✅ chạy |
| Learning Plan Model | learning_plan | plan-v1 | learning-plan-model | ✅ chạy |
| Recommendation Model | recommendation | recommendation-v1 | recommendation-engine | ✅ 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 — 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 — 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:
{
"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:
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.goals_summarylà tham chiếu sang Goal Model, không phải bản sao. Goal chỉ có một nguồn sự thật.strengths/gapschỉ 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 — 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.
{
"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 — 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. 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.
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 — 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.
{
"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 — 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 — 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).
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.