Prompts, Parsers and Chains
Compose prompts, models and parsers with the pipe operator.
What you will learn
- Write prompt templates
- Get structured output
- Build a chain with LCEL
Hard-coding prompts as strings becomes messy fast. LangChain gives you reusable prompt templates, output parsers and a way to connect them into chains with the pipe operator, called LCEL (LangChain Expression Language).
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful {role}. Answer in at most {words} words."),
("human", "{question}"),
])
messages = prompt.invoke({"role": "teacher", "words": 30, "question": "What is recursion?"})A first chain
The pipe | feeds the output of one step into the next: prompt, then model, then parser.
from langchain_core.output_parsers import StrOutputParser
chain = prompt | llm | StrOutputParser()
print(chain.invoke({"role": "teacher", "words": 30, "question": "What is recursion?"}))StrOutputParser turns the model's message object into a plain string. Every chain built this way automatically supports invoke, stream, batch and async versions.
Structured output
Free text is hard for programs to use. Ask the model for data that matches a schema, and LangChain returns a validated object.
from pydantic import BaseModel, Field
class Review(BaseModel):
sentiment: str = Field(description="positive, negative or neutral")
score: int = Field(ge=1, le=5)
summary: str
structured = llm.with_structured_output(Review)
result = structured.invoke("The battery is great but the screen scratches easily.")
print(result.sentiment, result.score)
print(result.model_dump())neutral 3
{'sentiment': 'neutral', 'score': 3, 'summary': 'Great battery but a screen that scratches easily.'}from langchain_core.runnables import RunnablePassthrough, RunnableParallel
summarize = ChatPromptTemplate.from_template("Summarize in one line: {text}") | llm | StrOutputParser()
translate = ChatPromptTemplate.from_template("Translate to French: {text}") | llm | StrOutputParser()
both = RunnableParallel(summary=summarize, french=translate)
print(both.invoke({"text": "LangChain helps build LLM applications."}))RunnableParallel runs branches at the same time. Other useful runnables: RunnableLambda to wrap your own function, and RunnablePassthrough to carry inputs alongside results.
Prompt-writing tips
- Be specific about role, task, format and length.
- Give one or two examples (few-shot) when the format matters.
- Put untrusted user text in its own clearly labeled section to reduce prompt-injection risk.
- Version and test your prompts like code.
Set set_debug(True) from langchain.globals to print every step's inputs and outputs, or use tracing (covered in a later lesson).
Try it yourself
Build a chain that takes a job description and returns a structured object with title, skills (list of strings) and seniority.
Show solution
class Job(BaseModel):
title: str
skills: list[str]
seniority: str
chain = ChatPromptTemplate.from_template("Extract job info:\n{jd}") | llm.with_structured_output(Job)
print(chain.invoke({"jd": "Senior Python engineer with SQL and Docker experience."}))