> ## Documentation Index
> Fetch the complete documentation index at: https://genai.codewithsiva.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Output Parsers

> Format raw LLM responses into structured data types like lists, dictionaries, or Pydantic objects

## 💻 Practice Notebook

Master the concepts from this page with hands-on practice:

[💻 VS Code](vscode://file/Users/sivaprasad/Downloads/GenAI%20With%20Python/public/notebooks/prompt-engg/prompt-engg-parsers-vscode.ipynb) | [🚀 Colab](https://colab.research.google.com/github/prasad230776/genai-course/blob/master/public/notebooks/prompt-engg/prompt-engg-parsers-colab.ipynb) | <a href="/public/notebooks/prompt-engg/prompt-engg-parsers-vscode.ipynb" download>📥 Download Notebook</a>

Large Language Models output plain text. However, applications often require structured data to feed into APIs, databases, or frontend components. Output Parsers bridge this gap.

**Main Concepts Covered**

* [1. Introduction to Output Parsers](#1-introduction-to-output-parsers)
* [2. Using Output Parsers](#2-using-output-parsers)
  * [2.1 StrOutputParser](#stroutputparser)
  * [2.2 JsonOutputParser](#jsonoutputparser)
  * [2.3 PydanticOutputParser](#pydanticoutputparser)
  * [2.4 List Output Parser (CommaSeparatedListOutputParser)](#list-output-parser-commaseparatedlistoutputparser)
* [3. Practice Exercises](#3-practice-exercises)

## 1. Introduction to Output Parsers

LangChain provides several output parsers to structure model outputs:

| Parser                           | Output Type                 | Example Use Case                                                 |
| -------------------------------- | --------------------------- | ---------------------------------------------------------------- |
| `StrOutputParser`                | `str` (String)              | Extracting clean text response (bypassing `AIMessage` wrappers). |
| `JsonOutputParser`               | `dict` (Dictionary)         | Extracting structured JSON keys and values.                      |
| `PydanticOutputParser`           | `BaseModel` (Python Object) | Parsing and validating outputs against a strict data schema.     |
| `CommaSeparatedListOutputParser` | `list` (List of strings)    | Splitting comma-separated words into a Python list.              |

<div align="right">[Back to Top](#)</div>

## 2. Using Output Parsers

### StrOutputParser

Converts the output of a chat model (`AIMessage`) into a clean, raw string.

#### Example 1: Standalone Usage

**Question:**
Create a standalone `StrOutputParser` and invoke it directly with an `AIMessage` to extract its raw string content.

**Plan & Steps:**

1. Import `AIMessage` and `StrOutputParser`.
2. Instantiate the parser.
3. Call `.invoke()` passing an `AIMessage` object and print the result.

```python theme={null}
from langchain_core.messages import AIMessage
from langchain_core.output_parsers import StrOutputParser

parser = StrOutputParser()
# Pass an AIMessage object to extract its content
response = parser.invoke(AIMessage(content="Hello World"))

print(response)       # "Hello World"
print(type(response))  # <class 'str'>
```

#### Example 2: Complete LCEL Chain with LLM

**Question:**
Create an LCEL chain that prompts a chat model for a joke and clean parses the output as a string.

**Plan & Steps:**

1. Initialize the chat model, a prompt template, and a `StrOutputParser`.
2. Chain the components: `prompt | model | StrOutputParser()`.
3. Invoke the chain passing a topic and print the clean string.

```python theme={null}
from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser

# Initialize model, prompt and parser
model = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
prompt = PromptTemplate.from_template("Tell me a one-line joke about {topic}.")

# Chain components together
chain = prompt | model | StrOutputParser()

# Invoke the chain
response = chain.invoke({"topic": "robots"})
print(response)       # e.g., "Why did the robot go on strike? Because it wanted more bytes."
print(type(response))  # <class 'str'>
```

<div align="right">[Back to Top](#)</div>

### JsonOutputParser

Parses JSON-formatted strings generated by LLMs into a native Python dictionary.

#### Example 1: Standalone Usage

**Question:**
Create a standalone `JsonOutputParser` and invoke it directly on a JSON-formatted string to extract a native Python dictionary.

**Plan & Steps:**

1. Import `JsonOutputParser`.
2. Instantiate the parser.
3. Call `.invoke()` passing a valid JSON string and print the result.

```python theme={null}
from langchain_core.output_parsers import JsonOutputParser

parser = JsonOutputParser()
response = parser.invoke("""
{
   "name": "John Doe",
   "age": 30,
   "occupation": "Software Engineer"
}
""")

print(response)       # {'name': 'John Doe', 'age': 30, 'occupation': 'Software Engineer'}
print(type(response))  # <class 'dict'>
```

#### Example 2: Complete LCEL Chain with LLM

**Question:**
Create an LCEL chain that queries a chat model to return a JSON object containing the capital and population of a country, using `JsonOutputParser` and its formatting instructions.

**Plan & Steps:**

1. Initialize the chat model, parser, and prompt template with `{format_instructions}`.
2. Compose the chain: `prompt | model | parser`.
3. Invoke the chain passing `country` and `format_instructions`.

```python theme={null}
from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import JsonOutputParser

model = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
parser = JsonOutputParser()

# Include formatting instructions in prompt
prompt = PromptTemplate.from_template(
    "Return a JSON object containing the capital and population of {country}.\n{format_instructions}"
)

# Chain components
chain = prompt | model | parser

# Invoke
response = chain.invoke({
    "country": "Japan",
    "format_instructions": parser.get_format_instructions()
})
print(response)       # e.g., {'capital': 'Tokyo', 'population': 14000000}
print(type(response))  # <class 'dict'>
```

<div align="right">[Back to Top](#)</div>

### PydanticOutputParser

Validates the output against a Pydantic model definition. This ensures type safety and field presence.

#### Example 1: Standalone Usage

**Question:**
Use `PydanticOutputParser` to parse and validate a raw JSON string into a structured Pydantic object model.

**Plan & Steps:**

1. Define a Pydantic schema class `Person`.
2. Instantiate `PydanticOutputParser` with the schema.
3. Call `.invoke()` with a JSON string to retrieve the validated object.

```python theme={null}
from pydantic import BaseModel
from langchain_core.output_parsers import PydanticOutputParser

# Define the schema
class Person(BaseModel):
    name: str
    age: int
    occupation: str

parser = PydanticOutputParser(pydantic_object=Person)
response = parser.invoke("""
{
   "name": "John Doe",
   "age": 30,
   "occupation": "Software Engineer"
}
""")

print(response)            # Person(name='John Doe', age=30, occupation='Software Engineer')
print(type(response))      # <class 'Person'>
print(response.name)       # "John Doe"
```

#### Example 2: Complete LCEL Chain with LLM

**Question:**
Build an LCEL chain using `PydanticOutputParser` to query and structure country information according to a strict data schema.

**Plan & Steps:**

1. Define the Pydantic schema `CountryInfo`.
2. Instantiate the parser and create a prompt template containing the `{format_instructions}` placeholder.
3. Chain the prompt, model, and parser together, then invoke with the query variables.

```python theme={null}
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser

class CountryInfo(BaseModel):
    capital: str = Field(description="The capital city of the country")
    official_languages: list[str] = Field(description="List of official languages")

# Setup model and parser
model = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
parser = PydanticOutputParser(pydantic_object=CountryInfo)

# Include formatting instructions in prompt
prompt = PromptTemplate.from_template(
    "Provide information about {country}.\n{format_instructions}"
)

chain = prompt | model | parser

# Invoke
response = chain.invoke({
    "country": "Germany",
    "format_instructions": parser.get_format_instructions()
})
print(response)       # e.g., CountryInfo(capital='Berlin', official_languages=['German'])
print(type(response))  # <class 'CountryInfo'>
```

#### Example 3: Parsing a List of Objects

**Question:**
Query the LLM to get a list of the top 3 most populous countries along with their population counts, and parse the response into a structured Python object containing a list of sub-objects.

**Plan & Steps:**

1. Define a Pydantic model for a single country (`CountryPopulation`) containing `name` and `population`.
2. Define a parent Pydantic model (`CountryList`) containing a list of `CountryPopulation` models (`countries`).
3. Instantiate a `PydanticOutputParser` using the parent `CountryList` schema.
4. Set up the prompt template injecting `{format_instructions}`.
5. Initialize the model and compose the LCEL chain (`prompt | model | parser`).
6. Invoke the chain, passing the format instructions.

```python theme={null}
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser

# 1. Define individual object schema
class CountryPopulation(BaseModel):
    name: str = Field(description="The name of the country")
    population: int = Field(description="The population of the country (approximate count)")

# 2. Define list container schema
class CountryList(BaseModel):
    countries: list[CountryPopulation] = Field(description="A list of countries and their populations")

# 3. Setup parser
parser = PydanticOutputParser(pydantic_object=CountryList)

# 4. Include formatting instructions in prompt
prompt = PromptTemplate.from_template(
    "List the top {count} most populous countries in the world.\n{format_instructions}"
)

# 5. Initialize model and compose chain
model = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
chain = prompt | model | parser

# 6. Invoke
response = chain.invoke({
    "count": 3,
    "format_instructions": parser.get_format_instructions()
})

print(response)
for country in response.countries:
    print(f"- {country.name}: {country.population:,} people")
```

<div align="right">[Back to Top](#)</div>

### List Output Parser (CommaSeparatedListOutputParser)

Splits comma-separated lists generated by the model into a Python list of strings.

#### Example 1: Standalone Usage

**Question:**
Use `CommaSeparatedListOutputParser` standalone to split a comma-separated string list into a Python list of strings.

**Plan & Steps:**

1. Instantiate `CommaSeparatedListOutputParser`.
2. Call `.invoke()` passing a comma-separated string list and print the result.

```python theme={null}
from langchain_core.output_parsers import CommaSeparatedListOutputParser

parser = CommaSeparatedListOutputParser()
response = parser.invoke("Python, Java, JavaScript, Go, Rust")

print(response)       # ['Python', 'Java', 'JavaScript', 'Go', 'Rust']
print(type(response))  # <class 'list'>
```

#### Example 2: Complete LCEL Chain with LLM

**Question:**
Build an LCEL chain that asks a chat model for the top 3 cities of a country and parses the response into a Python list using `CommaSeparatedListOutputParser`.

**Plan & Steps:**

1. Initialize the model, parser, and prompt.
2. Pipe the components: `prompt | model | parser`.
3. Invoke the chain passing the country and format instructions.

```python theme={null}
from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import CommaSeparatedListOutputParser

model = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
parser = CommaSeparatedListOutputParser()

prompt = PromptTemplate.from_template(
    "List the 3 largest cities in {country} as a comma-separated list.\n{format_instructions}"
)

chain = prompt | model | parser

# Invoke
response = chain.invoke({
    "country": "India",
    "format_instructions": parser.get_format_instructions()
})
print(response)       # e.g., ['Mumbai', 'Delhi', 'Bangalore']
print(type(response))  # <class 'list'>
```

<div align="right">[Back to Top](#)</div>

### `.invoke()` vs `.parse()`

You can execute parsers using either `.invoke()` or `.parse()`:

* **`.invoke()`** (Recommended)
  * **When to Use**: Standard practice in LCEL flows.
  * **Input Type**: `str` or `AIMessage`.
  * **LCEL Chain Support**: **Yes** (e.g., `chain = prompt | model | parser`).

* **`.parse()`**
  * **When to Use**: Legacy / standalone python scripts.
  * **Input Type**: `str`.
  * **LCEL Chain Support**: **No** (throws an error if piped).

> \[!TIP]
> Always prefer `.invoke()` in production systems since it natively supports async execution (`.ainvoke()`), streaming, and standard LCEL pipelining.

<div align="right">[Back to Top](#)</div>

## 3. Practice Exercises

### Practice 1: Comma Separated List Parsing

Create a prompt template that requests the model to list the top 3 programming languages for web development, and chain it with the `CommaSeparatedListOutputParser` to obtain a Python list.

<Accordion title="Solution">
  ```python theme={null}
  from langchain_core.prompts import PromptTemplate
  from langchain_core.output_parsers import CommaSeparatedListOutputParser
  from langchain.chat_models import init_chat_model

  llm = init_chat_model("groq:llama-3.3-70b-versatile")
  parser = CommaSeparatedListOutputParser()

  prompt = PromptTemplate(
      template="List 3 top programming languages for {use_case} as a comma-separated list.",
      input_variables=["use_case"]
  )

  chain = prompt | llm | parser
  result = chain.invoke({"use_case": "web development"})

  print(result)
  print(type(result)) # <class 'list'>
  ```
</Accordion>

<div align="right">[Back to Top](#)</div>
