Course Content
LangChain Mastery
7 sections · 109 lessons
How do you implement a custom prompt template with dynamic inputs?
What you need to know
"Dynamic input" means a value that is not simply passed in by the caller. There are three levels, from least to most code.
- Partial with a function — for values that are the same kind every time, such as the date or the app version.
- A step that computes variables — for values that need a lookup: documents, user profile, prices.
- An example selector or a custom class — when which examples or sections appear depends on the input.
Levels 1 and 2 together
1from datetime import date2from langchain_core.prompts import ChatPromptTemplate3from langchain_core.runnables import RunnablePassthrough45prompt = ChatPromptTemplate.from_messages([6 ("system", "Today is {today}. Label the enquiry hot, warm or cold. "7 "Current offers: {offers}"),8 ("human", "{enquiry}"),9]).partial(today=lambda: date.today().isoformat())1011build = RunnablePassthrough.assign(offers=lambda x: active_offers(x["city"])) | prompt12chain = build | llm | parser13chain.invoke({"enquiry": "2BHK in HSR, ready to book this week", "city": "Bengaluru"})partial(today=...) with a function means the date is fresh on every call, not frozen at start-up. RunnablePassthrough.assign keeps the original input and adds an offers key computed from city. The active_offers function can be tested on its own, without a model.
Level 3: examples chosen per input
1from langchain_core.example_selectors import SemanticSimilarityExampleSelector2from langchain_core.prompts import FewShotChatMessagePromptTemplate34selector = SemanticSimilarityExampleSelector.from_examples(5 examples, embeddings, InMemoryVectorStore, k=2, input_keys=["enquiry"])6few_shot = FewShotChatMessagePromptTemplate(7 example_selector=selector,8 example_prompt=ChatPromptTemplate.from_messages(9 [("human", "{enquiry}"), ("ai", "{label}")]),10 input_variables=["enquiry"],11)Put few_shot between the system and human messages. For each new enquiry, the selector embeds it and inserts the 2 most similar labelled examples.
Keep validation working
LangChain checks that every variable in the template is supplied. That check is what catches a renamed key before the model sees a literal {offers}. Keep variable names in one place and test the prompt with a sample input.
A real-life example
A real-estate firm's lead-qualification prompt labels website enquiries. With 6 fixed examples, it mislabelled villa enquiries, because all 6 examples were about flats. The team built a bank of 120 labelled enquiries and used a semantic example selector with k=3, so a villa question now sees villa examples. They also added the current offers per city through RunnablePassthrough.assign, because "no brokerage this month" changes how urgent a lead is. On 400 held-out enquiries, "hot" precision rose from 72% to 84%, and the prompt stayed shorter than before because it holds 3 examples instead of 6.
Follow-up questions to expect
- "Partial with a value or with a function?" — A value is fixed when you call
partial; a function runs on every format, which is what you want for time or anything that changes. - "When would you subclass
BasePromptTemplate?" — Rarely: only when prompt building is complex enough to need its own class. A function step before the prompt is usually clearer. - "How do you stop the prompt from growing too large?" — Limit
k, trim long inputs, or use a length-based example selector with a token budget.