2222import time
2323from typing import Any , Callable , Dict , List , Optional , Set , Tuple , TYPE_CHECKING , Union
2424
25+ from google import genai
26+ from google .cloud import aiplatform
2527from google .cloud .aiplatform import base
2628from google .cloud .aiplatform_v1beta1 .types import (
2729 content as gapic_content_types ,
@@ -373,6 +375,106 @@ def _generate_content_text_response(
373375 return constants .RESPONSE_ERROR
374376
375377
378+ def _generate_content_text_response_genai (
379+ model : str , client : genai .Client , prompt : str , max_retries : int = 3
380+ ) -> str :
381+ """Generates a text response from Gemini model from a text prompt with retries using genai module.
382+
383+ Args:
384+ model: The model name string.
385+ client: The genai client instance.
386+ prompt: The prompt to send to the model.
387+ max_retries: Maximum number of retries for response generation.
388+
389+ Returns:
390+ The text response from the model.
391+ Returns constants.RESPONSE_ERROR if there is an error after all retries.
392+ """
393+ for retry_attempt in range (max_retries ):
394+ try :
395+ response = client .models .generate_content (
396+ model = model ,
397+ contents = prompt ,
398+ )
399+ # The new SDK raises exceptions on blocked content instead of returning
400+ # block_reason directly, so if it succeeds, we can return the text.
401+ if response .text :
402+ return response .text
403+ else :
404+ _LOGGER .warning (
405+ "The model response was empty or blocked.\n "
406+ f"Prompt: { prompt } .\n "
407+ f"Retry attempt: { retry_attempt + 1 } /{ max_retries } "
408+ )
409+ except Exception as e : # pylint: disable=broad-except
410+ error_message = (
411+ f"Failed to generate response candidates from GenAI model "
412+ f"{ model } .\n "
413+ f"Error: { e } .\n "
414+ f"Prompt: { prompt } .\n "
415+ f"Retry attempt: { retry_attempt + 1 } /{ max_retries } "
416+ )
417+ _LOGGER .warning (error_message )
418+ if retry_attempt < max_retries - 1 :
419+ _LOGGER .info (
420+ f"Retrying response generation for prompt: { prompt } , attempt "
421+ f"{ retry_attempt + 1 } /{ max_retries } ..."
422+ )
423+
424+ final_error_message = (
425+ f"Failed to generate response from GenAI model { model } .\n " f"Prompt: { prompt } ."
426+ )
427+ _LOGGER .warning (final_error_message )
428+ return constants .RESPONSE_ERROR
429+
430+
431+ def _generate_responses_from_genai_model (
432+ model : str ,
433+ evaluation_run_config : evaluation_base .EvaluationRunConfig ,
434+ is_baseline_model : bool = False ,
435+ ) -> None :
436+ """Generates responses from Gemini model using genai module.
437+
438+ Args:
439+ model: The model name string.
440+ evaluation_run_config: Evaluation Run Configurations.
441+ is_baseline_model: Whether the model is a baseline model for PairwiseMetric.
442+ """
443+ df = evaluation_run_config .dataset .copy ()
444+
445+ _LOGGER .info (
446+ f"Generating a total of { evaluation_run_config .dataset .shape [0 ]} "
447+ f"responses from Gemini model { model } using genai module."
448+ )
449+ tasks = []
450+ client = genai .Client (
451+ vertexai = True ,
452+ project = aiplatform .initializer .global_config .project ,
453+ location = aiplatform .initializer .global_config .location ,
454+ )
455+ with tqdm (total = len (df )) as pbar :
456+ with futures .ThreadPoolExecutor (max_workers = constants .MAX_WORKERS ) as executor :
457+ for _ , row in df .iterrows ():
458+ task = executor .submit (
459+ _generate_content_text_response_genai ,
460+ prompt = row [constants .Dataset .PROMPT_COLUMN ],
461+ model = model ,
462+ client = client ,
463+ )
464+ task .add_done_callback (lambda _ : pbar .update (1 ))
465+ tasks .append (task )
466+ responses = [future .result () for future in tasks ]
467+ if is_baseline_model :
468+ evaluation_run_config .dataset = df .assign (baseline_model_response = responses )
469+ else :
470+ evaluation_run_config .dataset = df .assign (response = responses )
471+
472+ _LOGGER .info (
473+ f"All { evaluation_run_config .dataset .shape [0 ]} responses are successfully "
474+ f"generated from Gemini model { model } using genai module."
475+ )
476+
477+
376478def _generate_responses_from_gemini_model (
377479 model : generative_models .GenerativeModel ,
378480 evaluation_run_config : evaluation_base .EvaluationRunConfig ,
@@ -463,7 +565,7 @@ def _generate_response_from_custom_model_fn(
463565
464566
465567def _run_model_inference (
466- model : Union [generative_models .GenerativeModel , Callable [[str ], str ]],
568+ model : Union [str , generative_models .GenerativeModel , Callable [[str ], str ]],
467569 evaluation_run_config : evaluation_base .EvaluationRunConfig ,
468570 response_column_name : str = constants .Dataset .MODEL_RESPONSE_COLUMN ,
469571) -> None :
@@ -488,9 +590,18 @@ def _run_model_inference(
488590 if constants .Dataset .PROMPT_COLUMN in evaluation_run_config .dataset .columns :
489591 t1 = time .perf_counter ()
490592 if isinstance (model , generative_models .GenerativeModel ):
593+ _LOGGER .warning (
594+ "vertexai.generative_models.GenerativeModel is deprecated for "
595+ "evaluation and will be removed in June 2026. Please pass a "
596+ "string model name instead."
597+ )
491598 _generate_responses_from_gemini_model (
492599 model , evaluation_run_config , is_baseline_model
493600 )
601+ elif isinstance (model , str ):
602+ _generate_responses_from_genai_model (
603+ model , evaluation_run_config , is_baseline_model
604+ )
494605 elif callable (model ):
495606 _generate_response_from_custom_model_fn (
496607 model , evaluation_run_config , is_baseline_model
@@ -878,7 +989,7 @@ def evaluate(
878989 metrics : List [Union [str , metrics_base ._Metric ]],
879990 * ,
880991 model : Optional [
881- Union [generative_models .GenerativeModel , Callable [[str ], str ]]
992+ Union [str , generative_models .GenerativeModel , Callable [[str ], str ]]
882993 ] = None ,
883994 prompt_template : Optional [Union [str , prompt_template_base .PromptTemplate ]] = None ,
884995 metric_column_mapping : Dict [str , str ],
0 commit comments