aip-agents-binary 0.5.20__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.
- aip_agents/__init__.py +65 -0
- aip_agents/a2a/__init__.py +19 -0
- aip_agents/a2a/server/__init__.py +10 -0
- aip_agents/a2a/server/base_executor.py +1086 -0
- aip_agents/a2a/server/google_adk_executor.py +198 -0
- aip_agents/a2a/server/langflow_executor.py +180 -0
- aip_agents/a2a/server/langgraph_executor.py +270 -0
- aip_agents/a2a/types.py +232 -0
- aip_agents/agent/__init__.py +27 -0
- aip_agents/agent/base_agent.py +970 -0
- aip_agents/agent/base_langgraph_agent.py +2942 -0
- aip_agents/agent/google_adk_agent.py +926 -0
- aip_agents/agent/google_adk_constants.py +6 -0
- aip_agents/agent/hitl/__init__.py +24 -0
- aip_agents/agent/hitl/config.py +28 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
- aip_agents/agent/hitl/manager.py +532 -0
- aip_agents/agent/hitl/models.py +18 -0
- aip_agents/agent/hitl/prompt/__init__.py +9 -0
- aip_agents/agent/hitl/prompt/base.py +42 -0
- aip_agents/agent/hitl/prompt/deferred.py +73 -0
- aip_agents/agent/hitl/registry.py +149 -0
- aip_agents/agent/interface.py +138 -0
- aip_agents/agent/interfaces.py +65 -0
- aip_agents/agent/langflow_agent.py +464 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.py +433 -0
- aip_agents/agent/langgraph_react_agent.py +2514 -0
- aip_agents/agent/system_instruction_context.py +34 -0
- aip_agents/clients/__init__.py +10 -0
- aip_agents/clients/langflow/__init__.py +10 -0
- aip_agents/clients/langflow/client.py +477 -0
- aip_agents/clients/langflow/types.py +18 -0
- aip_agents/constants.py +23 -0
- aip_agents/credentials/manager.py +132 -0
- aip_agents/examples/__init__.py +5 -0
- aip_agents/examples/compare_streaming_client.py +783 -0
- aip_agents/examples/compare_streaming_server.py +142 -0
- aip_agents/examples/demo_memory_recall.py +401 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
- aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
- aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
- aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
- aip_agents/examples/hello_world_google_adk.py +41 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_stream.py +44 -0
- aip_agents/examples/hello_world_langchain.py +28 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
- aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
- aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
- aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
- aip_agents/examples/hello_world_langchain_stream.py +36 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
- aip_agents/examples/hello_world_langflow_agent.py +163 -0
- aip_agents/examples/hello_world_langgraph.py +39 -0
- aip_agents/examples/hello_world_langgraph_bosa_twitter.py +41 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_stream.py +43 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_model_switch_cli.py +210 -0
- aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
- aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
- aip_agents/examples/hello_world_pii_logger.py +21 -0
- aip_agents/examples/hello_world_sentry.py +133 -0
- aip_agents/examples/hello_world_step_limits.py +273 -0
- aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
- aip_agents/examples/hello_world_tool_output_client.py +46 -0
- aip_agents/examples/hello_world_tool_output_server.py +114 -0
- aip_agents/examples/hitl_demo.py +724 -0
- aip_agents/examples/mcp_configs/configs.py +63 -0
- aip_agents/examples/mcp_servers/common.py +76 -0
- aip_agents/examples/mcp_servers/mcp_name.py +29 -0
- aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
- aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
- aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
- aip_agents/examples/mcp_servers/mcp_time.py +10 -0
- aip_agents/examples/pii_demo_langgraph_client.py +69 -0
- aip_agents/examples/pii_demo_langgraph_server.py +126 -0
- aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
- aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
- aip_agents/examples/tools/__init__.py +27 -0
- aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
- aip_agents/examples/tools/adk_weather_tool.py +60 -0
- aip_agents/examples/tools/data_generator_tool.py +103 -0
- aip_agents/examples/tools/data_visualization_tool.py +312 -0
- aip_agents/examples/tools/image_artifact_tool.py +136 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
- aip_agents/examples/tools/langchain_weather_tool.py +48 -0
- aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
- aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
- aip_agents/examples/tools/pii_demo_tools.py +189 -0
- aip_agents/examples/tools/random_chart_tool.py +142 -0
- aip_agents/examples/tools/serper_tool.py +202 -0
- aip_agents/examples/tools/stock_tools.py +82 -0
- aip_agents/examples/tools/table_generator_tool.py +167 -0
- aip_agents/examples/tools/time_tool.py +82 -0
- aip_agents/examples/tools/weather_forecast_tool.py +38 -0
- aip_agents/executor/agent_executor.py +473 -0
- aip_agents/executor/base.py +48 -0
- aip_agents/mcp/__init__.py +1 -0
- aip_agents/mcp/client/__init__.py +14 -0
- aip_agents/mcp/client/base_mcp_client.py +369 -0
- aip_agents/mcp/client/connection_manager.py +193 -0
- aip_agents/mcp/client/google_adk/__init__.py +11 -0
- aip_agents/mcp/client/google_adk/client.py +381 -0
- aip_agents/mcp/client/langchain/__init__.py +11 -0
- aip_agents/mcp/client/langchain/client.py +265 -0
- aip_agents/mcp/client/persistent_session.py +359 -0
- aip_agents/mcp/client/session_pool.py +351 -0
- aip_agents/mcp/client/transports.py +215 -0
- aip_agents/mcp/utils/__init__.py +7 -0
- aip_agents/mcp/utils/config_validator.py +139 -0
- aip_agents/memory/__init__.py +14 -0
- aip_agents/memory/adapters/__init__.py +10 -0
- aip_agents/memory/adapters/base_adapter.py +717 -0
- aip_agents/memory/adapters/mem0.py +84 -0
- aip_agents/memory/base.py +84 -0
- aip_agents/memory/constants.py +49 -0
- aip_agents/memory/factory.py +86 -0
- aip_agents/memory/guidance.py +20 -0
- aip_agents/memory/simple_memory.py +47 -0
- aip_agents/middleware/__init__.py +17 -0
- aip_agents/middleware/base.py +88 -0
- aip_agents/middleware/manager.py +128 -0
- aip_agents/middleware/todolist.py +274 -0
- aip_agents/schema/__init__.py +69 -0
- aip_agents/schema/a2a.py +56 -0
- aip_agents/schema/agent.py +111 -0
- aip_agents/schema/hitl.py +157 -0
- aip_agents/schema/langgraph.py +37 -0
- aip_agents/schema/model_id.py +97 -0
- aip_agents/schema/step_limit.py +108 -0
- aip_agents/schema/storage.py +40 -0
- aip_agents/sentry/__init__.py +11 -0
- aip_agents/sentry/sentry.py +151 -0
- aip_agents/storage/__init__.py +41 -0
- aip_agents/storage/base.py +85 -0
- aip_agents/storage/clients/__init__.py +12 -0
- aip_agents/storage/clients/minio_client.py +318 -0
- aip_agents/storage/config.py +62 -0
- aip_agents/storage/providers/__init__.py +15 -0
- aip_agents/storage/providers/base.py +106 -0
- aip_agents/storage/providers/memory.py +114 -0
- aip_agents/storage/providers/object_storage.py +214 -0
- aip_agents/tools/__init__.py +33 -0
- aip_agents/tools/bosa_tools.py +105 -0
- aip_agents/tools/browser_use/__init__.py +82 -0
- aip_agents/tools/browser_use/action_parser.py +103 -0
- aip_agents/tools/browser_use/browser_use_tool.py +1112 -0
- aip_agents/tools/browser_use/llm_config.py +120 -0
- aip_agents/tools/browser_use/minio_storage.py +198 -0
- aip_agents/tools/browser_use/schemas.py +119 -0
- aip_agents/tools/browser_use/session.py +76 -0
- aip_agents/tools/browser_use/session_errors.py +132 -0
- aip_agents/tools/browser_use/steel_session_recording.py +317 -0
- aip_agents/tools/browser_use/streaming.py +813 -0
- aip_agents/tools/browser_use/structured_data_parser.py +257 -0
- aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
- aip_agents/tools/browser_use/types.py +78 -0
- aip_agents/tools/code_sandbox/__init__.py +26 -0
- aip_agents/tools/code_sandbox/constant.py +13 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +257 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
- aip_agents/tools/constants.py +165 -0
- aip_agents/tools/document_loader/__init__.py +44 -0
- aip_agents/tools/document_loader/base_reader.py +302 -0
- aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
- aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
- aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
- aip_agents/tools/document_loader/pdf_splitter.py +169 -0
- aip_agents/tools/gl_connector/__init__.py +5 -0
- aip_agents/tools/gl_connector/tool.py +351 -0
- aip_agents/tools/memory_search/__init__.py +22 -0
- aip_agents/tools/memory_search/base.py +200 -0
- aip_agents/tools/memory_search/mem0.py +258 -0
- aip_agents/tools/memory_search/schema.py +48 -0
- aip_agents/tools/memory_search_tool.py +26 -0
- aip_agents/tools/time_tool.py +117 -0
- aip_agents/tools/tool_config_injector.py +300 -0
- aip_agents/tools/web_search/__init__.py +15 -0
- aip_agents/tools/web_search/serper_tool.py +187 -0
- aip_agents/types/__init__.py +70 -0
- aip_agents/types/a2a_events.py +13 -0
- aip_agents/utils/__init__.py +79 -0
- aip_agents/utils/a2a_connector.py +1757 -0
- aip_agents/utils/artifact_helpers.py +502 -0
- aip_agents/utils/constants.py +22 -0
- aip_agents/utils/datetime/__init__.py +34 -0
- aip_agents/utils/datetime/normalization.py +231 -0
- aip_agents/utils/datetime/timezone.py +206 -0
- aip_agents/utils/env_loader.py +27 -0
- aip_agents/utils/event_handler_registry.py +58 -0
- aip_agents/utils/file_prompt_utils.py +176 -0
- aip_agents/utils/final_response_builder.py +211 -0
- aip_agents/utils/formatter_llm_client.py +231 -0
- aip_agents/utils/langgraph/__init__.py +19 -0
- aip_agents/utils/langgraph/converter.py +128 -0
- aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
- aip_agents/utils/langgraph/tool_output_management.py +967 -0
- aip_agents/utils/logger.py +195 -0
- aip_agents/utils/metadata/__init__.py +27 -0
- aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
- aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
- aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
- aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
- aip_agents/utils/metadata/activity_narrative/context.py +49 -0
- aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
- aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
- aip_agents/utils/metadata/schemas/__init__.py +16 -0
- aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
- aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
- aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
- aip_agents/utils/metadata_helper.py +358 -0
- aip_agents/utils/name_preprocessor/__init__.py +17 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
- aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
- aip_agents/utils/pii/__init__.py +25 -0
- aip_agents/utils/pii/pii_handler.py +397 -0
- aip_agents/utils/pii/pii_helper.py +207 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
- aip_agents/utils/reference_helper.py +273 -0
- aip_agents/utils/sse_chunk_transformer.py +831 -0
- aip_agents/utils/step_limit_manager.py +265 -0
- aip_agents/utils/token_usage_helper.py +156 -0
- aip_agents_binary-0.5.20.dist-info/METADATA +681 -0
- aip_agents_binary-0.5.20.dist-info/RECORD +280 -0
- aip_agents_binary-0.5.20.dist-info/WHEEL +5 -0
- aip_agents_binary-0.5.20.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""A2A server with artifact and reference tools for streaming comparison tests.
|
|
2
|
+
|
|
3
|
+
This server provides an agent with:
|
|
4
|
+
- table_generator tool: Returns artifacts (CSV files)
|
|
5
|
+
- mock_retrieval tool: Returns references
|
|
6
|
+
|
|
7
|
+
To run this server:
|
|
8
|
+
cd libs/aip_agents
|
|
9
|
+
poetry run python -m aip_agents.examples.compare_streaming_server
|
|
10
|
+
|
|
11
|
+
It will listen on http://localhost:18999 by default.
|
|
12
|
+
|
|
13
|
+
Authors:
|
|
14
|
+
AI Agent Platform Team
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import click
|
|
18
|
+
import uvicorn
|
|
19
|
+
from a2a.types import AgentCapabilities, AgentCard, AgentSkill
|
|
20
|
+
from langchain_openai import ChatOpenAI
|
|
21
|
+
|
|
22
|
+
from aip_agents.agent import LangGraphAgent
|
|
23
|
+
from aip_agents.examples.tools.mock_retrieval_tool import MockRetrievalTool
|
|
24
|
+
from aip_agents.examples.tools.pii_demo_tools import (
|
|
25
|
+
get_customer_info,
|
|
26
|
+
get_employee_data,
|
|
27
|
+
get_user_profile,
|
|
28
|
+
)
|
|
29
|
+
from aip_agents.examples.tools.random_chart_tool import RandomChartTool
|
|
30
|
+
from aip_agents.examples.tools.table_generator_tool import TableGeneratorTool
|
|
31
|
+
from aip_agents.utils.logger import get_logger
|
|
32
|
+
|
|
33
|
+
logger = get_logger(__name__)
|
|
34
|
+
|
|
35
|
+
SERVER_AGENT_NAME = "StreamingComparisonAgent"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@click.command()
|
|
39
|
+
@click.option("--host", "host", default="localhost", help="Host to bind the server to.")
|
|
40
|
+
@click.option("--port", "port", default=18999, help="Port to bind the server to.")
|
|
41
|
+
def main(host: str, port: int):
|
|
42
|
+
"""Runs the streaming comparison A2A server.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
host: Host to bind the server to.
|
|
46
|
+
port: Port to bind the server to.
|
|
47
|
+
"""
|
|
48
|
+
print(f"Starting {SERVER_AGENT_NAME} on http://{host}:{port}")
|
|
49
|
+
|
|
50
|
+
agent_card = AgentCard(
|
|
51
|
+
name=SERVER_AGENT_NAME,
|
|
52
|
+
description="Agent for comparing direct vs connector streaming with artifacts and references.",
|
|
53
|
+
url=f"http://{host}:{port}",
|
|
54
|
+
version="1.0.0",
|
|
55
|
+
defaultInputModes=["text"],
|
|
56
|
+
defaultOutputModes=["text"],
|
|
57
|
+
capabilities=AgentCapabilities(streaming=True),
|
|
58
|
+
skills=[
|
|
59
|
+
AgentSkill(
|
|
60
|
+
id="table_generation",
|
|
61
|
+
name="Table Generation",
|
|
62
|
+
description="Generates data tables as CSV artifacts.",
|
|
63
|
+
examples=["Generate a table with 3 rows"],
|
|
64
|
+
tags=["table", "artifact"],
|
|
65
|
+
),
|
|
66
|
+
AgentSkill(
|
|
67
|
+
id="mock_retrieval",
|
|
68
|
+
name="Mock Retrieval",
|
|
69
|
+
description="Retrieves mock data with references.",
|
|
70
|
+
examples=["Search for test data"],
|
|
71
|
+
tags=["retrieval", "references"],
|
|
72
|
+
),
|
|
73
|
+
AgentSkill(
|
|
74
|
+
id="customer_info",
|
|
75
|
+
name="Get Customer Information",
|
|
76
|
+
description="Retrieves customer information including email and phone number (PII masked).",
|
|
77
|
+
examples=["Get customer info for C001", "What is the email for customer C002?"],
|
|
78
|
+
tags=["customer", "pii"],
|
|
79
|
+
),
|
|
80
|
+
AgentSkill(
|
|
81
|
+
id="employee_data",
|
|
82
|
+
name="Get Employee Data",
|
|
83
|
+
description="Retrieves employee data including name, email, and salary (PII masked).",
|
|
84
|
+
examples=["Get employee data for E001", "What is the salary for employee E002?"],
|
|
85
|
+
tags=["employee", "pii"],
|
|
86
|
+
),
|
|
87
|
+
AgentSkill(
|
|
88
|
+
id="user_profile",
|
|
89
|
+
name="Get User Profile",
|
|
90
|
+
description="Retrieves user profile information with personal details (PII masked).",
|
|
91
|
+
examples=["Get user profile for U001", "What is the email for user U002?"],
|
|
92
|
+
tags=["user", "pii"],
|
|
93
|
+
),
|
|
94
|
+
],
|
|
95
|
+
tags=["test", "comparison", "artifacts", "references", "pii"],
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Token streaming disabled for now - will compare token streaming later
|
|
99
|
+
llm = ChatOpenAI(model="gpt-4.1", temperature=0, streaming=False)
|
|
100
|
+
table_tool = TableGeneratorTool()
|
|
101
|
+
mock_retrieval_tool = MockRetrievalTool()
|
|
102
|
+
random_chart_tool = RandomChartTool()
|
|
103
|
+
tools = [table_tool, mock_retrieval_tool, get_customer_info, get_employee_data, get_user_profile]
|
|
104
|
+
|
|
105
|
+
visualization_agent = LangGraphAgent(
|
|
106
|
+
name="RandomChartAgent",
|
|
107
|
+
instruction=(
|
|
108
|
+
"You are a visualization specialist. Whenever asked to produce a chart, visualization, or images "
|
|
109
|
+
"that summarize insights, call the random_chart_tool to generate a bar chart artifact. "
|
|
110
|
+
"Describe what the generated image represents."
|
|
111
|
+
),
|
|
112
|
+
model=llm,
|
|
113
|
+
tools=[random_chart_tool],
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
agent = LangGraphAgent(
|
|
117
|
+
name=SERVER_AGENT_NAME,
|
|
118
|
+
instruction=(
|
|
119
|
+
"You are a helpful assistant for testing streaming comparison. "
|
|
120
|
+
"When asked for a table, use the table_generator tool. "
|
|
121
|
+
"When asked to search or retrieve, use the mock_retrieval tool. "
|
|
122
|
+
"When asked for customer information, use the get_customer_info tool. "
|
|
123
|
+
"When asked for employee data, use the get_employee_data tool. "
|
|
124
|
+
"When asked for user profile, use the get_user_profile tool. "
|
|
125
|
+
"IMPORTANT: When you receive PII placeholders like <PERSON_1>, pass them WITH the angle brackets <> "
|
|
126
|
+
"to the tools - they are required for the PII system to work correctly. "
|
|
127
|
+
"Always use the tools when relevant to demonstrate artifacts, references, and PII masking."
|
|
128
|
+
),
|
|
129
|
+
model=llm,
|
|
130
|
+
tools=tools,
|
|
131
|
+
enable_a2a_token_streaming=False,
|
|
132
|
+
agents=[visualization_agent],
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
app = agent.to_a2a(agent_card=agent_card)
|
|
136
|
+
|
|
137
|
+
print("A2A application configured. Starting Uvicorn server...")
|
|
138
|
+
uvicorn.run(app, host=host, port=port)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
main()
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
"""Demo memory recall scenarios for demo@glair user data.
|
|
2
|
+
|
|
3
|
+
This script tests the exact scenarios mentioned by the user:
|
|
4
|
+
1. Recall memory by query semantically (without time period)
|
|
5
|
+
2. Recall memory by query semantically AND with time period
|
|
6
|
+
3. Recall memory by date (without query semantic)
|
|
7
|
+
4. Recall memory from last week (calendar week period)
|
|
8
|
+
5. General knowledge questions (to verify responses are not inappropriately grounded in personal memory)
|
|
9
|
+
|
|
10
|
+
These tests are designed to work with the demo@glair user data
|
|
11
|
+
from September 17-24, 2025.
|
|
12
|
+
|
|
13
|
+
Note: Uses a single reused LangGraphAgent instance across all scenarios
|
|
14
|
+
to avoid reinitialization. Model set to openai/gpt-4.1.
|
|
15
|
+
The base LangGraphAgent automatically registers the memory search tool
|
|
16
|
+
and adds memory recall guidance to the system instruction when memory_backend="mem0".
|
|
17
|
+
|
|
18
|
+
Evaluation: instead of keyword checks, we use a dedicated
|
|
19
|
+
"Judge LLM" (memoryless) to classify the agent's answer as grounded in
|
|
20
|
+
fetched memory vs likely hallucination.
|
|
21
|
+
|
|
22
|
+
Authors:
|
|
23
|
+
Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
import asyncio
|
|
27
|
+
import json
|
|
28
|
+
import os
|
|
29
|
+
from datetime import datetime
|
|
30
|
+
|
|
31
|
+
from dotenv import load_dotenv
|
|
32
|
+
from langchain_core.messages import HumanMessage
|
|
33
|
+
|
|
34
|
+
from aip_agents.agent import LangGraphAgent
|
|
35
|
+
|
|
36
|
+
load_dotenv()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class MemoryTestResult:
|
|
40
|
+
"""Container for test scenario results."""
|
|
41
|
+
|
|
42
|
+
JUDGE_SUCCESS_THRESHOLD = 0.7
|
|
43
|
+
MEMORY_DISPLAY_LIMIT = 300
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self, scenario_name: str, query: str, response: str = None, memory_fetched: str = None, error: str = None
|
|
47
|
+
) -> None:
|
|
48
|
+
"""Initialize a memory test result.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
scenario_name: Name of the test scenario.
|
|
52
|
+
query: The input query for the scenario.
|
|
53
|
+
response: The agent's response (optional).
|
|
54
|
+
memory_fetched: The raw memory retrieved from the tool (optional).
|
|
55
|
+
error: Any error message (optional).
|
|
56
|
+
"""
|
|
57
|
+
self.scenario_name = scenario_name
|
|
58
|
+
self.query = query
|
|
59
|
+
self.response = response
|
|
60
|
+
self.memory_fetched = memory_fetched
|
|
61
|
+
self.error = error
|
|
62
|
+
self.success = error is None
|
|
63
|
+
# Judge outputs
|
|
64
|
+
self.judge_verdict = None # "grounded" | "hallucination" | "general_knowledge"
|
|
65
|
+
self.judge_score = None # float 0..1
|
|
66
|
+
|
|
67
|
+
def set_success_from_judge(self, verdict: str, score: float | None):
|
|
68
|
+
"""Set success using judge verdict and confidence score.
|
|
69
|
+
|
|
70
|
+
Success criteria: (verdict == "grounded" or verdict == "general_knowledge") and
|
|
71
|
+
score >= JUDGE_SUCCESS_THRESHOLD.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
verdict (str): The judge's verdict ("grounded", "hallucination", or "general_knowledge").
|
|
75
|
+
score (float | None): The confidence score (0.0 to 1.0).
|
|
76
|
+
"""
|
|
77
|
+
if self.error or not self.response or verdict is None:
|
|
78
|
+
self.success = False
|
|
79
|
+
return
|
|
80
|
+
try:
|
|
81
|
+
self.success = (verdict.lower() in ["grounded", "general_knowledge"]) and (
|
|
82
|
+
score is not None and float(score) >= self.JUDGE_SUCCESS_THRESHOLD
|
|
83
|
+
)
|
|
84
|
+
except Exception:
|
|
85
|
+
self.success = False
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _print_memory_summary(memory_fetched: str):
|
|
89
|
+
"""Print memory with truncation.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
memory_fetched (str): The memory content to print.
|
|
93
|
+
"""
|
|
94
|
+
limit = MemoryTestResult.MEMORY_DISPLAY_LIMIT
|
|
95
|
+
truncated_memory = memory_fetched[:limit]
|
|
96
|
+
suffix = "..." if len(memory_fetched) > limit else ""
|
|
97
|
+
print(f"Memory: {truncated_memory}{suffix}")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _print_success_result(result: MemoryTestResult):
|
|
101
|
+
"""Print successful result details.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
result (MemoryTestResult): The test result to print.
|
|
105
|
+
"""
|
|
106
|
+
print("✅ Status: SUCCESS")
|
|
107
|
+
print(f"Output: {result.response}")
|
|
108
|
+
if result.memory_fetched:
|
|
109
|
+
_print_memory_summary(result.memory_fetched)
|
|
110
|
+
if result.judge_verdict is not None:
|
|
111
|
+
print(f"Judge: verdict={result.judge_verdict}, score={result.judge_score}")
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _print_failure_result(result: MemoryTestResult):
|
|
115
|
+
"""Print failure result details.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
result (MemoryTestResult): The test result to print.
|
|
119
|
+
"""
|
|
120
|
+
print("❌ Status: FAILED")
|
|
121
|
+
if result.error:
|
|
122
|
+
print(f"Error: {result.error}")
|
|
123
|
+
else:
|
|
124
|
+
print("Judge flagged as not grounded or low confidence")
|
|
125
|
+
if result.memory_fetched:
|
|
126
|
+
_print_memory_summary(result.memory_fetched)
|
|
127
|
+
if result.judge_verdict is not None:
|
|
128
|
+
print(f"Judge: verdict={result.judge_verdict}, score={result.judge_score}")
|
|
129
|
+
print(f"Output: {result.response}")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _print_header(start_time: datetime, end_time: datetime):
|
|
133
|
+
"""Print test header information.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
start_time (datetime): The start time of the tests.
|
|
137
|
+
end_time (datetime): The end time of the tests.
|
|
138
|
+
"""
|
|
139
|
+
duration = end_time - start_time
|
|
140
|
+
print("\n" + "=" * 80)
|
|
141
|
+
print("🧠 MEMORY RECALL TEST SUMMARY")
|
|
142
|
+
print("=" * 80)
|
|
143
|
+
print("Tested User ID: demo@glair")
|
|
144
|
+
print("Expected Data Range: September 17-24, 2025")
|
|
145
|
+
print(f"Test Duration: {duration.total_seconds():.2f} seconds")
|
|
146
|
+
print(f"Started: {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
147
|
+
print(f"Completed: {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
148
|
+
print("=" * 80)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _print_statistics(results: list[MemoryTestResult]):
|
|
152
|
+
"""Print test statistics.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
results (list[MemoryTestResult]): List of test results to analyze.
|
|
156
|
+
"""
|
|
157
|
+
print("\n" + "=" * 80)
|
|
158
|
+
print("📊 TEST STATISTICS")
|
|
159
|
+
print("=" * 80)
|
|
160
|
+
successful = sum(1 for r in results if r.success)
|
|
161
|
+
total = len(results)
|
|
162
|
+
print(f"Total Scenarios: {total}")
|
|
163
|
+
print(f"Successful: {successful}")
|
|
164
|
+
print(f"Failed: {total - successful}")
|
|
165
|
+
print(f"Success Rate: {(successful / total) * 100:.1f}%")
|
|
166
|
+
|
|
167
|
+
if successful == total:
|
|
168
|
+
print("\n🎉 All memory recall scenarios completed successfully!")
|
|
169
|
+
else:
|
|
170
|
+
print(f"\n⚠️ {total - successful} scenario(s) failed. Check details above.")
|
|
171
|
+
print("=" * 80)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def print_test_summary(results: list[MemoryTestResult], start_time: datetime):
|
|
175
|
+
"""Print a clean summary of all test results.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
results (list[MemoryTestResult]): List of test results to summarize.
|
|
179
|
+
start_time (datetime): The start time of the tests.
|
|
180
|
+
"""
|
|
181
|
+
end_time = datetime.now()
|
|
182
|
+
_print_header(start_time, end_time)
|
|
183
|
+
|
|
184
|
+
for i, result in enumerate(results, 1):
|
|
185
|
+
print(f"\n📋 SCENARIO {i}: {result.scenario_name}")
|
|
186
|
+
print("-" * 60)
|
|
187
|
+
print(f"Input: {result.query}")
|
|
188
|
+
|
|
189
|
+
if result.success:
|
|
190
|
+
_print_success_result(result)
|
|
191
|
+
else:
|
|
192
|
+
_print_failure_result(result)
|
|
193
|
+
|
|
194
|
+
_print_statistics(results)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
async def evaluate_with_judge(
|
|
198
|
+
judge_agent: LangGraphAgent, query: str, response: str, memory_fetched: str = None
|
|
199
|
+
) -> tuple[str | None, float | None]:
|
|
200
|
+
"""Evaluate if the response is grounded in memory using the judge agent.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
judge_agent (LangGraphAgent): The judge agent to use for evaluation.
|
|
204
|
+
query (str): The original user query.
|
|
205
|
+
response (str): The agent's response to evaluate.
|
|
206
|
+
memory_fetched (str, optional): The memory that was retrieved. Defaults to None.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
tuple[str | None, float | None]: Tuple of (verdict, score) where verdict is "grounded", "hallucination", or "general_knowledge", and score is a confidence score (0.0-1.0).
|
|
210
|
+
"""
|
|
211
|
+
memory_section = ""
|
|
212
|
+
if memory_fetched:
|
|
213
|
+
memory_section = f"\n\nActual Memory Retrieved from Tool:\n{memory_fetched}\n"
|
|
214
|
+
|
|
215
|
+
judge_prompt = (
|
|
216
|
+
"Evaluate the following assistant answer for whether it is grounded in the fetched personal memory, "
|
|
217
|
+
"is general knowledge, or is hallucination.\n\n"
|
|
218
|
+
f"User Query:\n{query}\n\n"
|
|
219
|
+
f"Assistant Answer:\n{response}{memory_section}\n"
|
|
220
|
+
"Your task is to determine if the assistant's answer is directly supported by the retrieved memory data, "
|
|
221
|
+
"is accurate general knowledge, or is incorrect/hallucinated. "
|
|
222
|
+
"Consider: Does the answer contain specific details that match the memory? "
|
|
223
|
+
"Are the facts, dates, names consistent with what was actually retrieved? "
|
|
224
|
+
"If no memory was retrieved and the query is general knowledge, classify as 'general_knowledge' "
|
|
225
|
+
"if the answer is correct.\n\n"
|
|
226
|
+
'Respond ONLY with JSON: {"verdict": "grounded|hallucination|general_knowledge", "score": <0..1>}'
|
|
227
|
+
)
|
|
228
|
+
judge_raw = await judge_agent.arun(judge_prompt)
|
|
229
|
+
judge_text = judge_raw.get("output") if isinstance(judge_raw, dict) else str(judge_raw)
|
|
230
|
+
verdict = None
|
|
231
|
+
score = None
|
|
232
|
+
try:
|
|
233
|
+
judge_obj = json.loads(judge_text)
|
|
234
|
+
verdict = judge_obj.get("verdict")
|
|
235
|
+
score = judge_obj.get("score")
|
|
236
|
+
except Exception:
|
|
237
|
+
# Fallback: attempt to parse simple keywords if JSON parse fails
|
|
238
|
+
lower = judge_text.lower()
|
|
239
|
+
if "general_knowledge" in lower:
|
|
240
|
+
verdict = "general_knowledge"
|
|
241
|
+
elif "grounded" in lower and "hallucination" not in lower:
|
|
242
|
+
verdict = "grounded"
|
|
243
|
+
else:
|
|
244
|
+
verdict = "hallucination"
|
|
245
|
+
score = 0.5
|
|
246
|
+
|
|
247
|
+
return verdict, score
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _check_environment_variables() -> bool:
|
|
251
|
+
"""Check required environment variables."""
|
|
252
|
+
if not os.getenv("MEM0_API_KEY"):
|
|
253
|
+
print("❌ Error: MEM0_API_KEY not found in environment variables.")
|
|
254
|
+
print("Please set MEM0_API_KEY in your .env file or environment.")
|
|
255
|
+
return False
|
|
256
|
+
|
|
257
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
258
|
+
print("❌ Error: OPENAI_API_KEY not found in environment variables.")
|
|
259
|
+
print("Please set OPENAI_API_KEY in your .env file or environment.")
|
|
260
|
+
return False
|
|
261
|
+
|
|
262
|
+
return True
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _create_agents() -> tuple[LangGraphAgent, LangGraphAgent]:
|
|
266
|
+
"""Create memory recall and judge agents."""
|
|
267
|
+
# Create memory recall agent - simplified instruction since built-in functionality handles complexity
|
|
268
|
+
agent = LangGraphAgent(
|
|
269
|
+
name="LangGraphMemoryEnhancerAgent",
|
|
270
|
+
instruction="You are a helpful assistant that try your best to answer the user's query.",
|
|
271
|
+
memory_backend="mem0",
|
|
272
|
+
agent_id="demo-user-test",
|
|
273
|
+
model="openai/gpt-4.1",
|
|
274
|
+
save_interaction_to_memory=False,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# Create judge agent with NO memory backend
|
|
278
|
+
judge_agent = LangGraphAgent(
|
|
279
|
+
name="Judge",
|
|
280
|
+
instruction=(
|
|
281
|
+
"You are an impartial evaluator (no tools, no memory). Given a user's query and an assistant's answer, "
|
|
282
|
+
"decide if the answer is grounded in fetched personal memory, is general knowledge, or is hallucination. "
|
|
283
|
+
"Output STRICT JSON with keys: verdict ('grounded'|'hallucination'|'general_knowledge'), "
|
|
284
|
+
"score (0..1), reason (short string). "
|
|
285
|
+
"- 'grounded' means the answer most likely came from specific recalled personal memory items. "
|
|
286
|
+
"- 'general_knowledge' means the answer is accurate general knowledge that doesn't require "
|
|
287
|
+
"personal memory. "
|
|
288
|
+
"- 'hallucination' means the answer is incorrect, guesses, or contradicts known facts. "
|
|
289
|
+
"Consider concreteness, specificity (dates, names), and whether the query requires personal memory "
|
|
290
|
+
"to answer."
|
|
291
|
+
),
|
|
292
|
+
memory_backend=None,
|
|
293
|
+
agent_id="judge-evaluator",
|
|
294
|
+
model="openai/gpt-4.1",
|
|
295
|
+
save_interaction_to_memory=False,
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
return agent, judge_agent
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
async def _run_single_scenario(
|
|
302
|
+
agent: LangGraphAgent,
|
|
303
|
+
judge_agent: LangGraphAgent,
|
|
304
|
+
scenario_name: str,
|
|
305
|
+
query: str,
|
|
306
|
+
output_file: str,
|
|
307
|
+
) -> MemoryTestResult:
|
|
308
|
+
"""Run a single memory recall scenario.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
agent (LangGraphAgent): The agent to run the scenario with.
|
|
312
|
+
judge_agent (LangGraphAgent): The judge agent to evaluate the response.
|
|
313
|
+
scenario_name (str): Name of the test scenario.
|
|
314
|
+
query (str): The query to run.
|
|
315
|
+
output_file (str): Path to the output file for logging.
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
MemoryTestResult: The test result containing response, memory, and evaluation.
|
|
319
|
+
"""
|
|
320
|
+
print(f"\n🔄 Running scenario: {scenario_name}")
|
|
321
|
+
print(f"Query: {query}")
|
|
322
|
+
|
|
323
|
+
memory_fetched = ""
|
|
324
|
+
final_response = ""
|
|
325
|
+
|
|
326
|
+
# Write stream_start header for this scenario
|
|
327
|
+
try:
|
|
328
|
+
with open(output_file, "a", encoding="utf-8") as f:
|
|
329
|
+
f.write(f"--- Scenario: {scenario_name} | Query: {query} | Time: {datetime.now().isoformat()} ---\n")
|
|
330
|
+
json.dump({"type": "stream_start", "query": query, "scenario": scenario_name}, f)
|
|
331
|
+
f.write("\n")
|
|
332
|
+
except Exception as e:
|
|
333
|
+
print(f" ⚠️ Could not write stream_start to {output_file}: {e}")
|
|
334
|
+
|
|
335
|
+
# Stream the agent execution and capture memory tool results + final response
|
|
336
|
+
final_response = await agent.arun(query=query, memory_user_id="demo@glair")
|
|
337
|
+
final_response_output = final_response["output"]
|
|
338
|
+
final_state = final_response["full_final_state"]
|
|
339
|
+
memory_fetched: HumanMessage = final_state["messages"][1].content.strip()
|
|
340
|
+
|
|
341
|
+
# Create test result with both memory and response
|
|
342
|
+
test_result = MemoryTestResult(scenario_name, query, final_response_output, memory_fetched)
|
|
343
|
+
|
|
344
|
+
# Evaluate with judge using both memory and response
|
|
345
|
+
verdict, score = await evaluate_with_judge(judge_agent, query, final_response_output, memory_fetched.strip())
|
|
346
|
+
test_result.judge_verdict = verdict
|
|
347
|
+
test_result.judge_score = score
|
|
348
|
+
test_result.set_success_from_judge(verdict, score)
|
|
349
|
+
|
|
350
|
+
return test_result
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
async def run_all_scenarios():
|
|
354
|
+
"""Run all memory recall test scenarios with a single reused agent and show clean summary."""
|
|
355
|
+
start_time = datetime.now()
|
|
356
|
+
|
|
357
|
+
print("🧠 Starting Memory Recall Testing with demo@glair data...")
|
|
358
|
+
print(f"Current time: {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
359
|
+
print("User ID: demo@glair")
|
|
360
|
+
print("Expected data range: September 17-24, 2025")
|
|
361
|
+
print("Running tests... (this may take a few moments)")
|
|
362
|
+
|
|
363
|
+
# Check environment variables
|
|
364
|
+
if not _check_environment_variables():
|
|
365
|
+
return
|
|
366
|
+
|
|
367
|
+
# Create agents
|
|
368
|
+
agent, judge_agent = _create_agents()
|
|
369
|
+
|
|
370
|
+
scenarios = [
|
|
371
|
+
("Semantic Search Without Time Period", "What is my name and birthday? How old am I now?"),
|
|
372
|
+
("Semantic Search With Time Period", "I mention my hobby on September 17, 2025, can you recall it?"),
|
|
373
|
+
("Date-Based Recall Without Semantic Query", "What did we talk about in 25 September 2025?"),
|
|
374
|
+
("Last Week Recall (Calendar Week)", "What did we discuss last week?"),
|
|
375
|
+
("General Knowledge - Capital of Indonesia", "What is the capital of Indonesia?"),
|
|
376
|
+
("General Knowledge - US President Inauguration", "Who was inaugurated as US president on January 20, 2009?"),
|
|
377
|
+
]
|
|
378
|
+
|
|
379
|
+
results = []
|
|
380
|
+
try:
|
|
381
|
+
# Tool stream capture output file (JSONL)
|
|
382
|
+
output_file = "memory_recall_tool_events.jsonl"
|
|
383
|
+
|
|
384
|
+
for scenario_name, query in scenarios:
|
|
385
|
+
try:
|
|
386
|
+
result = await _run_single_scenario(agent, judge_agent, scenario_name, query, output_file)
|
|
387
|
+
results.append(result)
|
|
388
|
+
except Exception as e:
|
|
389
|
+
print(f" ❌ Error: {str(e)}")
|
|
390
|
+
test_result = MemoryTestResult(scenario_name, query, error=str(e))
|
|
391
|
+
results.append(test_result)
|
|
392
|
+
|
|
393
|
+
# Print clean summary
|
|
394
|
+
print_test_summary(results, start_time)
|
|
395
|
+
|
|
396
|
+
except Exception as e:
|
|
397
|
+
print(f"❌ Error running scenarios: {e}")
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
if __name__ == "__main__":
|
|
401
|
+
asyncio.run(run_all_scenarios())
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Example of a General Assistant GoogleADKAgent that can delegate tasks to specialized agents.
|
|
2
|
+
|
|
3
|
+
This example demonstrates:
|
|
4
|
+
1. Configuring A2A settings for a client agent.
|
|
5
|
+
2. Creating a general assistant agent that can help with various queries.
|
|
6
|
+
3. Delegating specific tasks to specialized agents via A2A.
|
|
7
|
+
4. Handling responses and providing relevant advice.
|
|
8
|
+
|
|
9
|
+
Authors:
|
|
10
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
|
|
15
|
+
from aip_agents.agent.google_adk_agent import GoogleADKAgent
|
|
16
|
+
from aip_agents.schema.agent import A2AClientConfig
|
|
17
|
+
from aip_agents.utils.logger import get_logger
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def main():
|
|
23
|
+
"""Main function demonstrating the General Assistant agent with A2A capabilities."""
|
|
24
|
+
agent_name = "GoogleAssistantAgent"
|
|
25
|
+
# Create the agent with simplified instructions tailored to the agent name
|
|
26
|
+
assistant_agent = GoogleADKAgent(
|
|
27
|
+
name=agent_name,
|
|
28
|
+
instruction="You are a helpful assistant that can help with various tasks by delegating to specialized agents.",
|
|
29
|
+
model="gemini-2.0-flash",
|
|
30
|
+
tools=[],
|
|
31
|
+
max_iterations=5,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Discover agents
|
|
35
|
+
client_a2a_config = A2AClientConfig(
|
|
36
|
+
discovery_urls=["http://localhost:8002"],
|
|
37
|
+
)
|
|
38
|
+
agent_cards = assistant_agent.discover_agents(client_a2a_config)
|
|
39
|
+
|
|
40
|
+
query = "What is the weather in Jakarta?"
|
|
41
|
+
logger.info(f"Processing Query: {query}")
|
|
42
|
+
|
|
43
|
+
response = assistant_agent.send_to_agent(agent_cards[0], query)
|
|
44
|
+
logger.info(f"Raw response: \n\n{json.dumps(response, indent=4)}Q")
|
|
45
|
+
logger.info(f"Agent Response: {response['content']}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
main()
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Example of a General Assistant GoogleADKAgent that can delegate tasks to specialized agents.
|
|
2
|
+
|
|
3
|
+
This example demonstrates:
|
|
4
|
+
1. Configuring A2A settings for a client agent.
|
|
5
|
+
2. Creating a general assistant agent that can help with various queries.
|
|
6
|
+
3. Delegating specific tasks to specialized agents via A2A.
|
|
7
|
+
4. Handling responses and providing relevant advice.
|
|
8
|
+
|
|
9
|
+
Authors:
|
|
10
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from aip_agents.agent.google_adk_agent import GoogleADKAgent
|
|
14
|
+
from aip_agents.schema.agent import A2AClientConfig
|
|
15
|
+
from aip_agents.utils.logger import get_logger
|
|
16
|
+
|
|
17
|
+
logger = get_logger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def main():
|
|
21
|
+
"""Main function demonstrating the General Assistant agent with A2A capabilities."""
|
|
22
|
+
agent_name = "GoogleAssistantAgent"
|
|
23
|
+
assistant_agent = GoogleADKAgent(
|
|
24
|
+
name=agent_name,
|
|
25
|
+
instruction="You are a helpful assistant that can help with various tasks by delegating to specialized agents.",
|
|
26
|
+
model="gemini-2.0-flash",
|
|
27
|
+
tools=[],
|
|
28
|
+
max_iterations=5,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Discover agents
|
|
32
|
+
client_a2a_config = A2AClientConfig(
|
|
33
|
+
discovery_urls=["http://localhost:8002"],
|
|
34
|
+
)
|
|
35
|
+
agent_cards = assistant_agent.discover_agents(client_a2a_config)
|
|
36
|
+
|
|
37
|
+
# Register agents
|
|
38
|
+
assistant_agent.register_a2a_agents(agent_cards)
|
|
39
|
+
|
|
40
|
+
query = "What is the weather in Jakarta?"
|
|
41
|
+
logger.info(f"Processing Query: {query}")
|
|
42
|
+
|
|
43
|
+
response = assistant_agent.run(query)
|
|
44
|
+
logger.info(f"Assistant Agent Response: {response['output']}")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
main()
|