Prompt templates and chains
Build prompts that stay clean at scale, then compose them into chains with the pipe operator instead of nested function calls.
Prompts as reusable templates
A prompt template is a function from variables to messages. Keeping it separate from the call site means you can version it, test it with different inputs, and reuse it across scripts without copy-paste drift.
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
prompt = ChatPromptTemplate.from_messages([
("system", "You are a terse technical editor. Return the rewritten text only."),
("human", "Rewrite for clarity and keep every fact:\n\n{draft}"),
])
chain = prompt | ChatOpenAI(model="gpt-4o-mini", temperature=0) | StrOutputParser()
print(chain.invoke({"draft": "The system does the thing where it retries on failure."}))| Method | Returns | When to use |
|---|---|---|
| invoke | One result | Single input, the default call |
| batch | A list of results | Offline scoring; runs requests concurrently |
| stream | Chunks as they arrive | Anything a human is waiting on |
| ainvoke / abatch | Awaitable versions | Inside async web handlers |
| with_retry | A wrapped runnable | Flaky providers; retry with backoff |
| with_fallbacks | A wrapped runnable | Primary model unavailable or rate-limited |
The same Runnable interface is implemented by prompts, models, parsers and retrievers, which is what makes | work everywhere. Composition is lazy: nothing runs until you call invoke.
Composing and branching
from langchain_core.runnables import RunnableParallel, RunnablePassthrough, RunnableLambda
clean = RunnableLambda(lambda d: d["text"].strip())
chain = RunnableParallel(
summary=clean | summary_chain,
keywords=clean | keyword_chain,
original=RunnablePassthrough(), # pass the input through unchanged
)
out = chain.invoke({"text": " Long report body ... "})
print(out.keys()) # dict_keys(['summary', 'keywords', 'original'])- Put the variable instruction last in the prompt. Instructions buried above a long document are followed less reliably.
- Use an explicit output parser (
StrOutputParser,JsonOutputParser) rather than reading raw message objects. - Keep one chain per responsibility. A chain that retrieves, classifies, writes and emails is untestable.
- Log the fully rendered prompt in development - most prompt bugs are formatting bugs, not model bugs.
💡
A chain guarantees order, not correctness. If the model must return JSON, parse it and validate against a schema; a well-formed prompt is a request, not an enforced contract.
FAQ
How do I use few-shot examples without bloating the prompt?
Use a few-shot prompt template holding a small, role-tagged example list. Two or three well-chosen examples that cover the hard cases usually beat twenty easy ones.
Do I need LangChain at all?
No. A prompt string and an HTTP call are often enough. It earns its place when you want uniform streaming, batching, retries, fallbacks and tracing across several providers.
Related
Tools and agents Using a model API
Last refreshed 2026-09-18.