Fintech

How to Build a Retrieval Set for Customer Support Triage

Antonio Evans11 min read

A support agent's desk seen from above: a laptop screen shows a customer question with three retrieved cards beside it, one labeled 'Refund policy, section 4.2', one 'Help article: change plan', one 'Ticket #4821.
Key points

Key points

  1. 1A support triage retrieval set is three corpora in one index: policy chunks, help article sections and resolved tickets, each carrying metadata and a stable source ID.
  2. 2Chunk by document structure, not token count, so every passage still makes sense when it is read alone after retrieval.
  3. 3Metadata filters (product, plan, region, issue type, ticket status) stop the model from citing the wrong regional policy or a superseded article.
  4. 4Every model verdict must carry a citation to a specific source ID, and the pipeline must be tested on retrieval and generation separately.

Why support triage fits the retrieval pattern

Customer support triage is a classification and routing job dressed up as a writing job. An agent (human or automated) reads a complaint, decides what it is, decides how urgent it is, and points at the rule or precedent that justifies the decision. That is the same shape as the model plus retrieved context plus verdict pattern used in fraud and scam review, where an LLM scores a case and a reviewer acts on the score.

The Federal Reserve's payments improvement group describes exactly this pattern for fraud and scam work: a model guided by explicit context instructions and grounded in a knowledge base of policies, playbooks, decision trees and classification standards produces more consistent, defensible output than a model answering from training data alone FedPayments Improvement. A support desk needs the same guardrails, because the cost of an ungrounded answer is a wrong refund, a wrong retention offer or a misclassified chargeback.

The point of the retrieval set is not to give the model more words. It is to give the model the smallest set of passages that lets it reach the same verdict your best agent would reach, with a source you can show a customer or a regulator. Everything below is about building that set so it stays correct as products, plans and policies change.

The three corpora and what each is for

A working triage index usually mixes three document types, and they need different treatment.

Policy documents (refund rules, escalation matrices, acceptable-use terms, regional consumer rights) answer the question "what are we allowed to do." They are the highest-stakes corpus because a wrong citation creates a legal or financial exposure.

Help articles answer "how does the product work." They are the most volatile corpus: they change with every release and every UI change.

Resolved tickets answer "what did we actually do last time." They are the only corpus that captures judgment calls the written policy does not cover, such as how much goodwill credit a particular issue type usually attracts.

CorpusQuestion it answersChunk boundaryUpdate cadenceFailure if stale
PolicyWhat are we allowed to do?Section, heading kept with bodyOn any rule changeWrong refund, compliance exposure
Help articleHow does the product behave?One procedure step or one FAQ pairEvery releaseAgent tells customer to click a button that no longer exists
Resolved ticketWhat did we do before?Problem text plus resolution textContinuousPrecedent contradicts current policy

A useful rule of thumb: if a corpus item has no owner and no change trigger, it will rot. Policy chunks need a named owner in legal or compliance, help chunks need a trigger on the release process, and ticket chunks need a rule that excludes reopened or reversed resolutions.

Chunking policies so each passage stands alone

Retrieval hands the model a passage with no surrounding document. If the passage says "the 30-day window above does not apply to digital goods," the model has no idea what window, which product, or which jurisdiction. The fix is structural chunking: split on the document's own hierarchy so the heading travels with the body.

SurrealDB's survey of chunking strategies makes the tradeoff explicit. Fixed-size chunking is simple and fast but "completely ignores sentence and paragraph boundaries" and can split mid-sentence or mid-idea. Document-structure chunking, which splits on headers and sections, is slower to prepare but produces chunks that match how the document is actually organized SurrealDB. For policy documents, where a section is already the unit a human would cite, structure chunking wins.

A practical policy-chunk recipe:

  1. Split at heading level, using the deepest heading that still covers one rule.
  2. Prepend the heading path to the chunk text, for example "Refunds > Digital goods > EU consumers:" so the passage restates its own scope.
  3. Keep the effective date in the text or metadata, and keep superseded versions retrievable but filtered out by default.
  4. Cap the chunk at the point where a single section covers more than one distinct rule. Two rules in one chunk means the model can cite the passage for the wrong one.

Here is what a policy chunk looks like once prepared:

{
  "source_id": "policy-refund-0042-v3",
  "doc_title": "Refund Policy",
  "heading_path": "Refunds > Digital goods",
  "effective_from": "2025-03-01",
  "product": ["streaming", "ebooks"],
  "region": ["US", "CA"],
  "plan": ["consumer"],
  "text": "Refunds > Digital goods. Digital goods are refundable within 14 days of purchase only if the download has not been started. If the download was started, no refund applies unless the file is defective."
}

The AWS Bedrock documentation notes that when documents are ingested, content is split into manageable chunks, converted to embeddings, written to a vector index, and kept mapped back to the original document AWS documentation. That mapping is your citation trail, so never let a chunk lose its pointer to the parent document and heading.

Help articles need a different rule. Split at step boundaries so a procedure step does not arrive without the step before it. For FAQ-style articles, split per question and answer pair. A tutorial with eight numbered steps should produce eight chunks plus one overview chunk, not nine arbitrary token windows. The general guidance for prose knowledge bases favors sentence-aware or recursive splitting that respects natural language boundaries, which is close to what help articles need at the sentence level, while section boundaries should be respected at the article level Medium.

Chunking tickets as problem plus resolution pairs

Tickets are the corpus most teams get wrong, because the obvious approach (dump the whole thread) produces long, noisy passages full of greetings, apologies, agent names and internal notes. The model then retrieves the noise and cites the wrong thing.

Store each ticket as a pair: the customer's problem statement as written (cleaned of PII) plus the resolution that actually closed it. Keep the subject line attached, because it is often the densest summary of the issue available.

Chipper Cash's fraud email triage pipeline is a useful model. Before automation, an analyst read each alert, cross-referenced accounts across three dashboards and copy-pasted data by hand, at roughly 30 minutes per email. The rebuilt pipeline cleans HTML, strips disclaimers and links, and sends the cleaned text to a model with a strict JSON schema; it processes each email in under 20 seconds, with every action writing an audit trail Chipper Cash. Two lessons carry over directly to ticket ingestion: clean the text before it ever reaches the index, and make the model's output schema strict so downstream routing does not have to guess.

For a ticket chunk, keep:

  • the subject line
  • the customer's original problem description, trimmed to the relevant part
  • the resolution text, and whether it was a refund, replacement, workaround, escalation or no-fault answer
  • the outcome flag: resolved, resolved with reversal, reopened, or closed without resolution

Exclude internal notes by default. If an internal note explains the resolution, summarize it into the resolution field rather than appending the raw note, so the chunk reads as a clean precedent. Exclude tickets closed without resolution from the precedent corpus entirely; a no-resolution ticket teaches the model nothing useful and can teach it to give up.

The multi-evidence clinical triage study published in JMIR Medical Informatics is worth knowing about here. It built a retrieval-augmented system over a 3,000-case database for emergency triage and compared it against a prompt-only baseline, evaluating five-level triage classification with confusion matrices and quadratic weighted kappa ScienceDirect. The transferable insight is the evaluation shape: build a fixed test set of past cases with known correct triage levels, and compare the retrieved verdict against the human verdict using a graded agreement metric, not just a right or wrong count. Support triage benefits from the same treatment because the severity of a misroute varies.

Metadata that makes filters do the real work

Metadata is where support retrieval diverges most from general document search. A generic RAG pipeline embeds everything and hopes the query matches the right passage. A support pipeline can do better, because it already knows facts about the ticket before it searches: which product, which plan, which region, which channel, which customer tier.

Add filters on at least these dimensions:

FieldExample valuesWhat it prevents
productstreaming, payroll, cardsCiting a sibling product's policy
planconsumer, business, enterpriseApplying consumer refund rules to a contract customer
regionUS, EU, UK, APACCiting the wrong statutory rights
issue_typerefund, chargeback, login, billing, fraudMixing a fraud precedent into a login question
ticket_statusresolved, reopened, reversedCiting a precedent that was later overturned
effective date rangefrom, toCiting superseded policy
languageen, pt, jaRetrieving a passage in a language the customer cannot read

Two rules keep filters honest. First, filter before you rank, not after. If you retrieve the top 20 passages and then filter to region, you can end up with two results, and one of them may be irrelevant. Filter first so the ranking has a clean candidate pool. Second, make the absence of a match a valid outcome. If a US consumer asks about a policy that only exists for EU consumers, the model should return "no applicable policy found, escalate" rather than borrowing the EU text because it scored highest.

Chipper Cash's pipeline shows the conservative version of this principle in practice: its action flags for restricting a user or placing a lien are set to true only when the email explicitly requests it, and ambiguous language routes the case to manual review, because delaying action is preferable to locking the wrong account Chipper Cash. Apply the same asymmetry to refunds and account actions: when the retrieved evidence is thin or contradictory, triage to a human instead of guessing.

Citations: making every verdict point at a source

A support verdict without a citation is a rumor. The citation is what lets a supervisor audit the answer, lets a customer see the rule, and lets the next agent trust the handoff.

Build citation into the data model rather than the prompt. Every chunk carries a source_id that resolves to a human-readable location: document title, heading, and if useful, a URL and anchor. Then require the model's output schema to include a citation field that must reference one of the retrieved source_ids. If the model returns a citation that is not in the retrieved set, treat the response as a failed generation and retry or escalate.

MLflow's guidance on structured outputs maps directly here. It recommends schema-constrained generation or function calling as the default over prompted JSON, paired with runtime validation and a fallback path, and notes that schema enforcement guarantees syntactic validity but not value correctness MLflow. For citations, that distinction matters: a schema can force the model to emit a source_id, but only your validator can confirm the source_id was actually retrieved and actually supports the claim.

A minimal verdict schema looks like this:

{
  "issue_type": "refund_not_received",
  "severity": "low",
  "route_to": "billing_ops",
  "recommended_action": "issue_refund",
  "citation": ["policy-refund-0042-v3", "ticket-2023-1187"],
  "confidence": 0.82,
  "escalate": false
}

Two validation checks after generation:

  1. Every value in citation exists in the retrieved candidate set for this query.
  2. The recommended_action is consistent with at least one cited policy chunk, checked by a second small model or a rules table that maps policy clauses to allowed actions.

The second check is cheap and catches the most damaging error class: a correct-looking answer citing a real document that says something else. If you want a single, consistent endpoint for the extraction model, the router model and the validation model, Quanta Inference exposes text, image, audio and embedding models through one OpenAI-compatible API key, which keeps a multi-model pipeline to one integration.

Testing the set before it touches customers

You cannot improve what you do not measure, and a support retrieval system fails in two different places. Either the right passage was never retrieved, or it was retrieved and the model wrote something the passage does not support. Evaluate those separately.

Evidently's RAG evaluation guide splits the work exactly this way: retrieval quality is measured with ranking metrics such as recall@k against ground truth, or with manual and LLM-judged relevance scoring, while generation quality is measured with reference-based comparison to correct answers and reference-free checks for faithfulness and completeness Evidently AI. For support triage, recall@k is the metric that matters most, because a routing decision built on the wrong precedent is worse than an escalation built on no precedent.

A practical test set for a support desk:

  1. Pull a few hundred real tickets that were resolved by experienced agents, and label the correct issue type, route and action for each.
  2. For each, mark which policy chunk and which ticket precedent should have been retrieved.
  3. Measure recall@5: how often the correct policy chunk appears in the top five results after filtering.
  4. Measure citation validity: how often the model's citation is in the retrieved set and consistent with the action.
  5. Track escalation rate on the test set. A model that escalates everything scores well on safety and badly on usefulness; track both.

Synthetic question-answer pairs generated from the knowledge base can bootstrap the test set, and stress and adversarial testing should cover the cases where customers argue, quote a policy out of context, or ask for something outside the plan. A prompt that says "always cite policy" is not a control; a validator plus a test set is.

For teams that want the retrieval and evaluation harness built and maintained by specialists rather than staffed internally, a free discovery call with Quanta Consulting is a low-cost way to pressure-test the design before committing engineering time.

Operating the set after launch

The index is a living object, and most failures show up after week one. Build the operating loop at the same time as the first index.

  • Change triggers. A policy edit should invalidate and re-chunk the affected section the same day. Tag chunks with effective dates so a stale version can be filtered out before a fresh one is live.
  • Precedent decay. Ticket precedents lose value as policies change. Review precedents older than your policy cycle or, better, filter them by effective date alongside policy chunks.
  • Citation review. Sample a fixed number of automated verdicts per week and check the citation against the action. Log failures by source_id so you can see which documents cause the most bad citations.
  • Schema drift. Log raw and parsed outputs and set validation failure metrics, per the MLflow recommendation, so a model upgrade or prompt edit that breaks the schema shows up as a metric rather than as a customer complaint MLflow.
  • Human in the loop by design. Keep the escalation route visible in every verdict. The goal is not to remove the agent; it is to give the agent the passage and the precedent, so the decision takes seconds and the evidence is already attached.

The pattern generalizes beyond refunds and logins. The same model plus retrieved context plus verdict structure works for abuse review, chargeback intake and fraud first response, which is why the payments research on grounded classification, RAG evaluation and structured output all points in the same direction. Build the retrieval set once, keep it clean, and the model's job becomes small and auditable.

FAQ

FAQ

What is the difference between a retrieval set and a knowledge base?

A knowledge base is the collection of documents you maintain for humans: policies, help articles, internal wikis. A retrieval set is a derived index of those documents, split into self-contained passages with metadata and stable source IDs, optimized for a model to retrieve and cite. You can rebuild the retrieval set from the knowledge base at any time, and you should whenever the underlying documents change.

How small should each chunk be?

There is no universal token count, because the constraint is meaning, not size. Split where the document itself changes topic: a heading, a numbered step, a question-answer pair. The test is whether the passage still makes sense when read alone, with no surrounding text. If it needs the previous paragraph to be understood, the split is wrong, and the fix is to prepend the heading path or merge the fragments.

Should resolved tickets be in the same index as policy documents?

Keep them in the same index with different metadata values, so a single query can retrieve a policy rule and a precedent that applied it. Distinguish them with a corpus field and weight policy chunks above tickets in ranking, since a ticket records what happened once while a policy records what is allowed. Exclude reopened and reversed resolutions from the precedent pool, because they teach the model to repeat outcomes that were later corrected.

How do I stop the model from citing an outdated policy?

Two mechanisms work together. Store an effective date range on every policy chunk and apply a date filter by default, so superseded versions are not candidates. Keep superseded chunks retrievable only for queries that explicitly ask about a past period, such as a dispute on an old charge. Then validate the citation against the retrieved set, so the model cannot invent or borrow an out-of-window source.

How do I know the system is working?

Measure retrieval and generation separately on a fixed labeled test set of past tickets. Track recall@5 after filtering, citation validity, agreement between the model's route and the human route, and escalation rate. Review a sample of live verdicts weekly for citation-to-action consistency. A single blended accuracy number hides the difference between "retrieved the wrong passage" and "retrieved the right passage and misread it," and those two failures have different fixes.

Sources

Sources

  1. Guiding Large Language Models (LLMs) Toward Better ...
  2. What chunking strategies exist and how to choose one?
  3. How content chunking works for knowledge bases
  4. Mastering Document Chunking Strategies for Retrieval ...
  5. How We Automated Fraud Email Triage at Chipper Cash
  6. Multi-Evidence Clinical Reasoning With Retrieval ...
  7. Enforce, Validate, Observe: 3 LLM Structured Output ...
  8. A complete guide to RAG evaluation: metrics, testing and ...
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles