Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion packages/gen/README_sphynx.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ google-genai~=1.60.0 # google
boto3>=1.40.61 # amazon
aiobotocore>=3.0.0 # amazon
langchain~=1.2.6
langchain_google_genai~=4.2.0 # google
langchain_google_genai~=4.4.0 # google
langchain-classic~=1.0.0
langchain-community~=0.4.1
langchain-openai~=1.1.0
Expand Down
12 changes: 12 additions & 0 deletions packages/gen/gen_ai_hub/proxy/langchain/google_genai.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from langchain_google_genai import ChatGoogleGenerativeAI as ChatGoogleGenerativeAI_
from langchain_google_genai import GoogleGenerativeAIEmbeddings as GoogleGenerativeAIEmbeddings_
from langchain_google_genai.chat_models import _ClientCleanup # private upstream name, since 4.3.7
from pydantic import model_validator, ConfigDict

from gen_ai_hub.proxy.core.base import BaseProxyClient
Expand Down Expand Up @@ -115,6 +116,17 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, ChatGoogleGenerativeAI_):
def _init_parent(self, **kwargs):
ChatGoogleGenerativeAI_.__init__(self, **kwargs)

@model_validator(mode="after")
def _register_client_cleanup(self):
"""Register the injected client for cleanup.

Upstream wraps the client in a ``_ClientCleanup`` stored in
``_client_cleanup``, which ``async_client`` and ``aclose`` read. That
happens in a validator this class shadows, so do it here instead.
"""
self._client_cleanup = _ClientCleanup(self.client)
return self


class GoogleGenerativeAIEmbeddings(_BaseGoogleGenerativeAI, GoogleGenerativeAIEmbeddings_):
"""Drop-in replacement for langchain_google_genai.GoogleGenerativeAIEmbeddings."""
Expand Down
2 changes: 1 addition & 1 deletion packages/gen/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ dependencies = [
]

[project.optional-dependencies]
google = ["google-genai~=2.23.0", "langchain-google-genai~=4.3.6,<4.3.7"]
google = ["google-genai~=2.23.0", "langchain-google-genai~=4.4.0"]
amazon = ["boto3>=1.40.61", "aiobotocore>=3.2.0", "langchain-aws~=1.7.0"]
all = ["sap-ai-sdk-gen[google,amazon]"]

Expand Down
11 changes: 11 additions & 0 deletions packages/gen/tests/proxy/langchain_/test_google_genai.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import asyncio
import unittest
from unittest.mock import patch

from google.genai.client import AsyncClient
from langchain_classic.chains import LLMChain
from langchain_classic.prompts.chat import (
AIMessagePromptTemplate,
Expand All @@ -19,6 +21,15 @@ class TestGoogleGenerativeAILangchain(unittest.TestCase):
def setUpClass(cls) -> None:
cls.proxy_client = get_mocked_ai_core_client()

def test_async_client_available(self):
# `async_client` and `aclose` read `_client_cleanup`, which our validator
# has to set because the upstream validator that normally sets it is shadowed.
chat_model = ChatGoogleGenerativeAI(
proxy_model_name="gemini-2.0-flash", proxy_client=self.proxy_client
)
self.assertIsInstance(chat_model.async_client, AsyncClient)
asyncio.run(chat_model.aclose())

@patch("langchain_classic.chains.base.Chain.invoke")
def test_chat_model(self, mock_chain_invoke):
mock_chain_invoke.return_value = GOOGLE_GEMINI_INVOKE_RESPONSE
Expand Down
8 changes: 4 additions & 4 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading