Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions packages/components/nodes/agentflow/Agent/Agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1378,9 +1378,24 @@ class Agent_Agentflow implements INode {
isStructuredOutput
)

// End analytics tracking
// End analytics tracking (send full output for usage/cost)
if (analyticHandlers && llmIds) {
await analyticHandlers.onLLMEnd(llmIds, finalResponse)
const outputObj = this.prepareOutputObject(
response,
availableTools,
finalResponse,
startTime,
endTime,
timeDelta,
usedTools,
sourceDocuments,
artifacts,
additionalTokens,
isWaitingForHumanInput ?? false,
fileAnnotations,
isStructuredOutput
)
await analyticHandlers.onLLMEnd(llmIds, outputObj)
Comment thread
vellanki-santhosh marked this conversation as resolved.
}

// Send additional streaming events if needed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,12 +376,14 @@ class ConditionAgent_Agentflow implements INode {
const endTime = Date.now()
const timeDelta = endTime - startTime

// End analytics tracking
// End analytics tracking (pass usage metadata if present)
if (analyticHandlers && llmIds) {
await analyticHandlers.onLLMEnd(
llmIds,
typeof response.content === 'string' ? response.content : JSON.stringify(response.content)
)
const outputObj: any = {
content: typeof response.content === 'string' ? response.content : JSON.stringify(response.content)
}
if (response.usage_metadata) outputObj.usageMetadata = response.usage_metadata
if (response.response_metadata) outputObj.responseMetadata = response.response_metadata
await analyticHandlers.onLLMEnd(llmIds, outputObj)
}

let calledOutputName: string
Expand Down
4 changes: 2 additions & 2 deletions packages/components/nodes/agentflow/LLM/LLM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,9 @@ class LLM_Agentflow implements INode {
fileAnnotations
)

// End analytics tracking
// End analytics tracking (send full output for usage/cost)
if (analyticHandlers && llmIds) {
await analyticHandlers.onLLMEnd(llmIds, finalResponse)
await analyticHandlers.onLLMEnd(llmIds, output)
}

// Send additional streaming events if needed
Expand Down
62 changes: 55 additions & 7 deletions packages/components/src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1400,7 +1400,7 @@ export class AnalyticHandler {
return returnIds
}

async onLLMEnd(returnIds: ICommonObject, output: string) {
async onLLMEnd(returnIds: ICommonObject, output: any) {
if (Object.prototype.hasOwnProperty.call(this.handlers, 'langSmith')) {
const llmRun: RunTree | undefined = this.handlers['langSmith'].llmRun[returnIds['langSmith'].llmRun]
if (llmRun) {
Expand All @@ -1416,9 +1416,33 @@ export class AnalyticHandler {
if (Object.prototype.hasOwnProperty.call(this.handlers, 'langFuse')) {
const generation: LangfuseGenerationClient | undefined = this.handlers['langFuse'].generation[returnIds['langFuse'].generation]
if (generation) {
generation.end({
output: output
})
let outputText: string = ''
let usage: { promptTokens?: number; completionTokens?: number; totalTokens?: number } | undefined
let model: string | undefined

if (typeof output === 'string') {
outputText = output
} else if (output && typeof output === 'object') {
outputText = typeof output.content === 'string' ? output.content : tryJsonStringify(output, '[output]')
const usageMetadata = output.usageMetadata || output.usage_metadata
if (usageMetadata) {
usage = {
promptTokens: usageMetadata.input_tokens ?? usageMetadata.prompt_tokens ?? undefined,
completionTokens: usageMetadata.output_tokens ?? usageMetadata.completion_tokens ?? undefined,
totalTokens: usageMetadata.total_tokens ?? undefined
}
}
const responseMetadata = output.responseMetadata || output.response_metadata
if (responseMetadata) {
model = responseMetadata.model || responseMetadata.model_name || responseMetadata.modelId || undefined
}
}

const payload: any = { output: outputText }
if (usage && (usage.promptTokens || usage.completionTokens || usage.totalTokens)) payload.usage = usage
Comment thread
vellanki-santhosh marked this conversation as resolved.
if (model) payload.model = model

generation.end(payload)
}
}

Expand Down Expand Up @@ -1490,9 +1514,33 @@ export class AnalyticHandler {
if (Object.prototype.hasOwnProperty.call(this.handlers, 'langFuse')) {
const generation: LangfuseGenerationClient | undefined = this.handlers['langFuse'].generation[returnIds['langFuse'].generation]
if (generation) {
generation.end({
output: error
})
let errorText: string = ''
let usage: { promptTokens?: number; completionTokens?: number; totalTokens?: number } | undefined
let model: string | undefined

if (typeof error === 'string') {
errorText = error
} else if (error && typeof error === 'object') {
errorText = typeof error.message === 'string' ? error.message : tryJsonStringify(error, '[error]')
const usageMetadata = (error as any).usageMetadata || (error as any).usage_metadata
if (usageMetadata) {
usage = {
promptTokens: usageMetadata.input_tokens ?? usageMetadata.prompt_tokens ?? undefined,
completionTokens: usageMetadata.output_tokens ?? usageMetadata.completion_tokens ?? undefined,
totalTokens: usageMetadata.total_tokens ?? undefined
}
}
const responseMetadata = (error as any).responseMetadata || (error as any).response_metadata
if (responseMetadata) {
model = responseMetadata.model || responseMetadata.model_name || responseMetadata.modelId || undefined
}
}

const payload: any = { output: errorText, level: 'ERROR' }
if (usage && (usage.promptTokens || usage.completionTokens || usage.totalTokens)) payload.usage = usage
Comment thread
vellanki-santhosh marked this conversation as resolved.
if (model) payload.model = model

generation.end(payload)
}
}

Expand Down