From beadde8e4e6acfe99ffeef8eebfeaa85c7d7f830 Mon Sep 17 00:00:00 2001 From: Georgiy Tarasov Date: Wed, 5 Nov 2025 16:08:31 +0100 Subject: [PATCH] feat(max): parallel tool calls (#39954) Co-authored-by: kappa90 Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- ee/hogai/README.md | 2 +- ee/hogai/assistant/base.py | 73 +- ee/hogai/assistant/deep_research_assistant.py | 38 +- ee/hogai/assistant/insights_assistant.py | 75 +- ee/hogai/assistant/main_assistant.py | 89 +- ee/hogai/context/context.py | 2 +- ee/hogai/context/test/test_context.py | 2 +- ee/hogai/eval/README.md | 2 +- ee/hogai/eval/ci/conftest.py | 34 +- ee/hogai/eval/ci/eval_dashboard_creation.py | 20 +- ee/hogai/eval/ci/eval_insight_search.py | 13 +- ee/hogai/eval/ci/eval_memory.py | 2 +- ee/hogai/eval/ci/eval_memory_onboarding.py | 2 +- ee/hogai/eval/ci/eval_root.py | 13 +- ee/hogai/eval/ci/eval_root_documentation.py | 14 +- ee/hogai/eval/ci/eval_root_entity_search.py | 14 +- ee/hogai/eval/ci/eval_root_style.py | 16 +- .../eval/ci/eval_session_summarization.py | 13 +- ee/hogai/eval/ci/eval_surveys.py | 4 +- ee/hogai/eval/ci/eval_ui_context.py | 11 +- .../eval_create_feature_flag_tool.py | 4 - .../ci/max_tools/eval_edit_dashboard_tool.py | 14 +- .../eval/ci/max_tools/eval_navigate_tool.py | 13 +- ...val_revenue_analytics_filter_generation.py | 6 +- .../eval_session_replay_filter_generation.py | 6 +- .../max_tools/eval_tool_filter_generation.py | 6 +- ee/hogai/eval/offline/eval_sql.py | 2 +- ee/hogai/eval/scorers/__init__.py | 44 +- ee/hogai/graph/__init__.py | 33 - ee/hogai/graph/base/__init__.py | 9 + ee/hogai/graph/base/context.py | 22 + ee/hogai/graph/base/graph.py | 88 ++ ee/hogai/graph/{base.py => base/node.py} | 96 +-- .../graph/{billing => base/test}/__init__.py | 0 .../graph/base/test/test_assistant_graph.py | 47 + ee/hogai/graph/base/test/test_node_path.py | 502 +++++++++++ ee/hogai/graph/dashboards/nodes.py | 23 +- ee/hogai/graph/dashboards/test/test_nodes.py | 89 +- ee/hogai/graph/deep_research/graph.py | 30 +- ee/hogai/graph/deep_research/planner/nodes.py | 2 +- .../deep_research/planner/test/test_nodes.py | 3 +- .../task_executor/test/test_nodes.py | 6 +- .../deep_research/test/test_integration.py | 3 +- .../graph/deep_research/test/test_types.py | 2 +- ee/hogai/graph/deep_research/types.py | 21 +- ee/hogai/graph/funnels/nodes.py | 4 +- ee/hogai/graph/graph.py | 296 +------ ee/hogai/graph/inkeep_docs/nodes.py | 32 +- ee/hogai/graph/inkeep_docs/test/test_nodes.py | 23 +- ee/hogai/graph/insights/nodes.py | 114 +-- ee/hogai/graph/insights/prompts.py | 4 - ee/hogai/graph/insights/test/test_nodes.py | 39 +- .../test => insights_graph}/__init__.py | 0 ee/hogai/graph/insights_graph/graph.py | 155 ++++ ee/hogai/graph/mixins.py | 39 +- .../graph/parallel_task_execution/mixins.py | 14 +- ee/hogai/graph/query_executor/nodes.py | 27 +- ee/hogai/graph/retention/nodes.py | 4 +- ee/hogai/graph/root/nodes.py | 228 ++--- ee/hogai/graph/root/prompts.py | 4 + ee/hogai/graph/root/test/test_nodes.py | 560 ++++-------- ee/hogai/graph/root/tools/__init__.py | 21 +- .../root/tools/create_and_query_insight.py | 206 +++++ ee/hogai/graph/root/tools/create_dashboard.py | 53 ++ .../full_text_search/test/test_toolkit.py | 13 +- .../graph/root/tools/full_text_search/tool.py | 9 +- ee/hogai/graph/root/tools/legacy.py | 204 ----- ee/hogai/graph/root/tools/navigate.py | 6 +- .../root/tools/read_billing_tool/__init__.py | 0 .../tools/read_billing_tool}/prompts.py | 0 .../tools/read_billing_tool/test/__init__.py | 0 .../read_billing_tool}/test/test_nodes.py | 116 +-- .../tools/read_billing_tool/tool.py} | 57 +- ee/hogai/graph/root/tools/read_data.py | 24 +- ee/hogai/graph/root/tools/read_taxonomy.py | 6 +- ee/hogai/graph/root/tools/search.py | 191 ++-- .../graph/root/tools/session_summarization.py | 122 +++ .../test/test_create_and_query_insight.py | 253 ++++++ .../root/tools/test/test_create_dashboard.py | 248 ++++++ ee/hogai/graph/root/tools/test/test_search.py | 395 +++++---- .../tools/test/test_session_summarization.py | 193 +++++ ee/hogai/graph/root/tools/todo_write.py | 2 +- ee/hogai/graph/schema_generator/nodes.py | 29 +- .../graph/schema_generator/test/test_nodes.py | 71 +- ee/hogai/graph/session_summaries/nodes.py | 9 +- ee/hogai/graph/sql/nodes.py | 4 +- ee/hogai/graph/taxonomy/agent.py | 23 +- ee/hogai/graph/taxonomy/nodes.py | 16 - ee/hogai/graph/taxonomy/test/test_agent.py | 4 +- ee/hogai/graph/taxonomy/toolkit.py | 10 +- ee/hogai/graph/test/test_assistant_graph.py | 29 - .../graph/test/test_dispatcher_integration.py | 371 +++++--- ee/hogai/graph/trends/nodes.py | 4 +- ee/hogai/test/test_assistant.py | 577 +++++++++---- ee/hogai/tool.py | 70 +- ee/hogai/utils/dispatcher.py | 81 +- ee/hogai/utils/helpers.py | 3 +- ee/hogai/utils/state.py | 3 +- ee/hogai/utils/stream_processor.py | 263 +++--- ee/hogai/utils/test/test_dispatcher.py | 499 ++++++++--- ee/hogai/utils/test/test_stream_processor.py | 816 +++++++++++------- ee/hogai/utils/types/base.py | 38 +- ...ines--pipeline-destination-page--light.png | Bin 111129 -> 111101 bytes ...ts-trendsvalue--trends-area-edit--dark.png | Bin 79712 -> 79158 bytes ...s-trendsvalue--trends-area-edit--light.png | Bin 78321 -> 77775 bytes ...x-instance-with-contextual-tools--dark.png | Bin 46824 -> 47217 bytes ...-instance-with-contextual-tools--light.png | Bin 47315 -> 47875 bytes ...posthog-ai--reasoning-component--light.png | Bin 20341 -> 20338 bytes ...-app-sidepanels--side-panel-docs--dark.png | Bin 159720 -> 160044 bytes .../nodes/InsightViz/EditorFilters.tsx | 2 +- frontend/src/queries/schema.json | 1 - .../schema/schema-assistant-messages.ts | 1 - frontend/src/scenes/max/Thread.tsx | 10 +- .../scenes/max/components/ToolsDisplay.tsx | 7 +- frontend/src/scenes/max/max-constants.tsx | 33 +- frontend/src/scenes/max/maxGlobalLogic.tsx | 19 +- posthog/schema.py | 1 - .../backend/test/test_max_tool_integration.py | 3 - .../dashboards/backend/test/test_max_tools.py | 4 +- products/data_warehouse/backend/max_tools.py | 7 +- .../backend/test/test_max_tools.py | 36 +- products/error_tracking/backend/max_tools.py | 5 +- products/feature_flags/backend/max_tools.py | 5 +- .../product_analytics/backend/max_tools.py | 137 --- products/replay/backend/max_tools.py | 5 +- .../revenue_analytics/backend/max_tools.py | 5 +- products/surveys/backend/max_tools.py | 5 +- products/surveys/backend/test_max_tools.py | 3 +- 128 files changed, 5035 insertions(+), 3346 deletions(-) create mode 100644 ee/hogai/graph/base/__init__.py create mode 100644 ee/hogai/graph/base/context.py create mode 100644 ee/hogai/graph/base/graph.py rename ee/hogai/graph/{base.py => base/node.py} (53%) rename ee/hogai/graph/{billing => base/test}/__init__.py (100%) create mode 100644 ee/hogai/graph/base/test/test_assistant_graph.py create mode 100644 ee/hogai/graph/base/test/test_node_path.py rename ee/hogai/graph/{billing/test => insights_graph}/__init__.py (100%) create mode 100644 ee/hogai/graph/insights_graph/graph.py create mode 100644 ee/hogai/graph/root/tools/create_and_query_insight.py create mode 100644 ee/hogai/graph/root/tools/create_dashboard.py delete mode 100644 ee/hogai/graph/root/tools/legacy.py create mode 100644 ee/hogai/graph/root/tools/read_billing_tool/__init__.py rename ee/hogai/graph/{billing => root/tools/read_billing_tool}/prompts.py (100%) create mode 100644 ee/hogai/graph/root/tools/read_billing_tool/test/__init__.py rename ee/hogai/graph/{billing => root/tools/read_billing_tool}/test/test_nodes.py (89%) rename ee/hogai/graph/{billing/nodes.py => root/tools/read_billing_tool/tool.py} (91%) create mode 100644 ee/hogai/graph/root/tools/session_summarization.py create mode 100644 ee/hogai/graph/root/tools/test/test_create_and_query_insight.py create mode 100644 ee/hogai/graph/root/tools/test/test_create_dashboard.py create mode 100644 ee/hogai/graph/root/tools/test/test_session_summarization.py delete mode 100644 ee/hogai/graph/test/test_assistant_graph.py delete mode 100644 products/product_analytics/backend/max_tools.py diff --git a/ee/hogai/README.md b/ee/hogai/README.md index eed6ff5005..3e57b5ea85 100644 --- a/ee/hogai/README.md +++ b/ee/hogai/README.md @@ -320,7 +320,7 @@ class YourTaxonomyGraph(TaxonomyAgent[TaxonomyAgentState, TaxonomyAgentState[Max 4. Invoke it (typically from a `MaxTool`), mirroring `products/replay/backend/max_tools.py`: ```python -graph = YourTaxonomyGraph(team=self._team, user=self._user, tool_call_id=self._tool_call_id) +graph = YourTaxonomyGraph(team=self._team, user=self._user) graph_context = { "change": "Show me recordings of users in Germany that used a mobile device while performing a payment", diff --git a/ee/hogai/assistant/base.py b/ee/hogai/assistant/base.py index a7342ca49f..7fe0e2d505 100644 --- a/ee/hogai/assistant/base.py +++ b/ee/hogai/assistant/base.py @@ -9,7 +9,6 @@ import structlog import posthoganalytics from asgiref.sync import async_to_sync from langchain_core.callbacks.base import BaseCallbackHandler -from langchain_core.messages import AIMessageChunk from langchain_core.runnables.config import RunnableConfig from langgraph.errors import GraphRecursionError from langgraph.graph.state import CompiledStateGraph @@ -31,20 +30,19 @@ from posthog.event_usage import report_user_action from posthog.models import Team, User from posthog.sync import database_sync_to_async -from ee.hogai.graph.base import BaseAssistantNode from ee.hogai.utils.exceptions import GenerationCanceled from ee.hogai.utils.helpers import extract_stream_update -from ee.hogai.utils.state import ( - GraphValueUpdateTuple, - is_message_update, - is_state_update, - is_value_update, - validate_state_update, +from ee.hogai.utils.state import validate_state_update +from ee.hogai.utils.stream_processor import AssistantStreamProcessorProtocol +from ee.hogai.utils.types.base import ( + AssistantDispatcherEvent, + AssistantMessageUnion, + AssistantMode, + AssistantOutput, + AssistantResultUnion, + LangGraphUpdateEvent, ) -from ee.hogai.utils.stream_processor import AssistantStreamProcessor -from ee.hogai.utils.types import AssistantMessageUnion, AssistantOutput -from ee.hogai.utils.types.base import AssistantDispatcherEvent, AssistantMode, AssistantResultUnion, MessageChunkAction -from ee.hogai.utils.types.composed import AssistantMaxGraphState, AssistantMaxPartialGraphState, MaxNodeName +from ee.hogai.utils.types.composed import AssistantMaxGraphState, AssistantMaxPartialGraphState from ee.models import Conversation logger = structlog.get_logger(__name__) @@ -66,7 +64,7 @@ class BaseAssistant(ABC): _trace_id: Optional[str | UUID] _billing_context: Optional[MaxBillingContext] _initial_state: Optional[AssistantMaxGraphState | AssistantMaxPartialGraphState] - _stream_processor: AssistantStreamProcessor + _stream_processor: AssistantStreamProcessorProtocol """The stream processor that processes dispatcher actions and message chunks.""" def __init__( @@ -87,6 +85,7 @@ class BaseAssistant(ABC): billing_context: Optional[MaxBillingContext] = None, initial_state: Optional[AssistantMaxGraphState | AssistantMaxPartialGraphState] = None, callback_handler: Optional[BaseCallbackHandler] = None, + stream_processor: AssistantStreamProcessorProtocol, ): self._team = team self._contextual_tools = contextual_tools or {} @@ -121,22 +120,7 @@ class BaseAssistant(ABC): self._mode = mode self._initial_state = initial_state # Initialize the stream processor with node configuration - self._stream_processor = AssistantStreamProcessor( - streaming_nodes=self.STREAMING_NODES, - visualization_nodes=self.VISUALIZATION_NODES, - ) - - @property - @abstractmethod - def VISUALIZATION_NODES(self) -> dict[MaxNodeName, type[BaseAssistantNode]]: - """Nodes that can generate visualizations.""" - pass - - @property - @abstractmethod - def STREAMING_NODES(self) -> set[MaxNodeName]: - """Nodes that can stream messages to the client.""" - pass + self._stream_processor = stream_processor @abstractmethod def get_initial_state(self) -> AssistantMaxGraphState: @@ -175,7 +159,7 @@ class BaseAssistant(ABC): state = await self._init_or_update_state() config = self._get_config() - stream_mode: list[StreamMode] = ["values", "updates", "custom"] + stream_mode: list[StreamMode] = ["values", "custom"] if stream_message_chunks: stream_mode.append("messages") @@ -286,11 +270,11 @@ class BaseAssistant(ABC): # Add existing ids to streamed messages, so we don't send the messages again. for message in saved_state.messages: if message.id is not None: - self._stream_processor._streamed_update_ids.add(message.id) + self._stream_processor.mark_id_as_streamed(message.id) # Add the latest message id to streamed messages, so we don't send it multiple times. if self._latest_message and self._latest_message.id is not None: - self._stream_processor._streamed_update_ids.add(self._latest_message.id) + self._stream_processor.mark_id_as_streamed(self._latest_message.id) # If the graph previously hasn't reset the state, it is an interrupt. We resume from the point of interruption. if snapshot.next and self._latest_message and saved_state.graph_status == "interrupted": @@ -322,29 +306,12 @@ class BaseAssistant(ABC): async def _process_update(self, update: Any) -> list[AssistantResultUnion] | None: update = extract_stream_update(update) - new_message: AssistantResultUnion | None = None if not isinstance(update, AssistantDispatcherEvent): - if is_state_update(update): - _, new_state = update - self._state = validate_state_update(new_state, self._state_type) - elif is_value_update(update) and (new_message := await self._aprocess_value_update(update)): - return [new_message] + if updates := self._stream_processor.process_langgraph_update(LangGraphUpdateEvent(update=update)): + return updates + elif new_message := self._stream_processor.process(update): + return new_message - if is_message_update(update): - # Convert the message chunk update to a dispatcher event to prepare for a bright future without LangGraph - message, state = update[1] - if not isinstance(message, AIMessageChunk): - return None - update = AssistantDispatcherEvent( - action=MessageChunkAction(message=message), node_name=state["langgraph_node"] - ) - - if isinstance(update, AssistantDispatcherEvent) and (new_message := self._stream_processor.process(update)): - return [new_message] if new_message else None - - return None - - async def _aprocess_value_update(self, update: GraphValueUpdateTuple) -> AssistantResultUnion | None: return None def _build_root_config_for_persistence(self) -> RunnableConfig: diff --git a/ee/hogai/assistant/deep_research_assistant.py b/ee/hogai/assistant/deep_research_assistant.py index 56cdc4ad2d..4036af6430 100644 --- a/ee/hogai/assistant/deep_research_assistant.py +++ b/ee/hogai/assistant/deep_research_assistant.py @@ -1,5 +1,5 @@ from collections.abc import AsyncGenerator -from typing import Any, Optional +from typing import TYPE_CHECKING, Any, Optional from uuid import UUID from posthog.schema import AssistantMessage, HumanMessage, MaxBillingContext, VisualizationMessage @@ -7,13 +7,26 @@ from posthog.schema import AssistantMessage, HumanMessage, MaxBillingContext, Vi from posthog.models import Team, User from ee.hogai.assistant.base import BaseAssistant -from ee.hogai.graph import DeepResearchAssistantGraph -from ee.hogai.graph.base import BaseAssistantNode +from ee.hogai.graph.deep_research.graph import DeepResearchAssistantGraph from ee.hogai.graph.deep_research.types import DeepResearchNodeName, DeepResearchState, PartialDeepResearchState +from ee.hogai.utils.stream_processor import AssistantStreamProcessor from ee.hogai.utils.types import AssistantMode, AssistantOutput -from ee.hogai.utils.types.composed import MaxNodeName from ee.models import Conversation +if TYPE_CHECKING: + from ee.hogai.utils.types.composed import MaxNodeName + + +STREAMING_NODES: set["MaxNodeName"] = { + DeepResearchNodeName.ONBOARDING, + DeepResearchNodeName.PLANNER, + DeepResearchNodeName.TASK_EXECUTOR, +} + +VERBOSE_NODES: set["MaxNodeName"] = STREAMING_NODES | { + DeepResearchNodeName.PLANNER_TOOLS, +} + class DeepResearchAssistant(BaseAssistant): _state: Optional[DeepResearchState] @@ -48,20 +61,13 @@ class DeepResearchAssistant(BaseAssistant): trace_id=trace_id, billing_context=billing_context, initial_state=initial_state, + stream_processor=AssistantStreamProcessor( + verbose_nodes=VERBOSE_NODES, + streaming_nodes=STREAMING_NODES, + state_type=DeepResearchState, + ), ) - @property - def VISUALIZATION_NODES(self) -> dict[MaxNodeName, type[BaseAssistantNode]]: - return {} - - @property - def STREAMING_NODES(self) -> set[MaxNodeName]: - return { - DeepResearchNodeName.ONBOARDING, - DeepResearchNodeName.PLANNER, - DeepResearchNodeName.TASK_EXECUTOR, - } - def get_initial_state(self) -> DeepResearchState: if self._latest_message: return DeepResearchState( diff --git a/ee/hogai/assistant/insights_assistant.py b/ee/hogai/assistant/insights_assistant.py index 39848397f4..806116d3de 100644 --- a/ee/hogai/assistant/insights_assistant.py +++ b/ee/hogai/assistant/insights_assistant.py @@ -1,36 +1,32 @@ from collections.abc import AsyncGenerator -from typing import Any, Optional +from typing import TYPE_CHECKING, Any, Optional from uuid import UUID -from posthog.schema import ( - AssistantGenerationStatusEvent, - AssistantGenerationStatusType, - AssistantMessage, - HumanMessage, - MaxBillingContext, - VisualizationMessage, -) +from posthog.schema import AssistantMessage, HumanMessage, MaxBillingContext, VisualizationMessage from posthog.models import Team, User from ee.hogai.assistant.base import BaseAssistant -from ee.hogai.graph import FunnelGeneratorNode, RetentionGeneratorNode, SQLGeneratorNode, TrendsGeneratorNode -from ee.hogai.graph.base import BaseAssistantNode -from ee.hogai.graph.graph import InsightsAssistantGraph -from ee.hogai.graph.query_executor.nodes import QueryExecutorNode -from ee.hogai.graph.taxonomy.types import TaxonomyNodeName -from ee.hogai.utils.state import GraphValueUpdateTuple, validate_value_update -from ee.hogai.utils.types import ( - AssistantMode, - AssistantNodeName, - AssistantOutput, - AssistantState, - PartialAssistantState, -) -from ee.hogai.utils.types.base import AssistantResultUnion -from ee.hogai.utils.types.composed import MaxNodeName +from ee.hogai.graph.insights_graph.graph import InsightsGraph +from ee.hogai.utils.stream_processor import AssistantStreamProcessor +from ee.hogai.utils.types import AssistantMode, AssistantOutput, AssistantState, PartialAssistantState +from ee.hogai.utils.types.base import AssistantNodeName from ee.models import Conversation +if TYPE_CHECKING: + from ee.hogai.utils.types.composed import MaxNodeName + + +VERBOSE_NODES: set["MaxNodeName"] = { + AssistantNodeName.QUERY_EXECUTOR, + AssistantNodeName.FUNNEL_GENERATOR, + AssistantNodeName.RETENTION_GENERATOR, + AssistantNodeName.SQL_GENERATOR, + AssistantNodeName.TRENDS_GENERATOR, + AssistantNodeName.ROOT, + AssistantNodeName.ROOT_TOOLS, +} + class InsightsAssistant(BaseAssistant): _state: Optional[AssistantState] @@ -55,7 +51,7 @@ class InsightsAssistant(BaseAssistant): conversation, new_message=new_message, user=user, - graph=InsightsAssistantGraph(team, user).compile_full_graph(), + graph=InsightsGraph(team, user).compile_full_graph(), state_type=AssistantState, partial_state_type=PartialAssistantState, mode=AssistantMode.INSIGHTS_TOOL, @@ -65,24 +61,11 @@ class InsightsAssistant(BaseAssistant): trace_id=trace_id, billing_context=billing_context, initial_state=initial_state, + stream_processor=AssistantStreamProcessor( + verbose_nodes=VERBOSE_NODES, streaming_nodes=set(), state_type=AssistantState + ), ) - @property - def VISUALIZATION_NODES(self) -> dict[MaxNodeName, type[BaseAssistantNode]]: - return { - AssistantNodeName.TRENDS_GENERATOR: TrendsGeneratorNode, - AssistantNodeName.FUNNEL_GENERATOR: FunnelGeneratorNode, - AssistantNodeName.RETENTION_GENERATOR: RetentionGeneratorNode, - AssistantNodeName.SQL_GENERATOR: SQLGeneratorNode, - AssistantNodeName.QUERY_EXECUTOR: QueryExecutorNode, - } - - @property - def STREAMING_NODES(self) -> set[MaxNodeName]: - return { - TaxonomyNodeName.LOOP_NODE, - } - def get_initial_state(self) -> AssistantState: return AssistantState(messages=[]) @@ -127,13 +110,3 @@ class InsightsAssistant(BaseAssistant): "is_new_conversation": False, }, ) - - async def _aprocess_value_update(self, update: GraphValueUpdateTuple) -> AssistantResultUnion | None: - _, maybe_state_update = update - state_update = validate_value_update(maybe_state_update) - if intersected_nodes := state_update.keys() & self.VISUALIZATION_NODES.keys(): - node_name: MaxNodeName = intersected_nodes.pop() - node_val = state_update[node_name] - if isinstance(node_val, PartialAssistantState) and node_val.intermediate_steps: - return AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.GENERATION_ERROR) - return await super()._aprocess_value_update(update) diff --git a/ee/hogai/assistant/main_assistant.py b/ee/hogai/assistant/main_assistant.py index 4da7ceee09..da74e2ac28 100644 --- a/ee/hogai/assistant/main_assistant.py +++ b/ee/hogai/assistant/main_assistant.py @@ -1,29 +1,15 @@ from collections.abc import AsyncGenerator -from typing import Any, Optional +from typing import TYPE_CHECKING, Any, Optional from uuid import UUID -from posthog.schema import ( - AssistantGenerationStatusEvent, - AssistantGenerationStatusType, - AssistantMessage, - HumanMessage, - MaxBillingContext, - VisualizationMessage, -) +from posthog.schema import AssistantMessage, HumanMessage, MaxBillingContext, VisualizationMessage from posthog.models import Team, User from ee.hogai.assistant.base import BaseAssistant -from ee.hogai.graph import ( - AssistantGraph, - FunnelGeneratorNode, - RetentionGeneratorNode, - SQLGeneratorNode, - TrendsGeneratorNode, -) -from ee.hogai.graph.base import BaseAssistantNode -from ee.hogai.graph.insights.nodes import InsightSearchNode -from ee.hogai.utils.state import GraphValueUpdateTuple, validate_value_update +from ee.hogai.graph.graph import AssistantGraph +from ee.hogai.graph.taxonomy.types import TaxonomyNodeName +from ee.hogai.utils.stream_processor import AssistantStreamProcessor from ee.hogai.utils.types import ( AssistantMode, AssistantNodeName, @@ -31,10 +17,36 @@ from ee.hogai.utils.types import ( AssistantState, PartialAssistantState, ) -from ee.hogai.utils.types.base import AssistantResultUnion -from ee.hogai.utils.types.composed import MaxNodeName from ee.models import Conversation +if TYPE_CHECKING: + from ee.hogai.utils.types.composed import MaxNodeName + + +STREAMING_NODES: set["MaxNodeName"] = { + AssistantNodeName.ROOT, + AssistantNodeName.INKEEP_DOCS, + AssistantNodeName.MEMORY_ONBOARDING, + AssistantNodeName.MEMORY_INITIALIZER, + AssistantNodeName.MEMORY_ONBOARDING_ENQUIRY, + AssistantNodeName.MEMORY_ONBOARDING_FINALIZE, + AssistantNodeName.DASHBOARD_CREATION, +} + + +VERBOSE_NODES: set["MaxNodeName"] = { + AssistantNodeName.TRENDS_GENERATOR, + AssistantNodeName.FUNNEL_GENERATOR, + AssistantNodeName.RETENTION_GENERATOR, + AssistantNodeName.SQL_GENERATOR, + AssistantNodeName.INSIGHTS_SEARCH, + AssistantNodeName.QUERY_EXECUTOR, + AssistantNodeName.MEMORY_INITIALIZER_INTERRUPT, + AssistantNodeName.ROOT_TOOLS, + TaxonomyNodeName.TOOLS_NODE, + TaxonomyNodeName.TASK_EXECUTOR, +} + class MainAssistant(BaseAssistant): _state: Optional[AssistantState] @@ -69,30 +81,11 @@ class MainAssistant(BaseAssistant): trace_id=trace_id, billing_context=billing_context, initial_state=initial_state, + stream_processor=AssistantStreamProcessor( + verbose_nodes=VERBOSE_NODES, streaming_nodes=STREAMING_NODES, state_type=AssistantState + ), ) - @property - def VISUALIZATION_NODES(self) -> dict[MaxNodeName, type[BaseAssistantNode]]: - return { - AssistantNodeName.TRENDS_GENERATOR: TrendsGeneratorNode, - AssistantNodeName.FUNNEL_GENERATOR: FunnelGeneratorNode, - AssistantNodeName.RETENTION_GENERATOR: RetentionGeneratorNode, - AssistantNodeName.SQL_GENERATOR: SQLGeneratorNode, - AssistantNodeName.INSIGHTS_SEARCH: InsightSearchNode, - } - - @property - def STREAMING_NODES(self) -> set[MaxNodeName]: - return { - AssistantNodeName.ROOT, - AssistantNodeName.INKEEP_DOCS, - AssistantNodeName.MEMORY_ONBOARDING, - AssistantNodeName.MEMORY_INITIALIZER, - AssistantNodeName.MEMORY_ONBOARDING_ENQUIRY, - AssistantNodeName.MEMORY_ONBOARDING_FINALIZE, - AssistantNodeName.DASHBOARD_CREATION, - } - def get_initial_state(self) -> AssistantState: if self._latest_message: return AssistantState( @@ -142,13 +135,3 @@ class MainAssistant(BaseAssistant): "is_new_conversation": self._is_new_conversation, }, ) - - async def _aprocess_value_update(self, update: GraphValueUpdateTuple) -> AssistantResultUnion | None: - _, maybe_state_update = update - state_update = validate_value_update(maybe_state_update) - if intersected_nodes := state_update.keys() & self.VISUALIZATION_NODES.keys(): - node_name: MaxNodeName = intersected_nodes.pop() - node_val = state_update[node_name] - if isinstance(node_val, PartialAssistantState) and node_val.intermediate_steps: - return AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.GENERATION_ERROR) - return await super()._aprocess_value_update(update) diff --git a/ee/hogai/context/context.py b/ee/hogai/context/context.py index dae30936ca..ed5f1d6222 100644 --- a/ee/hogai/context/context.py +++ b/ee/hogai/context/context.py @@ -396,7 +396,7 @@ class AssistantContextManager(AssistantContextMixin): contextual_tools_prompt = [ f"<{tool_name}>\n" - f"{get_contextual_tool_class(tool_name)(team=self._team, user=self._user, tool_call_id="").format_context_prompt_injection(tool_context)}\n" # type: ignore + f"{get_contextual_tool_class(tool_name)(team=self._team, user=self._user).format_context_prompt_injection(tool_context)}\n" # type: ignore f"" for tool_name, tool_context in self.get_contextual_tools().items() if get_contextual_tool_class(tool_name) is not None diff --git a/ee/hogai/context/test/test_context.py b/ee/hogai/context/test/test_context.py index 3bba6785df..65a59982a0 100644 --- a/ee/hogai/context/test/test_context.py +++ b/ee/hogai/context/test/test_context.py @@ -507,7 +507,7 @@ Query results: 42 events # Mock the tool class mock_tool = MagicMock() mock_tool.format_context_prompt_injection.return_value = "Tool system prompt" - mock_get_contextual_tool_class.return_value = lambda team, user, tool_call_id: mock_tool + mock_get_contextual_tool_class.return_value = lambda team, user: mock_tool config = RunnableConfig( configurable={"contextual_tools": {"search_session_recordings": {"current_filters": {}}}} diff --git a/ee/hogai/eval/README.md b/ee/hogai/eval/README.md index a5521c5f56..ba1b28218d 100644 --- a/ee/hogai/eval/README.md +++ b/ee/hogai/eval/README.md @@ -52,7 +52,7 @@ from ee.hogai.eval.base import MaxPrivateEval from ee.hogai.eval.offline.conftest import EvaluationContext, capture_score, get_eval_context from ee.hogai.eval.schema import DatasetInput from ee.hogai.eval.scorers.sql import SQLSemanticsCorrectness, SQLSyntaxCorrectness -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantState from ee.models import Conversation diff --git a/ee/hogai/eval/ci/conftest.py b/ee/hogai/eval/ci/conftest.py index 528f8317e3..ecffff38f3 100644 --- a/ee/hogai/eval/ci/conftest.py +++ b/ee/hogai/eval/ci/conftest.py @@ -19,7 +19,7 @@ from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer # We want the PostHog set_up_evals fixture here from ee.hogai.eval.conftest import set_up_evals # noqa: F401 from ee.hogai.eval.scorers import PlanAndQueryOutput -from ee.hogai.graph.graph import AssistantGraph, InsightsAssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantNodeName, AssistantState from ee.models.assistant import Conversation, CoreMemory @@ -34,28 +34,10 @@ EVAL_USER_FULL_NAME = "Karen Smith" @pytest.fixture def call_root_for_insight_generation(demo_org_team_user): # This graph structure will first get a plan, then generate the SQL query. - - insights_subgraph = ( - # Insights subgraph without query execution, so we only create the queries - InsightsAssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) - .add_query_creation_flow(next_node=AssistantNodeName.END) - .compile() - ) graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - path_map={ - "insights": AssistantNodeName.INSIGHTS_SUBGRAPH, - "insights_search": AssistantNodeName.INSIGHTS_SEARCH, - "root": AssistantNodeName.ROOT, - "search_documentation": AssistantNodeName.END, - "end": AssistantNodeName.END, - } - ) - .add_node(AssistantNodeName.INSIGHTS_SUBGRAPH, insights_subgraph) - .add_edge(AssistantNodeName.INSIGHTS_SUBGRAPH, AssistantNodeName.END) - .add_insights_search() + .add_root() # TRICKY: We need to set a checkpointer here because async tests create a new event loop. .compile(checkpointer=DjangoCheckpointer()) ) @@ -85,15 +67,21 @@ def call_root_for_insight_generation(demo_org_team_user): final_state_raw = await graph.ainvoke(final_state, {"configurable": {"thread_id": conversation.id}}) final_state = AssistantState.model_validate(final_state_raw) - if not final_state.messages or not isinstance(final_state.messages[-1], VisualizationMessage): + # The order is a viz message, tool call message, and assistant message. + if ( + not final_state.messages + or not len(final_state.messages) >= 3 + or not isinstance(final_state.messages[-3], VisualizationMessage) + ): return { "plan": None, "query": None, "query_generation_retry_count": final_state.query_generation_retry_count, } + return { - "plan": final_state.messages[-1].plan, - "query": final_state.messages[-1].answer, + "plan": final_state.messages[-3].plan, + "query": final_state.messages[-3].answer, "query_generation_retry_count": final_state.query_generation_retry_count, } diff --git a/ee/hogai/eval/ci/eval_dashboard_creation.py b/ee/hogai/eval/ci/eval_dashboard_creation.py index 1c489b8adb..04e7599a98 100644 --- a/ee/hogai/eval/ci/eval_dashboard_creation.py +++ b/ee/hogai/eval/ci/eval_dashboard_creation.py @@ -1,5 +1,4 @@ import pytest -from unittest.mock import MagicMock, patch from braintrust import EvalCase from langchain_core.runnables import RunnableConfig @@ -7,8 +6,8 @@ from langchain_core.runnables import RunnableConfig from posthog.schema import AssistantMessage, AssistantToolCall, HumanMessage from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph from ee.hogai.graph.dashboards.nodes import DashboardCreationNode +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantMessageUnion, AssistantNodeName, AssistantState, PartialAssistantState from ee.models.assistant import Conversation @@ -21,18 +20,7 @@ def call_root_for_dashboard_creation(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "create_dashboard": AssistantNodeName.END, - "insights": AssistantNodeName.END, - "search_documentation": AssistantNodeName.END, - "session_summarization": AssistantNodeName.END, - "insights_search": AssistantNodeName.END, - "create_and_query_insight": AssistantNodeName.END, - "root": AssistantNodeName.END, - "end": AssistantNodeName.END, - } - ) + .add_root(lambda state: AssistantNodeName.END) .compile(checkpointer=DjangoCheckpointer()) ) @@ -172,9 +160,7 @@ async def eval_tool_routing_dashboard_creation(call_root_for_dashboard_creation, ) -@pytest.mark.django_db -@patch("ee.hogai.graph.base.get_stream_writer", return_value=MagicMock()) -async def eval_tool_call_dashboard_creation(patch_get_stream_writer, pytestconfig, demo_org_team_user): +async def eval_tool_call_dashboard_creation(pytestconfig, demo_org_team_user): conversation = await Conversation.objects.acreate(team=demo_org_team_user[1], user=demo_org_team_user[2]) dashboard_creation_node = DashboardCreationNode(demo_org_team_user[1], demo_org_team_user[2]) diff --git a/ee/hogai/eval/ci/eval_insight_search.py b/ee/hogai/eval/ci/eval_insight_search.py index bfcd9d26b6..edd98dbde4 100644 --- a/ee/hogai/eval/ci/eval_insight_search.py +++ b/ee/hogai/eval/ci/eval_insight_search.py @@ -8,7 +8,7 @@ from braintrust import EvalCase from posthog.schema import HumanMessage, VisualizationMessage from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantNodeName, AssistantState from ee.models.assistant import Conversation @@ -84,16 +84,7 @@ def call_insight_search(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "insights": AssistantNodeName.END, - "search_documentation": AssistantNodeName.END, - "root": AssistantNodeName.END, - "end": AssistantNodeName.END, - "insights_search": AssistantNodeName.INSIGHTS_SEARCH, - } - ) - .add_insights_search() + .add_root() .compile(checkpointer=DjangoCheckpointer()) ) diff --git a/ee/hogai/eval/ci/eval_memory.py b/ee/hogai/eval/ci/eval_memory.py index a75f4520ce..abfcdcd08a 100644 --- a/ee/hogai/eval/ci/eval_memory.py +++ b/ee/hogai/eval/ci/eval_memory.py @@ -9,7 +9,7 @@ from langchain_core.messages import AIMessage as LangchainAIMessage from posthog.schema import AssistantMessage, AssistantToolCall, HumanMessage from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantNodeName, AssistantState from ee.models.assistant import Conversation diff --git a/ee/hogai/eval/ci/eval_memory_onboarding.py b/ee/hogai/eval/ci/eval_memory_onboarding.py index 124238495a..492ba7e20b 100644 --- a/ee/hogai/eval/ci/eval_memory_onboarding.py +++ b/ee/hogai/eval/ci/eval_memory_onboarding.py @@ -13,7 +13,7 @@ from posthog.models.user import User from posthog.sync import database_sync_to_async from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.graph.memory.prompts import ( ENQUIRY_INITIAL_MESSAGE, SCRAPING_SUCCESS_KEY_PHRASE, diff --git a/ee/hogai/eval/ci/eval_root.py b/ee/hogai/eval/ci/eval_root.py index 7922b61944..cbb6f6540a 100644 --- a/ee/hogai/eval/ci/eval_root.py +++ b/ee/hogai/eval/ci/eval_root.py @@ -7,7 +7,7 @@ from braintrust import EvalCase from posthog.schema import AssistantMessage, AssistantToolCall, AssistantToolCallMessage, HumanMessage from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantMessageUnion, AssistantNodeName, AssistantState from ee.models.assistant import Conversation @@ -20,16 +20,7 @@ def call_root(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "insights": AssistantNodeName.END, - "billing": AssistantNodeName.END, - "insights_search": AssistantNodeName.END, - "search_documentation": AssistantNodeName.END, - "root": AssistantNodeName.ROOT, - "end": AssistantNodeName.END, - } - ) + .add_root(lambda state: AssistantNodeName.END) # TRICKY: We need to set a checkpointer here because async tests create a new event loop. .compile(checkpointer=DjangoCheckpointer()) ) diff --git a/ee/hogai/eval/ci/eval_root_documentation.py b/ee/hogai/eval/ci/eval_root_documentation.py index 60ef3ebbe9..cb522dd44a 100644 --- a/ee/hogai/eval/ci/eval_root_documentation.py +++ b/ee/hogai/eval/ci/eval_root_documentation.py @@ -5,7 +5,7 @@ from braintrust import EvalCase from posthog.schema import AssistantMessage, AssistantToolCall, HumanMessage from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantNodeName, AssistantState from ee.models.assistant import Conversation @@ -18,17 +18,7 @@ def call_root(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - path_map={ - "insights": AssistantNodeName.END, - "billing": AssistantNodeName.END, - "insights_search": AssistantNodeName.END, - "search_documentation": AssistantNodeName.END, - "root": AssistantNodeName.ROOT, - "end": AssistantNodeName.END, - }, - tools_node=AssistantNodeName.END, - ) + .add_root(router=lambda state: AssistantNodeName.END) # TRICKY: We need to set a checkpointer here because async tests create a new event loop. .compile(checkpointer=DjangoCheckpointer()) ) diff --git a/ee/hogai/eval/ci/eval_root_entity_search.py b/ee/hogai/eval/ci/eval_root_entity_search.py index d20ff16bb4..158137f24d 100644 --- a/ee/hogai/eval/ci/eval_root_entity_search.py +++ b/ee/hogai/eval/ci/eval_root_entity_search.py @@ -5,7 +5,7 @@ from braintrust import EvalCase from posthog.schema import AssistantMessage, AssistantToolCall, HumanMessage from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantNodeName, AssistantState from ee.models.assistant import Conversation @@ -18,17 +18,7 @@ def call_root(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - path_map={ - "insights": AssistantNodeName.END, - "billing": AssistantNodeName.END, - "insights_search": AssistantNodeName.END, - "search_documentation": AssistantNodeName.END, - "root": AssistantNodeName.ROOT, - "end": AssistantNodeName.END, - }, - tools_node=AssistantNodeName.END, - ) + .add_root(router=lambda state: AssistantNodeName.END) # TRICKY: We need to set a checkpointer here because async tests create a new event loop. .compile(checkpointer=DjangoCheckpointer()) ) diff --git a/ee/hogai/eval/ci/eval_root_style.py b/ee/hogai/eval/ci/eval_root_style.py index 9e071c1b24..8b1ef101f0 100644 --- a/ee/hogai/eval/ci/eval_root_style.py +++ b/ee/hogai/eval/ci/eval_root_style.py @@ -5,7 +5,7 @@ from braintrust import EvalCase from posthog.schema import AssistantMessage, HumanMessage -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantMessageUnion, AssistantNodeName, AssistantState from ee.models.assistant import Conversation @@ -60,19 +60,7 @@ def call_root(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - # Some requests will go via Inkeep, and this is realistic! Inkeep needs to adhere to our intended style too - "search_documentation": AssistantNodeName.INKEEP_DOCS, - "root": AssistantNodeName.ROOT, - "billing": AssistantNodeName.END, - "insights": AssistantNodeName.END, - "insights_search": AssistantNodeName.END, - "session_summarization": AssistantNodeName.END, - "end": AssistantNodeName.END, - } - ) - .add_inkeep_docs() + .add_root(lambda state: AssistantNodeName.END) .compile() ) diff --git a/ee/hogai/eval/ci/eval_session_summarization.py b/ee/hogai/eval/ci/eval_session_summarization.py index 16d3ebcea6..13818dead5 100644 --- a/ee/hogai/eval/ci/eval_session_summarization.py +++ b/ee/hogai/eval/ci/eval_session_summarization.py @@ -7,7 +7,7 @@ from langchain_core.runnables import RunnableConfig from posthog.schema import AssistantMessage, AssistantToolCall, HumanMessage from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.graph.session_summaries.nodes import _SessionSearch from ee.hogai.utils.types import AssistantMessageUnion, AssistantNodeName, AssistantState from ee.hogai.utils.yaml import load_yaml_from_raw_llm_content @@ -22,16 +22,7 @@ def call_root_for_replay_sessions(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "insights": AssistantNodeName.END, - "search_documentation": AssistantNodeName.END, - "session_summarization": AssistantNodeName.END, - "insights_search": AssistantNodeName.END, - "root": AssistantNodeName.END, - "end": AssistantNodeName.END, - } - ) + .add_root(lambda state: AssistantNodeName.END) .compile(checkpointer=DjangoCheckpointer()) ) diff --git a/ee/hogai/eval/ci/eval_surveys.py b/ee/hogai/eval/ci/eval_surveys.py index b7d8d48478..3772d8eae0 100644 --- a/ee/hogai/eval/ci/eval_surveys.py +++ b/ee/hogai/eval/ci/eval_surveys.py @@ -126,9 +126,7 @@ def call_surveys_max_tool(demo_org_team_user, create_feature_flags): "change": f"Create a survey based on these instructions: {instructions}", "output": None, } - graph = FeatureFlagLookupGraph(team=team, user=user, tool_call_id="test-tool-call-id").compile_full_graph( - checkpointer=DjangoCheckpointer() - ) + graph = FeatureFlagLookupGraph(team=team, user=user).compile_full_graph(checkpointer=DjangoCheckpointer()) result = await graph.ainvoke( graph_context, config={ diff --git a/ee/hogai/eval/ci/eval_ui_context.py b/ee/hogai/eval/ci/eval_ui_context.py index 40a01776a7..3dc03e74d4 100644 --- a/ee/hogai/eval/ci/eval_ui_context.py +++ b/ee/hogai/eval/ci/eval_ui_context.py @@ -15,7 +15,7 @@ from posthog.models.action.action import Action from posthog.models.team.team import Team from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantNodeName, AssistantState from ee.models.assistant import Conversation @@ -29,14 +29,7 @@ def call_root_with_ui_context(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "insights": AssistantNodeName.END, - "docs": AssistantNodeName.END, - "root": AssistantNodeName.END, - "end": AssistantNodeName.END, - } - ) + .add_root(lambda state: AssistantNodeName.END) # TRICKY: We need to set a checkpointer here because async tests create a new event loop. .compile(checkpointer=DjangoCheckpointer()) ) diff --git a/ee/hogai/eval/ci/max_tools/eval_create_feature_flag_tool.py b/ee/hogai/eval/ci/max_tools/eval_create_feature_flag_tool.py index 05414ccb70..7b94c52384 100644 --- a/ee/hogai/eval/ci/max_tools/eval_create_feature_flag_tool.py +++ b/ee/hogai/eval/ci/max_tools/eval_create_feature_flag_tool.py @@ -81,7 +81,6 @@ async def eval_create_feature_flag_basic(pytestconfig, demo_org_team_user): tool = await CreateFeatureFlagTool.create_tool_class( team=team, user=user, - tool_call_id="test-eval-call", state=AssistantState(messages=[]), config={ "configurable": { @@ -148,7 +147,6 @@ async def eval_create_feature_flag_with_rollout(pytestconfig, demo_org_team_user tool = await CreateFeatureFlagTool.create_tool_class( team=team, user=user, - tool_call_id="test-eval-call", state=AssistantState(messages=[]), config={ "configurable": { @@ -241,7 +239,6 @@ async def eval_create_feature_flag_with_property_filters(pytestconfig, demo_org_ tool = await CreateFeatureFlagTool.create_tool_class( team=team, user=user, - tool_call_id="test-eval-call", state=AssistantState(messages=[]), config={ "configurable": { @@ -336,7 +333,6 @@ async def eval_create_feature_flag_duplicate_handling(pytestconfig, demo_org_tea tool = await CreateFeatureFlagTool.create_tool_class( team=team, user=user, - tool_call_id="test-eval-call", state=AssistantState(messages=[]), config={ "configurable": { diff --git a/ee/hogai/eval/ci/max_tools/eval_edit_dashboard_tool.py b/ee/hogai/eval/ci/max_tools/eval_edit_dashboard_tool.py index 404c6d753f..b89dc7b4bf 100644 --- a/ee/hogai/eval/ci/max_tools/eval_edit_dashboard_tool.py +++ b/ee/hogai/eval/ci/max_tools/eval_edit_dashboard_tool.py @@ -1,5 +1,4 @@ import pytest -from unittest.mock import MagicMock, patch from braintrust import EvalCase from langchain_core.runnables import RunnableConfig @@ -13,18 +12,7 @@ from ee.hogai.eval.scorers import SemanticSimilarity from ee.models.assistant import Conversation -@pytest.fixture(autouse=True) -def mock_kafka_producer(): - """Mock Kafka producer to prevent Kafka errors in tests.""" - with patch("posthog.kafka_client.client._KafkaProducer.produce") as mock_produce: - mock_future = MagicMock() - mock_produce.return_value = mock_future - yield - - -@pytest.mark.django_db -@patch("ee.hogai.graph.base.get_stream_writer", return_value=MagicMock()) -async def eval_insights_addition(patch_get_stream_writer, pytestconfig, demo_org_team_user): +async def eval_insights_addition(pytestconfig, demo_org_team_user): """Test that adding insights to dashboard executes correctly.""" dashboard = await Dashboard.objects.acreate( diff --git a/ee/hogai/eval/ci/max_tools/eval_navigate_tool.py b/ee/hogai/eval/ci/max_tools/eval_navigate_tool.py index 634ea7953f..dfa9e50c37 100644 --- a/ee/hogai/eval/ci/max_tools/eval_navigate_tool.py +++ b/ee/hogai/eval/ci/max_tools/eval_navigate_tool.py @@ -6,7 +6,7 @@ from pydantic import BaseModel, Field from posthog.schema import AssistantMessage, AssistantNavigateUrl, AssistantToolCall, FailureMessage, HumanMessage from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.types import AssistantMessageUnion, AssistantNodeName, AssistantState from ee.models.assistant import Conversation @@ -48,16 +48,7 @@ def call_root(demo_org_team_user): graph = ( AssistantGraph(demo_org_team_user[1], demo_org_team_user[2]) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "insights": AssistantNodeName.END, - "billing": AssistantNodeName.END, - "insights_search": AssistantNodeName.END, - "search_documentation": AssistantNodeName.END, - "root": AssistantNodeName.ROOT, - "end": AssistantNodeName.END, - } - ) + .add_root(lambda state: AssistantNodeName.END) # TRICKY: We need to set a checkpointer here because async tests create a new event loop. .compile(checkpointer=DjangoCheckpointer()) ) diff --git a/ee/hogai/eval/ci/max_tools/eval_revenue_analytics_filter_generation.py b/ee/hogai/eval/ci/max_tools/eval_revenue_analytics_filter_generation.py index 63562d8aa4..18839ebf12 100644 --- a/ee/hogai/eval/ci/max_tools/eval_revenue_analytics_filter_generation.py +++ b/ee/hogai/eval/ci/max_tools/eval_revenue_analytics_filter_generation.py @@ -40,9 +40,9 @@ DUMMY_CURRENT_FILTERS = RevenueAnalyticsAssistantFilters( @pytest.fixture def call_filter_revenue_analytics(demo_org_team_user): - graph = RevenueAnalyticsFilterOptionsGraph( - demo_org_team_user[1], demo_org_team_user[2], tool_call_id="test-tool-call-id" - ).compile_full_graph(checkpointer=DjangoCheckpointer()) + graph = RevenueAnalyticsFilterOptionsGraph(demo_org_team_user[1], demo_org_team_user[2]).compile_full_graph( + checkpointer=DjangoCheckpointer() + ) async def callable(change: str) -> dict: conversation = await Conversation.objects.acreate(team=demo_org_team_user[1], user=demo_org_team_user[2]) diff --git a/ee/hogai/eval/ci/max_tools/eval_session_replay_filter_generation.py b/ee/hogai/eval/ci/max_tools/eval_session_replay_filter_generation.py index 4633426cff..e7cb0f5088 100644 --- a/ee/hogai/eval/ci/max_tools/eval_session_replay_filter_generation.py +++ b/ee/hogai/eval/ci/max_tools/eval_session_replay_filter_generation.py @@ -48,9 +48,9 @@ DUMMY_CURRENT_FILTERS = MaxRecordingUniversalFilters( @pytest.fixture def call_search_session_recordings(demo_org_team_user): - graph = SessionReplayFilterOptionsGraph( - demo_org_team_user[1], demo_org_team_user[2], tool_call_id="test-tool-call-id" - ).compile_full_graph(checkpointer=DjangoCheckpointer()) + graph = SessionReplayFilterOptionsGraph(demo_org_team_user[1], demo_org_team_user[2]).compile_full_graph( + checkpointer=DjangoCheckpointer() + ) async def callable(change: str) -> dict: conversation = await Conversation.objects.acreate(team=demo_org_team_user[1], user=demo_org_team_user[2]) diff --git a/ee/hogai/eval/ci/max_tools/eval_tool_filter_generation.py b/ee/hogai/eval/ci/max_tools/eval_tool_filter_generation.py index 295439cbe0..97e8e579ef 100644 --- a/ee/hogai/eval/ci/max_tools/eval_tool_filter_generation.py +++ b/ee/hogai/eval/ci/max_tools/eval_tool_filter_generation.py @@ -48,9 +48,9 @@ DUMMY_CURRENT_FILTERS = MaxRecordingUniversalFilters( @pytest.fixture def call_search_session_recordings(demo_org_team_user): - graph = SessionReplayFilterOptionsGraph( - demo_org_team_user[1], demo_org_team_user[2], tool_call_id="test-tool-call-id" - ).compile_full_graph(checkpointer=DjangoCheckpointer()) + graph = SessionReplayFilterOptionsGraph(demo_org_team_user[1], demo_org_team_user[2]).compile_full_graph( + checkpointer=DjangoCheckpointer() + ) async def callable(change: str) -> dict: conversation = await Conversation.objects.acreate(team=demo_org_team_user[1], user=demo_org_team_user[2]) diff --git a/ee/hogai/eval/offline/eval_sql.py b/ee/hogai/eval/offline/eval_sql.py index 42de1d6636..6d8ec46f91 100644 --- a/ee/hogai/eval/offline/eval_sql.py +++ b/ee/hogai/eval/offline/eval_sql.py @@ -18,7 +18,7 @@ from ee.hogai.eval.base import MaxPrivateEval from ee.hogai.eval.offline.conftest import EvaluationContext, capture_score, get_eval_context from ee.hogai.eval.schema import DatasetInput from ee.hogai.eval.scorers.sql import SQLSemanticsCorrectness, SQLSyntaxCorrectness -from ee.hogai.graph import AssistantGraph +from ee.hogai.graph.graph import AssistantGraph from ee.hogai.utils.helpers import find_last_message_of_type from ee.hogai.utils.types import AssistantState from ee.hogai.utils.warehouse import serialize_database_schema diff --git a/ee/hogai/eval/scorers/__init__.py b/ee/hogai/eval/scorers/__init__.py index fe059ad7da..c9e0155fbe 100644 --- a/ee/hogai/eval/scorers/__init__.py +++ b/ee/hogai/eval/scorers/__init__.py @@ -41,27 +41,29 @@ class ToolRelevance(ScorerWithPartial): raise TypeError(f"Eval case expected must be an AssistantToolCall, not {type(expected)}") if not isinstance(output, AssistantMessage): raise TypeError(f"Eval case output must be an AssistantMessage, not {type(output)}") - if output.tool_calls and len(output.tool_calls) > 1: - raise ValueError("Parallel tool calls not supported by this scorer yet") - score = 0.0 # 0.0 to 1.0 - if output.tool_calls and len(output.tool_calls) == 1: - tool_call = output.tool_calls[0] - # 0.5 point for getting the tool right - if tool_call.name == expected.name: - score += 0.5 - if not expected.args: - score += 0.5 if not tool_call.args else 0 # If no args expected, only score for lack of args - else: - score_per_arg = 0.5 / len(expected.args) - for arg_name, expected_arg_value in expected.args.items(): - if arg_name in self.semantic_similarity_args: - arg_similarity = AnswerSimilarity(model="text-embedding-3-small").eval( - output=tool_call.args.get(arg_name), expected=expected_arg_value - ) - score += arg_similarity.score * score_per_arg - elif tool_call.args.get(arg_name) == expected_arg_value: - score += score_per_arg - return Score(name=self._name(), score=score) + + best_score = 0.0 # 0.0 to 1.0 + if output.tool_calls: + # Check all tool calls and return the best match + for tool_call in output.tool_calls: + score = 0.0 + # 0.5 point for getting the tool right + if tool_call.name == expected.name: + score += 0.5 + if not expected.args: + score += 0.5 if not tool_call.args else 0 # If no args expected, only score for lack of args + else: + score_per_arg = 0.5 / len(expected.args) + for arg_name, expected_arg_value in expected.args.items(): + if arg_name in self.semantic_similarity_args: + arg_similarity = AnswerSimilarity(model="text-embedding-3-small").eval( + output=tool_call.args.get(arg_name), expected=expected_arg_value + ) + score += arg_similarity.score * score_per_arg + elif tool_call.args.get(arg_name) == expected_arg_value: + score += score_per_arg + best_score = max(best_score, score) + return Score(name=self._name(), score=best_score) class PlanAndQueryOutput(TypedDict, total=False): diff --git a/ee/hogai/graph/__init__.py b/ee/hogai/graph/__init__.py index 4f88326575..e69de29bb2 100644 --- a/ee/hogai/graph/__init__.py +++ b/ee/hogai/graph/__init__.py @@ -1,33 +0,0 @@ -from .deep_research.graph import DeepResearchAssistantGraph -from .funnels.nodes import FunnelGeneratorNode -from .graph import AssistantGraph, InsightsAssistantGraph -from .inkeep_docs.nodes import InkeepDocsNode -from .insights.nodes import InsightSearchNode -from .memory.nodes import MemoryInitializerNode -from .query_executor.nodes import QueryExecutorNode -from .query_planner.nodes import QueryPlannerNode -from .rag.nodes import InsightRagContextNode -from .retention.nodes import RetentionGeneratorNode -from .root.nodes import RootNode, RootNodeTools -from .schema_generator.nodes import SchemaGeneratorNode -from .sql.nodes import SQLGeneratorNode -from .trends.nodes import TrendsGeneratorNode - -__all__ = [ - "FunnelGeneratorNode", - "InkeepDocsNode", - "MemoryInitializerNode", - "QueryExecutorNode", - "InsightRagContextNode", - "RetentionGeneratorNode", - "RootNode", - "RootNodeTools", - "SchemaGeneratorNode", - "SQLGeneratorNode", - "QueryPlannerNode", - "TrendsGeneratorNode", - "AssistantGraph", - "InsightsAssistantGraph", - "InsightSearchNode", - "DeepResearchAssistantGraph", -] diff --git a/ee/hogai/graph/base/__init__.py b/ee/hogai/graph/base/__init__.py new file mode 100644 index 0000000000..7a56583a32 --- /dev/null +++ b/ee/hogai/graph/base/__init__.py @@ -0,0 +1,9 @@ +from .graph import BaseAssistantGraph, global_checkpointer +from .node import AssistantNode, BaseAssistantNode + +__all__ = [ + "BaseAssistantNode", + "AssistantNode", + "BaseAssistantGraph", + "global_checkpointer", +] diff --git a/ee/hogai/graph/base/context.py b/ee/hogai/graph/base/context.py new file mode 100644 index 0000000000..c644e086c7 --- /dev/null +++ b/ee/hogai/graph/base/context.py @@ -0,0 +1,22 @@ +import contextvars +from contextlib import contextmanager + +from ee.hogai.utils.types.base import NodePath + +node_path_context = contextvars.ContextVar[tuple[NodePath, ...]]("node_path_context") + + +@contextmanager +def set_node_path(node_path: tuple[NodePath, ...]): + token = node_path_context.set(node_path) + try: + yield + finally: + node_path_context.reset(token) + + +def get_node_path() -> tuple[NodePath, ...] | None: + try: + return node_path_context.get() + except LookupError: + return None diff --git a/ee/hogai/graph/base/graph.py b/ee/hogai/graph/base/graph.py new file mode 100644 index 0000000000..0f6a28cba0 --- /dev/null +++ b/ee/hogai/graph/base/graph.py @@ -0,0 +1,88 @@ +from abc import ABC, abstractmethod +from collections.abc import Callable +from functools import wraps +from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar + +from langgraph.graph.state import StateGraph + +from posthog.models import Team, User + +from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer +from ee.hogai.utils.types.base import AssistantGraphName, AssistantNodeName, NodePath, PartialStateType, StateType + +from .context import get_node_path, set_node_path +from .node import BaseAssistantNode + +if TYPE_CHECKING: + from ee.hogai.utils.types.composed import MaxNodeName + + +# Base checkpointer for all graphs +global_checkpointer = DjangoCheckpointer() + +T = TypeVar("T") + + +def with_node_path(func: Callable[..., T]) -> Callable[..., T]: + @wraps(func) + def wrapper(self, *args: Any, **kwargs: Any) -> T: + with set_node_path(self.node_path): + return func(self, *args, **kwargs) + + return wrapper + + +class BaseAssistantGraph(Generic[StateType, PartialStateType], ABC): + _team: Team + _user: User + _graph: StateGraph + _node_path: tuple[NodePath, ...] + + def __init__( + self, + team: Team, + user: User, + ): + self._team = team + self._user = user + self._has_start_node = False + self._graph = StateGraph(self.state_type) + self._node_path = (*(get_node_path() or ()), NodePath(name=self.graph_name.value)) + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + # Wrap all public methods with the node path context + for name, method in cls.__dict__.items(): + if callable(method) and not name.startswith("_") and name not in ("graph_name", "state_type", "node_path"): + setattr(cls, name, with_node_path(method)) + + @property + @abstractmethod + def state_type(self) -> type[StateType]: ... + + @property + @abstractmethod + def graph_name(self) -> AssistantGraphName: ... + + @property + def node_path(self) -> tuple[NodePath, ...]: + return self._node_path + + def add_edge(self, from_node: "MaxNodeName", to_node: "MaxNodeName"): + if from_node == AssistantNodeName.START: + self._has_start_node = True + self._graph.add_edge(from_node, to_node) + return self + + def add_node(self, node: "MaxNodeName", action: BaseAssistantNode[StateType, PartialStateType]): + self._graph.add_node(node, action) + return self + + def compile(self, checkpointer: DjangoCheckpointer | None | Literal[False] = None): + if not self._has_start_node: + raise ValueError("Start node not added to the graph") + # TRICKY: We check `is not None` because False has a special meaning of "no checkpointer", which we want to pass on + compiled_graph = self._graph.compile( + checkpointer=checkpointer if checkpointer is not None else global_checkpointer + ) + return compiled_graph diff --git a/ee/hogai/graph/base.py b/ee/hogai/graph/base/node.py similarity index 53% rename from ee/hogai/graph/base.py rename to ee/hogai/graph/base/node.py index 73fc911e80..4e3f0f5636 100644 --- a/ee/hogai/graph/base.py +++ b/ee/hogai/graph/base/node.py @@ -1,49 +1,45 @@ -from abc import ABC, abstractmethod -from collections.abc import Sequence +from abc import ABC from typing import Generic from uuid import UUID from django.conf import settings from langchain_core.runnables import RunnableConfig -from langgraph.config import get_stream_writer -from posthog.schema import AssistantMessage, AssistantToolCall, HumanMessage +from posthog.schema import HumanMessage -from posthog.models import Team -from posthog.models.user import User +from posthog.models import Team, User from posthog.sync import database_sync_to_async from ee.hogai.context import AssistantContextManager -from ee.hogai.graph.mixins import AssistantContextMixin -from ee.hogai.utils.dispatcher import AssistantDispatcher +from ee.hogai.graph.base.context import get_node_path, set_node_path +from ee.hogai.graph.mixins import AssistantContextMixin, AssistantDispatcherMixin from ee.hogai.utils.exceptions import GenerationCanceled from ee.hogai.utils.helpers import find_start_message -from ee.hogai.utils.types import ( - AssistantMessageUnion, +from ee.hogai.utils.types.base import ( AssistantState, + NodeEndAction, + NodePath, + NodeStartAction, PartialAssistantState, PartialStateType, StateType, ) -from ee.hogai.utils.types.composed import MaxNodeName from ee.models import Conversation -class BaseAssistantNode(Generic[StateType, PartialStateType], AssistantContextMixin, ABC): +class BaseAssistantNode(Generic[StateType, PartialStateType], AssistantContextMixin, AssistantDispatcherMixin, ABC): _config: RunnableConfig | None = None _context_manager: AssistantContextManager | None = None - _dispatcher: AssistantDispatcher | None = None - _parent_tool_call_id: str | None = None + _node_path: tuple[NodePath, ...] - def __init__(self, team: Team, user: User): + def __init__(self, team: Team, user: User, node_path: tuple[NodePath, ...] | None = None): self._team = team self._user = user - - @property - @abstractmethod - def node_name(self) -> MaxNodeName: - raise NotImplementedError + if node_path is None: + self._node_path = (*(get_node_path() or ()), NodePath(name=self.node_name)) + else: + self._node_path = node_path async def __call__(self, state: StateType, config: RunnableConfig) -> PartialStateType | None: """ @@ -54,25 +50,19 @@ class BaseAssistantNode(Generic[StateType, PartialStateType], AssistantContextMi self._dispatcher = None self._config = config - if isinstance(state, AssistantState) and state.root_tool_call_id: - # NOTE: we set the parent tool call id as the root tool call id - # This will be deprecated once all tools become MaxTools and are removed from the graph - self._parent_tool_call_id = state.root_tool_call_id - - self.dispatcher.node_start() + self.dispatcher.dispatch(NodeStartAction()) thread_id = (config.get("configurable") or {}).get("thread_id") if thread_id and await self._is_conversation_cancelled(thread_id): raise GenerationCanceled try: - new_state = await self.arun(state, config) + new_state = await self._arun_with_context(state, config) except NotImplementedError: - new_state = await database_sync_to_async(self.run, thread_sensitive=False)(state, config) + new_state = await database_sync_to_async(self._run_with_context, thread_sensitive=False)(state, config) + + self.dispatcher.dispatch(NodeEndAction(state=new_state)) - if new_state is not None and (messages := getattr(new_state, "messages", [])): - for message in messages: - self.dispatcher.message(message) return new_state def run(self, state: StateType, config: RunnableConfig) -> PartialStateType | None: @@ -82,6 +72,14 @@ class BaseAssistantNode(Generic[StateType, PartialStateType], AssistantContextMi async def arun(self, state: StateType, config: RunnableConfig) -> PartialStateType | None: raise NotImplementedError + def _run_with_context(self, state: StateType, config: RunnableConfig) -> PartialStateType | None: + with set_node_path(self.node_path): + return self.run(state, config) + + async def _arun_with_context(self, state: StateType, config: RunnableConfig) -> PartialStateType | None: + with set_node_path(self.node_path): + return await self.arun(state, config) + @property def context_manager(self) -> AssistantContextManager: if self._context_manager is None: @@ -97,26 +95,13 @@ class BaseAssistantNode(Generic[StateType, PartialStateType], AssistantContextMi return self._context_manager @property - def dispatcher(self) -> AssistantDispatcher: - """Create a dispatcher for this node""" - if self._dispatcher: - return self._dispatcher - - # Set writer from LangGraph context - try: - writer = get_stream_writer() - except RuntimeError: - # Not in streaming context (e.g., testing) - # Use noop writer - def noop(*_args, **_kwargs): - pass - - writer = noop - - self._dispatcher = AssistantDispatcher( - writer, node_name=self.node_name, parent_tool_call_id=self._parent_tool_call_id - ) - return self._dispatcher + def node_name(self) -> str: + config_name: str | None = None + if self._config: + config_name = self._config["metadata"].get("langgraph_node") + if config_name is not None: + config_name = str(config_name) + return config_name or self.__class__.__name__ async def _is_conversation_cancelled(self, conversation_id: UUID) -> bool: conversation = await self._aget_conversation(conversation_id) @@ -124,15 +109,6 @@ class BaseAssistantNode(Generic[StateType, PartialStateType], AssistantContextMi raise ValueError(f"Conversation {conversation_id} not found") return conversation.status == Conversation.Status.CANCELING - def _get_tool_call(self, messages: Sequence[AssistantMessageUnion], tool_call_id: str) -> AssistantToolCall: - for message in reversed(messages): - if not isinstance(message, AssistantMessage) or not message.tool_calls: - continue - for tool_call in message.tool_calls: - if tool_call.id == tool_call_id: - return tool_call - raise ValueError(f"Tool call {tool_call_id} not found in state") - def _is_first_turn(self, state: AssistantState) -> bool: last_message = state.messages[-1] if isinstance(last_message, HumanMessage): diff --git a/ee/hogai/graph/billing/__init__.py b/ee/hogai/graph/base/test/__init__.py similarity index 100% rename from ee/hogai/graph/billing/__init__.py rename to ee/hogai/graph/base/test/__init__.py diff --git a/ee/hogai/graph/base/test/test_assistant_graph.py b/ee/hogai/graph/base/test/test_assistant_graph.py new file mode 100644 index 0000000000..6329293848 --- /dev/null +++ b/ee/hogai/graph/base/test/test_assistant_graph.py @@ -0,0 +1,47 @@ +from posthog.test.base import BaseTest + +from langgraph.checkpoint.memory import InMemorySaver + +from ee.hogai.graph.base import AssistantNode +from ee.hogai.graph.base.graph import BaseAssistantGraph +from ee.hogai.utils.types import AssistantNodeName, AssistantState, PartialAssistantState +from ee.hogai.utils.types.base import AssistantGraphName +from ee.models import Conversation + + +class TestAssistantGraph(BaseTest): + async def test_pydantic_state_resets_with_none(self): + """When a None field is set, it should be reset to None.""" + + class TestAssistantGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + graph = TestAssistantGraph(self.team, self.user) + + class TestNode(AssistantNode): + @property + def node_name(self): + return AssistantNodeName.ROOT + + async def arun(self, state, config): + return PartialAssistantState(start_id=None) + + compiled_graph = ( + graph.add_node(AssistantNodeName.ROOT, TestNode(self.team, self.user)) + .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + .add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + .compile(checkpointer=InMemorySaver()) + ) + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + state = await compiled_graph.ainvoke( + AssistantState(messages=[], graph_status="resumed", start_id=None), + {"configurable": {"thread_id": conversation.id}}, + ) + self.assertEqual(state["start_id"], None) + self.assertEqual(state["graph_status"], "resumed") diff --git a/ee/hogai/graph/base/test/test_node_path.py b/ee/hogai/graph/base/test/test_node_path.py new file mode 100644 index 0000000000..d1c8961831 --- /dev/null +++ b/ee/hogai/graph/base/test/test_node_path.py @@ -0,0 +1,502 @@ +from posthog.test.base import BaseTest + +from langchain_core.runnables import RunnableConfig + +from ee.hogai.graph.base import AssistantNode +from ee.hogai.graph.base.context import get_node_path +from ee.hogai.graph.base.graph import BaseAssistantGraph +from ee.hogai.utils.types import AssistantNodeName, AssistantState, PartialAssistantState +from ee.hogai.utils.types.base import AssistantGraphName, NodePath +from ee.models import Conversation + + +class TestNodePath(BaseTest): + """ + Tests for node_path functionality across sync/async methods and graph compositions. + """ + + async def test_graph_to_async_node_has_two_elements(self): + """Graph -> Node (async) should have path: [graph, node]""" + captured_path = None + + class TestNode(AssistantNode): + async def arun(self, state, config): + nonlocal captured_path + captured_path = get_node_path() + return None + + class TestGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + def setup(self): + node = TestNode(self._team, self._user) + self.add_node(AssistantNodeName.ROOT, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + self.add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + return self + + graph = TestGraph(self.team, self.user) + compiled = graph.setup().compile(checkpointer=False) + + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + await compiled.ainvoke(AssistantState(messages=[]), {"configurable": {"thread_id": conversation.id}}) + + assert captured_path is not None + self.assertEqual(len(captured_path), 2) + self.assertEqual(captured_path[0].name, AssistantGraphName.ASSISTANT.value) + # Node name is determined at init time, so it's the class name + self.assertEqual(captured_path[1].name, "TestNode") + + async def test_graph_to_sync_node_has_two_elements(self): + """Graph -> Node (sync) should have path: [graph, node]""" + captured_path = None + + class TestNode(AssistantNode): + def run(self, state, config): + nonlocal captured_path + captured_path = get_node_path() + return None + + class TestGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + def setup(self): + node = TestNode(self._team, self._user) + self.add_node(AssistantNodeName.ROOT, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + self.add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + return self + + graph = TestGraph(self.team, self.user) + compiled = graph.setup().compile(checkpointer=False) + + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + await compiled.ainvoke(AssistantState(messages=[]), {"configurable": {"thread_id": conversation.id}}) + + assert captured_path is not None + self.assertEqual(len(captured_path), 2) + self.assertEqual(captured_path[0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_path[1].name, "TestNode") + + async def test_graph_to_node_to_async_node_has_three_elements(self): + """Graph -> Node -> Node (async) should have path: [graph, node, node]""" + captured_paths = [] + + class SecondNode(AssistantNode): + async def arun(self, state, config): + nonlocal captured_paths + captured_paths.append(get_node_path()) + return None + + class FirstNode(AssistantNode): + async def arun(self, state, config): + nonlocal captured_paths + captured_paths.append(get_node_path()) + # Call second node + second_node = SecondNode(self._team, self._user) + await second_node(state, config) + return None + + class TestGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + def setup(self): + node = FirstNode(self._team, self._user) + self.add_node(AssistantNodeName.ROOT, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + self.add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + return self + + graph = TestGraph(self.team, self.user) + compiled = graph.setup().compile(checkpointer=False) + + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + await compiled.ainvoke(AssistantState(messages=[]), {"configurable": {"thread_id": conversation.id}}) + + # First node: [graph, node] + assert captured_paths[0] is not None + self.assertEqual(len(captured_paths[0]), 2) + self.assertEqual(captured_paths[0][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[0][1].name, "FirstNode") + + # Second node: [graph, node, node] + assert captured_paths[1] is not None + self.assertEqual(len(captured_paths[1]), 3) + self.assertEqual(captured_paths[1][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[1][1].name, "FirstNode") + self.assertEqual(captured_paths[1][2].name, "SecondNode") + + async def test_graph_to_node_to_sync_node_has_three_elements(self): + """Graph -> Node -> Node (sync) - calling .run() directly doesn't extend path""" + captured_paths = [] + + class SecondNode(AssistantNode): + def run(self, state, config): + nonlocal captured_paths + captured_paths.append(get_node_path()) + return None + + class FirstNode(AssistantNode): + def run(self, state, config): + nonlocal captured_paths + captured_paths.append(get_node_path()) + # Call second node - note: calling run() directly bypasses context setting, + # so the second node won't have the proper path. This tests that direct .run() + # calls don't propagate context properly. + second_node = SecondNode(self._team, self._user) + second_node.run(state, config) + return None + + class TestGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + def setup(self): + node = FirstNode(self._team, self._user) + self.add_node(AssistantNodeName.ROOT, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + self.add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + return self + + graph = TestGraph(self.team, self.user) + compiled = graph.setup().compile(checkpointer=False) + + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + await compiled.ainvoke(AssistantState(messages=[]), {"configurable": {"thread_id": conversation.id}}) + + # First node: [graph, node] + assert captured_paths[0] is not None + self.assertEqual(len(captured_paths[0]), 2) + self.assertEqual(captured_paths[0][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[0][1].name, "FirstNode") + + # Second node: [graph, node] - initialized within FirstNode's context, so gets same path + assert captured_paths[1] is not None + self.assertEqual(len(captured_paths[1]), 2) + self.assertEqual(captured_paths[1][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[1][1].name, "FirstNode") # Same as first because initialized in same context + + async def test_graph_to_node_to_graph_to_node_has_four_elements(self): + """Graph -> Node -> Graph -> Node should have path: [graph, node, graph, node]""" + captured_paths = [] + + class InnerNode(AssistantNode): + async def arun(self, state, config): + nonlocal captured_paths + captured_paths.append(get_node_path()) + return None + + class InnerGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.INSIGHTS + + def setup(self): + node = InnerNode(self._team, self._user) + self.add_node(AssistantNodeName.TRENDS_GENERATOR, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.TRENDS_GENERATOR) + self.add_edge(AssistantNodeName.TRENDS_GENERATOR, AssistantNodeName.END) + return self + + class OuterNode(AssistantNode): + async def arun(self, state, config): + nonlocal captured_paths + captured_paths.append(get_node_path()) + # Call inner graph + inner_graph = InnerGraph(self._team, self._user) + compiled_inner = inner_graph.setup().compile(checkpointer=False) + await compiled_inner.ainvoke(state, config) + return None + + class OuterGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + def setup(self): + node = OuterNode(self._team, self._user) + self.add_node(AssistantNodeName.ROOT, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + self.add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + return self + + outer_graph = OuterGraph(self.team, self.user) + compiled = outer_graph.setup().compile(checkpointer=False) + + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + await compiled.ainvoke(AssistantState(messages=[]), {"configurable": {"thread_id": conversation.id}}) + + # Outer node: [graph, node] + assert captured_paths[0] is not None + self.assertEqual(len(captured_paths[0]), 2) + self.assertEqual(captured_paths[0][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[0][1].name, "OuterNode") + + # Inner node: [graph, node, graph, node] + assert captured_paths[1] is not None + self.assertEqual(len(captured_paths[1]), 4) + self.assertEqual(captured_paths[1][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[1][1].name, "OuterNode") + self.assertEqual(captured_paths[1][2].name, AssistantGraphName.INSIGHTS.value) + self.assertEqual(captured_paths[1][3].name, "InnerNode") + + async def test_graph_to_graph_to_node_has_three_elements(self): + """Graph -> Graph -> Node should have path: [graph, graph, node]""" + captured_path = None + + class InnerNode(AssistantNode): + async def arun(self, state, config): + nonlocal captured_path + captured_path = get_node_path() + return None + + class InnerGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.INSIGHTS + + def setup(self): + node = InnerNode(self._team, self._user) + self.add_node(AssistantNodeName.TRENDS_GENERATOR, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.TRENDS_GENERATOR) + self.add_edge(AssistantNodeName.TRENDS_GENERATOR, AssistantNodeName.END) + return self + + class OuterGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + async def invoke_inner_graph(self, state, config): + inner_graph = InnerGraph(self._team, self._user) + compiled_inner = inner_graph.setup().compile(checkpointer=False) + await compiled_inner.ainvoke(state, config) + + outer_graph = OuterGraph(self.team, self.user) + + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + await outer_graph.invoke_inner_graph( + AssistantState(messages=[]), RunnableConfig(configurable={"thread_id": conversation.id}) + ) + + # Inner node: [graph, node] - outer graph context is not propagated when calling graph methods directly + assert captured_path is not None + self.assertEqual(len(captured_path), 2) + self.assertEqual(captured_path[0].name, AssistantGraphName.INSIGHTS.value) + self.assertEqual(captured_path[1].name, "InnerNode") + + async def test_node_path_preserved_across_async_and_sync_methods(self): + """Test that calling .run() directly doesn't extend path""" + captured_paths = [] + + class SyncNode(AssistantNode): + def run(self, state, config): + nonlocal captured_paths + captured_paths.append(("sync", get_node_path())) + return None + + class AsyncNode(AssistantNode): + async def arun(self, state, config): + nonlocal captured_paths + captured_paths.append(("async", get_node_path())) + # Call sync node - calling .run() directly bypasses context setting + sync_node = SyncNode(self._team, self._user) + sync_node.run(state, config) + return None + + class TestGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + def setup(self): + node = AsyncNode(self._team, self._user) + self.add_node(AssistantNodeName.ROOT, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + self.add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + return self + + graph = TestGraph(self.team, self.user) + compiled = graph.setup().compile(checkpointer=False) + + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + await compiled.ainvoke(AssistantState(messages=[]), {"configurable": {"thread_id": conversation.id}}) + + # Async node: [graph, node] + self.assertEqual(captured_paths[0][0], "async") + assert captured_paths[0][1] is not None + self.assertEqual(len(captured_paths[0][1]), 2) + self.assertEqual(captured_paths[0][1][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[0][1][1].name, "AsyncNode") + + # Sync node: [graph, node] - initialized within AsyncNode's context, so gets same path + self.assertEqual(captured_paths[1][0], "sync") + assert captured_paths[1][1] is not None + self.assertEqual(len(captured_paths[1][1]), 2) + self.assertEqual(captured_paths[1][1][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[1][1][1].name, "AsyncNode") # Same as async because initialized in same context + + def test_node_path_with_explicit_node_path_parameter(self): + """Test that explicitly passing node_path overrides default behavior""" + custom_path = (NodePath(name="custom_graph"), NodePath(name="custom_node")) + + class TestNode(AssistantNode): + def run(self, state, config): + return None + + node = TestNode(self.team, self.user, node_path=custom_path) + + self.assertEqual(len(node._node_path), 2) + self.assertEqual(node._node_path[0].name, "custom_graph") + self.assertEqual(node._node_path[1].name, "custom_node") + + async def test_multiple_nested_graphs(self): + """Test deeply nested graph composition: Graph -> Node -> Graph -> Node -> Graph -> Node""" + captured_paths = [] + + class Level3Node(AssistantNode): + async def arun(self, state, config): + nonlocal captured_paths + captured_paths.append(("level3", get_node_path())) + return None + + class Level3Graph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.TAXONOMY + + def setup(self): + node = Level3Node(self._team, self._user) + self.add_node(AssistantNodeName.FUNNEL_GENERATOR, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.FUNNEL_GENERATOR) + self.add_edge(AssistantNodeName.FUNNEL_GENERATOR, AssistantNodeName.END) + return self + + class Level2Node(AssistantNode): + async def arun(self, state, config): + nonlocal captured_paths + captured_paths.append(("level2", get_node_path())) + # Call level 3 graph + level3_graph = Level3Graph(self._team, self._user) + compiled = level3_graph.setup().compile(checkpointer=False) + await compiled.ainvoke(state, config) + return None + + class Level2Graph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.INSIGHTS + + def setup(self): + node = Level2Node(self._team, self._user) + self.add_node(AssistantNodeName.TRENDS_GENERATOR, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.TRENDS_GENERATOR) + self.add_edge(AssistantNodeName.TRENDS_GENERATOR, AssistantNodeName.END) + return self + + class Level1Node(AssistantNode): + async def arun(self, state, config): + nonlocal captured_paths + captured_paths.append(("level1", get_node_path())) + # Call level 2 graph + level2_graph = Level2Graph(self._team, self._user) + compiled = level2_graph.setup().compile(checkpointer=False) + await compiled.ainvoke(state, config) + return None + + class Level1Graph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT + + def setup(self): + node = Level1Node(self._team, self._user) + self.add_node(AssistantNodeName.ROOT, node) + self.add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + self.add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + return self + + level1_graph = Level1Graph(self.team, self.user) + compiled = level1_graph.setup().compile(checkpointer=False) + + conversation = await Conversation.objects.acreate(team=self.team, user=self.user) + await compiled.ainvoke(AssistantState(messages=[]), {"configurable": {"thread_id": conversation.id}}) + + # Level 1: [graph, node] + assert captured_paths[0][1] is not None + self.assertEqual(len(captured_paths[0][1]), 2) + self.assertEqual(captured_paths[0][1][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[0][1][1].name, "Level1Node") + + # Level 2: [graph, node, graph, node] + assert captured_paths[1][1] is not None + self.assertEqual(len(captured_paths[1][1]), 4) + self.assertEqual(captured_paths[1][1][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[1][1][1].name, "Level1Node") + self.assertEqual(captured_paths[1][1][2].name, AssistantGraphName.INSIGHTS.value) + self.assertEqual(captured_paths[1][1][3].name, "Level2Node") + + # Level 3: [graph, node, graph, node, graph, node] + assert captured_paths[2][1] is not None + self.assertEqual(len(captured_paths[2][1]), 6) + self.assertEqual(captured_paths[2][1][0].name, AssistantGraphName.ASSISTANT.value) + self.assertEqual(captured_paths[2][1][1].name, "Level1Node") + self.assertEqual(captured_paths[2][1][2].name, AssistantGraphName.INSIGHTS.value) + self.assertEqual(captured_paths[2][1][3].name, "Level2Node") + self.assertEqual(captured_paths[2][1][4].name, AssistantGraphName.TAXONOMY.value) + self.assertEqual(captured_paths[2][1][5].name, "Level3Node") diff --git a/ee/hogai/graph/dashboards/nodes.py b/ee/hogai/graph/dashboards/nodes.py index d5af4b494c..4d820acd2e 100644 --- a/ee/hogai/graph/dashboards/nodes.py +++ b/ee/hogai/graph/dashboards/nodes.py @@ -89,13 +89,6 @@ class DashboardCreationNode(AssistantNode): def _get_found_insight_count(self, queries_metadata: dict[str, QueryMetadata]) -> int: return sum(len(query.found_insight_ids) for query in queries_metadata.values()) - def _dispatch_update_message(self, content: str) -> None: - self.dispatcher.message( - AssistantMessage( - content=content, - ) - ) - async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: dashboard_name = ( state.dashboard_name[:50] if state.dashboard_name else "Analytics Dashboard" @@ -117,18 +110,18 @@ class DashboardCreationNode(AssistantNode): for i, query in enumerate(state.search_insights_queries) } - self._dispatch_update_message(f"Searching for {pluralize(len(state.search_insights_queries), 'insight')}") + self.dispatcher.update(f"Searching for {pluralize(len(state.search_insights_queries), 'insight')}") result = await self._search_insights(result, config) - self._dispatch_update_message(f"Found {pluralize(self._get_found_insight_count(result), 'insight')}") + self.dispatcher.update(f"Found {pluralize(self._get_found_insight_count(result), 'insight')}") left_to_create = { query_id: result[query_id].query for query_id in result.keys() if not result[query_id].found_insight_ids } if left_to_create: - self._dispatch_update_message(f"Will create {pluralize(len(left_to_create), 'insight')}") + self.dispatcher.update(f"Will create {pluralize(len(left_to_create), 'insight')}") result = await self._create_insights(left_to_create, result, config) @@ -187,9 +180,7 @@ class DashboardCreationNode(AssistantNode): message = AssistantMessage(content="", id=str(uuid4()), tool_calls=tool_calls) executor = DashboardCreationExecutorNode(self._team, self._user) - result = await executor.arun( - AssistantState(messages=[message], root_tool_call_id=self._parent_tool_call_id), config - ) + result = await executor.arun(AssistantState(messages=[message], root_tool_call_id=self.tool_call_id), config) query_metadata = await self._process_insight_creation_results(tool_calls, result.task_results, query_metadata) @@ -211,9 +202,7 @@ class DashboardCreationNode(AssistantNode): message = AssistantMessage(content="", id=str(uuid4()), tool_calls=tool_calls) executor = DashboardCreationExecutorNode(self._team, self._user) - result = await executor.arun( - AssistantState(messages=[message], root_tool_call_id=self._parent_tool_call_id), config - ) + result = await executor.arun(AssistantState(messages=[message], root_tool_call_id=self.tool_call_id), config) final_task_executor_state = BaseStateWithTasks.model_validate(result) for task_result in final_task_executor_state.task_results: @@ -307,7 +296,7 @@ class DashboardCreationNode(AssistantNode): self, dashboard_name: str, insights: set[int], dashboard_id: int | None = None ) -> tuple[Dashboard, list[Insight]]: """Create a dashboard and add the insights to it.""" - self._dispatch_update_message("Saving your dashboard") + self.dispatcher.update("Saving your dashboard") @database_sync_to_async @transaction.atomic diff --git a/ee/hogai/graph/dashboards/test/test_nodes.py b/ee/hogai/graph/dashboards/test/test_nodes.py index a53bf0b9ac..cb0fd2e3c9 100644 --- a/ee/hogai/graph/dashboards/test/test_nodes.py +++ b/ee/hogai/graph/dashboards/test/test_nodes.py @@ -1,5 +1,5 @@ import pytest -from unittest import TestCase +from posthog.test.base import BaseTest from unittest.mock import AsyncMock, MagicMock, patch from langchain_core.runnables import RunnableConfig @@ -11,10 +11,17 @@ from posthog.models import Dashboard, Insight, Team, User from ee.hogai.graph.dashboards.nodes import DashboardCreationExecutorNode, DashboardCreationNode, QueryMetadata from ee.hogai.utils.helpers import build_dashboard_url, build_insight_url from ee.hogai.utils.types import AssistantState, PartialAssistantState -from ee.hogai.utils.types.base import BaseStateWithTasks, InsightArtifact, InsightQuery, TaskResult +from ee.hogai.utils.types.base import ( + AssistantNodeName, + BaseStateWithTasks, + InsightArtifact, + InsightQuery, + NodePath, + TaskResult, +) -class TestQueryMetadata(TestCase): +class TestQueryMetadata(BaseTest): def test_query_metadata_initialization(self): """Test QueryMetadata initialization with all fields.""" query = InsightQuery(name="Test Query", description="Test Description") @@ -33,21 +40,30 @@ class TestQueryMetadata(TestCase): self.assertEqual(metadata.query, query) -class TestDashboardCreationExecutorNode: - @pytest.fixture(autouse=True) - def setup_method(self): +class TestDashboardCreationExecutorNode(BaseTest): + def setUp(self): + super().setUp() self.mock_team = MagicMock(spec=Team) self.mock_team.id = 1 self.mock_user = MagicMock(spec=User) self.mock_user.id = 1 - self.node = DashboardCreationExecutorNode(self.mock_team, self.mock_user) + self.node = DashboardCreationExecutorNode( + self.mock_team, + self.mock_user, + ( + NodePath( + name=AssistantNodeName.DASHBOARD_CREATION_EXECUTOR.value, + message_id="test_message_id", + tool_call_id="test_tool_call_id", + ), + ), + ) def test_initialization(self): """Test node initialization.""" assert self.node._team == self.mock_team assert self.node._user == self.mock_user - @pytest.mark.asyncio async def test_aget_input_tuples_search_insights(self): """Test _aget_input_tuples for search_insights tasks.""" tool_calls = [ @@ -62,7 +78,6 @@ class TestDashboardCreationExecutorNode: assert task.name == "search_insights" assert callable_func == self.node._execute_search_insights - @pytest.mark.asyncio async def test_aget_input_tuples_create_insight(self): """Test _aget_input_tuples for create_insight tasks.""" tool_calls = [AssistantToolCall(id="task_1", name="create_insight", args={"query_description": "Test prompt"})] @@ -75,7 +90,6 @@ class TestDashboardCreationExecutorNode: assert task.name == "create_insight" assert callable_func == self.node._execute_create_insight - @pytest.mark.asyncio async def test_aget_input_tuples_unsupported_task(self): """Test _aget_input_tuples raises error for unsupported task type.""" tool_calls = [AssistantToolCall(id="task_1", name="unsupported_type", args={"query": "Test prompt"})] @@ -85,7 +99,6 @@ class TestDashboardCreationExecutorNode: assert "Unsupported task type: unsupported_type" in str(exc_info.value) - @pytest.mark.asyncio async def test_aget_input_tuples_no_tasks(self): """Test _aget_input_tuples returns empty list when no tasks.""" tool_calls: list[AssistantToolCall] = [] @@ -95,14 +108,24 @@ class TestDashboardCreationExecutorNode: assert len(input_tuples) == 0 -class TestDashboardCreationNode: - @pytest.fixture(autouse=True) - def setup_method(self): +class TestDashboardCreationNode(BaseTest): + def setUp(self): + super().setUp() self.mock_team = MagicMock(spec=Team) self.mock_team.id = 1 self.mock_user = MagicMock(spec=User) self.mock_user.id = 1 - self.node = DashboardCreationNode(self.mock_team, self.mock_user) + self.node = DashboardCreationNode( + self.mock_team, + self.mock_user, + ( + NodePath( + name=AssistantNodeName.DASHBOARD_CREATION.value, + message_id="test_message_id", + tool_call_id="test_tool_call_id", + ), + ), + ) def test_get_found_insight_count(self): """Test _get_found_insight_count calculates correct count.""" @@ -140,7 +163,6 @@ class TestDashboardCreationNode: expected_url = f"/project/{self.mock_team.id}/dashboard/{dashboard_id}" assert url == expected_url - @pytest.mark.asyncio @patch("ee.hogai.graph.dashboards.nodes.DashboardCreationExecutorNode") async def test_arun_missing_search_insights_queries(self, mock_executor_node_class): """Test arun returns error when search_insights_queries is missing.""" @@ -150,7 +172,7 @@ class TestDashboardCreationNode: state = AssistantState( dashboard_name="Create dashboard", search_insights_queries=None, - root_tool_call_id="test_call", + root_tool_call_id="test_tool_call_id", ) config = RunnableConfig() @@ -161,7 +183,6 @@ class TestDashboardCreationNode: assert isinstance(result.messages[0], AssistantToolCallMessage) assert "Search insights queries are required" in result.messages[0].content - @pytest.mark.asyncio @patch("ee.hogai.graph.dashboards.nodes.DashboardCreationExecutorNode") @patch.object(DashboardCreationNode, "_search_insights") @patch.object(DashboardCreationNode, "_create_insights") @@ -205,7 +226,7 @@ class TestDashboardCreationNode: state = AssistantState( dashboard_name="Create dashboard", search_insights_queries=[InsightQuery(name="Query 1", description="Description 1")], - root_tool_call_id="test_call", + root_tool_call_id="test_tool_call_id", ) config = RunnableConfig() @@ -217,7 +238,6 @@ class TestDashboardCreationNode: assert "Dashboard Created" in result.messages[0].content assert "Test Dashboard" in result.messages[0].content - @pytest.mark.asyncio @patch("ee.hogai.graph.dashboards.nodes.DashboardCreationExecutorNode") @patch.object(DashboardCreationNode, "_search_insights") @patch.object(DashboardCreationNode, "_create_insights") @@ -244,7 +264,7 @@ class TestDashboardCreationNode: state = AssistantState( dashboard_name="Create dashboard", search_insights_queries=[InsightQuery(name="Query 1", description="Description 1")], - root_tool_call_id="test_call", + root_tool_call_id="test_tool_call_id", ) config = RunnableConfig() @@ -255,7 +275,6 @@ class TestDashboardCreationNode: assert isinstance(result.messages[0], AssistantToolCallMessage) assert "No existing insights matched" in result.messages[0].content - @pytest.mark.asyncio @patch("ee.hogai.graph.dashboards.nodes.DashboardCreationExecutorNode") @patch.object(DashboardCreationNode, "_search_insights") @patch("ee.hogai.graph.dashboards.nodes.logger") @@ -268,7 +287,7 @@ class TestDashboardCreationNode: state = AssistantState( dashboard_name="Create dashboard", search_insights_queries=[InsightQuery(name="Query 1", description="Description 1")], - root_tool_call_id="test_call", + root_tool_call_id="test_tool_call_id", ) config = RunnableConfig() @@ -295,7 +314,7 @@ class TestDashboardCreationNode: result = self.node._create_success_response( mock_dashboard, mock_insights, # type: ignore[arg-type] - "test_call", + "test_tool_call_id", ["Query without insights"], ) @@ -309,7 +328,7 @@ class TestDashboardCreationNode: def test_create_no_insights_response(self): """Test _create_no_insights_response creates correct no insights message.""" - result = self.node._create_no_insights_response("test_call", "No insights found") + result = self.node._create_no_insights_response("test_tool_call_id", "No insights found") assert isinstance(result, PartialAssistantState) assert len(result.messages) == 1 @@ -320,27 +339,30 @@ class TestDashboardCreationNode: def test_create_error_response(self): """Test _create_error_response creates correct error message.""" with patch("ee.hogai.graph.dashboards.nodes.capture_exception") as mock_capture: - result = self.node._create_error_response("Test error", "test_call") + result = self.node._create_error_response("Test error", "test_tool_call_id") assert isinstance(result, PartialAssistantState) assert len(result.messages) == 1 assert isinstance(result.messages[0], AssistantToolCallMessage) assert result.messages[0].content == "Test error" assert isinstance(result.messages[0], AssistantToolCallMessage) - assert result.messages[0].tool_call_id == "test_call" + assert result.messages[0].tool_call_id == "test_tool_call_id" mock_capture.assert_called_once() -class TestDashboardCreationNodeAsyncMethods: - @pytest.fixture(autouse=True) - def setup_method(self): +class TestDashboardCreationNodeAsyncMethods(BaseTest): + def setUp(self): + super().setUp() self.mock_team = MagicMock(spec=Team) self.mock_team.id = 1 self.mock_user = MagicMock(spec=User) self.mock_user.id = 1 - self.node = DashboardCreationNode(self.mock_team, self.mock_user) + self.node = DashboardCreationNode( + self.mock_team, + self.mock_user, + node_path=(NodePath(name="test_node", message_id="test-id", tool_call_id="test_tool_call_id"),), + ) - @pytest.mark.asyncio @patch("ee.hogai.graph.dashboards.nodes.DashboardCreationExecutorNode") async def test_create_insights(self, mock_executor_node_class): """Test _create_insights method.""" @@ -389,7 +411,6 @@ class TestDashboardCreationNodeAsyncMethods: assert len(result["task_1"].created_insight_ids) == 2 assert len(result["task_1"].created_insight_messages) == 1 - @pytest.mark.asyncio @patch("ee.hogai.graph.dashboards.nodes.DashboardCreationExecutorNode") async def test_search_insights(self, mock_executor_node_class): """Test _search_insights method.""" @@ -430,7 +451,6 @@ class TestDashboardCreationNodeAsyncMethods: assert len(result["task_1"].found_insight_ids) == 2 assert len(result["task_1"].found_insight_messages) == 2 - @pytest.mark.asyncio @patch("ee.hogai.graph.dashboards.nodes.database_sync_to_async") async def test_create_dashboard_with_insights(self, mock_db_sync): """Test _create_dashboard_with_insights method.""" @@ -452,7 +472,6 @@ class TestDashboardCreationNodeAsyncMethods: assert result[1] == mock_insights mock_sync_func.assert_called_once() - @pytest.mark.asyncio async def test_process_insight_creation_results(self): """Test _process_insight_creation_results method.""" # Create simple mocked Team and User instances like other tests diff --git a/ee/hogai/graph/deep_research/graph.py b/ee/hogai/graph/deep_research/graph.py index 1cb3e68d73..d442f5366f 100644 --- a/ee/hogai/graph/deep_research/graph.py +++ b/ee/hogai/graph/deep_research/graph.py @@ -1,21 +1,25 @@ from typing import Literal, Optional -from posthog.models.team.team import Team -from posthog.models.user import User - from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer +from ee.hogai.graph.base import BaseAssistantGraph from ee.hogai.graph.deep_research.notebook.nodes import DeepResearchNotebookPlanningNode from ee.hogai.graph.deep_research.onboarding.nodes import DeepResearchOnboardingNode from ee.hogai.graph.deep_research.planner.nodes import DeepResearchPlannerNode, DeepResearchPlannerToolsNode from ee.hogai.graph.deep_research.report.nodes import DeepResearchReportNode from ee.hogai.graph.deep_research.task_executor.nodes import DeepResearchTaskExecutorNode -from ee.hogai.graph.deep_research.types import DeepResearchNodeName, DeepResearchState -from ee.hogai.graph.graph import BaseAssistantGraph +from ee.hogai.graph.deep_research.types import DeepResearchNodeName, DeepResearchState, PartialDeepResearchState +from ee.hogai.graph.title_generator.nodes import TitleGeneratorNode +from ee.hogai.utils.types.base import AssistantGraphName -class DeepResearchAssistantGraph(BaseAssistantGraph[DeepResearchState]): - def __init__(self, team: Team, user: User): - super().__init__(team, user, DeepResearchState) +class DeepResearchAssistantGraph(BaseAssistantGraph[DeepResearchState, PartialDeepResearchState]): + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.DEEP_RESEARCH + + @property + def state_type(self) -> type[DeepResearchState]: + return DeepResearchState def add_onboarding_node( self, node_map: Optional[dict[Literal["onboarding", "planning", "continue"], DeepResearchNodeName]] = None @@ -80,13 +84,21 @@ class DeepResearchAssistantGraph(BaseAssistantGraph[DeepResearchState]): builder.add_edge(DeepResearchNodeName.REPORT, next_node) return self + def add_title_generator(self, end_node: DeepResearchNodeName = DeepResearchNodeName.END): + self._has_start_node = True + + title_generator = TitleGeneratorNode(self._team, self._user) + self._graph.add_node(DeepResearchNodeName.TITLE_GENERATOR, title_generator) + self._graph.add_edge(DeepResearchNodeName.START, DeepResearchNodeName.TITLE_GENERATOR) + self._graph.add_edge(DeepResearchNodeName.TITLE_GENERATOR, end_node) + return self + def compile_full_graph(self, checkpointer: DjangoCheckpointer | None = None): return ( self.add_onboarding_node() .add_notebook_nodes() .add_planner_nodes() .add_report_node() - .add_title_generator() .add_task_executor() .compile(checkpointer=checkpointer) ) diff --git a/ee/hogai/graph/deep_research/planner/nodes.py b/ee/hogai/graph/deep_research/planner/nodes.py index 74a04d947a..6c8c1e0258 100644 --- a/ee/hogai/graph/deep_research/planner/nodes.py +++ b/ee/hogai/graph/deep_research/planner/nodes.py @@ -40,8 +40,8 @@ from ee.hogai.graph.deep_research.types import ( DeepResearchNodeName, DeepResearchState, PartialDeepResearchState, + TodoItem, ) -from ee.hogai.graph.root.tools.todo_write import TodoItem from ee.hogai.notebook.notebook_serializer import NotebookSerializer from ee.hogai.utils.helpers import normalize_ai_message from ee.hogai.utils.types import WithCommentary diff --git a/ee/hogai/graph/deep_research/planner/test/test_nodes.py b/ee/hogai/graph/deep_research/planner/test/test_nodes.py index 74f772db10..2c78a6e490 100644 --- a/ee/hogai/graph/deep_research/planner/test/test_nodes.py +++ b/ee/hogai/graph/deep_research/planner/test/test_nodes.py @@ -34,8 +34,7 @@ from ee.hogai.graph.deep_research.planner.prompts import ( WRITE_RESULT_FAILED_TOOL_RESULT, WRITE_RESULT_TOOL_RESULT, ) -from ee.hogai.graph.deep_research.types import DeepResearchState, PartialDeepResearchState -from ee.hogai.graph.root.tools.todo_write import TodoItem +from ee.hogai.graph.deep_research.types import DeepResearchState, PartialDeepResearchState, TodoItem from ee.hogai.utils.types import InsightArtifact from ee.hogai.utils.types.base import TaskResult diff --git a/ee/hogai/graph/deep_research/task_executor/test/test_nodes.py b/ee/hogai/graph/deep_research/task_executor/test/test_nodes.py index ab0f6b06c6..79c8545eac 100644 --- a/ee/hogai/graph/deep_research/task_executor/test/test_nodes.py +++ b/ee/hogai/graph/deep_research/task_executor/test/test_nodes.py @@ -128,7 +128,7 @@ class TestTaskExecutorNodeArun(TestTaskExecutorNode): class TestTaskExecutorInsightsExecution(TestTaskExecutorNode): @patch("ee.hogai.graph.deep_research.task_executor.nodes.DeepResearchTaskExecutorNode.dispatcher") - @patch("ee.hogai.graph.deep_research.task_executor.nodes.InsightsAssistantGraph") + @patch("ee.hogai.graph.deep_research.task_executor.nodes.InsightsGraph") async def test_execute_task_with_insights_successful(self, mock_insights_graph_class, mock_dispatcher): """Test successful task execution through insights pipeline.""" @@ -171,7 +171,7 @@ class TestTaskExecutorInsightsExecution(TestTaskExecutorNode): self.assertEqual(len(result.artifacts), 1) @patch("ee.hogai.graph.deep_research.task_executor.nodes.DeepResearchTaskExecutorNode.dispatcher") - @patch("ee.hogai.graph.deep_research.task_executor.nodes.InsightsAssistantGraph") + @patch("ee.hogai.graph.deep_research.task_executor.nodes.InsightsGraph") async def test_execute_task_with_insights_no_artifacts(self, mock_insights_graph_class, mock_dispatcher): """Test task execution that produces no artifacts.""" task = self._create_assistant_tool_call() @@ -209,7 +209,7 @@ class TestTaskExecutorInsightsExecution(TestTaskExecutorNode): @patch("ee.hogai.graph.deep_research.task_executor.nodes.capture_exception") @patch("ee.hogai.graph.deep_research.task_executor.nodes.DeepResearchTaskExecutorNode.dispatcher") - @patch("ee.hogai.graph.deep_research.task_executor.nodes.InsightsAssistantGraph") + @patch("ee.hogai.graph.deep_research.task_executor.nodes.InsightsGraph") async def test_execute_task_with_exception(self, mock_insights_graph_class, mock_dispatcher, mock_capture): """Test task execution that encounters an exception.""" task = self._create_assistant_tool_call() diff --git a/ee/hogai/graph/deep_research/test/test_integration.py b/ee/hogai/graph/deep_research/test/test_integration.py index 811a9ad651..621c51364f 100644 --- a/ee/hogai/graph/deep_research/test/test_integration.py +++ b/ee/hogai/graph/deep_research/test/test_integration.py @@ -27,8 +27,7 @@ from ee.hogai.graph.deep_research.onboarding.nodes import DeepResearchOnboarding from ee.hogai.graph.deep_research.planner.nodes import DeepResearchPlannerNode, DeepResearchPlannerToolsNode from ee.hogai.graph.deep_research.report.nodes import DeepResearchReportNode from ee.hogai.graph.deep_research.task_executor.nodes import DeepResearchTaskExecutorNode -from ee.hogai.graph.deep_research.types import DeepResearchIntermediateResult, DeepResearchState -from ee.hogai.graph.root.tools.todo_write import TodoItem +from ee.hogai.graph.deep_research.types import DeepResearchIntermediateResult, DeepResearchState, TodoItem from ee.hogai.utils.types.base import TaskResult from ee.models.assistant import Conversation diff --git a/ee/hogai/graph/deep_research/test/test_types.py b/ee/hogai/graph/deep_research/test/test_types.py index 06a9c835c7..4927596bc5 100644 --- a/ee/hogai/graph/deep_research/test/test_types.py +++ b/ee/hogai/graph/deep_research/test/test_types.py @@ -12,9 +12,9 @@ from ee.hogai.graph.deep_research.types import ( DeepResearchIntermediateResult, DeepResearchState, PartialDeepResearchState, + TodoItem, _SharedDeepResearchState, ) -from ee.hogai.graph.root.tools.todo_write import TodoItem from ee.hogai.utils.types.base import InsightArtifact, TaskResult """ diff --git a/ee/hogai/graph/deep_research/types.py b/ee/hogai/graph/deep_research/types.py index 49c69c2e8a..c6099f3052 100644 --- a/ee/hogai/graph/deep_research/types.py +++ b/ee/hogai/graph/deep_research/types.py @@ -1,19 +1,31 @@ from collections.abc import Sequence from enum import StrEnum -from typing import Annotated, Optional +from typing import Annotated, Literal, Optional from langgraph.graph import END, START from pydantic import BaseModel, Field from posthog.schema import DeepResearchNotebook -from ee.hogai.graph.root.tools.todo_write import TodoItem -from ee.hogai.utils.types import AssistantMessageUnion, add_and_merge_messages -from ee.hogai.utils.types.base import BaseStateWithMessages, BaseStateWithTasks, append, replace +from ee.hogai.utils.types.base import ( + AssistantMessageUnion, + BaseStateWithMessages, + BaseStateWithTasks, + add_and_merge_messages, + append, + replace, +) NotebookInfo = DeepResearchNotebook +class TodoItem(BaseModel): + content: str = Field(..., min_length=1) + status: Literal["pending", "in_progress", "completed"] + id: str + priority: Literal["low", "medium", "high"] + + class DeepResearchIntermediateResult(BaseModel): """ An intermediate result of a batch of work, that will be used to write the final report. @@ -69,3 +81,4 @@ class DeepResearchNodeName(StrEnum): PLANNER_TOOLS = "planner_tools" TASK_EXECUTOR = "task_executor" REPORT = "report" + TITLE_GENERATOR = "title_generator" diff --git a/ee/hogai/graph/funnels/nodes.py b/ee/hogai/graph/funnels/nodes.py index 766c8fe09d..e062c15b2b 100644 --- a/ee/hogai/graph/funnels/nodes.py +++ b/ee/hogai/graph/funnels/nodes.py @@ -1,7 +1,7 @@ from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnableConfig -from posthog.schema import AssistantFunnelsQuery, AssistantMessage +from posthog.schema import AssistantFunnelsQuery from ee.hogai.utils.types import AssistantState, PartialAssistantState from ee.hogai.utils.types.base import AssistantNodeName @@ -25,7 +25,7 @@ class FunnelGeneratorNode(SchemaGeneratorNode[AssistantFunnelsQuery]): return AssistantNodeName.FUNNEL_GENERATOR async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: - self.dispatcher.message(AssistantMessage(content="Creating funnel query")) + self.dispatcher.update("Creating funnel query") prompt = ChatPromptTemplate.from_messages( [ ("system", FUNNEL_SYSTEM_PROMPT), diff --git a/ee/hogai/graph/graph.py b/ee/hogai/graph/graph.py index 38da274d11..92598694c0 100644 --- a/ee/hogai/graph/graph.py +++ b/ee/hogai/graph/graph.py @@ -1,23 +1,11 @@ -from collections.abc import Hashable -from typing import Any, Generic, Literal, Optional, cast - -from langgraph.graph.state import StateGraph - -from posthog.models.team.team import Team -from posthog.models.user import User +from collections.abc import Callable +from typing import cast from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph.billing.nodes import BillingNode -from ee.hogai.graph.query_planner.nodes import QueryPlannerNode, QueryPlannerToolsNode -from ee.hogai.graph.session_summaries.nodes import SessionSummarizationNode +from ee.hogai.graph.base import BaseAssistantGraph from ee.hogai.graph.title_generator.nodes import TitleGeneratorNode -from ee.hogai.utils.types import AssistantNodeName, AssistantState, StateType -from ee.hogai.utils.types.composed import MaxNodeName +from ee.hogai.utils.types.base import AssistantGraphName, AssistantNodeName, AssistantState, PartialAssistantState -from .dashboards.nodes import DashboardCreationNode -from .funnels.nodes import FunnelGeneratorNode, FunnelGeneratorToolsNode -from .inkeep_docs.nodes import InkeepDocsNode -from .insights.nodes import InsightSearchNode from .memory.nodes import ( MemoryCollectorNode, MemoryCollectorToolsNode, @@ -28,51 +16,19 @@ from .memory.nodes import ( MemoryOnboardingFinalizeNode, MemoryOnboardingNode, ) -from .query_executor.nodes import QueryExecutorNode -from .rag.nodes import InsightRagContextNode -from .retention.nodes import RetentionGeneratorNode, RetentionGeneratorToolsNode from .root.nodes import RootNode, RootNodeTools -from .sql.nodes import SQLGeneratorNode, SQLGeneratorToolsNode -from .trends.nodes import TrendsGeneratorNode, TrendsGeneratorToolsNode - -global_checkpointer = DjangoCheckpointer() -class BaseAssistantGraph(Generic[StateType]): - _team: Team - _user: User - _graph: StateGraph - _parent_tool_call_id: str | None +class AssistantGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.ASSISTANT - def __init__(self, team: Team, user: User, state_type: type[StateType], parent_tool_call_id: str | None = None): - self._team = team - self._user = user - self._graph = StateGraph(state_type) - self._has_start_node = False - self._parent_tool_call_id = parent_tool_call_id + @property + def state_type(self) -> type[AssistantState]: + return AssistantState - def add_edge(self, from_node: MaxNodeName, to_node: MaxNodeName): - if from_node == AssistantNodeName.START: - self._has_start_node = True - self._graph.add_edge(from_node, to_node) - return self - - def add_node(self, node: MaxNodeName, action: Any): - if self._parent_tool_call_id: - action._parent_tool_call_id = self._parent_tool_call_id - self._graph.add_node(node, action) - return self - - def compile(self, checkpointer: DjangoCheckpointer | None | Literal[False] = None): - if not self._has_start_node: - raise ValueError("Start node not added to the graph") - # TRICKY: We check `is not None` because False has a special meaning of "no checkpointer", which we want to pass on - compiled_graph = self._graph.compile( - checkpointer=checkpointer if checkpointer is not None else global_checkpointer - ) - return compiled_graph - - def add_title_generator(self, end_node: MaxNodeName = AssistantNodeName.END): + def add_title_generator(self, end_node: AssistantNodeName = AssistantNodeName.END): self._has_start_node = True title_generator = TitleGeneratorNode(self._team, self._user) @@ -81,178 +37,19 @@ class BaseAssistantGraph(Generic[StateType]): self._graph.add_edge(AssistantNodeName.TITLE_GENERATOR, end_node) return self - -class InsightsAssistantGraph(BaseAssistantGraph[AssistantState]): - def __init__(self, team: Team, user: User, tool_call_id: str | None = None): - super().__init__(team, user, AssistantState, tool_call_id) - - def add_rag_context(self): - self._has_start_node = True - retriever = InsightRagContextNode(self._team, self._user) - self.add_node(AssistantNodeName.INSIGHT_RAG_CONTEXT, retriever) - self._graph.add_edge(AssistantNodeName.START, AssistantNodeName.INSIGHT_RAG_CONTEXT) - self._graph.add_edge(AssistantNodeName.INSIGHT_RAG_CONTEXT, AssistantNodeName.QUERY_PLANNER) - return self - - def add_trends_generator(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): - trends_generator = TrendsGeneratorNode(self._team, self._user) - self.add_node(AssistantNodeName.TRENDS_GENERATOR, trends_generator) - - trends_generator_tools = TrendsGeneratorToolsNode(self._team, self._user) - self.add_node(AssistantNodeName.TRENDS_GENERATOR_TOOLS, trends_generator_tools) - - self._graph.add_edge(AssistantNodeName.TRENDS_GENERATOR_TOOLS, AssistantNodeName.TRENDS_GENERATOR) - self._graph.add_conditional_edges( - AssistantNodeName.TRENDS_GENERATOR, - trends_generator.router, - path_map={ - "tools": AssistantNodeName.TRENDS_GENERATOR_TOOLS, - "next": next_node, - }, - ) - - return self - - def add_funnel_generator(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): - funnel_generator = FunnelGeneratorNode(self._team, self._user) - self.add_node(AssistantNodeName.FUNNEL_GENERATOR, funnel_generator) - - funnel_generator_tools = FunnelGeneratorToolsNode(self._team, self._user) - self.add_node(AssistantNodeName.FUNNEL_GENERATOR_TOOLS, funnel_generator_tools) - - self._graph.add_edge(AssistantNodeName.FUNNEL_GENERATOR_TOOLS, AssistantNodeName.FUNNEL_GENERATOR) - self._graph.add_conditional_edges( - AssistantNodeName.FUNNEL_GENERATOR, - funnel_generator.router, - path_map={ - "tools": AssistantNodeName.FUNNEL_GENERATOR_TOOLS, - "next": next_node, - }, - ) - - return self - - def add_retention_generator(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): - retention_generator = RetentionGeneratorNode(self._team, self._user) - self.add_node(AssistantNodeName.RETENTION_GENERATOR, retention_generator) - - retention_generator_tools = RetentionGeneratorToolsNode(self._team, self._user) - self.add_node(AssistantNodeName.RETENTION_GENERATOR_TOOLS, retention_generator_tools) - - self._graph.add_edge(AssistantNodeName.RETENTION_GENERATOR_TOOLS, AssistantNodeName.RETENTION_GENERATOR) - self._graph.add_conditional_edges( - AssistantNodeName.RETENTION_GENERATOR, - retention_generator.router, - path_map={ - "tools": AssistantNodeName.RETENTION_GENERATOR_TOOLS, - "next": next_node, - }, - ) - - return self - - def add_query_planner( - self, - path_map: Optional[ - dict[Literal["trends", "funnel", "retention", "sql", "continue", "end"], AssistantNodeName] - ] = None, - ): - query_planner = QueryPlannerNode(self._team, self._user) - self.add_node(AssistantNodeName.QUERY_PLANNER, query_planner) - self._graph.add_edge(AssistantNodeName.QUERY_PLANNER, AssistantNodeName.QUERY_PLANNER_TOOLS) - - query_planner_tools = QueryPlannerToolsNode(self._team, self._user) - self.add_node(AssistantNodeName.QUERY_PLANNER_TOOLS, query_planner_tools) - self._graph.add_conditional_edges( - AssistantNodeName.QUERY_PLANNER_TOOLS, - query_planner_tools.router, - path_map=path_map # type: ignore - or { - "continue": AssistantNodeName.QUERY_PLANNER, - "trends": AssistantNodeName.TRENDS_GENERATOR, - "funnel": AssistantNodeName.FUNNEL_GENERATOR, - "retention": AssistantNodeName.RETENTION_GENERATOR, - "sql": AssistantNodeName.SQL_GENERATOR, - "end": AssistantNodeName.END, - }, - ) - - return self - - def add_sql_generator(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): - sql_generator = SQLGeneratorNode(self._team, self._user) - self.add_node(AssistantNodeName.SQL_GENERATOR, sql_generator) - - sql_generator_tools = SQLGeneratorToolsNode(self._team, self._user) - self.add_node(AssistantNodeName.SQL_GENERATOR_TOOLS, sql_generator_tools) - - self._graph.add_edge(AssistantNodeName.SQL_GENERATOR_TOOLS, AssistantNodeName.SQL_GENERATOR) - self._graph.add_conditional_edges( - AssistantNodeName.SQL_GENERATOR, - sql_generator.router, - path_map={ - "tools": AssistantNodeName.SQL_GENERATOR_TOOLS, - "next": next_node, - }, - ) - - return self - - def add_query_executor(self, next_node: AssistantNodeName = AssistantNodeName.END): - query_executor_node = QueryExecutorNode(self._team, self._user) - self.add_node(AssistantNodeName.QUERY_EXECUTOR, query_executor_node) - self._graph.add_edge(AssistantNodeName.QUERY_EXECUTOR, next_node) - return self - - def add_query_creation_flow(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): - """Add all nodes and edges EXCEPT query execution.""" - return ( - self.add_rag_context() - .add_query_planner() - .add_trends_generator(next_node=next_node) - .add_funnel_generator(next_node=next_node) - .add_retention_generator(next_node=next_node) - .add_sql_generator(next_node=next_node) - ) - - def compile_full_graph(self, checkpointer: DjangoCheckpointer | None = None): - return self.add_query_creation_flow().add_query_executor().compile(checkpointer=checkpointer) - - -class AssistantGraph(BaseAssistantGraph[AssistantState]): - def __init__(self, team: Team, user: User): - super().__init__(team, user, AssistantState) - - def add_root( - self, - path_map: Optional[dict[Hashable, AssistantNodeName]] = None, - tools_node: AssistantNodeName = AssistantNodeName.ROOT_TOOLS, - ): - path_map = path_map or { - "insights": AssistantNodeName.INSIGHTS_SUBGRAPH, - "search_documentation": AssistantNodeName.INKEEP_DOCS, - "root": AssistantNodeName.ROOT, - "billing": AssistantNodeName.BILLING, - "end": AssistantNodeName.END, - "insights_search": AssistantNodeName.INSIGHTS_SEARCH, - "session_summarization": AssistantNodeName.SESSION_SUMMARIZATION, - "create_dashboard": AssistantNodeName.DASHBOARD_CREATION, - } + def add_root(self, router: Callable[[AssistantState], AssistantNodeName] | None = None): root_node = RootNode(self._team, self._user) self.add_node(AssistantNodeName.ROOT, root_node) root_node_tools = RootNodeTools(self._team, self._user) self.add_node(AssistantNodeName.ROOT_TOOLS, root_node_tools) - self._graph.add_edge(AssistantNodeName.ROOT, tools_node) self._graph.add_conditional_edges( - AssistantNodeName.ROOT_TOOLS, root_node_tools.router, path_map=cast(dict[Hashable, str], path_map) + AssistantNodeName.ROOT, router or cast(Callable[[AssistantState], AssistantNodeName], root_node.router) + ) + self._graph.add_conditional_edges( + AssistantNodeName.ROOT_TOOLS, + root_node_tools.router, + path_map={"root": AssistantNodeName.ROOT, "end": AssistantNodeName.END}, ) - return self - - def add_insights(self, next_node: AssistantNodeName = AssistantNodeName.ROOT): - insights_assistant_graph = InsightsAssistantGraph(self._team, self._user) - compiled_graph = insights_assistant_graph.compile_full_graph() - self.add_node(AssistantNodeName.INSIGHTS_SUBGRAPH, compiled_graph) - self._graph.add_edge(AssistantNodeName.INSIGHTS_SUBGRAPH, next_node) return self def add_memory_onboarding( @@ -332,55 +129,6 @@ class AssistantGraph(BaseAssistantGraph[AssistantState]): self._graph.add_edge(AssistantNodeName.MEMORY_COLLECTOR_TOOLS, AssistantNodeName.MEMORY_COLLECTOR) return self - def add_inkeep_docs(self, path_map: Optional[dict[Hashable, AssistantNodeName]] = None): - """Add the Inkeep docs search node to the graph.""" - path_map = path_map or { - "end": AssistantNodeName.END, - "root": AssistantNodeName.ROOT, - } - inkeep_docs_node = InkeepDocsNode(self._team, self._user) - self.add_node(AssistantNodeName.INKEEP_DOCS, inkeep_docs_node) - self._graph.add_conditional_edges( - AssistantNodeName.INKEEP_DOCS, - inkeep_docs_node.router, - path_map=cast(dict[Hashable, str], path_map), - ) - return self - - def add_billing(self): - billing_node = BillingNode(self._team, self._user) - self.add_node(AssistantNodeName.BILLING, billing_node) - self._graph.add_edge(AssistantNodeName.BILLING, AssistantNodeName.ROOT) - return self - - def add_insights_search(self, end_node: AssistantNodeName = AssistantNodeName.END): - path_map = { - "end": end_node, - "root": AssistantNodeName.ROOT, - } - - insights_search_node = InsightSearchNode(self._team, self._user) - self.add_node(AssistantNodeName.INSIGHTS_SEARCH, insights_search_node) - self._graph.add_conditional_edges( - AssistantNodeName.INSIGHTS_SEARCH, - insights_search_node.router, - path_map=cast(dict[Hashable, str], path_map), - ) - return self - - def add_session_summarization(self, end_node: AssistantNodeName = AssistantNodeName.END): - session_summarization_node = SessionSummarizationNode(self._team, self._user) - self.add_node(AssistantNodeName.SESSION_SUMMARIZATION, session_summarization_node) - self._graph.add_edge(AssistantNodeName.SESSION_SUMMARIZATION, AssistantNodeName.ROOT) - return self - - def add_dashboard_creation(self, end_node: AssistantNodeName = AssistantNodeName.END): - builder = self._graph - dashboard_creation_node = DashboardCreationNode(self._team, self._user) - builder.add_node(AssistantNodeName.DASHBOARD_CREATION, dashboard_creation_node) - builder.add_edge(AssistantNodeName.DASHBOARD_CREATION, AssistantNodeName.ROOT) - return self - def compile_full_graph(self, checkpointer: DjangoCheckpointer | None = None): return ( self.add_title_generator() @@ -388,11 +136,5 @@ class AssistantGraph(BaseAssistantGraph[AssistantState]): .add_memory_collector() .add_memory_collector_tools() .add_root() - .add_insights() - .add_inkeep_docs() - .add_billing() - .add_insights_search() - .add_session_summarization() - .add_dashboard_creation() .compile(checkpointer=checkpointer) ) diff --git a/ee/hogai/graph/inkeep_docs/nodes.py b/ee/hogai/graph/inkeep_docs/nodes.py index f4d8979789..7ab0dc6837 100644 --- a/ee/hogai/graph/inkeep_docs/nodes.py +++ b/ee/hogai/graph/inkeep_docs/nodes.py @@ -1,5 +1,5 @@ from collections.abc import Mapping, Sequence -from typing import Any, Literal +from typing import Any from uuid import uuid4 from django.conf import settings @@ -34,19 +34,22 @@ class InkeepDocsNode(RootNode): # Inheriting from RootNode to use the same mess async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: """Process the state and return documentation search results.""" - self.dispatcher.message(AssistantMessage(content="Checking PostHog documentation...", id=str(uuid4()))) + self.dispatcher.update("Checking PostHog documentation...") + messages = self._construct_messages( state.messages, state.root_conversation_start_id, state.root_tool_calls_count ) + message: LangchainAIMessage = await self._get_model().ainvoke(messages, config) - # NOTE: This is a hacky way to send these messages as part of the root tool call - # Can't think of a better interface for this at the moment. - self.dispatcher.set_as_root() + should_continue = INKEEP_DATA_CONTINUATION_PHRASE in message.content + + tool_prompt = "Checking PostHog documentation..." + if should_continue: + tool_prompt = "The documentation search results are provided in the next Assistant message.\nContinue with the user's data request." + return PartialAssistantState( messages=[ - AssistantToolCallMessage( - content="Checking PostHog documentation...", tool_call_id=state.root_tool_call_id, id=str(uuid4()) - ), + AssistantToolCallMessage(content=tool_prompt, tool_call_id=state.root_tool_call_id, id=str(uuid4())), AssistantMessage(content=message.content, id=str(uuid4())), ], root_tool_call_id=None, @@ -116,16 +119,3 @@ class InkeepDocsNode(RootNode): # Inheriting from RootNode to use the same mess ) -> list[BaseMessage]: # Original node has Anthropic messages, but Inkeep expects OpenAI messages return convert_to_openai_messages(conversation_window, tool_result_messages) - - def router(self, state: AssistantState) -> Literal["end", "root"]: - last_message = state.messages[-1] - if isinstance(last_message, AssistantMessage) and INKEEP_DATA_CONTINUATION_PHRASE in last_message.content: - # The continuation phrase solution is a little weird, but seems it's the best one for agentic capabilities - # I've found here. The alternatives that definitively don't work are: - # 1. Using tool calls in this node - the Inkeep API only supports providing their own pre-defined tools - # (for including extra search metadata), nothing else - # 2. Always going back to root, for root to judge whether to continue or not - GPT-4o is terrible at this, - # and I was unable to stop it from repeating the context from the last assistant message, i.e. the Inkeep - # output message (doesn't quite work to tell it to output an empty message, or to call an "end" tool) - return "root" - return "end" diff --git a/ee/hogai/graph/inkeep_docs/test/test_nodes.py b/ee/hogai/graph/inkeep_docs/test/test_nodes.py index 0afdda3d4a..5b7bed7c1d 100644 --- a/ee/hogai/graph/inkeep_docs/test/test_nodes.py +++ b/ee/hogai/graph/inkeep_docs/test/test_nodes.py @@ -67,6 +67,9 @@ class TestInkeepDocsNode(ClickhouseTestMixin, BaseTest): assert next_state is not None messages = cast(list, next_state.messages) self.assertEqual(len(messages), 2) + # Tool call message should have the continuation prompt + first_message = cast(AssistantToolCallMessage, messages[0]) + self.assertIn("Continue with the user's data request", first_message.content) second_message = cast(AssistantMessage, messages[1]) self.assertEqual(second_message.content, response_with_continuation) @@ -91,26 +94,6 @@ class TestInkeepDocsNode(ClickhouseTestMixin, BaseTest): self.assertIsInstance(messages[2], LangchainAIMessage) self.assertIsInstance(messages[3], LangchainHumanMessage) - def test_router_with_data_continuation(self): - node = InkeepDocsNode(self.team, self.user) - state = AssistantState( - messages=[ - HumanMessage(content="Explain PostHog trends, and show me an example trends insight"), - AssistantMessage(content=f"Here's the documentation: XYZ.\n{INKEEP_DATA_CONTINUATION_PHRASE}"), - ] - ) - self.assertEqual(node.router(state), "root") # Going back to root, so that the agent can continue with the task - - def test_router_without_data_continuation(self): - node = InkeepDocsNode(self.team, self.user) - state = AssistantState( - messages=[ - HumanMessage(content="How do I use feature flags?"), - AssistantMessage(content="Here's how to use feature flags..."), - ] - ) - self.assertEqual(node.router(state), "end") # Ending - async def test_tool_call_id_handling(self): """Test that tool_call_id is properly handled in both input and output states.""" test_tool_call_id = str(uuid4()) diff --git a/ee/hogai/graph/insights/nodes.py b/ee/hogai/graph/insights/nodes.py index 9939ea7831..4283db8693 100644 --- a/ee/hogai/graph/insights/nodes.py +++ b/ee/hogai/graph/insights/nodes.py @@ -4,7 +4,7 @@ import inspect import warnings from datetime import timedelta from functools import wraps -from typing import Literal, Optional, TypedDict +from typing import TYPE_CHECKING, Optional, TypedDict from uuid import uuid4 from django.db.models import Max @@ -16,7 +16,7 @@ from langchain_core.runnables import RunnableConfig from langchain_core.tools import tool from langchain_openai import ChatOpenAI -from posthog.schema import AssistantMessage, AssistantToolCallMessage, VisualizationMessage +from posthog.schema import AssistantToolCallMessage, VisualizationMessage from posthog.exceptions_capture import capture_exception from posthog.models import Insight @@ -28,18 +28,19 @@ from ee.hogai.graph.shared_prompts import HYPERLINK_USAGE_INSTRUCTIONS from ee.hogai.utils.helpers import build_insight_url from ee.hogai.utils.types import AssistantState, PartialAssistantState from ee.hogai.utils.types.base import AssistantNodeName -from ee.hogai.utils.types.composed import MaxNodeName from .prompts import ( - EMPTY_DATABASE_ERROR_MESSAGE, ITERATIVE_SEARCH_SYSTEM_PROMPT, ITERATIVE_SEARCH_USER_PROMPT, NO_INSIGHTS_FOUND_MESSAGE, PAGINATION_INSTRUCTIONS_TEMPLATE, - SEARCH_ERROR_INSTRUCTIONS, TOOL_BASED_EVALUATION_SYSTEM_PROMPT, ) +if TYPE_CHECKING: + from ee.hogai.utils.types.composed import MaxNodeName + + logger = structlog.get_logger(__name__) # Silence Pydantic serializer warnings for creation of VisualizationMessage/Query execution warnings.filterwarnings("ignore", category=UserWarning, message=".*Pydantic serializer.*") @@ -105,6 +106,10 @@ class InsightDict(TypedDict): short_id: str +class NoInsightsException(Exception): + """Exception indicating that the insight search cannot be done because the user does not have any insights.""" + + class InsightSearchNode(AssistantNode): PAGE_SIZE = 500 MAX_SEARCH_ITERATIONS = 6 @@ -114,7 +119,7 @@ class InsightSearchNode(AssistantNode): MAX_SERIES_TO_PROCESS = 3 @property - def node_name(self) -> MaxNodeName: + def node_name(self) -> "MaxNodeName": return AssistantNodeName.INSIGHTS_SEARCH def __init__(self, *args, **kwargs): @@ -133,9 +138,31 @@ class InsightSearchNode(AssistantNode): self._query_cache = {} self._insight_id_cache = {} - def _dispatch_update_message(self, content: str) -> None: - """Dispatch an update message to the assistant.""" - self.dispatcher.message(AssistantMessage(content=content)) + @timing_logger("InsightSearchNode.arun") + async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState | None: + self.dispatcher.update("Searching for insights") + search_query = state.search_insights_query + self._current_iteration = 0 + + total_count = await self._get_total_insights_count() + if total_count == 0: + raise NoInsightsException + + selected_insights = await self._search_insights_iteratively(search_query or "") + logger.warning( + f"{TIMING_LOG_PREFIX} search_insights_iteratively returned {len(selected_insights)} insights: {selected_insights}" + ) + + if selected_insights: + self.dispatcher.update(f"Evaluating {len(selected_insights)} insights to find the best match") + else: + self.dispatcher.update("No existing insights found, creating a new one") + + evaluation_result = await self._evaluate_insights_with_tools( + selected_insights, search_query or "", max_selections=1 + ) + + return self._handle_evaluation_result(evaluation_result, state) def _create_page_reader_tool(self): """Create tool for reading insights pages during agentic RAG loop.""" @@ -185,36 +212,6 @@ class InsightSearchNode(AssistantNode): return [select_insight, reject_all_insights] - @timing_logger("InsightSearchNode.arun") - async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState | None: - self._dispatch_update_message("Searching for insights") - search_query = state.search_insights_query - try: - self._current_iteration = 0 - - total_count = await self._get_total_insights_count() - if total_count == 0: - return self._handle_empty_database(state) - - selected_insights = await self._search_insights_iteratively(search_query or "") - logger.warning( - f"{TIMING_LOG_PREFIX} search_insights_iteratively returned {len(selected_insights)} insights: {selected_insights}" - ) - - if selected_insights: - self._dispatch_update_message(f"Evaluating {len(selected_insights)} insights to find the best match") - else: - self._dispatch_update_message("No existing insights found, creating a new one") - - evaluation_result = await self._evaluate_insights_with_tools( - selected_insights, search_query or "", max_selections=1 - ) - - return self._handle_evaluation_result(evaluation_result, state) - - except Exception as e: - return self._handle_search_error(e, state) - @timing_logger("InsightSearchNode._get_insights_queryset") def _get_insights_queryset(self): """Get Insight objects with latest view time annotated and cutoff date.""" @@ -235,10 +232,6 @@ class InsightSearchNode(AssistantNode): self._total_insights_count = await self._get_insights_queryset().acount() return self._total_insights_count - def _handle_empty_database(self, state: AssistantState) -> PartialAssistantState: - """Handle the case when no insights exist in the database. (Rare edge-case but still possible)""" - return self._create_error_response(EMPTY_DATABASE_ERROR_MESSAGE, state.root_tool_call_id) - def _handle_evaluation_result(self, evaluation_result: dict, state: AssistantState) -> PartialAssistantState: """Process the evaluation result and return appropriate response.""" if evaluation_result["should_use_existing"]: @@ -256,12 +249,12 @@ class InsightSearchNode(AssistantNode): return PartialAssistantState( messages=[ + *evaluation_result["visualization_messages"], AssistantToolCallMessage( content=formatted_content, tool_call_id=state.root_tool_call_id or "unknown", id=str(uuid4()), ), - *evaluation_result["visualization_messages"], ], selected_insight_ids=evaluation_result["selected_insights"], search_insights_query=None, @@ -284,16 +277,6 @@ class InsightSearchNode(AssistantNode): selected_insight_ids=None, ) - @timing_logger("InsightSearchNode._handle_search_error") - def _handle_search_error(self, e: Exception, state: AssistantState) -> PartialAssistantState: - """Handle exceptions during search process.""" - capture_exception(e) - logger.error(f"{TIMING_LOG_PREFIX} Error in InsightSearchNode: {e}", exc_info=True) - return self._create_error_response( - SEARCH_ERROR_INSTRUCTIONS, - state.root_tool_call_id, - ) - def _format_insight_for_display(self, insight: InsightDict) -> str: """Format a single insight for display.""" name = insight["name"] or insight["derived_name"] or "Unnamed" @@ -424,7 +407,7 @@ class InsightSearchNode(AssistantNode): selected_insights = [] for step in ["Searching through existing insights", "Analyzing available insights"]: - self._dispatch_update_message(step) + self.dispatcher.update(step) logger.warning(f"{TIMING_LOG_PREFIX} Starting iterative search, max_iterations={self._max_iterations}") while self._current_iteration < self._max_iterations: @@ -446,7 +429,7 @@ class InsightSearchNode(AssistantNode): logger.warning( f"{TIMING_LOG_PREFIX} STALL POINT(?): Streamed 'Finding the most relevant insights' - about to fetch page content" ) - self._dispatch_update_message("Finding the most relevant insights") + self.dispatcher.update("Finding the most relevant insights") logger.warning(f"{TIMING_LOG_PREFIX} Fetching page content for page {page_num}") tool_response = await self._get_page_content_for_tool(page_num) @@ -465,15 +448,15 @@ class InsightSearchNode(AssistantNode): content = response.content if isinstance(response.content, str) else str(response.content) selected_insights = self._parse_insight_ids(content) if selected_insights: - self._dispatch_update_message(f"Found {len(selected_insights)} relevant insights") + self.dispatcher.update(f"Found {len(selected_insights)} relevant insights") else: - self._dispatch_update_message("No matching insights found") + self.dispatcher.update("No matching insights found") break except Exception as e: capture_exception(e) error_message = f"Error during search" - self._dispatch_update_message(error_message) + self.dispatcher.update(error_message) break return selected_insights @@ -692,7 +675,7 @@ class InsightSearchNode(AssistantNode): """Create a VisualizationMessage to render the insight UI.""" try: for step in ["Executing insight query...", "Processing query parameters", "Running data analysis"]: - self._dispatch_update_message(step) + self.dispatcher.update(step) query_obj, _ = await self._process_insight_query(insight) @@ -786,7 +769,7 @@ class InsightSearchNode(AssistantNode): async def _run_evaluation_loop(self, user_query: str, insights_summary: list[str], max_selections: int) -> None: """Run the evaluation loop with LLM.""" for step in ["Analyzing insights to match your request", "Comparing insights for best fit"]: - self._dispatch_update_message(step) + self.dispatcher.update(step) tools = self._create_insight_evaluation_tools() llm_with_tools = self._model.bind_tools(tools) @@ -800,7 +783,7 @@ class InsightSearchNode(AssistantNode): if getattr(response, "tool_calls", None): # Only stream on first iteration to avoid noise if iteration == 0: - self._dispatch_update_message("Making evaluation decisions") + self.dispatcher.update("Making evaluation decisions") self._process_evaluation_tool_calls(response, messages, tools) else: break @@ -841,7 +824,7 @@ class InsightSearchNode(AssistantNode): num_insights = len(self._evaluation_selections) insight_word = "insight" if num_insights == 1 else "insights" - self._dispatch_update_message(f"Perfect! Found {num_insights} suitable {insight_word}") + self.dispatcher.update(f"Perfect! Found {num_insights} suitable {insight_word}") for _, selection in self._evaluation_selections.items(): insight = selection["insight"] @@ -871,7 +854,7 @@ class InsightSearchNode(AssistantNode): async def _create_rejection_result(self) -> dict: """Create result for when all insights are rejected.""" - self._dispatch_update_message("Will create a custom insight tailored to your request") + self.dispatcher.update("Will create a custom insight tailored to your request") return { "should_use_existing": False, @@ -880,9 +863,6 @@ class InsightSearchNode(AssistantNode): "visualization_messages": [], } - def router(self, state: AssistantState) -> Literal["root"]: - return "root" - @property def _model(self): return ChatOpenAI( diff --git a/ee/hogai/graph/insights/prompts.py b/ee/hogai/graph/insights/prompts.py index 10e2472df5..706aa3e0a1 100644 --- a/ee/hogai/graph/insights/prompts.py +++ b/ee/hogai/graph/insights/prompts.py @@ -36,7 +36,3 @@ Instructions: NO_INSIGHTS_FOUND_MESSAGE = ( "No existing insights found matching your query. Creating a new insight based on your request." ) - -SEARCH_ERROR_INSTRUCTIONS = "INSTRUCTIONS: Tell the user that you encountered an issue while searching for insights and suggest they try again with a different search term." - -EMPTY_DATABASE_ERROR_MESSAGE = "No insights found in the database." diff --git a/ee/hogai/graph/insights/test/test_nodes.py b/ee/hogai/graph/insights/test/test_nodes.py index 410f84a141..a1a18e0c20 100644 --- a/ee/hogai/graph/insights/test/test_nodes.py +++ b/ee/hogai/graph/insights/test/test_nodes.py @@ -23,7 +23,7 @@ from posthog.schema import ( from posthog.models import Insight, InsightViewed -from ee.hogai.graph.insights.nodes import InsightDict, InsightSearchNode +from ee.hogai.graph.insights.nodes import InsightDict, InsightSearchNode, NoInsightsException from ee.hogai.utils.types import AssistantState, PartialAssistantState from ee.models.assistant import Conversation @@ -115,11 +115,6 @@ class TestInsightSearchNode(BaseTest): short_id=insight.short_id, ) - def test_router_returns_root(self): - """Test that router returns 'root' as expected.""" - result = self.node.router(AssistantState(messages=[])) - self.assertEqual(result, "root") - async def test_load_insights_page(self): """Test loading paginated insights from database.""" # Load first page @@ -350,12 +345,6 @@ class TestInsightSearchNode(BaseTest): # Should return empty list when LLM fails to select anything self.assertEqual(len(result), 0) - def test_router_always_returns_root(self): - """Test that router always returns 'root'.""" - state = AssistantState(messages=[], root_tool_insight_plan="some plan", search_insights_query=None) - result = self.node.router(state) - self.assertEqual(result, "root") - async def test_evaluation_flow_returns_creation_when_no_suitable_insights(self): """Test that when evaluation returns NO, the system transitions to creation flow.""" selected_insights = [self.insight1.id, self.insight2.id] @@ -411,21 +400,6 @@ class TestInsightSearchNode(BaseTest): "root_tool_insight_plan should be set to search_query", ) - # Test router behavior with the returned state - # Create a new state that simulates what happens after this node runs - post_evaluation_state = AssistantState( - messages=state.messages, - root_tool_insight_plan=search_query, # This gets set to search_query - search_insights_query=None, # This gets cleared - ) - - router_result = self.node.router(post_evaluation_state) - self.assertEqual( - router_result, - "root", - "Router should always return root", - ) - # Verify that _evaluate_insights_with_tools was called with the search_query mock_evaluate.assert_called_once_with(selected_insights, search_query, max_selections=1) @@ -481,7 +455,7 @@ class TestInsightSearchNode(BaseTest): self.assertIsNone(result.root_tool_call_id) def test_run_with_no_insights(self): - """Test arun method when no insights exist.""" + """Test arun method when no insights exist - should raise NoInsightsException.""" # Clear all insights (done outside async context) InsightViewed.objects.all().delete() Insight.objects.all().delete() @@ -497,13 +471,10 @@ class TestInsightSearchNode(BaseTest): async def async_test(): # Mock the database calls that happen in async context with patch.object(self.node, "_get_total_insights_count", return_value=0): - result = await self.node.arun(state, {"configurable": {"thread_id": str(conversation.id)}}) - return result + await self.node.arun(state, {"configurable": {"thread_id": str(conversation.id)}}) - result = asyncio.run(async_test()) - self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(len(result.messages), 1) - self.assertIn("No insights found in the database", result.messages[0].content) + with self.assertRaises(NoInsightsException): + asyncio.run(async_test()) async def test_team_filtering(self): """Test that insights are filtered by team.""" diff --git a/ee/hogai/graph/billing/test/__init__.py b/ee/hogai/graph/insights_graph/__init__.py similarity index 100% rename from ee/hogai/graph/billing/test/__init__.py rename to ee/hogai/graph/insights_graph/__init__.py diff --git a/ee/hogai/graph/insights_graph/graph.py b/ee/hogai/graph/insights_graph/graph.py new file mode 100644 index 0000000000..6af85172c9 --- /dev/null +++ b/ee/hogai/graph/insights_graph/graph.py @@ -0,0 +1,155 @@ +from typing import Literal, Optional + +from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer +from ee.hogai.graph.base import BaseAssistantGraph +from ee.hogai.utils.types.base import AssistantGraphName, AssistantNodeName, AssistantState, PartialAssistantState + +from ..funnels.nodes import FunnelGeneratorNode, FunnelGeneratorToolsNode +from ..query_executor.nodes import QueryExecutorNode +from ..query_planner.nodes import QueryPlannerNode, QueryPlannerToolsNode +from ..rag.nodes import InsightRagContextNode +from ..retention.nodes import RetentionGeneratorNode, RetentionGeneratorToolsNode +from ..sql.nodes import SQLGeneratorNode, SQLGeneratorToolsNode +from ..trends.nodes import TrendsGeneratorNode, TrendsGeneratorToolsNode + + +class InsightsGraph(BaseAssistantGraph[AssistantState, PartialAssistantState]): + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.INSIGHTS + + @property + def state_type(self) -> type[AssistantState]: + return AssistantState + + def add_rag_context(self): + self._has_start_node = True + retriever = InsightRagContextNode(self._team, self._user) + self.add_node(AssistantNodeName.INSIGHT_RAG_CONTEXT, retriever) + self._graph.add_edge(AssistantNodeName.START, AssistantNodeName.INSIGHT_RAG_CONTEXT) + self._graph.add_edge(AssistantNodeName.INSIGHT_RAG_CONTEXT, AssistantNodeName.QUERY_PLANNER) + return self + + def add_trends_generator(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): + trends_generator = TrendsGeneratorNode(self._team, self._user) + self.add_node(AssistantNodeName.TRENDS_GENERATOR, trends_generator) + + trends_generator_tools = TrendsGeneratorToolsNode(self._team, self._user) + self.add_node(AssistantNodeName.TRENDS_GENERATOR_TOOLS, trends_generator_tools) + + self._graph.add_edge(AssistantNodeName.TRENDS_GENERATOR_TOOLS, AssistantNodeName.TRENDS_GENERATOR) + self._graph.add_conditional_edges( + AssistantNodeName.TRENDS_GENERATOR, + trends_generator.router, + path_map={ + "tools": AssistantNodeName.TRENDS_GENERATOR_TOOLS, + "next": next_node, + }, + ) + + return self + + def add_funnel_generator(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): + funnel_generator = FunnelGeneratorNode(self._team, self._user) + self.add_node(AssistantNodeName.FUNNEL_GENERATOR, funnel_generator) + + funnel_generator_tools = FunnelGeneratorToolsNode(self._team, self._user) + self.add_node(AssistantNodeName.FUNNEL_GENERATOR_TOOLS, funnel_generator_tools) + + self._graph.add_edge(AssistantNodeName.FUNNEL_GENERATOR_TOOLS, AssistantNodeName.FUNNEL_GENERATOR) + self._graph.add_conditional_edges( + AssistantNodeName.FUNNEL_GENERATOR, + funnel_generator.router, + path_map={ + "tools": AssistantNodeName.FUNNEL_GENERATOR_TOOLS, + "next": next_node, + }, + ) + + return self + + def add_retention_generator(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): + retention_generator = RetentionGeneratorNode(self._team, self._user) + self.add_node(AssistantNodeName.RETENTION_GENERATOR, retention_generator) + + retention_generator_tools = RetentionGeneratorToolsNode(self._team, self._user) + self.add_node(AssistantNodeName.RETENTION_GENERATOR_TOOLS, retention_generator_tools) + + self._graph.add_edge(AssistantNodeName.RETENTION_GENERATOR_TOOLS, AssistantNodeName.RETENTION_GENERATOR) + self._graph.add_conditional_edges( + AssistantNodeName.RETENTION_GENERATOR, + retention_generator.router, + path_map={ + "tools": AssistantNodeName.RETENTION_GENERATOR_TOOLS, + "next": next_node, + }, + ) + + return self + + def add_query_planner( + self, + path_map: Optional[ + dict[Literal["trends", "funnel", "retention", "sql", "continue", "end"], AssistantNodeName] + ] = None, + ): + query_planner = QueryPlannerNode(self._team, self._user) + self.add_node(AssistantNodeName.QUERY_PLANNER, query_planner) + self._graph.add_edge(AssistantNodeName.QUERY_PLANNER, AssistantNodeName.QUERY_PLANNER_TOOLS) + + query_planner_tools = QueryPlannerToolsNode(self._team, self._user) + self.add_node(AssistantNodeName.QUERY_PLANNER_TOOLS, query_planner_tools) + self._graph.add_conditional_edges( + AssistantNodeName.QUERY_PLANNER_TOOLS, + query_planner_tools.router, + path_map=path_map # type: ignore + or { + "continue": AssistantNodeName.QUERY_PLANNER, + "trends": AssistantNodeName.TRENDS_GENERATOR, + "funnel": AssistantNodeName.FUNNEL_GENERATOR, + "retention": AssistantNodeName.RETENTION_GENERATOR, + "sql": AssistantNodeName.SQL_GENERATOR, + "end": AssistantNodeName.END, + }, + ) + + return self + + def add_sql_generator(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): + sql_generator = SQLGeneratorNode(self._team, self._user) + self.add_node(AssistantNodeName.SQL_GENERATOR, sql_generator) + + sql_generator_tools = SQLGeneratorToolsNode(self._team, self._user) + self.add_node(AssistantNodeName.SQL_GENERATOR_TOOLS, sql_generator_tools) + + self._graph.add_edge(AssistantNodeName.SQL_GENERATOR_TOOLS, AssistantNodeName.SQL_GENERATOR) + self._graph.add_conditional_edges( + AssistantNodeName.SQL_GENERATOR, + sql_generator.router, + path_map={ + "tools": AssistantNodeName.SQL_GENERATOR_TOOLS, + "next": next_node, + }, + ) + + return self + + def add_query_executor(self, next_node: AssistantNodeName = AssistantNodeName.END): + query_executor_node = QueryExecutorNode(self._team, self._user) + self.add_node(AssistantNodeName.QUERY_EXECUTOR, query_executor_node) + self._graph.add_edge(AssistantNodeName.QUERY_EXECUTOR, next_node) + return self + + def add_query_creation_flow(self, next_node: AssistantNodeName = AssistantNodeName.QUERY_EXECUTOR): + """Add all nodes and edges EXCEPT query execution.""" + return ( + self.add_rag_context() + .add_query_planner() + .add_trends_generator(next_node=next_node) + .add_funnel_generator(next_node=next_node) + .add_retention_generator(next_node=next_node) + .add_sql_generator(next_node=next_node) + ) + + def compile_full_graph(self, checkpointer: DjangoCheckpointer | None = None): + return self.add_query_creation_flow().add_query_executor().compile(checkpointer=checkpointer) diff --git a/ee/hogai/graph/mixins.py b/ee/hogai/graph/mixins.py index f6596833f6..bbc309bb9d 100644 --- a/ee/hogai/graph/mixins.py +++ b/ee/hogai/graph/mixins.py @@ -1,5 +1,5 @@ import datetime -from abc import ABC +from abc import ABC, abstractmethod from typing import Any, get_args, get_origin from uuid import UUID @@ -7,15 +7,15 @@ from django.utils import timezone from langchain_core.runnables import RunnableConfig -from posthog.schema import AssistantMessage, CurrencyCode +from posthog.schema import CurrencyCode from posthog.event_usage import groups from posthog.models import Team from posthog.models.action.action import Action from posthog.models.user import User -from ee.hogai.utils.dispatcher import AssistantDispatcher -from ee.hogai.utils.types.base import BaseStateWithIntermediateSteps +from ee.hogai.utils.dispatcher import AssistantDispatcher, create_dispatcher_from_config +from ee.hogai.utils.types.base import BaseStateWithIntermediateSteps, NodePath from ee.models import Conversation, CoreMemory @@ -194,4 +194,33 @@ class TaxonomyUpdateDispatcherNodeMixin: content = "Picking relevant events and properties" if substeps: content = substeps[-1] - self.dispatcher.message(AssistantMessage(content=content)) + self.dispatcher.update(content) + + +class AssistantDispatcherMixin(ABC): + _node_path: tuple[NodePath, ...] + _config: RunnableConfig | None + _dispatcher: AssistantDispatcher | None = None + + @property + def node_path(self) -> tuple[NodePath, ...]: + return self._node_path + + @property + @abstractmethod + def node_name(self) -> str: ... + + @property + def tool_call_id(self) -> str: + parent_tool_call_id = next((path.tool_call_id for path in reversed(self._node_path) if path.tool_call_id), None) + if not parent_tool_call_id: + raise ValueError("No tool call ID found") + return parent_tool_call_id + + @property + def dispatcher(self) -> AssistantDispatcher: + """Create a dispatcher for this node""" + if self._dispatcher: + return self._dispatcher + self._dispatcher = create_dispatcher_from_config(self._config or {}, self.node_path) + return self._dispatcher diff --git a/ee/hogai/graph/parallel_task_execution/mixins.py b/ee/hogai/graph/parallel_task_execution/mixins.py index 4191df430e..a36c80c1fc 100644 --- a/ee/hogai/graph/parallel_task_execution/mixins.py +++ b/ee/hogai/graph/parallel_task_execution/mixins.py @@ -52,7 +52,7 @@ class WithInsightCreationTaskExecution: The type allows None for compatibility with the base class. """ # Import here to avoid circular dependency - from ee.hogai.graph.graph import InsightsAssistantGraph + from ee.hogai.graph.insights_graph.graph import InsightsGraph task = cast(AssistantToolCall, input_dict["task"]) artifacts = input_dict["artifacts"] @@ -60,7 +60,7 @@ class WithInsightCreationTaskExecution: self._current_task_id = task.id - # This is needed by the InsightsAssistantGraph to return an AssistantToolCallMessage + # This is needed by the InsightsGraph to return an AssistantToolCallMessage task_tool_call_id = f"task_{uuid.uuid4().hex[:8]}" query = task.args["query_description"] @@ -77,9 +77,7 @@ class WithInsightCreationTaskExecution: ) subgraph_result_messages: list[AssistantMessageUnion] = [] - assistant_graph = InsightsAssistantGraph( - self._team, self._user, tool_call_id=self._parent_tool_call_id - ).compile_full_graph() + assistant_graph = InsightsGraph(self._team, self._user).compile_full_graph() try: async for chunk in assistant_graph.astream( input_state, @@ -156,7 +154,7 @@ class WithInsightCreationTaskExecution: if isinstance(message, VisualizationMessage) and message.id: artifact = InsightArtifact( task_id=tool_call.id, - id=None, # The InsightsAssistantGraph does not create the insight objects + id=None, # The InsightsGraph does not create the insight objects content="", query=cast(AnyAssistantGeneratedQuery, message.answer), ) @@ -194,9 +192,7 @@ class WithInsightSearchTaskExecution: ) try: - result = await InsightSearchNode(self._team, self._user, tool_call_id=self._parent_tool_call_id).arun( - input_state, config - ) + result = await InsightSearchNode(self._team, self._user).arun(input_state, config) if not result or not result.messages: logger.warning("Task failed: no messages received from node executor", task_id=task.id) diff --git a/ee/hogai/graph/query_executor/nodes.py b/ee/hogai/graph/query_executor/nodes.py index af8df9d8a1..7acb0ec5c6 100644 --- a/ee/hogai/graph/query_executor/nodes.py +++ b/ee/hogai/graph/query_executor/nodes.py @@ -76,6 +76,21 @@ class QueryExecutorNode(AssistantNode): ) return PartialAssistantState(messages=[FailureMessage(content=str(err), id=str(uuid4()))]) + return PartialAssistantState( + messages=[ + AssistantToolCallMessage( + content=self._format_query_result(viz_message, results, example_prompt), + id=str(uuid4()), + tool_call_id=tool_call_id, + ) + ], + root_tool_call_id=None, + root_tool_insight_plan=None, + root_tool_insight_type=None, + rag_context=None, + ) + + def _format_query_result(self, viz_message: VisualizationMessage, results: str, example_prompt: str) -> str: query_result = QUERY_RESULTS_PROMPT.format( query_kind=viz_message.answer.kind, results=results, @@ -84,20 +99,10 @@ class QueryExecutorNode(AssistantNode): project_timezone=self.project_timezone, currency=self.project_currency, ) - formatted_query_result = f"{example_prompt}\n\n{query_result}" if isinstance(viz_message.answer, AssistantHogQLQuery): formatted_query_result = f"{example_prompt}\n\n{SQL_QUERY_PROMPT.format(query=viz_message.answer.query)}\n\n{formatted_query_result}" - - return PartialAssistantState( - messages=[ - AssistantToolCallMessage(content=formatted_query_result, id=str(uuid4()), tool_call_id=tool_call_id) - ], - root_tool_call_id=None, - root_tool_insight_plan=None, - root_tool_insight_type=None, - rag_context=None, - ) + return formatted_query_result def _get_example_prompt(self, viz_message: VisualizationMessage) -> str: if isinstance(viz_message.answer, AssistantTrendsQuery | TrendsQuery): diff --git a/ee/hogai/graph/retention/nodes.py b/ee/hogai/graph/retention/nodes.py index 689bf5c59a..6080c90b21 100644 --- a/ee/hogai/graph/retention/nodes.py +++ b/ee/hogai/graph/retention/nodes.py @@ -1,7 +1,7 @@ from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnableConfig -from posthog.schema import AssistantMessage, AssistantRetentionQuery +from posthog.schema import AssistantRetentionQuery from ee.hogai.utils.types import AssistantState, PartialAssistantState from ee.hogai.utils.types.base import AssistantNodeName @@ -25,7 +25,7 @@ class RetentionGeneratorNode(SchemaGeneratorNode[AssistantRetentionQuery]): return AssistantNodeName.RETENTION_GENERATOR async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: - self.dispatcher.message(AssistantMessage(content="Creating retention query")) + self.dispatcher.update("Creating retention query") prompt = ChatPromptTemplate.from_messages( [ ("system", RETENTION_SYSTEM_PROMPT), diff --git a/ee/hogai/graph/root/nodes.py b/ee/hogai/graph/root/nodes.py index 7cac956db9..b7dabd099c 100644 --- a/ee/hogai/graph/root/nodes.py +++ b/ee/hogai/graph/root/nodes.py @@ -3,27 +3,23 @@ from collections.abc import Awaitable, Mapping, Sequence from typing import TYPE_CHECKING, Literal, TypeVar, Union from uuid import uuid4 +import structlog import posthoganalytics from langchain_core.messages import ( AIMessage as LangchainAIMessage, BaseMessage, HumanMessage as LangchainHumanMessage, + ToolCall, ToolMessage as LangchainToolMessage, ) from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnableConfig from langgraph.errors import NodeInterrupt +from langgraph.types import Send from posthoganalytics import capture_exception from pydantic import BaseModel -from posthog.schema import ( - AssistantMessage, - AssistantTool, - AssistantToolCallMessage, - ContextMessage, - FailureMessage, - HumanMessage, -) +from posthog.schema import AssistantMessage, AssistantToolCallMessage, ContextMessage, FailureMessage, HumanMessage from posthog.models import Team, User @@ -36,8 +32,14 @@ from ee.hogai.tool import ToolMessagesArtifact from ee.hogai.utils.anthropic import add_cache_control, convert_to_anthropic_messages from ee.hogai.utils.helpers import convert_tool_messages_to_dict, normalize_ai_message from ee.hogai.utils.prompt import format_prompt_string -from ee.hogai.utils.types import AssistantMessageUnion, AssistantNodeName, AssistantState, InsightQuery -from ee.hogai.utils.types.base import PartialAssistantState, ReplaceMessages +from ee.hogai.utils.types.base import ( + AssistantMessageUnion, + AssistantNodeName, + AssistantState, + NodePath, + PartialAssistantState, + ReplaceMessages, +) from ee.hogai.utils.types.composed import MaxNodeName from .prompts import ( @@ -51,13 +53,13 @@ from .prompts import ( ROOT_TOOL_DOES_NOT_EXIST, ) from .tools import ( + CreateAndQueryInsightTool, + CreateDashboardTool, ReadDataTool, ReadTaxonomyTool, SearchTool, + SessionSummarizationTool, TodoWriteTool, - create_and_query_insight, - create_dashboard, - session_summarization, ) if TYPE_CHECKING: @@ -66,24 +68,14 @@ if TYPE_CHECKING: SLASH_COMMAND_INIT = "/init" SLASH_COMMAND_REMEMBER = "/remember" -RouteName = Literal[ - "insights", - "root", - "end", - "search_documentation", - "memory_onboarding", - "insights_search", - "billing", - "session_summarization", - "create_dashboard", -] - RootMessageUnion = HumanMessage | AssistantMessage | FailureMessage | AssistantToolCallMessage | ContextMessage T = TypeVar("T", RootMessageUnion, BaseMessage) RootTool = Union[type[BaseModel], "MaxTool"] +logger = structlog.get_logger(__name__) + class RootNode(AssistantNode): MAX_TOOL_CALLS = 24 @@ -95,8 +87,8 @@ class RootNode(AssistantNode): Determines the thinking configuration for the model. """ - def __init__(self, team: Team, user: User): - super().__init__(team, user) + def __init__(self, team: Team, user: User, node_path: tuple[NodePath, ...] | None = None): + super().__init__(team, user, node_path) self._window_manager = AnthropicConversationCompactionManager() async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: @@ -168,12 +160,25 @@ class RootNode(AssistantNode): if messages_to_replace: new_messages = ReplaceMessages([*messages_to_replace, assistant_message]) + # Set new tool call count + tool_call_count = (state.root_tool_calls_count or 0) + 1 if assistant_message.tool_calls else None + return PartialAssistantState( messages=new_messages, + root_tool_calls_count=tool_call_count, root_conversation_start_id=window_id, start_id=start_id, ) + def router(self, state: AssistantState): + last_message = state.messages[-1] + if not isinstance(last_message, AssistantMessage) or not last_message.tool_calls: + return AssistantNodeName.END + return [ + Send(AssistantNodeName.ROOT_TOOLS, state.model_copy(update={"root_tool_call_id": tool_call.id})) + for tool_call in last_message.tool_calls + ] + @property def node_name(self) -> MaxNodeName: return AssistantNodeName.ROOT @@ -226,11 +231,35 @@ class RootNode(AssistantNode): if self._is_hard_limit_reached(state.root_tool_calls_count): return base_model - return base_model.bind_tools(tools, parallel_tool_calls=False) + return base_model.bind_tools(tools, parallel_tool_calls=True) async def _get_tools(self, state: AssistantState, config: RunnableConfig) -> list[RootTool]: from ee.hogai.tool import get_contextual_tool_class + # Static toolkit + default_tools: list[type[MaxTool]] = [ + ReadTaxonomyTool, + ReadDataTool, + SearchTool, + TodoWriteTool, + ] + + # The contextual insights tool overrides the static tool. Only inject if it's injected. + if not CreateAndQueryInsightTool.is_editing_mode(self.context_manager): + default_tools.append(CreateAndQueryInsightTool) + + # Add session summarization tool if enabled + if self._has_session_summarization_feature_flag(): + default_tools.append(SessionSummarizationTool) + + # Add other lower-priority tools + default_tools.extend( + [ + CreateDashboardTool, + ] + ) + + # Processed tools available_tools: list[RootTool] = [] # Initialize the static toolkit @@ -238,37 +267,14 @@ class RootNode(AssistantNode): # This is just to bound the tools to the model dynamic_tools = ( tool_class.create_tool_class( - team=self._team, - user=self._user, - tool_call_id="", - state=state, - config=config, - context_manager=self.context_manager, - ) - for tool_class in ( - ReadTaxonomyTool, - ReadDataTool, - SearchTool, - TodoWriteTool, + team=self._team, user=self._user, state=state, config=config, context_manager=self.context_manager ) + for tool_class in default_tools ) available_tools.extend(await asyncio.gather(*dynamic_tools)) - # Insights tool - tool_names = self.context_manager.get_contextual_tools().keys() - is_editing_insight = AssistantTool.EDIT_CURRENT_INSIGHT in tool_names - if not is_editing_insight: - # This is the default tool, which can be overriden by the MaxTool based tool with the same name - available_tools.append(create_and_query_insight) - - # Check if session summarization is enabled for the user - if self._has_session_summarization_feature_flag(): - available_tools.append(session_summarization) - - # Dashboard creation tool - available_tools.append(create_dashboard) - # Inject contextual tools + tool_names = self.context_manager.get_contextual_tools().keys() awaited_contextual_tools: list[Awaitable[RootTool]] = [] for tool_name in tool_names: ContextualMaxToolClass = get_contextual_tool_class(tool_name) @@ -278,7 +284,6 @@ class RootNode(AssistantNode): ContextualMaxToolClass.create_tool_class( team=self._team, user=self._user, - tool_call_id="", state=state, config=config, context_manager=self.context_manager, @@ -366,51 +371,23 @@ class RootNodeTools(AssistantNode): def node_name(self) -> MaxNodeName: return AssistantNodeName.ROOT_TOOLS - async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: + async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState | None: last_message = state.messages[-1] - if not isinstance(last_message, AssistantMessage) or not last_message.tool_calls: - # Reset tools. - return PartialAssistantState(root_tool_calls_count=0) - tool_call_count = state.root_tool_calls_count or 0 + reset_state = PartialAssistantState(root_tool_call_id=None) + # Should never happen, but just in case. + if not isinstance(last_message, AssistantMessage) or not last_message.id or not state.root_tool_call_id: + return reset_state - tools_calls = last_message.tool_calls - if len(tools_calls) != 1: - raise ValueError("Expected exactly one tool call.") - - tool_names = self.context_manager.get_contextual_tools().keys() - is_editing_insight = AssistantTool.EDIT_CURRENT_INSIGHT in tool_names - tool_call = tools_calls[0] + # Find the current tool call in the last message. + tool_call = next( + (tool_call for tool_call in last_message.tool_calls or [] if tool_call.id == state.root_tool_call_id), None + ) + if not tool_call: + return reset_state from ee.hogai.tool import get_contextual_tool_class - if tool_call.name == "create_and_query_insight" and not is_editing_insight: - return PartialAssistantState( - root_tool_call_id=tool_call.id, - root_tool_insight_plan=tool_call.args["query_description"], - root_tool_calls_count=tool_call_count + 1, - ) - if tool_call.name == "session_summarization": - return PartialAssistantState( - root_tool_call_id=tool_call.id, - session_summarization_query=tool_call.args["session_summarization_query"], - # Safety net in case the argument is missing to avoid raising exceptions internally - should_use_current_filters=tool_call.args.get("should_use_current_filters", False), - summary_title=tool_call.args.get("summary_title"), - root_tool_calls_count=tool_call_count + 1, - ) - if tool_call.name == "create_dashboard": - raw_queries = tool_call.args["search_insights_queries"] - search_insights_queries = [InsightQuery.model_validate(query) for query in raw_queries] - - return PartialAssistantState( - root_tool_call_id=tool_call.id, - dashboard_name=tool_call.args.get("dashboard_name"), - search_insights_queries=search_insights_queries, - root_tool_calls_count=tool_call_count + 1, - ) - - # MaxTool flow ToolClass = get_contextual_tool_class(tool_call.name) # If the tool doesn't exist, return the message to the agent @@ -423,25 +400,32 @@ class RootNodeTools(AssistantNode): tool_call_id=tool_call.id, ) ], - root_tool_calls_count=tool_call_count + 1, ) # Initialize the tool and process it tool_class = await ToolClass.create_tool_class( team=self._team, user=self._user, - tool_call_id=tool_call.id, + # Tricky: set the node path to associated with the tool call + node_path=( + *self.node_path[:-1], + NodePath(name=AssistantNodeName.ROOT_TOOLS, message_id=last_message.id, tool_call_id=tool_call.id), + ), state=state, config=config, context_manager=self.context_manager, ) + try: - result = await tool_class.ainvoke(tool_call.model_dump(), config) + result = await tool_class.ainvoke( + ToolCall(type="tool_call", name=tool_call.name, args=tool_call.args, id=tool_call.id), config=config + ) if not isinstance(result, LangchainToolMessage): raise ValueError( f"Tool '{tool_call.name}' returned {type(result).__name__}, expected LangchainToolMessage" ) except Exception as e: + logger.exception("Error calling tool", extra={"tool_name": tool_call.name, "error": str(e)}) capture_exception( e, distinct_id=self._get_user_distinct_id(config), properties=self._get_debug_props(config) ) @@ -453,38 +437,11 @@ class RootNodeTools(AssistantNode): tool_call_id=tool_call.id, ) ], - root_tool_calls_count=tool_call_count + 1, ) if isinstance(result.artifact, ToolMessagesArtifact): return PartialAssistantState( messages=result.artifact.messages, - root_tool_calls_count=tool_call_count + 1, - ) - - # Handle the basic toolkit - if result.name == "search" and isinstance(result.artifact, dict): - match result.artifact.get("kind"): - case "insights": - return PartialAssistantState( - root_tool_call_id=tool_call.id, - search_insights_query=result.artifact.get("query"), - root_tool_calls_count=tool_call_count + 1, - ) - case "docs": - return PartialAssistantState( - root_tool_call_id=tool_call.id, - root_tool_calls_count=tool_call_count + 1, - ) - - if ( - result.name == "read_data" - and isinstance(result.artifact, dict) - and result.artifact.get("kind") == "billing_info" - ): - return PartialAssistantState( - root_tool_call_id=tool_call.id, - root_tool_calls_count=tool_call_count + 1, ) # If this is a navigation tool call, pause the graph execution @@ -496,7 +453,6 @@ class RootNodeTools(AssistantNode): id=str(uuid4()), tool_call_id=tool_call.id, ) - self.dispatcher.message(navigate_message) # Raising a `NodeInterrupt` ensures the assistant graph stops here and # surfaces the navigation confirmation to the client. The next user # interaction will resume the graph with potentially different @@ -512,29 +468,11 @@ class RootNodeTools(AssistantNode): return PartialAssistantState( messages=[tool_message], - root_tool_calls_count=tool_call_count + 1, ) - def router(self, state: AssistantState) -> RouteName: + # This is only for the Inkeep node. Remove when inkeep_docs is removed. + def router(self, state: AssistantState) -> Literal["root", "end"]: last_message = state.messages[-1] - if isinstance(last_message, AssistantToolCallMessage): return "root" # Let the root either proceed or finish, since it now can see the tool call result - if isinstance(last_message, AssistantMessage) and state.root_tool_call_id: - tool_calls = getattr(last_message, "tool_calls", None) - if tool_calls and len(tool_calls) > 0: - tool_call = tool_calls[0] - tool_call_name = tool_call.name - if tool_call_name == "read_data" and tool_call.args.get("kind") == "billing_info": - return "billing" - if tool_call_name == "create_dashboard": - return "create_dashboard" - if state.root_tool_insight_plan: - return "insights" - elif state.search_insights_query: - return "insights_search" - elif state.session_summarization_query: - return "session_summarization" - else: - return "search_documentation" return "end" diff --git a/ee/hogai/graph/root/prompts.py b/ee/hogai/graph/root/prompts.py index 411ed94ca2..de6d2671a1 100644 --- a/ee/hogai/graph/root/prompts.py +++ b/ee/hogai/graph/root/prompts.py @@ -112,6 +112,10 @@ The user is a product engineer and will primarily request you perform product ma - Tool results and user messages may include tags. tags contain useful information and reminders. They are NOT part of the user's provided input or the tool result. + +- You can invoke multiple tools within a single response. When a request involves several independent pieces of information, batch your tool calls together for optimal performance + + {{{billing_context}}} {{{core_memory_prompt}}} diff --git a/ee/hogai/graph/root/test/test_nodes.py b/ee/hogai/graph/root/test/test_nodes.py index d878cee623..8c060a4354 100644 --- a/ee/hogai/graph/root/test/test_nodes.py +++ b/ee/hogai/graph/root/test/test_nodes.py @@ -38,6 +38,7 @@ from ee.hogai.graph.root.prompts import ( ROOT_BILLING_CONTEXT_WITH_ACCESS_PROMPT, ROOT_BILLING_CONTEXT_WITH_NO_ACCESS_PROMPT, ) +from ee.hogai.tool import ToolMessagesArtifact from ee.hogai.utils.tests import FakeChatAnthropic, FakeChatOpenAI from ee.hogai.utils.types import AssistantState, PartialAssistantState from ee.hogai.utils.types.base import AssistantMessageUnion @@ -644,6 +645,147 @@ class TestRootNode(ClickhouseTestMixin, BaseTest): result = node._is_hard_limit_reached(tool_calls_count) self.assertEqual(result, expected) + async def test_node_increments_tool_count_on_tool_call(self): + """Test that RootNode increments tool count when assistant makes a tool call""" + with patch( + "ee.hogai.graph.root.nodes.RootNode._get_model", + return_value=FakeChatOpenAI( + responses=[ + LangchainAIMessage( + content="Let me help", + tool_calls=[ + { + "id": "tool-1", + "name": "create_and_query_insight", + "args": {"query_description": "test"}, + } + ], + ) + ] + ), + ): + node = RootNode(self.team, self.user) + + # Test starting from no tool calls + state_1 = AssistantState(messages=[HumanMessage(content="Hello")]) + result_1 = await node.arun(state_1, {}) + self.assertEqual(result_1.root_tool_calls_count, 1) + + # Test incrementing from existing count + state_2 = AssistantState( + messages=[HumanMessage(content="Hello")], + root_tool_calls_count=5, + ) + result_2 = await node.arun(state_2, {}) + self.assertEqual(result_2.root_tool_calls_count, 6) + + async def test_node_resets_tool_count_on_plain_response(self): + """Test that RootNode resets tool count when assistant responds without tool calls""" + with patch( + "ee.hogai.graph.root.nodes.RootNode._get_model", + return_value=FakeChatOpenAI(responses=[LangchainAIMessage(content="Here's your answer")]), + ): + node = RootNode(self.team, self.user) + + state = AssistantState( + messages=[HumanMessage(content="Hello")], + root_tool_calls_count=5, + ) + result = await node.arun(state, {}) + self.assertIsNone(result.root_tool_calls_count) + + def test_router_returns_end_for_plain_response(self): + """Test that router returns END when message has no tool calls""" + from ee.hogai.utils.types import AssistantNodeName + + node = RootNode(self.team, self.user) + + state = AssistantState( + messages=[ + HumanMessage(content="Hello"), + AssistantMessage(content="Hi there!"), + ] + ) + result = node.router(state) + self.assertEqual(result, AssistantNodeName.END) + + def test_router_returns_send_for_single_tool_call(self): + """Test that router returns Send for single tool call""" + from langgraph.types import Send + + from ee.hogai.utils.types import AssistantNodeName + + node = RootNode(self.team, self.user) + + state = AssistantState( + messages=[ + HumanMessage(content="Generate insights"), + AssistantMessage( + content="Let me help", + tool_calls=[ + AssistantToolCall( + id="tool-1", + name="create_and_query_insight", + args={"query_description": "test"}, + ) + ], + ), + ] + ) + result = node.router(state) + + # Verify it's a list of Send objects + self.assertIsInstance(result, list) + self.assertEqual(len(result), 1) + self.assertIsInstance(result[0], Send) + self.assertEqual(result[0].node, AssistantNodeName.ROOT_TOOLS) + self.assertEqual(result[0].arg.root_tool_call_id, "tool-1") + + def test_router_returns_multiple_sends_for_parallel_tool_calls(self): + """Test that router returns multiple Send objects for parallel tool calls""" + from langgraph.types import Send + + from ee.hogai.utils.types import AssistantNodeName + + node = RootNode(self.team, self.user) + + state = AssistantState( + messages=[ + HumanMessage(content="Generate multiple insights"), + AssistantMessage( + content="Let me create several insights", + tool_calls=[ + AssistantToolCall( + id="tool-1", + name="create_and_query_insight", + args={"query_description": "trends"}, + ), + AssistantToolCall( + id="tool-2", + name="create_and_query_insight", + args={"query_description": "funnel"}, + ), + AssistantToolCall( + id="tool-3", + name="create_and_query_insight", + args={"query_description": "retention"}, + ), + ], + ), + ] + ) + result = node.router(state) + + # Verify it's a list of Send objects + self.assertIsInstance(result, list) + self.assertEqual(len(result), 3) + + # Verify all are Send objects to ROOT_TOOLS + for i, send in enumerate(result): + self.assertIsInstance(send, Send) + self.assertEqual(send.node, AssistantNodeName.ROOT_TOOLS) + self.assertEqual(send.arg.root_tool_call_id, f"tool-{i+1}") + class TestRootNodeTools(BaseTest): def test_node_tools_router(self): @@ -675,9 +817,13 @@ class TestRootNodeTools(BaseTest): node = RootNodeTools(self.team, self.user) state = AssistantState(messages=[HumanMessage(content="Hello")]) result = await node.arun(state, {}) - self.assertEqual(result, PartialAssistantState(root_tool_calls_count=0)) + self.assertEqual(result, PartialAssistantState(root_tool_call_id=None)) + + @patch("ee.hogai.graph.root.tools.create_and_query_insight.CreateAndQueryInsightTool._arun_impl") + async def test_run_valid_tool_call(self, create_and_query_insight_mock): + test_message = AssistantToolCallMessage(content="Tool result", tool_call_id="xyz", id="msg-1") + create_and_query_insight_mock.return_value = ("", ToolMessagesArtifact(messages=[test_message])) - async def test_run_valid_tool_call(self): node = RootNodeTools(self.team, self.user) state = AssistantState( messages=[ @@ -688,17 +834,20 @@ class TestRootNodeTools(BaseTest): AssistantToolCall( id="xyz", name="create_and_query_insight", - args={"query_kind": "trends", "query_description": "test query"}, + args={"query_description": "test query"}, ) ], ) - ] + ], + root_tool_call_id="xyz", ) result = await node.arun(state, {}) self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(result.root_tool_call_id, "xyz") - self.assertEqual(result.root_tool_insight_plan, "test query") - self.assertEqual(result.root_tool_insight_type, None) # Insight type is determined by query planner node + assert result is not None + self.assertEqual(len(result.messages), 1) + assert isinstance(result.messages[0], AssistantToolCallMessage) + self.assertEqual(result.messages[0].tool_call_id, "xyz") + create_and_query_insight_mock.assert_called_once_with(query_description="test query") async def test_run_valid_contextual_tool_call(self): node = RootNodeTools(self.team, self.user) @@ -715,7 +864,8 @@ class TestRootNodeTools(BaseTest): ) ], ) - ] + ], + root_tool_call_id="xyz", ) result = await node.arun( @@ -730,69 +880,9 @@ class TestRootNodeTools(BaseTest): ) self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(result.root_tool_call_id, None) # Tool was fully handled by the node - self.assertIsNone(result.root_tool_insight_plan) # No insight plan for contextual tools - self.assertIsNone(result.root_tool_insight_type) # No insight type for contextual tools - - async def test_run_multiple_tool_calls_raises(self): - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Hello", - id="test-id", - tool_calls=[ - AssistantToolCall( - id="xyz1", - name="create_and_query_insight", - args={"query_kind": "trends", "query_description": "test query 1"}, - ), - AssistantToolCall( - id="xyz2", - name="create_and_query_insight", - args={"query_kind": "funnel", "query_description": "test query 2"}, - ), - ], - ) - ] - ) - with self.assertRaises(ValueError) as cm: - await node.arun(state, {}) - self.assertEqual(str(cm.exception), "Expected exactly one tool call.") - - async def test_run_increments_tool_count(self): - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Hello", - id="test-id", - tool_calls=[ - AssistantToolCall( - id="xyz", - name="create_and_query_insight", - args={"query_kind": "trends", "query_description": "test query"}, - ) - ], - ) - ], - root_tool_calls_count=2, # Starting count - ) - result = await node.arun(state, {}) - self.assertEqual(result.root_tool_calls_count, 3) # Should increment by 1 - - async def test_run_resets_tool_count(self): - node = RootNodeTools(self.team, self.user) - - # Test reset when no tool calls in AssistantMessage - state_1 = AssistantState(messages=[AssistantMessage(content="Hello", tool_calls=[])], root_tool_calls_count=3) - result = await node.arun(state_1, {}) - self.assertEqual(result.root_tool_calls_count, 0) - - # Test reset when last message is HumanMessage - state_2 = AssistantState(messages=[HumanMessage(content="Hello")], root_tool_calls_count=3) - result = await node.arun(state_2, {}) - self.assertEqual(result.root_tool_calls_count, 0) + assert result is not None + self.assertEqual(len(result.messages), 1) + self.assertIsInstance(result.messages[0], AssistantToolCallMessage) async def test_navigate_tool_call_raises_node_interrupt(self): """Test that navigate tool calls raise NodeInterrupt to pause graph execution""" @@ -805,7 +895,8 @@ class TestRootNodeTools(BaseTest): id="test-id", tool_calls=[AssistantToolCall(id="nav-123", name="navigate", args={"page_key": "insights"})], ) - ] + ], + root_tool_call_id="nav-123", ) mock_navigate_tool = AsyncMock() @@ -828,319 +919,6 @@ class TestRootNodeTools(BaseTest): self.assertEqual(interrupt_data.tool_call_id, "nav-123") self.assertEqual(interrupt_data.ui_payload, {"navigate": {"page_key": "insights"}}) - def test_billing_tool_routing(self): - """Test that billing tool calls are routed correctly""" - node = RootNodeTools(self.team, self.user) - - # Create state with billing tool call (read_data with kind=billing_info) - state = AssistantState( - messages=[ - AssistantMessage( - content="Let me check your billing information", - tool_calls=[AssistantToolCall(id="billing-123", name="read_data", args={"kind": "billing_info"})], - ) - ], - root_tool_call_id="billing-123", - ) - - # Should route to billing - self.assertEqual(node.router(state), "billing") - - def test_router_insights_path(self): - """Test router routes to insights when root_tool_insight_plan is set""" - node = RootNodeTools(self.team, self.user) - - state = AssistantState( - messages=[ - AssistantMessage( - content="Creating insight", - tool_calls=[ - AssistantToolCall( - id="insight-123", - name="create_and_query_insight", - args={"query_kind": "trends", "query_description": "test"}, - ) - ], - ) - ], - root_tool_call_id="insight-123", - root_tool_insight_plan="test query plan", - ) - - self.assertEqual(node.router(state), "insights") - - def test_router_insights_search_path(self): - """Test router routes to insights_search when search_insights_query is set""" - node = RootNodeTools(self.team, self.user) - - state = AssistantState( - messages=[ - AssistantMessage( - content="Searching insights", - tool_calls=[AssistantToolCall(id="search-123", name="search", args={"kind": "insights"})], - ) - ], - root_tool_call_id="search-123", - search_insights_query="test search query", - ) - - self.assertEqual(node.router(state), "insights_search") - - def test_router_session_summarization_path(self): - """Test router routes to session_summarization when session_summarization_query is set""" - node = RootNodeTools(self.team, self.user) - - state = AssistantState( - messages=[ - AssistantMessage( - content="Summarizing sessions", - tool_calls=[ - AssistantToolCall( - id="session-123", name="session_summarization", args={"session_summarization_query": "test"} - ) - ], - ) - ], - root_tool_call_id="session-123", - session_summarization_query="test session query", - ) - - self.assertEqual(node.router(state), "session_summarization") - - def test_router_create_dashboard_path(self): - """Test router routes to create_dashboard when create_dashboard tool is called""" - node = RootNodeTools(self.team, self.user) - - state = AssistantState( - messages=[ - AssistantMessage( - content="Creating dashboard", - tool_calls=[ - AssistantToolCall( - id="dashboard-123", name="create_dashboard", args={"search_insights_queries": []} - ) - ], - ) - ], - root_tool_call_id="dashboard-123", - ) - - self.assertEqual(node.router(state), "create_dashboard") - - def test_router_search_documentation_fallback(self): - """Test router routes to search_documentation when root_tool_call_id is set but no specific route""" - node = RootNodeTools(self.team, self.user) - - state = AssistantState( - messages=[ - AssistantMessage( - content="Searching docs", - tool_calls=[AssistantToolCall(id="search-123", name="search", args={"kind": "docs"})], - ) - ], - root_tool_call_id="search-123", - ) - - self.assertEqual(node.router(state), "search_documentation") - - async def test_arun_session_summarization_with_all_args(self): - """Test session_summarization tool call with all arguments""" - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Summarizing sessions", - id="test-id", - tool_calls=[ - AssistantToolCall( - id="session-123", - name="session_summarization", - args={ - "session_summarization_query": "test query", - "should_use_current_filters": True, - "summary_title": "Test Summary", - }, - ) - ], - ) - ] - ) - result = await node.arun(state, {}) - self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(result.root_tool_call_id, "session-123") - self.assertEqual(result.session_summarization_query, "test query") - self.assertEqual(result.should_use_current_filters, True) - self.assertEqual(result.summary_title, "Test Summary") - - async def test_arun_session_summarization_missing_optional_args(self): - """Test session_summarization tool call with missing optional arguments""" - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Summarizing sessions", - id="test-id", - tool_calls=[ - AssistantToolCall( - id="session-123", - name="session_summarization", - args={"session_summarization_query": "test query"}, - ) - ], - ) - ] - ) - result = await node.arun(state, {}) - self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(result.should_use_current_filters, False) # Default value - self.assertIsNone(result.summary_title) - - async def test_arun_create_dashboard_with_queries(self): - """Test create_dashboard tool call with search_insights_queries""" - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Creating dashboard", - id="test-id", - tool_calls=[ - AssistantToolCall( - id="dashboard-123", - name="create_dashboard", - args={ - "dashboard_name": "Test Dashboard", - "search_insights_queries": [ - {"name": "Query 1", "description": "Trends insight description"}, - {"name": "Query 2", "description": "Funnel insight description"}, - ], - }, - ) - ], - ) - ] - ) - result = await node.arun(state, {}) - self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(result.root_tool_call_id, "dashboard-123") - self.assertEqual(result.dashboard_name, "Test Dashboard") - self.assertIsNotNone(result.search_insights_queries) - assert result.search_insights_queries is not None - self.assertEqual(len(result.search_insights_queries), 2) - self.assertEqual(result.search_insights_queries[0].name, "Query 1") - self.assertEqual(result.search_insights_queries[1].name, "Query 2") - - async def test_arun_search_tool_insights_kind(self): - """Test search tool with kind=insights""" - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Searching insights", - id="test-id", - tool_calls=[ - AssistantToolCall(id="search-123", name="search", args={"query": "test", "kind": "insights"}) - ], - ) - ] - ) - - mock_tool = AsyncMock() - mock_tool.ainvoke.return_value = LangchainToolMessage( - content="Search results", - tool_call_id="search-123", - name="search", - artifact={"kind": "insights", "query": "test"}, - ) - - with mock_contextual_tool(mock_tool): - result = await node.arun(state, {"configurable": {"contextual_tools": {"search": {}}}}) - - self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(result.root_tool_call_id, "search-123") - self.assertEqual(result.search_insights_query, "test") - - async def test_arun_search_tool_docs_kind(self): - """Test search tool with kind=docs""" - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Searching docs", - id="test-id", - tool_calls=[ - AssistantToolCall(id="search-123", name="search", args={"query": "test", "kind": "docs"}) - ], - ) - ] - ) - - mock_tool = AsyncMock() - mock_tool.ainvoke.return_value = LangchainToolMessage( - content="Docs results", tool_call_id="search-123", name="search", artifact={"kind": "docs"} - ) - - with mock_contextual_tool(mock_tool): - result = await node.arun(state, {"configurable": {"contextual_tools": {"search": {}}}}) - - self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(result.root_tool_call_id, "search-123") - - async def test_arun_read_data_billing_info(self): - """Test read_data tool with kind=billing_info""" - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Reading billing info", - id="test-id", - tool_calls=[AssistantToolCall(id="read-123", name="read_data", args={"kind": "billing_info"})], - ) - ] - ) - - mock_tool = AsyncMock() - mock_tool.ainvoke.return_value = LangchainToolMessage( - content="Billing data", tool_call_id="read-123", name="read_data", artifact={"kind": "billing_info"} - ) - - with mock_contextual_tool(mock_tool): - result = await node.arun(state, {"configurable": {"contextual_tools": {"read_data": {}}}}) - - self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(result.root_tool_call_id, "read-123") - - async def test_arun_tool_updates_state(self): - """Test that when a tool updates its _state, the new messages are included""" - node = RootNodeTools(self.team, self.user) - state = AssistantState( - messages=[ - AssistantMessage( - content="Using tool", - id="test-id", - tool_calls=[AssistantToolCall(id="tool-123", name="test_tool", args={})], - ) - ] - ) - - mock_tool = AsyncMock() - # Simulate tool appending a message to state - updated_state = AssistantState( - messages=[ - *state.messages, - AssistantToolCallMessage(content="Tool result", tool_call_id="tool-123", id="msg-1"), - ] - ) - mock_tool._state = updated_state - mock_tool.ainvoke.return_value = LangchainToolMessage(content="Tool result", tool_call_id="tool-123") - - with mock_contextual_tool(mock_tool): - result = await node.arun(state, {"configurable": {"contextual_tools": {"test_tool": {}}}}) - - # Should include the new message from the updated state - self.assertIsInstance(result, PartialAssistantState) - self.assertEqual(len(result.messages), 1) - self.assertIsInstance(result.messages[0], AssistantToolCallMessage) - async def test_arun_tool_returns_wrong_type_returns_error_message(self): """Test that tool returning wrong type returns an error message""" node = RootNodeTools(self.team, self.user) @@ -1151,7 +929,8 @@ class TestRootNodeTools(BaseTest): id="test-id", tool_calls=[AssistantToolCall(id="tool-123", name="test_tool", args={})], ) - ] + ], + root_tool_call_id="tool-123", ) mock_tool = AsyncMock() @@ -1161,10 +940,11 @@ class TestRootNodeTools(BaseTest): result = await node.arun(state, {"configurable": {"contextual_tools": {"test_tool": {}}}}) self.assertIsInstance(result, PartialAssistantState) + assert result is not None self.assertEqual(len(result.messages), 1) assert isinstance(result.messages[0], AssistantToolCallMessage) self.assertEqual(result.messages[0].tool_call_id, "tool-123") - self.assertEqual(result.root_tool_calls_count, 1) + self.assertIn("internal error", result.messages[0].content) async def test_arun_unknown_tool_returns_error_message(self): """Test that unknown tool name returns an error message""" @@ -1176,14 +956,16 @@ class TestRootNodeTools(BaseTest): id="test-id", tool_calls=[AssistantToolCall(id="tool-123", name="unknown_tool", args={})], ) - ] + ], + root_tool_call_id="tool-123", ) with patch("ee.hogai.tool.get_contextual_tool_class", return_value=None): result = await node.arun(state, {}) self.assertIsInstance(result, PartialAssistantState) + assert result is not None self.assertEqual(len(result.messages), 1) assert isinstance(result.messages[0], AssistantToolCallMessage) self.assertEqual(result.messages[0].tool_call_id, "tool-123") - self.assertEqual(result.root_tool_calls_count, 1) + self.assertIn("does not exist", result.messages[0].content) diff --git a/ee/hogai/graph/root/tools/__init__.py b/ee/hogai/graph/root/tools/__init__.py index 793c94b097..7bf9c6298f 100644 --- a/ee/hogai/graph/root/tools/__init__.py +++ b/ee/hogai/graph/root/tools/__init__.py @@ -1,21 +1,26 @@ -from .legacy import create_and_query_insight, create_dashboard, session_summarization +from .create_and_query_insight import CreateAndQueryInsightTool, CreateAndQueryInsightToolArgs +from .create_dashboard import CreateDashboardTool, CreateDashboardToolArgs from .navigate import NavigateTool, NavigateToolArgs from .read_data import ReadDataTool, ReadDataToolArgs from .read_taxonomy import ReadTaxonomyTool from .search import SearchTool, SearchToolArgs +from .session_summarization import SessionSummarizationTool, SessionSummarizationToolArgs from .todo_write import TodoWriteTool, TodoWriteToolArgs __all__ = [ + "CreateAndQueryInsightTool", + "CreateAndQueryInsightToolArgs", + "CreateDashboardTool", + "CreateDashboardToolArgs", + "NavigateTool", + "NavigateToolArgs", + "ReadDataTool", + "ReadDataToolArgs", "ReadTaxonomyTool", "SearchTool", "SearchToolArgs", - "ReadDataTool", - "ReadDataToolArgs", + "SessionSummarizationTool", + "SessionSummarizationToolArgs", "TodoWriteTool", "TodoWriteToolArgs", - "NavigateTool", - "NavigateToolArgs", - "create_and_query_insight", - "session_summarization", - "create_dashboard", ] diff --git a/ee/hogai/graph/root/tools/create_and_query_insight.py b/ee/hogai/graph/root/tools/create_and_query_insight.py new file mode 100644 index 0000000000..a5f6985472 --- /dev/null +++ b/ee/hogai/graph/root/tools/create_and_query_insight.py @@ -0,0 +1,206 @@ +from typing import Literal + +from pydantic import BaseModel, Field + +from posthog.schema import AssistantTool, AssistantToolCallMessage, VisualizationMessage + +from ee.hogai.context.context import AssistantContextManager +from ee.hogai.graph.insights_graph.graph import InsightsGraph +from ee.hogai.graph.schema_generator.nodes import SchemaGenerationException +from ee.hogai.tool import MaxTool, ToolMessagesArtifact +from ee.hogai.utils.prompt import format_prompt_string +from ee.hogai.utils.types.base import AssistantState + +INSIGHT_TOOL_PROMPT = """ +Use this tool to create a product analytics insight for a given natural language description by spawning a subagent. +The tool generates a query and returns formatted text results for a specific data question or iterates on a previous query. It only retrieves a single query per call. If the user asks for multiple insights, you need to decompose a query into multiple subqueries and call the tool for each subquery. + +Follow these guidelines when retrieving data: +- If the same insight is already in the conversation history, reuse the retrieved data only when this does not violate the section (i.e. only when a presence-check, count, or sort on existing columns is enough). +- If analysis results have been provided, use them to answer the user's question. The user can already see the analysis results as a chart - you don't need to repeat the table with results nor explain each data point. +- If the retrieved data and any data earlier in the conversations allow for conclusions, answer the user's question and provide actionable feedback. +- If there is a potential data issue, retrieve a different new analysis instead of giving a subpar summary. Note: empty data is NOT a potential data issue. +- If the query cannot be answered with a UI-built insight type - trends, funnels, retention - choose the SQL type to answer the question (e.g. for listing events or aggregating in ways that aren't supported in trends/funnels/retention). + +IMPORTANT: Avoid generic advice. Take into account what you know about the product. Your answer needs to be super high-impact and no more than a few sentences. +Remember: do NOT retrieve data for the same query more than 3 times in a row. + +# Data schema + +You can pass events, actions, properties, and property values to this tool by specifying the "Data schema" section. + + +User: Calculate onboarding completion rate for the last week. +Assistant: I'm going to retrieve the existing data schema first. +*Retrieves matching events, properties, and property values* +Assistant: I'm going to create a new trends insight. +*Calls this tool with the query description: "Trends insight of the onboarding completion rate. Data schema: Relevant matching data schema"* + + +# Supported insight types +## Trends +A trends insight visualizes events over time using time series. They're useful for finding patterns in historical data. + +The trends insights have the following features: +- The insight can show multiple trends in one request. +- Custom formulas can calculate derived metrics, like `A/B*100` to calculate a ratio. +- Filter and break down data using multiple properties. +- Compare with the previous period and sample data. +- Apply various aggregation types, like sum, average, etc., and chart types. +- And more. + +Examples of use cases include: +- How the product's most important metrics change over time. +- Long-term patterns, or cycles in product's usage. +- The usage of different features side-by-side. +- How the properties of events vary using aggregation (sum, average, etc). +- Users can also visualize the same data points in a variety of ways. + +## Funnel +A funnel insight visualizes a sequence of events that users go through in a product. They use percentages as the primary aggregation type. Funnels use two or more series, so the conversation history should mention at least two events. + +The funnel insights have the following features: +- Various visualization types (steps, time-to-convert, historical trends). +- Filter data and apply exclusion steps. +- Break down data using a single property. +- Specify conversion windows, details of conversion calculation, attribution settings. +- Sample data. +- And more. + +Examples of use cases include: +- Conversion rates. +- Drop off steps. +- Steps with the highest friction and time to convert. +- If product changes are improving their funnel over time. +- Average/median time to convert. +- Conversion trends over time. + +## Retention +A retention insight visualizes how many users return to the product after performing some action. They're useful for understanding user engagement and retention. + +The retention insights have the following features: filter data, sample data, and more. + +Examples of use cases include: +- How many users come back and perform an action after their first visit. +- How many users come back to perform action X after performing action Y. +- How often users return to use a specific feature. + +## SQL +The 'sql' insight type allows you to write arbitrary SQL queries to retrieve data. + +The SQL insights have the following features: +- Filter data using arbitrary SQL. +- All ClickHouse SQL features. +- You can nest subqueries as needed. +""".strip() + +INSIGHT_TOOL_CONTEXT_PROMPT_TEMPLATE = """ +The user is currently editing an insight (aka query). Here is that insight's current definition, which can be edited using the `create_and_query_insight` tool: + +```json +{current_query} +``` + + +Do not remove any fields from the current insight definition. Do not change any other fields than the ones the user asked for. Keep the rest as is. + +""".strip() + +INSIGHT_TOOL_FAILURE_SYSTEM_REMINDER_PROMPT = """ + +Inform the user that you've encountered an error during the creation of the insight. Afterwards, try to generate a new insight with a different query. +Terminate if the error persists. + +""".strip() + +INSIGHT_TOOL_HANDLED_FAILURE_PROMPT = """ +The agent has encountered the error while creating an insight. + +Generated output: +``` +{{{output}}} +``` + +Error message: +``` +{{{error_message}}} +``` + +{{{system_reminder}}} +""".strip() + + +INSIGHT_TOOL_UNHANDLED_FAILURE_PROMPT = """ +The agent has encountered an unknown error while creating an insight. +{{{system_reminder}}} +""".strip() + + +class CreateAndQueryInsightToolArgs(BaseModel): + query_description: str = Field( + description=( + "A description of the query to generate, encapsulating the details of the user's request. " + "Include all relevant context from earlier messages too, as the tool won't see that conversation history. " + "If an existing insight has been used as a starting point, include that insight's filters and query in the description. " + "Don't be overly prescriptive with event or property names, unless the user indicated they mean this specific name (e.g. with quotes). " + "If the users seems to ask for a list of entities, rather than a count, state this explicitly." + ) + ) + + +class CreateAndQueryInsightTool(MaxTool): + name: Literal["create_and_query_insight"] = "create_and_query_insight" + args_schema: type[BaseModel] = CreateAndQueryInsightToolArgs + description: str = INSIGHT_TOOL_PROMPT + context_prompt_template: str = INSIGHT_TOOL_CONTEXT_PROMPT_TEMPLATE + thinking_message: str = "Coming up with an insight" + + async def _arun_impl(self, query_description: str) -> tuple[str, ToolMessagesArtifact | None]: + graph = InsightsGraph(self._team, self._user).compile_full_graph() + new_state = self._state.model_copy( + update={ + "root_tool_call_id": self.tool_call_id, + "root_tool_insight_plan": query_description, + }, + deep=True, + ) + try: + dict_state = await graph.ainvoke(new_state) + except SchemaGenerationException as e: + return format_prompt_string( + INSIGHT_TOOL_HANDLED_FAILURE_PROMPT, + output=e.llm_output, + error_message=e.validation_message, + system_reminder=INSIGHT_TOOL_FAILURE_SYSTEM_REMINDER_PROMPT, + ), None + + updated_state = AssistantState.model_validate(dict_state) + maybe_viz_message, tool_call_message = updated_state.messages[-2:] + + if not isinstance(tool_call_message, AssistantToolCallMessage): + return format_prompt_string( + INSIGHT_TOOL_UNHANDLED_FAILURE_PROMPT, system_reminder=INSIGHT_TOOL_FAILURE_SYSTEM_REMINDER_PROMPT + ), None + + # If the previous message is not a visualization message, the agent has requested human feedback. + if not isinstance(maybe_viz_message, VisualizationMessage): + return "", ToolMessagesArtifact(messages=[tool_call_message]) + + # If the contextual tool is available, we're editing an insight. + # Add the UI payload to the tool call message. + if self.is_editing_mode(self._context_manager): + tool_call_message = AssistantToolCallMessage( + content=tool_call_message.content, + ui_payload={self.get_name(): maybe_viz_message.answer.model_dump(exclude_none=True)}, + id=tool_call_message.id, + tool_call_id=tool_call_message.tool_call_id, + ) + + return "", ToolMessagesArtifact(messages=[maybe_viz_message, tool_call_message]) + + @classmethod + def is_editing_mode(cls, context_manager: AssistantContextManager) -> bool: + """ + Determines if the tool is in editing mode. + """ + return AssistantTool.CREATE_AND_QUERY_INSIGHT.value in context_manager.get_contextual_tools() diff --git a/ee/hogai/graph/root/tools/create_dashboard.py b/ee/hogai/graph/root/tools/create_dashboard.py new file mode 100644 index 0000000000..23d6b6d906 --- /dev/null +++ b/ee/hogai/graph/root/tools/create_dashboard.py @@ -0,0 +1,53 @@ +from typing import Literal + +from langchain_core.runnables import RunnableLambda +from pydantic import BaseModel, Field + +from ee.hogai.graph.dashboards.nodes import DashboardCreationNode +from ee.hogai.tool import MaxTool, ToolMessagesArtifact +from ee.hogai.utils.types.base import AssistantState, InsightQuery, PartialAssistantState + +CREATE_DASHBOARD_TOOL_PROMPT = """ +Use this tool when users ask to create, build, or make a new dashboard with insights. +This tool will search for existing insights that match the user's requirements so no need to call `search` tool, or create new insights if none are found, then combine them into a dashboard. +Do not call this tool if the user only asks to find, search for, or look up existing insights and does not ask to create a dashboard. +If you decided to use this tool, there is no need to call `search_insights` tool beforehand. The tool will search for existing insights that match the user's requirements and create new insights if none are found. +""".strip() + + +class CreateDashboardToolArgs(BaseModel): + search_insights_queries: list[InsightQuery] = Field( + description="A list of insights to be included in the dashboard. Include all the insights that the user mentioned." + ) + dashboard_name: str = Field( + description=( + "The name of the dashboard to be created based on the user request. It should be short and concise as it will be displayed as a header in the dashboard tile." + ) + ) + + +class CreateDashboardTool(MaxTool): + name: Literal["create_dashboard"] = "create_dashboard" + description: str = CREATE_DASHBOARD_TOOL_PROMPT + thinking_message: str = "Creating a dashboard" + context_prompt_template: str = "Creates a dashboard based on the user's request" + args_schema: type[BaseModel] = CreateDashboardToolArgs + show_tool_call_message: bool = False + + async def _arun_impl( + self, search_insights_queries: list[InsightQuery], dashboard_name: str + ) -> tuple[str, ToolMessagesArtifact | None]: + node = DashboardCreationNode(self._team, self._user) + chain: RunnableLambda[AssistantState, PartialAssistantState | None] = RunnableLambda(node) + copied_state = self._state.model_copy( + deep=True, + update={ + "root_tool_call_id": self.tool_call_id, + "search_insights_queries": search_insights_queries, + "dashboard_name": dashboard_name, + }, + ) + result = await chain.ainvoke(copied_state) + if not result or not result.messages: + return "Dashboard creation failed", None + return "", ToolMessagesArtifact(messages=result.messages) diff --git a/ee/hogai/graph/root/tools/full_text_search/test/test_toolkit.py b/ee/hogai/graph/root/tools/full_text_search/test/test_toolkit.py index 1112ade793..6139e99166 100644 --- a/ee/hogai/graph/root/tools/full_text_search/test/test_toolkit.py +++ b/ee/hogai/graph/root/tools/full_text_search/test/test_toolkit.py @@ -3,10 +3,13 @@ from unittest.mock import Mock, patch from django.conf import settings +from langchain_core.runnables import RunnableConfig from parameterized import parameterized -from ee.hogai.graph.root.tools.full_text_search.tool import ENTITY_MAP, EntitySearchToolkit, FTSKind +from ee.hogai.context import AssistantContextManager +from ee.hogai.graph.root.tools.full_text_search.tool import ENTITY_MAP, EntitySearchTool, FTSKind from ee.hogai.graph.shared_prompts import HYPERLINK_USAGE_INSTRUCTIONS +from ee.hogai.utils.types.base import AssistantState class TestEntitySearchToolkit(NonAtomicBaseTest): @@ -18,7 +21,13 @@ class TestEntitySearchToolkit(NonAtomicBaseTest): self.team.organization = Mock() self.team.organization.id = 789 self.user = Mock() - self.toolkit = EntitySearchToolkit(self.team, self.user) + self.toolkit = EntitySearchTool( + team=self.team, + user=self.user, + state=AssistantState(messages=[]), + config=RunnableConfig(configurable={}), + context_manager=AssistantContextManager(self.team, self.user, {}), + ) @parameterized.expand( [ diff --git a/ee/hogai/graph/root/tools/full_text_search/tool.py b/ee/hogai/graph/root/tools/full_text_search/tool.py index 8ecd54d9e5..e2d453a70c 100644 --- a/ee/hogai/graph/root/tools/full_text_search/tool.py +++ b/ee/hogai/graph/root/tools/full_text_search/tool.py @@ -6,13 +6,14 @@ import yaml from posthoganalytics import capture_exception from posthog.api.search import EntityConfig, search_entities -from posthog.models import Action, Cohort, Dashboard, Experiment, FeatureFlag, Insight, Survey, Team, User +from posthog.models import Action, Cohort, Dashboard, Experiment, FeatureFlag, Insight, Survey from posthog.rbac.user_access_control import UserAccessControl from posthog.sync import database_sync_to_async from products.error_tracking.backend.models import ErrorTrackingIssue from ee.hogai.graph.shared_prompts import HYPERLINK_USAGE_INSTRUCTIONS +from ee.hogai.tool import MaxSubtool from .prompts import ENTITY_TYPE_SUMMARY_TEMPLATE, FOUND_ENTITIES_MESSAGE_TEMPLATE @@ -91,14 +92,10 @@ SEARCH_KIND_TO_DATABASE_ENTITY_TYPE: dict[FTSKind, str] = { } -class EntitySearchToolkit: +class EntitySearchTool(MaxSubtool): MAX_ENTITY_RESULTS = 10 MAX_CONCURRENT_SEARCHES = 10 - def __init__(self, team: Team, user: User): - self._team = team - self._user = user - async def execute(self, query: str, search_kind: FTSKind) -> str: """Search for entities by query and entity.""" try: diff --git a/ee/hogai/graph/root/tools/legacy.py b/ee/hogai/graph/root/tools/legacy.py deleted file mode 100644 index e028434d10..0000000000 --- a/ee/hogai/graph/root/tools/legacy.py +++ /dev/null @@ -1,204 +0,0 @@ -# The module contains tools that are deprecated and will be replaced in the future with MaxTool implementations. -from pydantic import BaseModel, Field - -from ee.hogai.utils.types.base import InsightQuery - - -# Lower casing matters here. Do not change it. -class create_and_query_insight(BaseModel): - """ - Use this tool to spawn a subagent that will create a product analytics insight for a given description. - The tool generates a query and returns formatted text results for a specific data question or iterates on a previous query. It only retrieves a single query per call. If the user asks for multiple insights, you need to decompose a query into multiple subqueries and call the tool for each subquery. - - Follow these guidelines when retrieving data: - - If the same insight is already in the conversation history, reuse the retrieved data only when this does not violate the section (i.e. only when a presence-check, count, or sort on existing columns is enough). - - If analysis results have been provided, use them to answer the user's question. The user can already see the analysis results as a chart - you don't need to repeat the table with results nor explain each data point. - - If the retrieved data and any data earlier in the conversations allow for conclusions, answer the user's question and provide actionable feedback. - - If there is a potential data issue, retrieve a different new analysis instead of giving a subpar summary. Note: empty data is NOT a potential data issue. - - If the query cannot be answered with a UI-built insight type - trends, funnels, retention - choose the SQL type to answer the question (e.g. for listing events or aggregating in ways that aren't supported in trends/funnels/retention). - - IMPORTANT: Avoid generic advice. Take into account what you know about the product. Your answer needs to be super high-impact and no more than a few sentences. - Remember: do NOT retrieve data for the same query more than 3 times in a row. - - # Data schema - - You can pass events, actions, properties, and property values to this tool by specifying the "Data schema" section. - - - User: Calculate onboarding completion rate for the last week. - Assistant: I'm going to retrieve the existing data schema first. - *Retrieves matching events, properties, and property values* - Assistant: I'm going to create a new trends insight. - *Calls this tool with the query description: "Trends insight of the onboarding completion rate. Data schema: Relevant matching data schema"* - - - # Supported insight types - ## Trends - A trends insight visualizes events over time using time series. They're useful for finding patterns in historical data. - - The trends insights have the following features: - - The insight can show multiple trends in one request. - - Custom formulas can calculate derived metrics, like `A/B*100` to calculate a ratio. - - Filter and break down data using multiple properties. - - Compare with the previous period and sample data. - - Apply various aggregation types, like sum, average, etc., and chart types. - - And more. - - Examples of use cases include: - - How the product's most important metrics change over time. - - Long-term patterns, or cycles in product's usage. - - The usage of different features side-by-side. - - How the properties of events vary using aggregation (sum, average, etc). - - Users can also visualize the same data points in a variety of ways. - - ## Funnel - A funnel insight visualizes a sequence of events that users go through in a product. They use percentages as the primary aggregation type. Funnels use two or more series, so the conversation history should mention at least two events. - - The funnel insights have the following features: - - Various visualization types (steps, time-to-convert, historical trends). - - Filter data and apply exclusion steps. - - Break down data using a single property. - - Specify conversion windows, details of conversion calculation, attribution settings. - - Sample data. - - And more. - - Examples of use cases include: - - Conversion rates. - - Drop off steps. - - Steps with the highest friction and time to convert. - - If product changes are improving their funnel over time. - - Average/median time to convert. - - Conversion trends over time. - - ## Retention - A retention insight visualizes how many users return to the product after performing some action. They're useful for understanding user engagement and retention. - - The retention insights have the following features: filter data, sample data, and more. - - Examples of use cases include: - - How many users come back and perform an action after their first visit. - - How many users come back to perform action X after performing action Y. - - How often users return to use a specific feature. - - ## SQL - The 'sql' insight type allows you to write arbitrary SQL queries to retrieve data. - - The SQL insights have the following features: - - Filter data using arbitrary SQL. - - All ClickHouse SQL features. - - You can nest subqueries as needed. - """ - - query_description: str = Field( - description=( - "A description of the query to generate, encapsulating the details of the user's request. " - "Include all relevant context from earlier messages too, as the tool won't see that conversation history. " - "If an existing insight has been used as a starting point, include that insight's filters and query in the description. " - "Don't be overly prescriptive with event or property names, unless the user indicated they mean this specific name (e.g. with quotes). " - "If the users seems to ask for a list of entities, rather than a count, state this explicitly." - ) - ) - - -class session_summarization(BaseModel): - """ - Use this tool to summarize session recordings by analysing the events within those sessions to find patterns and issues. - It will return a textual summary of the captured session recordings. - - # When to use the tool: - When the user asks to summarize session recordings: - - "summarize" synonyms: "watch", "analyze", "review", and similar - - "session recordings" synonyms: "sessions", "recordings", "replays", "user sessions", and similar - - # When NOT to use the tool: - - When the user asks to find, search for, or look up session recordings, but doesn't ask to summarize them - - When users asks to update, change, or adjust session recordings filters - - # Synonyms - - "summarize": "watch", "analyze", "review", and similar - - "session recordings": "sessions", "recordings", "replays", "user sessions", and similar - - # Managing context - If the conversation history contains context about the current filters or session recordings, follow these steps: - - Convert the user query into a `session_summarization_query` - - The query should be used to understand the user's intent - - Decide if the query is relevant to the current filters and set `should_use_current_filters` accordingly - - Generate the `summary_title` based on the user's query and the current filters - - Otherwise: - - Convert the user query into a `session_summarization_query` - - The query should be used to search for relevant sessions and then summarize them - - Assume the `should_use_current_filters` should be always `false` - - Generate the `summary_title` based on the user's query - - # Additional guidelines - - CRITICAL: Always pass the user's complete, unmodified query to the `session_summarization_query` parameter - - DO NOT truncate, summarize, or extract keywords from the user's query - - The query is used to find relevant sessions - context helps find better matches - - Use explicit tool definition to make a decision - """ - - session_summarization_query: str = Field( - description=""" - - The user's complete query for session recordings summarization. - - This will be used to find relevant session recordings. - - Always pass the user's complete, unmodified query. - - Examples: - * 'summarize all session recordings from yesterday' - * 'analyze mobile user session recordings from last week, even if 1 second' - * 'watch last 300 session recordings of MacOS users from US' - * and similar - """ - ) - should_use_current_filters: bool = Field( - description=""" - - Whether to use current filters from user's UI to find relevant session recordings. - - IMPORTANT: Should be always `false` if the current filters or `search_session_recordings` tool are not present in the conversation history. - - Examples: - * Set to `true` if one of the conditions is met: - - the user wants to summarize "current/selected/opened/my/all/these" session recordings - - the user wants to use "current/these" filters - - the user's query specifies filters identical to the current filters - - if the user's query doesn't specify any filters/conditions - - the user refers to what they're "looking at" or "viewing" - * Set to `false` if one of the conditions is met: - - no current filters or `search_session_recordings` tool are present in the conversation - - the user specifies date/time period different from the current filters - - the user specifies conditions (user, device, id, URL, etc.) not present in the current filters - """, - ) - summary_title: str = Field( - description=""" - - The name of the summary that is expected to be generated from the user's `session_summarization_query` and/or `current_filters` (if present). - - The name should cover in 3-7 words what sessions would be to be summarized in the summary - - This won't be used for any search of filtering, only to properly label the generated summary. - - Examples: - * If `should_use_current_filters` is `false`, then the `summary_title` should be generated based on the `session_summarization_query`: - - query: "I want to watch all the sessions of user `user@example.com` in the last 30 days no matter how long" -> name: "Sessions of the user user@example.com (last 30 days)" - - query: "summarize my last 100 session recordings" -> name: "Last 100 sessions" - - and similar - * If `should_use_current_filters` is `true`, then the `summary_title` should be generated based on the current filters in the context (if present): - - filters: "{"key":"$os","value":["Mac OS X"],"operator":"exact","type":"event"}" -> name: "MacOS users" - - filters: "{"date_from": "-7d", "filter_test_accounts": True}" -> name: "All sessions (last 7 days)" - - and similar - * If there's not enough context to generated the summary name - keep it an empty string ("") - """ - ) - - -class create_dashboard(BaseModel): - """ - Use this tool when users ask to create, build, or make a new dashboard with insights. - This tool will search for existing insights that match the user's requirements so no need to call `search_insights` tool, or create new insights if none are found, then combine them into a dashboard. - Do not call this tool if the user only asks to find, search for, or look up existing insights and does not ask to create a dashboard. - If you decided to use this tool, there is no need to call `search_insights` tool beforehand. The tool will search for existing insights that match the user's requirements and create new insights if none are found. - """ - - search_insights_queries: list[InsightQuery] = Field( - description="A list of insights to be included in the dashboard. Include all the insights that the user mentioned." - ) - dashboard_name: str = Field( - description=( - "The name of the dashboard to be created based on the user request. It should be short and concise as it will be displayed as a header in the dashboard tile." - ) - ) diff --git a/ee/hogai/graph/root/tools/navigate.py b/ee/hogai/graph/root/tools/navigate.py index 84a741c4e2..50607d3a37 100644 --- a/ee/hogai/graph/root/tools/navigate.py +++ b/ee/hogai/graph/root/tools/navigate.py @@ -10,7 +10,7 @@ from posthog.models import Team, User from ee.hogai.context.context import AssistantContextManager from ee.hogai.tool import MaxTool from ee.hogai.utils.prompt import format_prompt_string -from ee.hogai.utils.types.base import AssistantState +from ee.hogai.utils.types.base import AssistantState, NodePath NAVIGATION_TOOL_PROMPT = """ Use the `navigate` tool to move between different pages in the PostHog application. @@ -57,7 +57,7 @@ class NavigateTool(MaxTool): *, team: Team, user: User, - tool_call_id: str, + node_path: tuple[NodePath, ...] | None = None, state: AssistantState | None = None, config: RunnableConfig | None = None, context_manager: AssistantContextManager | None = None, @@ -69,7 +69,7 @@ class NavigateTool(MaxTool): return cls( team=team, user=user, - tool_call_id=tool_call_id, + node_path=node_path, state=state, config=config, context_manager=context_manager, diff --git a/ee/hogai/graph/root/tools/read_billing_tool/__init__.py b/ee/hogai/graph/root/tools/read_billing_tool/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ee/hogai/graph/billing/prompts.py b/ee/hogai/graph/root/tools/read_billing_tool/prompts.py similarity index 100% rename from ee/hogai/graph/billing/prompts.py rename to ee/hogai/graph/root/tools/read_billing_tool/prompts.py diff --git a/ee/hogai/graph/root/tools/read_billing_tool/test/__init__.py b/ee/hogai/graph/root/tools/read_billing_tool/test/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ee/hogai/graph/billing/test/test_nodes.py b/ee/hogai/graph/root/tools/read_billing_tool/test/test_nodes.py similarity index 89% rename from ee/hogai/graph/billing/test/test_nodes.py rename to ee/hogai/graph/root/tools/read_billing_tool/test/test_nodes.py index 81e87f16d6..d07ad48ebf 100644 --- a/ee/hogai/graph/billing/test/test_nodes.py +++ b/ee/hogai/graph/root/tools/read_billing_tool/test/test_nodes.py @@ -2,11 +2,12 @@ import datetime from typing import cast from uuid import uuid4 -from posthog.test.base import BaseTest, ClickhouseTestMixin +from posthog.test.base import ClickhouseTestMixin, NonAtomicBaseTest from unittest.mock import patch +from langchain_core.runnables import RunnableConfig + from posthog.schema import ( - AssistantToolCallMessage, BillingSpendResponseBreakdownType, BillingUsageResponseBreakdownType, MaxAddonInfo, @@ -21,26 +22,30 @@ from posthog.schema import ( UsageHistoryItem, ) -from ee.hogai.graph.billing.nodes import BillingNode +from ee.hogai.context.context import AssistantContextManager +from ee.hogai.graph.root.tools.read_billing_tool.tool import ReadBillingTool from ee.hogai.utils.types import AssistantState -class TestBillingNode(ClickhouseTestMixin, BaseTest): +class TestBillingNode(ClickhouseTestMixin, NonAtomicBaseTest): + CLASS_DATA_LEVEL_SETUP = False + def setUp(self): super().setUp() - self.node = BillingNode(self.team, self.user) - self.tool_call_id = str(uuid4()) - self.state = AssistantState(messages=[], root_tool_call_id=self.tool_call_id) + self.tool = ReadBillingTool( + team=self.team, + user=self.user, + state=AssistantState(messages=[], root_tool_call_id=str(uuid4())), + config=RunnableConfig(configurable={}), + context_manager=AssistantContextManager(self.team, self.user, {}), + ) - def test_run_with_no_billing_context(self): - with patch.object(self.node.context_manager, "get_billing_context", return_value=None): - result = self.node.run(self.state, {}) - self.assertEqual(len(result.messages), 1) - message = result.messages[0] - self.assertIsInstance(message, AssistantToolCallMessage) - self.assertEqual(cast(AssistantToolCallMessage, message).content, "No billing information available") + async def test_run_with_no_billing_context(self): + with patch.object(self.tool._context_manager, "get_billing_context", return_value=None): + result = await self.tool.execute() + self.assertEqual(result, "No billing information available") - def test_run_with_billing_context(self): + async def test_run_with_billing_context(self): billing_context = MaxBillingContext( subscription_level=MaxBillingContextSubscriptionLevel.PAID, billing_plan="paid", @@ -50,17 +55,13 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): products=[], ) with ( - patch.object(self.node.context_manager, "get_billing_context", return_value=billing_context), - patch.object(self.node, "_format_billing_context", return_value="Formatted Context"), + patch.object(self.tool._context_manager, "get_billing_context", return_value=billing_context), + patch.object(self.tool, "_format_billing_context", return_value="Formatted Context"), ): - result = self.node.run(self.state, {}) - self.assertEqual(len(result.messages), 1) - message = result.messages[0] - self.assertIsInstance(message, AssistantToolCallMessage) - self.assertEqual(cast(AssistantToolCallMessage, message).content, "Formatted Context") - self.assertEqual(cast(AssistantToolCallMessage, message).tool_call_id, self.tool_call_id) + result = await self.tool.execute() + self.assertEqual(result, "Formatted Context") - def test_format_billing_context(self): + async def test_format_billing_context(self): billing_context = MaxBillingContext( subscription_level=MaxBillingContextSubscriptionLevel.PAID, billing_plan="paid", @@ -89,8 +90,8 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): settings=MaxBillingContextSettings(autocapture_on=True, active_destinations=2), ) - with patch.object(self.node, "_get_top_events_by_usage", return_value=[]): - formatted_string = self.node._format_billing_context(billing_context) + with patch.object(self.tool, "_get_top_events_by_usage", return_value=[]): + formatted_string = await self.tool._format_billing_context(billing_context) self.assertIn("(paid)", formatted_string) self.assertIn("Period: 2023-01-01 to 2023-01-31", formatted_string) @@ -123,19 +124,21 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ), ] - usage_table = self.node._format_history_table(usage_history) + usage_table = self.tool._format_history_table(usage_history) self.assertIn("### Overall (all projects)", usage_table) self.assertIn("| Data Type | 2023-01-01 | 2023-01-02 |", usage_table) self.assertIn("| Recordings | 100.00 | 200.00 |", usage_table) self.assertIn("| Events | 1.50 | 2.50 |", usage_table) - spend_table = self.node._format_history_table(spend_history) + spend_table = self.tool._format_history_table(spend_history) self.assertIn("| Mobile Recordings | 10.50 | 20.00 |", spend_table) def test_get_top_events_by_usage(self): mock_results = [("pageview", 1000), ("$autocapture", 500)] - with patch("ee.hogai.graph.billing.nodes.sync_execute", return_value=mock_results) as mock_sync_execute: - top_events = self.node._get_top_events_by_usage() + with patch( + "ee.hogai.graph.root.tools.read_billing_tool.tool.sync_execute", return_value=mock_results + ) as mock_sync_execute: + top_events = self.tool._get_top_events_by_usage() self.assertEqual(len(top_events), 2) self.assertEqual(top_events[0]["event"], "pageview") self.assertEqual(top_events[0]["count"], 1000) @@ -150,13 +153,14 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): def test_get_top_events_by_usage_query_fails(self): with patch( - "ee.hogai.graph.billing.nodes.sync_execute", side_effect=Exception("DB connection failed") + "ee.hogai.graph.root.tools.read_billing_tool.tool.sync_execute", + side_effect=Exception("DB connection failed"), ) as mock_sync_execute: - top_events = self.node._get_top_events_by_usage() + top_events = self.tool._get_top_events_by_usage() self.assertEqual(top_events, []) mock_sync_execute.assert_called_once() - def test_format_billing_context_with_addons(self): + async def test_format_billing_context_with_addons(self): """Test that addons are properly nested within products in the formatted output""" billing_context = MaxBillingContext( subscription_level=MaxBillingContextSubscriptionLevel.PAID, @@ -230,14 +234,14 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ) with patch.object( - self.node, + self.tool, "_get_top_events_by_usage", return_value=[ {"event": "$pageview", "count": 50000, "formatted_count": "50,000"}, {"event": "$autocapture", "count": 30000, "formatted_count": "30,000"}, ], ): - formatted_string = self.node._format_billing_context(billing_context) + formatted_string = await self.tool._format_billing_context(billing_context) # Check basic info self.assertIn("paid subscription (startup)", formatted_string) @@ -274,7 +278,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): self.assertIn("$pageview", formatted_string) self.assertIn("50,000 events", formatted_string) - def test_format_billing_context_no_subscription(self): + async def test_format_billing_context_no_subscription(self): """Test formatting when user has no active subscription (free plan)""" billing_context = MaxBillingContext( subscription_level=MaxBillingContextSubscriptionLevel.FREE, @@ -286,8 +290,8 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): trial=MaxBillingContextTrial(is_active=True, expires_at="2023-02-01", target="teams"), ) - with patch.object(self.node, "_get_top_events_by_usage", return_value=[]): - formatted_string = self.node._format_billing_context(billing_context) + with patch.object(self.tool, "_get_top_events_by_usage", return_value=[]): + formatted_string = await self.tool._format_billing_context(billing_context) self.assertIn("free subscription", formatted_string) self.assertIn("Active subscription: No (Free plan)", formatted_string) @@ -297,7 +301,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): def test_format_history_table_with_team_breakdown(self): """Test that history tables properly group by team when breakdown includes team IDs""" # Mock the teams map - self.node._teams_map = { + self.tool._teams_map = { 1: "Team Alpha (ID: 1)", 2: "Team Beta (ID: 2)", } @@ -337,7 +341,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ), ] - table = self.node._format_history_table(usage_history) + table = self.tool._format_history_table(usage_history) # Check team-specific tables self.assertIn("### Team Alpha (ID: 1)", table) @@ -349,7 +353,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): self.assertIn("| Recordings | 100.00 | 200.00 |", table) self.assertIn("| Feature Flag Requests | 50.00 | 100.00 |", table) - def test_format_billing_context_edge_cases(self): + async def test_format_billing_context_edge_cases(self): """Test edge cases and potential security issues""" billing_context = MaxBillingContext( subscription_level=MaxBillingContextSubscriptionLevel.CUSTOM, @@ -374,8 +378,8 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): settings=MaxBillingContextSettings(autocapture_on=True, active_destinations=0), ) - with patch.object(self.node, "_get_top_events_by_usage", return_value=[]): - formatted_string = self.node._format_billing_context(billing_context) + with patch.object(self.tool, "_get_top_events_by_usage", return_value=[]): + formatted_string = await self.tool._format_billing_context(billing_context) # Check deactivated status self.assertIn("Status: Account is deactivated", formatted_string) @@ -393,7 +397,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): # Check exceeded limit warning self.assertIn("⚠️ Usage limit exceeded", formatted_string) - def test_format_billing_context_complete_template_coverage(self): + async def test_format_billing_context_complete_template_coverage(self): """Test all possible template variables are covered""" billing_context = MaxBillingContext( subscription_level=MaxBillingContextSubscriptionLevel.PAID, @@ -472,14 +476,14 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ) # Mock teams map for history table - self.node._teams_map = {1: "Main Team (ID: 1)"} + self.tool._teams_map = {1: "Main Team (ID: 1)"} with patch.object( - self.node, + self.tool, "_get_top_events_by_usage", return_value=[{"event": "$identify", "count": 10000, "formatted_count": "10,000"}], ): - formatted_string = self.node._format_billing_context(billing_context) + formatted_string = await self.tool._format_billing_context(billing_context) # Verify all template sections are present self.assertIn("", formatted_string) @@ -545,12 +549,12 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ), ] - self.node._teams_map = { + self.tool._teams_map = { 84444: "Project 84444", 12345: "Project 12345", } - table = self.node._format_history_table(usage_history) + table = self.tool._format_history_table(usage_history) # Should always include aggregated table first self.assertIn("### Overall (all projects)", table) @@ -597,7 +601,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ), ] - table = self.node._format_history_table(usage_history) + table = self.tool._format_history_table(usage_history) # Should include aggregated table self.assertIn("### Overall (all projects)", table) @@ -645,7 +649,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ) ] - aggregated = self.node._create_aggregated_items(team_items, other_items) + aggregated = self.tool._create_aggregated_items(team_items, other_items) # Should have 2 aggregated items: events and feature flags self.assertEqual(len(aggregated), 2) @@ -687,7 +691,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ), ] - table = self.node._format_history_table(usage_history) + table = self.tool._format_history_table(usage_history) # Should only have aggregated table, no team-specific tables self.assertIn("### Overall (all projects)", table) @@ -721,18 +725,18 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ) ] - self.node._teams_map = { + self.tool._teams_map = { 123: "Project 123", } # Test usage history formatting - usage_table = self.node._format_history_table(usage_history) + usage_table = self.tool._format_history_table(usage_history) self.assertIn("### Overall (all projects)", usage_table) self.assertIn("### Project 123", usage_table) self.assertIn("| Events | 1,000.00 |", usage_table) # Test spend history formatting - spend_table = self.node._format_history_table(spend_history) + spend_table = self.tool._format_history_table(spend_history) self.assertIn("### Overall (all projects)", spend_table) self.assertIn("### Project 123", spend_table) self.assertIn("| Events | 50.00 |", spend_table) @@ -758,7 +762,7 @@ class TestBillingNode(ClickhouseTestMixin, BaseTest): ), ] - table = self.node._format_history_table(usage_history) + table = self.tool._format_history_table(usage_history) # Should handle empty dates gracefully and still show valid data self.assertIn("### Overall (all projects)", table) diff --git a/ee/hogai/graph/billing/nodes.py b/ee/hogai/graph/root/tools/read_billing_tool/tool.py similarity index 91% rename from ee/hogai/graph/billing/nodes.py rename to ee/hogai/graph/root/tools/read_billing_tool/tool.py index 985337862b..6d002e380c 100644 --- a/ee/hogai/graph/billing/nodes.py +++ b/ee/hogai/graph/root/tools/read_billing_tool/tool.py @@ -1,18 +1,19 @@ -from typing import Any, cast -from uuid import uuid4 +from typing import Any from langchain_core.prompts import PromptTemplate from langchain_core.runnables import RunnableConfig -from posthog.schema import AssistantToolCallMessage, MaxBillingContext, SpendHistoryItem, UsageHistoryItem +from posthog.schema import MaxBillingContext, SpendHistoryItem, UsageHistoryItem from posthog.clickhouse.client import sync_execute +from posthog.models import Team, User +from posthog.sync import database_sync_to_async -from ee.hogai.graph.base import AssistantNode -from ee.hogai.graph.billing.prompts import BILLING_CONTEXT_PROMPT +from ee.hogai.context.context import AssistantContextManager +from ee.hogai.tool import MaxSubtool from ee.hogai.utils.types import AssistantState -from ee.hogai.utils.types.base import AssistantNodeName, PartialAssistantState -from ee.hogai.utils.types.composed import MaxNodeName + +from .prompts import BILLING_CONTEXT_PROMPT # sync with frontend/src/scenes/billing/constants.ts USAGE_TYPES = [ @@ -33,33 +34,27 @@ USAGE_TYPES = [ ] -class BillingNode(AssistantNode): - _teams_map: dict[int, str] = {} +class ReadBillingTool(MaxSubtool): + def __init__( + self, + *, + team: Team, + user: User, + state: AssistantState, + config: RunnableConfig, + context_manager: AssistantContextManager, + ): + super().__init__(team=team, user=user, state=state, config=config, context_manager=context_manager) + self._teams_map: dict[int, str] = {} - @property - def node_name(self) -> MaxNodeName: - return AssistantNodeName.BILLING - - def run(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: - tool_call_id = cast(str, state.root_tool_call_id) - billing_context = self.context_manager.get_billing_context() + async def execute(self) -> str: + billing_context = self._context_manager.get_billing_context() if not billing_context: - return PartialAssistantState( - messages=[ - AssistantToolCallMessage( - content="No billing information available", id=str(uuid4()), tool_call_id=tool_call_id - ) - ], - root_tool_call_id=None, - ) - formatted_billing_context = self._format_billing_context(billing_context) - return PartialAssistantState( - messages=[ - AssistantToolCallMessage(content=formatted_billing_context, tool_call_id=tool_call_id, id=str(uuid4())), - ], - root_tool_call_id=None, - ) + return "No billing information available" + formatted_billing_context = await self._format_billing_context(billing_context) + return formatted_billing_context + @database_sync_to_async(thread_sensitive=False) def _format_billing_context(self, billing_context: MaxBillingContext) -> str: """Format billing context into a readable prompt section.""" # Convert billing context to a format suitable for the mustache template diff --git a/ee/hogai/graph/root/tools/read_data.py b/ee/hogai/graph/root/tools/read_data.py index 712d8c22d0..577743f5c3 100644 --- a/ee/hogai/graph/root/tools/read_data.py +++ b/ee/hogai/graph/root/tools/read_data.py @@ -1,4 +1,4 @@ -from typing import Any, Literal, Self +from typing import Literal, Self from langchain_core.runnables import RunnableConfig from pydantic import BaseModel @@ -9,12 +9,14 @@ from ee.hogai.context.context import AssistantContextManager from ee.hogai.graph.sql.mixins import HogQLDatabaseMixin from ee.hogai.tool import MaxTool from ee.hogai.utils.prompt import format_prompt_string -from ee.hogai.utils.types.base import AssistantState +from ee.hogai.utils.types.base import AssistantState, NodePath + +from .read_billing_tool.tool import ReadBillingTool READ_DATA_BILLING_PROMPT = """ # Billing information -Use this tool with the "billing_info" kind to retrieve the billing information if the user asks about billing, their subscription, their usage, or their spending. +Use this tool with the "billing_info" kind to retrieve the billing information if the user asks about their billing, subscription, product usage, spending, or cost reduction strategies. You can use the information retrieved to check which PostHog products and add-ons the user has activated, how much they are spending, their usage history across all products in the last 30 days, as well as trials, spending limits, billing period, and more. If the user wants to reduce their spending, always call this tool to get suggestions on how to do so. If an insight shows zero data, it could mean either the query is looking at the wrong data or there was a temporary data collection issue. You can investigate potential dips in usage/captured data using the billing tool. @@ -62,7 +64,7 @@ class ReadDataTool(HogQLDatabaseMixin, MaxTool): *, team: Team, user: User, - tool_call_id: str, + node_path: tuple[NodePath, ...] | None = None, state: AssistantState | None = None, config: RunnableConfig | None = None, context_manager: AssistantContextManager | None = None, @@ -83,21 +85,29 @@ class ReadDataTool(HogQLDatabaseMixin, MaxTool): return cls( team=team, user=user, - tool_call_id=tool_call_id, state=state, + node_path=node_path, config=config, args_schema=args, description=description, context_manager=context_manager, ) - async def _arun_impl(self, kind: ReadDataAdminAccessKind | ReadDataKind) -> tuple[str, dict[str, Any] | None]: + async def _arun_impl(self, kind: ReadDataAdminAccessKind | ReadDataKind) -> tuple[str, None]: match kind: case "billing_info": has_access = await self._context_manager.check_user_has_billing_access() if not has_access: return BILLING_INSUFFICIENT_ACCESS_PROMPT, None # used for routing - return "", self.args_schema(kind=kind).model_dump() + billing_tool = ReadBillingTool( + team=self._team, + user=self._user, + state=self._state, + config=self._config, + context_manager=self._context_manager, + ) + result = await billing_tool.execute() + return result, None case "datawarehouse_schema": return await self._serialize_database_schema(), None diff --git a/ee/hogai/graph/root/tools/read_taxonomy.py b/ee/hogai/graph/root/tools/read_taxonomy.py index 0fffab82e0..d088d7b5ca 100644 --- a/ee/hogai/graph/root/tools/read_taxonomy.py +++ b/ee/hogai/graph/root/tools/read_taxonomy.py @@ -9,7 +9,7 @@ from ee.hogai.context.context import AssistantContextManager from ee.hogai.graph.query_planner.toolkit import TaxonomyAgentToolkit from ee.hogai.tool import MaxTool from ee.hogai.utils.helpers import format_events_yaml -from ee.hogai.utils.types.base import AssistantState +from ee.hogai.utils.types.base import AssistantState, NodePath READ_TAXONOMY_TOOL_DESCRIPTION = """ Use this tool to explore the user's taxonomy (i.e. data schema). @@ -155,7 +155,7 @@ class ReadTaxonomyTool(MaxTool): *, team: Team, user: User, - tool_call_id: str, + node_path: tuple[NodePath, ...] | None = None, state: AssistantState | None = None, config: RunnableConfig | None = None, context_manager: AssistantContextManager | None = None, @@ -200,9 +200,9 @@ class ReadTaxonomyTool(MaxTool): return cls( team=team, user=user, - tool_call_id=tool_call_id, state=state, config=config, + node_path=node_path, args_schema=ReadTaxonomyToolArgsWithGroups, context_manager=context_manager, ) diff --git a/ee/hogai/graph/root/tools/search.py b/ee/hogai/graph/root/tools/search.py index 11c32dfb99..7f7910a282 100644 --- a/ee/hogai/graph/root/tools/search.py +++ b/ee/hogai/graph/root/tools/search.py @@ -1,17 +1,19 @@ -from typing import Any, Literal +from typing import Literal from django.conf import settings import posthoganalytics from langchain_core.output_parsers import SimpleJsonOutputParser from langchain_core.prompts import ChatPromptTemplate +from langchain_core.runnables import RunnableLambda from langchain_openai import ChatOpenAI from pydantic import BaseModel, Field -from posthog.models import Team, User - -from ee.hogai.graph.root.tools.full_text_search.tool import EntitySearchToolkit, FTSKind -from ee.hogai.tool import MaxTool +from ee.hogai.graph.insights.nodes import InsightSearchNode, NoInsightsException +from ee.hogai.graph.root.tools.full_text_search.tool import EntitySearchTool, FTSKind +from ee.hogai.tool import MaxSubtool, MaxTool, ToolMessagesArtifact +from ee.hogai.utils.prompt import format_prompt_string +from ee.hogai.utils.types.base import AssistantState, PartialAssistantState SEARCH_TOOL_PROMPT = """ Use this tool to search docs, insights, dashboards, cohorts, actions, experiments, feature flags, notebooks, error tracking issues, and surveys in PostHog. @@ -57,35 +59,10 @@ If you want to search for all entities, you should use `all`. """.strip() -DOCS_SEARCH_RESULTS_TEMPLATE = """Found {count} relevant documentation page(s): - -{docs} - -Use retrieved documentation to answer the user's question if it is relevant to the user's query. -Format the response using Markdown and reference the documentation using hyperlinks. -Every link to docs clearly explicitly be labeled, for example as "(see docs)". - +INVALID_ENTITY_KIND_PROMPT = """ +Invalid entity kind: {{{kind}}}. Please provide a valid entity kind for the tool. """.strip() -DOCS_SEARCH_NO_RESULTS_TEMPLATE = """ -No documentation found. - - -Do not answer the user's question if you did not find any documentation. Try rewriting the query. -If after a couple of attempts you still do not find any documentation, suggest the user navigate to the documentation page, which is available at `https://posthog.com/docs`. - -""".strip() - -DOC_ITEM_TEMPLATE = """ -# {title} -URL: {url} - -{text} -""".strip() - - -FTS_SEARCH_FEATURE_FLAG = "hogai-insights-fts-search" - ENTITIES = [f"{entity}" for entity in FTSKind if entity != FTSKind.INSIGHTS] SearchKind = Literal["insights", "docs", *ENTITIES] # type: ignore @@ -126,50 +103,106 @@ class SearchTool(MaxTool): context_prompt_template: str = "Searches documentation, insights, dashboards, cohorts, actions, experiments, feature flags, notebooks, error tracking issues, and surveys in PostHog" args_schema: type[BaseModel] = SearchToolArgs - @staticmethod - def _get_fts_entities(include_insight_fts: bool) -> list[str]: - if not include_insight_fts: - entities = [e for e in FTSKind if e != FTSKind.INSIGHTS] - else: - entities = list(FTSKind) - return [*entities, FTSKind.ALL] - - async def _arun_impl(self, kind: SearchKind, query: str) -> tuple[str, dict[str, Any] | None]: + async def _arun_impl(self, kind: str, query: str) -> tuple[str, ToolMessagesArtifact | None]: if kind == "docs": if not settings.INKEEP_API_KEY: return "This tool is not available in this environment.", None - if self._has_docs_search_feature_flag(): - return await self._search_docs(query), None + docs_tool = InkeepDocsSearchTool( + team=self._team, + user=self._user, + state=self._state, + config=self._config, + context_manager=self._context_manager, + ) + return await docs_tool.execute(query, self.tool_call_id) - fts_entities = SearchTool._get_fts_entities(SearchTool._has_fts_search_feature_flag(self._user, self._team)) + if kind == "insights" and not self._has_insights_fts_search_feature_flag(): + insights_tool = InsightSearchTool( + team=self._team, + user=self._user, + state=self._state, + config=self._config, + context_manager=self._context_manager, + ) + return await insights_tool.execute(query, self.tool_call_id) - if kind in fts_entities: - entity_search_toolkit = EntitySearchToolkit(self._team, self._user) - response = await entity_search_toolkit.execute(query, FTSKind(kind)) - return response, None - # Used for routing - return "Search tool executed", SearchToolArgs(kind=kind, query=query).model_dump() + if kind not in self._fts_entities: + return format_prompt_string(INVALID_ENTITY_KIND_PROMPT, kind=kind), None - def _has_docs_search_feature_flag(self) -> bool: + entity_search_toolkit = EntitySearchTool( + team=self._team, + user=self._user, + state=self._state, + config=self._config, + context_manager=self._context_manager, + ) + response = await entity_search_toolkit.execute(query, FTSKind(kind)) + return response, None + + @property + def _fts_entities(self) -> list[str]: + entities = list(FTSKind) + return [*entities, FTSKind.ALL] + + def _has_insights_fts_search_feature_flag(self) -> bool: return posthoganalytics.feature_enabled( - "max-inkeep-rag-docs-search", + "hogai-insights-fts-search", str(self._user.distinct_id), groups={"organization": str(self._team.organization_id)}, group_properties={"organization": {"id": str(self._team.organization_id)}}, send_feature_flag_events=False, ) - @staticmethod - def _has_fts_search_feature_flag(user: User, team: Team) -> bool: - return posthoganalytics.feature_enabled( - FTS_SEARCH_FEATURE_FLAG, - str(user.distinct_id), - groups={"organization": str(team.organization_id)}, - group_properties={"organization": {"id": str(team.organization_id)}}, - send_feature_flag_events=False, - ) - async def _search_docs(self, query: str) -> str: +DOCS_SEARCH_RESULTS_TEMPLATE = """Found {count} relevant documentation page(s): + +{docs} + +Use retrieved documentation to answer the user's question if it is relevant to the user's query. +Format the response using Markdown and reference the documentation using hyperlinks. +Every link to docs clearly explicitly be labeled, for example as "(see docs)". + +""".strip() + +DOCS_SEARCH_NO_RESULTS_TEMPLATE = """ +No documentation found. + + +Do not answer the user's question if you did not find any documentation. Try rewriting the query. +If after a couple of attempts you still do not find any documentation, suggest the user navigate to the documentation page, which is available at `https://posthog.com/docs`. + +""".strip() + +DOC_ITEM_TEMPLATE = """ +# {title} +URL: {url} + +{text} +""".strip() + + +class InkeepDocsSearchTool(MaxSubtool): + async def execute(self, query: str, tool_call_id: str) -> tuple[str, ToolMessagesArtifact | None]: + if self._has_rag_docs_search_feature_flag(): + return await self._search_using_rag_endpoint(query, tool_call_id) + else: + return await self._search_using_node(query, tool_call_id) + + async def _search_using_node(self, query: str, tool_call_id: str) -> tuple[str, ToolMessagesArtifact | None]: + # Avoid circular import + from ee.hogai.graph.inkeep_docs.nodes import InkeepDocsNode + + # Init the graph + node = InkeepDocsNode(self._team, self._user) + chain: RunnableLambda[AssistantState, PartialAssistantState | None] = RunnableLambda(node) + copied_state = self._state.model_copy(deep=True, update={"root_tool_call_id": tool_call_id}) + result = await chain.ainvoke(copied_state) + assert result is not None + return "", ToolMessagesArtifact(messages=result.messages) + + async def _search_using_rag_endpoint( + self, query: str, tool_call_id: str + ) -> tuple[str, ToolMessagesArtifact | None]: model = ChatOpenAI( model="inkeep-rag", base_url="https://api.inkeep.com/v1/", @@ -184,7 +217,7 @@ class SearchTool(MaxTool): rag_context_raw = await chain.ainvoke({"query": query}) if not rag_context_raw or not rag_context_raw.get("content"): - return DOCS_SEARCH_NO_RESULTS_TEMPLATE + return DOCS_SEARCH_NO_RESULTS_TEMPLATE, None rag_context = InkeepResponse.model_validate(rag_context_raw) @@ -197,7 +230,35 @@ class SearchTool(MaxTool): docs.append(DOC_ITEM_TEMPLATE.format(title=doc.title, url=doc.url, text=text)) if not docs: - return DOCS_SEARCH_NO_RESULTS_TEMPLATE + return DOCS_SEARCH_NO_RESULTS_TEMPLATE, None formatted_docs = "\n\n---\n\n".join(docs) - return DOCS_SEARCH_RESULTS_TEMPLATE.format(count=len(docs), docs=formatted_docs) + return DOCS_SEARCH_RESULTS_TEMPLATE.format(count=len(docs), docs=formatted_docs), None + + def _has_rag_docs_search_feature_flag(self) -> bool: + return posthoganalytics.feature_enabled( + "max-inkeep-rag-docs-search", + str(self._user.distinct_id), + groups={"organization": str(self._team.organization_id)}, + group_properties={"organization": {"id": str(self._team.organization_id)}}, + send_feature_flag_events=False, + ) + + +EMPTY_DATABASE_ERROR_MESSAGE = """ +The user doesn't have any insights created yet. +""".strip() + + +class InsightSearchTool(MaxSubtool): + async def execute(self, query: str, tool_call_id: str) -> tuple[str, ToolMessagesArtifact | None]: + try: + node = InsightSearchNode(self._team, self._user) + copied_state = self._state.model_copy( + deep=True, update={"search_insights_query": query, "root_tool_call_id": tool_call_id} + ) + chain: RunnableLambda[AssistantState, PartialAssistantState | None] = RunnableLambda(node) + result = await chain.ainvoke(copied_state) + return "", ToolMessagesArtifact(messages=result.messages) if result else None + except NoInsightsException: + return EMPTY_DATABASE_ERROR_MESSAGE, None diff --git a/ee/hogai/graph/root/tools/session_summarization.py b/ee/hogai/graph/root/tools/session_summarization.py new file mode 100644 index 0000000000..594358ec6b --- /dev/null +++ b/ee/hogai/graph/root/tools/session_summarization.py @@ -0,0 +1,122 @@ +from typing import Literal + +from langchain_core.runnables import RunnableLambda +from pydantic import BaseModel, Field + +from ee.hogai.graph.session_summaries.nodes import SessionSummarizationNode +from ee.hogai.tool import MaxTool, ToolMessagesArtifact +from ee.hogai.utils.types.base import AssistantState, PartialAssistantState + +SESSION_SUMMARIZATION_TOOL_PROMPT = """ +Use this tool to summarize session recordings by analysing the events within those sessions to find patterns and issues. +It will return a textual summary of the captured session recordings. + +# When to use the tool: +When the user asks to summarize session recordings: +- "summarize" synonyms: "watch", "analyze", "review", and similar +- "session recordings" synonyms: "sessions", "recordings", "replays", "user sessions", and similar + +# When NOT to use the tool: +- When the user asks to find, search for, or look up session recordings, but doesn't ask to summarize them +- When users asks to update, change, or adjust session recordings filters + +# Synonyms +- "summarize": "watch", "analyze", "review", and similar +- "session recordings": "sessions", "recordings", "replays", "user sessions", and similar + +# Managing context +If the conversation history contains context about the current filters or session recordings, follow these steps: +- Convert the user query into a `session_summarization_query` +- The query should be used to understand the user's intent +- Decide if the query is relevant to the current filters and set `should_use_current_filters` accordingly +- Generate the `summary_title` based on the user's query and the current filters + +Otherwise: +- Convert the user query into a `session_summarization_query` +- The query should be used to search for relevant sessions and then summarize them +- Assume the `should_use_current_filters` should be always `false` +- Generate the `summary_title` based on the user's query + +# Additional guidelines +- CRITICAL: Always pass the user's complete, unmodified query to the `session_summarization_query` parameter +- DO NOT truncate, summarize, or extract keywords from the user's query +- The query is used to find relevant sessions - context helps find better matches +- Use explicit tool definition to make a decision +""".strip() + + +class SessionSummarizationToolArgs(BaseModel): + session_summarization_query: str = Field( + description=""" + - The user's complete query for session recordings summarization. + - This will be used to find relevant session recordings. + - Always pass the user's complete, unmodified query. + - Examples: + * 'summarize all session recordings from yesterday' + * 'analyze mobile user session recordings from last week, even if 1 second' + * 'watch last 300 session recordings of MacOS users from US' + * and similar + """ + ) + should_use_current_filters: bool = Field( + description=""" + - Whether to use current filters from user's UI to find relevant session recordings. + - IMPORTANT: Should be always `false` if the current filters or `search_session_recordings` tool are not present in the conversation history. + - Examples: + * Set to `true` if one of the conditions is met: + - the user wants to summarize "current/selected/opened/my/all/these" session recordings + - the user wants to use "current/these" filters + - the user's query specifies filters identical to the current filters + - if the user's query doesn't specify any filters/conditions + - the user refers to what they're "looking at" or "viewing" + * Set to `false` if one of the conditions is met: + - no current filters or `search_session_recordings` tool are present in the conversation + - the user specifies date/time period different from the current filters + - the user specifies conditions (user, device, id, URL, etc.) not present in the current filters + """, + ) + summary_title: str = Field( + description=""" + - The name of the summary that is expected to be generated from the user's `session_summarization_query` and/or `current_filters` (if present). + - The name should cover in 3-7 words what sessions would be to be summarized in the summary + - This won't be used for any search of filtering, only to properly label the generated summary. + - Examples: + * If `should_use_current_filters` is `false`, then the `summary_title` should be generated based on the `session_summarization_query`: + - query: "I want to watch all the sessions of user `user@example.com` in the last 30 days no matter how long" -> name: "Sessions of the user user@example.com (last 30 days)" + - query: "summarize my last 100 session recordings" -> name: "Last 100 sessions" + - and similar + * If `should_use_current_filters` is `true`, then the `summary_title` should be generated based on the current filters in the context (if present): + - filters: "{"key":"$os","value":["Mac OS X"],"operator":"exact","type":"event"}" -> name: "MacOS users" + - filters: "{"date_from": "-7d", "filter_test_accounts": True}" -> name: "All sessions (last 7 days)" + - and similar + * If there's not enough context to generated the summary name - keep it an empty string ("") + """ + ) + + +class SessionSummarizationTool(MaxTool): + name: Literal["session_summarization"] = "session_summarization" + description: str = SESSION_SUMMARIZATION_TOOL_PROMPT + thinking_message: str = "Summarizing session recordings" + context_prompt_template: str = "Summarizes session recordings based on the user's query and current filters" + args_schema: type[BaseModel] = SessionSummarizationToolArgs + show_tool_call_message: bool = False + + async def _arun_impl( + self, session_summarization_query: str, should_use_current_filters: bool, summary_title: str + ) -> tuple[str, ToolMessagesArtifact | None]: + node = SessionSummarizationNode(self._team, self._user) + chain: RunnableLambda[AssistantState, PartialAssistantState | None] = RunnableLambda(node) + copied_state = self._state.model_copy( + deep=True, + update={ + "root_tool_call_id": self.tool_call_id, + "session_summarization_query": session_summarization_query, + "should_use_current_filters": should_use_current_filters, + "summary_title": summary_title, + }, + ) + result = await chain.ainvoke(copied_state) + if not result or not result.messages: + return "Session summarization failed", None + return "", ToolMessagesArtifact(messages=result.messages) diff --git a/ee/hogai/graph/root/tools/test/test_create_and_query_insight.py b/ee/hogai/graph/root/tools/test/test_create_and_query_insight.py new file mode 100644 index 0000000000..c2926d53db --- /dev/null +++ b/ee/hogai/graph/root/tools/test/test_create_and_query_insight.py @@ -0,0 +1,253 @@ +from typing import Any + +from posthog.test.base import ClickhouseTestMixin, NonAtomicBaseTest +from unittest.mock import AsyncMock, patch + +from langchain_core.runnables import RunnableConfig + +from posthog.schema import ( + AssistantMessage, + AssistantTool, + AssistantToolCallMessage, + AssistantTrendsQuery, + VisualizationMessage, +) + +from ee.hogai.context.context import AssistantContextManager +from ee.hogai.graph.root.tools.create_and_query_insight import ( + INSIGHT_TOOL_FAILURE_SYSTEM_REMINDER_PROMPT, + CreateAndQueryInsightTool, +) +from ee.hogai.graph.schema_generator.nodes import SchemaGenerationException +from ee.hogai.utils.types import AssistantState +from ee.hogai.utils.types.base import NodePath +from ee.models.assistant import Conversation + + +class TestCreateAndQueryInsightTool(ClickhouseTestMixin, NonAtomicBaseTest): + CLASS_DATA_LEVEL_SETUP = False + + def setUp(self): + super().setUp() + self.conversation = Conversation.objects.create(team=self.team, user=self.user) + self.tool_call_id = "test_tool_call_id" + + def _create_tool( + self, state: AssistantState | None = None, contextual_tools: dict[str, dict[str, Any]] | None = None + ): + """Helper to create tool instance with optional state and contextual tools.""" + if state is None: + state = AssistantState(messages=[]) + + config: RunnableConfig = RunnableConfig() + if contextual_tools: + config = RunnableConfig(configurable={"contextual_tools": contextual_tools}) + + context_manager = AssistantContextManager(team=self.team, user=self.user, config=config) + + return CreateAndQueryInsightTool( + team=self.team, + user=self.user, + state=state, + context_manager=context_manager, + node_path=(NodePath(name="test_node", tool_call_id=self.tool_call_id, message_id="test"),), + ) + + async def test_successful_insight_creation_returns_messages(self): + """Test successful insight creation returns visualization and tool call messages.""" + tool = self._create_tool() + + query = AssistantTrendsQuery(series=[]) + viz_message = VisualizationMessage(query="test query", answer=query, plan="test plan") + tool_call_message = AssistantToolCallMessage(content="Results are here", tool_call_id=self.tool_call_id) + + mock_state = AssistantState(messages=[viz_message, tool_call_message]) + + with patch("ee.hogai.graph.insights_graph.graph.InsightsGraph.compile_full_graph") as mock_compile: + mock_graph = AsyncMock() + mock_graph.ainvoke = AsyncMock(return_value=mock_state.model_dump()) + mock_compile.return_value = mock_graph + + result_text, artifact = await tool._arun_impl(query_description="test description") + + self.assertEqual(result_text, "") + self.assertIsNotNone(artifact) + self.assertEqual(len(artifact.messages), 2) + self.assertIsInstance(artifact.messages[0], VisualizationMessage) + self.assertIsInstance(artifact.messages[1], AssistantToolCallMessage) + + async def test_schema_generation_exception_returns_formatted_error(self): + """Test SchemaGenerationException is caught and returns formatted error message.""" + tool = self._create_tool() + + exception = SchemaGenerationException( + llm_output="Invalid query structure", validation_message="Missing required field: series" + ) + + with patch("ee.hogai.graph.insights_graph.graph.InsightsGraph.compile_full_graph") as mock_compile: + mock_graph = AsyncMock() + mock_graph.ainvoke = AsyncMock(side_effect=exception) + mock_compile.return_value = mock_graph + + result_text, artifact = await tool._arun_impl(query_description="test description") + + self.assertIsNone(artifact) + self.assertIn("Invalid query structure", result_text) + self.assertIn("Missing required field: series", result_text) + self.assertIn(INSIGHT_TOOL_FAILURE_SYSTEM_REMINDER_PROMPT, result_text) + + async def test_invalid_tool_call_message_type_returns_error(self): + """Test when the last message is not AssistantToolCallMessage, returns error.""" + tool = self._create_tool() + + viz_message = VisualizationMessage(query="test query", answer=AssistantTrendsQuery(series=[]), plan="test plan") + # Last message is AssistantMessage instead of AssistantToolCallMessage + invalid_message = AssistantMessage(content="Not a tool call message") + + mock_state = AssistantState(messages=[viz_message, invalid_message]) + + with patch("ee.hogai.graph.insights_graph.graph.InsightsGraph.compile_full_graph") as mock_compile: + mock_graph = AsyncMock() + mock_graph.ainvoke = AsyncMock(return_value=mock_state.model_dump()) + mock_compile.return_value = mock_graph + + result_text, artifact = await tool._arun_impl(query_description="test description") + + self.assertIsNone(artifact) + self.assertIn("unknown error", result_text) + self.assertIn(INSIGHT_TOOL_FAILURE_SYSTEM_REMINDER_PROMPT, result_text) + + async def test_human_feedback_requested_returns_only_tool_call_message(self): + """Test when visualization message is not present, returns only tool call message.""" + tool = self._create_tool() + + # When agent requests human feedback, there's no VisualizationMessage + some_message = AssistantMessage(content="I need help with this query") + tool_call_message = AssistantToolCallMessage(content="Need clarification", tool_call_id=self.tool_call_id) + + mock_state = AssistantState(messages=[some_message, tool_call_message]) + + with patch("ee.hogai.graph.insights_graph.graph.InsightsGraph.compile_full_graph") as mock_compile: + mock_graph = AsyncMock() + mock_graph.ainvoke = AsyncMock(return_value=mock_state.model_dump()) + mock_compile.return_value = mock_graph + + result_text, artifact = await tool._arun_impl(query_description="test description") + + self.assertEqual(result_text, "") + self.assertIsNotNone(artifact) + self.assertEqual(len(artifact.messages), 1) + self.assertIsInstance(artifact.messages[0], AssistantToolCallMessage) + self.assertEqual(artifact.messages[0].content, "Need clarification") + + async def test_editing_mode_adds_ui_payload(self): + """Test that in editing mode, UI payload is added to tool call message.""" + # Create tool with contextual tool available + tool = self._create_tool(contextual_tools={AssistantTool.CREATE_AND_QUERY_INSIGHT.value: {}}) + + query = AssistantTrendsQuery(series=[]) + viz_message = VisualizationMessage(query="test query", answer=query, plan="test plan") + tool_call_message = AssistantToolCallMessage(content="Results are here", tool_call_id=self.tool_call_id) + + mock_state = AssistantState(messages=[viz_message, tool_call_message]) + + with patch("ee.hogai.graph.insights_graph.graph.InsightsGraph.compile_full_graph") as mock_compile: + mock_graph = AsyncMock() + mock_graph.ainvoke = AsyncMock(return_value=mock_state.model_dump()) + mock_compile.return_value = mock_graph + + result_text, artifact = await tool._arun_impl(query_description="test description") + + self.assertEqual(result_text, "") + self.assertIsNotNone(artifact) + self.assertEqual(len(artifact.messages), 2) + + # Check that UI payload was added to tool call message + returned_tool_call_message = artifact.messages[1] + self.assertIsInstance(returned_tool_call_message, AssistantToolCallMessage) + self.assertIsNotNone(returned_tool_call_message.ui_payload) + self.assertIn("create_and_query_insight", returned_tool_call_message.ui_payload) + self.assertEqual( + returned_tool_call_message.ui_payload["create_and_query_insight"], query.model_dump(exclude_none=True) + ) + + async def test_non_editing_mode_no_ui_payload(self): + """Test that in non-editing mode, no UI payload is added to tool call message.""" + # Create tool without contextual tools (non-editing mode) + tool = self._create_tool(contextual_tools={}) + + query = AssistantTrendsQuery(series=[]) + viz_message = VisualizationMessage(query="test query", answer=query, plan="test plan") + tool_call_message = AssistantToolCallMessage(content="Results are here", tool_call_id=self.tool_call_id) + + mock_state = AssistantState(messages=[viz_message, tool_call_message]) + + with patch("ee.hogai.graph.insights_graph.graph.InsightsGraph.compile_full_graph") as mock_compile: + mock_graph = AsyncMock() + mock_graph.ainvoke = AsyncMock(return_value=mock_state.model_dump()) + mock_compile.return_value = mock_graph + + result_text, artifact = await tool._arun_impl(query_description="test description") + + self.assertEqual(result_text, "") + self.assertIsNotNone(artifact) + self.assertEqual(len(artifact.messages), 2) + + # Check that the original tool call message is returned without modification + returned_tool_call_message = artifact.messages[1] + self.assertIsInstance(returned_tool_call_message, AssistantToolCallMessage) + # In non-editing mode, the original message is returned as-is + self.assertEqual(returned_tool_call_message, tool_call_message) + + async def test_state_updates_include_tool_call_metadata(self): + """Test that the state passed to graph includes root_tool_call_id and root_tool_insight_plan.""" + initial_state = AssistantState(messages=[AssistantMessage(content="initial")]) + tool = self._create_tool(state=initial_state) + + query = AssistantTrendsQuery(series=[]) + viz_message = VisualizationMessage(query="test query", answer=query, plan="test plan") + tool_call_message = AssistantToolCallMessage(content="Results", tool_call_id=self.tool_call_id) + mock_state = AssistantState(messages=[viz_message, tool_call_message]) + + invoked_state = None + + async def capture_invoked_state(state): + nonlocal invoked_state + invoked_state = state + return mock_state.model_dump() + + with patch("ee.hogai.graph.insights_graph.graph.InsightsGraph.compile_full_graph") as mock_compile: + mock_graph = AsyncMock() + mock_graph.ainvoke = AsyncMock(side_effect=capture_invoked_state) + mock_compile.return_value = mock_graph + + await tool._arun_impl(query_description="my test query") + + # Verify the state passed to ainvoke has the correct metadata + self.assertIsNotNone(invoked_state) + validated_state = AssistantState.model_validate(invoked_state) + self.assertEqual(validated_state.root_tool_call_id, self.tool_call_id) + self.assertEqual(validated_state.root_tool_insight_plan, "my test query") + # Original message should still be there + self.assertEqual(len(validated_state.messages), 1) + assert isinstance(validated_state.messages[0], AssistantMessage) + self.assertEqual(validated_state.messages[0].content, "initial") + + async def test_is_editing_mode_classmethod(self): + """Test the is_editing_mode class method correctly detects editing mode.""" + # Test with editing mode enabled + config_editing: RunnableConfig = RunnableConfig( + configurable={"contextual_tools": {AssistantTool.CREATE_AND_QUERY_INSIGHT.value: {}}} + ) + context_manager_editing = AssistantContextManager(team=self.team, user=self.user, config=config_editing) + self.assertTrue(CreateAndQueryInsightTool.is_editing_mode(context_manager_editing)) + + # Test with editing mode disabled + config_not_editing = RunnableConfig(configurable={"contextual_tools": {}}) + context_manager_not_editing = AssistantContextManager(team=self.team, user=self.user, config=config_not_editing) + self.assertFalse(CreateAndQueryInsightTool.is_editing_mode(context_manager_not_editing)) + + # Test with other contextual tools but not create_and_query_insight + config_other = RunnableConfig(configurable={"contextual_tools": {"some_other_tool": {}}}) + context_manager_other = AssistantContextManager(team=self.team, user=self.user, config=config_other) + self.assertFalse(CreateAndQueryInsightTool.is_editing_mode(context_manager_other)) diff --git a/ee/hogai/graph/root/tools/test/test_create_dashboard.py b/ee/hogai/graph/root/tools/test/test_create_dashboard.py new file mode 100644 index 0000000000..39eb8e3150 --- /dev/null +++ b/ee/hogai/graph/root/tools/test/test_create_dashboard.py @@ -0,0 +1,248 @@ +from typing import cast +from uuid import uuid4 + +from posthog.test.base import ClickhouseTestMixin, NonAtomicBaseTest +from unittest.mock import AsyncMock, MagicMock, patch + +from posthog.schema import AssistantMessage + +from ee.hogai.context.context import AssistantContextManager +from ee.hogai.graph.root.tools.create_dashboard import CreateDashboardTool +from ee.hogai.utils.types import AssistantState, InsightQuery, PartialAssistantState +from ee.hogai.utils.types.base import NodePath + + +class TestCreateDashboardTool(ClickhouseTestMixin, NonAtomicBaseTest): + CLASS_DATA_LEVEL_SETUP = False + + def setUp(self): + super().setUp() + self.tool_call_id = str(uuid4()) + self.state = AssistantState(messages=[], root_tool_call_id=self.tool_call_id) + self.context_manager = AssistantContextManager(self.team, self.user, {}) + self.tool = CreateDashboardTool( + team=self.team, + user=self.user, + state=self.state, + context_manager=self.context_manager, + node_path=(NodePath(name="test_node", tool_call_id=self.tool_call_id, message_id="test"),), + ) + + async def test_execute_calls_dashboard_creation_node(self): + mock_node_instance = MagicMock() + mock_result = PartialAssistantState( + messages=[AssistantMessage(content="Dashboard created successfully with 3 insights")] + ) + + with patch("ee.hogai.graph.dashboards.nodes.DashboardCreationNode", return_value=mock_node_instance): + with patch("ee.hogai.graph.root.tools.create_dashboard.RunnableLambda") as mock_runnable: + mock_chain = MagicMock() + mock_chain.ainvoke = AsyncMock(return_value=mock_result) + mock_runnable.return_value = mock_chain + + insight_queries = [ + InsightQuery(name="Pageviews", description="Show pageviews for last 7 days"), + InsightQuery(name="User signups", description="Show user signups funnel"), + ] + + result, artifact = await self.tool._arun_impl( + search_insights_queries=insight_queries, + dashboard_name="Marketing Dashboard", + ) + + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + assert artifact is not None + self.assertEqual(len(artifact.messages), 1) + message = cast(AssistantMessage, artifact.messages[0]) + self.assertEqual(message.content, "Dashboard created successfully with 3 insights") + + async def test_execute_updates_state_with_all_parameters(self): + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Test response")]) + + insight_queries = [ + InsightQuery(name="Revenue Trends", description="Monthly revenue trends for Q4"), + InsightQuery(name="Churn Rate", description="Customer churn rate by cohort"), + InsightQuery(name="NPS Score", description="Net Promoter Score over time"), + ] + + async def mock_ainvoke(state): + self.assertEqual(state.search_insights_queries, insight_queries) + self.assertEqual(state.dashboard_name, "Executive Summary Q4") + self.assertEqual(state.root_tool_call_id, self.tool_call_id) + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.dashboards.nodes.DashboardCreationNode"): + with patch("ee.hogai.graph.root.tools.create_dashboard.RunnableLambda", return_value=mock_chain): + await self.tool._arun_impl( + search_insights_queries=insight_queries, + dashboard_name="Executive Summary Q4", + ) + + async def test_execute_with_single_insight_query(self): + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Dashboard with one insight created")]) + + insight_queries = [InsightQuery(name="Daily Active Users", description="Count of daily active users")] + + async def mock_ainvoke(state): + self.assertEqual(len(state.search_insights_queries), 1) + self.assertEqual(state.search_insights_queries[0].name, "Daily Active Users") + self.assertEqual(state.search_insights_queries[0].description, "Count of daily active users") + self.assertEqual(state.dashboard_name, "User Activity Dashboard") + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.dashboards.nodes.DashboardCreationNode"): + with patch("ee.hogai.graph.root.tools.create_dashboard.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool._arun_impl( + search_insights_queries=insight_queries, + dashboard_name="User Activity Dashboard", + ) + + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + + async def test_execute_with_many_insight_queries(self): + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Large dashboard created")]) + + insight_queries = [ + InsightQuery(name=f"Insight {i}", description=f"Description for insight {i}") for i in range(10) + ] + + async def mock_ainvoke(state): + self.assertEqual(len(state.search_insights_queries), 10) + self.assertEqual(state.search_insights_queries[0].name, "Insight 0") + self.assertEqual(state.search_insights_queries[9].name, "Insight 9") + self.assertEqual(state.dashboard_name, "Comprehensive Dashboard") + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.dashboards.nodes.DashboardCreationNode"): + with patch("ee.hogai.graph.root.tools.create_dashboard.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool._arun_impl( + search_insights_queries=insight_queries, + dashboard_name="Comprehensive Dashboard", + ) + + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + + async def test_execute_returns_failure_message_when_result_is_none(self): + async def mock_ainvoke(state): + return None + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.dashboards.nodes.DashboardCreationNode"): + with patch("ee.hogai.graph.root.tools.create_dashboard.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool._arun_impl( + search_insights_queries=[InsightQuery(name="Test", description="Test insight")], + dashboard_name="Test Dashboard", + ) + + self.assertEqual(result, "Dashboard creation failed") + self.assertIsNone(artifact) + + async def test_execute_returns_failure_message_when_result_has_no_messages(self): + mock_result = PartialAssistantState(messages=[]) + + async def mock_ainvoke(state): + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.dashboards.nodes.DashboardCreationNode"): + with patch("ee.hogai.graph.root.tools.create_dashboard.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool._arun_impl( + search_insights_queries=[InsightQuery(name="Test", description="Test insight")], + dashboard_name="Test Dashboard", + ) + + self.assertEqual(result, "Dashboard creation failed") + self.assertIsNone(artifact) + + async def test_execute_preserves_original_state(self): + """Test that the original state is not modified when creating the copied state""" + original_queries = [InsightQuery(name="Original", description="Original insight")] + original_state = AssistantState( + messages=[], + root_tool_call_id=self.tool_call_id, + search_insights_queries=original_queries, + dashboard_name="Original Dashboard", + ) + + tool = CreateDashboardTool( + team=self.team, + user=self.user, + state=original_state, + context_manager=self.context_manager, + node_path=(NodePath(name="test_node", tool_call_id=self.tool_call_id, message_id="test"),), + ) + + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Test")]) + + new_queries = [InsightQuery(name="New", description="New insight")] + + async def mock_ainvoke(state): + # Verify the new state has updated values + self.assertEqual(state.search_insights_queries, new_queries) + self.assertEqual(state.dashboard_name, "New Dashboard") + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.dashboards.nodes.DashboardCreationNode"): + with patch("ee.hogai.graph.root.tools.create_dashboard.RunnableLambda", return_value=mock_chain): + await tool._arun_impl( + search_insights_queries=new_queries, + dashboard_name="New Dashboard", + ) + + # Verify original state was not modified + self.assertEqual(original_state.search_insights_queries, original_queries) + self.assertEqual(original_state.dashboard_name, "Original Dashboard") + self.assertEqual(original_state.root_tool_call_id, self.tool_call_id) + + async def test_execute_with_complex_insight_descriptions(self): + """Test that complex insight descriptions with special characters are handled correctly""" + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Dashboard created")]) + + insight_queries = [ + InsightQuery( + name="User Journey", + description='Show funnel from "Sign up" → "Create project" → "Invite team" for users with property email containing "@company.com"', + ), + InsightQuery( + name="Revenue (USD)", + description="Track total revenue in USD from 2024-01-01 to 2024-12-31, filtered by plan_type = 'premium' OR plan_type = 'enterprise'", + ), + ] + + async def mock_ainvoke(state): + self.assertEqual(len(state.search_insights_queries), 2) + self.assertIn("@company.com", state.search_insights_queries[0].description) + self.assertIn("'premium'", state.search_insights_queries[1].description) + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.dashboards.nodes.DashboardCreationNode"): + with patch("ee.hogai.graph.root.tools.create_dashboard.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool._arun_impl( + search_insights_queries=insight_queries, + dashboard_name="Complex Dashboard", + ) + + self.assertEqual(result, "") + self.assertIsNotNone(artifact) diff --git a/ee/hogai/graph/root/tools/test/test_search.py b/ee/hogai/graph/root/tools/test/test_search.py index 4bbdb14b9f..5077b79eaa 100644 --- a/ee/hogai/graph/root/tools/test/test_search.py +++ b/ee/hogai/graph/root/tools/test/test_search.py @@ -1,27 +1,178 @@ -from posthog.test.base import BaseTest -from unittest.mock import patch +from typing import cast +from uuid import uuid4 + +from posthog.test.base import ClickhouseTestMixin, NonAtomicBaseTest +from unittest.mock import AsyncMock, MagicMock, patch from django.test import override_settings from langchain_core import messages +from langchain_core.runnables import RunnableConfig +from posthog.schema import AssistantMessage + +from ee.hogai.context.context import AssistantContextManager from ee.hogai.graph.root.tools.search import ( DOC_ITEM_TEMPLATE, - DOCS_SEARCH_NO_RESULTS_TEMPLATE, DOCS_SEARCH_RESULTS_TEMPLATE, + EMPTY_DATABASE_ERROR_MESSAGE, + InkeepDocsSearchTool, + InsightSearchTool, SearchTool, ) from ee.hogai.utils.tests import FakeChatOpenAI +from ee.hogai.utils.types import AssistantState, PartialAssistantState +from ee.hogai.utils.types.base import NodePath -class TestSearchToolDocumentation(BaseTest): +class TestSearchTool(ClickhouseTestMixin, NonAtomicBaseTest): + CLASS_DATA_LEVEL_SETUP = False + def setUp(self): super().setUp() - self.tool = SearchTool(team=self.team, user=self.user, tool_call_id="test-tool-call-id") + self.tool_call_id = "test_tool_call_id" + self.state = AssistantState(messages=[], root_tool_call_id=str(uuid4())) + self.context_manager = AssistantContextManager(self.team, self.user, {}) + self.tool = SearchTool( + team=self.team, + user=self.user, + state=self.state, + context_manager=self.context_manager, + node_path=(NodePath(name="test_node", tool_call_id=self.tool_call_id, message_id="test"),), + ) + + async def test_run_docs_search_without_api_key(self): + with patch("ee.hogai.graph.root.tools.search.settings") as mock_settings: + mock_settings.INKEEP_API_KEY = None + result, artifact = await self.tool._arun_impl(kind="docs", query="How to use feature flags?") + self.assertEqual(result, "This tool is not available in this environment.") + self.assertIsNone(artifact) + + async def test_run_docs_search_with_api_key(self): + mock_docs_tool = MagicMock() + mock_docs_tool.execute = AsyncMock(return_value=("", MagicMock())) + + with ( + patch("ee.hogai.graph.root.tools.search.settings") as mock_settings, + patch("ee.hogai.graph.root.tools.search.InkeepDocsSearchTool", return_value=mock_docs_tool), + ): + mock_settings.INKEEP_API_KEY = "test-key" + result, artifact = await self.tool._arun_impl(kind="docs", query="How to use feature flags?") + + mock_docs_tool.execute.assert_called_once_with("How to use feature flags?", self.tool_call_id) + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + + async def test_run_insights_search(self): + mock_insights_tool = MagicMock() + mock_insights_tool.execute = AsyncMock(return_value=("", MagicMock())) + + with patch("ee.hogai.graph.root.tools.search.InsightSearchTool", return_value=mock_insights_tool): + result, artifact = await self.tool._arun_impl(kind="insights", query="user signups") + + mock_insights_tool.execute.assert_called_once_with("user signups", self.tool_call_id) + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + + async def test_run_unknown_kind(self): + result, artifact = await self.tool._arun_impl(kind="unknown", query="test") + self.assertEqual(result, "Invalid entity kind: unknown. Please provide a valid entity kind for the tool.") + self.assertIsNone(artifact) + + @patch("ee.hogai.graph.root.tools.search.EntitySearchTool.execute") + async def test_arun_impl_error_tracking_issues_returns_routing_data(self, mock_execute): + mock_execute.return_value = "Search results for error tracking issues" + + result, artifact = await self.tool._arun_impl( + kind="error_tracking_issues", query="test error tracking issue query" + ) + + self.assertEqual(result, "Search results for error tracking issues") + self.assertIsNone(artifact) + mock_execute.assert_called_once_with("test error tracking issue query", "error_tracking_issues") + + @patch("ee.hogai.graph.root.tools.search.EntitySearchTool.execute") + @patch("ee.hogai.graph.root.tools.search.SearchTool._has_insights_fts_search_feature_flag") + async def test_arun_impl_insight_with_feature_flag_disabled( + self, mock_has_insights_fts_search_feature_flag, mock_execute + ): + mock_has_insights_fts_search_feature_flag.return_value = False + mock_execute.return_value = "Search results for insights" + + result, artifact = await self.tool._arun_impl(kind="insights", query="test insight query") + + self.assertEqual(result, "The user doesn't have any insights created yet.") + self.assertIsNone(artifact) + mock_execute.assert_not_called() + + @patch("ee.hogai.graph.root.tools.search.EntitySearchTool.execute") + @patch("ee.hogai.graph.root.tools.search.SearchTool._has_insights_fts_search_feature_flag") + async def test_arun_impl_insight_with_feature_flag_enabled( + self, mock_has_insights_fts_search_feature_flag, mock_execute + ): + mock_has_insights_fts_search_feature_flag.return_value = True + mock_execute.return_value = "Search results for insights" + + result, artifact = await self.tool._arun_impl(kind="insights", query="test insight query") + + self.assertEqual(result, "Search results for insights") + self.assertIsNone(artifact) + mock_execute.assert_called_once_with("test insight query", "insights") + + +class TestInkeepDocsSearchTool(ClickhouseTestMixin, NonAtomicBaseTest): + CLASS_DATA_LEVEL_SETUP = False + + def setUp(self): + super().setUp() + self.tool_call_id = str(uuid4()) + self.state = AssistantState(messages=[], root_tool_call_id=self.tool_call_id) + self.context_manager = AssistantContextManager(self.team, self.user, {}) + self.tool = InkeepDocsSearchTool( + team=self.team, + user=self.user, + state=self.state, + config=RunnableConfig(configurable={}), + context_manager=self.context_manager, + ) + + async def test_execute_calls_inkeep_docs_node(self): + mock_node_instance = MagicMock() + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Here is the answer from docs")]) + + with patch("ee.hogai.graph.inkeep_docs.nodes.InkeepDocsNode", return_value=mock_node_instance): + with patch("ee.hogai.graph.root.tools.search.RunnableLambda") as mock_runnable: + mock_chain = MagicMock() + mock_chain.ainvoke = AsyncMock(return_value=mock_result) + mock_runnable.return_value = mock_chain + + result, artifact = await self.tool.execute("How to track events?", "test-tool-call-id") + + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + assert artifact is not None + self.assertEqual(len(artifact.messages), 1) + message = cast(AssistantMessage, artifact.messages[0]) + self.assertEqual(message.content, "Here is the answer from docs") + + async def test_execute_updates_state_with_tool_call_id(self): + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Test response")]) + + async def mock_ainvoke(state): + self.assertEqual(state.root_tool_call_id, "custom-tool-call-id") + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.inkeep_docs.nodes.InkeepDocsNode"): + with patch("ee.hogai.graph.root.tools.search.RunnableLambda", return_value=mock_chain): + await self.tool.execute("test query", "custom-tool-call-id") @override_settings(INKEEP_API_KEY="test-inkeep-key") @patch("ee.hogai.graph.root.tools.search.ChatOpenAI") - async def test_search_docs_with_successful_results(self, mock_llm_class): + @patch("ee.hogai.graph.root.tools.search.InkeepDocsSearchTool._has_rag_docs_search_feature_flag", return_value=True) + async def test_search_docs_with_successful_results(self, mock_has_rag_docs_search_feature_flag, mock_llm_class): response_json = """{ "content": [ { @@ -47,7 +198,7 @@ class TestSearchToolDocumentation(BaseTest): fake_llm = FakeChatOpenAI(responses=[messages.AIMessage(content=response_json)]) mock_llm_class.return_value = fake_llm - result = await self.tool._search_docs("how to use feature") + result, _ = await self.tool.execute("how to use feature", "test-tool-call-id") expected_doc_1 = DOC_ITEM_TEMPLATE.format( title="Feature Documentation", @@ -68,196 +219,76 @@ class TestSearchToolDocumentation(BaseTest): self.assertEqual(mock_llm_class.call_args.kwargs["api_key"], "test-inkeep-key") self.assertEqual(mock_llm_class.call_args.kwargs["streaming"], False) - @override_settings(INKEEP_API_KEY="test-inkeep-key") - @patch("ee.hogai.graph.root.tools.search.ChatOpenAI") - async def test_search_docs_with_no_results(self, mock_llm_class): - fake_llm = FakeChatOpenAI(responses=[messages.AIMessage(content="{}")]) - mock_llm_class.return_value = fake_llm - result = await self.tool._search_docs("nonexistent feature") +class TestInsightSearchTool(ClickhouseTestMixin, NonAtomicBaseTest): + CLASS_DATA_LEVEL_SETUP = False - self.assertEqual(result, DOCS_SEARCH_NO_RESULTS_TEMPLATE) - - @override_settings(INKEEP_API_KEY="test-inkeep-key") - @patch("ee.hogai.graph.root.tools.search.ChatOpenAI") - async def test_search_docs_with_empty_content(self, mock_llm_class): - fake_llm = FakeChatOpenAI(responses=[messages.AIMessage(content='{"content": []}')]) - mock_llm_class.return_value = fake_llm - - result = await self.tool._search_docs("query") - - self.assertEqual(result, DOCS_SEARCH_NO_RESULTS_TEMPLATE) - - @override_settings(INKEEP_API_KEY="test-inkeep-key") - @patch("ee.hogai.graph.root.tools.search.ChatOpenAI") - async def test_search_docs_filters_non_document_types(self, mock_llm_class): - response_json = """{ - "content": [ - { - "type": "snippet", - "record_type": "code", - "url": "https://posthog.com/code", - "title": "Code Snippet", - "source": {"type": "text", "content": [{"type": "text", "text": "Code example"}]} - }, - { - "type": "answer", - "record_type": "answer", - "url": "https://posthog.com/answer", - "title": "Answer", - "source": {"type": "text", "content": [{"type": "text", "text": "Answer text"}]} - } - ] - }""" - - fake_llm = FakeChatOpenAI(responses=[messages.AIMessage(content=response_json)]) - mock_llm_class.return_value = fake_llm - - result = await self.tool._search_docs("query") - - self.assertEqual(result, DOCS_SEARCH_NO_RESULTS_TEMPLATE) - - @override_settings(INKEEP_API_KEY="test-inkeep-key") - @patch("ee.hogai.graph.root.tools.search.ChatOpenAI") - async def test_search_docs_handles_empty_source_content(self, mock_llm_class): - response_json = """{ - "content": [ - { - "type": "document", - "record_type": "page", - "url": "https://posthog.com/docs/feature", - "title": "Feature Documentation", - "source": {"type": "text", "content": []} - } - ] - }""" - - fake_llm = FakeChatOpenAI(responses=[messages.AIMessage(content=response_json)]) - mock_llm_class.return_value = fake_llm - - result = await self.tool._search_docs("query") - - expected_doc = DOC_ITEM_TEMPLATE.format( - title="Feature Documentation", url="https://posthog.com/docs/feature", text="" - ) - expected_result = DOCS_SEARCH_RESULTS_TEMPLATE.format(count=1, docs=expected_doc) - - self.assertEqual(result, expected_result) - - @override_settings(INKEEP_API_KEY="test-inkeep-key") - @patch("ee.hogai.graph.root.tools.search.ChatOpenAI") - async def test_search_docs_handles_mixed_document_types(self, mock_llm_class): - response_json = """{ - "content": [ - { - "type": "document", - "record_type": "page", - "url": "https://posthog.com/docs/valid", - "title": "Valid Doc", - "source": {"type": "text", "content": [{"type": "text", "text": "Valid content"}]} - }, - { - "type": "snippet", - "record_type": "code", - "url": "https://posthog.com/code", - "title": "Code Snippet", - "source": {"type": "text", "content": [{"type": "text", "text": "Code"}]} - }, - { - "type": "document", - "record_type": "guide", - "url": "https://posthog.com/docs/another", - "title": "Another Valid Doc", - "source": {"type": "text", "content": [{"type": "text", "text": "More content"}]} - } - ] - }""" - - fake_llm = FakeChatOpenAI(responses=[messages.AIMessage(content=response_json)]) - mock_llm_class.return_value = fake_llm - - result = await self.tool._search_docs("query") - - expected_doc_1 = DOC_ITEM_TEMPLATE.format( - title="Valid Doc", url="https://posthog.com/docs/valid", text="Valid content" - ) - expected_doc_2 = DOC_ITEM_TEMPLATE.format( - title="Another Valid Doc", url="https://posthog.com/docs/another", text="More content" - ) - expected_result = DOCS_SEARCH_RESULTS_TEMPLATE.format( - count=2, docs=f"{expected_doc_1}\n\n---\n\n{expected_doc_2}" + def setUp(self): + super().setUp() + self.tool_call_id = str(uuid4()) + self.state = AssistantState(messages=[], root_tool_call_id=self.tool_call_id) + self.context_manager = AssistantContextManager(self.team, self.user, {}) + self.tool = InsightSearchTool( + team=self.team, + user=self.user, + state=self.state, + config=RunnableConfig(configurable={}), + context_manager=self.context_manager, ) - self.assertEqual(result, expected_result) + async def test_execute_calls_insight_search_node(self): + mock_node_instance = MagicMock() + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Found 3 insights matching your query")]) - @override_settings(INKEEP_API_KEY=None) - async def test_arun_impl_docs_without_api_key(self): - result, artifact = await self.tool._arun_impl(kind="docs", query="test query") + with patch("ee.hogai.graph.insights.nodes.InsightSearchNode", return_value=mock_node_instance): + with patch("ee.hogai.graph.root.tools.search.RunnableLambda") as mock_runnable: + mock_chain = MagicMock() + mock_chain.ainvoke = AsyncMock(return_value=mock_result) + mock_runnable.return_value = mock_chain - self.assertEqual(result, "This tool is not available in this environment.") - self.assertIsNone(artifact) + result, artifact = await self.tool.execute("user signups by week", self.tool_call_id) - @override_settings(INKEEP_API_KEY="test-key") - @patch("ee.hogai.graph.root.tools.search.posthoganalytics.feature_enabled") - async def test_arun_impl_docs_with_feature_flag_disabled(self, mock_feature_enabled): - mock_feature_enabled.return_value = False + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + assert artifact is not None + self.assertEqual(len(artifact.messages), 1) + message = cast(AssistantMessage, artifact.messages[0]) + self.assertEqual(message.content, "Found 3 insights matching your query") - result, artifact = await self.tool._arun_impl(kind="docs", query="test query") + async def test_execute_updates_state_with_search_query(self): + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Test response")]) - self.assertEqual(result, "Search tool executed") - self.assertEqual(artifact, {"kind": "docs", "query": "test query"}) + async def mock_ainvoke(state): + self.assertEqual(state.search_insights_query, "custom search query") + self.assertEqual(state.root_tool_call_id, self.tool_call_id) + return mock_result - @override_settings(INKEEP_API_KEY="test-key") - @patch("ee.hogai.graph.root.tools.search.posthoganalytics.feature_enabled") - @patch.object(SearchTool, "_search_docs") - async def test_arun_impl_docs_with_feature_flag_enabled(self, mock_search_docs, mock_feature_enabled): - mock_feature_enabled.return_value = True - mock_search_docs.return_value = "Search results" + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke - result, artifact = await self.tool._arun_impl(kind="docs", query="test query") + with patch("ee.hogai.graph.insights.nodes.InsightSearchNode"): + with patch("ee.hogai.graph.root.tools.search.RunnableLambda", return_value=mock_chain): + await self.tool.execute("custom search query", self.tool_call_id) - self.assertEqual(result, "Search results") - self.assertIsNone(artifact) - mock_search_docs.assert_called_once_with("test query") + async def test_execute_handles_no_insights_exception(self): + from ee.hogai.graph.insights.nodes import NoInsightsException - async def test_arun_impl_insights_returns_routing_data(self): - result, artifact = await self.tool._arun_impl(kind="insights", query="test insight query") + with patch("ee.hogai.graph.insights.nodes.InsightSearchNode", side_effect=NoInsightsException()): + result, artifact = await self.tool.execute("user signups", self.tool_call_id) - self.assertEqual(result, "Search tool executed") - self.assertEqual(artifact, {"kind": "insights", "query": "test insight query"}) + self.assertEqual(result, EMPTY_DATABASE_ERROR_MESSAGE) + self.assertIsNone(artifact) - @patch("ee.hogai.graph.root.tools.search.EntitySearchToolkit.execute") - async def test_arun_impl_error_tracking_issues_returns_routing_data(self, mock_execute): - mock_execute.return_value = "Search results for error tracking issues" + async def test_execute_returns_none_artifact_when_result_is_none(self): + async def mock_ainvoke(state): + return None - result, artifact = await self.tool._arun_impl( - kind="error_tracking_issues", query="test error tracking issue query" - ) + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke - self.assertEqual(result, "Search results for error tracking issues") - self.assertIsNone(artifact) - mock_execute.assert_called_once_with("test error tracking issue query", "error_tracking_issues") + with patch("ee.hogai.graph.insights.nodes.InsightSearchNode"): + with patch("ee.hogai.graph.root.tools.search.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool.execute("test query", self.tool_call_id) - @patch("ee.hogai.graph.root.tools.search.EntitySearchToolkit.execute") - @patch("ee.hogai.graph.root.tools.search.SearchTool._has_fts_search_feature_flag") - async def test_arun_impl_insight_with_feature_flag_disabled(self, mock_has_fts_search_feature_flag, mock_execute): - mock_has_fts_search_feature_flag.return_value = False - mock_execute.return_value = "Search results for insights" - - result, artifact = await self.tool._arun_impl(kind="insights", query="test insight query") - - self.assertEqual(result, "Search tool executed") - self.assertEqual(artifact, {"kind": "insights", "query": "test insight query"}) - mock_execute.assert_not_called() - - @patch("ee.hogai.graph.root.tools.search.EntitySearchToolkit.execute") - @patch("ee.hogai.graph.root.tools.search.SearchTool._has_fts_search_feature_flag") - async def test_arun_impl_insight_with_feature_flag_enabled(self, mock_has_fts_search_feature_flag, mock_execute): - mock_has_fts_search_feature_flag.return_value = True - mock_execute.return_value = "Search results for insights" - - result, artifact = await self.tool._arun_impl(kind="insights", query="test insight query") - - self.assertEqual(result, "Search results for insights") - self.assertIsNone(artifact) - mock_execute.assert_called_once_with("test insight query", "insights") + self.assertEqual(result, "") + self.assertIsNone(artifact) diff --git a/ee/hogai/graph/root/tools/test/test_session_summarization.py b/ee/hogai/graph/root/tools/test/test_session_summarization.py new file mode 100644 index 0000000000..ff6d4965c6 --- /dev/null +++ b/ee/hogai/graph/root/tools/test/test_session_summarization.py @@ -0,0 +1,193 @@ +from typing import cast +from uuid import uuid4 + +from posthog.test.base import ClickhouseTestMixin, NonAtomicBaseTest +from unittest.mock import AsyncMock, MagicMock, patch + +from posthog.schema import AssistantMessage + +from ee.hogai.context.context import AssistantContextManager +from ee.hogai.graph.root.tools.session_summarization import SessionSummarizationTool +from ee.hogai.utils.types import AssistantState, PartialAssistantState +from ee.hogai.utils.types.base import NodePath + + +class TestSessionSummarizationTool(ClickhouseTestMixin, NonAtomicBaseTest): + CLASS_DATA_LEVEL_SETUP = False + + def setUp(self): + super().setUp() + self.tool_call_id = str(uuid4()) + self.state = AssistantState(messages=[], root_tool_call_id=self.tool_call_id) + self.context_manager = AssistantContextManager(self.team, self.user, {}) + self.tool = SessionSummarizationTool( + team=self.team, + user=self.user, + state=self.state, + context_manager=self.context_manager, + node_path=(NodePath(name="test_node", tool_call_id=self.tool_call_id, message_id="test"),), + ) + + async def test_execute_calls_session_summarization_node(self): + mock_node_instance = MagicMock() + mock_result = PartialAssistantState( + messages=[AssistantMessage(content="Session summary: 10 sessions analyzed with 5 key patterns found")] + ) + + with patch("ee.hogai.graph.session_summaries.nodes.SessionSummarizationNode", return_value=mock_node_instance): + with patch("ee.hogai.graph.root.tools.session_summarization.RunnableLambda") as mock_runnable: + mock_chain = MagicMock() + mock_chain.ainvoke = AsyncMock(return_value=mock_result) + mock_runnable.return_value = mock_chain + + result, artifact = await self.tool._arun_impl( + session_summarization_query="summarize all sessions from yesterday", + should_use_current_filters=False, + summary_title="All sessions from yesterday", + ) + + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + assert artifact is not None + self.assertEqual(len(artifact.messages), 1) + message = cast(AssistantMessage, artifact.messages[0]) + self.assertEqual(message.content, "Session summary: 10 sessions analyzed with 5 key patterns found") + + async def test_execute_updates_state_with_all_parameters(self): + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Test response")]) + + async def mock_ainvoke(state): + self.assertEqual(state.session_summarization_query, "analyze mobile user sessions") + self.assertEqual(state.should_use_current_filters, True) + self.assertEqual(state.summary_title, "Mobile user sessions") + self.assertEqual(state.root_tool_call_id, self.tool_call_id) + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.session_summaries.nodes.SessionSummarizationNode"): + with patch("ee.hogai.graph.root.tools.session_summarization.RunnableLambda", return_value=mock_chain): + await self.tool._arun_impl( + session_summarization_query="analyze mobile user sessions", + should_use_current_filters=True, + summary_title="Mobile user sessions", + ) + + async def test_execute_with_should_use_current_filters_false(self): + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Test response")]) + + async def mock_ainvoke(state): + self.assertEqual(state.should_use_current_filters, False) + self.assertEqual(state.session_summarization_query, "watch last 300 session recordings") + self.assertEqual(state.summary_title, "Last 300 sessions") + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.session_summaries.nodes.SessionSummarizationNode"): + with patch("ee.hogai.graph.root.tools.session_summarization.RunnableLambda", return_value=mock_chain): + await self.tool._arun_impl( + session_summarization_query="watch last 300 session recordings", + should_use_current_filters=False, + summary_title="Last 300 sessions", + ) + + async def test_execute_returns_failure_message_when_result_is_none(self): + async def mock_ainvoke(state): + return None + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.session_summaries.nodes.SessionSummarizationNode"): + with patch("ee.hogai.graph.root.tools.session_summarization.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool._arun_impl( + session_summarization_query="test query", + should_use_current_filters=False, + summary_title="Test", + ) + + self.assertEqual(result, "Session summarization failed") + self.assertIsNone(artifact) + + async def test_execute_returns_failure_message_when_result_has_no_messages(self): + mock_result = PartialAssistantState(messages=[]) + + async def mock_ainvoke(state): + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.session_summaries.nodes.SessionSummarizationNode"): + with patch("ee.hogai.graph.root.tools.session_summarization.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool._arun_impl( + session_summarization_query="test query", + should_use_current_filters=False, + summary_title="Test", + ) + + self.assertEqual(result, "Session summarization failed") + self.assertIsNone(artifact) + + async def test_execute_with_empty_summary_title(self): + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Summary completed")]) + + async def mock_ainvoke(state): + self.assertEqual(state.summary_title, "") + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.session_summaries.nodes.SessionSummarizationNode"): + with patch("ee.hogai.graph.root.tools.session_summarization.RunnableLambda", return_value=mock_chain): + result, artifact = await self.tool._arun_impl( + session_summarization_query="summarize sessions", + should_use_current_filters=False, + summary_title="", + ) + + self.assertEqual(result, "") + self.assertIsNotNone(artifact) + + async def test_execute_preserves_original_state(self): + """Test that the original state is not modified when creating the copied state""" + original_query = "original query" + original_state = AssistantState( + messages=[], + root_tool_call_id=self.tool_call_id, + session_summarization_query=original_query, + ) + + tool = SessionSummarizationTool( + team=self.team, + user=self.user, + state=original_state, + context_manager=self.context_manager, + node_path=(NodePath(name="test_node", tool_call_id=self.tool_call_id, message_id="test"),), + ) + + mock_result = PartialAssistantState(messages=[AssistantMessage(content="Test")]) + + async def mock_ainvoke(state): + # Verify the new state has updated values + self.assertEqual(state.session_summarization_query, "new query") + return mock_result + + mock_chain = MagicMock() + mock_chain.ainvoke = mock_ainvoke + + with patch("ee.hogai.graph.session_summaries.nodes.SessionSummarizationNode"): + with patch("ee.hogai.graph.root.tools.session_summarization.RunnableLambda", return_value=mock_chain): + await tool._arun_impl( + session_summarization_query="new query", + should_use_current_filters=True, + summary_title="New Summary", + ) + + # Verify original state was not modified + self.assertEqual(original_state.session_summarization_query, original_query) + self.assertEqual(original_state.root_tool_call_id, self.tool_call_id) diff --git a/ee/hogai/graph/root/tools/todo_write.py b/ee/hogai/graph/root/tools/todo_write.py index 816c19b6ce..f8670eef8b 100644 --- a/ee/hogai/graph/root/tools/todo_write.py +++ b/ee/hogai/graph/root/tools/todo_write.py @@ -138,11 +138,11 @@ When unsure, use this tool. Proactive task management shows attentiveness and he """.strip() +# Has its unique schema that doesn't match the Deep Research schema class TodoItem(BaseModel): content: str = Field(..., min_length=1) status: Literal["pending", "in_progress", "completed"] id: str - priority: Literal["low", "medium", "high"] class TodoWriteToolArgs(BaseModel): diff --git a/ee/hogai/graph/schema_generator/nodes.py b/ee/hogai/graph/schema_generator/nodes.py index f2e957ac58..2149c58071 100644 --- a/ee/hogai/graph/schema_generator/nodes.py +++ b/ee/hogai/graph/schema_generator/nodes.py @@ -13,7 +13,7 @@ from langchain_core.messages import ( from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate from langchain_core.runnables import RunnableConfig -from posthog.schema import FailureMessage, VisualizationMessage +from posthog.schema import VisualizationMessage from posthog.models.group_type_mapping import GroupTypeMapping @@ -36,6 +36,15 @@ from .utils import Q, SchemaGeneratorOutput RETRIES_ALLOWED = 2 +class SchemaGenerationException(Exception): + """An error occurred while generating a schema in the `SchemaGeneratorNode` node.""" + + def __init__(self, llm_output: str, validation_message: str): + super().__init__("Failed to generate schema") + self.llm_output = llm_output + self.validation_message = validation_message + + class SchemaGeneratorNode(AssistantNode, Generic[Q]): INSIGHT_NAME: str """ @@ -87,9 +96,8 @@ class SchemaGeneratorNode(AssistantNode, Generic[Q]): chain = generation_prompt | merger | self._model | self._parse_output - result: SchemaGeneratorOutput[Q] | None = None try: - result = await chain.ainvoke( + result: SchemaGeneratorOutput[Q] = await chain.ainvoke( { "project_datetime": self.project_now, "project_timezone": self.project_timezone, @@ -120,18 +128,9 @@ class SchemaGeneratorNode(AssistantNode, Generic[Q]): query_generation_retry_count=len(intermediate_steps) + 1, ) - if not result: - # We've got no usable result after exhausting all iteration attempts - it's failure message time - return PartialAssistantState( - messages=[ - FailureMessage( - content=f"It looks like I'm having trouble generating this {self.INSIGHT_NAME} insight." - ) - ], - intermediate_steps=None, - plan=None, - query_generation_retry_count=len(intermediate_steps) + 1, - ) + if isinstance(e, PydanticOutputParserException): + raise SchemaGenerationException(e.llm_output, e.validation_message) + raise SchemaGenerationException(e.llm_output or "No input was provided.", str(e)) # We've got a result that either passed the quality check or we've exhausted all attempts at iterating - return return PartialAssistantState( diff --git a/ee/hogai/graph/schema_generator/test/test_nodes.py b/ee/hogai/graph/schema_generator/test/test_nodes.py index 1e1ea5e1c1..2dc0c4507b 100644 --- a/ee/hogai/graph/schema_generator/test/test_nodes.py +++ b/ee/hogai/graph/schema_generator/test/test_nodes.py @@ -13,7 +13,12 @@ from langchain_core.runnables import RunnableConfig, RunnableLambda from posthog.schema import AssistantMessage, AssistantTrendsQuery, FailureMessage, HumanMessage, VisualizationMessage -from ee.hogai.graph.schema_generator.nodes import RETRIES_ALLOWED, SchemaGeneratorNode, SchemaGeneratorToolsNode +from ee.hogai.graph.schema_generator.nodes import ( + RETRIES_ALLOWED, + SchemaGenerationException, + SchemaGeneratorNode, + SchemaGeneratorToolsNode, +) from ee.hogai.graph.schema_generator.parsers import PydanticOutputParserException from ee.hogai.graph.schema_generator.utils import SchemaGeneratorOutput from ee.hogai.utils.types import AssistantState, PartialAssistantState @@ -258,7 +263,7 @@ class TestSchemaGeneratorNode(BaseTest): self.assertEqual(action.log, "Field validation failed") async def test_quality_check_failure_with_retries_exhausted(self): - """Test quality check failure with retries exhausted still returns VisualizationMessage.""" + """Test quality check failure with retries exhausted raises SchemaGenerationException.""" node = DummyGeneratorNode(self.team, self.user) with ( patch.object(DummyGeneratorNode, "_model") as generator_model_mock, @@ -273,26 +278,25 @@ class TestSchemaGeneratorNode(BaseTest): ) # Start with RETRIES_ALLOWED intermediate steps (so no more allowed) - new_state = await node.arun( - AssistantState( - messages=[HumanMessage(content="Text", id="0")], - start_id="0", - intermediate_steps=cast( - list[IntermediateStep], - [ - (AgentAction(tool="handle_incorrect_response", tool_input="", log=""), "retry"), - ], - ) - * RETRIES_ALLOWED, - ), - {}, - ) + with self.assertRaises(SchemaGenerationException) as cm: + await node.arun( + AssistantState( + messages=[HumanMessage(content="Text", id="0")], + start_id="0", + intermediate_steps=cast( + list[IntermediateStep], + [ + (AgentAction(tool="handle_incorrect_response", tool_input="", log=""), "retry"), + ], + ) + * RETRIES_ALLOWED, + ), + {}, + ) - # Should return VisualizationMessage despite quality check failure - self.assertEqual(new_state.intermediate_steps, None) - self.assertEqual(len(new_state.messages), 1) - self.assertEqual(new_state.messages[0].type, "ai/viz") - self.assertEqual(cast(VisualizationMessage, new_state.messages[0]).answer, self.basic_trends) + # Verify the exception contains the expected information + self.assertEqual(cm.exception.llm_output, '{"query": "test"}') + self.assertEqual(cm.exception.validation_message, "Quality check failed") async def test_node_leaves_failover(self): node = DummyGeneratorNode(self.team, self.user) @@ -329,20 +333,17 @@ class TestSchemaGeneratorNode(BaseTest): schema = DummySchema.model_construct(query=[]).model_dump() # type: ignore generator_model_mock.return_value = RunnableLambda(lambda _: json.dumps(schema)) - new_state = await node.arun( - AssistantState( - messages=[HumanMessage(content="Text")], - intermediate_steps=[ - (AgentAction(tool="", tool_input="", log="exception"), "exception"), - (AgentAction(tool="", tool_input="", log="exception"), "exception"), - ], - ), - {}, - ) - self.assertEqual(new_state.intermediate_steps, None) - self.assertEqual(len(new_state.messages), 1) - self.assertIsInstance(new_state.messages[0], FailureMessage) - self.assertEqual(new_state.plan, None) + with self.assertRaises(SchemaGenerationException): + await node.arun( + AssistantState( + messages=[HumanMessage(content="Text")], + intermediate_steps=[ + (AgentAction(tool="", tool_input="", log="exception"), "exception"), + (AgentAction(tool="", tool_input="", log="exception"), "exception"), + ], + ), + {}, + ) async def test_agent_reconstructs_conversation_with_failover(self): action = AgentAction(tool="fix", tool_input="validation error", log="exception") diff --git a/ee/hogai/graph/session_summaries/nodes.py b/ee/hogai/graph/session_summaries/nodes.py index 4d33fee929..8e5692256a 100644 --- a/ee/hogai/graph/session_summaries/nodes.py +++ b/ee/hogai/graph/session_summaries/nodes.py @@ -11,7 +11,6 @@ from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnableConfig from posthog.schema import ( - AssistantMessage, AssistantToolCallMessage, MaxRecordingUniversalFilters, NotebookUpdateMessage, @@ -70,11 +69,7 @@ class SessionSummarizationNode(AssistantNode): """Push summarization progress as reasoning messages""" content = prepare_reasoning_progress_message(progress_message) if content: - self.dispatcher.message( - AssistantMessage( - content=content, - ) - ) + self.dispatcher.update(content) async def _stream_notebook_content(self, content: dict, state: AssistantState, partial: bool = True) -> None: """Stream TipTap content directly to a notebook if notebook_id is present in state.""" @@ -202,7 +197,7 @@ class _SessionSearch: tool = await SearchSessionRecordingsTool.create_tool_class( team=self._node._team, user=self._node._user, - tool_call_id=self._node._parent_tool_call_id or "", + node_path=self._node.node_path, state=state, config=config, context_manager=self._node.context_manager, diff --git a/ee/hogai/graph/sql/nodes.py b/ee/hogai/graph/sql/nodes.py index eb9da64c9c..36d3840bf9 100644 --- a/ee/hogai/graph/sql/nodes.py +++ b/ee/hogai/graph/sql/nodes.py @@ -1,6 +1,6 @@ from langchain_core.runnables import RunnableConfig -from posthog.schema import AssistantHogQLQuery, AssistantMessage +from posthog.schema import AssistantHogQLQuery from posthog.hogql.context import HogQLContext @@ -25,7 +25,7 @@ class SQLGeneratorNode(HogQLGeneratorMixin, SchemaGeneratorNode[AssistantHogQLQu return AssistantNodeName.SQL_GENERATOR async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: - self.dispatcher.message(AssistantMessage(content="Creating SQL query")) + self.dispatcher.update("Creating SQL query") prompt = await self._construct_system_prompt() return await super()._run_with_prompt(state, prompt, config=config) diff --git a/ee/hogai/graph/taxonomy/agent.py b/ee/hogai/graph/taxonomy/agent.py index 3ae8a99dab..bfb7b4b01e 100644 --- a/ee/hogai/graph/taxonomy/agent.py +++ b/ee/hogai/graph/taxonomy/agent.py @@ -3,34 +3,43 @@ from typing import Generic from posthog.models import Team, User from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph.graph import BaseAssistantGraph +from ee.hogai.graph.base import BaseAssistantGraph from ee.hogai.utils.types import PartialStateType, StateType +from ee.hogai.utils.types.base import AssistantGraphName from .nodes import StateClassMixin, TaxonomyAgentNode, TaxonomyAgentToolsNode from .toolkit import TaxonomyAgentToolkit from .types import TaxonomyNodeName -class TaxonomyAgent(BaseAssistantGraph[StateType], Generic[StateType, PartialStateType], StateClassMixin): +class TaxonomyAgent( + BaseAssistantGraph[StateType, PartialStateType], Generic[StateType, PartialStateType], StateClassMixin +): """Taxonomy agent that can be configured with different node classes.""" def __init__( self, team: Team, user: User, - tool_call_id: str, loop_node_class: type["TaxonomyAgentNode"], tools_node_class: type["TaxonomyAgentToolsNode"], toolkit_class: type["TaxonomyAgentToolkit"], ): - # Extract the State type from the generic parameter - state_class, _ = self._get_state_class(TaxonomyAgent) - super().__init__(team, user, state_class, parent_tool_call_id=tool_call_id) - + super().__init__(team, user) self._loop_node_class = loop_node_class self._tools_node_class = tools_node_class self._toolkit_class = toolkit_class + @property + def state_type(self) -> type[StateType]: + # Extract the State type from the generic parameter + state_type, _ = self._get_state_class(TaxonomyAgent) + return state_type + + @property + def graph_name(self) -> AssistantGraphName: + return AssistantGraphName.TAXONOMY + def compile_full_graph(self, checkpointer: DjangoCheckpointer | None = None): """Compile a complete taxonomy graph.""" return self.add_taxonomy_generator().compile(checkpointer=checkpointer) diff --git a/ee/hogai/graph/taxonomy/nodes.py b/ee/hogai/graph/taxonomy/nodes.py index 327b1cbb48..1db0ef30d8 100644 --- a/ee/hogai/graph/taxonomy/nodes.py +++ b/ee/hogai/graph/taxonomy/nodes.py @@ -40,25 +40,10 @@ TaxonomyPartialStateType = TypeVar("TaxonomyPartialStateType", bound=TaxonomyAge TaxonomyNodeBound = BaseAssistantNode[TaxonomyStateType, TaxonomyPartialStateType] -class ParentToolCallIdMixin(BaseAssistantNode[TaxonomyStateType, TaxonomyPartialStateType]): - _parent_tool_call_id: str | None = None - _toolkit: TaxonomyAgentToolkit - - async def __call__(self, state: TaxonomyStateType, config: RunnableConfig) -> TaxonomyPartialStateType | None: - """ - Run the assistant node and handle cancelled conversation before the node is run. - """ - if self._parent_tool_call_id: - self._toolkit._parent_tool_call_id = self._parent_tool_call_id - - return await super().__call__(state, config) - - class TaxonomyAgentNode( Generic[TaxonomyStateType, TaxonomyPartialStateType], StateClassMixin, TaxonomyUpdateDispatcherNodeMixin, - ParentToolCallIdMixin, TaxonomyNodeBound, ABC, ): @@ -173,7 +158,6 @@ class TaxonomyAgentToolsNode( Generic[TaxonomyStateType, TaxonomyPartialStateType], StateClassMixin, TaxonomyUpdateDispatcherNodeMixin, - ParentToolCallIdMixin, TaxonomyNodeBound, ): """Base tools node for taxonomy agents.""" diff --git a/ee/hogai/graph/taxonomy/test/test_agent.py b/ee/hogai/graph/taxonomy/test/test_agent.py index cb0551a864..23eaded165 100644 --- a/ee/hogai/graph/taxonomy/test/test_agent.py +++ b/ee/hogai/graph/taxonomy/test/test_agent.py @@ -36,14 +36,13 @@ class TestTaxonomyAgent(BaseTest): self.mock_graph = Mock() # Patch StateGraph in the parent class where it's actually used - self.patcher = patch("ee.hogai.graph.graph.StateGraph") + self.patcher = patch("ee.hogai.graph.base.graph.StateGraph") mock_state_graph_class = self.patcher.start() mock_state_graph_class.return_value = self.mock_graph self.agent = ConcreteTaxonomyAgent( team=self.team, user=self.user, - tool_call_id="test_tool_call_id", loop_node_class=MockTaxonomyAgentNode, tools_node_class=MockTaxonomyAgentToolsNode, toolkit_class=MockTaxonomyAgentToolkit, @@ -75,7 +74,6 @@ class TestTaxonomyAgent(BaseTest): NonGenericAgent( team=self.team, user=self.user, - tool_call_id="test_tool_call_id", loop_node_class=MockTaxonomyAgentNode, tools_node_class=MockTaxonomyAgentToolsNode, toolkit_class=MockTaxonomyAgentToolkit, diff --git a/ee/hogai/graph/taxonomy/toolkit.py b/ee/hogai/graph/taxonomy/toolkit.py index 5ccde1c15c..676a3bb12b 100644 --- a/ee/hogai/graph/taxonomy/toolkit.py +++ b/ee/hogai/graph/taxonomy/toolkit.py @@ -122,10 +122,6 @@ class TaxonomyTaskExecutorNode( Task executor node specifically for taxonomy operations. """ - def __init__(self, team: Team, user: User, parent_tool_call_id: str | None): - super().__init__(team, user) - self._parent_tool_call_id = parent_tool_call_id - @property def node_name(self) -> MaxNodeName: return TaxonomyNodeName.TASK_EXECUTOR @@ -148,8 +144,6 @@ class TaxonomyTaskExecutorNode( class TaxonomyAgentToolkit: """Base toolkit for taxonomy agents that handle tool execution.""" - _parent_tool_call_id: str | None - def __init__(self, team: Team, user: User): self._team = team self._user = user @@ -391,7 +385,7 @@ class TaxonomyAgentToolkit: ) ) message = AssistantMessage(content="", id=str(uuid4()), tool_calls=tool_calls) - executor = TaxonomyTaskExecutorNode(self._team, self._user, parent_tool_call_id=self._parent_tool_call_id) + executor = TaxonomyTaskExecutorNode(self._team, self._user) result = await executor.arun(AssistantState(messages=[message]), RunnableConfig()) final_result = {} @@ -651,7 +645,7 @@ class TaxonomyAgentToolkit: for event_name_or_action_id in event_name_or_action_ids ] message = AssistantMessage(content="", id=str(uuid4()), tool_calls=tool_calls) - executor = TaxonomyTaskExecutorNode(self._team, self._user, parent_tool_call_id=self._parent_tool_call_id) + executor = TaxonomyTaskExecutorNode(self._team, self._user) result = await executor.arun(AssistantState(messages=[message]), RunnableConfig()) return {task_result.id: task_result.result for task_result in result.task_results} diff --git a/ee/hogai/graph/test/test_assistant_graph.py b/ee/hogai/graph/test/test_assistant_graph.py deleted file mode 100644 index bd2a144b02..0000000000 --- a/ee/hogai/graph/test/test_assistant_graph.py +++ /dev/null @@ -1,29 +0,0 @@ -from posthog.test.base import BaseTest - -from langchain_core.runnables import RunnableLambda -from langgraph.checkpoint.memory import InMemorySaver - -from ee.hogai.graph.graph import BaseAssistantGraph -from ee.hogai.utils.types import AssistantNodeName, AssistantState, PartialAssistantState - - -class TestAssistantGraph(BaseTest): - async def test_pydantic_state_resets_with_none(self): - """When a None field is set, it should be reset to None.""" - - async def runnable(state: AssistantState) -> PartialAssistantState: - return PartialAssistantState(start_id=None) - - graph = BaseAssistantGraph(self.team, self.user, state_type=AssistantState) - compiled_graph = ( - graph.add_node(AssistantNodeName.ROOT, RunnableLambda(runnable)) - .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) - .compile(checkpointer=InMemorySaver()) - ) - state = await compiled_graph.ainvoke( - AssistantState(messages=[], graph_status="resumed", start_id=None), - {"configurable": {"thread_id": "test"}}, - ) - self.assertEqual(state["start_id"], None) - self.assertEqual(state["graph_status"], "resumed") diff --git a/ee/hogai/graph/test/test_dispatcher_integration.py b/ee/hogai/graph/test/test_dispatcher_integration.py index db8c36240f..2687579a1b 100644 --- a/ee/hogai/graph/test/test_dispatcher_integration.py +++ b/ee/hogai/graph/test/test_dispatcher_integration.py @@ -4,8 +4,7 @@ Integration tests for dispatcher usage in BaseAssistantNode and graph execution. These tests ensure that the dispatcher pattern works correctly end-to-end in real graph execution. """ -import uuid -from typing import Any +from typing import cast from posthog.test.base import BaseTest from unittest.mock import MagicMock, patch @@ -14,30 +13,40 @@ from langchain_core.runnables import RunnableConfig from posthog.schema import AssistantMessage -from ee.hogai.graph.base import BaseAssistantNode -from ee.hogai.utils.dispatcher import MessageAction, NodeStartAction -from ee.hogai.utils.types import AssistantNodeName -from ee.hogai.utils.types.base import AssistantDispatcherEvent, AssistantState, PartialAssistantState +from ee.hogai.graph.base.node import BaseAssistantNode +from ee.hogai.utils.types.base import ( + AssistantDispatcherEvent, + AssistantGraphName, + AssistantNodeName, + AssistantState, + MessageAction, + NodeEndAction, + NodePath, + NodeStartAction, + PartialAssistantState, + UpdateAction, +) -class MockAssistantNode(BaseAssistantNode): +class MockAssistantNode(BaseAssistantNode[AssistantState, PartialAssistantState]): """Mock node for testing dispatcher integration.""" - def __init__(self, team, user): - super().__init__(team, user) + def __init__(self, team, user, node_path=None): + super().__init__(team, user, node_path) self.arun_called = False self.messages_dispatched = [] @property - def node_name(self) -> AssistantNodeName: + def node_name(self) -> str: return AssistantNodeName.ROOT - async def arun(self, state, config: RunnableConfig) -> PartialAssistantState: + async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: self.arun_called = True # Simulate dispatching messages during execution - self.dispatcher.message(AssistantMessage(content="Processing...")) - self.dispatcher.message(AssistantMessage(content="Done!")) + self.dispatcher.update("Processing...") + self.dispatcher.message(AssistantMessage(content="Intermediate result")) + self.dispatcher.update("Done!") return PartialAssistantState(messages=[AssistantMessage(content="Final result")]) @@ -57,147 +66,169 @@ class TestDispatcherIntegration(BaseTest): node = MockAssistantNode(self.mock_team, self.mock_user) state = AssistantState(messages=[]) - config = RunnableConfig() + config = RunnableConfig(metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_1"}) - await node.arun(state, config) + with patch("ee.hogai.utils.dispatcher.get_stream_writer", side_effect=RuntimeError("Not streaming")): + await node(state, config) self.assertTrue(node.arun_called) self.assertIsNotNone(node.dispatcher) + async def test_node_path_propagation(self): + """Test that node_path is correctly set and propagated.""" + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT), + ) + + node = MockAssistantNode(self.mock_team, self.mock_user, node_path=node_path) + + self.assertEqual(node.node_path, node_path) + + async def test_dispatcher_dispatches_node_start_and_end(self): + """Test that NODE_START and NODE_END actions are dispatched.""" + node = MockAssistantNode(self.mock_team, self.mock_user) + + state = AssistantState(messages=[]) + config = RunnableConfig(metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_2"}) + + dispatched_actions = [] + + def capture_write(event): + if isinstance(event, AssistantDispatcherEvent): + dispatched_actions.append(event) + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write): + await node(state, config) + + # Should have dispatched actions in this order: + # 1. NODE_START + # 2. UpdateAction ("Processing...") + # 3. MessageAction (intermediate) + # 4. UpdateAction ("Done!") + # 5. NODE_END with final state + self.assertGreater(len(dispatched_actions), 0) + + # Verify NODE_START is first + self.assertIsInstance(dispatched_actions[0].action, NodeStartAction) + + # Verify NODE_END is last + last_action = dispatched_actions[-1].action + self.assertIsInstance(last_action, NodeEndAction) + self.assertIsNotNone(cast(NodeEndAction, last_action).state) + async def test_messages_dispatched_during_node_execution(self): """Test that messages dispatched during node execution are sent to writer.""" node = MockAssistantNode(self.mock_team, self.mock_user) state = AssistantState(messages=[]) - config = RunnableConfig() + config = RunnableConfig(metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_3"}) dispatched_actions = [] - def capture_write(update: Any): - dispatched_actions.append(update) + def capture_write(event: AssistantDispatcherEvent): + dispatched_actions.append(event) - # Mock get_stream_writer to return our test writer - with patch("ee.hogai.graph.base.get_stream_writer", return_value=capture_write): - # Call the node (not arun) to trigger __call__ which handles dispatching + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write): await node(state, config) - # Should have: - # 1. NODE_START from __call__ - # 2. Two MESSAGE actions from arun (Processing..., Done!) - # 3. One MESSAGE action from returned state (Final result) + # Find the update and message actions (excluding NODE_START and NODE_END) + update_actions = [e for e in dispatched_actions if isinstance(e.action, UpdateAction)] + message_actions = [e for e in dispatched_actions if isinstance(e.action, MessageAction)] - self.assertEqual(len(dispatched_actions), 4) - self.assertIsInstance(dispatched_actions[0], AssistantDispatcherEvent) - self.assertIsInstance(dispatched_actions[0].action, NodeStartAction) - self.assertIsInstance(dispatched_actions[1], AssistantDispatcherEvent) - self.assertIsInstance(dispatched_actions[1].action, MessageAction) - self.assertEqual(dispatched_actions[1].action.message.content, "Processing...") - self.assertIsInstance(dispatched_actions[2], AssistantDispatcherEvent) - self.assertIsInstance(dispatched_actions[2].action, MessageAction) - self.assertEqual(dispatched_actions[2].action.message.content, "Done!") - self.assertIsInstance(dispatched_actions[3], AssistantDispatcherEvent) - self.assertIsInstance(dispatched_actions[3].action, MessageAction) - self.assertEqual(dispatched_actions[3].action.message.content, "Final result") + # Should have 2 updates: "Processing..." and "Done!" + self.assertEqual(len(update_actions), 2) + self.assertEqual(cast(UpdateAction, update_actions[0].action).content, "Processing...") + self.assertEqual(cast(UpdateAction, update_actions[1].action).content, "Done!") - async def test_node_start_action_dispatched(self): - """Test that NODE_START action is dispatched at node entry.""" + # Should have 1 message: intermediate (final message is in NODE_END state, not dispatched separately) + self.assertEqual(len(message_actions), 1) + msg = cast(MessageAction, message_actions[0].action).message + self.assertEqual(cast(AssistantMessage, msg).content, "Intermediate result") + + async def test_node_path_included_in_dispatched_events(self): + """Test that node_path is included in all dispatched events.""" + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT), + ) + + node = MockAssistantNode(self.mock_team, self.mock_user, node_path=node_path) + + state = AssistantState(messages=[]) + config = RunnableConfig(metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_4"}) + + dispatched_events = [] + + def capture_write(event: AssistantDispatcherEvent): + dispatched_events.append(event) + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write): + await node(state, config) + + # Verify all events have the correct node_path + for event in dispatched_events: + self.assertEqual(event.node_path, node_path) + + async def test_node_run_id_included_in_dispatched_events(self): + """Test that node_run_id is included in all dispatched events.""" node = MockAssistantNode(self.mock_team, self.mock_user) state = AssistantState(messages=[]) - config = RunnableConfig() + checkpoint_ns = "checkpoint_xyz_789" + config = RunnableConfig( + metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": checkpoint_ns} + ) - dispatched_actions = [] + dispatched_events = [] - def capture_write(update): - if isinstance(update, AssistantDispatcherEvent): - dispatched_actions.append(update.action) + def capture_write(event: AssistantDispatcherEvent): + dispatched_events.append(event) - with patch("ee.hogai.graph.base.get_stream_writer", return_value=capture_write): + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write): await node(state, config) - # Should have at least one NODE_START action - from ee.hogai.utils.dispatcher import NodeStartAction + # Verify all events have the correct node_run_id + for event in dispatched_events: + self.assertEqual(event.node_run_id, checkpoint_ns) - node_start_actions = [action for action in dispatched_actions if isinstance(action, NodeStartAction)] - self.assertGreater(len(node_start_actions), 0) - - @patch("ee.hogai.graph.base.get_stream_writer") - async def test_parent_tool_call_id_propagation(self, mock_get_stream_writer): - """Test that parent_tool_call_id is propagated to dispatched messages.""" - parent_tool_call_id = str(uuid.uuid4()) - - class NodeWithParent(BaseAssistantNode): - @property - def node_name(self): - return AssistantNodeName.ROOT - - async def arun(self, state, config: RunnableConfig) -> PartialAssistantState: - # Dispatch message - should inherit parent_tool_call_id from state - self.dispatcher.message(AssistantMessage(content="Child message")) - return PartialAssistantState(messages=[]) - - node = NodeWithParent(self.mock_team, self.mock_user) - - state = {"messages": [], "parent_tool_call_id": parent_tool_call_id} - config = RunnableConfig() - - dispatched_messages = [] - - def capture_write(update): - if isinstance(update, AssistantDispatcherEvent) and isinstance(update.action, MessageAction): - dispatched_messages.append(update.action.message) - - mock_get_stream_writer.return_value = capture_write - - await node.arun(state, config) - - # Verify dispatched messages have parent_tool_call_id - assistant_messages = [msg for msg in dispatched_messages if isinstance(msg, AssistantMessage)] - for msg in assistant_messages: - # If the implementation propagates it, this should be true - # Otherwise this test will help catch that as a potential issue - if msg.parent_tool_call_id: - self.assertEqual(msg.parent_tool_call_id, parent_tool_call_id) - - @patch("ee.hogai.graph.base.get_stream_writer") - async def test_dispatcher_error_handling(self, mock_get_stream_writer): + async def test_dispatcher_error_handling_does_not_crash_node(self): """Test that errors in dispatcher don't crash node execution.""" - class FailingDispatcherNode(BaseAssistantNode): + class FailingDispatcherNode(BaseAssistantNode[AssistantState, PartialAssistantState]): @property def node_name(self): return AssistantNodeName.ROOT - async def arun(self, state, config: RunnableConfig) -> PartialAssistantState: + async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: # Try to dispatch - if writer fails, should handle gracefully - self.dispatcher.message(AssistantMessage(content="Test")) + self.dispatcher.update("Test") return PartialAssistantState(messages=[AssistantMessage(content="Result")]) node = FailingDispatcherNode(self.mock_team, self.mock_user) state = AssistantState(messages=[]) - config = RunnableConfig() + config = RunnableConfig(metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_5"}) # Make writer raise an error def failing_writer(data): raise RuntimeError("Writer failed") - mock_get_stream_writer.return_value = failing_writer + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=failing_writer): + # Should not crash - node should complete + result = await node(state, config) + self.assertIsNotNone(result) - # Should not crash - node should complete - result = await node.arun(state, config) - self.assertIsNotNone(result) + async def test_messages_in_partial_state_dispatched_via_node_end(self): + """Test that messages in PartialState are dispatched via NODE_END.""" - async def test_messages_in_partial_state_are_auto_dispatched(self): - """Test that messages in PartialState are automatically dispatched.""" - - class NodeReturningMessages(BaseAssistantNode): + class NodeReturningMessages(BaseAssistantNode[AssistantState, PartialAssistantState]): @property def node_name(self): return AssistantNodeName.ROOT - async def arun(self, state, config: RunnableConfig) -> PartialAssistantState: - # Return messages in state - should be auto-dispatched + async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: + # Return messages in state return PartialAssistantState( messages=[ AssistantMessage(content="Message 1"), @@ -208,39 +239,139 @@ class TestDispatcherIntegration(BaseTest): node = NodeReturningMessages(self.mock_team, self.mock_user) state = AssistantState(messages=[]) - config = RunnableConfig() + config = RunnableConfig(metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_6"}) - dispatched_messages = [] + dispatched_events = [] - def capture_write(update): - if isinstance(update, AssistantDispatcherEvent) and isinstance(update.action, MessageAction): - dispatched_messages.append(update.action.message) + def capture_write(event: AssistantDispatcherEvent): + dispatched_events.append(event) - with patch("ee.hogai.graph.base.get_stream_writer", return_value=capture_write): + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write): await node(state, config) - # Should have dispatched the messages from PartialState (and NODE_START) - # We expect at least 2 message actions (Message 1 and Message 2) - self.assertGreaterEqual(len(dispatched_messages), 2) + # Should have NODE_END action with state containing messages + node_end_actions = [e for e in dispatched_events if isinstance(e.action, NodeEndAction)] + self.assertEqual(len(node_end_actions), 1) + + node_end_state = cast(NodeEndAction, node_end_actions[0].action).state + self.assertIsNotNone(node_end_state) + assert node_end_state is not None + self.assertEqual(len(node_end_state.messages), 2) async def test_node_returns_none_state_handling(self): """Test that node can return None state without errors.""" - class NoneStateNode(BaseAssistantNode): + class NoneStateNode(BaseAssistantNode[AssistantState, PartialAssistantState]): @property def node_name(self): return AssistantNodeName.ROOT - async def arun(self, state, config: RunnableConfig) -> None: + async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState | None: # Dispatch a message but return None state - self.dispatcher.message(AssistantMessage(content="Test")) + self.dispatcher.update("Test") return None node = NoneStateNode(self.mock_team, self.mock_user) state = AssistantState(messages=[]) - config = RunnableConfig() + config = RunnableConfig(metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_7"}) - result = await node(state, config) - # Should handle None gracefully - self.assertIsNone(result) + with patch("ee.hogai.utils.dispatcher.get_stream_writer", side_effect=RuntimeError("Not streaming")): + result = await node(state, config) + # Should handle None gracefully + self.assertIsNone(result) + + async def test_nested_node_path_in_dispatched_events(self): + """Test that nested nodes have correct node_path.""" + # Simulate a nested node path (e.g., from a tool call) + parent_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id="msg_123", tool_call_id="tc_123"), + NodePath(name=AssistantGraphName.INSIGHTS), + ) + + node = MockAssistantNode(self.mock_team, self.mock_user, node_path=parent_path) + + state = AssistantState(messages=[]) + config = RunnableConfig( + metadata={"langgraph_node": AssistantNodeName.TRENDS_GENERATOR, "langgraph_checkpoint_ns": "cp_8"} + ) + + dispatched_events = [] + + def capture_write(event: AssistantDispatcherEvent): + dispatched_events.append(event) + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write): + await node(state, config) + + # Verify all events have the nested path + for event in dispatched_events: + self.assertIsNotNone(event.node_path) + assert event.node_path is not None + self.assertEqual(event.node_path, parent_path) + self.assertEqual(len(event.node_path), 3) + self.assertEqual(event.node_path[1].message_id, "msg_123") + self.assertEqual(event.node_path[1].tool_call_id, "tc_123") + + async def test_update_actions_include_node_metadata(self): + """Test that update actions include correct node metadata.""" + node = MockAssistantNode(self.mock_team, self.mock_user) + + state = AssistantState(messages=[]) + config = RunnableConfig(metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_9"}) + + dispatched_events = [] + + def capture_write(event: AssistantDispatcherEvent): + dispatched_events.append(event) + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write): + await node(state, config) + + # Find update actions + update_events = [e for e in dispatched_events if isinstance(e.action, UpdateAction)] + + for event in update_events: + self.assertEqual(event.node_name, AssistantNodeName.ROOT) + self.assertEqual(event.node_run_id, "cp_9") + self.assertIsNotNone(event.node_path) + + async def test_concurrent_node_executions_independent_dispatchers(self): + """Test that concurrent node executions use independent dispatchers.""" + node1 = MockAssistantNode(self.mock_team, self.mock_user) + node2 = MockAssistantNode(self.mock_team, self.mock_user) + + state = AssistantState(messages=[]) + config1 = RunnableConfig( + metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_10a"} + ) + config2 = RunnableConfig( + metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "cp_10b"} + ) + + events1 = [] + events2 = [] + + def capture_write1(event: AssistantDispatcherEvent): + events1.append(event) + + def capture_write2(event: AssistantDispatcherEvent): + events2.append(event) + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write1): + await node1(state, config1) + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=capture_write2): + await node2(state, config2) + + # Verify events went to separate lists + self.assertGreater(len(events1), 0) + self.assertGreater(len(events2), 0) + + # Verify node_run_ids are different + for event in events1: + self.assertEqual(event.node_run_id, "cp_10a") + + for event in events2: + self.assertEqual(event.node_run_id, "cp_10b") diff --git a/ee/hogai/graph/trends/nodes.py b/ee/hogai/graph/trends/nodes.py index cb11eb2ba7..6034a7ef58 100644 --- a/ee/hogai/graph/trends/nodes.py +++ b/ee/hogai/graph/trends/nodes.py @@ -1,7 +1,7 @@ from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnableConfig -from posthog.schema import AssistantMessage, AssistantTrendsQuery +from posthog.schema import AssistantTrendsQuery from ee.hogai.utils.types import AssistantState from ee.hogai.utils.types.base import AssistantNodeName, PartialAssistantState @@ -25,7 +25,7 @@ class TrendsGeneratorNode(SchemaGeneratorNode[AssistantTrendsQuery]): return AssistantNodeName.TRENDS_GENERATOR async def arun(self, state: AssistantState, config: RunnableConfig) -> PartialAssistantState: - self.dispatcher.message(AssistantMessage(content="Creating trends query")) + self.dispatcher.update("Creating trends query") prompt = ChatPromptTemplate.from_messages( [ ("system", TRENDS_SYSTEM_PROMPT), diff --git a/ee/hogai/test/test_assistant.py b/ee/hogai/test/test_assistant.py index 588ba4d2ae..ccdf8e00df 100644 --- a/ee/hogai/test/test_assistant.py +++ b/ee/hogai/test/test_assistant.py @@ -9,7 +9,7 @@ from posthog.test.base import ( _create_person, flush_persons_and_events, ) -from unittest.mock import AsyncMock, patch +from unittest.mock import AsyncMock, MagicMock, patch from django.test import override_settings @@ -61,13 +61,13 @@ from posthog.models import Action from ee.hogai.assistant.base import BaseAssistant from ee.hogai.django_checkpoint.checkpointer import DjangoCheckpointer -from ee.hogai.graph.base import BaseAssistantNode +from ee.hogai.graph.base import AssistantNode from ee.hogai.graph.funnels.nodes import FunnelsSchemaGeneratorOutput +from ee.hogai.graph.insights_graph.graph import InsightsGraph from ee.hogai.graph.memory import prompts as memory_prompts from ee.hogai.graph.retention.nodes import RetentionSchemaGeneratorOutput from ee.hogai.graph.root.nodes import SLASH_COMMAND_INIT from ee.hogai.graph.trends.nodes import TrendsSchemaGeneratorOutput -from ee.hogai.utils.state import GraphValueUpdateTuple from ee.hogai.utils.tests import FakeAnthropicRunnableLambdaWithTokenCounter, FakeChatAnthropic, FakeChatOpenAI from ee.hogai.utils.types import ( AssistantMode, @@ -76,16 +76,21 @@ from ee.hogai.utils.types import ( AssistantState, PartialAssistantState, ) +from ee.hogai.utils.types.base import ReplaceMessages from ee.models.assistant import Conversation, CoreMemory from ..assistant import Assistant -from ..graph import AssistantGraph, InsightsAssistantGraph +from ..graph.graph import AssistantGraph title_generator_mock = patch( "ee.hogai.graph.title_generator.nodes.TitleGeneratorNode._model", return_value=FakeChatOpenAI(responses=[messages.AIMessage(content="Title")]), ) +query_executor_mock = patch( + "ee.hogai.graph.query_executor.nodes.QueryExecutorNode._format_query_result", new=MagicMock(return_value="Result") +) + class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): CLASS_DATA_LEVEL_SETUP = False @@ -118,7 +123,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ), ).start() - self.checkpointer_patch = patch("ee.hogai.graph.graph.global_checkpointer", new=DjangoCheckpointer()) + self.checkpointer_patch = patch("ee.hogai.graph.base.graph.global_checkpointer", new=DjangoCheckpointer()) self.checkpointer_patch.start() def tearDown(self): @@ -232,14 +237,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): graph = ( AssistantGraph(self.team, self.user) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "insights": AssistantNodeName.INSIGHTS_SUBGRAPH, - "root": AssistantNodeName.ROOT, - "end": AssistantNodeName.END, - } - ) - .add_insights(AssistantNodeName.ROOT) + .add_root() .compile() ) @@ -269,7 +267,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): { "id": "1", "name": "create_and_query_insight", - "args": {"query_description": "Foobar", "query_kind": insight_type}, + "args": {"query_description": "Foobar"}, } ], ) @@ -302,7 +300,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): AssistantToolCall( id="1", name="create_and_query_insight", - args={"query_description": "Foobar", "query_kind": insight_type}, + args={"query_description": "Foobar"}, ) ], ), @@ -327,12 +325,12 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): snapshot: StateSnapshot = await graph.aget_state(config) self.assertFalse(snapshot.next) self.assertFalse(snapshot.values.get("intermediate_steps")) - self.assertFalse(snapshot.values["plan"]) - self.assertFalse(snapshot.values["graph_status"]) - self.assertFalse(snapshot.values["root_tool_call_id"]) - self.assertFalse(snapshot.values["root_tool_insight_plan"]) - self.assertFalse(snapshot.values["root_tool_insight_type"]) - self.assertFalse(snapshot.values["root_tool_calls_count"]) + self.assertFalse(snapshot.values.get("plan")) + self.assertFalse(snapshot.values.get("graph_status")) + self.assertFalse(snapshot.values.get("root_tool_call_id")) + self.assertFalse(snapshot.values.get("root_tool_insight_plan")) + self.assertFalse(snapshot.values.get("root_tool_insight_type")) + self.assertFalse(snapshot.values.get("root_tool_calls_count")) async def test_trends_interrupt_when_asking_for_help(self): await self._test_human_in_the_loop("trends") @@ -345,7 +343,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): async def test_ai_messages_appended_after_interrupt(self): with patch("ee.hogai.graph.query_planner.nodes.QueryPlannerNode._get_model") as mock: - graph = InsightsAssistantGraph(self.team, self.user).compile_full_graph() + graph = InsightsGraph(self.team, self.user).compile_full_graph() config: RunnableConfig = { "configurable": { "thread_id": self.conversation.id, @@ -441,16 +439,13 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): self.assertIsInstance(output[1][1], FailureMessage) async def test_new_conversation_handles_serialized_conversation(self): - from ee.hogai.graph.base import BaseAssistantNode - - class TestNode(BaseAssistantNode): + class TestNode(AssistantNode): @property def node_name(self): return AssistantNodeName.ROOT async def arun(self, state, config): - self.dispatcher.message(AssistantMessage(content="Hello")) - return PartialAssistantState() + return PartialAssistantState(messages=[AssistantMessage(content="Hello", id=str(uuid4()))]) test_node = TestNode(self.team, self.user) graph = ( @@ -478,16 +473,13 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): self.assertNotEqual(output[0][0], "conversation") async def test_async_stream(self): - from ee.hogai.graph.base import BaseAssistantNode - - class TestNode(BaseAssistantNode): + class TestNode(AssistantNode): @property def node_name(self): return AssistantNodeName.ROOT async def arun(self, state, config): - self.dispatcher.message(AssistantMessage(content="bar")) - return PartialAssistantState() + return PartialAssistantState(messages=[AssistantMessage(content="bar", id=str(uuid4()))]) test_node = TestNode(self.team, self.user) graph = ( @@ -517,12 +509,13 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): self.assertConversationEqual(actual_output, expected_output) async def test_async_stream_handles_exceptions(self): - def node_handler(state): - raise ValueError() + class NodeHandler(AssistantNode): + async def arun(self, state, config): + raise ValueError graph = ( AssistantGraph(self.team, self.user) - .add_node(AssistantNodeName.ROOT, node_handler) + .add_node(AssistantNodeName.ROOT, NodeHandler(self.team, self.user)) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) .add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) .compile() @@ -536,12 +529,11 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ("message", HumanMessage(content="foo")), ("message", FailureMessage()), ] - actual_output = [] - async for event in assistant.astream(): - actual_output.append(event) + actual_output, _ = await self._run_assistant_graph(graph, message="foo") self.assertConversationEqual(actual_output, expected_output) @title_generator_mock + @query_executor_mock @patch("ee.hogai.graph.schema_generator.nodes.SchemaGeneratorNode._model") @patch("ee.hogai.graph.query_planner.nodes.QueryPlannerNode._get_model") @patch("ee.hogai.graph.root.nodes.RootNode._get_model") @@ -556,7 +548,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): { "id": "xyz", "name": "create_and_query_insight", - "args": {"query_description": "Foobar", "query_kind": "trends"}, + "args": {"query_description": "Foobar"}, } ], ) @@ -596,7 +588,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): AssistantToolCall( id="xyz", name="create_and_query_insight", - args={"query_description": "Foobar", "query_kind": "trends"}, + args={"query_description": "Foobar"}, ) ], ), @@ -611,7 +603,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ), ("update", AssistantUpdateEvent(id="message_2", tool_call_id="xyz", content="Creating trends query")), ("message", VisualizationMessage(query="Foobar", answer=query, plan="Plan")), - ("message", {"tool_call_id": "xyz", "type": "tool"}), # Don't check content as it's implementation detail + ("message", AssistantToolCallMessage(tool_call_id="xyz", content="Result")), ("message", AssistantMessage(content="The results indicate a great future for you.")), ] self.assertConversationEqual(actual_output, expected_output) @@ -634,6 +626,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ) @title_generator_mock + @query_executor_mock @patch("ee.hogai.graph.schema_generator.nodes.SchemaGeneratorNode._model") @patch("ee.hogai.graph.query_planner.nodes.QueryPlannerNode._get_model") @patch("ee.hogai.graph.root.nodes.RootNode._get_model") @@ -648,7 +641,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): { "id": "xyz", "name": "create_and_query_insight", - "args": {"query_description": "Foobar", "query_kind": "funnel"}, + "args": {"query_description": "Foobar"}, } ], ) @@ -693,7 +686,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): AssistantToolCall( id="xyz", name="create_and_query_insight", - args={"query_description": "Foobar", "query_kind": "funnel"}, + args={"query_description": "Foobar"}, ) ], ), @@ -708,7 +701,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ), ("update", AssistantUpdateEvent(id="message_2", tool_call_id="xyz", content="Creating funnel query")), ("message", VisualizationMessage(query="Foobar", answer=query, plan="Plan")), - ("message", {"tool_call_id": "xyz", "type": "tool"}), # Don't check content as it's implementation detail + ("message", AssistantToolCallMessage(tool_call_id="xyz", content="Result")), ("message", AssistantMessage(content="The results indicate a great future for you.")), ] self.assertConversationEqual(actual_output, expected_output) @@ -731,6 +724,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ) @title_generator_mock + @query_executor_mock @patch("ee.hogai.graph.schema_generator.nodes.SchemaGeneratorNode._model") @patch("ee.hogai.graph.query_planner.nodes.QueryPlannerNode._get_model") @patch("ee.hogai.graph.root.nodes.RootNode._get_model") @@ -747,7 +741,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): { "id": "xyz", "name": "create_and_query_insight", - "args": {"query_description": "Foobar", "query_kind": "retention"}, + "args": {"query_description": "Foobar"}, } ], ) @@ -792,7 +786,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): AssistantToolCall( id="xyz", name="create_and_query_insight", - args={"query_description": "Foobar", "query_kind": "retention"}, + args={"query_description": "Foobar"}, ) ], ), @@ -807,7 +801,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ), ("update", AssistantUpdateEvent(id="message_2", tool_call_id="xyz", content="Creating retention query")), ("message", VisualizationMessage(query="Foobar", answer=query, plan="Plan")), - ("message", {"tool_call_id": "xyz", "type": "tool"}), # Don't check content as it's implementation detail + ("message", AssistantToolCallMessage(tool_call_id="xyz", content="Result")), ("message", AssistantMessage(content="The results indicate a great future for you.")), ] self.assertConversationEqual(actual_output, expected_output) @@ -830,6 +824,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ) @title_generator_mock + @query_executor_mock @patch("ee.hogai.graph.schema_generator.nodes.SchemaGeneratorNode._model") @patch("ee.hogai.graph.query_planner.nodes.QueryPlannerNode._get_model") @patch("ee.hogai.graph.root.nodes.RootNode._get_model") @@ -844,7 +839,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): { "id": "xyz", "name": "create_and_query_insight", - "args": {"query_description": "Foobar", "query_kind": "sql"}, + "args": {"query_description": "Foobar"}, } ], ) @@ -883,7 +878,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): AssistantToolCall( id="xyz", name="create_and_query_insight", - args={"query_description": "Foobar", "query_kind": "sql"}, + args={"query_description": "Foobar"}, ) ], ), @@ -898,7 +893,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ), ("update", AssistantUpdateEvent(id="message_2", tool_call_id="xyz", content="Creating SQL query")), ("message", VisualizationMessage(query="Foobar", answer=query, plan="Plan")), - ("message", {"tool_call_id": "xyz", "type": "tool"}), # Don't check content as it's implementation detail + ("message", AssistantToolCallMessage(tool_call_id="xyz", content="Result")), ("message", AssistantMessage(content="The results indicate a great future for you.")), ] self.assertConversationEqual(actual_output, expected_output) @@ -1096,7 +1091,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): { "id": str(uuid4()), "name": "create_and_query_insight", - "args": {"query_description": "Foobar", "query_kind": "trends"}, + "args": {"query_description": "Foobar"}, } ], ) @@ -1138,7 +1133,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): graph = ( AssistantGraph(self.team, self.user) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root({"root": AssistantNodeName.ROOT, "end": AssistantNodeName.END}) + .add_root() .compile() ) self.assertEqual(self.conversation.status, Conversation.Status.IDLE) @@ -1158,7 +1153,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): graph = ( AssistantGraph(self.team, self.user) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root({"root": AssistantNodeName.ROOT, "end": AssistantNodeName.END}) + .add_root() .compile() ) @@ -1177,7 +1172,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): { "id": "1", "name": "create_and_query_insight", - "args": {"query_description": "Foobar", "query_kind": "trends"}, + "args": {"query_description": "Foobar"}, } ], ) @@ -1209,14 +1204,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): graph = ( AssistantGraph(self.team, self.user) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "search_documentation": AssistantNodeName.INKEEP_DOCS, - "root": AssistantNodeName.ROOT, - "end": AssistantNodeName.END, - } - ) - .add_inkeep_docs() + .add_root() .compile() ) @@ -1235,45 +1223,25 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): self.assertConversationEqual( output, [ - ( - "message", - HumanMessage( - content="How do I use feature flags?", - id="d93b3d57-2ff3-4c63-8635-8349955b16f0", - parent_tool_call_id=None, - type="human", - ui_context=None, - ), - ), + ("message", HumanMessage(content="How do I use feature flags?")), ( "message", AssistantMessage( content="", - id="ea1f4faf-85b4-4d98-b044-842b7092ba5d", - meta=None, - parent_tool_call_id=None, tool_calls=[ AssistantToolCall( args={"kind": "docs", "query": "test"}, id="1", name="search", type="tool_call" ) ], - type="ai", ), ), ( "update", - AssistantUpdateEvent(id="message_2", tool_call_id="1", content="Checking PostHog documentation..."), + AssistantUpdateEvent(content="Checking PostHog documentation...", id="1", tool_call_id="1"), ), ( "message", - AssistantToolCallMessage( - content="Checking PostHog documentation...", - id="00149847-0bcd-4b7c-a514-bab176312ae8", - parent_tool_call_id=None, - tool_call_id="1", - type="tool", - ui_payload=None, - ), + AssistantToolCallMessage(content="Checking PostHog documentation...", tool_call_id="1"), ), ( "message", @@ -1283,12 +1251,10 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ) @title_generator_mock + @query_executor_mock @patch("ee.hogai.graph.schema_generator.nodes.SchemaGeneratorNode._model") @patch("ee.hogai.graph.query_planner.nodes.QueryPlannerNode._get_model") - @patch("ee.hogai.graph.graph.QueryExecutorNode") - async def test_insights_tool_mode_flow( - self, query_executor_mock, planner_mock, generator_mock, title_generator_mock - ): + async def test_insights_tool_mode_flow(self, planner_mock, generator_mock, title_generator_mock): """Test that the insights tool mode works correctly.""" query = AssistantTrendsQuery(series=[]) tool_call_id = str(uuid4()) @@ -1315,25 +1281,6 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ) generator_mock.return_value = RunnableLambda(lambda _: TrendsSchemaGeneratorOutput(query=query)) - class QueryExecutorNodeMock(BaseAssistantNode): - def __init__(self, team, user): - super().__init__(team, user) - - @property - def node_name(self): - return AssistantNodeName.QUERY_EXECUTOR - - async def arun(self, state, config): - return PartialAssistantState( - messages=[ - AssistantToolCallMessage( - content="The results indicate a great future for you.", tool_call_id=tool_call_id - ) - ] - ) - - query_executor_mock.return_value = QueryExecutorNodeMock(self.team, self.user) - # Run in insights tool mode output, _ = await self._run_assistant_graph( conversation=self.conversation, @@ -1347,9 +1294,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ("message", VisualizationMessage(query="Foobar", answer=query, plan="Plan")), ( "message", - AssistantToolCallMessage( - content="The results indicate a great future for you.", tool_call_id=tool_call_id - ), + AssistantToolCallMessage(content="Result", tool_call_id=tool_call_id), ), ] self.assertConversationEqual(output, expected_output) @@ -1387,7 +1332,6 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): async def test_merges_messages_with_same_id(self): """Test that messages with the same ID are merged into one.""" - from ee.hogai.graph.base import BaseAssistantNode message_ids = [str(uuid4()), str(uuid4())] @@ -1395,7 +1339,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): first_content = "First version of message" updated_content = "Updated version of message" - class MessageUpdatingNode(BaseAssistantNode): + class MessageUpdatingNode(AssistantNode): def __init__(self, team, user): super().__init__(team, user) self.call_count = 0 @@ -1447,7 +1391,6 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): async def test_assistant_filters_messages_correctly(self): """Test that the Assistant class correctly filters messages based on should_output_assistant_message.""" - from ee.hogai.graph.base import BaseAssistantNode output_messages = [ # Should be output (has content) @@ -1467,7 +1410,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): for test_message, expected_in_output in output_messages: # Create a simple graph that produces different message types to test filtering - class MessageFilteringNode(BaseAssistantNode): + class MessageFilteringNode(AssistantNode): def __init__(self, team, user, message_to_return): super().__init__(team, user) self.message_to_return = message_to_return @@ -1477,8 +1420,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): return AssistantNodeName.ROOT async def arun(self, state, config): - self.dispatcher.message(self.message_to_return) - return PartialAssistantState() + return PartialAssistantState(messages=[self.message_to_return]) # Create a graph with our test node node = MessageFilteringNode(self.team, self.user, test_message) @@ -1505,12 +1447,13 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): """Test that ui_context persists when retrieving conversation state across multiple runs.""" # Create a simple graph that just returns the initial state - def return_initial_state(state): - return {"messages": [AssistantMessage(content="Response from assistant")]} + class ReturnInitialStateNode(AssistantNode): + async def arun(self, state, config): + return PartialAssistantState(messages=[AssistantMessage(content="Response from assistant")]) graph = ( AssistantGraph(self.team, self.user) - .add_node(AssistantNodeName.ROOT, return_initial_state) + .add_node(AssistantNodeName.ROOT, ReturnInitialStateNode(self.team, self.user)) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) .add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) .compile() @@ -1585,8 +1528,8 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): tool_calls=[ { "id": "xyz", - "name": "edit_current_insight", - "args": {"query_description": "Foobar", "query_kind": "trends"}, + "name": "create_and_query_insight", + "args": {"query_description": "Foobar"}, } ], ) @@ -1622,20 +1565,13 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): output, assistant = await self._run_assistant_graph( test_graph=AssistantGraph(self.team, self.user) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root( - { - "root": AssistantNodeName.ROOT, - "insights": AssistantNodeName.INSIGHTS_SUBGRAPH, - "end": AssistantNodeName.END, - } - ) - .add_insights() + .add_root() .compile(), conversation=self.conversation, is_new_conversation=True, message="Hello", mode=AssistantMode.ASSISTANT, - contextual_tools={"edit_current_insight": {"current_query": "query"}}, + contextual_tools={"create_and_query_insight": {"current_query": "query"}}, ) expected_output = [ @@ -1645,23 +1581,30 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): "message", AssistantMessage( content="", + id="56076433-5d90-4248-9a46-df3fda42bd0a", tool_calls=[ AssistantToolCall( + args={"query_description": "Foobar"}, id="xyz", - name="edit_current_insight", - args={"query_description": "Foobar", "query_kind": "trends"}, + name="create_and_query_insight", + type="tool_call", ) ], ), ), + ( + "update", + AssistantUpdateEvent(content="Picking relevant events and properties", tool_call_id="xyz", id=""), + ), + ("update", AssistantUpdateEvent(content="Creating trends query", tool_call_id="xyz", id="")), ("message", VisualizationMessage(query="Foobar", answer=query, plan="Plan")), ( "message", - { - "tool_call_id": "xyz", - "type": "tool", - "ui_payload": {"edit_current_insight": query.model_dump(exclude_none=True)}, - }, # Don't check content as it's implementation detail + AssistantToolCallMessage( + content="The results indicate a great future for you.", + tool_call_id="xyz", + ui_payload={"create_and_query_insight": query.model_dump(exclude_none=True)}, + ), ), ("message", AssistantMessage(content="Everything is fine")), ] @@ -1671,7 +1614,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): state = AssistantState.model_validate(snapshot.values) expected_state_messages = [ ContextMessage( - content="\nContextual tools that are available to you on this page are:\n\nThe user is currently editing an insight (aka query). Here is that insight's current definition, which can be edited using the `edit_current_insight` tool:\n\n```json\nquery\n```\n\nIMPORTANT: DO NOT REMOVE ANY FIELDS FROM THE CURRENT INSIGHT DEFINITION. DO NOT CHANGE ANY OTHER FIELDS THAN THE ONES THE USER ASKED FOR. KEEP THE REST AS IS.\n\nIMPORTANT: this context may or may not be relevant to your tasks. You should not respond to this context unless it is highly relevant to your task.\n" + content="\nContextual tools that are available to you on this page are:\n\nThe user is currently editing an insight (aka query). Here is that insight's current definition, which can be edited using the `create_and_query_insight` tool:\n\n```json\nquery\n```\n\n\nDo not remove any fields from the current insight definition. Do not change any other fields than the ones the user asked for. Keep the rest as is.\n\n\nIMPORTANT: this context may or may not be relevant to your tasks. You should not respond to this context unless it is highly relevant to your task.\n" ), HumanMessage(content="Hello"), AssistantMessage( @@ -1679,8 +1622,8 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): tool_calls=[ AssistantToolCall( id="xyz", - name="edit_current_insight", - args={"query_description": "Foobar", "query_kind": "trends"}, + name="create_and_query_insight", + args={"query_description": "Foobar"}, ) ], ), @@ -1688,7 +1631,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): AssistantToolCallMessage( content="The results indicate a great future for you.", tool_call_id="xyz", - ui_payload={"edit_current_insight": query.model_dump(exclude_none=True)}, + ui_payload={"create_and_query_insight": query.model_dump(exclude_none=True)}, ), AssistantMessage(content="Everything is fine"), ] @@ -1705,7 +1648,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): graph = ( AssistantGraph(self.team, self.user) .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) - .add_root({"root": AssistantNodeName.ROOT, "end": AssistantNodeName.END}) + .add_root() .compile() ) @@ -1757,16 +1700,14 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): # Tests for ainvoke method async def test_ainvoke_basic_functionality(self): """Test ainvoke returns all messages at once without streaming.""" - from ee.hogai.graph.base import BaseAssistantNode - class TestNode(BaseAssistantNode): + class TestNode(AssistantNode): @property def node_name(self): return AssistantNodeName.ROOT async def arun(self, state, config): - self.dispatcher.message(AssistantMessage(content="Response")) - return PartialAssistantState() + return PartialAssistantState(messages=[AssistantMessage(content="Response", id=str(uuid4()))]) test_node = TestNode(self.team, self.user) graph = ( @@ -1798,28 +1739,6 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): self.assertIsInstance(item[1], AssistantMessage) self.assertEqual(cast(AssistantMessage, item[1]).content, "Response") - async def test_process_value_update_returns_none(self): - """Test that _aprocess_value_update returns None for basic state updates (ACKs are now handled by reducer).""" - - assistant = Assistant.create( - self.team, self.conversation, new_message=HumanMessage(content="Hello"), user=self.user - ) - - # Create a value update tuple that doesn't match special nodes - update = cast( - GraphValueUpdateTuple, - ( - AssistantNodeName.ROOT, - {"root": {"messages": []}}, # Empty update that doesn't match visualization or verbose nodes - ), - ) - - # Process the update - result = await assistant._aprocess_value_update(update) - - # Should return None (ACK events are now generated by the reducer) - self.assertIsNone(result) - def test_billing_context_in_config(self): billing_context = MaxBillingContext( has_active_subscription=True, @@ -1855,7 +1774,225 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): ) config = assistant._get_config() - self.assertEqual(config.get("configurable", {}).get("billing_context"), billing_context) + self.assertEqual(config["configurable"]["billing_context"], billing_context) + + @patch("ee.hogai.context.context.AssistantContextManager.check_user_has_billing_access", return_value=True) + @patch("ee.hogai.graph.root.nodes.RootNode._get_model") + async def test_billing_tool_execution(self, root_mock, access_mock): + """Test that the billing tool can be called and returns formatted billing information.""" + billing_context = MaxBillingContext( + subscription_level=MaxBillingContextSubscriptionLevel.PAID, + billing_plan="startup", + has_active_subscription=True, + is_deactivated=False, + products=[ + MaxProductInfo( + name="Product Analytics", + type="analytics", + description="Track user behavior", + current_usage=50000, + usage_limit=100000, + has_exceeded_limit=False, + is_used=True, + percentage_usage=0.5, + addons=[], + ) + ], + settings=MaxBillingContextSettings(autocapture_on=True, active_destinations=2), + ) + + # Mock the root node to call the read_data tool with billing_info kind + tool_call_id = str(uuid4()) + + def root_side_effect(msgs: list[BaseMessage]): + # Check if we've already received a tool result + last_message = msgs[-1] + if ( + isinstance(last_message.content, list) + and isinstance(last_message.content[-1], dict) + and last_message.content[-1]["type"] == "tool_result" + ): + # After tool execution, respond with final message + return messages.AIMessage(content="Your billing information shows you're on a startup plan.") + + # First call - request the billing tool + return messages.AIMessage( + content="", + tool_calls=[ + { + "id": tool_call_id, + "name": "read_data", + "args": {"kind": "billing_info"}, + } + ], + ) + + root_mock.return_value = FakeAnthropicRunnableLambdaWithTokenCounter(root_side_effect) + + # Create a minimal test graph + test_graph = ( + AssistantGraph(self.team, self.user) + .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + .add_root() + .compile() + ) + + # Run the assistant with billing context + assistant = Assistant.create( + team=self.team, + conversation=self.conversation, + user=self.user, + new_message=HumanMessage(content="What's my current billing status?"), + billing_context=billing_context, + ) + assistant._graph = test_graph + + output: list[AssistantOutput] = [] + async for event in assistant.astream(): + output.append(event) + + # Verify we received messages + self.assertGreater(len(output), 0) + + # Find the assistant's final response + assistant_messages = [msg for event_type, msg in output if isinstance(msg, AssistantMessage)] + self.assertGreater(len(assistant_messages), 0) + + # Verify the assistant received and used the billing information + # The mock returns "Your billing information shows you're on a startup plan." + final_message = cast(AssistantMessage, assistant_messages[-1]) + self.assertIn("billing", final_message.content.lower()) + self.assertIn("startup", final_message.content.lower()) + + async def test_messages_without_id_are_yielded(self): + """Test that messages without ID are always yielded.""" + + class MessageWithoutIdNode(AssistantNode): + call_count = 0 + + async def arun(self, state, config): + self.call_count += 1 + # Return message without ID - should always be yielded + return PartialAssistantState( + messages=[ + AssistantMessage(content=f"Message {self.call_count} without ID"), + AssistantMessage(content=f"Message {self.call_count} without ID"), + ] + ) + + node = MessageWithoutIdNode(self.team, self.user) + graph = ( + AssistantGraph(self.team, self.user) + .add_node(AssistantNodeName.ROOT, node) + .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + .add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + .compile() + ) + + # Run the assistant multiple times + output1, _ = await self._run_assistant_graph(graph, message="First run", conversation=self.conversation) + output2, _ = await self._run_assistant_graph(graph, message="Second run", conversation=self.conversation) + + # Both runs should yield their messages (human + assistant message each) + self.assertEqual(len(output1), 3) # Human message + AI message + AI message + self.assertEqual(len(output2), 3) # Human message + AI message + AI message + + async def test_messages_with_id_are_deduplicated(self): + """Test that messages with ID are deduplicated during streaming.""" + message_id = str(uuid4()) + + class DuplicateMessageNode(AssistantNode): + call_count = 0 + + async def arun(self, state, config): + self.call_count += 1 + # Always return the same message with same ID + return PartialAssistantState( + messages=[ + AssistantMessage(id=message_id, content=f"Call {self.call_count}"), + AssistantMessage(id=message_id, content=f"Call {self.call_count}"), + ] + ) + + node = DuplicateMessageNode(self.team, self.user) + graph = ( + AssistantGraph(self.team, self.user) + .add_node(AssistantNodeName.ROOT, node) + .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + .add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + .compile() + ) + + # Create assistant and manually test the streaming behavior + assistant = Assistant.create( + self.team, + self.conversation, + new_message=HumanMessage(content="Test message"), + user=self.user, + is_new_conversation=False, + ) + assistant._graph = graph + + # Collect all streamed messages + streamed_messages = [] + async for event_type, message in assistant.astream(stream_first_message=False): + if event_type == AssistantEventType.MESSAGE: + streamed_messages.append(message) + + # Should only get one message despite the node being called multiple times + assistant_messages = [ + msg for msg in streamed_messages if isinstance(msg, AssistantMessage) and msg.id == message_id + ] + self.assertEqual(len(assistant_messages), 1, "Message with same ID should only be yielded once") + + async def test_replaced_messaged_are_not_double_streamed(self): + """Test that existing messages are not streamed again""" + # Create messages with IDs that should be tracked + message_id_1 = str(uuid4()) + message_id_2 = str(uuid4()) + call_count = [0] + + # Create a simple graph that returns messages with IDs + class TestNode(AssistantNode): + async def arun(self, state, config): + result = None + if call_count[0] == 0: + result = PartialAssistantState( + messages=[ + AssistantMessage(id=message_id_1, content="Message 1"), + ] + ) + else: + result = PartialAssistantState( + messages=ReplaceMessages( + [ + AssistantMessage(id=message_id_1, content="Message 1"), + AssistantMessage(id=message_id_2, content="Message 2"), + ] + ) + ) + call_count[0] += 1 + return result + + graph = ( + AssistantGraph(self.team, self.user) + .add_node(AssistantNodeName.ROOT, TestNode(self.team, self.user)) + .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + .add_edge(AssistantNodeName.ROOT, AssistantNodeName.END) + .compile() + ) + + output, _ = await self._run_assistant_graph(graph, message="First run", conversation=self.conversation) + # Filter for assistant messages only, as the test is about tracking assistant message IDs + assistant_output = [(event_type, msg) for event_type, msg in output if isinstance(msg, AssistantMessage)] + self.assertEqual(len(assistant_output), 1) + self.assertEqual(cast(AssistantMessage, assistant_output[0][1]).id, message_id_1) + + output, _ = await self._run_assistant_graph(graph, message="Second run", conversation=self.conversation) + # Filter for assistant messages only, as the test is about tracking assistant message IDs + assistant_output = [(event_type, msg) for event_type, msg in output if isinstance(msg, AssistantMessage)] + self.assertEqual(len(assistant_output), 1) + self.assertEqual(cast(AssistantMessage, assistant_output[0][1]).id, message_id_2) @patch( "ee.hogai.graph.conversation_summarizer.nodes.AnthropicConversationSummarizer.summarize", @@ -1887,22 +2024,7 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): mock_tool.return_value = ("Event list" * 128000, None) mock_should_compact.side_effect = cycle([False, True]) # Also changed this - graph = ( - AssistantGraph(self.team, self.user) - .add_root( - path_map={ - "insights": AssistantNodeName.END, - "search_documentation": AssistantNodeName.END, - "root": AssistantNodeName.ROOT, - "end": AssistantNodeName.END, - "insights_search": AssistantNodeName.END, - "session_summarization": AssistantNodeName.END, - "create_dashboard": AssistantNodeName.END, - } - ) - .add_memory_onboarding() - .compile() - ) + graph = AssistantGraph(self.team, self.user).add_root().add_memory_onboarding().compile() expected_output = [ ("message", HumanMessage(content="First")), @@ -1928,3 +2050,86 @@ class TestAssistant(ClickhouseTestMixin, NonAtomicBaseTest): self.assertEqual(state.start_id, new_human_message.id) # should be equal to the summary message, minus reasoning message self.assertEqual(state.root_conversation_start_id, state.messages[3].id) + + @patch("ee.hogai.graph.root.tools.search.SearchTool._arun_impl", return_value=("Docs doubt it", None)) + @patch( + "ee.hogai.graph.root.tools.read_taxonomy.ReadTaxonomyTool._run_impl", + return_value=("Hedgehogs have not talked yet", None), + ) + @patch("ee.hogai.graph.root.nodes.RootNode._get_model") + async def test_root_node_can_execute_multiple_tool_calls(self, root_mock, search_mock, read_taxonomy_mock): + """Test that the root node can execute multiple tool calls in parallel.""" + tool_call_id1, tool_call_id2 = [str(uuid4()), str(uuid4())] + + def root_side_effect(msgs: list[BaseMessage]): + # Check if we've already received a tool result + last_message = msgs[-1] + if ( + isinstance(last_message.content, list) + and isinstance(last_message.content[-1], dict) + and last_message.content[-1]["type"] == "tool_result" + ): + # After tool execution, respond with final message + return messages.AIMessage(content="No") + + return messages.AIMessage( + content="Not sure. Let me check.", + tool_calls=[ + { + "id": tool_call_id1, + "name": "search", + "args": {"kind": "docs", "query": "Do hedgehogs speak?"}, + }, + { + "id": tool_call_id2, + "name": "read_taxonomy", + "args": {"query": {"kind": "events"}}, + }, + ], + ) + + root_mock.return_value = FakeAnthropicRunnableLambdaWithTokenCounter(root_side_effect) + + # Create a minimal test graph + graph = ( + AssistantGraph(self.team, self.user) + .add_edge(AssistantNodeName.START, AssistantNodeName.ROOT) + .add_root() + .compile() + ) + + expected_output = [ + (AssistantEventType.MESSAGE, HumanMessage(content="Do hedgehogs speak?")), + ( + AssistantEventType.MESSAGE, + AssistantMessage( + content="Not sure. Let me check.", + tool_calls=[ + { + "id": tool_call_id1, + "name": "search", + "args": {"kind": "docs", "query": "Do hedgehogs speak?"}, + }, + { + "id": tool_call_id2, + "name": "read_taxonomy", + "args": {"query": {"kind": "events"}}, + }, + ], + ), + ), + ( + AssistantEventType.MESSAGE, + AssistantToolCallMessage(content="Docs doubt it", tool_call_id=tool_call_id1), + ), + ( + AssistantEventType.MESSAGE, + AssistantToolCallMessage(content="Hedgehogs have not talked yet", tool_call_id=tool_call_id2), + ), + (AssistantEventType.MESSAGE, AssistantMessage(content="No")), + ] + output, _ = await self._run_assistant_graph( + graph, message="Do hedgehogs speak?", conversation=self.conversation + ) + + self.assertConversationEqual(output, expected_output) diff --git a/ee/hogai/tool.py b/ee/hogai/tool.py index 704c569ff2..3213639291 100644 --- a/ee/hogai/tool.py +++ b/ee/hogai/tool.py @@ -1,6 +1,7 @@ import json import pkgutil import importlib +from abc import ABC, abstractmethod from collections.abc import Sequence from typing import Any, Literal, Self @@ -16,9 +17,9 @@ from posthog.models import Team, User import products from ee.hogai.context.context import AssistantContextManager -from ee.hogai.graph.mixins import AssistantContextMixin -from ee.hogai.utils.types import AssistantState -from ee.hogai.utils.types.base import AssistantMessageUnion +from ee.hogai.graph.base.context import get_node_path, set_node_path +from ee.hogai.graph.mixins import AssistantContextMixin, AssistantDispatcherMixin +from ee.hogai.utils.types.base import AssistantMessageUnion, AssistantState, NodePath CONTEXTUAL_TOOL_NAME_TO_TOOL: dict[AssistantTool, type["MaxTool"]] = {} @@ -51,7 +52,7 @@ class ToolMessagesArtifact(BaseModel): messages: Sequence[AssistantMessageUnion] -class MaxTool(AssistantContextMixin, BaseTool): +class MaxTool(AssistantContextMixin, AssistantDispatcherMixin, BaseTool): # LangChain's default is just "content", but we always want to return the tool call artifact too # - it becomes the `ui_payload` response_format: Literal["content_and_artifact"] = "content_and_artifact" @@ -66,7 +67,7 @@ class MaxTool(AssistantContextMixin, BaseTool): _config: RunnableConfig _state: AssistantState _context_manager: AssistantContextManager - _tool_call_id: str + _node_path: tuple[NodePath, ...] # DEPRECATED: Use `_arun_impl` instead def _run_impl(self, *args, **kwargs) -> tuple[str, Any]: @@ -82,7 +83,7 @@ class MaxTool(AssistantContextMixin, BaseTool): *, team: Team, user: User, - tool_call_id: str, + node_path: tuple[NodePath, ...] | None = None, state: AssistantState | None = None, config: RunnableConfig | None = None, name: str | None = None, @@ -102,7 +103,10 @@ class MaxTool(AssistantContextMixin, BaseTool): super().__init__(**tool_kwargs, **kwargs) self._team = team self._user = user - self._tool_call_id = tool_call_id + if node_path is None: + self._node_path = (*(get_node_path() or ()), NodePath(name=self.node_name)) + else: + self._node_path = node_path self._state = state if state else AssistantState(messages=[]) self._config = config if config else RunnableConfig(configurable={}) self._context_manager = context_manager or AssistantContextManager(team, user, self._config) @@ -120,19 +124,35 @@ class MaxTool(AssistantContextMixin, BaseTool): CONTEXTUAL_TOOL_NAME_TO_TOOL[accepted_name] = cls def _run(self, *args, config: RunnableConfig, **kwargs): + """LangChain default runner.""" try: - return self._run_impl(*args, **kwargs) + return self._run_with_context(*args, **kwargs) except NotImplementedError: pass - return async_to_sync(self._arun_impl)(*args, **kwargs) + return async_to_sync(self._arun_with_context)(*args, **kwargs) async def _arun(self, *args, config: RunnableConfig, **kwargs): + """LangChain default runner.""" try: - return await self._arun_impl(*args, **kwargs) + return await self._arun_with_context(*args, **kwargs) except NotImplementedError: pass return await super()._arun(*args, config=config, **kwargs) + def _run_with_context(self, *args, **kwargs): + """Sets the context for the tool.""" + with set_node_path(self.node_path): + return self._run_impl(*args, **kwargs) + + async def _arun_with_context(self, *args, **kwargs): + """Sets the context for the tool.""" + with set_node_path(self.node_path): + return await self._arun_impl(*args, **kwargs) + + @property + def node_name(self) -> str: + return f"max_tool.{self.get_name()}" + @property def context(self) -> dict: return self._context_manager.get_contextual_tools().get(self.get_name(), {}) @@ -149,7 +169,7 @@ class MaxTool(AssistantContextMixin, BaseTool): *, team: Team, user: User, - tool_call_id: str, + node_path: tuple[NodePath, ...] | None = None, state: AssistantState | None = None, config: RunnableConfig | None = None, context_manager: AssistantContextManager | None = None, @@ -160,5 +180,31 @@ class MaxTool(AssistantContextMixin, BaseTool): Override this factory to dynamically modify the tool name, description, args schema, etc. """ return cls( - team=team, user=user, tool_call_id=tool_call_id, state=state, config=config, context_manager=context_manager + team=team, user=user, node_path=node_path, state=state, config=config, context_manager=context_manager ) + + +class MaxSubtool(AssistantDispatcherMixin, ABC): + _config: RunnableConfig + + def __init__( + self, + *, + team: Team, + user: User, + state: AssistantState, + config: RunnableConfig, + context_manager: AssistantContextManager, + ): + self._team = team + self._user = user + self._state = state + self._context_manager = context_manager + + @abstractmethod + async def execute(self, *args, **kwargs) -> Any: + pass + + @property + def node_name(self) -> str: + return f"max_subtool.{self.__class__.__name__}" diff --git a/ee/hogai/utils/dispatcher.py b/ee/hogai/utils/dispatcher.py index 0b7a3b0e75..7cfa1db995 100644 --- a/ee/hogai/utils/dispatcher.py +++ b/ee/hogai/utils/dispatcher.py @@ -1,21 +1,19 @@ from collections.abc import Callable -from typing import TYPE_CHECKING, Any +from typing import Any +from langchain_core.runnables import RunnableConfig +from langgraph.config import get_stream_writer from langgraph.types import StreamWriter -from posthog.schema import AssistantMessage, AssistantToolCallMessage - from ee.hogai.utils.types.base import ( AssistantActionUnion, AssistantDispatcherEvent, AssistantMessageUnion, MessageAction, - NodeStartAction, + NodePath, + UpdateAction, ) -if TYPE_CHECKING: - from ee.hogai.utils.types.composed import MaxNodeName - class AssistantDispatcher: """ @@ -26,13 +24,14 @@ class AssistantDispatcher: The dispatcher does NOT update state - it just emits actions to the stream. """ - _parent_tool_call_id: str | None = None + _node_path: tuple[NodePath, ...] def __init__( self, writer: StreamWriter | Callable[[Any], None], - node_name: "MaxNodeName", - parent_tool_call_id: str | None = None, + node_path: tuple[NodePath, ...], + node_name: str, + node_run_id: str, ): """ Create a dispatcher for a specific node. @@ -40,9 +39,10 @@ class AssistantDispatcher: Args: node_name: The name of the node dispatching actions (for attribution) """ - self._node_name = node_name self._writer = writer - self._parent_tool_call_id = parent_tool_call_id + self._node_path = node_path + self._node_name = node_name + self._node_run_id = node_run_id def dispatch(self, action: AssistantActionUnion) -> None: """ @@ -56,7 +56,11 @@ class AssistantDispatcher: action: Action dict with "type" and "payload" keys """ try: - self._writer(AssistantDispatcherEvent(action=action, node_name=self._node_name)) + self._writer( + AssistantDispatcherEvent( + action=action, node_path=self._node_path, node_name=self._node_name, node_run_id=self._node_run_id + ) + ) except Exception as e: # Log error but don't crash node execution # The dispatcher should be resilient to writer failures @@ -69,34 +73,29 @@ class AssistantDispatcher: """ Dispatch a message to the stream. """ - if self._parent_tool_call_id: - # If the dispatcher is initialized with a parent tool call id, set the parent tool call id on the message - # This is to ensure that the message is associated with the correct tool call - # Don't set parent_tool_call_id on: - # 1. AssistantToolCallMessage with the same tool_call_id (to avoid self-reference) - # 2. AssistantMessage with tool_calls containing the same ID (to avoid cycles) - should_skip = False - if isinstance(message, AssistantToolCallMessage) and self._parent_tool_call_id == message.tool_call_id: - should_skip = True - elif isinstance(message, AssistantMessage) and message.tool_calls: - # Check if any tool call has the same ID as the parent - for tool_call in message.tool_calls: - if tool_call.id == self._parent_tool_call_id: - should_skip = True - break - - if not should_skip: - message.parent_tool_call_id = self._parent_tool_call_id self.dispatch(MessageAction(message=message)) - def node_start(self) -> None: - """ - Dispatch a node start action to the stream. - """ - self.dispatch(NodeStartAction()) + def update(self, content: str): + """Dispatch a transient update message to the stream that will be associated with a tool call in the UI.""" + self.dispatch(UpdateAction(content=content)) - def set_as_root(self) -> None: - """ - Set the dispatcher as the root. - """ - self._parent_tool_call_id = None + +def create_dispatcher_from_config(config: RunnableConfig, node_path: tuple[NodePath, ...]) -> AssistantDispatcher: + """Create a dispatcher from a RunnableConfig and node path""" + # Set writer from LangGraph context + try: + writer = get_stream_writer() + except RuntimeError: + # Not in streaming context (e.g., testing) + # Use noop writer + def noop(*_args, **_kwargs): + pass + + writer = noop + + metadata = config.get("metadata") or {} + node_name: str = metadata.get("langgraph_node") or "" + # `langgraph_checkpoint_ns` contains the nested path to the node, so it's more accurate for streaming. + node_run_id: str = metadata.get("langgraph_checkpoint_ns") or "" + + return AssistantDispatcher(writer, node_path=node_path, node_run_id=node_run_id, node_name=node_name) diff --git a/ee/hogai/utils/helpers.py b/ee/hogai/utils/helpers.py index 98c417b7c9..609217f800 100644 --- a/ee/hogai/utils/helpers.py +++ b/ee/hogai/utils/helpers.py @@ -38,8 +38,7 @@ from posthog.hogql_queries.query_runner import ExecutionMode from posthog.models import Team from posthog.taxonomy.taxonomy import CORE_FILTER_DEFINITIONS_BY_GROUP -from ee.hogai.utils.types import AssistantMessageUnion -from ee.hogai.utils.types.base import AssistantDispatcherEvent +from ee.hogai.utils.types.base import AssistantDispatcherEvent, AssistantMessageUnion def remove_line_breaks(line: str) -> str: diff --git a/ee/hogai/utils/state.py b/ee/hogai/utils/state.py index 2d94ae6cc0..4af17c1b94 100644 --- a/ee/hogai/utils/state.py +++ b/ee/hogai/utils/state.py @@ -5,7 +5,7 @@ from structlog import get_logger from ee.hogai.graph.deep_research.types import DeepResearchNodeName, PartialDeepResearchState from ee.hogai.graph.taxonomy.types import TaxonomyAgentState, TaxonomyNodeName -from ee.hogai.utils.types import PartialAssistantState +from ee.hogai.utils.types.base import PartialAssistantState from ee.hogai.utils.types.composed import AssistantMaxGraphState, AssistantMaxPartialGraphState, MaxNodeName # A state update can have a partial state or a LangGraph's reserved dataclasses like Interrupt. @@ -45,6 +45,7 @@ def validate_value_update( class LangGraphState(TypedDict): langgraph_node: MaxNodeName + langgraph_checkpoint_ns: str GraphMessageUpdateTuple = tuple[Literal["messages"], tuple[Union[AIMessageChunk, Any], LangGraphState]] diff --git a/ee/hogai/utils/stream_processor.py b/ee/hogai/utils/stream_processor.py index f995092dbe..dba0062bc9 100644 --- a/ee/hogai/utils/stream_processor.py +++ b/ee/hogai/utils/stream_processor.py @@ -1,4 +1,4 @@ -from typing import cast +from typing import Generic, Protocol, TypeVar, cast, get_args import structlog from langchain_core.messages import AIMessageChunk @@ -6,7 +6,6 @@ from langchain_core.messages import AIMessageChunk from posthog.schema import ( AssistantGenerationStatusEvent, AssistantGenerationStatusType, - AssistantMessage, AssistantToolCallMessage, AssistantUpdateEvent, FailureMessage, @@ -16,21 +15,51 @@ from posthog.schema import ( ) from ee.hogai.utils.helpers import normalize_ai_message, should_output_assistant_message -from ee.hogai.utils.state import merge_message_chunk +from ee.hogai.utils.state import is_message_update, is_state_update, merge_message_chunk from ee.hogai.utils.types.base import ( AssistantDispatcherEvent, + AssistantGraphName, AssistantMessageUnion, AssistantResultUnion, + BaseStateWithMessages, + LangGraphUpdateEvent, MessageAction, MessageChunkAction, + NodeEndAction, + NodePath, NodeStartAction, + UpdateAction, ) from ee.hogai.utils.types.composed import MaxNodeName logger = structlog.get_logger(__name__) -class AssistantStreamProcessor: +class AssistantStreamProcessorProtocol(Protocol): + """Protocol defining the interface for assistant stream processors.""" + + _streamed_update_ids: set[str] + """Tracks the IDs of messages that have been streamed.""" + + def process(self, event: AssistantDispatcherEvent) -> list[AssistantResultUnion] | None: + """Process a dispatcher event and return a result or None.""" + ... + + def process_langgraph_update(self, event: LangGraphUpdateEvent) -> list[AssistantResultUnion] | None: + """Process a LangGraph update event and return a list of results or None.""" + ... + + def mark_id_as_streamed(self, message_id: str) -> None: + """Mark a message ID as streamed.""" + self._streamed_update_ids.add(message_id) + + +StateType = TypeVar("StateType", bound=BaseStateWithMessages) + +MESSAGE_TYPE_TUPLE = get_args(AssistantMessageUnion) + + +class AssistantStreamProcessor(AssistantStreamProcessorProtocol, Generic[StateType]): """ Reduces streamed actions to client-facing messages. @@ -38,36 +67,34 @@ class AssistantStreamProcessor: handlers based on action type and message characteristics. """ + _verbose_nodes: set[MaxNodeName] + """Nodes that emit messages.""" _streaming_nodes: set[MaxNodeName] """Nodes that produce streaming messages.""" - _visualization_nodes: dict[MaxNodeName, type] - """Nodes that produce visualization messages.""" - _tool_call_id_to_message: dict[str, AssistantMessage] - """Maps tool call IDs to their parent messages for message chain tracking.""" - _streamed_update_ids: set[str] - """Tracks the IDs of messages that have been streamed.""" - _chunks: AIMessageChunk + _chunks: dict[str, AIMessageChunk] """Tracks the current message chunk.""" + _state: StateType | None + """Tracks the current state.""" + _state_type: type[StateType] + """The type of the state.""" - def __init__( - self, - streaming_nodes: set[MaxNodeName], - visualization_nodes: dict[MaxNodeName, type], - ): + def __init__(self, verbose_nodes: set[MaxNodeName], streaming_nodes: set[MaxNodeName], state_type: type[StateType]): """ Initialize the stream processor with node configuration. Args: + verbose_nodes: Nodes that produce messages streaming_nodes: Nodes that produce streaming messages - visualization_nodes: Nodes that produce visualization messages """ + # If a node is streaming node, it should also be verbose. + self._verbose_nodes = verbose_nodes | streaming_nodes self._streaming_nodes = streaming_nodes - self._visualization_nodes = visualization_nodes - self._tool_call_id_to_message = {} self._streamed_update_ids = set() - self._chunks = AIMessageChunk(content="") + self._chunks = {} + self._state_type = state_type + self._state = None - def process(self, event: AssistantDispatcherEvent) -> AssistantResultUnion | None: + def process(self, event: AssistantDispatcherEvent) -> list[AssistantResultUnion] | None: """ Reduce streamed actions to client messages. @@ -75,86 +102,113 @@ class AssistantStreamProcessor: to specialized handlers based on action type and message characteristics. """ action = event.action - node_name = event.node_name - - if isinstance(action, MessageChunkAction): - return self._handle_message_stream(action.message, cast(MaxNodeName, node_name)) if isinstance(action, NodeStartAction): - return AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.ACK) + self._chunks[event.node_run_id] = AIMessageChunk(content="") + return [AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.ACK)] + + if isinstance(action, NodeEndAction): + if event.node_run_id in self._chunks: + del self._chunks[event.node_run_id] + return self._handle_node_end(event, action) + + if isinstance(action, MessageChunkAction) and (result := self._handle_message_stream(event, action.message)): + return [result] if isinstance(action, MessageAction): message = action.message + if result := self._handle_message(event, message): + return [result] - # Register any tool calls for later parent chain lookups - self._register_tool_calls(message) - result = self._handle_message(message, cast(MaxNodeName, node_name)) - return ( - result if result is not None else AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.ACK) + if isinstance(action, UpdateAction) and (update_event := self._handle_update_message(event, action)): + return [update_event] + + return None + + def process_langgraph_update(self, event: LangGraphUpdateEvent) -> list[AssistantResultUnion] | None: + """ + Process a LangGraph update event. + """ + if is_message_update(event.update): + # Convert the message chunk update to a dispatcher event to prepare for a bright future without LangGraph + maybe_message_chunk, state = event.update[1] + if not isinstance(maybe_message_chunk, AIMessageChunk): + return None + action = AssistantDispatcherEvent( + action=MessageChunkAction(message=maybe_message_chunk), + node_name=state["langgraph_node"], + node_run_id=state["langgraph_checkpoint_ns"], ) + return self.process(action) - def _find_parent_ids(self, message: AssistantMessage) -> tuple[str | None, str | None]: - """ - Walk up the message chain to find the root parent's message_id and tool_call_id. + if is_state_update(event.update): + new_state = self._state_type.model_validate(event.update[1]) + self._state = new_state - Returns (root_message_id, root_tool_call_id) for the root message in the chain. - Includes cycle detection and max depth protection. - """ - root_tool_call_id = message.parent_tool_call_id - if root_tool_call_id is None: - return message.id, None + return None - root_message_id = None - visited: set[str] = set() + def _handle_message( + self, action: AssistantDispatcherEvent, message: AssistantMessageUnion + ) -> AssistantResultUnion | None: + """Handle a message from a node.""" + node_name = cast(MaxNodeName, action.node_name) + produced_message: AssistantResultUnion | None = None - while root_tool_call_id is not None: - if root_tool_call_id in visited: - # Cycle detected, we skip this message - return None, None + # Output all messages from the top-level graph. + if not self._is_message_from_nested_node_or_graph(action.node_path or ()): + produced_message = self._handle_root_message(message, node_name) + # Other message types with parents (viz, notebook, failure, tool call) + else: + produced_message = self._handle_special_child_message(message, node_name) - visited.add(root_tool_call_id) - parent_message = self._tool_call_id_to_message.get(root_tool_call_id) - if parent_message is None: - # The parent message is not registered, we skip this message as it could come - # from a sub-nested graph invoked directly by a contextual tool. - return None, None + # Messages with existing IDs must be deduplicated. + # Messages WITHOUT IDs must be streamed because they're progressive. + if isinstance(produced_message, MESSAGE_TYPE_TUPLE) and produced_message.id is not None: + if produced_message.id in self._streamed_update_ids: + return None + self._streamed_update_ids.add(produced_message.id) - next_parent_tool_call_id = parent_message.parent_tool_call_id - root_message_id = parent_message.id - if next_parent_tool_call_id is None: - return root_message_id, root_tool_call_id - root_tool_call_id = next_parent_tool_call_id - raise ValueError("Should not reach here") + return produced_message - def _register_tool_calls(self, message: AssistantMessageUnion) -> None: - """Register any tool calls in the message for later lookup.""" - if isinstance(message, AssistantMessage) and message.tool_calls is not None: - for tool_call in message.tool_calls: - self._tool_call_id_to_message[tool_call.id] = message + def _is_message_from_nested_node_or_graph(self, node_path: tuple[NodePath, ...]) -> bool: + """Check if the message is from a nested node or graph.""" + if not node_path: + return False + # The first path is always the top-level graph. + # The second path is always the top-level node. + # If the path is longer than 2, it's a MaxTool or nested graphs. + if len(node_path) > 2 and next((path for path in node_path[1:] if path.name in AssistantGraphName), None): + return True + return False def _handle_root_message( self, message: AssistantMessageUnion, node_name: MaxNodeName ) -> AssistantMessageUnion | None: """Handle messages with no parent (root messages).""" - if not should_output_assistant_message(message): + if node_name not in self._verbose_nodes or not should_output_assistant_message(message): return None return message - def _handle_assistant_message_with_parent(self, message: AssistantMessage) -> AssistantUpdateEvent | None: + def _handle_update_message( + self, event: AssistantDispatcherEvent, action: UpdateAction + ) -> AssistantUpdateEvent | None: """Handle AssistantMessage that has a parent, creating an AssistantUpdateEvent.""" - parent_id, parent_tool_call_id = self._find_parent_ids(message) - - if parent_tool_call_id is None or parent_id is None: + if not event.node_path or not action.content: return None - if message.content == "": + # Find the closest tool call id to the update. + parent_path = next((path for path in reversed(event.node_path) if path.tool_call_id), None) + # Updates from the top-level graph nodes are not supported. + if not parent_path: return None - return AssistantUpdateEvent( - id=parent_id, - tool_call_id=parent_tool_call_id, - content=message.content, - ) + tool_call_id = parent_path.tool_call_id + message_id = parent_path.message_id + + if not message_id or not tool_call_id: + return None + + return AssistantUpdateEvent(id=message_id, tool_call_id=tool_call_id, content=action.content) def _handle_special_child_message( self, message: AssistantMessageUnion, node_name: MaxNodeName @@ -164,14 +218,10 @@ class AssistantStreamProcessor: These messages are returned as-is regardless of where in the nesting hierarchy they are. """ - # Return visualization messages only if from visualization nodes - if isinstance(message, VisualizationMessage | MultiVisualizationMessage): - if node_name in self._visualization_nodes: - return message - return None - # These message types are always returned as-is - if isinstance(message, NotebookUpdateMessage | FailureMessage): + if isinstance(message, VisualizationMessage | MultiVisualizationMessage) or isinstance( + message, NotebookUpdateMessage | FailureMessage + ): return message if isinstance(message, AssistantToolCallMessage): @@ -181,37 +231,44 @@ class AssistantStreamProcessor: # Should not reach here raise ValueError(f"Unhandled special message type: {type(message).__name__}") - def _handle_message(self, message: AssistantMessageUnion, node_name: MaxNodeName) -> AssistantResultUnion | None: - # Messages with existing IDs must be deduplicated. - # Messages WITHOUT IDs must be streamed because they're progressive. - if hasattr(message, "id") and message.id is not None: - if message.id in self._streamed_update_ids: - return None - self._streamed_update_ids.add(message.id) - - # Root messages (no parent) are filtered by VERBOSE_NODES - if message.parent_tool_call_id is None: - return self._handle_root_message(message, node_name) - - # AssistantMessage with parent creates AssistantUpdateEvent - if isinstance(message, AssistantMessage): - return self._handle_assistant_message_with_parent(message) - else: - # Other message types with parents (viz, notebook, failure, tool call) - return self._handle_special_child_message(message, node_name) - - def _handle_message_stream(self, message: AIMessageChunk, node_name: MaxNodeName) -> AssistantResultUnion | None: + def _handle_message_stream( + self, event: AssistantDispatcherEvent, message: AIMessageChunk + ) -> AssistantResultUnion | None: """ Process LLM chunks from "messages" stream mode. With dispatch pattern, complete messages are dispatched by nodes. This handles AIMessageChunk for ephemeral streaming (responsiveness). """ + node_name = cast(MaxNodeName, event.node_name) + run_id = event.node_run_id + if node_name not in self._streaming_nodes: return None + if run_id not in self._chunks: + self._chunks[run_id] = AIMessageChunk(content="") # Merge message chunks - self._chunks = merge_message_chunk(self._chunks, message) + self._chunks[run_id] = merge_message_chunk(self._chunks[run_id], message) # Stream ephemeral message (no ID = not persisted) - return normalize_ai_message(self._chunks) + return normalize_ai_message(self._chunks[run_id]) + + def _handle_node_end( + self, event: AssistantDispatcherEvent, action: NodeEndAction + ) -> list[AssistantResultUnion] | None: + """Handle the end of a node. Reset the streaming chunks.""" + if not isinstance(action.state, BaseStateWithMessages): + return None + results: list[AssistantResultUnion] = [] + for message in action.state.messages: + if new_event := self.process( + AssistantDispatcherEvent( + action=MessageAction(message=message), + node_name=event.node_name, + node_run_id=event.node_run_id, + node_path=event.node_path, + ) + ): + results.extend(new_event) + return results diff --git a/ee/hogai/utils/test/test_dispatcher.py b/ee/hogai/utils/test/test_dispatcher.py index 4152edbe08..b70088df60 100644 --- a/ee/hogai/utils/test/test_dispatcher.py +++ b/ee/hogai/utils/test/test_dispatcher.py @@ -1,165 +1,426 @@ +""" +Comprehensive tests for AssistantDispatcher. + +Tests the dispatcher logic that emits actions to LangGraph custom stream. +""" + from posthog.test.base import BaseTest -from unittest.mock import AsyncMock, MagicMock +from unittest.mock import MagicMock, patch from langchain_core.runnables import RunnableConfig from posthog.schema import AssistantMessage, AssistantToolCall -from ee.hogai.graph.base import BaseAssistantNode -from ee.hogai.utils.dispatcher import AssistantDispatcher -from ee.hogai.utils.types import AssistantState, PartialAssistantState -from ee.hogai.utils.types.base import AssistantDispatcherEvent, AssistantNodeName +from ee.hogai.utils.dispatcher import AssistantDispatcher, create_dispatcher_from_config +from ee.hogai.utils.types.base import ( + AssistantDispatcherEvent, + AssistantGraphName, + AssistantNodeName, + MessageAction, + NodePath, + UpdateAction, +) -class TestMessageDispatcher(BaseTest): +class TestAssistantDispatcher(BaseTest): + """Test the AssistantDispatcher in isolation.""" + def setUp(self): - self._writer = MagicMock() - self._writer.__aiter__ = AsyncMock(return_value=iter([])) - self._writer.write = AsyncMock() + super().setUp() + self.dispatched_events: list[AssistantDispatcherEvent] = [] - def test_create_dispatcher(self): - """Test creating a MessageDispatcher""" - dispatcher = AssistantDispatcher(self._writer, node_name=AssistantNodeName.ROOT) + def mock_writer(event): + self.dispatched_events.append(event) + + self.writer = mock_writer + self.node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT), + ) + + def test_create_dispatcher_with_basic_params(self): + """Test creating a dispatcher with required parameters.""" + dispatcher = AssistantDispatcher( + writer=self.writer, + node_path=self.node_path, + node_name=AssistantNodeName.ROOT, + node_run_id="test_run_123", + ) self.assertEqual(dispatcher._node_name, AssistantNodeName.ROOT) - self.assertEqual(dispatcher._writer, self._writer) + self.assertEqual(dispatcher._node_run_id, "test_run_123") + self.assertEqual(dispatcher._node_path, self.node_path) + self.assertEqual(dispatcher._writer, self.writer) - async def test_dispatch_with_writer(self): - """Test dispatching with a writer""" - dispatched_actions = [] + def test_dispatch_message_action(self): + """Test dispatching a message via the message() method.""" + dispatcher = AssistantDispatcher( + writer=self.writer, + node_path=self.node_path, + node_name=AssistantNodeName.ROOT, + node_run_id="test_run_456", + ) - def mock_writer(data): - dispatched_actions.append(data) - - dispatcher = AssistantDispatcher(mock_writer, node_name=AssistantNodeName.ROOT) - - message = AssistantMessage(content="test message", parent_tool_call_id="tc1") + message = AssistantMessage(content="Test message") dispatcher.message(message) - self.assertEqual(len(dispatched_actions), 1) + self.assertEqual(len(self.dispatched_events), 1) + event = self.dispatched_events[0] - # Verify action structure - event = dispatched_actions[0] self.assertIsInstance(event, AssistantDispatcherEvent) - self.assertEqual(event.action.type, "MESSAGE") + self.assertIsInstance(event.action, MessageAction) + assert isinstance(event.action, MessageAction) self.assertEqual(event.action.message, message) self.assertEqual(event.node_name, AssistantNodeName.ROOT) + self.assertEqual(event.node_run_id, "test_run_456") + self.assertEqual(event.node_path, self.node_path) + + def test_dispatch_update_action(self): + """Test dispatching an update via the update() method.""" + dispatcher = AssistantDispatcher( + writer=self.writer, + node_path=self.node_path, + node_name=AssistantNodeName.TRENDS_GENERATOR, + node_run_id="test_run_789", + ) + + dispatcher.update("Processing query...") + + self.assertEqual(len(self.dispatched_events), 1) + event = self.dispatched_events[0] + + self.assertIsInstance(event, AssistantDispatcherEvent) + self.assertIsInstance(event.action, UpdateAction) + assert isinstance(event.action, UpdateAction) + self.assertEqual(event.action.content, "Processing query...") + self.assertEqual(event.node_name, AssistantNodeName.TRENDS_GENERATOR) + self.assertEqual(event.node_run_id, "test_run_789") + + def test_dispatch_multiple_messages(self): + """Test dispatching multiple messages in sequence.""" + dispatcher = AssistantDispatcher( + writer=self.writer, + node_path=self.node_path, + node_name=AssistantNodeName.ROOT, + node_run_id="test_run_multi", + ) + + message1 = AssistantMessage(content="First message") + message2 = AssistantMessage(content="Second message") + message3 = AssistantMessage(content="Third message") + + dispatcher.message(message1) + dispatcher.message(message2) + dispatcher.message(message3) + + self.assertEqual(len(self.dispatched_events), 3) + + contents = [] + for event in self.dispatched_events: + if isinstance(event.action, MessageAction): + msg = event.action.message + if isinstance(msg, AssistantMessage): + contents.append(msg.content) + self.assertEqual(contents, ["First message", "Second message", "Third message"]) + + def test_dispatch_message_with_tool_calls(self): + """Test dispatching a message with tool calls preserves all data.""" + dispatcher = AssistantDispatcher( + writer=self.writer, + node_path=self.node_path, + node_name=AssistantNodeName.ROOT, + node_run_id="test_run_tools", + ) + + tool_call = AssistantToolCall(id="tool_123", name="search", args={"query": "test query"}) + message = AssistantMessage(content="Running search...", tool_calls=[tool_call]) + + dispatcher.message(message) + + self.assertEqual(len(self.dispatched_events), 1) + event = self.dispatched_events[0] + + self.assertIsInstance(event.action, MessageAction) + assert isinstance(event.action, MessageAction) + dispatched_message = event.action.message + assert isinstance(dispatched_message, AssistantMessage) + self.assertEqual(dispatched_message.content, "Running search...") + self.assertIsNotNone(dispatched_message.tool_calls) + assert dispatched_message.tool_calls is not None + self.assertEqual(len(dispatched_message.tool_calls), 1) + self.assertEqual(dispatched_message.tool_calls[0].id, "tool_123") + self.assertEqual(dispatched_message.tool_calls[0].name, "search") + self.assertEqual(dispatched_message.tool_calls[0].args, {"query": "test query"}) + + def test_dispatch_with_nested_node_path(self): + """Test that nested node paths are preserved in dispatched events.""" + nested_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id="msg_123", tool_call_id="tc_123"), + NodePath(name=AssistantGraphName.INSIGHTS), + NodePath(name=AssistantNodeName.TRENDS_GENERATOR), + ) + + dispatcher = AssistantDispatcher( + writer=self.writer, node_path=nested_path, node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id="run_1" + ) + + message = AssistantMessage(content="Nested message") + dispatcher.message(message) + + self.assertEqual(len(self.dispatched_events), 1) + event = self.dispatched_events[0] + + self.assertEqual(event.node_path, nested_path) + assert event.node_path is not None + self.assertEqual(len(event.node_path), 4) + self.assertEqual(event.node_path[1].message_id, "msg_123") + self.assertEqual(event.node_path[1].tool_call_id, "tc_123") + + def test_dispatch_error_handling_continues_execution(self): + """Test that dispatch errors are caught and logged but don't crash.""" + + def failing_writer(event): + raise RuntimeError("Writer failed!") + + dispatcher = AssistantDispatcher( + writer=failing_writer, + node_path=self.node_path, + node_name=AssistantNodeName.ROOT, + node_run_id="test_run_error", + ) + + message = AssistantMessage(content="This should not crash") + + # Should not raise exception + with patch("logging.getLogger") as mock_get_logger: + mock_logger = MagicMock() + mock_get_logger.return_value = mock_logger + + dispatcher.message(message) + + # Verify error was logged + mock_logger.error.assert_called_once() + args, kwargs = mock_logger.error.call_args + self.assertIn("Failed to dispatch action", args[0]) + + def test_dispatch_mixed_actions(self): + """Test dispatching both messages and updates in sequence.""" + dispatcher = AssistantDispatcher( + writer=self.writer, + node_path=self.node_path, + node_name=AssistantNodeName.TRENDS_GENERATOR, + node_run_id="test_run_mixed", + ) + + dispatcher.update("Starting analysis...") + dispatcher.message(AssistantMessage(content="Found 3 insights")) + dispatcher.update("Finalizing results...") + + self.assertEqual(len(self.dispatched_events), 3) + + self.assertIsInstance(self.dispatched_events[0].action, UpdateAction) + assert isinstance(self.dispatched_events[0].action, UpdateAction) + self.assertEqual(self.dispatched_events[0].action.content, "Starting analysis...") + + self.assertIsInstance(self.dispatched_events[1].action, MessageAction) + assert isinstance(self.dispatched_events[1].action, MessageAction) + assert isinstance(self.dispatched_events[1].action.message, AssistantMessage) + self.assertEqual(self.dispatched_events[1].action.message.content, "Found 3 insights") + + self.assertIsInstance(self.dispatched_events[2].action, UpdateAction) + assert isinstance(self.dispatched_events[2].action, UpdateAction) + self.assertEqual(self.dispatched_events[2].action.content, "Finalizing results...") + + def test_dispatch_preserves_message_id(self): + """Test that message IDs are preserved through dispatch.""" + dispatcher = AssistantDispatcher( + writer=self.writer, + node_path=self.node_path, + node_name=AssistantNodeName.ROOT, + node_run_id="test_run_id_preservation", + ) + + message = AssistantMessage(id="msg_xyz_789", content="Message with ID") + dispatcher.message(message) + + event = self.dispatched_events[0] + assert isinstance(event.action, MessageAction) + self.assertEqual(event.action.message.id, "msg_xyz_789") + + def test_dispatch_with_empty_node_path(self): + """Test dispatcher with an empty node path.""" + dispatcher = AssistantDispatcher( + writer=self.writer, node_path=(), node_name=AssistantNodeName.ROOT, node_run_id="test_run_empty_path" + ) + + message = AssistantMessage(content="Root level message") + dispatcher.message(message) + + self.assertEqual(len(self.dispatched_events), 1) + event = self.dispatched_events[0] + self.assertEqual(event.node_path, ()) -class MockNode(BaseAssistantNode[AssistantState, PartialAssistantState]): - """Mock node for testing""" +class TestCreateDispatcherFromConfig(BaseTest): + """Test the create_dispatcher_from_config helper function.""" - @property - def node_name(self): - return AssistantNodeName.ROOT + def test_create_dispatcher_from_config_with_stream_writer(self): + """Test creating dispatcher from config with LangGraph stream writer.""" + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) - async def arun(self, state, config): - # Use dispatch to add a message - self.dispatcher.message(AssistantMessage(content="Test message from node")) - return PartialAssistantState() + config = RunnableConfig( + metadata={"langgraph_node": AssistantNodeName.TRENDS_GENERATOR, "langgraph_checkpoint_ns": "checkpoint_abc"} + ) + + mock_writer = MagicMock() + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", return_value=mock_writer): + dispatcher = create_dispatcher_from_config(config, node_path) + + self.assertEqual(dispatcher._node_name, AssistantNodeName.TRENDS_GENERATOR) + self.assertEqual(dispatcher._node_run_id, "checkpoint_abc") + self.assertEqual(dispatcher._node_path, node_path) + self.assertEqual(dispatcher._writer, mock_writer) + + def test_create_dispatcher_from_config_without_stream_writer(self): + """Test creating dispatcher when not in streaming context (e.g., testing).""" + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) + + config = RunnableConfig( + metadata={"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "checkpoint_xyz"} + ) + + # Simulate RuntimeError when get_stream_writer is called outside streaming context + with patch("ee.hogai.utils.dispatcher.get_stream_writer", side_effect=RuntimeError("Not in streaming context")): + dispatcher = create_dispatcher_from_config(config, node_path) + + # Should create a noop writer + self.assertEqual(dispatcher._node_name, AssistantNodeName.ROOT) + self.assertEqual(dispatcher._node_run_id, "checkpoint_xyz") + self.assertEqual(dispatcher._node_path, node_path) + + # Verify the noop writer doesn't raise exceptions + message = AssistantMessage(content="Test") + dispatcher.message(message) # Should not crash + + def test_create_dispatcher_with_missing_metadata(self): + """Test creating dispatcher when metadata fields are missing.""" + node_path = (NodePath(name=AssistantGraphName.ASSISTANT),) + + config = RunnableConfig(metadata={}) + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", side_effect=RuntimeError("Not in streaming context")): + dispatcher = create_dispatcher_from_config(config, node_path) + + # Should use empty strings as defaults + self.assertEqual(dispatcher._node_name, "") + self.assertEqual(dispatcher._node_run_id, "") + self.assertEqual(dispatcher._node_path, node_path) + + def test_create_dispatcher_preserves_node_path(self): + """Test that node path is correctly passed through to the dispatcher.""" + nested_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id="msg_1", tool_call_id="tc_1"), + NodePath(name=AssistantGraphName.INSIGHTS), + ) + + config = RunnableConfig( + metadata={"langgraph_node": AssistantNodeName.TRENDS_GENERATOR, "langgraph_checkpoint_ns": "cp_1"} + ) + + with patch("ee.hogai.utils.dispatcher.get_stream_writer", side_effect=RuntimeError("Not in streaming context")): + dispatcher = create_dispatcher_from_config(config, nested_path) + + self.assertEqual(dispatcher._node_path, nested_path) + self.assertEqual(len(dispatcher._node_path), 3) class TestDispatcherIntegration(BaseTest): - async def test_node_dispatch_flow(self): - """Test that a node can dispatch messages""" - # Use sync test helpers since BaseTest provides them - team, user = self.team, self.user + """Integration tests for dispatcher usage patterns.""" - node = MockNode(team=team, user=user) + def test_dispatcher_in_node_context(self): + """Test typical usage pattern within a node.""" + dispatched_events = [] - # Track dispatched actions - dispatched_actions = [] + def mock_writer(event): + dispatched_events.append(event) - def mock_writer(data): - dispatched_actions.append(data) - - # Set up node's dispatcher - node._dispatcher = AssistantDispatcher(mock_writer, node_name=AssistantNodeName.ROOT) - - # Run the node - state = AssistantState(messages=[]) - config = RunnableConfig(configurable={}) - - await node.arun(state, config) - - # Verify action was dispatched - self.assertEqual(len(dispatched_actions), 1) - - event = dispatched_actions[0] - self.assertIsInstance(event, AssistantDispatcherEvent) - self.assertEqual(event.action.type, "MESSAGE") - self.assertEqual(event.action.message.content, "Test message from node") - self.assertEqual(event.action.message.parent_tool_call_id, None) - self.assertEqual(event.node_name, AssistantNodeName.ROOT) - - async def test_action_preservation_through_stream(self): - """Test that action data is preserved through the stream""" - - captured_updates = [] - - def mock_writer(data): - captured_updates.append(data) - - dispatcher = AssistantDispatcher(mock_writer, node_name=AssistantNodeName.ROOT) - - # Create complex message with metadata - message = AssistantMessage( - content="Complex message", - parent_tool_call_id="tc123", - tool_calls=[AssistantToolCall(id="tool1", name="search", args={"query": "test"})], + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT), ) - dispatcher.message(message) + dispatcher = AssistantDispatcher( + writer=mock_writer, node_path=node_path, node_name=AssistantNodeName.ROOT, node_run_id="integration_run_1" + ) - # Extract action - event = captured_updates[0] - self.assertIsInstance(event, AssistantDispatcherEvent) + # Simulate node execution pattern + dispatcher.update("Starting node execution...") - # Verify all message fields preserved - payload = event.action.message - self.assertEqual(payload.content, "Complex message") - self.assertEqual(payload.parent_tool_call_id, "tc123") - self.assertIsNotNone(payload.tool_calls) - self.assertEqual(len(payload.tool_calls), 1) - self.assertEqual(payload.tool_calls[0].name, "search") + tool_call = AssistantToolCall(id="tc_int_1", name="generate_insight", args={"type": "trends"}) + dispatcher.message(AssistantMessage(content="Generating insight", tool_calls=[tool_call])) - async def test_multiple_dispatches_from_node(self): - """Test that a node can dispatch multiple messages""" - # Use sync test helpers since BaseTest provides them - team, user = self.team, self.user + dispatcher.update("Processing data...") - class MultiDispatchNode(BaseAssistantNode[AssistantState, PartialAssistantState]): - @property - def node_name(self): - return AssistantNodeName.ROOT + dispatcher.message(AssistantMessage(content="Insight generated successfully")) - async def arun(self, state, config): - # Dispatch multiple messages - self.dispatcher.message(AssistantMessage(content="First message")) - self.dispatcher.message(AssistantMessage(content="Second message")) - self.dispatcher.message(AssistantMessage(content="Third message")) - return PartialAssistantState() + # Verify all events were dispatched + self.assertEqual(len(dispatched_events), 4) - node = MultiDispatchNode(team=team, user=user) + # Verify event types and order + self.assertIsInstance(dispatched_events[0].action, UpdateAction) + self.assertIsInstance(dispatched_events[1].action, MessageAction) + self.assertIsInstance(dispatched_events[2].action, UpdateAction) + self.assertIsInstance(dispatched_events[3].action, MessageAction) - dispatched_actions = [] + # Verify all events have consistent metadata + for event in dispatched_events: + self.assertEqual(event.node_name, AssistantNodeName.ROOT) + self.assertEqual(event.node_run_id, "integration_run_1") + self.assertEqual(event.node_path, node_path) - def mock_writer(data): - dispatched_actions.append(data) + def test_concurrent_dispatchers(self): + """Test multiple dispatchers can coexist without interference.""" + dispatched_events_1 = [] + dispatched_events_2 = [] - node._dispatcher = AssistantDispatcher(mock_writer, node_name=AssistantNodeName.ROOT) + def writer_1(event): + dispatched_events_1.append(event) - state = AssistantState(messages=[]) - config = RunnableConfig(configurable={}) + def writer_2(event): + dispatched_events_2.append(event) - await node.arun(state, config) + path_1 = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) + path_2 = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.TRENDS_GENERATOR)) - # Verify all three dispatches - self.assertEqual(len(dispatched_actions), 3) + dispatcher_1 = AssistantDispatcher( + writer=writer_1, node_path=path_1, node_name=AssistantNodeName.ROOT, node_run_id="run_1" + ) - contents = [] - for event in dispatched_actions: - self.assertIsInstance(event, AssistantDispatcherEvent) - contents.append(event.action.message.content) + dispatcher_2 = AssistantDispatcher( + writer=writer_2, node_path=path_2, node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id="run_2" + ) - self.assertEqual(contents, ["First message", "Second message", "Third message"]) + # Dispatch from both + dispatcher_1.message(AssistantMessage(content="From dispatcher 1")) + dispatcher_2.message(AssistantMessage(content="From dispatcher 2")) + dispatcher_1.update("Update from dispatcher 1") + dispatcher_2.update("Update from dispatcher 2") + + # Verify each dispatcher wrote to its own writer + self.assertEqual(len(dispatched_events_1), 2) + self.assertEqual(len(dispatched_events_2), 2) + + # Verify events went to correct writers + assert isinstance(dispatched_events_1[0].action, MessageAction) + assert isinstance(dispatched_events_1[0].action.message, AssistantMessage) + self.assertEqual(dispatched_events_1[0].action.message.content, "From dispatcher 1") + assert isinstance(dispatched_events_2[0].action, MessageAction) + assert isinstance(dispatched_events_2[0].action.message, AssistantMessage) + self.assertEqual(dispatched_events_2[0].action.message.content, "From dispatcher 2") + + # Verify node names are correct + self.assertEqual(dispatched_events_1[0].node_name, AssistantNodeName.ROOT) + self.assertEqual(dispatched_events_2[0].node_name, AssistantNodeName.TRENDS_GENERATOR) diff --git a/ee/hogai/utils/test/test_stream_processor.py b/ee/hogai/utils/test/test_stream_processor.py index 25a434e63e..f6dca2e50a 100644 --- a/ee/hogai/utils/test/test_stream_processor.py +++ b/ee/hogai/utils/test/test_stream_processor.py @@ -1,15 +1,14 @@ """ -Comprehensive tests for AssistantMessageReducer. +Comprehensive tests for AssistantStreamProcessor. -Tests the reducer logic that processes dispatcher actions -and routes messages appropriately. +Tests the stream processor logic that handles dispatcher actions, +routes messages based on node paths, and manages streaming state. """ from typing import cast from uuid import uuid4 from posthog.test.base import BaseTest -from unittest.mock import MagicMock from langchain_core.messages import AIMessageChunk @@ -17,7 +16,6 @@ from posthog.schema import ( AssistantGenerationStatusEvent, AssistantGenerationStatusType, AssistantMessage, - AssistantToolCall, AssistantToolCallMessage, AssistantUpdateEvent, FailureMessage, @@ -29,13 +27,20 @@ from posthog.schema import ( VisualizationMessage, ) +from ee.hogai.utils.state import GraphValueUpdateTuple from ee.hogai.utils.stream_processor import AssistantStreamProcessor from ee.hogai.utils.types.base import ( AssistantDispatcherEvent, + AssistantGraphName, AssistantNodeName, + AssistantState, + LangGraphUpdateEvent, MessageAction, MessageChunkAction, + NodeEndAction, + NodePath, NodeStartAction, + UpdateAction, ) @@ -44,406 +49,581 @@ class TestStreamProcessor(BaseTest): def setUp(self): super().setUp() - # Create a reducer with test node configuration self.stream_processor = AssistantStreamProcessor( + verbose_nodes={AssistantNodeName.ROOT, AssistantNodeName.TRENDS_GENERATOR}, streaming_nodes={AssistantNodeName.TRENDS_GENERATOR}, - visualization_nodes={AssistantNodeName.TRENDS_GENERATOR: MagicMock()}, + state_type=AssistantState, ) def _create_dispatcher_event( self, - action: MessageAction | NodeStartAction | MessageChunkAction, + action: MessageAction | NodeStartAction | MessageChunkAction | NodeEndAction | UpdateAction, node_name: AssistantNodeName = AssistantNodeName.ROOT, + node_run_id: str = "test_run_id", + node_path: tuple[NodePath, ...] | None = None, ) -> AssistantDispatcherEvent: """Helper to create a dispatcher event for testing.""" - return AssistantDispatcherEvent(action=action, node_name=node_name) + return AssistantDispatcherEvent( + action=action, node_name=node_name, node_run_id=node_run_id, node_path=node_path + ) - def test_node_start_action_returns_ack(self): - """Test NODE_START action returns ACK status event.""" - event = self._create_dispatcher_event(NodeStartAction()) + # Node lifecycle tests + + def test_node_start_initializes_chunk_and_returns_ack(self): + """Test NodeStartAction initializes a chunk for the run_id and returns ACK.""" + run_id = "test_run_123" + event = self._create_dispatcher_event(NodeStartAction(), node_run_id=run_id) result = self.stream_processor.process(event) self.assertIsNotNone(result) - result = cast(AssistantGenerationStatusEvent, result) - self.assertEqual(result.type, AssistantGenerationStatusType.ACK) + assert result is not None + self.assertEqual(len(result), 1) + first_result = result[0] + self.assertIsInstance(first_result, AssistantGenerationStatusEvent) + assert isinstance(first_result, AssistantGenerationStatusEvent) + self.assertEqual(first_result.type, AssistantGenerationStatusType.ACK) + self.assertIn(run_id, self.stream_processor._chunks) + self.assertEqual(self.stream_processor._chunks[run_id].content, "") - def test_message_with_tool_calls_stores_in_registry(self): - """Test AssistantMessage with tool_calls is stored in _tool_call_id_to_message.""" - tool_call_id = str(uuid4()) - message = AssistantMessage( - content="Test", - tool_calls=[AssistantToolCall(id=tool_call_id, name="test_tool", args={})], - ) + def test_node_end_cleans_up_chunk(self): + """Test NodeEndAction removes the chunk for the run_id.""" + run_id = "test_run_456" + self.stream_processor._chunks[run_id] = AIMessageChunk(content="test") - event = self._create_dispatcher_event(MessageAction(message=message)) + state = AssistantState(messages=[]) + event = self._create_dispatcher_event(NodeEndAction(state=state), node_run_id=run_id) self.stream_processor.process(event) - # Should be stored in registry - self.assertIn(tool_call_id, self.stream_processor._tool_call_id_to_message) - self.assertEqual(self.stream_processor._tool_call_id_to_message[tool_call_id], message) + self.assertNotIn(run_id, self.stream_processor._chunks) - def test_assistant_message_with_parent_creates_assistant_update_event(self): - """Test AssistantMessage with parent_tool_call_id creates AssistantUpdateEvent.""" - # First, register a parent message - parent_tool_call_id = str(uuid4()) - parent_message = AssistantMessage( - id=str(uuid4()), - content="Parent", - tool_calls=[AssistantToolCall(id=parent_tool_call_id, name="test", args={})], - parent_tool_call_id=None, + def test_node_end_processes_messages_from_state(self): + """Test NodeEndAction processes all messages from the final state.""" + run_id = "test_run_789" + message1 = AssistantMessage(id=str(uuid4()), content="Message 1") + message2 = AssistantMessage(id=str(uuid4()), content="Message 2") + state = AssistantState(messages=[message1, message2]) + + event = self._create_dispatcher_event( + NodeEndAction(state=state), node_name=AssistantNodeName.ROOT, node_run_id=run_id ) - self.stream_processor._tool_call_id_to_message[parent_tool_call_id] = parent_message + results = self.stream_processor.process(event) - # Now send a child message - child_message = AssistantMessage(content="Child content", parent_tool_call_id=parent_tool_call_id) - event = self._create_dispatcher_event(MessageAction(message=child_message)) + self.assertIsNotNone(results) + assert results is not None + self.assertEqual(len(results), 2) + self.assertEqual(results[0], message1) + self.assertEqual(results[1], message2) + + # Message streaming tests + + def test_message_chunk_streaming_for_streaming_nodes(self): + """Test MessageChunkAction streams chunks for nodes in streaming_nodes.""" + run_id = "stream_run_1" + chunk = AIMessageChunk(content="Hello ") + + event = self._create_dispatcher_event( + MessageChunkAction(message=chunk), node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id=run_id + ) result = self.stream_processor.process(event) - self.assertIsInstance(result, AssistantUpdateEvent) - result = cast(AssistantUpdateEvent, result) - self.assertEqual(result.id, parent_message.id) - self.assertEqual(result.tool_call_id, parent_tool_call_id) - self.assertEqual(result.content, "Child content") + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertIsInstance(result[0], AssistantMessage) + assert isinstance(result[0], AssistantMessage) + self.assertEqual(result[0].content, "Hello ") + self.assertIsNone(result[0].id) - def test_nested_parent_chain_resolution(self): - """Test finding parent IDs through nested chain of parents.""" - # Create chain: root -> intermediate -> leaf - root_tool_call_id = str(uuid4()) - root_message = AssistantMessage( - id=str(uuid4()), - content="Root", - tool_calls=[AssistantToolCall(id=root_tool_call_id, name="root_tool", args={})], - parent_tool_call_id=None, + def test_message_chunk_ignored_for_non_streaming_nodes(self): + """Test MessageChunkAction returns None for nodes not in streaming_nodes.""" + run_id = "stream_run_2" + chunk = AIMessageChunk(content="Hello ") + + event = self._create_dispatcher_event( + MessageChunkAction(message=chunk), node_name=AssistantNodeName.ROOT, node_run_id=run_id ) - - intermediate_tool_call_id = str(uuid4()) - intermediate_message = AssistantMessage( - id=str(uuid4()), - content="Intermediate", - tool_calls=[AssistantToolCall(id=intermediate_tool_call_id, name="intermediate_tool", args={})], - parent_tool_call_id=root_tool_call_id, - ) - - # Register both in the registry - self.stream_processor._tool_call_id_to_message[root_tool_call_id] = root_message - self.stream_processor._tool_call_id_to_message[intermediate_tool_call_id] = intermediate_message - - # Send leaf message that references intermediate - leaf_message = AssistantMessage(content="Leaf content", parent_tool_call_id=intermediate_tool_call_id) - event = self._create_dispatcher_event(MessageAction(message=leaf_message)) result = self.stream_processor.process(event) - # Should resolve to root + self.assertIsNone(result) - self.assertIsInstance(result, AssistantUpdateEvent) - result = cast(AssistantUpdateEvent, result) - # Note: The unpacking swaps the values, so id is tool_call_id and parent_tool_call_id is message_id - self.assertEqual(result.id, root_message.id) - self.assertEqual(result.tool_call_id, root_tool_call_id) + def test_multiple_chunks_merged_correctly(self): + """Test that multiple MessageChunkActions are merged correctly.""" + run_id = "stream_run_3" - def test_missing_parent_message_returns_ack(self): - """Test that missing parent message returns ACK.""" - missing_parent_id = str(uuid4()) - child_message = AssistantMessage(content="Orphan", parent_tool_call_id=missing_parent_id) - - event = self._create_dispatcher_event(MessageAction(message=child_message)) - - result = self.stream_processor.process(event) - self.assertIsInstance(result, AssistantGenerationStatusEvent) - result = cast(AssistantGenerationStatusEvent, result) - self.assertEqual(result.type, AssistantGenerationStatusType.ACK) - - def test_parent_without_id_returns_ack(self): - """Test that parent message without ID logs warning and returns None.""" - parent_tool_call_id = str(uuid4()) - # Parent message WITHOUT an id - parent_message = AssistantMessage( - id=None, # No ID - content="Parent", - tool_calls=[AssistantToolCall(id=parent_tool_call_id, name="test", args={})], - parent_tool_call_id=None, + chunk1 = AIMessageChunk(content="Hello ") + event1 = self._create_dispatcher_event( + MessageChunkAction(message=chunk1), node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id=run_id ) - self.stream_processor._tool_call_id_to_message[parent_tool_call_id] = parent_message + result1 = self.stream_processor.process(event1) - child_message = AssistantMessage(content="Child", parent_tool_call_id=parent_tool_call_id) - event = self._create_dispatcher_event(MessageAction(message=child_message)) + chunk2 = AIMessageChunk(content="world!") + event2 = self._create_dispatcher_event( + MessageChunkAction(message=chunk2), node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id=run_id + ) + result2 = self.stream_processor.process(event2) + self.assertIsNotNone(result1) + assert result1 is not None + assert isinstance(result1[0], AssistantMessage) + self.assertEqual(result1[0].content, "Hello ") + self.assertIsNotNone(result2) + assert result2 is not None + assert isinstance(result2[0], AssistantMessage) + self.assertEqual(result2[0].content, "Hello world!") + + def test_concurrent_chunks_from_different_runs(self): + """Test that chunks from different node runs are kept separate.""" + run_id_1 = "stream_run_4a" + run_id_2 = "stream_run_4b" + + chunk1 = AIMessageChunk(content="Run 1") + event1 = self._create_dispatcher_event( + MessageChunkAction(message=chunk1), node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id=run_id_1 + ) + self.stream_processor.process(event1) + + chunk2 = AIMessageChunk(content="Run 2") + event2 = self._create_dispatcher_event( + MessageChunkAction(message=chunk2), node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id=run_id_2 + ) + self.stream_processor.process(event2) + + self.assertEqual(self.stream_processor._chunks[run_id_1].content, "Run 1") + self.assertEqual(self.stream_processor._chunks[run_id_2].content, "Run 2") + + def test_handles_mixed_content_types_in_chunks(self): + """Test that stream processor handles switching between string and list content formats.""" + run_id = "stream_run_5" + + # Start with string content + chunk1 = AIMessageChunk(content="initial string") + event1 = self._create_dispatcher_event( + MessageChunkAction(message=chunk1), node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id=run_id + ) + self.stream_processor.process(event1) + + # Switch to list format (OpenAI Responses API) + chunk2 = AIMessageChunk(content=[{"type": "text", "text": "list content"}]) + event2 = self._create_dispatcher_event( + MessageChunkAction(message=chunk2), node_name=AssistantNodeName.TRENDS_GENERATOR, node_run_id=run_id + ) + result = self.stream_processor.process(event2) + + # The result should normalize to string content + self.assertIsNotNone(result) + assert result is not None + assert isinstance(result[0], AssistantMessage) + self.assertEqual(result[0].content, "list content") + + # Root vs nested message handling tests + + def test_root_message_from_verbose_node_returned(self): + """Test messages from root level (node_path <= 2) in verbose nodes are returned.""" + message = AssistantMessage(id=str(uuid4()), content="Root message") + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) + + event = self._create_dispatcher_event( + MessageAction(message=message), node_name=AssistantNodeName.ROOT, node_path=node_path + ) result = self.stream_processor.process(event) - self.assertIsInstance(result, AssistantGenerationStatusEvent) - result = cast(AssistantGenerationStatusEvent, result) - self.assertEqual(result.type, AssistantGenerationStatusType.ACK) - def test_visualization_message_in_visualization_nodes(self): - """Test VisualizationMessage is returned when node is in VISUALIZATION_NODES.""" + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], message) + + def test_root_message_from_non_verbose_node_filtered(self): + """Test messages from root level in non-verbose nodes are filtered out.""" + message = AssistantMessage(id=str(uuid4()), content="Non-verbose message") + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.BILLING)) + + event = self._create_dispatcher_event( + MessageAction(message=message), node_name=AssistantNodeName.BILLING, node_path=node_path + ) + result = self.stream_processor.process(event) + + self.assertIsNone(result) + + def test_nested_visualization_message_returned(self): + """Test VisualizationMessage from nested node/graph is returned.""" query = TrendsQuery(series=[]) viz_message = VisualizationMessage(query="test query", answer=query, plan="test plan") - viz_message.parent_tool_call_id = str(uuid4()) - # Register parent - parent_message = AssistantMessage( - id=str(uuid4()), - content="Parent", - tool_calls=[AssistantToolCall(id=viz_message.parent_tool_call_id, name="test", args={})], + # Create a deep node path indicating this is from a nested graph + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id=str(uuid4()), tool_call_id=str(uuid4())), + NodePath(name=AssistantGraphName.INSIGHTS), + NodePath(name=AssistantNodeName.TRENDS_GENERATOR), ) - self.stream_processor._tool_call_id_to_message[viz_message.parent_tool_call_id] = parent_message - node_name = AssistantNodeName.TRENDS_GENERATOR - event = self._create_dispatcher_event(MessageAction(message=viz_message), node_name=node_name) + event = self._create_dispatcher_event( + MessageAction(message=viz_message), node_name=AssistantNodeName.TRENDS_GENERATOR, node_path=node_path + ) result = self.stream_processor.process(event) - self.assertEqual(result, viz_message) + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], viz_message) - def test_visualization_message_not_in_visualization_nodes(self): - """Test VisualizationMessage raises error when from non-visualization node.""" - query = TrendsQuery(series=[]) - viz_message = VisualizationMessage(query="test query", answer=query, plan="test plan") - viz_message.parent_tool_call_id = str(uuid4()) - - # Register parent - parent_message = AssistantMessage( - id=str(uuid4()), - content="Parent", - tool_calls=[AssistantToolCall(id=viz_message.parent_tool_call_id, name="test", args={})], - ) - self.stream_processor._tool_call_id_to_message[viz_message.parent_tool_call_id] = parent_message - - node_name = AssistantNodeName.ROOT # Not a visualization node - event = self._create_dispatcher_event(MessageAction(message=viz_message), node_name=node_name) - - result = self.stream_processor.process(event) - self.assertEqual(result, AssistantGenerationStatusEvent(type=AssistantGenerationStatusType.ACK)) - - def test_multi_visualization_message_in_visualization_nodes(self): - """Test MultiVisualizationMessage is returned when node is in VISUALIZATION_NODES.""" + def test_nested_multi_visualization_message_returned(self): + """Test MultiVisualizationMessage from nested node/graph is returned.""" query = TrendsQuery(series=[]) viz_item = VisualizationItem(query="test query", answer=query, plan="test plan") multi_viz_message = MultiVisualizationMessage(visualizations=[viz_item]) - multi_viz_message.parent_tool_call_id = str(uuid4()) - # Register parent - parent_message = AssistantMessage( - id=str(uuid4()), - content="Parent", - tool_calls=[AssistantToolCall(id=multi_viz_message.parent_tool_call_id, name="test", args={})], + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id=str(uuid4()), tool_call_id=str(uuid4())), + NodePath(name=AssistantGraphName.INSIGHTS), + NodePath(name=AssistantNodeName.TRENDS_GENERATOR), ) - self.stream_processor._tool_call_id_to_message[multi_viz_message.parent_tool_call_id] = parent_message - node_name = AssistantNodeName.TRENDS_GENERATOR - event = self._create_dispatcher_event(MessageAction(message=multi_viz_message), node_name=node_name) + event = self._create_dispatcher_event( + MessageAction(message=multi_viz_message), node_name=AssistantNodeName.TRENDS_GENERATOR, node_path=node_path + ) result = self.stream_processor.process(event) - self.assertEqual(result, multi_viz_message) + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], multi_viz_message) - def test_notebook_update_message_returns_as_is(self): - """Test NotebookUpdateMessage is returned directly.""" + def test_nested_notebook_message_returned(self): + """Test NotebookUpdateMessage from nested node/graph is returned.""" content = ProsemirrorJSONContent(type="doc", content=[]) notebook_message = NotebookUpdateMessage(notebook_id="nb123", content=content) - notebook_message.parent_tool_call_id = str(uuid4()) - # Register parent - parent_message = AssistantMessage( - id=str(uuid4()), - content="Parent", - tool_calls=[AssistantToolCall(id=notebook_message.parent_tool_call_id, name="test", args={})], + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id=str(uuid4()), tool_call_id=str(uuid4())), + NodePath(name=AssistantGraphName.INSIGHTS), + NodePath(name=AssistantNodeName.TRENDS_GENERATOR), ) - self.stream_processor._tool_call_id_to_message[notebook_message.parent_tool_call_id] = parent_message - event = self._create_dispatcher_event(MessageAction(message=notebook_message)) + event = self._create_dispatcher_event( + MessageAction(message=notebook_message), node_name=AssistantNodeName.TRENDS_GENERATOR, node_path=node_path + ) result = self.stream_processor.process(event) - self.assertEqual(result, notebook_message) + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], notebook_message) - def test_failure_message_returns_as_is(self): - """Test FailureMessage is returned directly.""" + def test_nested_failure_message_returned(self): + """Test FailureMessage from nested node/graph is returned.""" failure_message = FailureMessage(content="Something went wrong") - failure_message.parent_tool_call_id = str(uuid4()) - # Register parent - parent_message = AssistantMessage( - id=str(uuid4()), - content="Parent", - tool_calls=[AssistantToolCall(id=failure_message.parent_tool_call_id, name="test", args={})], + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id=str(uuid4()), tool_call_id=str(uuid4())), + NodePath(name=AssistantGraphName.INSIGHTS), + NodePath(name=AssistantNodeName.TRENDS_GENERATOR), ) - self.stream_processor._tool_call_id_to_message[failure_message.parent_tool_call_id] = parent_message - event = self._create_dispatcher_event(MessageAction(message=failure_message)) + event = self._create_dispatcher_event( + MessageAction(message=failure_message), node_name=AssistantNodeName.TRENDS_GENERATOR, node_path=node_path + ) result = self.stream_processor.process(event) - self.assertEqual(result, failure_message) + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], failure_message) - def test_assistant_tool_call_message_returns_as_is(self): - """Test AssistantToolCallMessage with parent is filtered out (returns ACK).""" + def test_nested_tool_call_message_filtered(self): + """Test AssistantToolCallMessage from nested node/graph is filtered out.""" tool_call_message = AssistantToolCallMessage(content="Tool result", tool_call_id=str(uuid4())) - tool_call_message.parent_tool_call_id = str(uuid4()) - # Register parent - parent_message = AssistantMessage( - id=str(uuid4()), - content="Parent", - tool_calls=[AssistantToolCall(id=tool_call_message.parent_tool_call_id, name="test", args={})], - ) - self.stream_processor._tool_call_id_to_message[tool_call_message.parent_tool_call_id] = parent_message - - event = self._create_dispatcher_event(MessageAction(message=tool_call_message)) - result = self.stream_processor.process(event) - - # New behavior: AssistantToolCallMessages with parents are filtered out - self.assertIsInstance(result, AssistantGenerationStatusEvent) - result = cast(AssistantGenerationStatusEvent, result) - self.assertEqual(result.type, AssistantGenerationStatusType.ACK) - - def test_cycle_detection_in_parent_chain(self): - """Test that circular parent chains are detected and returns ACK.""" - # Create circular chain: A -> B -> A - tool_call_a = str(uuid4()) - tool_call_b = str(uuid4()) - - message_a = AssistantMessage( - id=str(uuid4()), - content="A", - tool_calls=[AssistantToolCall(id=tool_call_a, name="tool_a", args={})], - parent_tool_call_id=tool_call_b, # Points to B + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id=str(uuid4()), tool_call_id=str(uuid4())), + NodePath(name=AssistantGraphName.INSIGHTS), + NodePath(name=AssistantNodeName.TRENDS_GENERATOR), ) - message_b = AssistantMessage( - id=str(uuid4()), - content="B", - tool_calls=[AssistantToolCall(id=tool_call_b, name="tool_b", args={})], - parent_tool_call_id=tool_call_a, # Points to A - ) - - self.stream_processor._tool_call_id_to_message[tool_call_a] = message_a - self.stream_processor._tool_call_id_to_message[tool_call_b] = message_b - - # Try to process a child of B - child_message = AssistantMessage(content="Child", parent_tool_call_id=tool_call_b) - event = self._create_dispatcher_event(MessageAction(message=child_message)) - - result = self.stream_processor.process(event) - - # Cycle detection returns ACK instead of raising error - self.assertIsInstance(result, AssistantGenerationStatusEvent) - result = cast(AssistantGenerationStatusEvent, result) - self.assertEqual(result.type, AssistantGenerationStatusType.ACK) - - def test_handles_mixed_content_types_in_chunks(self): - """Test that stream processor correctly handles switching between string and list content formats.""" - # Test string to list transition - self.stream_processor._chunks = AIMessageChunk(content="initial string content") - - # Simulate a chunk from OpenAI Responses API (list format) - list_chunk = AIMessageChunk(content=[{"type": "text", "text": "new content from o3"}]) event = self._create_dispatcher_event( - MessageChunkAction(message=list_chunk), node_name=AssistantNodeName.TRENDS_GENERATOR - ) - self.stream_processor.process(event) - - # Verify the chunks were reset to list format - self.assertIsInstance(self.stream_processor._chunks.content, list) - self.assertEqual(len(self.stream_processor._chunks.content), 1) - self.assertEqual(cast(dict, self.stream_processor._chunks.content[0])["text"], "new content from o3") - - # Test list to string transition - string_chunk = AIMessageChunk(content="back to string format") - event = self._create_dispatcher_event( - MessageChunkAction(message=string_chunk), node_name=AssistantNodeName.TRENDS_GENERATOR - ) - self.stream_processor.process(event) - - # Verify the chunks were reset to string format - self.assertIsInstance(self.stream_processor._chunks.content, str) - self.assertEqual(self.stream_processor._chunks.content, "back to string format") - - def test_handles_multiple_list_chunks(self): - """Test that multiple list-format chunks are properly concatenated.""" - # Start with empty chunks - self.stream_processor._chunks = AIMessageChunk(content="") - - # Add first list chunk - chunk1 = AIMessageChunk(content=[{"type": "text", "text": "First part"}]) - event = self._create_dispatcher_event( - MessageChunkAction(message=chunk1), node_name=AssistantNodeName.TRENDS_GENERATOR - ) - self.stream_processor.process(event) - - # Add second list chunk - chunk2 = AIMessageChunk(content=[{"type": "text", "text": " second part"}]) - event = self._create_dispatcher_event( - MessageChunkAction(message=chunk2), node_name=AssistantNodeName.TRENDS_GENERATOR + MessageAction(message=tool_call_message), node_name=AssistantNodeName.TRENDS_GENERATOR, node_path=node_path ) result = self.stream_processor.process(event) - # Verify the result is an AssistantMessage with combined content - self.assertIsInstance(result, AssistantMessage) - result = cast(AssistantMessage, result) - self.assertEqual(result.content, "First part second part") + self.assertIsNone(result) - def test_messages_without_id_are_yielded(self): - """Test that messages without ID are always yielded.""" - # Create messages without IDs + def test_short_node_path_treated_as_root(self): + """Test that node_path with length <= 2 is treated as root level.""" + message = AssistantMessage(id=str(uuid4()), content="Short path message") + + # Path with just 2 elements (graph + node) + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) + + event = self._create_dispatcher_event( + MessageAction(message=message), node_name=AssistantNodeName.ROOT, node_path=node_path + ) + result = self.stream_processor.process(event) + + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], message) + + # UpdateAction tests + + def test_update_action_creates_update_event_with_parent_from_path(self): + """Test UpdateAction creates AssistantUpdateEvent using closest tool_call_id from node_path.""" + message_id = str(uuid4()) + tool_call_id = str(uuid4()) + + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id=message_id, tool_call_id=tool_call_id), + NodePath(name=AssistantGraphName.INSIGHTS), + ) + + event = self._create_dispatcher_event( + UpdateAction(content="Update content"), node_name=AssistantNodeName.TRENDS_GENERATOR, node_path=node_path + ) + result = self.stream_processor.process(event) + + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertIsInstance(result[0], AssistantUpdateEvent) + update_event = cast(AssistantUpdateEvent, result[0]) + self.assertEqual(update_event.id, message_id) + self.assertEqual(update_event.tool_call_id, tool_call_id) + self.assertEqual(update_event.content, "Update content") + + def test_update_action_without_parent_returns_none(self): + """Test UpdateAction without parent tool_call_id in node_path returns None.""" + # No tool_call_id in any path element + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) + + event = self._create_dispatcher_event( + UpdateAction(content="Update content"), node_name=AssistantNodeName.ROOT, node_path=node_path + ) + result = self.stream_processor.process(event) + + self.assertIsNone(result) + + def test_update_action_without_node_path_returns_none(self): + """Test UpdateAction without node_path returns None.""" + event = self._create_dispatcher_event(UpdateAction(content="Update content"), node_path=None) + result = self.stream_processor.process(event) + + self.assertIsNone(result) + + def test_update_action_finds_closest_tool_call_in_reversed_path(self): + """Test UpdateAction finds the closest (most recent) tool_call_id by reversing the path.""" + # Multiple tool calls in the path - should find the closest one (last in reversed iteration) + message_id_1 = str(uuid4()) + tool_call_id_1 = str(uuid4()) + message_id_2 = str(uuid4()) + tool_call_id_2 = str(uuid4()) + + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id=message_id_1, tool_call_id=tool_call_id_1), + NodePath(name=AssistantGraphName.INSIGHTS, message_id=message_id_2, tool_call_id=tool_call_id_2), + NodePath(name=AssistantNodeName.TRENDS_GENERATOR), + ) + + event = self._create_dispatcher_event( + UpdateAction(content="Update content"), node_name=AssistantNodeName.TRENDS_GENERATOR, node_path=node_path + ) + result = self.stream_processor.process(event) + + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + update_event = cast(AssistantUpdateEvent, result[0]) + # Should use the closest parent (last one in reversed path) + self.assertEqual(update_event.id, message_id_2) + self.assertEqual(update_event.tool_call_id, tool_call_id_2) + + # Message deduplication tests + + def test_messages_with_id_deduplicated(self): + """Test that messages with the same ID are deduplicated.""" + message_id = str(uuid4()) + message1 = AssistantMessage(id=message_id, content="First occurrence") + message2 = AssistantMessage(id=message_id, content="Second occurrence") + + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) + + # Process first message - should be returned + event1 = self._create_dispatcher_event( + MessageAction(message=message1), node_name=AssistantNodeName.ROOT, node_path=node_path + ) + result1 = self.stream_processor.process(event1) + self.assertIsNotNone(result1) + assert result1 is not None + self.assertEqual(result1[0], message1) + + # Process second message with same ID - should be filtered + event2 = self._create_dispatcher_event( + MessageAction(message=message2), node_name=AssistantNodeName.ROOT, node_path=node_path + ) + result2 = self.stream_processor.process(event2) + self.assertIsNone(result2) + + def test_messages_without_id_not_deduplicated(self): + """Test that messages without ID are always yielded (not deduplicated).""" message1 = AssistantMessage(content="Message without ID") message2 = AssistantMessage(content="Another message without ID") - # Process first message - event1 = self._create_dispatcher_event(MessageAction(message=message1)) + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) + + event1 = self._create_dispatcher_event( + MessageAction(message=message1), node_name=AssistantNodeName.ROOT, node_path=node_path + ) result1 = self.stream_processor.process(event1) - self.assertEqual(result1, message1) + self.assertIsNotNone(result1) + assert result1 is not None + self.assertEqual(result1[0], message1) - # Process second message with same content - event2 = self._create_dispatcher_event(MessageAction(message=message2)) + event2 = self._create_dispatcher_event( + MessageAction(message=message2), node_name=AssistantNodeName.ROOT, node_path=node_path + ) result2 = self.stream_processor.process(event2) - self.assertEqual(result2, message2) + self.assertIsNotNone(result2) + assert result2 is not None + self.assertEqual(result2[0], message2) - # Both should be yielded since they have no IDs - - def test_messages_with_id_are_deduplicated(self): - """Test that messages with ID are deduplicated during streaming.""" + def test_preexisting_message_ids_filtered(self): + """Test that stream processor filters messages with IDs already in _streamed_update_ids.""" message_id = str(uuid4()) - # Create multiple messages with the same ID - message1 = AssistantMessage(id=message_id, content="First occurrence") - message2 = AssistantMessage(id=message_id, content="Second occurrence") - message3 = AssistantMessage(id=message_id, content="Third occurrence") + # Pre-populate the streamed IDs + self.stream_processor._streamed_update_ids.add(message_id) - # Process first message - should be yielded - event1 = self._create_dispatcher_event(MessageAction(message=message1)) - result1 = self.stream_processor.process(event1) - self.assertEqual(result1, message1) - self.assertIn(message_id, self.stream_processor._streamed_update_ids) + message = AssistantMessage(id=message_id, content="Already seen") + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.ROOT)) - # Process second message with same ID - should return ACK - event2 = self._create_dispatcher_event(MessageAction(message=message2)) - result2 = self.stream_processor.process(event2) - self.assertIsInstance(result2, AssistantGenerationStatusEvent) - result2 = cast(AssistantGenerationStatusEvent, result2) - self.assertEqual(result2.type, AssistantGenerationStatusType.ACK) + event = self._create_dispatcher_event( + MessageAction(message=message), node_name=AssistantNodeName.ROOT, node_path=node_path + ) + result = self.stream_processor.process(event) - # Process third message with same ID - should also return ACK - event3 = self._create_dispatcher_event(MessageAction(message=message3)) - result3 = self.stream_processor.process(event3) - self.assertIsInstance(result3, AssistantGenerationStatusEvent) - result3 = cast(AssistantGenerationStatusEvent, result3) - self.assertEqual(result3.type, AssistantGenerationStatusType.ACK) + self.assertIsNone(result) - def test_stream_processor_with_preexisting_message_ids(self): - """Test that stream processor correctly filters messages when initialized with existing IDs.""" - message_id_1 = str(uuid4()) - message_id_2 = str(uuid4()) + # LangGraph update processing tests - # Simulate existing messages by pre-populating the streamed IDs set - self.stream_processor._streamed_update_ids.add(message_id_1) + def test_langgraph_message_chunk_processed(self): + """Test that LangGraph message chunk updates are converted and processed.""" + chunk = AIMessageChunk(content="LangGraph chunk") + state = {"langgraph_node": AssistantNodeName.TRENDS_GENERATOR, "langgraph_checkpoint_ns": "checkpoint_123"} - # Try to process message with existing ID - should be filtered out - message1 = AssistantMessage(id=message_id_1, content="Already seen") - event1 = self._create_dispatcher_event(MessageAction(message=message1)) - result1 = self.stream_processor.process(event1) - self.assertIsInstance(result1, AssistantGenerationStatusEvent) - result1 = cast(AssistantGenerationStatusEvent, result1) - self.assertEqual(result1.type, AssistantGenerationStatusType.ACK) + update = ["messages", (chunk, state)] + event = LangGraphUpdateEvent(update=update) - # Process message with new ID - should be yielded - message2 = AssistantMessage(id=message_id_2, content="New message") - event2 = self._create_dispatcher_event(MessageAction(message=message2)) - result2 = self.stream_processor.process(event2) - self.assertEqual(result2, message2) - self.assertIn(message_id_2, self.stream_processor._streamed_update_ids) + result = self.stream_processor.process_langgraph_update(event) + + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertIsInstance(result[0], AssistantMessage) + assert isinstance(result[0], AssistantMessage) + self.assertEqual(result[0].content, "LangGraph chunk") + + def test_langgraph_state_update_stored(self): + """Test that LangGraph state updates are stored in _state.""" + new_state_dict = {"messages": [], "plan": "Test plan"} + update = cast(GraphValueUpdateTuple, ["values", new_state_dict]) + + event = LangGraphUpdateEvent(update=update) + result = self.stream_processor.process_langgraph_update(event) + + self.assertIsNone(result) + self.assertIsNotNone(self.stream_processor._state) + assert self.stream_processor._state is not None + self.assertEqual(self.stream_processor._state.plan, "Test plan") + + def test_langgraph_non_message_chunk_ignored(self): + """Test that LangGraph updates that are not AIMessageChunk are ignored.""" + regular_message = AssistantMessage(content="Not a chunk") + state = {"langgraph_node": AssistantNodeName.ROOT, "langgraph_checkpoint_ns": "checkpoint_456"} + + update = ["messages", (regular_message, state)] + event = LangGraphUpdateEvent(update=update) + + result = self.stream_processor.process_langgraph_update(event) + + self.assertIsNone(result) + + def test_langgraph_invalid_update_format_ignored(self): + """Test that invalid LangGraph update formats are ignored.""" + update = "invalid_format" + event = LangGraphUpdateEvent(update=update) + + result = self.stream_processor.process_langgraph_update(event) + + self.assertIsNone(result) + + # Edge cases and error conditions + + def test_empty_node_path_treated_as_root(self): + """Test that empty node_path is treated as root level.""" + message = AssistantMessage(id=str(uuid4()), content="Empty path message") + + event = self._create_dispatcher_event( + MessageAction(message=message), node_name=AssistantNodeName.ROOT, node_path=() + ) + result = self.stream_processor.process(event) + + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], message) + + def test_none_node_path_treated_as_root(self): + """Test that None node_path is treated as root level.""" + message = AssistantMessage(id=str(uuid4()), content="None path message") + + event = self._create_dispatcher_event( + MessageAction(message=message), node_name=AssistantNodeName.ROOT, node_path=None + ) + result = self.stream_processor.process(event) + + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], message) + + def test_node_end_with_none_state_returns_none(self): + """Test NodeEndAction with None state returns None.""" + event = self._create_dispatcher_event(NodeEndAction(state=None)) + result = self.stream_processor.process(event) + + self.assertIsNone(result) + + def test_update_action_with_empty_content_returns_none(self): + """Test UpdateAction with empty content returns None.""" + node_path = ( + NodePath(name=AssistantGraphName.ASSISTANT), + NodePath(name=AssistantNodeName.ROOT, message_id=str(uuid4()), tool_call_id=str(uuid4())), + ) + + event = self._create_dispatcher_event(UpdateAction(content=""), node_path=node_path) + result = self.stream_processor.process(event) + + self.assertIsNone(result) + + def test_special_messages_from_root_level_returned(self): + """Test that special message types from root level are handled by root message logic.""" + # VisualizationMessage from root should be returned if from verbose node + query = TrendsQuery(series=[]) + viz_message = VisualizationMessage(query="test", answer=query, plan="plan") + + node_path = (NodePath(name=AssistantGraphName.ASSISTANT), NodePath(name=AssistantNodeName.TRENDS_GENERATOR)) + + event = self._create_dispatcher_event( + MessageAction(message=viz_message), node_name=AssistantNodeName.TRENDS_GENERATOR, node_path=node_path + ) + result = self.stream_processor.process(event) + + self.assertIsNotNone(result) + assert result is not None + self.assertEqual(len(result), 1) + self.assertEqual(result[0], viz_message) diff --git a/ee/hogai/utils/types/base.py b/ee/hogai/utils/types/base.py index ce2eef08f1..1b9e5afb46 100644 --- a/ee/hogai/utils/types/base.py +++ b/ee/hogai/utils/types/base.py @@ -299,7 +299,7 @@ class _SharedAssistantState(BaseStateWithMessages, BaseStateWithIntermediateStep """ The ID of the message to start from to keep the message window short enough. """ - root_tool_call_id: Optional[str] = Field(default=None) + root_tool_call_id: Annotated[Optional[str], replace] = Field(default=None) """ The ID of the tool call from the root node. """ @@ -311,7 +311,7 @@ class _SharedAssistantState(BaseStateWithMessages, BaseStateWithIntermediateStep """ The type of insight to generate. """ - root_tool_calls_count: Optional[int] = Field(default=None) + root_tool_calls_count: Annotated[Optional[int], replace] = Field(default=None) """ Tracks the number of tool calls made by the root node to terminate the loop. """ @@ -399,7 +399,6 @@ class AssistantNodeName(StrEnum): MEMORY_COLLECTOR_TOOLS = "memory_collector_tools" INKEEP_DOCS = "inkeep_docs" INSIGHT_RAG_CONTEXT = "insight_rag_context" - INSIGHTS_SUBGRAPH = "insights_subgraph" TITLE_GENERATOR = "title_generator" INSIGHTS_SEARCH = "insights_search" SESSION_SUMMARIZATION = "session_summarization" @@ -413,6 +412,13 @@ class AssistantNodeName(StrEnum): REVENUE_ANALYTICS_FILTER_OPTIONS_TOOLS = "revenue_analytics_filter_options_tools" +class AssistantGraphName(StrEnum): + ASSISTANT = "assistant_graph" + INSIGHTS = "insights_graph" + TAXONOMY = "taxonomy_graph" + DEEP_RESEARCH = "deep_research_graph" + + class AssistantMode(StrEnum): ASSISTANT = "assistant" INSIGHTS_TOOL = "insights_tool" @@ -443,9 +449,33 @@ class NodeStartAction(BaseModel): type: Literal["NODE_START"] = "NODE_START" -AssistantActionUnion = MessageAction | MessageChunkAction | NodeStartAction +class NodeEndAction(BaseModel, Generic[PartialStateType]): + type: Literal["NODE_END"] = "NODE_END" + state: PartialStateType | None = None + + +class UpdateAction(BaseModel): + type: Literal["UPDATE"] = "UPDATE" + content: str + + +AssistantActionUnion = MessageAction | MessageChunkAction | NodeStartAction | NodeEndAction | UpdateAction + + +class NodePath(BaseModel): + """Defines a vertice of the assistant graph path.""" + + name: str + message_id: str | None = None + tool_call_id: str | None = None class AssistantDispatcherEvent(BaseModel): action: AssistantActionUnion = Field(discriminator="type") + node_path: tuple[NodePath, ...] | None = None node_name: str + node_run_id: str + + +class LangGraphUpdateEvent(BaseModel): + update: Any diff --git a/frontend/__snapshots__/scenes-app-data-pipelines--pipeline-destination-page--light.png b/frontend/__snapshots__/scenes-app-data-pipelines--pipeline-destination-page--light.png index 77339b9eec634972dc3338f9cf01435de5c69ac1..53f216329798ce538844901c77a3fa6d1d5e762a 100644 GIT binary patch delta 74232 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

>Z>=PLTUZusmTmV+XDbWY}+ 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 delta 73556 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 diff --git a/frontend/__snapshots__/scenes-app-insights-trendsvalue--trends-area-edit--dark.png b/frontend/__snapshots__/scenes-app-insights-trendsvalue--trends-area-edit--dark.png index 9dd9468aff18456cb0a8335868142cade64cb198..c7d0ddff1884a2b9c5c52f1ec3c6da173978b6db 100644 GIT binary patch literal 79158 zcmc$`bySpL_cn@62%?09fOLma(l|=@&@CX{-Jpa>NOwv}4oD0g(hbrzbayi}=f?N_ z*6)w+oIlQ5=UZnMYcVs={lvZR*!#NnwI@(sRtyuJ2pt6l1ye%&BNPSYAtnmSBWKk6 z;2Zehy*%*mo;_3yf>PA~Y6Au3HHyT?_ew6w+cVBuxE+^I_9yGx@!XWLMM_jHCVs!p z&}W^f75$MIPteEx=8ahm^?`9l32i$a*LDy|Z7yBzClQgvp-U32$@)1mDOtNe3jFW> z4qUd8^&qx;%iIHY?fKZHCZ~9@!Cg^MzCcVApZt4=GKzKh@ZY)stp1L52zW&mR12Hc6z#M)$v;E=(6G**82C3D6Tm%ojZ+n|$ z7#bDbeU-oc@@FKfh>??1XdZnaL(I@f$=%fnFy$yBRMd?rA`+_oMeK$czYQv>=b*#{ z>2dJzsH==sgnVmyLJS(t5-M|tC1lWP@^zGtEHi99|Jj|DO*1{o_af-6NPyU=?MF8l+sqpP~}|;yxSNx552Kkf01sB6yy` zooQS&l^ulMzs4<5!+t#L$kc-_LZK*jci_`Q0V05#p z>TIUgd2h08V4WnU6@l=Wu3*j-{gGEnn$D|Opmd-7-+;Nij83H;$y<8se%fo$A)Cza z%FD+$-PKj%?p$o$aPHO<3w!gX#Blpt$5P`;%ZQdm{F#GJ3G2z`Xwp`O>(Q#NcYVCx z#P#KaxnISlJzZUd+*Xj$W5bVHUZbUk#EMU#u)vRyY^YE*bA^0>VFJ347NWmD7CSOA zQKe+&uG1j}(Y9i-v9at%(weoWNMdfQUpYDE9EoRVeqX)_#Ia}-ahQBkek8Ga)@jWo zg|t$+vM+=x4uikQ$VeYw-`g{TmMUB2i=75hU+SZ|_xz;R{mIWrUfq;=Mfm!*B=e9# zW6I7<$BVRUopv+`nIC|ADhboO`hXi|9{7yDB*y>F`F zmYQL};_Es@f*uotnE_Ta=sb4I^ZN@eRn1=47muH$4Qsz1%U9mIx!&h>)I!Y6NX
a_|eVtP2UENSucO5Bbj%AS9m|Lo;85=a@6uLhC;QJU;@a8Nk zf>MkgH^{K3VWB%mI)UGDGa8Rk1(S&57?@$st5&P>a((b7&5QT;_GS-B{^8s0#n!Fo z@nGE>15q3Zi%uO?g!oj&$$b9##cAO8@85%iSrLvBmpb)seSLjDE{$poIi>+NR0$mOkSy9QsOiO)ZfX}V7wU(wDyCCBtM@>Vsiy&n4 zx>7U0du<&ob%4*|@$n{`RbUdKnchj*#^1-%_tWjZ zfq_Pw1)pN;G(P8MRPu%fL0Z{lCItMe=kU-Fsi4P5wS5kySg6x3!n7ka#h^U|AN3)J zjJu1=)$y=*(THgxn7`fQy52Z1?0m6H%|=;mZ4cfiDCH^1rtq#zTQ@d(oTHOdk&~x` z)dSXOt?Nq zy)D$#mRed`i5#X(FVN7)LqkI=Dk{jy$^D%g+g8wIWo1uKowmkch6J(h zff?Ve3Kiu4b{Y1>-W(63i-~m@^(A^<9pv~Mu+{CwFsfGZrz_^jrg@b9v|p2jX;!{K z_XnM1)v5by-Z3?GF$R;@?n)JKM7mElIn~)*{MxO=^_qdJ~z%UN8iC>-Dl5H z&w#}=%1xdVxg}jn>d1lBR&BRaIX6~SRrS4XF*i3iJe)X%*EKOALA$|2x%d$a{O88o zzG!BrpB~hGrJh0wNj;)rr*oC8;l!%=*uVK`JK_g$y)TY8hI8bqcgR0H#({*s;xTJI zz1!~@3Zu`_;#hTUovncpYMcGRhJAHb0#iqRs~Rf3v9#Ft$lg%Io1>equ@!^M z+Z{NaOCU@#fb#)6 z#5SUOc(mZcwHd54c6N4090HR>Qh}+t{(i1EZ{AQ+wzMquN&eEVaqv1`e@^}}T^<`^ zVS)Z@dJMLuu}Rn>jVKM5%wB5$f%%j_JmT*4oWSK1qN)UhJ0rGtCQ$N+9{O!>C(n6l z&K0N*1mbi!Z%?F4M70aJpPn7|4A2LeO_fWivqIF^kmxD-qSesOwof+XvzZ!O(k?bB?$c2Z9h z6oi|N9v&ZSRqi6uaArex(9qF|-q{F)ryNM(D;`f-@PupZfH{19EoQTn(%jrk%w@5> zxvAmcbg!qB&uLq$?ku=Jg>MwLb#cCiVceHU9ml8^dwn#p6a3P9vc6VzX9^yGMe^3L zdl{yAOXXJwoaxEdxUScEBY1bZIeL^Cwi@eZ2ZlsFc4x9Ipt|~eI%U-vUuGD1Apw_t z8x0L!Rj^jP_U9MC;#mv@K`u(&Gf8h6B{#PV*2cn(F_?KrC`q{n7bmCXT*IFnxlF_i zv2+rb;qWh5G4KzU@0_%8XpIH~_TuY36_e}g>L$z9n6xiW0?7Kk4wt)tExgYb_;#}~ ziMjHWHnXMTCZ?ul8_7!a+q&nxbv3cui@t!9cmKYu(UBA$WW{nGmuS+Ecl z6%lc8jTBlo&$ z)PaBkEJEFSH<>(6?aivT4iVKV%FLys^P2aPBz#V1C*z|tH79J2^7|~gR%DLg+%G}& z*IqvNz?d_ z02&7PX_vX3K)!}|?9&hbytc4L#p!E}!wY4IsHldQPHJAun^tM2ijoR=ne*@86UTZkT=6G%bvIEc7d!{DXz)jVvqMG3r#L5n;*)t`-x6M6qxHOh2y z>H|zgD5NeeDGD}dB26Mo&p{+3E9(RuGS}pD&(VNKMZLgON}c#IV*k9V=DP?a@t66& z^E4-hj3UKzO9M*mzZ$CMr(T755Av~>qd`CSb?jkVqNuJ{Y(pboqo*^UJjWHOt{P*` z^HIftWiroo4HlX$`EVyE_nJ)})^H6a@`eWq|Lfr%C!c%3NHngZn8JJ0ygV$dQ0n@r z&cKODw0tg#zsBZ_7SLMJ*{=8hZ7i6U77<~zNyk7(Dez-}^$ia8K3xeR%c-=qh3NQS zb#hL2vpc&}rqkso%4u=EW|h2>`h0QT**L>a>qLzwfBIPv8N|@Ayjh=w7W1Qn=>+9!!b)fqx zRCSaXh!NL2gR^q^Ib;TsxM``D&9o3bN!%YAZrn-(NBS z^goI_r-li<>*mt%Wtz8BjOWWAqV}iT)sHX)7re9^u9AXZvbwuE&cMx)M{BHfL7Q`p z#Q|c(5OFoNvphxPat-FVVfz&g*lBNqea)EH)j@4raNN4(7DE}6`}yH$foiemQJ<<` zIPiL}1l*YTulh3knVFe^%hswaGMAO@AI$7X6Y_5Ici5f?1RR4h!|2xs0aeZV=61Z! zyUUvz#(T5Ze%Pd8$Wc|@LhV|sn=4m;cMfb~^47^o*Zui>r>Cccgb7cckxGiY7>01) zZJ7)v6Tj0RJi&_RFg25x$0nzu`>s{%biLfQghLZDU9rQeC}#Z7-RB6QeWp*|o)ISz zn_Looc#K}Q5+V}O?EJ;{@S&>ec!Q_s?ad`wOg@61-uXlh^*QQ8e$wlfXF}{xKcH@m z7UV=lE#)gW4si(RHCK@e)acf^1Y$4l%nT0>>W${>q77n^3HI77&CUwIU@+C9E0NdO z(kZ+=0s`05*4}3a9ec5?<770;8KYoM#N0;L7nlg2?zaisIcX{tmRoOZ ze$Gw7wCQ3p@bCa|lSLZbe!9Pq2|_utcQ$Mcn*gl!2?+3! z^1D>kt=(;2Atu`sZ;*RpHWK$~IXI31u(p*5yfeecpz-TnmWo5Wn=spuS4j{3xyi zeQa(ii!`M@G*f2F(rPie6^tRik+!7C@|+H?n@)TVQB!eWC^|g!G!*4BHYG3 z_)eU|Q5CGN&ufpY)}Y9^bi_R|(f-@tR(o!2&1iq9Ht-8#ZhtXxa)p_uVb40_Uc^fp znHJqN5kEXjnz4Jk8=2U(U7PDdRJ<^lr7qA^HT$BZ^IhQI*-s*te6wF<^{sd`U@Gp5 zqB;sLHEA2)c!Po57KFz#(Z{jX&pu;^u~TQ zKtVxaYy5UL{lk-@eh@|hoFaH(asyViO5s_xVGlkcx@~9r)&oSWPsn;3Tn>hc8;eel zwgx-}0QYf9E0@}vDzJ9E!Op09!*4#;%kZv7qoU4>GBZ8n1mQ{2;fkf>{9GSg!2Zl#1cH)^b=K$3+rHn^kI1NByBTFs;?> zR7;*@pJT(&Fe}c`7H54(NGu zKEyC1j*T-?(UfZ@28S=C0BT%f!NmxqNL$gdb6yQwXCe2i;yGxXialX^zoQa7SN0>< zRiHtW`5t*|*S7|w*7Y{t@E>*gDlbpkCe`Uu(vJMCcl)ff;BrSa$e8DlsVWR_>HhvM z#xvRT5$5b*5`kZpeiT`Gj6#%g^>(_GwJ<_*D(a}6zaRh1DIg|a?v5!ib9^5}9n}Sn zM@B{2U%P#O?#>NK#l|}UID8%qe$4gdo^|7O`Uvmj2B-;c;r|L2t7ZjT0v{QMrK%m1ygB!2Lfu!xZGe7@zG z@wb4vJ`l$54@gRsP}9;rdALpPS8g)s(d=gnmKAg}5JVVXx}y>j0NJBHR6s~bXgO7` zQ*)ejaWVs-w*>0*K=j9o>!Q+BR8%%|1ur1rOSto15}r)M<*vI`rXsBzq_Zc^nnqxg zI!%8bL%aN2Poi%Uy@K?%Y8VvDui{v!!s zZBju*yxeaL3=A^1pK0=R9PI4GY=8FpQ*4U(`LBx7biE_Qsc_LfJulbW=>d^fZayB{ zu>=SKBir=-{o3nGBu=2;>S}2Mdroc5*ut&`Zv8W11>CR>fL3Q}-3hUJZ9p<-yReW+ zS2wNMH#BIc#KZ!UZnMxVNAl`bmBj30(iSYR7L_R}D4^WY;>Kfz2_FKm$o&e{4vqjz z!Nk-%koGK+!FRA`=67Wm zqW7g&DjcoF9mKa6*0McNWopyu+OGaN;i8n9Gs0ESk@iMd!^~4f%EiB%UQ*K}iNj&l zo2y$3dDPYEBXQriMjT&`%~~gnEU6WYGqFpT$x`UMSg2b~nnO)mIW&j0XT{DcbN_qN zm51RV$cLQo6@2?P5FIx-##dvzWK^KSO#LEox1v+C#%2L}d*k_%S>w;jQv{U}MBHY- z?cRe6R*iDuJf&0~`~J4J1V$mRtE|Rb8#1yzz-Mg|p#|W(=T`s}}2cUvLCr z+ii|)04@VKG|@P}=Mbz{@7DK(AauA|buN=OpR&h7zPrq?jkB`t|18RyAPxSp16CUd zU!*3}D$8+wIwU27wdXd%&u+8|0D6DuKC z`;I?tsbqM?M(WHmicbqX@drk1=~fdb+EQ=%-@``nsqnyzPcGbGVU|ozC%RCZf%}Ii zait`8MJvg43dTlN{RbU@$Y6o8DxkEuYKMm_+$9p^ueWj(4~9i z%o?65r4psP_|sEGE6DroV(ggY$$rNJEYDT3n<3KnKat0ul*i<%9Kby}#)#AHF@Et#buoVA37}&3vTOa~Hu=Y2^>@BWooc z5hk|>axLFKX3#6rlrfoC!2xrFfjUubyF> z9RjI^M<5e6mW`<_%#_h_{KER(1r5)ECF_)p(#-&&tGTn@8T)7f$7)McTkqJ;^!wwE z=jW%2hg_Kc&oV~GDU{2C3w{|eXHx2#SqZ4*ac;+4=0l&zxxn#v1k);)Lh2kJEMyYM zER6UB+h~T@c^WJfaL}w9d5y19I2#L!bk61ARp2|MVNqm5-S?_%CZ6Vqf&@$(@PEhX z)#q&frf`j=e(Cv7FfGa`$?Oz9_iz3)%pbIYO>*!3l1VxkmJ_->Kbb4v2zz7DeswbL z1+QZ5TBF&zY7iqbI6|8e*o|{!Q)Ua*hnY3G9QStNHVbPYexmS87W6cl zDklW_GQim-zcIMjYb?Gz>}gYW^mwGfiCtkyM|ZX5AS5CEqLx{lG_F+^8C7m3-@D|X zIrh?vO*k>U+X^F6D0DdF1izA{D6zk=2`WW@JwSLqIoJID==i@9rd`Y!gI zUA)MsTn9GGF`NI@rX9r;%3H=P?zK@gRGDI;B=-g>b1T+jNO2E-6tegy=ISxrb@)2O zgMC5ZJ=|)EkW6*aEM1<3B4Rz5RnYr%dooqv(gBASSmP(}(Kceos8bn0a@)s?X`{jA zX39(BCj$z5>S}`mlnW7-}(3A80BbUwMxv$IIK6F1QycBc71)xlf*($KPqY5 zYb*9si6K}}?v8UsVOaH0yNNJ&ZP*cEIlUS;?S+dQUW&GB)uBH94;O$ksx&Z0k*(o= z6tU@$JESG;Y)wrx)b`iFV-9MFkj||Rzk9wvm!YiKCi$DLkJ_oR2`=nXeg%rQ9G-K! z2r`6;0SfP$zwH-R)*^>lMHSq}{7WJsCphWLfjITI*!8@ADrmw2x~pq8Q`5s3X4W)V zdRQyuKimQzu_m8lfc*Q4$CSqEmQcwbb#jL+5|RpW6*^X&{{OTGv*tiH@XIugw+P$; zu~{{iO_#rK?|MR~q$C=8dSY%MnEA4MWpwK*#3Dl;@0MxH4D09)qs`aTsCKSYCs42_ zXnG=#k2(DLD@QtB$Hxl44i`79sBi)aoN(i#b84Ob>{T;mCb>Tb%A5S==3gg5@Re>9 z{k~#nsFb;$TWBQmGRC!L4>l*djz#>lg*!7f{b2J@q+xVO?ArFWz7Y*RDy9H^@A3$P zvX_^Rl`KAaNJ0V?4^LiJqMT0D1y*9YR+&c(4Wp(6s+8F(N_=7fjo;sDh6YGiCcL|& zScXK-|Mi``;tNv4%`Fk|nkrI*xQqjR;cG_mycuuP=`u!#o)+|p%Q5El2Y>GFicF`& zBZpL@t9sIeN9DvaCagyj@kAx8EiXr=q?m59flHxC(=f8POtpt*xJnud4w{+PXgtFi zG~qDAq{Njh*I?kHnX*}_asbyF%;l^;_sgKaS1hXYd+ePn0~e!e=2$N7d1AOR=SebU z*_{&P^&3{*iHV6RzIT#YZ}m<{owJ~MxQ7UUpdL8CK(8eg8Fl{4n&7gIYAdTMN0F0T^dK`kA-tI=2Y(XNEDQ)|4vAh zi+@uNn4@9yozQ!xSaCyq$k*`I18EYByLQ5TEpJ04VUcS_Yb*2&V-R=`PNC)Yxd&-a zsp~m9tU^?9iRiA~pK`jO3{wpwD^nwyu1;~7Fvh4kA_D$HAgn{RVDxFrYl*v7D7geM zl^(Vb4cH>a!!a%=Jd<>y6*T>l=z%qJ4hF?1|JbShQ27Go`(K5bVxyfq%%W+*6EXF~ z^WMpLP`)^$x3EDIL|l>iqOLyjuRp1ejVRn5K&ewyi^W6jzK%Wsr~Kt7UA;q;K)Dj9 zQm_)^O)?0+{r811=hy#DW%EBAsbBY7%gyECoX~+Zp@EUF|IUaeZZxa0tuW%>%nJ)h ziZL%{j2qaB`D|#|(cYdaXurEYxHRfvn>CnuP5t7a^LY!vL14gSNJ0Z;Qg{QWQBfxf zlo(`4?!qpV=nRI#hhiA3>poA#q;{Tu<8{MJt*vdge8ulV@Q=U~K2hCpy`MG)z}kvQ9<^UCC!WRf<({_+9WEsO zx5CmlO0lOn=>8i>cQz}OlS2Ffb<#%G z<3{h1H4UQ5m7S3>3ENKa3?$|dFK;!01Y)kZm__a!Q&($yui(xiIvgOsz>N_#wG=NZvDawCTfc{E1E}%X5`=OBOkk$!osrD9=f|TV}BYzmi_COt^dsp$7)X`hrGD=%tVp#sxDh&nknRW9l1%v4d4gCyjR^;VqsWlIX5o*yuhe?LRCss=!8rN@Ok?N646SdWyuC3+94*cjBJ_gg+ z)G%2ZOzdGH;>eXl?dt7yBRVNG5hEpq<;W#LQ1u9m){184Ja310rkzpm#1Cc0-hW0- zCo_2Bs7&BffR42__Qi$_AA_u@#kn;plqEHlWUTPqvMp$|#{FFsO(?BjvXHml!J@Up zs7j%l_L=IPU2;=H?1h?&9dBNd`3Ga#FBVOX1uw4SHl&2iyrq=-lXIvv)s<9efA}Lj z9QC13`wwDfjWc>=!ESqVPaJC;^X2T&5Cz5Id!-R}NM}nx*y--11gh!ZpZ8Razvv2C zQL^pNPtA?lj~C;TQ;I%iM6|6dP=c%!`Es1@IH`bJGGm?10rXE%BN};20OrEb7r>Tr zSWfw24|NS6?ao~Kh4-iM1K9s5DWiL+6bP1Z@KG_6 zkAk@e=qrFoptV!)dBn5s%iY48m0KTQ))$b}#_zLrrUK+y?|m=se|^ox#lpoUtGd%Y zYF)ElZBibzmGYl!!)=efJ~alc)8Y_ATsQ*)}KnuZE5?v(%HU13^g#w4Ic+bbDKQ6 zWMw+txz7EB3a}otS8c&2R-b`Rs7X+8)^W26q{RUj5;C2g^3; zs_Qi4nHMa2i^kA?ylUaim8fh;Z%8>z^|#hW`_ZDoiiZ&-Pc60{&&_>j>Lf5wLMu?7 z4$Q$+>$F)Tqeq?_G7~HKN-JE@8zq`-%IdYzlfqj*xT1*?TcVYo24LrcrOe$?7zOq|*iI#rJ7e0QI78#}eFXCST;p zhvW6JlUj+4x*F~)Q&G`hMQnVRLb?l@8X9)QrluP;&E>~FmW+&y57J{lR!*5Nw3$_J zKffDVv*gNdoVp}>Zke78(;z)Kd!>46D0WxxMEXuNyBi%MWnyWenJkpRc=s>}ub`~7 zRGm2~DvFqxI4L1P`D~Q+rt-I3+N@tVkZobT;y+w$!>HD>-CqCN?6_>_9}`1O-rC*$ z_IeIO-`xD#90|w}cXvKW=k4{}9?&d`P<9Orta0_HV4Ru^Ct?rfDR#)F2%wQ`z+#DA z6bs*0B*(|&0(xL^aj4F9xT?wp(wW&Ir_(6wadjqfwA#l%Rld4Q+uGJ^M# z4@Sob)%g>L*rtFgY2afJDtYz!aliRu%6O|NW@+^M9UUF*>K~(xg+Ic=X#L8q=TwSi zEi4LSl%*iwE1d^kvSw66toKsgMky%Cj=`W{Lk5py3dXA-3DWJ3=_&<|nI=FIc)USN z2Hf?oKwZ_|86_G2$jl;L{x);Kw^>_T+mheE*QYDPtULyHruF)gxQ`AFV!J;3Vb53w zWZcQ$>H(W5UaTVkR9gKr)@TzamD$-MV5$9VYC$7MQc}3NBPslVREckMuIumh#kn1E zO}4^{-J{Cyio?HtRJUpJUGrgP0{JmA79c7ROXB5zN}X3wy&l+>CU2aVy&p#vFX`0~ zNo>nu+}{f}rmCuUVI=I5#r@|;FROT(aA-q76eC9}WI0l`5I=b1HhTJmbbGKR_}50Y zy%EoN5gy^Wyb%jAzlm_BC}uTJcg;#jX_>v%T*Gi)RE}|nPfTck-0vX;S52&X5)hSP zL}P@~p+8XqpBX+?heWOtu@c|M&|E0xU)0SIjao%S=#^#M-DqcP^9{;z*N)VrO6 zy{p&6TQKb9`Mh2aeqVJS5mS$yIoWeas;G!9Qo7-6F2gqfD=F|}OTaVc0lp*P=(xCF zn{7`hq^DPYkP0Qc>v+B|`YKvdj$PdGC@RU@ODII;9lD5Ai~)w(S|Y_YXWNQSM2lV!O=C18NQEIJF95 zhY{6f7>&5shb!$rG^JnuyRb04#oo@YtG@`JvW=Murp#bS%~>>PBAX_d6cIrm@x4v| zO;`tz*0^4sZOnRpEl`1V_4UEBy#A?8r0J;7;YwyKxIx|SeYd22|EX1QDbAv5oGmvU z9+!$${^WIE+f?CS>n~j(unXGJ`EmF#R*w!;0sNCOp>XOfP<_py`=-}D4dLv@Q8L4m zQO$I@GZu zhljXCaE;g4iT|mt_(GIt68ZaTnoQZu(W@b&PDVNNB=jA?oAv1skn87s^1ODM) z`6GE;kztNIkg7yTmgQ=kj{_?N0T;uirX;kE8N}gsy3zn-V zU0qjnp2sML@;6Pjrw*)@FeSwm{|U^=8Dp?Ht@TRiDjSHXq|>-eSMqP&dt?hD zp?O!vYpKuzJi+p}yHL?F6&1`G;$%MO^k!xy9Se~e^m=yN=6K+j2p(g6zMFp|pRAK; z>2UEpupKa=U*V}CRs2f9v3-DZ)@$wAmDH{Q8A(kR)hh1X+htRwm6Ly?9rNSA>`qmr ze>Pk)dxSAsywy@bL$}uJLos4(%xJ7PPok^qhB5#M`BpYJUl0@LK=X(=?Z~*t(y)i% z=Co2$!MVl*Xyh;rF0yyOy$48V5;-lK*`%R%K}G&r)d=rp`6o{!oD?bkL(MHd( zoHm;O;w9kjU_Q|)0A%HqlpvSM;C5K=?&y8I4z|Jkg|U1Zu9At~T2&;_kkmMCZ3E{6 zX=coZW+NqjS5(;9{9c>Yy&JAvEI)`s-uRW z?c2y&73nOI@PPza|5ESd5j}lge?Q#a9XV331oefae`?)t0%+d*hQG!>2g~!qg^brB z1be8&;Ie`gCYvG{myocsFz9wwHKBxR)1iQra2N8Esy-?N$G9F0 z#gvyjKssXz$Ug);eeK8gG$|=b(aYqkuaKItCt1(3?~SwX5Gt-^yxsrXYCXabIui{jc+bnY8Hsi@lTc+%k?PFC7k# zd*Vv`!T~flHZ(%>zh6I#v4-X$c)J<1H8}XjFTAre;B6id0bH)H$7cknyqjV-9%ytq zh{S&J{NPVBqAtqVeFp9_Se7M55%HHJC5e$04$lwVnJ9S;L3QR{1<6Y9TRjnj{+PAy ztRXwE(7PW0baS2NU)XDW;4s|{F^H;?l7@&|SrrMtrmM;H_xG2kA$jBR-KvUTL;+W1 zg8^3th)q^kS6>9i_dI-uaD**9E-Ncb6BS6}H$_Cz0^}|LR5`Ex;*)x)Uf5b#)D_XQ zh`eEEXUubkh+80%F5Z;blJF5-EGBPJu&}&WeL-?vs$I+7b1%j%whCg^E0+gTesA%# zWvp0tV6wU*COg~LS0GKdca4^nRhNzl`QY~7Gi!inCZ{a(SV}&=s;B&7I4fN+8e5?c z9i)y~hvfNxeGI}Uot#kn>kF$7k1s_8T|j}5GK>Gun_Blg^zj_}{QF^fEaNO@@I)!? z!^1;KOBlNT5gCs(-3vjtvv&Z`X6lLJISaj~!^P(t{I|21g)?~e6N%i|*9xc0tHmc7 ze>SocLfE`)VFm&j2Hc>>mH(bi~gvm z6q=U>JiU{Jib`xz5zE)F0UxXb>cOZJXDUZ4QFO)h^mv8bSw$YR-ZJ&|IcrM{o-2B+ zAu)#yPT)r%k8|sUfl4e6vt=tiJ%!4mt?$o2OvRjjX90Snqg6|=+%bu&)Yam-t;e!l z%YN0wNt*rb?{`}CdjrJmW##22Be{BRZjV)OPj}eT1nW0P?ct@Rhr6ToQpR$-m+lYT z9QIV^V5$E8u064Rd=4h=ORGB>0jF~&A1=>a#*1}-OLbuFIMhZzYWba)XBvuyWoQa3 zHHhlLlg!Q+3I2tTkMFqo&KbF>VZkXz8<5p%w+#7jZ+5CO0l~Ccp&qM!-DCZjff3i$ zctCr7e0|+eRX*m#D~l6KmJ19pVpJKo5Abr-Mc@Rf(J-L zBCsladm0y7~-MoP!@2J#f=2TL@xzfYc756`L6Ab*vU{1rZ?>@P4jcnY!g0 z5C*1Fsexj_C>SPCldv%cw};wEcK*KoIPJCz7(r)QO$_~sUd_o?j z9_`jwoFlnLEBxrQk&&P~=}e8X6sSI=0r~GLQacQZyNN5z84-C^qt8bnmwOLHi5;*> zjq4O1dqJk{qW`GKQJSgIK*3G^L<52IziQTfti?#b;y9*)R$DQqmS`l;fAS8W82qCi z24yg?G1W=C`bfeuOhe@Vt&H4z=(K3`UB#w}Dg`~)1cnN++OwU0n~+k^j1g!ud$$&A&UNc>Yfc;XjA|Z)$n}4>jqa^{X1O zWp^a_*E9Ja`)K3`wu8U0{$ua_=OKLmzdz#tUf2A8$QJ)^Zlp{lCq7}Vx-CcTCwAe8 zO|@MH3yJN?0A;Cpc@qBK%`MidhU3b^suK0~LdCirb5*vU7sq+ZWZ(S#+x#)s3L550 z=}s}thO#7}Lj~RI;z%7oKP|8XBp+$8St(h6V2JTR&K!1jx}%|$0A&f0ke61;sH7*d zddY0!Z+#u#7;0MssKDfMJEu{{{NMrS`s| zp&?XqP#DJ4_dkUsun%s+vI;8wnb6s5=bJ#*I`+rAAm67Hp zZ=Mlx>~D@r`Gt>+WI1kmvCEfb;be^a%(A5>unSdrUaEL_NZai5=*|g#OL|)!Im`Kg z_A^j9KO+;pIq2YRVSeewYGGlaQmk`6|Nf(eg@f>)eqK-yd@OnlvW=^K;b&*@fN%o! z=EPW~hbA0P$+N6xYHA{Z!iZJv_wNyB@7X#Y=e^m$urMBnb>W3DihzMNG66T2oheSk zbNA)wV`tTEo;)mXU;k&8-O*j3#Cx@0S@@6auJVK1NL&H;mT#Dz`>%a6=!$@9UrJI^ z9{>)i{NkJuZ#YQylYH7PunamjWj#BqOqLK@!G??t#GNBKrtO%l*HzWG!aBuH*{09( zlvIy=zeciFEPGYa1PqMdoQS;FDOtiex=C$ze6sQ(?lWmsVKR?=a}3{Pcy^Sb@g7}= zM_f!o%kJ6GP-g^jpg2`B(0D%+N}euGOH*P{FIl8*Sph|*IyDYm&U4oj)%KO3T3WmA ztOwLf;#tYlL_K=Aji}fe0ErK3syd)7%%;Z*1||9+J*fX~bvS3>DcSA-X5{%{Pw`VS z?GoB76AWHJ>7Ji0g*9B+*~YQxfJrc2<5(7_%KbnlK}BLO@hc7meiA6cw&{&80d*3b z2p13y1_nMd-Ta2R1vE3;gEg$$-YFbkxIhHuq#WK*?LntY!C0n{F#O$~Xb zvu_F>p`h%23ku5INng(09Tkn-ar?|qzHwI(touvv2=(*f z(^&vo#w=NNu0}!k9y1)BUs*S(tz?v$Hcf z!E=YnQtJxKOU3b@F)=Y}Oo9&U@^*IJplI%8Ls9-)Ornw7<*4&ZxJV`E_B^mv*}WGQ}Wi zTJxzXConJ&{8T}S?GjDP-c6mW{aWAU*Vi{JB=W`A%DA-ybGzi8T zX5E|9E?LXsy~5lC2?o}sISmP8R!|tR+!X}~QgpOxkhSD@ng9CWNsnDc&tWk>&@2## zq|#!uNWAtdw|{wPvRQyOR7_J>9Uwn(&W7jwf${>crG9aNC5zr{I?zKq#b8`nD;4`f zDJr=sS;O#}PPB~s-R*#)WTu!-B;e>bDionmDcFE^G&Th2fwQ4`U+q8%gqT>smoMH` zO$2_}iNB7E?lh@D+7EtF0p!Zp50+@FZbu3p$Gw)wegWxB^R~KOiQ_a3Nl-NFijJrs&+S5{$T6M6;@QvoN$JX;OM`Wn4iTEOv@Q$o36CJy+-Ic=(TsO#4bAOWad&^$@TS+O8HV?Q>hdoX8B}urJv`Kh))fLqzxvi$ zNmr>g1eLimYEAwuZc7GV2xVmI5*6*o-in>>?i46BNc@s*{$_^7gjJ`roghTlu4#r5##d6ITpde=z`5hYe}fx7E=}Et02*uvvLL z3lB=c-mRC<8v*L;nuJ1J5t4Vmb-_;cn6%1n1@P90MsMrt&}JnvW?6mxp^Fo5e$NYs zmTxDI4WPac)k_Q-f7RFnTgWTdu*wQG5{iCZt@Vv2(Rx-QJ9~ zL9xtL_&KXF$7D-l18xRIygeYBvYl_tE*QXlS=o*8J)tdYEQ0x$q@+4SwJIez%?q2f zR8+V+T{%D)acjIMxRfY<@$SpOudm|IAL8|pr`9`{aQ{v=uI?!Mq$-c={y{`uNm${x zubWdzT#Ky2Jq!k!=L)~mQSsf@yLONC>*Fz~9{QnNTzVZ+Or|8H%wSsF)GC763d{$7 z@&yUDCrNG!)m3NBY7h9$l|A@%31*f!M)l?eoBxZpw~Wg2>-I(wQ2_ywP)d+SkdST^ zq+3cFq`N`7Za_goy1P?aT17-a>F!24r1MPuKhHj6oc-)E&UnXu?+<=Jxa(TiT66wt zQkAP_3|;QbiAYIFL6JkX3e<&GR^YWWyTSY?aI#cYYC@O-8TESl>~lOfna*7s1xfTn ziO+q|Jzt$K2zVTSm}?D!o+(T={n+$sb_D8m`Z(5ixX;;FPFp9b4cIqnR8|M$x!gaV z+G%bMEhh$79tSMS6KWZ)5**0Mx-wO=^KzZtyA$s`yRDnqWa@|?Wjxu}RAjgkyRumX zPA2c;ozER+2CacDV4?m#>@3>RnPKL(u3Eb}F%^h)Q3(}7liR`G9%G(E=>dc60H_{%hlf>-x6vb+o>fHTu7WrM z%8rDDgyAAJn=go6hZPN*iDjK{XC8~IxO#F5+^UF zR7XC*z9Hy+Nr7h^1~d=68_3wHtkh&wSNWwMt;nQX;^XsaZRh~rJfs_(-Nby?{*JK8 zvti=$;ufBAQtm2TA6`D2wShbr|C`^!!q#ISt5e`rOeIS=JJ+;al~h|iINUz69Nlp- zTKlhS@F5lN`t|Fs9e5k>=d)a359`Yk2S5J{*5<01%-BMQg`xxKJ#l*^Ef}HZ# zRbm=6Y*v-QL=QUH3<7hKlGaoBYK28whf5p){nYE|+})pyi;1cBIDwmc-TOS=7R-rO z6O-Avh#>LN3BHf@fOIyU0;Tqtu|&%3PB1wa*T}H*f$#M*@ZX)zwcfhnBqt@MQSVrn zG%*bINlyY>?e``IiF(B5L`yh!y~W5DxO*T31@duzFLlL(ZmJ?BzUzJ5NC(7P5GU2G z5A(cf%M7|h2KIdletzN4>I|Q+DL!Oiu-N}qK2c+(USnxyXt+3BVh!qMJ+%(Lcm179 zMKP(Vmn&%^Bc;`Rp5xLYA`8F}GcjpWF)lBuxKD6$CEjajuo)N`xpVtActtWI54DRu z&knh)Cyz(Vv##I7c#%uAC-*#~J)7j}W)7{-9aPj0)!LNIIeulaepyhPUVtkJwofBN zLy2JeJ=3_YzjwsrLfHu>vgsB@3Th;zb4yYIbe)FbIoN%cv;pnNx9w~s1K>jWDe#wi zzj}pEJW^rja2*7f2o*94 zY&8u2_R9HG*#Bq(eIEb$Q+PbQZTC;J{9QQt?+=hF{&#-mb=yyc+Elx-!GF+!&d#7C zo8Xw{Q9EHfu76%A25bDmKS0O-^*8gs^O64NXPJ+2f$IT}bi`@xO10H@q0O{Q3a0I; z)%tOjIz)t9);wZNrW2o%^Cw0e^L=E8AGb_%P~Yn2OLRmQa9TBZyuQkP%y8%LQ{>1z zzSnas(pw!cepqQXSMKUcA!c`q6*{yWIyl_7DC;OgjaU19@9sYrQknHS->!8~uE`Qh z-H9mT7At#^ExeShz`?s@3gH|3|4^0rGCyR80-cufO!`5Li(UAVS)Wq`wLI;`(4?~L zuIj%&m@*Ns3SrWfNUAdnpK-b<_(td&kq2hi4F3pab5*ne3!tTg@^Mk>&a z9T-YT5U7CHDuEe}ccn5}9iVqLG$~xG@`d}ET8~frLO**-O4LDG$=@~nbZpd#oI@al z9D%pttf#Nvy|8P2dWV<6vjemM)Myl5CwdL)e*#5+`KIs)*_W*YN=3qgJX! zbU5li&tas~)RX>3S#8Pt7FPue7r2uZ;miWl=NIADu^~cXePG3ATD;{^^+)M4d~RP; z_h?SUw&!;I@GGOC|9TvA;Ey^oKwk0VzyiCTgq4ZN}(zUWE;3 zaT2EcQ#gMwo3hQ~IG$^f#|7;A=hS4bTGP>wqR_~da^;qHPb_^DY&$vf7VP=x?>CTD z)`VH>=*$_={_Co^o-m0NdVld&1#1}cCWatLG;qHem_i6E$m0?bZ)d zz(nRPu5_`rH8A;Nz5O4ec!^?83)8g-&hW_(ecPIx4U?GYuMgIibiG3(icc59KbPsY zq1>8rahTz>oqf8hg?{>kQtt0tJ|;v2iK5(?^1S3v%r#3;VV4#1CiPsA`vf3HPFz|1 zOIaPWf8R?%Wo8&bkqw;G982>#(rm`v=7agGAP=VMg0gFP_DD=ASEkAKQdp|UQq>=u8MJZ7+H}ht?mf4T_H_(oey}i?xex`+7 z{kb?lS=d`Wi0{XU+^v*L^nD)?_h0vxf9_3rX%T&oowCOBMksi2glnvwAffLOJLXU9 z7KOU&c;x?lu6&Y9mV$bN)SAe*+bAg5!r3Ou5p(6wTUKoX?l>d3|9f^t`1O8$jii8A(M@x-4*N=j%fIJ>Pv<)WpZc)5-2PZiQ{m6>u9uf$#Io(S~%@%K~4NI9$4ynp7r@BT!Q;^i^dQ#}GPnSpoN zWNc|Yaa^rLw>STib4c`2^h7GW>}B_Um5zLn>%)wo6Gj!K3w}lL1^e4*#Qnxv=dzl_ zV1JZ<9fL7F)#Ay7)`P_v;|PktA)e|&2W}GKd|{mp%3GLDAOy@kc+I!GEX0bkoM_6N9|73z~CU$u#J~6YS|C^>qzuNRg$=*x_!D;bh>yK^8x44&EZqSe`6?tg#p9aBtle?^w5JIT?hD8~85HTox5L6rC2 z;^*Cc`&_H^#Q@j0Z_hg#12G7-{50CWJs%szyNnk3Oz)~uYwfhO*Y-UR6x>*ko*8*P zM>E%~2W8*w%X?*}TT>0&3+wI85XvNrx@yClZ&9oB=uv>oQioR=5jzW0cp|`|FO>KB z=e)f!UF^o9)6&RDNk1?Ao~X83*r<9|t5JP%3+rBO{$;K|3i2}z4UMruy!02Dgkoy) zfR)`t@Bg*By0o&wpgx-;Jsrp7DlG_9>*XBpW&Y-tCJ>JInKbU<;Jlc2@)aKC2C*Mas9*ANA|XuMao&QqBIzr#rcYCO+Mp%P@)t@)@{Mmjz|zPn4- z)F^l1xnp~>NsaVLURrcBY` z7<|>u!f!0qZrSxudK3CKk!`}hsHkgzmfXePT0WUORl9r67D6W%*Bv(14M#)Q~dObk)5!!&xVzqw5;A{-JID@lU|`n3!HAWGlKXwR*NJKi_XiJRjCHl7b`-G z;h#rJFMmH~-54M84m{s&GE%mb8Qe1p0WloO#knMO;syqpK*Be=b&{2$ zhvk})=?WcQtdH1?-un}E#qDwY6kv`_-9{N{X{Z8z_+Gf@I54U=&O%>td>oF5Na3rw z*!HG;&F>{4k?-r@r4up-hGTfI!6^uDRWsepvldTy0iYT zUh?&k5=<Y&k%j)g7sd4-TjdNuxV(cPOVgn67i$9 zeA&J(DH#ICNQLxfBW``Z16;SwtA5eQuAf%zh__L|y*x!V>&xVUn=CWuUR3Ud&Elv? zP}rL`QOE9UNIp0UiVc(#D$YqalH3k9cF(pky{?)*Q-!>R7{C+(lj%J9G-|asn8Ybq zr2N8)gMC@IWa}L{pR9fnyT5@y|GjVFMuAVNTZsK?i>*gM4~DH#gvfMV4yC724$L zqZOhK9V)Yz7kV9g79-a0NKQsl1^B*Drt-VrbAk$~!6n4*<~2BHVATV^06^GKy02YJ zvnMQCFd4Ojg15xsrG=T1_9O#>{RW{Oxvy^QTgkXG-IfYFVMy|Hf`j9s9Jl-7c|zq1 zH5s-3VaWX_8%Y3K3%?Ol!4#G-H`gdq)#!?2h9X`*q_eUfvDdbHkkuB%mrv%@LALs?bTd*tAe48R8T z1xL70S&>Z~3q zo7oVuwcUtUB<3sz_&>^#h`J2>27cn*`#8r&n`7&bTp{UlEE0e32{}0xRn@G0V#aNz zs#;w(!c!=1n<1Jk&traMD6@yhKhNe%%N;tKKX4bjM_Gb zEetV?W7VCyp${bx+#g)6gjg>GcGiqnl+KV`;ieZ{UfpkB@qUn!l0H*> zjuX4THYU>VA?mx*lLfB-uXDDhiLei7^SZcQo}Ywoh(e^v&qR)~BTV8;Cgudc6h@{S z4cNH244%KntE?zpbt_s``Wn5j=4xlwtS0Kmoc?f+E)cirdE9#m7AcU}1R2LWTTP$_ ze0k=7d-W#;9{SnA=0Jr}2xN$gi-}d+%*0~bUw!u98%0C%NlOl%M*t}?F;>Fs{%w7A zKteEWrrwD``1@yX;z4@vfCzGCN+zlu2I40kruO#e6JafCWvN4sj+eX5T9d->yv|D0 zdPpO~A>JD8?b|&ZfM^d_rx+|p)6C7yaleHd5%+&EA1a=!>gemaI!yO924GkRw%yMg z?gEFdZX3=nE=?XM8Vh2WB_$?l0`8@~d4&D^{73HaU-sjW5yfSjZU&Nm6ZP&#Th>yy zvAjT~-K$n!*55xsE6W-;eVf{)<|E$5mpRIIty=DekCuD8yX!M$;rbYTre;k1<+_>sbQjVY;?hQ^DYeYo49|Y1oS3XB@&E|J%L{JrFcN{(_wV)fpOm})HYUNMU31;vHK3KdnmDa_sfKEX z&N?rQ-10aO`*ddbF@^|R_J@lN>sfC5j zbfZeZAN{Nk`ZFb^hLU4=n=qp}Jml=S(N zfViAv0C9S>Ge;>aD|^EXAv_0NG=1?Ot+?_l=nTDXVzf3w`PXRir>7FS^DiU^N&R14 zd5z;tVb zmJW9#fK7mLGo=5%oCmE+G0F<6l%nSXd>krTS`&0OkPUV=@G97Y-&sjoT2nL6e5i1H zy7>`nQ(_`GI!;dN*a1q&isVH;52g#Ax8>$1P3u}(URo+N&Jq$y)>Ce|CK?~TXqdr5 z$$TGP&J&r#H#fJYCblNf{_iW6ef-xeLJ&gh*~h(7)M!7*YFz}HC_CG&g^+NFOZ9w& zNcHpy!o!_oxM`75RHhK@4uf=syWB5P3 z_OuPc#YPXk=totT!f?%p+0*H0utsPVAdGFE8!tzChj~J5iQjZ)N_%0#*{rpDAh0PQbyXQ$DCVEY2 zdbd=p!dOga>BZM}aSnn&McHJ9y0a%rcmanq>96YQc%EMd;I<^tBe#K|Sb1ApOY5m# z#E&mfVZ|vqNtLn=6Q+NqKl=S=&F5#MHx+2*$ywF3h5Y1SAC0GjbVBDkvn#JFE#CVl z?EA~13{d>XFd3dyw6%wmg?U|OL$EMw4(5r$PIb{0e+Wi{^FbQ9H%4r&S%MB;&gOQ5PyQZ zr<<3cbFnNclE!yB@H4vSG6MbD`fB-^o-M+{4v*Tw>7@3rZx$~x@O@DTI%2fT&q*~{7<5xB<^(f*5ooXjle6LW0hDqft zFpZ9@2}=dZF{q`|_jHuT!s`f|qq)nq%>N*XM*1~F#bc_KqepOj`d>x3^YMcq!72j} zn}Eu!(C~k%kN;ix-Uz8k=2!qctSfe`pM7)1rO2$3CbrUeviU)JdTM~Rwy$_NDG!eo z4FVA$j&k$ZY26$L|KR-Ax~^#g{14DD!Eas*qq-if#Xv?^UiSl$)-OvcGS5zhyVCxv zME+Z}|4ibr8mnl#lS)KMNx9vn#-wu^1T}=0t+kFdS{O?-vr0P}hDe`V<=1*#H2E~` zy^_06YRR*PBl?IQ4(oQx@^#4C=b0knk#=z5wgiFN9EJ#!*2nnBNR8>CYYG9CCOv69 z?x~(>DJj~M8_<0|L_9|b#Xbi0L|miyMea_=Y$At+^VazdX9b$_mn064h$7}PCph2fW4xL`&m_wKpiD%|Lh?Y-ic2i(HaVgbeJ)!!7vlQ31LpE^ ztG`ug;EFXd<`_R;*XUKL-^?E&$>Cs!jFNxw2uF6S}xj-9@Tno+mHfc{^Ue z86QT*C8nmP_AC)(-3IMV=NBQQkvEyQ)|30I z6L~Hx-6_zYlJYwmE{K^>ho}g^B@_M*^qN;TB#-ti+4GPvi4dgX{7!%SoFX{WRO2zu z+qU_0ih-ikwRx1lq9omI_Pc}RuDg@WawLj=hWMf@5gS3t8$lQj?}iC!h7+C^aNQgF zJ>M3()Z0NlooV<>7bp)e8SXi!{(;|5%{GE7nA~+on6Gv71?F0h=DV83 zw0O3c0)`qRWhO+{esCx?%@}o;@Wk?f=q%DoSzg{|fJXcppa5;=klTQXC6~lGTB`AT zb-;vLI-b{Q@9g6dm-Q*V#6Yw51fWc+JKUf9?QfEQZ8h+ARYRd?!a8WWZS?vzis)U* z?7kwCa2e|HYQUDK>KtgDQ*SZFP2@P_t@NZ-7FASKm|yY{|DnejrrlhJbjKmILOw-s zeRfs?^~vdG?F)G_T-*t{!d8)_8Y?_1RpXJtp&=kd!CPQ|L>fNj&OgjE8v1}ugIDf& zmr^Sj=;zU_KMq-i-YLe?w%g+Bc%lVG7WoAQ7UpIa7OTI0sj3-IzDUd+co7NfAMs^> zaxytN`SDUakt!yB8yZI2{h?_|6ekHClI;PFU?vYA*WgzlSL3+H^eOzQpDT!KO@yAZ z1W-ubSPuZb+Zohxq-iGR(see%NVfrDjXL8#EuL80!$gE~}l@2kxY zFU6Q2FV&HKI$!k6oc(w^@=SZK|>?)vUZD3 zAb~k2L$TVpr2YY)6X*KO!00hos|E)yj!=^;?#jY_0Q|Yy_lElitE!Tp zEQUW*E7dvL=l@{8R6#aY4g7z>fbn>#*4E-8-Mx_O{#(4f){$xwhvJVVTJJ_;;{z1_i5Fm&2g8{joLX9(wY_k=KNq|NapK*$BX;FbGO%c9@8J;5=@e>eO(k&C1G(=aH~P z$nt3regJP14Grz=@WOL%knjdE7T-IxMT}Z3TxwGAprpc*ccbuo6t-0_Re(F zyWj7PKJ*n)oQ^BQxNwjFZ!};pqd@jKaEn%5k6n#ovEKM)XCU5{Eh#4_=ry06Hd9hD z=8xVv`q2xz{W7gOPQ&lBrw5_a%@-MgZT)M*C6yLOI%H`!n+>)DE4Ml<nOH9q_q^q#}UwDAEp#iYy2Q^AASekQ<0$GJcHhS&^?G z__<_fb2|B`Le<<{1v;U(ZJ8Sz!K|_2^h7~VH2mqpcspD_OSVunNHt-$4bdPJv}DCD zghJ=ISEs3H6X(s}RNsu1;#eChNlHF1sr3hbeuHdDb|?I4POC$ZuO|txe6NDn=RlW1YH#l~?8k}do6aQ}L)z1sz%Xi+^5pdab3=j3> z@c#S<9DwLYa(ewNZE5JCwlMTJTv# zaQnih&`zx%4lpCPyPT?;}u4h4Yh$h)9cRsNWmDcIfJ-5ejH zI-bj7O5x+M7~Y2xszjs4*4d76EX*I7l=SSx;}U4drKJ@II`hTvEkH~uW}GT@{@10e z$yxgG>(_l~UG!TPh4pjgI8q`p*}Gpr_SUO{;}r?XnN%uUZU!qgZ;-`d+i#4bK^O#V z7|6cqnq0Vo;kB=p%nvK5!XrI#&;Gq~>1|_h;?AupVKBrK8a#SFbPo;C0ogAS+F?LmhG53Thg^)KW z&i<)#4rNK-TgiE)#j_6z%3c)Y2t}J0^Nc;oJf6!xRyW*rg}hykQa0RO7tp!PCV!m= zNJnnmox97J$Yn6YKtMh^aTc7F<=@=wRc+4u?c0Girw!vv+#6%pulv_0I_jsh;0XUVaD%;t?y8Ex*_Zu4|!f)V=1T(jg%OwT5;eP)6v9YmRSR|c4e(*xv37m<) zjb#P+kGj@bKF!&3a8$!+DzEnwDm0kVO432UCHsC-s=N?Q{$yMINI2hP%+t8AidG9V zjO9%xTS0Nq^P)Q?eZENtPa}OW83{@=-+#ex@Z{6$(UI49EGHooO)B?%`r{W8Eb+(q zpWbHQx^JUq0Jkv&^oT|*D}!smi+=9l}>{i$B>uRcoP(v_g_2TvB@0mVgc z-}*Lx2H>QRu4dz7-S%tJ2R~VUgc1ubY2R1>*H^8iJa^q7?sd8ybzQ6w$1r%JVi6j)R%BZ=& zIpE$AxfDq%3lfM%x6PZxJQikV3Fi~%X8;)M>(4QD6Z>yXhrIJpH8sN!fr)$sM8kCU z4V~HgW)|x#M$Y<-OhZ-PuTaS`a>SloCHTEB9rwrng8J?&?*btQr7&t%Uy1~@EEAsd zw|G5;Tu-Zd?b;VZ8P1n~PGCLYQ^0Gx8CIfM9bNo_<=74i5WQJ#w#rMl`g$&#)8!?6 zR;56{4S$iJSYZTIZn!X$b~*eCb-og#ITjFcpG5|+$o zMtVZ(u$7#n#I8Bz_|M8n%B7#uFhmGCC<1c}kPW2i;?aCFxg{laac~5$rawvS8sp+b zr_jKLgsIXXRP5u$p*e_VdF#E_)Tx%;}&Y66|iP3GC* zyLaz^TAiwQ60lz+AYX)f3K$k3-zMrT!&Ly2y}EE7c*1Lbm>s2Ba=@_9M4_hR1RwEymRpMsflaZjGKO-lQueI3Yqf6e!q zW(^4F7CwjFJzDG-022~A8`}y0bo#UF$X89$e0n~xA+w!(Tr3I5JVf+Xy^K%2cmF8k zJ2yGgmVYD%UT$8$BO2}6Bd5YQYWa=8uQ9U3>U=kK%;YwY-od(>qC0Hs*vaEY*2o$- zVmJSW0OwBqV3DB_$5GcvnOqWyNq78mvu9p*<#&iM*4Cb?ciCQEu7N2f$veD{I=+Nq zPktI5ow5oEXhV3OVHIn(C{_%Qj0nMlhi7T4=`6rn(e9AX1sRRpavJc)ogLKjmmb^G z{=y-CX{3D1E?@(koT`C9H!ZgxHqN7~U^m&CoXagME1T_l+yeyMa<^u0wxmI=Rq0fH zVsW{{&cScBMnyippq)3g;1#P%=4fp*3W-c9GF&?eiNM04`c3r#n<_ff_xcaIV2xU@ z1-MLOBlQQwkAjKxj61sthB95*?#Ia*8|T8u%Q1QP;zOa~=W1X7nqb4895eGzFuQ{7y1zEx@b&90oAIi*Q3E%j#xPmI3?<^& zpLFrjZu|Bd+9y(;J!Unv`w6d`eeFC=@-X4`lDPOdti~5%5R1^q1*8}}*#Q_`2MHeA zfCD4@`dn-taZ@?|`1KwHd!GB;U)L8OISZOG6sZH7IbAuT^m*z@`OE0oRQmz0r&KTY zyL6~<&W>-;t2b3uDYxYmL`tR78s210ydaciqnS#gnDNr@C7MDdPyVqjYmr~v@Vtmj zshY0?-O!z9K;;Zqm^(r0!I&T3y8;<>QVCZ{T9OE zaV#(YEJ7hG&==hg0aHOgxMYEEs?!uVX9?oX=SP4d^lk`-VB8#WMV^2h|I0qg;1_mAYvsjy#F;`PYs_4)c%PHWKnZ zFAY{~VTushn1xTL9NiDR5VM*y1+hTe6}ho{Bz1LlnI4Mp?I$BQgKW&>iRYDd?@0*b z?Gzzjr?nr{H!4}B-LJOrWkcHLg*86J-B$UEmb_n7b@}Q`*|YU`%ekIOU;K~SL^;*v zP*$esI>gJnxxbWse$&q_JS6*`&!{t-I^_Pw#F2~g;BT=|BGBg^9>lY zKDu$umQeN<&GtQ&&sx+;+>gOX06+>lJ<^UecoLn@+h5n@=x&Y&_WLVU4wOE@h>D0% z$aCHlr+RLu$it)F(V^R|yVKp#O(M(TagUFHn7_z94q95xw^j6+ zk=(v_?IQ)u{M%k_-c2rkNZ;~nLV~@Fw1n*)1tO_2C^H0gS*owxfVR-w^c}&IAE1E( z1;|@mol?yyl^Q3c{6Q}pJ&(10^#qA@ zQU9~gfICgBt-VrceJZW=8&onYJ-U!-MsgAd%@Ib%PS*-EH1kJfDEHOzT3OW96ME7D zXgx1*F7{&7uTsB#YatviOo%vM{h7o~*7B4(jmqO)_}TfYfpP8!_QSHleA8ww>$STY z1JQ;3V%aTk&RnmH>yH>F+EB5+6jmgOguEX&84eCZ0A~|uo+9mp&^h`HzQPRBuw6_b z;=tgvd+~C+vtP+!v(pT+MnqpaoA<^a;c0Av(ec49ULkd z2BT17gXd9#J675>L*B{ZJ`*UPQ;nRLMDs_-TK>j@SHh-M%$7QDE2+bOwcrt~9DUdD z+U$zzFQkGtA}p1g6SU7h-9Oh$Lqta_-?%>efnF5eZCHc{59JFq_BFkQ$rRT0bgv6lw{A2D$C2Qdp{j7v?Kh3!d|dAf^>m%H zgs;kGq)A*CGn9T$3Q6H1Bcm+qx@p%v#>pBh@;?E0JN?w#IMLr&WSk+QOUKLE+4x1j z$?}0TY1yxtQHt_66nJnGy;8i9;G-T0A5s`KNN%}>_)+2JH&e&E>&$wN-|X3Jl-_XWM$Re^q5l8GYn0{rF`cJxKRjcsnI}5b272ozUI_ zj+fT^m3)O9)~DtWmO0w}6%hfzT0RJ?%=dr*J}|2Hk`GxI-u=qR=XStuOmAp z<-+VtYCtSfI)B{HQV{M?AYdTFo_Ocoklze)_ZMGe)N}hn6r@?>(ZE+XHZyI9U>gZF zVqF$YkrjslIs2%|NAzrO(7SESEEH> z93k#d^K#<#s>O>J1^bdaFd6mWfH@Q$S(#f*Objp{t;YR3Iol;B1vswl->(Yv0W7iGG;DUZoSQz_}3Of8No=k4o^ zn$Y}T`WpRP3&3^s02m6Wz#CxBv1%;a9a7#3yDYYemfyPz3L_=f)J)fqyprjc4Vd`q zczC|NW5;SMQ7=-3!dGR74AV;%`c2^cIV^@U>7?S{$3`VlG8JXbf?v=ELWl2Ts6bNXO08+H4OFRslPaE0Z#}QdIX+!Ro5Y{rrMQ0}UkUAEB$&v9>lg zuBQ_c*A`)8Sj-O`U+SzeY);T&*YvZtjL2PTogaiq@< zx1sYtL*KV!i_<}4P9Uln`MSZ9YcSU;?#}iM-TS?y`h#}?!qg@y3h#+H%vllL9XL3` z3~WU=p4#=X%cABM5E z1}2NWy4tC5wWz4z_pwkb=`&Hv&ihM?%h@@(bUdDSnxhKUCgCdGfUCsX$u-y2)3adj z3K|*Z@ODsr7rjEAOXfpZ-2m1?h0g(xF z7LQ4kpz7>+B!=7E*a$K|TI_r~ZW70K5g=7Pe`tI0qNo z7JS_BoD2W#-|5Bx&O}yz(puG$L~tT3+SdWPfJDayJ1snxG;isgSnH%dF%Y{e3>gNR z^Eg18Q6eyixb@BswR1G8rED(!+CUBu-81YCIii>S;&8JeqIZW@ zo}#P494Y+;G$$KbicOlsnzZkiromsgrs?eA!-u~X+Mfqg1O`?EUeC7Q^LeV?d3TRD zDmGPTdI-gbH9IQ{jL~WP`;L$iUP_}45^gC}yQz8p$26Qu@dY_KtKRE!_2yT1&XYI8 zZeo%|#KmoY)K}8cnNIh;o~;&2CUkhnmT! z5%Sst<_pwy2Yb96Fr4C%5-k)^4h;9u%`~c4x*4qxml)E2u*h?dq6yvH7`B>jtOhjM z{cLDs@1OdHlJjsVv#sm=+=gegEP>VNMFxHplk77lS7Kx&I*6P;y11|jY1=3BzqL83 zXf5Bt@BoHF3)*Qp?sqw?FdG>gP(5>;Mq~!G~>F?YP1q5^421 z-&+bvn_;B>Gttc%N}rMOGFrs($&|*5p4uOAmFQ)3$35VPV#{8NqQU`ZHC=4>r`pp( zSCvd+@8G9jJE>Tzv8=ck*S)&BDmi?5ddkOVqdx=cAj7V*>^q-ttAu$V zV4-t^%y(C{LL8ROnV|Ls?PhyzH~l!K2WT07{$!G|uXUR_XN;Z0x3sS#Z^w#rTuZlX zYxgcz%EJ;>1kEB9l~md3@e?R9|3#_LZ@$v--I8Iq7_I_)(S~%b2FH~75EU7yYzsYj zEJd<CkC$rF2b8Ow27Q zsrDF~pK7QfJ9j4|e=aM#sag7lHqwwhLm&P)(!*nyBG40h%BQG(`Gw?4z93`{C+34} zt_4u>=IdxPKiS1?XasFM+#jK+-se>FyHRi2|LkUJW!A9Tav#PuVqQa{+c})7z0|{K z{a`a1%L8+D-OqnD!xR_ExNh2}FhNh8J(lCr1vmHA*iaaf(QJ2NKUn!D{gWmLc1ty8 zXC9J&HP|j4jnBV+i+}WN{r3G)elN!>AfVU=E?FM|r|^30>`Uc$7Vj3~$ZyG@fDZ|M zt5IP{P7Zlcs+K?(4^bchB6tT*B0iUz>}60Qeso*v2VGs3_+{+T*A}xVn(3?La8&P& z`NsDbYTLhlVH4vneVk5}h1G_V?cAJ3eZzb1-C8$p5z`v`~ zI_>o{zK^met%U#^`{Rhg%!xxD`V@9t>&ek8DO7TH5r%2L|DjOkd;D#oJ)=}J--Fww%%5~!{rPAd&u z;jJn6hmQ;wz8%=iG!<#q%8iuL99pRLq#7vMwr_5#iHoy3ms**2T*u3a53v9({Lmw=wjky->;DBIPKazt=5Y6;X8G+@kVe8t zpVzcEk?2{lf((o}Ds@|$fer@riyRRzpWIt6at8Y%j<8rbQ9??J=j^A9A3usI#lt5? zUqTe;V5@@=<;CyvjkR1qtNa%L?{1FQxSn$x_Ajn(tnV&FfQ4o_U;im8#2r~3+0b5t zaNe33n; sW;)&dBE$Oei=%kQEUFFj0Vn70jJZAH4d1hn<6QF(R1atiV4PoEhCwC zk?wh=rPKet7wOw51Xwkg0(iEKqQbxzbGeOL=zn&m{3Nc@=R)2Uz)?+3YC-0b(Qtj; zW;}~sf1Lxk)qYzQgSDE5HV($S+#%pze74hy^;TM2ye?a15G|E zIh%=G7Tp@SdxRy5Vi|!f5At3>ggxLhH8bNd)k}t)`>EN1pPoT=CwMg~g^MmN@8C<7 zPvrMJAaaLU5|>0!+fh8DojAzP0vT&mqb9;GO)DgF3fdz)v3j;Yp6 zK13ALX!CYZg}Gm)=9*on(4>8Mzp85OT{C1F% z!g+i;Ma1$60^MnVLRPfjCI|$Q{m)>GRoACVm4yXnS1Ua&o6G-M<#ihkO+^cAlmA?6 z_oFQnVoXs0tE#{k`|1E35G-9=|EsZ z%MMl7AA$+ge6Tmb76EG%I?cgPpVAG24&naJr28{9h@xQS8@K}z5pm20sN_WU)}PNC z-aZw6lbdUddEFoOo+K{McGzD^G)Le!pbVs>Ol$JKdPYMj%Vz0dxEkQHEs(EXDfXGE z>*R#uFe4Pl1We1}$W|{2zDV4A!Y*rPh?{RI;g5dG4~Z^nx#hW$H?fE!A|f85LHMzv zVh=73&ZuHIllERst?tZFcI8CPPZFk)f!{t<34SX5a>?AQYilqAnTxBI5i*_;Ba*Hh z;37F&T8Ft#VQeNc4l~V4r-csZUnT!kv5grHd10`!nRJ^A7pIs0cDyjlYoepWZmH8K zTtpbY^jB&pXEUiLl^=Y|%Nr){-3|eH&jS#S8N9#I*#&VHNJs${F1E=6?$aQZ*%&Te z*nMp=JStU&KTuJ^F68m%X!jthan#El^h(?wzkCYJTH@nh-s!p6s~KuglZUpzuWPA_ zfEt0FAijUJHARc~BLjj{7Al@gGeObn)SH8=Z0?6{726LsMo1iH3kN0iu&Z0WfTgi4ap%-zQ1#?)jN-?Bd)qSMuKX7{+5ruztI?@W=&8)fc&Yx zUm66>S#QA%)*Hy5eJ(Fv#(M4_cch7j+ZlYJmHB_Dd+VsGzP?`+3x5VGEg+zPv>;N_ zD4^2ar666>%{EB^Y3Y(K=?>}c?rt{SvF{gro-@vS-}k*|oO|v+cMXPP$lmO|)?9PV z`HfH9F9dBqE?Xy2`U06Ssz4R6J3*QE@2HpVeRZo$hK&|=HlbN&r9ATD5}JN=$MiLV z&`@xVr%KWlw4$ku?%)8$_lZig{hcLQaDQrPelJc;47+_uCXWa8_>FJ$)w!iBXw6srs0C!~yo*L-GMVk+XEWoK+ z=W(za$uk)H@#u@sgG0-%xW~hHZlduYtK@yyUmg5Ymtb#Uv4!N@v$&hxq{z=7v%hHm z;>91h$PC3oAnaCLxsEYIsTuXuytyao1v)x9WqmzgM^w1k_COYSkx{#72tD4-Z?I~N z<~vG4F5@lU_RT98G-6wf#*1gTbe6w2Hd5>9CBfMNGP8vd$4ih5S$#UwAX%rinIuUw z%KZ!Uz36M{$+qzieujpc3n(dOob8jC9x9RJDhFgu@W}Rfj+I&~(3iQ)?Clbv>i%TXrk^f&2+~nb6tBYT8&S$ zFLlII@csi(%aQsB`)rnaIdwqOaKZNM{MWV+^)E+|57?0q+H6h-mHEDBdz##t`q3lCla2bCGdy48`Sq^OLfhoSc$PYQHC4=`vxDLFCVX^_Y?(EIb^w zvmN0}ihZ;2W^AWYyrs*9-ZC{FmyNN(@*=+=(7t8;DDHK6g=9f=F_fjbKAdlSdU}Nq z9Hi>&HxIe#L`5Oz4t_Fr-_;h-P82uL=9JW&PI?WPq2~eA7{m9*ETcw?a67n3%ocyV zfOP>3?I`Oh+0Dj8#GiDLu3Q+U;xIvu7&71P;NTF#pb52c^G~}#?U-n&w^{5gP%rKG zWRBL=Tj0KnQEI*7oXl8Td%@qIQS&zw?$*p90YJ`M6aTXQ895 zjm;a~@$`Fv_NSNrP48t=V5erKVR|u=jrMWx{KG$H>1eBpQU(C=mqs8kDm*-G?L*8D zD{Jd-08p)`baiz#L;3XEJV%SsxsWc`tg9~w79_JjwzXg}*y(9-_sFpI>pz#&>ZsnV#-E z;%hkNV2Xen{B1uhJH(a@UDUxnl2v)R8gP%*bJ3_+o!dhwRWCMO3>K=$gg0p?`P&GW&gHh`)F zL|#V&`^?V6f$W$ti6vyD^_F{u&B&@*Rpj1AYYMcr%YVgy0_4S)EB6)WQej#zjS7!^ zf*UJvaV27)>YSol*bc;_mA*71ZCTloDR`0n?~BXb#j>WEc2EX_3``^h2OZMig}vS1 zoiV#B{R*7}ik5z4#Ke(7bRpk(5zCJI^}l1k%+0~~>!G+;Hl|J)HMs%5N*?D!JRHsC z_-yB}$4HU!oF=Lf&@cnog%c>@y^DRJn5DMZQyS7u`}JkbOalrGzAfgO@vhbPm#Yr6 zgtUMAhOS;=mFZZRsWvspG@hmTE$rvddwxL)bK&kA8LDg+Uf`dEhe!AebUW%!YHBw@ zyutZw)dN+|C4kFz9gY7QvB`B9-MNW_O>G>rH^1}qAH~hJgfxn3X=&LYM>C|OBTKDr zI&C~;VxoDt@gjsF61D^{I_TOR=OlQ60E07_7C=Tt9fg;s^b4@eaK`Gr9d~$n zZ}kYp0es2QtE|lRoT)QW@dYYHBqUF4R|i2}wJu}ChQ(yLs8%mFDr&sK`MSG)_pcj( z)))uJ(hrTf6%)Hhb0P9z`{GE5(`v2t{(YX=dZuS0E@Xp#KYk>07QiH|~r^DhO#0zwTNga)tQC2b-NT3h4Us%?^m zvm@m+{ta6y>~}E7nz@v-kl_g z0wt1b^=vMqKVf2{PPVy&b)Y;tR+V{nV6F{U>wL;d#(NfDTDk(KGdea#!tFG>+&$W! z`DX%AX)>BT6_&p;8@|2R72lVJcoY{id5>=*9H2fh`}sdzJObIWB??vQ!b-p2n#Xd@ zq7(8s6TUZ8*<9**NVYuMWC`|`f^x7e!M4_HgnrGfQL;#$UZy&7!ZL~*V;LlHPfX;j z@=o$|bFneMUF8c70Yfch-9kr-HxW_Wnf*D{pNK7wiVWburd{rs8iG5MQ}IOycJ>0e z*?^3UjNr1i5-&bpEyL16LFCu7a$^e=yDen!J=jXNFnKIn_=i~(0RF3Q^UC6GKpjXa`a5wBvjvX|Fn=(>xI*&va zI1Tw{N;-g_ZK}^2tXDAW?YY6P+KG3fFX7M&AN8FOkYW{bw2@5O%i-*PK*ku|uB_ZV zt_Tj62UWGcK|iqUds_iJAhkB9?biGIx=T60PQLyD70jU8^i&MYcm?xNRk5ynHc(^R z+F31f=(C_}q1|$&#iPkim$BbXodavwfzy&ims5vxoNM7Q3?{1?vdo}|Q?kP+z~$%0 zh}nq4{_>wEo?c#NBZ<~o8azk)>xJesS)<91I8x+}wmU4v#pxI{SSqUqZO$r6!6p^f z@eTMg-8N59tUak%0q_d!_HP<<0S2)?arfc5#OKP=($L7r;n9)v7%w{7g%#Oj2Fmjz zv9pcKb_oX`Kgo{D)b7BmsHg~d0hnDNWasP@TwGdgJi2kqw*!=%`DXj%=w&P>C*RSu zm?~BF*X18}C(yxz{L?HSq!h$LIpc#f))Kud9qciN@>hHlS`;k2D8+t8{0z)<=-Yyc z!frB7>-Q#bxWa`v+j_(Yiq3WpHgd%0q7~;lDMjWr;zS6O!A=)IgnPyZA;)*g$xz3a z1Or1u2_8Hk3lf3Lq3_MShIW8IGr4%gOR3@=hDuf#Q=kx`YySaTTWj(}6|zsXHA0qm zs^%KCqp1g^zqptlo7J#zl z*!VfxLE^*nxTCtIsU6Ql#-7^+R}}P91#TNM_8d4>Kq(yl@7nO*T?X{F@`*9g^aK9J zGtX8*yA*c^BR5yZ`sz^-ZRpbS($eB&ql|(ug+Fiyzkg@(c&<9Z{}aex1>lQdQmttT zbClbUdaSDIV*~!1#~cPJ9>aI8d!lQ;_I0Pig5csFS|{asMEWty|Hp>3;sC#*W@Aom zPI^Jjr)q8GU>#va&1CXUQL#6j7ZFg=`D3aHe3y7B{r56mYT!&gJvAb66!0$&;sp#$L>C;d< z?CG+BtClilx{ZB*(nwc#Z%NiOy!3iYj%Mm1C0T?!r!|rU7gs%pDK$ZhYY|KlXXVX}9=K2*u9I{uoIAbVTrEtu0>6`H$1xc`5Pm zG-1l8zF(g0U4??zuurm_R5K^1)oNT?T6kDk>RJ(648`hDuCM#i?lFTR{XEm{5Q-1q z5-={}MusTj5o~Eg!&I;pZtz+2qnZUPUpPcZq|x}BhH~|y`D2*vI?>2z^Mx-X&nLWA zZ?^Vzvf(@fI!x=;K@EeY?@O|zd^d|67hLrk?rc>=nqH=Nl=Y zqaV1sUDK?zX>#oSN1XRDTIXlb6Jk^^u;`jjNMIAbSYzuFY}Ql?3fO39qJ2;7=^xKo zwh^*IKb%~X6NJCPQ|6yBR)rxhDIi(cWkUpZ}W0y=h)cVe&h%dtKt0zTi@UP1h#HR z=qYw#WmK<^G92KD*)Yj@df=P`Zk41N?B4^>~YeC_Bf zm;M`8YY+l;jfFkDE$WmUGn?M=v|b$SU*)XczYk1wo-g%QEi^ti3HI@sgmN1m-aOc4 zfH&|@%4l3P{XdYDc0}`%T~7hG>Eu35vu^(ldh^*EaH3J_MXrwOY{$g1r^aTy?Cb zqj@@mzx{F-TB+hdPW;0+(0!QQw1XNCIQ|JvxLg5ZcZtnf^^-6*Ypm!F&3p$F)Y%s< zc!mxpV*_NFO}#a5N_IhM+XD<=i8X4@Vzj#vc zMq|h|D;))AS5}f(b{gvwDKQTZ53&8S)_LqXT5`^X63OoR2DgQA07vYrt7~0t85J1< z^>OkCG?j);CkpJRJ{JrAdj8qn{qq+A_r=|nf5@IaJvAztU17%(iIu1#v;U+Lfp5iuh!p|ED2j=efGJHfs%g>0>fW%kAc%C$qRX;kUk3 zH{;fb#wls( zE)d^@O5Wy)y=CCh)Vz97)BD4#zw+)}Tc2pCusf7FV`E^@SW845RdW)MO>f^i3{a~$ zpJQ-yD=h~Kp*gU(XG8wl&fb@Bb6_)Id;SUisKX_+=NG$@P!{-Jjw)}R9$y;eLzWc_ zxFHy5PEPk#k#UzW^G(-c2ZMTpeKbHrDk_<3rS-j*qi8m z9rH096co*LAKG}hRWKpA@%wSmL58G{?pVN&>nH=oqTZAMLr_b98!OqN;S3bqH-b>e zlD9;meJp^5sMu&gX8*RX(BEtEC9(o%OHw1Kv5UAIna@MQ$!TMZm~E6Mye?8lG%>s>RSKYxZgg=&^5 zm<%{yze9*eips9qcy5b4kO<`@fA*|-Xo%(lxYCC>*?(K9HMdMFpW67|YPmO5KCQpG zWuZ;=-0nqHH5|GY2Cxj2z4qnX8@LfG1)>j%>Yv`Ok6&TdJ4=VF{OI5C_y&UHbY(Dm zrrg11|7<-^H{tq4-1_QEQm0~?DIHbeuFS@}#iq*Ye$_t;wXFlB4I# zMvx;&j#sjSN=6vluP;qcLdKM~1-wytKlmP}@51_2) z`tCl7Z&Ez@(cfDPuJXLd z_rWY3iU|3{*U+lizv>M6hcaFM`&qsXH9YWlkA*1%{#~eC`?tUI|5<4JHwr{U+sL=F zIshwF!N8wCDS|}2k|i&}lCpX5%ztU)7Oz3z8wx?Wk{DT@v9Ud4Vq%@)RD?XgH*gmC zIDXVmsHnKOxMV2RCIWJ<@iDdAGlS@|uf}W^Q-@8&9ljVUld;(nO(Q$ zE%j8D1d+rq*LT^OnD+MX?(CNDPYH0>02oULmQ%;Q#o_9)-3~tAq{IY+aVG7zZC+$+0pY1Sn{C#Os-kS0qU&0&Rt{CK|XBGpR5A zWKRqCMa5a*fptEY;hs2;WTBR6)R!|iZnHR8S1z;?#~BZ(^oN*0$Fyl1*7W*S^DI`$ zHsvNDJ!)L!oD2oH-8~6m+{V25 zO{A@O!h9s($Z~0V=*MJ3ngT;lPY>O1jse5QA1{1KuYrPCO4U<{*_@_MmY_te%AVzO ze<~qwub(7?L7kfjkI-tPDvDN~HjVV%_|uze1B#|8P_ATO^m5NsFK^6{TPoaOv`%oq z$Mj1vsAIIw>|!g>pK?L2Ho=DlQ27AB(Fnp3kd1x$nbd5gq-k(a$spl&O=}qI=~6%y ze4T?`-tD`$g3Y|9ZTeDmTFU#Ze4l7m%!&&hZ0YchcE1z2Ug_}O#KeCflzl?qy3iI5?m$mX{c>}A&Q1{k zrQ4ZH8%Rk>fgtTbd*AHPCg(rK>G5H0hzQox-4%Ce$)wik|2N_Nsvb1{qh(}%$)uE) zhC@+z`Snls@0SO5gH)SyR>9<M=gC2l&Le8EJHjqfq1(n#ozF{5ZF0U!f3#sS)|V87U3ZpswA8Hf6ZGnS zNFMQ;EK~4CR~qgPgHe#}@+i;7pYvWYm`~etao8<3ZeYeQw5z@mbgo=!i=@XJbegGu zBH((5&weX!`6=ahQc*$G!nF-TWci0KEHXl_{_uA{5ywOSPC691W96u-%iiG>WoC`a zcnCf-pAJM67+qusbag3lbhxGN0e*gm3GJ-I_0}tF7~6!bCP(xT@Z>#U88kX@?*gx~ zPwtSM$lbK#N4W^*nH-zdy#B6n+~UBxeRX$V>Fwkf$!J~x$7Dcg1vSdCwjg%^anNQd zPcq0O;(Jlmmfyd7|B_h(H80#-CMJd@EVdTM>qX>b4*1wLIqBbuRcgMzf7U-ZSlcXe zIIW}s19zV&yzzZ{SWv9oMcsAyPo%|v3j8g+pfv8Te^$l;YZtkOTXAv8J?VJYJ$tUr z?QJSD%?U?A3Y?qJ`cLlRemMDw^WEUcNRy)ZekLPkXn43{rtu>)q6ZIN3TA1({?OAh zTN--!>hJX0RZR`^%#>S=yKIo>-4Vq{75DQe!qjY%vThn_ll)^r&jOZRky@LnXT3wzyOkR#U-9~<-@7SZp6y>DCnMV)&!NW? zb$`>wb@je$NJPYa{1B z$o$;hbvr^43z=pkY#D27Yp;AZwn$i~vu3Cu)}uB%J9A$33Spcxo0*>8&is7L8rIRV zKrbj{Nprm3F?G%LPm`_2>tG#^H@gwOv}AI(PQ3z3T&NI1>T2)OHaR-Fmr5FI~y^hlZ- zM*`MTs65=lJK9<8gFcdnU~jpqV&*)!NqHSdF?T^)Q$(eQ2^L8tg6CT8&`j!*Xk@Q0yI6Z^+(Zqwc&yK46jN>e zUU|MpG@Hk77msz9sM%CU#_#1cG&BW%<&O7$Q&9 z&MQjOkY`Zp=`FaNRv5hWst#g$AQky4c)c}9@Gz? z{xB-iS=l>1wt;6V0ia{)V*R~cFDS6Amxh_wX&EkZJpFj6m4do_&pM_YjutRfB(Y!09M5f$}MTX*7 z7Wp3lBVgX5pk~GQuqs#EjWtd2JHd>J>0Y$?A>kU+-wf`-gD`Fc$zcbeA8%Y%N_zS5YLHZX!|CFUH()x);6~p@Q{_`&{mLw>9FBxsdwd!%oMYqL`RT;6C)HsqQ1yCq8{~g_1*SsV9giD5l5= zQN{!GAzdY3p=Um|rpU6vwz-!8EZ*ANC167YS@1LM4qkEFmlc@v@{=VME}|a#<7M9< z-_Fa=HyADQ>n6ihPZ<;QjJ-5c1R%LvSfh zihb_z5hSIbp7G@}yR~yt`&coNfM{%-=kFae0|O~B#}tJpBhZQlfKI_0ckz(A=-pEE zUANl=8{90b({*(Aq)o$~CLTMT{P6S3oJxK1+57C z7IP{FqFC;WbuEfePgotuvV|h!+1V%3>1i$PnFFV&poE0{eEF7O)7v#%R*T8=!k00d zo-s2|&uC?;3zr}|IvNLm#ib~ZhX!tGDeqZ|SU5POQu9Fge@hXo`ETHl)(jXTwJ z03~^1UI0hX`2T<`2-Fe)BoWB|bN#|e2JOFT+(5Mbe})|S|01o85nJx2&Nu7nbqMB| ze`(-n8$~f)={dl6*gLE8)7;PY4qD8ei=2v3b&x#DeQ%uIkvJHbIYm( zMo)NOql$B}h~NHQATwXQIZSzwoR{NER(2iPyIw#81pkbK~&Kd1DI3AIn3I78hUmHky?GMV&xD z#wcEnOgWqKhG)TO>S_;NW`Of>{)c?@hY+_;E)LcL-j&4nwIF@V+3EfWmE@Obo?B0> zZr`q1Tp0p~@^%B!L-slvd^+h0Y3#IE06Hq+8tT_;^!aa^x)vvYk! zN7n+>v%S@>{BNZz(FhVranT;9)9;@?y~AxWY;RNN=CT_c?*E;Wj)jk6;yfDL4R^`T zHrF()pV<^^qlX`NYKA>^CnsZFU35&DYagFoxyaq)0S*C+?^x$}RL24+H`*_5M1#O3 zL#R9i_f&Bbk)^MNgtF9gQ?=?m&(8K`Wq1)fg}YBIH5yiMrN0~6V`iD@g=UmUK+9UY z;ky&0Y!#<&fJ>d5^YiP1A72ulwZ7buS`Tg8vop6>jvwFM7Z4yXb@c)M+XI%ELjH%7 z%_fElg(=GA@}ePpzEQ>Y#~PnbmE<#|n?|Q~4sySLw^EZwqo#YxNDGfi2;e)$caME^ z#fib`Y!hnuP_kKRbeyNVPA+2-6 zAl})UTLE=7TFM(1P(pj{8|nW2J0a)$7)}A#*_~YsdRkSNfuz!b&h61E{dNT9x@UE1ZJdUwz+DDSC?pyo3!ZyYMS{ zQ}g*j>k~z!q#OP7z&7)%J2jKK-q>#Qs92)soFLBG3&bEPo8XSslxU`)qFYfyTQKXS z2!ohMU{mr!|8Q76uohGS4|EGZiyE(_gcFDvKadQAZxEu&`l9O}d{uRAaJ-bAOa zoX2X>J=}4Hgr_n<@jlCMR39CFb4(Rm-n6Ug~n zMUz)xINbX}Q&Tf#tF(}5eqQ%wtW;!_J$HqazFKL4_$SuBlp0LJ&<(rPoI7aLJQrm< z^H6q#A7DnwQUTxiAuIO!9?E>HR{GF)KbqHh`1iYQcRy{{JH*+8dNi0o0+7f)EU^xE zwf7EVbH>9|R#v$~xXS8OyQqm6;};YU=cMiD{vY{b;~37L1$-yU67!zmcQvotqnM*F z(pucT;|fO1wZY9&=mtT)mr|J^iC^Kwf(i;zZQkrk6azcYhiJlrFXUe1_L)6y_>nGJ zlb06zN>RYOghfP~B^0NzaqtaoP=({ZMs{a^Vxp)e75l)vNYF%G?QeRccbWZ8;?D?- zjE%K)N$2NUxfu{ z*Gc&W*GBSpNm%2QnO~E2_nme`=KL!UyN@)HlViawcf=PE#63F}Eslof(&5oKIa#cf z(oi)S18e#@V9$dZ^ z_gImkl4y#bKf#;5!tUAFC|eJINI5ADMcmEH1;r-wHTnXqifuX1T;By!Vs2HEDkX@_ zl@-!^)nSo!cS)}-c04Vcovke@`Z}C%n3_p|9}=UR*VN>3`^yCNrDpVtlC2v0odb

Pafma1(%$mUL&tf!fWKpWDk=4^1PzFy+p(8oiXJ5a z9%B00yXqp06-0LK@q$|D)TTT28j30f1cx8Raahiq4Hj|C^(eL}El+j%yF&x*ZxiXK zQjv?6);P9w3m$Sbeu%{+lkqJNQ6ehx*U*!jmn+ia)rWu8$P+y=?bJ8_;^CHR&n7m| zCvE$o9eQ#E1fjtS!OL<51qE0hf;Vm$u92q5`G*Btthr__2MUwI_Vq=30$MU^gUWRuG zd-c3g-hMIw;elQ!Xf?mek&^dAFK(e-{U@NOpydU*%1Uq7TNfEqCrrBd&cU0O5(@IP zRB?+GV=i2Vb0hunKJE?o&f8U&$uJV=drC4F>%A_MRJHmw0U5GmYzz|HC^}O+sMpAd z1Ca$ezjYw|BaG;=-X_YY*ty~SL%A=`>zY15zi;>*XXD#>V>RK+Zt<9=2$3+wG49djarwl1EFg<}O2 zkeW~iMnv2j+Z!mMT^?jj=6m1xaUu2{KBGp{@f+PMUvBa^TICj+{WhD3T|~9Vq@vdY ziqj$}wM|`(=Rb#Bh8n^L_l_B+X51id!BE6NJEW_f(D(~^KhHeT4ipD6BlX0h!vX_w z&Zcz)9J!E~_dJC!+tS2T=oC2pl)CXdx77tR>xAO!V@8b%a9n?1=~8Yqkh8mg_v9Wv zJ`qvF!ge}%U}wPYYNdUD9H`8!l34C{W(o5v(dU#EejXWde3yP(?`0hQViA0e}pk`&US@m9D zL!-7hj~vi$&Nvip?tX}?5aQt^@b9m{$>4D(@-12sfKH#7}n*CGr^zrr& z>x;GAj=p8f?s*`zE+3Hix}8%1M7Xk_164K#uqqHgGtCb(Di~y(~rMMJ`{zNEa@p$N}yUl2CY+ z;G*I9-(McQ@)vLazxx*N?W+p3I`-02Qx1$ygX-;HWK&N;pJtgM&Qlrg!ps)6>6K?@BcSdN?QN+0Al=iZ&jLJ#>A6j zdL_u*@Q0iNZc_Iv$^hX6EOXOL{)bO9-fOs%u(V^}zJ1&J>Sr}`(?^hgoFC`e2<|^t zbocKY4ol5&|LN>>4-#QDf$0Q?%A+8V^6|d7Z87AX+RFdBew`~VIhQ|WCT74V9ypO8 zg)iPsP51s80T|=t;U=>D{rmsXxmTWw&Q1I*G}jEw6(`>4cR!~WNj<-cQ3i-4K*LDb zejvO}j1Gr3?37$;-n>pJIuO^O0<#rQ$`CA3MSK;QUx#c~ha z4&qv||MF-&e+y7EEiD;PQsU+l3#BNS{(WmqXLH;6b#4hbNzdPK;^h+v)c8vL(gUb+ z_*x2MW+KIhe^2Bk9sBDVij>`Oj~ud&X#3(c0D;R{A{r z=g;KifUvNm#i^NJv$I%U7Z0N+aOORv^zRcLzZm(%|1MA}N-D*F2_h?@S3){EI%&ze zQnA&*NOuWFRps|3aLI9UZ>KHxf^ZaTn+UuKf&zg6DwjQ zJHg&E2`pKI->9AcjTF7ZK5}WY^Q-%O>)AP-6k;7+WrdL!pU_39C85R9hP%LK*!#OG zOnGQXS6BC%f+IF&g?&o_@b_`0KWeIpj#qP9ugMpNaawox(gfU0N1wZ20So&^Mps{- ze3|v1{{DJ^V+ICx81ZMeWN_1*<}YxhRm7;pkhk0iOYASJHpVttb3gZ2UF z%@8~BB1Q+h0MP=QDgiz|0^~A*+lhmu+PJkK2_VVs?m4=;d%85c>d_jtPZ6iqFDU~c zCT|0jV{`{E-^kIl&<$`ZYg({_&{4)oH4>b7@tq72}U zR6P}g9sct*uUqNGPKW+j9&eshxa`knMFQ&}!*FdTS1b(^w`#PNeqDW1S2xH%fX{%2 zjGEzm0(ye9U^pnQPvq($^p)(OGbT%kn(X}5bT=R|wMSv;`v>q7oEUB^z3t1c{}$zn zu{Mw~0tULB(7BH0w5H@fxrRA6JDaYSUm)OSgNKJ#|LPSKP^EJv0aOG4euyxO9rrT< z?1VZyHeoUoOp$W9vnj;EXlPJ1vk7vYE;C1S(9up)WY}36^P&R|*YG-5A>S?glUegB zpzGcI_L3}Br7w&~nZ>&K7hn)TDT>zNY|3pDYVr+|5zV$slYg$Pk5-W25$1u9)y<=$ z)ENQ}ivwUo5wfOQT0bBr9vA$I7)TljnU)lTpSr?^}yvd#06&ljc z*L%OhiV&l}iyVWN#$Hci$MA3SZJ^e$8IN*1ANfXtM=n6W9yxe@|K8lLz-lXM-}lQr z-b9t%Mt_0XIc?X^y|{AR(qe6GJ&>usOAjOBJOPYl zx&4&;^57-W$JZn$1H<_^l4@~ru{DAtLn3l`6wwIiZ1XPyy6rzx<7Kbnvr~$Pfxk@z z5Gy33H)TN>0Q+u)o*Oy})El4x&>bui&$-mLtHcIXU6ola`Tr#-2m{{CVw&qnfVn zd`L-tVWCmaur^RnH~>r*vbQ?q4DLKo%!=ThNm`AFh!wb==Cjb9&_dthV6$4)x4Am_ zh>B_fv>h}(Wt~MsGCx>Z{bXLCBJqW!Wxn;Wsq0T{a^@#HUqW-B&u#qv0Yd^vopOi6 zh~w3$Z`{a%_0lS|2~C80Ti*kw>XrVsGype)tB&zNCWfL?p(%0QG0!>dczvp?<`|eZ znHt6SV7R7E41jjxxkB7oIRT}xm(hIX7KbOmyvD)D*e7(@o)3cWI)_fA>KrFDLQ~D| zaI1LZ_oNqo`-c!lk7Ssqm-e0KP&XhrhgR{>U@!e>J5BZa$1qP=>(LI-od=R^l@7ds z9nvUjI$DNHaux^h%h3^-mGR}TGu3mSL75C0NwgKv<%Fp~Uu>ebWwb-~WM`w^h@icxI{}HIWeo4=Bs%<8S6O^G^f>YQRfL(?yvvNJL!h zJDk?7G1Ucz$jhYMZ^XoI{^Qh{AWBsyq@f`Y&Ev?cv)l^uV*tSgQm*|rrNw-DwApw` zd9B`5qhC$2p(ZD@TyJ821C;#6%RD03P8)!b2IMqBmyaYYAF5!>gvK!`E^+yXKci4+ zNkht#^g+X-m%FJoZRf$XDDv>eA??=4INbODL|r>!p$5WE7|2m^Tkbu;ympnlv8in; z^Rqd*m(wYd<_=S{QT5ksSl)oU(`LKWh^YY`@C&f>xheMu>yL@-NCY?67g8RV>7}75 z06Drh_T<(8SW+nNHd!;f#O`BC%C=B0L|^Kh<^0L7nt>FB^5ux)ZEWlSmSqY}FcBkU z*6sa#jTdq*D+6Si?ykil8Hi-SGU-ji!wUr;_j;dA5>~_7vcp>wWgb?RmSbfGr-SBv z$x#?>ot;&BO>scw77`LFEiTSHw%!F`)yc_;hdzLLU^5E`jVmSS$sJi=lt+`!)n`qG zfU>Vy)VKf`83~CtyeAQ;gfoB!=UB`UW^QZtXErxAfkE;T5K?4^okb>0>$Pqg z5PRsvXYtzLibQ%}2*6*MzP@FJ6PA(b2 z%?i%Tu{G$&^cweYa2}AHX^r%Y15e5e?@8alKsbkGm~Y2tQba`jSpof?^2U*TZNCW@ z1ZMkRc4nKfiCB{P47&5O1_cZ`oR3z4*hCu|W}yd5sANuI;qhFE^@~4`)UGj5Sj%M? zjwQ#QYDMde=DR0|;=#W2gtX0irapt!$Yo9gFrGFrI) z(UV!A4)8#x*_e6z&=x@z?xHy)hI6kreI(t#?3o^(c~^P zQPAjlvZ<_;;-3N>5y;wC`pssS5#kXMwY9%M#s_ZBPxtwDbtwvgq5G}`T>Xx~m|!;@ zCyVRJUI48Gpn|nN0dy$X9eI0s&1m=%b2&_rks>=L0D_;YqKbNI9jT)d1D1WJ!5aW7diQmkXGs&qqnFOhout4>;4+(9jYdEP_n*SJ;%&SSd?&T_F3B

UhvRaQa@p)ea#a9qi`{f|c{l+(gvx4Z_;B>_*0*sXp#x$mP4n}>d4gVB zd*(csu7-c=Ue{J2NV&|$Um}fjUYt6B3=$XE@_pjt0+YXanBsgWZeN|DaCS5H-)Vd< zqxbEj9`a$s7;SEs4^@vn;XbK@1+2(w$+Is_p*3_H+qRt(xVYAa15wQTUVO>8k4S1} zkiwIuFKlc~UkTpAZ{q_wV{qarmc7PWI{jafPe;3x7xnGM_4KI7Zr*UAXT-T%zh!Ss|xYAi`hPBT96!F2uy#7o#mL4Tyt8$G)) zmu|S-*$EGMViNA>=Lf9Mz!c`$IU;tGrJ=NS7%C9eg-Xpvnf*1srWdAQF9if|$9)nh zX}5+2)UnEx$B?GyLUT|WeM}5DZknrV@48Mu@O#+D4lQSZJ}aDbRunr-Zn8Q01J<%Xw~lLikv9Ylni|T*r+K zOm^3ov_ZUf8;ufECsY&6T_8z#7Z^&wKG16mGu2g~0c!E9k?PZj;L?-9Vdvux8x1+D@BOHR~n74!?c`G#xp4W!#>|VWc<;uD=xlr8q z}+cbl0}+k6WNx>K9L~VLHIld z1%jTl8FsDs+mGo)TYy7;29#dO=!%0!LV{%msZaac{&c;t<`xX}-#Uch2fkKNE3JB| z%a?GoqN?Y8ih27Ipj82!WYlR^T-V2JCluLJ)al)ngW!%C8n&geh2zl(#DaD(rtJ;Z zXa&uilcIgFOMov25R!&}3C}=&;L=9giORN(-jojVxa`*P3sm;Y-DN&&DH>BhB^O(zUi)E31hcH>F+cGMQ&zy0WZMask`eYRJcx z=snMDyAz^+rgCGIukCSZAZFTlj#ewS+sE3UpY~oSb@)}#a3u|OZK>9BKh}+8G+VX- zab~$#hp+k5&o6uDDwrY^biE?tIoYT*wAhmd#mj<;%oW7h_EIMoQexC%yjX9oXy#6a zYN5)W7e4S}?|TVFyBrOf(G6!Pb|E^>RK{~Rx+_liN{MYpA04hFgsAPz1g3P*FT@)e z7PbB|yz@*^-GkRCY&nTL05-O+Ij5?S~^Wf<;HYI z;b<>N&CbfcLb*5>j#_waGZs;Ev~@GySo>YG$0rt+w}TaID|oP0II&h{SqM-!=wky_ zPTdBnaJud2TyFZ)?gcm@C?3+#?=leZjoA#F*Sb6AJYx=tOtf4Wtu4mNo-1>S&ReLu zl&!QHW@PpzsxI%tRCS1klg;GEGhZJk?w<$a?_i54J>DBJbDj%QWM9i^8q$kCY-R4C z%!v)tn@Z3lWjcvMj5=%^WmRS$Bg^mdt#&fEKTitF?t344qmT4`=BYxD{p(wJ^o?ih z2}d4p-l)A&)6gIh3ymDJ`*U)QRe2sFchia`*V#(gLItI*>IoKF+ggY$W~`H*@qt)oh1!LQWQXBs;iJDF2q?gK1Gv5l5EI6ab?RJq@s0Lz92p z%67Wxnzjv7cc#67#PXDz}Dy>&f6?cWUYV0Kj~)IX852!D9xZm1; z;aeZgwFT2Yt*N94i)r@+l9&)p0_&uWHs_eM!FaGh zmGL=h^wO0hO}jt#Fw0tq%*t2|d()Z>I2UY63>tT@pzolLC)|uH4s|_3>anq2gSpI} zvQ1Ns>qOzl*MxF1z+*J-8zz`J? zQIMp#n)?0gR~^Q?$=y+3(Ay(8w!;&~Tj4{@^x7ko=Tcs4H&j?6?eT5e+sfg@e0cVf zG0BmY^TR|~h}3!I=Sypa4Uv|}YvCpZOD3qYd_7;JqQ-7v?X}Pr*#I3%Im;i#67JSx zrXdEE{nP$l-op!cc&>_v6vhRIcoPW4U6)Z1^}SAde{&{~rmn89{F8rBQ0PcX&n8tw zM6~8EZ9f$O0RgGYQ)H0hE0p!x0ey=hNrm8kwE0oW`Td1RnM&;EbK?W&8n?0hq4^QH z!*2}@q=?nc2I3yj9%cr?Z8WS7UX0}y9XvGw_*9V}s?8fnZNyhL;wL0$P3X%A%M87v)stxC9*Iq2I zc}2ZuO_trrkW>kG|Jqxg->dsf6Sfmynk-2vC6DGSj!BJsN~~dh#D79tWIN~%7xRq6 zY+v1`VsAK&ee}2b`q=Tp+}t(I(t?h0M;Q80VlJzL!w^k)mZGHNHN_b$mzw-5P0M!` zLSn206aI|_(6m|VS2a_Xmfjpcp2;dj*6T+A+qcGPJTBKY)X$!-U%0q7WnMX=YcmQK9j zJ9(OdZkcXD$894fDk_R+d4AF>nIpEN2E|E7y=p-T*__@4+rvK|6_y>&tM*AMtT*%< zeIV_;fo6U0K@W<_9$mSm&x|U)Vg-A?y^V;c1aG3MkVI5ixENWI*3v?kd9=c6ButUs zi5r5lZ^q0(fL}EqTg+~SNwR2e?rpE?lGa#>^RgsGD z*uDgf%4W5&lk3vT%EhAlWBohSXRnuKNGGKdVr@sQ&+PS3Go%Q!p2W5?d;54zXP!fz z`zx6Uo~O5FQW3B9muhAtYVz5v88TwQ$<7}yI+>`)x%z;JkS?sFd$)R$;7q9l@@ z{1oAhSeQ^TjT|rM=|}7JvOXI6P@X3eJ-xDh^nbPYmQitS?Ydz0&Q7u;z(xWgSR9uG z_nlxN1PJaHg1bvW5yLG&fZ)O1odPPjLvW{pI|UT3{j$$@&ggNwZ};iZ_uu{MN5ZID zwQ8;@?|kK%&-2;yCK;FMHzoPlgovpE7aS=$-rbbc+zl)uZ2@#Nz@?*SP*>De?qe&q zIji?Ha}_l!b#UF^Q@#9#m8i!{>J@2f8mH>w#j|DaK*MRq>gzvtc6NRp*zwzb?7uzi zXLUL8iG2TEQMp%odUes%t?Cx1BNy$+3BbhTDfA638#V0qWjXuhFRp%D?2L*F35n`0 zurV-D1fLvzGaab}rd?T_9FHPBmHQjNQFkm{KEW*Ejy+v{M zBbr)_Y8`1K;Fq*Ba4=Nas}mHU)SOJ)lB*lBFuIi;EY#|=(>b@*81&;50>F|{KK!#otag`GsPGgw_ z{L7FiGnO8=SnH;?4)F5fTJyrv8pxcp+=G1W=1ZIl7W*m1&ZTg zG6I%!t+e=j#^;bxTbS>nINn2n`I{`Vx?5s7xw2L)bG$k@Y*ji)DnW@fCJ`Ifwwqr} zkagQQj7*{%v+-VcoGg`qjfs>=^`Pz=jr-B)=Q$n}wl5bE92Yak5d|Qf?Wxn&PV)gY zh8min_US6QLi*WBdxi=bOQ(+O$Mv#t$8v2!Yz1zrF;g`1^e~AVLm8v04&*&m=0#f> zz4;PyC0osv$LlC38JWHO{xsqJ2`S(LXw$o9mSgyXlUxa&${t$_Ij@UP!60`_(o)B0 ziiHz2w#RTV*XsFW2u=w`Ig#~0R8ge8JJn0m+_ODF!D4dus@SFcmc}HyBUk743f7r( zXO^>r1pQ%QLM`VvJ9Xt-9n?O|R?T#Nj#Er$<@)-$G2+C?02TzBkkPbN`TocQ$*VU*wm)H~lOX7dtr`9?{g65! zDdYL40QdcI#7=hp;(S*}*SdXc-Ldf2yXCnyg$TfTqtB=7yr~7ZKI=ok0kv5JITDA} zGW~NTqIz?Nk=?M#tR++#t8ddi3RsX1i$m8EY0Ca zSd+g$oPM2sf4c8}5E3FK%VyFSe2u2W1BM_;>^u20bSUXL-K;B{e|a*vEl zaM|+&8w7}F1jhYppxas-gNjPmd$VU*S_ntbx@hrd4T|POIHm*PIG;6Uj%iTfuMcGw zgk4 zx6lrIWTDlv6R5SPTav<5wX$>oi#X1Gc-#BWOMl}HEIM?;RtMc&QIXP)Zhl(`97{oW zPsa#^UuzfWP8%gi-w{4boJ1S>a;{ zp+HdPe6wM0QODV3G0y1~{@T2XxX1Zviswxn`d}uTK=>%7-9Tt}pculUw?{kVzJ;Y$ zXg#*)z!MQb&d%@DE&Ul*q1!~Eh&RMwFsZ;hJYicdmvNr$dJ4-FJik2+{i)@F%!cia z`t7Tl4RXL!IyL(0;bz_!)VBYd9pgh2G()>RqMj3y8=J~u6Me9Fd{#(qJ*n z$=w*8zp@RRW5o--$O~1@sZO8K9*wsiG&OjjFC7gn&Jd@IVovYkxj!w_kGvg3a_Rl; zjGldBAk76=4UC*z?~K7YBs^r4l^4JX4XrllOKAfR0;#hqW4Y%fV)M6ehlhvzI$g+N z_4j+wOv?(N3t_)z3d5r%FX)@~rARtD&gusVB_$<2u#tMzZWZ_yfV<)0hu|NF5vv@w zyCw;8P1=V+XK|Q~*?+tJ;Df71CSb$S)j`3Y{x%op^+A6&+yW`mEaj$>61tr~*m<=+<0>jZoeP{@cT zH|h*-e(fXdAhy$-zEv(1d}`E(EtZWs94Bx&-0HlV=K{O9+V1FeF)@F#g~f7=aWb~{ zTyGiZLruKt71ESl;w%NUTY4H_`!=nxVFmZ6RJ4`Pj7%Woq-6$(m}9c*}O2 zuj$aRG9SDD+{#EJV_~&w#%%;SjdQHjNZYTP^h(h*S-ErZ1_A~pLw5J%^g1yuvQh)9 z6^WcjiFofFuhkgY*w`S?U|5@|_{(I^Okj9G6*_z2CU&B-AB(dr+R9NYPNrjEW)4iE z12#+>1jvgZ6ZA4gFmS-`_U+r8ZEaC#-RCnpGw;&r{I+pq@Sa84DAp+3eu~Fwv=mqw znYhbm9|j9>oqY;M9_ZPMi{G|-A}YsWF}9=1WH1~*Nqf%oc#8qK7-+}65gQ}0oZ*#4 z4s#$p0iBVOlA_Rpku`mFrkQ{MiJ$Vfj@n1rS}2Kq!*X{D05 zIS?WIQ1J9ya_|yJ%>t278K!nMM1t~YZyZZX7TGwvwLe9H#tI=Us+ONf$8e46!Ir%~ z>OO&*HLKnHaQVn#^xZ6GVREI^7!wHHJsfq3_S!Be}bQ!^sKurx^&0k%y_$t3%A{90`28i|Q6_rWex* z9Af0bH0?1K?G!1^WeKZ(NW)?@cO1X%@$kt9h?Mr2%kgXGhY~p}eOwx|w;rc%DeU=4 z$SINs<55s)*=d^p3fgk)O5V^A-H)Z98h2`v*chB(qm^@ z0DQX{VXkMI1Hh_sOyiuQgPA0taI=Q8H}t8;>2CRx*C)?_K!?UnQBJLLUmNj6CM^TIEuMgM#KBmXJZv42s&%e0V4{8i&3mW>t0&lHn z_F%rUqPJH*TwCKmY@zQFI-ZfBahC@PIH%xA5P7LG?oIO5aogSSAP8#l*pxF6sD&R~ zn45zTeLc!ZhiCUIaYT(-u)wqJ_m@G1s%3-SsEc}kSL%?K*|xaH6ZzWwmWQ+ERMG6?DeL_V%r7&>QGRpMs2kn z2+ITu;w-_o?<{@GsCb0jLl*AkCXL=qiWCkKuU1cO}_XwKYetnXq|Caf#1b9Vf z_Lz18@=NctnyM_zJ4$rYhjiO9<^w|I1=ezSPjX~ee{wVCD*?SuXr$+yn*;4k9XfT+v9twyBW6E;;Ek2K;{u<;8s)I+b<2N#x%PO&`)=p8OPBcc zPIveCv3rxr7l~xB;{Y)@7#zmb?hcKcxxRsLgkmTV7X)z(Uv`6w#O}#OVDiKD@BdC@ z@+xzkj0J+1RYB~<<%uPHo&6Oy-3)gij43F~kfJ34p{*+qAu>|-<*WXQtp;wH|A(0A z|2B~N_nZGiWclw7`FDr>SDNA9li}Z!;opiGBS_}^!ByvgNHOiFr2 z>Yp232ma_T6RE!v0BRlc)SX_ajfO%YWULzwGvpA`)6*Lmq?X2Km$8%FW_cxPQwCZ3 z9174uy>XLt5U!`$A|qpE0ak#QJsIl(;1HWe#K+4itEPQ-$zT3Wpk~tF&)(kA4u$jV4kGmuW36%rZqu)WJp8nvO*Ido{Q~98oE%VcVq{WP z)YMcgf1EPtGTGE5=AaFSf(p3o#Gd_sDg^w$lnfF}I0d0AGPtSu7Rt;A`IwoRp?j7K zb0oK%tD%x)wXvpyJj=9{f+F0d9NMzwDtD4#z$Vw~)>Vhj%y0_Ea%So!i+9D88jof< z$b_ZoxIazAm+~n!?sdI=>lS$S*%nonI?Bp>liWJF%O7&I$|hW6zJ4vquRW+PW3LkW z?b3S(ZSSB;ITGK`2JX1QNcuw63 zlpz-r6O)^yof`egs#46VY{G)fHUIeu;2sE&)3%(XtSng#>B9e2bQs0wHlV8fP??Ww?Zqm+AI4cF`wLuLOc zQ-L=B%t;%XCQZ&|-q`rJBtY(dU$y0q+WOwgkrtF>OLjYspDZ8a@JfxGCT)FJ0X8I zW)K-C%QJnTAH;hG*XJFsMQYmG%otZJwA6A#hzRHgD7vCn`Q{vy{<(XH>(R0iQ9ci? z+wS1X0qJ6O^(Z&St)q+k+}(h*h)*GLBW@GWAyjsqHt-mLo#3DGX^<7zI$$mvnVI&c zq2#fC17lHxzwL30g3E2BU^?6KaL^yvZJgbtbEz)959fARk-exLr%A|3WHaAhLAt+C zQ#*|1wF9);F5Ftnwk;KYQi?=O!>VQwZdtbT4*FsO>Kj}RD{~1R@kiSotQ+N+THkS2 z=)^W|cgInKi-!8*Od+Q^S~M@sJ;|e2pAJ|JKKO5c3b79eg?LR}?Wr}mELprpvuh-x zyzetGNKV?ctYh5wcL7_mvy>cM0xHzeVvkjvTJK+zjXfBhs4Og2m_ zH7!D~)J{5T5x3Z0j2t{cxUf0}Ot#jLhXewf@8OpEkI9q*T~R@YQwZs<*BXy8s+munD{)Pe!RY`yM$*)fY0D@T%!RO_%IsWnC zGH|sVkma=ZO_f7VtSYuhdfC4uRbFsS)Btmt`D!Rkm)K)R0TNs!#W zoqM9?yjka+;5_3C!&-sZ*HT8BC}ow)(9zL-<8v@25!0$N53QIV(GP~nSd&cWdUi+# zc<<81cm(=*10_dtx-3g(Q8^#sH0dxLp=t?36m}P;vFAY@=;|8r?Vv?aQ*g|y;Z>$(fdoJTy)NoF6v&E+F z$|C5>49uaSFhS>MS)un*fExYlBQC%8C_h;OeKe$@AKHI@w3<(*x#^KC5iE4PW`{o6 z&Ia7uW1C|rha7itW595^B#Q?Mt>)O(f@#EcAD@2N9aPal9j%}Nde0~9AveR34tN)8 z{=IcSKR?$>$moX4kqk;XC}s+wg%iJjzvq{<&=o_A6kPb0oOF>IuGwzSh72bTN2ZND z49B8{SxEgaY%b=^Q5s4QjbH5`-_34hIkPx!Nx}EF(Vdr98bpuC#d>F&`~erj{_GiO z;^~Av&9P4P{d5coMD`v5{-?hf^D4H%R_7oK*^Rmdpv4ij&-6SQp>Xy(#~3QXPzJT{ zU@osc*=8(MWnyK`FQX{SFt!Q*&mP-?@eKykzCGOd0f9uG;c?%BA&rS-QnQ`$rDYX7 zg&7lZatL59-Wi{VM8Z}zyF*~+L}$L_Bqhy&FLVGjq0U=iHgc;<2gY3_VEM)IFG4Ndq;Kwgs%)a`Yg}ASwJ;U(;Fry8 zbG*Y)6nu<4*=kYIv@u}5R`fBv`K{chE-hcmo^nA_q6k*t;8z{=(%e9%uz`^gw#uwW zilx%|2!l@+&r?PvGPe?)k+p%saEsR8%0t*eSLiZ9mFTM73uOWtPhs~$dpthOJ!wTG>1uO zLIRDL+;HCbklP`r=7mHJ6f$U~qjwgCb(B?Ap%dI;JHXg>bb;yPTQ5<-czC!0tOPCu zSQk-$%iBVHDpUKnN?j^)-uzcCZAyHJ8PBxB2!^7O`;+@n8b0XIVF_+}JFJa34dUO} zgiV2flIK?-_tfjx1#M3#Ft7>1NPzazi z+Nj3u#S5Zz+_oOKMKSiz{q+qRnwa{P!gil3~onY~6`kq=$u zK(V(H@R`o$78c;vP=oYnwc}&>#)DY#* zL+?LqBUrq^qf)yrO@p(h3(kY23~<;h07yim)O2^NB>^TTvaOUAJA6Cuq8y2>J$6Jn zu7`RY!4`(tTPxgo5m8gzac1JlShZFp6~+q?r6^~SEa;;I_q}s)RlvLZ3Mft?-r;YjoH8g^+Re_`e){_*Ro3;sYS~Nq1CMzbndRzG!(Mo~4^4`&B z@HmaSCkTX3mO`aisMvJhJR>5K$djP78Ay#hJ1p)IVx*%}Eqd1ml~haA`re1j*B(E( z@0WxFNHXks8Wq-hl9G~e7>T%CU~gm=G=5l_m?+r|*Fq$yFNzGfEilHgEm3k9Cx8L5 znXdPQIu2rQbWw(9I)!gy>o!oPP+0NJf9-D$KG)rtsGOgl?@yPd;oUB*bw8#J`Xv!i zfvsA#gd&r&jm_4<77e9stKQ+Ef0oW{(RkL862vx0o};DY3ll{f@BDVRI_%4v$bA4% z>E;$8(FxW+pI-xvn&8n=D<5kj{&>2OFd4YUL+rkG^}{(Aj`41O$&}E=d#Y9!;H#l) zCd=A)_W)w5hW zA_|>z(KpmD-tJ~(ydawy&2abT6#P;ubBs@=@V2n1sBf(MTl6v>96=wl;gyadWr|LS z@4bM)LCjQ?lvGq?D@|Z3{YqB0r`x0mz`nC`)hQKp5utpnR+hODzwG3GyQI3<6(`7; zE*aMD_xSeK03P>522eOHlaoWu#Y|q!#6(ikM(;V2M2W-vYZSMUqebL*=nD8&f-oz8 zx}*TLl&=!$Z5BEP&4M(E5@nyJBxixtqz6JCXVqift4IGlzwkN7!6}LdWj;rJio%2Kbon4<(7MDzUM_-7iOTTlHo+#B}B~lY6Y;g5W3$ z8QJabD0am2b&TZ8ixBYd*8iWtwEr<4?OPErN*0e&3$%OI$1X3gu`! zjLZz0ikj6GmQoq|v>awr45UgC;Vkq}eQsJQgV^%B<;<4zHhO03!0KFuJU;*qs5%2m z2jGu)IXg{9*zD>)R`ccD<78*gF2lk1i;9wpo>7BUesEE8LScd$^r2iIafEgz2}a)Z zX?LCv4V|GQHJji;rKD7pF=p)UUXO}WgKU5tQz)SN3Y7huKno3iGT zetztq8JPiB@faBxq@*Gh6%}*dJ$fWGnwymLwkN)pc6ADo+mE2(PK95sC{{Mso27P`@39xS^+0 zl}ezeJM=Gl+D2i#wL<}Yj8iX-Q`zT{nX*%ou4XZvtQtJma_*Lspf1}9jN@}0G0Xp8 zX89%ur`(GS4-GBa9)83m3uNMmGtAq`9L5-TEzH1byQ7TiaQPlzNgZ@WW{b4NLsr>S z=zu{-?a4(d2TN4e6B#fp*x~#hsNF|FqY@I%+i1@Ze>DUXdsOX3Gk)^TuZClTR{1$O zOiWBi+u8XTS2J@L7qJ;xyTt{(n%Q_$!+d0FM?XM0h-G=o;Em%JnR?w$pD$)NC!FF%i`|a3E<6nT)4jI06N9KFf(?IG>TzRt=dN zfJAn5nnS9~77kBD%A8A`+1G&!jrI5yGLJ_uC|IMCPYu|K$L#E&6fFkWp{)d2VI9Zj zFj>AlG5>|O#3xsA(-H~Q`%~B2#PEc6zE4a94dz=KUn)qHjjkCc5hEZm_c{Z5e zHB6fC8tM%vLI&d5);m1kbpW;wC`}DVZ-LcL1@4jW7U9P$rNf%MR#PXa4Qg#=WdLEh zEXI!loz>jAdNz3{$lCzkguzd)yD_hvi7(T-&b$WDvbLb!^!A z4Z@%V)*6VTy+kaJBmj@Y*>kg_xS9$v8wji#YnUpfY(S373LW+w&kEl%)C}f6SeYm^ z+x~Le%eC7#&buYjmC&9&(F*g{-4O#mQCU~FrRJMAkR2hz1|V3So7_*QS_f%J(^672 zVT6i{oVYk{b&S z+0Z&w@ZcolXjI_}EgfB6Q=<~!=6iQ1fWm-pfUV)Kt*CI$ues_7c$DpYKnGh@^FBFb ztvChP9vKPg##k`|&TeIC9&GbSZL>@2fud+2x0%!FPhm|)#Xca`h| zaBVDdOftr@sttmo)5Fic>)d1D*9MuD*I7*uR=X7U%Lo?QS*H6Eqfbt7z7$T~f~O^6 z(Oeetr_WS)RPf5DZv-OtPaDy6ex$70u_wGX=pf#sP0(4ofTCOs4b0^r!3Ce#*tO_R z@Z|Lk4U_5o?gDdnrh>ORp2^SnQ`CA%Lz0-k(Afb-DuM}cVEf=5XHHj-TNV$Vmpfs$ z0oB zgtfAe_!t?vSbrr-M5lb}&K|=0_3N*RZm;c02$htSG}I!(;MmgH)0_}-o}R=+(i>WT z{Qg`)p;*rbh_K1kZIYTRYimP%UcC4?%DnZJ9=P2}`NDmk$nJ%{dYqeU@oK)ND?D}m z<6}eqJrWOeSC3VwkJw^&oJyu5uy{(!$lO(TO1e5>LN)IEJYDAYl0Bd23%#<9Kk!R; zWz4W?6XstcnKi1d_0nD>@+jELB)(zN{8ni`I+N%?YyBnHgBf%%!e2cWeH7yJ@Ik$K zRN^R4zIN#YPR`2WVjSqy<%PYI6|U*-=r=Rgih2!XLDM4?SJyFDl$9~D$ z(ZPY4(8kAZ^VhVOS93_U8L>ZUH<^DEaN7uly048C5~KFl$o~8zGn0O8!1E@%*n{4) z%ihIywst|(81(rURVJ?Ea#QmWb*^S>)x{p2w;nz(GZo3HiRE06G!x%^i?cgX)Sk|) zu3uZz1g)-kuHlHP-lqgZ5Bt-^#s?qm^*~Lae93%k%Ke&@)H+X-Hbc0$*yQnXK!RZZ zTKQD(cENGD8n9e*Io>_y0a?u@3i}*1p`4W!_S*S@@zUzsLg%fdD|mR)L)q!6sRxIL zV}su!B8E0L;z5a1GVGnX_Tu8=_^8YNQ0}-g>D*iaMZU)^vlPN^JL8O0B6`BXfguR4 z&)UQLprah^?W4g_nVtAK(#ZDO`prE;&(D8s9lAZZfrocL>DRA&51wrxBg$?@d|MyE zEu?N8o>1|lTRT`M%FjEX=LMC2b5d{N(thLQL=fDnozzeSA(?Ksnf~<5pL*%UFqVrRLUQnU>3;&LX8? z_w3fptWk6>H7Qp(USv(PTzmoQ{o$m{%+Hr-iNe((BW}UC=;#MwZTKGH`X^h~m71~y z1bY%pq!ilwo12?Eo10r(GOu3g3KJBwmn%*lz3>k0xILWbK0ETI?YC3H8w3OjnFC%E zRhgNGvL0s|-MyN7CaT66uTrz}^7ImvhX=A0vwVE4S8vqEAnEy^w(;RWkEalnXzlc26=ph$({nN7^>vrri%VexdfYQMm93M|tCP+)^ z)WckSWp>(vspW`*(0zM(QA^9vib2XC%l$y38Vdto={9e?CdC4=VY5qc>Lt#2^m>r;%!>f*m+wQXa`8FCjNZP z#G#l!JUqz#`SWM%%84%sm-YqnG~m ze!QNin=5FltOQ>V)QRx$@ktZVx{fQ2_@&|hTK@q5_BFPARg{o`o%s6hK~`oag}T%4 z*GAiiUkD{|Ge3Eit8BD52c7+G$ylTI%eTN{&Acx!8?SE_ySckV?(n&2ZS9oEYSy4> zoQx5cx(|`-@V(oZJ}YVGSaKl9ZDCz&ZoS#<%ueRZz7LTn>mIdg4FjWqfW5)cvj?WN zj_y72r?!=`aVzulhs_lEg~7P(n>ZZWkOp@s(6IXH(QgoLKf zkhL!o3sOoZ`rbz|MoJ|=c*rGGjNFeurNp;zGZgf0sI*NTXciCht*fgW8>^a|d*tDP zeoue)AY|#pQ)+csP*1bD@XXLRKffn7<@3ypf5cu{5y=gMtwVn^Wuq?XD18-u2FCnu zDcLwuVu$6v+m7CE#0F&zI|zi(X!7 z^a>}RKK>4(!RqSc?H!EJwh@)DujacVltm<^#;>3%s$^!YE1vesNd!>_1}6X#xKj7I zq2-2T*jr+rUk%TKaIH;^q96ku%kQL}_$Hc}tx&`wwLhpmt@`_~okvmTbsqz++8RsZm}_1Vc| zDV^s`O69e078U5e%C~W|2zD4|^TlS3V?_MV{(h7b=6RtiB@qz^LRr(=`X`(=526fGrh z9uf_-6A=N|i7$qNge2b5*cfEVn*)}oroytbvI6((RY!A1WYYV6ML)V9qt`YzGOdi= z>^fwr%ij}p@N_d4M^Ge0ExZqKF;UMgTgoYA40`?RjRv;lA?9noY9R+NZ)VZ9sfCvN zYkS3&i8)l9Q;!ZCd!rfb6z#B6R4j|mEiR&*w|>{5v3lSaL%6CM|8v4^eRBVd{I6e_ z$;ssY<%LI&cPQ3LxExQ%0^7p6VyoD4o>Dk{<%;8CP5Nl7eyXuRz)#;AQ+EDQJpR#N zy&V{jttPCwG946=ln}K%KeVrQuqov#t0*ZI3pdxGlaq_HvW}ppG_Y(hDY^9`G3w!( za+Zcp29A@1!%y@{xLCT9_Zx+V+jc(DXG=Y3RM~!Y1wCGg1N+Jro&Av!8}5sT{hUttc@%3rs!a{+NOG_%S&dNcHkw_$$zC zIyySC$S{KJ$4pfE@U=f)-+%Doho{fgK~gJDzWcLovxffag5SP={V{L5x=Jx`E2g1= z*p3wqdoH0|cGJ-W?GQs{@ly0bqK_7ZDuclN%R)@EJlTT}tI`JtGQrY4hv8_z&x!&U zqR&LaKq3AcTZ~W8I~o8l2%jk76LyujZ2|N2J1L!;SAKtPulVTLzV77K-reiHy&;Cz z9P!O?I0_w?c~oxhdR&~-DEocvH`K2`vd0n?-!ZjNothGR-#3(?_B>!qu$Xp51$UdH zPzcy%wt#eCq5>IKv-8Rh$JwChD;gUTV(4sYdnBXcHhcB$zVU1nOeF)3Hni5stgkFHXz@#qEwdYlapUJ*bGOO7$AT zRPw(5CHLY*^{do&R%h!Go4!Y*W2M=nEv2OnYX$XsW`$mX(=TC4N__Ut)vT;eN(%Lv znK8^5T+xfHPx~WWX^@w9-!b7`uIgQ2EG8sujtAlrJl(_X$7{1d$r)z%4uLpMllGsg zun{qnqCnIoQE*!l$+@@~sH?Zz^$1Olj8Kvag}2OxM?~>9Ri=~(u(7=tEMr?kDAJK6 zSWX(+z4YStJ8cgI15>QxRjIpCLP>!L3UtJd8aY>+%qoc5Z+0|9+`ud^fje&rJ&(Gp zprjP{lr>N=!h(_y#dCknP^-$`V7k5&TeGu1Hg=S;^e1(&({xf(KS%Bomc}PAj`Yr* zH_F;i-PLaqhJTGvgGn%()4v=YlMh=)+q@s_OnaZ{xNNe{7mn(V44cG_{QX4Iy#!Fp z%h@W~>C(aXlR6@$m~O{^`OPT}$e_LSZjFmFQjfn0wpN%L8lom8Jz7gkkBQFn^pt*_ zv{&XR?t9^0m?pPoZ0@ec>$co_oj{FiB+jO+ zRffscBSB+jVQd~P$jEXZ>1d`getw4axMlPcVib>)Ef46I!dX4|*L`PeC_ergN=fvA zocvpXWBog?h0U2SuYzwHA3sIKUt8f){FsFWG>-S017pUW*2o>5=uy;qve|FJ-6ssu z)4778uo}Ah`u#897zU>P=Zc-=YXpcNb*dX%VUHghXvfFX(@Q>!TB~pBNS7re?2SsY zyW*MdBB1^Dtw2H#D;qupV#7F$_Wdf}~)=F4W&0p$I@8GTFUH}*RHD#*FCc3T_g zJ3wZ!MUz(g)hjR<1Q#RZv$jEqA&3uMVbmv-Uo{8sYtD)w{;bDm0Y z1K+H2)Lca>)?Fa6ZHDu{g!%zt>Y(W;KVgyM+R2QiO1Zzk?y5)GeaTDSi8_JTKTq=h zWkf6TBkpRV=wYY38riW8f$zETIWc`7-w>n3H?p>_ zUgIbC7N>UnJVu&4SVL$*k*Lq#_3}mFy>a8ur!EuCE=*V;p$v|#d(Iiz;bcQ-TRB09 z-!ibe>sq7Do-wrC(h(G9WA<53BEy1%VUnV^j0&2-LkZ9A_;9&rma7}+#D566)+nd; z1vxNM^Z$vmyVot_^`0N^#rhw_tgZhNQ@)h;kDd}h+vxvA->iG%f;t>t-(JN3^Z)

Yv5vU03n^;pN>U1loZwP8<89h_a2iDvgAK8Z{v8 zq>KO0<+`lEApJYi#60m*4+GF6+Pd>;IhwZnOxzxM|oY#Yp$|MvKzh z+P@P%-W~fU8zlFwSuLzw}T)trNSLjyaO{iVq+j=}Z%#`S@h-Z3!;{$nq}pRNkmhvYAYJ*r&f|2?$t05=&~7C7fZzCO>X6tZXzoJlfhqj!J*ty0IQDZ|=Mz z&pny9qC|tozLcRO8P-S;-(1@{!g=26vuWkN%DYzx`IBt3)^6UkH+1XKzBK}Zf;w(C zI286wKh`RCCrQ;}Q~SZp)ER4DRkItpUhLF z^HeKsD_=8A7TN`0Hh9L~Cz5v6YP`&BFzfa!Pom1YR<#?){+Q7TjIi~Rb=lwdob_;N zc1>gutxB)l6$*N4di=0q>K^T*P8k`Qu~M^qO%|Q~xx1z6?g!big-GIHqT=5cZ7Z#+ zx5f@}Wd8oF+lMDg*%4BYh|2cIinf0%X7cQorxDMf0%Gbfp|K^fA)TIHW>jX{-QGD_ z!%-=J-?F1tAXv7-MNQX@9OS8aus{t zckPOI>4bTincD2CtHggMFbi3^@2oTg3!Sc>SEJoq;(z`6vAa4HB)`hE0^8Fu=3KBF zeEB|3PlDRI|o6hjgQLNN|}m~?~Iun9p0yb!LgH*fYp@hY@u(X3RRfM6d8OFg~3{`}+P&`?=y zatqLNi-=n0<;e`C#Wy33m!K5R>OR)M4#-VAT?)bW?%@kZ$0jd!5#(#2xhgS zO$-gPZ)^-))y?(}%;_Rp$kGbU$@jd(&*u8$2YE9mZ1W^dk2G2MENof6A5- z`|Mp>8nsN_5D~@ATAGnOc* z{027Y@F%weh4Blz^X}R4P+DQzo<;2d&0L6ND#SwIAO$^7rZF(QJcSYdIW!a>6{W4H z*tv-7lUKOKuV$h4{DYdIh*2uR!vXvXn_^G*dqlqS@(TbQER^lKs=!1Fw7I1vWrg_| za}#OV1b)(7YIO6q^9#AbPc8i0QJD2dR@{aytn{sjM&EjOzPO-{`J$+nl|jfpn~#@i zfg8Dp!y)u=#pY3g6xM+KY}qZA}}HXEbEMHRKR zo91oxlahU4Hx-kRAm0~|Dm67-eMBVr_YaZ>H-i7vzw_jQK)`xtO^tiEB$1DgP1GyV z6zYZdcP08?i?$LsfBN#}S4l}FIA$Xn;tb(wk7(oC8FdpDAjR)qwPb}wZuYilJbc&y zr?A~x@e&RK8uH%I#pG-Cs275mkh60It6KH@j??C>!MWK>6r)7%G8OCRZPR7_59h*q zrp}Mimw!)VQY$jfp%6m)HYH(BjuyRW65kjL48AicI{%Rfvl5M5?b125^)KI_)2~ds z{*9S2qa|WJvFxIs_teqIbq(|w5nGe+{sDcMWOE(K4XqM&X4GP&&wy!Z8|@YS2-?`1 zSFGrklg-OsK8~bpR@es~vSV8}EjO1QUk9}^I|YS29dzB^dy8>L_o`i7P&dl9GRfmR z24a1NaAy~nt5>cpEX13em{^#aa>b&-VS!~p^4)F5v zd3dLcl8{i(19u0vwKY{@(*Pw7NCmAkvx8;JRx#t_#}>&lGUjt}ajn`{O-)U$#ZHVC z&rl%!VjAJyfvV8ZXAR5oOku&7&Gq!Zj86V7Q54J&&fxjNW?Qi? zK=rsg8j(X6o`pG|?(w22Rk!%Y!SRbCVbnS`Wo_N*Y`aDHR93}l-)~+jz{sHE#)^$0 zBEx(AVza`hPzci5GxT3 zRz8m~sTF%ZwUfX+xA>Hg-2+lkFfa){Ru*Q$)|+g{GqJqBu-(2btVmCn5V}W818K~> zygbo?UKgxY&*qP=!Em42{l4;2b!I|Bn~_G5#5aH)%hfsm{P(?Yg#0y$i6*+b?^~Tl z)Jq+9rwKu+2eYxd3OL1+)%?@HpM+hxdNr1wkDCuWdX-WM?;-Aq9vyvdAjaSiJ<&!v z9S8LWT{x9bH9qR8&?r^~CSi2@AbT0MD_aVgyn;YxEqj6dTBOXrBnG zcY00s_uCC`)T|ljRnps80;hoB&g>jq?cD~0 zC7YvG>2V&JYH(YW1o9H3q_0HRlnMm|1vaMEA3Pw~M+7ddVri4s*7WfLrM*TSo%a8d zbCAwe&JKiZ02P(P(oe$KdG$;s6^(?i-+prDqG}Thv$Ij<8>?MZ7@H!KF?_hWt><#E^Ep$p&TTc@u^hilYHN^KCxzAr7 zQo9kCDirXB|K8)rZDPM{H#_q0hzrxwPcL*S?>R`-RlB9yx6NGPcUli`OEEE_=N+xo zAK0`p{f`8LQ4wRYP#piL1&7f%pm&Fdtxj$rG<(d7BJ=ZuV`5h8uk1G)VQSr>02?&l z5lQ#;6&cxc^|2b93UsuoX>CO4vvl0XWNqykMAVQR1SmnkB$bAmQq9{#d9Plb+_PrS zPdNin7LiWxhgk=QZ^%RyRa6q-dx?o{Yz*DkD{2r9@vQ8jBsFY7*?DXl;;b?cw#>!z z7k1a3)Ej;@hCaS2C@83G$gB}n8sI)(vwuE{5eC&XWykfZ-DhF62x-V|lslnqj{Sio zK3_X-H(STD*Oc>d>iiu#ESr=brci(X$ia-Ay?@@e2{sZ7i}f|dVw!8JMpj>f6Iuau z*(8f`4(yl@4^Kplcgg=Kx4?v#zFnRXyLm@k2lKPy{Kx&(`IZeTfoK2aqQ%9bTnGIU zPInw0WLX&t9L(1|e;n~qP1RYv%JvZMrj_0w$7@$sbyel_`Bfu~aN>bh^rOPvTc43v z*!O82yUwOgiASUeqF%px{Y}tHJ34zcMWfs@QbjRWyYypCUPyZSVwh|m{;h9)y}fG6 z$|2$K=vqvqMh49OL4Ln%E8!Vn!r=`wT)%O{?eHSQpjl5X%ch+XuHIwm%E!R44Mr}h z*LZ{h@v#6ln0}Y@ul9ly-DtbP`6mkGy-ab#tBrQE4kw<&HG@%jmo-k- z((^s494HW`0fL*5svsUW+v~$p3(xv)J($U8zrt;e`)t$F)HFXx8TXxjUyvz-EUqq9LmZK?Y@rO5@v)tmLjjcn=LH!3wPUB@P%Yh-_c5Ui%9`GCw> z)D-TqcywZz;kVcGj_#epu@z?sk2zDP61e_~`asmToMKDBYH4B5_gkKeWme*u>E^0u)E>qx-{$gn#!;?YsCtW|7pVDzY((kuf1gD{IY_K3#Z-< S!O@FmONz;e=DpDU_!^V(Lil`tvY``aa|rvB>^2S|J6&$> z1ge8xFz@^K2^`>$SPxS#y@XO}TeCzD5Bn)j;e@gHp5s@8vpN2lq~&iJPG5gD?fLV^ z)J(=3oxPl0b1;mF=p{l1*F-=NcvN2VgA=2*xRM;raJY~L*WL~0WC>Fp8g4HsVR#s{HiC%)T-!|g^Jx)$Hu4(XA%Ni>& zmy(JRh8e16AGRS-aU`rF`#{qKsL%s5<$6a)$&;mwc7NSp;B!F!vc0S?6xH>4&S=!9 zXqsZ?tEahdq2ay_4f5hPUTQFAN4ooh6m5~BnbBkMqWU@}2GLRH5jy43W7Gn^y00x9 z9I}I9Nkh!%UqEx3)iVxP-^*jat8x^V6w5CsencZ_Djw0`jg>}a`~1F@UkIXODZ6)) z<>WDGVcg%uV-g~aLvs@E>rSUfbP@%0V5W~yM{`F1#rvkp^fQJLT@D)tH|--r1(ll< z^E0oIAE*83@M7Ap)KgWW!i?v>A6x{i+)N%pDs)rU&7KX^W(`(?3YoX8j@b8yC}i^2 zD7#k<8{ORrS#ud9{|pZglalSFez2B{Oi6xr)8^t9=_Hp~U>wiwa6g zF=b`)<3)4Y?k6jLF9l)c8&dAN}x;=3aJrav-eW7@?3hN^hji$gvR-|cLuIz^L#u)V6e6@CU<%E#GdspFB zcRzLFl#rJ~3SqDu$;48dl~f31d}MgIT+Kp5!%d*MCAEY_US41S06ypI;_~mz z)Yz^KB-5rFfJ=U}p@K-S!+X~@;R~6W`re0SM&A0&Cdpj(G|ZK5ngqH0guki@+v*Oh zmobP!NknR@tG`aOv$F@`d17GOopuHGr2s+MIpPPy($esDfKhpBVi-n!~-jipps z%?~%Rnos;C6L~pTjp25_|6Qle&&JpN>J%A;tDs4sP&T7;w(ehrX^o4MQ&jcdLW}oH z624{&byd~b8Z36_!%w^8)bbP-Gu4gzvY%6U4vsgl($XM=97W?KFCqFf)g|A*cR@dX zbl97lgsCeR{cUR_BVDX)4B;bx^(u60+?(5e(`kDm{O{ke7ldP+oSYa?m$TiD7h{1x zs&8f;=c5*hobcYGmD#TCS}%2WuQ+G~XjpPs&cr2iJ8m(Nk%0c0d-QG@nV6XP-@kvp zz4lzQ$=nzg)0IWPn-AgTI%CrPeSKNk=D(H9ByNev`(ZJB1s4Zhdt2~=vw!|1!LQ%T z|Ug9Y8nGCo8iKL`guXI~zhWNiEx?D{xKB)^OSh+jsI`X)?8Eo1OOUHc=TCf8JP%w2PfB`&{@biCE*z~55pkRO z0>7-JBu{(Zd)mR#k9!SlG|x!30n>U>^FEm$MqJ5ey9t`D*8@mI>R~ z1e#>z8FX!@#%hfyi6C9f3mAMxSureDuUB@s$t%GS883d01$E*{(3#+MJ-t2}G%V79 zjoIyN?rco8_Q_x3AM;g-Zw;k-HnV4E1S{mIP$I3qO9xB#E#YH+#Nr5G> znc)(+L|%!{30PlgHM*UI@+(!>)&_Pg=H})uEQGxzs;8r)1Cv4b@8ejtzjk?sJ-D1Q zjb4V6jfr&h1{uN^dy{3Mgvz++zgf7aqXw}(ug?#bxLtm<}GHjnw&QK+#Qxea@-Jy&t zALON}Dy#8a*|y!;I``X)9Bd&r%b8r(*vzc*HE%m3Glx0$f=EXp3KOPx?-bKyUJ~>C z77ixZnX0%sUvk!{Q7V{ibnl9I7X)^Dg$&_f(7u}+k*|y;bafs#omP#iQ+1BT1Z<{G z&dxBkleP1M;;vJ~XU|@~{@Vn0CZoX=mi2-2My}-DO}N?ZZClNOl#b57lP!*~wzjl9 zb>9rYE>p#*cB~3kfa$oy)$zzv7Q;RnswleN+ncjhp&-7!DR`Y>e*!SGDXb=ooxz@1 zP%wioHsJ+>{CC>PTotaz>$fe>ZN+&wO-xMadcn@sKRkTcFLk6Il)VAW>YEQ=so2

~mAR+y__1i{>37DpmF+f$Yuv9KxQG%XB5I8W8@oa?cz8A? zJR%{s@6NpC(X>v#IqPNsvfQsshl)3QD{r#_j>4%4hC{<-TZNf1IjkhiV$;q<~u4j~z z2}y~G5=fKv&OyQ%7u#iboF69mT~FQqwMw6ubhi4Y(reZ_%{TIfho31Gs$5*{HR1Df zg84P?e%1!;yJj6O*qLHixLT|@8FW~jydxqbt1M@=1ReEu=RIXG`tSYFs8{b|xnt7R zhD_l$L~K2GvD!*eDkBv!t{U4%Hjer>ZhYGOqIsa-nr=>kk(=!!!mfXjKP5s0>i%*Q zZ%qC2$=qDSB*G_ubwnDE)pXQ&rH3C26LWJkui;AzrJ&$iKhcBxDS&e*e1;`nEbjit z)Wn3-^|TL6R!%Oi?Ck6mKKIo@e&wz43`8d^#m$U+M_$Gwy|Ot>jc8W}>_ zh_S-s?jNm11%|W~!^N=Lr`z-=zYF5atwo*N|ByC9>qA^M5>l zics&a;9Mh@7nM#+_T)J@p8EmEgH6xG04BGhSd3c1T9Pb;=I~Fo9N5!dFC)+yi%@&RJ(^X_>TDR10TzGg7Q*}JT9y&}ZGCZ83 z$`KpMXEo&h4u2)l&`6^rAv)MR4;Ic+SXPk1Lr{#73x^HmE}w=x{@y%O0!kr7J(ng8 zPpFs88yy}S<0Io`qor+I4t}D5DxL++fKUA)vhy(>b(-P;MHN`Gorzh5hIsg-oAFSD zNJ~`GWeZrChnZ%OzI824PfQ^Dq|a#hs$~ru!_{7-yt|(h@a8QZLDF#5AMZ%Re{?Oy zR^TK{<$x%oiw1i#pC?)^SW)JY78VNqCtO@;+K<7tqYJmd*8KYzQU-p240#;>cWPKk zL{!Ppe!6zqk6^BO&;>W`w|WN$dEB52dGJU*Wf46xtPW!pM)_`#Qux_ z)`u_ySh)!cFz@>fq1milg-*5rzWVaNI58hR0ll^KXHDDvK``EkTPzRNzCj+s5fEA- z{XfT%|KAq*VYT~k6Zwc$Q@f`xL)`dM)2VE`bbm_ajF?tX{|R_M#3)`Pv36`iZnB6kG_x$*Hw0=gz)?e?ZuZp=5ZI$EK z^3uwHde^%4ORQRSSMKkT-ZJKbM;EUp{0zKO;4M>6M z8ndQ&$}M%_17ZV?4yCy>)eCG!MnMENT5Hd^Y@f>!cVmHy3(1Ci3vm%iV6pX3v%TvW z8p^9yCj5Zq>MFP*jOe#)qmz*UKa_fTi1=`ogNy6qV+C6gS*Z<^JU5S$_;24t0_eY% z7#ZrK)+P*~2rya{mtqK>!J|EZm81 z>o4Q`RvMfeygokM5tvtD_=i3u9_J3gkW0kSY1KOob%&GD(ajmdionm6g>}c<8%Gqp zF=Rizcth}6dX^i&MFl$2Ok8$nCRU{q`noGE{ zHaawhPStI>duV@uJd~@dvXYotUuI{@a&mG~B;<|jCZFuaAl! zfB$m0902@~dAFmRSNv{QC*yu?J|HlBM?nFC+_tGHm+gt60_Ea=xC$|U^!abkZ9!E3 zk)qb9#PA*s9DwZY|L--*XhXLHP6T3o!RuaB;%tF>gd>F!Ibk2UDGAAv5zg{tz5 z#i!3-zMd@4=Lvt4hpMV-(@o|5OtP&z+uJ(>bCj27v!km?qr&uL3^rYT2quWl zinaB@));KQ-dW<^8_lgtFYZBB|KjD4({NmmlT|W!z*hb;T4#&j_@KmSrOr^5OlxXx z=<_v-?6S%jyFGT&J=}|rJrzGKd;cWuQxc#;cBYkg*~F4t9U!<2syOQJBn?``G)&P&5AL= z91g-}&h-sD-%3Q5YiGqRM8OMH^*}@!%cz~FTIN^hn(W2jxkilS+X~#>y?M`Hj5T%} zD6!<|P_-&coYzj`Fr~GXm8Z{Aj7PFhnpRS}LQ@s;6lkKksMfs>CU|(&lR0grU`n*u zfx(1#9;e&R)@)#9xgIW46NgfwBavgiR~D635bd`2(`jvOC3^Gb=jgJ&krCy)cjK@v zDI}BOOzThW4W*sgL&o~d)RH5>i3=kK;~b}XwAv5QnHMN`=X!7u0w6JXvN$K|$fM-%<}S0ebaQc~G~SIw+Cj?q+=`<7__F`Cn_t zyvJ3?U@^(r$@&;95je7}wyWFnIZ}7mN75{YpNoAm3LtAI7L>Ji$~VVZoeNn%j5Z~| ziz|z`l%|e$q|9OG{&dr7A8!dCgl~n?n07nM-(&`xp*|j1ne&Ly-Vygvqe!DX7bmjV zXuz{gZ5jsaw0Lc&E^ccB61PZcU%Fz!ndL^1I)75b6dfIvvOsJ7JI(RwN+*R0GK7OT z-!XO2LMDhKD>Vupj{1+ref&%-cbr&uG-@RBN=$teXPYb4m4PnQ)nxX)kQ)m3ln8TX z(7EhShjHhuynzWSl8qz8om&a<7<+Ql$H*UQ!`^WT%Pc{xx30^M~8(Oo0%0buAKr4l5MiY#)*Lu9!$s)0v2txbq1T+ zSS(v5u))WhD@y=Wffx9c84WhLUG$tk0)C2sZ)r)%AF$$g;h;`3Hy$=Ft}s$Spv(5! z+IXJ)bB1E1moK$Sm(8Hv{fSk(Gss(06=t74E!R7f%+)!1ULME$gf%xeZ*Q9u5)v}Z zS3BOC1WCrf(qpZ7bAe}Bph4t>b=8do zf${k8lN%VUt$OCT9s2daQ;28fp%}vx!Ko>2T8#yplfXViB(+qUkuU5ju-akmOL9yx%eeEhx25f9qE(yPpx zaE&cN5ebe{b8}x!ReZrZwe;eF&}{yhEE5F7L3MLB4{Wu2fPHCc>Gt+ECKeVl#HL0Q zpwx{T3{?`M-HhYoMyfG{`(&8Nchf)UmE-GbWHl<8+|GZ4acuAELiP0;gQ?>q_c`?g z>s@9j`RY|ua(KATa%%LVu7tQa3etoSlF3-%#`%Gs=k3Kfru2QtqmcCTCz_er)}ofA zw6qmGe$ zM|zQmM?RDXYS8X$crjy@)16k)nK?aLeUVFak4yD_LLF)~PrE{4)-j^CNwexxh`v|x zXnt!1qNC&4E55ki;IEv{huF#!wH0f}8+%w#W)>E!S(GJ|I>$Y*QGbAnYG`PD{#=;% zn5qA}uaAc3#UcE+PPUturizNw-L1PXG|ksn=s!<6 z{8H4MoHde(V?4ygBBA3!sJ{O5yW_>hqU7b}QIe^A@O~Js<9PbMJ3?T(6Ay9fAb=94 zoxXIM0YBKl(D3r|l;*>FZZ|P%7X>y79^LuG&`@~dvc>ZIZ7@JGoTQ|rCm#cj4g2Ew z^t-=6yGsrDE#@2HJw1mrHNU9k=NMJ|4eWi@GpGX71FJ7}RZpiX7C;=o>FI}tZ@Br9 zT8S4=a6G0JYy1dvB>r&+m$w9lCdTu296a|9x#j4-qNAP)5$qZo%}B0mlbft}V@CEq z%Dcb)hqqJhROqSfuRes4o76XIQlMpDhsLFUqgEV~IDyTl~XpQl7YuxBx z>xITZv!pJC58_kJ_4%gxR^KB<8u-SDk*20*^`Tyu)cMt`Ex=%m=CND~dwDUOUz})G z?_)u`qiM&9`9ny3l6ag=Pq*>!y+cYJpRk*&SD*$S%2PZB4Q67M05&qx-HVHp*{Z#7 zjhWrVK|go4Cx0Phb&8P#z;s!&?lkIb8N_ejOtxog%-a0yZ?3M0_*3|!Yrw`e?|HX# zcYDSO(O>Syn6BDesGObMikeW<*UyYqcD*SEKs*k3q5lTknL4(RW|N0E?b*RbT9a_$ zn~z*UWGNZzlcQR&l_dxN_<3B)6}I(R!bu^HWM1xX z3hYbP&Wu>lyT7MDrmIA6_ ze9*Moc8#G5urwp79%=&?TZ~<*F}x0R`x7P2Ui3abGf2oaI)As9x@4PfYrUq&n(&`~ z9JY#8VSzy2v$Iz&{L1j+-893+pWc~v1muSN^2L3(_c-n^qygjZhH9*(aeqgi-kq%{wVX4Nj%}w=0dm|=Ddg&pi37yLoen$VXa^y|XTAL!~MEg5{N8Ok0Gisbz*L)AkK$u$*{{ZRNxLQBz6vd#ST#0(WPnGUYaQ zdEnUb{}fOMQviU!9WMysAjy6USly|3<=)e#@a8D$5s&Kw zO5hc5joq-h9It!cPHyk3YRqjjXURz6zjs1|faJ<0+NDPbN%mcp{ zTeS`+TE7=YuqdT4p;F0Qyaqk2fGz_JnN%YC34pHv@S5Jk)#ygQiL5@3hkb3IpGwXZ zK8v0ELsCEIQcP`>cG0@Fe+y-Pk1<$UhvO*?ai?k5`44qmMM*QP8M|9a@kPOltPIkKDB| z#fu79@WW<2Ig7O<=M?y{=07`$$k3}hcXZ&^sZm7*h>~A!mr1AcIG37@6W_Go^R~G? z^;`}$#BLokvQeqw=SIhG>D3gj>~G4V3$w`iQz!5<={DLw{-0Wa`U8Om-4MyAC-!7| zqOOD^jGsNvEKh5XD6A@4<85XzauxDh2j%ah@^6QncrlLWrbSlj;RR3b6lrYP$?duVrQd9j!8Pa)Xjq}CA4Qr)FEm?f)C4E!C1a_<$nRb;!qq}bMq zlI;ILD*(G~lHdSaF$6G2VT`&(U^)t4?D#i1$tgsgGkzi}A)!cPBkqRgj7UWns_j^zB&F00kF?zVA?}<0LrR3D zkb#%JqMB`?2PG$*kHU!L@#rWjpnU*0j(rDy@(`vE`HJHLOp#2GIB4z$oP~{h8 z6s46-X+gGy08W96bvrIU9aaK1?YF-x${0mZ6{)1rgR%hDUZ9xBjedWsZ&g0R8MsJ@ zx+R%~+)8OYf;45is+}{k50|M|eC-$BQ`l3hjMIbV^Y~G3>1xOW2D$)iEiDv~SW(E&cZ@VL9sfzQ3mjzg2f=RV1gCK@E;;*B(;Y9Tor11 zyI=dv50}rXgTH;7rHSsD`FDRV0c097>93`_A$`)0rDKwMxqzFp8jh-{0D_PH1P-e) zSixDVG`~??{*^{0AVNala9+3n84<;-uA`ml{QkuMKQp4>j*~*UZ!&wC7cVu&1=f!G zfN^$D{TT+`Fl<-eML3>9r^bU$`}EF|mU;eK;@lBYhN zJh(S z_`5fkZxAG(Gx&AC{~oBloa~h#s8Ft5>Pq zMii23()x~ec38L^bu?*63t&rOm?CX;i)TSVE~Qh2OK}jpY5( z`ZlS!;3ASz!PYBmfCXI~$pvh?y$`ck8StDI*h@xJqS>udJpb&jz(b}#xU%PV|CSgz1dij(_$e{*$tO|_ zNTxy1>Lsq4bLDbrkju#?CX|_(nM8z_dL}%_s5eiZ0t5QmZ?aKut!n

1dT6`Xe%O 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 diff --git a/frontend/__snapshots__/scenes-app-insights-trendsvalue--trends-area-edit--light.png b/frontend/__snapshots__/scenes-app-insights-trendsvalue--trends-area-edit--light.png index 176e4d0aea1495157002c730555b52dcddff723d..fa59bb523f481218118840b1eb53f3dbe443673f 100644 GIT binary patch literal 77775 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

&?+UHf|k>6Lo)F5e>ER@lrM= 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 Hr-UW|zQW8{ literal 20341 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
W7&;o8W?K_WY<6T(J(t0V?P=xUB!j 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

35q@XWrZMAcZO_ZV#rP zNQfuW-lRl3bxJypUl%r>JlpG{C{tV1QmBpcT;32zejF&hWvL=cF7!%H?s58VRdT%V zRj+Ub12M4@PmjOfp%cn(WrzokYmblrCq`*%ng#s+9m%SrWN;4zP&eQnTI@an#&%d7 z$#5;nEov(FMEoJ5(-ZHbT#U0iJ7Ji@%F1EB%!!D#N-c!0u08Tx$HX7OZWh0^t^`xz z=$Ng)lfG&F(y3MMpqA&BO8RDFQiMk6pnkSZ!-q6Z823A8qx#)F@#p{!znD5+&pdrN z+6v(*Z3N{;_@i6rp13?T20J-93E^I{>Uhw@zIu}=DD`LOW@LZ_qu6I?qarVVm5gj! zI6~dIJTsF;UxT^#%%b)3fOYyk`=y~5%#DKubMj$xIj*kedV03K0dlIU^J}!E+J}*z zLUY5RVN9NX^f=EE5b*x2VHa>nfrBLtT=O1BooTb5uMiQPS#s_Q3%gn{sCnYG{~;;j za0i86w9Hh;w6w6Wu;ANL!n0ykl$D3fcniubQps-Ih?O?LvTuJ-^e;gk>p73Pui*+; zjFpsj-@kvqx98!0uuC5C;EDYWm-^A3CAFv-5Pq2BVw9AXFH>{AX&;%+drMo5^FK3j zN4yJEv;&}IWrg>D;c$n13GG#`ySTeM-k`a-tbU(6eps_$_c;Et!mX_f2py0egypq8 ziqaadkdn#?WUB6j+a#|L&s#m_B+)0LQ!h5TLPlnH2RprUDX4`t`(_UEV`7!d-ac+J ziy+0l;4Y8-l<$SU5Rt)K;u zhG^q4v#b;)mw_Ed`F`<KMCI2SPWjmP;x( z-D};KKl*o~PK}%nn3-r#7$0>ul#6apI3W3mLWk4Vbi6FGMrmD=ocH;WTYPTp3e_#E z?kRV~$Z3dr0`w~En_6hOF3W^WMd*ao0d>r?fdU}sW2T0g3+BbYbl|;+itjHOb#O0E)MJs8Vx~S+S zO9dkeKV6aYTASbDR|sF1&`2fC*A!T94hr7BfT*zyTs@fmkQ;}*fxN*_H_hUzuNrRE z#W5iX&qzPQoq6UR7ontS%WpbTO;Rn~s6BP0s(4OHJ*jD# z;(5Z!sP*pB%NNC2e*hO}Wtf;%hx%^ad+cR_#VS?LtT&H<>)PTc#H}}%==oRYwz%FQ z;ec#!tc=5A@M<##2H%7`phe3J4zN?vd?5?J7)+q&s9k^_ur{gyvQ>tRaCrECjbK#h TEylOLppf=-^>bP0l+XkK5-{87 diff --git a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--dark.png b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--dark.png index 397d2310803db6c85da8dc9afd5bfa16fe43bc24..b897157a5261d2df1289f1cc50d94751822fc200 100644 GIT binary patch literal 160044 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

{PrXN>|(-% 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�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%0AxnxFM&LIhB2I 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%0Dee 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 ) : null @@ -834,9 +835,10 @@ function ReasoningAnswer({ content, completed, id, showCompletionIcon = true }: interface ToolCallsAnswerProps { toolCalls: EnhancedToolCall[] + registeredToolMap: Record } -function ToolCallsAnswer({ toolCalls }: ToolCallsAnswerProps): JSX.Element { +function ToolCallsAnswer({ toolCalls, registeredToolMap }: ToolCallsAnswerProps): JSX.Element { // Separate todo_write tool calls from regular tool calls const todoWriteToolCalls = toolCalls.filter((tc) => tc.name === 'todo_write') const regularToolCalls = toolCalls.filter((tc) => tc.name !== 'todo_write') @@ -867,7 +869,7 @@ function ToolCallsAnswer({ toolCalls }: ToolCallsAnswerProps): JSX.Element { let description = `Executing ${toolCall.name}` if (definition) { if (definition.displayFormatter) { - description = definition.displayFormatter(toolCall) + description = definition.displayFormatter(toolCall, { registeredToolMap }) } if (commentary) { description = commentary diff --git a/frontend/src/scenes/max/components/ToolsDisplay.tsx b/frontend/src/scenes/max/components/ToolsDisplay.tsx index 5b5f8008db..da43f87adf 100644 --- a/frontend/src/scenes/max/components/ToolsDisplay.tsx +++ b/frontend/src/scenes/max/components/ToolsDisplay.tsx @@ -68,7 +68,8 @@ export const ToolsDisplay: React.FC = ({ isFloating, tools, b // or border-secondary (--color-posthog-3000-400) because the former is almost invisible here, and the latter too distinct {toolDef?.icon || } - {toolDef?.name} + {/* Controls how the create_and_query_insight tool displays its name */} + {tool.name} ) })} @@ -173,7 +174,9 @@ function ToolsExplanation({ toolsInReverse }: { toolsInReverse: ToolRegistration if (toolDef?.subtools) { tools.push(...Object.values(toolDef.subtools)) } else { - tools.push({ name: toolDef?.name, description: toolDef?.description, icon: toolDef?.icon }) + // Taking `tool` name and description from the registered tool, not the tool definition. + // This makes tool substitution correctly work (create_and_query_insight). + tools.push({ name: tool.name, description: tool.description, icon: toolDef?.icon }) } return tools }, diff --git a/frontend/src/scenes/max/max-constants.tsx b/frontend/src/scenes/max/max-constants.tsx index d60e737480..2400d7c9ab 100644 --- a/frontend/src/scenes/max/max-constants.tsx +++ b/frontend/src/scenes/max/max-constants.tsx @@ -25,7 +25,10 @@ export interface ToolDefinition { ToolDefinition > icon: JSX.Element - displayFormatter?: (toolCall: EnhancedToolCall) => string + displayFormatter?: ( + toolCall: EnhancedToolCall, + { registeredToolMap }: { registeredToolMap: Record } + ) => string /** * If only available in a specific product, specify it here. * We're using Scene instead of ProductKey, because that's more flexible (specifically for SQL editor there @@ -160,14 +163,18 @@ export const TOOL_DEFINITIONS: Record, Tool }, }, create_and_query_insight: { - name: 'Query data', - description: 'Query data by creating insights and SQL queries', + name: 'Edit the insight', + description: "Edit the insight you're viewing", icon: iconForType('product_analytics'), - displayFormatter: (toolCall) => { - if (toolCall.status === 'completed') { - return 'Created an insight' + product: Scene.Insight, + displayFormatter: (toolCall, { registeredToolMap }) => { + const isEditing = registeredToolMap.create_and_query_insight + if (isEditing) { + return toolCall.status === 'completed' + ? 'Edited the insight you are viewing' + : 'Editing the insight you are viewing...' } - return 'Creating an insight...' + return toolCall.status === 'completed' ? 'Created an insight' : 'Creating an insight...' }, }, search_session_recordings: { @@ -327,18 +334,6 @@ export const TOOL_DEFINITIONS: Record, Tool return 'Fixing SQL...' }, }, - edit_current_insight: { - name: 'Edit the insight', - description: "Edit the insight you're viewing", - icon: iconForType('product_analytics'), - product: Scene.Insight, - displayFormatter: (toolCall) => { - if (toolCall.status === 'completed') { - return 'Edited the insight you are viewing' - } - return 'Editing the insight you are viewing...' - }, - }, filter_revenue_analytics: { name: 'Filter revenue analytics', description: 'Filter revenue analytics to find the most impactful revenue insights', diff --git a/frontend/src/scenes/max/maxGlobalLogic.tsx b/frontend/src/scenes/max/maxGlobalLogic.tsx index 9e238fd1aa..cac6232a74 100644 --- a/frontend/src/scenes/max/maxGlobalLogic.tsx +++ b/frontend/src/scenes/max/maxGlobalLogic.tsx @@ -73,8 +73,8 @@ export const STATIC_TOOLS: ToolRegistration[] = [ }, { identifier: 'create_and_query_insight' as const, - name: TOOL_DEFINITIONS['create_and_query_insight'].name, - description: TOOL_DEFINITIONS['create_and_query_insight'].description, + name: 'Query data', + description: 'Query data by creating insights and SQL queries', }, ] @@ -210,17 +210,10 @@ export const maxGlobalLogic = kea([ ], toolMap: [ (s) => [s.registeredToolMap, s.availableStaticTools], - (registeredToolMap, availableStaticTools) => { - if (registeredToolMap.edit_current_insight) { - availableStaticTools = availableStaticTools.filter( - (tool) => tool.identifier !== 'create_and_query_insight' - ) - } - return { - ...Object.fromEntries(availableStaticTools.map((tool) => [tool.identifier, tool])), - ...registeredToolMap, - } - }, + (registeredToolMap, availableStaticTools) => ({ + ...Object.fromEntries(availableStaticTools.map((tool) => [tool.identifier, tool])), + ...registeredToolMap, + }), ], tools: [(s) => [s.toolMap], (toolMap): ToolRegistration[] => Object.values(toolMap)], editInsightToolRegistered: [ diff --git a/posthog/schema.py b/posthog/schema.py index 24e071dfd4..ba02d59095 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -267,7 +267,6 @@ class AssistantTool(StrEnum): CREATE_HOG_FUNCTION_INPUTS = "create_hog_function_inputs" CREATE_MESSAGE_TEMPLATE = "create_message_template" NAVIGATE = "navigate" - EDIT_CURRENT_INSIGHT = "edit_current_insight" FILTER_ERROR_TRACKING_ISSUES = "filter_error_tracking_issues" FIND_ERROR_TRACKING_IMPACTFUL_ISSUE_EVENT_LIST = "find_error_tracking_impactful_issue_event_list" EXPERIMENT_RESULTS_SUMMARY = "experiment_results_summary" diff --git a/products/dashboards/backend/test/test_max_tool_integration.py b/products/dashboards/backend/test/test_max_tool_integration.py index 80011d75dd..37d4fa86a9 100644 --- a/products/dashboards/backend/test/test_max_tool_integration.py +++ b/products/dashboards/backend/test/test_max_tool_integration.py @@ -96,7 +96,6 @@ async def test_dashboard_metadata_update(dashboard_setup): tool = EditCurrentDashboardTool( team=dashboard.team, user=conversation.user, - tool_call_id="test-tool-call-id", config=RunnableConfig( configurable={ "thread_id": conversation.id, @@ -133,7 +132,6 @@ async def test_dashboard_metadata_update_no_permissions(dashboard_setup_no_perms tool = EditCurrentDashboardTool( team=dashboard.team, user=conversation.user, - tool_call_id="test-tool-call-id", config=RunnableConfig( configurable={ "thread_id": conversation.id, @@ -155,7 +153,6 @@ async def test_dashboard_add_insights(dashboard_setup): tool = EditCurrentDashboardTool( team=dashboard.team, user=conversation.user, - tool_call_id="test-tool-call-id", config=RunnableConfig( configurable={ "thread_id": conversation.id, diff --git a/products/dashboards/backend/test/test_max_tools.py b/products/dashboards/backend/test/test_max_tools.py index 711608f997..206417d67b 100644 --- a/products/dashboards/backend/test/test_max_tools.py +++ b/products/dashboards/backend/test/test_max_tools.py @@ -25,9 +25,7 @@ class TestEditCurrentDashboardTool: configurable = {"team": mock_team, "user": mock_user} if context: configurable["contextual_tools"] = {"edit_current_dashboard": context} - tool = EditCurrentDashboardTool( - team=mock_team, user=mock_user, config={"configurable": configurable}, tool_call_id="test-tool-call-id" - ) + tool = EditCurrentDashboardTool(team=mock_team, user=mock_user, config={"configurable": configurable}) return tool @pytest.mark.asyncio diff --git a/products/data_warehouse/backend/max_tools.py b/products/data_warehouse/backend/max_tools.py index 92f76f5438..b7d9384d3f 100644 --- a/products/data_warehouse/backend/max_tools.py +++ b/products/data_warehouse/backend/max_tools.py @@ -113,11 +113,10 @@ class HogQLGeneratorToolsNode(TaxonomyAgentToolsNode[TaxonomyAgentState, Taxonom class HogQLGeneratorGraph(TaxonomyAgent[TaxonomyAgentState, TaxonomyAgentState[FinalAnswerArgs]]): - def __init__(self, team: Team, user: User, tool_call_id: str): + def __init__(self, team: Team, user: User): super().__init__( team, user, - tool_call_id, loop_node_class=HogQLGeneratorNode, tools_node_class=HogQLGeneratorToolsNode, toolkit_class=HogQLGeneratorToolkit, @@ -134,9 +133,7 @@ class HogQLGeneratorTool(HogQLGeneratorMixin, MaxTool): current_query: str | None = self.context.get("current_query", "") user_prompt = HOGQL_GENERATOR_USER_PROMPT.format(instructions=instructions, current_query=current_query) - graph = HogQLGeneratorGraph( - team=self._team, user=self._user, tool_call_id=self._tool_call_id - ).compile_full_graph() + graph = HogQLGeneratorGraph(team=self._team, user=self._user).compile_full_graph() graph_context = { "change": user_prompt, diff --git a/products/data_warehouse/backend/test/test_max_tools.py b/products/data_warehouse/backend/test/test_max_tools.py index 30ba13ea3c..c780b868bf 100644 --- a/products/data_warehouse/backend/test/test_max_tools.py +++ b/products/data_warehouse/backend/test/test_max_tools.py @@ -43,9 +43,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): mock_graph.ainvoke.return_value = mock_result mock_compile.return_value = mock_graph - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) tool_call = AssistantToolCall( id="1", name="generate_hogql_query", @@ -83,9 +81,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): mock_graph.ainvoke.return_value = mock_result mock_compile.return_value = mock_graph - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) tool_call = AssistantToolCall( id="1", name="generate_hogql_query", @@ -119,9 +115,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): mock_compile.return_value = mock_graph - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) tool_call = AssistantToolCall( id="1", name="generate_hogql_query", @@ -171,9 +165,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): "SELECT suspicious_query FROM events", "Suspicious query detected" ) - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) tool_call = AssistantToolCall( id="1", name="generate_hogql_query", @@ -223,9 +215,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): mock_graph.ainvoke.return_value = mock_result mock_compile.return_value = mock_graph - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) tool_call = AssistantToolCall( id="1", name="generate_hogql_query", @@ -263,9 +253,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): mock_graph.ainvoke.return_value = graph_result mock_compile.return_value = mock_graph - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) tool_call = AssistantToolCall( id="1", name="generate_hogql_query", @@ -301,9 +289,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): mock_graph.ainvoke.return_value = graph_result mock_compile.return_value = mock_graph - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) tool_call = AssistantToolCall( id="1", name="generate_hogql_query", @@ -339,9 +325,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): mock_graph.ainvoke.return_value = graph_result mock_compile.return_value = mock_graph - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) tool_call = AssistantToolCall( id="1", name="generate_hogql_query", @@ -353,9 +337,7 @@ class TestDataWarehouseMaxTools(NonAtomicBaseTest): def test_current_query_included_in_system_prompt_template(self): """Test that the system prompt template includes the current query section.""" - tool = HogQLGeneratorTool( - team=self.team, user=self.user, state=AssistantState(messages=[]), tool_call_id="test-tool-call-id" - ) + tool = HogQLGeneratorTool(team=self.team, user=self.user, state=AssistantState(messages=[])) # Verify the system prompt template contains the expected current query section self.assertIn("The current HogQL query", tool.context_prompt_template) diff --git a/products/error_tracking/backend/max_tools.py b/products/error_tracking/backend/max_tools.py index 95fc69075a..d994186403 100644 --- a/products/error_tracking/backend/max_tools.py +++ b/products/error_tracking/backend/max_tools.py @@ -155,11 +155,10 @@ class ErrorTrackingIssueImpactToolsNode( class ErrorTrackingIssueImpactGraph( TaxonomyAgent[TaxonomyAgentState, TaxonomyAgentState[ErrorTrackingIssueImpactToolOutput]] ): - def __init__(self, team: Team, user: User, tool_call_id: str): + def __init__(self, team: Team, user: User): super().__init__( team, user, - tool_call_id, loop_node_class=ErrorTrackingIssueImpactLoopNode, tools_node_class=ErrorTrackingIssueImpactToolsNode, toolkit_class=ErrorTrackingIssueImpactToolkit, @@ -177,7 +176,7 @@ class ErrorTrackingIssueImpactTool(MaxTool): args_schema: type[BaseModel] = IssueImpactQueryArgs async def _arun_impl(self, instructions: str) -> tuple[str, ErrorTrackingIssueImpactToolOutput]: - graph = ErrorTrackingIssueImpactGraph(team=self._team, user=self._user, tool_call_id=self._tool_call_id) + graph = ErrorTrackingIssueImpactGraph(team=self._team, user=self._user) graph_context = { "change": f"Goal: {instructions}", diff --git a/products/feature_flags/backend/max_tools.py b/products/feature_flags/backend/max_tools.py index 14d8a08b21..7cfaa5bd88 100644 --- a/products/feature_flags/backend/max_tools.py +++ b/products/feature_flags/backend/max_tools.py @@ -439,11 +439,10 @@ class FeatureFlagGeneratorGraph(TaxonomyAgent[TaxonomyAgentState, TaxonomyAgentS 4. Generate structured feature flag configuration """ - def __init__(self, team: Team, user: User, tool_call_id: str): + def __init__(self, team: Team, user: User): super().__init__( team, user, - tool_call_id, loop_node_class=FeatureFlagCreationNode, tools_node_class=FeatureFlagCreationToolsNode, toolkit_class=FeatureFlagToolkit, @@ -501,7 +500,7 @@ The tool will automatically: async def _create_flag_from_instructions(self, instructions: str) -> FeatureFlagCreationSchema: """Use TaxonomyAgent graph to generate structured flag configuration.""" - graph = FeatureFlagGeneratorGraph(team=self._team, user=self._user, tool_call_id=self._tool_call_id) + graph = FeatureFlagGeneratorGraph(team=self._team, user=self._user) graph_context = { "change": f"Create a feature flag based on these instructions: {instructions}", diff --git a/products/product_analytics/backend/max_tools.py b/products/product_analytics/backend/max_tools.py deleted file mode 100644 index 6af7ccdb0c..0000000000 --- a/products/product_analytics/backend/max_tools.py +++ /dev/null @@ -1,137 +0,0 @@ -from uuid import uuid4 - -from pydantic import BaseModel, Field - -from posthog.schema import AssistantMessage, AssistantToolCallMessage, VisualizationMessage - -from ee.hogai.tool import MaxTool, ToolMessagesArtifact -from ee.hogai.utils.types import AssistantState - -QUERY_KIND_DESCRIPTION_PROMPT = """ -## Trends -A trends insight visualizes events over time using time series. They're useful for finding patterns in historical data. - -The trends insights have the following features: -- The insight can show multiple trends in one request. -- Custom formulas can calculate derived metrics, like `A/B*100` to calculate a ratio. -- Filter and break down data using multiple properties. -- Compare with the previous period and sample data. -- Apply various aggregation types, like sum, average, etc., and chart types. -- And more. - -Examples of use cases include: -- How the product's most important metrics change over time. -- Long-term patterns, or cycles in product's usage. -- The usage of different features side-by-side. -- How the properties of events vary using aggregation (sum, average, etc). -- Users can also visualize the same data points in a variety of ways. - -## Funnel -A funnel insight visualizes a sequence of events that users go through in a product. They use percentages as the primary aggregation type. Funnels use two or more series, so the conversation history should mention at least two events. - -The funnel insights have the following features: -- Various visualization types (steps, time-to-convert, historical trends). -- Filter data and apply exclusion steps. -- Break down data using a single property. -- Specify conversion windows, details of conversion calculation, attribution settings. -- Sample data. -- And more. - -Examples of use cases include: -- Conversion rates. -- Drop off steps. -- Steps with the highest friction and time to convert. -- If product changes are improving their funnel over time. -- Average/median time to convert. -- Conversion trends over time. - -## Retention -A retention insight visualizes how many users return to the product after performing some action. They're useful for understanding user engagement and retention. - -The retention insights have the following features: filter data, sample data, and more. - -Examples of use cases include: -- How many users come back and perform an action after their first visit. -- How many users come back to perform action X after performing action Y. -- How often users return to use a specific feature. - -## SQL -The 'sql' insight type allows you to write arbitrary SQL queries to retrieve data. - -The SQL insights have the following features: -- Filter data using arbitrary SQL. -- All ClickHouse SQL features. -- You can nest subqueries as needed. -""".strip() - - -class EditCurrentInsightArgs(BaseModel): - """ - Edits the insight visualization the user is currently working on, by creating a query or iterating on a previous query. - """ - - query_description: str = Field( - description="The new query to edit the current insight. Must include all details from the current insight plus any change on top of them. Include any relevant information from the current conversation, as the tool does not have access to the conversation." - ) - query_kind: str = Field(description=QUERY_KIND_DESCRIPTION_PROMPT) - - -class EditCurrentInsightTool(MaxTool): - name: str = "edit_current_insight" - description: str = ( - "Update the insight the user is currently working on, based on the current insight's JSON schema." - ) - context_prompt_template: str = """The user is currently editing an insight (aka query). Here is that insight's current definition, which can be edited using the `edit_current_insight` tool: - -```json -{current_query} -``` - -IMPORTANT: DO NOT REMOVE ANY FIELDS FROM THE CURRENT INSIGHT DEFINITION. DO NOT CHANGE ANY OTHER FIELDS THAN THE ONES THE USER ASKED FOR. KEEP THE REST AS IS. -""".strip() - - args_schema: type[BaseModel] = EditCurrentInsightArgs - - async def _arun_impl(self, query_kind: str, query_description: str) -> tuple[str, ToolMessagesArtifact]: - from ee.hogai.graph.graph import InsightsAssistantGraph # avoid circular import - - if "current_query" not in self.context: - raise ValueError("Context `current_query` is required for the `create_and_query_insight` tool") - - graph = InsightsAssistantGraph(self._team, self._user, tool_call_id=self._tool_call_id).compile_full_graph() - state = self._state - last_message = state.messages[-1] - if not isinstance(last_message, AssistantMessage): - raise ValueError("Last message is not an AssistantMessage") - if last_message.tool_calls is None or len(last_message.tool_calls) == 0: - raise ValueError("Last message has no tool calls") - - state.root_tool_insight_plan = query_description - root_tool_call_id = last_message.tool_calls[0].id - - # We need to set a new root tool call id to sub-nest the graph within the contextual tool call - # and avoid duplicating messages in the stream - state.root_tool_call_id = str(uuid4()) - - state_dict = await graph.ainvoke(state, config=self._config) - state = AssistantState.model_validate(state_dict) - - result = state.messages[-1] - viz_messages = [message for message in state.messages if isinstance(message, VisualizationMessage)] - viz_message = viz_messages[-1] if viz_messages else None - if not viz_message: - raise ValueError("Visualization was not generated") - if not isinstance(result, AssistantToolCallMessage): - raise ValueError("Last message is not an AssistantToolCallMessage") - - return "", ToolMessagesArtifact( - messages=[ - viz_message, - AssistantToolCallMessage( - content=result.content, - ui_payload={self.get_name(): viz_message.answer.model_dump(exclude_none=True)}, - id=str(uuid4()), - tool_call_id=root_tool_call_id, - ), - ] - ) diff --git a/products/replay/backend/max_tools.py b/products/replay/backend/max_tools.py index ea88a5004e..656c22e0ab 100644 --- a/products/replay/backend/max_tools.py +++ b/products/replay/backend/max_tools.py @@ -90,11 +90,10 @@ class SessionReplayFilterOptionsGraph( ): """Graph for generating filtering options for session replay.""" - def __init__(self, team: Team, user: User, tool_call_id: str): + def __init__(self, team: Team, user: User): super().__init__( team, user, - tool_call_id=tool_call_id, loop_node_class=SessionReplayFilterNode, tools_node_class=SessionReplayFilterOptionsToolsNode, toolkit_class=SessionReplayFilterOptionsToolkit, @@ -131,7 +130,7 @@ class SearchSessionRecordingsTool(MaxTool): Reusable method to call graph to avoid code/prompt duplication and enable different processing of the results, based on the place the tool is used. """ - graph = SessionReplayFilterOptionsGraph(team=self._team, user=self._user, tool_call_id=self._tool_call_id) + graph = SessionReplayFilterOptionsGraph(team=self._team, user=self._user) pretty_filters = json.dumps(self.context.get("current_filters", {}), indent=2) user_prompt = USER_FILTER_OPTIONS_PROMPT.format(change=change, current_filters=pretty_filters) graph_context = { diff --git a/products/revenue_analytics/backend/max_tools.py b/products/revenue_analytics/backend/max_tools.py index d34d2323a7..afc5d922b7 100644 --- a/products/revenue_analytics/backend/max_tools.py +++ b/products/revenue_analytics/backend/max_tools.py @@ -153,11 +153,10 @@ class RevenueAnalyticsFilterOptionsGraph( ): """Graph for generating filtering options for revenue analytics.""" - def __init__(self, team: Team, user: User, tool_call_id: str): + def __init__(self, team: Team, user: User): super().__init__( team, user, - tool_call_id, loop_node_class=RevenueAnalyticsFilterNode, tools_node_class=RevenueAnalyticsFilterOptionsToolsNode, toolkit_class=RevenueAnalyticsFilterOptionsToolkit, @@ -192,7 +191,7 @@ class FilterRevenueAnalyticsTool(MaxTool): Reusable method to call graph to avoid code/prompt duplication and enable different processing of the results, based on the place the tool is used. """ - graph = RevenueAnalyticsFilterOptionsGraph(team=self._team, user=self._user, tool_call_id=self._tool_call_id) + graph = RevenueAnalyticsFilterOptionsGraph(team=self._team, user=self._user) pretty_filters = json.dumps(self.context.get("current_filters", {}), indent=2) user_prompt = USER_FILTER_OPTIONS_PROMPT.format(change=change, current_filters=pretty_filters) graph_context = { diff --git a/products/surveys/backend/max_tools.py b/products/surveys/backend/max_tools.py index 547074fc43..2ddbb20c76 100644 --- a/products/surveys/backend/max_tools.py +++ b/products/surveys/backend/max_tools.py @@ -52,7 +52,7 @@ class CreateSurveyTool(MaxTool): Create a survey from natural language instructions. """ - graph = FeatureFlagLookupGraph(team=self._team, user=self._user, tool_call_id=self._tool_call_id) + graph = FeatureFlagLookupGraph(team=self._team, user=self._user) graph_context = { "change": f"Create a survey based on these instructions: {instructions}", @@ -286,11 +286,10 @@ class SurveyLookupToolsNode(TaxonomyAgentToolsNode[TaxonomyAgentState, TaxonomyA class FeatureFlagLookupGraph(TaxonomyAgent[TaxonomyAgentState, TaxonomyAgentState[SurveyCreationSchema]]): """Graph for feature flag lookup operations.""" - def __init__(self, team: Team, user: User, tool_call_id: str): + def __init__(self, team: Team, user: User): super().__init__( team, user, - tool_call_id, loop_node_class=SurveyLoopNode, tools_node_class=SurveyLookupToolsNode, toolkit_class=SurveyToolkit, diff --git a/products/surveys/backend/test_max_tools.py b/products/surveys/backend/test_max_tools.py index 7380676fa1..e097918e44 100644 --- a/products/surveys/backend/test_max_tools.py +++ b/products/surveys/backend/test_max_tools.py @@ -45,7 +45,7 @@ class TestSurveyCreatorTool(BaseTest): def _setup_tool(self): """Helper to create a SurveyCreatorTool instance with mocked dependencies""" - tool = CreateSurveyTool(team=self.team, user=self.user, config=self._config, tool_call_id="test-tool-call-id") + tool = CreateSurveyTool(team=self.team, user=self.user, config=self._config) return tool def test_get_team_survey_config(self): @@ -468,7 +468,6 @@ class TestSurveyAnalysisTool(BaseTest): tool = SurveyAnalysisTool( team=self.team, user=self.user, - tool_call_id="test-tool-call-id", config={ **self._config, "configurable": {

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 P>TZchTu%|!c=rDQggnCa diff --git a/frontend/__snapshots__/scenes-app-posthog-ai--max-instance-with-contextual-tools--dark.png b/frontend/__snapshots__/scenes-app-posthog-ai--max-instance-with-contextual-tools--dark.png index 6fc02e772471fdf0d05ba2e326f1f4370bd57cd6..be639a9d446d59e86c1ba01f032899c519c1bb75 100644 GIT binary patch delta 29518 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 Tg!iM7NM}!-mwh91_3nQFzOa~A delta 29122 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 z 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