Skip to main content

A Structured Output Framework for LLM Outputs

Project description

StrictJSON v6.2.0 — parse_yaml

Make AI give answers in a neat, tidy format

parse_yaml helps you get clean, structured answers from Large Language Models (LLMs) like ChatGPT. It tells the LLM exactly what shape the answer should be, so you don’t have to fix it later.

It uses YAML, a simple way of writing lists and information, kind of like an easier version of JSON. It also checks the answer automatically to make sure it makes sense.

Old versions (e.g. strict_json) that used JSON still work, but parse_yaml is the new and improved method.


What Makes It Useful

  • Easy to read — YAML looks like tidy notes, not messy code.
  • Checks answers — makes sure the LLM gives the right types (like numbers, dates, or words).
  • Understands many data types.
  • Fixes mistakes automatically (tries again up to three times by default - changeable via num_tries parameter).
  • Works with any LLM model (ChatGPT, Claude, Gemini, etc.).

How to Install

pip install strictjson

Quick Example

Here is a small program that asks the AI for a blog post idea:

from strictjson import parse_yaml

def llm(system_prompt: str, user_prompt: str, **kwargs) -> str:
    from openai import OpenAI
    client = OpenAI()
    messages = []
    if system_prompt:
        messages.append({"role": "system", "content": system_prompt})
    messages.append({"role": "user", "content": user_prompt})
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        temperature=0,
        messages=messages
    )
    return resp.choices[0].message.content

result = parse_yaml(
  system_prompt="You are concise",
  user_prompt="Write a blog post idea about AI in education",
  output_format={
    "title": "str",
    "tags": "List[str]",
    "published": "bool"
  },
  llm=llm
)

print(result)
# {'title': 'Adaptive Tutors', 'tags': ['ai', 'edtech', 'personalization'], 'published': False}

Data Types You Can Use

You can use simple data types like these:

Type Example Meaning
str "Hello" text or words
int 5 whole number
float 3.14 number with decimals
bool True / False yes or no
List[int] [1, 2, 3] a list of numbers
Dict[str, Any] {"a": 1, "b": 2} a dictionary (key-value pairs)
date 2025-05-09 a calendar date
datetime 2025-05-09T14:30 date and time
UUID "550e8400-e29b-41d4-a716-446655440000" a unique ID
Decimal 12.50 an exact number (good for money)

A datatype Any refers to any datatype.

A datatype list or dict used without [], will be defaulted to List[Any] or Dict[str, Any].


What Happens Behind the Scenes

  1. You tell parse_yaml what kind of answer you want.
  2. It builds a simple template for the LLM to follow.
  3. The LLM fills in that template in YAML format.
  4. parse_yaml checks if the result is correct. If not, it fixes or retries it.
  5. You get a clean Python dictionary at the end.

More Examples

1. Creative ideas

parse_yaml(
  system_prompt="Be imaginative but safe",
  user_prompt="Give me 5 names on a weather theme",
  output_format={
    "Names": "5 cool weather names, List[str]",
    "Meanings": "name → meaning, Dict[str, str]"
  },
  llm=llm,
)

Example Output:

{
  "Names": ["Storm Whisper", "Cloud Dancer", "Thunder Heart", "Rain Song", "Sun Chaser"],
  "Meanings": {
    "Storm Whisper": "Someone calm even in chaos",
    "Cloud Dancer": "Light and free-spirited",
    "Thunder Heart": "Strong and passionate",
    "Rain Song": "Gentle and emotional",
    "Sun Chaser": "Always positive"
  }
}

2. Finding facts

parse_yaml(
  system_prompt="Extract information",
  user_prompt="Article about NASA",
  output_format={
    "Entities": "organisations only, List[str]",
    "Sentiment": "Enum['Happy','Sad','Neutral']",
    "Summary": "str"
  },
  llm=llm,
)

Example Output:

{
  "Entities": ["NASA", "SpaceX", "Boeing"],
  "Sentiment": "Happy",
  "Summary": "NASA announced a new partnership with SpaceX to develop next-generation spacecraft. The article is optimistic about future space exploration."
}

3. Nested information

parse_yaml(
  system_prompt="Plan a party",
  user_prompt="Generate a kids party for Alex",
  output_format={
    "name": "str",
    "date": "date",
    "participants": "List[Dict[str, Any]]"
  },
  llm=llm,
)

Example Output:

{
  "name": "Alex's Birthday Party",
  "date": "2026-03-12",
  "participants": [
    {"name": "Ava", "age": 8, "gift": "Lego set"},
    {"name": "Ben", "age": 9, "gift": "Book"},
    {"name": "Liam", "age": 8, "gift": "Art kit"}
  ]
}

Using Your Own Models

You can also define your own data rules using Pydantic models. This is for developers who want strong type checking.

from typing import List
from pydantic import BaseModel, Field
from datetime import date as Date

class Participant(BaseModel):
    Name: str = Field(..., pattern=r"^A.*$")
    Age: int = Field(..., ge=5, le=12)

class CalendarEvent(BaseModel):
    name: str
    date: Date
    participants: List[Participant]

result = parse_yaml(
    system_prompt="You are a helpful assistant",
    user_prompt="Generate a birthday event for Alex",
    pydantic_model=CalendarEvent,
    llm=llm
)


Async Example (For Advanced Users)

If you are writing an async app, use this version:

from openai import AsyncOpenAI

async def llm_async(system_prompt: str, user_prompt: str, **kwargs):
    client = AsyncOpenAI()
    resp = await client.chat.completions.create(
        model="gpt-4o-mini",
        temperature=0,
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt},
        ]
    )
    return resp.choices[0].message.content

result = await parse_yaml_async(
  system_prompt="Summarise this research abstract",
  user_prompt=abstract,
  output_format={"Summary": "<= 3 sentences, str"},
  llm=llm_async,
)
#{"Summary": "The research explores how artificial intelligence can personalize learning for students. It highlights improved engagement and adaptive feedback as key benefits. The study concludes that AI can complement teachers by automating routine assessments."}

Multimodal Inputs (For Advanced Users)

Image Reading (Vision)

parse_yaml can process images with decorator @image_parser parse_yaml_async can process images with decorator @image_parser_async. They convert any <<image_url_or_path>> in your prompt into structured multimodal input for vision-capable models (like Gemini, Claude, or GPT-4o). You need to use the OpenAI interface to use this parser.

Example (Sync)

from strictjson import parse_yaml
from strictjson.utils import image_parser
import os

@image_parser
def llm(system_prompt, user_prompt, **kwargs):
    from openai import OpenAI
    client = OpenAI(base_url="https://openrouter.ai/api/v1",
                    api_key=os.environ["OPENROUTER_API_KEY"])
    messages = []
    if system_prompt:
        messages.append({"role": "system",
                         "content": [{"type": "text", "text": system_prompt}]})
    messages.append({"role": "user", "content": user_prompt})
    resp = client.chat.completions.create(
        model="google/gemini-2.5-flash", messages=messages)
    return resp.choices[0].message.content

img1 = "https://.../map1.png"
img2 = "https://.../map2.png"

res = parse_yaml(
  system_prompt="Describe the game states",
  user_prompt=f"State1: <<{img1}>>, State2: <<{img2}>>",
  output_format={
    "State 1": "str",
    "State 2": "str",
    "Thoughts": "str"
  },
  llm=llm
)

Example (Async)

from strictjson import parse_yaml_async
from strictjson.utils import image_parser_async
import os

@image_parser_async
async def llm_async(system_prompt, user_prompt, **kwargs):
    from openai import AsyncOpenAI
    client = AsyncOpenAI(base_url="https://openrouter.ai/api/v1",
                         api_key=os.environ["OPENROUTER_API_KEY"])
    messages = []
    if system_prompt:
        messages.append({"role": "system",
                         "content": [{"type": "text", "text": system_prompt}]})
    messages.append({"role": "user", "content": user_prompt})
    resp = await client.chat.completions.create(
        model="google/gemini-2.5-flash", messages=messages)
    return resp.choices[0].message.content

filepath = "ai_electricity.png"
res = await parse_yaml_async(
  system_prompt="Extract text and describe the image",
  user_prompt=f"Image: <<{filepath}>>",
  output_format={
    "Image Text": "str",
    "Image Description": "str"
  },
  llm=llm_async
)

Project Info

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

strictjson-6.2.0.tar.gz (27.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

strictjson-6.2.0-py3-none-any.whl (30.1 kB view details)

Uploaded Python 3

File details

Details for the file strictjson-6.2.0.tar.gz.

File metadata

  • Download URL: strictjson-6.2.0.tar.gz
  • Upload date:
  • Size: 27.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.18

File hashes

Hashes for strictjson-6.2.0.tar.gz
Algorithm Hash digest
SHA256 99908cd367eb86a270efc398404b1720bb635955a6dec2c9a5580f8db7859195
MD5 3e93a2b5eae16c62b2f2b031529e69c0
BLAKE2b-256 1168b6670fec6be6e5bf09b027c6f2108e3a0f936118b78932087e801d746488

See more details on using hashes here.

File details

Details for the file strictjson-6.2.0-py3-none-any.whl.

File metadata

  • Download URL: strictjson-6.2.0-py3-none-any.whl
  • Upload date:
  • Size: 30.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.18

File hashes

Hashes for strictjson-6.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3b3de65f919a11d46730992909bd7b4555ac00ed0e03f7af01fe01227bbaf587
MD5 8d8adb2d9954c6bfcbf2ecc7fc701858
BLAKE2b-256 5df5478c604db2a6f2bba959a97c4e325265598fb82d2bd06272925e1922b226

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page