Structured Outputs¶
Structured Outputs supported after version dria==0.0.65
Structured outputs best explained in OpenAI's blog post:
Structured Outputs is a feature that ensures the model will always generate responses that adhere to your supplied JSON Schema, so you don't need to worry about the model omitting a required key, or hallucinating an invalid enum value.
Dria Network supports structured outputs for all providers including OpenAI
, Gemini
and Ollama
.
However, structured outputs are only supported by models that are capable of function calling.
Enabling structured outputs is simple. You just need to provide a schema to the WorkflowBuilder
instance, rest will be handled by Dria SDK.
Lets walkthrough a simple example where we generate a book review using structured outputs. See full code here.
First we define a schema for the book review:
from pydantic import BaseModel, Field
class BookReview(BaseModel):
"""Book review specification."""
title: str = Field(..., description="Book title")
rating: int = Field(..., description="Rating from 1-5 stars")
genre: str = Field(..., description="Book genre")
review_text: str = Field(..., description="Short review text")
recommended: bool = Field(..., description="Whether the book is recommended")
Now we'll create a SingletonTemplate
instance:
class BookReviewSingleton(SingletonTemplate):
"""Workflow generator."""
def workflow(self, **kwargs) -> Workflow:
pass
def parse_result(self, result: List[TaskResult]):
pass
workflow
is used to define task and parse_result
is used to parse the results.
from dria.factory.workflows.template import SingletonTemplate
from dria.models import Task, Model, TaskResult
from dria.factory.utilities import parse_json
from dria_workflows import Workflow, WorkflowBuilder, Operator, Edge, Write
from typing import List
class BookReviewSingleton(SingletonTemplate):
"""Workflow generator."""
def workflow(self) -> Workflow:
builder = WorkflowBuilder()
builder.set_max_tokens(2000)
builder.set_max_time(120)
builder.set_max_steps(20)
builder.generative_step(
prompt="Create a simple book review",
schema=BookReview,
operator=Operator.GENERATION,
outputs=[Write.new("response")]
)
# Define the flow of execution
builder.flow([Edge(source="0", target="_end")])
# Set the return value, read 'response' key from memory as return value
builder.set_return_value("response")
return builder.build()
def parse_result(self, result: List[TaskResult]):
"""Parse results."""
return [{"generation": parse_json(r.result), "model": r.model} for r in result]
That's it! We have defined a structured output for book review generation.
We'll run it using the following code:
async def execute_workflow(dria: Dria, **kwargs):
tasks = Task(workflow=Generator().workflow(**kwargs), models=[Model.GPT4O_MINI])
res = await dria.execute(tasks, timeout=60)
return Generator().parse_result(res)
if __name__ == "__main__":
dria = Dria(rpc_token=os.environ["DRIA_RPC_TOKEN"])
print(asyncio.run(execute_workflow(dria, num_samples=1)))
Parsed result:
[
{
"generation": {
"genre": "Fiction",
"rating": 4,
"recommended": true,
"review_text": "A captivating story with compelling characters and exquisite prose. The plot twists kept me on the edge of my seat!",
"title": "The Whispering Woods"
},
"model": "gpt-4o-mini"
}
]
Voila! We have successfully generated a book review using structured outputs.
Full code:¶
See the full code to execute a book review generation task using structured outputs:
import asyncio
from typing import List
from dria.client import Dria
from dria.factory.workflows.template import SingletonTemplate
from dria.models import Task, Model, TaskResult
from dria.factory.utilities import parse_json
from dria_workflows import Workflow, WorkflowBuilder, Operator, Edge, Write
from pydantic import BaseModel, Field
import json
import os
class BookReview(BaseModel):
"""Book review specification."""
title: str = Field(..., description="Book title")
rating: int = Field(..., description="Rating from 1-5 stars")
genre: str = Field(..., description="Book genre")
review_text: str = Field(..., description="Short review text")
recommended: bool = Field(..., description="Whether the book is recommended")
class BookReviewSingleton(SingletonTemplate):
"""Workflow generator."""
def workflow(self) -> Workflow:
builder = WorkflowBuilder()
builder.set_max_tokens(2000)
builder.set_max_time(120)
builder.set_max_steps(20)
builder.generative_step(
prompt="Create a simple book review",
schema=BookReview,
operator=Operator.GENERATION,
outputs=[Write.new("response")]
)
builder.flow([Edge(source="0", target="_end")])
builder.set_return_value("response")
return builder.build()
def parse_result(self, result: List[TaskResult]):
"""Parse results."""
return [{"generation": parse_json(r.result), "model": r.model} for r in result]
async def execute_workflow(dria: Dria):
task = Task(workflow=BookReviewSingleton().workflow(), models=[Model.GPT4O_MINI])
res = await dria.execute(task, timeout=60)
return BookReviewSingleton().parse_result(res)
if __name__ == "__main__":
dria = Dria(rpc_token=os.environ["DRIA_RPC_TOKEN"])
print(json.dumps(asyncio.run(execute_workflow(dria)), indent=4))