Unpacking Output Parsers with LangChain
Data Mastery Series — Episode 33: LangChain Website (Part 8)
Unpacking Output Parsers with LangChain
Data Mastery Series — Episode 33: LangChain Website (Part 8)

Connect with me and follow our journey: Linkedin, Facebook
Welcome to Episode 33 of the Data Mastery Series, where we continue our journey exploring LangChain, a powerful tool for integrating AI into real-world applications. If you’ve been following along, you’ve seen how LangChain can elevate your data workflows. Here’s a quick recap of what we’ve covered so far:
- Part 1: LangChain Model I/O Basics
- Part 2–3: Prompt Templates and Few-Shot Prompts
- Part 4–6: Deep Dive into Chat Models (Part 1, Part 2, Part 3)
- Part 7: LLM Fundamentals
Note:This post is a reflection on my learning journey to better understand LangChain. The content is based on resources found link. I hope you find it insightful and useful!
In today’s episode, we’re diving into Output Parsers. These tools are essential for transforming AI-generated outputs into structured formats like JSON, CSV, or even custom models. Whether you’re integrating with an API, running analyses, or preparing data for visualization, Output Parsers are your go-to solution.
What Are Output Parsers?
LLMs are excellent at generating human-like text, but applications often require more than plain text. Output Parsers help bridge the gap by converting unstructured AI outputs into structured data formats such as JSON, CSV, or custom data structures. This ensures seamless integration into workflows while maintaining data integrity and usability.
Exploring Output Parsers in LangChain
LangChain provides a variety of Output Parsers, each tailored for specific use cases. Here’s a breakdown of some key parsers:
1. OpenAI Tools:
OpenAI Tools Parsers enable LLMs to interact with predefined functions, returning structured data. For instance, they can extract arguments, filter specific keys, or validate outputs using a schema.
- JsonOutputToolsParser: Converts function call outputs into JSON.
Example - OpenAI Tools (JsonOutputToolsParser)
Define a simple data structure
class Joke(BaseModel):
"""Joke to tell user."""
setup: str = Field(description="question to set up a joke")
punchline: str = Field(description="answer to resolve the joke")
Create a prompt
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant"),
("user", "{input}")
])
Initialize the LLM and bind the Joke tool
model = ChatOpenAI(api_key=OPENAI_API_KEY, model="gpt-3.5-turbo", temperature=0).bind_tools([Joke])
Use JsonOutputToolsParser to initialize the parser and chain
parser = JsonOutputToolsParser()
chain = prompt | model | parser
Get the result
result = chain.invoke({"input": "เล่าเรื่องตลกให้ฟังที ภาษาไทย"}) # Tell me a joke in Thai
print(result)
Output:
'''
[{'args': {'setup': 'เป็นคนที่ชอบนอนเป็นเวลานานมาก', 'punchline': 'เรียกว่าคนนอนยาว'}, 'type': 'Joke'}]
'''
- JsonOutputKeyToolsParser: Extracts specific keys from the output.
Example - OpenAI Tools (JsonOutputKeyToolsParser)
Above is same example 1
Use JsonOutputKeyToolsParser to parse the output
parser = JsonOutputKeyToolsParser(key_name="Joke")
Creating a chain
chain = prompt | model | parser
Get the result
result = chain.invoke({"input": "เล่าเรื่องตลกให้ฟังที ภาษาไทย ขอเรื่องใหม่ๆ"}) # Tell me a new joke in Thai.
print(result)
Output:
'''
[{'setup': 'เป็นไงถ้าเสียงของคุณเป็นเสียงของเสือ?', 'punchline': 'คนที่อยู่ข้างๆคงรู้สึกเหมือนอยู่ในสวนสัตว์'}]
'''
- PydanticToolsParser: Validates and formats outputs into custom data models using Pydantic.
Example - OpenAI Tools (PydanticToolsParser)
class Joke(BaseModel):
"""Joke to tell user."""
setup: str = Field(description="question to set up a joke")
punchline: str = Field(description="answer to resolve the joke")
# Ensure the setup ends with a question mark
@Field.validator("setup")
def question_ends_with_question_mark(cls, value: str, info: FieldValidationInfo):
if not value.endswith("?"):
raise ValueError("Badly formed question! Setup must end with a question mark.")
return value
Set up the chain
parser = PydanticToolsParser(tools=[Joke]) # Parse output using the Joke model
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant"),
("user", "{input}")
])
model = ChatOpenAI(api_key=OPENAI_API_KEY, model="gpt-3.5-turbo", temperature=0).bind_tools([Joke])
chain = prompt | model | parser
Get a joke from the AI
result = chain.invoke({"input": "Tell me a joke"})
print(result)
Output:
'''
[Joke(setup="Why couldn't the bicycle stand up by itself?", punchline='Because it was two tired!')]
'''
2. OpenAI Functions:
Similar to OpenAI Tools Parsers, these parsers format data returned by OpenAI’s function-calling capabilities. You can extract structured data or validate it using schemas. Examples include:
- JsonOutputFunctionsParser: Formats outputs as JSON.
Example - OpenAI Functions (JsonOutputFunctionsParser)
class Joke(BaseModel):
"""Joke to tell user."""
setup: str = Field(description="question to set up a joke")
punchline: str = Field(description="answer to resolve the joke")
openai_functions = [convert_pydantic_to_openai_function(Joke)]
model = ChatOpenAI(api_key=OPENAI_API_KEY, temperature=0)
prompt = ChatPromptTemplate.from_messages(
[("system", "You are helpful assistant"), ("user", "{input}")]
)
Use JsonOutputFunctionsParser to parse the output
parser = JsonOutputFunctionsParser()
Bind OpenAI functions to the model
chain = prompt | model.bind(functions=openai_functions) | parser
Invoke the chain
result = chain.invoke({"input": "Tell me a joke."})
print(result) # Outputs the joke in JSON format
Output:
'''
{'setup': "Why couldn't the bicycle stand up by itself?", 'punchline': 'Because it was two tired!'}
'''
- JsonKeyOutputFunctionsParser: Extracts specific keys from JSON outputs.
Example - OpenAI Functions (JsonKeyOutputFunctionsParser)
class Jokes(BaseModel):
joke: List[Joke]
funniness_level: int
Extract only the "joke" key
parser = JsonKeyOutputFunctionsParser(key_name="joke")
openai_functions = [convert_pydantic_to_openai_function(Jokes)]
chain = prompt | model.bind(functions=openai_functions) | parser
result = chain.invoke({"input": "tell me two jokes"})
print(result)
Output:
'''
[{'setup': "Why couldn't the bicycle stand up by itself?", 'punchline': 'It was two tired.'},
{'setup': 'What do you call a fish wearing a crown?', 'punchline': 'A kingfish.'}]
'''
- PydanticOutputFunctionsParser: Combines validation and formatting for more reliable outputs.
Example - OpenAI Functions (PydanticOutputFunctionsParser)
Define a Joke schema
class Joke(BaseModel):
"""Joke to tell user."""
setup: str = Field(..., description="Question to set up a joke.")
punchline: str = Field(..., description="Answer to resolve the joke.")
# Custom validation logic using `field_validator` in Pydantic v2
@field_validator("setup")
def question_ends_with_question_mark(cls, field):
if not field.endswith("?"):
raise ValueError("Setup must be a question ending with a question mark!")
return field
PydanticOutputFunctionsParser with updated schema
parser = PydanticOutputFunctionsParser(pydantic_schema=Joke)
Convert the Pydantic schema to OpenAI functions
openai_functions = [convert_pydantic_to_openai_function(Joke)]
Create a chain using LangChain utilities
chain = prompt | model.bind(functions=openai_functions) | parser
Example usage
result = chain.invoke({"input": "tell me a joke"})
print(result)
Output:
'''
setup="Why couldn't the bicycle stand up by itself?" punchline='It was two tired!'
'''
3. JSON**:**
JSON is one of the most versatile data formats for APIs and storage. LangChain’s JsonOutputParser ensures LLM outputs conform to predefined JSON schemas, with optional integration into Pydantic for validation.
Example - JSON (with Pydantic)
Define the data structure
class Joke(BaseModel):
setup: str = Field(description="question to set up a joke")
punchline: str = Field(description="answer to resolve the joke")
Initialize the model
model = ChatOpenAI(api_key=OPENAI_API_KEY, temperature=0)
Create a JSON parser with the defined schema
parser = JsonOutputParser(pydantic_object=Joke)
Define a prompt template
prompt = PromptTemplate(
template="Answer the user query.\n{format_instructions}\n{query}\n",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
Combine prompt, model, and parser into a chain
chain = prompt | model | parser
Generate a joke
joke_query = "Tell me a joke."
result = chain.invoke({"query": joke_query})
print(result)
Output:
'''
{'setup': "Why couldn't the bicycle stand up by itself?", 'punchline': 'Because it was two tired!'}
'''
Example - JSON (without Pydantic)
parser = JsonOutputParser()
result = chain.invoke({"query": "Tell me a joke."})
print(result)
Output:
'''
{'response': "Why couldn't the bicycle stand up by itself? Because it was two tired!"}
'''
4. CSV:
When working with tabular data, LangChain’s CommaSeparatedListOutputParser simplifies the creation of structured lists. This parser is ideal for generating CSV-like outputs for spreadsheets or database
Example - CSV
Initialize the output parser
output_parser = CommaSeparatedListOutputParser()
Get formatting instructions
format_instructions = output_parser.get_format_instructions()
Create a prompt template
prompt = PromptTemplate(
template="List five {subject}.\n{format_instructions}",
input_variables=["subject"],
partial_variables={"format_instructions": format_instructions},
)
Initialize the model
model = ChatOpenAI(api_key=OPENAI_API_KEY, temperature=0)
Combine prompt, model, and parser into a chain
chain = prompt | model | output_parser
Generate a list of ice cream flavors
result = chain.invoke({"subject": "ice cream flavors"})
print(result)
Output:
'''
['Vanilla', 'Chocolate', 'Strawberry', 'Mint Chocolate Chip', 'Cookies and Cream']
'''
5. Pandas DataFrame:
For Python users, Pandas DataFrame Output Parser is a game-changer. It allows LLMs to interact directly with tabular data, enabling dynamic queries, calculations, and seamless integration into data analysis workflows.
Example - Pandas DataFrame
Query 1: Retrieve a specific column
Create a DataFrame
df = pd.DataFrame({
"num_legs": [2, 4, 8, 0],
"num_wings": [2, 0, 0, 0],
"num_specimen_seen": [10, 2, 1, 8],
})
Create format_parser_output function
def format_parser_output(parser_output: Dict[str, Any]) -> None:
for key in parser_output.keys():
parser_output[key] = parser_output[key].to_dict()
return pprint.PrettyPrinter(width=4, compact=True).pprint(parser_output)
Initialize the parser
parser = PandasDataFrameOutputParser(dataframe=df)
Define a query
df_query = "Retrieve the num_wings column."
Create a prompt
prompt = PromptTemplate(
template="Answer the user query.\n{format_instructions}\n{query}\n",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
Initialize the model
model = ChatOpenAI(api_key=OPENAI_API_KEY, temperature=0)
Combine prompt, model, and parser into a chain
chain = prompt | model | parser
Execute the query
parser_output = chain.invoke({"query": df_query})
format_parser_output(parser_output)
Output:
'''
{'num_wings': {0: 2,
1: 0,
2: 0,
3: 0}}
'''
Example - Pandas DataFrame
Query 2: Retrieve a specific row
df_query = "Retrieve the first row."
parser_output = chain.invoke({"query": df_query})
format_parser_output(parser_output)
Output:
'''
{'0': {'num_legs': 2,
'num_specimen_seen': 10,
'num_wings': 2}}
'''
Example - Pandas DataFrame
Query 3: Perform a calculation
df_query = "Retrieve the average of the num_legs column from rows 1 to 3."
parser_output = chain.invoke({"query": df_query})
print(parser_output)
Output:
'''
{'mean': 4.0}
'''
6. Datetime
LangChain’s DatetimeOutputParser converts LLM outputs into Python datetime objects. This is particularly useful for applications requiring precise date and time data for further processing or analysis.
Example - Datetime
Initialize the parser
output_parser = DatetimeOutputParser()
Create a prompt
template = """Answer the users question:
{question}
{format_instructions}"""
prompt = PromptTemplate.from_template(
template,
partial_variables={"format_instructions": output_parser.get_format_instructions()},
)
Combine prompt, model, and parser into a chain
chain = prompt | OpenAI(api_key=OPENAI_API_KEY) | output_parser
Ask a datetime-related question
output = chain.invoke({"question": "When was Bitcoin founded?"})
print(output)
Output:
'''
2009-01-03 18:15:05
'''
7. Enum: Categorizing Outputs
Enums are perfect for categorizing outputs into predefined values, such as color codes or status levels. The EnumOutputParser ensures LLM outputs conform to a specified set of valid categories.
Example - Datetime
Define an Enum
class Colors(Enum):
RED = "red"
GREEN = "green"
BLUE = "blue"
Initialize the parser
parser = EnumOutputParser(enum=Colors)
Create a prompt
prompt = PromptTemplate.from_template(
"""What color eyes does this person have?
Person: {person}
Instructions: {instructions}"""
).partial(instructions=parser.get_format_instructions())
Combine prompt, model, and parser into a chain
chain = prompt | ChatOpenAI(api_key=OPENAI_API_KEY) | parser
Query the chain
result = chain.invoke({"person": "Frank Sinatra"})
print(result)
Output:
'''
<Colors.BLUE: 'blue'>
'''
Why Output Parsers Are Essential
Output Parsers unlock a world of possibilities for AI applications by offering:
- Structured Data Integration: Convert raw text into actionable formats like JSON or CSV for seamless downstream processing.
- Validation: Use schemas to enforce data integrity, reducing errors in workflows.
- Customization: Tailor outputs to specific needs using tools like Pydantic models or Enums.
- Flexibility: Support for real-time data streaming, enabling interactive applications.
In this episode, we explored how LangChain’s Output Parsers transform unstructured AI outputs into usable formats. From JSON to Pandas DataFrames, these tools are essential for building robust, data-driven applications.
Stay tuned for the next episode, where we’ll delve into even more advanced features of LangChain, helping you master this incredible framework step by step. 🚀
Data Science Explore the world of data science with Donato_Story
Dashboard Discover the power of data visualization with Donato_Story
Donato_Journey Join me on my journey (Thai version)
Course_Review Discover the training courses with Donato_Story (Thai version)
Let’s Connect!
Your feedback is invaluable. Feel free to share your thoughts or questions in the comments below. You can also connect with me on:
- Medium: medium.com/donato-story
- Facebook: web.facebook.com/DonatoStory
- Linkedin: linkedin.com/in/nattapong-thanngam
Originally published on Medium
Related
Chat with Document: A Closer Look at Splitting, Embeddings, and RAG
Data Mastery Series — Episode 21: The Chat with Document and Langchain Series (Part 2)
Chat with Document: Basics and Demonstrations
Data Mastery Series — Episode 20: The Chat with Document and Langchain Series (Part 1)
Continue Exploring Chat Models with LangChain
Data Mastery Series — Episode 31: LangChain Website (Part 6)
Continue Exploring Retrievers with LangChain
Data Mastery Series — Episode 39: LangChain Website (Part 14 )