mirror of
https://github.com/EvolutionAPI/adk-python.git
synced 2025-07-13 23:17:35 -06:00
ADK changes
PiperOrigin-RevId: 764776124
This commit is contained in:
parent
a9345a072e
commit
ac52eab88e
228
tests/unittests/fast_api/test_fast_api.py
Normal file → Executable file
228
tests/unittests/fast_api/test_fast_api.py
Normal file → Executable file
@ -21,6 +21,10 @@ from unittest.mock import patch
|
|||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from google.adk.agents.base_agent import BaseAgent
|
from google.adk.agents.base_agent import BaseAgent
|
||||||
from google.adk.agents.run_config import RunConfig
|
from google.adk.agents.run_config import RunConfig
|
||||||
|
from google.adk.evaluation.eval_case import EvalCase
|
||||||
|
from google.adk.evaluation.eval_case import Invocation
|
||||||
|
from google.adk.evaluation.eval_set import EvalSet
|
||||||
|
from google.adk.evaluation.eval_result import EvalSetResult
|
||||||
from google.adk.cli.fast_api import get_fast_api_app
|
from google.adk.cli.fast_api import get_fast_api_app
|
||||||
from google.adk.events import Event
|
from google.adk.events import Event
|
||||||
from google.adk.runners import Runner
|
from google.adk.runners import Runner
|
||||||
@ -281,12 +285,107 @@ def mock_memory_service():
|
|||||||
return MagicMock()
|
return MagicMock()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_eval_sets_manager():
|
||||||
|
"""Create a mock eval sets manager."""
|
||||||
|
|
||||||
|
# Storage for eval sets.
|
||||||
|
eval_sets = {}
|
||||||
|
|
||||||
|
class MockEvalSetsManager:
|
||||||
|
"""Mock eval sets manager."""
|
||||||
|
|
||||||
|
def create_eval_set(self, app_name, eval_set_id):
|
||||||
|
"""Create an eval set."""
|
||||||
|
if app_name not in eval_sets:
|
||||||
|
eval_sets[app_name] = {}
|
||||||
|
|
||||||
|
if eval_set_id in eval_sets[app_name]:
|
||||||
|
raise ValueError(f"Eval set {eval_set_id} already exists.")
|
||||||
|
|
||||||
|
eval_sets[app_name][eval_set_id] = EvalSet(
|
||||||
|
eval_set_id=eval_set_id, eval_cases=[]
|
||||||
|
)
|
||||||
|
return eval_set_id
|
||||||
|
|
||||||
|
def get_eval_set(self, app_name, eval_set_id):
|
||||||
|
"""Get an eval set."""
|
||||||
|
if app_name not in eval_sets:
|
||||||
|
raise ValueError(f"App {app_name} not found.")
|
||||||
|
if eval_set_id not in eval_sets[app_name]:
|
||||||
|
raise ValueError(f"Eval set {eval_set_id} not found in app {app_name}.")
|
||||||
|
return eval_sets[app_name][eval_set_id]
|
||||||
|
|
||||||
|
def list_eval_sets(self, app_name):
|
||||||
|
"""List eval sets."""
|
||||||
|
if app_name not in eval_sets:
|
||||||
|
raise ValueError(f"App {app_name} not found.")
|
||||||
|
return list(eval_sets[app_name].keys())
|
||||||
|
|
||||||
|
def add_eval_case(self, app_name, eval_set_id, eval_case):
|
||||||
|
"""Add an eval case to an eval set."""
|
||||||
|
if app_name not in eval_sets:
|
||||||
|
raise ValueError(f"App {app_name} not found.")
|
||||||
|
if eval_set_id not in eval_sets[app_name]:
|
||||||
|
raise ValueError(f"Eval set {eval_set_id} not found in app {app_name}.")
|
||||||
|
eval_sets[app_name][eval_set_id].eval_cases.append(eval_case)
|
||||||
|
|
||||||
|
return MockEvalSetsManager()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_eval_set_results_manager():
|
||||||
|
"""Create a mock eval set results manager."""
|
||||||
|
|
||||||
|
# Storage for eval set results.
|
||||||
|
eval_set_results = {}
|
||||||
|
|
||||||
|
class MockEvalSetResultsManager:
|
||||||
|
"""Mock eval set results manager."""
|
||||||
|
|
||||||
|
def save_eval_set_result(
|
||||||
|
self, app_name, eval_set_id, eval_case_results
|
||||||
|
):
|
||||||
|
if app_name not in eval_set_results:
|
||||||
|
eval_set_results[app_name] = {}
|
||||||
|
eval_set_result_id = f"{app_name}_{eval_set_id}_eval_result"
|
||||||
|
eval_set_result = EvalSetResult(
|
||||||
|
eval_set_result_id=eval_set_result_id,
|
||||||
|
eval_set_result_name=eval_set_result_id,
|
||||||
|
eval_set_id=eval_set_id,
|
||||||
|
eval_case_results=eval_case_results,
|
||||||
|
)
|
||||||
|
if eval_set_result_id not in eval_set_results[app_name]:
|
||||||
|
eval_set_results[app_name][eval_set_result_id] = eval_set_result
|
||||||
|
else:
|
||||||
|
eval_set_results[app_name][eval_set_result_id].append(eval_set_result)
|
||||||
|
|
||||||
|
def get_eval_set_result(self, app_name, eval_set_result_id):
|
||||||
|
if app_name not in eval_set_results:
|
||||||
|
raise ValueError(f"App {app_name} not found.")
|
||||||
|
if eval_set_result_id not in eval_set_results[app_name]:
|
||||||
|
raise ValueError(
|
||||||
|
f"Eval set result {eval_set_result_id} not found in app {app_name}."
|
||||||
|
)
|
||||||
|
return eval_set_results[app_name][eval_set_result_id]
|
||||||
|
|
||||||
|
def list_eval_set_results(self, app_name):
|
||||||
|
"""List eval set results."""
|
||||||
|
if app_name not in eval_set_results:
|
||||||
|
raise ValueError(f"App {app_name} not found.")
|
||||||
|
return list(eval_set_results[app_name].keys())
|
||||||
|
|
||||||
|
return MockEvalSetResultsManager()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def test_app(
|
def test_app(
|
||||||
mock_session_service,
|
mock_session_service,
|
||||||
mock_artifact_service,
|
mock_artifact_service,
|
||||||
mock_memory_service,
|
mock_memory_service,
|
||||||
mock_agent_loader,
|
mock_agent_loader,
|
||||||
|
mock_eval_sets_manager,
|
||||||
|
mock_eval_set_results_manager,
|
||||||
):
|
):
|
||||||
"""Create a TestClient for the FastAPI app without starting a server."""
|
"""Create a TestClient for the FastAPI app without starting a server."""
|
||||||
|
|
||||||
@ -309,6 +408,14 @@ def test_app(
|
|||||||
"google.adk.cli.fast_api.AgentLoader",
|
"google.adk.cli.fast_api.AgentLoader",
|
||||||
return_value=mock_agent_loader,
|
return_value=mock_agent_loader,
|
||||||
),
|
),
|
||||||
|
patch(
|
||||||
|
"google.adk.cli.fast_api.LocalEvalSetsManager",
|
||||||
|
return_value=mock_eval_sets_manager,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"google.adk.cli.fast_api.LocalEvalSetResultsManager",
|
||||||
|
return_value=mock_eval_set_results_manager,
|
||||||
|
),
|
||||||
):
|
):
|
||||||
# Get the FastAPI app, but don't actually run it
|
# Get the FastAPI app, but don't actually run it
|
||||||
app = get_fast_api_app(
|
app = get_fast_api_app(
|
||||||
@ -339,6 +446,35 @@ async def create_test_session(
|
|||||||
return test_session_info
|
return test_session_info
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
async def create_test_eval_set(
|
||||||
|
test_app, test_session_info, mock_eval_sets_manager
|
||||||
|
):
|
||||||
|
"""Create a test eval set using the mocked eval sets manager."""
|
||||||
|
_ = mock_eval_sets_manager.create_eval_set(
|
||||||
|
app_name=test_session_info["app_name"],
|
||||||
|
eval_set_id="test_eval_set_id",
|
||||||
|
)
|
||||||
|
test_eval_case = EvalCase(
|
||||||
|
eval_id="test_eval_case_id",
|
||||||
|
conversation=[
|
||||||
|
Invocation(
|
||||||
|
invocation_id="test_invocation_id",
|
||||||
|
user_content=types.Content(
|
||||||
|
parts=[types.Part(text="test_user_content")],
|
||||||
|
role="user",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
_ = mock_eval_sets_manager.add_eval_case(
|
||||||
|
app_name=test_session_info["app_name"],
|
||||||
|
eval_set_id="test_eval_set_id",
|
||||||
|
eval_case=test_eval_case,
|
||||||
|
)
|
||||||
|
return test_session_info
|
||||||
|
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
# Test Cases
|
# Test Cases
|
||||||
#################################################
|
#################################################
|
||||||
@ -479,6 +615,98 @@ def test_list_artifact_names(test_app, create_test_session):
|
|||||||
logger.info(f"Listed {len(data)} artifacts")
|
logger.info(f"Listed {len(data)} artifacts")
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_eval_set_not_found(test_app):
|
||||||
|
"""Test getting an eval set that doesn't exist."""
|
||||||
|
url = "/apps/test_app_name/eval_sets/test_eval_set_id_not_found"
|
||||||
|
response = test_app.get(url)
|
||||||
|
assert response.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_eval_set(test_app, test_session_info):
|
||||||
|
"""Test creating an eval set."""
|
||||||
|
url = f"/apps/{test_session_info['app_name']}/eval_sets/test_eval_set_id"
|
||||||
|
response = test_app.post(url)
|
||||||
|
|
||||||
|
# Verify the response
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_eval_sets(test_app, create_test_eval_set):
|
||||||
|
"""Test get eval set."""
|
||||||
|
info = create_test_eval_set
|
||||||
|
url = f"/apps/{info['app_name']}/eval_sets"
|
||||||
|
response = test_app.get(url)
|
||||||
|
|
||||||
|
# Verify the response
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
assert isinstance(data, list)
|
||||||
|
assert len(data) == 1
|
||||||
|
assert data[0] == "test_eval_set_id"
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_eval_set_result_not_found(test_app):
|
||||||
|
"""Test getting an eval set result that doesn't exist."""
|
||||||
|
url = "/apps/test_app_name/eval_results/test_eval_result_id_not_found"
|
||||||
|
response = test_app.get(url)
|
||||||
|
assert response.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_eval(test_app, create_test_eval_set):
|
||||||
|
"""Test running an eval."""
|
||||||
|
|
||||||
|
# Helper function to verify eval case result.
|
||||||
|
def verify_eval_case_result(actual_eval_case_result):
|
||||||
|
expected_eval_case_result = {
|
||||||
|
"evalSetId": "test_eval_set_id",
|
||||||
|
"evalId": "test_eval_case_id",
|
||||||
|
"finalEvalStatus": 1,
|
||||||
|
"overallEvalMetricResults": [{
|
||||||
|
"metricName": "tool_trajectory_avg_score",
|
||||||
|
"threshold": 0.5,
|
||||||
|
"score": 1.0,
|
||||||
|
"evalStatus": 1,
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
for k, v in expected_eval_case_result.items():
|
||||||
|
assert actual_eval_case_result[k] == v
|
||||||
|
|
||||||
|
info = create_test_eval_set
|
||||||
|
url = f"/apps/{info['app_name']}/eval_sets/test_eval_set_id/run_eval"
|
||||||
|
payload = {
|
||||||
|
"eval_ids": ["test_eval_case_id"],
|
||||||
|
"eval_metrics": [
|
||||||
|
{"metric_name": "tool_trajectory_avg_score", "threshold": 0.5}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
response = test_app.post(url, json=payload)
|
||||||
|
|
||||||
|
# Verify the response
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
assert len(data) == 1
|
||||||
|
verify_eval_case_result(data[0])
|
||||||
|
|
||||||
|
# Verify the eval set result is saved via get_eval_result endpoint.
|
||||||
|
url = f"/apps/{info['app_name']}/eval_results/{info['app_name']}_test_eval_set_id_eval_result"
|
||||||
|
response = test_app.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
assert isinstance(data, dict)
|
||||||
|
assert data["evalSetId"] == "test_eval_set_id"
|
||||||
|
assert data["evalSetResultId"] == f"{info['app_name']}_test_eval_set_id_eval_result"
|
||||||
|
assert len(data["evalCaseResults"]) == 1
|
||||||
|
verify_eval_case_result(data["evalCaseResults"][0])
|
||||||
|
|
||||||
|
# Verify the eval set result is saved via list_eval_results endpoint.
|
||||||
|
url = f"/apps/{info['app_name']}/eval_results"
|
||||||
|
response = test_app.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
assert data == [f"{info['app_name']}_test_eval_set_id_eval_result"]
|
||||||
|
|
||||||
|
|
||||||
def test_debug_trace(test_app):
|
def test_debug_trace(test_app):
|
||||||
"""Test the debug trace endpoint."""
|
"""Test the debug trace endpoint."""
|
||||||
# This test will likely return 404 since we haven't set up trace data,
|
# This test will likely return 404 since we haven't set up trace data,
|
||||||
|
Loading…
Reference in New Issue
Block a user