YAMLOutputParser (yaml_parser.py)
On this page
class output_parser.yaml_parser.YAMLOutputParser(BaseOutputParser)
Overview
Extracts and parses YAML from raw LLM text, with optional Pydantic validation. Requires PyYAML — unlike the JSON/CSV/list parsers, this dependency is not optional at the class level: __init__ raises ImportError immediately if yaml isn't importable, even if you never call parse().
Depends on base_parser.py and PyYAML (required); optionally pydantic.
Constructor
YAMLOutputParser(pydantic_model: Optional[Type] = None)
Raises:
ImportError("PyYAML is required for YAMLOutputParser. Install it with: pip install pyyaml")ifyamlis not installed (checked via the module-levelYAML_AVAILABLEflag set at import time).- Same
pydantic_modelvalidation asJSONOutputParserif a model is provided.
Public Methods
parse
def parse(self, text: str) -> Any
Returns: parsed YAML content (dict, list, scalar, etc.), or a pydantic_model instance if configured.
Raises:
ParsingError("Cannot parse empty text", ...)for empty input.ParsingError(f"Invalid YAML: {e}", ...)ifyaml.safe_load()raisesyaml.YAMLError.ParsingError("YAML parsed to None/empty.", ...)if the result isNone(e.g. input was just whitespace/comments after extraction).ParsingError(f"Expected YAML mapping for Pydantic model, got {type}", ...)if a model is configured but the parsed data isn't adict.ParsingError(f"YAML does not match schema for {name}: {e}", ...)if Pydantic construction fails.- Also propagates any
ParsingErrorraised inside_extract_yaml(see below) — these are not caught/wrapped again byparse(), they bubble up as-is.
Algorithm (_extract_yaml, multi-step cleaning pipeline):
- Empty input → raises
ParsingErrorimmediately. - Best case: regex-search for a
```yaml/```yml/ bare```fence. If found and non-empty, returns the inner content directly — no further cleaning applied. - No fence found: splits into lines and filters out noise: lines that are just
```fences, lines that are literally"yaml"/"yml"on their own, and lines starting with common LLM chatter prefixes ("here is","here's","the following","below is","this is"— case-insensitive). - If the cleaned text is empty after filtering, raises
ParsingError("Text became empty after cleaning; no YAML content found."). - Searches for the first line matching a YAML key pattern (
^[\s\-]*[a-zA-Z0-9_\-]+\s*:\s*) and slices the text starting from that match — this trims any remaining leading prose that survived the line-filter step. If no key pattern is found, uses the full cleaned text as-is. - Final sanity check: if the resulting text contains no
:at all, raisesParsingError("Extracted text does not look like valid YAML (missing ':')."). - Any unexpected exception during this process is caught and re-raised as
ParsingError(f"Unexpected error during YAML extraction: {e}", cause=e).
[!NOTE] Source contains embedded Arabic comments The
_extract_yamlmethod's source contains a small number of inline Arabic-language comments (e.g.# تجاهل markdown— "ignore markdown",# تجاهل yaml لوحدها— "ignore yaml alone",# تجاهل جمل LLM— "ignore LLM sentences",# سيبه يعدي زي ما هو— "let it pass through as-is"). These are developer comments only and have no effect on behavior or the public API.
get_format_instructions
If pydantic_model is set, builds a ```yaml fenced example listing each schema property as field: <type> # required or # optional. Otherwise returns a generic YAML instruction with a hardcoded key: value / list example.
Complexity
_extract_yaml is O(n) in text length — one pass to split into lines, one filtering pass, one regex search for the key pattern. yaml.safe_load()'s complexity is governed by PyYAML itself (generally linear in document size for typical structures).
Thread Safety
Safe to share across threads for concurrent parse() calls — no mutable instance state beyond pydantic_model. yaml.safe_load itself is stateless per-call.
Side Effects
None beyond raising exceptions — no logging, no I/O, no global state mutation. Uses yaml.safe_load specifically (not yaml.load), which is intentionally restricted to prevent arbitrary Python object construction/code execution from untrusted YAML input.
Examples
# Basic — fenced YAML
parser = YAMLOutputParser()
text = '''
```yaml
name: Alice
age: 30
skills:
- Python
- YAML
''' result = parser.parse(text)
text = "Here is the YAML:\nname: Bob\nrole: engineer" result = parser.parse(text)
from pydantic import BaseModel class Config(BaseModel): name: str age: int parser = YAMLOutputParser(pydantic_model=Config) config = parser.parse("name: Alice\nage: 30")
try: parser.parse("just some prose with no colon anywhere") except ParsingError as e: print(str(e))
from output_parser.yaml_parser import YAML_AVAILABLE if YAML_AVAILABLE: parser = YAMLOutputParser() else: parser = None # fall back to another format
## Best Practices
- Check `output_parser.yaml_parser.YAML_AVAILABLE` before constructing this class in environments where `pyyaml` may not be installed, to fail gracefully rather than catching `ImportError`.
- Always instruct the LLM to wrap YAML in a ` ```yaml ` fence via `get_format_instructions()` — the unfenced extraction path (steps 3–6 above) is a best-effort fallback, not a guarantee, and can fail on YAML that doesn't start with a clean `key:` line.
## Common Mistakes
- Assuming YAML support works out of the box — unlike `pydantic`, `PyYAML` failing to import raises immediately in `__init__`, not lazily. Wrap construction in a `try`/`except ImportError` if you need to support environments without it.
- Relying on the "LLM chatter" line filter to catch every possible preamble phrasing — it only matches a fixed, hardcoded set of prefixes (`"here is"`, `"here's"`, `"the following"`, `"below is"`, `"this is"`). Other preambles (e.g. `"Sure! The configuration is:"`) will not be filtered and could interfere with extraction if they land on a line containing a `:` before the actual YAML key pattern is found.
## Related APIs
- [`BaseOutputParser`, `ParsingError`](base_parser.md)
- [`OutputParser`](output_parser.md) — the orchestrator's internal `_parse_yaml` is a much simpler variant (fence-or-whole-text, no line-filtering pipeline).
## Version History
Not determinable from source.