Templates separate prompt wording from data and plug directly into chains.
A prompt template turns a dict of variables into model input. ChatPromptTemplate.from_messages takes a list of (role, template) pairs whose {placeholders} are filled at run time:
prompt = ChatPromptTemplate.from_messages([
("system", "You translate to {language}."),
("human", "{text}"),
])
prompt.invoke({"language": "French", "text": "Good morning"})The result is a ChatPromptValue; .to_messages() shows the messages that will be sent.
Useful features:
MessagesPlaceholder("history")inserts a whole list of messages, e.g. chat history or agent scratchpad. Useoptional=Trueif it may be absent.prompt.partial(language="French")pre-fills some variables, returning a new template.prompt.input_variableslists what the template needs; missing variables raise aKeyErrorat invoke time.- Literal braces in the text must be doubled:
{{and}}, which matters when prompts contain JSON examples. Alternatively usetemplate_format="jinja2"or"mustache".
Templates are runnables, so they compose with models using | (next lesson). For simple single-message prompts, ChatPromptTemplate.from_template("Summarize: {text}") creates a template with one human message.
Keep prompts in code or a prompt registry under version control; small wording changes can shift quality significantly.
Example
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", 'You are a {role}. Answer in {language} as JSON: {{"answer": ...}}'),
MessagesPlaceholder("history", optional=True),
("human", "{question}"),
])
print(sorted(prompt.input_variables)) # ['language', 'question', 'role']
support = prompt.partial(role="support agent", language="English")
value = support.invoke({
"history": [("human", "My order is late."), ("ai", "Sorry! Order number?")],
"question": "It's order 1234.",
})
for m in value.to_messages():
print(m.type, "|", m.content)
# system | You are a support agent. Answer in English as JSON: {"answer": ...}
# human | My order is late.
# ai | Sorry! Order number?
# human | It's order 1234.Remember
ChatPromptTemplate.from_messagesfills{variables}into role messagesMessagesPlaceholderinjects message lists such as historypartialpre-fills variables; double braces for literal{}in templates
Watch out for
- Putting raw JSON with single braces into a template, which LangChain then treats as variables and fails.