Skip to content

feat(go/plugins): Generic OpenAI plugin #2440

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

Open
wants to merge 61 commits into
base: main
Choose a base branch
from

Conversation

kekoawong
Copy link
Contributor

@kekoawong kekoawong commented Mar 23, 2025

Adding support for an openai go plugin, along with additional generic support for any providers compatible with the openai (from feature request #2204). Collaboration between @xavidop @yukinagae @kekoawong.

Checklist:

  • Support complete response from chat completions
  • Support streaming from chat completions
  • Add generic compatibility
  • Add embedding support
  • Add tools support

@github-actions github-actions bot added docs Improvements or additions to documentation go labels Mar 23, 2025
Copy link
Contributor

@yukinagae yukinagae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

initted bool
client *openaiGo.Client
Opts []option.RequestOption
Provider string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments here would be good. What is provider?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added here: kekoawong#11

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, don't see anything here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd like comments on each field of OpenAICompatible. As a user, how do I know what you put for Provider? Comment explaining what it is and examples of what goes in there is helpful without looking up documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

},
{
name: "float and int fields",
config: &openai.ChatCompletionNewParams{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should try not to depend directly on the config type defined elsewhere (like in 3P SDKs) so that the SDKs are implementation details and we could in theory swap out to another or even call the REST API directly. We sometimes implement configuration via native Genkit features so if we have it both natively and in the config, it will be confusing as to what happens when you combine them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed here: kekoawong#11

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.Log("genkit initialized")

// Initialize the OpenAI plugin
apiKeyOption := option.WithAPIKey(apiKey)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which other options do we (want to) support? Maybe APIKey should be a top level field in OpenAI like it is in GoogleAI? Better to err on the side of being simple and complete rather than supporting everything that the SDK supports.

feat(go/openai plugin): support additional OpenAI models
)

type OpenAI struct {
Opts []option.RequestOption
Copy link
Contributor

@yukinagae yukinagae Apr 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Opts field is never used, in other words, the current implementation does not handle the passed options.

For example, even if the API key is passed via the option like this, the OpenAI client is reading the environment variable instead:

apiKeyOption := option.WithAPIKey("sk-xxxxx")
oai := &openai.OpenAI{
    Opts: []option.RequestOption{apiKeyOption},
}

Copy link
Collaborator

@apascal07 apascal07 Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, we might want to just bring out APIKey as a top level field in the OpenAI struct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in here: kekoawong#11

t.Logf("streaming response: %+v", finalOutput)
})

t.Run("tool usage with basic completion", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function calling test is flaky depending on the model. It seems to be related to math.Pow(), and I'll give it a try to fix it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is fixed already

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I haven't done this yet. What I’ve found so far is that the math.Pow() function returns a value between 11 and 13, depending on how the model generates code and handles floating-point values internally. Since all tests are currently passing and the issue isn’t critical, I’d leave it as is for now and revise it if it comes up again.

t.Logf("tool usage with basic completion response: %+v", out)
})

t.Run("tool usage with streaming", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's flaky, just like the function calling test with basic completion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is fixed already

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment: #2440 (comment)

@xavidop xavidop mentioned this pull request Apr 9, 2025
3 tasks
}

// DefineModel defines a model in the registry
func (o *OpenAICompatible) DefineModel(g *genkit.Genkit, name, provider string, info ai.ModelInfo) (ai.Model, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (o *OpenAICompatible) DefineModel(g *genkit.Genkit, name, provider string, info ai.ModelInfo) (ai.Model, error) {
func (o *OpenAICompatible) DefineModel(g *genkit.Genkit, provider, name string, info ai.ModelInfo) (ai.Model, error) {

}

// DefineEmbedder defines an embedder with a given name.
func (o *OpenAICompatible) DefineEmbedder(g *genkit.Genkit, name string, provider string) (ai.Embedder, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (o *OpenAICompatible) DefineEmbedder(g *genkit.Genkit, name string, provider string) (ai.Embedder, error) {
func (o *OpenAICompatible) DefineEmbedder(g *genkit.Genkit, provider, name string) (ai.Embedder, error) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to documentation go
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

4 participants