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(py): Refactored Plugins API to follow generic Plugin interface. #1950

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

kirgrim
Copy link
Contributor

@kirgrim kirgrim commented Feb 12, 2025

Description

  • Refactored Plugin API to use generic genkit.core.plugin_abc.Plugin interface
  • Updated VertexAI implementation to follow the new specification

Checklist (if applicable):

@kirgrim kirgrim requested review from yesudeep and Irillit February 12, 2025 15:52
@github-actions github-actions bot added feature New feature or request python Python labels Feb 12, 2025

from genkit.core.schemas import GenerateRequest, GenerateResponse

if typing.TYPE_CHECKING:

Choose a reason for hiding this comment

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

Why? just import the genkit

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why? just import the genkit

circular import issue: we import plugin into the genkit veneer for initializaion, here we need it only for type annotation

@kirgrim kirgrim requested a review from kamilkorski February 12, 2025 17:00
@kirgrim kirgrim force-pushed the hrymailo/feat/moving-py-genkit-plugins-to-classes branch from d5d1c5b to 6c20f99 Compare February 12, 2025 17:02
@kirgrim kirgrim requested a review from Irillit February 12, 2025 17:03
@kirgrim kirgrim force-pushed the hrymailo/feat/moving-py-genkit-plugins-to-classes branch from 6c20f99 to f0c4bb7 Compare February 12, 2025 17:14
self, veneer: Genkit, name: str, metadata: dict | None = None
) -> None:
"""
Generic method for defining arbitrary plugin's model
Copy link
Contributor

Choose a reason for hiding this comment

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

Please, change the description. It is no longer generic.

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
Contributor Author

Choose a reason for hiding this comment

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

Please use Google style docstrings: https://google.github.io/styleguide/pyguide.html#381-docstrings

updated according to the guidelines

for plugin in plugins:
plugin(self)
plugin.attach_to_veneer(veneer=self)
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like you add all the models here. I wonder, if attach_to_veneer() should accept Genkit here.You can attach it:

  1. To registry inside the attach_to_veneer()
  2. Just return values. We'll have the dictionary of the SUPPORTED_MODELS with ModelInfo, and, if we need, a Callable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like you add all the models here. I wonder, if attach_to_veneer() should accept Genkit here.You can attach it:

  1. To registry inside the attach_to_veneer()
  2. Just return values. We'll have the dictionary of the SUPPORTED_MODELS with ModelInfo, and, if we need, a Callable.
  1. do not really support this approach as we have a different ways of defining models/embedders/etc based on plugin
  2. it is not only models, also embedders and logic is not always that trivial according to JS implementations

@@ -66,9 +65,9 @@ def delete_runtime_file() -> None:
self.thread = threading.Thread(target=self.start_server)
self.thread.start()

if plugins is not None:
if plugins:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think, there should be an error, if there are no plugins. Genkit becomes useless.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think, there should be an error, if there are no plugins. Genkit becomes useless.

I do not think that we need to raise an error in such case: we do not know how developers are going to use our library and maybe they would just use server and insert models/plugins later on.

Although I would add warning in case no plugins are provided

from genkit.core.reflection import make_reflection_server
from genkit.core.registry import Registry
from genkit.core.schemas import GenerateRequest, GenerateResponse, Message

Plugin = Callable[['Genkit'], None]


class Genkit:
Copy link
Contributor

Choose a reason for hiding this comment

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

In init of that class we also have a 'model' paramter, that is added as model field and never used. At the same time attach_to_veneer registers all the models. Do we have a special reason of keeping it? Should we filter it or pass it to some method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In init of that class we also have a 'model' paramter, that is added as model field and never used. At the same time attach_to_veneer registers all the models. Do we have a special reason of keeping it? Should we filter it or pass it to some method?

Not sure, but would not update interface of this class as a part of this PR

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I found it later. It seems that it looks for a model.

)

@abc.abstractmethod
def _model_callback(self, request: GenerateRequest) -> GenerateResponse:
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder, if here we have only one callback. One provider has several models at once.

Copy link
Contributor Author

@kirgrim kirgrim Feb 13, 2025

Choose a reason for hiding this comment

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

I wonder, if here we have only one callback. One provider has several models at once.

afaik, as a rule, each single callback receives GenerateRequest and returns GenerateResponse I would prefer not to complicate things and handle any special cases separately in the future

Copy link
Contributor

Choose a reason for hiding this comment

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

Well, look. VertexAI should support the following models (from the JS code):

export const SUPPORTED_V1_MODELS = {
  'gemini-1.0-pro': gemini10Pro,
};

export const SUPPORTED_V15_MODELS = {
  'gemini-1.5-pro': gemini15Pro,
  'gemini-1.5-flash': gemini15Flash,
  'gemini-2.0-flash-001': gemini20Flash001,
  'gemini-2.0-flash-lite-preview-02-05': gemini20FlashLitePreview0205,
  'gemini-2.0-pro-exp-02-05': gemini20ProExp0205,
};

Let me check, but probably they should all be in a registry in order you want to call them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, look. VertexAI should support the following models (from the JS code):

export const SUPPORTED_V1_MODELS = {
  'gemini-1.0-pro': gemini10Pro,
};

export const SUPPORTED_V15_MODELS = {
  'gemini-1.5-pro': gemini15Pro,
  'gemini-1.5-flash': gemini15Flash,
  'gemini-2.0-flash-001': gemini20Flash001,
  'gemini-2.0-flash-lite-preview-02-05': gemini20FlashLitePreview0205,
  'gemini-2.0-pro-exp-02-05': gemini20ProExp0205,
};

Let me check, but probably they should all be in a registry in order you want to call them.

yes, definitely, but implementation of the production-ready VertexAI is a separate task. Here I just introduced interface and made our minimal working sample work

@kirgrim kirgrim force-pushed the hrymailo/feat/moving-py-genkit-plugins-to-classes branch from f0c4bb7 to 168cad7 Compare February 13, 2025 15:14
@kirgrim kirgrim force-pushed the hrymailo/feat/moving-py-genkit-plugins-to-classes branch from 168cad7 to be033a4 Compare February 13, 2025 15:17
from genkit.core.reflection import make_reflection_server
from genkit.core.registry import Registry
from genkit.core.schemas import GenerateRequest, GenerateResponse, Message

Plugin = Callable[['Genkit'], None]
logger = logging.getLogger(__name__)


class Genkit:
Copy link
Contributor

Choose a reason for hiding this comment

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

I also heard Kamil proposed to use an interface for Genkit. If we do a separate AsyncGenkit veneer, that means that the interface might be a good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I also heard Kamil proposed to use an interface for Genkit. If we do a separate AsyncGenkit veneer, that means that the interface might be a good idea.

yeah, it might, but also would keep it as a separate effort from this PR

@kirgrim kirgrim requested a review from Irillit February 13, 2025 15:25
@yesudeep
Copy link
Contributor

Can you please rebase this PR? I think the PR checks should pass now

@yesudeep yesudeep added this to the py-0.1.0 milestone Feb 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request python Python
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

4 participants