From 55b9741aa1a8442164c705bff904413bdec3fe7b Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Wed, 8 Apr 2026 12:09:36 +0300 Subject: [PATCH 1/9] docs(llma): migrate onboarding docs to OpenTelemetry auto-instrumentation Replace PostHog SDK wrapper approach with standard OpenTelemetry auto-instrumentation across 22 provider onboarding guides. Each doc now follows a 3-step pattern: install OTel deps, set up tracing, call the provider with the native SDK. --- docs/onboarding/llm-analytics/anthropic.tsx | 180 +++++++--------- .../onboarding/llm-analytics/azure-openai.tsx | 162 +++++++------- docs/onboarding/llm-analytics/cerebras.tsx | 190 +++++++--------- docs/onboarding/llm-analytics/cohere.tsx | 194 +++++++---------- docs/onboarding/llm-analytics/deepseek.tsx | 194 +++++++---------- .../onboarding/llm-analytics/fireworks-ai.tsx | 194 +++++++---------- docs/onboarding/llm-analytics/groq.tsx | 193 +++++++---------- docs/onboarding/llm-analytics/helicone.tsx | 192 +++++++---------- .../onboarding/llm-analytics/hugging-face.tsx | 190 +++++++--------- docs/onboarding/llm-analytics/langchain.tsx | 178 ++++++--------- docs/onboarding/llm-analytics/langgraph.tsx | 142 +++++------- docs/onboarding/llm-analytics/llamaindex.tsx | 87 +++----- docs/onboarding/llm-analytics/mistral.tsx | 194 +++++++---------- docs/onboarding/llm-analytics/ollama.tsx | 196 +++++++---------- docs/onboarding/llm-analytics/openai.tsx | 194 +++++++---------- docs/onboarding/llm-analytics/openrouter.tsx | 203 +++++++----------- docs/onboarding/llm-analytics/perplexity.tsx | 190 +++++++--------- docs/onboarding/llm-analytics/portkey.tsx | 194 +++++++---------- docs/onboarding/llm-analytics/together-ai.tsx | 190 +++++++--------- .../llm-analytics/vercel-ai-gateway.tsx | 191 +++++++--------- docs/onboarding/llm-analytics/vercel-ai.tsx | 17 +- docs/onboarding/llm-analytics/xai.tsx | 194 +++++++---------- 22 files changed, 1603 insertions(+), 2256 deletions(-) diff --git a/docs/onboarding/llm-analytics/anthropic.tsx b/docs/onboarding/llm-analytics/anthropic.tsx index a7006309715e..329647a220e9 100644 --- a/docs/onboarding/llm-analytics/anthropic.tsx +++ b/docs/onboarding/llm-analytics/anthropic.tsx @@ -9,13 +9,12 @@ export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinit return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. + Install the OpenTelemetry SDK, the Anthropic instrumentation, and the Anthropic SDK. - - ), - }, - { - title: 'Install the Anthropic SDK', - badge: 'required', - content: ( - <> - - Install the Anthropic SDK. The PostHog SDK instruments your LLM calls by wrapping the Anthropic - client. The PostHog SDK **does not** proxy your calls. - - - - + - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. ), }, { - title: 'Initialize PostHog and the Anthropic wrapper', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then pass it to our Anthropic wrapper. + Configure OpenTelemetry to auto-instrument Anthropic SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = Anthropic( - api_key="sk-ant-api...", # Replace with your Anthropic API key - posthog_client=posthog # This is an optional parameter. If it is not provided, a default client will be used. - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + AnthropicInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { Anthropic } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ) - - const client = new Anthropic({ - apiKey: 'sk-ant-api...', // Replace with your Anthropic API key - posthog: phClient + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { AnthropicInstrumentation } from '@traceloop/instrumentation-anthropic' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new AnthropicInstrumentation()], }) + sdk.start() `, }, ]} /> - -
- - **Note:** This also works with the `AsyncAnthropic` client as well as `AnthropicBedrock`, - `AnthropicVertex`, and the async versions of those. - -
), }, { - title: 'Call Anthropic LLMs', + title: 'Call Anthropic', badge: 'required', content: ( <> - Now, when you use the Anthropic SDK to call LLMs, PostHog automatically captures an - `$ai_generation` event. You can enrich the event with additional data such as the trace ID, - distinct ID, custom properties, groups, and privacy mode options. + Now, when you use the Anthropic SDK to call LLMs, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. - {dedent` - **Notes:** - - This also works when message streams are used (e.g. \`stream=True\` or \`client.messages.stream(...)\`). - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. + **Note:** This also works with the `AsyncAnthropic` client as well as `AnthropicBedrock`, + `AnthropicVertex`, and the async versions of those. + + - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} +
+ + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/azure-openai.tsx b/docs/onboarding/llm-analytics/azure-openai.tsx index 44cff9902d53..b62af8e02e65 100644 --- a/docs/onboarding/llm-analytics/azure-openai.tsx +++ b/docs/onboarding/llm-analytics/azure-openai.tsx @@ -9,11 +9,11 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin return [ { - title: 'Install the SDKs', + title: 'Install dependencies', badge: 'required', content: ( <> - Setting up analytics starts with installing the PostHog and OpenAI SDKs. + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. + + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and Azure OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Azure OpenAI through PostHog's AzureOpenAI wrapper to capture all the details of the - call. Initialize PostHog with your PostHog project token and host from [your project - settings](https://app.posthog.com/settings/project), then pass the PostHog client along with - your Azure OpenAI config (the API key, API version, and endpoint) to our AzureOpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = AzureOpenAI( - api_key="", - api_version="2024-10-21", - azure_endpoint="https://.openai.azure.com", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { AzureOpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const client = new AzureOpenAI({ - apiKey: '', - apiVersion: '2024-10-21', - endpoint: 'https://.openai.azure.com', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncAzureOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -120,9 +121,8 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin content: ( <> - Now, when you call Azure OpenAI, PostHog automatically captures an `$ai_generation` event. You - can also capture or modify additional properties with the distinct ID, trace ID, properties, - groups, and privacy mode parameters. + Now, when you call Azure OpenAI, PostHog automatically captures `$ai_generation` events via the + OpenTelemetry instrumentation. ", - messages: [{ role: "user", content: "Tell me a fun fact about hedgehogs" }], - posthogDistinctId: "user_123", // optional - posthogTraceId: "trace_123", // optional - posthogProperties: { conversation_id: "abc123", paid: true }, // optional - posthogGroups: { company: "company_id_in_your_db" }, // optional - posthogPrivacyMode: false // optional - }); - - console.log(completion.choices[0].message.content) + import { AzureOpenAI } from 'openai' + + const client = new AzureOpenAI({ + apiKey: '', + apiVersion: '2024-10-21', + endpoint: 'https://.openai.azure.com', + }) + + const response = await client.chat.completions.create({ + model: '', + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -168,13 +174,9 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin
- {dedent` - **Notes:** - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/cerebras.tsx b/docs/onboarding/llm-analytics/cerebras.tsx index 24e595c20c32..cd3cdff48879 100644 --- a/docs/onboarding/llm-analytics/cerebras.tsx +++ b/docs/onboarding/llm-analytics/cerebras.tsx @@ -9,14 +9,11 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Cerebras through the OpenAI client and generate a response. We'll use PostHog's OpenAI - provider to capture all the details of the call. Initialize PostHog with your PostHog project - token and host from [your project settings](https://app.posthog.com/settings/project), then pass - the PostHog client along with the Cerebras config (the base URL and API key) to our OpenAI - wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.cerebras.ai/v1", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.cerebras.ai/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti content: ( <> - Now, when you call Cerebras with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Cerebras, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'llama-3.3-70b', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -202,12 +175,7 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti
{dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/cohere.tsx b/docs/onboarding/llm-analytics/cohere.tsx index 29ba9e973bea..91f463e5a8a7 100644 --- a/docs/onboarding/llm-analytics/cohere.tsx +++ b/docs/onboarding/llm-analytics/cohere.tsx @@ -9,14 +9,11 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Cohere through the OpenAI-compatible API and generate a response. We'll use PostHog's - OpenAI provider to capture all the details of the call. Initialize PostHog with your PostHog - project token and host from [your project settings](https://app.posthog.com/settings/project), - then pass the PostHog client along with the Cohere config (the base URL and API key) to our - OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.cohere.ai/compatibility/v1", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.cohere.ai/compatibility/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition content: ( <> - Now, when you call Cohere with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Cohere, PostHog automatically captures `$ai_generation` + events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'command-a-03-2025', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -201,14 +174,9 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition
- {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/deepseek.tsx b/docs/onboarding/llm-analytics/deepseek.tsx index d7f8d3af0aba..7cf01aa64fc8 100644 --- a/docs/onboarding/llm-analytics/deepseek.tsx +++ b/docs/onboarding/llm-analytics/deepseek.tsx @@ -9,14 +9,11 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call DeepSeek through the OpenAI client and generate a response. We'll use PostHog's OpenAI - provider to capture all the details of the call. Initialize PostHog with your PostHog project - token and host from [your project settings](https://app.posthog.com/settings/project), then pass - the PostHog client along with the DeepSeek config (the base URL and API key) to our OpenAI - wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.deepseek.com", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.deepseek.com', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti content: ( <> - Now, when you call DeepSeek with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call DeepSeek, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'deepseek-chat', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -201,14 +174,9 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti
- {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/fireworks-ai.tsx b/docs/onboarding/llm-analytics/fireworks-ai.tsx index 4c68e36cfd95..40140b6e181c 100644 --- a/docs/onboarding/llm-analytics/fireworks-ai.tsx +++ b/docs/onboarding/llm-analytics/fireworks-ai.tsx @@ -9,14 +9,11 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Fireworks AI through the OpenAI client and generate a response. We'll use PostHog's - OpenAI provider to capture all the details of the call. Initialize PostHog with your PostHog - project token and host from [your project settings](https://app.posthog.com/settings/project), - then pass the PostHog client along with the Fireworks AI config (the base URL and API key) to - our OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.fireworks.ai/inference/v1", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.fireworks.ai/inference/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin content: ( <> - Now, when you call Fireworks AI with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Fireworks AI, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'accounts/fireworks/models/llama-v3p3-70b-instruct', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -201,14 +174,9 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin
- {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/groq.tsx b/docs/onboarding/llm-analytics/groq.tsx index 43cf630c8512..f917b5f22cb8 100644 --- a/docs/onboarding/llm-analytics/groq.tsx +++ b/docs/onboarding/llm-analytics/groq.tsx @@ -9,14 +9,11 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[] return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Groq through the OpenAI client and generate a response. We'll use PostHog's OpenAI - provider to capture all the details of the call. Initialize PostHog with your PostHog project - token and host from [your project settings](https://app.posthog.com/settings/project), then pass - the PostHog client along with the Groq config (the base URL and API key) to our OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.groq.com/openai/v1", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.groq.com/openai/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -152,9 +121,8 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[] content: ( <> - Now, when you call Groq with the OpenAI SDK, PostHog automatically captures an `$ai_generation` - event. You can also capture or modify additional properties with the distinct ID, trace ID, - properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Groq, PostHog automatically captures `$ai_generation` + events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'llama-3.3-70b-versatile', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -200,14 +174,9 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[]
- {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/helicone.tsx b/docs/onboarding/llm-analytics/helicone.tsx index 65e9cf3e016c..c56d9d1e0e24 100644 --- a/docs/onboarding/llm-analytics/helicone.tsx +++ b/docs/onboarding/llm-analytics/helicone.tsx @@ -9,7 +9,7 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> @@ -21,10 +21,7 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti
- - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Helicone through the OpenAI client and generate a response. We'll use PostHog's OpenAI - provider to capture all the details of the call. Initialize PostHog with your PostHog project - token and host from [your project settings](https://app.posthog.com/settings/project), then pass - the PostHog client along with the Helicone config (the base URL and API key) to our OpenAI - wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://ai-gateway.helicone.ai/", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://ai-gateway.helicone.ai/', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -161,9 +129,8 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti content: ( <> - Now, when you call Helicone with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you call Helicone with the OpenAI SDK, PostHog automatically captures `$ai_generation` + events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'gpt-5-mini', + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -209,14 +180,9 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti
- {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/hugging-face.tsx b/docs/onboarding/llm-analytics/hugging-face.tsx index 6eb0146b3c24..7454a61fa631 100644 --- a/docs/onboarding/llm-analytics/hugging-face.tsx +++ b/docs/onboarding/llm-analytics/hugging-face.tsx @@ -9,14 +9,11 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Hugging Face Inference API through the OpenAI-compatible endpoint and generate a - response. We'll use PostHog's OpenAI provider to capture all the details of the call. Initialize - PostHog with your PostHog project token and host from [your project - settings](https://app.posthog.com/settings/project), then pass the PostHog client along with the - Hugging Face config (the base URL and API key) to our OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://router.huggingface.co/v1/", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://router.huggingface.co/v1/', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin content: ( <> - Now, when you call Hugging Face with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Hugging Face, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'meta-llama/Llama-3.3-70B-Instruct', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -202,12 +175,7 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin
{dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/langchain.tsx b/docs/onboarding/llm-analytics/langchain.tsx index 56a3125cd28c..3b86936efa5f 100644 --- a/docs/onboarding/llm-analytics/langchain.tsx +++ b/docs/onboarding/llm-analytics/langchain.tsx @@ -3,19 +3,18 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. + Install the OpenTelemetry SDK, the LangChain instrumentation, and LangChain with OpenAI. - - ), - }, - { - title: 'Install LangChain and OpenAI SDKs', - badge: 'required', - content: ( - <> - - Install LangChain. The PostHog SDK instruments your LLM calls by wrapping LangChain. The PostHog - SDK **does not** proxy your calls. - - - - + - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. ), }, { - title: 'Initialize PostHog and LangChain', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then pass it to the LangChain - `CallbackHandler` wrapper. Optionally, you can provide a user distinct ID, trace ID, PostHog - properties, [groups](https://posthog.com/docs/product-analytics/group-analytics), and privacy - mode. + Configure OpenTelemetry to auto-instrument LangChain calls and export traces to PostHog. PostHog + converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.langchain import LangchainInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - callback_handler = CallbackHandler( - client=posthog, # This is an optional parameter. If it is not provided, a default client will be used. - distinct_id="user_123", # optional - trace_id="trace_456", # optional - properties={"conversation_id": "abc123"}, # optional - groups={"company": "company_id_in_your_db"}, # optional - privacy_mode=False # optional - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + LangchainInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { PostHog } from 'posthog-node'; - import { LangChainCallbackHandler } from '@posthog/ai'; - import { ChatOpenAI } from '@langchain/openai'; - import { ChatPromptTemplate } from '@langchain/core/prompts'; - - const phClient = new PostHog( - '', - { host: '' } - ); - - const callbackHandler = new LangChainCallbackHandler({ - client: phClient, - distinctId: 'user_123', // optional - traceId: 'trace_456', // optional - properties: { conversationId: 'abc123' }, // optional - groups: { company: 'company_id_in_your_db' }, // optional - privacyMode: false, // optional - debug: false // optional - when true, logs all events to console - }); + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { LangChainInstrumentation } from '@traceloop/instrumentation-langchain' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new LangChainInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- - **Note:** If you want to capture LLM events anonymously, **don't** pass a distinct ID to the - `CallbackHandler`. See our docs on [anonymous vs identified - events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - -
), }, @@ -163,8 +123,8 @@ export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinit content: ( <> - When you invoke your chain, pass the `callback_handler` in the `config` as part of your - `callbacks`: + Use LangChain as normal. The OpenTelemetry instrumentation automatically captures + `$ai_generation` events for each LLM call — no callback handlers needed. - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. + Install the OpenTelemetry SDK, the LangChain instrumentation, and LangGraph with OpenAI. - - ), - }, - { - title: 'Install LangGraph', - badge: 'required', - content: ( - <> - - Install LangGraph and LangChain. PostHog instruments your LLM calls through LangChain-compatible - callback handlers that LangGraph supports. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then create a LangChain `CallbackHandler`. + Configure OpenTelemetry to auto-instrument LangChain calls and export traces to PostHog. + LangGraph is built on LangChain, so the same instrumentation captures all LLM calls. PostHog + converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.langchain import LangchainInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - callback_handler = CallbackHandler( - client=posthog, - distinct_id="user_123", # optional - trace_id="trace_456", # optional - properties={"conversation_id": "abc123"}, # optional - groups={"company": "company_id_in_your_db"}, # optional - privacy_mode=False # optional - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + LangchainInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { PostHog } from 'posthog-node'; - import { LangChainCallbackHandler } from '@posthog/ai'; - - const phClient = new PostHog( - '', - { host: '' } - ); - - const callbackHandler = new LangChainCallbackHandler({ - client: phClient, - distinctId: 'user_123', // optional - traceId: 'trace_456', // optional - properties: { conversationId: 'abc123' }, // optional - groups: { company: 'company_id_in_your_db' }, // optional - privacyMode: false, // optional - }); + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { LangChainInstrumentation } from '@traceloop/instrumentation-langchain' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new LangChainInstrumentation()], + }) + sdk.start() `, }, ]} /> - - - - LangGraph is built on LangChain, so it supports LangChain-compatible callback handlers. - PostHog's `CallbackHandler` captures `$ai_generation` events and trace hierarchy - automatically without proxying your calls. - - ), }, @@ -145,8 +124,8 @@ export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinit content: ( <> - Pass the `callback_handler` in the `config` when invoking your LangGraph graph. PostHog - automatically captures generation events for each LLM call. + Use LangGraph as normal. The OpenTelemetry instrumentation automatically captures + `$ai_generation` events for each LLM call — no callback handlers needed. { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, Markdown, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - Setting up analytics starts with installing the PostHog SDK. The LlamaIndex integration uses - PostHog's OpenAI wrapper. + Install LlamaIndex, OpenAI, and the OpenTelemetry SDK with the LlamaIndex instrumentation. ), }, { - title: 'Install LlamaIndex', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Install LlamaIndex with the OpenAI integration. PostHog instruments your LLM calls by wrapping - the OpenAI client that LlamaIndex uses. - - - - - ), - }, - { - title: 'Initialize PostHog and LlamaIndex', - badge: 'required', - content: ( - <> - - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then create a PostHog OpenAI wrapper and - pass it to LlamaIndex's `OpenAI` LLM class. + Configure OpenTelemetry to auto-instrument LlamaIndex calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.llamaindex import LlamaIndexInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - openai_client = OpenAI( - api_key="your_openai_api_key", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) - llm = LlamaOpenAI( - model="gpt-5-mini", - api_key="your_openai_api_key", - ) - llm._client = openai_client + LlamaIndexInstrumentor().instrument() `} /> - - - - PostHog's `OpenAI` wrapper is a proper subclass of `openai.OpenAI`, so it can replace the - internal client used by LlamaIndex's OpenAI LLM. PostHog captures `$ai_generation` events - automatically without proxying your calls. **Note:** This approach accesses an internal - attribute (`_client`) which may change in future LlamaIndex versions. Check for updates if - you encounter issues after upgrading LlamaIndex. - - ), }, @@ -100,15 +72,18 @@ export const getLlamaIndexSteps = (ctx: OnboardingComponentsContext): StepDefini content: ( <> - Use LlamaIndex as normal. PostHog automatically captures an `$ai_generation` event for each LLM - call made through the wrapped client. + Use LlamaIndex as normal. The OpenTelemetry instrumentation automatically captures + `$ai_generation` events for each LLM call. - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Mistral through the OpenAI client and generate a response. We'll use PostHog's OpenAI - provider to capture all the details of the call. Initialize PostHog with your PostHog project - token and host from [your project settings](https://app.posthog.com/settings/project), then pass - the PostHog client along with the Mistral config (the base URL and API key) to our OpenAI - wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.mistral.ai/v1", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.mistral.ai/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinitio content: ( <> - Now, when you call Mistral with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Mistral, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'mistral-large-latest', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -201,14 +174,9 @@ export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinitio
- {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/ollama.tsx b/docs/onboarding/llm-analytics/ollama.tsx index d943490e6605..673f89f6e21d 100644 --- a/docs/onboarding/llm-analytics/ollama.tsx +++ b/docs/onboarding/llm-analytics/ollama.tsx @@ -9,21 +9,11 @@ export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - - **Note:** Make sure Ollama is running locally before making API calls. You can start it with - `ollama serve`. - - - - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Ollama through the OpenAI client and generate a response. We'll use PostHog's OpenAI - provider to capture all the details of the call. Initialize PostHog with your PostHog project - token and host from [your project settings](https://app.posthog.com/settings/project), then pass - the PostHog client along with the Ollama config (the base URL) to our OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="http://localhost:11434/v1", - api_key="ollama", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'http://localhost:11434/v1', - apiKey: 'ollama', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -159,9 +121,8 @@ export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition content: ( <> - Now, when you call Ollama with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Ollama, PostHog automatically captures `$ai_generation` + events via the OpenTelemetry instrumentation. {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `} diff --git a/docs/onboarding/llm-analytics/openai.tsx b/docs/onboarding/llm-analytics/openai.tsx index b80b5a6959aa..c60f6cc28df0 100644 --- a/docs/onboarding/llm-analytics/openai.tsx +++ b/docs/onboarding/llm-analytics/openai.tsx @@ -9,14 +9,11 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then pass it to our OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - api_key="your_openai_api_key", - posthog_client=posthog # This is an optional parameter. If it is not provided, a default client will be used. - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - apiKey: 'your_openai_api_key', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -148,9 +121,8 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition content: ( <> - Now, when you use the OpenAI SDK to call LLMs, PostHog automatically captures an - `$ai_generation` event. You can enrich the event with additional data such as the trace ID, - distinct ID, custom properties, groups, and privacy mode options. + Now, when you use the OpenAI SDK to call OpenAI, PostHog automatically captures `$ai_generation` + events via the OpenTelemetry instrumentation. - {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. @@ -223,8 +192,8 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition content: ( <> - PostHog can also capture embedding generations as `$ai_embedding` events. Just make sure to use - the same `posthog.ai.openai` client to do so: + PostHog can also capture embedding generations as `$ai_embedding` events. The OpenTelemetry + instrumentation automatically captures these when you use the embeddings API: diff --git a/docs/onboarding/llm-analytics/openrouter.tsx b/docs/onboarding/llm-analytics/openrouter.tsx index cd883119b766..90ae49ed8fc6 100644 --- a/docs/onboarding/llm-analytics/openrouter.tsx +++ b/docs/onboarding/llm-analytics/openrouter.tsx @@ -9,23 +9,11 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - - OpenRouter also offers a native [Broadcast - feature](https://openrouter.ai/docs/guides/features/broadcast/posthog) that can - automatically send LLM analytics data to PostHog without requiring SDK instrumentation. This - is a simpler option if you don't need the additional customization that our SDK provides. - - - - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call OpenRouter through the OpenAI client and generate a response. We'll use PostHog's OpenAI - provider to capture all the details of the call. Initialize PostHog with your PostHog project - token and host from [your project settings](https://app.posthog.com/settings/project), then pass - the PostHog client along with the OpenRouter config (the base URL and API key) to our OpenAI - wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://openrouter.ai/api/v1", - api_key="", - posthog_client=posthog # This is an optional parameter. If it is not provided, a default client will be used. - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://openrouter.ai/api/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -162,9 +121,8 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini content: ( <> - Now, when you call OpenRouter with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call OpenRouter, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'gpt-5-mini', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -211,12 +175,7 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini
{dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/perplexity.tsx b/docs/onboarding/llm-analytics/perplexity.tsx index 84279dec69a4..a91b34dacc51 100644 --- a/docs/onboarding/llm-analytics/perplexity.tsx +++ b/docs/onboarding/llm-analytics/perplexity.tsx @@ -9,14 +9,11 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Perplexity through the OpenAI client and generate a response. We'll use PostHog's OpenAI - provider to capture all the details of the call. Initialize PostHog with your PostHog project - token and host from [your project settings](https://app.posthog.com/settings/project), then pass - the PostHog client along with the Perplexity config (the base URL and API key) to our OpenAI - wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.perplexity.ai", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.perplexity.ai', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini content: ( <> - Now, when you call Perplexity with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Perplexity, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'sonar', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -202,12 +175,7 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini
{dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/portkey.tsx b/docs/onboarding/llm-analytics/portkey.tsx index 00209a6f178a..4989a5fb4c3d 100644 --- a/docs/onboarding/llm-analytics/portkey.tsx +++ b/docs/onboarding/llm-analytics/portkey.tsx @@ -9,7 +9,7 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> @@ -21,10 +21,7 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio
- - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI and Portkey SDKs', - badge: 'required', - content: ( - <> - - Install the OpenAI and Portkey SDKs. The PostHog SDK instruments your LLM calls by wrapping the - OpenAI client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and Portkey-routed client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then pass it along with the Portkey gateway - URL and your Portkey API key to our OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url=PORTKEY_GATEWAY_URL, - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - import { PORTKEY_GATEWAY_URL } from 'portkey-ai' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: PORTKEY_GATEWAY_URL, - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -161,9 +129,8 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio content: ( <> - Now, when you call Portkey with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you call Portkey with the OpenAI SDK, PostHog automatically captures `$ai_generation` + events via the OpenTelemetry instrumentation. /gpt-5-mini", - messages: [{ role: "user", content: "Tell me a fun fact about hedgehogs" }], - posthogDistinctId: "user_123", // optional - posthogTraceId: "trace_123", // optional - posthogProperties: { conversation_id: "abc123", paid: true }, // optional - posthogGroups: { company: "company_id_in_your_db" }, // optional - posthogPrivacyMode: false // optional - }); - - console.log(completion.choices[0].message.content) + import OpenAI from 'openai' + import { PORTKEY_GATEWAY_URL } from 'portkey-ai' + + const client = new OpenAI({ + baseURL: PORTKEY_GATEWAY_URL, + apiKey: '', + }) + + const response = await client.chat.completions.create({ + model: '@/gpt-5-mini', + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -209,14 +182,9 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio
- {dedent` - **Notes:** - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - The \`@\` prefix is the name you chose when setting up the integration in your [Portkey dashboard](https://app.portkey.ai/). - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/together-ai.tsx b/docs/onboarding/llm-analytics/together-ai.tsx index 8a2fb8b74377..f06c2c2d9052 100644 --- a/docs/onboarding/llm-analytics/together-ai.tsx +++ b/docs/onboarding/llm-analytics/together-ai.tsx @@ -9,14 +9,11 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Together AI through the OpenAI client and generate a response. We'll use PostHog's - OpenAI provider to capture all the details of the call. Initialize PostHog with your PostHog - project token and host from [your project settings](https://app.posthog.com/settings/project), - then pass the PostHog client along with the Together AI config (the base URL and API key) to our - OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.together.xyz/v1", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.together.xyz/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini content: ( <> - Now, when you call Together AI with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call Together AI, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -202,12 +175,7 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini
{dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx b/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx index 2995148b28e8..9157ca738482 100644 --- a/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx +++ b/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx @@ -9,7 +9,7 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> @@ -20,10 +20,7 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call Vercel AI Gateway through the OpenAI client and generate a response. We'll use PostHog's - OpenAI provider to capture all the details of the call. Initialize PostHog with your PostHog - project token and host from [your project settings](https://app.posthog.com/settings/project), - then pass the PostHog client along with the Vercel AI Gateway base URL to our OpenAI wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://ai-gateway.vercel.sh/v1", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://ai-gateway.vercel.sh/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -159,9 +128,8 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD content: ( <> - Now, when you call Vercel AI Gateway with the OpenAI SDK, PostHog automatically captures an - `$ai_generation` event. You can also capture or modify additional properties with the distinct - ID, trace ID, properties, groups, and privacy mode parameters. + Now, when you call Vercel AI Gateway with the OpenAI SDK, PostHog automatically captures + `$ai_generation` events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'gpt-5-mini', + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -207,14 +179,9 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD
- {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/vercel-ai.tsx b/docs/onboarding/llm-analytics/vercel-ai.tsx index 31a0aa539bec..1b3d0779eb70 100644 --- a/docs/onboarding/llm-analytics/vercel-ai.tsx +++ b/docs/onboarding/llm-analytics/vercel-ai.tsx @@ -45,18 +45,23 @@ export const getVercelAISteps = (ctx: OnboardingComponentsContext): StepDefiniti ', - host: '', - }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], }) sdk.start() `} @@ -93,8 +98,6 @@ export const getVercelAISteps = (ctx: OnboardingComponentsContext): StepDefiniti }) console.log(result.text) - - await sdk.shutdown() `} /> diff --git a/docs/onboarding/llm-analytics/xai.tsx b/docs/onboarding/llm-analytics/xai.tsx index a64fb5c9f93d..c6698a1364ba 100644 --- a/docs/onboarding/llm-analytics/xai.tsx +++ b/docs/onboarding/llm-analytics/xai.tsx @@ -9,14 +9,11 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. - - ), - }, - { - title: 'Install the OpenAI SDK', - badge: 'required', - content: ( - <> - - Install the OpenAI SDK. The PostHog SDK instruments your LLM calls by wrapping the OpenAI - client. The PostHog SDK **does not** proxy your calls. - - + + + These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the + background. + + ), }, { - title: 'Initialize PostHog and OpenAI client', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - We call xAI through the OpenAI-compatible API and generate a response. We'll use PostHog's - OpenAI provider to capture all the details of the call. Initialize PostHog with your PostHog - project token and host from [your project settings](https://app.posthog.com/settings/project), - then pass the PostHog client along with the xAI config (the base URL and API key) to our OpenAI - wrapper. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "user.id": "user_123", # optional: identifies the user in PostHog + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - client = OpenAI( - base_url="https://api.x.ai/v1", - api_key="", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - baseURL: 'https://api.x.ai/v1', - apiKey: '', - posthog: phClient, - }); - - // ... your code here ... - - // IMPORTANT: Shutdown the client when you're done to ensure all events are sent - phClient.shutdown() + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'user.id': 'user_123', // optional: identifies the user in PostHog + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - -
- **Note:** This also works with the `AsyncOpenAI` client. -
- - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, @@ -153,9 +121,8 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] content: ( <> - Now, when you call xAI with the OpenAI SDK, PostHog automatically captures an `$ai_generation` - event. You can also capture or modify additional properties with the distinct ID, trace ID, - properties, groups, and privacy mode parameters. + Now, when you use the OpenAI SDK to call xAI, PostHog automatically captures `$ai_generation` + events via the OpenTelemetry instrumentation. ', + }) + + const response = await client.chat.completions.create({ + model: 'grok-3', + max_completion_tokens: 1024, + messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], + }) + + console.log(response.choices[0].message.content) `, }, ]} @@ -201,14 +174,9 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[]
- {dedent` - **Notes:** - - We also support the old \`chat.completions\` API. - - This works with responses where \`stream=True\`. - - If you want to capture LLM events anonymously, **don't** pass a distinct ID to the request. - - See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. - `} + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
From e95a64fc0a097b558bbbc9c78c61de28f0d99b4f Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Wed, 8 Apr 2026 12:15:31 +0300 Subject: [PATCH 2/9] chore(llma): remove proxy callout from OTel onboarding docs --- docs/onboarding/llm-analytics/anthropic.tsx | 9 +-------- docs/onboarding/llm-analytics/azure-openai.tsx | 9 +-------- docs/onboarding/llm-analytics/cerebras.tsx | 9 +-------- docs/onboarding/llm-analytics/cohere.tsx | 9 +-------- docs/onboarding/llm-analytics/deepseek.tsx | 9 +-------- docs/onboarding/llm-analytics/fireworks-ai.tsx | 9 +-------- docs/onboarding/llm-analytics/groq.tsx | 9 +-------- docs/onboarding/llm-analytics/helicone.tsx | 7 ------- docs/onboarding/llm-analytics/hugging-face.tsx | 9 +-------- docs/onboarding/llm-analytics/langchain.tsx | 9 +-------- docs/onboarding/llm-analytics/langgraph.tsx | 9 +-------- docs/onboarding/llm-analytics/mistral.tsx | 9 +-------- docs/onboarding/llm-analytics/ollama.tsx | 9 +-------- docs/onboarding/llm-analytics/openai.tsx | 9 +-------- docs/onboarding/llm-analytics/openrouter.tsx | 9 +-------- docs/onboarding/llm-analytics/perplexity.tsx | 9 +-------- docs/onboarding/llm-analytics/portkey.tsx | 7 ------- docs/onboarding/llm-analytics/together-ai.tsx | 9 +-------- docs/onboarding/llm-analytics/vercel-ai-gateway.tsx | 7 ------- docs/onboarding/llm-analytics/vercel-ai.tsx | 9 +-------- docs/onboarding/llm-analytics/xai.tsx | 9 +-------- 21 files changed, 18 insertions(+), 165 deletions(-) diff --git a/docs/onboarding/llm-analytics/anthropic.tsx b/docs/onboarding/llm-analytics/anthropic.tsx index 329647a220e9..e62eb6348b77 100644 --- a/docs/onboarding/llm-analytics/anthropic.tsx +++ b/docs/onboarding/llm-analytics/anthropic.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -35,13 +35,6 @@ export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinit }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/azure-openai.tsx b/docs/onboarding/llm-analytics/azure-openai.tsx index b62af8e02e65..f636c2378f4a 100644 --- a/docs/onboarding/llm-analytics/azure-openai.tsx +++ b/docs/onboarding/llm-analytics/azure-openai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/cerebras.tsx b/docs/onboarding/llm-analytics/cerebras.tsx index cd3cdff48879..b3e20060ac43 100644 --- a/docs/onboarding/llm-analytics/cerebras.tsx +++ b/docs/onboarding/llm-analytics/cerebras.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/cohere.tsx b/docs/onboarding/llm-analytics/cohere.tsx index 91f463e5a8a7..f2e3b43c66d8 100644 --- a/docs/onboarding/llm-analytics/cohere.tsx +++ b/docs/onboarding/llm-analytics/cohere.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/deepseek.tsx b/docs/onboarding/llm-analytics/deepseek.tsx index 7cf01aa64fc8..61a8f3715c86 100644 --- a/docs/onboarding/llm-analytics/deepseek.tsx +++ b/docs/onboarding/llm-analytics/deepseek.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/fireworks-ai.tsx b/docs/onboarding/llm-analytics/fireworks-ai.tsx index 40140b6e181c..9c0d74756fbd 100644 --- a/docs/onboarding/llm-analytics/fireworks-ai.tsx +++ b/docs/onboarding/llm-analytics/fireworks-ai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/groq.tsx b/docs/onboarding/llm-analytics/groq.tsx index f917b5f22cb8..038fa0d4a494 100644 --- a/docs/onboarding/llm-analytics/groq.tsx +++ b/docs/onboarding/llm-analytics/groq.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[] }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/helicone.tsx b/docs/onboarding/llm-analytics/helicone.tsx index c56d9d1e0e24..e3d846bbc316 100644 --- a/docs/onboarding/llm-analytics/helicone.tsx +++ b/docs/onboarding/llm-analytics/helicone.tsx @@ -41,13 +41,6 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/hugging-face.tsx b/docs/onboarding/llm-analytics/hugging-face.tsx index 7454a61fa631..49c007d54ef7 100644 --- a/docs/onboarding/llm-analytics/hugging-face.tsx +++ b/docs/onboarding/llm-analytics/hugging-face.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/langchain.tsx b/docs/onboarding/llm-analytics/langchain.tsx index 3b86936efa5f..ad729dd46fd7 100644 --- a/docs/onboarding/llm-analytics/langchain.tsx +++ b/docs/onboarding/llm-analytics/langchain.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, Markdown, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -35,13 +35,6 @@ export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinit }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/langgraph.tsx b/docs/onboarding/llm-analytics/langgraph.tsx index be6392104224..95e239b1a56c 100644 --- a/docs/onboarding/llm-analytics/langgraph.tsx +++ b/docs/onboarding/llm-analytics/langgraph.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, Markdown, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -35,13 +35,6 @@ export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinit }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/mistral.tsx b/docs/onboarding/llm-analytics/mistral.tsx index d30045d53ad2..54e8afe892c5 100644 --- a/docs/onboarding/llm-analytics/mistral.tsx +++ b/docs/onboarding/llm-analytics/mistral.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinitio }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/ollama.tsx b/docs/onboarding/llm-analytics/ollama.tsx index 673f89f6e21d..02df0b343592 100644 --- a/docs/onboarding/llm-analytics/ollama.tsx +++ b/docs/onboarding/llm-analytics/ollama.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/openai.tsx b/docs/onboarding/llm-analytics/openai.tsx index c60f6cc28df0..28790c7732b3 100644 --- a/docs/onboarding/llm-analytics/openai.tsx +++ b/docs/onboarding/llm-analytics/openai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/openrouter.tsx b/docs/onboarding/llm-analytics/openrouter.tsx index 90ae49ed8fc6..f983612c451f 100644 --- a/docs/onboarding/llm-analytics/openrouter.tsx +++ b/docs/onboarding/llm-analytics/openrouter.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/perplexity.tsx b/docs/onboarding/llm-analytics/perplexity.tsx index a91b34dacc51..9498d646d1f8 100644 --- a/docs/onboarding/llm-analytics/perplexity.tsx +++ b/docs/onboarding/llm-analytics/perplexity.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/portkey.tsx b/docs/onboarding/llm-analytics/portkey.tsx index 4989a5fb4c3d..15526d465f2a 100644 --- a/docs/onboarding/llm-analytics/portkey.tsx +++ b/docs/onboarding/llm-analytics/portkey.tsx @@ -41,13 +41,6 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/together-ai.tsx b/docs/onboarding/llm-analytics/together-ai.tsx index f06c2c2d9052..bb8ed6a57f72 100644 --- a/docs/onboarding/llm-analytics/together-ai.tsx +++ b/docs/onboarding/llm-analytics/together-ai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx b/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx index 9157ca738482..ce2fb6cb93cc 100644 --- a/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx +++ b/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx @@ -40,13 +40,6 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/vercel-ai.tsx b/docs/onboarding/llm-analytics/vercel-ai.tsx index 1b3d0779eb70..6c2b413b3567 100644 --- a/docs/onboarding/llm-analytics/vercel-ai.tsx +++ b/docs/onboarding/llm-analytics/vercel-ai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getVercelAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -21,13 +21,6 @@ export const getVercelAISteps = (ctx: OnboardingComponentsContext): StepDefiniti npm install @posthog/ai @ai-sdk/openai ai @opentelemetry/sdk-node @opentelemetry/resources `} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, diff --git a/docs/onboarding/llm-analytics/xai.tsx b/docs/onboarding/llm-analytics/xai.tsx index c6698a1364ba..4377335c5af0 100644 --- a/docs/onboarding/llm-analytics/xai.tsx +++ b/docs/onboarding/llm-analytics/xai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -33,13 +33,6 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] }, ]} /> - - - - These SDKs **do not** proxy your calls. They only send analytics data to PostHog in the - background. - - ), }, From 97177f34ebb1365b2568461207d080d90a2937da Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Wed, 8 Apr 2026 12:28:45 +0300 Subject: [PATCH 3/9] fix(llma): address review feedback on OTel onboarding docs - Remove user.id from Vercel AI resource (posthog_distinct_id in experimental_telemetry is the established mechanism for that SDK) - Normalize service.name to 'my-app' in Vercel AI doc - Add anonymous events Blockquote to langchain, langgraph, llamaindex - Add Node tab to OpenAI embeddings step --- docs/onboarding/llm-analytics/langchain.tsx | 10 ++++++- docs/onboarding/llm-analytics/langgraph.tsx | 10 ++++++- docs/onboarding/llm-analytics/llamaindex.tsx | 10 ++++++- docs/onboarding/llm-analytics/openai.tsx | 29 +++++++++++++++----- docs/onboarding/llm-analytics/vercel-ai.tsx | 3 +- 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/docs/onboarding/llm-analytics/langchain.tsx b/docs/onboarding/llm-analytics/langchain.tsx index ad729dd46fd7..e4ae2224cbbf 100644 --- a/docs/onboarding/llm-analytics/langchain.tsx +++ b/docs/onboarding/llm-analytics/langchain.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -165,6 +165,14 @@ export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinit ]} /> +
+ + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ PostHog automatically captures an `$ai_generation` event along with these properties: diff --git a/docs/onboarding/llm-analytics/langgraph.tsx b/docs/onboarding/llm-analytics/langgraph.tsx index 95e239b1a56c..64b52d63976d 100644 --- a/docs/onboarding/llm-analytics/langgraph.tsx +++ b/docs/onboarding/llm-analytics/langgraph.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -179,6 +179,14 @@ export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinit ]} /> +
+ + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ {dedent` PostHog automatically captures \`$ai_generation\` events and creates a trace hierarchy based on how LangGraph components are nested. You can expect captured events to have the following properties: diff --git a/docs/onboarding/llm-analytics/llamaindex.tsx b/docs/onboarding/llm-analytics/llamaindex.tsx index e1f4c19287ec..67ceaa4e3d0c 100644 --- a/docs/onboarding/llm-analytics/llamaindex.tsx +++ b/docs/onboarding/llm-analytics/llamaindex.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getLlamaIndexSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, dedent, snippets } = ctx + const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -98,6 +98,14 @@ export const getLlamaIndexSteps = (ctx: OnboardingComponentsContext): StepDefini `} /> +
+ + **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource + attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ {dedent` You can expect captured \`$ai_generation\` events to have the following properties: diff --git a/docs/onboarding/llm-analytics/openai.tsx b/docs/onboarding/llm-analytics/openai.tsx index 28790c7732b3..bf9e4069dc58 100644 --- a/docs/onboarding/llm-analytics/openai.tsx +++ b/docs/onboarding/llm-analytics/openai.tsx @@ -190,13 +190,28 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition ), diff --git a/docs/onboarding/llm-analytics/vercel-ai.tsx b/docs/onboarding/llm-analytics/vercel-ai.tsx index 6c2b413b3567..29bd009d3986 100644 --- a/docs/onboarding/llm-analytics/vercel-ai.tsx +++ b/docs/onboarding/llm-analytics/vercel-ai.tsx @@ -44,8 +44,7 @@ export const getVercelAISteps = (ctx: OnboardingComponentsContext): StepDefiniti const sdk = new NodeSDK({ resource: resourceFromAttributes({ - 'service.name': 'my-ai-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'service.name': 'my-app', }), spanProcessors: [ new tracing.SimpleSpanProcessor( From d0c19b088eb95390415b68359eaf526e7be73ce5 Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Wed, 8 Apr 2026 17:54:15 +0300 Subject: [PATCH 4/9] fix(llma): use posthog.distinct_id and add custom property examples to docs --- docs/onboarding/llm-analytics/anthropic.tsx | 10 ++++++---- docs/onboarding/llm-analytics/azure-openai.tsx | 10 ++++++---- docs/onboarding/llm-analytics/cerebras.tsx | 8 +++++--- docs/onboarding/llm-analytics/cohere.tsx | 10 ++++++---- docs/onboarding/llm-analytics/deepseek.tsx | 10 ++++++---- docs/onboarding/llm-analytics/fireworks-ai.tsx | 10 ++++++---- docs/onboarding/llm-analytics/groq.tsx | 10 ++++++---- docs/onboarding/llm-analytics/helicone.tsx | 10 ++++++---- docs/onboarding/llm-analytics/hugging-face.tsx | 8 +++++--- docs/onboarding/llm-analytics/langchain.tsx | 10 ++++++---- docs/onboarding/llm-analytics/langgraph.tsx | 10 ++++++---- docs/onboarding/llm-analytics/llamaindex.tsx | 7 ++++--- docs/onboarding/llm-analytics/mistral.tsx | 10 ++++++---- docs/onboarding/llm-analytics/ollama.tsx | 8 +++++--- docs/onboarding/llm-analytics/openai.tsx | 10 ++++++---- docs/onboarding/llm-analytics/openrouter.tsx | 8 +++++--- docs/onboarding/llm-analytics/perplexity.tsx | 8 +++++--- docs/onboarding/llm-analytics/portkey.tsx | 10 ++++++---- docs/onboarding/llm-analytics/together-ai.tsx | 8 +++++--- docs/onboarding/llm-analytics/vercel-ai-gateway.tsx | 10 ++++++---- docs/onboarding/llm-analytics/xai.tsx | 10 ++++++---- 21 files changed, 118 insertions(+), 77 deletions(-) diff --git a/docs/onboarding/llm-analytics/anthropic.tsx b/docs/onboarding/llm-analytics/anthropic.tsx index e62eb6348b77..312b3a38caef 100644 --- a/docs/onboarding/llm-analytics/anthropic.tsx +++ b/docs/onboarding/llm-analytics/anthropic.tsx @@ -63,7 +63,8 @@ export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinit resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -90,7 +91,8 @@ export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinit const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -170,8 +172,8 @@ export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinit
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/azure-openai.tsx b/docs/onboarding/llm-analytics/azure-openai.tsx index f636c2378f4a..976f0c86bacb 100644 --- a/docs/onboarding/llm-analytics/azure-openai.tsx +++ b/docs/onboarding/llm-analytics/azure-openai.tsx @@ -61,7 +61,8 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -167,8 +169,8 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/cerebras.tsx b/docs/onboarding/llm-analytics/cerebras.tsx index b3e20060ac43..e1111cf2f5e9 100644 --- a/docs/onboarding/llm-analytics/cerebras.tsx +++ b/docs/onboarding/llm-analytics/cerebras.tsx @@ -61,7 +61,8 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -168,7 +170,7 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti
{dedent` - **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`posthog.distinct_id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/cohere.tsx b/docs/onboarding/llm-analytics/cohere.tsx index f2e3b43c66d8..db30a7a9110c 100644 --- a/docs/onboarding/llm-analytics/cohere.tsx +++ b/docs/onboarding/llm-analytics/cohere.tsx @@ -61,7 +61,8 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -167,8 +169,8 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/deepseek.tsx b/docs/onboarding/llm-analytics/deepseek.tsx index 61a8f3715c86..b56771c300d1 100644 --- a/docs/onboarding/llm-analytics/deepseek.tsx +++ b/docs/onboarding/llm-analytics/deepseek.tsx @@ -61,7 +61,8 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -167,8 +169,8 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/fireworks-ai.tsx b/docs/onboarding/llm-analytics/fireworks-ai.tsx index 9c0d74756fbd..9eacd57c9e86 100644 --- a/docs/onboarding/llm-analytics/fireworks-ai.tsx +++ b/docs/onboarding/llm-analytics/fireworks-ai.tsx @@ -61,7 +61,8 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -167,8 +169,8 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/groq.tsx b/docs/onboarding/llm-analytics/groq.tsx index 038fa0d4a494..9243d032e2f6 100644 --- a/docs/onboarding/llm-analytics/groq.tsx +++ b/docs/onboarding/llm-analytics/groq.tsx @@ -61,7 +61,8 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[] resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[] const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -167,8 +169,8 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[]
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/helicone.tsx b/docs/onboarding/llm-analytics/helicone.tsx index e3d846bbc316..aa5ad28ec4a4 100644 --- a/docs/onboarding/llm-analytics/helicone.tsx +++ b/docs/onboarding/llm-analytics/helicone.tsx @@ -69,7 +69,8 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -96,7 +97,8 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -173,8 +175,8 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/hugging-face.tsx b/docs/onboarding/llm-analytics/hugging-face.tsx index 49c007d54ef7..b08f33e1d077 100644 --- a/docs/onboarding/llm-analytics/hugging-face.tsx +++ b/docs/onboarding/llm-analytics/hugging-face.tsx @@ -61,7 +61,8 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -168,7 +170,7 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin
{dedent` - **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`posthog.distinct_id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/langchain.tsx b/docs/onboarding/llm-analytics/langchain.tsx index e4ae2224cbbf..6e7970e8806e 100644 --- a/docs/onboarding/llm-analytics/langchain.tsx +++ b/docs/onboarding/llm-analytics/langchain.tsx @@ -63,7 +63,8 @@ export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinit resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -90,7 +91,8 @@ export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinit const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -167,8 +169,8 @@ export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinit
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/langgraph.tsx b/docs/onboarding/llm-analytics/langgraph.tsx index 64b52d63976d..b389f3b9a5d7 100644 --- a/docs/onboarding/llm-analytics/langgraph.tsx +++ b/docs/onboarding/llm-analytics/langgraph.tsx @@ -64,7 +64,8 @@ export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinit resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -91,7 +92,8 @@ export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinit const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -181,8 +183,8 @@ export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinit
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/llamaindex.tsx b/docs/onboarding/llm-analytics/llamaindex.tsx index 67ceaa4e3d0c..413dffc9a49e 100644 --- a/docs/onboarding/llm-analytics/llamaindex.tsx +++ b/docs/onboarding/llm-analytics/llamaindex.tsx @@ -48,7 +48,8 @@ export const getLlamaIndexSteps = (ctx: OnboardingComponentsContext): StepDefini resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -100,8 +101,8 @@ export const getLlamaIndexSteps = (ctx: OnboardingComponentsContext): StepDefini
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/mistral.tsx b/docs/onboarding/llm-analytics/mistral.tsx index 54e8afe892c5..7147df2104bf 100644 --- a/docs/onboarding/llm-analytics/mistral.tsx +++ b/docs/onboarding/llm-analytics/mistral.tsx @@ -61,7 +61,8 @@ export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinitio resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinitio const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -167,8 +169,8 @@ export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinitio
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/ollama.tsx b/docs/onboarding/llm-analytics/ollama.tsx index 02df0b343592..6b0f420cb885 100644 --- a/docs/onboarding/llm-analytics/ollama.tsx +++ b/docs/onboarding/llm-analytics/ollama.tsx @@ -61,7 +61,8 @@ export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -168,7 +170,7 @@ export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition
{dedent` - **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`posthog.distinct_id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/openai.tsx b/docs/onboarding/llm-analytics/openai.tsx index bf9e4069dc58..ecd73b82b10e 100644 --- a/docs/onboarding/llm-analytics/openai.tsx +++ b/docs/onboarding/llm-analytics/openai.tsx @@ -61,7 +61,8 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -163,8 +165,8 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/openrouter.tsx b/docs/onboarding/llm-analytics/openrouter.tsx index f983612c451f..995806e2a963 100644 --- a/docs/onboarding/llm-analytics/openrouter.tsx +++ b/docs/onboarding/llm-analytics/openrouter.tsx @@ -61,7 +61,8 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -168,7 +170,7 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini
{dedent` - **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`posthog.distinct_id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/perplexity.tsx b/docs/onboarding/llm-analytics/perplexity.tsx index 9498d646d1f8..f6aca4671d2e 100644 --- a/docs/onboarding/llm-analytics/perplexity.tsx +++ b/docs/onboarding/llm-analytics/perplexity.tsx @@ -61,7 +61,8 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -168,7 +170,7 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini
{dedent` - **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`posthog.distinct_id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/portkey.tsx b/docs/onboarding/llm-analytics/portkey.tsx index 15526d465f2a..5f2fa3e8d023 100644 --- a/docs/onboarding/llm-analytics/portkey.tsx +++ b/docs/onboarding/llm-analytics/portkey.tsx @@ -69,7 +69,8 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -96,7 +97,8 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -175,8 +177,8 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/together-ai.tsx b/docs/onboarding/llm-analytics/together-ai.tsx index bb8ed6a57f72..90620171e24f 100644 --- a/docs/onboarding/llm-analytics/together-ai.tsx +++ b/docs/onboarding/llm-analytics/together-ai.tsx @@ -61,7 +61,8 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -168,7 +170,7 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini
{dedent` - **Note:** If you want to capture LLM events anonymously, omit the \`user.id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit the \`posthog.distinct_id\` resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. `}
diff --git a/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx b/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx index ce2fb6cb93cc..0d413bf8bdc9 100644 --- a/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx +++ b/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx @@ -68,7 +68,8 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -95,7 +96,8 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -172,8 +174,8 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
diff --git a/docs/onboarding/llm-analytics/xai.tsx b/docs/onboarding/llm-analytics/xai.tsx index 4377335c5af0..94a2e647e14c 100644 --- a/docs/onboarding/llm-analytics/xai.tsx +++ b/docs/onboarding/llm-analytics/xai.tsx @@ -61,7 +61,8 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] resource = Resource(attributes={ SERVICE_NAME: "my-app", - "user.id": "user_123", # optional: identifies the user in PostHog + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through }) exporter = OTLPSpanExporter( @@ -88,7 +89,8 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] const sdk = new NodeSDK({ resource: resourceFromAttributes({ 'service.name': 'my-app', - 'user.id': 'user_123', // optional: identifies the user in PostHog + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through }), spanProcessors: [ new tracing.SimpleSpanProcessor( @@ -167,8 +169,8 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[]
- **Note:** If you want to capture LLM events anonymously, omit the `user.id` resource - attribute. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
From ccb95d619e278310772fba6d5b7da5f874555768 Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Wed, 8 Apr 2026 18:05:42 +0300 Subject: [PATCH 5/9] feat(llma): add migration callout linking to previous SDK wrapper examples --- docs/onboarding/llm-analytics/anthropic.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/azure-openai.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/cerebras.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/cohere.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/deepseek.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/fireworks-ai.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/groq.tsx | 12 +++++++++++- docs/onboarding/llm-analytics/helicone.tsx | 11 +++++++++++ docs/onboarding/llm-analytics/hugging-face.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/langchain.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/langgraph.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/llamaindex.tsx | 10 +++++++++- docs/onboarding/llm-analytics/mistral.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/ollama.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/openai.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/openrouter.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/perplexity.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/portkey.tsx | 11 +++++++++++ docs/onboarding/llm-analytics/together-ai.tsx | 13 ++++++++++++- docs/onboarding/llm-analytics/vercel-ai-gateway.tsx | 11 +++++++++++ docs/onboarding/llm-analytics/xai.tsx | 12 +++++++++++- 21 files changed, 244 insertions(+), 18 deletions(-) diff --git a/docs/onboarding/llm-analytics/anthropic.tsx b/docs/onboarding/llm-analytics/anthropic.tsx index 312b3a38caef..983e87259940 100644 --- a/docs/onboarding/llm-analytics/anthropic.tsx +++ b/docs/onboarding/llm-analytics/anthropic.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinit badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-anthropic) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-anthropic) + wrapper examples. + + + Install the OpenTelemetry SDK, the Anthropic instrumentation, and the Anthropic SDK. diff --git a/docs/onboarding/llm-analytics/azure-openai.tsx b/docs/onboarding/llm-analytics/azure-openai.tsx index 976f0c86bacb..3f08dab93509 100644 --- a/docs/onboarding/llm-analytics/azure-openai.tsx +++ b/docs/onboarding/llm-analytics/azure-openai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-azure-openai) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-azure-openai) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-cerebras) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-cerebras) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-cohere) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-cohere) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-deepseek) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-deepseek) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-fireworks-ai) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-fireworks-ai) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,16 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[] badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-groq) and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-groq) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-helicone) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-helicone) + wrapper examples. + + + Helicone is an open-source AI gateway that provides access to 100+ LLM providers through an diff --git a/docs/onboarding/llm-analytics/hugging-face.tsx b/docs/onboarding/llm-analytics/hugging-face.tsx index b08f33e1d077..5f070fd10648 100644 --- a/docs/onboarding/llm-analytics/hugging-face.tsx +++ b/docs/onboarding/llm-analytics/hugging-face.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-hugging-face) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-hugging-face) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinit badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-langchain) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-langchain) + wrapper examples. + + + Install the OpenTelemetry SDK, the LangChain instrumentation, and LangChain with OpenAI. diff --git a/docs/onboarding/llm-analytics/langgraph.tsx b/docs/onboarding/llm-analytics/langgraph.tsx index b389f3b9a5d7..aceaa9a64879 100644 --- a/docs/onboarding/llm-analytics/langgraph.tsx +++ b/docs/onboarding/llm-analytics/langgraph.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinit badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-langgraph) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-langgraph) + wrapper examples. + + + Install the OpenTelemetry SDK, the LangChain instrumentation, and LangGraph with OpenAI. diff --git a/docs/onboarding/llm-analytics/llamaindex.tsx b/docs/onboarding/llm-analytics/llamaindex.tsx index 413dffc9a49e..c043cfc964c0 100644 --- a/docs/onboarding/llm-analytics/llamaindex.tsx +++ b/docs/onboarding/llm-analytics/llamaindex.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getLlamaIndexSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,14 @@ export const getLlamaIndexSteps = (ctx: OnboardingComponentsContext): StepDefini badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the [Python wrapper + example](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-llamaindex). + + + Install LlamaIndex, OpenAI, and the OpenTelemetry SDK with the LlamaIndex instrumentation. diff --git a/docs/onboarding/llm-analytics/mistral.tsx b/docs/onboarding/llm-analytics/mistral.tsx index 7147df2104bf..0e3206c4c232 100644 --- a/docs/onboarding/llm-analytics/mistral.tsx +++ b/docs/onboarding/llm-analytics/mistral.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinitio badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-mistral) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-mistral) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-ollama) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-ollama) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-openai) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-openai) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-openrouter) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-openrouter) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-perplexity) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-perplexity) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-portkey) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-portkey) + wrapper examples. + + + Portkey acts as an AI gateway that routes requests to 250+ LLM providers. The model string diff --git a/docs/onboarding/llm-analytics/together-ai.tsx b/docs/onboarding/llm-analytics/together-ai.tsx index 90620171e24f..e878ba0a1868 100644 --- a/docs/onboarding/llm-analytics/together-ai.tsx +++ b/docs/onboarding/llm-analytics/together-ai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,17 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-together-ai) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-together-ai) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-vercel-ai-gateway) + and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-vercel-ai-gateway) + wrapper examples. + + + Vercel AI Gateway provides a unified OpenAI-compatible API for accessing multiple LLM diff --git a/docs/onboarding/llm-analytics/xai.tsx b/docs/onboarding/llm-analytics/xai.tsx index 94a2e647e14c..f66505e2ff8a 100644 --- a/docs/onboarding/llm-analytics/xai.tsx +++ b/docs/onboarding/llm-analytics/xai.tsx @@ -3,7 +3,7 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, Markdown, Blockquote, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties @@ -13,6 +13,16 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] badge: 'required', content: ( <> + + + These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. + The previous PostHog SDK wrapper is still available — see the + [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-xai) and + [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-xai) + wrapper examples. + + + Install the OpenTelemetry SDK, the OpenAI instrumentation, and the OpenAI SDK. Date: Wed, 8 Apr 2026 18:24:32 +0300 Subject: [PATCH 6/9] fix(llma): update callout wording to focus on current examples --- docs/onboarding/llm-analytics/anthropic.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/azure-openai.tsx | 16 ++++++++++------ docs/onboarding/llm-analytics/cerebras.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/cohere.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/deepseek.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/fireworks-ai.tsx | 16 ++++++++++------ docs/onboarding/llm-analytics/groq.tsx | 16 ++++++++++------ docs/onboarding/llm-analytics/helicone.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/hugging-face.tsx | 16 ++++++++++------ docs/onboarding/llm-analytics/langchain.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/langgraph.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/llamaindex.tsx | 8 +++++--- docs/onboarding/llm-analytics/mistral.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/ollama.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/openai.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/openrouter.tsx | 16 ++++++++++------ docs/onboarding/llm-analytics/perplexity.tsx | 16 ++++++++++------ docs/onboarding/llm-analytics/portkey.tsx | 17 ++++++++++------- docs/onboarding/llm-analytics/together-ai.tsx | 16 ++++++++++------ .../llm-analytics/vercel-ai-gateway.tsx | 16 ++++++++++------ docs/onboarding/llm-analytics/xai.tsx | 16 ++++++++++------ 21 files changed, 205 insertions(+), 134 deletions(-) diff --git a/docs/onboarding/llm-analytics/anthropic.tsx b/docs/onboarding/llm-analytics/anthropic.tsx index 983e87259940..61e8f1f56d22 100644 --- a/docs/onboarding/llm-analytics/anthropic.tsx +++ b/docs/onboarding/llm-analytics/anthropic.tsx @@ -13,14 +13,17 @@ export const getAnthropicSteps = (ctx: OnboardingComponentsContext): StepDefinit badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-anthropic) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-anthropic) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-anthropic) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-anthropic) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-anthropic) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-anthropic) + examples. diff --git a/docs/onboarding/llm-analytics/azure-openai.tsx b/docs/onboarding/llm-analytics/azure-openai.tsx index 3f08dab93509..a0cb8cf6723f 100644 --- a/docs/onboarding/llm-analytics/azure-openai.tsx +++ b/docs/onboarding/llm-analytics/azure-openai.tsx @@ -13,14 +13,18 @@ export const getAzureOpenAISteps = (ctx: OnboardingComponentsContext): StepDefin badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-azure-openai) + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-azure-openai) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-azure-openai) - wrapper examples. + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-azure-openai) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-azure-openai) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-azure-openai) + examples. diff --git a/docs/onboarding/llm-analytics/cerebras.tsx b/docs/onboarding/llm-analytics/cerebras.tsx index 6e37b2ccc14f..8d15f140c62b 100644 --- a/docs/onboarding/llm-analytics/cerebras.tsx +++ b/docs/onboarding/llm-analytics/cerebras.tsx @@ -13,14 +13,17 @@ export const getCerebrasSteps = (ctx: OnboardingComponentsContext): StepDefiniti badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-cerebras) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-cerebras) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-cerebras) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-cerebras) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-cerebras) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-cerebras) + examples. diff --git a/docs/onboarding/llm-analytics/cohere.tsx b/docs/onboarding/llm-analytics/cohere.tsx index fe3eef5e451b..ea11c3a1f5f9 100644 --- a/docs/onboarding/llm-analytics/cohere.tsx +++ b/docs/onboarding/llm-analytics/cohere.tsx @@ -13,14 +13,17 @@ export const getCohereSteps = (ctx: OnboardingComponentsContext): StepDefinition badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-cohere) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-cohere) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-cohere) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-cohere) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-cohere) and + [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-cohere) + examples. diff --git a/docs/onboarding/llm-analytics/deepseek.tsx b/docs/onboarding/llm-analytics/deepseek.tsx index 2a3458b3b338..809b5fe52923 100644 --- a/docs/onboarding/llm-analytics/deepseek.tsx +++ b/docs/onboarding/llm-analytics/deepseek.tsx @@ -13,14 +13,17 @@ export const getDeepSeekSteps = (ctx: OnboardingComponentsContext): StepDefiniti badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-deepseek) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-deepseek) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-deepseek) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-deepseek) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-deepseek) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-deepseek) + examples. diff --git a/docs/onboarding/llm-analytics/fireworks-ai.tsx b/docs/onboarding/llm-analytics/fireworks-ai.tsx index fa7f26a34d7e..55c24443a9ec 100644 --- a/docs/onboarding/llm-analytics/fireworks-ai.tsx +++ b/docs/onboarding/llm-analytics/fireworks-ai.tsx @@ -13,14 +13,18 @@ export const getFireworksAISteps = (ctx: OnboardingComponentsContext): StepDefin badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-fireworks-ai) + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-fireworks-ai) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-fireworks-ai) - wrapper examples. + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-fireworks-ai) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-fireworks-ai) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-fireworks-ai) + examples. diff --git a/docs/onboarding/llm-analytics/groq.tsx b/docs/onboarding/llm-analytics/groq.tsx index e75d77e883b5..f5a7865c71eb 100644 --- a/docs/onboarding/llm-analytics/groq.tsx +++ b/docs/onboarding/llm-analytics/groq.tsx @@ -13,13 +13,17 @@ export const getGroqSteps = (ctx: OnboardingComponentsContext): StepDefinition[] badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-groq) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-groq) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-groq) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-groq) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-groq) and + [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-groq) + examples. diff --git a/docs/onboarding/llm-analytics/helicone.tsx b/docs/onboarding/llm-analytics/helicone.tsx index 524bdb32455f..c020c21f1c28 100644 --- a/docs/onboarding/llm-analytics/helicone.tsx +++ b/docs/onboarding/llm-analytics/helicone.tsx @@ -13,14 +13,17 @@ export const getHeliconeSteps = (ctx: OnboardingComponentsContext): StepDefiniti badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-helicone) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-helicone) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-helicone) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-helicone) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-helicone) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-helicone) + examples. diff --git a/docs/onboarding/llm-analytics/hugging-face.tsx b/docs/onboarding/llm-analytics/hugging-face.tsx index 5f070fd10648..583d78337744 100644 --- a/docs/onboarding/llm-analytics/hugging-face.tsx +++ b/docs/onboarding/llm-analytics/hugging-face.tsx @@ -13,14 +13,18 @@ export const getHuggingFaceSteps = (ctx: OnboardingComponentsContext): StepDefin badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-hugging-face) + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-hugging-face) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-hugging-face) - wrapper examples. + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-hugging-face) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-hugging-face) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-hugging-face) + examples. diff --git a/docs/onboarding/llm-analytics/langchain.tsx b/docs/onboarding/llm-analytics/langchain.tsx index c6c4baccbff9..c77081b708c0 100644 --- a/docs/onboarding/llm-analytics/langchain.tsx +++ b/docs/onboarding/llm-analytics/langchain.tsx @@ -13,14 +13,17 @@ export const getLangChainSteps = (ctx: OnboardingComponentsContext): StepDefinit badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-langchain) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-langchain) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-langchain) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-langchain) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-langchain) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-langchain) + examples. diff --git a/docs/onboarding/llm-analytics/langgraph.tsx b/docs/onboarding/llm-analytics/langgraph.tsx index aceaa9a64879..4af98aaa0d0c 100644 --- a/docs/onboarding/llm-analytics/langgraph.tsx +++ b/docs/onboarding/llm-analytics/langgraph.tsx @@ -13,14 +13,17 @@ export const getLangGraphSteps = (ctx: OnboardingComponentsContext): StepDefinit badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-langgraph) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-langgraph) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-langgraph) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-langgraph) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-langgraph) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-langgraph) + examples. diff --git a/docs/onboarding/llm-analytics/llamaindex.tsx b/docs/onboarding/llm-analytics/llamaindex.tsx index c043cfc964c0..c2f97ff1de86 100644 --- a/docs/onboarding/llm-analytics/llamaindex.tsx +++ b/docs/onboarding/llm-analytics/llamaindex.tsx @@ -13,10 +13,12 @@ export const getLlamaIndexSteps = (ctx: OnboardingComponentsContext): StepDefini badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the [Python wrapper + See the complete [Python + example](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-llamaindex) + on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see the [Python + wrapper example](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-llamaindex). diff --git a/docs/onboarding/llm-analytics/mistral.tsx b/docs/onboarding/llm-analytics/mistral.tsx index 0e3206c4c232..cd07f4c281fe 100644 --- a/docs/onboarding/llm-analytics/mistral.tsx +++ b/docs/onboarding/llm-analytics/mistral.tsx @@ -13,14 +13,17 @@ export const getMistralSteps = (ctx: OnboardingComponentsContext): StepDefinitio badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-mistral) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-mistral) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-mistral) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-mistral) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-mistral) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-mistral) + examples. diff --git a/docs/onboarding/llm-analytics/ollama.tsx b/docs/onboarding/llm-analytics/ollama.tsx index d364b3031e65..86bd2cd5f104 100644 --- a/docs/onboarding/llm-analytics/ollama.tsx +++ b/docs/onboarding/llm-analytics/ollama.tsx @@ -13,14 +13,17 @@ export const getOllamaSteps = (ctx: OnboardingComponentsContext): StepDefinition badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-ollama) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-ollama) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-ollama) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-ollama) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-ollama) and + [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-ollama) + examples. diff --git a/docs/onboarding/llm-analytics/openai.tsx b/docs/onboarding/llm-analytics/openai.tsx index fbcf0a7eda48..5a2ee45ea190 100644 --- a/docs/onboarding/llm-analytics/openai.tsx +++ b/docs/onboarding/llm-analytics/openai.tsx @@ -13,14 +13,17 @@ export const getOpenAISteps = (ctx: OnboardingComponentsContext): StepDefinition badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-openai) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-openai) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-openai) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-openai) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-openai) and + [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-openai) + examples. diff --git a/docs/onboarding/llm-analytics/openrouter.tsx b/docs/onboarding/llm-analytics/openrouter.tsx index df6005906a68..dab91e919c58 100644 --- a/docs/onboarding/llm-analytics/openrouter.tsx +++ b/docs/onboarding/llm-analytics/openrouter.tsx @@ -13,14 +13,18 @@ export const getOpenRouterSteps = (ctx: OnboardingComponentsContext): StepDefini badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-openrouter) + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-openrouter) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-openrouter) - wrapper examples. + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-openrouter) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-openrouter) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-openrouter) + examples. diff --git a/docs/onboarding/llm-analytics/perplexity.tsx b/docs/onboarding/llm-analytics/perplexity.tsx index 8418c96f9342..c3c58ffc3d6a 100644 --- a/docs/onboarding/llm-analytics/perplexity.tsx +++ b/docs/onboarding/llm-analytics/perplexity.tsx @@ -13,14 +13,18 @@ export const getPerplexitySteps = (ctx: OnboardingComponentsContext): StepDefini badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-perplexity) + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-perplexity) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-perplexity) - wrapper examples. + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-perplexity) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-perplexity) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-perplexity) + examples. diff --git a/docs/onboarding/llm-analytics/portkey.tsx b/docs/onboarding/llm-analytics/portkey.tsx index 20a2bb8dc1c9..f7e6f50bed66 100644 --- a/docs/onboarding/llm-analytics/portkey.tsx +++ b/docs/onboarding/llm-analytics/portkey.tsx @@ -13,14 +13,17 @@ export const getPortkeySteps = (ctx: OnboardingComponentsContext): StepDefinitio badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-portkey) - and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-portkey) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-portkey) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-portkey) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-portkey) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-portkey) + examples. diff --git a/docs/onboarding/llm-analytics/together-ai.tsx b/docs/onboarding/llm-analytics/together-ai.tsx index e878ba0a1868..684473633c37 100644 --- a/docs/onboarding/llm-analytics/together-ai.tsx +++ b/docs/onboarding/llm-analytics/together-ai.tsx @@ -13,14 +13,18 @@ export const getTogetherAISteps = (ctx: OnboardingComponentsContext): StepDefini badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-together-ai) + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-together-ai) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-together-ai) - wrapper examples. + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-together-ai) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-together-ai) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-together-ai) + examples. diff --git a/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx b/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx index fd8e81402680..140dfc3d2f69 100644 --- a/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx +++ b/docs/onboarding/llm-analytics/vercel-ai-gateway.tsx @@ -13,14 +13,18 @@ export const getVercelAIGatewaySteps = (ctx: OnboardingComponentsContext): StepD badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-vercel-ai-gateway) + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-vercel-ai-gateway) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-vercel-ai-gateway) - wrapper examples. + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-vercel-ai-gateway) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-vercel-ai-gateway) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-vercel-ai-gateway) + examples. diff --git a/docs/onboarding/llm-analytics/xai.tsx b/docs/onboarding/llm-analytics/xai.tsx index f66505e2ff8a..80cf7ea1c4f5 100644 --- a/docs/onboarding/llm-analytics/xai.tsx +++ b/docs/onboarding/llm-analytics/xai.tsx @@ -13,13 +13,17 @@ export const getXAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] badge: 'required', content: ( <> - + - These docs now use OpenTelemetry auto-instrumentation, which is the recommended approach. - The previous PostHog SDK wrapper is still available — see the - [Node.js](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-xai) and - [Python](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-xai) - wrapper examples. + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-xai) and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-xai) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-xai) and + [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-xai) + examples. From b4839787e13f8fbec0909346aff71c40fd90203a Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Thu, 9 Apr 2026 10:32:19 +0300 Subject: [PATCH 7/9] feat(llma): migrate autogen, instructor, mirascope, semantic-kernel, smolagents, pydantic-ai docs to OTel --- docs/onboarding/llm-analytics/autogen.tsx | 109 +++++----- docs/onboarding/llm-analytics/instructor.tsx | 200 +++++++++--------- docs/onboarding/llm-analytics/mirascope.tsx | 109 +++++----- docs/onboarding/llm-analytics/pydantic-ai.tsx | 115 +++++----- .../llm-analytics/semantic-kernel.tsx | 115 +++++----- docs/onboarding/llm-analytics/smolagents.tsx | 110 +++++----- 6 files changed, 360 insertions(+), 398 deletions(-) diff --git a/docs/onboarding/llm-analytics/autogen.tsx b/docs/onboarding/llm-analytics/autogen.tsx index 304777a151d2..8c4364efa9b5 100644 --- a/docs/onboarding/llm-analytics/autogen.tsx +++ b/docs/onboarding/llm-analytics/autogen.tsx @@ -3,94 +3,75 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getAutoGenSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK. The AutoGen integration uses - PostHog's OpenAI wrapper since AutoGen uses OpenAI under the hood. - + + + See the complete [Python + example](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-autogen) + on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see the [Python + wrapper + example](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-autogen). + + - - - ), - }, - { - title: 'Install AutoGen', - badge: 'required', - content: ( - <> - - Install AutoGen with the OpenAI extension. PostHog instruments your LLM calls by wrapping the - OpenAI client that AutoGen uses internally. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and AutoGen. ), }, { - title: 'Initialize PostHog and AutoGen', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then create a PostHog OpenAI wrapper and - pass it to AutoGen's `OpenAIChatCompletionClient`. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - openai_client = OpenAI( - api_key="your_openai_api_key", - posthog_client=posthog, - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) - model_client = OpenAIChatCompletionClient( - model="gpt-4o", - openai_client=openai_client, - ) + OpenAIInstrumentor().instrument() `} /> - - - - AutoGen's `OpenAIChatCompletionClient` accepts a custom OpenAI client via the - `openai_client` parameter. PostHog's `OpenAI` wrapper is a proper subclass of - `openai.OpenAI`, so it works directly. PostHog captures `$ai_generation` events - automatically without proxying your calls. - - ), }, @@ -101,12 +82,20 @@ export const getAutoGenSteps = (ctx: OnboardingComponentsContext): StepDefinitio <> Use AutoGen as normal. PostHog automatically captures an `$ai_generation` event for each LLM - call made through the wrapped OpenAI client. + call made through the OpenAI SDK that AutoGen uses internally. +
+ + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ {dedent` You can expect captured \`$ai_generation\` events to have the following properties: diff --git a/docs/onboarding/llm-analytics/instructor.tsx b/docs/onboarding/llm-analytics/instructor.tsx index 0930a1fc0a60..bf06ff413ac9 100644 --- a/docs/onboarding/llm-analytics/instructor.tsx +++ b/docs/onboarding/llm-analytics/instructor.tsx @@ -3,51 +3,32 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getInstructorSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK for your language. LLM analytics - works best with our Python and Node SDKs. - + + + See the complete + [Node.js](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-instructor) + and + [Python](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-instructor) + examples on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see + the [Node.js + wrapper](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-instructor) + and [Python + wrapper](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-instructor) + examples. + + - - - ), - }, - { - title: 'Install Instructor and OpenAI SDKs', - badge: 'required', - content: ( - <> - - Install Instructor and the OpenAI SDK. PostHog instruments your LLM calls by wrapping the OpenAI - client, which Instructor uses under the hood. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and Instructor. - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then create a PostHog OpenAI wrapper and - pass it to Instructor. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - openai_client = OpenAI( - api_key="your_openai_api_key", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) - client = instructor.from_openai(openai_client) + OpenAIInstrumentor().instrument() `, }, { language: 'typescript', file: 'Node', code: dedent` - import Instructor from '@instructor-ai/instructor' - import { OpenAI } from '@posthog/ai' - import { PostHog } from 'posthog-node' - import { z } from 'zod' - - const phClient = new PostHog( - '', - { host: '' } - ); - - const openai = new OpenAI({ - apiKey: 'your_openai_api_key', - posthog: phClient, - }); - - const client = Instructor({ client: openai, mode: 'TOOLS' }) + import { NodeSDK, tracing } from '@opentelemetry/sdk-node' + import { resourceFromAttributes } from '@opentelemetry/resources' + import { PostHogTraceExporter } from '@posthog/ai/otel' + import { OpenAIInstrumentation } from '@opentelemetry/instrumentation-openai' + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + 'service.name': 'my-app', + 'posthog.distinct_id': 'user_123', // optional: identifies the user in PostHog + foo: 'bar', // custom properties are passed through + }), + spanProcessors: [ + new tracing.SimpleSpanProcessor( + new PostHogTraceExporter({ + apiKey: '', + host: '', + }) + ), + ], + instrumentations: [new OpenAIInstrumentation()], + }) + sdk.start() `, }, ]} /> - - - - PostHog's `OpenAI` wrapper is a proper subclass of `openai.OpenAI`, so it works directly - with `instructor.from_openai()`. PostHog captures `$ai_generation` events automatically - without proxying your calls. - - ), }, { - title: 'Use Instructor with structured outputs', + title: 'Extract structured data', badge: 'required', content: ( <> - Now use Instructor to extract structured data from LLM responses. PostHog automatically captures - an `$ai_generation` event for each call. + Use Instructor to extract structured data from LLM responses. PostHog automatically captures an + `$ai_generation` event for each call made through the OpenAI SDK that Instructor wraps. +
+ + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ {dedent` You can expect captured \`$ai_generation\` events to have the following properties: diff --git a/docs/onboarding/llm-analytics/mirascope.tsx b/docs/onboarding/llm-analytics/mirascope.tsx index 701c382990d8..ee79679d3782 100644 --- a/docs/onboarding/llm-analytics/mirascope.tsx +++ b/docs/onboarding/llm-analytics/mirascope.tsx @@ -3,113 +3,110 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getMirascopeSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK. The Mirascope integration uses - PostHog's OpenAI wrapper since Mirascope supports passing a custom OpenAI client. - + + + See the complete [Python + example](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-mirascope) + on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see the [Python + wrapper + example](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-mirascope). + + - - - ), - }, - { - title: 'Install Mirascope', - badge: 'required', - content: ( - <> - - Install Mirascope with OpenAI support. PostHog instruments your LLM calls by wrapping the OpenAI - client that Mirascope uses under the hood. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and Mirascope. ), }, { - title: 'Initialize PostHog and Mirascope', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then create a PostHog OpenAI wrapper and - pass it to Mirascope's `@call` decorator via the `client` parameter. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - openai_client = OpenAI( - api_key="your_openai_api_key", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) + + OpenAIInstrumentor().instrument() `} /> - - - - Mirascope's `@call` decorator accepts a `client` parameter for passing a custom OpenAI - client. PostHog's `OpenAI` wrapper is a proper subclass of `openai.OpenAI`, so it works - directly. PostHog captures `$ai_generation` events automatically without proxying your - calls. - - ), }, { - title: 'Make your first call', + title: 'Call your LLMs', badge: 'required', content: ( <> - Use Mirascope as normal, passing the wrapped client to the call decorator. PostHog automatically - captures an `$ai_generation` event for each LLM call. + Use Mirascope as normal. PostHog automatically captures an `$ai_generation` event for each LLM + call made through the OpenAI SDK that Mirascope uses internally. +
+ + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ {dedent` You can expect captured \`$ai_generation\` events to have the following properties: diff --git a/docs/onboarding/llm-analytics/pydantic-ai.tsx b/docs/onboarding/llm-analytics/pydantic-ai.tsx index 0affe67681f5..da1e0666f092 100644 --- a/docs/onboarding/llm-analytics/pydantic-ai.tsx +++ b/docs/onboarding/llm-analytics/pydantic-ai.tsx @@ -3,95 +3,77 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getPydanticAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK. The Pydantic AI integration uses - PostHog's OpenAI wrapper. - + + + See the complete [Python + example](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-pydantic-ai) + on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see the [Python + wrapper + example](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-pydantic-ai). + + - - - ), - }, - { - title: 'Install Pydantic AI', - badge: 'required', - content: ( - <> - - Install Pydantic AI with OpenAI support. PostHog instruments your LLM calls by wrapping the - OpenAI client that Pydantic AI uses. - + Install the OpenTelemetry SDK and Pydantic AI. ), }, { - title: 'Initialize PostHog and Pydantic AI', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then create a PostHog `AsyncOpenAI` - wrapper, pass it to an `OpenAIProvider`, and use that with Pydantic AI's `OpenAIChatModel`. + Configure OpenTelemetry to export traces to PostHog and enable Pydantic AI's built-in OTel + instrumentation. PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" - ) - openai_client = AsyncOpenAI( - api_key="your_openai_api_key", - posthog_client=posthog + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - provider = OpenAIProvider(openai_client=openai_client) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) - model = OpenAIChatModel( - "gpt-5-mini", - provider=provider - ) + # Enable automatic OTel instrumentation for all Pydantic AI agents + Agent.instrument_all() `} /> - - - - PostHog's `AsyncOpenAI` wrapper is a proper subclass of `openai.AsyncOpenAI`, so it works - directly as the client for Pydantic AI's `OpenAIProvider`. PostHog captures `$ai_generation` - events automatically without proxying your calls. - - ), }, @@ -101,27 +83,32 @@ export const getPydanticAISteps = (ctx: OnboardingComponentsContext): StepDefini content: ( <> - Create a Pydantic AI agent with the model and run it. PostHog automatically captures an - `$ai_generation` event for each LLM call. + Create a Pydantic AI agent and run it. PostHog automatically captures an `$ai_generation` event + for each LLM call via the OTel instrumentation. +
+ + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ {dedent` You can expect captured \`$ai_generation\` events to have the following properties: diff --git a/docs/onboarding/llm-analytics/semantic-kernel.tsx b/docs/onboarding/llm-analytics/semantic-kernel.tsx index 1388015ba892..cccee595933c 100644 --- a/docs/onboarding/llm-analytics/semantic-kernel.tsx +++ b/docs/onboarding/llm-analytics/semantic-kernel.tsx @@ -3,121 +3,118 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getSemanticKernelSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK. The Semantic Kernel integration - uses PostHog's OpenAI wrapper. - + + + See the complete [Python + example](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-semantic-kernel) + on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see the [Python + wrapper + example](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-semantic-kernel). + + - - - ), - }, - { - title: 'Install Semantic Kernel', - badge: 'required', - content: ( - <> - - Install Semantic Kernel with OpenAI support. PostHog instruments your LLM calls by wrapping the - OpenAI client that Semantic Kernel uses under the hood. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and Semantic Kernel. ), }, { - title: 'Initialize PostHog and Semantic Kernel', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then create a PostHog `AsyncOpenAI` wrapper - and pass it to Semantic Kernel's `OpenAIChatCompletion` service. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - openai_client = AsyncOpenAI( - api_key="your_openai_api_key", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) - kernel = Kernel() - kernel.add_service( - OpenAIChatCompletion( - ai_model_id="gpt-5-mini", - async_client=openai_client, - ) - ) + OpenAIInstrumentor().instrument() `} /> - - - - PostHog's `AsyncOpenAI` wrapper is a proper subclass of `openai.AsyncOpenAI`, so it works - directly as the `async_client` parameter in Semantic Kernel's `OpenAIChatCompletion`. - PostHog captures `$ai_generation` events automatically without proxying your calls. - - ), }, { - title: 'Run your kernel function', + title: 'Run your kernel', badge: 'required', content: ( <> Use Semantic Kernel as normal. PostHog automatically captures an `$ai_generation` event for each - LLM call made through the wrapped client. + LLM call made through the OpenAI SDK that Semantic Kernel uses internally. +
+ + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ {dedent` You can expect captured \`$ai_generation\` events to have the following properties: diff --git a/docs/onboarding/llm-analytics/smolagents.tsx b/docs/onboarding/llm-analytics/smolagents.tsx index 7710fe7e1aef..1bebaa8c940f 100644 --- a/docs/onboarding/llm-analytics/smolagents.tsx +++ b/docs/onboarding/llm-analytics/smolagents.tsx @@ -3,91 +3,75 @@ import { OnboardingComponentsContext, createInstallation } from 'scenes/onboardi import { StepDefinition } from '../steps' export const getSmolagentsSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => { - const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx + const { CodeBlock, CalloutBox, Markdown, Blockquote, dedent, snippets } = ctx const NotableGenerationProperties = snippets?.NotableGenerationProperties return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - - Setting up analytics starts with installing the PostHog SDK. The smolagents integration uses - PostHog's OpenAI wrapper. - + + + See the complete [Python + example](https://github.com/PostHog/posthog-python/tree/master/examples/example-ai-smolagents) + on GitHub. If you're using the PostHog SDK wrapper instead of OpenTelemetry, see the [Python + wrapper + example](https://github.com/PostHog/posthog-python/tree/7223c52/examples/example-ai-smolagents). + + - - - ), - }, - { - title: 'Install smolagents and OpenAI', - badge: 'required', - content: ( - <> - - Install smolagents and the OpenAI SDK. PostHog instruments your LLM calls by wrapping the OpenAI - client, which you can pass to smolagents' `OpenAIServerModel`. - + Install the OpenTelemetry SDK, the OpenAI instrumentation, and smolagents. ), }, { - title: 'Initialize PostHog and smolagents', + title: 'Set up OpenTelemetry tracing', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then create a PostHog OpenAI wrapper and - pass it to smolagents' `OpenAIServerModel`. + Configure OpenTelemetry to auto-instrument OpenAI SDK calls and export traces to PostHog. + PostHog converts `gen_ai.*` spans into `$ai_generation` events automatically. ", - host="" + from opentelemetry import trace + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import SimpleSpanProcessor + from opentelemetry.sdk.resources import Resource, SERVICE_NAME + from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter + from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor + + resource = Resource(attributes={ + SERVICE_NAME: "my-app", + "posthog.distinct_id": "user_123", # optional: identifies the user in PostHog + "foo": "bar", # custom properties are passed through + }) + + exporter = OTLPSpanExporter( + endpoint="/i/v0/ai/otel", + headers={"Authorization": "Bearer "}, ) - openai_client = OpenAI( - api_key="your_openai_api_key", - posthog_client=posthog - ) + provider = TracerProvider(resource=resource) + provider.add_span_processor(SimpleSpanProcessor(exporter)) + trace.set_tracer_provider(provider) - model = OpenAIServerModel( - model_id="gpt-5-mini", - client=openai_client, - ) + OpenAIInstrumentor().instrument() `} /> - - - - PostHog's `OpenAI` wrapper is a drop-in replacement for `openai.OpenAI`. By passing it as - the `client` to `OpenAIServerModel`, all LLM calls made by smolagents are automatically - captured as `$ai_generation` events. - - ), }, @@ -98,25 +82,31 @@ export const getSmolagentsSteps = (ctx: OnboardingComponentsContext): StepDefini <> Use smolagents as normal. PostHog automatically captures an `$ai_generation` event for each LLM - call made through the wrapped OpenAI client. + call made through the OpenAI SDK that smolagents uses internally. +
+ + **Note:** If you want to capture LLM events anonymously, omit the `posthog.distinct_id` + resource attribute. See our docs on [anonymous vs identified + events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + +
+ {dedent` You can expect captured \`$ai_generation\` events to have the following properties: From 0109746dda7f6975b6895ee76dfda1f98664555c Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Thu, 9 Apr 2026 11:03:26 +0300 Subject: [PATCH 8/9] feat(llma): migrate mastra doc to @mastra/posthog exporter --- docs/onboarding/llm-analytics/mastra.tsx | 144 +++++++++++------------ 1 file changed, 70 insertions(+), 74 deletions(-) diff --git a/docs/onboarding/llm-analytics/mastra.tsx b/docs/onboarding/llm-analytics/mastra.tsx index f6d9e8b4f11e..2a7b5f1ae414 100644 --- a/docs/onboarding/llm-analytics/mastra.tsx +++ b/docs/onboarding/llm-analytics/mastra.tsx @@ -9,126 +9,122 @@ export const getMastraSteps = (ctx: OnboardingComponentsContext): StepDefinition return [ { - title: 'Install the PostHog SDK', + title: 'Install dependencies', badge: 'required', content: ( <> - Setting up analytics starts with installing the PostHog SDK. + + + See the complete [Node.js + example](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-mastra) on + GitHub. If you're using the PostHog SDK wrapper instead, see the [Node.js wrapper + example](https://github.com/PostHog/posthog-js/tree/e08ff1be/examples/example-ai-mastra). + + - - - ), - }, - { - title: 'Install Mastra', - badge: 'required', - content: ( - <> - Install Mastra and a model provider SDK. Mastra uses the Vercel AI SDK under the hood, so you - can use any Vercel AI-compatible model provider. + Install Mastra with the official `@mastra/posthog` exporter. Mastra's observability system sends + traces to PostHog as `$ai_generation` events automatically. - - - - These SDKs **do not** proxy your calls. They only fire off an async call to PostHog in the - background to send the data. You can also use LLM analytics with other SDKs or our API, but - you will need to capture the data in the right format. See the schema in the [manual capture - section](https://posthog.com/docs/llm-analytics/installation/manual-capture) for more - details. - - ), }, { - title: 'Initialize PostHog and wrap your model', + title: 'Configure Mastra with the PostHog exporter', badge: 'required', content: ( <> - Initialize PostHog with your project token and host from [your project - settings](https://app.posthog.com/settings/project), then use `withTracing` from `@posthog/ai` - to wrap the model you pass to your Mastra agent. + Initialize Mastra with an `Observability` config that uses the `PosthogExporter`. Pass your + PostHog project token and host from [your project + settings](https://app.posthog.com/settings/project). ', - { host: '' } - ); - - const openaiClient = createOpenAI({ - apiKey: 'your_openai_api_key', - compatibility: 'strict' - }); - - const agent = new Agent({ - name: "my-agent", - instructions: "You are a helpful assistant.", - model: withTracing(openaiClient("gpt-4o"), phClient, { - posthogDistinctId: "user_123", // optional - posthogTraceId: "trace_123", // optional - posthogProperties: { conversationId: "abc123" }, // optional - posthogPrivacyMode: false, // optional - posthogGroups: { company: "companyIdInYourDb" }, // optional + import { Mastra } from '@mastra/core' + import { Agent } from '@mastra/core/agent' + import { Observability } from '@mastra/observability' + import { PosthogExporter } from '@mastra/posthog' + + const weatherAgent = new Agent({ + id: 'weather-agent', + name: 'Weather Agent', + instructions: 'You are a helpful assistant with access to weather data.', + model: { id: 'openai/gpt-4o-mini' }, + }) + + const mastra = new Mastra({ + agents: { weatherAgent }, + observability: new Observability({ + configs: { + posthog: { + serviceName: 'my-app', + exporters: [ + new PosthogExporter({ + apiKey: '', + host: '', + defaultDistinctId: 'user_123', // fallback if no userId in metadata + }), + ], + }, + }, }), - }); + }) `} /> - - - You can enrich LLM events with additional data by passing parameters such as the trace ID, - distinct ID, custom properties, groups, and privacy mode options. - ), }, { - title: 'Use your Mastra agent', + title: 'Run your agent', badge: 'required', content: ( <> - Now, when your Mastra agent makes LLM calls, PostHog automatically captures an `$ai_generation` - event for each one. + Use Mastra as normal. The `PosthogExporter` automatically captures `$ai_generation` events for + each LLM call, including token usage, cost, latency, and the full conversation. + + + + Pass `tracingOptions.metadata` to `generate()` to attach per-request metadata. The `userId` + field maps to PostHog's distinct ID, `sessionId` maps to `$ai_session_id`, and any other keys + are passed through as custom event properties.
- **Note:** If you want to capture LLM events anonymously, **don't** pass a distinct ID to the - request. See our docs on [anonymous vs identified - events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more. + **Note:** If you want to capture LLM events anonymously, omit `userId` from + `tracingOptions.metadata` and don't set `defaultDistinctId`. See our docs on [anonymous vs + identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn + more.
From 8d9388227aa510808cfd10190329a6d04d07bb7b Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Thu, 9 Apr 2026 11:16:06 +0300 Subject: [PATCH 9/9] feat(llma): split manual capture doc into steps for TOC --- docs/onboarding/llm-analytics/manual.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/onboarding/llm-analytics/manual.tsx b/docs/onboarding/llm-analytics/manual.tsx index 7636d439414f..f34322177351 100644 --- a/docs/onboarding/llm-analytics/manual.tsx +++ b/docs/onboarding/llm-analytics/manual.tsx @@ -298,13 +298,16 @@ export const getManualSteps = (ctx: OnboardingComponentsContext): StepDefinition ))} - + + ), + }, + { + title: 'Event properties', + content: ( + <> - {dedent` - ### Event Properties - - Each event type has specific properties. See the tabs below for detailed property documentation for each event type. - `} + Each event type has specific properties. See the tabs below for detailed property documentation + for each event type.