Skip to content

Commit 0222eb1

Browse files
author
James Nguyen
committed
feat(dea): parameterize url_agent_name and agent_type_uri options
1 parent 03d5d3c commit 0222eb1

4 files changed

Lines changed: 187 additions & 4 deletions

File tree

datasets/dea-tools/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,26 @@ This file is the main driver that dictates how evaluations are executed. Key par
3030
* `set_up_script` & `tear_down_script`: Scripts that prep and clean up the Dataform environment. You can comment out `tear_down_script` if you want to keep the workspace alive after the run for debugging.
3131
* `dataform_workspace_gcs_archive`: Saves a ZIP archive of the workspace artifacts to a GCS bucket.
3232

33+
### Parameterized Agent & Environment Configuration:
34+
The model configuration file is defined in `datasets/model_configs/gcp_data_engineering_agent_model.yaml`. In your model configuration YAML file, you can configure target environments and agent personas:
35+
36+
```yaml
37+
generator: "data_engineering_agent"
38+
gcp_project_id: !ENV ${EVAL_GCP_PROJECT_ID}
39+
gcp_region: !ENV ${EVAL_GCP_PROJECT_REGION}
40+
41+
# Parameterized Agent Options:
42+
model_env: local # Target environment: "local", "staging", or "prod" (defaults to "prod")
43+
port: 9876 # Required port for local Boq servers when env="local"
44+
agent_type: sparkagent # Desired agent persona (e.g., "sparkagent", "dataengineeringagent")
45+
46+
```
47+
48+
* **`model_env`**: Configures the host environment (`local` uses `http://localhost:{port}`, `staging` uses `https://staging-geminidataanalytics.sandbox.googleapis.com`, `prod` uses `https://geminidataanalytics.googleapis.com`).
49+
50+
* **`port`**: Specifies the HTTP port for local Boq servers (required when `env="local"`).
51+
* **`agent_type`**: Sets the desired agent persona (e.g., "sparkagent", "dataengineeringagent").
52+
3353
## 3. Run EvalBench
3454

3555
You can run EvalBench for DEA in two modes:

datasets/model_configs/gcp_data_engineering_agent_model.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ gcp_project_id: !ENV ${EVAL_GCP_PROJECT_ID}
33
gcp_region: !ENV ${EVAL_GCP_PROJECT_REGION:us-west4}
44
dataform_repository: !ENV ${EVAL_DEA_REPOSITORY_ID}
55
dataform_workspace: !ENV ${EVAL_DEA_WORKSPACE_ID}
6+
7+
model_env: prod
8+
agent_type: dataengineeringagent
69
execs_per_minute: 10

evalbench/generators/models/gcp_data_engineering_agent.py

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,21 @@
5050
"https://geminidataanalytics.googleapis.com/a2a/extensions/"
5151
"finishreason/v1"
5252
)
53+
AGENT_TYPE_URI = (
54+
"https://geminidataanalytics.googleapis.com/a2a/extensions/"
55+
"agenttype/v1"
56+
)
57+
58+
# Mapping from agent_type to AGENT_TYPE_URI value
59+
AGENT_TYPE_MAP = {
60+
"sparkagent": "SPARK_AGENT",
61+
}
62+
5363

5464
# All required A2A Extension Headers combined
5565
ALL_EXTENSIONS = (
5666
f"{MESSAGE_LEVEL_URI},{INSTRUCTION_URI},{GCP_RESOURCE_URI},"
57-
f"{CONVERSATION_TOKEN_URI},{FINISH_REASON_URI}"
67+
f"{CONVERSATION_TOKEN_URI},{FINISH_REASON_URI},{AGENT_TYPE_URI}"
5868
)
5969

6070
logger = logging.getLogger(__name__)
@@ -211,6 +221,28 @@ def __init__(self, querygenerator_config: dict[str, Any]):
211221
self.name = "data_engineering_agent"
212222
gcp_project_id = querygenerator_config.get("gcp_project_id", "")
213223
gcp_region = querygenerator_config.get("gcp_region", "")
224+
env_val = querygenerator_config.get("model_env")
225+
226+
if not isinstance(env_val, str):
227+
raise TypeError(
228+
"Configuration key 'model_env' must be a string, "
229+
f"got {type(env_val).__name__}."
230+
)
231+
env = env_val.lower()
232+
233+
self.agent_type = querygenerator_config.get(
234+
"agent_type", "dataengineeringagent"
235+
).lower()
236+
match self.agent_type:
237+
case "dataengineeringagent":
238+
self.agent_type_uri = None
239+
case "sparkagent":
240+
self.agent_type_uri = AGENT_TYPE_MAP.get(self.agent_type)
241+
case _:
242+
raise ValueError(
243+
f"Unsupported agent_type '{self.agent_type}'. "
244+
"Must be 'dataengineeringagent' or 'sparkagent'."
245+
)
214246

215247
if not gcp_project_id:
216248
raise ValueError(
@@ -223,10 +255,26 @@ def __init__(self, querygenerator_config: dict[str, Any]):
223255
"DataEngineeringAgentGenerator."
224256
)
225257

258+
if env == "local":
259+
port = querygenerator_config.get("port", 9876)
260+
261+
host = f"http://localhost:{port}"
262+
elif env == "staging":
263+
host = (
264+
"https://staging-geminidataanalytics."
265+
"sandbox.googleapis.com"
266+
)
267+
elif env == "prod":
268+
host = "https://geminidataanalytics.googleapis.com"
269+
else:
270+
raise ValueError(
271+
f"Unsupported env: '{env}'. "
272+
"Expected 'local', 'staging', or 'prod'."
273+
)
274+
226275
self.endpoint = (
227-
f"https://geminidataanalytics.googleapis.com/v1/a2a/projects/"
228-
f"{gcp_project_id}/locations/{gcp_region}/"
229-
f"agents/dataengineeringagent"
276+
f"{host}/v1/a2a/projects/{gcp_project_id}/"
277+
f"locations/{gcp_region}/agents/{self.agent_type}"
230278
)
231279

232280
self.auth_interceptor = AuthInterceptor(GcpAdcCredentialService())
@@ -324,6 +372,9 @@ async def _run_client(
324372
message_req.metadata[GCP_RESOURCE_URI] = {
325373
"gcpResourceId": target_workspace
326374
}
375+
# Configure Agent Type extension
376+
if self.agent_type_uri:
377+
message_req.metadata[AGENT_TYPE_URI] = self.agent_type_uri
327378

328379
# Handle ConversationToken state memory thread-safely
329380
token = ""

evalbench/test/gcp_data_engineering_agent_test.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def valid_config():
5555
"gcp_region": "us-east1",
5656
"dataform_repository": "test-repo",
5757
"dataform_workspace": "test-workspace",
58+
"model_env": "prod",
5859
}
5960

6061

@@ -165,6 +166,97 @@ def test_data_engineering_agent_generator_setup(valid_config):
165166
assert generator.auth_interceptor is not None
166167

167168

169+
def test_generator_parameterized_staging_env(valid_config):
170+
config = valid_config.copy()
171+
config["model_env"] = "staging"
172+
with patch("google.auth.default") as mock_auth_default:
173+
mock_creds = MagicMock()
174+
mock_creds.valid = True
175+
mock_auth_default.return_value = (mock_creds, "test-project")
176+
177+
generator = DataEngineeringAgentGenerator(config)
178+
179+
expected_endpoint = (
180+
"https://staging-geminidataanalytics.sandbox.googleapis.com/"
181+
"v1/a2a/projects/test-project-123/locations/us-east1/agents/"
182+
"dataengineeringagent"
183+
)
184+
assert generator.endpoint == expected_endpoint
185+
186+
187+
def test_generator_parameterized_sparkagent(valid_config):
188+
config = valid_config.copy()
189+
config["model_env"] = "staging"
190+
config["agent_type"] = "sparkagent"
191+
with patch("google.auth.default") as mock_auth_default:
192+
mock_creds = MagicMock()
193+
mock_creds.valid = True
194+
mock_auth_default.return_value = (mock_creds, "test-project")
195+
196+
generator = DataEngineeringAgentGenerator(config)
197+
198+
expected_endpoint = (
199+
"https://staging-geminidataanalytics.sandbox.googleapis.com/"
200+
"v1/a2a/projects/test-project-123/locations/us-east1/agents/"
201+
"sparkagent"
202+
)
203+
assert generator.endpoint == expected_endpoint
204+
assert generator.agent_type == "sparkagent"
205+
assert generator.agent_type_uri == "SPARK_AGENT"
206+
207+
208+
def test_generator_parameterized_local_env(valid_config):
209+
config = valid_config.copy()
210+
config["model_env"] = "local"
211+
config["port"] = 9876
212+
config["agent_type"] = "sparkagent"
213+
with patch("google.auth.default") as mock_auth_default:
214+
mock_creds = MagicMock()
215+
mock_creds.valid = True
216+
mock_auth_default.return_value = (mock_creds, "test-project")
217+
218+
generator = DataEngineeringAgentGenerator(config)
219+
220+
expected_endpoint = (
221+
"http://localhost:9876/v1/a2a/projects/test-project-123/"
222+
"locations/us-east1/agents/sparkagent"
223+
)
224+
assert generator.endpoint == expected_endpoint
225+
226+
227+
def test_generator_parameterized_local_port_override(valid_config):
228+
config = valid_config.copy()
229+
config["model_env"] = "local"
230+
config["port"] = 8080
231+
config["agent_type"] = "dataengineeringagent"
232+
with patch("google.auth.default") as mock_auth_default:
233+
mock_creds = MagicMock()
234+
mock_creds.valid = True
235+
mock_auth_default.return_value = (mock_creds, "test-project")
236+
237+
generator = DataEngineeringAgentGenerator(config)
238+
239+
expected_endpoint = (
240+
"http://localhost:8080/v1/a2a/projects/test-project-123/"
241+
"locations/us-east1/agents/dataengineeringagent"
242+
)
243+
assert generator.endpoint == expected_endpoint
244+
245+
246+
def test_generator_setup_unsupported_env_raises_value_error(valid_config):
247+
config = valid_config.copy()
248+
config["model_env"] = "invalid_env"
249+
with patch("google.auth.default") as mock_auth_default:
250+
mock_creds = MagicMock()
251+
mock_creds.valid = True
252+
mock_auth_default.return_value = (mock_creds, "test-project")
253+
254+
with pytest.raises(ValueError) as excinfo:
255+
DataEngineeringAgentGenerator(config)
256+
257+
assert "Unsupported env: 'invalid_env'" in str(excinfo.value)
258+
259+
168260
@pytest.mark.anyio
169261
@patch("google.auth.default")
170262
@patch("generators.models.gcp_data_engineering_agent.create_client")
@@ -305,6 +397,23 @@ async def mock_close():
305397
assert called_card.capabilities.extended_agent_card is True
306398

307399

400+
def test_generator_setup_unsupported_agent_type_raises_error(
401+
valid_config,
402+
):
403+
config = valid_config.copy()
404+
config["agent_type"] = "unsupportedagent"
405+
406+
with patch("google.auth.default") as mock_auth_default:
407+
mock_creds = MagicMock()
408+
mock_creds.valid = True
409+
mock_auth_default.return_value = (mock_creds, "test-project")
410+
411+
with pytest.raises(ValueError) as excinfo:
412+
DataEngineeringAgentGenerator(config)
413+
414+
assert "Unsupported agent_type 'unsupportedagent'" in str(excinfo.value)
415+
416+
308417
@patch("evaluator.dataengineeringagentevaluator.AgentScoreWork")
309418
@patch("evaluator.dataengineeringagentevaluator.SimulatedUser")
310419
def test_evaluator_process_scenario(

0 commit comments

Comments
 (0)