From 6bd397ce8b2e1352ddb7d77234819b23a0a75ed2 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Wed, 13 Mar 2024 08:28:55 -0400 Subject: [PATCH] genai: remove FunctionSchema (#69) Remove the schema inference feature until we can be sure it is the right design. --- genai/client_test.go | 7 ---- genai/schema.go | 85 -------------------------------------------- genai/schema_test.go | 69 ----------------------------------- 3 files changed, 161 deletions(-) delete mode 100644 genai/schema.go delete mode 100644 genai/schema_test.go diff --git a/genai/client_test.go b/genai/client_test.go index 01d7397..57cf748 100644 --- a/genai/client_test.go +++ b/genai/client_test.go @@ -356,13 +356,6 @@ func TestLive(t *testing.T) { Required: []string{"location"}, }) }) - t.Run("inferred", func(t *testing.T) { - s, err := FunctionSchema(func(string) {}, "location") - if err != nil { - t.Fatal(err) - } - weatherChat(t, s) - }) }) } diff --git a/genai/schema.go b/genai/schema.go deleted file mode 100644 index 5be6049..0000000 --- a/genai/schema.go +++ /dev/null @@ -1,85 +0,0 @@ -package genai - -import ( - "errors" - "fmt" - "reflect" -) - -// FunctionSchema returns a Schema for a Go function. -// Not all functions can be represented as Schemas. -// At present, variadic functions are not supported, and parameters -// must be of builtin, pointer, slice or array type. -// -// Parameter names are not available to the program. They can be supplied -// as arguments. If omitted, the names "p0", "p1", ... are used. -func FunctionSchema(function any, paramNames ...string) (*Schema, error) { - t := reflect.TypeOf(function) - if t == nil || t.Kind() != reflect.Func { - return nil, fmt.Errorf("value of type %T is not a function", function) - } - if t.IsVariadic() { - return nil, errors.New("variadic functions not supported") - } - params := map[string]*Schema{} - var req []string - for i := 0; i < t.NumIn(); i++ { - var name string - if i < len(paramNames) { - name = paramNames[i] - } else { - name = fmt.Sprintf("p%d", i) - } - s, err := typeSchema(t.In(i)) - if err != nil { - return nil, fmt.Errorf("param %s: %w", name, err) - } - params[name] = s - // All parameters are required. - req = append(req, name) - } - return &Schema{ - Type: TypeObject, - Properties: params, - Required: req, - }, nil - -} - -func typeSchema(t reflect.Type) (_ *Schema, err error) { - defer func() { - if err != nil { - err = fmt.Errorf("%s: %w", t, err) - } - }() - switch t.Kind() { - case reflect.Bool: - return &Schema{Type: TypeBoolean}, nil - case reflect.String: - return &Schema{Type: TypeString}, nil - case reflect.Int, reflect.Int64, reflect.Uint32: - return &Schema{Type: TypeInteger, Format: "int64"}, nil - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16: - return &Schema{Type: TypeInteger, Format: "int32"}, nil - case reflect.Float32: - return &Schema{Type: TypeNumber, Format: "float"}, nil - case reflect.Float64, reflect.Uint, reflect.Uint64, reflect.Uintptr: - return &Schema{Type: TypeNumber, Format: "double"}, nil - case reflect.Slice, reflect.Array: - elemSchema, err := typeSchema(t.Elem()) - if err != nil { - return nil, err - } - return &Schema{Type: TypeArray, Items: elemSchema}, nil - case reflect.Pointer: - // Treat a *T as a nullable T. - s, err := typeSchema(t.Elem()) - if err != nil { - return nil, err - } - s.Nullable = true - return s, nil - default: - return nil, errors.New("not supported") - } -} diff --git a/genai/schema_test.go b/genai/schema_test.go deleted file mode 100644 index c7089a8..0000000 --- a/genai/schema_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package genai - -import ( - "reflect" - "testing" -) - -var intSchema = &Schema{Type: TypeInteger, Format: "int64"} - -func TestTypeSchema(t *testing.T) { - for _, test := range []struct { - in any - want *Schema - }{ - {true, &Schema{Type: TypeBoolean}}, - {"", &Schema{Type: TypeString}}, - {1, intSchema}, - {byte(1), &Schema{Type: TypeInteger, Format: "int32"}}, - {1.2, &Schema{Type: TypeNumber, Format: "double"}}, - {float32(1.2), &Schema{Type: TypeNumber, Format: "float"}}, - {new(int), &Schema{Type: TypeInteger, Format: "int64", Nullable: true}}, - { - []int{}, - &Schema{Type: TypeArray, Items: intSchema}, - }, - } { - got, err := typeSchema(reflect.TypeOf(test.in)) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(got, test.want) { - t.Errorf("%T:\ngot %+v\nwant %+v", test.in, got, test.want) - } - } -} - -func TestFunctionSchema(t *testing.T) { - f := func(a int, b string, c float64) int { return 0 } - got, err := FunctionSchema(f, "a", "b") - if err != nil { - t.Fatal(err) - } - want := &Schema{ - Type: TypeObject, - Properties: map[string]*Schema{ - "a": intSchema, - "b": {Type: TypeString}, - "p2": {Type: TypeNumber, Format: "double"}, - }, - Required: []string{"a", "b", "p2"}, - } - if !reflect.DeepEqual(got, want) { - t.Errorf("\ngot %+v\nwant %+v", got, want) - } -} - -func TestFunctionSchemaErrors(t *testing.T) { - for i, f := range []any{ - nil, - 3, // not a function - func(x ...int) {}, // variadic - func(x any) {}, // unsupported type - } { - _, err := FunctionSchema(f) - if err == nil { - t.Errorf("#%d: got nil, want error", i) - } - } -}