DS DevShelfHub Projects · AI tools
Tutorials / LangChain / Prompt Templates
LangChain Intermediate · 11 min read Page 3 of 20

LangChain Prompt Templates: From Basics to Structured Outputs

By DevShelfHub

PromptTemplate, ChatPromptTemplate, few-shot prompts, structured outputs, guardrails, and debugging tips.

Series progress3 / 20
LangChain prompt templates — PromptTemplate, ChatPromptTemplate, and structured outputs

PromptTemplate

A PromptTemplate is a string with named placeholders. You fill them in at runtime.

python
from langchain_core.prompts import PromptTemplate

template = PromptTemplate.from_template(
    "You are a helpful assistant. Answer this question: {question}"
)

prompt = template.invoke({"question": "What is LangChain?"})

Use PromptTemplate when working with plain LLMs (text-in). For chat models, use ChatPromptTemplate.

ChatPromptTemplate

Chat models expect a list of messages. ChatPromptTemplate lets you template that list with variables.

python
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are an expert in {topic}. Be concise."),
    ("human", "{question}"),
])

chain = prompt | llm | StrOutputParser()
chain.invoke({"topic": "Python", "question": "What is a decorator?"})

The system message sets the context; the human message is the user's input. Both accept variables.

Few-shot prompts

Show the model examples of the input/output pattern you expect. This significantly improves output quality for structured tasks.

python
from langchain_core.prompts import FewShotChatMessagePromptTemplate

examples = [
    {"input": "happy", "output": "sad"},
    {"input": "tall",  "output": "short"},
]

example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"), ("ai", "{output}")
])

few_shot_prompt = FewShotChatMessagePromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
)

final_prompt = ChatPromptTemplate.from_messages([
    ("system", "Give the antonym of the word."),
    few_shot_prompt,
    ("human", "{input}"),
])

Structured outputs (JSON mode)

Instead of parsing free text, you can tell the model to return a specific JSON schema every time. LangChain's .with_structured_output() handles this cleanly using Pydantic.

python
from pydantic import BaseModel
from langchain_openai import ChatOpenAI

class MovieReview(BaseModel):
    title: str
    rating: int      # 1–10
    summary: str

llm = ChatOpenAI(model="gpt-4o-mini")
structured_llm = llm.with_structured_output(MovieReview)

result = structured_llm.invoke("Review the movie Inception")
print(result.title)    # "Inception"
print(result.rating)   # 9
print(result.summary)  # "A mind-bending thriller..."

The model is forced to output valid JSON matching your Pydantic schema. No output parsing needed — you get a typed Python object back.

Guardrails & validation

Structured outputs give you implicit validation — if the model's output does not match the schema, LangChain raises an error. For explicit guardrails, add validators to your Pydantic model:

python
from pydantic import BaseModel, field_validator

class MovieReview(BaseModel):
    title: str
    rating: int
    summary: str

    @field_validator("rating")
    @classmethod
    def rating_in_range(cls, v):
        if not 1 <= v <= 10:
            raise ValueError("Rating must be between 1 and 10")
        return v

If the model returns a rating of 11, the validator rejects it before it reaches your code. Combine with LangChain's .with_retry() to automatically ask the model to try again.

Prompt debugging tips

1. Print the rendered prompt before sending

print(prompt.invoke({"topic": "Python", "question": "..."}))

Always verify the prompt looks exactly as intended before debugging the model's output.

2. Enable verbose mode

from langchain.globals import set_verbose
set_verbose(True)

Prints every prompt and response to the console as they happen. Turn off in production.

3. Use LangSmith for tracing

Set LANGCHAIN_TRACING_V2=true and LANGCHAIN_API_KEY to get a full trace of every chain run in the LangSmith UI — inputs, outputs, latency, token counts.

4. Test prompts in isolation

Before adding a prompt to a chain, invoke it standalone with llm.invoke(prompt.invoke({...})). Isolate whether the issue is the prompt or the chain.

Quick summary

  • Use ChatPromptTemplate for all modern chat models
  • Few-shot examples dramatically improve output quality for structured tasks
  • .with_structured_output(PydanticModel) returns typed Python objects, no parsing needed
  • Add field_validator to enforce output constraints and combine with .with_retry()
  • Debug with set_verbose(True) locally and LangSmith in production

LangChain Prompt Templates FAQ

What is a PromptTemplate in LangChain?

A PromptTemplate is a string with named placeholders that you fill in at runtime, such as 'Answer this question: {question}'. You build it with PromptTemplate.from_template() and call .invoke() with a dict of values. Use it with plain text-in LLMs; for chat models, use ChatPromptTemplate instead.

What is the difference between PromptTemplate and ChatPromptTemplate?

PromptTemplate produces a single string for text-in LLMs. ChatPromptTemplate produces a list of role-tagged messages (system, human, ai) for modern chat models like GPT-4o and Claude. Since nearly all current models are chat models, ChatPromptTemplate is what you should use for new projects.

How do I get structured JSON output from a LangChain prompt?

Call .with_structured_output(YourPydanticModel) on the chat model. LangChain forces the model to return JSON matching your Pydantic schema and gives you back a typed Python object — no manual parsing. Add field validators to your model to reject invalid values automatically.

What is a few-shot prompt in LangChain?

A few-shot prompt includes a handful of example input/output pairs so the model learns the pattern you expect. In LangChain you build these with FewShotChatMessagePromptTemplate, which injects the examples into the prompt. Few-shot examples noticeably improve output quality on structured tasks.

How do I debug LangChain prompts?

Print the rendered prompt with prompt.invoke({...}) before sending it, enable set_verbose(True) to log every prompt and response locally, use LangSmith tracing in production by setting LANGCHAIN_TRACING_V2=true, and test prompts in isolation before adding them to a chain.

Quick jump: API Reference