Skip to content

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ạiLà gìVí dụAi sinh ra
Computed modelKế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 ModelEngine
Declared modelDữ liệu do người khai. Không có engine, không tự đổi.Student Portrait, Parent Belief, Exam TargetNgườ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.

Modelmodel_kindVersion hiện tạiEngineTrạng thái
Learner Modellearnerlearner-v2Learner Model Engine✅ chạy
Learner Context Modelcontextcontext-v1Context Engine✅ chạy
Goal Modelgoalgoal-v1Goal Engine✅ chạy
Readiness Modelreadinessreadiness-v1Readiness Engine✅ chạy
Retention Modelretentionretention-v1Retention 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 Modelconstraintconstraint-v1constraint-model✅ chạy
Learning Plan Modellearning_planplan-v1learning-plan-model✅ chạy
Recommendation Modelrecommendationrecommendation-v1recommendation-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:

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 — 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 — 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.

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_retentionR(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_daysS — trí nhớ này bền bao lâu; retrieval thành công làm S tăng
retrieval_count / successful_retrieval_countSố lần thử / số lần đúng
last_exposure_at / last_successful_retrieval_at / last_strong_evidence_atBa 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ảngNội dungVì sao giữ lịch sử
parent_beliefsNiềm tin định kỳ theo môn: worry_level, perceived_state, predicted_score, will_passSo "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ụ huynhBằ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.

Trace ​

  • REQ-INT-16 (Goal), REQ-INT-23..28 (Retention), REQ-POR-01..08 (Portrait), REQ-PAR-05 (observation).
  • Thiết kế: SDD-002 §2/§3/§16/§17, SDD-015, SDD-017.
  • Kiểm chứng: QG-005.