mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
docs: Update ADK release analyzer to use Gemini 3 Pro with retry and improve file filtering
Co-authored-by: Xuan Yang <xygoogle@google.com> PiperOrigin-RevId: 861784867
This commit is contained in:
committed by
Copybara-Service
parent
3bcd8f7f7a
commit
2155a35c51
@@ -57,8 +57,25 @@ from google.adk import Agent
|
|||||||
from google.adk.agents.loop_agent import LoopAgent
|
from google.adk.agents.loop_agent import LoopAgent
|
||||||
from google.adk.agents.readonly_context import ReadonlyContext
|
from google.adk.agents.readonly_context import ReadonlyContext
|
||||||
from google.adk.agents.sequential_agent import SequentialAgent
|
from google.adk.agents.sequential_agent import SequentialAgent
|
||||||
|
from google.adk.models import Gemini
|
||||||
from google.adk.tools.exit_loop_tool import exit_loop
|
from google.adk.tools.exit_loop_tool import exit_loop
|
||||||
from google.adk.tools.tool_context import ToolContext
|
from google.adk.tools.tool_context import ToolContext
|
||||||
|
from google.genai import types
|
||||||
|
|
||||||
|
# Retry configuration for handling API rate limits and overload
|
||||||
|
_RETRY_OPTIONS = types.HttpRetryOptions(
|
||||||
|
initial_delay=10,
|
||||||
|
attempts=8,
|
||||||
|
exp_base=2,
|
||||||
|
max_delay=300,
|
||||||
|
http_status_codes=[429, 503],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use gemini-3-pro-preview for planning and summary (better quality)
|
||||||
|
GEMINI_PRO_WITH_RETRY = Gemini(
|
||||||
|
model="gemini-3-pro-preview",
|
||||||
|
retry_options=_RETRY_OPTIONS,
|
||||||
|
)
|
||||||
|
|
||||||
# Maximum number of files per analysis group to avoid context overflow
|
# Maximum number of files per analysis group to avoid context overflow
|
||||||
MAX_FILES_PER_GROUP = 5
|
MAX_FILES_PER_GROUP = 5
|
||||||
@@ -249,7 +266,7 @@ def get_release_context(tool_context: ToolContext) -> dict[str, Any]:
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
planner_agent = Agent(
|
planner_agent = Agent(
|
||||||
model="gemini-2.5-pro",
|
model=GEMINI_PRO_WITH_RETRY,
|
||||||
name="release_planner",
|
name="release_planner",
|
||||||
description=(
|
description=(
|
||||||
"Plans the analysis by fetching release info and organizing files into"
|
"Plans the analysis by fetching release info and organizing files into"
|
||||||
@@ -272,12 +289,12 @@ efficient processing.
|
|||||||
|
|
||||||
3. Call `get_changed_files_summary` to get the list of changed files WITHOUT
|
3. Call `get_changed_files_summary` to get the list of changed files WITHOUT
|
||||||
the full patches (to save context space).
|
the full patches (to save context space).
|
||||||
- **IMPORTANT**: Pass `local_repo_path="{LOCAL_REPOS_DIR_PATH}/{CODE_REPO}"`
|
- **IMPORTANT**: Pass these parameters:
|
||||||
to use local git and avoid GitHub API's 300-file limit.
|
- `local_repo_path="{LOCAL_REPOS_DIR_PATH}/{CODE_REPO}"` to avoid 300-file limit
|
||||||
|
- `path_filter="src/google/adk/"` to only get ADK source files (reduces token usage)
|
||||||
|
|
||||||
4. Filter and organize the files:
|
4. Further filter the returned files:
|
||||||
- **INCLUDE** only files in `src/google/adk/` directory
|
- **EXCLUDE** test files and `__init__.py` files
|
||||||
- **EXCLUDE** test files, `__init__.py`, and files outside src/
|
|
||||||
- **IMPORTANT**: Do NOT exclude any file just because it has few changes.
|
- **IMPORTANT**: Do NOT exclude any file just because it has few changes.
|
||||||
Even single-line changes to public APIs need documentation updates.
|
Even single-line changes to public APIs need documentation updates.
|
||||||
- **PRIORITIZE** by importance:
|
- **PRIORITIZE** by importance:
|
||||||
@@ -423,7 +440,7 @@ files and finding related documentation that needs updating.
|
|||||||
|
|
||||||
|
|
||||||
file_group_analyzer = Agent(
|
file_group_analyzer = Agent(
|
||||||
model="gemini-2.5-pro",
|
model=GEMINI_PRO_WITH_RETRY,
|
||||||
name="file_group_analyzer",
|
name="file_group_analyzer",
|
||||||
description=(
|
description=(
|
||||||
"Analyzes a group of changed files and generates recommendations."
|
"Analyzes a group of changed files and generates recommendations."
|
||||||
@@ -507,7 +524,7 @@ Present a summary of:
|
|||||||
|
|
||||||
|
|
||||||
summary_agent = Agent(
|
summary_agent = Agent(
|
||||||
model="gemini-2.5-pro",
|
model=GEMINI_PRO_WITH_RETRY,
|
||||||
name="summary_agent",
|
name="summary_agent",
|
||||||
description="Compiles recommendations and creates the GitHub issue.",
|
description="Compiles recommendations and creates the GitHub issue.",
|
||||||
instruction=summary_instruction,
|
instruction=summary_instruction,
|
||||||
@@ -542,7 +559,7 @@ analysis_pipeline = SequentialAgent(
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
root_agent = Agent(
|
root_agent = Agent(
|
||||||
model="gemini-2.5-pro",
|
model=GEMINI_PRO_WITH_RETRY,
|
||||||
name="adk_release_analyzer",
|
name="adk_release_analyzer",
|
||||||
description=(
|
description=(
|
||||||
"Analyzes ADK Python releases and generates documentation update"
|
"Analyzes ADK Python releases and generates documentation update"
|
||||||
|
|||||||
@@ -605,6 +605,7 @@ def get_changed_files_summary(
|
|||||||
start_tag: str,
|
start_tag: str,
|
||||||
end_tag: str,
|
end_tag: str,
|
||||||
local_repo_path: Optional[str] = None,
|
local_repo_path: Optional[str] = None,
|
||||||
|
path_filter: Optional[str] = None,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Gets a summary of changed files between two releases without patches.
|
"""Gets a summary of changed files between two releases without patches.
|
||||||
|
|
||||||
@@ -620,6 +621,9 @@ def get_changed_files_summary(
|
|||||||
local_repo_path: Optional absolute path to local git repo. If provided
|
local_repo_path: Optional absolute path to local git repo. If provided
|
||||||
and valid, uses git diff instead of GitHub API to get complete
|
and valid, uses git diff instead of GitHub API to get complete
|
||||||
file list (avoids 300-file limit).
|
file list (avoids 300-file limit).
|
||||||
|
path_filter: Optional path prefix to filter files. Only files whose
|
||||||
|
path starts with this prefix will be included. Example:
|
||||||
|
"src/google/adk/" to only include ADK source files.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A dictionary containing the status and a summary of changed files.
|
A dictionary containing the status and a summary of changed files.
|
||||||
@@ -627,7 +631,7 @@ def get_changed_files_summary(
|
|||||||
# Use local git if valid path is provided (avoids GitHub API 300-file limit)
|
# Use local git if valid path is provided (avoids GitHub API 300-file limit)
|
||||||
if local_repo_path and os.path.isdir(os.path.join(local_repo_path, ".git")):
|
if local_repo_path and os.path.isdir(os.path.join(local_repo_path, ".git")):
|
||||||
return _get_changed_files_from_local_git(
|
return _get_changed_files_from_local_git(
|
||||||
local_repo_path, start_tag, end_tag, repo_owner, repo_name
|
local_repo_path, start_tag, end_tag, repo_owner, repo_name, path_filter
|
||||||
)
|
)
|
||||||
|
|
||||||
# Fall back to GitHub API (limited to 300 files)
|
# Fall back to GitHub API (limited to 300 files)
|
||||||
@@ -689,6 +693,7 @@ def _get_changed_files_from_local_git(
|
|||||||
end_tag: str,
|
end_tag: str,
|
||||||
repo_owner: str,
|
repo_owner: str,
|
||||||
repo_name: str,
|
repo_name: str,
|
||||||
|
path_filter: Optional[str] = None,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Gets changed files using local git commands (no file limit).
|
"""Gets changed files using local git commands (no file limit).
|
||||||
|
|
||||||
@@ -698,6 +703,7 @@ def _get_changed_files_from_local_git(
|
|||||||
end_tag: The newer tag (head) for the comparison.
|
end_tag: The newer tag (head) for the comparison.
|
||||||
repo_owner: Repository owner for compare URL.
|
repo_owner: Repository owner for compare URL.
|
||||||
repo_name: Repository name for compare URL.
|
repo_name: Repository name for compare URL.
|
||||||
|
path_filter: Optional path prefix to filter files.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A dictionary containing the status and a summary of changed files.
|
A dictionary containing the status and a summary of changed files.
|
||||||
@@ -766,6 +772,10 @@ def _get_changed_files_from_local_git(
|
|||||||
status_code = parts[0][0] # First char is the status
|
status_code = parts[0][0] # First char is the status
|
||||||
filename = parts[-1] # Last part is filename (handles renames)
|
filename = parts[-1] # Last part is filename (handles renames)
|
||||||
|
|
||||||
|
# Apply path filter if specified
|
||||||
|
if path_filter and not filename.startswith(path_filter):
|
||||||
|
continue
|
||||||
|
|
||||||
stats = file_stats.get(
|
stats = file_stats.get(
|
||||||
filename,
|
filename,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -701,7 +701,6 @@ def cli_eval(
|
|||||||
separated list of eval names and then add that as a suffix to the eval set
|
separated list of eval names and then add that as a suffix to the eval set
|
||||||
file name, demarcated by a `:`.
|
file name, demarcated by a `:`.
|
||||||
|
|
||||||
\b
|
|
||||||
For example, we have `sample_eval_set_file.json` file that has following the
|
For example, we have `sample_eval_set_file.json` file that has following the
|
||||||
eval cases:
|
eval cases:
|
||||||
sample_eval_set_file.json:
|
sample_eval_set_file.json:
|
||||||
@@ -722,7 +721,6 @@ def cli_eval(
|
|||||||
separated list of eval names and then add that as a suffix to the eval set
|
separated list of eval names and then add that as a suffix to the eval set
|
||||||
file name, demarcated by a `:`.
|
file name, demarcated by a `:`.
|
||||||
|
|
||||||
\b
|
|
||||||
For example, we have `sample_eval_set_id` that has following the eval cases:
|
For example, we have `sample_eval_set_id` that has following the eval cases:
|
||||||
sample_eval_set_id:
|
sample_eval_set_id:
|
||||||
|....... eval_1
|
|....... eval_1
|
||||||
@@ -731,7 +729,6 @@ def cli_eval(
|
|||||||
|....... eval_4
|
|....... eval_4
|
||||||
|....... eval_5
|
|....... eval_5
|
||||||
|
|
||||||
\b
|
|
||||||
If we did:
|
If we did:
|
||||||
sample_eval_set_id:eval_1,eval_2,eval_3
|
sample_eval_set_id:eval_1,eval_2,eval_3
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user