RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /Courses
  5. /LangChain for Local AI
  6. /Ch. 8
LangChain for Local AI

08. LangChain Output Parsers

Chapter 8 of 18 · 25 min
KEY INSIGHT

Output parsers decouple the LLM's freeform text output from your application's type system, wrapping extraction and retry logic so your code receives typed Python objects.

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.

EXERCISE

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.

← Chapter 7
Router Chains
Chapter 9 →
Memory: ConversationBuffer