cd /news/large-language-models/langchain-series-3-prompts-explained… · home topics large-language-models article
[ARTICLE · art-25778] src=pub.towardsai.net pub= topic=large-language-models verified=true sentiment=↑ positive

LangChain Series #3: Prompts Explained — Prompt Templates, Chat Prompts, Dynamic Prompting…

LangChain introduces dynamic prompt templates and chat prompts to improve LLM output quality. The framework supports PromptTemplate for reusable dynamic prompts and ChatPromptTemplate for chat models with message history. These tools enable developers to generate customized instructions and manage conversations efficiently.

read6 min publishedJun 12, 2026

No matter how powerful a model is, the quality of its output depends heavily on the instructions you provide.

In LangChain, prompts are much more than simple strings. They allow developers to dynamically generate instructions, manage conversations, inject chat history, and even enforce structured outputs.

A prompt is an instruction, question, or input given to a model to guide its response.

For example:

Explain what a Transformer model is.              orSummarize the Attention Is All You Need paper.

The model uses this prompt as context to generate an output.

One of the first concepts to understand is the difference between static and dynamic prompting.

Static prompts use hardcoded instructions. Only the user input changes while the prompt structure remains the same.

Example:

user_input = "Attention Is All You Need"
prompt = f"Summarize this topic: {user_input}"

Generated prompt:

Summarize this topic: Attention Is All You Need

Why is it called Static?

Because the structure never changes.

Summarize this topic:

will always remain the same.

** Limitations of Static Prompts: **While simple, static prompts have several drawbacks:

This is where Prompt Templates become useful.

Dynamic prompts generate instructions at runtime. Instead of hardcoding values, placeholders are used and filled dynamically.

Example:

Explain the research paper {paper}in a {style} stylewith a {length} explanation.

Generated prompt:

Explain the research paper Attention Is All You Needin a Beginner-Friendly stylewith a Long explanation.

The prompt changes based on user selections.

LangChain provides PromptTemplate to create reusable dynamic prompts.

from langchain_core.prompts import PromptTemplatetemplate = PromptTemplate(    input_variables=[        "paper",        "style",        "length",        "style_instruction"    ],    validate_template=True,    template="""Please summarize the research paper titled "{paper}"Explanation Style: {style}Explanation Length: {length}Style Guidelines:{style_instruction}""")

Create once and use many times.

PromptTemplate checks missing variables.

validate_template=True

helps catch mistakes early.

Prompt Templates work seamlessly with:

Updating a single template updates your entire application.

The template can be populated using:

final_prompt = template.invoke({    "paper": paper_input,    "style": style_input,    "length": length_input,    "style_instruction": style_instructions[style_input]})

This creates a customized prompt based on user selections.

Traditional LLMs accept plain text:

Input ↓String ↓Output

Chat Models work differently.

They accept a sequence of messages.

System MessageHuman MessageAI Message

and return an AI response.

LangChain provides three primary message types.

from langchain_core.messages import (    SystemMessage,    HumanMessage,    AIMessage)

Defines the model’s behavior.

SystemMessage(    content="You are a concise AI assistant.")

Represents user input.

HumanMessage(    content="Tell me about LangChain.")

Stores previous responses.

AIMessage(    content=response.content)

ChatPromptTemplate helps create dynamic prompts for chat models.

Example from our project:

from langchain_core.prompts import ChatPromptTemplatechat_template = ChatPromptTemplate([    ('system', 'You are a helpful {domain} expert'),    ('human', 'Explain in simple terms what is {topic}')])prompt = chat_template.invoke({    'domain': 'machine learning',    'topic': 'diffusion models'})

Instead of managing message objects manually, we can generate them dynamically.

Benefits:

Real chatbots need conversation history.

LangChain solves this using: MessagesPlaceholder

Example:

from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholderchat_template = ChatPromptTemplate([    ('system', 'You are a helpful customer support agent'),    MessagesPlaceholder(        variable_name='chat_history'    ),    ('human', '{query}')])

They allow dynamic insertion of:

without manually rebuilding prompts every time.

This becomes extremely useful in: Chatbots, Agents, Customer Support Systems

So far, our models have returned plain text responses.

Example:

The sentiment of the review is positive.

While this is easy for humans to read, it is difficult for applications to process programmatically.

Imagine building:

Instead of plain text, we often need structured data like:

{    "sentiment": "positive",    "summary": "The product received favorable feedback."}

This is where Structured Outputs and Output Parsers become useful.

Structured Outputs allow LLMs to return data in predefined formats.

Instead of generating free-form text, we define a schema that the model should follow.

    User Input       ↓      LLM       ↓Structured Response

LangChain supports multiple ways to define these structures.

** TypedDict: **Use TypedDict when:-

Example:

from typing import TypedDictclass Person(TypedDict):    name: str    age: int

Why TypedDict Has No Validation

Consider:

person = {    "name": "Bob",    "age": "25"}

Even though age should be an integer, TypedDict will not raise an error.

This is because TypedDict provides type hints but does not validate data.

** Pydantic Models: **Use Pydantic when:-

Example:

from pydantic import BaseModelclass Student(BaseModel):    name: str    age: int = 18

Why Use Pydantic?

** JSON Schema: **Another popular approach is JSON Schema.

Example:

{  "title": "student",  "type": "object",  "properties": {    "name": "string",    "age": "integer"  },  "required": ["name"]}

When Should You Use JSON Schema?

What if the model cannot generate structured output natively?

This is where Output Parsers come in.

Output Parsers convert raw LLM responses into structured formats.

LLM Output     ↓Output Parser     ↓Structured Data

LangChain provides multiple output parsers.

** String Output Parser: **The simplest parser. It converts model responses into plain strings.

Example:

from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpointfrom dotenv import load_dotenvfrom langchain_core.prompts import PromptTemplateload_dotenv()llm = HuggingFaceEndpoint(    repo_id="google/gemma-2-2b-it",    task="text-generation")model = ChatHuggingFace(llm=llm)# 1st prompt -> detailed reporttemplate1 = PromptTemplate(    template='Write a detailed report on {topic}',    input_variables=['topic'])# 2nd prompt -> summarytemplate2 = PromptTemplate(    template='Write a 5 line summary on the following text. /n {text}',    input_variables=['text'])prompt1 = template1.invoke({'topic':'black hole'})result = model.invoke(prompt1)prompt2 = template2.invoke({'text':result.content})result1 = model.invoke(prompt2)print(result1.content)

This parser is commonly used inside chains.

** JSON Output Parser: **JSON Output Parser converts responses into JSON objects.

Example:

from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpointfrom dotenv import load_dotenvfrom langchain_core.prompts import PromptTemplatefrom langchain_core.output_parsers import JsonOutputParserload_dotenv()llm = HuggingFaceEndpoint(    repo_id="Qwen/Qwen2.5-7B-Instruct",    task="text-generation")model = ChatHuggingFace(llm=llm)json_parser = JsonOutputParser()template = PromptTemplate(    template='Give me 5 facts about {topic} \n {format_instruction}',    input_variables=['topic'],    partial_variables={'format_instruction': json_parser.get_format_instructions()})# prompt = template.format()# model_output = model.invoke(prompt)# final_result = json_parser.parse(model_output.content)chain = template | model | json_parserchain_result = chain.invoke({'topic': 'Origami'})print(chain_result)

The parser automatically injects formatting instructions into the prompt.

Why Use JsonOutputParser?

** Structured Output Parser: **StructuredOutputParser allows us to define required fields explicitly.

Example:

from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpointfrom dotenv import load_dotenvfrom langchain_core.prompts import PromptTemplatefrom langchain_classic.output_parsers.structured import StructuredOutputParser, ResponseSchemaload_dotenv()llm = HuggingFaceEndpoint(    repo_id="Qwen/Qwen2.5-7B-Instruct",    task="text-generation")model = ChatHuggingFace(llm=llm)response_schema = [    ResponseSchema(name="fact1", description="The first fact about the topic"),     ResponseSchema(name="fact2", description="The second fact about the topic"),    ResponseSchema(name="fact3", description="The third fact about the topic"),    ResponseSchema(name="fact4", description="The fourth fact about the topic"),        ResponseSchema(name="fact5", description="The fifth fact about the topic")]parser = StructuredOutputParser.from_response_schemas(response_schema)template = PromptTemplate(    template='Give me 5 facts about {topic} \n {format_instruction}',    input_variables=['topic'],    partial_variables={'format_instruction': parser.get_format_instructions()})chain = template | model | parserchain_result = chain.invoke({'topic': 'Origami'})print(chain_result)

** Pydantic Output Parser: **PydanticOutputParser combines structure and validation.

Example:

from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpointfrom dotenv import load_dotenvfrom langchain_core.prompts import PromptTemplatefrom langchain_core.output_parsers import PydanticOutputParserfrom pydantic import BaseModel, Fieldload_dotenv()llm = HuggingFaceEndpoint(    repo_id="Qwen/Qwen2.5-7B-Instruct",    task="text-generation")model = ChatHuggingFace(llm=llm)class Person(BaseModel):    name: str = Field(description='Name of the person')    age: int = Field(gt=18, description='Age of the person')    city: str = Field(description='Name of the city the person belongs to')parser = PydanticOutputParser(pydantic_object=Person)template = PromptTemplate(    template='Generate the name, age and city of a fictional {place} person \n {format_instruction}',    input_variables=['place'],    partial_variables={'format_instruction':parser.get_format_instructions()})chain = template | model | parserfinal_result = chain.invoke({'place':'sri lankan'})print(final_result)

Structured outputs make LLM responses predictable and easier to integrate into applications.

LangChain provides multiple approaches:

Understanding these tools is essential when building reliable AI applications that need structured, machine-readable data rather than free-form text.

In the next article, we’ll dive into Chains in LangChain and learn how to combine prompts, models, and output parsers into powerful end-to-end AI pipelines using LCEL.

**Code Repository: **https://github.com/Atul245/LangChain-for-developers

If you found this article helpful, consider:

⭐ Starring the repository

🍴 Forking the repository

👤 Following me for more content on LangChain, Generative AI, and AI Engineering

Connect with me on LinkedIn: https://www.linkedin.com/in/atulkumar8/

🚀 LangChain Series #3: Prompts Explained — Prompt Templates, Chat Prompts, Dynamic Prompting… was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

── more in #large-language-models 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/langchain-series-3-p…] indexed:0 read:6min 2026-06-12 ·