Topic 7.3
Expanding the Query
In one line
Expansion adds words or text to the query so it can match passages written in other words: synonyms and acronyms, or a short guessed answer that is embedded instead of the question. It raises recall, and it can also pull in noise.
Think of it like this
You look for a pair of trainers in a shop where the sign says "sports shoes". If you also search for "sneakers", "sports shoes" and "running shoes", you find them. Expansion is that habit: think of the other names for the thing before you walk the aisles.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Query expansion
- Adding words or text to a query so it can match passages written differently.
- Synonym
- A different word with a similar meaning, such as "refund" and "money back".
- Acronym
- A short form made of initials or abbreviations, such as "pw" for password.
- HyDE
- Hypothetical Document Embeddings: embed a model's guessed answer instead of the question.
- Recall
- Of the passages that should be found, how many were found.
- Precision
- Of the passages returned, how many were useful.
- Term weight
- How much a word counts in the score. Added words can count less than the user's.
Step by step
01Step 1: see why it is needed
"refund if I cancel" finds nothing by keywords. The handbook says "refunded" and "cancelled". The words are the same family, but a keyword search compares exact tokens.
02Step 2: write the expansion table
A dictionary from a word to related words. Keep it small and about your own domain. Weights: the user's words 1.0, added words 0.5.
EXPAND = {
"refund": ["refunded", "credit"],
"cancel": ["cancelled", "cancellations"],
"pw": ["password", "reset"],
"charge": ["fee", "charged", "cost", "dollars"],
}03Step 3: run and watch recall and precision
The first two questions go from nothing to the right passage. The third already worked and now gets two irrelevant passages in its top three. The same tool helped twice and hurt once.
04Step 4: try the other kind, a guessed answer
Instead of adding words, ask a model to write a short plausible answer, and search with that. The question is vague. The guess talks about late fees, in the style of the handbook.
05Step 5: test the guess on a question the handbook cannot answer
The dog question has no answer in the handbook. The question itself shows no signal, but the guess matches a fee passage strongly. A guess can make an unanswerable question look answerable.
06Step 6: use real vectors
Open the first lab. A real model ranks the damage passage above the late-fee passage for the plain question and gets it right for a one-sentence guess. The lab shows real scores. The toy shows why.
Try it yourself
- 1
Break the weights
In the first example change the added weight from 0.5 to 1.0. Which question changes? Is the noise in the battery question now worse?
- 2
Add one more expansion
Add
"scooter": ["bike"]to the table and ask"scooter helmet". Is the answer right? Think about what it does to a user who asked about scooters. - 3
Write a bad guess
In the HyDE example, change the guess for the first question to
"Helmets are free with every rental.". Predict the best hit and run. What does that say about trusting the guess? - 4
Use the lab
In the lab, write a guess of your own for the damage question and watch the scores. How short can the guess be before the late-fee passage loses the lead?
Code & diagrams
Scores are sums of weights: 1.0 for the user's words, 0.5 for added words. The top-3 list for the battery question shows the noise the expansion adds.
Expected output
Q: refund if I cancel
added words: cancelled cancellations refunded credit
plain top 3: none
expanded top 3: D1 (2.0)
Q: pw help
added words: password reset
plain top 3: none
expanded top 3: D3 (1.0)
Q: how long does the battery charge last
added words: fee charged cost dollars
plain top 3: D7 (2.0)
expanded top 3: D7 (2.0), D6 (1.0), D5 (0.5)A toy: six hand-made word groups (money, time, account, damage, safety, battery), summed and normalised. A real model has hundreds of learned directions. The guesses are scripted. Real scores are in the lab.
Expected output
question: What happens if I'm slow getting back?
search: D2 1.000, D9 1.000, D6 0.962
guess: Returning the bike late costs extra, a fee for every 15 minutes after the booked end time.
search: D6 1.000, D1 0.983, D2 0.962
question: Can I take my dog along?
search: no signal
guess: Pets are not allowed on the bike and a cleaning fee of 20 dollars applies.
search: D8 0.970, D12 0.514, D4 0.500Try: The question "Why was I charged extra after my ride?" does not retrieve the late-fee passage first. Replace it with a short sentence a helpful assistant might guess as the answer (do not copy the handbook). Does the late-fee passage reach the top?
Goals
- The late-return passage is the best match
Press Search. Then change one thing (a word in the question, a passage, the ranker) and compare the scores.
Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Let added words count as much as real words
In the Python tab, change the weight of added words in expand: replace weights.setdefault(extra, 0.5) with weights.setdefault(extra, 1.0). Run.
Myth vs fact
Myth
More query words always means better recall without cost.
Fact
Added words also match passages you did not want. Recall can rise while precision falls.
Myth
HyDE means the model knows the answer.
Fact
The guess is written without your documents and may be wrong. It is only used as a better-shaped search text.
Myth
Embeddings make synonyms unnecessary.
Fact
Embeddings handle common synonyms well, but company acronyms, product codes and rare jargon can still be missed.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Mine your expansion table from data: search logs with no clicks, questions that scored low, and the words support staff use. Do not write it from imagination.
- ▸
Keep the plain query in the mix. Search with the original and the expansion and fuse the lists (Topic 7.4). Replacing the original is what makes expansion dangerous.
- ▸
HyDE costs one generation call per question, with the delay of a full model call. Run it only when the plain search is weak, for example when the top score is under a threshold you measured.
Remember this
- 1
Why expansion exists. Rewriting repairs the question. Expansion goes further and adds to it, because the words in the question may never appear in the right passage. "refund" against "refunded", "pw" against "password", "money back" against "refunded in full". Keyword search is hit hardest (Topic 1.6), but embedding models also have gaps for company acronyms and jargon they never saw.
- 2
Synonyms and acronyms from a table. The simplest expansion is a hand-kept dictionary:
refundalso meansrefundedandcredit,pwalso meanspasswordandreset. The example weights the user's own words 1.0 and added words 0.5, so an expansion can help find a passage but cannot outvote the user's own words. For "refund if I cancel" the plain search finds nothing and the expanded search finds D1 (the refunds passage) with score 2.0. - 3
Weights matter, and so does restraint. The third question in the example, "how long does the battery charge last", already retrieves the right passage (D7 with 2.0). Expanding
chargeintofee,charged,costanddollarskeeps D7 first but fills the rest of the top three with fee passages (D6 at 1.0 and D5 at 0.5). Precision at three dropped: two of the three results are now irrelevant. The wordchargehas two meanings in this handbook (battery and fees), and a table cannot tell which one the user meant. - 4
Hypothetical document embeddings (HyDE). A different kind of expansion: ask a model to *guess the answer*, then embed that guess and search with it instead of (or next to) the question. A question and its answer are different kinds of text, and a guessed answer is written in the same style as the passages. The guess may be wrong in detail and still right in topic. For "What happens if I'm slow getting back?" the toy embedder has almost no signal in the question: it ties D2 and D9 at the top. The guess about a late fee puts D6 first.
- 5
HyDE can invent a topic. Look at the second case in the same example: "Can I take my dog along?" The handbook says nothing about pets. The question has no signal at all, which is honest. The model's guess ("a cleaning fee of 20 dollars applies") has a lot of signal, so retrieval returns D8, the monthly pass passage, with a score of 0.97: a confident match for a question the handbook cannot answer. A guess can create evidence that does not exist. Always keep a refusal check after retrieval (Topic 8.4).
- 6
The toy and the real thing. The embedder in the example is a toy: six hand-made word groups, summed and normalised. Its numbers are not what a real model returns. The lab below uses a real embedding model in your browser: the question "Why was I charged extra after my ride?" ranks the damage passage above the late-fee passage, and a one-sentence guess flips it. Use the toy to understand the idea and the lab to see real scores.
- 7
When expansion hurts precision. More query words mean more candidate passages, so the top of the list gets noisier. Expand only when the plain query finds nothing or a weak result, weight added terms lower than the user's own, cap the number of added terms, and measure precision as well as recall (Topic 9.3). Combining the plain list and the expanded list with fusion (Topic 7.4) is gentler than replacing one with the other.
Explain it without notes
What problem does query expansion solve, and what is the risk?
Explain HyDE in your own words. Why can a guess retrieve better than the question?
Give a situation where HyDE makes things worse.
How would you stop expansion from lowering precision?
Practice
Write expand(words, table) that returns the words followed by the table's extra words for each of them, without repeats and keeping order. Print the result for ["refund", "cancel"] with table = {"refund": ["refunded", "credit"], "cancel": ["cancelled"]}.
Write score(weights, text) that sums the weights of the words of weights (a dict) found in the text. Print the score of the late-fee sentence for {"late": 1.0, "fee": 0.5, "charged": 0.5}.
Trade-offs
- ↔
A synonym table: cheap and controllable, but it needs upkeep and cannot choose a sense for an ambiguous word.
- ↔
HyDE: bridges question-to-passage style, but costs a model call and can invent evidence.
- ↔
Replacing the query with an expansion versus fusing both: replacing is simpler, fusing is safer.
Done when you can
Done when you can expand a query with weighted synonyms and acronyms.
Done when you can explain HyDE and name its main risk.
Done when you can show with numbers that an expansion lowered precision.
Done when you can say when to expand and when to leave the query alone.