Tutorial: LLM Output Parsing (E19)¶
This tutorial corresponds to the example file examples/E19_llm_output_parsing_example.py
.
It demonstrates how to reliably extract structured data from an LLM's text response. It shows how to:
- Use genie.llm.parse_output()
to convert LLM text into Python objects.
- Configure and use JSONOutputParserPlugin
to extract JSON.
- Configure and use PydanticOutputParserPlugin
to parse JSON directly into a Pydantic model instance for validation and type safety.
Example Code¶
examples/E19_llm_output_parsing_example.py¶
"""
Example: Using LLM Output Parsing (genie.llm.parse_output
)
This example demonstrates how to use genie.llm.parse_output
to parse
structured data (like JSON) from an LLM's text response. It also shows
parsing into a Pydantic model.
To Run:
1. Ensure Genie Tooling is installed (poetry install --all-extras
).
(Pydantic is a core dependency).
2. Ensure Ollama is running and 'mistral:latest' is pulled (or configure a different LLM).
3. Run from the root of the project:
poetry run python examples/E19_llm_output_parsing_example.py
"""
import asyncio
import logging
from typing import Optional
from genie_tooling.config.features import FeatureSettings from genie_tooling.config.models import MiddlewareConfig from genie_tooling.genie import Genie from genie_tooling.llm_providers.types import LLMChatResponse from pydantic import BaseModel, Field
class ExtractedInfo(BaseModel): name: str = Field(description="The full name of the person.") age: Optional[int] = Field(None, description="The person's age, if mentioned.") city: Optional[str] = Field(None, description="The city the person lives in, if mentioned.")
async def run_llm_output_parsing_demo(): print("--- LLM Output Parsing Example ---") logging.basicConfig(level=logging.INFO)
app_config = MiddlewareConfig(
features=FeatureSettings(
llm="ollama",
llm_ollama_model_name="mistral:latest",
default_llm_output_parser="json_output_parser" # Set default
)
)
genie: Optional[Genie] = None
try:
print("\nInitializing Genie for LLM output parsing...")
genie = await Genie.create(config=app_config)
print("Genie initialized!")
print("\n--- Parsing to Dictionary (JSON) ---")
prompt_for_json = (
"Extract the name, age, and city from the following text "
"and return it as a JSON object: "
"'John Doe is 42 years old and lives in New York. He enjoys programming.' "
"Ensure your output is ONLY the JSON object."
)
print(f"Sending prompt for JSON: {prompt_for_json}")
try:
llm_response_json: LLMChatResponse = await genie.llm.chat(
[{"role": "user", "content": prompt_for_json}]
)
print(f"LLM Raw Text Output: {llm_response_json['message']['content']}")
parsed_dict = await genie.llm.parse_output(llm_response_json) # Uses default JSON parser
print(f"Parsed Dictionary: {parsed_dict}")
if isinstance(parsed_dict, dict):
print(f" Name from dict: {parsed_dict.get('name')}")
except Exception as e_json:
print(f"Error during JSON parsing: {e_json}")
print("\n--- Parsing to Pydantic Model ---")
prompt_for_pydantic = (
"From the text 'Alice is thirty and resides in London.', "
"extract the name, age, and city. Format as a JSON object "
"suitable for a model with fields: name (str), age (int, optional), city (str, optional)."
"Output ONLY the JSON object."
)
print(f"Sending prompt for Pydantic: {prompt_for_pydantic}")
try:
llm_response_pydantic: LLMChatResponse = await genie.llm.chat(
[{"role": "user", "content": prompt_for_pydantic}]
)
print(f"LLM Raw Text Output: {llm_response_pydantic['message']['content']}")
parsed_model_instance = await genie.llm.parse_output(
llm_response_pydantic,
parser_id="pydantic_output_parser_v1",
schema=ExtractedInfo
)
if isinstance(parsed_model_instance, ExtractedInfo):
print(f"Parsed Pydantic Model: {parsed_model_instance.model_dump()}")
print(f" Name from model: {parsed_model_instance.name}")
print(f" Age from model: {parsed_model_instance.age}")
else:
print(f"Parsing did not return an ExtractedInfo instance. Got: {type(parsed_model_instance)}")
except Exception as e_pydantic:
print(f"Error during Pydantic parsing: {e_pydantic}")
except Exception as e:
print(f"\nAn error occurred: {e}")
logging.exception("LLM output parsing demo error details:")
finally:
if genie:
await genie.close()
print("\nGenie torn down.")
if name == "main": asyncio.run(run_llm_output_parsing_demo())