76027ddb2f
Merge https://github.com/google/adk-python/pull/4414 **Please ensure you have read the [contribution guide](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) before creating a pull request.** ### Link to Issue or Description of Change **1. Link to an existing issue (if applicable):** - Related: #4410 - Fixes: #2602 **Problem:** `AgentEvaluator.evaluate()` did not support built-in eval set result persistence, making it harder to reuse the same workflow as CLI/Web paths that already use `EvalSetResultsManager`. Also, introducing new parameters in the middle of method signatures would break positional-argument compatibility for existing users. **Solution:** This PR adds optional eval result persistence to `AgentEvaluator` while preserving backward compatibility: - Add optional parameters to `AgentEvaluator.evaluate()` and `AgentEvaluator.evaluate_eval_set()`: - `app_name: Optional[str] = None` - `eval_set_results_manager: Optional[EvalSetResultsManager] = None` - Persist results per eval set (a single save aggregating all `EvalCaseResult`s), aligning `AgentEvaluator` with existing CLI/Web/API (`LocalEvalService`) persistence behavior. - Resolve `app_name` from explicit input first, then derive from `agent_module` (including `.agent` suffix handling). - Save results before failure assertion so failed eval runs still leave artifacts for inspection. - Keep existing positional argument behavior by appending new parameters at the end of public method signatures. - Add/extend tests to verify: - explicit and derived `app_name` - save-on-failure behavior - argument propagation from `evaluate()` to `evaluate_eval_set()` - positional-argument backward compatibility - Add an integration usage example for `app_name` omission with `LocalEvalSetResultsManager`. - For multi-run evals, all runs and eval cases are aggregated into a single result file per eval set (each run contributes one `EvalCaseResult`). ### Testing Plan **Unit Tests:** - [x] I have added or updated unit tests for my change. - [x] All unit tests pass locally. ``` % pytest tests/unittests/evaluation ======================== 357 passed, 169 warnings in 9.68s ========================= ``` **Manual End-to-End (E2E) Tests:** ``` % pytest tests/integration/test_with_test_file.py::test_with_single_test_file_saves_eval_set_result ======================== 1 passed, 14 warnings in 5.24s ======================== ``` Verify a result file is created under: `<tmp_path>/<derived_app_name>/.adk/eval_history/*.evalset_result.json` (e.g., 1 file containing 2 `EvalCaseResult`s when num_runs=2 on a single-case eval fixture). This is helpful for debugging failed integration tests. ### Checklist - [x] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) document. - [x] I have performed a self-review of my own code. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have added tests that prove my fix is effective or that my feature works. - [x] New and existing unit tests pass locally with my changes. - [x] I have manually tested my changes end-to-end. - [x] Any dependent changes have been merged and published in downstream modules. ### Additional context - This PR intentionally preserves public API positional compatibility by appending new optional parameters at the tail of method signatures. - A generated local eval result JSON file may exist in the working tree from manual verification and is intentionally not part of the code change. Co-authored-by: Yi Liu <yiliuly@google.com> COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4414 from ftnext:agent-evaluator-save-evalset-result 873973e549c0a4b25b83e1ef81e1b4148ab4e379 PiperOrigin-RevId: 962597058