From 17291949cb0b8857f849f228d651b580f40c5763 Mon Sep 17 00:00:00 2001 From: Mark McDonald Date: Mon, 29 Jan 2024 15:27:39 +0800 Subject: [PATCH 1/2] Add a more explicit error when no `parts` returned When a response has been blocked, the API will return a `Candidate` (with `finish_reason`, `safety_ratings`, etc) that does not have `Part`s. Given blocking is common enough, and we can identify this case, I've added a more explicit (and helpful?) error message to guide users if this happens. --- google/generativeai/types/generation_types.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/google/generativeai/types/generation_types.py b/google/generativeai/types/generation_types.py index 57ce2e0de..b4db16966 100644 --- a/google/generativeai/types/generation_types.py +++ b/google/generativeai/types/generation_types.py @@ -324,6 +324,13 @@ def text(self): ValueError: If the candidate list or parts list does not contain exactly one entry. """ parts = self.parts + if not parts: + raise ValueError( + "The `response.text` quick accessor only works when the response contains a valid " + "`Part`, but none was returned. Check the `candidate.safety_ratings` to see if the " + "response was blocked." + ) + if len(parts) != 1 or "text" not in parts[0]: raise ValueError( "The `response.text` quick accessor only works for " From 55d618f2236916e0f22e0840bd14a343d41baa8a Mon Sep 17 00:00:00 2001 From: Mark McDonald Date: Mon, 29 Jan 2024 15:42:50 +0800 Subject: [PATCH 2/2] Run latest version of `black` These appear to be new changes, unrelated to this PR, but sure why not. --- google/generativeai/embedding.py | 6 ++---- google/generativeai/notebook/lib/llmfn_outputs.py | 6 ++---- google/generativeai/notebook/magics_engine.py | 4 +--- google/generativeai/text.py | 6 ++---- google/generativeai/types/generation_types.py | 8 +++++--- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/google/generativeai/embedding.py b/google/generativeai/embedding.py index 42edb7fcf..982116eca 100644 --- a/google/generativeai/embedding.py +++ b/google/generativeai/embedding.py @@ -93,8 +93,7 @@ def embed_content( task_type: EmbeddingTaskTypeOptions | None = None, title: str | None = None, client: glm.GenerativeServiceClient | None = None, -) -> text_types.EmbeddingDict: - ... +) -> text_types.EmbeddingDict: ... @overload @@ -104,8 +103,7 @@ def embed_content( task_type: EmbeddingTaskTypeOptions | None = None, title: str | None = None, client: glm.GenerativeServiceClient | None = None, -) -> text_types.BatchEmbeddingDict: - ... +) -> text_types.BatchEmbeddingDict: ... def embed_content( diff --git a/google/generativeai/notebook/lib/llmfn_outputs.py b/google/generativeai/notebook/lib/llmfn_outputs.py index 0defdfd1f..c0bf50fe2 100644 --- a/google/generativeai/notebook/lib/llmfn_outputs.py +++ b/google/generativeai/notebook/lib/llmfn_outputs.py @@ -109,12 +109,10 @@ def __len__(self) -> int: # Needed for Sequence[LLMFnOutputEntry]. @overload - def __getitem__(self, x: int) -> LLMFnOutputEntry: - ... + def __getitem__(self, x: int) -> LLMFnOutputEntry: ... @overload - def __getitem__(self, x: slice) -> Sequence[LLMFnOutputEntry]: - ... + def __getitem__(self, x: slice) -> Sequence[LLMFnOutputEntry]: ... def __getitem__(self, x: int | slice) -> LLMFnOutputEntry | Sequence[LLMFnOutputEntry]: return self._outputs.__getitem__(x) diff --git a/google/generativeai/notebook/magics_engine.py b/google/generativeai/notebook/magics_engine.py index 0be004e07..ea6eeb46f 100644 --- a/google/generativeai/notebook/magics_engine.py +++ b/google/generativeai/notebook/magics_engine.py @@ -61,9 +61,7 @@ def parse_line( ) -> tuple[parsed_args_lib.ParsedArgs, parsed_args_lib.PostProcessingTokens]: return cmd_line_parser.CmdLineParser().parse_line(line, placeholders) - def _get_handler( - self, line: str, placeholders: AbstractSet[str] - ) -> tuple[ + def _get_handler(self, line: str, placeholders: AbstractSet[str]) -> tuple[ command.Command, parsed_args_lib.ParsedArgs, Sequence[post_process_utils.ParsedPostProcessExpr], diff --git a/google/generativeai/text.py b/google/generativeai/text.py index 98d49964d..0c90dc1ff 100644 --- a/google/generativeai/text.py +++ b/google/generativeai/text.py @@ -263,8 +263,7 @@ def generate_embeddings( model: model_types.BaseModelNameOptions, text: str, client: glm.TextServiceClient = None, -) -> text_types.EmbeddingDict: - ... +) -> text_types.EmbeddingDict: ... @overload @@ -272,8 +271,7 @@ def generate_embeddings( model: model_types.BaseModelNameOptions, text: Sequence[str], client: glm.TextServiceClient = None, -) -> text_types.BatchEmbeddingDict: - ... +) -> text_types.BatchEmbeddingDict: ... def generate_embeddings( diff --git a/google/generativeai/types/generation_types.py b/google/generativeai/types/generation_types.py index b4db16966..10ab86676 100644 --- a/google/generativeai/types/generation_types.py +++ b/google/generativeai/types/generation_types.py @@ -268,9 +268,11 @@ class BaseGenerateContentResponse: def __init__( self, done: bool, - iterator: None - | Iterable[glm.GenerateContentResponse] - | AsyncIterable[glm.GenerateContentResponse], + iterator: ( + None + | Iterable[glm.GenerateContentResponse] + | AsyncIterable[glm.GenerateContentResponse] + ), result: glm.GenerateContentResponse, chunks: Iterable[glm.GenerateContentResponse], ):