{"slug": "why-teachers-need-explainable-ai-not-just-accurate-ai-building-the-kc-dashboard", "title": "Why teachers need explainable AI, not just accurate AI — building the KC dashboard", "summary": "NumPath redesigned its teacher dashboard to replace a single \"7-day accuracy\" score with a Knowledge Component (KC) mastery panel that shows color-coded progress bars for individual skills (e.g., borrowing, place value). The authors chose to display a three-tier label system (Novice/Developing/Mastered) with the option to expand for raw data, arguing that this provides actionable information—such as identifying that a student needs targeted borrowing practice—rather than just a vague struggling indicator. The dashboard also includes access controls allowing teachers to view any student's data while students can only see their own, and the backend uses a left-join strategy for cleaner, testable code.", "body_md": "## What We Built\n\nNumPath's teacher dashboard previously showed one number per student: 7-day accuracy. A teacher looking at \"Emma — 43%\" has no idea whether Emma is struggling with borrowing, place value, number sense, or all three. The number is technically correct and completely unactionable.\n\nIn this post I'll walk through how we added a Knowledge Component (KC) mastery panel to the dashboard — colour-coded progress bars per skill that expand to show p_mastery %, mastery level label, and opportunity count. The backend piece is a single endpoint backed by a left-join use case. The research reason it matters is more interesting than the code.\n\n## The Design Decision\n\nThe core choice was: **what data does a teacher actually need?** We had three options:\n\n-**Accuracy-only**(what we had): fast to compute, no additional queries, but unactionable -** Raw BKT parameters**: show`p_mastery`\n\n,`p_learn`\n\n,`p_guess`\n\n,`p_slip`\n\n— complete but overwhelming for a classroom teacher -**KC mastery levels**: translate`p_mastery`\n\ninto a three-tier label (Novice / Developing / Mastered) with colour coding, keeping the raw number available on expand\n\nWe chose option 3. The mastery level thresholds are defined as named constants in `get_kc_states.py`\n\n:\n\n``` python\n_MASTERY_DEVELOPING = 0.40\n_MASTERY_MASTERED   = 0.80\n\ndef _mastery_level(p_mastery: float) -> str:\n    if p_mastery >= _MASTERY_MASTERED:\n        return \"Mastered\"\n    if p_mastery >= _MASTERY_DEVELOPING:\n        return \"Developing\"\n    return \"Novice\"\n```\n\nOne deliberate UX choice: a student with no attempts at all still sees all 5 skills at 0% / Novice. There's no \"no data yet\" placeholder. The teacher sees the full KC grid from day one — an empty bar is information (\"this student hasn't encountered this skill yet\"), not an error.\n\nThe access control pattern is worth noting too. We added a `require_authenticated`\n\ndependency — any valid JWT — and enforced role logic in the route handler:\n\n```\n@router.get(\"/{student_id}/kc-states\", response_model=KCStatesResponse)\nasync def get_kc_states(\n    student_id: uuid.UUID,\n    db: AsyncSession = Depends(get_db),\n    auth: dict = Depends(require_authenticated),\n) -> KCStatesResponse:\n    role = auth.get(\"role\")\n    if role == \"student\" and auth.get(\"sub\") != str(student_id):\n        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=\"Access denied\")\n    ...\n```\n\nStudents see their own KC states. Teachers see any student's. The rule lives in one place — the route — rather than being split across two separate dependency functions.\n\n## Why It Matters for the Research\n\nThe MacLellan ITS framework's \"Teacher-in-the-Loop\" principle isn't just about giving teachers a screen. It's about giving them**information they can act on**. A 43% accuracy number tells a teacher \"this student is struggling.\" A KC panel that shows SUB_BORROW at 12% (Novice, 8 attempts) while PLACE_VALUE is at 67% (Developing, 14 attempts) tells a teacher \"this student needs targeted borrowing practice — and they've already tried eight times, so hints aren't landing.\"\n\nThat's the difference between a reporting tool and a teaching tool. The RCT we're designing in Phase 4 will measure whether teachers who have KC-level visibility actually intervene differently than those who see accuracy alone. This dashboard is the instrument we're studying, not just a convenience feature.\n\n## What We Learned\n\nThe left-join strategy — two separate queries plus a dict lookup — turned out to be cleaner than an ORM `outerjoin()`\n\n. SQLAlchemy async `outerjoin()`\n\nwith nullable columns requires explicit handling of None values in ways that are easy to get wrong. Two queries and a `dict.get()`\n\nwith a default is more readable and easier to test with mocks:\n\n```\nkc_by_skill_id = {record.skill_id: record for record in kc_records}\n\nsummaries = [\n    KCStateSummary(\n        skill_code=skill.code,\n        p_mastery=round(kc_by_skill_id[skill.id].p_mastery, 3)\n        if skill.id in kc_by_skill_id else 0.0,\n        ...\n    )\n    for skill in all_skills\n]\n```\n\nNine unit tests covering the use case ran in 0.03s with no live database. That's the payoff for keeping the domain logic in a use case rather than inline in the route.\n\n## What's Next\n\nPhase 2 of the KC dashboard adds recent attempt history to the student detail panel — the specific problems a student got wrong, with their classified mistake codes, so a teacher can see patterns as they form.\n\n## Key Takeaways\n\n-**Accuracy is output, KC mastery is signal**— a single accuracy number is not enough for a teacher to act; per-KC mastery state is the minimum viable explainability for an ITS -**Empty is informative, not broken**— showing all KCs at 0% for a new student tells a teacher \"this skill hasn't been practised yet\"; hiding it implies the data is missing -**Two queries + dict > one complex join**— for small, static reference data (5 skills), two simple queries and a dict lookup are more readable, testable, and maintainable than an ORM outer join with nullable column handling", "url": "https://wpnews.pro/news/why-teachers-need-explainable-ai-not-just-accurate-ai-building-the-kc-dashboard", "canonical_source": "https://dev.to/orieken/why-teachers-need-explainable-ai-not-just-accurate-ai-building-the-kc-dashboard-4iga", "published_at": "2026-05-21 03:51:51+00:00", "updated_at": "2026-05-21 04:01:43.643130+00:00", "lang": "en", "topics": ["artificial-intelligence", "data", "products", "research"], "entities": ["NumPath", "KC dashboard", "Knowledge Component"], "alternates": {"html": "https://wpnews.pro/news/why-teachers-need-explainable-ai-not-just-accurate-ai-building-the-kc-dashboard", "markdown": "https://wpnews.pro/news/why-teachers-need-explainable-ai-not-just-accurate-ai-building-the-kc-dashboard.md", "text": "https://wpnews.pro/news/why-teachers-need-explainable-ai-not-just-accurate-ai-building-the-kc-dashboard.txt", "jsonld": "https://wpnews.pro/news/why-teachers-need-explainable-ai-not-just-accurate-ai-building-the-kc-dashboard.jsonld"}}