mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-19 06:45:50 +00:00
fix: 修复缓存
This commit is contained in:
@@ -2907,7 +2907,12 @@ async function* queryModel(
|
|||||||
provider: getAPIProvider(),
|
provider: getAPIProvider(),
|
||||||
input: convertMessagesToLangfuse(messagesForAPI, systemPrompt),
|
input: convertMessagesToLangfuse(messagesForAPI, systemPrompt),
|
||||||
output: convertOutputToLangfuse(newMessages),
|
output: convertOutputToLangfuse(newMessages),
|
||||||
usage: { input_tokens: usage.input_tokens, output_tokens: usage.output_tokens },
|
usage: {
|
||||||
|
input_tokens: usage.input_tokens,
|
||||||
|
output_tokens: usage.output_tokens,
|
||||||
|
cache_creation_input_tokens: usage.cache_creation_input_tokens,
|
||||||
|
cache_read_input_tokens: usage.cache_read_input_tokens,
|
||||||
|
},
|
||||||
startTime: new Date(startIncludingRetries),
|
startTime: new Date(startIncludingRetries),
|
||||||
endTime: new Date(),
|
endTime: new Date(),
|
||||||
completionStartTime: ttftMs > 0 ? new Date(start + ttftMs) : undefined,
|
completionStartTime: ttftMs > 0 ? new Date(start + ttftMs) : undefined,
|
||||||
|
|||||||
@@ -284,6 +284,48 @@ describe('Langfuse integration', () => {
|
|||||||
}))
|
}))
|
||||||
expect(mockRootEnd).toHaveBeenCalled()
|
expect(mockRootEnd).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('includes cache tokens in usageDetails when provided', async () => {
|
||||||
|
process.env.LANGFUSE_PUBLIC_KEY = 'pk-test'
|
||||||
|
process.env.LANGFUSE_SECRET_KEY = 'sk-test'
|
||||||
|
const { createTrace, recordLLMObservation } = await import('../tracing.js')
|
||||||
|
const span = createTrace({ sessionId: 's1', model: 'claude-3', provider: 'firstParty' })
|
||||||
|
mockStartObservation.mockClear()
|
||||||
|
mockRootUpdate.mockClear()
|
||||||
|
recordLLMObservation(span, {
|
||||||
|
model: 'claude-3',
|
||||||
|
provider: 'firstParty',
|
||||||
|
input: [],
|
||||||
|
output: [],
|
||||||
|
usage: { input_tokens: 10000, output_tokens: 50, cache_creation_input_tokens: 2000, cache_read_input_tokens: 7000 },
|
||||||
|
})
|
||||||
|
expect(mockRootUpdate).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
usageDetails: {
|
||||||
|
input: 19000, // 10000 + 2000 + 7000
|
||||||
|
output: 50,
|
||||||
|
cache_read: 7000,
|
||||||
|
cache_creation: 2000,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('omits cache fields when not provided', async () => {
|
||||||
|
process.env.LANGFUSE_PUBLIC_KEY = 'pk-test'
|
||||||
|
process.env.LANGFUSE_SECRET_KEY = 'sk-test'
|
||||||
|
const { createTrace, recordLLMObservation } = await import('../tracing.js')
|
||||||
|
const span = createTrace({ sessionId: 's1', model: 'claude-3', provider: 'firstParty' })
|
||||||
|
mockRootUpdate.mockClear()
|
||||||
|
recordLLMObservation(span, {
|
||||||
|
model: 'claude-3',
|
||||||
|
provider: 'firstParty',
|
||||||
|
input: [],
|
||||||
|
output: [],
|
||||||
|
usage: { input_tokens: 100, output_tokens: 20 },
|
||||||
|
})
|
||||||
|
expect(mockRootUpdate).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
usageDetails: { input: 100, output: 20 },
|
||||||
|
}))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('recordToolObservation', () => {
|
describe('recordToolObservation', () => {
|
||||||
|
|||||||
@@ -68,7 +68,12 @@ export function recordLLMObservation(
|
|||||||
provider: string
|
provider: string
|
||||||
input: unknown
|
input: unknown
|
||||||
output: unknown
|
output: unknown
|
||||||
usage: { input_tokens: number; output_tokens: number }
|
usage: {
|
||||||
|
input_tokens: number
|
||||||
|
output_tokens: number
|
||||||
|
cache_creation_input_tokens?: number
|
||||||
|
cache_read_input_tokens?: number
|
||||||
|
}
|
||||||
startTime?: Date
|
startTime?: Date
|
||||||
endTime?: Date
|
endTime?: Date
|
||||||
completionStartTime?: Date
|
completionStartTime?: Date
|
||||||
@@ -109,11 +114,17 @@ export function recordLLMObservation(
|
|||||||
gen.otelSpan.setAttribute(LangfuseOtelSpanAttributes.TRACE_USER_ID, userId)
|
gen.otelSpan.setAttribute(LangfuseOtelSpanAttributes.TRACE_USER_ID, userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Anthropic splits input into uncached + cache_read + cache_creation.
|
||||||
|
// Langfuse's "input" should be the total prompt tokens so cost calc is correct.
|
||||||
|
const cacheRead = params.usage.cache_read_input_tokens ?? 0
|
||||||
|
const cacheCreation = params.usage.cache_creation_input_tokens ?? 0
|
||||||
gen.update({
|
gen.update({
|
||||||
output: params.output,
|
output: params.output,
|
||||||
usageDetails: {
|
usageDetails: {
|
||||||
input: params.usage.input_tokens,
|
input: params.usage.input_tokens + cacheCreation + cacheRead,
|
||||||
output: params.usage.output_tokens,
|
output: params.usage.output_tokens,
|
||||||
|
...(cacheRead > 0 && { cache_read: cacheRead }),
|
||||||
|
...(cacheCreation > 0 && { cache_creation: cacheCreation }),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user