A persistent challenge with large language models (LLMs) is their tendency to produce output that is unpredictable. Despite carefully crafted prompts, LLMs often deviate from expectations, making their output difficult to reuse or integrate into workflows. Even worse, the results are often not repeatable, complicating downstream processing.
\ In this blog post, we explore structured meta-prompting, a technique that dynamically generates JSON schemas for solutions before performing tasks. This helps to create more reusable, reliable, and predictable prompts.
BackgroundMost modern LLMs now offer a JSON output mode, but the results don’t always conform to an expected schema. Developers often resort to check-and-retry mechanisms, which are time-consuming, expensive, and prone to breaking the user experience.
\ With gpt4o, OpenAI introduced structured outputs which guaranteed that the output would conform to a user-provided JSON schema. Although exact details are not disclosed, this is likely achieved a combination of constrained decoding and pre-sample logit biasing. Similar capabilities are offered by other tools like guidance, outlines, inversion, CommandR, SGLang. These approaches empower developers to guide outputs into JSON schemas, each with unique trade-offs.
What is structured meta-prompting?Structured meta-prompting is any technique that uses an LLM to dynamically create a structured description of a problem prior to producing a solution. This method offers several advantages over direct prompting:
\
\
CodeLet’s walk through an example where we use structured meta-prompting to create an outline for a new bestselling spy thriller novel.
All the code for this blog post is available in this Colab Notebook.:::info make sure to set your OPENAI_API_KEY in the Colab Secrets
:::
1. Generating a structuredThe first step is to define a JSON schema that describes the desired output. To do this, we’ll create a JSON schema for a JSON schema — effectively, a meta-schema! This is provided as part of the specification but we need to make some changes.
1.1 Tweaking the meta-schemaOpenAI and Cohere’s structured output APIs impose several restrictions on standard JSON schemas. This is quite unfortunate but something we can work around for now. We’ll tweak the meta-schema to ensure compatibility:
from jsonschema import Draft202012Validator def openai_compatible_metaschema(schema: Dict[str, object]): schema["type"] = "object" del schema["allOf"] return schema openai_json_metaschema = openai_compatible_metaschema( copy.deepcopy(Draft202012Validator.META_SCHEMA) )\ Note*: Apparently* inversion does not have any such restrictions and supports arbitrary JSON schemas…but no public access yet!
1.2 Adding restrictions to our meta-promptNext, we incorporate guidelines into the prompt to ensure the resulting JSON schema adheres to OpenAI’s constraints. For instance:
We now define the meta-prompt to generate a JSON schema for the spy thriller outline
from langchain.prompts import ChatPromptTemplate task_description = "Write an outline for a bestselling spy thriller novel" task_guidelines = """ - You must follow one of the six basic story arcs: Rags to riches, Riches to rags, Icarus, Oedipus, Cinderella, Man in a hole - Outputs must include characters, plot points (including exposition, rising action, climax, falling action, and resolution), central conflict, setting, major turning points or "beats," character arcs, and a synopsis of the story; essentially, a detailed breakdown of the key elements that will drive the narrative throughout the novel. """ prompt_messages = ChatPromptTemplate.from_messages( [ ( "system", "You are an expert in creating JSON schemas. You have been asked to generate a detailed JSON schema for the output of a given task based based on a task desciption and some guidelines.", ), ( "system", "Your JSON schema must always adhere to the following system system guidelines for JSON schemas:\nWe invoke the LLM to create the schema:
messages = prompt_messages.format_messages( system_guidelines=system_guidelines, task_description=task_description, task_guidelines=task_guidelines ) ## Make sure to set up OPENAI_API_KEY in your Colab Secrets ## https://x.com/GoogleColab/status/1719798406195867814 client = OpenAI(api_key=userdata.get('OPENAI_API_KEY')) model = "gpt-4o" metaprompt_completion = client.beta.chat.completions.parse( model=model, messages=convert_to_penai_messages(messages), response_format={ "type": "json_schema", "json_schema": JSONSchema( name="JsonMetaschema", description="JSON Metaschema for the 2020-12 Draft of the JSON Schema specification that can be used to validate JSON data", schema=openai_json_metaschema, strict=False, ) } ) task_output_schema = json.loads(metaprompt_completion.choices[0].message.content) print(json.dumps(task_output_schema, indent=2))\
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Outline for a Bestselling Spy Thriller Novel", "type": "object", "properties": { "storyArc": { "type": "string", "enum": [ "Rags to riches", "Riches to rags", "Icarus", "Oedipus", "Cinderella", "Man in a hole" ] }, "characters": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "role": { "type": "string" }, "description": { "type": "string" }, "arc": { "type": "string" } }, "required": ["name", "role", "description", "arc"], "additionalProperties": false }, "minItems": 1 }, "plotPoints": { "type": "object", "properties": { "exposition": { "type": "string" }, "risingAction": { "type": "string" }, "climax": { "type": "string" }, "fallingAction": { "type": "string" }, "resolution": { "type": "string" } }, "required": [ "exposition", "risingAction", "climax", "fallingAction", "resolution" ], "additionalProperties": false }, "centralConflict": { "type": "string" }, "setting": { "type": "string" }, "majorTurningPoints": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, "characterArcs": { "type": "object", "properties": { "protagonistArc": { "type": "string" }, "antagonistArc": { "type": "string" }, "supportingCharactersArcs": { "type": "array", "items": { "type": "string" }, "minItems": 0 } }, "required": [ "protagonistArc", "antagonistArc", "supportingCharactersArcs" ], "additionalProperties": false }, "synopsis": { "type": "string" } }, "required": [ "storyArc", "characters", "plotPoints", "centralConflict", "setting", "majorTurningPoints", "characterArcs", "synopsis" ], "additionalProperties": false }\ We now have a schema describes the outline for our spy thriller novel. This can be persisted in a file or in a database.
2. Generating a solution 2.1 Prompt setupUsing the schema, we define a prompt for the novel outline. we’ll use some basic role-play prompting and guidelines:
user_requirements = "Tell a story about counter-intelligence operative working against the clock. The novel should be extremely realistic, slow burn." task_prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a world-renowned author that has written dozens of bestselling thriller novels. Your task is to create an outline for a new novel based on the user's requirements.", ), ( "user", "Please write a novel outline based strictly on the following requirements\ Here’s the outline for our next spy thriller:
{ "storyArc": "Cinderella", "synopsis": "In 'The Clockwork Veil', Ethan Cross, a savvy counter-intelligence operative, is thrust into a high-pressure scenario where leaked documents threaten national integrity. As he races against time to unmask a mole within the agency, Ethan confronts his personal fears and the boundaries of the meticulous strategies he's known for. This slow-burn thriller follows Ethan's transformation in a world where every second could spell disaster, culminating in a showdown with Lena Grey\u2014a former ally who has turned the clockwork of espionage into her personal vendetta. Through grit and cunning, Ethan must adapt his methods, realizing that in the world of espionage, the most powerful weapon is a well-timed intuition.", "characters": [ { "name": "Ethan Cross", "role": "Protagonist", "description": "A meticulous and resourceful counter-intelligence operative known for his analytical mind and calm demeanor under pressure.", "arc": "Ethan transforms from a methodical planner to a decisive action-taker as he confronts his personal fears and realizes the importance of instinct." }, { "name": "Lena Grey", "role": "Antagonist", "description": "A brilliant but disillusioned former operative now turned mole, seeking vengeance against the agency she believes wronged her.", "arc": "Lena starts with a single-minded focus on revenge but gradually becomes conflicted as old loyalties resurface." }, { "name": "Dr. Julia Ward", "role": "Supporting Character", "description": "An astute psychologist who helps Ethan manage the stress of his demanding role and assists in profiling Lena's psychological state.", "arc": "Julia grows from a secondary advisory role to a key player in helping Ethan unearth Lena's motivations." }, { "name": "Michael Garner", "role": "Supporting Character", "description": "Ethan's trusted field partner and an expert in electronic surveillance, providing vital technical support.", "arc": "Michael's experience is tested as he learns to adapt to unpredictable situations, becoming more versatile in his approach." } ], "plotPoints": { "exposition": "Ethan Cross is tasked with investigating a series of leaked documents that could compromise national security. The leaks point to an insider within the agency.", "risingAction": "As Ethan dives deeper, he uncovers a trail leading to Lena Grey, a former colleague presumed dead. Evidence mounts as Ethan closes in, forcing him to question his long-standing methodologies.", "climax": "Ethan finally confronts Lena, who has rigged a trap to destroy critical evidence. In a tense standoff, Ethan must choose between following protocol or taking a risk to stop her.", "fallingAction": "With quick thinking and a new reliance on intuition, Ethan manages to disarm the trap. Lena, deflated, questions her own motives as old memories of camaraderie surface.", "resolution": "Lena is apprehended, the mole hunt ends, and Ethan reflects on his journey, acknowledging the balance between calculated strategy and spontaneity." }, "centralConflict": "Ethan Cross must identify and capture a mole within the agency who is leaking classified information, while dealing with his own rigid attachment to protocol in a dynamically evolving threat landscape.", "setting": "The story unfolds across various global locations including the bustling intelligence hub of Langley, a remote cabin in the Swiss Alps, and the teeming streets of Berlin, lending an authentic and international scope to the narrative.", "majorTurningPoints": [ "Ethan discovers the identity of the mole as his former colleague Lena Grey.", "Lena executes a series of diversions leading to a crisis within the agency.", "Ethan's adherence to protocol nearly costs him a critical breakthrough.", "Ethan's confrontation with Lena culminates in an uncharacteristic display of intuition that saves the mission." ], "characterArcs": { "protagonistArc": "Ethan evolves from strictly adhering to procedures to embracing a balance between strategy and instinctive decision-making, essential in high-stakes situations.", "antagonistArc": "Lena's journey from spite-fueled revenge to questioning her own motivations reflects a shift from isolation to an internal struggle with her past loyalties.", "supportingCharactersArcs": [ "Julia grows from providing psychological insights to playing an active role in strategizing the final approach to Lena.", "Michael transitions from a technical support role to becoming a crucial element in executing Ethan\u2019s plans, emphasizing adaptability." ] } } d\ We can now reuse this schema to generate multiple solutions in a pipeline with strong guarantees about the fields the output contains.
ConclusionStructured meta-prompting enables you to define structure on the fly, making LLM outputs more reliable for downstream processes. Stay tuned for the next post, where we’ll explore combining structured meta-prompting with other techniques.
All Rights Reserved. Copyright , Central Coast Communications, Inc.