SHEN YIFull-Stack & AI

Paris • Singapore • Shanghai

RAG Formation · Lesson · Grounded answer generation

Context assembly and evidence budgets

Understand how retrieved results become model context—and how truncation can remove the evidence you needed.

$ lesson --status
▸ course RAG Formation
▸ lesson 09 / 16
▸ phase Grounded answer generation
▸ status Complete
● build → measure → learn

Standalone lesson

Learn the full lesson and test your understanding here.

The 16-lesson RAG Formation curriculum is complete. This page contains the complete lesson content, local reference material, and instant browser exercises.

Today’s tangible win

One evidence-survival map for a multi-hop answer, plus a bounded, defensible context-budget recommendation.

Watch the walkthrough

1 · The skill

Take q30 or q63 and follow it end to end—from the sources retrieval dug up, through context assembly, all the way to the prompt budget.

  • Context assembly: the step that turns backend results into the actual text the answering model reads. In this system it runs across four channels — summary, vector, fulltext, and graph — and build_context() gives each populated channel a max-min fair share of one character budget. It drops whole retrieved items where possible, reports what survived, and avoids starving a channel while another still has surplus. Each summary, vector, and fulltext item is capped at 1,200 characters; graph context is capped at 6,000; and the combined max_context_chars budget defaults to 32,000 characters (configurable from 1,000 to 50,000).
  • Chunk size versus context budget: the earlier indexing discovery is separate: the unified indexer uses 500-token chunks for Qdrant/Meilisearch/Summary and 1,200-token chunks for LightRAG. Those are indexing-time token sizes, not the answering model's character budget. Changing 500 to 800 would require re-indexing; it would not change build_context()'s answer-context limit by itself.
  • Evidence budget: the ceiling on how much context you can afford, set by character count, tokens, latency, or cost.
  • Source survival: whether the evidence an answer actually needs is still standing after formatting and truncation have had their say. The code comment describing the approach this replaced says it plainly: the old fixed-order concatenation meant "position, not relevance" decided what reached the model — the graph block was always last, so it was always the first thing lost.
  • Not the same path as Lessons 5–8: those lessons' --mode retrieval hits /api/v1/search, which has no fusion — plain concatenation, nothing more. This lesson's --mode answer hits /api/v1/qa, which does real per-channel budget allocation. Don't carry "no fusion" over from Lesson 8 — it doesn't apply here.

Primary reading: Anthropic — Contextual Retrieval

2 · Run the evidence loop

cd demo
python3 eval.py run --mode answer --workspace meridian_demo --category multi_hop --tag lesson-09-context

For every source, check these fields in the per-question report instead of guessing from the rendered answer:

  • results[].answer.stats.context_chars_by_index — how many characters of each channel (summary/vector/fulltext/graph) actually made it into the prompt.
  • results[].answer.stats.max_context_chars — the configured combined character budget; the current API defaults to 32000, not the indexing chunk size.
  • results[].answer.stats.context_items_included and .context_items_dropped — the second key only appears when something was dropped, listed per channel.
  • results[].answer.stats.context_hard_truncated — should be absent or false; if it's true, the fair-allocation backstop had to slice mid-string, which the design is meant to make unreachable.
  • results[].answer.sources and .source_hit.all — the citations that actually survived, and whether they cover every expected source.

If truncation cuts a source before generation, the model never sees it—finding it during retrieval doesn’t count for anything. For a multi-hop question specifically, check context_chars_by_index.graph and whether graph shows up in context_items_dropped first — that tells you whether the connecting evidence even survived into the prompt, before you conclude the model reasoned poorly over evidence it already had.

3 · Decision worksheet

Baseline evidenceOne hypothesis/changeMetricRegression checkBounded conclusion
_________________________

4 · Retrieval practice

Question: Retrieval pulled in every source you expected, but one gets truncated before generation even starts. Where did this actually break?

Mission connection

A system can’t cite evidence the model never saw. This is exactly where solid retrieval quietly turns into a partial answer, or a hallucinated one.

5 · Deliverable and next action

  1. Save the command output, or a summary report.
  2. Fill in the decision worksheet.
  3. Write down one failure case and what you’ll check next.

One evidence-survival map for a multi-hop answer, plus a bounded, defensible context-budget recommendation.

Next: Lesson 10 — Prompts that answer only from evidence.

Ask me follow-up questions about the evidence, the metric, the failure case, or whatever you want to try next. I’m your teacher for this course.