google-adk 0.0.1__py3-none-any.whl → 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google/adk/__init__.py +20 -0
- google/adk/agents/__init__.py +32 -0
- google/adk/agents/active_streaming_tool.py +38 -0
- google/adk/agents/base_agent.py +345 -0
- google/adk/agents/callback_context.py +112 -0
- google/adk/agents/invocation_context.py +181 -0
- google/adk/agents/langgraph_agent.py +140 -0
- google/adk/agents/live_request_queue.py +64 -0
- google/adk/agents/llm_agent.py +376 -0
- google/adk/agents/loop_agent.py +62 -0
- google/adk/agents/parallel_agent.py +96 -0
- google/adk/agents/readonly_context.py +46 -0
- google/adk/agents/remote_agent.py +50 -0
- google/adk/agents/run_config.py +87 -0
- google/adk/agents/sequential_agent.py +45 -0
- google/adk/agents/transcription_entry.py +34 -0
- google/adk/artifacts/__init__.py +23 -0
- google/adk/artifacts/base_artifact_service.py +128 -0
- google/adk/artifacts/gcs_artifact_service.py +195 -0
- google/adk/artifacts/in_memory_artifact_service.py +133 -0
- google/adk/auth/__init__.py +22 -0
- google/adk/auth/auth_credential.py +220 -0
- google/adk/auth/auth_handler.py +268 -0
- google/adk/auth/auth_preprocessor.py +116 -0
- google/adk/auth/auth_schemes.py +67 -0
- google/adk/auth/auth_tool.py +55 -0
- google/adk/cli/__init__.py +15 -0
- google/adk/cli/__main__.py +18 -0
- google/adk/cli/agent_graph.py +122 -0
- google/adk/cli/browser/adk_favicon.svg +17 -0
- google/adk/cli/browser/assets/audio-processor.js +51 -0
- google/adk/cli/browser/assets/config/runtime-config.json +3 -0
- google/adk/cli/browser/index.html +33 -0
- google/adk/cli/browser/main-XUU6OGCC.js +75 -0
- google/adk/cli/browser/polyfills-FFHMD2TL.js +18 -0
- google/adk/cli/browser/styles-4VDSPQ37.css +17 -0
- google/adk/cli/cli.py +181 -0
- google/adk/cli/cli_deploy.py +181 -0
- google/adk/cli/cli_eval.py +282 -0
- google/adk/cli/cli_tools_click.py +479 -0
- google/adk/cli/fast_api.py +774 -0
- google/adk/cli/media_streamer/__init__.py +19 -0
- google/adk/cli/media_streamer/index.html +228 -0
- google/adk/cli/utils/__init__.py +49 -0
- google/adk/cli/utils/envs.py +57 -0
- google/adk/cli/utils/evals.py +93 -0
- google/adk/cli/utils/logs.py +72 -0
- google/adk/code_executors/__init__.py +49 -0
- google/adk/code_executors/base_code_executor.py +97 -0
- google/adk/code_executors/code_execution_utils.py +256 -0
- google/adk/code_executors/code_executor_context.py +202 -0
- google/adk/code_executors/container_code_executor.py +196 -0
- google/adk/code_executors/unsafe_local_code_executor.py +71 -0
- google/adk/code_executors/vertex_ai_code_executor.py +234 -0
- google/adk/evaluation/__init__.py +31 -0
- google/adk/evaluation/agent_evaluator.py +329 -0
- google/adk/evaluation/evaluation_constants.py +24 -0
- google/adk/evaluation/evaluation_generator.py +270 -0
- google/adk/evaluation/response_evaluator.py +135 -0
- google/adk/evaluation/trajectory_evaluator.py +184 -0
- google/adk/events/__init__.py +21 -0
- google/adk/events/event.py +130 -0
- google/adk/events/event_actions.py +55 -0
- google/adk/examples/__init__.py +28 -0
- google/adk/examples/base_example_provider.py +35 -0
- google/adk/examples/example.py +27 -0
- google/adk/examples/example_util.py +123 -0
- google/adk/examples/vertex_ai_example_store.py +104 -0
- google/adk/flows/__init__.py +14 -0
- google/adk/flows/llm_flows/__init__.py +20 -0
- google/adk/flows/llm_flows/_base_llm_processor.py +52 -0
- google/adk/flows/llm_flows/_code_execution.py +458 -0
- google/adk/flows/llm_flows/_nl_planning.py +129 -0
- google/adk/flows/llm_flows/agent_transfer.py +132 -0
- google/adk/flows/llm_flows/audio_transcriber.py +109 -0
- google/adk/flows/llm_flows/auto_flow.py +49 -0
- google/adk/flows/llm_flows/base_llm_flow.py +559 -0
- google/adk/flows/llm_flows/basic.py +72 -0
- google/adk/flows/llm_flows/contents.py +370 -0
- google/adk/flows/llm_flows/functions.py +486 -0
- google/adk/flows/llm_flows/identity.py +47 -0
- google/adk/flows/llm_flows/instructions.py +137 -0
- google/adk/flows/llm_flows/single_flow.py +57 -0
- google/adk/memory/__init__.py +35 -0
- google/adk/memory/base_memory_service.py +74 -0
- google/adk/memory/in_memory_memory_service.py +62 -0
- google/adk/memory/vertex_ai_rag_memory_service.py +177 -0
- google/adk/models/__init__.py +31 -0
- google/adk/models/anthropic_llm.py +243 -0
- google/adk/models/base_llm.py +87 -0
- google/adk/models/base_llm_connection.py +76 -0
- google/adk/models/gemini_llm_connection.py +200 -0
- google/adk/models/google_llm.py +331 -0
- google/adk/models/lite_llm.py +673 -0
- google/adk/models/llm_request.py +98 -0
- google/adk/models/llm_response.py +111 -0
- google/adk/models/registry.py +102 -0
- google/adk/planners/__init__.py +23 -0
- google/adk/planners/base_planner.py +66 -0
- google/adk/planners/built_in_planner.py +75 -0
- google/adk/planners/plan_re_act_planner.py +208 -0
- google/adk/runners.py +456 -0
- google/adk/sessions/__init__.py +41 -0
- google/adk/sessions/base_session_service.py +133 -0
- google/adk/sessions/database_session_service.py +522 -0
- google/adk/sessions/in_memory_session_service.py +206 -0
- google/adk/sessions/session.py +54 -0
- google/adk/sessions/state.py +71 -0
- google/adk/sessions/vertex_ai_session_service.py +356 -0
- google/adk/telemetry.py +189 -0
- google/adk/tests/__init__.py +14 -0
- google/adk/tests/integration/.env.example +10 -0
- google/adk/tests/integration/__init__.py +18 -0
- google/adk/tests/integration/conftest.py +119 -0
- google/adk/tests/integration/fixture/__init__.py +14 -0
- google/adk/tests/integration/fixture/agent_with_config/__init__.py +15 -0
- google/adk/tests/integration/fixture/agent_with_config/agent.py +88 -0
- google/adk/tests/integration/fixture/callback_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/callback_agent/agent.py +105 -0
- google/adk/tests/integration/fixture/context_update_test/OWNERS +1 -0
- google/adk/tests/integration/fixture/context_update_test/__init__.py +15 -0
- google/adk/tests/integration/fixture/context_update_test/agent.py +43 -0
- google/adk/tests/integration/fixture/context_update_test/successful_test.session.json +582 -0
- google/adk/tests/integration/fixture/context_variable_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/context_variable_agent/agent.py +115 -0
- google/adk/tests/integration/fixture/customer_support_ma/__init__.py +15 -0
- google/adk/tests/integration/fixture/customer_support_ma/agent.py +172 -0
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/agent.py +338 -0
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/order_query.test.json +69 -0
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/test_config.json +6 -0
- google/adk/tests/integration/fixture/flow_complex_spark/__init__.py +15 -0
- google/adk/tests/integration/fixture/flow_complex_spark/agent.py +182 -0
- google/adk/tests/integration/fixture/flow_complex_spark/sample.debug.log +243 -0
- google/adk/tests/integration/fixture/flow_complex_spark/sample.session.json +190 -0
- google/adk/tests/integration/fixture/hello_world_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/hello_world_agent/agent.py +95 -0
- google/adk/tests/integration/fixture/hello_world_agent/roll_die.test.json +24 -0
- google/adk/tests/integration/fixture/hello_world_agent/test_config.json +6 -0
- google/adk/tests/integration/fixture/home_automation_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/home_automation_agent/agent.py +304 -0
- google/adk/tests/integration/fixture/home_automation_agent/simple_test.test.json +5 -0
- google/adk/tests/integration/fixture/home_automation_agent/simple_test2.test.json +5 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_config.json +5 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/dependent_tool_calls.test.json +18 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/eval_data.test.json +17 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/test_config.json +6 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_multi_turn_conversation.test.json +18 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test.test.json +17 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test2.test.json +5 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/test_config.json +5 -0
- google/adk/tests/integration/fixture/tool_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/tool_agent/agent.py +218 -0
- google/adk/tests/integration/fixture/tool_agent/files/Agent_test_plan.pdf +0 -0
- google/adk/tests/integration/fixture/trip_planner_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/trip_planner_agent/agent.py +110 -0
- google/adk/tests/integration/fixture/trip_planner_agent/initial.session.json +13 -0
- google/adk/tests/integration/fixture/trip_planner_agent/test_config.json +5 -0
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/initial.session.json +13 -0
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/test_config.json +5 -0
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/trip_inquiry_sub_agent.test.json +7 -0
- google/adk/tests/integration/fixture/trip_planner_agent/trip_inquiry.test.json +19 -0
- google/adk/tests/integration/models/__init__.py +14 -0
- google/adk/tests/integration/models/test_google_llm.py +65 -0
- google/adk/tests/integration/test_callback.py +70 -0
- google/adk/tests/integration/test_context_variable.py +67 -0
- google/adk/tests/integration/test_evalute_agent_in_fixture.py +76 -0
- google/adk/tests/integration/test_multi_agent.py +28 -0
- google/adk/tests/integration/test_multi_turn.py +42 -0
- google/adk/tests/integration/test_single_agent.py +23 -0
- google/adk/tests/integration/test_sub_agent.py +26 -0
- google/adk/tests/integration/test_system_instruction.py +177 -0
- google/adk/tests/integration/test_tools.py +287 -0
- google/adk/tests/integration/test_with_test_file.py +34 -0
- google/adk/tests/integration/tools/__init__.py +14 -0
- google/adk/tests/integration/utils/__init__.py +16 -0
- google/adk/tests/integration/utils/asserts.py +75 -0
- google/adk/tests/integration/utils/test_runner.py +97 -0
- google/adk/tests/unittests/__init__.py +14 -0
- google/adk/tests/unittests/agents/__init__.py +14 -0
- google/adk/tests/unittests/agents/test_base_agent.py +407 -0
- google/adk/tests/unittests/agents/test_langgraph_agent.py +191 -0
- google/adk/tests/unittests/agents/test_llm_agent_callbacks.py +138 -0
- google/adk/tests/unittests/agents/test_llm_agent_fields.py +231 -0
- google/adk/tests/unittests/agents/test_loop_agent.py +136 -0
- google/adk/tests/unittests/agents/test_parallel_agent.py +92 -0
- google/adk/tests/unittests/agents/test_sequential_agent.py +114 -0
- google/adk/tests/unittests/artifacts/__init__.py +14 -0
- google/adk/tests/unittests/artifacts/test_artifact_service.py +276 -0
- google/adk/tests/unittests/auth/test_auth_handler.py +575 -0
- google/adk/tests/unittests/conftest.py +73 -0
- google/adk/tests/unittests/fast_api/__init__.py +14 -0
- google/adk/tests/unittests/fast_api/test_fast_api.py +269 -0
- google/adk/tests/unittests/flows/__init__.py +14 -0
- google/adk/tests/unittests/flows/llm_flows/__init__.py +14 -0
- google/adk/tests/unittests/flows/llm_flows/_test_examples.py +142 -0
- google/adk/tests/unittests/flows/llm_flows/test_agent_transfer.py +311 -0
- google/adk/tests/unittests/flows/llm_flows/test_functions_long_running.py +244 -0
- google/adk/tests/unittests/flows/llm_flows/test_functions_request_euc.py +346 -0
- google/adk/tests/unittests/flows/llm_flows/test_functions_sequential.py +93 -0
- google/adk/tests/unittests/flows/llm_flows/test_functions_simple.py +258 -0
- google/adk/tests/unittests/flows/llm_flows/test_identity.py +66 -0
- google/adk/tests/unittests/flows/llm_flows/test_instructions.py +164 -0
- google/adk/tests/unittests/flows/llm_flows/test_model_callbacks.py +142 -0
- google/adk/tests/unittests/flows/llm_flows/test_other_configs.py +46 -0
- google/adk/tests/unittests/flows/llm_flows/test_tool_callbacks.py +269 -0
- google/adk/tests/unittests/models/__init__.py +14 -0
- google/adk/tests/unittests/models/test_google_llm.py +224 -0
- google/adk/tests/unittests/models/test_litellm.py +804 -0
- google/adk/tests/unittests/models/test_models.py +60 -0
- google/adk/tests/unittests/sessions/__init__.py +14 -0
- google/adk/tests/unittests/sessions/test_session_service.py +227 -0
- google/adk/tests/unittests/sessions/test_vertex_ai_session_service.py +246 -0
- google/adk/tests/unittests/streaming/__init__.py +14 -0
- google/adk/tests/unittests/streaming/test_streaming.py +50 -0
- google/adk/tests/unittests/tools/__init__.py +14 -0
- google/adk/tests/unittests/tools/apihub_tool/clients/test_apihub_client.py +499 -0
- google/adk/tests/unittests/tools/apihub_tool/test_apihub_toolset.py +204 -0
- google/adk/tests/unittests/tools/application_integration_tool/clients/test_connections_client.py +600 -0
- google/adk/tests/unittests/tools/application_integration_tool/clients/test_integration_client.py +630 -0
- google/adk/tests/unittests/tools/application_integration_tool/test_application_integration_toolset.py +345 -0
- google/adk/tests/unittests/tools/google_api_tool/__init__.py +13 -0
- google/adk/tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py +657 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_auto_auth_credential_exchanger.py +145 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_base_auth_credential_exchanger.py +68 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_oauth2_exchanger.py +153 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_service_account_exchanger.py +196 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/test_auth_helper.py +573 -0
- google/adk/tests/unittests/tools/openapi_tool/common/test_common.py +436 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test.yaml +1367 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_spec_parser.py +628 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_toolset.py +139 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_operation_parser.py +406 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_rest_api_tool.py +966 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_tool_auth_handler.py +201 -0
- google/adk/tests/unittests/tools/retrieval/__init__.py +14 -0
- google/adk/tests/unittests/tools/retrieval/test_vertex_ai_rag_retrieval.py +147 -0
- google/adk/tests/unittests/tools/test_agent_tool.py +167 -0
- google/adk/tests/unittests/tools/test_base_tool.py +141 -0
- google/adk/tests/unittests/tools/test_build_function_declaration.py +277 -0
- google/adk/tests/unittests/utils.py +304 -0
- google/adk/tools/__init__.py +51 -0
- google/adk/tools/_automatic_function_calling_util.py +346 -0
- google/adk/tools/agent_tool.py +176 -0
- google/adk/tools/apihub_tool/__init__.py +19 -0
- google/adk/tools/apihub_tool/apihub_toolset.py +209 -0
- google/adk/tools/apihub_tool/clients/__init__.py +13 -0
- google/adk/tools/apihub_tool/clients/apihub_client.py +332 -0
- google/adk/tools/apihub_tool/clients/secret_client.py +115 -0
- google/adk/tools/application_integration_tool/__init__.py +19 -0
- google/adk/tools/application_integration_tool/application_integration_toolset.py +230 -0
- google/adk/tools/application_integration_tool/clients/connections_client.py +903 -0
- google/adk/tools/application_integration_tool/clients/integration_client.py +253 -0
- google/adk/tools/base_tool.py +144 -0
- google/adk/tools/built_in_code_execution_tool.py +59 -0
- google/adk/tools/crewai_tool.py +72 -0
- google/adk/tools/example_tool.py +62 -0
- google/adk/tools/exit_loop_tool.py +23 -0
- google/adk/tools/function_parameter_parse_util.py +307 -0
- google/adk/tools/function_tool.py +87 -0
- google/adk/tools/get_user_choice_tool.py +28 -0
- google/adk/tools/google_api_tool/__init__.py +14 -0
- google/adk/tools/google_api_tool/google_api_tool.py +59 -0
- google/adk/tools/google_api_tool/google_api_tool_set.py +107 -0
- google/adk/tools/google_api_tool/google_api_tool_sets.py +55 -0
- google/adk/tools/google_api_tool/googleapi_to_openapi_converter.py +521 -0
- google/adk/tools/google_search_tool.py +68 -0
- google/adk/tools/langchain_tool.py +86 -0
- google/adk/tools/load_artifacts_tool.py +113 -0
- google/adk/tools/load_memory_tool.py +58 -0
- google/adk/tools/load_web_page.py +41 -0
- google/adk/tools/long_running_tool.py +39 -0
- google/adk/tools/mcp_tool/__init__.py +42 -0
- google/adk/tools/mcp_tool/conversion_utils.py +161 -0
- google/adk/tools/mcp_tool/mcp_tool.py +113 -0
- google/adk/tools/mcp_tool/mcp_toolset.py +272 -0
- google/adk/tools/openapi_tool/__init__.py +21 -0
- google/adk/tools/openapi_tool/auth/__init__.py +19 -0
- google/adk/tools/openapi_tool/auth/auth_helpers.py +498 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/__init__.py +25 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/auto_auth_credential_exchanger.py +105 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/base_credential_exchanger.py +55 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/oauth2_exchanger.py +117 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/service_account_exchanger.py +97 -0
- google/adk/tools/openapi_tool/common/__init__.py +19 -0
- google/adk/tools/openapi_tool/common/common.py +300 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/__init__.py +32 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.py +231 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py +144 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py +260 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +496 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.py +268 -0
- google/adk/tools/preload_memory_tool.py +72 -0
- google/adk/tools/retrieval/__init__.py +36 -0
- google/adk/tools/retrieval/base_retrieval_tool.py +37 -0
- google/adk/tools/retrieval/files_retrieval.py +33 -0
- google/adk/tools/retrieval/llama_index_retrieval.py +41 -0
- google/adk/tools/retrieval/vertex_ai_rag_retrieval.py +107 -0
- google/adk/tools/tool_context.py +90 -0
- google/adk/tools/toolbox_tool.py +46 -0
- google/adk/tools/transfer_to_agent_tool.py +21 -0
- google/adk/tools/vertex_ai_search_tool.py +96 -0
- google/adk/version.py +16 -0
- google_adk-0.0.1.dist-info/LICENSE.txt → google_adk-0.0.2.dist-info/LICENSE +32 -0
- google_adk-0.0.2.dist-info/METADATA +73 -0
- google_adk-0.0.2.dist-info/RECORD +308 -0
- {google_adk-0.0.1.dist-info → google_adk-0.0.2.dist-info}/WHEEL +1 -2
- google_adk-0.0.2.dist-info/entry_points.txt +3 -0
- agent_kit/__init__.py +0 -0
- google_adk-0.0.1.dist-info/METADATA +0 -15
- google_adk-0.0.1.dist-info/RECORD +0 -6
- google_adk-0.0.1.dist-info/top_level.txt +0 -1
@@ -0,0 +1,370 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from __future__ import annotations
|
16
|
+
|
17
|
+
import copy
|
18
|
+
from typing import AsyncGenerator
|
19
|
+
from typing import Generator
|
20
|
+
from typing import Optional
|
21
|
+
|
22
|
+
from google.genai import types
|
23
|
+
from typing_extensions import override
|
24
|
+
|
25
|
+
from ...agents.invocation_context import InvocationContext
|
26
|
+
from ...events.event import Event
|
27
|
+
from ...models.llm_request import LlmRequest
|
28
|
+
from ._base_llm_processor import BaseLlmRequestProcessor
|
29
|
+
from .functions import remove_client_function_call_id
|
30
|
+
|
31
|
+
|
32
|
+
class _ContentLlmRequestProcessor(BaseLlmRequestProcessor):
|
33
|
+
"""Builds the contents for the LLM request."""
|
34
|
+
|
35
|
+
@override
|
36
|
+
async def run_async(
|
37
|
+
self, invocation_context: InvocationContext, llm_request: LlmRequest
|
38
|
+
) -> AsyncGenerator[Event, None]:
|
39
|
+
from ...agents.llm_agent import LlmAgent
|
40
|
+
|
41
|
+
agent = invocation_context.agent
|
42
|
+
if not isinstance(agent, LlmAgent):
|
43
|
+
return
|
44
|
+
|
45
|
+
if agent.include_contents != 'none':
|
46
|
+
llm_request.contents = _get_contents(
|
47
|
+
invocation_context.branch,
|
48
|
+
invocation_context.session.events,
|
49
|
+
agent.name,
|
50
|
+
)
|
51
|
+
|
52
|
+
# Maintain async generator behavior
|
53
|
+
if False: # Ensures it behaves as a generator
|
54
|
+
yield # This is a no-op but maintains generator structure
|
55
|
+
|
56
|
+
|
57
|
+
request_processor = _ContentLlmRequestProcessor()
|
58
|
+
|
59
|
+
|
60
|
+
def _rearrange_events_for_async_function_responses_in_history(
|
61
|
+
events: list[Event],
|
62
|
+
) -> list[Event]:
|
63
|
+
"""Rearrange the async function_response events in the history."""
|
64
|
+
|
65
|
+
function_call_id_to_response_events_index: dict[str, list[Event]] = {}
|
66
|
+
for i, event in enumerate(events):
|
67
|
+
function_responses = event.get_function_responses()
|
68
|
+
if function_responses:
|
69
|
+
for function_response in function_responses:
|
70
|
+
function_call_id = function_response.id
|
71
|
+
function_call_id_to_response_events_index[function_call_id] = i
|
72
|
+
|
73
|
+
result_events: list[Event] = []
|
74
|
+
for event in events:
|
75
|
+
if event.get_function_responses():
|
76
|
+
# function_response should be handled together with function_call below.
|
77
|
+
continue
|
78
|
+
elif event.get_function_calls():
|
79
|
+
|
80
|
+
function_response_events_indices = set()
|
81
|
+
for function_call in event.get_function_calls():
|
82
|
+
function_call_id = function_call.id
|
83
|
+
if function_call_id in function_call_id_to_response_events_index:
|
84
|
+
function_response_events_indices.add(
|
85
|
+
function_call_id_to_response_events_index[function_call_id]
|
86
|
+
)
|
87
|
+
result_events.append(event)
|
88
|
+
if not function_response_events_indices:
|
89
|
+
continue
|
90
|
+
if len(function_response_events_indices) == 1:
|
91
|
+
result_events.append(
|
92
|
+
events[next(iter(function_response_events_indices))]
|
93
|
+
)
|
94
|
+
else: # Merge all async function_response as one response event
|
95
|
+
result_events.append(
|
96
|
+
_merge_function_response_events(
|
97
|
+
[events[i] for i in sorted(function_response_events_indices)]
|
98
|
+
)
|
99
|
+
)
|
100
|
+
continue
|
101
|
+
else:
|
102
|
+
result_events.append(event)
|
103
|
+
|
104
|
+
return result_events
|
105
|
+
|
106
|
+
|
107
|
+
def _rearrange_events_for_latest_function_response(
|
108
|
+
events: list[Event],
|
109
|
+
) -> list[Event]:
|
110
|
+
"""Rearrange the events for the latest function_response.
|
111
|
+
|
112
|
+
If the latest function_response is for an async function_call, all events
|
113
|
+
bewteen the initial function_call and the latest function_response will be
|
114
|
+
removed.
|
115
|
+
|
116
|
+
Args:
|
117
|
+
events: A list of events.
|
118
|
+
|
119
|
+
Returns:
|
120
|
+
A list of events with the latest function_response rearranged.
|
121
|
+
"""
|
122
|
+
if not events:
|
123
|
+
return events
|
124
|
+
|
125
|
+
function_responses = events[-1].get_function_responses()
|
126
|
+
if not function_responses:
|
127
|
+
# No need to process, since the latest event is not fuction_response.
|
128
|
+
return events
|
129
|
+
|
130
|
+
function_responses_ids = set()
|
131
|
+
for function_response in function_responses:
|
132
|
+
function_responses_ids.add(function_response.id)
|
133
|
+
|
134
|
+
function_calls = events[-2].get_function_calls()
|
135
|
+
|
136
|
+
if function_calls:
|
137
|
+
for function_call in function_calls:
|
138
|
+
# The latest function_response is already matched
|
139
|
+
if function_call.id in function_responses_ids:
|
140
|
+
return events
|
141
|
+
|
142
|
+
function_call_event_idx = -1
|
143
|
+
# look for corresponding function call event reversely
|
144
|
+
for idx in range(len(events) - 2, -1, -1):
|
145
|
+
event = events[idx]
|
146
|
+
function_calls = event.get_function_calls()
|
147
|
+
if function_calls:
|
148
|
+
for function_call in function_calls:
|
149
|
+
if function_call.id in function_responses_ids:
|
150
|
+
function_call_event_idx = idx
|
151
|
+
break
|
152
|
+
if function_call_event_idx != -1:
|
153
|
+
# in case the last response event only have part of the responses
|
154
|
+
# for the function calls in the function call event
|
155
|
+
for function_call in function_calls:
|
156
|
+
function_responses_ids.add(function_call.id)
|
157
|
+
break
|
158
|
+
|
159
|
+
if function_call_event_idx == -1:
|
160
|
+
raise ValueError(
|
161
|
+
'No function call event found for function responses ids:'
|
162
|
+
f' {function_responses_ids}'
|
163
|
+
)
|
164
|
+
|
165
|
+
# collect all function response between last function response event
|
166
|
+
# and function call event
|
167
|
+
|
168
|
+
function_response_events: list[Event] = []
|
169
|
+
for idx in range(function_call_event_idx + 1, len(events) - 1):
|
170
|
+
event = events[idx]
|
171
|
+
function_responses = event.get_function_responses()
|
172
|
+
if (
|
173
|
+
function_responses
|
174
|
+
and function_responses[0].id in function_responses_ids
|
175
|
+
):
|
176
|
+
function_response_events.append(event)
|
177
|
+
function_response_events.append(events[-1])
|
178
|
+
|
179
|
+
result_events = events[: function_call_event_idx + 1]
|
180
|
+
result_events.append(
|
181
|
+
_merge_function_response_events(function_response_events)
|
182
|
+
)
|
183
|
+
|
184
|
+
return result_events
|
185
|
+
|
186
|
+
|
187
|
+
def _get_contents(
|
188
|
+
current_branch: Optional[str], events: list[Event], agent_name: str = ''
|
189
|
+
) -> list[types.Content]:
|
190
|
+
"""Get the contents for the LLM request.
|
191
|
+
|
192
|
+
Args:
|
193
|
+
current_branch: The current branch of the agent.
|
194
|
+
events: A list of events.
|
195
|
+
agent_name: The name of the agent.
|
196
|
+
|
197
|
+
Returns:
|
198
|
+
A list of contents.
|
199
|
+
"""
|
200
|
+
filtered_events = []
|
201
|
+
# Parse the events, leaving the contents and the function calls and
|
202
|
+
# responses from the current agent.
|
203
|
+
for event in events:
|
204
|
+
if not event.content or not event.content.role:
|
205
|
+
# Skip events without content, or generated neither by user nor by model.
|
206
|
+
# E.g. events purely for mutating session states.
|
207
|
+
continue
|
208
|
+
if not _is_event_belongs_to_branch(current_branch, event):
|
209
|
+
# Skip events not belong to current branch.
|
210
|
+
continue
|
211
|
+
|
212
|
+
filtered_events.append(
|
213
|
+
_convert_foreign_event(event)
|
214
|
+
if _is_other_agent_reply(agent_name, event)
|
215
|
+
else event
|
216
|
+
)
|
217
|
+
|
218
|
+
result_events = _rearrange_events_for_latest_function_response(
|
219
|
+
filtered_events
|
220
|
+
)
|
221
|
+
result_events = _rearrange_events_for_async_function_responses_in_history(
|
222
|
+
result_events
|
223
|
+
)
|
224
|
+
contents = []
|
225
|
+
for event in result_events:
|
226
|
+
content = copy.deepcopy(event.content)
|
227
|
+
remove_client_function_call_id(content)
|
228
|
+
contents.append(content)
|
229
|
+
return contents
|
230
|
+
|
231
|
+
|
232
|
+
def _is_other_agent_reply(current_agent_name: str, event: Event) -> bool:
|
233
|
+
"""Whether the event is a reply from another agent."""
|
234
|
+
return bool(
|
235
|
+
current_agent_name
|
236
|
+
and event.author != current_agent_name
|
237
|
+
and event.author != 'user'
|
238
|
+
)
|
239
|
+
|
240
|
+
|
241
|
+
def _convert_foreign_event(event: Event) -> Event:
|
242
|
+
"""Converts an event authored by another agent as a user-content event.
|
243
|
+
|
244
|
+
This is to provide another agent's output as context to the current agent, so
|
245
|
+
that current agent can continue to respond, such as summarizing previous
|
246
|
+
agent's reply, etc.
|
247
|
+
|
248
|
+
Args:
|
249
|
+
event: The event to convert.
|
250
|
+
|
251
|
+
Returns:
|
252
|
+
The converted event.
|
253
|
+
|
254
|
+
"""
|
255
|
+
if not event.content or not event.content.parts:
|
256
|
+
return event
|
257
|
+
|
258
|
+
content = types.Content()
|
259
|
+
content.role = 'user'
|
260
|
+
content.parts = [types.Part(text='For context:')]
|
261
|
+
for part in event.content.parts:
|
262
|
+
if part.text:
|
263
|
+
content.parts.append(
|
264
|
+
types.Part(text=f'[{event.author}] said: {part.text}')
|
265
|
+
)
|
266
|
+
elif part.function_call:
|
267
|
+
content.parts.append(
|
268
|
+
types.Part(
|
269
|
+
text=(
|
270
|
+
f'[{event.author}] called tool `{part.function_call.name}`'
|
271
|
+
f' with parameters: {part.function_call.args}'
|
272
|
+
)
|
273
|
+
)
|
274
|
+
)
|
275
|
+
elif part.function_response:
|
276
|
+
# Otherwise, create a new text part.
|
277
|
+
content.parts.append(
|
278
|
+
types.Part(
|
279
|
+
text=(
|
280
|
+
f'[{event.author}] `{part.function_response.name}` tool'
|
281
|
+
f' returned result: {part.function_response.response}'
|
282
|
+
)
|
283
|
+
)
|
284
|
+
)
|
285
|
+
# Fallback to the original part for non-text and non-functionCall parts.
|
286
|
+
else:
|
287
|
+
content.parts.append(part)
|
288
|
+
|
289
|
+
return Event(
|
290
|
+
timestamp=event.timestamp,
|
291
|
+
author='user',
|
292
|
+
content=content,
|
293
|
+
branch=event.branch,
|
294
|
+
)
|
295
|
+
|
296
|
+
|
297
|
+
def _merge_function_response_events(
|
298
|
+
function_response_events: list[Event],
|
299
|
+
) -> Event:
|
300
|
+
"""Merges a list of function_response events into one event.
|
301
|
+
|
302
|
+
The key goal is to ensure:
|
303
|
+
1. function_call and function_response are always of the same number.
|
304
|
+
2. The function_call and function_response are consecutively in the content.
|
305
|
+
|
306
|
+
Args:
|
307
|
+
function_response_events: A list of function_response events.
|
308
|
+
NOTE: function_response_events must fulfill these requirements: 1. The
|
309
|
+
list is in increasing order of timestamp; 2. the first event is the
|
310
|
+
initial function_reponse event; 3. all later events should contain at
|
311
|
+
least one function_response part that related to the function_call
|
312
|
+
event. (Note, 3. may not be true when aync function return some
|
313
|
+
intermediate response, there could also be some intermediate model
|
314
|
+
response event without any function_response and such event will be
|
315
|
+
ignored.)
|
316
|
+
Caveat: This implementation doesn't support when a parallel function_call
|
317
|
+
event contains async function_call of the same name.
|
318
|
+
|
319
|
+
Returns:
|
320
|
+
A merged event, that is
|
321
|
+
1. All later function_response will replace function_response part in
|
322
|
+
the initial function_response event.
|
323
|
+
2. All non-function_response parts will be appended to the part list of
|
324
|
+
the initial function_response event.
|
325
|
+
"""
|
326
|
+
if not function_response_events:
|
327
|
+
raise ValueError('At least one function_response event is required.')
|
328
|
+
|
329
|
+
merged_event = function_response_events[0].model_copy(deep=True)
|
330
|
+
parts_in_merged_event: list[types.Part] = merged_event.content.parts # type: ignore
|
331
|
+
|
332
|
+
if not parts_in_merged_event:
|
333
|
+
raise ValueError('There should be at least one function_response part.')
|
334
|
+
|
335
|
+
part_indices_in_merged_event: dict[str, int] = {}
|
336
|
+
for idx, part in enumerate(parts_in_merged_event):
|
337
|
+
if part.function_response:
|
338
|
+
function_call_id: str = part.function_response.id # type: ignore
|
339
|
+
part_indices_in_merged_event[function_call_id] = idx
|
340
|
+
|
341
|
+
for event in function_response_events[1:]:
|
342
|
+
if not event.content.parts:
|
343
|
+
raise ValueError('There should be at least one function_response part.')
|
344
|
+
|
345
|
+
for part in event.content.parts:
|
346
|
+
if part.function_response:
|
347
|
+
function_call_id: str = part.function_response.id # type: ignore
|
348
|
+
if function_call_id in part_indices_in_merged_event:
|
349
|
+
parts_in_merged_event[
|
350
|
+
part_indices_in_merged_event[function_call_id]
|
351
|
+
] = part
|
352
|
+
else:
|
353
|
+
parts_in_merged_event.append(part)
|
354
|
+
part_indices_in_merged_event[function_call_id] = (
|
355
|
+
len(parts_in_merged_event) - 1
|
356
|
+
)
|
357
|
+
|
358
|
+
else:
|
359
|
+
parts_in_merged_event.append(part)
|
360
|
+
|
361
|
+
return merged_event
|
362
|
+
|
363
|
+
|
364
|
+
def _is_event_belongs_to_branch(
|
365
|
+
invocation_branch: Optional[str], event: Event
|
366
|
+
) -> bool:
|
367
|
+
"""Event belongs to a branch, when event.branch is prefix of the invocation branch."""
|
368
|
+
if not invocation_branch or not event.branch:
|
369
|
+
return True
|
370
|
+
return invocation_branch.startswith(event.branch)
|