08. LangChain Output Parsers
Output parsers convert the raw text from an LLM into structured Python types. Without a parser, the model's response is a string you must parse manually with regex or string splitting. With a parser, you define the target type and LangChain handles the extraction. LangChain provides: SimpleJsonOutputParser, PydanticOutputParser, RetryOutputParser, StructuredOutputParser, and CommaSeparatedListOutputParser.
Start with the simplest: CommaSeparatedListOutputParser:
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate
from langchain_ollama import ChatOllama
from langchain.chains import LLMChain
llm = ChatOllama(model="llama3.2:3b", temperature=0)
parser = CommaSeparatedListOutputParser()
# Combine parser with prompt template
template = PromptTemplate.from_template(
"List the primary colors. {format_instructions}\nJust list them.",
partial_variables={"format_instructions": parser.get_format_instructions()},
)
chain = LLMChain(prompt=template, llm=llm)
result = chain.invoke({})
colors = parser.parse(result["text"])
print(colors)
# ['red', 'blue', 'yellow'] (as a Python list)
The parser.get_format_instructions() method returns a string that tells the model how to format its output. This is the key mechanism across all parsers—the template injects these instructions automatically.
For structured objects, use PydanticOutputParser with a Pydantic model:
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain_ollama import ChatOllama
from langchain.chains import LLMChain
from pydantic import BaseModel, Field
class Recipe(BaseModel):
name: str = Field(description="Name of the recipe")
ingredients: list[str] = Field(description="List of ingredients")
prep_time_minutes: int = Field(description="Preparation time in minutes")
steps: list[str] = Field(description="Step-by-step instructions")
parser = PydanticOutputParser(pydantic_object=Recipe)
template = PromptTemplate.from_template(
"Generate a recipe for {dish}. {format_instructions}",
partial_variables={"format_instructions": parser.get_format_instructions()},
)
chain = LLMChain(
prompt=template,
llm=llm,
)
result = chain.invoke({"dish": "classic pancakes"})
recipe = parser.parse(result["text"])
print(recipe.name)
print(f"Prep time: {recipe.prep_time_minutes} min")
print(f"Ingredients: {recipe.ingredients}")
This gives you a fully typed Python object. Type errors come from the model output failing to parse—expect OutputParserException if the model returns malformed JSON.
RetryOutputParser wraps another parser with retry logic—if the first parse fails, it constructs a follow-up prompt asking the model to correct its output:
from langchain.output_parsers import RetryOutputParser, PydanticOutputParser
from langchain_core.output_parser import StrOutputParser
# Wrap with retry: max 3 attempts before raising
retry_parser = RetryOutputParser(
parser=parser,
max_retries=3,
retry_chain=LLMChain(
prompt=PromptTemplate.from_template(
"The model failed to parse the recipe. "
"Fix the following output to be valid JSON: {text}. "
"Return valid JSON only, no explanation."
),
llm=llm,
),
)
try:
recipe = retry_parser.parse_with_prompt(result["text"], prompt=template)
except Exception as e:
print(f"All retries failed: {e}")
Failure mode: parsers assume the model will return valid JSON or the expected format. Ollama models with lower instruction-following scores (the 3B variants, especially with higher temperatures) are unreliable at following format instructions. Keep temperature at 0 for structured output tasks, and test with your specific model before relying on parsing in production.
For calling parsers directly outside of a chain, use parser.parse(model_output_string):
# Direct parsing without a chain
raw_output = llm.invoke("List five programming languages.")
langs = parser.parse(raw_output.content)
This pattern is useful when you want to parse a response from a model that was called outside of a template-driven chain.
Define a Pydantic model with BaseModel for a product review (fields: rating [int], pros [list[str]], cons [list[str]], summary [str]). Use PydanticOutputParser with an LLMChain to generate a fake product review and parse it into the model instance. Print each field of the parsed result.