Question Answering

Multi-hop questions

A multi-hop question needs facts from more than one place, answered in a chain — one lookup's answer becomes the next lookup's question.

On this page 5
  1. Why it exists
  2. How it works
  3. Where you have already seen it
  4. Remember this
  5. What to learn next

One lesson, three depths. Pick the one that fits you today — you can switch any time.

Beginner — No maths. Plain English.

A multi-hop question needs facts from more than one place, chained together to reach the final answer.

Think about finding a friend's phone number through a friend of a friend. You ask one person for a name. Then you ask someone else for that name's number. Neither person alone had the whole answer.

Why it exists

The extractive QA lessons so far assumed one passage holds the whole answer. Plenty of real questions do not work that way.

"In which city is the headquarters of the organisation that launched Chandrayaan-3?" needs two separate facts. One document says who launched Chandrayaan-3. A different document says where that organisation is headquartered. Neither document alone answers the question.

A system that only searches once, then answers, misses this entirely. It searches for something matching the whole question, and no single passage matches a question built from two different facts.

How it works

Question: "In which city is the headquarters of the organisation
           that launched Chandrayaan-3?"

Hop 1: "Who launched Chandrayaan-3?"
       -> search finds: "Chandrayaan-3 was launched by ISRO..."
       -> answer: ISRO

Hop 2: "Where is ISRO headquartered?"     <- built from hop 1's answer
       -> search finds: "ISRO is headquartered in Bengaluru..."
       -> answer: Bengaluru

Final answer: Bengaluru

Each hop is an ordinary, single-passage lookup. The chaining across hops is what makes the whole thing work.

Where you have already seen it

  • "Who is the CEO of the company that makes the iPhone?" A good answer here chains "iPhone maker" to "that company's CEO."
  • Genealogy research tools. Finding a great-grandparent's birthplace often chains through several intermediate family records.
  • AI research agents that "browse" multiple pages. Each page visited is often one hop in a longer chain.

Remember this

  • A multi-hop question needs facts from more than one source, combined in sequence.
  • One hop's answer often becomes the next hop's question.
  • A single-search system misses these questions entirely, because no one passage matches the whole thing.

What to learn next

Developer — Code and libraries.

This answers a multi-hop question by chaining two extractive QA calls, using the first hop's answer to build the second hop's question.

Setup

bash
pip install transformers torch

The first run downloads deepset/minilm-uncased-squad2, about 130 MB.

Chaining two hops

multi_hop.py
import torch
from transformers import AutoTokenizer, AutoModelForQuestionAnswering

name = "deepset/minilm-uncased-squad2"
tok = AutoTokenizer.from_pretrained(name)
model = AutoModelForQuestionAnswering.from_pretrained(name)
model.eval()

def answer(question, context):
    inputs = tok(question, context, return_tensors="pt")
    with torch.no_grad():
        out = model(**inputs)
    start = torch.argmax(out.start_logits)
    end = torch.argmax(out.end_logits) + 1
    if start == 0 and end == 1:
        return None
    return tok.decode(inputs["input_ids"][0][start:end]).strip()

context_a = "Chandrayaan-3 was launched by ISRO in July 2023 to study the Moon's south pole."
context_b = "ISRO is headquartered in Bengaluru, India, and was founded in 1969."

multi_hop_q = "In which city is the headquarters of the organisation that launched Chandrayaan-3?"

# Attempt 1: ask the multi-hop question directly, against context A alone
direct = answer(multi_hop_q, context_a)
print("direct attempt on context A only:", direct)

# Hop 1: find the organisation
hop1_q = "Who launched Chandrayaan-3?"
hop1_answer = answer(hop1_q, context_a)
print("hop 1 answer:", hop1_answer)

# Hop 2: build a new question from hop 1's answer, search a different context
hop2_q = f"Where is {hop1_answer} headquartered?"
hop2_answer = answer(hop2_q, context_b)
print("hop 2 question:", hop2_q)
print("hop 2 answer:  ", hop2_answer)
Output
direct attempt on context A only: None
hop 1 answer: isro
hop 2 question: Where is isro headquartered?
hop 2 answer:   bengaluru, india

Line by line

The direct attempt correctly returns None. Context A never mentions a headquarters city, so a well-behaved extractive model — the same abstention mechanism from the previous lesson — refuses to guess, rather than pointing at the wrong thing.

hop1_answer becomes part of hop2_q, built with an f-string. This is the entire multi-hop mechanism made visible: the second question is not written in advance. It is constructed at runtime, from the first hop's real output.

Hop 2 searches context_b, a different passage from hop 1. In a real system, this would be a fresh retrieval call — searching the whole corpus again with the new, hop-1-derived question — not a hardcoded second passage as shown here for clarity.

The final answer, "bengaluru, india," never appeared in context A, and the question of "which city" never appeared in context B alone. Neither passage alone could answer the original question.

Common mistakes

Assuming a single retrieval call will find both needed passages at once. A retriever matches the original question's wording against passages. "Chandrayaan-3" and "headquartered" rarely co-occur naturally in one passage, so a plain search often finds only context A, never context B, on the first attempt.

Chaining hops with no check on whether hop 1 actually succeeded. If hop1_answer is None, the code above would build the nonsensical question "Where is None headquartered?" Production chains check each hop's result before building the next one.

Assuming every question labelled "multi-hop" truly needs multiple hops. Some questions look complex but are answerable from one well-chosen passage. Decomposing unnecessarily adds cost and extra chances for one hop to fail.

Hard-coding the number of hops. Real multi-hop questions vary in depth — two hops, three hops, sometimes more. Production systems typically use a model to decide dynamically whether another hop is needed, rather than a fixed loop count.

Try it yourself

Swap context_b for a passage that does not mention ISRO's headquarters at all, and re-run.

Hop 2 should now return None, correctly — the retrieved passage for hop 2, in this rewritten version, does not contain the answer either. This is the realistic failure case: hop 1 succeeds, hop 2's retrieval fails to surface the right passage, and the overall chain still comes up empty.

What to learn next

Researcher — Mathematics and papers.

Formal structure

A multi-hop question Q decomposes into a chain of sub-questions q_1, ..., q_k, where each q_i for i > 1 is a function of the answer a_{i-1} to the previous sub-question: q_i = f(q_i, a_{i-1}). The final answer is a_k. This is a strict generalisation of the single-hop extractive setting from earlier lessons, which is the special case k = 1.

HotpotQA and the multi-hop benchmark literature

Yang, Qi, Zhang et al. (2018), HotpotQA: A Dataset for Diverse, Explainable Multi-hop Question Answering (arXiv:1809.09600), established the dominant benchmark for this task. Two features of its design matter beyond the multi-hop questions themselves. First, it requires supporting-fact labels — sentence-level annotations of which specific sentences, across which documents, justify the answer — which lets systems be scored on reasoning path quality, not only final-answer accuracy. Second, it includes distractor documents alongside the genuinely relevant ones, testing whether a system can identify the right two passages out of ten, not only reason correctly given the right two handed to it directly.

Two architectural approaches

Iterative retrieval, as implemented in the developer block, alternates retrieval and reading: retrieve, extract or generate an intermediate answer, formulate a new query from it, retrieve again. This is interpretable — each hop is inspectable — and its failure modes are localised to a specific hop, at the cost of compounding error: if hop 1's retrieval or extraction is wrong, hop 2 inherits that error with no mechanism to recover.

Joint multi-document reading, by contrast, retrieves a candidate set of passages once, concatenates or otherwise jointly encodes several of them, and performs reasoning within a single model call across all of them. This avoids compounding hop-wise error but requires the initial retrieval to have already surfaced every needed passage, since there is no second retrieval step to correct an initial miss.

Query reformulation as the hard sub-problem

The step f(q_i, a_{i-1}), building the next query, is the least well-solved part of the iterative approach. The developer block's f-string is deliberately naive, useful for exposition. Production systems generally use a language model to generate the next query, conditioned on the original question, the chain so far, and the last hop's answer — closer to the query rewriting covered in Handling "what about last year?", applied here across hops of one reasoning chain rather than across conversational turns.

Key references

  • Yang, Z., Qi, P., Zhang, S. et al. (2018). HotpotQA: A Dataset for Diverse, Explainable Multi-hop Question Answering. arXiv:1809.09600

Current state and open problems

Whether a given multi-hop benchmark genuinely requires multi-hop reasoning, rather than being solvable through single-hop shortcuts and dataset artefacts, has been a recurring methodological concern in the literature. Systems have been shown to score well on some multi-hop benchmarks using only one of the two required passages, exploiting statistical patterns rather than performing the intended reasoning chain. This means a high benchmark score is not, on its own, strong evidence that a system performs genuine multi-hop reasoning — a caution directly relevant to the next lesson's discussion of what benchmarks actually test.

What to learn next