Skip to content

Commit

Permalink
move json schema to directory/package (#407)
Browse files Browse the repository at this point in the history
* move json schema to directory/package

* added jsonschema to README
  • Loading branch information
jmacwhyte committed Jun 24, 2023
1 parent 5f4ef29 commit 0ca4ea4
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 54 deletions.
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,66 @@ func main() {
```
</details>

<details>
<summary>JSON Schema for function calling</summary>

It is now possible for chat completion to choose to call a function for more information ([see developer docs here](https://platform.openai.com/docs/guides/gpt/function-calling)).

In order to describe the type of functions that can be called, a JSON schema must be provided. Many JSON schema libraries exist and are more advanced than what we can offer in this library, however we have included a simple `jsonschema` package for those who want to use this feature without formatting their own JSON schema payload.

The developer documents give this JSON schema definition as an example:

```json
{
"name":"get_current_weather",
"description":"Get the current weather in a given location",
"parameters":{
"type":"object",
"properties":{
"location":{
"type":"string",
"description":"The city and state, e.g. San Francisco, CA"
},
"unit":{
"type":"string",
"enum":[
"celsius",
"fahrenheit"
]
}
},
"required":[
"location"
]
}
}
```

Using the `jsonschema` package, this schema could be created using structs as such:

```go
FunctionDefinition{
Name: "get_current_weather",
Parameters: jsonschema.Definition{
Type: jsonschema.Object,
Properties: map[string]jsonschema.Definition{
"location": {
Type: jsonschema.String,
Description: "The city and state, e.g. San Francisco, CA",
},
"unit": {
Type: jsonschema.String,
Enum: []string{"celcius", "fahrenheit"},
},
},
Required: []string{"location"},
},
}
```

The `Parameters` field of a `FunctionDefinition` can accept either of the above styles, or even a nested struct from another library (as long as it can be marshalled into JSON).
</details>

<details>
<summary>Error handling</summary>

Expand Down
39 changes: 4 additions & 35 deletions chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,47 +62,16 @@ type FunctionDefinition struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
// Parameters is an object describing the function.
// You can pass a raw byte array describing the schema,
// or you can pass in a struct which serializes to the proper JSONSchema.
// The JSONSchemaDefinition struct is provided for convenience, but you should
// consider another specialized library for more complex schemas.
// You can pass a []byte describing the schema,
// or you can pass in a struct which serializes to the proper JSON schema.
// The jsonschema package is provided for convenience, but you should
// consider another specialized library if you require more complex schemas.
Parameters any `json:"parameters"`
}

// Deprecated: use FunctionDefinition instead.
type FunctionDefine = FunctionDefinition

type JSONSchemaType string

const (
JSONSchemaTypeObject JSONSchemaType = "object"
JSONSchemaTypeNumber JSONSchemaType = "number"
JSONSchemaTypeString JSONSchemaType = "string"
JSONSchemaTypeArray JSONSchemaType = "array"
JSONSchemaTypeNull JSONSchemaType = "null"
JSONSchemaTypeBoolean JSONSchemaType = "boolean"
)

// JSONSchemaDefinition is a struct for JSON Schema.
// It is fairly limited and you may have better luck using a third-party library.
type JSONSchemaDefinition struct {
// Type is a type of JSON Schema.
Type JSONSchemaType `json:"type,omitempty"`
// Description is a description of JSON Schema.
Description string `json:"description,omitempty"`
// Enum is a enum of JSON Schema. It used if Type is JSONSchemaTypeString.
Enum []string `json:"enum,omitempty"`
// Properties is a properties of JSON Schema. It used if Type is JSONSchemaTypeObject.
Properties map[string]JSONSchemaDefinition `json:"properties,omitempty"`
// Required is a required of JSON Schema. It used if Type is JSONSchemaTypeObject.
Required []string `json:"required,omitempty"`
// Items is a property of JSON Schema. It used if Type is JSONSchemaTypeArray.
Items *JSONSchemaDefinition `json:"items,omitempty"`
}

// Deprecated: use JSONSchemaDefinition instead.
type JSONSchemaDefine = JSONSchemaDefinition

type FinishReason string

const (
Expand Down
39 changes: 20 additions & 19 deletions chat_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package openai_test

import (
. "github.com/sashabaranov/go-openai"
"github.com/sashabaranov/go-openai/internal/test/checks"

"context"
"encoding/json"
"fmt"
Expand All @@ -13,6 +10,10 @@ import (
"strings"
"testing"
"time"

. "github.com/sashabaranov/go-openai"
"github.com/sashabaranov/go-openai/internal/test/checks"
"github.com/sashabaranov/go-openai/jsonschema"
)

func TestChatCompletionsWrongModel(t *testing.T) {
Expand Down Expand Up @@ -128,22 +129,22 @@ func TestChatCompletionsFunctions(t *testing.T) {
},
Functions: []FunctionDefinition{{
Name: "test",
Parameters: &JSONSchemaDefinition{
Type: JSONSchemaTypeObject,
Properties: map[string]JSONSchemaDefinition{
Parameters: &jsonschema.Definition{
Type: jsonschema.Object,
Properties: map[string]jsonschema.Definition{
"count": {
Type: JSONSchemaTypeNumber,
Type: jsonschema.Number,
Description: "total number of words in sentence",
},
"words": {
Type: JSONSchemaTypeArray,
Type: jsonschema.Array,
Description: "list of words in sentence",
Items: &JSONSchemaDefinition{
Type: JSONSchemaTypeString,
Items: &jsonschema.Definition{
Type: jsonschema.String,
},
},
"enumTest": {
Type: JSONSchemaTypeString,
Type: jsonschema.String,
Enum: []string{"hello", "world"},
},
},
Expand All @@ -165,22 +166,22 @@ func TestChatCompletionsFunctions(t *testing.T) {
},
Functions: []FunctionDefine{{
Name: "test",
Parameters: &JSONSchemaDefine{
Type: JSONSchemaTypeObject,
Properties: map[string]JSONSchemaDefine{
Parameters: &jsonschema.Definition{
Type: jsonschema.Object,
Properties: map[string]jsonschema.Definition{
"count": {
Type: JSONSchemaTypeNumber,
Type: jsonschema.Number,
Description: "total number of words in sentence",
},
"words": {
Type: JSONSchemaTypeArray,
Type: jsonschema.Array,
Description: "list of words in sentence",
Items: &JSONSchemaDefine{
Type: JSONSchemaTypeString,
Items: &jsonschema.Definition{
Type: jsonschema.String,
},
},
"enumTest": {
Type: JSONSchemaTypeString,
Type: jsonschema.String,
Enum: []string{"hello", "world"},
},
},
Expand Down
35 changes: 35 additions & 0 deletions jsonschema/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Package jsonschema provides very simple functionality for representing a JSON schema as a
// (nested) struct. This struct can be used with the chat completion "function call" feature.
// For more complicated schemas, it is recommended to use a dedicated JSON schema library
// and/or pass in the schema in []byte format.
package jsonschema

type DataType string

const (
Object DataType = "object"
Number DataType = "number"
Integer DataType = "integer"
String DataType = "string"
Array DataType = "array"
Null DataType = "null"
Boolean DataType = "boolean"
)

// Definition is a struct for describing a JSON Schema.
// It is fairly limited and you may have better luck using a third-party library.
type Definition struct {
// Type specifies the data type of the schema.
Type DataType `json:"type,omitempty"`
// Description is the description of the schema.
Description string `json:"description,omitempty"`
// Enum is used to restrict a value to a fixed set of values. It must be an array with at least
// one element, where each element is unique. You will probably only use this with strings.
Enum []string `json:"enum,omitempty"`
// Properties describes the properties of an object, if the schema type is Object.
Properties map[string]Definition `json:"properties,omitempty"`
// Required specifies which properties are required, if the schema type is Object.
Required []string `json:"required,omitempty"`
// Items specifies which data type an array contains, if the schema type is Array.
Items *Definition `json:"items,omitempty"`
}

0 comments on commit 0ca4ea4

Please sign in to comment.