Skip to content

JSON Format Reference

This document describes the JSON structures for the three main objects in structured-prompts: 1. StructuredPrompt - the source prompt structure 2. IntermediateRepresentation (IR) - rendered chunks with metadata 3. CompiledIR - optimized index for querying subtrees

StructuredPrompt JSON

The StructuredPrompt.toJSON() method exports a hierarchical tree structure with explicit children arrays.

Structure

{
  prompt_id: "uuid-string",      // UUID of the root StructuredPrompt
  children: [                     // Array of child elements
    {
      type: "static",             // Element type
      id: "uuid-1",               // Element UUID
      parent_id: "root-uuid",     // Parent element UUID
      key: 0,                     // Integer index for statics, string for interpolations
      index: 0,                   // Position in element sequence
      value: "literal text",      // For static elements
      source_location: {          // Or null if unavailable
        filename: "script.py",
        filepath: "/path/to/script.py",
        line: 42
      }
    },
    {
      type: "interpolation",      // Simple string interpolation
      id: "uuid-2",
      parent_id: "root-uuid",
      key: "variable_name",
      index: 1,
      expression: "variable_name",
      conversion: "r",            // "r", "s", "a", or null
      format_spec: "variable_name",
      render_hints: "",
      value: "interpolated value",
      source_location: {...}
    },
    {
      type: "nested_prompt",      // Nested StructuredPrompt
      id: "uuid-3",
      parent_id: "root-uuid",
      key: "nested",
      index: 2,
      expression: "nested_var",
      conversion: null,
      format_spec: "nested",
      render_hints: "",
      prompt_id: "nested-uuid",   // UUID of the nested prompt
      children: [                 // Nested prompt's elements
        {...},
        ...
      ],
      source_location: {...}
    },
    {
      type: "list",               // List of StructuredPrompts
      id: "uuid-4",
      parent_id: "root-uuid",
      key: "items",
      index: 3,
      expression: "items_var",
      conversion: null,
      format_spec: "items:sep=, ",
      render_hints: "sep=, ",
      separator: ", ",            // Parsed separator (default: "\n")
      children: [                 // Array of list items
        {
          prompt_id: "item-uuid-1",
          children: [...]         // First item's elements
        },
        {
          prompt_id: "item-uuid-2",
          children: [...]         // Second item's elements
        }
      ],
      source_location: {...}
    },
    {
      type: "image",              // PIL Image object
      id: "uuid-5",
      parent_id: "root-uuid",
      key: "img",
      index: 4,
      expression: "img",
      conversion: null,
      format_spec: "img",
      render_hints: "",
      image_data: {               // Base64-encoded image
        base64_data: "iVBORw0KGg...",
        format: "PNG",
        width: 100,
        height: 200,
        mode: "RGB"
      },
      source_location: {...}
    }
  ]
}

Element Types

  • static: Literal text between interpolations
  • interpolation: Simple string variable (not a nested prompt)
  • nested_prompt: A StructuredPrompt interpolated into another prompt
  • list: A list of StructuredPrompts
  • image: A PIL Image object

Walk all elements recursively:

function walkTree(children, callback, depth = 0) {
  for (const element of children) {
    callback(element, depth);

    if (element.children) {
      if (element.type === "list") {
        // List items: each has {prompt_id, children}
        for (const item of element.children) {
          walkTree(item.children, callback, depth + 1);
        }
      } else {
        // Regular nested children
        walkTree(element.children, callback, depth + 1);
      }
    }
  }
}

// Example: print all interpolations
const data = structuredPrompt.toJSON();
walkTree(data.children, (elem, depth) => {
  if (elem.type === "interpolation") {
    console.log(`${"  ".repeat(depth)}${elem.key}: ${elem.value}`);
  }
});

Find element by ID:

function findElementById(children, targetId) {
  for (const elem of children) {
    if (elem.id === targetId) return elem;

    if (elem.children) {
      if (elem.type === "list") {
        for (const item of elem.children) {
          const result = findElementById(item.children, targetId);
          if (result) return result;
        }
      } else {
        const result = findElementById(elem.children, targetId);
        if (result) return result;
      }
    }
  }
  return null;
}

Get parent element:

function getParent(data, element) {
  const parentId = element.parent_id;

  // Check if parent is root
  if (parentId === data.prompt_id) return null;

  // Find parent in tree
  return findElementById(data.children, parentId);
}

IntermediateRepresentation JSON

The IntermediateRepresentation.toJSON() method exports rendered chunks with metadata and source prompt reference.

Structure

{
  chunks: [                       // Array of rendered chunks
    {
      type: "TextChunk",
      text: "rendered text",
      element_id: "element-uuid", // UUID of source element
      id: "chunk-uuid",
      metadata: {}                // Optional metadata
    },
    {
      type: "ImageChunk",
      image: {                    // Serialized image
        base64_data: "iVBORw0KGg...",
        format: "PNG",
        width: 100,
        height: 200,
        mode: "RGB"
      },
      element_id: "element-uuid",
      id: "chunk-uuid",
      metadata: {}
    }
  ],
  source_prompt_id: "prompt-uuid", // UUID of source StructuredPrompt (or null)
  id: "ir-uuid",                   // UUID of this IR
  metadata: {}                     // Optional metadata
}

Working with Chunks

Get all text from IR:

const ir = structuredPrompt.ir();
const data = ir.toJSON();

// Concatenate all text chunks
const fullText = data.chunks
  .filter(chunk => chunk.type === "TextChunk")
  .map(chunk => chunk.text)
  .join("");

Find chunks by element:

function getChunksForElement(data, elementId) {
  return data.chunks.filter(chunk => chunk.element_id === elementId);
}

// Example: get all chunks produced by a specific element
const chunks = getChunksForElement(data, "element-uuid");
chunks.forEach(chunk => {
  if (chunk.type === "TextChunk") {
    console.log(chunk.text);
  }
});

Map chunks to source elements:

// Build a map: element_id -> chunks
const chunksByElement = {};
for (const chunk of data.chunks) {
  if (!chunksByElement[chunk.element_id]) {
    chunksByElement[chunk.element_id] = [];
  }
  chunksByElement[chunk.element_id].push(chunk);
}

CompiledIR JSON

The CompiledIR.toJSON() method exports an optimized index for querying element subtrees.

Structure

{
  ir_id: "ir-uuid",               // UUID of the source IR
  subtree_map: {                  // element_id -> list of chunk_ids in subtree
    "element-uuid-1": ["chunk-1", "chunk-2"],
    "element-uuid-2": ["chunk-3"],
    "prompt-uuid": ["chunk-1", "chunk-2", "chunk-3"]  // All chunks for prompt
  },
  num_elements: 10                // Total number of elements indexed
}

Using the Subtree Map

The subtree_map enables efficient queries for all chunks produced by an element and its descendants.

Get all chunks for an element subtree:

// Given compiled IR data and IR data
const compiledData = compiledIr.toJSON();
const irData = ir.toJSON();

function getChunksForSubtree(compiledData, irData, elementId) {
  const chunkIds = compiledData.subtree_map[elementId] || [];

  // Build chunk lookup
  const chunkLookup = {};
  for (const chunk of irData.chunks) {
    chunkLookup[chunk.id] = chunk;
  }

  // Return chunks in order
  return chunkIds.map(id => chunkLookup[id]);
}

// Example: get all chunks for a nested prompt element
const chunks = getChunksForSubtree(compiledData, irData, "nested-prompt-uuid");
const text = chunks
  .filter(c => c.type === "TextChunk")
  .map(c => c.text)
  .join("");

Count chunks by subtree:

function countChunksBySubtree(compiledData) {
  const counts = {};
  for (const [elementId, chunkIds] of Object.entries(compiledData.subtree_map)) {
    counts[elementId] = chunkIds.length;
  }
  return counts;
}

Complete Example: All Three Together

This example shows how to work with all three JSON structures together.

// 1. Get StructuredPrompt structure
const promptData = structuredPrompt.toJSON();

// 2. Render to IR and get chunks
const ir = structuredPrompt.ir();
const irData = ir.toJSON();

// 3. Compile IR for efficient queries
const compiled = ir.compile();
const compiledData = compiled.toJSON();

// Now we can:
// - Navigate the source structure (promptData)
// - Access rendered chunks (irData)
// - Query element subtrees efficiently (compiledData)

// Example: Find an interpolation and get its rendered text
walkTree(promptData.children, (elem) => {
  if (elem.type === "interpolation" && elem.key === "user_name") {
    // Get all chunks this element produced
    const chunks = getChunksForSubtree(compiledData, irData, elem.id);
    const renderedText = chunks
      .filter(c => c.type === "TextChunk")
      .map(c => c.text)
      .join("");

    console.log(`Interpolation '${elem.key}' rendered as: ${renderedText}`);
    console.log(`Original value was: ${elem.value}`);
  }
});

Use Cases

StructuredPrompt JSON

  • Navigate prompt structure without Python
  • Analyze prompt composition
  • Extract metadata and source locations
  • Build external analysis tools

IntermediateRepresentation JSON

  • Access rendered output chunks
  • Map rendered text back to source elements
  • Store rendered prompts with provenance
  • Multi-modal output handling (text + images)

CompiledIR JSON

  • Efficient subtree queries (which chunks came from element X?)
  • Optimization analysis (token counting by element)
  • Interactive debugging (hover over element, show its output)
  • Performance-critical applications

Widget Visualization

The widget renderer uses a combined JSON structure with all three objects:

{
  source_prompt: {...},   // StructuredPrompt.toJSON()
  ir: {...},              // IntermediateRepresentation.toJSON()
  compiled_ir: {...}      // CompiledIR.toJSON()
}

This combined structure enables the widget to: - Display the prompt structure with syntax highlighting - Show rendered output chunks - Highlight which chunks correspond to which elements - Provide interactive exploration of the prompt tree