google-cloud-agentplatform 2.4.0__tar.gz → 2.6.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.4.0/google_cloud_agentplatform.egg-info → google_cloud_agentplatform-2.6.0}/PKG-INFO +2 -2
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_evals_common.py +120 -81
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_evals_constant.py +14 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_evals_data_converters.py +17 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_evals_metric_handlers.py +8 -15
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_evals_visualization.py +17 -3
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_runtimes_utils.py +18 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/evals.py +6 -6
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/memory_banks.py +268 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/model_garden.py +1027 -61
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/runtimes.py +26 -8
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/types/__init__.py +72 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/types/common.py +807 -5
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/types/evals.py +1 -1
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/frameworks/adk.py +218 -85
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/version.py +1 -1
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0/google_cloud_agentplatform.egg-info}/PKG-INFO +2 -2
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/google_cloud_agentplatform.egg-info/requires.txt +1 -1
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/pyproject.toml +1 -1
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/LICENSE +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/README.md +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/__init__.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/__init__.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_bigquery_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_datasets_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_evals_builtin_tools.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_evals_metric_loaders.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_evals_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_gcs_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_logging_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_memory_bank_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_observability_data_converter.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_operations_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_prompt_management_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_prompt_optimizer_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_skills_utils.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/_transformers.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/a2a_task_events.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/a2a_tasks.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/client.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/datasets.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/endpoints.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/example_stores.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/feedback_contexts.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/feedback_entries.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/live.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/live_runtimes.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/memories.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/memory_revisions.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/prompt_optimizer.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/prompts.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/rag.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/runtime_revisions.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/sandbox_snapshots.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/sandbox_templates.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/sandboxes.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/serving_profiles.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/session_events.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/sessions.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/skill_revisions.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/skills.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/types/agent_engines.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/types/prompt_optimizer.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/types/prompts.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/frameworks/__init__.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/frameworks/a2a.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/frameworks/ag2.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/frameworks/langchain.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/frameworks/langgraph.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/frameworks/llama_index.py +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/google_cloud_agentplatform.egg-info/SOURCES.txt +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/google_cloud_agentplatform.egg-info/dependency_links.txt +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/google_cloud_agentplatform.egg-info/top_level.txt +0 -0
- {google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: google-cloud-agentplatform
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
4
4
|
Summary: Google Cloud Agent Platform Client Library
|
|
5
5
|
Author-email: Google LLC <googleapis-packages@google.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -31,7 +31,7 @@ Requires-Dist: google-cloud-storage<4.0.0,>=1.32.0; extra == "agent-engines"
|
|
|
31
31
|
Requires-Dist: opentelemetry-sdk<2; extra == "agent-engines"
|
|
32
32
|
Requires-Dist: opentelemetry-exporter-gcp-logging<2.0.0,>=1.11.0a0; extra == "agent-engines"
|
|
33
33
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http<2; extra == "agent-engines"
|
|
34
|
-
Requires-Dist: opentelemetry-instrumentation-google-genai<
|
|
34
|
+
Requires-Dist: opentelemetry-instrumentation-google-genai<2.0.0,>=0.3b0; extra == "agent-engines"
|
|
35
35
|
Requires-Dist: pydantic<3,>=2.11.1; extra == "agent-engines"
|
|
36
36
|
Provides-Extra: a2a
|
|
37
37
|
Requires-Dist: google-cloud-agentplatform[agent_engines]; extra == "a2a"
|
|
@@ -22,6 +22,7 @@ import datetime
|
|
|
22
22
|
import json
|
|
23
23
|
import logging
|
|
24
24
|
import os
|
|
25
|
+
import random
|
|
25
26
|
import threading
|
|
26
27
|
import time
|
|
27
28
|
from typing import Any, Callable, Literal, Optional, Union, cast
|
|
@@ -122,6 +123,11 @@ def _temp_logger_level(logger_name: str, level: int) -> None: # type: ignore[mi
|
|
|
122
123
|
logger_instance.setLevel(original_level)
|
|
123
124
|
|
|
124
125
|
|
|
126
|
+
def _is_missing(value: Any) -> bool:
|
|
127
|
+
"""Returns True for None or a scalar NaN, such as a missing DataFrame cell."""
|
|
128
|
+
return bool(pd.api.types.is_scalar(value) and pd.isna(value))
|
|
129
|
+
|
|
130
|
+
|
|
125
131
|
def _get_api_client_with_location(
|
|
126
132
|
api_client: BaseApiClient, location: Optional[str]
|
|
127
133
|
) -> BaseApiClient:
|
|
@@ -153,6 +159,8 @@ def _get_runtime_instance(
|
|
|
153
159
|
client = agentplatform.Client(
|
|
154
160
|
project=api_client.project,
|
|
155
161
|
location=api_client.location,
|
|
162
|
+
credentials=api_client._credentials,
|
|
163
|
+
http_options=api_client._http_options,
|
|
156
164
|
)
|
|
157
165
|
_thread_local_data.runtime_instances[agent_name] = client.runtimes.get(
|
|
158
166
|
name=agent_name
|
|
@@ -160,6 +168,45 @@ def _get_runtime_instance(
|
|
|
160
168
|
return _thread_local_data.runtime_instances[agent_name]
|
|
161
169
|
|
|
162
170
|
|
|
171
|
+
def _is_retryable_error(e: Exception) -> bool:
|
|
172
|
+
"""Returns True for transient errors that are safe to retry with backoff."""
|
|
173
|
+
if isinstance(e, genai_errors.APIError):
|
|
174
|
+
return e.code in _evals_constant.RETRYABLE_STATUS_CODES
|
|
175
|
+
return isinstance(
|
|
176
|
+
e, (api_exceptions.ResourceExhausted, api_exceptions.ServiceUnavailable)
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _get_retry_backoff(
|
|
181
|
+
e: Exception, attempt: int, max_retries: int, operation: str
|
|
182
|
+
) -> Optional[float]:
|
|
183
|
+
"""Returns the seconds to wait before the next attempt, or None to stop.
|
|
184
|
+
|
|
185
|
+
Retryable errors back off exponentially with jitter. Other errors fail
|
|
186
|
+
fast, and the last attempt never waits.
|
|
187
|
+
"""
|
|
188
|
+
if not _is_retryable_error(e) or attempt == max_retries - 1:
|
|
189
|
+
logger.error(
|
|
190
|
+
"Error during %s on attempt %d/%d: %s",
|
|
191
|
+
operation,
|
|
192
|
+
attempt + 1,
|
|
193
|
+
max_retries,
|
|
194
|
+
e,
|
|
195
|
+
)
|
|
196
|
+
return None
|
|
197
|
+
backoff = 2**attempt + random.uniform(0, 1)
|
|
198
|
+
logger.warning(
|
|
199
|
+
"Retryable error during %s on attempt %d/%d: %s. Retrying in %.1f"
|
|
200
|
+
" seconds...",
|
|
201
|
+
operation,
|
|
202
|
+
attempt + 1,
|
|
203
|
+
max_retries,
|
|
204
|
+
e,
|
|
205
|
+
backoff,
|
|
206
|
+
)
|
|
207
|
+
return backoff
|
|
208
|
+
|
|
209
|
+
|
|
163
210
|
def _generate_content_with_retry(
|
|
164
211
|
api_client: BaseApiClient,
|
|
165
212
|
model: str,
|
|
@@ -222,29 +269,11 @@ def _generate_content_with_retry(
|
|
|
222
269
|
}
|
|
223
270
|
else:
|
|
224
271
|
return response
|
|
225
|
-
except api_exceptions.ResourceExhausted as e:
|
|
226
|
-
logger.warning(
|
|
227
|
-
"Resource Exhausted error on attempt %d/%d: %s. Retrying in %s"
|
|
228
|
-
" seconds...",
|
|
229
|
-
attempt + 1,
|
|
230
|
-
max_retries,
|
|
231
|
-
e,
|
|
232
|
-
2**attempt,
|
|
233
|
-
)
|
|
234
|
-
if attempt == max_retries - 1:
|
|
235
|
-
return {"error": f"Resource exhausted after retries: {e}"}
|
|
236
|
-
time.sleep(2**attempt)
|
|
237
272
|
except Exception as e: # pylint: disable=broad-exception-caught
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
attempt + 1
|
|
241
|
-
|
|
242
|
-
e,
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
if attempt == max_retries - 1:
|
|
246
|
-
return {"error": f"Failed after retries: {e}"}
|
|
247
|
-
time.sleep(1)
|
|
273
|
+
backoff = _get_retry_backoff(e, attempt, max_retries, "generate_content")
|
|
274
|
+
if backoff is None:
|
|
275
|
+
return {"error": f"Failed on attempt {attempt + 1}/{max_retries}: {e}"}
|
|
276
|
+
time.sleep(backoff)
|
|
248
277
|
return {"error": f"Failed to generate content after {max_retries} retries"}
|
|
249
278
|
|
|
250
279
|
|
|
@@ -267,9 +296,8 @@ def _build_generate_content_config(
|
|
|
267
296
|
for key in [
|
|
268
297
|
"system_instruction",
|
|
269
298
|
"tools",
|
|
270
|
-
"
|
|
299
|
+
"tool_config",
|
|
271
300
|
"safety_settings",
|
|
272
|
-
"labels",
|
|
273
301
|
]:
|
|
274
302
|
if key in request_dict:
|
|
275
303
|
merged_config_dict[key] = request_dict[key]
|
|
@@ -1561,7 +1589,7 @@ def _build_interaction_id_dataset(
|
|
|
1561
1589
|
eval_cases = []
|
|
1562
1590
|
for i, row in enumerate(loaded_data):
|
|
1563
1591
|
interaction = row.get(_evals_constant.INTERACTION_ID)
|
|
1564
|
-
if not interaction:
|
|
1592
|
+
if _is_missing(interaction) or not interaction:
|
|
1565
1593
|
raise ValueError(f"Missing `interaction_id` value for row {i}.")
|
|
1566
1594
|
eval_cases.append(
|
|
1567
1595
|
types.EvalCase(
|
|
@@ -1871,12 +1899,12 @@ def _execute_inference_concurrently(
|
|
|
1871
1899
|
max_workers = AGENT_MAX_WORKERS if runtime or agent else MAX_WORKERS
|
|
1872
1900
|
with tqdm(total=len(prompt_dataset), desc=progress_desc) as pbar:
|
|
1873
1901
|
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
1874
|
-
for index, row in prompt_dataset.iterrows():
|
|
1902
|
+
for index, (_, row) in enumerate(prompt_dataset.iterrows()):
|
|
1875
1903
|
try:
|
|
1876
1904
|
if (
|
|
1877
1905
|
has_agent_data
|
|
1878
1906
|
and AGENT_DATA in row.index
|
|
1879
|
-
and row.get(AGENT_DATA)
|
|
1907
|
+
and not _is_missing(row.get(AGENT_DATA))
|
|
1880
1908
|
):
|
|
1881
1909
|
agent_data_obj = row[AGENT_DATA]
|
|
1882
1910
|
if isinstance(agent_data_obj, dict):
|
|
@@ -2101,7 +2129,7 @@ def _run_litellm_inference(
|
|
|
2101
2129
|
|
|
2102
2130
|
with tqdm(total=len(prompt_dataset), desc=f"LiteLLM Inference ({model})") as pbar:
|
|
2103
2131
|
with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
|
|
2104
|
-
for index, row in prompt_dataset.iterrows():
|
|
2132
|
+
for index, (_, row) in enumerate(prompt_dataset.iterrows()):
|
|
2105
2133
|
messages = _convert_prompt_row_to_litellm_messages(row)
|
|
2106
2134
|
future = executor.submit(
|
|
2107
2135
|
_call_litellm_completion, model=model, messages=messages
|
|
@@ -3481,7 +3509,9 @@ def _create_runtime_session(
|
|
|
3481
3509
|
raise RuntimeError(
|
|
3482
3510
|
"Failed to create session: runtime.api_client is None."
|
|
3483
3511
|
) from exc
|
|
3484
|
-
|
|
3512
|
+
from . import sessions
|
|
3513
|
+
|
|
3514
|
+
operation = sessions.Sessions(runtime.api_client._api_client).create(
|
|
3485
3515
|
name=runtime.api_resource.name,
|
|
3486
3516
|
user_id=user_id,
|
|
3487
3517
|
config=types.CreateRuntimeSessionConfig(
|
|
@@ -3545,10 +3575,12 @@ def _execute_agent_run_with_retry(
|
|
|
3545
3575
|
return {"error": "runtime.api_resource is None."}
|
|
3546
3576
|
if runtime.api_client is None:
|
|
3547
3577
|
return {"error": "runtime.api_client is None."}
|
|
3578
|
+
from . import sessions
|
|
3579
|
+
|
|
3548
3580
|
session_name = f"{runtime.api_resource.name}/sessions/{session_id}"
|
|
3549
3581
|
base_ts = datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc)
|
|
3550
3582
|
for i, ag_event in enumerate(history_events):
|
|
3551
|
-
runtime.api_client.
|
|
3583
|
+
sessions.Sessions(runtime.api_client._api_client).events.append(
|
|
3552
3584
|
name=session_name,
|
|
3553
3585
|
author=ag_event.author or "user",
|
|
3554
3586
|
invocation_id="history",
|
|
@@ -3570,28 +3602,11 @@ def _execute_agent_run_with_retry(
|
|
|
3570
3602
|
if event and CONTENT in event and PARTS in event[CONTENT]:
|
|
3571
3603
|
responses.append(event)
|
|
3572
3604
|
return responses
|
|
3573
|
-
except api_exceptions.ResourceExhausted as e:
|
|
3574
|
-
logger.warning(
|
|
3575
|
-
"Resource Exhausted error on attempt %d/%d: %s. Retrying in %s"
|
|
3576
|
-
" seconds...",
|
|
3577
|
-
attempt + 1,
|
|
3578
|
-
max_retries,
|
|
3579
|
-
e,
|
|
3580
|
-
2**attempt,
|
|
3581
|
-
)
|
|
3582
|
-
if attempt == max_retries - 1:
|
|
3583
|
-
return {"error": f"Resource exhausted after retries: {e}"}
|
|
3584
|
-
time.sleep(2**attempt)
|
|
3585
3605
|
except Exception as e: # pylint: disable=broad-exception-caught
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
attempt + 1
|
|
3589
|
-
|
|
3590
|
-
e,
|
|
3591
|
-
)
|
|
3592
|
-
if attempt == max_retries - 1:
|
|
3593
|
-
return {"error": f"Failed after retries: {e}"}
|
|
3594
|
-
time.sleep(1)
|
|
3606
|
+
backoff = _get_retry_backoff(e, attempt, max_retries, "agent engine run")
|
|
3607
|
+
if backoff is None:
|
|
3608
|
+
return {"error": f"Failed on attempt {attempt + 1}/{max_retries}: {e}"}
|
|
3609
|
+
time.sleep(backoff)
|
|
3595
3610
|
return {"error": f"Failed to get agent run results after {max_retries} retries"}
|
|
3596
3611
|
|
|
3597
3612
|
|
|
@@ -3623,7 +3638,7 @@ async def _execute_local_agent_run_with_retry_async(
|
|
|
3623
3638
|
# Lazy-import ADK dependencies to avoid top-level import failures when
|
|
3624
3639
|
# google-adk is not installed.
|
|
3625
3640
|
from google.adk.runners import Runner
|
|
3626
|
-
from google.adk.sessions import InMemorySessionService
|
|
3641
|
+
from google.adk.sessions.in_memory_session_service import InMemorySessionService
|
|
3627
3642
|
|
|
3628
3643
|
# Multi-turn agent scraping with user simulation.
|
|
3629
3644
|
if user_simulator_config or "conversation_plan" in row:
|
|
@@ -3697,28 +3712,13 @@ async def _execute_local_agent_run_with_retry_async(
|
|
|
3697
3712
|
if event and CONTENT in event and PARTS in event[CONTENT]:
|
|
3698
3713
|
events.append(event)
|
|
3699
3714
|
return events
|
|
3700
|
-
except api_exceptions.ResourceExhausted as e:
|
|
3701
|
-
logger.warning(
|
|
3702
|
-
"Resource Exhausted error on attempt %d/%d: %s. Retrying"
|
|
3703
|
-
" in %s seconds...",
|
|
3704
|
-
attempt + 1,
|
|
3705
|
-
max_retries,
|
|
3706
|
-
e,
|
|
3707
|
-
2**attempt,
|
|
3708
|
-
)
|
|
3709
|
-
if attempt == max_retries - 1:
|
|
3710
|
-
return {"error": f"Resource exhausted after retries: {e}"}
|
|
3711
|
-
await asyncio.sleep(2**attempt)
|
|
3712
3715
|
except Exception as e: # pylint: disable=broad-exception-caught
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
)
|
|
3719
|
-
if attempt == max_retries - 1:
|
|
3720
|
-
return {"error": f"Failed after retries: {e}"}
|
|
3721
|
-
await asyncio.sleep(1)
|
|
3716
|
+
backoff = _get_retry_backoff(e, attempt, max_retries, "agent run")
|
|
3717
|
+
if backoff is None:
|
|
3718
|
+
return {
|
|
3719
|
+
"error": f"Failed on attempt {attempt + 1}/{max_retries}: {e}"
|
|
3720
|
+
}
|
|
3721
|
+
await asyncio.sleep(backoff)
|
|
3722
3722
|
return {"error": f"Failed to get agent run results after {max_retries} retries"}
|
|
3723
3723
|
|
|
3724
3724
|
|
|
@@ -3734,7 +3734,10 @@ def _convert_gcs_to_evaluation_item_result(
|
|
|
3734
3734
|
return types.EvaluationItemResult(**eval_item_data)
|
|
3735
3735
|
except Exception as e:
|
|
3736
3736
|
logger.error(
|
|
3737
|
-
"Failed to load evaluation result from GCS: %s. Error: %s",
|
|
3737
|
+
"Failed to load evaluation result from GCS: %s. Error: %s",
|
|
3738
|
+
gcs_uri,
|
|
3739
|
+
e,
|
|
3740
|
+
exc_info=True,
|
|
3738
3741
|
)
|
|
3739
3742
|
return types.EvaluationItemResult()
|
|
3740
3743
|
|
|
@@ -3751,7 +3754,10 @@ def _convert_gcs_to_evaluation_item_request(
|
|
|
3751
3754
|
return types.EvaluationItemRequest(**eval_item_data)
|
|
3752
3755
|
except Exception as e:
|
|
3753
3756
|
logger.error(
|
|
3754
|
-
"Failed to load evaluation request from GCS: %s. Error: %s",
|
|
3757
|
+
"Failed to load evaluation request from GCS: %s. Error: %s",
|
|
3758
|
+
gcs_uri,
|
|
3759
|
+
e,
|
|
3760
|
+
exc_info=True,
|
|
3755
3761
|
)
|
|
3756
3762
|
return types.EvaluationItemRequest()
|
|
3757
3763
|
|
|
@@ -3874,7 +3880,7 @@ def _drop_empty_columns(df: "pd.DataFrame") -> "pd.DataFrame":
|
|
|
3874
3880
|
def is_empty(x: Any) -> bool:
|
|
3875
3881
|
if isinstance(x, (list, dict)):
|
|
3876
3882
|
return not x
|
|
3877
|
-
return
|
|
3883
|
+
return _is_missing(x)
|
|
3878
3884
|
|
|
3879
3885
|
cols_to_drop = [col for col in df.columns if df[col].apply(is_empty).all()]
|
|
3880
3886
|
return df.drop(columns=cols_to_drop)
|
|
@@ -3925,16 +3931,16 @@ def _get_eval_cases_eval_dfs_from_eval_items(
|
|
|
3925
3931
|
item.
|
|
3926
3932
|
- eval_dfs: A list of EvaluationDatasets, one for each candidate.
|
|
3927
3933
|
"""
|
|
3928
|
-
dataset_rows = []
|
|
3934
|
+
dataset_rows: list[dict[str, Any]] = []
|
|
3929
3935
|
eval_case_results = []
|
|
3930
|
-
for
|
|
3936
|
+
for eval_item in eval_items:
|
|
3931
3937
|
if (
|
|
3932
3938
|
eval_item
|
|
3933
3939
|
and eval_item.evaluation_response
|
|
3934
3940
|
and eval_item.evaluation_response.request
|
|
3935
3941
|
):
|
|
3936
3942
|
eval_case_results.append(
|
|
3937
|
-
_get_eval_case_result_from_eval_item(
|
|
3943
|
+
_get_eval_case_result_from_eval_item(len(dataset_rows), eval_item)
|
|
3938
3944
|
)
|
|
3939
3945
|
dataset_rows.append(
|
|
3940
3946
|
_convert_request_to_dataset_row(eval_item.evaluation_response.request)
|
|
@@ -4119,6 +4125,36 @@ def _get_content(row: dict[str, Any], column: str) -> Optional[genai_types.Conte
|
|
|
4119
4125
|
)
|
|
4120
4126
|
|
|
4121
4127
|
|
|
4128
|
+
# Columns mapped to EvaluationItemRequest fields; all others go to extra_context.
|
|
4129
|
+
_EVALUATION_SET_STANDARD_COLUMNS = _evals_constant.COMMON_DATASET_COLUMNS | {
|
|
4130
|
+
_evals_constant.RESPONSE,
|
|
4131
|
+
"interaction",
|
|
4132
|
+
"gemini_agent",
|
|
4133
|
+
}
|
|
4134
|
+
|
|
4135
|
+
|
|
4136
|
+
def _to_extra_context_content(value: Any) -> Optional[genai_types.Content]:
|
|
4137
|
+
if isinstance(value, str):
|
|
4138
|
+
return genai_types.Content(parts=[genai_types.Part(text=value)])
|
|
4139
|
+
if isinstance(value, genai_types.Content):
|
|
4140
|
+
return value
|
|
4141
|
+
parts = []
|
|
4142
|
+
for content in _evals_metric_handlers._value_to_content_list(value):
|
|
4143
|
+
parts.extend(content.parts or [])
|
|
4144
|
+
return genai_types.Content(parts=parts) if parts else None
|
|
4145
|
+
|
|
4146
|
+
|
|
4147
|
+
def _get_extra_context(row: "pd.Series") -> Optional[dict[str, genai_types.Content]]:
|
|
4148
|
+
extra_context = {}
|
|
4149
|
+
for column, value in row.items():
|
|
4150
|
+
if column in _EVALUATION_SET_STANDARD_COLUMNS or _is_missing(value):
|
|
4151
|
+
continue
|
|
4152
|
+
content = _to_extra_context_content(value)
|
|
4153
|
+
if content:
|
|
4154
|
+
extra_context[str(column)] = content
|
|
4155
|
+
return extra_context or None
|
|
4156
|
+
|
|
4157
|
+
|
|
4122
4158
|
def _create_evaluation_set_from_dataframe(
|
|
4123
4159
|
api_client: BaseApiClient,
|
|
4124
4160
|
gcs_dest_prefix: str,
|
|
@@ -4173,6 +4209,8 @@ def _create_evaluation_set_from_dataframe(
|
|
|
4173
4209
|
if _evals_constant.RESPONSE in row or agent_data_obj or intermediate_events:
|
|
4174
4210
|
# Resolve the oneof conflict: prioritize agent_data over flat text
|
|
4175
4211
|
response_text = row.get(_evals_constant.RESPONSE) or None
|
|
4212
|
+
if _is_missing(response_text):
|
|
4213
|
+
response_text = None
|
|
4176
4214
|
|
|
4177
4215
|
if agent_data_obj and response_text:
|
|
4178
4216
|
logger.info(
|
|
@@ -4227,7 +4265,7 @@ def _create_evaluation_set_from_dataframe(
|
|
|
4227
4265
|
prompt = types.EvaluationPrompt(
|
|
4228
4266
|
prompt_template_data=types.PromptTemplateData(values=values)
|
|
4229
4267
|
)
|
|
4230
|
-
elif _evals_constant.PROMPT
|
|
4268
|
+
elif not _is_missing(row.get(_evals_constant.PROMPT)):
|
|
4231
4269
|
prompt = types.EvaluationPrompt(text=row[_evals_constant.PROMPT])
|
|
4232
4270
|
|
|
4233
4271
|
eval_item_requests.append(
|
|
@@ -4235,12 +4273,13 @@ def _create_evaluation_set_from_dataframe(
|
|
|
4235
4273
|
prompt=prompt or None,
|
|
4236
4274
|
golden_response=(
|
|
4237
4275
|
types.CandidateResponse(text=row[_evals_constant.REFERENCE])
|
|
4238
|
-
if _evals_constant.REFERENCE
|
|
4276
|
+
if not _is_missing(row.get(_evals_constant.REFERENCE))
|
|
4239
4277
|
else None
|
|
4240
4278
|
),
|
|
4241
4279
|
candidate_responses=(
|
|
4242
4280
|
candidate_responses if candidate_responses else None
|
|
4243
4281
|
),
|
|
4282
|
+
extra_context=_get_extra_context(row),
|
|
4244
4283
|
)
|
|
4245
4284
|
)
|
|
4246
4285
|
logger.info("Writing evaluation item requests to GCS.")
|
|
@@ -120,3 +120,17 @@ COMMON_DATASET_COLUMNS = frozenset(
|
|
|
120
120
|
INTERACTION_ID,
|
|
121
121
|
}
|
|
122
122
|
)
|
|
123
|
+
|
|
124
|
+
# HTTP status codes that are safe to retry with backoff.
|
|
125
|
+
RETRYABLE_STATUS_CODES = frozenset(
|
|
126
|
+
{
|
|
127
|
+
408, # RequestTimeout (DEADLINE_EXCEEDED)
|
|
128
|
+
409, # Conflict / Aborted (ABORTED)
|
|
129
|
+
429, # TooManyRequests / ResourceExhausted (RESOURCE_EXHAUSTED)
|
|
130
|
+
499, # Client Closed Request (CANCELLED)
|
|
131
|
+
500, # InternalServerError (INTERNAL)
|
|
132
|
+
502, # BadGateway
|
|
133
|
+
503, # ServiceUnavailable (UNAVAILABLE)
|
|
134
|
+
504, # GatewayTimeout (DEADLINE_EXCEEDED)
|
|
135
|
+
}
|
|
136
|
+
)
|
|
@@ -230,6 +230,18 @@ class _FlattenEvalDataConverter(_evals_utils.EvalDataConverter):
|
|
|
230
230
|
"Invalid prompt type for case %s: %s" % (i, type(prompt_data))
|
|
231
231
|
)
|
|
232
232
|
|
|
233
|
+
if (
|
|
234
|
+
isinstance(conversation_history_data, str)
|
|
235
|
+
and conversation_history_data.strip()
|
|
236
|
+
):
|
|
237
|
+
try:
|
|
238
|
+
conversation_history_data = json.loads(conversation_history_data)
|
|
239
|
+
except json.JSONDecodeError:
|
|
240
|
+
logger.warning(
|
|
241
|
+
"Could not decode conversation_history JSON string for case %s.",
|
|
242
|
+
eval_case_id,
|
|
243
|
+
)
|
|
244
|
+
|
|
233
245
|
conversation_history: Optional[list[types.evals.Message]] = None
|
|
234
246
|
if isinstance(conversation_history_data, list):
|
|
235
247
|
conversation_history = []
|
|
@@ -242,6 +254,11 @@ class _FlattenEvalDataConverter(_evals_utils.EvalDataConverter):
|
|
|
242
254
|
)
|
|
243
255
|
)
|
|
244
256
|
elif isinstance(content, dict):
|
|
257
|
+
if isinstance(content.get("content"), str):
|
|
258
|
+
content = {
|
|
259
|
+
"role": content.get("role"),
|
|
260
|
+
"parts": [{"text": content["content"]}],
|
|
261
|
+
}
|
|
245
262
|
try:
|
|
246
263
|
validated_content = genai_types.Content.model_validate(
|
|
247
264
|
content
|
|
@@ -39,19 +39,6 @@ from . import types
|
|
|
39
39
|
|
|
40
40
|
logger = logging.getLogger(__name__)
|
|
41
41
|
_MAX_RETRIES = 5
|
|
42
|
-
# HTTP status codes that are safe to retry with backoff.
|
|
43
|
-
_RETRYABLE_STATUS_CODES = frozenset(
|
|
44
|
-
{
|
|
45
|
-
408, # RequestTimeout (DEADLINE_EXCEEDED)
|
|
46
|
-
409, # Conflict / Aborted (ABORTED)
|
|
47
|
-
429, # TooManyRequests / ResourceExhausted (RESOURCE_EXHAUSTED)
|
|
48
|
-
499, # Client Closed Request (CANCELLED)
|
|
49
|
-
500, # InternalServerError (INTERNAL)
|
|
50
|
-
502, # BadGateway
|
|
51
|
-
503, # ServiceUnavailable (UNAVAILABLE)
|
|
52
|
-
504, # GatewayTimeout (DEADLINE_EXCEEDED)
|
|
53
|
-
}
|
|
54
|
-
)
|
|
55
42
|
|
|
56
43
|
R = TypeVar("R")
|
|
57
44
|
T = TypeVar("T", types.Metric, types.MetricSource, types.LLMMetric)
|
|
@@ -64,7 +51,7 @@ def _call_with_retry(
|
|
|
64
51
|
"""Calls ``fn()`` with exponential backoff + jitter on retryable errors.
|
|
65
52
|
|
|
66
53
|
Retries up to ``_MAX_RETRIES`` times on errors whose HTTP status code is
|
|
67
|
-
in ``
|
|
54
|
+
in ``_evals_constant.RETRYABLE_STATUS_CODES`` (Aborted, DeadlineExceeded,
|
|
68
55
|
ResourceExhausted, ServiceUnavailable, Cancelled). Non-retryable errors
|
|
69
56
|
are re-raised immediately. If all retries are exhausted the last
|
|
70
57
|
exception is re-raised so the caller can decide how to handle it.
|
|
@@ -84,7 +71,7 @@ def _call_with_retry(
|
|
|
84
71
|
try:
|
|
85
72
|
return fn()
|
|
86
73
|
except genai_errors.APIError as e:
|
|
87
|
-
if e.code in
|
|
74
|
+
if e.code in _evals_constant.RETRYABLE_STATUS_CODES:
|
|
88
75
|
backoff = 2**attempt + random.uniform(0, 1)
|
|
89
76
|
logger.warning(
|
|
90
77
|
"Retryable error (code=%s) on attempt %d/%d for metric"
|
|
@@ -686,6 +673,12 @@ def _build_evaluation_instance(
|
|
|
686
673
|
other_data_map["context"] = types.evals.InstanceData(text=eval_case.context)
|
|
687
674
|
elif isinstance(eval_case.context, genai_types.Content):
|
|
688
675
|
other_data_map["context"] = _content_to_instance_data(eval_case.context)
|
|
676
|
+
else:
|
|
677
|
+
other_data_map["context"] = types.evals.InstanceData(
|
|
678
|
+
contents=types.evals.InstanceDataContents(
|
|
679
|
+
contents=_value_to_content_list(eval_case.context)
|
|
680
|
+
)
|
|
681
|
+
)
|
|
689
682
|
|
|
690
683
|
# 3. Extract custom variables from LLMMetric templates
|
|
691
684
|
if prompt_template:
|
|
@@ -23,7 +23,7 @@ import textwrap
|
|
|
23
23
|
from typing import Any, Optional
|
|
24
24
|
|
|
25
25
|
import pandas as pd
|
|
26
|
-
|
|
26
|
+
import pydantic_core
|
|
27
27
|
|
|
28
28
|
from . import _evals_common
|
|
29
29
|
from . import types
|
|
@@ -229,6 +229,20 @@ def _extract_dataset_rows(dataset: types.EvaluationDataset) -> list[dict[str, An
|
|
|
229
229
|
}
|
|
230
230
|
processed_rows.append(processed_row)
|
|
231
231
|
|
|
232
|
+
for row in processed_rows:
|
|
233
|
+
if isinstance(row["agent_data"], str) or not isinstance(
|
|
234
|
+
row["intermediate_events"], str
|
|
235
|
+
):
|
|
236
|
+
continue
|
|
237
|
+
try:
|
|
238
|
+
events = json.loads(row["intermediate_events"])
|
|
239
|
+
except json.JSONDecodeError:
|
|
240
|
+
continue
|
|
241
|
+
if isinstance(events, list) and events:
|
|
242
|
+
row["agent_data"] = json.dumps(
|
|
243
|
+
{"turns": [{"turn_index": 0, "events": events}]}, ensure_ascii=False
|
|
244
|
+
)
|
|
245
|
+
|
|
232
246
|
return processed_rows
|
|
233
247
|
|
|
234
248
|
|
|
@@ -1155,7 +1169,7 @@ def get_comparison_html(eval_result_json: str) -> str:
|
|
|
1155
1169
|
winRateText = m.win_rates.map((rate, i) => `<b>${{candidateNames ? candidateNames[i] : `Candidate #${{i+1}}`}}</b> wins: <b>${{(rate * 100).toFixed(1)}}%</b>`).join('<br>');
|
|
1156
1170
|
if (m.tie_rate !== undefined) {{ winRateText += `<br>Ties: <b>${{(m.tie_rate * 100).toFixed(1)}}%</b>`; }}
|
|
1157
1171
|
}}
|
|
1158
|
-
table += `<tr><td>${{m.metric_name}}</td><td>${{m.mean_score.toFixed(4)}}</td><td>${{m.stdev_score.toFixed(4)}}</td><td>${{winRateText}}</td></tr>`;
|
|
1172
|
+
table += `<tr><td>${{m.metric_name}}</td><td>${{m.mean_score != null ? m.mean_score.toFixed(4) : 'N/A'}}</td><td>${{m.stdev_score != null ? m.stdev_score.toFixed(4) : 'N/A'}}</td><td>${{winRateText}}</td></tr>`;
|
|
1159
1173
|
}});
|
|
1160
1174
|
container.innerHTML = table + '</tbody></table>';
|
|
1161
1175
|
}}
|
|
@@ -1469,7 +1483,7 @@ def display_evaluation_result(
|
|
|
1469
1483
|
result_dump = eval_result_obj.model_dump(
|
|
1470
1484
|
mode="json", exclude_none=True, exclude={"evaluation_dataset"}
|
|
1471
1485
|
)
|
|
1472
|
-
except
|
|
1486
|
+
except pydantic_core.PydanticSerializationError as e:
|
|
1473
1487
|
logger.error(
|
|
1474
1488
|
"Serialization Error: %s\nCould not display the evaluation "
|
|
1475
1489
|
"result due to a data serialization issue. Please check the "
|
|
@@ -52,6 +52,7 @@ import httpx
|
|
|
52
52
|
import proto
|
|
53
53
|
|
|
54
54
|
from google.api_core import exceptions
|
|
55
|
+
from google.genai import errors as google_genai_errors
|
|
55
56
|
from google.genai import types as google_genai_types
|
|
56
57
|
from google.api import httpbody_pb2
|
|
57
58
|
from google.protobuf import struct_pb2
|
|
@@ -564,6 +565,23 @@ def _await_operation(
|
|
|
564
565
|
return operation
|
|
565
566
|
|
|
566
567
|
|
|
568
|
+
def _raise_for_operation_error(
|
|
569
|
+
*,
|
|
570
|
+
operation: Any,
|
|
571
|
+
message: str,
|
|
572
|
+
) -> None:
|
|
573
|
+
"""Raises an APIError for a failed operation with a context note."""
|
|
574
|
+
try:
|
|
575
|
+
google_genai_errors.APIError.raise_error(
|
|
576
|
+
operation.error.get("code"), operation.error, None
|
|
577
|
+
)
|
|
578
|
+
except google_genai_errors.APIError as e:
|
|
579
|
+
# TODO(yifany): Drop guard once Python 3.10 support is removed.
|
|
580
|
+
if sys.version_info >= (3, 11):
|
|
581
|
+
e.add_note(message)
|
|
582
|
+
raise
|
|
583
|
+
|
|
584
|
+
|
|
567
585
|
def _compare_requirements(
|
|
568
586
|
*,
|
|
569
587
|
requirements: Mapping[str, str],
|
{google_cloud_agentplatform-2.4.0 → google_cloud_agentplatform-2.6.0}/agentplatform/_genai/evals.py
RENAMED
|
@@ -3070,7 +3070,7 @@ class Evals(_api_module.BaseModule):
|
|
|
3070
3070
|
events are replayed as session history for local ADK agents.
|
|
3071
3071
|
model: Optional type is experimental and may change in future versions.
|
|
3072
3072
|
The model to use for inference, optional for agent evaluations.
|
|
3073
|
-
- For Google Gemini models, provide the model name string (e.g., "gemini-
|
|
3073
|
+
- For Google Gemini models, provide the model name string (e.g., "gemini-flash-latest").
|
|
3074
3074
|
- For third-party models via LiteLLM, use the format "provider/model_name"
|
|
3075
3075
|
(e.g., "openai/gpt-4o"). Ensure the necessary API key (e.g., OPENAI_API_KEY)
|
|
3076
3076
|
is set as an environment variable.
|
|
@@ -3342,7 +3342,7 @@ class Evals(_api_module.BaseModule):
|
|
|
3342
3342
|
with the content.
|
|
3343
3343
|
generator_model_config: Optional. Configuration for the model used
|
|
3344
3344
|
in custom rubric generation. Only used if `prompt_template` is provided.
|
|
3345
|
-
e.g., {"autorater_model": "gemini-
|
|
3345
|
+
e.g., {"autorater_model": "gemini-flash-latest"}.
|
|
3346
3346
|
rubric_content_type: Optional. The type of rubric content to be
|
|
3347
3347
|
generated. Only used if `prompt_template` is provided.
|
|
3348
3348
|
rubric_type_ontology: Optional. A pre-defined list of allowed types
|
|
@@ -3619,12 +3619,12 @@ class Evals(_api_module.BaseModule):
|
|
|
3619
3619
|
If provided, `agent_info` must be None. If omitted and `agent_info` is provided,
|
|
3620
3620
|
this will be automatically constructed using `agent_info` and `user_simulator_config`.
|
|
3621
3621
|
The `model` field of an inference config accepts a short Gemini model
|
|
3622
|
-
name (e.g. `gemini-
|
|
3622
|
+
name (e.g. `gemini-flash-latest`), which is automatically expanded to a
|
|
3623
3623
|
fully-qualified resource name using the client's project and location,
|
|
3624
3624
|
or an already fully-qualified publisher-model or endpoint resource
|
|
3625
3625
|
name.
|
|
3626
3626
|
Example:
|
|
3627
|
-
{"candidate-1": types.EvaluationRunInferenceConfig(model="gemini-
|
|
3627
|
+
{"candidate-1": types.EvaluationRunInferenceConfig(model="gemini-flash-latest")}
|
|
3628
3628
|
labels: The labels to apply to the evaluation run.
|
|
3629
3629
|
loss_analysis_metrics: This field is experimental and may change in future
|
|
3630
3630
|
versions. Optional list of metrics to run loss analysis on. The
|
|
@@ -6261,12 +6261,12 @@ class AsyncEvals(_api_module.BaseModule):
|
|
|
6261
6261
|
If provided, `agent_info` must be None. If omitted and `agent_info` is provided,
|
|
6262
6262
|
this will be automatically constructed using `agent_info` and `user_simulator_config`.
|
|
6263
6263
|
The `model` field of an inference config accepts a short Gemini model
|
|
6264
|
-
name (e.g. `gemini-
|
|
6264
|
+
name (e.g. `gemini-flash-latest`), which is automatically expanded to a
|
|
6265
6265
|
fully-qualified resource name using the client's project and location,
|
|
6266
6266
|
or an already fully-qualified publisher-model or endpoint resource
|
|
6267
6267
|
name.
|
|
6268
6268
|
Example:
|
|
6269
|
-
{"candidate-1": types.EvaluationRunInferenceConfig(model="gemini-
|
|
6269
|
+
{"candidate-1": types.EvaluationRunInferenceConfig(model="gemini-flash-latest")}
|
|
6270
6270
|
red_teaming_config: This field is experimental and may change in future
|
|
6271
6271
|
versions. Optional configuration for automated Agent Red Teaming
|
|
6272
6272
|
analysis. Specifies attack categories and vulnerable tools to
|