diff --git a/libs/genai/langchain_google_genai/chat_models.py b/libs/genai/langchain_google_genai/chat_models.py index 3c8119be6..cb8b906c8 100644 --- a/libs/genai/langchain_google_genai/chat_models.py +++ b/libs/genai/langchain_google_genai/chat_models.py @@ -6,6 +6,7 @@ import json import logging import mimetypes +import re import time import uuid import warnings @@ -58,6 +59,8 @@ from langchain_core.language_models import ( LangSmithParams, LanguageModelInput, + ModelProfile, + ModelProfileRegistry, is_openai_data_block, ) from langchain_core.language_models.chat_models import BaseChatModel @@ -124,6 +127,7 @@ ImageBytesLoader, image_bytes_to_b64_string, ) +from langchain_google_genai.data._profiles import _PROFILES from . import _genai_extension as genaix @@ -137,6 +141,13 @@ "__gemini_function_call_thought_signatures__" ) +_MODEL_PROFILES = cast("ModelProfileRegistry", _PROFILES) + + +def _get_default_model_profile(model_name: str) -> ModelProfile: + default = _MODEL_PROFILES.get(model_name) or {} + return default.copy() + def _bytes_to_base64(data: bytes) -> str: return base64.b64encode(data).decode("utf-8") @@ -2070,6 +2081,14 @@ def async_client(self) -> v1betaGenerativeServiceAsyncClient: ) return self.async_client_running + @model_validator(mode="after") + def _set_model_profile(self) -> Self: + """Set model profile if not overridden.""" + if self.profile is None: + model_id = re.sub(r"-\d{3}$", "", self.model.replace("models/", "")) + self.profile = _get_default_model_profile(model_id) + return self + @property def _identifying_params(self) -> dict[str, Any]: """Get the identifying parameters.""" diff --git a/libs/genai/langchain_google_genai/data/__init__.py b/libs/genai/langchain_google_genai/data/__init__.py new file mode 100644 index 000000000..07c24b141 --- /dev/null +++ b/libs/genai/langchain_google_genai/data/__init__.py @@ -0,0 +1 @@ +"""Model profile data. All edits should be made in profile_augmentations.toml.""" diff --git a/libs/genai/langchain_google_genai/data/_profiles.py b/libs/genai/langchain_google_genai/data/_profiles.py new file mode 100644 index 000000000..ec57b81ca --- /dev/null +++ b/libs/genai/langchain_google_genai/data/_profiles.py @@ -0,0 +1,432 @@ +"""Auto-generated model profiles. + +DO NOT EDIT THIS FILE MANUALLY. +This file is generated by the langchain-profiles CLI tool. + +It contains data derived from the models.dev project. + +Source: https://github.com/sst/models.dev +License: MIT License + +To update these data, refer to the instructions here: + +https://docs.langchain.com/oss/python/langchain/models#updating-or-overwriting-profile-data +""" + +from typing import Any + +_PROFILES: dict[str, dict[str, Any]] = { + "gemini-embedding-001": { + "max_input_tokens": 2048, + "max_output_tokens": 3072, + "image_inputs": False, + "audio_inputs": False, + "video_inputs": False, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": False, + "tool_calling": False, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-image": { + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "image_inputs": True, + "audio_inputs": False, + "video_inputs": False, + "image_outputs": True, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": False, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-preview-05-20": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-flash-lite-latest": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-3-pro-preview": { + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-flash-latest": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-pro-preview-05-06": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-preview-tts": { + "max_input_tokens": 8000, + "max_output_tokens": 16000, + "image_inputs": False, + "audio_inputs": False, + "video_inputs": False, + "image_outputs": False, + "audio_outputs": True, + "video_outputs": False, + "reasoning_output": False, + "tool_calling": False, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.0-flash-lite": { + "max_input_tokens": 1048576, + "max_output_tokens": 8192, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": False, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-live-2.5-flash-preview-native-audio": { + "max_input_tokens": 131072, + "max_output_tokens": 65536, + "image_inputs": False, + "audio_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": True, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.0-flash": { + "max_input_tokens": 1048576, + "max_output_tokens": 8192, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": False, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-lite": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-pro-preview-06-05": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-live-2.5-flash": { + "max_input_tokens": 128000, + "max_output_tokens": 8000, + "image_inputs": True, + "audio_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": True, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-lite-preview-06-17": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-image-preview": { + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "image_inputs": True, + "audio_inputs": False, + "video_inputs": False, + "image_outputs": True, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": False, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-preview-09-2025": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-preview-04-17": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-pro-preview-tts": { + "max_input_tokens": 8000, + "max_output_tokens": 16000, + "image_inputs": False, + "audio_inputs": False, + "video_inputs": False, + "image_outputs": False, + "audio_outputs": True, + "video_outputs": False, + "reasoning_output": False, + "tool_calling": False, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-pro": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-1.5-flash": { + "max_input_tokens": 1000000, + "max_output_tokens": 8192, + "image_inputs": True, + "audio_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": False, + "tool_calling": True, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-1.5-flash-8b": { + "max_input_tokens": 1000000, + "max_output_tokens": 8192, + "image_inputs": True, + "audio_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": False, + "tool_calling": True, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-2.5-flash-lite-preview-09-2025": { + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "image_inputs": True, + "audio_inputs": True, + "pdf_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": True, + "tool_calling": True, + "structured_output": True, + "image_url_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, + "gemini-1.5-pro": { + "max_input_tokens": 1000000, + "max_output_tokens": 8192, + "image_inputs": True, + "audio_inputs": True, + "video_inputs": True, + "image_outputs": False, + "audio_outputs": False, + "video_outputs": False, + "reasoning_output": False, + "tool_calling": True, + "image_url_inputs": True, + "pdf_inputs": True, + "image_tool_message": True, + "tool_choice": True, + }, +} diff --git a/libs/genai/langchain_google_genai/data/profile_augmentations.toml b/libs/genai/langchain_google_genai/data/profile_augmentations.toml new file mode 100644 index 000000000..cc2fde6ea --- /dev/null +++ b/libs/genai/langchain_google_genai/data/profile_augmentations.toml @@ -0,0 +1,7 @@ +provider = "google" + +[overrides] +image_url_inputs = true +pdf_inputs = true +image_tool_message = true +tool_choice = true diff --git a/libs/genai/pyproject.toml b/libs/genai/pyproject.toml index 3b1dc7f57..84393e65e 100644 --- a/libs/genai/pyproject.toml +++ b/libs/genai/pyproject.toml @@ -55,6 +55,9 @@ test_integration = [ "pytest>=8.4.0,<9.0.0", ] +[tool.uv.sources] +langchain-core = { git = "https://github.com/langchain-ai/langchain", subdirectory = "libs/core", branch = "cc/model_profiles_distributed" } + [tool.ruff] fix = true diff --git a/libs/genai/tests/unit_tests/test_chat_models.py b/libs/genai/tests/unit_tests/test_chat_models.py index 1c7db6b1a..3aacc807e 100644 --- a/libs/genai/tests/unit_tests/test_chat_models.py +++ b/libs/genai/tests/unit_tests/test_chat_models.py @@ -212,6 +212,19 @@ def test_api_key_masked_when_passed_via_constructor( assert captured.out == "**********" +def test_profile() -> None: + model = ChatGoogleGenerativeAI(model="gemini-1.5-flash") + assert model.profile + assert not model.profile["reasoning_output"] + + model = ChatGoogleGenerativeAI(model="gemini-2.5-flash") + assert model.profile + assert model.profile["reasoning_output"] + + model = ChatGoogleGenerativeAI(model="foo") + assert model.profile == {} + + def test_parse_history() -> None: convert_system_message_to_human = False system_input = "You're supposed to answer math questions." diff --git a/libs/genai/uv.lock b/libs/genai/uv.lock index ff1408a96..f691a92ed 100644 --- a/libs/genai/uv.lock +++ b/libs/genai/uv.lock @@ -484,8 +484,8 @@ wheels = [ [[package]] name = "langchain-core" -version = "1.0.5" -source = { registry = "https://pypi.org/simple" } +version = "1.0.7" +source = { git = "https://github.com/langchain-ai/langchain?subdirectory=libs%2Fcore&branch=cc%2Fmodel_profiles_distributed#b7ec8735b2589fe1815ce3c58e41410824bf67b7" } dependencies = [ { name = "jsonpatch" }, { name = "langsmith" }, @@ -495,10 +495,6 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d9/61/c356e19525a210baf960968dbfb03ee38a05e05ddb41efeb32abfcb4e360/langchain_core-1.0.5.tar.gz", hash = "sha256:7ecbad9a60dde626252733a9c18c7377f4468cfe00465ffa99f5e9c6cb9b82d2", size = 778259, upload-time = "2025-11-14T16:59:27.277Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/ee/aaf2343a35080154c82ceb110e03dd00f15459bc72e518df51724cbc41a9/langchain_core-1.0.5-py3-none-any.whl", hash = "sha256:d24c0cf12cfcd96dd4bd479aa91425f3a6652226cd824228ae422a195067b74e", size = 471506, upload-time = "2025-11-14T16:59:25.629Z" }, -] [[package]] name = "langchain-google-genai" @@ -545,7 +541,7 @@ typing = [ requires-dist = [ { name = "filetype", specifier = ">=1.2.0,<2.0.0" }, { name = "google-ai-generativelanguage", specifier = ">=0.9.0,<1.0.0" }, - { name = "langchain-core", specifier = ">=1.0.5,<2.0.0" }, + { name = "langchain-core", git = "https://github.com/langchain-ai/langchain?subdirectory=libs%2Fcore&branch=cc%2Fmodel_profiles_distributed" }, { name = "pydantic", specifier = ">=2.0.0,<3.0.0" }, ]