Skip to content

Commit 6536757

Browse files
feat: 对其他 provider 提供 langfuse 监控
1 parent a0dc454 commit 6536757

3 files changed

Lines changed: 66 additions & 0 deletions

File tree

src/services/api/gemini/index.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import type { SDKAssistantMessageError } from '../../../entrypoints/agentSdkType
1818
import type { SystemPrompt } from '../../../utils/systemPromptType.js'
1919
import type { ThinkingConfig } from '../../../utils/thinking.js'
2020
import type { Options } from '../claude.js'
21+
import { recordLLMObservation } from '../../../services/langfuse/tracing.js'
22+
import { convertMessagesToLangfuse, convertOutputToLangfuse, convertToolsToLangfuse } from '../../../services/langfuse/convert.js'
2123
import { streamGeminiGenerateContent } from './client.js'
2224
import { anthropicMessagesToGemini, resolveGeminiModel, adaptGeminiStreamToAnthropic, anthropicToolsToGemini, anthropicToolChoiceToGemini, GEMINI_THOUGHT_SIGNATURE_FIELD } from '@ant/model-provider'
2325

@@ -100,6 +102,7 @@ export async function* queryModelGemini(
100102

101103
const adaptedStream = adaptGeminiStreamToAnthropic(stream, geminiModel)
102104
const contentBlocks: Record<number, any> = {}
105+
const collectedMessages: AssistantMessage[] = []
103106
let partialMessage: any = undefined
104107
let ttftMs = 0
105108
const start = Date.now()
@@ -160,6 +163,7 @@ export async function* queryModelGemini(
160163
uuid: randomUUID(),
161164
timestamp: new Date().toISOString(),
162165
}
166+
collectedMessages.push(message)
163167
yield message
164168
break
165169
}
@@ -174,6 +178,22 @@ export async function* queryModelGemini(
174178
...(event.type === 'message_start' ? { ttftMs } : undefined),
175179
} as StreamEvent
176180
}
181+
182+
// Record LLM observation in Langfuse (no-op if not configured)
183+
recordLLMObservation(options.langfuseTrace ?? null, {
184+
model: geminiModel,
185+
provider: 'gemini',
186+
input: convertMessagesToLangfuse(messagesForAPI, systemPrompt),
187+
output: convertOutputToLangfuse(collectedMessages),
188+
usage: {
189+
input_tokens: 0,
190+
output_tokens: 0,
191+
},
192+
startTime: new Date(start),
193+
endTime: new Date(),
194+
completionStartTime: ttftMs > 0 ? new Date(start + ttftMs) : undefined,
195+
tools: convertToolsToLangfuse(toolSchemas as unknown[]),
196+
})
177197
} catch (error) {
178198
const errorMessage = error instanceof Error ? error.message : String(error)
179199
logForDebugging(`[Gemini] Error: ${errorMessage}`, { level: 'error' })

src/services/api/grok/index.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { toolToAPISchema } from '../../../utils/api.js'
1414
import { logForDebugging } from '../../../utils/debug.js'
1515
import { addToTotalSessionCost } from '../../../cost-tracker.js'
1616
import { calculateUSDCost } from '../../../utils/modelCost.js'
17+
import { recordLLMObservation } from '../../../services/langfuse/tracing.js'
18+
import { convertMessagesToLangfuse, convertOutputToLangfuse, convertToolsToLangfuse } from '../../../services/langfuse/convert.js'
1719
import type { Options } from '../claude.js'
1820
import { randomUUID } from 'crypto'
1921
import {
@@ -92,6 +94,7 @@ export async function* queryModelGrok(
9294
const adaptedStream = adaptOpenAIStreamToAnthropic(stream as AsyncIterable<ChatCompletionChunk>, grokModel)
9395

9496
const contentBlocks: Record<number, any> = {}
97+
const collectedMessages: AssistantMessage[] = []
9598
let partialMessage: any = undefined
9699
let usage = {
97100
input_tokens: 0,
@@ -157,6 +160,7 @@ export async function* queryModelGrok(
157160
uuid: randomUUID(),
158161
timestamp: new Date().toISOString(),
159162
}
163+
collectedMessages.push(m)
160164
yield m
161165
break
162166
}
@@ -182,6 +186,24 @@ export async function* queryModelGrok(
182186
...(event.type === 'message_start' ? { ttftMs } : undefined),
183187
} as StreamEvent
184188
}
189+
190+
// Record LLM observation in Langfuse (no-op if not configured)
191+
recordLLMObservation(options.langfuseTrace ?? null, {
192+
model: grokModel,
193+
provider: 'grok',
194+
input: convertMessagesToLangfuse(messagesForAPI, systemPrompt),
195+
output: convertOutputToLangfuse(collectedMessages),
196+
usage: {
197+
input_tokens: usage.input_tokens,
198+
output_tokens: usage.output_tokens,
199+
cache_creation_input_tokens: usage.cache_creation_input_tokens,
200+
cache_read_input_tokens: usage.cache_read_input_tokens,
201+
},
202+
startTime: new Date(start),
203+
endTime: new Date(),
204+
completionStartTime: ttftMs > 0 ? new Date(start + ttftMs) : undefined,
205+
tools: convertToolsToLangfuse(toolSchemas as unknown[]),
206+
})
185207
} catch (error) {
186208
const errorMessage = error instanceof Error ? error.message : String(error)
187209
logForDebugging(`[Grok] Error: ${errorMessage}`, { level: 'error' })

src/services/api/openai/index.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { logForDebugging } from '../../../utils/debug.js'
2424
import { addToTotalSessionCost } from '../../../cost-tracker.js'
2525
import { calculateUSDCost } from '../../../utils/modelCost.js'
2626
import { isOpenAIThinkingEnabled, resolveOpenAIMaxTokens, buildOpenAIRequestBody } from './requestBody.js'
27+
import { recordLLMObservation } from '../../../services/langfuse/tracing.js'
28+
import { convertMessagesToLangfuse, convertOutputToLangfuse, convertToolsToLangfuse } from '../../../services/langfuse/convert.js'
2729
export { isOpenAIThinkingEnabled, resolveOpenAIMaxTokens, buildOpenAIRequestBody }
2830
import { getModelMaxOutputTokens } from '../../../utils/context.js'
2931
import type { Options } from '../claude.js'
@@ -246,6 +248,7 @@ export async function* queryModelOpenAI(
246248

247249
// Accumulate content blocks and usage, same as the Anthropic path in claude.ts
248250
const contentBlocks: Record<number, any> = {}
251+
const collectedMessages: AssistantMessage[] = []
249252
let partialMessage: any
250253
let stopReason: string | null = null
251254
let usage = {
@@ -323,6 +326,9 @@ export async function* queryModelOpenAI(
323326
partialMessage, contentBlocks, tools, agentId: options.agentId,
324327
usage, stopReason, maxTokens,
325328
})) {
329+
if (output.type === 'assistant') {
330+
collectedMessages.push(output)
331+
}
326332
yield output
327333
}
328334
// Reset partialMessage so the post-loop safety fallback does not
@@ -346,6 +352,24 @@ export async function* queryModelOpenAI(
346352
} as StreamEvent
347353
}
348354

355+
// Record LLM observation in Langfuse (no-op if not configured)
356+
recordLLMObservation(options.langfuseTrace ?? null, {
357+
model: openaiModel,
358+
provider: 'openai',
359+
input: convertMessagesToLangfuse(messagesForAPI, systemPrompt),
360+
output: convertOutputToLangfuse(collectedMessages),
361+
usage: {
362+
input_tokens: usage.input_tokens,
363+
output_tokens: usage.output_tokens,
364+
cache_creation_input_tokens: usage.cache_creation_input_tokens,
365+
cache_read_input_tokens: usage.cache_read_input_tokens,
366+
},
367+
startTime: new Date(start),
368+
endTime: new Date(),
369+
completionStartTime: ttftMs > 0 ? new Date(start + ttftMs) : undefined,
370+
tools: convertToolsToLangfuse(toolSchemas as unknown[]),
371+
})
372+
349373
// Safety: if stream ended without message_stop, assemble and yield whatever we have
350374
if (partialMessage) {
351375
for (const output of assembleFinalAssistantOutputs({

0 commit comments

Comments
 (0)