google-cloud-agentplatform 2.3.0__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {google_cloud_agentplatform-2.3.0/google_cloud_agentplatform.egg-info → google_cloud_agentplatform-2.4.0}/PKG-INFO +1 -1
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_evals_common.py +28 -18
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_evals_data_converters.py +306 -1
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_evals_metric_handlers.py +21 -5
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_evals_metric_loaders.py +9 -4
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_evals_visualization.py +3 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_transformers.py +5 -1
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/evals.py +14 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/runtimes.py +8 -2
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/types/__init__.py +6 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/types/common.py +140 -6
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/frameworks/adk.py +35 -18
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/version.py +1 -1
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0/google_cloud_agentplatform.egg-info}/PKG-INFO +1 -1
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/LICENSE +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/README.md +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/__init__.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/__init__.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_bigquery_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_datasets_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_evals_builtin_tools.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_evals_constant.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_evals_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_gcs_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_logging_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_memory_bank_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_observability_data_converter.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_operations_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_prompt_management_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_prompt_optimizer_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_runtimes_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/_skills_utils.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/a2a_task_events.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/a2a_tasks.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/client.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/datasets.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/endpoints.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/example_stores.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/feedback_contexts.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/feedback_entries.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/live.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/live_runtimes.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/memories.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/memory_banks.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/memory_revisions.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/model_garden.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/prompt_optimizer.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/prompts.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/rag.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/runtime_revisions.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/sandbox_snapshots.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/sandbox_templates.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/sandboxes.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/serving_profiles.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/session_events.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/sessions.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/skill_revisions.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/skills.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/types/agent_engines.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/types/evals.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/types/prompt_optimizer.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/types/prompts.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/frameworks/__init__.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/frameworks/a2a.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/frameworks/ag2.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/frameworks/langchain.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/frameworks/langgraph.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/frameworks/llama_index.py +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/google_cloud_agentplatform.egg-info/SOURCES.txt +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/google_cloud_agentplatform.egg-info/dependency_links.txt +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/google_cloud_agentplatform.egg-info/requires.txt +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/google_cloud_agentplatform.egg-info/top_level.txt +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/pyproject.toml +0 -0
- {google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/setup.cfg +0 -0
|
@@ -2654,7 +2654,7 @@ def _execute_inference(
|
|
|
2654
2654
|
"Gemini Agent inference completed in %.2f seconds.",
|
|
2655
2655
|
end_time - start_time,
|
|
2656
2656
|
)
|
|
2657
|
-
|
|
2657
|
+
evaluation_dataset = types.EvaluationDataset(
|
|
2658
2658
|
eval_dataset_df=results_df,
|
|
2659
2659
|
candidate_name=gemini_agent.split("/")[-1],
|
|
2660
2660
|
)
|
|
@@ -2759,7 +2759,12 @@ def _execute_inference(
|
|
|
2759
2759
|
results_df.to_json(full_dest_path, orient="records", lines=True)
|
|
2760
2760
|
logger.info("Results saved locally to: %s", full_dest_path)
|
|
2761
2761
|
except Exception as e: # pylint: disable=broad-exception-caught
|
|
2762
|
-
logger.error(
|
|
2762
|
+
logger.error(
|
|
2763
|
+
"Failed to save results to %s. Error: %s",
|
|
2764
|
+
full_dest_path,
|
|
2765
|
+
e,
|
|
2766
|
+
exc_info=True,
|
|
2767
|
+
)
|
|
2763
2768
|
|
|
2764
2769
|
return evaluation_dataset
|
|
2765
2770
|
|
|
@@ -2886,6 +2891,21 @@ def _resolve_dataset_inputs(
|
|
|
2886
2891
|
return processed_eval_dataset, num_response_candidates
|
|
2887
2892
|
|
|
2888
2893
|
|
|
2894
|
+
def _prebuilt_evaluation_run_metric(
|
|
2895
|
+
resolved_metric: types.Metric,
|
|
2896
|
+
) -> types.EvaluationRunMetric:
|
|
2897
|
+
"""Builds the evaluation run metric for a resolved RubricMetric."""
|
|
2898
|
+
if resolved_metric.name in _evals_constant.SUPPORTED_PREDEFINED_METRICS:
|
|
2899
|
+
metric_config = t.t_metrics([resolved_metric])[0]
|
|
2900
|
+
else:
|
|
2901
|
+
metric_config = {
|
|
2902
|
+
"predefined_metric_spec": {"metric_spec_name": resolved_metric.name}
|
|
2903
|
+
}
|
|
2904
|
+
return types.EvaluationRunMetric(
|
|
2905
|
+
metric=resolved_metric.name, metric_config=metric_config
|
|
2906
|
+
)
|
|
2907
|
+
|
|
2908
|
+
|
|
2889
2909
|
def _resolve_evaluation_run_metrics(
|
|
2890
2910
|
metrics: Union[list[types.EvaluationRunMetric], list[types.Metric]], api_client: Any
|
|
2891
2911
|
) -> list[types.EvaluationRunMetric]:
|
|
@@ -2903,14 +2923,7 @@ def _resolve_evaluation_run_metrics(
|
|
|
2903
2923
|
resolved_metric = metric_instance.resolve(api_client=api_client)
|
|
2904
2924
|
if resolved_metric.name:
|
|
2905
2925
|
resolved_metrics_list.append(
|
|
2906
|
-
|
|
2907
|
-
metric=resolved_metric.name,
|
|
2908
|
-
metric_config=types.UnifiedMetric(
|
|
2909
|
-
predefined_metric_spec=genai_types.PredefinedMetricSpec(
|
|
2910
|
-
metric_spec_name=resolved_metric.name,
|
|
2911
|
-
)
|
|
2912
|
-
),
|
|
2913
|
-
)
|
|
2926
|
+
_prebuilt_evaluation_run_metric(resolved_metric)
|
|
2914
2927
|
)
|
|
2915
2928
|
except Exception as e:
|
|
2916
2929
|
logger.error(
|
|
@@ -2944,14 +2957,7 @@ def _resolve_evaluation_run_metrics(
|
|
|
2944
2957
|
)
|
|
2945
2958
|
if resolved_metric.name:
|
|
2946
2959
|
resolved_metrics_list.append(
|
|
2947
|
-
|
|
2948
|
-
metric=resolved_metric.name,
|
|
2949
|
-
metric_config=types.UnifiedMetric(
|
|
2950
|
-
predefined_metric_spec=genai_types.PredefinedMetricSpec(
|
|
2951
|
-
metric_spec_name=resolved_metric.name,
|
|
2952
|
-
)
|
|
2953
|
-
),
|
|
2954
|
-
)
|
|
2960
|
+
_prebuilt_evaluation_run_metric(resolved_metric)
|
|
2955
2961
|
)
|
|
2956
2962
|
else:
|
|
2957
2963
|
raise TypeError(
|
|
@@ -3020,6 +3026,7 @@ def _execute_evaluation( # type: ignore[no-untyped-def]
|
|
|
3020
3026
|
dest: Optional[str] = None,
|
|
3021
3027
|
location: Optional[str] = None,
|
|
3022
3028
|
evaluation_service_qps: Optional[float] = None,
|
|
3029
|
+
allow_cross_region_model: Optional[bool] = None,
|
|
3023
3030
|
**kwargs,
|
|
3024
3031
|
) -> types.EvaluationResult:
|
|
3025
3032
|
"""Evaluates a dataset using the provided metrics.
|
|
@@ -3035,6 +3042,8 @@ def _execute_evaluation( # type: ignore[no-untyped-def]
|
|
|
3035
3042
|
evaluation_service_qps: The rate limit (queries per second) for calls
|
|
3036
3043
|
to the evaluation service. Defaults to 10. Increase this value if
|
|
3037
3044
|
your project has a higher EvaluateInstances API quota.
|
|
3045
|
+
allow_cross_region_model: Opt-in flag to authorize cross-region
|
|
3046
|
+
routing for judge models.
|
|
3038
3047
|
**kwargs: Extra arguments to pass to evaluation, such as `agent_info`.
|
|
3039
3048
|
|
|
3040
3049
|
Returns:
|
|
@@ -3117,6 +3126,7 @@ def _execute_evaluation( # type: ignore[no-untyped-def]
|
|
|
3117
3126
|
evaluation_result = _evals_metric_handlers.compute_metrics_and_aggregate(
|
|
3118
3127
|
evaluation_run_config,
|
|
3119
3128
|
evaluation_service_qps=evaluation_service_qps,
|
|
3129
|
+
allow_cross_region_model=allow_cross_region_model,
|
|
3120
3130
|
)
|
|
3121
3131
|
t2 = time.perf_counter()
|
|
3122
3132
|
logger.info("Evaluation took: %f seconds", t2 - t1)
|
|
@@ -15,15 +15,18 @@
|
|
|
15
15
|
"""Dataset converters for evals."""
|
|
16
16
|
|
|
17
17
|
import copy
|
|
18
|
+
import datetime
|
|
18
19
|
import json
|
|
19
20
|
import logging
|
|
20
|
-
from typing import Any, Optional, Union
|
|
21
|
+
from typing import Any, Optional, TypeVar, Union
|
|
21
22
|
|
|
22
23
|
from google.genai import _common
|
|
23
24
|
from google.genai import types as genai_types
|
|
25
|
+
from pydantic import alias_generators
|
|
24
26
|
from pydantic import ValidationError
|
|
25
27
|
from typing_extensions import override
|
|
26
28
|
|
|
29
|
+
from . import _evals_constant
|
|
27
30
|
from . import _evals_utils
|
|
28
31
|
from . import _observability_data_converter
|
|
29
32
|
from . import types
|
|
@@ -605,6 +608,308 @@ class _OpenAIDataConverter(_evals_utils.EvalDataConverter):
|
|
|
605
608
|
return types.EvaluationDataset(eval_cases=eval_cases)
|
|
606
609
|
|
|
607
610
|
|
|
611
|
+
_ADK_EVAL_CASE_FIELDS = frozenset(
|
|
612
|
+
{
|
|
613
|
+
"eval_id",
|
|
614
|
+
"conversation",
|
|
615
|
+
"conversation_scenario",
|
|
616
|
+
"session_input",
|
|
617
|
+
"creation_timestamp",
|
|
618
|
+
"rubrics",
|
|
619
|
+
"final_session_state",
|
|
620
|
+
}
|
|
621
|
+
)
|
|
622
|
+
_ADK_EVAL_CASE_KEYS = _ADK_EVAL_CASE_FIELDS | {
|
|
623
|
+
alias_generators.to_camel(field) for field in _ADK_EVAL_CASE_FIELDS
|
|
624
|
+
}
|
|
625
|
+
_ADK_SESSION_INPUT_FIELDS = ("app_name", "user_id", "state")
|
|
626
|
+
_ADK_DEFAULT_RUBRIC_GROUP = "adk_rubrics"
|
|
627
|
+
_REFERENCE_TRAJECTORY = "reference_trajectory"
|
|
628
|
+
|
|
629
|
+
_GenaiModel = TypeVar("_GenaiModel", bound=_common.BaseModel)
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
def _get_adk_field(data: dict[str, Any], name: str) -> Any:
|
|
633
|
+
"""Returns an ADK eval set field, which ADK accepts in snake or camel case."""
|
|
634
|
+
if not isinstance(data, dict):
|
|
635
|
+
raise TypeError(f"Expected a JSON object for '{name}', got {type(data)}.")
|
|
636
|
+
if name in data:
|
|
637
|
+
return data[name]
|
|
638
|
+
return data.get(alias_generators.to_camel(name))
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
def _validate_adk_genai(model: type[_GenaiModel], data: Any) -> _GenaiModel:
|
|
642
|
+
"""Validates ADK eval set JSON as a genai type.
|
|
643
|
+
|
|
644
|
+
Validating in JSON mode decodes base64 bytes fields, such as inline data and
|
|
645
|
+
thought signatures, the same way ADK does when it reads an eval set file.
|
|
646
|
+
|
|
647
|
+
Args:
|
|
648
|
+
model: The genai type to validate as.
|
|
649
|
+
data: The parsed JSON value from the eval set.
|
|
650
|
+
|
|
651
|
+
Returns:
|
|
652
|
+
The validated genai object.
|
|
653
|
+
"""
|
|
654
|
+
return model.model_validate_json(json.dumps(data))
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
def _adk_content(data: dict[str, Any], default_role: str) -> genai_types.Content:
|
|
658
|
+
"""Validates an ADK Content, filling in the role when the file omits it."""
|
|
659
|
+
content = _validate_adk_genai(genai_types.Content, data)
|
|
660
|
+
if not content.role:
|
|
661
|
+
content.role = default_role
|
|
662
|
+
return content
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
def _adk_user_content(invocation: dict[str, Any]) -> genai_types.Content:
|
|
666
|
+
"""Returns the user content of an ADK invocation."""
|
|
667
|
+
user_content = _get_adk_field(invocation, "user_content")
|
|
668
|
+
if user_content is None:
|
|
669
|
+
raise ValueError("Every invocation must have user_content.")
|
|
670
|
+
return _adk_content(user_content, "user")
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
def _adk_intermediate_events(
|
|
674
|
+
intermediate_data: Optional[dict[str, Any]],
|
|
675
|
+
) -> list[tuple[Optional[str], genai_types.Content]]:
|
|
676
|
+
"""Returns (author, content) pairs from ADK IntermediateData or InvocationEvents."""
|
|
677
|
+
if not intermediate_data:
|
|
678
|
+
return []
|
|
679
|
+
invocation_events = _get_adk_field(intermediate_data, "invocation_events")
|
|
680
|
+
if invocation_events is not None:
|
|
681
|
+
return [
|
|
682
|
+
(
|
|
683
|
+
_get_adk_field(event, "author"),
|
|
684
|
+
_validate_adk_genai(
|
|
685
|
+
genai_types.Content, _get_adk_field(event, "content")
|
|
686
|
+
),
|
|
687
|
+
)
|
|
688
|
+
for event in invocation_events
|
|
689
|
+
if _get_adk_field(event, "content")
|
|
690
|
+
]
|
|
691
|
+
|
|
692
|
+
events: list[tuple[Optional[str], genai_types.Content]] = []
|
|
693
|
+
tool_uses = _get_adk_field(intermediate_data, "tool_uses")
|
|
694
|
+
if tool_uses:
|
|
695
|
+
events.append(
|
|
696
|
+
(
|
|
697
|
+
None,
|
|
698
|
+
genai_types.Content(
|
|
699
|
+
role="model",
|
|
700
|
+
parts=[
|
|
701
|
+
genai_types.Part(
|
|
702
|
+
function_call=_validate_adk_genai(
|
|
703
|
+
genai_types.FunctionCall, tool_use
|
|
704
|
+
)
|
|
705
|
+
)
|
|
706
|
+
for tool_use in tool_uses
|
|
707
|
+
],
|
|
708
|
+
),
|
|
709
|
+
)
|
|
710
|
+
)
|
|
711
|
+
tool_responses = _get_adk_field(intermediate_data, "tool_responses")
|
|
712
|
+
if tool_responses:
|
|
713
|
+
events.append(
|
|
714
|
+
(
|
|
715
|
+
None,
|
|
716
|
+
genai_types.Content(
|
|
717
|
+
role="user",
|
|
718
|
+
parts=[
|
|
719
|
+
genai_types.Part(
|
|
720
|
+
function_response=_validate_adk_genai(
|
|
721
|
+
genai_types.FunctionResponse, tool_response
|
|
722
|
+
)
|
|
723
|
+
)
|
|
724
|
+
for tool_response in tool_responses
|
|
725
|
+
],
|
|
726
|
+
),
|
|
727
|
+
)
|
|
728
|
+
)
|
|
729
|
+
for author, parts in (
|
|
730
|
+
_get_adk_field(intermediate_data, "intermediate_responses") or []
|
|
731
|
+
):
|
|
732
|
+
events.append(
|
|
733
|
+
(
|
|
734
|
+
author,
|
|
735
|
+
genai_types.Content(
|
|
736
|
+
role="model",
|
|
737
|
+
parts=[
|
|
738
|
+
_validate_adk_genai(genai_types.Part, part) for part in parts
|
|
739
|
+
],
|
|
740
|
+
),
|
|
741
|
+
)
|
|
742
|
+
)
|
|
743
|
+
return events
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
class AdkEvalSetConverter(_evals_utils.EvalDataConverter):
|
|
747
|
+
"""Converter for ADK eval sets (the `.evalset.json` format).
|
|
748
|
+
|
|
749
|
+
Reads the eval set JSON directly, so google-adk does not need to be
|
|
750
|
+
installed.
|
|
751
|
+
"""
|
|
752
|
+
|
|
753
|
+
def _invocation_to_messages(
|
|
754
|
+
self, invocation: dict[str, Any], turn_index: int
|
|
755
|
+
) -> list[types.evals.Message]:
|
|
756
|
+
"""Converts an earlier ADK invocation into conversation history messages."""
|
|
757
|
+
turn_id = _get_adk_field(invocation, "invocation_id") or str(turn_index)
|
|
758
|
+
timestamp = _get_adk_field(invocation, "creation_timestamp")
|
|
759
|
+
messages = [
|
|
760
|
+
types.evals.Message(
|
|
761
|
+
turn_id=turn_id,
|
|
762
|
+
author="user",
|
|
763
|
+
content=_adk_user_content(invocation),
|
|
764
|
+
creation_timestamp=(
|
|
765
|
+
datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
|
|
766
|
+
if timestamp
|
|
767
|
+
else None
|
|
768
|
+
),
|
|
769
|
+
)
|
|
770
|
+
]
|
|
771
|
+
messages.extend(
|
|
772
|
+
types.evals.Message(turn_id=turn_id, author=author, content=content)
|
|
773
|
+
for author, content in _adk_intermediate_events(
|
|
774
|
+
_get_adk_field(invocation, "intermediate_data")
|
|
775
|
+
)
|
|
776
|
+
)
|
|
777
|
+
final_response = _get_adk_field(invocation, "final_response")
|
|
778
|
+
if final_response:
|
|
779
|
+
messages.append(
|
|
780
|
+
types.evals.Message(
|
|
781
|
+
turn_id=turn_id, content=_adk_content(final_response, "model")
|
|
782
|
+
)
|
|
783
|
+
)
|
|
784
|
+
return messages
|
|
785
|
+
|
|
786
|
+
def _convert_rubrics(
|
|
787
|
+
self, rubrics: list[dict[str, Any]]
|
|
788
|
+
) -> dict[str, types.RubricGroup]:
|
|
789
|
+
"""Groups ADK rubrics by their type, which ADK uses to select rubrics."""
|
|
790
|
+
groups: dict[str, list[types.evals.Rubric]] = {}
|
|
791
|
+
for rubric in rubrics:
|
|
792
|
+
rubric_type = _get_adk_field(rubric, "type")
|
|
793
|
+
rubric_content = _get_adk_field(rubric, "rubric_content") or {}
|
|
794
|
+
groups.setdefault(rubric_type or _ADK_DEFAULT_RUBRIC_GROUP, []).append(
|
|
795
|
+
types.evals.Rubric(
|
|
796
|
+
rubric_id=_get_adk_field(rubric, "rubric_id"),
|
|
797
|
+
type=rubric_type,
|
|
798
|
+
content=types.evals.RubricContent(
|
|
799
|
+
property=types.evals.RubricContentProperty(
|
|
800
|
+
description=_get_adk_field(rubric_content, "text_property")
|
|
801
|
+
)
|
|
802
|
+
),
|
|
803
|
+
)
|
|
804
|
+
)
|
|
805
|
+
return {
|
|
806
|
+
name: types.RubricGroup(rubrics=group) for name, group in groups.items()
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
def _convert_eval_case(self, case: dict[str, Any]) -> types.EvalCase:
|
|
810
|
+
"""Converts one ADK EvalCase into an EvalCase."""
|
|
811
|
+
if not isinstance(case, dict):
|
|
812
|
+
raise TypeError(f"Expected an ADK EvalCase object, got {type(case)}.")
|
|
813
|
+
conversation = _get_adk_field(case, "conversation")
|
|
814
|
+
scenario = _get_adk_field(case, "conversation_scenario")
|
|
815
|
+
if (conversation is None) == (scenario is None):
|
|
816
|
+
raise ValueError(
|
|
817
|
+
"Exactly one of conversation and conversation_scenario must be set."
|
|
818
|
+
)
|
|
819
|
+
|
|
820
|
+
fields: dict[str, Any] = {"eval_case_id": _get_adk_field(case, "eval_id")}
|
|
821
|
+
rubrics = list(_get_adk_field(case, "rubrics") or [])
|
|
822
|
+
if scenario is not None:
|
|
823
|
+
fields["user_scenario"] = types.evals.UserScenario(
|
|
824
|
+
starting_prompt=_get_adk_field(scenario, "starting_prompt"),
|
|
825
|
+
conversation_plan=_get_adk_field(scenario, "conversation_plan"),
|
|
826
|
+
)
|
|
827
|
+
else:
|
|
828
|
+
if not conversation:
|
|
829
|
+
raise ValueError("conversation must have at least one invocation.")
|
|
830
|
+
*earlier_invocations, last_invocation = conversation
|
|
831
|
+
fields["prompt"] = _adk_user_content(last_invocation)
|
|
832
|
+
history = []
|
|
833
|
+
for turn_index, invocation in enumerate(earlier_invocations):
|
|
834
|
+
history.extend(self._invocation_to_messages(invocation, turn_index))
|
|
835
|
+
if history:
|
|
836
|
+
fields["conversation_history"] = history
|
|
837
|
+
final_response = _get_adk_field(last_invocation, "final_response")
|
|
838
|
+
if final_response:
|
|
839
|
+
fields["reference"] = types.ResponseCandidate(
|
|
840
|
+
response=_adk_content(final_response, "model")
|
|
841
|
+
)
|
|
842
|
+
reference_trajectory: list[genai_types.Content] = []
|
|
843
|
+
for _, content in _adk_intermediate_events(
|
|
844
|
+
_get_adk_field(last_invocation, "intermediate_data")
|
|
845
|
+
):
|
|
846
|
+
reference_trajectory.extend(
|
|
847
|
+
genai_types.Content(
|
|
848
|
+
role="model",
|
|
849
|
+
parts=[genai_types.Part(function_call=part.function_call)],
|
|
850
|
+
)
|
|
851
|
+
for part in content.parts or []
|
|
852
|
+
if part.function_call
|
|
853
|
+
)
|
|
854
|
+
if reference_trajectory:
|
|
855
|
+
fields[_REFERENCE_TRAJECTORY] = reference_trajectory
|
|
856
|
+
rubrics.extend(_get_adk_field(last_invocation, "rubrics") or [])
|
|
857
|
+
|
|
858
|
+
if rubrics:
|
|
859
|
+
fields["rubric_groups"] = self._convert_rubrics(rubrics)
|
|
860
|
+
session_input = _get_adk_field(case, "session_input")
|
|
861
|
+
if session_input:
|
|
862
|
+
fields[_evals_constant.SESSION_INPUT] = {
|
|
863
|
+
name: value
|
|
864
|
+
for name in _ADK_SESSION_INPUT_FIELDS
|
|
865
|
+
if (value := _get_adk_field(session_input, name)) is not None
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
reserved_keys = set(fields)
|
|
869
|
+
for field_name in types.EvalCase.model_fields:
|
|
870
|
+
reserved_keys.update((field_name, alias_generators.to_camel(field_name)))
|
|
871
|
+
for key, value in case.items():
|
|
872
|
+
if key in _ADK_EVAL_CASE_KEYS:
|
|
873
|
+
continue
|
|
874
|
+
if key in reserved_keys:
|
|
875
|
+
logger.warning(
|
|
876
|
+
"Skipping ADK eval case field '%s' because it conflicts with"
|
|
877
|
+
" an EvalCase field.",
|
|
878
|
+
key,
|
|
879
|
+
)
|
|
880
|
+
continue
|
|
881
|
+
fields[key] = value
|
|
882
|
+
return types.EvalCase(**fields)
|
|
883
|
+
|
|
884
|
+
@override
|
|
885
|
+
def convert(self, raw_data: dict[str, Any]) -> types.EvaluationDataset:
|
|
886
|
+
"""Converts a parsed ADK EvalSet into an EvaluationDataset."""
|
|
887
|
+
if not isinstance(raw_data, dict):
|
|
888
|
+
raise ValueError(
|
|
889
|
+
"Expected an ADK EvalSet JSON object, got"
|
|
890
|
+
f" {type(raw_data)}. For the legacy list format, load the"
|
|
891
|
+
" file with google.adk.evaluation.local_eval_sets_manager"
|
|
892
|
+
".load_eval_set_from_file() and pass"
|
|
893
|
+
" eval_set.model_dump(mode='json') instead."
|
|
894
|
+
)
|
|
895
|
+
adk_eval_cases = _get_adk_field(raw_data, "eval_cases")
|
|
896
|
+
if not isinstance(adk_eval_cases, list):
|
|
897
|
+
raise ValueError("Expected an ADK EvalSet with an 'eval_cases' list.")
|
|
898
|
+
|
|
899
|
+
eval_cases = []
|
|
900
|
+
for i, case in enumerate(adk_eval_cases):
|
|
901
|
+
try:
|
|
902
|
+
eval_cases.append(self._convert_eval_case(case))
|
|
903
|
+
except (TypeError, ValueError) as e:
|
|
904
|
+
case_id = (
|
|
905
|
+
_get_adk_field(case, "eval_id") if isinstance(case, dict) else None
|
|
906
|
+
)
|
|
907
|
+
raise ValueError(
|
|
908
|
+
f"Failed to convert ADK eval case '{case_id or i}': {e}"
|
|
909
|
+
) from e
|
|
910
|
+
return types.EvaluationDataset(eval_cases=eval_cases)
|
|
911
|
+
|
|
912
|
+
|
|
608
913
|
def auto_detect_dataset_schema(
|
|
609
914
|
raw_dataset: list[dict[str, Any]],
|
|
610
915
|
) -> Union[EvalDatasetSchema, str]:
|
|
@@ -288,6 +288,7 @@ class MetricHandler(abc.ABC, Generic[T]):
|
|
|
288
288
|
def __init__(self, module: "evals.Evals", metric: T):
|
|
289
289
|
self.module = module
|
|
290
290
|
self.metric: T = metric
|
|
291
|
+
self.allow_cross_region_model: Optional[bool] = None
|
|
291
292
|
|
|
292
293
|
@property
|
|
293
294
|
@abc.abstractmethod
|
|
@@ -761,6 +762,7 @@ class LLMMetricHandler(MetricHandler[types.LLMMetric]):
|
|
|
761
762
|
lambda: self.module._evaluate_instances(
|
|
762
763
|
metrics=[self.metric],
|
|
763
764
|
instance=instance,
|
|
765
|
+
allow_cross_region_model=self.allow_cross_region_model,
|
|
764
766
|
),
|
|
765
767
|
self.metric_name,
|
|
766
768
|
)
|
|
@@ -981,7 +983,7 @@ class PredefinedMetricHandler(MetricHandler[types.Metric]):
|
|
|
981
983
|
raise ValueError(
|
|
982
984
|
f"Metric '{self.metric.name}' is not a supported predefined metric."
|
|
983
985
|
)
|
|
984
|
-
if (
|
|
986
|
+
if self.metric.name.startswith("multi_turn") and (
|
|
985
987
|
self.metric.judge_model
|
|
986
988
|
or self.metric.judge_model_generation_config
|
|
987
989
|
or self.metric.judge_model_sampling_count
|
|
@@ -989,7 +991,8 @@ class PredefinedMetricHandler(MetricHandler[types.Metric]):
|
|
|
989
991
|
logger.warning(
|
|
990
992
|
"Autorater config settings (judge_model, "
|
|
991
993
|
"judge_model_generation_config, judge_model_sampling_count) "
|
|
992
|
-
"are ignored for
|
|
994
|
+
"are ignored for multi-turn metric '%s'. Use "
|
|
995
|
+
"judge_model_step_configs to set its judges.",
|
|
993
996
|
self.metric.name,
|
|
994
997
|
)
|
|
995
998
|
|
|
@@ -1071,6 +1074,7 @@ class PredefinedMetricHandler(MetricHandler[types.Metric]):
|
|
|
1071
1074
|
metrics=[self.metric],
|
|
1072
1075
|
instance=payload.get("instance"),
|
|
1073
1076
|
autorater_config=payload.get("autorater_config"),
|
|
1077
|
+
allow_cross_region_model=self.allow_cross_region_model,
|
|
1074
1078
|
),
|
|
1075
1079
|
metric_name,
|
|
1076
1080
|
)
|
|
@@ -1318,6 +1322,7 @@ class RegisteredMetricHandler(MetricHandler[types.Metric]):
|
|
|
1318
1322
|
metric_sources=[metric_source],
|
|
1319
1323
|
instance=payload.get("instance"),
|
|
1320
1324
|
autorater_config=payload.get("autorater_config"),
|
|
1325
|
+
allow_cross_region_model=self.allow_cross_region_model,
|
|
1321
1326
|
),
|
|
1322
1327
|
metric_name,
|
|
1323
1328
|
)
|
|
@@ -1404,12 +1409,16 @@ MetricHandlerType = TypeVar(
|
|
|
1404
1409
|
|
|
1405
1410
|
|
|
1406
1411
|
def get_handler_for_metric(
|
|
1407
|
-
module: "evals.Evals",
|
|
1412
|
+
module: "evals.Evals",
|
|
1413
|
+
metric: types.Metric,
|
|
1414
|
+
allow_cross_region_model: Optional[bool] = None,
|
|
1408
1415
|
) -> Union[MetricHandlerType, Any]:
|
|
1409
1416
|
"""Returns a metric handler for the given metric."""
|
|
1410
1417
|
for condition, handler_class in _METRIC_HANDLER_MAPPING:
|
|
1411
1418
|
if condition(metric): # type: ignore[no-untyped-call]
|
|
1412
|
-
|
|
1419
|
+
handler = handler_class(module=module, metric=metric)
|
|
1420
|
+
handler.allow_cross_region_model = allow_cross_region_model
|
|
1421
|
+
return handler
|
|
1413
1422
|
raise ValueError(f"Unsupported metric: {metric.name}")
|
|
1414
1423
|
|
|
1415
1424
|
|
|
@@ -1548,6 +1557,7 @@ def _rate_limited_get_metric_result(
|
|
|
1548
1557
|
def compute_metrics_and_aggregate(
|
|
1549
1558
|
evaluation_run_config: EvaluationRunConfig,
|
|
1550
1559
|
evaluation_service_qps: Optional[float] = None,
|
|
1560
|
+
allow_cross_region_model: Optional[bool] = None,
|
|
1551
1561
|
) -> types.EvaluationResult:
|
|
1552
1562
|
"""Computes metrics and aggregates them for a given evaluation run config.
|
|
1553
1563
|
|
|
@@ -1556,6 +1566,8 @@ def compute_metrics_and_aggregate(
|
|
|
1556
1566
|
evaluation_service_qps: Optional QPS limit for the evaluation service.
|
|
1557
1567
|
Defaults to _DEFAULT_EVAL_SERVICE_QPS (10). Users with higher
|
|
1558
1568
|
quotas can increase this value.
|
|
1569
|
+
allow_cross_region_model: Opt-in flag to authorize cross-region
|
|
1570
|
+
routing for judge models.
|
|
1559
1571
|
"""
|
|
1560
1572
|
metric_handlers = []
|
|
1561
1573
|
all_futures = []
|
|
@@ -1574,7 +1586,11 @@ def compute_metrics_and_aggregate(
|
|
|
1574
1586
|
|
|
1575
1587
|
for eval_metric in evaluation_run_config.metrics:
|
|
1576
1588
|
metric_handlers.append(
|
|
1577
|
-
get_handler_for_metric(
|
|
1589
|
+
get_handler_for_metric(
|
|
1590
|
+
evaluation_run_config.evals_module,
|
|
1591
|
+
eval_metric,
|
|
1592
|
+
allow_cross_region_model=allow_cross_region_model,
|
|
1593
|
+
)
|
|
1578
1594
|
)
|
|
1579
1595
|
|
|
1580
1596
|
eval_case_count = len(evaluation_run_config.dataset.eval_cases)
|
|
@@ -215,8 +215,11 @@ class LazyLoadedPrebuiltMetric:
|
|
|
215
215
|
if self._resolved_metric:
|
|
216
216
|
return self._resolved_metric
|
|
217
217
|
|
|
218
|
+
# The shared cache is keyed by name and version only, so a metric with
|
|
219
|
+
# overrides (such as judge_model_step_configs) must bypass it.
|
|
220
|
+
use_cache = not self.metric_kwargs
|
|
218
221
|
cache_key = f"{self.name}@{self.version or 'default'}"
|
|
219
|
-
if cache_key in LazyLoadedPrebuiltMetric._cache:
|
|
222
|
+
if use_cache and cache_key in LazyLoadedPrebuiltMetric._cache:
|
|
220
223
|
self._resolved_metric = LazyLoadedPrebuiltMetric._cache[cache_key]
|
|
221
224
|
logger.debug("Metric '%s' found in cache.", cache_key)
|
|
222
225
|
return self._resolved_metric
|
|
@@ -225,7 +228,8 @@ class LazyLoadedPrebuiltMetric:
|
|
|
225
228
|
api_metric = self._resolve_api_predefined()
|
|
226
229
|
if api_metric:
|
|
227
230
|
self._resolved_metric = api_metric
|
|
228
|
-
|
|
231
|
+
if use_cache:
|
|
232
|
+
LazyLoadedPrebuiltMetric._cache[cache_key] = self._resolved_metric
|
|
229
233
|
return self._resolved_metric
|
|
230
234
|
|
|
231
235
|
# Fallback to GCS loading for custom LLM-based Prebuilt Metrics
|
|
@@ -234,8 +238,9 @@ class LazyLoadedPrebuiltMetric:
|
|
|
234
238
|
)
|
|
235
239
|
try:
|
|
236
240
|
gcs_metric = self._fetch_and_parse(api_client)
|
|
237
|
-
|
|
238
|
-
|
|
241
|
+
if use_cache:
|
|
242
|
+
final_cache_key = f"{self.name}@{self.version}"
|
|
243
|
+
LazyLoadedPrebuiltMetric._cache[final_cache_key] = gcs_metric
|
|
239
244
|
self._resolved_metric = gcs_metric
|
|
240
245
|
return self._resolved_metric
|
|
241
246
|
except Exception as e:
|
|
@@ -232,6 +232,9 @@ def _extract_dataset_rows(dataset: types.EvaluationDataset) -> list[dict[str, An
|
|
|
232
232
|
return processed_rows
|
|
233
233
|
|
|
234
234
|
|
|
235
|
+
extract_dataset_rows = _extract_dataset_rows
|
|
236
|
+
|
|
237
|
+
|
|
235
238
|
def get_evaluation_html(eval_result_json: str) -> str:
|
|
236
239
|
"""Returns a self-contained HTML for single evaluation visualization."""
|
|
237
240
|
payload_b64 = _encode_to_base64(eval_result_json)
|
|
@@ -64,10 +64,14 @@ def t_metrics(
|
|
|
64
64
|
elif (
|
|
65
65
|
metric_name and metric_name in _evals_constant.SUPPORTED_PREDEFINED_METRICS
|
|
66
66
|
):
|
|
67
|
-
|
|
67
|
+
predefined_spec: dict[str, Any] = {
|
|
68
68
|
"metric_spec_name": metric_name,
|
|
69
69
|
"metric_spec_parameters": metric.metric_spec_parameters,
|
|
70
70
|
}
|
|
71
|
+
step_configs = getv(metric, ["judge_model_step_configs"])
|
|
72
|
+
if step_configs:
|
|
73
|
+
predefined_spec["step_autorater_configs"] = step_configs
|
|
74
|
+
metric_payload_item["predefined_metric_spec"] = predefined_spec
|
|
71
75
|
# Custom Code Execution Metric
|
|
72
76
|
elif (
|
|
73
77
|
hasattr(metric, "remote_custom_function") and metric.remote_custom_function
|
{google_cloud_agentplatform-2.3.0 → google_cloud_agentplatform-2.4.0}/agentplatform/_genai/evals.py
RENAMED
|
@@ -392,6 +392,13 @@ def _EvaluateInstancesRequestParameters_to_vertex(
|
|
|
392
392
|
],
|
|
393
393
|
)
|
|
394
394
|
|
|
395
|
+
if getv(from_object, ["allow_cross_region_model"]) is not None:
|
|
396
|
+
setv(
|
|
397
|
+
to_object,
|
|
398
|
+
["allowCrossRegionModel"],
|
|
399
|
+
getv(from_object, ["allow_cross_region_model"]),
|
|
400
|
+
)
|
|
401
|
+
|
|
395
402
|
if getv(from_object, ["config"]) is not None:
|
|
396
403
|
setv(to_object, ["config"], getv(from_object, ["config"]))
|
|
397
404
|
|
|
@@ -1935,6 +1942,7 @@ class Evals(_api_module.BaseModule):
|
|
|
1935
1942
|
metrics: Optional[list[types.MetricOrDict]] = None,
|
|
1936
1943
|
instance: Optional[types.EvaluationInstanceOrDict] = None,
|
|
1937
1944
|
metric_sources: Optional[list[types.MetricSourceOrDict]] = None,
|
|
1945
|
+
allow_cross_region_model: Optional[bool] = None,
|
|
1938
1946
|
config: Optional[types.EvaluateInstancesConfigOrDict] = None,
|
|
1939
1947
|
) -> types.EvaluateInstancesResponse:
|
|
1940
1948
|
"""
|
|
@@ -1956,6 +1964,7 @@ class Evals(_api_module.BaseModule):
|
|
|
1956
1964
|
metrics=metrics,
|
|
1957
1965
|
instance=instance,
|
|
1958
1966
|
metric_sources=metric_sources,
|
|
1967
|
+
allow_cross_region_model=allow_cross_region_model,
|
|
1959
1968
|
config=config,
|
|
1960
1969
|
)
|
|
1961
1970
|
|
|
@@ -3171,6 +3180,8 @@ class Evals(_api_module.BaseModule):
|
|
|
3171
3180
|
- evaluation_service_qps: The rate limit (queries per second) for
|
|
3172
3181
|
calls to the evaluation service. Defaults to 10. Increase this
|
|
3173
3182
|
value if your project has a higher EvaluateInstances API quota.
|
|
3183
|
+
- allow_cross_region_model: Opt-in flag to authorize cross-region
|
|
3184
|
+
routing for judge models.
|
|
3174
3185
|
**kwargs: Extra arguments to pass to evaluation, such as `agent_info`.
|
|
3175
3186
|
|
|
3176
3187
|
Returns:
|
|
@@ -3214,6 +3225,7 @@ class Evals(_api_module.BaseModule):
|
|
|
3214
3225
|
dest=config.dest,
|
|
3215
3226
|
location=location,
|
|
3216
3227
|
evaluation_service_qps=getattr(config, "evaluation_service_qps", None),
|
|
3228
|
+
allow_cross_region_model=getattr(config, "allow_cross_region_model", None),
|
|
3217
3229
|
**kwargs,
|
|
3218
3230
|
)
|
|
3219
3231
|
|
|
@@ -4944,6 +4956,7 @@ class AsyncEvals(_api_module.BaseModule):
|
|
|
4944
4956
|
metrics: Optional[list[types.MetricOrDict]] = None,
|
|
4945
4957
|
instance: Optional[types.EvaluationInstanceOrDict] = None,
|
|
4946
4958
|
metric_sources: Optional[list[types.MetricSourceOrDict]] = None,
|
|
4959
|
+
allow_cross_region_model: Optional[bool] = None,
|
|
4947
4960
|
config: Optional[types.EvaluateInstancesConfigOrDict] = None,
|
|
4948
4961
|
) -> types.EvaluateInstancesResponse:
|
|
4949
4962
|
"""
|
|
@@ -4965,6 +4978,7 @@ class AsyncEvals(_api_module.BaseModule):
|
|
|
4965
4978
|
metrics=metrics,
|
|
4966
4979
|
instance=instance,
|
|
4967
4980
|
metric_sources=metric_sources,
|
|
4981
|
+
allow_cross_region_model=allow_cross_region_model,
|
|
4968
4982
|
config=config,
|
|
4969
4983
|
)
|
|
4970
4984
|
|