Attach summaries to every node

There are two reasonable ways to attach a summary to each node. The cheap way is heuristic: take the first paragraph under the heading, clean it up, call it the summary. The LLM way is to send each section to a cheap model with a "summarize this in two sentences" prompt. The workshop ships with the heuristic, and we will talk about when to upgrade.

tree.py
python
def flush_content():
    """Attach accumulated content and derive a summary."""
    if current_content_lines and stack:
        content = "\n".join(current_content_lines).strip()
        if content:
            stack[-1][1].content += "\n\n" + content
            # Heuristic summary: first paragraph, stripped of hash chars,
            # capped to 300 characters. Cheap and surprisingly effective
            # for well-written technical documents.
            if not stack[-1][1].summary:
                first_para = content.replace("#", "").strip()[:300]
                stack[-1][1].summary = first_para
    current_content_lines.clear()

The builder flushes accumulated lines into the current node whenever it encounters a new heading. On the first flush per node, it captures a 300-character snippet as the summary.

The heuristic works because well-written technical documents put their topic sentence first. For documents where that assumption breaks (think legal contracts, transcripts, messy user-generated content), you swap in a batch LLM pass that reads each section and writes a short summary. The rest of the pipeline is unchanged.

tree.py
python
def _distribute_content_to_leaves(self, node: TreeNode):
    """
    If a node has children, its content is effectively a section header.
    We keep a short summary but let children hold the full text.
    """
    if not node.children:
        return

    if len(node.content) > 500:
        node.summary = node.content[:500] + "..."
        node.content = node.summary

    for child in node.children:
        self._distribute_content_to_leaves(child)

After building the tree, we walk it and push content down to the leaves. Parent nodes keep a short summary only. This matches the routing pattern: parents are read for navigation, leaves are read for answers.

Add a post-processing walk that runs after the tree is built but before it is cached. Batch the section bodies into groups of say twenty, send each group to a cheap model with a "summarize each in two sentences" prompt, and attach the responses. Because this runs before caching, you pay once and reuse forever.

Quiz: Quiz

Loading practice…

Checkpoint: Tree and summaries checkpoint

Loading practice…