diff --git a/ee/hogai/trends/prompts.py b/ee/hogai/trends/prompts.py index 2543b1efc26e0..a4620158434a3 100644 --- a/ee/hogai/trends/prompts.py +++ b/ee/hogai/trends/prompts.py @@ -1,5 +1,5 @@ react_system_prompt = """ -You're a product analyst agent. Your task is to define trends series and their events, actions, and property filters and property filter values from the user's data in order to correctly answer on the user's question. Answer the following question as best you can. +You're a product analyst agent. Your task is to define trends series: events, property filters, and values of property filters from the user's data in order to correctly answer on the user's question. You have access to the following tools: {{tools}} @@ -40,17 +40,9 @@ ## General Information -Trends insights enable users to plot data from people, events, and properties however they want. They're useful for finding patterns in data, as well as monitoring users' product to ensure everything is running smoothly. For example, using trends, users can analyze: -- How product's most important metrics change over time. -- Long-term patterns, or cycles in product's usage. -- How a specific change affects 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. +Trends insights enable users to plot data from people, events, and properties however they want. They're useful for finding patterns in data, as well as monitoring users' product to ensure everything is running smoothly. Users can use multiple independent series in a single query to see trends. They can also use a formula to calculate a metric. Each series has its own set of property filters, so you must define them for each series. -Users can use multiple independent series in a single query to see trends. They can also use a formula to calculate a metric. Each series has its own set of property filters, so you must define them for each series. - -## Events and Actions +## Events You’ll be given a list of events in addition to the user’s question. Events are sorted by their popularity where the most popular events are at the top of the list. Prioritize popular events. You must always specify events to use. @@ -94,7 +86,7 @@ If the math aggregation is more complex or not listed above, use custom formulas to perform mathematical operations like calculating percentages or metrics. If you use a formula, you must use the following syntax: `A/B`, where `A` and `B` are the names of the series. You can combine math aggregations and formulas. When using a formula, you must: -- Identify and specify **all** events or actions needed to solve the formula. +- Identify and specify **all** events needed to solve the formula. - Carefully review the list of available events to find appropriate events for each part of the formula. - Ensure that you find events corresponding to both the numerator and denominator in ratio calculations. @@ -103,7 +95,7 @@ ## Property Filters -**Look for property filters** that the user wants to apply. These can include filtering by person's geography, event's browser, session duration, or any custom properties. Properties can be one of four data types: strings, numbers, dates, and booleans. +**Look for property filters** that the user wants to apply. Understand the user's intent and identify the minimum set of properties needed to answer the question. Do not use property filters excessively. Property filters can include filtering by person's geography, event's browser, session duration, or any custom properties. They can be one of four data types: String, Numeric, Boolean, and DateTime. When using a property filter, you must: - **Prioritize properties that are directly related to the context or objective of the user's query.** Avoid using properties for identification like IDs because neither the user nor you can retrieve the data. Instead, prioritize filtering based on general properties like `paidCustomer` or `icp_score`. You don't need to find properties for a time frame. @@ -149,7 +141,7 @@ ## Breakdown Series by Properties -Optionally, you can breakdown all series by multiple properties. Users can use breakdowns to split up trends insights by the values of a specific property, such as by `$current_url`, `$geoip_country`, `email`, or company's name like `company name`. +Optionally, if you understand that the user wants to split the data by a property, you can break down all series by multiple properties. Users can use breakdowns to split up trends insights by the values of a specific property, such as by `$current_url`, `$geoip_country`, `email`, or company's name like `company name`. Always use the minimum set of breakdowns needed to answer the question. When using breakdowns, you must: - **Identify the property group** and name for each breakdown. @@ -171,7 +163,8 @@ """ react_user_prompt = """ -Question: What events, actions, properties and/or property values should I use to answer this question: "{{question}}"? +Answer the following question as best you can. +Question: What events, properties and/or property values should I use to answer this question "{{question}}"? """ react_follow_up_prompt = """ @@ -202,20 +195,12 @@ """ trends_system_prompt = """ -You're a recognized head of product growth with the skills of a top-tier data engineer. Your task is to implement queries of trends insights for customers using a JSON schema. You will be given a plan describing series and breakdowns. Answer the user's questions as best you can. +Act as an expert product manager. Your task is to generate a JSON schema of trends insights. You will be given a generation plan describing series, filters, and breakdowns. Use the plan and following instructions to create a correct query answering the user's question. Below is the additional context. -Trends insights enable users to plot data from people, events, and properties however they want. They're useful for finding patterns in your data, as well as monitoring users' product to ensure everything is running smoothly. For example, using trends, users can analyze: -- How product's most important metrics change over time. -- Long-term patterns, or cycles in product's usage. -- How a specific change affects 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. - Follow this instruction to create a query: -* Build series according to the plan. The plan includes event or action names, math types, property filters, and breakdowns. +* Build series according to the plan. The plan includes event, math types, property filters, and breakdowns. Properties can be of multiple types: String, Numeric, Bool, and DateTime. A property can be an array of those types and only has a single type. * Check operators of property filters for individual and all series. Make sure the operators correspond to the user's request. You need to use the "contains" operator for strings if the user didn't ask for a very specific value or letter case matters. * Determine a visualization type that will answer the user's question in the best way. * Determine if the user wants to name the series or use the default names. @@ -239,38 +224,61 @@ You can determine if a feature flag is enabled by checking if it's set to true or 1 in the `$feature/...` property. For example, if you want to check if the multiple-breakdowns feature is enabled, you need to check if `$feature/multiple-breakdowns` is true or 1. -Learn on these examples: -Q: How many users do I have? -A: {"dateRange":{"date_from":"all"},"interval":"month","kind":"TrendsQuery","series":[{"event":"user signed up","kind":"EventsNode","math":"total"}],"trendsFilter":{"display":"BoldNumber"}} -Q: Show a bar chart of the organic search traffic for the last month grouped by week. -A: {"dateRange":{"date_from":"-30d","date_to":null,"explicitDate":false},"interval":"week","kind":"TrendsQuery","series":[{"event":"$pageview","kind":"EventsNode","math":"dau","properties":[{"key":"$referring_domain","operator":"icontains","type":"event","value":"google"},{"key":"utm_source","operator":"is_not_set","type":"event","value":"is_not_set"}]}],"trendsFilter":{"display":"ActionsBar"}} -Q: insight created unique users & first-time users for the last 12m) -A: {"dateRange":{"date_from":"-12m","date_to":""},"filterTestAccounts":true,"interval":"month","kind":"TrendsQuery","series":[{"event":"insight created","kind":"EventsNode","math":"dau","custom_name":"insight created"},{"event":"insight created","kind":"EventsNode","math":"first_time_for_user","custom_name":"insight created"}],"trendsFilter":{"display":"ActionsLineGraph"}} -Q: What are the top 10 referring domains for the last month? -A: {"breakdownFilter":{"breakdown_type":"event","breakdowns":[{"group_type_index":null,"histogram_bin_count":null,"normalize_url":null,"property":"$referring_domain","type":"event"}]},"dateRange":{"date_from":"-30d"},"interval":"day","kind":"TrendsQuery","series":[{"event":"$pageview","kind":"EventsNode","math":"total","custom_name":"$pageview"}]} -Q: What is the DAU to MAU ratio of users from the US and Australia that viewed a page in the last 7 days? Compare it to the previous period. -A: {"compareFilter":{"compare":true,"compare_to":null},"dateRange":{"date_from":"-7d"},"interval":"day","kind":"TrendsQuery","properties":{"type":"AND","values":[{"type":"AND","values":[{"key":"$geoip_country_name","operator":"exact","type":"event","value":["United States","Australia"]}]}]},"series":[{"event":"$pageview","kind":"EventsNode","math":"dau","custom_name":"$pageview"},{"event":"$pageview","kind":"EventsNode","math":"monthly_active","custom_name":"$pageview"}],"trendsFilter":{"aggregationAxisFormat":"percentage_scaled","display":"ActionsLineGraph","formula":"A/B"}} -Q: I want to understand how old are dashboard results when viewed from the beginning of this year grouped by a month. Display the results for percentiles of 99, 95, 90, average, and median by the property "refreshAge". -A: {"dateRange":{"date_from":"yStart","date_to":null,"explicitDate":false},"filterTestAccounts":true,"interval":"month","kind":"TrendsQuery","series":[{"event":"viewed dashboard","kind":"EventsNode","math":"p99","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"p95","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"p90","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"avg","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"median","math_property":"refreshAge","custom_name":"viewed dashboard"}],"trendsFilter":{"aggregationAxisFormat":"duration","display":"ActionsLineGraph"}} -Q: organizations joined in the last 30 days by day from the google search -A: {"dateRange":{"date_from":"-30d"},"filterTestAccounts":false,"interval":"day","kind":"TrendsQuery","properties":{"type":"AND","values":[{"type":"OR","values":[{"key":"$initial_utm_source","operator":"exact","type":"person","value":["google"]}]}]},"series":[{"event":"user signed up","kind":"EventsNode","math":"unique_group","math_group_type_index":0,"name":"user signed up","properties":[{"key":"is_organization_first_user","operator":"exact","type":"person","value":["true"]}]}],"trendsFilter":{"display":"ActionsLineGraph"}} -Q: trends for the last two weeks of the onboarding completed event by unique projects with a session duration more than 5 minutes and the insight analyzed event by unique projects with a breakdown by event's Country Name. exclude the US. -A: {"kind":"TrendsQuery","series":[{"kind":"EventsNode","event":"onboarding completed","name":"onboarding completed","properties":[{"key":"$session_duration","value":300,"operator":"gt","type":"session"}],"math":"unique_group","math_group_type_index":2},{"kind":"EventsNode","event":"insight analyzed","name":"insight analyzed","math":"unique_group","math_group_type_index":2}],"trendsFilter":{"display":"ActionsBar","showValuesOnSeries":true,"showPercentStackView":false,"showLegend":false},"breakdownFilter":{"breakdowns":[{"property":"$geoip_country_name","type":"event"}],"breakdown_limit":5},"properties":{"type":"AND","values":[{"type":"AND","values":[{"key":"$geoip_country_code","value":["US"],"operator":"is_not","type":"event"}]}]},"dateRange":{"date_from":"-14d","date_to":null},"interval":"day"} +## Schema Examples + +### How many users do I have? + +``` +{"dateRange":{"date_from":"all"},"interval":"month","kind":"TrendsQuery","series":[{"event":"user signed up","kind":"EventsNode","math":"total"}],"trendsFilter":{"display":"BoldNumber"}} +``` + +### Show a bar chart of the organic search traffic for the last month grouped by week. + +``` +{"dateRange":{"date_from":"-30d","date_to":null,"explicitDate":false},"interval":"week","kind":"TrendsQuery","series":[{"event":"$pageview","kind":"EventsNode","math":"dau","properties":[{"key":"$referring_domain","operator":"icontains","type":"event","value":"google"},{"key":"utm_source","operator":"is_not_set","type":"event","value":"is_not_set"}]}],"trendsFilter":{"display":"ActionsBar"}} +``` + +### insight created unique users & first-time users for the last 12m) + +``` +{"dateRange":{"date_from":"-12m","date_to":""},"filterTestAccounts":true,"interval":"month","kind":"TrendsQuery","series":[{"event":"insight created","kind":"EventsNode","math":"dau","custom_name":"insight created"},{"event":"insight created","kind":"EventsNode","math":"first_time_for_user","custom_name":"insight created"}],"trendsFilter":{"display":"ActionsLineGraph"}} +``` + +### What are the top 10 referring domains for the last month? + +``` +{"breakdownFilter":{"breakdown_type":"event","breakdowns":[{"group_type_index":null,"histogram_bin_count":null,"normalize_url":null,"property":"$referring_domain","type":"event"}]},"dateRange":{"date_from":"-30d"},"interval":"day","kind":"TrendsQuery","series":[{"event":"$pageview","kind":"EventsNode","math":"total","custom_name":"$pageview"}]} +``` + +### What is the DAU to MAU ratio of users from the US and Australia that viewed a page in the last 7 days? Compare it to the previous period. + +``` +{"compareFilter":{"compare":true,"compare_to":null},"dateRange":{"date_from":"-7d"},"interval":"day","kind":"TrendsQuery","properties":{"type":"AND","values":[{"type":"AND","values":[{"key":"$geoip_country_name","operator":"exact","type":"event","value":["United States","Australia"]}]}]},"series":[{"event":"$pageview","kind":"EventsNode","math":"dau","custom_name":"$pageview"},{"event":"$pageview","kind":"EventsNode","math":"monthly_active","custom_name":"$pageview"}],"trendsFilter":{"aggregationAxisFormat":"percentage_scaled","display":"ActionsLineGraph","formula":"A/B"}} +``` + +### I want to understand how old are dashboard results when viewed from the beginning of this year grouped by a month. Display the results for percentiles of 99, 95, 90, average, and median by the property "refreshAge". + +``` +{"dateRange":{"date_from":"yStart","date_to":null,"explicitDate":false},"filterTestAccounts":true,"interval":"month","kind":"TrendsQuery","series":[{"event":"viewed dashboard","kind":"EventsNode","math":"p99","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"p95","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"p90","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"avg","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"median","math_property":"refreshAge","custom_name":"viewed dashboard"}],"trendsFilter":{"aggregationAxisFormat":"duration","display":"ActionsLineGraph"}} +``` + +### organizations joined in the last 30 days by day from the google search + +``` +{"dateRange":{"date_from":"-30d"},"filterTestAccounts":false,"interval":"day","kind":"TrendsQuery","properties":{"type":"AND","values":[{"type":"OR","values":[{"key":"$initial_utm_source","operator":"exact","type":"person","value":["google"]}]}]},"series":[{"event":"user signed up","kind":"EventsNode","math":"unique_group","math_group_type_index":0,"name":"user signed up","properties":[{"key":"is_organization_first_user","operator":"exact","type":"person","value":["true"]}]}],"trendsFilter":{"display":"ActionsLineGraph"}} +``` + +### trends for the last two weeks of the onboarding completed event by unique projects with a session duration more than 5 minutes and the insight analyzed event by unique projects with a breakdown by event's Country Name. exclude the US. + +``` +{"kind":"TrendsQuery","series":[{"kind":"EventsNode","event":"onboarding completed","name":"onboarding completed","properties":[{"key":"$session_duration","value":300,"operator":"gt","type":"session"}],"math":"unique_group","math_group_type_index":2},{"kind":"EventsNode","event":"insight analyzed","name":"insight analyzed","math":"unique_group","math_group_type_index":2}],"trendsFilter":{"display":"ActionsBar","showValuesOnSeries":true,"showPercentStackView":false,"showLegend":false},"breakdownFilter":{"breakdowns":[{"property":"$geoip_country_name","type":"event"}],"breakdown_limit":5},"properties":{"type":"AND","values":[{"type":"AND","values":[{"key":"$geoip_country_code","value":["US"],"operator":"is_not","type":"event"}]}]},"dateRange":{"date_from":"-14d","date_to":null},"interval":"day"} +``` Obey these rules: - if the date range is not specified, use the best judgment to select a reasonable date range. If it is a question that can be answered with a single number, you may need to use the longest possible date range. - Filter internal users by default if the user doesn't specify. - Only use events and properties defined by the user. You can't create new events or property definitions. -For your reference, there is a description of the data model. - -The "events" table has the following columns: -* timestamp (DateTime) - date and time of the event. Events are sorted by timestamp in ascending order. -* uuid (UUID) - unique identifier of the event. -* person_id (UUID) - unique identifier of the person who performed the event. -* event (String) - the name of the event. -* properties (Map) - additional properties of the event. Properties can be of multiple types: String, Int, Decimal, Float, and Bool. A property can be an array of those types. A property always has only ONE type. If the property starts with a $, it is a system-defined property. If the property doesn't start with a $, it is a user-defined property. There is a list of system-defined properties: $browser, $browser_version, and $os. User-defined properties can have any name. - Remember, your efforts will be rewarded with a $100 tip if you manage to implement a perfect query that follows the user's instructions and return the desired result. Do not hallucinate. """ diff --git a/ee/hogai/trends/test/test_toolkit.py b/ee/hogai/trends/test/test_toolkit.py index 12cd086b033c5..b44b5f822baf9 100644 --- a/ee/hogai/trends/test/test_toolkit.py +++ b/ee/hogai/trends/test/test_toolkit.py @@ -92,6 +92,13 @@ def test_retrieve_entity_properties(self): toolkit.retrieve_entity_properties("session"), ) + def test_retrieve_entity_properties_returns_descriptive_feedback_without_properties(self): + toolkit = TrendsAgentToolkit(self.team) + self.assertEqual( + toolkit.retrieve_entity_properties("person"), + "Properties do not exist in the taxonomy for the entity person.", + ) + def test_retrieve_entity_property_values(self): toolkit = TrendsAgentToolkit(self.team) self.assertEqual( @@ -173,6 +180,13 @@ def test_group_names(self): toolkit = TrendsAgentToolkit(self.team) self.assertEqual(toolkit._entity_names, ["person", "session", "proj", "org"]) + def test_retrieve_event_properties_returns_descriptive_feedback_without_properties(self): + toolkit = TrendsAgentToolkit(self.team) + self.assertEqual( + toolkit.retrieve_event_properties("pageview"), + "Properties do not exist in the taxonomy for the event pageview.", + ) + def test_empty_events(self): toolkit = TrendsAgentToolkit(self.team) self.assertEqual( diff --git a/ee/hogai/trends/toolkit.py b/ee/hogai/trends/toolkit.py index a2f438756f3d1..614724cb43ab6 100644 --- a/ee/hogai/trends/toolkit.py +++ b/ee/hogai/trends/toolkit.py @@ -210,7 +210,7 @@ def tools(self) -> list[ToolkitTool]: ``` Args: - final_response: List all events, actions, and properties that you want to use to answer the question. + final_response: List all events and properties that you want to use to answer the question. """, }, ] @@ -285,6 +285,9 @@ def retrieve_entity_properties(self, entity: str) -> str: ).values_list("name", "property_type") props = list(qs) + if not props: + return f"Properties do not exist in the taxonomy for the entity {entity}." + return self._generate_properties_xml(props) def retrieve_event_properties(self, event_name: str) -> str: @@ -305,15 +308,17 @@ def retrieve_event_properties(self, event_name: str) -> str: team=self._team, type=PropertyDefinition.Type.EVENT, name__in=[item.property for item in response.results] ) property_to_type = {property_definition.name: property_definition.property_type for property_definition in qs} + props = [ + (item.property, property_to_type.get(item.property)) + for item in response.results + # Exclude properties that exist in the taxonomy, but don't have a type. + if item.property in property_to_type + ] - return self._generate_properties_xml( - [ - (item.property, property_to_type.get(item.property)) - for item in response.results - # Exclude properties that exist in the taxonomy, but don't have a type. - if item.property in property_to_type - ] - ) + if not props: + return f"Properties do not exist in the taxonomy for the event {event_name}." + + return self._generate_properties_xml(props) def _format_property_values( self, sample_values: list, sample_count: Optional[int] = 0, format_as_string: bool = False @@ -475,6 +480,7 @@ def _flatten_schema(self): "PersonPropertyFilter", "SessionPropertyFilter", "FeaturePropertyFilter", + "GroupPropertyFilter", ) # Clean up the property filters diff --git a/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown-edit--light.png b/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown-edit--light.png index 78ea79ea3f745..74e8409c16b8b 100644 Binary files a/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown-edit--light.png and b/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown-edit--light.png differ 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 29fe5a51e80b4..98c143d93d5b7 100644 Binary files a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--dark.png and b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--light.png b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--light.png index 71f9dac33c3cd..20db67811b7c3 100644 Binary files a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--light.png and b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-docs--light.png differ diff --git a/frontend/src/queries/schema.json b/frontend/src/queries/schema.json index e8baa13682fd7..8eeb35fa92177 100644 --- a/frontend/src/queries/schema.json +++ b/frontend/src/queries/schema.json @@ -1,62 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { - "AIActionsNode": { - "additionalProperties": false, - "properties": { - "custom_name": { - "type": "string" - }, - "event": { - "description": "The event or `null` for all events.", - "type": ["string", "null"] - }, - "fixedProperties": { - "items": { - "$ref": "#/definitions/AIPropertyFilter" - }, - "type": "array" - }, - "kind": { - "const": "EventsNode", - "type": "string" - }, - "math": { - "$ref": "#/definitions/MathType" - }, - "math_group_type_index": { - "enum": [0, 1, 2, 3, 4], - "type": "number" - }, - "math_property": { - "type": "string" - }, - "math_property_type": { - "type": "string" - }, - "name": { - "type": "string" - }, - "orderBy": { - "description": "Columns to order by", - "items": { - "type": "string" - }, - "type": "array" - }, - "properties": { - "items": { - "$ref": "#/definitions/AIPropertyFilter" - }, - "type": "array" - }, - "response": { - "type": "object" - } - }, - "required": ["kind"], - "type": "object" - }, "AIEventsNode": { "additionalProperties": false, "properties": { @@ -5536,14 +5480,7 @@ "series": { "description": "Events and actions to include", "items": { - "anyOf": [ - { - "$ref": "#/definitions/AIEventsNode" - }, - { - "$ref": "#/definitions/AIActionsNode" - } - ] + "$ref": "#/definitions/AIEventsNode" }, "type": "array" }, diff --git a/frontend/src/queries/schema.ts b/frontend/src/queries/schema.ts index a437aa9cea660..8a7d08b52932f 100644 --- a/frontend/src/queries/schema.ts +++ b/frontend/src/queries/schema.ts @@ -916,12 +916,6 @@ export interface AIEventsNode fixedProperties?: AIPropertyFilter[] } -export interface AIActionsNode - extends Omit { - properties?: AIPropertyFilter[] - fixedProperties?: AIPropertyFilter[] -} - export interface ExperimentalAITrendsQuery { kind: NodeKind.TrendsQuery /** @@ -931,7 +925,7 @@ export interface ExperimentalAITrendsQuery { */ interval?: IntervalType /** Events and actions to include */ - series: (AIEventsNode | AIActionsNode)[] + series: AIEventsNode[] /** Properties specific to the trends insight */ trendsFilter?: TrendsFilter /** Breakdown of the events and actions */ diff --git a/posthog/schema.py b/posthog/schema.py index de42df84b396e..a5468a7a4bac8 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -4906,53 +4906,6 @@ class WebOverviewQuery(BaseModel): useSessionsTable: Optional[bool] = None -class AIActionsNode(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - custom_name: Optional[str] = None - event: Optional[str] = Field(default=None, description="The event or `null` for all events.") - fixedProperties: Optional[ - list[ - Union[ - EventPropertyFilter, - PersonPropertyFilter, - SessionPropertyFilter, - GroupPropertyFilter, - FeaturePropertyFilter, - ] - ] - ] = None - kind: Literal["EventsNode"] = "EventsNode" - math: Optional[ - Union[ - BaseMathType, - FunnelMathType, - PropertyMathType, - CountPerActorMathType, - Literal["unique_group"], - Literal["hogql"], - ] - ] = None - math_group_type_index: Optional[MathGroupTypeIndex] = None - math_property: Optional[str] = None - math_property_type: Optional[str] = None - name: Optional[str] = None - orderBy: Optional[list[str]] = Field(default=None, description="Columns to order by") - properties: Optional[ - list[ - Union[ - EventPropertyFilter, - PersonPropertyFilter, - SessionPropertyFilter, - GroupPropertyFilter, - FeaturePropertyFilter, - ] - ] - ] = None - response: Optional[dict[str, Any]] = None - - class AIEventsNode(BaseModel): model_config = ConfigDict( extra="forbid", @@ -5129,7 +5082,7 @@ class ExperimentalAITrendsQuery(BaseModel): ] ] = Field(default=[], description="Property filters for all series") samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") - series: list[Union[AIEventsNode, AIActionsNode]] = Field(..., description="Events and actions to include") + series: list[AIEventsNode] = Field(..., description="Events and actions to include") trendsFilter: Optional[TrendsFilter] = Field(default=None, description="Properties specific to the trends insight")