From af089a65ae9bbadecdf178da45a6c9c0577df2de Mon Sep 17 00:00:00 2001 From: thorwebdev <5748289+thorwebdev@users.noreply.github.com> Date: Fri, 5 Dec 2025 12:06:28 -0500 Subject: [PATCH] feat: add Gemini client identification. --- .../services/google/gemini_live/llm.py | 16 +++++++++++++ .../services/google/gemini_live/llm_vertex.py | 1 + src/pipecat/services/google/image.py | 23 +++++++++++++++++-- src/pipecat/services/google/llm.py | 16 +++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/pipecat/services/google/gemini_live/llm.py b/src/pipecat/services/google/gemini_live/llm.py index 19bcda730..ed242aa81 100644 --- a/src/pipecat/services/google/gemini_live/llm.py +++ b/src/pipecat/services/google/gemini_live/llm.py @@ -24,6 +24,7 @@ from loguru import logger from PIL import Image from pydantic import BaseModel, Field +from pipecat import __version__ from pipecat.adapters.schemas.tools_schema import ToolsSchema from pipecat.adapters.services.gemini_adapter import GeminiLLMAdapter from pipecat.frames.frames import ( @@ -682,6 +683,21 @@ class GeminiLiveLLMService(LLMService): self._context = None self._api_key = api_key self._http_options = http_options + + # Add client header + client_header = {"x-goog-api-client": f"pipecat/{__version__}"} + if self._http_options is None: + self._http_options = {"headers": client_header} + elif isinstance(self._http_options, dict): + if "headers" in self._http_options: + self._http_options["headers"].update(client_header) + else: + self._http_options["headers"] = client_header + elif hasattr(self._http_options, "headers"): + if self._http_options.headers is None: + self._http_options.headers = client_header + else: + self._http_options.headers.update(client_header) self._session: AsyncSession = None self._connection_task = None diff --git a/src/pipecat/services/google/gemini_live/llm_vertex.py b/src/pipecat/services/google/gemini_live/llm_vertex.py index a38154755..c58ef311d 100644 --- a/src/pipecat/services/google/gemini_live/llm_vertex.py +++ b/src/pipecat/services/google/gemini_live/llm_vertex.py @@ -126,6 +126,7 @@ class GeminiLiveVertexLLMService(GeminiLiveLLMService): credentials=self._credentials, project=self._project_id, location=self._location, + http_options=self._http_options, ) @property diff --git a/src/pipecat/services/google/image.py b/src/pipecat/services/google/image.py index f92c7bb2b..030fe7ee5 100644 --- a/src/pipecat/services/google/image.py +++ b/src/pipecat/services/google/image.py @@ -16,12 +16,13 @@ import os # Suppress gRPC fork warnings os.environ["GRPC_ENABLE_FORK_SUPPORT"] = "false" -from typing import AsyncGenerator, Optional +from typing import Any, AsyncGenerator, Optional from loguru import logger from PIL import Image from pydantic import BaseModel, Field +from pipecat import __version__ from pipecat.frames.frames import ErrorFrame, Frame, URLImageRawFrame from pipecat.services.image_service import ImageGenService @@ -60,6 +61,7 @@ class GoogleImageGenService(ImageGenService): *, api_key: str, params: Optional[InputParams] = None, + http_options: Optional[Any] = None, **kwargs, ): """Initialize the GoogleImageGenService with API key and parameters. @@ -67,11 +69,28 @@ class GoogleImageGenService(ImageGenService): Args: api_key: Google AI API key for authentication. params: Configuration parameters for image generation. Defaults to InputParams(). + http_options: HTTP options for the client. **kwargs: Additional arguments passed to the parent ImageGenService. """ super().__init__(**kwargs) self._params = params or GoogleImageGenService.InputParams() - self._client = genai.Client(api_key=api_key) + + # Add client header + client_header = {"x-goog-api-client": f"pipecat/{__version__}"} + if http_options is None: + http_options = {"headers": client_header} + elif isinstance(http_options, dict): + if "headers" in http_options: + http_options["headers"].update(client_header) + else: + http_options["headers"] = client_header + elif hasattr(http_options, "headers"): + if http_options.headers is None: + http_options.headers = client_header + else: + http_options.headers.update(client_header) + + self._client = genai.Client(api_key=api_key, http_options=http_options) self.set_model_name(self._params.model) def can_generate_metrics(self) -> bool: diff --git a/src/pipecat/services/google/llm.py b/src/pipecat/services/google/llm.py index 840b473b2..f28a4c1b0 100644 --- a/src/pipecat/services/google/llm.py +++ b/src/pipecat/services/google/llm.py @@ -22,6 +22,7 @@ from loguru import logger from PIL import Image from pydantic import BaseModel, Field +from pipecat import __version__ from pipecat.adapters.services.gemini_adapter import GeminiLLMAdapter, GeminiLLMInvocationParams from pipecat.frames.frames import ( AudioRawFrame, @@ -714,6 +715,21 @@ class GoogleLLMService(LLMService): self._api_key = api_key self._system_instruction = system_instruction self._http_options = http_options + + # Add client header + client_header = {"x-goog-api-client": f"pipecat/{__version__}"} + if self._http_options is None: + self._http_options = {"headers": client_header} + elif isinstance(self._http_options, dict): + if "headers" in self._http_options: + self._http_options["headers"].update(client_header) + else: + self._http_options["headers"] = client_header + elif hasattr(self._http_options, "headers"): + if self._http_options.headers is None: + self._http_options.headers = client_header + else: + self._http_options.headers.update(client_header) self._settings = { "max_tokens": params.max_tokens,