Providing Input to LLMs: Exploring Prompt Templates and Message Wrappers
💡 1. What is PromptTemplate?
A PromptTemplate is a fixed prompt text combined with dynamic user-provided input variables. This allows for flexible and reusable prompts in LLM-based applications.
💡 2. More templates
Different types of prompt templates serve various AI use cases:
ChatPromptTemplate:
A structured template for building multi-turn conversations.
It helps organize messages for chat models, ensuring that each role (e.g., system, user, assistant) is clearly defined.
FewShotPromptTemplate:
Includes example inputs and outputs to guide the model.
This helps improve accuracy by providing context on how to respond based on prior examples.
💡 3. Message wrapper class
Message wrappers assign one of the predefined roles - USER, SYSTEM, or AI - to a prompt template. These roles help guide the model’s behavior and responses.
Key message wrapper classes:
HumanMessage:
Assigns the user role to the prompt, helping the LLM understand the user’s query.
SystemMessage:
Uses the system role to provide instructions or context, guiding the model’s behavior.
AIMessage:
Assigns the AI role for the model’s response, maintaining chat history and providing continuity in the conversation.
1. PromptTemplate
LangChain’s prompt templates are a powerful feature that helps developers structure prompts efficiently. A prompt template acts as a blueprint for crafting precise queries to a Large Language Model (LLM), ensuring more useful responses.
Instead of manually writing a new prompt each time, you can create a template with placeholders that dynamically insert specific details as needed. This approach improves consistency, reusability, and efficiency in AI-driven applications.
🧠Mental Model : Prompt Templates as Fill-in-the-Blanks
Think of a prompt template like a fill-in-the-blank worksheet.
Instead of writing a full sentence from scratch every time, you use a predefined structure with blanks that can be filled based on the context.
This ensures that prompts are consistent, reusable, and adaptable across different queries.
📗 Example : Product Description Prompt Template
Imagine you’re building an app that asks LLMs for product descriptions. Instead of writing the full prompt every time, you use a prompt template that dynamically fills in the product name each time you call it.
from langchain.prompts import PromptTemplate
# Create the template with a placeholder {product_name}
template = PromptTemplate.from_template("Write a short description of the product called {product_name}.")
# Use the template with a specific product name
formatted_prompt = template.format_prompt(product_name="Smartphone")
llm.invoke(formatted_prompt)
Here, we used the .from_template()
function because it’s the easiest way to create a prompt template
when you only need to substitute simple placeholders. It allows you to quickly define a template with
placeholders and fill them in when needed.
1.2. PromptTemplate constructor
Another option to create a PromptTemplate
object is by passing the template string as an argument to the constructor. This method is simple and straightforward, especially when you want to define a template inline.
# Example 1. Basic PromptTemplate
template = PromptTemplate(
template="Tell me a {adjective} joke about {content}.",
input_variables=["adjective", "content"]
)
# Example 2. PromptTemplate with partial_variables
template = PromptTemplate(
template="Tell me a {adjective} joke about {content}. (Version {version})",
input_variables=["adjective", "content"],
# Fixed value i.e. output parsing instructions
partial_variables={"version": "1.0"}
)
# Example 3. Dynamic prompt
def dynamic_prompt(topic, include_explanation):
prompt = f"Tell me about {topic}."
if include_explanation:
prompt += " Explain it in detail."
return prompt
template = PromptTemplate(
template=dynamic_prompt,
input_variables=["topic", "include_explanation"]
)
1.3. .invoke
vs .format_prompt
to get formatted prompt message
Both functions .invoke
and .format_prompt
creates PromptValue
which then passed to LLM
Key Differences:
.invoke():
Use when you want to execute the chain and get a response.
.format_prompt():
Use when you need to prepare a prompt with placeholders for dynamic values.
template = PromptTemplate
.from_template("Tell me a {adjective} joke about {content}.")
# Using .invoke
formatted_template = template
.invoke({"adjective": "hilarious", "content": "dogs"}).text
# Using .format_prompt
final_prompt = template
.format_prompt(adjective="hilarious", content="dogs")
llm.invoke(formatted_template)
2. More prompt templates
Two other popular classes are ChatPromptTemplate
and FewShotPromptTemplate
. They help organize how you ask the
model questions or provide additional information. This makes it easier to interact with LLMs in different
contexts, whether it’s for simple conversations or more complex tasks.
2.1. ChatPromptTemplate
Used for creating prompts that involve a conversation between a user and a model. It helps structure the dialogue so the model can understand the flow. Think of it as a template for writing questions and answers in a chat.
📗 Example : Chat Prompt Template with Multiple Templates
Chat prompt templates can include multiple predefined templates, each assigned to a specific role (e.g., system, user). This allows structured interactions between the user and the LLM.
from langchain.prompts import ChatPromptTemplate
# Define a chat prompt template with system and user messages
prompt_template = ChatPromptTemplate([
("system", "You are a helpful assistant"),
("user", "Tell me a joke about {topic}")
])
# Format the prompt with a specific topic
formatted_chat_prompt = prompt_template.invoke({"topic": "cats"})
llm.invoke(formatted_chat_prompt)
2.2. FewShot PromptTemplate
Used when you want to give the model a few examples
before asking it to do something. This helps the model
understand the task better
by seeing how it’s done with a few examples
. It’s like showing the model examples
before asking it to make its own guess.
📗 Example : Few-Shot Prompt for Product Descriptions
This example uses a Few-Shot Prompt Template to generate product descriptions based on past examples. Instead of relying on a single prompt, it provides multiple example-product pairs to guide the LLM in producing more relevant and natural responses.
from langchain.prompts import PromptTemplate, FewShotPromptTemplate
# Defines how each example looks
example_prompt = PromptTemplate.from_template("Product: {product}\nDescription: {description}")
# Examples of past product descriptions
few_shot_examples = [
{
"product": "Wireless Noise-Canceling Headphones",
"description": "Experience immersive sound with industry-leading noise cancellation. Enjoy up to 30 hours of battery life and seamless Bluetooth connectivity."
},
{
"product": "Ergonomic Office Chair",
"description": "Designed for comfort and productivity, this chair features adjustable lumbar support, breathable mesh fabric, and a smooth reclining function."
},
{
"product": "Smart Water Bottle",
"description": "Stay hydrated effortlessly! This bottle tracks your water intake and glows to remind you when it’s time to drink. BPA-free and rechargeable."
}
]
# Create a Few-Shot Prompt Template using the examples
few_shot_template = FewShotPromptTemplate(
examples=few_shot_examples,
example_prompt=example_prompt,
suffix="Product: {input}\nDescription:", # What LLM should generate
input_variables=["input"]
)
# Format the prompt with a specific product
formatted_prompt = few_shot_template.format_prompt(input="Portable Espresso Maker")
llm.invoke(formatted_prompt)
3. Message class
Messages are similar to PromptTemplate, but they come with predefined roles (such as system, user, and assistant) and can also include metadata. They help structure conversations in a way that aligns with how LLMs (like ChatGPT) process chat-style interactions.
🧠Mental Model : Messages as Role-Based Communication
Think of Messages like actors in a play, each with a specific role.
SystemMessage is the director giving instructions to shape how the AI should behave.
HumanMessage is the actor delivering lines to move the conversation forward.
AIMessage is the assistant responding with scripted or dynamic dialogue.
ToolMessage is like a background crew member supplying external data for the AI to use.
RemoveMessage is the editor, cutting unnecessary parts of the script to keep the conversation focused.
This structured interaction ensures the AI follows a logical, well-defined, and context-aware flow in chat-based applications.
3.1. HumanMessage
and SystemMessage
HumanMessage
– Represents user input. Used when a human asks a question or provides input to the AI.
SystemMessage
– Sets the AI’s behavior. Used to define the assistant’s role or personality.
human_message = HumanMessage(
content="Tell me about the history of artificial intelligence."
)
system_message_professional = SystemMessage(
content="You are a highly professional assistant who provides detailed and formal responses."
)
system_message_casual = SystemMessage(
content="You are a fun and casual AI that explains things in a simple, friendly way."
)
out = llm.invoke([system_message_professional, human_message])
3.2. AIMessage
AIMessage represents the LLM’s response. It is used for storing and managing LLM-generated responses. Unlike HumanMessage, which captures user input, AIMessage explicitly defines what the model has said to ensure a natural conversation flow.
LangChain is a Python framework for developing applications powered by large language models (LLMs).
Core features include prompt structuring, output formatting, and chaining operations. More advanced workflows support tools integration, memory, data loaders, and decision-making to create more dynamic and sophisticated applications.
3.3. Why Use AIMessage
Maintaining conversation history:
Storing AI-generated responses helps in multi-turn interactions.
Providing consistent replies:
Ensuring that the AI’s response is retained for future context.
Logging AI outputs:
Tracking responses for debugging, analytics, or user experience improvements.
Chaining responses:
Using previous AI responses as input for follow-up queries.
ChatPromptTemplate + AIMessage
You can use ChatPromptTemplate
to structure conversations while incorporating previous AIMessage responses to maintain history.
chat_prompt = ChatPromptTemplate.from_messages([
SystemMessage(content="You are an AI tutor helping with Python."),
HumanMessage(content="How do I create a list in Python?"),
AIMessage(content="You can create a list using square brackets, like this: my_list = [1, 2, 3]."),
HumanMessage(content="How can I add an item to it?"),
("assistant", "{response}") # AI's new response
])
3.4. ToolMessage
ToolMessage
represents a response from a tool or function within a LangChain conversation.
It is similar to AIMessage, but instead of coming from the LLM, it stores results from an external tool (e.g., a math function, API call, or database query).
Useful for storing intermediate steps when the AI delegates a task to a tool.
3.5. RemoveMessage
RemoveMessage is a special message type in LangChain that does not correspond to any roles. It acts as a placeholder to remove specific messages from a conversation history before passing it to an LLM.