asa / scripts /lib /chat /pack_loader.py
defenestrate's picture
ASA Space: squashed history (instructions and settings live in the private pack)
526950e
Raw History Blame Contribute Delete
2.81 kB
"""ContextPack assembler.
Composes deterministic packs from retrieval results:
- course_constitution: all course_meta records (always loaded)
- topic: retrieval top-K
- module: full topic content (intent-driven)
assessment_safe is enforced upstream (catalog only contains student_access=True
records by construction in sub-project #1's _student_visible_files).
"""
from __future__ import annotations
from dataclasses import dataclass, field
from scripts.lib.catalog_loader import Catalog
from scripts.lib.ranker import RetrievalResult
_ASSESSMENT_KINDS = {"question", "slide_answer"}
_MODULE_INTENTS = {"summarize", "explain"}
@dataclass
class ContextPack:
course_constitution: list[dict] = field(default_factory=list)
topic: list[RetrievalResult] = field(default_factory=list)
module: list[dict] = field(default_factory=list)
has_assessment_content: bool = False
has_redacted_tier: bool = False
def assemble(
*,
intent: str,
retrieved: list[RetrievalResult],
catalog: Catalog,
mode: str = "tutor",
) -> ContextPack:
"""Compose a ContextPack from an intent + retrieval results + mode.
In review mode the module block is expanded whenever the dominant-topic
threshold is met, regardless of intent — faculty queries about a concept
consistently want every occurrence across the term, not the intent-driven
subset that's right for student tutoring.
"""
by_doc_id = {r["doc_id"]: r for r in catalog.records}
constitution = [r for r in catalog.records if r.get("kind") == "course_meta"]
topic = list(retrieved)
module: list[dict] = []
module_eligible = mode == "review" or intent in _MODULE_INTENTS
if module_eligible and len(retrieved) >= 2:
# Find the topic with the most retrieved records
topic_counts: dict[str, int] = {}
for r in retrieved:
rec = by_doc_id.get(r.doc_id, {})
t = rec.get("topic", "")
if t:
topic_counts[t] = topic_counts.get(t, 0) + 1
if topic_counts:
dominant_topic = max(topic_counts, key=lambda k: topic_counts[k])
if topic_counts[dominant_topic] >= 2:
module = [
rec for rec in catalog.records
if rec.get("topic") == dominant_topic
]
has_assessment = any(
by_doc_id.get(r.doc_id, {}).get("kind") in _ASSESSMENT_KINDS
for r in retrieved
)
has_redacted = any(
by_doc_id.get(r.doc_id, {}).get("privacy_tier") == "redacted_classroom_speech"
for r in retrieved
)
return ContextPack(
course_constitution=constitution,
topic=topic,
module=module,
has_assessment_content=has_assessment,
has_redacted_tier=has_redacted,
)