How to Intermediate · 3 min read

How to build multi-hop reasoning with DSPy

Quick answer
Use dspy to build multi-hop reasoning by defining multiple Signature classes representing each reasoning step and chaining them with dspy.ChainOfThought. This enables sequential AI calls where outputs from one step feed as inputs to the next, creating a multi-hop reasoning pipeline.

PREREQUISITES

  • Python 3.8+
  • OpenAI API key (free tier works)
  • pip install dspy openai>=1.0

Setup

Install dspy and openai packages, and set your OpenAI API key as an environment variable.

  • Run pip install dspy openai
  • Export your API key: export OPENAI_API_KEY='your_api_key' on Linux/macOS or set in Windows environment variables
bash
pip install dspy openai

Step by step

Define multiple dspy.Signature classes for each reasoning step, then chain them with dspy.ChainOfThought to perform multi-hop reasoning. The example below shows a two-step reasoning: first extracting key facts, then answering a question based on those facts.

python
import os
import dspy
from openai import OpenAI

# Configure DSPy with OpenAI LLM
lm = dspy.LM("openai/gpt-4o-mini", api_key=os.environ["OPENAI_API_KEY"])
dspy.configure(lm=lm)

# Step 1: Extract key facts from text
class ExtractFacts(dspy.Signature):
    text: str = dspy.InputField()
    facts: str = dspy.OutputField()

# Step 2: Answer question using extracted facts
class AnswerQuestion(dspy.Signature):
    facts: str = dspy.InputField()
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

# Define the multi-hop reasoning chain
class MultiHopReasoning(dspy.ChainOfThought):
    extract_facts = ExtractFacts()
    answer_question = AnswerQuestion()

    def __call__(self, text: str, question: str) -> str:
        # Step 1: Extract facts
        facts_result = self.extract_facts(text=text)
        # Step 2: Answer question using facts
        answer_result = self.answer_question(facts=facts_result.facts, question=question)
        return answer_result.answer

# Instantiate the chain
chain = MultiHopReasoning()

# Example input
input_text = (
    "Marie Curie was a physicist and chemist who conducted pioneering research on radioactivity."
)
input_question = "What field did Marie Curie contribute to?"

# Run multi-hop reasoning
answer = chain(text=input_text, question=input_question)
print("Answer:", answer)
output
Answer: Marie Curie contributed to physics and chemistry, specifically in the field of radioactivity.

Common variations

You can extend multi-hop reasoning by adding more Signature classes for additional reasoning steps. Use async calls with dspy by defining async methods and calling await. You can also switch models by changing the LM initialization, e.g., to openai/gpt-4o for stronger reasoning.

python
import asyncio

async def async_multi_hop():
    # Async version of the chain call
    answer = await chain.acall(text=input_text, question=input_question)
    print("Async answer:", answer)

asyncio.run(async_multi_hop())
output
Async answer: Marie Curie contributed to physics and chemistry, specifically in the field of radioactivity.

Troubleshooting

  • If you get API authentication errors, verify OPENAI_API_KEY is set correctly in your environment.
  • If outputs are empty or irrelevant, increase max_tokens or adjust prompt templates inside your Signature classes.
  • For rate limits, add retry logic or reduce request frequency.

Key Takeaways

  • Use multiple dspy.Signature classes to represent each reasoning step.
  • Chain steps with dspy.ChainOfThought to enable multi-hop reasoning pipelines.
  • Configure dspy with an OpenAI LLM for seamless AI calls.
  • Support async and different models by adjusting dspy.LM and method calls.
  • Handle API errors by verifying keys and tuning prompt parameters.
Verified 2026-04 · openai/gpt-4o-mini, openai/gpt-4o
Verify ↗