From c33f0e8a542eac6e391bd048c0625bf05850fad4 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Mon, 20 Jan 2025 18:12:38 +0100 Subject: [PATCH 01/11] feat(max): Allow typing while Max is thinking (#27679) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- frontend/src/scenes/max/QuestionInput.tsx | 14 ++------------ frontend/src/scenes/max/maxLogic.ts | 19 +++++++++++++++---- posthog/geoip.py | 4 ++-- posthog/helpers/tests/test_geoip.py | 12 +++++++++--- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/frontend/src/scenes/max/QuestionInput.tsx b/frontend/src/scenes/max/QuestionInput.tsx index 8ed6eaa4821b63..244ba1b8b1adff 100644 --- a/frontend/src/scenes/max/QuestionInput.tsx +++ b/frontend/src/scenes/max/QuestionInput.tsx @@ -4,12 +4,10 @@ import clsx from 'clsx' import { useActions, useValues } from 'kea' import { useEffect, useRef } from 'react' -import { maxGlobalLogic } from './maxGlobalLogic' import { maxLogic } from './maxLogic' export function QuestionInput(): JSX.Element { - const { dataProcessingAccepted } = useValues(maxGlobalLogic) - const { question, threadGrouped, inputDisabled, threadLoading } = useValues(maxLogic) + const { question, threadGrouped, threadLoading, inputDisabled, submissionDisabledReason } = useValues(maxLogic) const { askMax, setQuestion } = useActions(maxLogic) const textAreaRef = useRef(null) @@ -50,15 +48,7 @@ export function QuestionInput(): JSX.Element { type={isFloating && !question ? 'secondary' : 'primary'} onClick={() => askMax(question)} tooltip="Let's go!" - disabledReason={ - !dataProcessingAccepted - ? 'Please accept OpenAI processing data' - : !question - ? 'I need some input first' - : threadLoading - ? 'Thinking…' - : undefined - } + disabledReason={submissionDisabledReason} size="small" icon={} /> diff --git a/frontend/src/scenes/max/maxLogic.ts b/frontend/src/scenes/max/maxLogic.ts index ffeb4ba2f9717b..d8b6873f1cce6f 100644 --- a/frontend/src/scenes/max/maxLogic.ts +++ b/frontend/src/scenes/max/maxLogic.ts @@ -21,6 +21,7 @@ import { import { NodeKind, RefreshType, SuggestedQuestionsQuery } from '~/queries/schema/schema-general' import { Conversation } from '~/types' +import { maxGlobalLogic } from './maxGlobalLogic' import type { maxLogicType } from './maxLogicType' export interface MaxLogicProps { @@ -44,7 +45,7 @@ export const maxLogic = kea([ props({} as MaxLogicProps), key(({ conversationId }) => conversationId || 'new-conversation'), connect({ - values: [projectLogic, ['currentProject']], + values: [projectLogic, ['currentProject'], maxGlobalLogic, ['dataProcessingAccepted']], }), actions({ askMax: (prompt: string) => ({ prompt }), @@ -326,9 +327,19 @@ export const maxLogic = kea([ return false }, ], - inputDisabled: [ - (s) => [s.threadLoading, s.formPending], - (threadLoading, formPending) => threadLoading || formPending, + inputDisabled: [(s) => [s.formPending], (formPending) => formPending], + submissionDisabledReason: [ + (s) => [s.formPending, s.dataProcessingAccepted, s.question, s.threadLoading], + (formPending, dataProcessingAccepted, question, threadLoading): string | undefined => + !dataProcessingAccepted + ? 'Please accept OpenAI processing data' + : formPending + ? 'Please choose one of the options above' + : !question + ? 'I need some input first' + : threadLoading + ? 'Thinking…' + : undefined, ], }), afterMount(({ actions, values }) => { diff --git a/posthog/geoip.py b/posthog/geoip.py index 1038e297ba8fa8..6c8911775eb1a8 100644 --- a/posthog/geoip.py +++ b/posthog/geoip.py @@ -42,8 +42,8 @@ def get_geoip_properties(ip_address: Optional[str]) -> dict[str, str]: $geoip_postal_code $geoip_time_zone """ - if not ip_address or not geoip or ip_address == "127.0.0.1": - # "127.0.0.1" would throw "The address 127.0.0.1 is not in the database." below + if not ip_address or not geoip or ip_address == "127.0.0.1" or ip_address.startswith("192.168."): + # Local addresses would otherwise throw "The address 127.0.0.1 is not in the database." below return {} try: diff --git a/posthog/helpers/tests/test_geoip.py b/posthog/helpers/tests/test_geoip.py index b41e0f66f9ce51..c2e1f4d09db4a9 100644 --- a/posthog/helpers/tests/test_geoip.py +++ b/posthog/helpers/tests/test_geoip.py @@ -10,7 +10,8 @@ australia_ip = "13.106.122.3" uk_ip = "31.28.64.3" us_ip_v6 = "2600:6c52:7a00:11c:1b6:b7b0:ea19:6365" -local_ip = "127.0.0.1" +localhost_ip = "127.0.0.1" +local_network_ip = "192.168.97.2" mexico_ip = "187.188.10.252" australia_ip_2 = "13.106.122.3" @@ -46,8 +47,13 @@ def test_geoip_with_invalid_database_file_returns_successfully(self): class TestGeoIPError(TestCase): - def test_geoip_on_local_ip_returns_successfully(self): - properties = get_geoip_properties(local_ip) + def test_geoip_on_localhost_ip_returns_successfully(self): + properties = get_geoip_properties(localhost_ip) + + self.assertEqual(properties, {}) + + def test_geoip_on_local_network_ip_returns_successfully(self): + properties = get_geoip_properties(local_network_ip) self.assertEqual(properties, {}) From 8ef951296b25541af491d8d0a92572772fa47d50 Mon Sep 17 00:00:00 2001 From: Peter Hicks Date: Mon, 20 Jan 2025 13:17:32 -0800 Subject: [PATCH 02/11] fix(view-name-help): Client side validation for view names. (#27706) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- ...uccess--second-recording-in-list--dark.png | Bin 118501 -> 119199 bytes .../editor/multitabEditorLogic.tsx | 8 +++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png b/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png index 4d5c533689f81c2f3f543857d28626df7d450702..d7f54c8d0cdf14de34aea37df51562704a0866d7 100644 GIT binary patch literal 119199 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 z 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 Ug+JMg`geK?GOE&Lk|rPi53x`+1^@s6 literal 118501 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

b6=;qLFslN6a)R5EsE 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[ LemonDialog.openForm({ title: 'Save as view', initialValues: { viewName: '' }, + description: `View names can only contain letters, numbers, '_', or '$'. Spaces are not allowed.`, content: ( ), errors: { - viewName: (name) => (!name ? 'You must enter a name' : undefined), + viewName: (name) => + !name + ? 'You must enter a name' + : !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) + ? 'Name must be valid' + : undefined, }, onSubmit: async ({ viewName }) => { await asyncActions.saveAsViewSubmit(viewName) From af67abaa0feb78f124990879cabdbae7f8ef2150 Mon Sep 17 00:00:00 2001 From: Robbie Date: Mon, 20 Jan 2025 21:32:23 +0000 Subject: [PATCH 03/11] feat(web-analytics): Add migration for revenue tracking config (#27701) --- .../test_clickhouse_funnel_person.ambr | 4 +- .../api/test/__snapshots__/test_action.ambr | 3 + .../test/__snapshots__/test_annotation.ambr | 3 + .../api/test/__snapshots__/test_decide.ambr | 64 +++++++++++++++++ .../api/test/__snapshots__/test_element.ambr | 1 + .../test/__snapshots__/test_feature_flag.ambr | 2 + .../api/test/__snapshots__/test_insight.ambr | 11 +++ .../test_organization_feature_flag.ambr | 18 +++++ .../test/__snapshots__/test_preflight.ambr | 1 + .../api/test/__snapshots__/test_survey.ambr | 16 +++++ .../__snapshots__/test_dashboard.ambr | 69 +++++++++++++++++++ .../__snapshots__/test_notebook.ambr | 4 ++ ...549_add_revenue_tracking_config_to_team.py | 17 +++++ posthog/migrations/max_migration.txt | 2 +- .../test/__snapshots__/test_filter.ambr | 5 ++ posthog/models/team/team.py | 1 + .../test_session_recordings.ambr | 35 ++++++++++ .../test_process_scheduled_changes.ambr | 11 +++ .../test/__snapshots__/test_feature_flag.ambr | 18 +++++ 19 files changed, 281 insertions(+), 4 deletions(-) create mode 100644 posthog/migrations/0549_add_revenue_tracking_config_to_team.py diff --git a/ee/clickhouse/views/test/funnel/__snapshots__/test_clickhouse_funnel_person.ambr b/ee/clickhouse/views/test/funnel/__snapshots__/test_clickhouse_funnel_person.ambr index f561791090a1d4..7272f10b35d606 100644 --- a/ee/clickhouse/views/test/funnel/__snapshots__/test_clickhouse_funnel_person.ambr +++ b/ee/clickhouse/views/test/funnel/__snapshots__/test_clickhouse_funnel_person.ambr @@ -56,7 +56,6 @@ e."$group_0" as aggregation_target, if(notEmpty(pdi.distinct_id), pdi.person_id, e.person_id) as person_id, person.person_props as person_props, - person.pmat_email as pmat_email, if(event = 'step one', 1, 0) as step_0, if(step_0 = 1, timestamp, null) as latest_0, if(event = 'step two', 1, 0) as step_1, @@ -80,7 +79,6 @@ HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id INNER JOIN (SELECT id, - argMax(pmat_email, version) as pmat_email, argMax(properties, version) as person_props FROM person WHERE team_id = 99999 @@ -97,7 +95,7 @@ AND event IN ['step one', 'step three', 'step two'] AND toTimeZone(timestamp, 'UTC') >= toDateTime('2021-05-01 00:00:00', 'UTC') AND toTimeZone(timestamp, 'UTC') <= toDateTime('2021-05-10 23:59:59', 'UTC') - AND (("pmat_email" ILIKE '%g0%' + AND ((replaceRegexpAll(JSONExtractRaw(person_props, 'email'), '^"|"$', '') ILIKE '%g0%' OR replaceRegexpAll(JSONExtractRaw(person_props, 'name'), '^"|"$', '') ILIKE '%g0%' OR replaceRegexpAll(JSONExtractRaw(e.properties, 'distinct_id'), '^"|"$', '') ILIKE '%g0%' OR replaceRegexpAll(JSONExtractRaw(group_properties_0, 'name'), '^"|"$', '') ILIKE '%g0%' diff --git a/posthog/api/test/__snapshots__/test_action.ambr b/posthog/api/test/__snapshots__/test_action.ambr index 1c30638dd3dba4..17ce6c0ffbf1a4 100644 --- a/posthog/api/test/__snapshots__/test_action.ambr +++ b/posthog/api/test/__snapshots__/test_action.ambr @@ -86,6 +86,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -395,6 +396,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -913,6 +915,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/__snapshots__/test_annotation.ambr b/posthog/api/test/__snapshots__/test_annotation.ambr index 3030d76b5ec624..ea0087116ed299 100644 --- a/posthog/api/test/__snapshots__/test_annotation.ambr +++ b/posthog/api/test/__snapshots__/test_annotation.ambr @@ -86,6 +86,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -390,6 +391,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -840,6 +842,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/__snapshots__/test_decide.ambr b/posthog/api/test/__snapshots__/test_decide.ambr index 0969aae1933ccb..62aabb86e792b2 100644 --- a/posthog/api/test/__snapshots__/test_decide.ambr +++ b/posthog/api/test/__snapshots__/test_decide.ambr @@ -321,6 +321,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -396,6 +397,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -484,6 +486,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -704,6 +707,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -790,6 +794,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -881,6 +886,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1254,6 +1260,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1329,6 +1336,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1419,6 +1427,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1498,6 +1507,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1702,6 +1712,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1915,6 +1926,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2119,6 +2131,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2230,6 +2243,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2325,6 +2339,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2400,6 +2415,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2490,6 +2506,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2569,6 +2586,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2773,6 +2791,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2974,6 +2993,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3178,6 +3198,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3289,6 +3310,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3363,6 +3385,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3490,6 +3513,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3568,6 +3592,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3647,6 +3672,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3867,6 +3893,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4046,6 +4073,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4121,6 +4149,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4200,6 +4229,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4651,6 +4681,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4726,6 +4757,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4814,6 +4846,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5034,6 +5067,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5120,6 +5154,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5211,6 +5246,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5330,6 +5366,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5550,6 +5587,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5697,6 +5735,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5917,6 +5956,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6249,6 +6289,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6324,6 +6365,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6414,6 +6456,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6493,6 +6536,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6697,6 +6741,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6787,6 +6832,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7003,6 +7049,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7134,6 +7181,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7301,6 +7349,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7412,6 +7461,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7763,6 +7813,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7874,6 +7925,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7969,6 +8021,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8044,6 +8097,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8134,6 +8188,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8213,6 +8268,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8417,6 +8473,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8507,6 +8564,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8723,6 +8781,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8850,6 +8909,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9017,6 +9077,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9128,6 +9189,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9471,6 +9533,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9582,6 +9645,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/__snapshots__/test_element.ambr b/posthog/api/test/__snapshots__/test_element.ambr index 23e9116d5c2c4e..247d6485633b2e 100644 --- a/posthog/api/test/__snapshots__/test_element.ambr +++ b/posthog/api/test/__snapshots__/test_element.ambr @@ -86,6 +86,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/__snapshots__/test_feature_flag.ambr b/posthog/api/test/__snapshots__/test_feature_flag.ambr index 4862130f80d6a0..788ebf035efeb1 100644 --- a/posthog/api/test/__snapshots__/test_feature_flag.ambr +++ b/posthog/api/test/__snapshots__/test_feature_flag.ambr @@ -1365,6 +1365,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1536,6 +1537,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/__snapshots__/test_insight.ambr b/posthog/api/test/__snapshots__/test_insight.ambr index 8d45446fe20c29..befc1238f3dbd7 100644 --- a/posthog/api/test/__snapshots__/test_insight.ambr +++ b/posthog/api/test/__snapshots__/test_insight.ambr @@ -827,6 +827,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -894,6 +895,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -968,6 +970,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1042,6 +1045,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1186,6 +1190,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1445,6 +1450,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1733,6 +1739,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1884,6 +1891,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2012,6 +2020,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2189,6 +2198,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2291,6 +2301,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr b/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr index f8d58510517a20..e55922a925665b 100644 --- a/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr +++ b/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr @@ -135,6 +135,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -214,6 +215,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -418,6 +420,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -496,6 +499,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -627,6 +631,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -729,6 +734,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -803,6 +809,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -947,6 +954,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1045,6 +1053,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1147,6 +1156,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1221,6 +1231,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1365,6 +1376,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1462,6 +1474,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1567,6 +1580,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1771,6 +1785,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1849,6 +1864,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1999,6 +2015,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2804,6 +2821,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/__snapshots__/test_preflight.ambr b/posthog/api/test/__snapshots__/test_preflight.ambr index 3d795cb483a19f..97717524ef968d 100644 --- a/posthog/api/test/__snapshots__/test_preflight.ambr +++ b/posthog/api/test/__snapshots__/test_preflight.ambr @@ -86,6 +86,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/__snapshots__/test_survey.ambr b/posthog/api/test/__snapshots__/test_survey.ambr index d4dbcf04c207f9..1cfc5163a0fbef 100644 --- a/posthog/api/test/__snapshots__/test_survey.ambr +++ b/posthog/api/test/__snapshots__/test_survey.ambr @@ -89,6 +89,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -156,6 +157,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -235,6 +237,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -464,6 +467,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -565,6 +569,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -656,6 +661,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -885,6 +891,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -986,6 +993,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1065,6 +1073,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1139,6 +1148,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1368,6 +1378,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1458,6 +1469,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1537,6 +1549,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1775,6 +1788,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1886,6 +1900,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2208,6 +2223,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr b/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr index 3a3372182c5339..2d6cda02ccf853 100644 --- a/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr +++ b/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr @@ -86,6 +86,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -279,6 +280,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -630,6 +632,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -954,6 +957,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1399,6 +1403,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1473,6 +1478,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1606,6 +1612,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1673,6 +1680,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1747,6 +1755,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1821,6 +1830,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1965,6 +1975,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2091,6 +2102,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2310,6 +2322,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2767,6 +2780,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2869,6 +2883,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3004,6 +3019,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3071,6 +3087,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3169,6 +3186,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3295,6 +3313,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3502,6 +3521,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3706,6 +3726,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3808,6 +3829,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3949,6 +3971,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4097,6 +4120,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4171,6 +4195,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4245,6 +4270,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4389,6 +4415,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4515,6 +4542,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -4716,6 +4744,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5066,6 +5095,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5390,6 +5420,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5544,6 +5575,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -5987,6 +6019,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6114,6 +6147,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6303,6 +6337,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6578,6 +6613,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6680,6 +6716,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6782,6 +6819,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6888,6 +6926,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6962,6 +7001,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7106,6 +7146,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7180,6 +7221,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7254,6 +7296,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7409,6 +7452,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7535,6 +7579,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7754,6 +7799,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7958,6 +8004,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8060,6 +8107,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8174,6 +8222,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8248,6 +8297,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8322,6 +8372,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8466,6 +8517,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8592,6 +8644,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8799,6 +8852,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9010,6 +9064,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9112,6 +9167,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9214,6 +9270,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9288,6 +9345,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9362,6 +9420,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9587,6 +9646,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -9741,6 +9801,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -10058,6 +10119,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -10244,6 +10306,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -10311,6 +10374,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -10438,6 +10502,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -10627,6 +10692,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -10910,6 +10976,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -11037,6 +11104,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -11226,6 +11294,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr b/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr index f04ae7b79e148c..7e43ca96c15925 100644 --- a/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr +++ b/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr @@ -86,6 +86,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -243,6 +244,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -482,6 +484,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -886,6 +889,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/migrations/0549_add_revenue_tracking_config_to_team.py b/posthog/migrations/0549_add_revenue_tracking_config_to_team.py new file mode 100644 index 00000000000000..50255931c8aae5 --- /dev/null +++ b/posthog/migrations/0549_add_revenue_tracking_config_to_team.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.15 on 2025-01-15 21:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("posthog", "0548_migrate_early_access_features"), + ] + + operations = [ + migrations.AddField( + model_name="team", + name="revenue_tracking_config", + field=models.JSONField(blank=True, null=True), + ), + ] diff --git a/posthog/migrations/max_migration.txt b/posthog/migrations/max_migration.txt index 042765a585ca62..becfcae2442132 100644 --- a/posthog/migrations/max_migration.txt +++ b/posthog/migrations/max_migration.txt @@ -1 +1 @@ -0548_migrate_early_access_features +0549_add_revenue_tracking_config_to_team \ No newline at end of file diff --git a/posthog/models/filters/test/__snapshots__/test_filter.ambr b/posthog/models/filters/test/__snapshots__/test_filter.ambr index 54c29b6f1d174e..64e6e69cbd10e6 100644 --- a/posthog/models/filters/test/__snapshots__/test_filter.ambr +++ b/posthog/models/filters/test/__snapshots__/test_filter.ambr @@ -53,6 +53,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -127,6 +128,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -201,6 +203,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -275,6 +278,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -349,6 +353,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/models/team/team.py b/posthog/models/team/team.py index 48ecc81c07ddd8..76d75cf9f1a608 100644 --- a/posthog/models/team/team.py +++ b/posthog/models/team/team.py @@ -297,6 +297,7 @@ class Meta: cookieless_server_hash_mode = models.SmallIntegerField( default=CookielessServerHashMode.DISABLED, choices=CookielessServerHashMode.choices, null=True ) + revenue_tracking_config = models.JSONField(null=True, blank=True) primary_dashboard = models.ForeignKey( "posthog.Dashboard", diff --git a/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr b/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr index c7592a392ffd4a..8f1a76560faab3 100644 --- a/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr +++ b/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr @@ -53,6 +53,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -127,6 +128,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -201,6 +203,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -275,6 +278,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -349,6 +353,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -532,6 +537,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -633,6 +639,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -999,6 +1006,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1153,6 +1161,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1227,6 +1236,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1301,6 +1311,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1375,6 +1386,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1449,6 +1461,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1523,6 +1536,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1630,6 +1644,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1901,6 +1916,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2013,6 +2029,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2120,6 +2137,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2542,6 +2560,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2687,6 +2706,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3111,6 +3131,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3289,6 +3310,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3528,6 +3550,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3763,6 +3786,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -3908,6 +3932,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6129,6 +6154,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6320,6 +6346,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6745,6 +6772,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -6890,6 +6918,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7311,6 +7340,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7469,6 +7499,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -7887,6 +7918,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8032,6 +8064,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8525,6 +8558,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -8670,6 +8704,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr b/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr index 91ad671f85aafd..5883b794a5c98c 100644 --- a/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr +++ b/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr @@ -76,6 +76,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -200,6 +201,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -279,6 +281,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -483,6 +486,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -626,6 +630,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -779,6 +784,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -858,6 +864,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1025,6 +1032,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1136,6 +1144,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1267,6 +1276,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1623,6 +1633,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", diff --git a/posthog/test/__snapshots__/test_feature_flag.ambr b/posthog/test/__snapshots__/test_feature_flag.ambr index 3ebee0f6b7d724..70a55d29e8020a 100644 --- a/posthog/test/__snapshots__/test_feature_flag.ambr +++ b/posthog/test/__snapshots__/test_feature_flag.ambr @@ -177,6 +177,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -274,6 +275,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -353,6 +355,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -557,6 +560,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -658,6 +662,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -737,6 +742,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -804,6 +810,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1008,6 +1015,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1172,6 +1180,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1376,6 +1385,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1477,6 +1487,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1598,6 +1609,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1677,6 +1689,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -1881,6 +1894,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2198,6 +2212,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2369,6 +2384,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2448,6 +2464,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", @@ -2652,6 +2669,7 @@ "posthog_team"."recording_domains", "posthog_team"."human_friendly_comparison_periods", "posthog_team"."cookieless_server_hash_mode", + "posthog_team"."revenue_tracking_config", "posthog_team"."primary_dashboard_id", "posthog_team"."default_data_theme", "posthog_team"."extra_settings", From 4812eb8d55acfed579b0128128e56ffd67c18512 Mon Sep 17 00:00:00 2001 From: timgl Date: Mon, 20 Jan 2025 13:54:23 -0800 Subject: [PATCH 04/11] fix(cohorts): Fix all events action with cohorts (#27675) --- ee/clickhouse/models/test/test_cohort.py | 58 ++++++++++++++++++++++++ posthog/queries/foss_cohort_query.py | 7 ++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/ee/clickhouse/models/test/test_cohort.py b/ee/clickhouse/models/test/test_cohort.py index 1600584169a28e..6f55fd9f0e0de8 100644 --- a/ee/clickhouse/models/test/test_cohort.py +++ b/ee/clickhouse/models/test/test_cohort.py @@ -1447,3 +1447,61 @@ def test_calculate_people_ch_in_multiteam_project(self): self.assertCountEqual([r[0] for r in results_team1], [person2_team1.uuid]) self.assertCountEqual([r[0] for r in results_team2], [person1_team2.uuid]) + + def test_cohortpeople_action_all_events(self): + # Create an action that matches all events (no specific event defined) + action = Action.objects.create(team=self.team, name="all events", steps_json=[{"event": None}]) + + # Create two people + Person.objects.create( + team_id=self.team.pk, + distinct_ids=["1"], + properties={"$some_prop": "something", "$another_prop": "something"}, + ) + + Person.objects.create( + team_id=self.team.pk, + distinct_ids=["2"], + properties={"$some_prop": "something", "$another_prop": "something"}, + ) + + # Create different types of events for both people + _create_event( + event="$pageview", + team=self.team, + distinct_id="1", + properties={"attr": "some_val"}, + timestamp=datetime.now() - timedelta(hours=12), + ) + + _create_event( + event="$autocapture", + team=self.team, + distinct_id="2", + properties={"attr": "some_val"}, + timestamp=datetime.now() - timedelta(hours=12), + ) + + # Create a cohort based on the "all events" action + cohort = Cohort.objects.create( + team=self.team, groups=[{"action_id": action.pk, "days": 1}], name="cohort_all_events" + ) + cohort.calculate_people_ch(pending_version=0) + + # Both people should be in the cohort since they both performed some event + results = self._get_cohortpeople(cohort) + self.assertEqual(len(results), 2) + + # Create a person with no events + Person.objects.create( + team_id=self.team.pk, + distinct_ids=["3"], + properties={"$some_prop": "something", "$another_prop": "something"}, + ) + + # Recalculate cohort + cohort.calculate_people_ch(pending_version=1) + + # Should still only have 2 people since person 3 has no events + results = self._get_cohortpeople(cohort) + self.assertEqual(len(results), 2) diff --git a/posthog/queries/foss_cohort_query.py b/posthog/queries/foss_cohort_query.py index f11e53abb528de..47010cb20efe45 100644 --- a/posthog/queries/foss_cohort_query.py +++ b/posthog/queries/foss_cohort_query.py @@ -360,11 +360,16 @@ def _get_behavior_subquery(self) -> tuple[str, dict[str, Any], str]: ) date_condition, date_params = self._get_date_condition() + if len(self._events) > 0: + event_condition = f"AND event IN %({event_param_name})s" + else: + event_condition = "" + query = f""" SELECT {", ".join(_fields)} FROM events {self.EVENT_TABLE_ALIAS} {self._get_person_ids_query()} WHERE team_id = %(team_id)s - AND event IN %({event_param_name})s + {event_condition} {date_condition} {person_prop_query} GROUP BY person_id From 29d403497b8f0d25d9bb624b8afa56a4a764c01e Mon Sep 17 00:00:00 2001 From: Rafael Audibert <32079912+rafaeelaudibert@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:54:53 -0300 Subject: [PATCH 05/11] Small tweaks to Web Vitals (#27702) --- .../src/queries/nodes/WebVitals/WebVitals.tsx | 2 +- .../WebVitals/WebVitalsPathBreakdown.tsx | 24 +++----- .../nodes/WebVitals/WebVitalsProgressBar.tsx | 59 +++++++++++++------ .../queries/nodes/WebVitals/definitions.ts | 17 ++++++ ...ashboard.tsx => WebAnalyticsDashboard.tsx} | 37 ++++-------- .../WebAnalyticsLiveUserCount.tsx | 12 ++-- .../web-analytics/WebAnalyticsScene.tsx | 2 +- .../web-analytics/webAnalyticsLogic.tsx | 36 +++++------ 8 files changed, 106 insertions(+), 83 deletions(-) rename frontend/src/scenes/web-analytics/{WebDashboard.tsx => WebAnalyticsDashboard.tsx} (92%) diff --git a/frontend/src/queries/nodes/WebVitals/WebVitals.tsx b/frontend/src/queries/nodes/WebVitals/WebVitals.tsx index 6ff389a001fa75..e66c649cf05c83 100644 --- a/frontend/src/queries/nodes/WebVitals/WebVitals.tsx +++ b/frontend/src/queries/nodes/WebVitals/WebVitals.tsx @@ -89,7 +89,7 @@ export function WebVitals(props: { /> -

+
diff --git a/frontend/src/queries/nodes/WebVitals/WebVitalsPathBreakdown.tsx b/frontend/src/queries/nodes/WebVitals/WebVitalsPathBreakdown.tsx index d7f5e400220332..b2e3a493b77e38 100644 --- a/frontend/src/queries/nodes/WebVitals/WebVitalsPathBreakdown.tsx +++ b/frontend/src/queries/nodes/WebVitals/WebVitalsPathBreakdown.tsx @@ -13,7 +13,7 @@ import { import { QueryContext } from '~/queries/types' import { dataNodeLogic } from '../DataNode/dataNodeLogic' -import { getValueWithUnit, ICON_PER_BAND } from './definitions' +import { computePositionInBand, getValueWithUnit, ICON_PER_BAND } from './definitions' let uniqueNode = 0 export function WebVitalsPathBreakdown(props: { @@ -147,7 +147,7 @@ const Content = ({ ) : values?.length ? ( values?.map(({ path, value }) => { - const width = computeWidth(value, threshold) + const width = computePositionInBand(value, threshold) * 100 return (
- {path} - {value} + + {path} + + + {value >= 1 ? value.toFixed(0) : value.toFixed(2)} +
) }) @@ -174,15 +178,3 @@ const Content = ({
) } - -const computeWidth = (value: number, threshold: { good: number; poor: number }): string => { - if (value < threshold.good) { - return `${(value / threshold.good) * 100}%` - } - - if (value > threshold.poor) { - return `${((value - threshold.poor) / (threshold.good - threshold.poor)) * 100}%` - } - - return `${((value - threshold.good) / (threshold.poor - threshold.good)) * 100}%` -} diff --git a/frontend/src/queries/nodes/WebVitals/WebVitalsProgressBar.tsx b/frontend/src/queries/nodes/WebVitals/WebVitalsProgressBar.tsx index a6042759266d5c..7d82e8882b207f 100644 --- a/frontend/src/queries/nodes/WebVitals/WebVitalsProgressBar.tsx +++ b/frontend/src/queries/nodes/WebVitals/WebVitalsProgressBar.tsx @@ -1,7 +1,9 @@ import clsx from 'clsx' import { WebVitalsThreshold } from 'scenes/web-analytics/webAnalyticsLogic' -import { getMetricBand, getThresholdColor } from './definitions' +import { WebVitalsMetricBand } from '~/queries/schema' + +import { computePositionInBand, getMetricBand, getThresholdColor } from './definitions' interface WebVitalsProgressBarProps { value?: number @@ -9,9 +11,6 @@ interface WebVitalsProgressBarProps { } export function WebVitalsProgressBar({ value, threshold }: WebVitalsProgressBarProps): JSX.Element { - const indicatorPercentage = Math.min((value ?? 0 / threshold.end) * 100, 100) - - const thresholdColor = getThresholdColor(value, threshold) const band = getMetricBand(value, threshold) const goodWidth = (threshold.good / threshold.end) * 100 @@ -25,7 +24,9 @@ export function WebVitalsProgressBar({ value, threshold }: WebVitalsProgressBarP className={clsx('absolute h-full rounded-full', band === 'good' ? 'bg-success' : 'bg-muted')} // eslint-disable-next-line react/forbid-dom-props style={{ width: `${goodWidth}%` }} - /> + > + +
{/* Yellow segment up to "poor" threshold */}
+ > + +
{/* Red segment after "poor" threshold */}
- - {/* Indicator line */} - {value != null && ( -
- )} + > + +
) } + +type IndicatorLineProps = { + value: number | undefined + threshold: WebVitalsThreshold + band: WebVitalsMetricBand | 'none' +} + +const IndicatorLine = ({ value, threshold, band }: IndicatorLineProps): JSX.Element | null => { + if (!value) { + return null + } + + const thisBand = getMetricBand(value, threshold) + if (thisBand !== band) { + return null + } + + const positionInBand = computePositionInBand(value, threshold) + const color = getThresholdColor(value, threshold) + + return ( +
+ ) +} diff --git a/frontend/src/queries/nodes/WebVitals/definitions.ts b/frontend/src/queries/nodes/WebVitals/definitions.ts index 5f989d94864091..6af898cc45f2e0 100644 --- a/frontend/src/queries/nodes/WebVitals/definitions.ts +++ b/frontend/src/queries/nodes/WebVitals/definitions.ts @@ -125,3 +125,20 @@ export const getThresholdColor = (value: number | undefined, threshold: WebVital return 'danger' } + +// Returns a value between 0 and 1 that represents the position of the value inside that band +// +// Useful to display the indicator line in the progress bar +// or the width of the segment in the path breakdown +export const computePositionInBand = (value: number, threshold: WebVitalsThreshold): number => { + if (value <= threshold.good) { + return value / threshold.good + } + + // Values can be much higher than what we consider the end, so max out at 1 + if (value > threshold.poor) { + return Math.min((value - threshold.poor) / (threshold.end - threshold.poor), 1) + } + + return (value - threshold.good) / (threshold.poor - threshold.good) +} diff --git a/frontend/src/scenes/web-analytics/WebDashboard.tsx b/frontend/src/scenes/web-analytics/WebAnalyticsDashboard.tsx similarity index 92% rename from frontend/src/scenes/web-analytics/WebDashboard.tsx rename to frontend/src/scenes/web-analytics/WebAnalyticsDashboard.tsx index 547a535d25ee84..465ebc02319232 100644 --- a/frontend/src/scenes/web-analytics/WebDashboard.tsx +++ b/frontend/src/scenes/web-analytics/WebAnalyticsDashboard.tsx @@ -6,10 +6,10 @@ import { CompareFilter } from 'lib/components/CompareFilter/CompareFilter' import { DateFilter } from 'lib/components/DateFilter/DateFilter' import { VersionCheckerBanner } from 'lib/components/VersionChecker/VersionCheckerBanner' import { FEATURE_FLAGS } from 'lib/constants' -import { useWindowSize } from 'lib/hooks/useWindowSize' import { IconOpenInNew } from 'lib/lemon-ui/icons' import { LemonButton } from 'lib/lemon-ui/LemonButton' import { LemonSegmentedSelect } from 'lib/lemon-ui/LemonSegmentedSelect/LemonSegmentedSelect' +import { LemonTabs } from 'lib/lemon-ui/LemonTabs' import { PostHogComDocsURL } from 'lib/lemon-ui/Link/Link' import { Popover } from 'lib/lemon-ui/Popover' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' @@ -94,6 +94,8 @@ const Filters = (): JSX.Element => { /> + +
) @@ -359,9 +361,6 @@ export const LearnMorePopover = ({ url, title, description }: LearnMorePopoverPr } export const WebAnalyticsDashboard = (): JSX.Element => { - const { isWindowLessThan } = useWindowSize() - const isMobile = isWindowLessThan('sm') - const { productTab } = useValues(webAnalyticsLogic) const { setProductTab } = useActions(webAnalyticsLogic) @@ -373,26 +372,16 @@ export const WebAnalyticsDashboard = (): JSX.Element => {
-
-
- -
- - {featureFlags[FEATURE_FLAGS.WEB_VITALS] && ( - - )} -
+ {featureFlags[FEATURE_FLAGS.WEB_VITALS] && ( + + activeKey={productTab} + onChange={setProductTab} + tabs={[ + { key: ProductTab.ANALYTICS, label: 'Web analytics' }, + { key: ProductTab.WEB_VITALS, label: 'Web vitals' }, + ]} + /> + )} diff --git a/frontend/src/scenes/web-analytics/WebAnalyticsLiveUserCount.tsx b/frontend/src/scenes/web-analytics/WebAnalyticsLiveUserCount.tsx index a74305754377d1..18ce5abaed98b6 100644 --- a/frontend/src/scenes/web-analytics/WebAnalyticsLiveUserCount.tsx +++ b/frontend/src/scenes/web-analytics/WebAnalyticsLiveUserCount.tsx @@ -27,10 +27,12 @@ export const WebAnalyticsLiveUserCount = (): JSX.Element | null => { const tooltip = `${usersOnlineString}${inTeamString}${updatedAgoString}` return ( - - - {humanFriendlyLargeNumber(liveUserCount)} currently online - - +
+ + + {humanFriendlyLargeNumber(liveUserCount)} currently online + + +
) } diff --git a/frontend/src/scenes/web-analytics/WebAnalyticsScene.tsx b/frontend/src/scenes/web-analytics/WebAnalyticsScene.tsx index bd9a57a0a65228..f880a977e68db8 100644 --- a/frontend/src/scenes/web-analytics/WebAnalyticsScene.tsx +++ b/frontend/src/scenes/web-analytics/WebAnalyticsScene.tsx @@ -1,8 +1,8 @@ import { PageHeader } from 'lib/components/PageHeader' import { SceneExport } from 'scenes/sceneTypes' +import { WebAnalyticsDashboard } from 'scenes/web-analytics/WebAnalyticsDashboard' import { webAnalyticsLogic } from 'scenes/web-analytics/webAnalyticsLogic' import { WebAnalyticsMenu } from 'scenes/web-analytics/WebAnalyticsMenu' -import { WebAnalyticsDashboard } from 'scenes/web-analytics/WebDashboard' export function WebAnalyticsScene(): JSX.Element { return ( diff --git a/frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx b/frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx index 4cf7b4522cd1a9..4f7318a620b1d9 100644 --- a/frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx +++ b/frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx @@ -157,9 +157,9 @@ export interface ErrorTrackingTile extends BaseTile { query: QuerySchema } -export type WebDashboardTile = QueryTile | TabsTile | ReplayTile | ErrorTrackingTile +export type WebAnalyticsTile = QueryTile | TabsTile | ReplayTile | ErrorTrackingTile -export interface WebDashboardModalQuery { +export interface WebAnalyticsModalQuery { tileId: TileId tabId?: string title?: string @@ -225,12 +225,13 @@ export interface WebAnalyticsStatusCheck { isSendingPageLeavesScroll: boolean } +// We're setting end to 20% above the poor threshold to have much more space in the UI for the good and poor segments export type WebVitalsThreshold = { good: number; poor: number; end: number } export const WEB_VITALS_THRESHOLDS: Record = { - INP: { good: 200, poor: 500, end: 550 }, - LCP: { good: 2500, poor: 4000, end: 4400 }, - CLS: { good: 0.1, poor: 0.25, end: 0.3 }, - FCP: { good: 1800, poor: 3000, end: 3300 }, + INP: { good: 200, poor: 500, end: 500 * 1.2 }, + LCP: { good: 2500, poor: 4000, end: 4000 * 1.2 }, + CLS: { good: 0.1, poor: 0.25, end: 0.25 * 1.2 }, + FCP: { good: 1800, poor: 3000, end: 3000 * 1.2 }, } export const WEB_VITALS_COLORS = { @@ -416,7 +417,7 @@ export const webAnalyticsLogic = kea([ }, ], isPathCleaningEnabled: [ - null as boolean | null, + true as boolean, persistConfig, { setIsPathCleaningEnabled: (_, { isPathCleaningEnabled }) => isPathCleaningEnabled, @@ -626,7 +627,7 @@ export const webAnalyticsLogic = kea([ }, featureFlags, isGreaterThanMd - ): WebDashboardTile[] => { + ): WebAnalyticsTile[] => { const dateRange = { date_from: dateFrom, date_to: dateTo } const sampling = { enabled: false, forceSamplingRate: { numerator: 1, denominator: 10 } } @@ -793,7 +794,7 @@ export const webAnalyticsLogic = kea([ />
} - checked={!!isPathCleaningEnabled} + checked={isPathCleaningEnabled} onChange={(value) => actions.setIsPathCleaningEnabled(value)} className="h-full" /> @@ -856,7 +857,7 @@ export const webAnalyticsLogic = kea([ properties: webAnalyticsFilters, percentile: webVitalsPercentile, metric: webVitalsTab, - doPathCleaning: !!isPathCleaningEnabled, + doPathCleaning: isPathCleaningEnabled, thresholds: [ WEB_VITALS_THRESHOLDS[webVitalsTab].good, WEB_VITALS_THRESHOLDS[webVitalsTab].poor, @@ -876,7 +877,7 @@ export const webAnalyticsLogic = kea([ ] } - const allTiles: (WebDashboardTile | null)[] = [ + const allTiles: (WebAnalyticsTile | null)[] = [ { kind: 'query', tileId: TileId.OVERVIEW, @@ -982,7 +983,7 @@ export const webAnalyticsLogic = kea([ { includeScrollDepth: false, // TODO needs some perf work before it can be enabled includeBounceRate: true, - doPathCleaning: !!isPathCleaningEnabled, + doPathCleaning: isPathCleaningEnabled, }, { control: pathCleaningControl, @@ -1026,7 +1027,7 @@ export const webAnalyticsLogic = kea([ { includeBounceRate: true, includeScrollDepth: false, - doPathCleaning: !!isPathCleaningEnabled, + doPathCleaning: isPathCleaningEnabled, }, { control: pathCleaningControl, @@ -1060,7 +1061,7 @@ export const webAnalyticsLogic = kea([ { includeBounceRate: false, includeScrollDepth: false, - doPathCleaning: !!isPathCleaningEnabled, + doPathCleaning: isPathCleaningEnabled, }, { control: pathCleaningControl, @@ -1600,12 +1601,12 @@ export const webAnalyticsLogic = kea([ ], modal: [ (s) => [s.tiles, s._modalTileAndTab], - (tiles, modalTileAndTab): WebDashboardModalQuery | null => { + (tiles, modalTileAndTab): WebAnalyticsModalQuery | null => { if (!modalTileAndTab) { return null } const { tileId, tabId } = modalTileAndTab - const tile: WebDashboardTile | undefined = tiles.find((tile) => tile.tileId === tileId) + const tile: WebAnalyticsTile | undefined = tiles.find((tile) => tile.tileId === tileId) if (!tile) { return null } @@ -1812,7 +1813,7 @@ export const webAnalyticsLogic = kea([ return query } - const tile: WebDashboardTile | undefined = tiles.find((tile) => tile.tileId === tileId) + const tile: WebAnalyticsTile | undefined = tiles.find((tile) => tile.tileId === tileId) if (!tile) { return undefined } @@ -2021,6 +2022,7 @@ export const webAnalyticsLogic = kea([ setCompareFilter: stateToUrl, setProductTab: stateToUrl, setWebVitalsPercentile: stateToUrl, + setIsPathCleaningEnabled: stateToUrl, } }), From 95798a23ca2afb737a2298933443163c637d6ab6 Mon Sep 17 00:00:00 2001 From: timgl Date: Mon, 20 Jan 2025 14:05:21 -0800 Subject: [PATCH 06/11] fix(cohort): Fix creating static cohort from SQL (#27676) --- .../src/scenes/insights/InsightPageHeader.tsx | 91 +++++++++---------- .../src/scenes/insights/insightDataLogic.tsx | 14 ++- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/frontend/src/scenes/insights/InsightPageHeader.tsx b/frontend/src/scenes/insights/InsightPageHeader.tsx index f193c615a10102..bdcd2023c490db 100644 --- a/frontend/src/scenes/insights/InsightPageHeader.tsx +++ b/frontend/src/scenes/insights/InsightPageHeader.tsx @@ -242,9 +242,11 @@ export function InsightPageHeader({ insightLogicProps }: { insightLogicProps: In label="Debug panel" /> ) : null} - {hogQL && ( - <> - + + {(hogQL || showCohortButton) && } + {hogQL && + !isHogQLQuery(query) && + !(isDataVisualizationNode(query) && isHogQLQuery(query.source)) && ( { @@ -263,50 +265,47 @@ export function InsightPageHeader({ insightLogicProps }: { insightLogicProps: In > Edit SQL directly - {showCohortButton && ( - { - LemonDialog.openForm({ - title: 'Save as static cohort', - description: ( -
- Your query must export a person_id,{' '} - actor_id or id column, - which must match the id of the{' '} - persons table -
- ), - initialValues: { - name: '', - }, - content: ( - - - - ), - errors: { - name: (name) => - !name ? 'You must enter a name' : undefined, - }, - onSubmit: async ({ name }) => { - createStaticCohort(name, { - kind: NodeKind.HogQLQuery, - query: hogQL, - }) - }, + )} + {hogQL && showCohortButton && ( + { + LemonDialog.openForm({ + title: 'Save as static cohort', + description: ( +
+ Your query must export a person_id,{' '} + actor_id or id column, which must + match the id of the persons table +
+ ), + initialValues: { + name: '', + }, + content: ( + + + + ), + errors: { + name: (name) => (!name ? 'You must enter a name' : undefined), + }, + onSubmit: async ({ name }) => { + createStaticCohort(name, { + kind: NodeKind.HogQLQuery, + query: hogQL, }) - }} - fullWidth - > - Save as static cohort -
- )} - + }, + }) + }} + fullWidth + > + Save as static cohort +
)} {hasDashboardItemId && ( <> diff --git a/frontend/src/scenes/insights/insightDataLogic.tsx b/frontend/src/scenes/insights/insightDataLogic.tsx index ced59ae6c29141..25945a236be339 100644 --- a/frontend/src/scenes/insights/insightDataLogic.tsx +++ b/frontend/src/scenes/insights/insightDataLogic.tsx @@ -13,7 +13,7 @@ import { insightVizDataNodeKey } from '~/queries/nodes/InsightViz/InsightViz' import { getDefaultQuery, queryFromKind } from '~/queries/nodes/InsightViz/utils' import { queryExportContext } from '~/queries/query' import { DataVisualizationNode, InsightVizNode, Node, NodeKind } from '~/queries/schema/schema-general' -import { isDataTableNode, isDataVisualizationNode, isHogQuery, isInsightVizNode } from '~/queries/utils' +import { isDataTableNode, isDataVisualizationNode, isHogQLQuery, isHogQuery, isInsightVizNode } from '~/queries/utils' import { ExportContext, InsightLogicProps, InsightType } from '~/types' import { teamLogic } from '../teamLogic' @@ -171,8 +171,16 @@ export const insightDataLogic = kea([ ], hogQL: [ - (s) => [s.insightData], - (insightData): string | null => { + (s) => [s.insightData, s.query], + (insightData, query): string | null => { + // Try to get it from the query itself, so we don't have to wait for the response + if (isDataVisualizationNode(query) && isHogQLQuery(query.source)) { + return query.source.query + } + if (isHogQLQuery(query)) { + return query.query + } + // Otherwise, get it from the response if (insightData && 'hogql' in insightData && insightData.hogql !== '') { return insightData.hogql } From 67e03d834e1ad8523648f682c118eef884f79dae Mon Sep 17 00:00:00 2001 From: Robbie Date: Mon, 20 Jan 2025 22:25:08 +0000 Subject: [PATCH 07/11] fix(web-analytics): Fix opening session attribution explorer from web analytics dashboard (#27700) --- frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx b/frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx index 4f7318a620b1d9..38fe7c064d4f18 100644 --- a/frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx +++ b/frontend/src/scenes/web-analytics/webAnalyticsLogic.tsx @@ -86,6 +86,7 @@ export enum TileId { export enum ProductTab { ANALYTICS = 'analytics', WEB_VITALS = 'web-vitals', + SESSION_ATTRIBUTION_EXPLORER = 'session-attribution-explorer', } export type WebVitalsPercentile = PropertyMathType.P75 | PropertyMathType.P90 | PropertyMathType.P99 @@ -2047,6 +2048,10 @@ export const webAnalyticsLogic = kea([ percentile, }: Record ): void => { + if (![ProductTab.ANALYTICS, ProductTab.WEB_VITALS].includes(productTab)) { + return + } + const parsedFilters = isWebAnalyticsPropertyFilters(filters) ? filters : undefined if (parsedFilters && !objectsEqual(parsedFilters, values.webAnalyticsFilters)) { From 3c5c2b1999e0111d88f8ba9f05b500e8b1a3733a Mon Sep 17 00:00:00 2001 From: timgl Date: Mon, 20 Jan 2025 15:42:17 -0800 Subject: [PATCH 08/11] revert: perf(quereies): run queries over websockets (#27576) (#27655) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- frontend/src/queries/query.ts | 17 +--- frontend/src/queries/queryWebSocket.ts | 121 ------------------------- posthog/api/query_ws.py | 115 ----------------------- posthog/api/test/test_query_ws.py | 98 -------------------- posthog/api/websocket.py | 45 --------- posthog/asgi.py | 22 +---- posthog/settings/web.py | 2 - requirements.in | 4 +- requirements.txt | 27 +----- 9 files changed, 6 insertions(+), 445 deletions(-) delete mode 100644 frontend/src/queries/queryWebSocket.ts delete mode 100644 posthog/api/query_ws.py delete mode 100644 posthog/api/test/test_query_ws.py delete mode 100644 posthog/api/websocket.py diff --git a/frontend/src/queries/query.ts b/frontend/src/queries/query.ts index 823694d23b826f..d43de44d73bdb6 100644 --- a/frontend/src/queries/query.ts +++ b/frontend/src/queries/query.ts @@ -6,7 +6,6 @@ import posthog from 'posthog-js' import { OnlineExportContext, QueryExportContext } from '~/types' -import { QueryWebSocketManager } from './queryWebSocket' import { DashboardFilter, DataNode, @@ -80,8 +79,6 @@ export async function pollForResults( throw new Error(QUERY_TIMEOUT_ERROR_MESSAGE) } -let socket: null | QueryWebSocketManager = null - /** * Execute a query node and return the response, use async query if enabled */ @@ -104,19 +101,9 @@ async function executeQuery( !SYNC_ONLY_QUERY_KINDS.includes(queryNode.kind) && !!featureFlagLogic.findMounted()?.values.featureFlags?.[FEATURE_FLAGS.QUERY_ASYNC] - const refreshParam: RefreshType | undefined = - refresh && isAsyncQuery ? 'force_async' : isAsyncQuery ? 'async' : refresh - - if (posthog.isFeatureEnabled('query-websocket')) { - if (!socket) { - socket = new QueryWebSocketManager( - `${window.location.protocol == 'https:' ? 'wss' : 'ws'}://${window.location.host}/ws/query/` - ) - } - return socket.sendQuery(queryNode, methodOptions, refreshParam, queryId, filtersOverride, variablesOverride) - } - if (!pollOnly) { + const refreshParam: RefreshType | undefined = + refresh && isAsyncQuery ? 'force_async' : isAsyncQuery ? 'async' : refresh const response = await api.query( queryNode, methodOptions, diff --git a/frontend/src/queries/queryWebSocket.ts b/frontend/src/queries/queryWebSocket.ts deleted file mode 100644 index 6eab830876ded4..00000000000000 --- a/frontend/src/queries/queryWebSocket.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { ApiMethodOptions } from 'lib/api' - -import { DashboardFilter, DataNode, HogQLVariable, RefreshType } from './schema' - -export class QueryWebSocketManager { - private socket: WebSocket | null = null - private url: string - private pendingQueries = new Map< - string, - { payload: any; resolve: (value: any) => void; reject: (reason?: any) => void } - >() - private idleTimeout: NodeJS.Timeout | null = null - private idleTimeoutDuration = 20000 // 20 seconds of idle time before disconnecting - - constructor(url: string) { - this.url = url - } - - private connect(): void { - if ( - this.socket && - (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING) - ) { - return // Avoid redundant connections - } - - this.socket = new WebSocket(this.url) - - this.socket.onopen = () => { - this.resendPendingQueries() - } - - this.socket.onmessage = (event) => { - const response = JSON.parse(event.data) - const { client_query_id, data, error } = response - - if (this.pendingQueries.has(client_query_id)) { - const { resolve, reject } = this.pendingQueries.get(client_query_id)! - this.pendingQueries.delete(client_query_id) - if (error) { - reject(new Error(error)) - } else { - resolve(data) - } - this.startIdleTimeout() // Restart idle timeout after handling a message - } - } - - this.socket.onclose = () => { - if (this.pendingQueries.size > 0) { - this.connect() - } - } - } - - private disconnect(): void { - if (this.socket) { - this.socket.close() - this.socket = null - } - } - - private resendPendingQueries(): void { - for (const [_, { payload }] of this.pendingQueries) { - this.socket?.send(JSON.stringify(payload)) - } - } - - private startIdleTimeout(): void { - if (this.idleTimeout) { - clearTimeout(this.idleTimeout) - } - if (this.pendingQueries.size === 0) { - this.idleTimeout = setTimeout(() => this.disconnect(), this.idleTimeoutDuration) - } - } - - public sendQuery( - queryNode: N, - methodOptions?: ApiMethodOptions, - refreshParam?: RefreshType | undefined, - queryId?: string, - filtersOverride?: DashboardFilter | null, - variablesOverride?: Record | null - /** - * Whether to limit the function to just polling the provided query ID. - * This is important in shared contexts, where we cannot create arbitrary queries via POST – we can only GET. - */ - ): Promise> { - const client_query_id = queryId || Math.random().toString(36).substring(2) - - const payload = { - query: queryNode, - methodOptions: methodOptions, - refresh: refreshParam, - client_query_id: client_query_id, - filtersOverride: filtersOverride, - variablesOverride: variablesOverride, - } - - return new Promise((resolve, reject) => { - this.pendingQueries.set(client_query_id, { payload, resolve, reject }) - - if (!this.socket || this.socket.readyState === WebSocket.CLOSED) { - this.connect() - } - - if (this.socket?.readyState === WebSocket.OPEN) { - this.socket.send(JSON.stringify(payload)) - } - - // Add a timeout for the query - setTimeout(() => { - if (this.pendingQueries.has(client_query_id)) { - this.pendingQueries.delete(client_query_id) - reject(new Error('Query timed out.')) - } - }, 600000) // 600 seconds timeout - }) - } -} diff --git a/posthog/api/query_ws.py b/posthog/api/query_ws.py deleted file mode 100644 index 66265ca2c0ff44..00000000000000 --- a/posthog/api/query_ws.py +++ /dev/null @@ -1,115 +0,0 @@ -from posthog.api.services.query import process_query_model -from posthog.hogql_queries.query_runner import ExecutionMode, execution_mode_from_refresh -from posthog.clickhouse.query_tagging import tag_queries -from pydantic import BaseModel -from posthog.errors import ExposedCHQueryError -from posthog.hogql.errors import ExposedHogQLError -from sentry_sdk import capture_exception -from asgiref.sync import sync_to_async - -from posthog.rate_limit import ClickHouseBurstRateThrottle, ClickHouseSustainedRateThrottle, HogQLQueryThrottle -from posthog.api.websocket import BaseWebsocketConsumer -import json -import uuid -from typing import Generic, TypeVar - -T = TypeVar("T") - - -class Response(BaseModel, Generic[T]): - status: int - result: T - client_query_id: str - - -def _query(user, query, execution_mode, query_id): - return process_query_model( - user.team, - query, - execution_mode=execution_mode, - query_id=query_id, - user=user, - ) - - -class QueryConsumer(BaseWebsocketConsumer): - def get_throttles(self, data): - if query := data.get("query"): - if isinstance(query, dict) and query.get("kind") == "HogQLQuery": - return [HogQLQueryThrottle()] - return [ClickHouseBurstRateThrottle(), ClickHouseSustainedRateThrottle()] - - async def connect(self): - # Accept the WebSocket connection - if not await self.check_authentication(): - return - await self.accept() - - async def disconnect(self, close_code): - # Handle WebSocket disconnection (if needed) - pass - - async def receive(self, text_data): - try: - data = json.loads(text_data) - if not await self.check_throttling(data): - return - - # Extract and process the query - client_query_id = data.get("client_query_id") or uuid.uuid4().hex - execution_mode = execution_mode_from_refresh(data.get("refresh")) - response_status = 200 - - # Add tagging if needed - # self._tag_client_query_id(client_query_id) - - # websockets we always want to "block" - if execution_mode in [ - ExecutionMode.RECENT_CACHE_CALCULATE_ASYNC_IF_STALE, - ExecutionMode.RECENT_CACHE_CALCULATE_ASYNC_IF_STALE_AND_BLOCKING_ON_MISS, - ExecutionMode.EXTENDED_CACHE_CALCULATE_ASYNC_IF_STALE, - ]: - execution_mode = ExecutionMode.RECENT_CACHE_CALCULATE_BLOCKING_IF_STALE - if execution_mode in [ExecutionMode.CALCULATE_ASYNC_ALWAYS]: - execution_mode = ExecutionMode.CALCULATE_BLOCKING_ALWAYS - - tag_queries(query=data["query"]) - - # Execute query asynchronously - result = await sync_to_async(_query)( - self.scope["user"], - data["query"], - execution_mode=execution_mode, - query_id=client_query_id, - ) - - # Send response back to the client - response: Response = Response(status=response_status, result=result, client_query_id=client_query_id) - await self.send(response.model_dump_json(by_alias=True)) - - except (ExposedHogQLError, ExposedCHQueryError) as e: - # Handle validation errors - await self.send( - json.dumps( - { - "status": 400, - "error": str(e), - "client_query_id": client_query_id, - "code": getattr(e, "code_name", None), - } - ) - ) - - except Exception as e: - # Handle unexpected errors - capture_exception(e) - await self.send( - json.dumps( - { - "status": 500, - "error": "Internal server error", - "client_query_id": client_query_id, - "exception": str(e), - } - ) - ) diff --git a/posthog/api/test/test_query_ws.py b/posthog/api/test/test_query_ws.py deleted file mode 100644 index 60f51779cac48d..00000000000000 --- a/posthog/api/test/test_query_ws.py +++ /dev/null @@ -1,98 +0,0 @@ -from unittest.mock import patch -from freezegun import freeze_time -from channels.testing import WebsocketCommunicator -from django.test import TransactionTestCase -from posthog.rate_limit import ClickHouseSustainedRateThrottle -from asgiref.sync import sync_to_async -from posthog.models.organization import Organization -from posthog.models.team import Team -from posthog.models.user import User -from posthog.models.project import Project -import random - - -from posthog.asgi import application - -from typing import Optional - -import functools - - -class AuthWebsocketCommunicator(WebsocketCommunicator): - def __init__(self, application, path, user, *args, **kwargs): - super().__init__(self._asgi_with_user(application, user), path, *args, **kwargs) - - @classmethod - def _asgi_with_user(cls, asgi_app, user): - """ - Update the scope of an ASGI app such that a particular user - is already assumed to have been authenticated. - """ - - async def app(scope, receive, send): - scope["user"] = user - return await asgi_app(scope, receive, send) - - functools.update_wrapper(app, asgi_app) - return app - - -class TestQueryConsumer(TransactionTestCase): - user: Optional[User] = None - - async def _create_user(self): - # self.team = self.create_team_with_organization(self.organization) - # self.user = self.create_user_with_organization(self.organization) - - if self.user: - return self.user - org = await Organization.objects.acreate(slug=f"org-{random.randint(1, 1000000)}") - project_id = await sync_to_async(Team.objects.increment_id_sequence)() - project = await Project.objects.acreate(id=project_id, organization=org) - await Team.objects.acreate(organization=org, project=project) - self.user = await User.objects.acreate(email=f"bla-{random.randint(1, 10000000)}@bla.com") - - await sync_to_async(org.members.add)(self.user) - return self.user - - @freeze_time("2025-01-01 12:00:00") - async def test_query_consumer_success(self): - # Test a successful query - communicator = AuthWebsocketCommunicator(application, "/ws/query/", await self._create_user()) - connected, _ = await communicator.connect() - self.assertTrue(connected) - - query = {"query": {"select": ["count()", "event"], "where": ["event == 'sign up'"]}} - await communicator.send_json_to(query) - - response = await communicator.receive_json_from() - self.assertEqual(response["status"], 200, response) - self.assertIn("result", response) - self.assertIn("client_query_id", response) - - await communicator.disconnect() - - @freeze_time("2025-01-01 12:00:00") - async def test_rate_limit_exceeded(self): - # Test rate limit exceeded scenario - with patch.object(ClickHouseSustainedRateThrottle, "allow_request", return_value=False): - communicator = AuthWebsocketCommunicator(application, "/ws/query/", await self._create_user()) - # Authenticate the user - connected, _ = await communicator.connect() - self.assertTrue(connected) - - query = {"query": {"select": ["count()", "event"]}} - await communicator.send_json_to(query) - - response = await communicator.receive_json_from() - self.assertEqual(response["status"], 429, response) - self.assertEqual(response["error"], "Rate limit exceeded: Request was throttled.") - - await communicator.disconnect() - - async def test_unauthenticated_access(self): - # Test unauthenticated access - communicator = WebsocketCommunicator(application, "/ws/query/") - connected, code = await communicator.connect() - self.assertFalse(connected) - self.assertEqual(code, 401) diff --git a/posthog/api/websocket.py b/posthog/api/websocket.py deleted file mode 100644 index 3fd6eb8933a769..00000000000000 --- a/posthog/api/websocket.py +++ /dev/null @@ -1,45 +0,0 @@ -from channels.generic.websocket import AsyncWebsocketConsumer -from rest_framework.exceptions import Throttled -from rest_framework.views import APIView -from rest_framework.request import Request -from django.contrib.auth.models import AnonymousUser -from asgiref.sync import sync_to_async - -from django.test import RequestFactory -from typing import cast -import json - - -class BaseWebsocketConsumer(AsyncWebsocketConsumer): - async def check_authentication(self): - """Check if the user is authenticated.""" - user = self.scope.get("user", AnonymousUser()) - - if not user.is_authenticated: - await self.close(code=401) - return False - return True - - async def check_throttling(self, data): - # Apply throttling - throttles = self.get_throttles(data) - view = APIView() # DRF expects a view instance - view.request = cast(Request, RequestFactory()) - view.request.user = self.scope["user"] # Attach the user object - - try: - for throttle in throttles: - if not await sync_to_async(throttle.allow_request)(view.request, view): - raise Throttled() - except Throttled as e: - await self.send( - json.dumps( - { - "status": 429, - "error": f"Rate limit exceeded: {str(e.detail)}", - } - ) - ) - return False - - return True diff --git a/posthog/asgi.py b/posthog/asgi.py index 39e68b77c20e42..3ac5d2ff51524b 100644 --- a/posthog/asgi.py +++ b/posthog/asgi.py @@ -1,19 +1,10 @@ import os from django.core.asgi import get_asgi_application +from django.http.response import HttpResponse os.environ.setdefault("DJANGO_SETTINGS_MODULE", "posthog.settings") os.environ.setdefault("SERVER_GATEWAY_INTERFACE", "ASGI") -# Initialize Django ASGI application early to ensure the AppRegistry is populated -# before importing any models -django_asgi_app = get_asgi_application() - -from django.http.response import HttpResponse # noqa -from channels.routing import ProtocolTypeRouter, URLRouter # noqa -from channels.auth import AuthMiddlewareStack # noqa -from posthog.api.query_ws import QueryConsumer # noqa -from django.urls import path # noqa - # Django doesn't support lifetime requests and raises an exception # when it receives them. This creates a lot of noise in sentry so @@ -27,13 +18,4 @@ async def inner(scope, receive, send): return inner -websocket_urlpatterns = [ - path("ws/query/", QueryConsumer.as_asgi()), -] - -application = ProtocolTypeRouter( - { - "http": lifetime_wrapper(django_asgi_app), - "websocket": AuthMiddlewareStack(URLRouter(websocket_urlpatterns)), - } -) +application = lifetime_wrapper(get_asgi_application()) diff --git a/posthog/settings/web.py b/posthog/settings/web.py index b0197655d06cbf..2e1462ce8afb2a 100644 --- a/posthog/settings/web.py +++ b/posthog/settings/web.py @@ -60,7 +60,6 @@ # Application definition INSTALLED_APPS = [ - "daphne", "whitenoise.runserver_nostatic", # makes sure that whitenoise handles static files in development "django.contrib.admin", "django.contrib.auth", @@ -88,7 +87,6 @@ "products.early_access_features", # TODO: add this automatically ] -ASGI_APPLICATION = "posthog.asgi.application" MIDDLEWARE = [ "posthog.middleware.PrometheusBeforeMiddlewareWithTeamIds", diff --git a/requirements.in b/requirements.in index 7cb42435cffd4f..779ddb47f0506f 100644 --- a/requirements.in +++ b/requirements.in @@ -120,6 +120,4 @@ lxml==4.9.4 # Do not change this version - it will break SAML grpcio~=1.63.2 # Version constrained so that `deepeval` can be installed in in dev tenacity~=8.4.2 # Version constrained so that `deepeval` can be installed in in dev markdown-it-py~=3.0.0 -tzlocal~=5.1 -channels==4.2.0 -daphne==4.1.2 +tzlocal~=5.1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 0674ab18994f99..bd5f3ee651e06a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -40,10 +40,7 @@ anyio==4.6.2.post1 # starlette # watchfiles asgiref==3.7.2 - # via - # channels - # daphne - # django + # via django asn1crypto==1.5.1 # via snowflake-connector-python astunparse==1.6.3 @@ -109,8 +106,6 @@ cffi==1.16.0 # cryptography # pynacl # snowflake-connector-python -channels==4.2.0 - # via -r requirements.in charset-normalizer==2.1.0 # via # requests @@ -147,18 +142,14 @@ coloredlogs==14.0 # via dagster conditional-cache==1.2 # via -r requirements.in -constantly==23.10.4 - # via twisted croniter==5.0.1 # via dagster cryptography==39.0.2 # via # -r requirements.in - # autobahn # paramiko # pyjwt # pyopenssl - # service-identity # snowflake-connector-python # social-auth-core # urllib3 @@ -183,8 +174,6 @@ dagster-postgres==0.25.8 # via -r requirements.in dagster-webserver==1.9.8 # via -r requirements.in -daphne==4.1.2 - # via -r requirements.in dataclasses-json==0.6.7 # via langchain-community decorator==5.1.1 @@ -202,7 +191,6 @@ dj-database-url==0.5.0 django==4.2.18 # via # -r requirements.in - # channels # django-axes # django-cors-headers # django-deprecate-fields @@ -378,23 +366,15 @@ humanfriendly==10.0 # via coloredlogs humanize==4.9.0 # via dlt -hyperlink==21.0.0 - # via - # autobahn - # twisted idna==3.10 # via # anyio # httpx - # hyperlink # requests # snowflake-connector-python # trio - # twisted # urllib3 # yarl -incremental==24.7.2 - # via twisted infi-clickhouse-orm @ git+https://github.com/PostHog/infi.clickhouse_orm@9578c79f29635ee2c1d01b7979e89adab8383de2 # via -r requirements.in inflection==0.5.1 @@ -910,10 +890,6 @@ trio==0.26.0 # trio-websocket trio-websocket==0.11.1 # via selenium -twisted==24.11.0 - # via daphne -txaio==23.1.1 - # via autobahn types-protobuf==4.22.0.0 # via temporalio types-setuptools==69.0.0.0 @@ -935,7 +911,6 @@ typing-extensions==4.12.2 # sqlalchemy # stripe # temporalio - # twisted # typing-inspect typing-inspect==0.9.0 # via dataclasses-json From df697b749d5205c301b1f439b26c911ee0e8376a Mon Sep 17 00:00:00 2001 From: Georgiy Tarasov Date: Tue, 21 Jan 2025 00:50:58 +0100 Subject: [PATCH 09/11] chore: bump posthoganalytics (#27703) --- requirements.in | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.in b/requirements.in index 779ddb47f0506f..185d49a7e5ab81 100644 --- a/requirements.in +++ b/requirements.in @@ -66,7 +66,7 @@ pandas==2.2.0 paramiko==3.4.0 Pillow==10.2.0 pdpyras==5.2.0 -posthoganalytics==3.8.3 +posthoganalytics~=3.8.4 psutil==6.0.0 psycopg2-binary==2.9.7 pymssql==2.3.1 diff --git a/requirements.txt b/requirements.txt index bd5f3ee651e06a..edba548419f9f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -559,7 +559,7 @@ pluggy==1.5.0 # via dlt ply==3.11 # via jsonpath-ng -posthoganalytics==3.8.3 +posthoganalytics==3.8.4 # via -r requirements.in prometheus-client==0.14.1 # via django-prometheus From 7c6d824f685e6c6cc4d67dbfd0702a903c676db0 Mon Sep 17 00:00:00 2001 From: Peter Kirkham Date: Mon, 20 Jan 2025 16:59:20 -0800 Subject: [PATCH 10/11] feat: ai cost data moved from custom app to inline ps (#27574) Co-authored-by: Ben White --- plugin-server/package.json | 1 + plugin-server/pnpm-lock.yaml | 7 + plugin-server/src/types.ts | 55 + .../src/utils/ai-cost-data/anthropic/index.ts | 479 ++++ .../utils/ai-cost-data/awsBedrock/index.ts | 18 + .../src/utils/ai-cost-data/azure/index.ts | 98 + .../src/utils/ai-cost-data/cohere/index.ts | 19 + .../src/utils/ai-cost-data/fireworks/index.ts | 204 ++ .../src/utils/ai-cost-data/google/index.ts | 80 + .../src/utils/ai-cost-data/groq/index.ts | 89 + .../src/utils/ai-cost-data/mappings.ts | 234 ++ .../src/utils/ai-cost-data/mistral/index.ts | 69 + .../ai-cost-data/openai/fine-tuned-models.ts | 39 + .../src/utils/ai-cost-data/openai/index.ts | 817 +++++++ .../utils/ai-cost-data/openrouter/index.ts | 2159 +++++++++++++++++ .../src/utils/ai-cost-data/qstash/index.ts | 29 + .../ai-cost-data/togetherai/chat/index.ts | 503 ++++ .../ai-cost-data/togetherai/chat/llama.ts | 210 ++ .../togetherai/completion/index.ts | 228 ++ .../togetherai/completion/llama.ts | 134 + .../event-pipeline/prepareEventStep.ts | 14 + .../event-pipeline/processAiEvent.ts | 103 + .../worker/ingestion/process-ai-event.test.ts | 149 ++ 23 files changed, 5738 insertions(+) create mode 100644 plugin-server/src/utils/ai-cost-data/anthropic/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/awsBedrock/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/azure/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/cohere/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/fireworks/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/google/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/groq/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/mappings.ts create mode 100644 plugin-server/src/utils/ai-cost-data/mistral/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/openai/fine-tuned-models.ts create mode 100644 plugin-server/src/utils/ai-cost-data/openai/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/openrouter/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/qstash/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/togetherai/chat/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/togetherai/chat/llama.ts create mode 100644 plugin-server/src/utils/ai-cost-data/togetherai/completion/index.ts create mode 100644 plugin-server/src/utils/ai-cost-data/togetherai/completion/llama.ts create mode 100644 plugin-server/src/worker/ingestion/event-pipeline/processAiEvent.ts create mode 100644 plugin-server/tests/worker/ingestion/process-ai-event.test.ts diff --git a/plugin-server/package.json b/plugin-server/package.json index c324b9a8e94c51..4c12e76998b018 100644 --- a/plugin-server/package.json +++ b/plugin-server/package.json @@ -75,6 +75,7 @@ "graphile-worker": "0.13.0", "ioredis": "^4.27.6", "ipaddr.js": "^2.1.0", + "js-big-decimal": "^2.2.0", "kafkajs": "^2.2.0", "kafkajs-snappy": "^1.1.0", "lru-cache": "^6.0.0", diff --git a/plugin-server/pnpm-lock.yaml b/plugin-server/pnpm-lock.yaml index d7e991770d31f0..c2c42164689ad1 100644 --- a/plugin-server/pnpm-lock.yaml +++ b/plugin-server/pnpm-lock.yaml @@ -109,6 +109,9 @@ dependencies: ipaddr.js: specifier: ^2.1.0 version: 2.1.0 + js-big-decimal: + specifier: ^2.2.0 + version: 2.2.0 kafkajs: specifier: ^2.2.0 version: 2.2.4 @@ -8039,6 +8042,10 @@ packages: engines: {node: '>=10'} dev: true + /js-big-decimal@2.2.0: + resolution: {integrity: sha512-qJFDTcgBGvuPzsck0jNm1puKvJQ3AL8J3bIyrvF1KfsbljOVj8N/o9Kbr8RXlBx1J8aapcRpMCiG6h1l6QgYhQ==} + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 86bc630edbdfc9..ad84b8c728bd20 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -1271,3 +1271,58 @@ export type AppMetric2Type = { | 'fetch' count: number } + +interface TextOperator { + operator: 'equals' | 'startsWith' | 'includes' + value: string +} + +export interface ModelDetails { + matches: string[] + searchTerms: string[] + info: { + releaseDate: string + maxTokens?: number + description: string + tradeOffs: string[] + benchmarks: { + [key: string]: number + } + capabilities: string[] + strengths: string[] + weaknesses: string[] + recommendations: string[] + } +} + +export type ModelDetailsMap = { + [key: string]: ModelDetails +} + +export interface ModelRow { + model: TextOperator + cost: { + prompt_token: number + completion_token: number + } + showInPlayground?: boolean + targetUrl?: string + dateRange?: { + start: string + end: string + } +} + +export interface ModelRow { + model: TextOperator + cost: { + prompt_token: number + completion_token: number + } + showInPlayground?: boolean + targetUrl?: string + dateRange?: { + start: string + end: string + } +} diff --git a/plugin-server/src/utils/ai-cost-data/anthropic/index.ts b/plugin-server/src/utils/ai-cost-data/anthropic/index.ts new file mode 100644 index 00000000000000..d7204071bb5d9c --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/anthropic/index.ts @@ -0,0 +1,479 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelDetailsMap, ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'claude-instant-1', + }, + cost: { + prompt_token: 0.00000163, + completion_token: 0.0000551, + }, + }, + { + model: { + operator: 'equals', + value: 'claude-v1', + }, + cost: { + prompt_token: 0.000008, + completion_token: 0.000024, + }, + }, + + { + model: { + operator: 'equals', + value: 'claude-2', + }, + cost: { + prompt_token: 0.000008, + completion_token: 0.000024, + }, + }, + + { + model: { + operator: 'equals', + value: 'claude-instant-1.2', + }, + cost: { + prompt_token: 0.00000163, + completion_token: 0.00000551, + }, + }, + { + model: { + operator: 'equals', + value: 'claude-2.0', + }, + cost: { + prompt_token: 0.00001102, + completion_token: 0.00003268, + }, + }, + { + model: { + operator: 'equals', + value: 'claude-3-opus-20240229', + }, + cost: { + prompt_token: 0.000015, + completion_token: 0.000075, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'claude-3-sonnet-20240229', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000015, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'claude-3-5-sonnet-20240620', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000015, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'claude-3-5-sonnet-20241022', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000015, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'claude-3-haiku-20240307', + }, + cost: { + prompt_token: 0.00000025, + completion_token: 0.00000125, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'claude-3-5-haiku-20241022', + }, + cost: { + prompt_token: 0.000001, + completion_token: 0.000005, + }, + showInPlayground: true, + }, +] + +export const modelDetails: ModelDetailsMap = { + 'claude-3-opus': { + matches: ['claude-3-opus-20240229'], + searchTerms: ['claude 3 opus', 'claude-3-opus', 'opus'], + info: { + maxTokens: 200000, + releaseDate: '2024-03-04', + description: + "Claude 3 Opus is Anthropic's most advanced model, demonstrating exceptional performance across complex tasks with near-perfect recall in long-context scenarios and sophisticated capabilities in coding, analysis, and creative work.", + tradeOffs: [ + 'Premium pricing reflects advanced capabilities', + 'Higher latency due to model complexity', + 'Resource-intensive for optimal performance', + ], + benchmarks: { + mmlu: 0.868, + hellaswag: 0.954, + bbh: 0.868, + math: 0.952, + }, + capabilities: [ + 'Near-perfect recall with 200k context window', + 'Advanced mathematical reasoning and problem-solving', + 'Superior code generation and debugging', + 'Complex document analysis and summarization', + 'Sophisticated data extraction and interpretation', + 'Multi-step reasoning tasks', + 'Advanced pattern recognition', + ], + strengths: [ + 'Exceptional context handling (>99% accuracy in NIAH tests)', + 'Strong performance in mathematical tasks (95.2% accuracy)', + 'Advanced code generation capabilities (68.4% success rate)', + 'Precise document summarization', + 'Focused and actionable responses', + 'Self-awareness in identifying artificial content', + 'Consistent performance across diverse tasks', + ], + weaknesses: [ + 'Occasional struggles with PDF data extraction', + 'Challenges with heat map interpretation', + 'Potential for hallucination in visual analysis', + 'May return errors for certain coding edge cases', + 'Higher latency compared to lighter models', + ], + recommendations: [ + 'Large-context processing applications', + 'Complex mathematical and analytical tasks', + 'Advanced software development projects', + 'Detailed document analysis and summarization', + 'Research and academic applications', + 'Enterprise-grade AI solutions', + 'Tasks requiring high accuracy and reliability', + ], + }, + }, + 'claude-3-sonnet': { + matches: ['claude-3-sonnet-20240229', 'claude-3-5-sonnet-20240620', 'claude-3-5-sonnet-20241022'], + searchTerms: ['claude 3 sonnet', 'claude-3-sonnet', 'sonnet', 'claude 3.5 sonnet'], + info: { + maxTokens: 200000, + releaseDate: '2024-03-04', + description: + 'Claude 3 Sonnet offers a strong balance of intelligence and speed, suitable for most use cases.', + tradeOffs: ['Lower cost than Opus', 'Slightly reduced capabilities compared to Opus'], + benchmarks: { + mmlu: 0.887, // 88.7% on MMLU + hellaswag: 0.89, // 89% on HellaSwag + bbh: 0.931, + }, + capabilities: [ + 'General reasoning and analysis', + 'Code generation and review', + 'Content creation and editing', + 'Task automation', + 'Data analysis', + ], + strengths: [ + 'Balanced performance profile', + 'Reliable output quality', + 'Good response speed', + 'Strong general knowledge', + 'Versatile across many tasks', + ], + weaknesses: [ + 'May need guidance on complex tasks', + 'Less specialized than Opus', + 'Moderate processing speed', + ], + recommendations: [ + 'General purpose development', + 'Content creation and editing', + 'Business analysis', + 'Educational applications', + 'Daily productivity tasks', + ], + }, + }, + 'claude-3-haiku': { + matches: ['claude-3-haiku-20240307', 'claude-3-5-haiku-20241022'], + searchTerms: ['claude 3 haiku', 'claude-3-haiku', 'haiku', 'claude 3.5 haiku'], + info: { + maxTokens: 200000, + releaseDate: '2024-03-04', + description: + 'Claude 3 Haiku is optimized for rapid response times and high throughput, delivering impressive speed while maintaining reliable performance. It excels in scenarios requiring quick interactions and efficient processing of straightforward tasks.', + tradeOffs: [ + 'Optimized for speed and efficiency', + 'Excellent performance-to-cost ratio', + 'Best suited for high-throughput applications', + 'Balance of speed and reliability', + ], + benchmarks: { + mmlu: 0.752, + hellaswag: 0.859, + bbh: 0.737, + }, + capabilities: [ + 'High-speed token generation (134 tokens/sec)', + 'Low latency responses (0.43s to first token)', + 'Efficient streaming support', + 'Function/tool calling', + 'JSON mode support', + 'Parallel query processing', + 'Context window handling up to 200k tokens', + ], + strengths: [ + 'Superior output speed (134.2 tokens/second)', + 'Minimal latency (0.43s TTFT)', + 'Consistent performance across context lengths', + 'Efficient resource utilization', + 'Cost-effective processing', + 'Reliable API features', + 'Stable performance over time', + ], + weaknesses: [ + 'Performance varies with input length', + 'Latency increases with context size', + 'Lower quality index compared to larger models', + 'Variable speed with parallel processing', + 'Response time sensitivity to input complexity', + ], + recommendations: [ + 'Real-time applications', + 'Customer service automation', + 'Quick content checks', + 'Simple queries and responses', + 'High-volume, straightforward tasks', + ], + }, + }, + 'claude-2': { + matches: ['claude-2', 'claude-2.0'], + searchTerms: ['claude 2', 'claude-2'], + info: { + maxTokens: 200000, + releaseDate: '2023-07-11', + description: + "Claude 2 is Anthropic's previous generation model, offering reliable performance for various tasks.", + tradeOffs: ['More affordable than Claude 3', 'Less capable than newer models'], + benchmarks: {}, + capabilities: [ + 'General text generation', + 'Basic analysis', + 'Code assistance', + 'Content creation', + 'Task automation', + ], + strengths: [ + 'Stable performance', + 'Reliable outputs', + 'Good general knowledge', + 'Cost-effective', + 'Proven track record', + ], + weaknesses: ['Older architecture', 'Limited advanced features', 'Less refined outputs'], + recommendations: [ + 'Legacy applications', + 'Basic automation', + 'General text processing', + 'Simple analysis tasks', + 'Standard content creation', + ], + }, + }, + 'claude-instant': { + matches: ['claude-instant-1', 'claude-instant-1.2'], + searchTerms: ['claude instant', 'claude-instant'], + info: { + maxTokens: 100000, + releaseDate: '2023-08-09', + description: "Claude Instant is Anthropic's faster, lighter previous generation model.", + tradeOffs: ['Fastest response times in Claude 2 series', 'Most affordable', 'Reduced capabilities'], + benchmarks: { + mmlu: 0.734, + }, + capabilities: [ + 'Quick responses', + 'Basic text processing', + 'Simple queries', + 'Lightweight tasks', + 'Efficient processing', + ], + strengths: [ + 'Fast processing speed', + 'Resource efficient', + 'Cost-effective', + 'Consistent performance', + 'Low latency', + ], + weaknesses: ['Basic capabilities only', 'Limited analysis depth', 'Simpler responses'], + recommendations: [ + 'Quick response systems', + 'Basic chatbots', + 'Simple automation', + 'High-volume processing', + 'Efficient text handling', + ], + }, + }, + 'claude-3.5-sonnet': { + matches: ['claude-3-5-sonnet-20240620', 'claude-3-5-sonnet-20241022'], + searchTerms: ['claude 3.5 sonnet', 'claude-3-5-sonnet'], + info: { + maxTokens: 200000, + releaseDate: '2024-06-20', + description: + "Claude 3.5 Sonnet is Anthropic's latest model, delivering enhanced performance with optimized speed and efficiency. It excels in graduate-level reasoning, undergraduate knowledge, and code generation while maintaining high throughput.", + tradeOffs: [ + 'Balanced performance-to-cost ratio', + 'Optimized for production workloads', + 'High throughput with moderate latency', + 'Strong accuracy with reasonable resource usage', + ], + benchmarks: { + mmlu: 0.887, + hellaswag: 0.89, + bbh: 0.931, + multilingual_math: 0.916, // 91.6% on multilingual math tasks + reasoning_over_text: 0.871, // 87.1% on reasoning over text + }, + capabilities: [ + 'Advanced graduate-level reasoning', + 'Strong undergraduate knowledge base', + 'Superior code generation and review', + 'Complex data extraction and analysis', + 'Multi-step problem solving', + 'High-accuracy classification tasks', + 'Efficient document processing', + ], + strengths: [ + 'Exceptional coding performance', + 'High precision in classification (85%)', + 'Strong data extraction capabilities', + 'Efficient throughput (~79 tokens/second)', + 'Reliable performance on complex tasks', + 'Excellent multilingual math processing', + 'Superior text reasoning abilities', + ], + weaknesses: [ + 'Lower performance on abstract reasoning puzzles', + 'Struggles with numerical and date-related questions', + 'May introduce regressions in certain classification scenarios', + 'Requires clear prompting for optimal performance', + 'Variable performance on complex extraction tasks', + ], + recommendations: [ + 'Production-grade applications requiring reliability', + 'Code generation and review systems', + 'Complex data extraction pipelines', + 'High-accuracy classification systems', + 'Document analysis and processing', + 'Educational and academic applications', + 'Enterprise-scale deployments', + ], + }, + }, + 'claude-3.5-haiku': { + matches: ['claude-3-5-haiku-20241022'], + searchTerms: ['claude 3.5 haiku', 'claude-3-5-haiku'], + info: { + maxTokens: 200000, + releaseDate: '2024-10-22', + description: + 'Claude 3.5 Haiku represents a significant advancement in high-throughput, cost-effective AI processing. It delivers enhanced performance over its predecessor while maintaining exceptional speed and efficiency, making it ideal for large-scale applications requiring quick responses.', + tradeOffs: [ + 'Optimized for maximum throughput', + 'Enhanced speed-to-performance ratio', + 'Improved cost efficiency', + 'Better balance of speed and accuracy', + ], + benchmarks: { + quality_index: 62, // Improved Quality Index over Claude 3 Haiku + throughput: 145, // tokens per second + ttft: 0.39, // Time to First Token in seconds + }, + capabilities: [ + 'Enhanced token generation speed (145 tokens/sec)', + 'Reduced latency (0.39s to first token)', + 'Improved parallel processing', + 'Advanced streaming capabilities', + 'Robust function calling', + 'Enhanced JSON mode reliability', + 'Efficient context handling up to 200k tokens', + 'Improved error handling', + ], + strengths: [ + 'Superior throughput (145 tokens/second)', + 'Minimal startup latency (0.39s TTFT)', + 'Enhanced stability under load', + 'Improved response consistency', + 'Better error recovery', + 'More reliable streaming', + 'Enhanced parallel processing capabilities', + 'Optimized resource utilization', + ], + weaknesses: [ + 'Performance degradation with very long contexts', + 'Variability in complex reasoning tasks', + 'May struggle with nuanced analysis', + 'Limited creative capabilities', + 'Reduced performance in edge cases', + ], + recommendations: [ + 'High-volume API services', + 'Real-time chat systems', + 'Large-scale data processing', + 'Streaming applications', + 'Cost-sensitive deployments', + 'Quick-response systems', + 'Parallel processing workflows', + 'Resource-constrained environments', + ], + }, + }, +} + +const reverseModelMap: { [key: string]: string } = {} + +for (const parentModel in modelDetails) { + const details = modelDetails[parentModel] + details.matches.forEach((modelName) => { + reverseModelMap[modelName] = parentModel + }) +} + +export const anthropicProvider = { + costs, + modelDetails, + reverseModelMap, +} diff --git a/plugin-server/src/utils/ai-cost-data/awsBedrock/index.ts b/plugin-server/src/utils/ai-cost-data/awsBedrock/index.ts new file mode 100644 index 00000000000000..92ed36602dd6c9 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/awsBedrock/index.ts @@ -0,0 +1,18 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'meta.llama3-8b-instruct-v1%3A0', + }, + cost: { + prompt_token: 0.00022, + completion_token: 0.00072, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/azure/index.ts b/plugin-server/src/utils/ai-cost-data/azure/index.ts new file mode 100644 index 00000000000000..8f84b5491841ed --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/azure/index.ts @@ -0,0 +1,98 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'gpt-4-turbo-preview', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-45-turbo', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt4-turbo-preview', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-preview-1106', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-35-turbo-1106', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt35', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-35-turbo-0613', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-35-16k', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000004, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-vision', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/cohere/index.ts b/plugin-server/src/utils/ai-cost-data/cohere/index.ts new file mode 100644 index 00000000000000..2e57172fd4727f --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/cohere/index.ts @@ -0,0 +1,19 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'cohere/command-r', + }, + cost: { + prompt_token: 0.0000005, + completion_token: 0.0000015, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/fireworks/index.ts b/plugin-server/src/utils/ai-cost-data/fireworks/index.ts new file mode 100644 index 00000000000000..cd9eba97ac5395 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/fireworks/index.ts @@ -0,0 +1,204 @@ +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/mixtral-8x7b-instruct', + }, + cost: { + prompt_token: 0.0000005, + completion_token: 0.0000005, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/mixtral-8x22b-instruct', + }, + cost: { + prompt_token: 0.0000012, + completion_token: 0.0000012, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/yi-large', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000003, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/sd3', + }, + cost: { + prompt_token: 0.00013, + completion_token: 0.00013, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/sd3-medium', + }, + cost: { + prompt_token: 0.00013, + completion_token: 0.00013, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/stable-diffusion-xl-1024-v1-0', + }, + cost: { + prompt_token: 0.00013, + completion_token: 0.00013, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/playground-v2-1024px-aesthetic', + }, + cost: { + prompt_token: 0.00013, + completion_token: 0.00013, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/playground-v2-5-1024px-aesthetic', + }, + cost: { + prompt_token: 0.00013, + completion_token: 0.00013, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/SSD-1B', + }, + cost: { + prompt_token: 0.00013, + completion_token: 0.00013, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/japanese-stable-diffusion-xl', + }, + cost: { + prompt_token: 0.00013, + completion_token: 0.00013, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/sd3-turbo', + }, + cost: { + prompt_token: 0.00013, + completion_token: 0.00013, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/sd3-ControlNet', + }, + cost: { + prompt_token: 0.0002, + completion_token: 0.0002, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/sd3-medium-ControlNet', + }, + cost: { + prompt_token: 0.0002, + completion_token: 0.0002, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/stable-diffusion-xl-1024-v1-0-ControlNet', + }, + cost: { + prompt_token: 0.0002, + completion_token: 0.0002, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/playground-v2-1024px-aesthetic-ControlNet', + }, + cost: { + prompt_token: 0.0002, + completion_token: 0.0002, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/playground-v2-5-1024px-aesthetic-ControlNet', + }, + cost: { + prompt_token: 0.0002, + completion_token: 0.0002, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/SSD-1B-ControlNet', + }, + cost: { + prompt_token: 0.0002, + completion_token: 0.0002, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/japanese-stable-diffusion-xl-ControlNet', + }, + cost: { + prompt_token: 0.0002, + completion_token: 0.0002, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/sd3-turbo-ControlNet', + }, + cost: { + prompt_token: 0.0002, + completion_token: 0.0002, + }, + }, + { + model: { + operator: 'equals', + value: 'accounts/fireworks/models/llama-v3p1-405b-instruct', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000003, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/google/index.ts b/plugin-server/src/utils/ai-cost-data/google/index.ts new file mode 100644 index 00000000000000..9d151095dc5bd2 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/google/index.ts @@ -0,0 +1,80 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'includes', + value: 'gemini-pro', + }, + cost: { + prompt_token: 0.000000125, + completion_token: 0.000000375, + }, + }, + { + model: { + operator: 'equals', + value: 'gemini-1.0-pro-vision-001', + }, + cost: { + prompt_token: 0.000000125, + completion_token: 0.000000375, + }, + }, + { + model: { + operator: 'equals', + value: 'gemini-1.0-pro', + }, + cost: { + prompt_token: 0.000000125, + completion_token: 0.000000375, + }, + }, + { + model: { + operator: 'includes', + value: 'gemini-1.5-flash', + }, + cost: { + prompt_token: 0.00000035, + completion_token: 0.00000105, + }, + }, + { + model: { + operator: 'equals', + value: 'gemini-flash-1.5-8b', + }, + cost: { + prompt_token: 3.75e-8, + completion_token: 1.5e-7, + }, + }, + { + model: { + operator: 'includes', + value: 'gemini-1.5-pro', + }, + cost: { + prompt_token: 0.0000035, + completion_token: 0.0000105, + }, + }, + { + model: { + operator: 'equals', + value: 'claude-3-5-sonnet-v2@20241022', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000015, + }, + showInPlayground: false, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/groq/index.ts b/plugin-server/src/utils/ai-cost-data/groq/index.ts new file mode 100644 index 00000000000000..0a608a08319d58 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/groq/index.ts @@ -0,0 +1,89 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'llama2-70b-4096', + }, + cost: { + prompt_token: 0.0000007, + completion_token: 0.0000008, + }, + }, + { + model: { + operator: 'equals', + value: 'mixtral-8x7b-32768', + }, + cost: { + prompt_token: 0.00000024, + completion_token: 0.00000024, + }, + }, + { + model: { + operator: 'equals', + value: 'gemma-7b-it', + }, + cost: { + prompt_token: 0.00000007, + completion_token: 0.00000007, + }, + }, + { + model: { + operator: 'equals', + value: 'gemma2-9b-it', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + { + model: { + operator: 'equals', + value: 'llama3-70b-8192', + }, + cost: { + prompt_token: 0.00000059, + completion_token: 0.00000079, + }, + }, + { + model: { + operator: 'equals', + value: 'llama3-8b-8192', + }, + cost: { + prompt_token: 0.00000005, + completion_token: 0.00000008, + }, + }, + { + model: { + operator: 'equals', + value: 'llama3-groq-70b-8192-tool-use-preview', + }, + cost: { + prompt_token: 0.00000089, + completion_token: 0.00000089, + }, + }, + { + model: { + operator: 'equals', + value: 'llama3-groq-8b-8192-tool-use-preview', + }, + cost: { + prompt_token: 0.00000019, + completion_token: 0.00000019, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/mappings.ts b/plugin-server/src/utils/ai-cost-data/mappings.ts new file mode 100644 index 00000000000000..ef2530d753524d --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/mappings.ts @@ -0,0 +1,234 @@ +import { ModelDetailsMap, ModelRow } from 'types' + +import { anthropicProvider } from './anthropic' +import { costs as awsBedrockCosts } from './awsBedrock' +import { costs as azureCosts } from './azure' +import { costs as cohereCosts } from './cohere' +import { costs as fireworksAICosts } from './fireworks' +import { costs as googleCosts } from './google' +import { costs as groqCosts } from './groq' +import { costs as mistralCosts } from './mistral' +import { openAIProvider } from './openai' +import { costs as fineTunedOpenAICosts } from './openai/fine-tuned-models' +import { costs as openRouterCosts } from './openrouter' +import { costs as qstashCosts } from './qstash' +import { costs as togetherAIChatCosts } from './togetherai/chat' +import { costs as togetherAIChatLlamaCosts } from './togetherai/chat/llama' +import { costs as togetherAICompletionCosts } from './togetherai/completion' +import { costs as togetherAICompletionLlamaCosts } from './togetherai/completion' + +const openAiPattern = /^https:\/\/api\.openai\.com/ +const anthropicPattern = /^https:\/\/api\.anthropic\.com/ +const azurePattern = /^(https?:\/\/)?([^.]*\.)?(openai\.azure\.com|azure-api\.net)(\/.*)?$/ +const localProxyPattern = /^http:\/\/127\.0\.0\.1:\d+\/v\d+\/?$/ +const heliconeProxyPattern = /^https:\/\/oai\.hconeai\.com/ +const amdbartekPattern = /^https:\/\/.*\.amdbartek\.dev/ +const anyscalePattern = /^https:\/\/api\.endpoints\.anyscale\.com/ +const cloudflareAiGatewayPattern = /^https:\/\/gateway\.ai\.cloudflare\.com/ +const twoYFV = /^https:\/\/api\.2yfv\.com/ +const togetherPattern = /^https:\/\/api\.together\.xyz/ +const lemonFox = /^https:\/\/api\.lemonfox\.ai/ +const fireworks = /^https:\/\/api\.fireworks\.ai/ +const perplexity = /^https:\/\/api\.perplexity\.ai/ +const googleapis = /^https:\/\/(.*\.)?googleapis\.com/ +// openrouter.ai or api.openrouter.ai +const openRouter = /^https:\/\/(api\.)?openrouter\.ai/ +//api.wisdominanutshell.academy +const wisdomInANutshell = /^https:\/\/api\.wisdominanutshell\.academy/ +// api.groq.com +const groq = /^https:\/\/api\.groq\.com/ +// cohere.ai +const cohere = /^https:\/\/api\.cohere\.ai/ +// api.mistral.ai +const mistral = /^https:\/\/api\.mistral\.ai/ +// https://api.deepinfra.com +const deepinfra = /^https:\/\/api\.deepinfra\.com/ +//https://qstash.upstash.io/llm +const qstash = /^https:\/\/qstash\.upstash\.io/ +//https://www.firecrawl.dev/ +const firecrawl = /^https:\/\/api\.firecrawl\.dev/ +// https://bedrock-runtime.{some-region}.amazonaws.com/{something-after} +const awsBedrock = /^https:\/\/bedrock-runtime\.[a-z0-9-]+\.amazonaws\.com\/.*/ + +export const providersNames = [ + 'OPENAI', + 'ANTHROPIC', + 'AZURE', + 'LOCAL', + 'HELICONE', + 'AMDBARTEK', + 'ANYSCALE', + 'CLOUDFLARE', + '2YFV', + 'TOGETHER', + 'LEMONFOX', + 'FIREWORKS', + 'PERPLEXITY', + 'GOOGLE', + 'OPENROUTER', + 'WISDOMINANUTSHELL', + 'GROQ', + 'COHERE', + 'MISTRAL', + 'DEEPINFRA', + 'QSTASH', + 'FIRECRAWL', + 'AWS', +] as const + +export type ProviderName = (typeof providersNames)[number] + +export type ModelNames = (typeof modelNames)[number] + +export const providers: { + pattern: RegExp + provider: ProviderName + costs?: ModelRow[] + modelDetails?: ModelDetailsMap +}[] = [ + { + pattern: openAiPattern, + provider: 'OPENAI', + costs: [...openAIProvider.costs, ...fineTunedOpenAICosts], + modelDetails: openAIProvider.modelDetails, + }, + { + pattern: anthropicPattern, + provider: 'ANTHROPIC', + costs: anthropicProvider.costs, + modelDetails: anthropicProvider.modelDetails, + }, + { + pattern: azurePattern, + provider: 'AZURE', + costs: [...azureCosts, ...openAIProvider.costs], + }, + { + pattern: localProxyPattern, + provider: 'LOCAL', + }, + { + pattern: heliconeProxyPattern, + provider: 'HELICONE', + }, + { + pattern: amdbartekPattern, + provider: 'AMDBARTEK', + }, + { + pattern: anyscalePattern, + provider: 'ANYSCALE', + }, + { + pattern: cloudflareAiGatewayPattern, + provider: 'CLOUDFLARE', + }, + { + pattern: twoYFV, + provider: '2YFV', + }, + { + pattern: togetherPattern, + provider: 'TOGETHER', + costs: [ + ...togetherAIChatCosts, + ...togetherAIChatLlamaCosts, + ...togetherAICompletionCosts, + ...togetherAICompletionLlamaCosts, + ], + }, + { + pattern: lemonFox, + provider: 'LEMONFOX', + }, + { + pattern: fireworks, + provider: 'FIREWORKS', + costs: fireworksAICosts, + }, + { + pattern: perplexity, + provider: 'PERPLEXITY', + }, + { + pattern: googleapis, + provider: 'GOOGLE', + costs: googleCosts, + }, + { + pattern: openRouter, + provider: 'OPENROUTER', + costs: openRouterCosts, + }, + { + pattern: wisdomInANutshell, + provider: 'WISDOMINANUTSHELL', + }, + { + pattern: groq, + provider: 'GROQ', + costs: groqCosts, + }, + { + pattern: cohere, + provider: 'COHERE', + costs: cohereCosts, + }, + { + pattern: mistral, + provider: 'MISTRAL', + costs: mistralCosts, + }, + { + pattern: deepinfra, + provider: 'DEEPINFRA', + }, + { + pattern: qstash, + provider: 'QSTASH', + costs: qstashCosts, + }, + { + pattern: firecrawl, + provider: 'FIRECRAWL', + }, + { + pattern: awsBedrock, + provider: 'AWS', + costs: awsBedrockCosts, + }, +] + +export const playgroundModels: { + name: string + provider: ProviderName +}[] = + (providers + .map((provider) => { + return provider.costs + ?.filter((cost) => cost.showInPlayground) + .map((cost) => ({ + name: cost.model.value, + provider: provider.provider, + })) + }) + .flat() + .filter((model) => model !== undefined) as { + name: string + provider: ProviderName + }[]) ?? [] + +export const defaultProvider = providers.find((provider) => provider.provider === 'OPENAI')! + +export const allCosts = providers.flatMap((provider) => provider.costs ?? []) + +export const approvedDomains = providers.map((provider) => provider.pattern) + +export const modelNames = allCosts.map((cost) => cost.model.value) + +export const parentModelNames = providers.reduce((acc, provider) => { + if (provider.modelDetails) { + acc[provider.provider] = Object.keys(provider.modelDetails) + } + return acc +}, {} as Record) diff --git a/plugin-server/src/utils/ai-cost-data/mistral/index.ts b/plugin-server/src/utils/ai-cost-data/mistral/index.ts new file mode 100644 index 00000000000000..6ca8611f0d7f69 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/mistral/index.ts @@ -0,0 +1,69 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'open-mistral-7b', + }, + cost: { + prompt_token: 0.00000025, + completion_token: 0.00000025, + }, + }, + { + model: { + operator: 'equals', + value: 'open-mixtral-8x7b', + }, + cost: { + prompt_token: 0.0000007, + completion_token: 0.0000007, + }, + }, + { + model: { + operator: 'equals', + value: 'mistral-small-latest', + }, + cost: { + prompt_token: 0.000002, + completion_token: 0.000006, + }, + }, + { + model: { + operator: 'equals', + value: 'mistral-medium-latest', + }, + cost: { + prompt_token: 0.0000027, + completion_token: 0.0000081, + }, + }, + { + model: { + operator: 'equals', + value: 'mistral-large-latest', + }, + cost: { + prompt_token: 0.000008, + completion_token: 0.000024, + }, + }, + { + model: { + operator: 'equals', + value: 'mistral-embed', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/openai/fine-tuned-models.ts b/plugin-server/src/utils/ai-cost-data/openai/fine-tuned-models.ts new file mode 100644 index 00000000000000..3345492b7f3cd4 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/openai/fine-tuned-models.ts @@ -0,0 +1,39 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'startsWith', + value: 'ft:gpt-3.5-turbo-', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000006, + }, + }, + { + model: { + operator: 'startsWith', + value: 'ft:gpt-4o-mini-2024-07-18:', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000012, + }, + }, + { + model: { + operator: 'startsWith', + value: 'ft:gpt-4o-2024-08-06:', + }, + cost: { + prompt_token: 0.00000375, + completion_token: 0.000015, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/openai/index.ts b/plugin-server/src/utils/ai-cost-data/openai/index.ts new file mode 100644 index 00000000000000..2c1dc8236f07f5 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/openai/index.ts @@ -0,0 +1,817 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelDetailsMap, ModelRow } from '../../../types' + +const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'ada', + }, + cost: { + prompt_token: 0.0000004, + completion_token: 0.0000004, + }, + }, + { + model: { + operator: 'equals', + value: 'text-ada-001', + }, + cost: { + prompt_token: 0.0000004, + completion_token: 0.0000004, + }, + }, + { + model: { + operator: 'equals', + value: 'babbage', + }, + cost: { + prompt_token: 0.0000005, + completion_token: 0.0000005, + }, + }, + { + model: { + operator: 'equals', + value: 'curie', + }, + cost: { + prompt_token: 0.000002, + completion_token: 0.000002, + }, + }, + { + model: { + operator: 'equals', + value: 'text-curie-001', + }, + cost: { + prompt_token: 0.000002, + completion_token: 0.000002, + }, + }, + { + model: { + operator: 'equals', + value: 'davinci', + }, + cost: { + prompt_token: 0.00002, + completion_token: 0.00002, + }, + }, + { + model: { + operator: 'equals', + value: 'text-davinci-001', + }, + cost: { + prompt_token: 0.00002, + completion_token: 0.00002, + }, + }, + { + model: { + operator: 'equals', + value: 'text-davinci-002', + }, + cost: { + prompt_token: 0.00002, + completion_token: 0.00002, + }, + }, + { + model: { + operator: 'equals', + value: 'text-davinci-003', + }, + cost: { + prompt_token: 0.00002, + completion_token: 0.00002, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-3.5-turbo', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-3.5-turbo-0301', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-35-turbo', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-3.5-turbo-1106', + }, + cost: { + prompt_token: 0.000001, + completion_token: 0.000002, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-3.5-turbo-instruct', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-3.5-turbo-instruct-0914', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4', + }, + cost: { + prompt_token: 0.00003, + completion_token: 0.00006, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-0314', + }, + cost: { + prompt_token: 0.00003, + completion_token: 0.00006, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-0613', + }, + cost: { + prompt_token: 0.00003, + completion_token: 0.00006, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-32k', + }, + cost: { + prompt_token: 0.00006, + completion_token: 0.00012, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-32k-0314', + }, + cost: { + prompt_token: 0.00006, + completion_token: 0.00012, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-32k-0613', + }, + cost: { + prompt_token: 0.00006, + completion_token: 0.00012, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-0125-preview', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-1106-preview', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-1106-vision-preview', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4o', + }, + cost: { + prompt_token: 0.000005, + completion_token: 0.000015, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4o-2024-05-13', + }, + cost: { + prompt_token: 0.000005, + completion_token: 0.000015, + }, + showInPlayground: true, + }, + + { + model: { + operator: 'equals', + value: 'gpt-4o-mini', + }, + cost: { + prompt_token: 0.00000015, + completion_token: 0.0000006, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4o-mini-2024-07-18', + }, + cost: { + prompt_token: 0.00000015, + completion_token: 0.0000006, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-3.5-turbo-0613', + }, + cost: { + prompt_token: 0.0000015, + completion_token: 0.000002, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-35-turbo-16k', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000004, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-3.5-turbo-16k-0613', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000004, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-3.5-turbo-0125', + }, + cost: { + prompt_token: 0.0000005, + completion_token: 0.0000015, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-turbo', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-turbo-2024-04-09', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-turbo-0125-preview', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'text-embedding-ada-002', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'text-embedding-ada', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'text-embedding-ada-002-v2', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'text-embedding-3-small', + }, + cost: { + prompt_token: 0.00000002, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'text-embedding-3-large', + }, + cost: { + prompt_token: 0.00000013, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-4-vision-preview', + }, + cost: { + prompt_token: 0.00001, + completion_token: 0.00003, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-35-turbo-16k-0613', + }, + showInPlayground: true, + cost: { + prompt_token: 0.000003, + completion_token: 0.000004, + }, + }, + { + model: { + operator: 'equals', + value: 'gpt-4o-2024-08-06', + }, + showInPlayground: true, + cost: { + prompt_token: 0.0000025, + completion_token: 0.00001, + }, + }, + { + model: { + operator: 'equals', + value: 'o1-preview', + }, + cost: { + prompt_token: 0.000015, + completion_token: 0.00006, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'o1-preview-2024-09-12', + }, + cost: { + prompt_token: 0.000015, + completion_token: 0.00006, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'o1-mini', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000012, + }, + showInPlayground: true, + }, + { + model: { + operator: 'equals', + value: 'o1-mini-2024-09-12', + }, + cost: { + prompt_token: 0.000003, + completion_token: 0.000012, + }, + showInPlayground: true, + }, +] + +const modelDetails: ModelDetailsMap = { + 'gpt-4': { + matches: [ + 'gpt-4', + 'gpt-4-0314', + 'gpt-4-0613', + 'gpt-4-32k', + 'gpt-4-32k-0314', + 'gpt-4-0125-preview', + 'gpt-4-1106-preview', + ], + searchTerms: ['gpt 4', 'gpt-4', 'chat gpt 4', '4', 'chat 4'], + info: { + maxTokens: 8192, + releaseDate: '2024-03-13', + description: + 'GPT-4 is the latest and most advanced model in the GPT series, demonstrating sophisticated capabilities in complex reasoning, theory of mind, and narrative understanding.', + tradeOffs: [ + 'More expensive than GPT-3.5 Turbo', + 'Performance can vary even with temperature=0', + 'May struggle with world-building in absurd scenarios', + ], + benchmarks: { + mmlu: 0.864, + ifeval: 0.67, + hellaswag: 0.953, + bbh: 0.831, + }, + capabilities: [ + 'Advanced reasoning', + 'Theory of mind', + 'Complex narrative understanding', + 'Chain-of-thought processing', + ], + strengths: [ + 'Strong performance in theory of mind tasks', + 'Ability to track and reason about multiple entities', + 'Can explain its reasoning process', + ], + weaknesses: [ + 'May struggle with highly abstract or unrealistic scenarios', + 'Output can be non-deterministic even at temperature=0', + "Performance depends on how 'normal' the scenario is", + ], + recommendations: [ + 'Complex reasoning and analysis tasks', + 'Professional content creation and editing', + 'Advanced coding and technical problem-solving', + 'Multi-step planning and strategy development', + 'Academic research and paper writing', + 'Detailed technical documentation', + ], + }, + }, + 'gpt-4o': { + matches: ['gpt-4o', 'gpt-4o-2024-05-13'], + searchTerms: ['gpt 4o', 'gpt-4o', 'chat gpt 4o', '4o', 'chat 4o'], + info: { + maxTokens: 128000, + releaseDate: '2024-05-13', + description: + 'GPT-4 Optimized (GPT-4o) is designed for high performance in reasoning, creativity, and technical tasks while maintaining consistent output quality.', + tradeOffs: [ + 'Higher resource requirements for optimal performance', + 'Increased cost per token for premium capabilities', + 'May require more specific prompting for best results', + 'Larger context window increases memory usage', + 'Response time varies with complexity of task', + ], + benchmarks: { + mmlu: 0.887, + ifeval: 0.902, + hellaswag: 0.942, + bbh: 0.913, + }, + capabilities: [ + 'Advanced reasoning and problem-solving', + 'Strong coding abilities', + 'Mathematical computation', + 'Creative content generation', + 'Technical analysis', + ], + strengths: [ + 'Consistent output quality', + 'Strong technical performance', + 'Reliable response generation', + 'Broad knowledge base', + ], + weaknesses: [ + 'May produce overconfident responses', + 'Requires clear prompt engineering', + 'Performance varies with task complexity', + ], + recommendations: [ + 'Technical and analytical projects', + 'Software development tasks', + 'Mathematical problem-solving', + 'Content creation and analysis', + ], + }, + }, + 'gpt-4o-mini': { + matches: ['gpt-4o-mini', 'gpt-4o-mini-2024-07-18'], + searchTerms: ['gpt 4o mini', 'gpt-4o-mini', 'chat gpt 4o mini', 'chat 4o mini'], + info: { + maxTokens: 128000, + releaseDate: '2024-07-18', + description: + 'GPT-4o Mini is a cost-optimized variant of GPT-4o, designed for high-efficiency processing while maintaining strong performance. It excels in rapid inference and resource-efficient operations, making it ideal for production deployments requiring a balance of cost and capability.', + tradeOffs: [ + 'Lower cost per token compared to GPT-4o', + 'Reduced latency for faster processing', + 'Smaller model size for efficient deployment', + 'Optimized for common tasks and queries', + 'Balance of performance and resource usage', + ], + benchmarks: { + mmlu: 0.82, + ifeval: 0.872, + hellaswag: 0.885, + truthfulqa: 0.793, + gsm8k: 0.846, + }, + capabilities: [ + 'Efficient natural language processing', + 'Quick response generation', + 'Code understanding and generation', + 'Task-specific optimization', + 'Resource-efficient inference', + 'Consistent output quality', + 'Scalable deployment support', + ], + strengths: [ + 'Cost-effective processing', + 'Low latency responses', + 'Efficient resource utilization', + 'Strong performance on common tasks', + 'Reliable output quality', + 'Optimized for production use', + 'Excellent scaling characteristics', + ], + weaknesses: [ + 'Lower performance on complex reasoning', + 'Reduced capability in specialized domains', + 'Limited context understanding vs larger models', + 'May struggle with nuanced tasks', + 'Less suitable for cutting-edge research', + ], + recommendations: [ + 'High-volume production deployments', + 'Cost-sensitive applications', + 'Real-time processing needs', + 'Standard NLP tasks', + 'Efficient API integrations', + 'Resource-constrained environments', + 'Scalable system architectures', + ], + }, + }, + 'gpt-4-turbo': { + matches: ['gpt-4-turbo', 'gpt-4-turbo-2024-04-09', 'gpt-4-turbo-0125-preview'], + searchTerms: ['gpt 4 turbo', 'gpt-4-turbo', 'chat gpt 4 turbo', '4 turbo', 'chat 4 turbo'], + info: { + maxTokens: 128000, + releaseDate: '2024-04-09', + description: 'GPT-4 Turbo is a more recent model that offers a balance between cost and performance.', + tradeOffs: ['More expensive than GPT-3.5 Turbo'], + benchmarks: { + bbh: 0.876, + hellaswag: 0.942, + mmlu: 0.865, + }, + capabilities: [], + strengths: [], + weaknesses: [], + recommendations: [], + }, + }, + 'gpt-3.5-turbo': { + matches: [ + 'gpt-3.5-turbo', + 'gpt-3.5-turbo-0301', + 'gpt-35-turbo', + 'gpt-3.5-turbo-1106', + 'gpt-3.5-turbo-instruct', + 'gpt-3.5-turbo-instruct-0914', + 'gpt-3.5-turbo-0613', + 'gpt-3.5-turbo-16k', + 'gpt-3.5-turbo-16k-0613', + 'gpt-35-turbo-16k', + 'gpt-35-turbo-16k-0613', + 'gpt-3.5-turbo-0125', + ], + searchTerms: ['gpt 3.5', 'gpt-3.5', 'chat gpt 3.5', 'chat 3.5'], + info: { + maxTokens: 16385, + releaseDate: '2023-11-06', + description: 'GPT-3.5 Turbo is a more recent model that offers a balance between cost and performance.', + tradeOffs: ['More expensive than GPT-3.5 Turbo'], + benchmarks: { + hellaswag: 0.855, + mmlu: 0.698, + }, + capabilities: [], + strengths: [], + weaknesses: [], + recommendations: [], + }, + }, + 'text-embedding-3': { + matches: ['text-embedding-3-small', 'text-embedding-3-large'], + searchTerms: ['text embedding 3', 'text-embedding-3'], + info: { + maxTokens: 3072, + releaseDate: '2022-12-15', + description: 'Text Embedding 3 is a model that offers a balance between cost and performance.', + tradeOffs: ['More expensive than GPT-3.5 Turbo'], + benchmarks: {}, + capabilities: [], + strengths: [], + weaknesses: [], + recommendations: [], + }, + }, + 'text-embedding-ada': { + matches: ['text-embedding-ada-002', 'text-embedding-ada', 'text-embedding-ada-002-v2'], + searchTerms: ['text embedding ada', 'text-embedding-ada'], + info: { + maxTokens: 1536, + releaseDate: '2022-12-15', + description: 'Text Embedding Ada is a model that offers a balance between cost and performance.', + tradeOffs: ['More expensive than GPT-3.5 Turbo'], + benchmarks: {}, + capabilities: [], + strengths: [], + weaknesses: [], + recommendations: [], + }, + }, + 'o1-preview': { + matches: ['o1-preview', 'o1-preview-2024-09-12'], + searchTerms: ['o1 preview', 'o1-preview', 'chat gpt o1', 'chat gpt o1 preview', 'chat o1', 'chat o1 preview'], + info: { + maxTokens: 128000, + releaseDate: '2024-09-12', + description: 'O1 Preview is a model that offers a balance between cost and performance.', + tradeOffs: ['More expensive than GPT-3.5 Turbo'], + benchmarks: { + mmlu: 0.908, + }, + capabilities: [], + strengths: [], + weaknesses: [], + recommendations: [], + }, + }, + 'o1-mini': { + matches: ['o1-mini', 'o1-mini-2024-09-12'], + searchTerms: ['o1 mini', 'o1-mini', 'chat gpt o1 mini', 'chat o1 mini'], + info: { + maxTokens: 128000, + releaseDate: '2024-09-12', + description: 'O1 Mini is a model that offers a balance between cost and performance.', + tradeOffs: ['More expensive than GPT-3.5 Turbo'], + benchmarks: {}, + capabilities: [], + strengths: [], + weaknesses: [], + recommendations: [], + }, + }, + 'gpt-4-vision-preview': { + matches: ['gpt-4-vision-preview', 'gpt-4-1106-vision-preview'], + searchTerms: ['gpt 4 vision', 'gpt-4-vision', 'gpt 4 vision preview', 'chat gpt 4 vision', 'chat 4 vision'], + info: { + maxTokens: 128000, + releaseDate: '2023-11-06', + description: 'GPT-4 Vision is a model that offers a balance between cost and performance.', + tradeOffs: ['More expensive than GPT-3.5 Turbo'], + benchmarks: { + bbh: 0.876, + hellaswag: 0.942, + mmlu: 0.865, + }, + capabilities: ['Vision'], + strengths: ['Can process images'], + weaknesses: ['More expensive than GPT-3.5 Turbo'], + recommendations: ['Use for tasks that require image processing'], + }, + }, +} + +const reverseModelMap: { [key: string]: string } = {} + +for (const parentModel in modelDetails) { + const details = modelDetails[parentModel] + details.matches.forEach((modelName) => { + reverseModelMap[modelName] = parentModel + }) +} + +export const openAIProvider = { + costs, + modelDetails, + reverseModelMap, +} diff --git a/plugin-server/src/utils/ai-cost-data/openrouter/index.ts b/plugin-server/src/utils/ai-cost-data/openrouter/index.ts new file mode 100644 index 00000000000000..aa15db0758ac8f --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/openrouter/index.ts @@ -0,0 +1,2159 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'sao10k/l3.3-euryale-70b', + }, + cost: { + prompt_token: 1.5e-6, + completion_token: 1.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'inflatebot/mn-mag-mell-r1', + }, + cost: { + prompt_token: 9e-7, + completion_token: 9e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/o1', + }, + cost: { + prompt_token: 1.5e-5, + completion_token: 6e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'eva-unit-01/eva-llama-3.33-70b', + }, + cost: { + prompt_token: 4e-6, + completion_token: 6e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'x-ai/grok-2-vision-1212', + }, + cost: { + prompt_token: 2e-6, + completion_token: 1e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'x-ai/grok-2-1212', + }, + cost: { + prompt_token: 2e-6, + completion_token: 1e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'cohere/command-r7b-12-2024', + }, + cost: { + prompt_token: 3.75e-8, + completion_token: 1.5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-2.0-flash-exp:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-exp-1206:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.3-70b-instruct', + }, + cost: { + prompt_token: 1.3e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'amazon/nova-lite-v1', + }, + cost: { + prompt_token: 6e-8, + completion_token: 2.4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'amazon/nova-micro-v1', + }, + cost: { + prompt_token: 3.5e-8, + completion_token: 1.4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'amazon/nova-pro-v1', + }, + cost: { + prompt_token: 8e-7, + completion_token: 3.2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwq-32b-preview', + }, + cost: { + prompt_token: 1.3e-7, + completion_token: 2e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-exp-1121:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'google/learnlm-1.5-pro-experimental:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'eva-unit-01/eva-qwen-2.5-72b', + }, + cost: { + prompt_token: 4e-6, + completion_token: 6e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4o-2024-11-20', + }, + cost: { + prompt_token: 2.5e-6, + completion_token: 1e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-large-2411', + }, + cost: { + prompt_token: 2e-6, + completion_token: 6e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-large-2407', + }, + cost: { + prompt_token: 2e-6, + completion_token: 6e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/pixtral-large-2411', + }, + cost: { + prompt_token: 2e-6, + completion_token: 6e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'x-ai/grok-vision-beta', + }, + cost: { + prompt_token: 5e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-exp-1114:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'infermatic/mn-inferor-12b', + }, + cost: { + prompt_token: 2.5e-7, + completion_token: 5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwen-2.5-coder-32b-instruct', + }, + cost: { + prompt_token: 8e-8, + completion_token: 1.8e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'raifle/sorcererlm-8x22b', + }, + cost: { + prompt_token: 4.5e-6, + completion_token: 4.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'eva-unit-01/eva-qwen-2.5-32b', + }, + cost: { + prompt_token: 2.6e-6, + completion_token: 3.4e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'thedrummer/unslopnemo-12b', + }, + cost: { + prompt_token: 5e-7, + completion_token: 5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3.5-haiku-20241022:beta', + }, + cost: { + prompt_token: 8e-7, + completion_token: 4e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3.5-haiku-20241022', + }, + cost: { + prompt_token: 8e-7, + completion_token: 4e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3.5-haiku:beta', + }, + cost: { + prompt_token: 8e-7, + completion_token: 4e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3.5-haiku', + }, + cost: { + prompt_token: 8e-7, + completion_token: 4e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'neversleep/llama-3.1-lumimaid-70b', + }, + cost: { + prompt_token: 3.375e-6, + completion_token: 4.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthracite-org/magnum-v4-72b', + }, + cost: { + prompt_token: 1.875e-6, + completion_token: 2.25e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3.5-sonnet:beta', + }, + cost: { + prompt_token: 3e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3.5-sonnet', + }, + cost: { + prompt_token: 3e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'x-ai/grok-beta', + }, + cost: { + prompt_token: 5e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/ministral-8b', + }, + cost: { + prompt_token: 1e-7, + completion_token: 1e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/ministral-3b', + }, + cost: { + prompt_token: 4e-8, + completion_token: 4e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwen-2.5-7b-instruct', + }, + cost: { + prompt_token: 2.7e-7, + completion_token: 2.7e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'nvidia/llama-3.1-nemotron-70b-instruct', + }, + cost: { + prompt_token: 2e-7, + completion_token: 2e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'inflection/inflection-3-pi', + }, + cost: { + prompt_token: 2.5e-6, + completion_token: 1e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'inflection/inflection-3-productivity', + }, + cost: { + prompt_token: 2.5e-6, + completion_token: 1e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-flash-1.5-8b', + }, + cost: { + prompt_token: 3.75e-8, + completion_token: 1.5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'anthracite-org/magnum-v2-72b', + }, + cost: { + prompt_token: 3e-6, + completion_token: 3e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'liquid/lfm-40b', + }, + cost: { + prompt_token: 1.5e-7, + completion_token: 1.5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'thedrummer/rocinante-12b', + }, + cost: { + prompt_token: 2.5e-7, + completion_token: 5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.2-3b-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.2-3b-instruct', + }, + cost: { + prompt_token: 1.8e-8, + completion_token: 3e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.2-1b-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.2-1b-instruct', + }, + cost: { + prompt_token: 1e-8, + completion_token: 2e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.2-90b-vision-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.2-90b-vision-instruct', + }, + cost: { + prompt_token: 9e-7, + completion_token: 9e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.2-11b-vision-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.2-11b-vision-instruct', + }, + cost: { + prompt_token: 5.5e-8, + completion_token: 5.5e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwen-2.5-72b-instruct', + }, + cost: { + prompt_token: 2.3e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwen-2-vl-72b-instruct', + }, + cost: { + prompt_token: 4e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'neversleep/llama-3.1-lumimaid-8b', + }, + cost: { + prompt_token: 1.875e-7, + completion_token: 1.125e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/o1-mini-2024-09-12', + }, + cost: { + prompt_token: 3e-6, + completion_token: 1.2e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/o1-preview', + }, + cost: { + prompt_token: 1.5e-5, + completion_token: 6e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/o1-preview-2024-09-12', + }, + cost: { + prompt_token: 1.5e-5, + completion_token: 6e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/o1-mini', + }, + cost: { + prompt_token: 3e-6, + completion_token: 1.2e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/pixtral-12b', + }, + cost: { + prompt_token: 1e-7, + completion_token: 1e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'cohere/command-r-08-2024', + }, + cost: { + prompt_token: 1.425e-7, + completion_token: 5.7e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'cohere/command-r-plus-08-2024', + }, + cost: { + prompt_token: 2.375e-6, + completion_token: 9.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwen-2-vl-7b-instruct', + }, + cost: { + prompt_token: 1e-7, + completion_token: 1e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-flash-1.5-exp', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'sao10k/l3.1-euryale-70b', + }, + cost: { + prompt_token: 3.5e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-flash-1.5-8b-exp', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'ai21/jamba-1-5-large', + }, + cost: { + prompt_token: 2e-6, + completion_token: 8e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'ai21/jamba-1-5-mini', + }, + cost: { + prompt_token: 2e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'microsoft/phi-3.5-mini-128k-instruct', + }, + cost: { + prompt_token: 1e-7, + completion_token: 1e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'nousresearch/hermes-3-llama-3.1-70b', + }, + cost: { + prompt_token: 2e-7, + completion_token: 2e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'nousresearch/hermes-3-llama-3.1-405b', + }, + cost: { + prompt_token: 9e-7, + completion_token: 9e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'perplexity/llama-3.1-sonar-huge-128k-online', + }, + cost: { + prompt_token: 5e-6, + completion_token: 5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/chatgpt-4o-latest', + }, + cost: { + prompt_token: 5e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'sao10k/l3-lunaris-8b', + }, + cost: { + prompt_token: 3e-8, + completion_token: 6e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'aetherwiing/mn-starcannon-12b', + }, + cost: { + prompt_token: 8e-7, + completion_token: 1.2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4o-2024-08-06', + }, + cost: { + prompt_token: 2.5e-6, + completion_token: 1e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-405b', + }, + cost: { + prompt_token: 2e-6, + completion_token: 2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'nothingiisreal/mn-celeste-12b', + }, + cost: { + prompt_token: 8e-7, + completion_token: 1.2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'perplexity/llama-3.1-sonar-small-128k-chat', + }, + cost: { + prompt_token: 2e-7, + completion_token: 2e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-pro-1.5-exp', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'perplexity/llama-3.1-sonar-large-128k-chat', + }, + cost: { + prompt_token: 1e-6, + completion_token: 1e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'perplexity/llama-3.1-sonar-large-128k-online', + }, + cost: { + prompt_token: 1e-6, + completion_token: 1e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'perplexity/llama-3.1-sonar-small-128k-online', + }, + cost: { + prompt_token: 2e-7, + completion_token: 2e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-405b-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-405b-instruct', + }, + cost: { + prompt_token: 9e-7, + completion_token: 9e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-405b-instruct:nitro', + }, + cost: { + prompt_token: 1.462e-5, + completion_token: 1.462e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-8b-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-8b-instruct', + }, + cost: { + prompt_token: 2e-8, + completion_token: 5e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-70b-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-70b-instruct', + }, + cost: { + prompt_token: 1.3e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3.1-70b-instruct:nitro', + }, + cost: { + prompt_token: 3.25e-6, + completion_token: 3.25e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-nemo', + }, + cost: { + prompt_token: 4e-8, + completion_token: 9e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/codestral-mamba', + }, + cost: { + prompt_token: 2.5e-7, + completion_token: 2.5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4o-mini', + }, + cost: { + prompt_token: 1.5e-7, + completion_token: 6e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4o-mini-2024-07-18', + }, + cost: { + prompt_token: 1.5e-7, + completion_token: 6e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwen-2-7b-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwen-2-7b-instruct', + }, + cost: { + prompt_token: 5.4e-8, + completion_token: 5.4e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemma-2-27b-it', + }, + cost: { + prompt_token: 2.7e-7, + completion_token: 2.7e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'alpindale/magnum-72b', + }, + cost: { + prompt_token: 1.875e-6, + completion_token: 2.25e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemma-2-9b-it:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemma-2-9b-it', + }, + cost: { + prompt_token: 3e-8, + completion_token: 6e-8, + }, + }, + { + model: { + operator: 'equals', + value: '01-ai/yi-large', + }, + cost: { + prompt_token: 3e-6, + completion_token: 3e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'ai21/jamba-instruct', + }, + cost: { + prompt_token: 5e-7, + completion_token: 7e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3.5-sonnet-20240620:beta', + }, + cost: { + prompt_token: 3e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3.5-sonnet-20240620', + }, + cost: { + prompt_token: 3e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'sao10k/l3-euryale-70b', + }, + cost: { + prompt_token: 3.5e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'cognitivecomputations/dolphin-mixtral-8x22b', + }, + cost: { + prompt_token: 9e-7, + completion_token: 9e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'qwen/qwen-2-72b-instruct', + }, + cost: { + prompt_token: 3.4e-7, + completion_token: 3.9e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-7b-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-7b-instruct', + }, + cost: { + prompt_token: 3e-8, + completion_token: 5.5e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-7b-instruct:nitro', + }, + cost: { + prompt_token: 7e-8, + completion_token: 7e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-7b-instruct-v0.3', + }, + cost: { + prompt_token: 3e-8, + completion_token: 5.5e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'nousresearch/hermes-2-pro-llama-3-8b', + }, + cost: { + prompt_token: 3e-8, + completion_token: 3e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'microsoft/phi-3-mini-128k-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'microsoft/phi-3-mini-128k-instruct', + }, + cost: { + prompt_token: 1e-7, + completion_token: 1e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'microsoft/phi-3-medium-128k-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'microsoft/phi-3-medium-128k-instruct', + }, + cost: { + prompt_token: 1e-6, + completion_token: 1e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'neversleep/llama-3-lumimaid-70b', + }, + cost: { + prompt_token: 3.375e-6, + completion_token: 4.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-flash-1.5', + }, + cost: { + prompt_token: 7.5e-8, + completion_token: 3e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'perplexity/llama-3-sonar-large-32k-online', + }, + cost: { + prompt_token: 1e-6, + completion_token: 1e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'deepseek/deepseek-chat', + }, + cost: { + prompt_token: 1.4e-7, + completion_token: 2.8e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'perplexity/llama-3-sonar-small-32k-chat', + }, + cost: { + prompt_token: 2e-7, + completion_token: 2e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'perplexity/llama-3-sonar-large-32k-chat', + }, + cost: { + prompt_token: 1e-6, + completion_token: 1e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4o-2024-05-13', + }, + cost: { + prompt_token: 5e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-guard-2-8b', + }, + cost: { + prompt_token: 1.8e-7, + completion_token: 1.8e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4o', + }, + cost: { + prompt_token: 2.5e-6, + completion_token: 1e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4o:extended', + }, + cost: { + prompt_token: 6e-6, + completion_token: 1.8e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'neversleep/llama-3-lumimaid-8b:extended', + }, + cost: { + prompt_token: 1.875e-7, + completion_token: 1.125e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'neversleep/llama-3-lumimaid-8b', + }, + cost: { + prompt_token: 1.875e-7, + completion_token: 1.125e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3-8b-instruct:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3-8b-instruct', + }, + cost: { + prompt_token: 3e-8, + completion_token: 6e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3-8b-instruct:extended', + }, + cost: { + prompt_token: 1.875e-7, + completion_token: 1.125e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3-8b-instruct:nitro', + }, + cost: { + prompt_token: 2e-7, + completion_token: 2e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3-70b-instruct', + }, + cost: { + prompt_token: 2.3e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-3-70b-instruct:nitro', + }, + cost: { + prompt_token: 7.92e-7, + completion_token: 7.92e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mixtral-8x22b-instruct', + }, + cost: { + prompt_token: 9e-7, + completion_token: 9e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'microsoft/wizardlm-2-8x22b', + }, + cost: { + prompt_token: 5e-7, + completion_token: 5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'microsoft/wizardlm-2-7b', + }, + cost: { + prompt_token: 5.5e-8, + completion_token: 5.5e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-pro-1.5', + }, + cost: { + prompt_token: 1.25e-6, + completion_token: 5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4-turbo', + }, + cost: { + prompt_token: 1e-5, + completion_token: 3e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'cohere/command-r-plus', + }, + cost: { + prompt_token: 2.85e-6, + completion_token: 1.425e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'cohere/command-r-plus-04-2024', + }, + cost: { + prompt_token: 2.85e-6, + completion_token: 1.425e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'databricks/dbrx-instruct', + }, + cost: { + prompt_token: 1.08e-6, + completion_token: 1.08e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'sophosympatheia/midnight-rose-70b', + }, + cost: { + prompt_token: 8e-7, + completion_token: 8e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'cohere/command', + }, + cost: { + prompt_token: 9.5e-7, + completion_token: 1.9e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'cohere/command-r', + }, + cost: { + prompt_token: 4.75e-7, + completion_token: 1.425e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3-haiku:beta', + }, + cost: { + prompt_token: 2.5e-7, + completion_token: 1.25e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3-haiku', + }, + cost: { + prompt_token: 2.5e-7, + completion_token: 1.25e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3-opus:beta', + }, + cost: { + prompt_token: 1.5e-5, + completion_token: 7.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3-opus', + }, + cost: { + prompt_token: 1.5e-5, + completion_token: 7.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3-sonnet:beta', + }, + cost: { + prompt_token: 3e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-3-sonnet', + }, + cost: { + prompt_token: 3e-6, + completion_token: 1.5e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'cohere/command-r-03-2024', + }, + cost: { + prompt_token: 4.75e-7, + completion_token: 1.425e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-large', + }, + cost: { + prompt_token: 2e-6, + completion_token: 6e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-3.5-turbo-0613', + }, + cost: { + prompt_token: 1e-6, + completion_token: 2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4-turbo-preview', + }, + cost: { + prompt_token: 1e-5, + completion_token: 3e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'nousresearch/nous-hermes-2-mixtral-8x7b-dpo', + }, + cost: { + prompt_token: 5.4e-7, + completion_token: 5.4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-small', + }, + cost: { + prompt_token: 2e-7, + completion_token: 6e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-tiny', + }, + cost: { + prompt_token: 2.5e-7, + completion_token: 2.5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-medium', + }, + cost: { + prompt_token: 2.75e-6, + completion_token: 8.1e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-7b-instruct-v0.2', + }, + cost: { + prompt_token: 1.8e-7, + completion_token: 1.8e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'cognitivecomputations/dolphin-mixtral-8x7b', + }, + cost: { + prompt_token: 5e-7, + completion_token: 5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-pro-vision', + }, + cost: { + prompt_token: 5e-7, + completion_token: 1.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'google/gemini-pro', + }, + cost: { + prompt_token: 5e-7, + completion_token: 1.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mixtral-8x7b', + }, + cost: { + prompt_token: 5.4e-7, + completion_token: 5.4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mixtral-8x7b-instruct', + }, + cost: { + prompt_token: 2.4e-7, + completion_token: 2.4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mixtral-8x7b-instruct:nitro', + }, + cost: { + prompt_token: 5.4e-7, + completion_token: 5.4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'openchat/openchat-7b:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'openchat/openchat-7b', + }, + cost: { + prompt_token: 5.5e-8, + completion_token: 5.5e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'neversleep/noromaid-20b', + }, + cost: { + prompt_token: 1.5e-6, + completion_token: 2.25e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-2:beta', + }, + cost: { + prompt_token: 8e-6, + completion_token: 2.4e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-2', + }, + cost: { + prompt_token: 8e-6, + completion_token: 2.4e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-2.1:beta', + }, + cost: { + prompt_token: 8e-6, + completion_token: 2.4e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-2.1', + }, + cost: { + prompt_token: 8e-6, + completion_token: 2.4e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'teknium/openhermes-2.5-mistral-7b', + }, + cost: { + prompt_token: 1.7e-7, + completion_token: 1.7e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4-vision-preview', + }, + cost: { + prompt_token: 1e-5, + completion_token: 3e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'lizpreciatior/lzlv-70b-fp16-hf', + }, + cost: { + prompt_token: 3.5e-7, + completion_token: 4e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'undi95/toppy-m-7b:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'undi95/toppy-m-7b:nitro', + }, + cost: { + prompt_token: 7e-8, + completion_token: 7e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'undi95/toppy-m-7b', + }, + cost: { + prompt_token: 7e-8, + completion_token: 7e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'alpindale/goliath-120b', + }, + cost: { + prompt_token: 9.375e-6, + completion_token: 9.375e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openrouter/auto', + }, + cost: { + prompt_token: -1.0, + completion_token: -1.0, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-3.5-turbo-1106', + }, + cost: { + prompt_token: 1e-6, + completion_token: 2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4-1106-preview', + }, + cost: { + prompt_token: 1e-5, + completion_token: 3e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'google/palm-2-chat-bison-32k', + }, + cost: { + prompt_token: 1e-6, + completion_token: 2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'google/palm-2-codechat-bison-32k', + }, + cost: { + prompt_token: 1e-6, + completion_token: 2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'jondurbin/airoboros-l2-70b', + }, + cost: { + prompt_token: 5e-7, + completion_token: 5e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'xwin-lm/xwin-lm-70b', + }, + cost: { + prompt_token: 3.75e-6, + completion_token: 3.75e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-3.5-turbo-instruct', + }, + cost: { + prompt_token: 1.5e-6, + completion_token: 2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'mistralai/mistral-7b-instruct-v0.1', + }, + cost: { + prompt_token: 1.8e-7, + completion_token: 1.8e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'pygmalionai/mythalion-13b', + }, + cost: { + prompt_token: 8e-7, + completion_token: 1.2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-3.5-turbo-16k', + }, + cost: { + prompt_token: 3e-6, + completion_token: 4e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4-32k', + }, + cost: { + prompt_token: 6e-5, + completion_token: 0.00012, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4-32k-0314', + }, + cost: { + prompt_token: 6e-5, + completion_token: 0.00012, + }, + }, + { + model: { + operator: 'equals', + value: 'nousresearch/nous-hermes-llama2-13b', + }, + cost: { + prompt_token: 1.7e-7, + completion_token: 1.7e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'mancer/weaver', + }, + cost: { + prompt_token: 1.5e-6, + completion_token: 2.25e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'huggingfaceh4/zephyr-7b-beta:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-2.0:beta', + }, + cost: { + prompt_token: 8e-6, + completion_token: 2.4e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'anthropic/claude-2.0', + }, + cost: { + prompt_token: 8e-6, + completion_token: 2.4e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'undi95/remm-slerp-l2-13b', + }, + cost: { + prompt_token: 8e-7, + completion_token: 1.2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'undi95/remm-slerp-l2-13b:extended', + }, + cost: { + prompt_token: 1.125e-6, + completion_token: 1.125e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'google/palm-2-chat-bison', + }, + cost: { + prompt_token: 1e-6, + completion_token: 2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'google/palm-2-codechat-bison', + }, + cost: { + prompt_token: 1e-6, + completion_token: 2e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'gryphe/mythomax-l2-13b:free', + }, + cost: { + prompt_token: 0.0, + completion_token: 0.0, + }, + }, + { + model: { + operator: 'equals', + value: 'gryphe/mythomax-l2-13b', + }, + cost: { + prompt_token: 7e-8, + completion_token: 7e-8, + }, + }, + { + model: { + operator: 'equals', + value: 'gryphe/mythomax-l2-13b:nitro', + }, + cost: { + prompt_token: 2e-7, + completion_token: 2e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'gryphe/mythomax-l2-13b:extended', + }, + cost: { + prompt_token: 1.125e-6, + completion_token: 1.125e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/llama-2-13b-chat', + }, + cost: { + prompt_token: 1.98e-7, + completion_token: 1.98e-7, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-3.5-turbo', + }, + cost: { + prompt_token: 5e-7, + completion_token: 1.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-3.5-turbo-0125', + }, + cost: { + prompt_token: 5e-7, + completion_token: 1.5e-6, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4', + }, + cost: { + prompt_token: 3e-5, + completion_token: 6e-5, + }, + }, + { + model: { + operator: 'equals', + value: 'openai/gpt-4-0314', + }, + cost: { + prompt_token: 3e-5, + completion_token: 6e-5, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/qstash/index.ts b/plugin-server/src/utils/ai-cost-data/qstash/index.ts new file mode 100644 index 00000000000000..8d78767c20e49a --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/qstash/index.ts @@ -0,0 +1,29 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'includes', + value: 'llama', + }, + cost: { + prompt_token: 3e-7, + completion_token: 3e-7, + }, + }, + { + model: { + operator: 'includes', + value: 'mistral', + }, + cost: { + prompt_token: 3e-7, + completion_token: 3e-7, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/togetherai/chat/index.ts b/plugin-server/src/utils/ai-cost-data/togetherai/chat/index.ts new file mode 100644 index 00000000000000..1da29272e33d88 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/togetherai/chat/index.ts @@ -0,0 +1,503 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'allenai/OLMo-7B-Instruct', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'allenai/OLMo-7B-Twin-2T', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'allenai/OLMo-7B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'Austism/chronos-hermes-13b', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'deepseek-ai/deepseek-coder-33b-instruct', + }, + cost: { + prompt_token: 0.0000008, + completion_token: 0.0000008, + }, + }, + + { + model: { + operator: 'equals', + value: 'garage-bAInd/Platypus2-70B-instruct', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'google/gemma-2b-it', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'google/gemma-7b-it', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'Gryphe/MythoMax-L2-13b', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'lmsys/vicuna-13b-v1.5', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'lmsys/vicuna-7b-v1.5', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'mistralai/Mistral-7B-Instruct-v0.1', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'mistralai/Mistral-7B-Instruct-v0.2', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'mistralai/Mixtral-8x7B-Instruct-v0.1', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'NousResearch/Nous-Capybara-7B-V1p9', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'NousResearch/Nous-Hermes-2-Mixtral-8x7B-SFT', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'NousResearch/Nous-Hermes-2-Yi-34B', + }, + cost: { + prompt_token: 0.0000008, + completion_token: 0.0000008, + }, + }, + + { + model: { + operator: 'equals', + value: 'openchat/openchat-3.5-1210', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'Open-Orca/Mistral-7B-OpenOrca', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-0.5B-Chat', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-1.8B-Chat', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-4B-Chat', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-7B-Chat', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-14B-Chat', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'snorkelai/Snorkel-Mistral-PairRM-DPO', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/alpaca-7b', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'teknium/OpenHermes-2-Mistral-7B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'teknium/OpenHermes-2p5-Mistral-7B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/RedPajama-INCITE-Chat-3B-v1', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/RedPajama-INCITE-7B-Chat', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/StripedHyena-Nous-7B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'Undi95/ReMM-SLERP-L2-13B', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'Undi95/Toppy-M-7B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'WizardLM/WizardLM-13B-V1.2', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'upstage/SOLAR-10.7B-Instruct-v1.0', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000018, + completion_token: 0.00000018, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000088, + completion_token: 0.00000088, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.0000035, + completion_token: 0.0000035, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-8B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000018, + completion_token: 0.00000018, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-70B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000088, + completion_token: 0.00000088, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-8B-Instruct-Lite', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-70B-Instruct-Lite', + }, + cost: { + prompt_token: 0.00000054, + completion_token: 0.00000054, + }, + }, + + { + model: { + operator: 'equals', + value: 'microsoft/WizardLM-2-8x22B', + }, + cost: { + prompt_token: 0.0000012, + completion_token: 0.0000012, + }, + }, + + { + model: { + operator: 'equals', + value: 'mistralai/Mixtral-8x22B-Instruct-v0.1', + }, + cost: { + prompt_token: 0.0000024, + completion_token: 0.0000024, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/togetherai/chat/llama.ts b/plugin-server/src/utils/ai-cost-data/togetherai/chat/llama.ts new file mode 100644 index 00000000000000..ea27590629c419 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/togetherai/chat/llama.ts @@ -0,0 +1,210 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'codellama/CodeLlama-13b-Instruct-hf', + }, + cost: { + prompt_token: 0.000000225, + completion_token: 0.000000225, + }, + }, + + { + model: { + operator: 'equals', + value: 'codellama/CodeLlama-34b-Instruct-hf', + }, + cost: { + prompt_token: 0.000000776, + completion_token: 0.000000776, + }, + }, + + { + model: { + operator: 'equals', + value: 'codellama/CodeLlama-70b-Instruct-hf', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'codellama/CodeLlama-7b-Instruct-hf', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-2-70b-chat-hf', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-2-13b-chat-hf', + }, + cost: { + prompt_token: 0.000000225, + completion_token: 0.000000225, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-2-7b-chat-hf', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-3-70b-chat-hf', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-3-8b-chat-hf', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'NousResearch/Nous-Hermes-llama-2-7b', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'NousResearch/Nous-Hermes-Llama2-13b', + }, + cost: { + prompt_token: 0.000000225, + completion_token: 0.000000225, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/Llama-2-7B-32K-Instruct', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000088, + completion_token: 0.00000088, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000018, + completion_token: 0.00000018, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.000005, + completion_token: 0.000005, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-70B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000088, + completion_token: 0.00000088, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-8B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000018, + completion_token: 0.00000018, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-70B-Instruct-Lite', + }, + cost: { + prompt_token: 0.00000054, + completion_token: 0.00000054, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-8B-Instruct-Lite', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/togetherai/completion/index.ts b/plugin-server/src/utils/ai-cost-data/togetherai/completion/index.ts new file mode 100644 index 00000000000000..8ca03a8fa40c63 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/togetherai/completion/index.ts @@ -0,0 +1,228 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'zero-one-ai/Yi-34B', + }, + cost: { + prompt_token: 0.0000008, + completion_token: 0.0000008, + }, + }, + + { + model: { + operator: 'equals', + value: 'zero-one-ai/Yi-6B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'google/gemma-2b', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'google/gemma-7b', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'microsoft/phi-2', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'Nexusflow/NexusRaven-V2-13B', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-0.5B', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-1.8B', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-4B', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-7B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-14B', + }, + cost: { + prompt_token: 0.0000003, + completion_token: 0.0000003, + }, + }, + + { + model: { + operator: 'equals', + value: 'Qwen/Qwen1.5-72B', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/GPT-JT-Moderation-6B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/RedPajama-INCITE-Base-3B-v1', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/RedPajama-INCITE-7B-Base', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/RedPajama-INCITE-Instruct-3B-v1', + }, + cost: { + prompt_token: 0.0000001, + completion_token: 0.0000001, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/RedPajama-INCITE-7B-Instruct', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/StripedHyena-Hessian-7B', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'mistralai/Mistral-7B-v0.1', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'mistralai/Mixtral-8x7B-v0.1', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, +] diff --git a/plugin-server/src/utils/ai-cost-data/togetherai/completion/llama.ts b/plugin-server/src/utils/ai-cost-data/togetherai/completion/llama.ts new file mode 100644 index 00000000000000..1df44bd2de8650 --- /dev/null +++ b/plugin-server/src/utils/ai-cost-data/togetherai/completion/llama.ts @@ -0,0 +1,134 @@ +/** + * + * DO NOT EDIT THIS FILE UNLESS IT IS IN /costs + */ + +import { ModelRow } from '../../../../types' + +export const costs: ModelRow[] = [ + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-2-70b-hf', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-2-13b-hf', + }, + cost: { + prompt_token: 0.000000225, + completion_token: 0.000000225, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-2-7b-hf', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3-70B', + }, + cost: { + prompt_token: 0.0000009, + completion_token: 0.0000009, + }, + }, + + { + model: { + operator: 'equals', + value: 'meta-llama/Llama-3-8b-hf', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + + { + model: { + operator: 'equals', + value: 'togethercomputer/LLaMA-2-7B-32K', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.0000002, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000088, + completion_token: 0.00000088, + }, + }, + { + model: { + operator: 'equals', + value: 'meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.000005, + completion_token: 0.000005, + }, + }, + { + model: { + operator: 'includes', + value: 'togethercomputer/Meta-Llama-3.1-8B-Instruct-Reference', + }, + cost: { + prompt_token: 0.0000002, + completion_token: 0.00000018, + }, + }, + { + model: { + operator: 'includes', + value: 'togethercomputer/Meta-Llama-3.1-70B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.00000088, + completion_token: 0.00000088, + }, + }, + { + model: { + operator: 'includes', + value: 'togethercomputer/Meta-Llama-3.1-405B-Instruct-Turbo', + }, + cost: { + prompt_token: 0.000005, + completion_token: 0.000005, + }, + }, +] diff --git a/plugin-server/src/worker/ingestion/event-pipeline/prepareEventStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/prepareEventStep.ts index 6725bbf3456616..e9280adf69f640 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/prepareEventStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/prepareEventStep.ts @@ -1,9 +1,12 @@ import { PluginEvent } from '@posthog/plugin-scaffold' +import { captureException } from '@sentry/node' import { PreIngestionEvent } from 'types' +import { status } from '../../../utils/status' import { parseEventTimestamp } from '../timestamps' import { captureIngestionWarning } from '../utils' import { invalidTimestampCounter } from './metrics' +import { processAiEvent } from './processAiEvent' import { EventPipelineRunner } from './runner' export async function prepareEventStep( @@ -19,6 +22,17 @@ export async function prepareEventStep( tsParsingIngestionWarnings.push(captureIngestionWarning(runner.hub.db.kafkaProducer, team_id, type, details)) } + if (event.event === '$ai_generation' || event.event === '$ai_embedding') { + try { + event = processAiEvent(event) + } catch (error) { + // NOTE: Whilst this is pre-production we want to make it as optional as possible + // so we don't block the pipeline if it fails + captureException(error) + status.error(error) + } + } + const preIngestionEvent = await runner.eventsProcessor.processEvent( String(event.distinct_id), event, diff --git a/plugin-server/src/worker/ingestion/event-pipeline/processAiEvent.ts b/plugin-server/src/worker/ingestion/event-pipeline/processAiEvent.ts new file mode 100644 index 00000000000000..226b7eb45bf88b --- /dev/null +++ b/plugin-server/src/worker/ingestion/event-pipeline/processAiEvent.ts @@ -0,0 +1,103 @@ +import { PluginEvent } from '@posthog/plugin-scaffold' +import bigDecimal from 'js-big-decimal' + +import { ModelRow } from '../../../types' +import { providers } from '../../../utils/ai-cost-data/mappings' + +export const processAiEvent = (event: PluginEvent): PluginEvent => { + if ((event.event !== '$ai_generation' && event.event !== '$ai_embedding') || !event.properties) { + return event + } + event = processCost(event) + event = extractCoreModelParams(event) + return event +} + +const processCost = (event: PluginEvent) => { + if (!event.properties || !event.properties['$ai_provider'] || !event.properties['$ai_model']) { + return event + } + + const provider = providers.find((provider) => event?.properties?.$ai_provider === provider.provider.toLowerCase()) + if (!provider || !provider.costs) { + return event + } + + const cost = findCostFromModel(provider.costs, event.properties['$ai_model']) + if (!cost) { + return event + } + + event.properties['$ai_input_cost_usd'] = parseFloat( + bigDecimal.multiply(cost.cost.prompt_token, event.properties['$ai_input_tokens'] || 0) + ) + event.properties['$ai_output_cost_usd'] = parseFloat( + bigDecimal.multiply(cost.cost.completion_token, event.properties['$ai_output_tokens'] || 0) + ) + + event.properties['$ai_total_cost_usd'] = parseFloat( + bigDecimal.add(event.properties['$ai_input_cost_usd'], event.properties['$ai_output_cost_usd']) + ) + + return event +} + +export const extractCoreModelParams = (event: PluginEvent): PluginEvent => { + if (!event.properties || !event.properties['$ai_provider'] || !event.properties['$ai_model']) { + return event + } + const provider = event.properties['$ai_provider'].toLowerCase() + + const params = event.properties['$ai_model_parameters'] + + if (!params) { + return event + } + + if (provider === 'anthropic') { + if (params.temperature !== undefined) { + event.properties.$ai_temperature = params.temperature + } + if (params.max_tokens !== undefined) { + event.properties.$ai_max_tokens = params.max_tokens + } + if (params.stream !== undefined) { + event.properties.$ai_stream = params.stream + } + } else if (provider === 'openai') { + if (params.temperature !== undefined) { + event.properties.$ai_temperature = params.temperature + } + if (params.max_completion_tokens !== undefined) { + event.properties.$ai_max_tokens = params.max_completion_tokens + } + if (params.stream !== undefined) { + event.properties.$ai_stream = params.stream + } + } else { + // Default to openai-like params + if (params.temperature !== undefined) { + event.properties.$ai_temperature = params.temperature + } + if (params.max_completion_tokens !== undefined) { + event.properties.$ai_max_tokens = params.max_completion_tokens + } + if (params.stream !== undefined) { + event.properties.$ai_stream = params.stream + } + } + + return event +} + +const findCostFromModel = (costs: ModelRow[], aiModel: string): ModelRow | undefined => { + return costs.find((cost) => { + const valueLower = cost.model.value.toLowerCase() + if (cost.model.operator === 'startsWith') { + return aiModel.startsWith(valueLower) + } else if (cost.model.operator === 'includes') { + return aiModel.includes(valueLower) + } + return valueLower === aiModel + }) +} diff --git a/plugin-server/tests/worker/ingestion/process-ai-event.test.ts b/plugin-server/tests/worker/ingestion/process-ai-event.test.ts new file mode 100644 index 00000000000000..3f51a27314d6c9 --- /dev/null +++ b/plugin-server/tests/worker/ingestion/process-ai-event.test.ts @@ -0,0 +1,149 @@ +import { PluginEvent } from '@posthog/plugin-scaffold' + +import { processAiEvent } from '../../../src/worker/ingestion/event-pipeline/processAiEvent' + +describe('processAiEvent()', () => { + let event: PluginEvent + + beforeEach(() => { + event = { + distinct_id: 'test_id', + team_id: 1, + uuid: 'test-uuid', + timestamp: '2024-01-01T00:00:00.000Z', + event: '$ai_generation', + properties: { + $ai_model: 'gpt-4', + $ai_provider: 'openai', + $ai_input_tokens: 100, + $ai_output_tokens: 50, + }, + ip: '127.0.0.1', + site_url: 'https://test.com', + now: '2024-01-01T00:00:00.000Z', + } as PluginEvent + }) + + describe('event matching', () => { + it('matches $ai_generation events', () => { + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeDefined() + expect(result.properties.$ai_input_cost_usd).toBeDefined() + expect(result.properties.$ai_output_cost_usd).toBeDefined() + }) + + it('matches $ai_embedding events', () => { + event.event = '$ai_embedding' + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeDefined() + expect(result.properties.$ai_input_cost_usd).toBeDefined() + expect(result.properties.$ai_output_cost_usd).toBeDefined() + }) + + it('does not match other events', () => { + event.event = '$other_event' + const result = processAiEvent(event) + expect(result).toEqual(event) + }) + }) + + describe('model matching', () => { + it('matches exact model names', () => { + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeDefined() + expect(result.properties.$ai_input_cost_usd).toBeDefined() + expect(result.properties.$ai_output_cost_usd).toBeDefined() + }) + + it('matches model variants', () => { + event.properties.$ai_model = 'gpt-4-turbo-0125-preview' + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeDefined() + expect(result.properties.$ai_input_cost_usd).toBeDefined() + expect(result.properties.$ai_output_cost_usd).toBeDefined() + }) + + it('handles unknown models', () => { + event.properties.$ai_model = 'unknown-model' + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeUndefined() + expect(result.properties.$ai_input_cost_usd).toBeUndefined() + expect(result.properties.$ai_output_cost_usd).toBeUndefined() + }) + }) + + describe('cost calculation', () => { + it('calculates correct cost for prompt and completion tokens', () => { + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeGreaterThan(0) + }) + + it('handles missing token counts', () => { + delete event.properties.$ai_input_tokens + delete event.properties.$ai_output_tokens + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBe(0) + expect(result.properties.$ai_input_cost_usd).toBe(0) + expect(result.properties.$ai_output_cost_usd).toBe(0) + }) + + it('handles zero token counts', () => { + event.properties.$ai_input_tokens = 0 + event.properties.$ai_output_tokens = 0 + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBe(0) + expect(result.properties.$ai_input_cost_usd).toBe(0) + expect(result.properties.$ai_output_cost_usd).toBe(0) + }) + }) + + describe('provider handling', () => { + it('processes OpenAI events', () => { + event.properties.$ai_provider = 'openai' + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeDefined() + expect(result.properties.$ai_input_cost_usd).toBeDefined() + expect(result.properties.$ai_output_cost_usd).toBeDefined() + }) + + it('processes Anthropic events', () => { + event.properties.$ai_provider = 'anthropic' + event.properties.$ai_model = 'claude-2' + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeDefined() + expect(result.properties.$ai_input_cost_usd).toBeDefined() + expect(result.properties.$ai_output_cost_usd).toBeDefined() + }) + }) + + describe('model parameters', () => { + it('dont extract core model parameters if not present', () => { + const result = processAiEvent(event) + expect(result.properties.$ai_temperature).toBeUndefined() + expect(result.properties.$ai_max_tokens).toBeUndefined() + expect(result.properties.$ai_stream).toBeUndefined() + }) + + it('extracts core model parameters if present', () => { + event.properties.$ai_model_parameters = { + temperature: 0.5, + max_completion_tokens: 100, + stream: false, + } + const result = processAiEvent(event) + expect(result.properties.$ai_temperature).toBe(0.5) + expect(result.properties.$ai_max_tokens).toBe(100) + expect(result.properties.$ai_stream).toBe(false) + }) + }) + + describe('error handling', () => { + it('handles missing required properties', () => { + delete event.properties.$ai_model + const result = processAiEvent(event) + expect(result.properties.$ai_total_cost_usd).toBeUndefined() + expect(result.properties.$ai_input_cost_usd).toBeUndefined() + expect(result.properties.$ai_output_cost_usd).toBeUndefined() + }) + }) +}) From b3f06db1d6d3146c6bc0c2cf49fbbf17744e9bd0 Mon Sep 17 00:00:00 2001 From: Joshua Snyder Date: Tue, 21 Jan 2025 08:45:37 +0000 Subject: [PATCH 11/11] feat: standardize cross selling events (#27483) --- .../TaxonomicFilterEmptyState.tsx | 18 +++++++++++++++-- frontend/src/lib/utils/cross-sell.ts | 20 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 frontend/src/lib/utils/cross-sell.ts diff --git a/frontend/src/lib/components/TaxonomicFilter/TaxonomicFilterEmptyState.tsx b/frontend/src/lib/components/TaxonomicFilter/TaxonomicFilterEmptyState.tsx index c13f378c25d848..54a45180dded1d 100644 --- a/frontend/src/lib/components/TaxonomicFilter/TaxonomicFilterEmptyState.tsx +++ b/frontend/src/lib/components/TaxonomicFilter/TaxonomicFilterEmptyState.tsx @@ -1,10 +1,13 @@ import { IconOpenSidebar, IconPlus } from '@posthog/icons' import { LemonButton } from '@posthog/lemon-ui' +import { useActions } from 'kea' +import { router } from 'kea-router' import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types' +import { ProductCrossSellLocation, trackProductCrossSell } from 'lib/utils/cross-sell' import type React from 'react' import { urls } from 'scenes/urls' -import { PipelineStage } from '~/types' +import { PipelineStage, ProductKey } from '~/types' import { BuilderHog3 } from '../hedgehogs' @@ -21,6 +24,8 @@ type EmptyStateProps = { } const EmptyState = ({ title, description, action, docsUrl, hog: Hog, groupType }: EmptyStateProps): JSX.Element => { + const { push } = useActions(router) + return (
@@ -33,7 +38,16 @@ const EmptyState = ({ title, description, action, docsUrl, hog: Hog, groupType } } - to={action.to} + onClick={() => { + trackProductCrossSell({ + from: ProductKey.PRODUCT_ANALYTICS, + to: ProductKey.DATA_WAREHOUSE, + location: ProductCrossSellLocation.TAXONOMIC_FILTER_EMPTY_STATE, + context: {}, + }) + + push(action.to) + }} data-attr={`taxonomic-filter-empty-state-${groupType}-new-button`} > {action.text} diff --git a/frontend/src/lib/utils/cross-sell.ts b/frontend/src/lib/utils/cross-sell.ts new file mode 100644 index 00000000000000..1687390465fe51 --- /dev/null +++ b/frontend/src/lib/utils/cross-sell.ts @@ -0,0 +1,20 @@ +import posthog from 'posthog-js' + +import type { ProductKey } from '~/types' + +export type ProductCrossSellContext = Record + +export enum ProductCrossSellLocation { + TAXONOMIC_FILTER_EMPTY_STATE = 'taxonomic_filter_empty_state', +} + +export type ProductCrossSellProperties = { + from: ProductKey + to: ProductKey + location: ProductCrossSellLocation + context?: ProductCrossSellContext +} + +export function trackProductCrossSell(properties: ProductCrossSellProperties): void { + posthog.capture('product cross sell interaction', properties) +}