Foundations 6 min read Updated Sep 8, 2026

Prompts, Models & Output Parsers

Almost every LangChain project you'll build starts with the same three pieces, piped together: a prompt template, a model, and something that shapes the model's reply into what your code actually needs. Get comfortable with this trio and you can build a surprising amount before you ever need anything fancier.

Prompt templates: reusable prompts with blanks to fill in

Instead of string-concatenating your prompt by hand every time, a ChatPromptTemplate lets you define the shape once, with variables you fill in per call:

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a concise assistant. Answer in one sentence."),
    ("human", "{question}"),
])

For anything conversational, you'll also reach for MessagesPlaceholder, which reserves a spot in the template for a whole list of prior messages - the chat history - rather than a single string variable.

Models: one interface, swap providers freely

LangChain's chat model classes all implement the same interface, so a chain built against one provider works against another with essentially a one-line change:

from langchain.chat_models import init_chat_model

model = init_chat_model("claude-sonnet-5", model_provider="anthropic")
# swapping to a different provider is just a different string here

init_chat_model is the current recommended entry point precisely because it keeps that provider choice as configuration rather than baked into your imports - handy when you want to compare models or swap providers without touching the rest of your chain.

Output parsers: turning a reply into something usable

A raw model response is a message object, not automatically the plain string or structured value your downstream code wants. That's what output parsers are for.

For plain text, StrOutputParser just extracts the text content:

from langchain_core.output_parsers import StrOutputParser

chain = prompt | model | StrOutputParser()
answer = chain.invoke({"question": "What's LCEL in one line?"})

For anything you actually want to use programmatically - a category, a confidence score, a list of extracted fields - the current recommended path is with_structured_output, which takes a schema (usually a Pydantic model) and gets the model to return data matching it directly, rather than you writing a custom parser to coax structure out of free text:

from pydantic import BaseModel

class Sentiment(BaseModel):
    label: str      # "positive", "neutral", or "negative"
    confidence: float

structured_model = model.with_structured_output(Sentiment)
result = (prompt | structured_model).invoke({"question": review_text})
print(result.label, result.confidence)
StrOutputParser with_structured_output input Prompt template Model any provider Text plain string Structured typed object

Same prompt and model, two different endings - which parser you attach decides what shape comes out.

Putting it together, and streaming it

Every piece above is a Runnable, which is why they pipe together so cleanly - and it's also why every chain you build this way automatically gets a few things for free, including .stream() for token-by-token output instead of waiting for the whole response:

for chunk in chain.stream({"question": "Explain RAG in two sentences."}):
    print(chunk, end="", flush=True)
Where to go from here: once your prompt needs to reference your own documents instead of just the user's question, you're stepping into retrieval - covered next.
Share this guide

Was this guide helpful?

Thanks for the feedback!

Want more hands-on AI builds like this?

APA Mastery runs live, practical sessions on working with modern AI tools - not just theory.

See What's On →
← PreviousWhat Is LangChain? (And How It Relates To LangGraph)