-
Notifications
You must be signed in to change notification settings - Fork 175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Structured Output #1443
base: main
Are you sure you want to change the base?
Add Structured Output #1443
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,37 @@ You can pass images to the Driver if the model supports it: | |
--8<-- "docs/griptape-framework/drivers/src/prompt_drivers_images.py" | ||
``` | ||
|
||
## Structured Output | ||
|
||
Some LLMs provide functionality often referred to as "Structured Output". This means instructing the LLM to output data in a particular format, usually JSON. This can be useful for forcing the LLM to output in a parsable format that can be used by downstream systems. | ||
|
||
Structured output can be enabled or disabled for a Prompt Driver by setting the [use_native_structured_output](../../reference/griptape/drivers.md#griptape.drivers.BasePromptDriver.use_native_structured_output). | ||
|
||
If `use_native_structured_output=True`, you can change _how_ the output is structured by setting the [native_structured_output_strategy](../../reference/griptape/drivers.md#griptape.drivers.BasePromptDriver.native_structured_output_strategy) to one of: | ||
|
||
- `native`: The Driver will use the LLM's structured output functionality provided by the API. | ||
- `tool`: Griptape will pass a special Tool, [StructuredOutputTool](../../reference/griptape/tools/structured_output_tool.md) and try to force the LLM to use a Tool. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In what cases would you use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually why do I need to pass the boolean in addition to the strategy name? If I just pass the strategy name is that not sufficient to infer that it should be used? In other words can you just remove the |
||
|
||
### JSON Schema | ||
|
||
The easiest way to get started with structured output is by using a [JsonSchemaRule](../structures/rulesets.md#json-schema). If a [schema.Schema](https://pypi.org/project/schema/) instance is provided to the Rule, Griptape will convert it to a JSON Schema and provide it to the LLM using the selected structured output strategy. | ||
|
||
```python | ||
--8<-- "docs/griptape-framework/drivers/src/prompt_drivers_structured_output.py" | ||
``` | ||
|
||
### Multiple Schemas | ||
|
||
If multiple `JsonSchemaRule`s are provided, Griptape will merge them into a single JSON Schema using `anyOf`. | ||
|
||
Some LLMs may not support `anyOf` as a top-level JSON Schema. To work around this, you can try using another `native_structured_output_strategy`: | ||
|
||
```python | ||
--8<-- "docs/griptape-framework/drivers/src/prompt_drivers_structured_output_multi.py" | ||
``` | ||
|
||
Not every LLM supports `use_native_structured_output` or all `native_structured_output_strategy` options. | ||
|
||
## Prompt Drivers | ||
|
||
Griptape offers the following Prompt Drivers for interacting with LLMs. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import schema | ||
from rich.pretty import pprint | ||
|
||
from griptape.drivers import OpenAiChatPromptDriver | ||
from griptape.rules import JsonSchemaRule, Rule | ||
from griptape.structures import Pipeline | ||
from griptape.tasks import PromptTask | ||
|
||
pipeline = Pipeline( | ||
tasks=[ | ||
PromptTask( | ||
prompt_driver=OpenAiChatPromptDriver( | ||
model="gpt-4o", | ||
use_native_structured_output=True, | ||
native_structured_output_strategy="native", | ||
Comment on lines
+14
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems weird to see |
||
), | ||
rules=[ | ||
Rule("You are a helpful math tutor. Guide the user through the solution step by step."), | ||
JsonSchemaRule( | ||
schema.Schema( | ||
{ | ||
"steps": [schema.Schema({"explanation": str, "output": str})], | ||
"final_answer": str, | ||
} | ||
) | ||
), | ||
], | ||
) | ||
] | ||
) | ||
|
||
output = pipeline.run("How can I solve 8x + 7 = -23").output.value | ||
|
||
|
||
pprint(output) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import schema | ||
from rich.pretty import pprint | ||
|
||
from griptape.drivers import OpenAiChatPromptDriver | ||
from griptape.rules import JsonSchemaRule | ||
from griptape.structures import Pipeline | ||
from griptape.tasks import PromptTask | ||
|
||
pipeline = Pipeline( | ||
tasks=[ | ||
PromptTask( | ||
prompt_driver=OpenAiChatPromptDriver( | ||
model="gpt-4o", | ||
use_native_structured_output=True, | ||
native_structured_output_strategy="tool", | ||
), | ||
rules=[ | ||
JsonSchemaRule(schema.Schema({"color": "red"})), | ||
JsonSchemaRule(schema.Schema({"color": "blue"})), | ||
], | ||
Comment on lines
+12
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is really hard for me to imagine what this would do (let alone decide to use it). How do the rules interact with the |
||
) | ||
] | ||
) | ||
|
||
output = pipeline.run("Pick a color").output.value | ||
|
||
|
||
pprint(output) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,9 @@ A [Ruleset](../../reference/griptape/rules/ruleset.md) can be used to define [Ru | |
[JsonSchemaRule](../../reference/griptape/rules/json_schema_rule.md)s defines a structured format for the LLM's output by providing a JSON schema. | ||
This is particularly useful when you need the LLM to return well-formed data, such as JSON objects, with specific fields and data types. | ||
|
||
If the Prompt Driver supports [Structured Output](../drivers/prompt-drivers.md#structured-output), Griptape will use the schema provided to the `JsonSchemaRule` to ensure JSON output. | ||
If the Prompt Driver does not support Structured Output, Griptape will include the schema in the system prompt using [this template](https://github.com/griptape-ai/griptape/blob/main/griptape/templates/rules/json_schema.j2). | ||
Comment on lines
+32
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest not using |
||
|
||
```python | ||
--8<-- "docs/griptape-framework/structures/src/json_schema_rule.py" | ||
``` | ||
|
@@ -47,6 +50,10 @@ Although Griptape leverages the `schema` library, you're free to use any JSON sc | |
|
||
For example, using `pydantic`: | ||
|
||
!!! warning | ||
|
||
Griptape does not yet support using `pydantic` schemas for[Structured Output](../drivers/prompt-drivers.md#structured-output). It is recommended to pass a `schema.Schema` instance. | ||
|
||
```python | ||
--8<-- "docs/griptape-framework/structures/src/json_schema_rule_pydantic.py" | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the default strategy? (Maybe mention it here?)