Skip to content
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

feat(go): new plugin creation way + dep issues fixed #2496

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3bba12b
Outline for plugin
kekoawong Mar 14, 2025
6dbfd2f
add openai client package
kekoawong Mar 14, 2025
c124510
Added outline for supported models
kekoawong Mar 14, 2025
d749d68
incomplete generate file
kekoawong Mar 17, 2025
db4caf3
Initial builder of generate functionality complete
kekoawong Mar 17, 2025
1afb36f
Added live tests for the generator function
kekoawong Mar 17, 2025
78c365a
Added generator functionality
kekoawong Mar 18, 2025
ec2383e
Added testing docs
kekoawong Mar 18, 2025
c699625
Added package changes
kekoawong Mar 18, 2025
eadab5b
Moved to compat_oai
kekoawong Mar 20, 2025
d4e4cc0
Moved to compat_oai
kekoawong Mar 20, 2025
5e2cb4b
Updated testing functions
kekoawong Mar 20, 2025
e8e8121
Renamed generator to ModelGenerator
kekoawong Mar 20, 2025
e731e3b
Added docstrings
kekoawong Mar 20, 2025
7c897c5
Added live test for plugin
kekoawong Mar 20, 2025
0849271
Updated documentation on how to run tests
kekoawong Mar 20, 2025
5e39216
Tests failing
kekoawong Mar 20, 2025
343d2c6
Tests still failing initially
kekoawong Mar 21, 2025
a7cf666
Added multimodal capabilities
kekoawong Mar 21, 2025
0d54e56
Added usage and request initialization
kekoawong Mar 23, 2025
e3caa0c
Merge pull request #1 from kekoawong/kekoawong/open-ai-plugin
kekoawong Mar 23, 2025
8eb80d7
Added embedding support
yukinagae Mar 24, 2025
ffe8955
Remove check for embedder, since users can add them
yukinagae Mar 24, 2025
33595be
Merge pull request #2 from kekoawong/yukinagae/openai-plugin-embedder
yukinagae Mar 24, 2025
4f08315
feat: make the plugin generic
xavidop Mar 26, 2025
a9f982d
fix: rename file
xavidop Mar 26, 2025
78c3661
Update openai.go
xavidop Mar 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,18 @@ retract (
)

require (
cloud.google.com/go/aiplatform v1.68.0
cloud.google.com/go/firestore v1.16.0
cloud.google.com/go/logging v1.11.0
firebase.google.com/go/v4 v4.14.1
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.46.0
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.22.0
github.com/aymerick/raymond v2.0.2+incompatible
github.com/google/generative-ai-go v0.19.0
github.com/google/go-cmp v0.6.0
github.com/invopop/jsonschema v0.12.0
github.com/jba/slog v0.2.0
github.com/lib/pq v1.10.9
github.com/pgvector/pgvector-go v0.2.0
github.com/stretchr/testify v1.9.0
github.com/weaviate/weaviate v1.26.0-rc.1
github.com/weaviate/weaviate-go-client/v4 v4.15.0
github.com/wk8/go-ordered-map/v2 v2.1.8
Expand All @@ -34,14 +33,22 @@ require (
golang.org/x/tools v0.23.0
google.golang.org/api v0.197.0
google.golang.org/genai v0.5.0
google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)

require (
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/ai v0.8.0 // indirect
cloud.google.com/go/auth v0.9.3 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute/metadata v0.5.0 // indirect
Expand Down Expand Up @@ -81,6 +88,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/openai/openai-go v0.1.0-alpha.65
github.com/pkg/errors v0.9.1 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
Expand Down
24 changes: 18 additions & 6 deletions go/go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
cloud.google.com/go/ai v0.8.0 h1:rXUEz8Wp2OlrM8r1bfmpF2+VKqc1VJpafE3HgzRnD/w=
cloud.google.com/go/ai v0.8.0/go.mod h1:t3Dfk4cM61sytiggo2UyGsDVW3RF1qGZaUKDrZFyqkE=
cloud.google.com/go/aiplatform v1.68.0 h1:EPPqgHDJpBZKRvv+OsB3cr0jYz3EL2pZ+802rBPcG8U=
cloud.google.com/go/aiplatform v1.68.0/go.mod h1:105MFA3svHjC3Oazl7yjXAmIR89LKhRAeNdnDKJczME=
cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U=
cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk=
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
Expand Down Expand Up @@ -149,8 +145,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/generative-ai-go v0.19.0 h1:R71szggh8wHMCUlEMsW2A/3T+5LdEIkiaHSYgSpUgdg=
github.com/google/generative-ai-go v0.19.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
Expand Down Expand Up @@ -223,6 +217,12 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/openai/openai-go v0.1.0-alpha.63 h1:bOlYE6NJcPdjG3OMl9rZnxJrxmwcG6zlEKOD1MHP9Is=
github.com/openai/openai-go v0.1.0-alpha.63/go.mod h1:3SdE6BffOX9HPEQv8IL/fi3LYZ5TUpRYaqGQZbyk11A=
github.com/openai/openai-go v0.1.0-alpha.65 h1:G12sA6OaL+cVMElMO3m5RVFwKhhg40kmGeGhaYZIoYw=
github.com/openai/openai-go v0.1.0-alpha.65/go.mod h1:3SdE6BffOX9HPEQv8IL/fi3LYZ5TUpRYaqGQZbyk11A=
github.com/openai/openai-go v0.1.0-alpha.66 h1:s+txdNJIsEVcDT+N3Ir+9vDlh1X0o2mdU5Of9l1xvCI=
github.com/openai/openai-go v0.1.0-alpha.66/go.mod h1:3SdE6BffOX9HPEQv8IL/fi3LYZ5TUpRYaqGQZbyk11A=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/pgvector/pgvector-go v0.2.0 h1:NZdW4NxUxdSCzaev3LVHb9ORf+LdX+uZOQVqQ6s2Zyg=
github.com/pgvector/pgvector-go v0.2.0/go.mod h1:OQpvU5QZGQOPI9quIXAyHaRZ5yGk/RGUDbs9C3DPUNE=
Expand Down Expand Up @@ -258,7 +258,19 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
github.com/uptrace/bun v1.1.12 h1:sOjDVHxNTuM6dNGaba0wUuz7KvDE1BmNu9Gqs2gJSXQ=
Expand Down
154 changes: 154 additions & 0 deletions go/plugins/compat_oai/compat_oai.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package compat_oai

import (
"context"
"strings"
"sync"

"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
openaiGo "github.com/openai/openai-go"
"github.com/openai/openai-go/option"
)

var (
// BasicText describes model capabilities for text-only GPT models.
BasicText = ai.ModelInfoSupports{
Multiturn: true,
Tools: true,
SystemRole: true,
Media: false,
}

// Multimodal describes model capabilities for multimodal GPT models.
Multimodal = ai.ModelInfoSupports{
Multiturn: true,
Tools: true,
SystemRole: true,
Media: true,
}
)

// State management
var state struct {
mu sync.Mutex
initted bool
client *openaiGo.Client
}

func OpenAICompatible(ctx context.Context, g *genkit.Genkit, provider string, opts ...option.RequestOption) error {

state.mu.Lock()
defer state.mu.Unlock()
if state.initted {
panic("compat_oai.Init already called")
}

// create client
client := openaiGo.NewClient(opts...)
state.client = client
state.initted = true

return nil
}

// DefineModel defines a model in the registry
func DefineModel(g *genkit.Genkit, name string, info ai.ModelInfo, provider string) (ai.Model, error) {
if !state.initted {
panic("compat_oai.Init not called")
}

// Strip provider prefix if present to check against supportedModels
modelName := strings.TrimPrefix(name, provider+"/")

return genkit.DefineModel(g, provider, name, &info, func(
ctx context.Context,
input *ai.ModelRequest,
cb func(context.Context, *ai.ModelResponseChunk) error,
) (*ai.ModelResponse, error) {
generator := NewModelGenerator(state.client, modelName)

// Configure the generator with input
if input.Messages != nil {
generator.WithMessages(input.Messages)
}
if input.Config != nil {
generator.WithConfig(input.Config)
}

// Generate response
resp, err := generator.Generate(ctx, cb)
if err != nil {
return nil, err
}

// Ensure response has required fields
if resp == nil {
resp = &ai.ModelResponse{}
}
if resp.Message == nil {
resp.Message = &ai.Message{
Role: ai.RoleModel,
}
}
if resp.Usage == nil {
resp.Usage = &ai.GenerationUsage{}
}

return resp, nil
}), nil
}

// DefineEmbedder defines an embedder with a given name.
func DefineEmbedder(g *genkit.Genkit, name string, provider string) (ai.Embedder, error) {
if !state.initted {
panic("compat_oai.Init not called")
}

return genkit.DefineEmbedder(g, provider, name, func(ctx context.Context, input *ai.EmbedRequest) (*ai.EmbedResponse, error) {
var data openaiGo.EmbeddingNewParamsInputArrayOfStrings
for _, doc := range input.Documents {
for _, p := range doc.Content {
data = append(data, p.Text)
}
}

params := openaiGo.EmbeddingNewParams{
Input: openaiGo.F[openaiGo.EmbeddingNewParamsInputUnion](data),
Model: openaiGo.F(name),
EncodingFormat: openaiGo.F(openaiGo.EmbeddingNewParamsEncodingFormatFloat),
}

embeddingResp, err := state.client.Embeddings.New(ctx, params)
if err != nil {
return nil, err
}

resp := &ai.EmbedResponse{}
for _, emb := range embeddingResp.Data {
embedding := make([]float32, len(emb.Embedding))
for i, val := range emb.Embedding {
embedding[i] = float32(val)
}
resp.Embeddings = append(resp.Embeddings, &ai.DocumentEmbedding{Embedding: embedding})
}
return resp, nil
}), nil
}

// IsDefinedEmbedder reports whether the named [Embedder] is defined by this plugin.
func IsDefinedEmbedder(g *genkit.Genkit, name string, provider string) bool {
return genkit.IsDefinedEmbedder(g, provider, name)
}

// Embedder returns the [ai.Embedder] with the given name.
// It returns nil if the embedder was not defined.
func Embedder(g *genkit.Genkit, name string, provider string) ai.Embedder {
return genkit.LookupEmbedder(g, provider, name)
}

// Model returns the [ai.Model] with the given name.
// It returns nil if the model was not defined.
func Model(g *genkit.Genkit, name string, provider string) ai.Model {
return genkit.LookupModel(g, provider, name)
}
Loading