-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Improve handling of JSON Schema in OpenAI API Response Context #819
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
Improve handling of JSON Schema in OpenAI API Response Context #819
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #819 +/- ##
==========================================
+ Coverage 98.46% 99.01% +0.55%
==========================================
Files 24 26 +2
Lines 1364 1418 +54
==========================================
+ Hits 1343 1404 +61
+ Misses 15 8 -7
Partials 6 6 ☔ View full report in Codecov by Sentry. |
jsonschema/json.go
Outdated
| return string(bytes) | ||
| } | ||
|
|
||
| func Warp[T any](v T) SchemaWrapper[T] { |
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.
@eiixy heads up: I think you meant Wrap instead of Warp here.
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.
Or even better: GenerateSchemaForType
jsonschema/json.go
Outdated
| } | ||
| d.Required = requiredFields | ||
| d.Properties = properties | ||
| default: |
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.
I suggest we either return an error or panic here
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.
Thank you for the suggestion!
api_integration_test.go
Outdated
| KebabCase string `json:"kebab_case" required:"true" description:"KebabCase"` | ||
| SnakeCase string `json:"snake_case" required:"true" description:"SnakeCase"` | ||
| } | ||
| schema := jsonschema.Warp(MyStructuredResponse{}) |
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.
Great stuff, I guess we should put a proper README example on how to use this. That should be one of the top examples for sure.
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.
I have added an example use case from OpenAI documentation to the README. For reference, please see: https://platform.openai.com/docs/guides/structured-outputs/examples
jsonschema/json.go
Outdated
| }) | ||
| } | ||
|
|
||
| type SchemaWrapper[T any] struct { |
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.
Pardon my ignorance: do we even need this type?
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.
The SchemaWrapper type is intended to bind the Definition and type together to ensure consistency during unmarshalling. This way, the schema’s type remains aligned with the initial definition, reducing the risk of errors or mismatches during data handling.
sw, err := jsonschema.Wrap(MyStructuredResponse{})
result, err := sw.Unmarshal(`{...}`)or
var result MyStructuredResponse{}
schema, err := jsonschema.GenerateSchemaForType(result)
schema.Unmarshal(`{...}`, &result)|
Great work, super excited for this! |
|
If this PR is not going to be finished soon, would it be possible to lift the small change to Also, I feel that using |
|
@sashabaranov @gspeicher I have updated the PR status to "ready." Please review the latest changes and let me know if there are any further adjustments needed. Thank you for your suggestions and patience! |
|
@eiixy thanks for pulling this together quickly. My feedback is centered around
|
type Result struct {
Steps []struct {
Explanation string `json:"explanation"`
Output string `json:"output"`
} `json:"steps"`
FinalAnswer string `json:"final_answer"`
}
sw, err := jsonschema.Wrap(Result{})
if err != nil {
log.Fatalf("JSONSchema Wrap error: %v", err)
}
resp, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
Model: openai.GPT4oMini,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleSystem,
Content: "You are a helpful math tutor. Guide the user through the solution step by step.",
},
{
Role: openai.ChatMessageRoleUser,
Content: "how can I solve 8x + 7 = -23",
},
},
ResponseFormat: &openai.ChatCompletionResponseFormat{
Type: openai.ChatCompletionResponseFormatTypeJSONSchema,
JSONSchema: &openai.ChatCompletionResponseFormatJSONSchema{
Name: "math_reasoning",
Schema: sw,
Strict: true,
},
},
})
if err != nil {
log.Fatalf("CreateChatCompletion error: %v", err)
}
result, err := sw.Unmarshal(resp.Choices[0].Message.Content)
if err != nil {
log.Fatalf("Unmarshal error: %v", err)
} |
|
Taking your example and converting it to use would become: Again, this is not my library so I defer to @sashabaranov but I personally don't see the point in including that alternative since the standard Having said that, I'm chomping at the bit to see this PR get merged and start using Structured Output so I'm not going to die on this hill. |
I've removed the |
| _, ok := data.(string) | ||
| return ok | ||
| case Number: // float64 and int | ||
| _, ok := data.(float64) |
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.
should we also support float32 here?
sashabaranov
left a comment
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.
Great work, thank you!!
|
I’m building a service-to-service integration that needs to bind incoming chat-completion requests directly into the Go client’s ChatCompletionRequest struct. But when doing this get the following error: This is happening cause Schema is of type json.Marshaler which does not implement an unmarshal function. |
Uh oh!
There was an error while loading. Please reload this page.