Skip to content

Assessment Engine ​

Mọi con số về đứa trẻ trong hệ thống này đều bắt đầu từ đây. Đo sai thì mọi model phía sau đều sai theo — một cách âm thầm.

Thiết kế: SDD-002 §5/§18 · Code: modules/knowledge/routes.ts (chẩn đoán) · modules/learning/routes.ts (đo mức vững, học vượt) · modules/exams/routes.ts (đề thi)


1. Bốn loại đo ​

LoạikindSố câuReliabilityCâu hỏi trả lời
Chẩn đoándiagnostic150.8 × attempt"Em đang ở đâu trên cả môn?"
Đo mức vữngmastery_check60.8 × attempt"Bài này em đã vững chưa?"
Học vượtmastery_check (skip)100.8 × attempt"Em có thể bỏ qua cả Unit này không?"
Đề thiexamcả đề0.85 cố định"Nếu thi thật thì được bao nhiêu?"

Đề thi có reliability cao nhất và cố định: bài thi có kiểm soát, làm liền mạch, không ngắt quãng — đáng tin hơn từng câu lẻ trong lúc học.


2. Chẩn đoán — cửa vào của mọi thứ ​

POST /v1/diagnostic/start → POST /v1/diagnostic/{sessionId}/submit

Cổng chặn: phải có Learner Model trước ​

ts
const model = await DB.prepare("SELECT version FROM learner_models WHERE learner_id=?1").first();
if (!model) return errorResponse(c, "CONFLICT", "Cần hoàn tất hồ sơ và khởi tạo Learner Model trước khi chẩn đoán");

REQ-ONB-04, WF-01 §4. Đo trước khi có hồ sơ thì không biết quy kết bằng chứng vào đâu, và không có ngữ cảnh (lớp mấy, school nào) để chọn câu cho đúng.

Chọn câu: 15 câu canonical, mỗi node một câu ​

sql
WHERE role='canonical' AND status='published'
GROUP BY node_id
ORDER BY grade, level LIMIT 15

GROUP BY node_id là điểm mấu chốt: chẩn đoán trải rộng, không đào sâu. 15 câu ở 15 node khác nhau cho bức tranh sơ bộ về cả môn; 15 câu ở 3 node thì chỉ biết 3 node.

Đổi lại, mỗi node chỉ có một bằng chứng → confidence sau chẩn đoán còn rất thấp. Đúng như thiết kế: chẩn đoán là bản đồ thô, không phải kết luận.

INSUFFICIENT_RELIABLE_EVIDENCE — chống rác cả phiên ​

timed.length >= 3  AND  (số câu < 2500ms) / timed.length >= 0.5
→ insufficient = true
→ reliability của MỌI câu bị ép xuống 0.05

Đây là biện pháp cấp phiên, khác với rapid-guess cấp câu (REQ-INT-22). Một đứa trẻ bấm bừa hết 15 câu trong 40 giây sẽ không bị ghi nhận là "yếu toàn bộ môn" — model chỉ ghi rằng chưa đo được gì.

Cờ evidence_reliability: "insufficient" trả về cùng cockpit để UI nói rõ đây chưa phải kết luận.

Không có lớp bảo vệ này, hậu quả là thật: một phiên bấm bừa sẽ đẩy mastery xuống, kéo readiness xuống, và Parent Recommendation sẽ báo với bố mẹ rằng con đang có lỗ hổng nghiêm trọng.

Có run log riêng ​

Chẩn đoán là workflow duy nhất ngoài WF-04/WF-15/WF-17 có run log đầy đủ: WF-03 Diagnosis, với step mastery_retention_update ghi lại responses / scored / nodes_updated / evidence_reliability.

Nộp xong → chạy WF-04 (trigger: AssessmentCompleted) → trả về cockpit luôn. Learner làm xong bài chẩn đoán là thấy ngay việc nên làm, không phải bấm thêm.


3. Đo mức vững & Học vượt ​

Dùng chung POST /v1/learners/{id}/practice/start với Learning Engine, khác ở kind.

Lấy đúng phần kho để dành ​

ưu tiên: câu để dành (phân loại/khó nhất)
rồi:     câu chưa gặp
cuối:    câu đã gặp

Ngược chiều hoàn toàn với luyện tập — đó là toàn bộ ý nghĩa của cơ chế reserve.

Học vượt: một bong bóng, và phải chờ 3 tiếng nếu trượt ​

ts
const SKIP_COOLDOWN_MS = 3 * 60 * 60 * 1000;

Lỗ hổng đã bịt (SRC-141): trước đây trượt rồi thi lại ngay, và đề ra y hệt 10 câu cũ — thử vài lần là thuộc đáp án rồi "vượt" cả unit mà không hề vững.

Hai lớp sửa:

  1. Đề xáo theo seed phiên → lần thi lại không bao giờ ra đúng đề cũ (có test khoá).
  2. Chờ 3 tiếng → lần thử sau là trí nhớ thật, không phải trí nhớ ngắn hạn.

Thông báo nói rõ đường đi thay thế, không để learner cụt hứng:

"Học vượt thử lại được sau 47 phút nữa. Trong lúc chờ, con cứ học đường thường — làm xong "Đo cuối" là mở unit sau."

check_available chỉ bật khi node có ≥ 6 câu (SRC-077): Assessment Experience chỉ mở khi đủ câu để đo cho ra kết luận.


4. Đề thi — chấm theo node, không theo câu ​

POST /v1/exams/{examId}/start → POST /v1/exam-attempts/{attemptId}/submit

Điểm khác biệt lớn nhất với ba loại trên: bằng chứng được gộp theo node trước khi vào model.

với mỗi câu:  correct → cộng points; ghi exam_attempt_answers
gộp theo node: performance   = số câu đúng / tổng câu của node đó
               difficulty    = trung bình difficulty các câu
một node → MỘT evidence với performance là PHÂN SỐ (0..1), không phải 0/1

Vì sao gộp: một đề hỏi 4 câu về "Hằng đẳng thức" thì đúng 3/4 là thông tin tốt hơn nhiều so với bốn bằng chứng nhị phân rời rạc. updateMastery() nhận performance = 0.75 và dịch chuyển đúng mức.

Retention thì vẫn cần nhị phân — quy ước: node đạt ≥ 70% trong đề coi là retrieval thành công (SDD-017 §4).

Đề miễn nhiễm với việc item gốc bị gỡ ​

Nội dung câu hỏi đã được sao vào exam_questions lúc dựng đề, nên item gốc bị gỡ không làm đề sai. Chỉ có difficulty là còn đọc từ items:

item_ref trỏ tới item đã lùi khỏi 'published'
  → difficulty về mức trung tính 0.5
  → console.warn("EXAM_ITEM_WITHDRAWN", { exam_id, question_id, item_ref, status })

Không còn tin hồ sơ chất lượng của item đó thì không dùng độ khó của nó để cân bằng chứng nữa — và kêu lên để Coral thấy đề nào đang trỏ vào câu đã gỡ.


5. Ba tầng chống rác đầu vào ​

Đây là phần đáng giá nhất của engine này. Ba tầng độc lập, áp cho cùng một mục tiêu: model không được tin vào dữ liệu không đáng tin.

TầngPhạm viCơ chếHậu quả
Câumột lần trả lờiattemptReliability() — < 2500 ms, chuỗi ≥3reliability 0.05, không tính là "đã đo"
Phiêncả bài chẩn đoán≥ 50% câu rapidreliability mọi câu ép về 0.05
Tự khaimột câujustification_kind: "guessed"hạ retention reliability, giữ nguyên mastery

Cộng thêm hai lớp bảo vệ nội dung:

  • Chỉ phát câu published — câu bị learner báo sai hoặc bị sàng lọc máy gắn cờ đã lùi về candidate và không tới tay đứa trẻ tiếp theo (AS-06.3.2, AS-10.4.1).
  • Câu bị gỡ giữa phiên: chấm tiếp nhưng không ghi evidence (Learning §5).

Và một lối thoát trung thực: "Chưa biết" (selected_index = -1) có reliability 0.7 — cao hơn hẳn đoán bừa. Nói thật là mình không biết là một hành động có giá trị đo, không phải bỏ cuộc.


6. Đường đi của một bằng chứng ​

Trả lời
  → attemptReliability()                    ← tầng chống rác
  → updateMastery()                         → learner_skill_state   (sự thật sống)
  → retentionStatementForEvidence()         → learner_retention     (trí nhớ, tách riêng)
  → DB.batch  [responses + evidence + skill_state + retention]      ← MỘT giao dịch
  → publishEvent("learner.evidence.recorded")
  → WF-04 (diagnostic/exam) hoặc updateLearnerModelInBackground (practice)

Gộp DB.batch là bắt buộc. Nếu evidence ghi được mà mastery hỏng, model sẽ vĩnh viễn tin rằng lần trả lời đó chưa từng xảy ra — và không có cách nào phát hiện.

Idempotency bám event_id (diag:{session}:{item}, practice:{session}:{item}, exam:{attempt}:{node}) với INSERT OR IGNORE. Client bấm nộp hai lần, mạng retry — bằng chứng chỉ vào một lần.


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

  1. Chẩn đoán chỉ chạy sau khi có Learner Model (REQ-ONB-04).
  2. Chẩn đoán trải rộng — mỗi node một câu, không đào sâu.
  3. ≥ 50% câu rapid → cả phiên bị hạ reliability, không ghi mastery thấp giả.
  4. Đo lấy câu để dành, luyện tập không đụng tới.
  5. Học vượt trượt → chờ 3 tiếng và đề phải khác.
  6. Đề thi gộp bằng chứng theo node, performance là phân số.
  7. Item gốc bị gỡ không làm sai đề — chỉ hạ difficulty về trung tính.
  8. Mọi bằng chứng vào DB trong một DB.batch, idempotent theo event_id.
  9. "Chưa biết" là lựa chọn hợp lệ, reliability 0.7.

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

ViệcTrạng thái
Adaptive item selection — chọn câu tiếp theo theo kết quả câu trước❌ chưa; đề cố định lúc start
Chẩn đoán ưu tiên node thuộc goal blueprint⚠️ ghi trong comment nhưng query không thực hiện — chỉ ORDER BY grade, level
Kho câu quá mỏng (trung bình 8,5 câu/bài)⚠️ đã cảnh báo qua pool_warning, nhưng gốc là thiếu nội dung
mastery_check chưa có run log riêng như WF-03⏳ chẩn đoán và đề thi có, đo mức vững thì chưa
Assessment sinh từ largest_uncertainty của Readiness⏳ Readiness đã tính next_assessment_priority, chưa ai gọi

Dòng thứ hai đáng chú ý: comment nói "ưu tiên node thuộc goal blueprint" nhưng câu SQL không có mệnh đề nào làm việc đó. Comment mô tả ý định, không phải hiện trạng.

Trace ​

  • REQ-INT-22 (insufficient reliable evidence), REQ-ONB-04 (gate Learner Model), REQ-EXAM-07 (3 lớp đo), REQ-INT-21.
  • Nguồn: SRC-003 §5, SRC-077, SRC-141 (reserve + cooldown), SRC-105.
  • Thiết kế: SDD-002 §5/§18, SDD-012 §4, SDD-017 §4.
  • Kiểm chứng: QG-005; selection.test.ts khoá luật chọn câu.
  • Liên quan: Learning Engine · Engines §1 · Retention · Workflows WF-03.