Courses / Build and Evaluate RAG Applications

Session 5 of 8

Data Architecture for AI Workloads

Overview

Chapter 5 — Data Architecture for AI Workloads

Course: Build and Evaluate RAG Applications

Prerequisites: You can read and run a short Python script. From earlier in this course and in Taking AI to Production you need three ideas, each restated in a sentence in the notes before it is used: a chunk is a piece of a document that a retrieval pipeline stores and looks up, retrieval answers can only be as good as the chunks it can find, and a system under load can serve reduced or cached answers when capacity runs out (the simplify mode from Taking AI to Production). Source of truth, index, ingestion, upsert, orphan, staleness and retention are defined in the notes before they are used.

What the reader can do after this chapter:

  • Name the source of truth for each piece of data in a retrieval system, and say which copies are derived from it and can be rebuilt.
  • Work out, from the state of a source and of an index, which documents are current, stale, missing or orphaned, and write the plan of upserts and deletes that brings the index into line.
  • Defend an ingestion design in a review by stating how it detects changes, how it propagates deletions, how stale it is allowed to get, and what is purged when retention ends.

Core question this chapter answers: When an AI system answers from an index of your documents, how do you keep that index faithful to the source of truth, through edits, deletions and retention rules, and how do you know when it is not?

Connections:

  • Builds on: the degradation.tsv from the previous lesson in Taking AI to Production, whose simplify mode serves reduced or cached answers and whose defer-batch mode postpones work. This chapter asks where that data is kept, how old it may be before it is wrong, and how an answer says so.
  • Leads into: a lesson in Taking AI to Production, which prices AI workloads. It opens with the upsert lines in the ingest-plan.tsv this chapter’s project writes, because each one is a chunk that has to be embedded again.

Your answers are scored

This chapter is assessed. The quiz is marked against a key held separately from your materials. Questions 1–8 are multiple choice and are marked by comparing your letter with the key. Questions 9–10 ask for a short answer in an exact format, and each one is marked by a rule printed with the question, so you can check that your answer has the right shape before you submit it.

  • Nothing is judged by reading it for style. An answer either matches the rule or it does not.
  • All three project tasks are scored from an evidence file of key: value lines and one tab-separated file. Every accepted value, or the rule that decides it, follows from what the task prints.

Notes

Build and Evaluate RAG Applications — Chapter 5: Data Architecture for AI Workloads

Before you start

Nothing to install for the reading. For the project you need Python 3 and nothing beyond its standard library. You do not need a cloud account, a search service or an API key: the project compares a printed source with a printed index, and does not call a service.

Keep one question in mind while you read: if this answer is wrong, is the problem in the model, or in the data the model was shown, and which copy of that data is the true one?

Summary

A retrieval system answers from an index, and an index is a copy: it is built from a source of truth by a job, and it is as faithful to that source as the job makes it. Four rules decide the faithfulness: how the job notices that a source document changed, how it removes what the source has dropped (a job that adds and updates but does not remove leaves orphans behind), how stale the index may be before it counts as broken, and what is purged from the index and the other derived stores when a retention rule ends a document’s life. A defensible data design names the source of truth, makes the index rebuildable from it, and states these four rules in a form that can be measured.

Key concepts

Term Definition
Source of truth The one place where the current, authoritative version of a piece of data lives. Other copies are checked against it, and it is what a rebuild reads from.
Derived copy Data built from the source of truth by a job, such as a search index, a set of embeddings or a cache of answers. It can be dropped and rebuilt, and it can drift from the source.
Index The store a retrieval step searches. In this chapter, it holds chunks, each under a key, built from the documents in the source.
Ingestion pipeline The job that reads the source, splits documents into chunks, and writes them to the index. It runs in numbered runs, on a schedule or on an event.
Upsert A write that inserts an entry if its key is new and replaces it if the key exists. Writing the same entry twice leaves the same result.
Idempotent Safe to repeat: running the operation again after it has succeeded changes nothing further.
Change detection How the pipeline decides which documents need work: for example a version number, a content hash or a last-modified timestamp.
Orphan An entry in the index whose source document no longer exists. It can still be retrieved and cited.
Staleness How far the index is behind the source for a document, counted here in runs since the source changed.
Freshness target The staleness a team agrees to allow, for example “no more than two runs”, stated so that it can be measured.
Retention A rule that ends a document’s life: after a stated point it must no longer be kept, so it is removed from the source and from the derived copies.
Soft delete Marking a document as deleted first, so that the pipeline can remove its derived copies before the source itself is physically removed.

Explanations

The failure, before the explanation

Here is a report a support lead sends to the team that runs an internal policy assistant.

Report: “The assistant told a new starter that expense claims need a manager’s signature. That rule was withdrawn. The assistant cited page expenses-v2, which no longer exists on the wiki. Retrieval worked. The model answered from what it was given. What went wrong?”

Nothing is wrong with the model, and nothing is wrong with retrieval: it found the best chunk in the index. The index still holds the chunks of a page that the wiki deleted, because the scheduled job adds new pages and updates changed pages and was not taught to remove anything. The assistant is faithful to its index. The index is not faithful to the wiki. To see where to look, you need a name for each copy and a rule for which one is true.

Source of truth and derived copies

Take the report above. The wiki holds the current policy, and the index holds a copy made by a job. When the two disagree, the wiki is right, because it is the place where someone edits a policy and where a legal review takes one down. The index is a derived copy, and so are the embeddings computed from the chunks, and so is a cache of answers kept for reuse. The source of truth is the single place that is allowed to be right when copies disagree.

A second way to see it is a library. The book on the shelf is the source of truth. The catalogue card says where to find it and what it is about, and it is a copy: if a book is withdrawn and nobody pulls its card, a reader is sent to an empty shelf, and nobody blames the reader. The same holds for the card in an index: the search worked as designed, and the card was stale.

Where you use it. A data design can start by writing down, for each kind of data, which store is the source of truth and which stores are derived. A support ticket system, a document store or a database is usually the source, and the index and caches are derived.

What a review listens for. “Where does the data really live?” is the first question. An answer such as “in the index, it is quicker to query” is a red flag, because of what happens next.

What changes in operations. A derived copy can be dropped and rebuilt, and the rebuild is a routine event, not a disaster. The Azure AI Search documentation lists changes that “require an index drop and rebuild”, for example changing a field definition, and says the rebuild ends with loading documents “from an external source”. For production schema changes it suggests creating and testing a new index side by side and then using an index alias to swap indexes “without changing application code” (Microsoft Learn, Update or Rebuild an Index - Azure AI Search). That is only possible when an external source exists. A team that keeps the only copy of a document in its index has nothing to reload from.

Versus the neighbour it gets confused with. A backup is not a source of truth: it is a copy of the source, kept to restore it. An index is not a backup either. It holds a transformed copy, chunks and embeddings, from which the original document cannot be restored.

Ingestion: noticing change, and writing it safely

Suppose a handbook page is edited. The pipeline has to find out. Three ways to find out are common. It can compare a version number that the source keeps. It can compare a content hash, a short fingerprint of the document’s text, which changes whenever the text changes. Or it can compare a last-modified timestamp. The Azure AI Search documentation describes the third: for content from Azure Storage, “change detection occurs automatically because indexers keep track of the last update using the built-in timestamps on objects and files in Azure Storage” (Microsoft Learn, Changed and Deleted Blobs - Azure AI Search). The same page warns that changing document keys or directory names “breaks the internal tracking information”, so a stable key per document is a design decision and not a detail.

A second way to see the writing step is a printing shop reprinting a page of a manual. The shop swaps the old page for the new page with the same page number, and the manual is complete. Doing the swap twice leaves the same manual. That is an upsert: insert if the key is new, replace if it exists. The Azure documentation describes upload as “similar to an ‘upsert’ where the document is inserted if it’s new, and updated or replaced if it exists”, and a mergeOrUpload action as the most common choice for incremental updates, and it notes that the entries are identified by a unique key (Microsoft Learn, Update or Rebuild an Index - Azure AI Search). Writes that are upserts can be retried after a timeout without making a mess.

Now the edge that catches teams. Documents are split into chunks, and each chunk is its own entry with its own key, for example handbook#0, handbook#1, handbook#2. Suppose an edit shortens the page from five chunks to three. The pipeline upserts handbook#0 to handbook#2, each replacing an entry. Nothing names handbook#3 or handbook#4, so they stay in the index, holding text from the old version, and they still match queries. The fix is part of the design: when a document is re-ingested, the plan also deletes the old chunks the new version no longer has. This is a consequence of the key scheme in this chapter and not a statement about any one product; a store that keeps a document as one entry under one key replaces it whole.

Where you use it. Pick a change-detection signal the source actually provides, give each document a stable key, make the write an upsert, and plan the deletes for chunks that disappear.

What a review listens for. “What happens if the job runs twice?” and “What happens to the extra chunks when a page gets shorter?” A pipeline that cannot answer both is not safe to retry.

What changes in operations. Retries become cheap and safe: the Azure documentation notes that some status codes are retryable and that delete operations are idempotent. It also means a failed run can simply be run again.

Versus the neighbour it gets confused with. A full re-index on each run also keeps the index current and needs no change detection. It costs a re-embedding of the whole corpus each time, which a lesson in Taking AI to Production prices. Incremental ingestion trades that cost for a pipeline that has to be right about what changed.

Deletion: the half that jobs forget

Return to the report. The page was deleted, and nothing in the job looks at pages that are gone. The Azure AI Search documentation states this for its storage indexers: “Although change detection is a given, deletion detection isn’t. An indexer doesn’t track object deletion in data sources. To avoid having orphan search documents, you can implement a ‘soft delete’ strategy that results in deleting search documents first, with physical deletion in Azure Storage following as a second step” (Microsoft Learn, Changed and Deleted Blobs - Azure AI Search). The order is the point: if the source file is removed first, there is nothing left for the job to notice. The page lists two ways to do it, the storage service’s own blob soft delete, and a custom metadata flag such as IsDeleted.

The same page adds two details that show how easy this is to get wrong. The policy “must be applied from the very first indexer run”: documents deleted before the policy was in place “remain in your index, even if you add the policy to the indexer later and reset it”, and its suggested repair is a new index with a new indexer. And with native soft delete, the indexer removes a document only if it processes the blob “while it’s in a soft deleted state”, and the documentation advises setting the soft-delete retention “much higher than your indexer interval schedule”.

A second way to see deletion is a recall notice. A manufacturer who stops selling a part has to tell the shops that hold one, and a notice that reaches just the shops that call is not a recall. An index that is told about edits and not about removals is a shop that was not told.

Where you use it. Add a deletion step to the design from the start: detect what has left the source, or have the source mark deletions first, and delete the derived chunks by key.

What a review listens for. “How does a deleted document leave the index?” An answer of “it expires eventually” needs a stated rule behind it. A weaker answer is “we re-index when someone reports it.”

What changes in operations. Orphans are found by a check that compares the keys in the index with the keys in the source, which the project does. Physical removal inside a search service is not instant: the Azure documentation says deleted documents “don’t immediately free up space” and that a background process performs the physical deletion, so counts can lag behind the deletes.

Versus the neighbour it gets confused with. Changing what the model is told (“ignore withdrawn pages”) or lowering the number of chunks retrieved does not remove an orphan. It only makes the orphan appear less often.

Freshness: how stale is allowed

Take the handbook again. The source is edited at one moment, and the index changes only when a run of the job completes. The gap between them is staleness, and it can be nearly a whole schedule interval. That is a fact of the design, not a bug. A freshness target says how much is acceptable: “an edit is searchable within two runs”. Counting in runs keeps the target independent of how often the job runs.

A second way to see it is a newspaper: yesterday’s edition is correct for yesterday. Nobody calls it a defect that it does not contain today’s news, but a newspaper that printed last month’s prices without saying so would be misleading. The index needs the same label, which is its freshness target, stated and monitored.

The simplify mode from Taking AI to Production serves cached answers when capacity runs out. A cached answer is a derived copy with an age, so it carries a freshness target of its own and has to be dropped when its source changes or ends. Different data can carry different targets. A price list that changes often may need a target of one run, a policy handbook two or three, an archive of old reports many. For facts that change from one request to the next, such as an order status, no index is fresh enough, and a model should call a tool instead (the choice of lever from Getting Started with AI).

Where you use it. Write a freshness target per kind of data, measure the staleness of each document (runs since its source change that the index has not yet reflected), and alert on documents that breach.

What a review listens for. “How stale can this get, and how would you know?” A target without a measurement is a hope.

What changes in operations. Staleness is cut by running the job more often, by triggering it on a source event, or by letting a rare change trigger a single-document update. Each costs something: more runs mean more embedding work, and an event trigger adds a moving part.

Versus the neighbour it gets confused with. A stale index is not the same as a wrong answer from a model. A stale index retrieves faithfully the old text. It needs a data fix, and a prompt or model change leaves it in place.

Retention: what ends a document’s life, and the copies it leaves behind

Suppose a regulation says customer records may be kept until a stated date and no longer. The record is deleted from the database on that date, and the project’s index, the embeddings made from it, and a cache of answers that quoted it all hold copies. The rule has been followed in one place. Retention means the rule is applied to each derived copy of the data, and not just to the source.

A second way to see it is a shredder next to a photocopier. Shredding the original is not compliance if the photocopies are in a drawer. The design question is therefore a list: which stores hold copies of this data? Typical answers are the index, any store of embeddings, a cache of answers, logs that captured the retrieved text, and exports or backups.

In practice the cleanest design makes the source say when data ends, for example a retain_until field, and has the pipeline treat an expired document like a deleted one: remove its chunks, and invalidate any cached answer that cited it. A cached answer that cites a document whose chunks have been removed is a copy that has outlived its source.

Where you use it. Keep a register of derived stores per kind of data, and give each a purge path that the pipeline can run by key.

What a review listens for. “If this document must be gone by the end of its retention period, what else holds it?” The answer is a list, and an auditor will ask for it.

What changes in operations. Purges need keys. A cache that cannot be searched by the document it cites cannot be purged selectively, and the safe purge left is the whole cache. Backups that hold copies need their own stated rule.

Versus the neighbour it gets confused with. Deleting a document from the source is not the same as deleting it from the system. Access control hides a document from some users and leaves the copy in place; retention removes the copy.

Three situations you will meet, and what they mean for your design

Before the table, three situations:

  1. A team indexes a shared drive. People rename folders, move files and delete old ones, and the assistant starts citing paths that return “not found”.
  2. A product page is rewritten and now has half as many sections. Questions about the old sections still get an answer that the page no longer contains.
  3. A compliance officer asks that the records for a closed account be removed by a stated date, and the team has to say where the records still live.
What you see What it means What to do
Citations to files that are gone, after moves and deletes (situation 1) The pipeline tracks changes and not removals, and a changed path may be a changed key Keep stable document keys, detect or mark deletions, and delete derived chunks by key
Old sections still answered after a rewrite (situation 2) The upsert replaced the chunks it named and left the extra old chunks Plan deletes for chunk numbers the new version no longer has, and check the result with an index-versus-source comparison
“Where does that record still live?” (situation 3) Retention was applied to the source and not the copies List derived stores, give each a purge path, and make the pipeline run it from the retention field

Flashcards

Say the answer aloud before revealing it. Speaking it is what exposes the gaps that reading past a written answer hides.

What is the difference between a source of truth and a derived copy?

The source of truth is the one place allowed to be right when copies disagree, where edits are made and documents are taken down. A derived copy, such as an index, a set of embeddings or a cache, is built from it by a job. It can be dropped and rebuilt, and it can drift from the source.

Why must an index be rebuildable from an external source?

Some changes, such as changing a field definition, need the index to be dropped and rebuilt, and the rebuild loads documents from an external source. A team whose only copy of the text is in the index has nothing to reload from.

What is an upsert, and why does it make a retry safe?

A write that inserts an entry if its key is new and replaces it if the key exists. Running it twice leaves the same result, so a job that timed out can be run again without creating duplicates.

A document shrinks from five chunks to three. What goes wrong with upserts alone?

Each chunk is its own entry. The upserts replace the three entries they name, and the two extra old chunks are not named, so they stay in the index and still match queries. The plan has to delete them by key.

What does the Azure AI Search documentation say about detecting deletions from storage?

Change detection is automatic for storage content, from timestamps, but an indexer does not track object deletion in data sources. To avoid orphan search documents it suggests a soft delete, which removes the search document first and the physical file second.

Why must a deletion policy be in place from the first indexer run?

The documentation says documents deleted before the policy was implemented remain in the index even if the policy is added later and the indexer is reset. Its suggested repair is a new index with a new indexer.

What is an orphan, and how do you find one?

An entry in the index whose source document no longer exists. You find them by comparing the keys in the index with the keys in the source, and anything in the index and not in the source is an orphan.

What is staleness, and why count it in runs?

How far the index is behind the source for a document: runs since the source change that the index has not yet reflected. Counting in runs keeps the freshness target the same whatever the schedule of the job.

When is an index not fresh enough whatever the schedule?

For a fact that changes from one request to the next, such as a current order status. The model should call a tool for it, because any indexed copy is already out of date.

Why is deleting from the source not enough for retention?

The index, the embeddings, the cache of answers and any logs that captured the text are derived copies, and each holds the data after the source is purged. Retention is applied to each of them, and each needs a purge path by key.

Model answer

The question: “Our assistant cited a policy that was withdrawn. How should the data behind it be designed so that this does not happen, and how would you know if it did?” This is the question a lead engineer asks in a design review, and an interviewer for a cloud AI architecture role asks to hear a design and not a patch. A strong answer hits five beats, in this order:

  1. Source of truth — name where the data really lives, and say that the index and the caches are derived copies that can be rebuilt from it.
  2. Change — say how the pipeline notices an edit (version, hash or timestamp) and writes it as a safe, repeatable upsert with stable keys, including the delete of chunks that disappear.
  3. Deletion — say how a removed document leaves the index, with the source marking or the pipeline detecting the deletion first and deleting derived chunks by key.
  4. Freshness — state a target in runs for each kind of data, and measure each document’s staleness.
  5. Retention — list the derived stores that hold the data, and give each a purge path driven by the source’s retention field.

“I would start by naming the source of truth, the wiki, and treating the index, the embeddings and the answer cache as copies that a job builds from it and that I can rebuild. The citation of a withdrawn page tells me the job handles edits and not removals, so I would add a deletion path: either the source marks a page as deleted first, or the job compares the keys in the index with the keys in the source, and then deletes the page’s chunks by key. For edits I would use a stable key per document, change detection from a version or hash, and upserts that can be retried, plus a delete for any chunk the new version no longer has. I would write down a freshness target for each kind of data, counted in runs, and measure the staleness of each document so that a breach raises an alert. And I would keep a list of the stores that hold copies, the index, the embeddings, the cache and the logs, with a purge by key for each, driven by a retention field in the source. I would check the whole thing with a comparison of index keys against source keys on each run, because that is how I would know if it failed.”

Missing a beat is a failure state. Without source of truth the answer patches the index and cannot rebuild it. Without change it leaves extra chunks behind after an edit. Without deletion it keeps the very failure in the question. Without freshness it has no way to say when the index is broken. Without retention it passes a review of the index and fails an audit of the copies.

Why this matters

  • Design reviews ask for it. “What is the source of truth, and what happens when a document is deleted?” is asked of any retrieval design, and an answer with a list of derived stores is stronger than one about the model.
  • Quality follows it. A retrieval step finds what the index holds. When answers are wrong in a way a model change does not fix, the first check is an index-versus-source comparison.
  • Compliance follows it. A retention rule that reaches the source and not the copies can be failed in an audit, and the way to prove it was met is the list of derived stores with a purge path for each.
  • Operations follow it. A pipeline made of upserts can be retried, and a rebuild from the source is a routine event. A pipeline that cannot be rerun safely turns a failed run into an incident.

After this chapter

The project for this chapter is Audit an Index and Write the Ingest Plan (project.md). You will compare a printed source with a printed index, sort each document into a state, write the plan of upserts and deletes as ingest-plan.tsv, check that a second run has nothing to do, and report which documents breach a freshness target and which cached answers must be dropped.

A lesson in Taking AI to Production opens with the upsert lines in your plan: each is a chunk that has to be embedded again, which is the part of ingestion that costs tokens. It shows how to model that spend before it is incurred and how to control it by structure and not by vigilance.

Project

Hands-on Project — Audit an Index and Write the Ingest Plan

Objective

Compare a source of documents with the index built from it, sort every document into a state, write the plan of upserts and deletes that brings the index into line, and check how stale and how exposed the index is, so that keeping an index faithful rests on a stated rule and not on hope.

What this project needs: Python 3 and its standard library only. No task needs a cloud account, a search service or an API key. The source, the index and the cache are printed below, and every check is an exact comparison. All three tasks are required.

Your evidence file. Keep one plain-text file, chapter5-evidence.txt. Each task tells you which lines to add. Every line has the form key: value, one per line, with the key in lower case exactly as printed. Write what your code printed, not what you expected it to print. Where a value is a list, write its items comma-separated with no spaces, in the order given.

The data and the rules for all tasks

Copy this into your Python file. A run is one execution of the ingestion job; runs are numbered, and CURRENT_RUN is the run that is about to start.

  • SOURCE holds one tuple per document in the source of truth: (doc_id, version, n_chunks, edited_run, retain_until). edited_run is the run during which that version was saved. retain_until is the last run in which the document may be kept, or None for no limit.
  • INDEX maps a doc_id to (version, n_chunks, indexed_run): the version that was indexed, how many chunks it produced, and the run that indexed it. Its chunk ids are doc_id#0 up to doc_id#(n_chunks-1).
  • CACHE holds answers kept for reuse, as (cache_id, doc_id): the document each cached answer cites.
CURRENT_RUN = 20
SLA_RUNS = 2
SOURCE = [
    ("d1", 3, 4, 18, None), ("d2", 1, 2, 5, None), ("d3", 2, 3, 14, None), ("d4", 5, 1, 20, None),
    ("d5", 2, 5, 12, 15), ("d6", 1, 3, 3, None), ("d7", 4, 2, 17, None), ("d8", 1, 2, 19, 30),
]
INDEX = {
    "d1": (3, 4, 18), "d2": (1, 2, 6), "d3": (1, 4, 10), "d4": (4, 2, 15),
    "d5": (2, 5, 13), "d7": (4, 2, 18), "d9": (1, 3, 2), "d10": (2, 1, 8),
}
CACHE = [("c1", "d5"), ("c2", "d1"), ("c3", "d5"), ("c4", "d9"), ("c5", "d3")]

The state rule. For each document in SOURCE, take the first of these that applies:

  1. retain_until is not None and is less than CURRENT_RUN: expired.
  2. The doc_id is not in INDEX: missing.
  3. The indexed version differs from the source version: stale.
  4. Otherwise: current.

An orphan is a doc_id that is in INDEX and not in SOURCE.

Task 1 — Audit the index

Write state(doc) following the state rule. Print the state of all eight documents, the count of each state, and the orphans in the order they appear in INDEX.

Add to your evidence file:

t1_counts: <count per state in the form current=N,stale=N,missing=N,expired=N>
t1_state_d3: <state of d3>
t1_state_d5: <state of d5>
t1_orphans: <orphan ids, in INDEX order>

Output: one Python file with state, and four evidence lines.

Task 2 — Write the ingest plan

This task needs only the data and the rules above. Build plan, a list of (action, chunk_id) pairs, by going through SOURCE in order and then the orphans in INDEX order:

  • For a stale or missing document with n chunks, upsert its chunks doc_id#0 to doc_id#(n-1). If the document is in INDEX with more indexed chunks than n, also delete each indexed chunk numbered n or higher.
  • For an expired document, delete each of its chunks in INDEX. There are none to delete when it is not in INDEX.
  • For an orphan, delete each of its chunks in INDEX.
  • A current document gets no action.

Within one document, list its upserts in ascending chunk number, then its deletes in ascending chunk number. Write ingest-plan.tsv: one line per action, with the action, a single tab character and the chunk id, in plan order.

Then apply the plan to INDEX: a document that was upserted gets (source version, n_chunks, CURRENT_RUN), and a document whose chunks were all deleted is removed from INDEX. Build the plan a second time from the new INDEX.

Add to your evidence file:

t2_upserts: <number of upsert lines>
t2_deletes: <number of delete lines>
t2_final_chunks: <number of chunks in INDEX after the plan is applied>
t2_rerun_actions: <number of actions in the second plan>

Output: an ingest-plan.tsv of twenty lines, and four evidence lines.

Task 3 — Check staleness and exposure

This task needs only the data and the rules above, and the states from Task 1 as they were before the plan was applied.

  • Lag. For each stale or missing document, the lag is CURRENT_RUN minus edited_run. A document breaches the freshness target when its lag is greater than SLA_RUNS.
  • Exposure. A cached answer must be dropped when the document it cites was expired, stale or an orphan. The others are kept.

Add to your evidence file:

t3_breach_ids: <ids of documents that breach, in SOURCE order>
t3_max_lag: <the largest lag among stale and missing documents>
t3_dropped: <ids of dropped cached answers, in CACHE order>
t3_kept_count: <number of cached answers kept>

Output: four evidence lines.

What carries forward

Keep ingest-plan.tsv and chapter5-evidence.txt. A lesson in Taking AI to Production opens with the upsert lines in your plan: each one is a chunk that has to be turned into an embedding again, which is the part of ingestion that costs tokens, and that lesson asks what that spend should be modelled and capped by.

TechEazy Consulting training material — not affiliated with or endorsed by OpenAI, Anthropic, Microsoft or any other company named in this course.