Skip to main content
HomeTutorialsArtificial Intelligence (AI)

Prompt Chaining Tutorial: What Is Prompt Chaining and How to Use It?

Prompt chaining is a technique that involves breaking down a complex task into a series of smaller, interconnected prompts, where the output of one prompt serves as the input for the next, guiding the LLM through a structured reasoning process.
Jul 9, 2024  · 19 min read

Have you ever tried assembling a piece of furniture without reading the instructions? If you're lucky, you might get some parts together, but the result can be pretty messy without step-by-step guidance. This is similar to the challenge faced by large language models (LLMs) when they tackle complex problems. These models have incredible potential, but they often miss the mark when a task requires detailed, multi-step reasoning.

When given a single prompt, LLMs might provide answers that are too broad, lack depth, or miss critical details. This limitation stems from the difficulty in capturing all necessary context and providing adequate guidance within a single prompt.

The solution to this is prompt chaining.

Prompt chaining involves breaking down a complex task into a series of smaller, more manageable prompts. Each prompt tackles a specific part of the task, and the output from one prompt serves as the input for the next. This method allows for a more structured approach, guiding the LLM through a chain of reasoning steps that lead to a more accurate and comprehensive answer. Using a logical sequence of prompts, we can fully use LLMs to effectively solve complex problems.

This tutorial is part of my “Prompt Engineering: From Zero to Hero” series of blog posts:

  1. Prompt Engineering for Everyone
  2. Zero-Shot Prompting
  3. Few-Shot Prompting
  4. Prompt Chaining

What Is Prompt Chaining?

Prompt chaining is a method where the output of one LLM prompt is used as the input for the next prompt in a sequence. This technique involves creating a series of connected prompts, each focusing on a specific part of the overall problem. Following this sequence allows the LLM to be guided through a structured reasoning process, helping it produce more accurate and detailed responses.

The main purpose of prompt chaining is to improve the performance, reliability, and clarity of LLM applications. For complex tasks, a single prompt often doesn't provide enough depth and context for a good answer. Prompt chaining solves this by breaking the task into smaller steps, ensuring each step is handled carefully. This method improves the quality of the LLM output and makes it easier to understand how the final result was reached.

Let’s take a look at some of the benefits of prompt chaining:

Benefit

Description

Example

Breaks Down Complexity

Decomposes complex tasks into smaller, manageable subtasks, allowing the LLM to focus on one aspect at a time.

Generating a research paper step-by-step (outline, sections, conclusion) instead of all at once.

Improves Accuracy

Guides the LLM's reasoning through intermediate steps, providing more context for precise and relevant responses.

Diagnosing a technical issue by identifying symptoms, narrowing down causes, and suggesting solutions.

Enhances Explainability

Increases transparency in the LLM's decision-making process, making it easier to understand how conclusions are reached.

Explaining a legal decision by outlining relevant laws, applying them to a case, and reaching a conclusion with each step clearly documented.

How to Implement Prompt Chaining

Implementing prompt chaining involves a systematic approach to breaking down a complex task and guiding an LLM through a series of well-defined steps. 

Let’s see how you can effectively create and execute a prompt chain.

Identify subtasks

The first step in prompt chaining is decomposing the complex task into smaller, manageable subtasks. Each subtask should represent a distinct aspect of the overall problem. This way, the LLM can focus on one part at a time.

For example, suppose you want the LLM to write a comprehensive report on climate change. The subtasks could include:

  • Researching historical climate data
  • Summarizing key findings from scientific literature
  • Analyzing the impact of climate change on different ecosystem
  • Proposing potential solutions and mitigation strategies

Design prompts

Next, design clear and concise prompts for each subtask. Each prompt should be specific and direct, ensuring that the LLM understands the task and can generate relevant output. Importantly, the output of one prompt should be suitable as input for the next, creating a flow of information.

For our subtasks above, we could create the following prompts:

  • Subtask 1 Prompt: "Summarize the key trends in global temperature changes over the past century."
  • Subtask 2 Prompt: "Based on the trends identified, list the major scientific studies that discuss the causes of these changes."
  • Subtask 3 Prompt: "Summarize the findings of the listed studies, focusing on the impact of climate change on marine ecosystems."
  • Subtask 4 Prompt: "Propose three strategies to mitigate the impact of climate change on marine ecosystems based on the summarized findings."

Chain execution

Now, we need to execute the prompts sequentially, passing the output of one prompt as the input to the next. This step-by-step execution ensures that the LLM builds upon its previous outputs, creating a cohesive and comprehensive result.

For our example, the outputs for our subtasks would look something like this:

  • Output of Subtask 1: "The global temperature has risen by approximately 1.2 degrees Celsius over the past century, with significant increases observed in the past 20 years."
  • Input for Subtask 2: "Given that global temperatures have risen by 1.2 degrees Celsius over the past century, list the major scientific studies that discuss the causes of these changes."
  • Output of Subtask 2: "Key studies include: 'The Role of Greenhouse Gases in Global Warming' by Dr. Smith, 'Deforestation and Climate Change' by Dr. Jones, and 'Oceanic Changes and Climate Patterns' by Dr. Lee."
  • Input for Subtask 3: "Summarize the findings of 'The Role of Greenhouse Gases in Global Warming' by Dr. Smith, 'Deforestation and Climate Change' by Dr. Jones, and 'Oceanic Changes and Climate Patterns' by Dr. Lee, focusing on the impact of climate change on marine ecosystems."

Error handling

Implementing error-handling mechanisms is key to addressing potential issues during prompt execution. This can include setting up checks to verify the quality and relevance of the output before proceeding to the next prompt and creating fallback prompts to guide the LLM back on track if it deviates from the expected path. For example:

  • Error Check 1: After each output, verify that the information is relevant and complete. If the summary of trends in global temperature changes is incomplete, prompt the LLM to provide additional details.
  • Fallback Prompt: If the LLM fails to list relevant scientific studies, use a more specific prompt such as "List five peer-reviewed studies from the past decade that discuss the causes of global temperature rise."

Implementation

Let’s see how to implement this in Python!

Step 1: Setting up the environment

First, we need to import the required libraries. We'll use the OpenAI class from the openai package and os to handle environment variables.

import openai
import os

Storing sensitive information, like API keys, securely is crucial. One way to achieve this is by setting the API key as an environment variable. You can do it by using an OpenAI API key.

os.environ['OPENAI_API_KEY'] = 'your-api-key-here'

Make sure to replace 'your-api-key-here' with your actual OpenAI API key.

With the API key set, you can now initialize the OpenAI client. This client will be used to make API calls to OpenAI’s services.

Client = OpenAI ()

Step 2: Defining a function to interact with OpenAI's chat completions API.

Now, we’ll create a Python function to interact with OpenAI's chat completions API. This function will prompt the API and return the generated response.

def get_completion(prompt, model="gpt-3.5-turbo"):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=[
                {"role": "system", "content": "You are a helpful assistant."},
                {"role": "user", "content": prompt}
            ],
            temperature=0,
        )
        return response.choices[0].message.content
    except Exception as e:
        print(f"An error occurred: {e}")
        return None

Let’s break down this function—it:

  • Takes a prompt and an optional model parameter.
  • Makes an API call to OpenAI using the chat completions endpoint.
  • Sets up the conversation with a system message and a user message (the prompt)
  • Sets the temperature to 0 for more deterministic outputs (increase the temperature for more creative outputs).
  • Returns the response's content or None if an error occurs.

Step 3: Chaining multiple prompts

Now, we'll create a Python function that chains together multiple prompts, feeding the output of one prompt as the input to the next.

def prompt_chain(initial_prompt, follow_up_prompts):
    result = get_completion(initial_prompt)
    if result is None:
        return "Initial prompt failed."
    print(f"Initial output: {result}\n")
    for i, prompt in enumerate(follow_up_prompts, 1):
        full_prompt = f"{prompt}\n\nPrevious output: {result}"
        result = get_completion(full_prompt)
        if result is None:
            return f"Prompt {i} failed."
        print(f"Step {i} output: {result}\n")
    return result

The prompt_chain function implements prompt chaining. It:

  • Starts with an initial prompt and gets its completion.
  • Iterates through a list of follow-up prompts.
  • For each follow-up prompt, it combines the prompt with the previous output, gets a completion for this combined prompt, and updates the result.
  • If any step fails, it returns an error message.
  • The output of each step is printed for visibility.

Step 4: Example usage

We’ll now demonstrate how to use the prompt_chain function to create a sequence of prompts that build on each other. This example will focus on summarizing key trends in global temperature changes and exploring related scientific studies and mitigation strategies, but you can apply it to your own use case!

initial_prompt = "Summarize the key trends in global temperature changes over the past century."
follow_up_prompts = [
    "Based on the trends identified, list the major scientific studies that discuss the causes of these changes.",
    "Summarize the findings of the listed studies, focusing on the impact of climate change on marine ecosystems.",
    "Propose three strategies to mitigate the impact of climate change on marine ecosystems based on the summarized findings."
]
final_result = prompt_chain(initial_prompt, follow_up_prompts)
print("Final result:", final_result)

Here, we define an initial prompt about global temperature changes, and then we set up a list of follow-up prompts that build on each other. Next, we call the prompt_chain function with these prompts and, finally, we print the final result.

How it works together

Let’s summarize the process:

  1. The initial prompt gets a summary of temperature trends.
  2. The first follow-up uses this summary to find relevant studies.
  3. The second follow-up summarizes these studies' findings about marine ecosystems.
  4. The final prompt uses all this information to propose mitigation strategies.

This chaining allows for a step-by-step approach to complex queries, where each step builds on the information from the previous steps.

Prompt Chaining Techniques

Prompt chaining can be implemented in various ways to suit different types of tasks and requirements. Here, we explore three primary techniques: Sequential Chaining, Conditional Chaining, and Looping Chaining.

Sequential chaining

Sequential chaining involves linking prompts in a straightforward, linear sequence. Each prompt depends on the output of the previous one, creating a step-by-step flow of information and tasks. This technique is ideal for tasks that require a logical progression from one stage to the next, such as:

  • Text summarization: Breaking down a long document into summarized sections, then combining those summaries into a cohesive overall summary.
  • Code generation: Generating code snippets step-by-step, such as first creating function definitions, then implementing those functions, and finally writing test cases.

The code snippet in the previous section is an example of sequential chaining.

Conditional chaining

Conditional chaining introduces branching into the prompt chain based on the LLM's output. This technique allows for more flexible and adaptable workflows, enabling the LLM to take different paths depending on the responses it generates.

Let’s see how we can implement conditional chaining to perform sentiment analysis.

def analyze_sentiment(text):
    prompt = f"Analyze the sentiment of the following text and respond with only one word - 'positive', 'negative', or 'neutral': {text}"
    sentiment = get_completion(prompt)
    return sentiment.strip().lower()

def conditional_prompt_chain(initial_prompt):
    result = get_completion(initial_prompt)
    if result is None:
        return "Initial prompt failed."
    print(f"Initial output: {result}\n")
    sentiment = analyze_sentiment(result)
    print(f"Sentiment: {sentiment}\n")
    if sentiment == 'positive':
        follow_up = "Given this positive outlook, what are three potential opportunities we can explore?"
    elif sentiment == 'negative':
        follow_up = "Considering these challenges, what are three possible solutions we can implement?"
    else:  # neutral
        follow_up = "Based on this balanced view, what are three key areas we should focus on for a comprehensive approach?"
    final_result = get_completion(f"{follow_up}\n\nContext: {result}")
    return final_result

# Example usage
initial_prompt = "Analyze the current state of renewable energy adoption globally."
final_result = conditional_prompt_chain(initial_prompt)
print("Final result:", final_result)

First, we define a new function, analyze_sentiment(), that uses the language model to determine the sentiment of a given text. Then, in the conditional_prompt_chain() function, we start with the initial prompt about renewable energy adoption. After getting the initial response, we analyze its sentiment. Based on the sentiment, we choose a different follow-up prompt:

  •  For a positive sentiment, we ask about opportunities.
  •  For a negative sentiment, we ask about solutions.
  •  For a neutral sentiment, we ask about key focus areas.

The chosen follow-up prompt is then sent to the language model along with the context from the initial response. The final result is the response to this conditional follow-up prompt.

Notice that the choice of the second prompt is not predetermined but depends on the content of the first response. Also, the flow of the conversation adapts based on the sentiment analysis, showing how the chain can branch into different paths. This allows for more dynamic and context-aware interactions with the language model.

When you run this code, the specific follow-up question will depend on whether the initial analysis of renewable energy adoption is perceived as positive, negative, or neutral. This creates a more adaptive and responsive chain of prompts.

Looping chaining

Looping chaining involves creating loops within a prompt chain to iterate over data or perform repetitive tasks. This technique is useful when dealing with lists or collections of items that require similar processing steps. Some of the benefits and challenges of this approach are:

  • Efficiency: Automates repetitive tasks, saving time and effort.
  • Data processing: Suitable for tasks like processing multiple records, batch summarization, or iterative improvements.
  • Challenges: Requires careful handling to avoid infinite loops and ensure that each iteration produces meaningful progress.

Let’s see how looping chaining would be implemented for a text completeness task:

def check_completeness(text):
    prompt = f"Analyze the following text and respond with only 'complete' if it covers all necessary aspects, or 'incomplete' if more information is needed:\n\n{text}"
    response = get_completion(prompt)
    return response.strip().lower() == 'complete'

def looping_prompt_chain(initial_prompt, max_iterations=5):
    current_response = get_completion(initial_prompt)
    if current_response is None:
        return "Initial prompt failed."
    print(f"Initial output: {current_response}\n")
    iteration = 0
    while iteration < max_iterations:
        if check_completeness(current_response):
            print(f"Complete response achieved after {iteration + 1} iterations.")
            return current_response
        print(f"Iteration {iteration + 1}: Response incomplete. Expanding...")
        expand_prompt = f"The following response is incomplete. Please expand on it to make it more comprehensive:\n\n{current_response}"
        new_response = get_completion(expand_prompt)
        if new_response is None:
            return f"Expansion failed at iteration {iteration + 1}."
        current_response = new_response
        print(f"Expanded response: {current_response}\n")
        iteration += 1
    print(f"Maximum iterations ({max_iterations}) reached without achieving completeness.")
    return current_response

# Example usage
initial_prompt = "Explain the process of photosynthesis."
final_result = looping_prompt_chain(initial_prompt)
print("Final result:", final_result)

First, we define a new function, check_completeness(), that uses the language model to determine if a given response is complete or needs more information.

Then, in the looping_prompt_chain() function, we start with the initial prompt about photosynthesis. After getting the initial response, we enter a loop:

  • We check if the current response is complete using check_completeness().
  • If it's complete, we exit the loop and return the result.
  • If it's incomplete, we generate a new prompt asking to expand on the previous response.
  • We then get a new response based on this expansion prompt.

This process continues until we get a response deemed complete or reach the maximum number of iterations (default is 5).

The loop ensures that we keep refining and expanding the response until it's considered complete or we hit the iteration limit.

When you run this code, it will attempt to provide a comprehensive explanation of photosynthesis, potentially going through multiple iterations of expansion if the initial responses are deemed incomplete. This creates a more thorough and adaptive chain of prompts, aiming for a comprehensive final result.

Practical Applications of Prompt Chaining

Prompt chaining can significantly enhance the capabilities of LLMs across various applications. In this section, we explore some practical uses of prompt chaining, demonstrating how it can be applied to real-world tasks.

Question answering over documents

Prompt chaining can be used to summarize long documents and then generate answers to specific questions. This involves first breaking down the document into manageable sections, summarizing each section, and then using these summaries to answer detailed questions.

Let’s see how to implement this:

def split_document(document, max_length=1000):
    """Split the document into sections of approximately max_length characters."""
    words = document.split()
    sections = []
    current_section = []
    current_length = 0
    for word in words:
        if current_length + len(word) + 1 > max_length and current_section:
            sections.append(' '.join(current_section))
            current_section = []
            current_length = 0
        current_section.append(word)
        current_length += len(word) + 1
    if current_section:
        sections.append(' '.join(current_section))
    return sections

def summarize_section(section):
    prompt = f"Summarize the following text in a concise manner:\n\n{section}"
    return get_completion(prompt)

def answer_question(summaries, question):
    context = "\n\n".join(summaries)
    prompt = f"Given the following context, answer the question:\n\nContext:\n{context}\n\nQuestion: {question}"
    return get_completion(prompt)

def document_qa(document, questions):
    # Step 1: Split the document
    sections = split_document(document)
    print(f"Document split into {len(sections)} sections.")
    # Step 2: Summarize each section
    summaries = []
    for i, section in enumerate(sections):
        summary = summarize_section(section)
        summaries.append(summary)
        print(f"Section {i+1} summarized.")
    # Step 3: Answer questions
    answers = []
    for question in questions:
        answer = answer_question(summaries, question)
        answers.append((question, answer))
    return answers

# Example usage
long_document = """
[Insert a long document here. For brevity, we are using a placeholder. 
In a real scenario, this would be a much longer text, maybe several 
paragraphs or pages about a specific topic.]
This is a long document about climate change. It discusses various aspects 
including causes, effects, and potential solutions. The document covers 
topics such as greenhouse gas emissions, rising global temperatures, 
melting ice caps, sea level rise, extreme weather events, impact on 
biodiversity, and strategies for mitigation and adaptation.
The document also explores the economic implications of climate change, 
international agreements like the Paris Agreement, renewable energy 
technologies, and the role of individual actions in combating climate change.
[Continue with more detailed information about climate change...]
"""
questions = [
    "What are the main causes of climate change mentioned in the document?",
    "What are some of the effects of climate change discussed?",
    "What solutions or strategies are proposed to address climate change?"
]
results = document_qa(long_document, questions)
for question, answer in results:
    print(f"\nQ: {question}")
    print(f"A: {answer}")

This code snippet demonstrates how prompt chaining can be used for complex tasks like document analysis and question answering. It breaks down a large task (understanding a long document) into smaller, manageable steps (summarizing sections). It uses the output of one step (summaries) as input for the next (answering questions). It allows for handling documents that might be too long to process in a single prompt.

When you run this code with a real, long document, it will split the document into manageable sections, summarize each section, and use these summaries to answer the provided questions about climate change causes, effects, and solutions.

Text generation with fact verification

Text generation with fact verification involves generating text and incorporating fact-checking steps within the prompt chain. This ensures the output is not only coherent but also accurate.

def generate_text(topic):
    prompt = f"Write a short paragraph about {topic}."
    return get_completion(prompt)

def extract_facts(text):
    prompt = f"Extract the key factual claims from the following text, listing each claim on a new line:\n\n{text}"
    return get_completion(prompt)

def verify_facts(facts):
    verified_facts = []
    for fact in facts.split('\n'):
        if fact.strip():
            prompt = f"Verify the following statement and respond with 'True' if it's factually correct, 'False' if it's incorrect, or 'Uncertain' if it can't be verified without additional research: '{fact}'"
            verification = get_completion(prompt)
            verified_facts.append((fact, verification.strip()))
    return verified_facts

def revise_text(original_text, verified_facts):
    context = "Original text:\n" + original_text + "\n\nVerified facts:\n"
    for fact, verification in verified_facts:
        context += f"- {fact}: {verification}\n"
    
    prompt = f"{context}\n\nRewrite the original text, keeping the verified facts, removing or correcting any false information, and indicating any uncertain claims as 'It is claimed that...' or similar phrasing."
    return get_completion(prompt)

def text_generation_with_verification(topic):
    print(f"Generating text about: {topic}")
    # Step 1: Generate initial text
    initial_text = generate_text(topic)
    print("\nInitial Text:")
    print(initial_text)
    # Step 2: Extract facts
    extracted_facts = extract_facts(initial_text)
    print("\nExtracted Facts:")
    print(extracted_facts)
    # Step 3: Verify facts
    verified_facts = verify_facts(extracted_facts)
    print("\nVerified Facts:")
    for fact, verification in verified_facts:
        print(f"- {fact}: {verification}")
    # Step 4: Revise text
    revised_text = revise_text(initial_text, verified_facts)
    print("\nRevised Text:")
    print(revised_text)
    return revised_text

# Example usage
topic = "the effects of climate change on polar bears"
final_text = text_generation_with_verification(topic)

The text_generation_with_verification() function manages the entire process. It starts by using generate_text() to create an initial paragraph about the topic. Then, extract_facts() pulls out key claims from this text. verify_facts() checks these claims, labeling them as True, False, or Uncertain. Lastly, revise_text() rewrites the original text, fixing any errors and noting uncertain information. This process helps ensure the final text is both informative and accurate.

The prompt chaining occurs in several steps: the initial text generation, fact extraction from the generated text, verification of each extracted fact, and revision of the text based on verified facts.

When you run this code with a topic like "the effects of climate change on polar bears," it will generate initial text about the topic, extract factual claims from this text, verify each of these claims, and revise the text based on the verified facts, ensuring a more accurate final output. Remember that you can use your own topic of choice!

Code generation with debugging

Using prompt chaining to write code and then test it can speed up development. This method helps make sure the code works properly and does what it's supposed to do. It goes beyond just making sure the code runs without errors.

def generate_code(task):
    prompt = f"Write a Python function to {task}. Include comments explaining the code."
    return get_completion(prompt)

def generate_test_cases(code):
    prompt = f"Given the following Python code, generate 3 test cases to verify its functionality. Include both input and expected output for each test case:\n\n{code}"
    return get_completion(prompt)

def run_tests(code, test_cases):
    prompt = f"""
    Given the following Python code and test cases, run the tests and report the results. 
    If any tests fail, explain why and suggest fixes.
    Code:
    {code}
    Test Cases:
    {test_cases}
    For each test case, respond with:
    1. "PASS" if the test passes
    2. "FAIL" if the test fails, along with an explanation of why it failed and a suggested fix
    """
    return get_completion(prompt)

def debug_code(code, test_results):
    prompt = f"""
    Given the following Python code and test results, debug the code to fix any issues.
    Provide the corrected code along with explanations of the changes made.
    Original Code:
    {code}
    Test Results:
    {test_results}
    """
    return get_completion(prompt)

def code_generation_with_debugging(task):
    print(f"Generating code for task: {task}")
    # Step 1: Generate initial code
    initial_code = generate_code(task)
    print("\nInitial Code:")
    print(initial_code)
    # Step 2: Generate test cases
    test_cases = generate_test_cases(initial_code)
    print("\nGenerated Test Cases:")
    print(test_cases)
    # Step 3: Run tests
    test_results = run_tests(initial_code, test_cases)
    print("\nTest Results:")
    print(test_results)
    # Step 4: Debug code if necessary
    if "FAIL" in test_results:
        print("\nDebugging code...")
        debugged_code = debug_code(initial_code, test_results)
        print("\nDebugged Code:")
        print(debugged_code)    
        # Optionally, you can run tests again on the debugged code
        print("\nRe-running tests on debugged code...")
        final_test_results = run_tests(debugged_code, test_cases)
        print("\nFinal Test Results:")
        print(final_test_results)    
        return debugged_code
    else:
        print("\nAll tests passed. No debugging necessary.")
        return initial_code

# Example usage
task = "calculate the factorial of a number"
final_code = code_generation_with_debugging(task)

The code_generation_with_debugging() function manages the whole process. It works like this: First, generate_code() writes some Python code for the task. Then, generate_test_cases() creates tests for this code. run_tests() checks if the code passes these tests. If any tests fail, debug_code() tries to fix the problems.

Note that each step builds on the last one. It starts with writing code, then makes tests, runs them, and fixes any issues. This breaks down coding into smaller, easier steps. This method shows how prompt chaining can handle complex tasks like coding. It copies how real programmers work: write code, test it, and fix any problems. Each step uses what came before, allowing for steady code improvement.

When you run this code with a task like "calculate the factorial of a number," it will generate initial Python code for calculating the factorial, create test cases for this function, simulate running these tests, and report the results. If any tests fail, it will attempt to debug and fix the code, then re-run the tests.

Multi-step reasoning tasks

Prompt chaining can solve complex problems requiring multiple reasoning steps, such as mathematical word problems or logical puzzles. Each step builds on the previous one, ensuring a structured and thorough approach.

def solve_step_by_step(problem):
    steps = []
    current_problem = problem
    while True:
        prompt = f"Solve the following problem step by step. Provide the next step only and explain it clearly:\n\n{current_problem}"
        step = get_completion(prompt)
        if step is None or "solution" in step.lower():
            break
        steps.append(step)
        current_problem = f"{current_problem}\n\n{step}"
        print(f"Step {len(steps)}: {step}\n")
    return steps

def combine_steps(steps):
    combined_steps = "\n".join(steps)
    prompt = f"Combine the following steps into a coherent solution for the problem:\n\n{combined_steps}"
    return get_completion(prompt)

def multi_step_reasoning(problem):
    print(f"Solving problem: {problem}")    
    # Step 1: Solve step by step
    steps = solve_step_by_step(problem)    
    # Step 2: Combine steps into a final solution
    final_solution = combine_steps(steps)
    print("\nFinal Solution:")
    print(final_solution)
    return final_solution

# Example usage
problem = "A car travels 60 miles per hour for 2 hours, then 40 miles per hour for 3 hours. What is the total distance traveled by the car?"
final_solution = multi_step_reasoning(problem)

First, solve_step_by_step() breaks down the problem into smaller parts. It asks the AI model for each step, one by one, until the solution is complete. Each step is saved. Then, combine_steps() takes all these steps and asks the AI to merge them into one clear explanation. The get_completion() function handles talking to the OpenAI API throughout this process.

For this example, it will solve this problem: "A car drives 60 miles per hour for 2 hours, then 40 miles per hour for 3 hours. How far does it go in total?"

When you run this code, it will break down the problem into smaller reasoning steps, collect and print each step, and combine the steps into a final solution and print it.

Best Practices for Prompt Chaining

It’s essential to follow certain best practices to maximize the effectiveness of prompt chaining. These practices ensure that your chains are robust, accurate, and efficient, leading to better outcomes and more reliable LLM applications.

Prompt design

Using clear and concise prompts is essential for getting the best results from an LLM. When your prompts are straightforward, the model can easily understand what you need, which reduces confusion and improves the quality of the responses.

Here are some tips:

  • Use simple language: Avoid complex words and technical jargon.
  • Be direct: Clearly state what you want without adding unnecessary details.
  • Focus on one task: Each prompt should address a single task or question. 

For example:

  • Instead of: "Can you please summarize the key points of the historical trends in global temperatures over the past century, focusing on any significant changes and their potential causes, as well as notable events that might have influenced these trends?"
  • Use: "Summarize the key points of historical global temperature trends over the past century."

Using well-structured prompts is also key to helping the LLM follow the logical flow of a task. When your prompts are organized and coherent, the model can better understand and respond appropriately.

Here are some tips:

  • Break down complex tasks: Divide the task into smaller, manageable steps.
  • Ensure logical flow: Make sure each prompt builds on the previous one and logically leads to the next.

Structuring your prompts this way guides the LLM through the task step-by-step, leading to better and more accurate responses. For example:

  • Step 1: "List the major changes in global temperatures over the past century."
  • Step 2: "Identify potential causes for each major change in global temperatures."

Experimentation

Different tasks need different ways of chaining prompts. Picking the right method for your task can make a big difference. It's a good idea to try out different approaches and see what works best for what you're trying to do. Testing and comparing can help you find the best way to get good results.

It's important to check how well your prompt chains are working often. Look at how accurate, complete, and relevant the outputs are. This helps you see what's working and what needs to be improved. By doing this regularly, you can make changes and improvements as needed and ensure you are getting the best results.

Iterative refinement

Iterative refinement based on feedback and results leads to more precise and effective prompts. You can continuously improve the performance of your LLM by collecting feedback from outputs, identifying shortcomings, and adjusting prompts accordingly. This ongoing process ensures that your prompts become increasingly accurate and relevant over time. For example:

  • Initial prompt: "Describe the impact of climate change."
  • Refined prompt: "Describe the impact of climate change on coastal ecosystems over the past decade."

Refine chain structure

How you arrange your prompt chain can really affect the end result. Changing the order and logic of your prompts is helpful based on what you see working. This makes sure each step makes sense after the one before it. When you do this, you can get better and more logical answers from the AI.

Error handling

Robust error handling ensures the prompt chain can continue functioning even if individual prompts fail. By setting up checks for output validity and using fallback prompts, you can guide the LLM back on track when errors occur. This approach maintains the flow and reliability of the prompt chain, ensuring consistent performance.

Monitoring and logging

It's important to keep an eye on how well your prompt chains are working. This helps you understand what's effective and spot any problems. Use tools to record important information like what goes into the prompts, what comes out, and how long it takes. For instance, write down each step of the chain, what it is produced, and any errors that happen. If you do this, you can study the process and make it better, leading to improved results.

Keeping detailed records helps you fix problems and make your prompt chains better. Store these records in a neat way so it's easier to study them and learn from them. This helps you spot issues and fine-tune your prompt chains. As a result, you can make them work better and give more accurate answers

Following these best practices will allow you to create effective and reliable prompt chains that improve the capabilities of LLMs, making sure that you get better performance and more meaningful results across various applications.

Conclusion

In this article, we explored prompt chaining, a technique for enhancing the performance of LLMs on complex tasks by breaking them into smaller, more manageable prompts. We covered different chaining methods, their applications, and best practices to help you effectively leverage LLMs for a wide range of use cases.

If you want to learn more about prompt engineering, I recommend these articles:

FAQs

Are there any frameworks or tools that facilitate prompt chaining for LLMs?

While there isn't a dedicated framework for prompt chaining, tools like LangChain, PyTorch, and TensorFlow can be used to implement and manage prompt chaining workflows, using their capabilities for handling sequential data and model outputs.

What are some alternative approaches to enhancing LLM performance besides prompt chaining?

Fine-tuning on domain-specific datasets, knowledge distillation, function integration, iterative refinement and parameter adjustment are some alternative approaches.

They offer unique benefits and can be used individually or in combination to improve LLM performance for specific tasks or use cases.

Can prompt chaining be integrated with automated systems for real-time applications?

Yes, prompt chaining can be integrated into automated systems such as chatbots, virtual assistants, and real-time data analysis platforms to enhance the accuracy and coherence of their responses and outputs.

What are the potential challenges of implementing prompt chaining in production environments?

Challenges include managing prompt dependencies, ensuring low latency for real-time applications, handling errors and incomplete outputs effectively, and maintaining the scalability and performance of the system as the complexity of tasks increases.


Photo of Dr Ana Rojo-Echeburúa
Author
Dr Ana Rojo-Echeburúa
LinkedIn
Twitter

Ana Rojo Echeburúa is an AI and data scientist with a PhD in Applied Mathematics. She loves turning data into actionable insights and has extensive experience leading technical teams. Ana enjoys working closely with clients to solve their business problems and create innovative AI solutions. Known for her problem-solving skills and clear communication, she is passionate about AI, especially large language models and generative AI. As the co-founder and CTO of Simpli, a Tech Insurance AI company, Ana is dedicated to continuous learning and ethical AI development, always pushing the boundaries of technology.

Topics

Learn more about AI!

Course

Understanding Prompt Engineering

1 hr
15.7K
Master ChatGPT for business and creativity: Learn prompt engineering, few-shot learning, and response evaluation.
See DetailsRight Arrow
Start Course
See MoreRight Arrow
Related

blog

Prompt Optimization Techniques: Prompt Engineering for Everyone

This article introduces you to prompt optimization, covering techniques such as being specific, providing context, defining the desired format, and using examples, as well as more advanced strategies like role-playing and chain-of-thought prompting.
Dr Ana Rojo-Echeburúa's photo

Dr Ana Rojo-Echeburúa

10 min

tutorial

An Introduction to Prompt Engineering with LangChain

Discover the power of prompt engineering in LangChain, an essential technique for eliciting precise and relevant responses from AI models.
Moez Ali's photo

Moez Ali

11 min

tutorial

Chain-of-Thought Prompting: Step-by-Step Reasoning with LLMs

Unlock the full potential of Large Language Models (LLMs) with our guide on Chain-of-Thought (CoT) prompting. Learn how to enhance reasoning and problem-solving abilities in LLMs.
Andrea Valenzuela's photo

Andrea Valenzuela

13 min

tutorial

Few-Shot Prompting: Examples, Theory, Use Cases

Few-shot prompting is a technique in which an AI model is given a few examples of a task to learn from before generating a response, using those examples to improve its performance on similar tasks.
Dr Ana Rojo-Echeburúa's photo

Dr Ana Rojo-Echeburúa

10 min

code-along

A Beginner's Guide to Prompt Engineering with ChatGPT

Explore the power of prompt engineering with ChatGPT.
Adel Nehme's photo

Adel Nehme

code-along

Advanced ChatGPT Prompt Engineering

In this session, you'll learn advanced prompting skills such as using prompt templates, testing the quality of your prompts, and working with images in prompts.
Isabella Bedoya's photo

Isabella Bedoya

See MoreSee More