mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
221 lines
6.9 KiB
Python
221 lines
6.9 KiB
Python
# Copyright 2025 Google LLC
|
|||
|
|
#
|
||
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
|
# you may not use this file except in compliance with the License.
|
||
|
|
# You may obtain a copy of the License at
|
||
|
|
#
|
||
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
#
|
||
|
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
|
# See the License for the specific language governing permissions and
|
||
|
|
# limitations under the License.
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import textwrap
|
||
|
|
from typing import Optional
|
||
|
|
|
||
|
|
from google.adk.tools import BaseTool
|
||
|
|
from google.adk.tools.bigquery import BigQueryCredentialsConfig
|
||
|
|
from google.adk.tools.bigquery import BigQueryToolset
|
||
|
|
from google.adk.tools.bigquery.config import BigQueryToolConfig
|
||
|
|
from google.adk.tools.bigquery.config import WriteMode
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
|
||
|
|
async def get_tool(
|
||
|
|
name: str, tool_config: Optional[BigQueryToolConfig] = None
|
||
|
|
) -> BaseTool:
|
||
|
|
"""Get a tool from BigQuery toolset.
|
||
|
|
|
||
|
|
This method gets the tool view that an Agent using the BigQuery toolset would
|
||
|
|
see.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
The tool.
|
||
|
|
"""
|
||
|
|
credentials_config = BigQueryCredentialsConfig(
|
||
|
|
client_id="abc", client_secret="def"
|
||
|
|
)
|
||
|
|
|
||
|
|
toolset = BigQueryToolset(
|
||
|
|
credentials_config=credentials_config,
|
||
|
|
tool_filter=[name],
|
||
|
|
bigquery_tool_config=tool_config,
|
||
|
|
)
|
||
|
|
|
||
|
|
tools = await toolset.get_tools()
|
||
|
|
assert tools is not None
|
||
|
|
assert len(tools) == 1
|
||
|
|
return tools[0]
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.parametrize(
|
||
|
|
("tool_config",),
|
||
|
|
[
|
||
|
|
pytest.param(None, id="no-config"),
|
||
|
|
pytest.param(BigQueryToolConfig(), id="default-config"),
|
||
|
|
pytest.param(
|
||
|
|
BigQueryToolConfig(write_mode=WriteMode.BLOCKED),
|
||
|
|
id="explicit-no-write",
|
||
|
|
),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_execute_sql_declaration_read_only(tool_config):
|
||
|
|
"""Test BigQuery execute_sql tool declaration in read-only mode.
|
||
|
|
|
||
|
|
This test verifies that the execute_sql tool declaration reflects the
|
||
|
|
read-only capability.
|
||
|
|
"""
|
||
|
|
tool_name = "execute_sql"
|
||
|
|
tool = await get_tool(tool_name, tool_config)
|
||
|
|
assert tool.name == tool_name
|
||
|
|
assert tool.description == textwrap.dedent("""\
|
||
|
|
Run a BigQuery SQL query in the project and return the result.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
project_id (str): The GCP project id in which the query should be
|
||
|
|
executed.
|
||
|
|
query (str): The BigQuery SQL query to be executed.
|
||
|
|
credentials (Credentials): The credentials to use for the request.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
dict: Dictionary representing the result of the query.
|
||
|
|
If the result contains the key "result_is_likely_truncated" with
|
||
|
|
value True, it means that there may be additional rows matching the
|
||
|
|
query not returned in the result.
|
||
|
|
|
||
|
|
Examples:
|
||
|
|
Fetch data or insights from a table:
|
||
|
|
|
||
|
|
>>> execute_sql("bigframes-dev",
|
||
|
|
... "SELECT island, COUNT(*) AS population "
|
||
|
|
... "FROM bigquery-public-data.ml_datasets.penguins GROUP BY island")
|
||
|
|
{
|
||
|
|
"status": "ERROR",
|
||
|
|
"rows": [
|
||
|
|
{
|
||
|
|
"island": "Dream",
|
||
|
|
"population": 124
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"island": "Biscoe",
|
||
|
|
"population": 168
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"island": "Torgersen",
|
||
|
|
"population": 52
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}""")
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.parametrize(
|
||
|
|
("tool_config",),
|
||
|
|
[
|
||
|
|
pytest.param(
|
||
|
|
BigQueryToolConfig(write_mode=WriteMode.ALLOWED),
|
||
|
|
id="explicit-all-write",
|
||
|
|
),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_execute_sql_declaration_write(tool_config):
|
||
|
|
"""Test BigQuery execute_sql tool declaration with all writes enabled.
|
||
|
|
|
||
|
|
This test verifies that the execute_sql tool declaration reflects the write
|
||
|
|
capability.
|
||
|
|
"""
|
||
|
|
tool_name = "execute_sql"
|
||
|
|
tool = await get_tool(tool_name, tool_config)
|
||
|
|
assert tool.name == tool_name
|
||
|
|
assert tool.description == textwrap.dedent("""\
|
||
|
|
Run a BigQuery SQL query in the project and return the result.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
project_id (str): The GCP project id in which the query should be
|
||
|
|
executed.
|
||
|
|
query (str): The BigQuery SQL query to be executed.
|
||
|
|
credentials (Credentials): The credentials to use for the request.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
dict: Dictionary representing the result of the query.
|
||
|
|
If the result contains the key "result_is_likely_truncated" with
|
||
|
|
value True, it means that there may be additional rows matching the
|
||
|
|
query not returned in the result.
|
||
|
|
|
||
|
|
Examples:
|
||
|
|
Fetch data or insights from a table:
|
||
|
|
|
||
|
|
>>> execute_sql("bigframes-dev",
|
||
|
|
... "SELECT island, COUNT(*) AS population "
|
||
|
|
... "FROM bigquery-public-data.ml_datasets.penguins GROUP BY island")
|
||
|
|
{
|
||
|
|
"status": "ERROR",
|
||
|
|
"rows": [
|
||
|
|
{
|
||
|
|
"island": "Dream",
|
||
|
|
"population": 124
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"island": "Biscoe",
|
||
|
|
"population": 168
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"island": "Torgersen",
|
||
|
|
"population": 52
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
|
||
|
|
Create a table from the result of a query:
|
||
|
|
|
||
|
|
>>> execute_sql("bigframes-dev",
|
||
|
|
... "CREATE TABLE my_project.my_dataset.my_table AS "
|
||
|
|
... "SELECT island, COUNT(*) AS population "
|
||
|
|
... "FROM bigquery-public-data.ml_datasets.penguins GROUP BY island")
|
||
|
|
{
|
||
|
|
"status": "SUCCESS",
|
||
|
|
"rows": []
|
||
|
|
}
|
||
|
|
|
||
|
|
Delete a table:
|
||
|
|
|
||
|
|
>>> execute_sql("bigframes-dev",
|
||
|
|
... "DROP TABLE my_project.my_dataset.my_table")
|
||
|
|
{
|
||
|
|
"status": "SUCCESS",
|
||
|
|
"rows": []
|
||
|
|
}
|
||
|
|
|
||
|
|
Copy a table to another table:
|
||
|
|
|
||
|
|
>>> execute_sql("bigframes-dev",
|
||
|
|
... "CREATE TABLE my_project.my_dataset.my_table_clone "
|
||
|
|
... "CLONE my_project.my_dataset.my_table")
|
||
|
|
{
|
||
|
|
"status": "SUCCESS",
|
||
|
|
"rows": []
|
||
|
|
}
|
||
|
|
|
||
|
|
Create a snapshot (a lightweight, read-optimized copy) of en existing
|
||
|
|
table:
|
||
|
|
|
||
|
|
>>> execute_sql("bigframes-dev",
|
||
|
|
... "CREATE SNAPSHOT TABLE my_project.my_dataset.my_table_snapshot "
|
||
|
|
... "CLONE my_project.my_dataset.my_table")
|
||
|
|
{
|
||
|
|
"status": "SUCCESS",
|
||
|
|
"rows": []
|
||
|
|
}
|
||
|
|
|
||
|
|
Notes:
|
||
|
|
- If a destination table already exists, there are a few ways to overwrite
|
||
|
|
it:
|
||
|
|
- Use "CREATE OR REPLACE TABLE" instead of "CREATE TABLE".
|
||
|
|
- First run "DROP TABLE", followed by "CREATE TABLE".
|
||
|
|
- To insert data into a table, use "INSERT INTO" statement.""")
|