03. Prompt Templates

Chapter 3 of 18 · 20 min

Prompt templates convert hardcoded strings into parameterizable prompts. A template is a string with named placeholders that gets rendered with runtime values at invocation time. LangChain provides two core template classes: PromptTemplate (for standard completion-style prompts) and ChatPromptTemplate (for multi-message chat workflows). This chapter covers PromptTemplate; ChatPromptTemplate gets its own chapter.

The basic pattern:

from langchain.prompts import PromptTemplate

template = PromptTemplate.from_template(
    "Translate this text to {target_language}: {text}"
)

# Render with runtime values
rendered = template.invoke({
    "target_language": "French",
    "text": "Hello, how are you?"
})
print(rendered)
# PromptTemplate(input_variables=['target_language', 'text'], template='Translate...')

The .invoke() method returns a PromptValue object. To get the raw string for inspection:

print(rendered.to_string())
# Translate this text to French: Hello, how are you?

print(rendered.to_messages())
# [HumanMessage(content='Translate this text to French: Hello, how are you?')]

You can also construct the template with explicit input variable declarations:

template = PromptTemplate(
    input_variables=["topic", "tone"],
    template="Write a {tone} tweet about {topic}."
)

Explicit declaration is useful when from_template would incorrectly infer input variables from a string that contains ambiguous placeholders.

For composing templates (a common pattern when building multi-step chains), use PipelinePromptTemplate:

from langchain.prompts import PipelinePromptTemplate, PromptTemplate

# Partial prompt: a variable used in multiple composite prompts
intro_template = PromptTemplate.from_template(
    "You are an expert {field} analyst."
)

# Main prompt that uses the partial variable
main_prompt = PromptTemplate.from_template(
    "{intro}\n\nNow answer this question: {question}"
)

pipeline_prompt = PipelinePromptTemplate(
    final_prompt=main_prompt,
    pipeline_prompts=[
        ("intro", intro_template),
        ("question", PromptTemplate.from_template("{question}"))
    ]
)

rendered = pipeline_prompt.invoke({
    "field": "financial",
    "question": "What is compound interest?"
})
print(rendered.to_string())
# You are an expert financial analyst.
# Now answer this question: What is compound interest?

One practical use: standardizing system prompts across chains so you don't copy-paste the same instructions into every llm.invoke() call.

Failure mode: if a required input variable is missing from the dict you pass to .invoke(), LangChain raises KeyError with a message that names the missing key. The traceback points to prompt.invoke(...) directly, so the fix is obvious—but only if you pass a complete dict.

For creating templates from a file on disk (useful for long system prompts you want to edit without touching code):

    file.Path("prompts/summarizer.txt").read_text()
)

Ensure the file exists and contains {variable_names} matching your input variables. LangChain does not validate this at construction time—only at invoke time.

EXERCISE

Create a PromptTemplate that accepts language, task, and audience variables. Render it with language="Python", task="raise an exception", and audience="new developers". Print the rendered string.