feat(llma): add $ai_stop_reason property to LLM analytics#54037
Conversation
Captures the LLM's reason for stopping generation (e.g. "stop", "end_turn", "tool_use", "SAFETY") as a top-level queryable event property. Previously, finish_reason was stripped from OTel events and never extracted from SDK wrappers.
Prompt To Fix All With AIThis is a comment left during a code review.
Path: nodejs/src/ingestion/ai/otel/middleware/vercel-ai.test.ts
Line: 97
Comment:
**Missing test for `gen_ai.response.finish_reasons` array path**
The `gen_ai.response.finish_reasons` fallback (the `else if` branch in `vercel-ai.ts`) is untested. That branch has its own logic — array type check plus `[0]` indexing — and currently any breakage there would go undetected. A parametrised test covering `ai.response.finishReason` (primary), `gen_ai.response.finish_reasons` array (fallback), and neither present (undefined) would cover the three cases OnceAndOnlyOnce.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: nodejs/src/ingestion/ai/otel/middleware/traceloop.test.ts
Line: 207-208
Comment:
**`finish_reason`-only path is not exercised**
The test has both `llm.response.stop_reason` and `llm.response.finish_reason` present. The case where only `llm.response.finish_reason` is provided (no `stop_reason`) is untested, so a regression in the `??` fallback would go undetected. A parametrised test covering both-present (stop_reason wins), finish_reason-only, and neither-present (undefined) would match the preference for parameterised tests.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "feat(llma): add $ai_stop_reason property..." | Re-trigger Greptile |
|
Size Change: +8.45 kB (+0.01%) Total Size: 128 MB
ℹ️ View Unchanged
|
| expect(key).not.toBe('operation.name') | ||
| expect(key).not.toBe('resource.name') | ||
| } | ||
| expect(event.properties!['$ai_stop_reason']).toBe('stop') |
There was a problem hiding this comment.
Missing test for
gen_ai.response.finish_reasons array path
The gen_ai.response.finish_reasons fallback (the else if branch in vercel-ai.ts) is untested. That branch has its own logic — array type check plus [0] indexing — and currently any breakage there would go undetected. A parametrised test covering ai.response.finishReason (primary), gen_ai.response.finish_reasons array (fallback), and neither present (undefined) would cover the three cases OnceAndOnlyOnce.
Prompt To Fix With AI
This is a comment left during a code review.
Path: nodejs/src/ingestion/ai/otel/middleware/vercel-ai.test.ts
Line: 97
Comment:
**Missing test for `gen_ai.response.finish_reasons` array path**
The `gen_ai.response.finish_reasons` fallback (the `else if` branch in `vercel-ai.ts`) is untested. That branch has its own logic — array type check plus `[0]` indexing — and currently any breakage there would go undetected. A parametrised test covering `ai.response.finishReason` (primary), `gen_ai.response.finish_reasons` array (fallback), and neither present (undefined) would cover the three cases OnceAndOnlyOnce.
How can I resolve this? If you propose a fix, please make it concise.| // stop_reason takes priority over finish_reason | ||
| expect(event.properties!['$ai_stop_reason']).toBe('end_turn') |
There was a problem hiding this comment.
finish_reason-only path is not exercised
The test has both llm.response.stop_reason and llm.response.finish_reason present. The case where only llm.response.finish_reason is provided (no stop_reason) is untested, so a regression in the ?? fallback would go undetected. A parametrised test covering both-present (stop_reason wins), finish_reason-only, and neither-present (undefined) would match the preference for parameterised tests.
Prompt To Fix With AI
This is a comment left during a code review.
Path: nodejs/src/ingestion/ai/otel/middleware/traceloop.test.ts
Line: 207-208
Comment:
**`finish_reason`-only path is not exercised**
The test has both `llm.response.stop_reason` and `llm.response.finish_reason` present. The case where only `llm.response.finish_reason` is provided (no `stop_reason`) is untested, so a regression in the `??` fallback would go undetected. A parametrised test covering both-present (stop_reason wins), finish_reason-only, and neither-present (undefined) would match the preference for parameterised tests.
How can I resolve this? If you propose a fix, please make it concise.
andrewm4894
left a comment
There was a problem hiding this comment.
oh interesting - we can do some stuff with this one i think
|
🎭 Playwright report · View test results →
These issues are not necessarily caused by your changes. |
|
Companion PRs:
|
- Test finish_reason-only path (no stop_reason) in traceloop middleware - Test gen_ai.response.finish_reasons array path in vercel-ai middleware - Test undefined when neither reason is present
|
This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, please remove the |
…top-reason # Conflicts: # frontend/src/taxonomy/core-filter-definitions-by-group.json
|
⏭️ Skipped snapshot commit because branch advanced to The new commit will trigger its own snapshot update workflow. If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:
|
Reflects PR #54037 which adds $ai_stop_reason to LLM analytics, capturing why model responses ended (e.g. stop, end_turn, max_tokens, tool_use).
Problem
LLM analytics users cannot filter or analyze why model responses ended. The finish/stop reason from providers (e.g.
stop,end_turn,tool_use,max_tokens,SAFETY) was either stripped from OTel events or never extracted by SDK wrappers. This was reported as a user feature request on the LLM analytics docs page.Changes
llm.response.finish_reason,llm.response.stop_reason,ai.response.finishReason, andgen_ai.response.finish_reasonsto$ai_stop_reasoninstead of stripping them$ai_stop_reasonproperty definition intaxonomy.py,hogql/ai.py, and regenerated frontend JSONCompanion PRs:
@posthog/aiextraction for OpenAI, Anthropic, Gemini, Vercel AI SDK, LangChainHow did you test this code?
Publish to changelog?
no