Conversation
Every span that serializes the conversation carried its own full copy of each inline attachment, so one file was exported four or more times per turn and again on every later turn that replayed it. Replace base64 payloads in span input and output with a type-and-size descriptor before export: raw base64 always, data: URIs while Langfuse media upload is disabled, and serialized byte buffers. Hosts can restore full export with `inlineMediaTracing.enabled` or `LANGFUSE_TRACE_INLINE_MEDIA`.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #578
What breaks
Every span that serializes the conversation exports its own copy of each inline attachment (#578). A 2.86 MiB PDF produced a 15.3 MiB trace: four copies of the 3.8 MiB base64 payload, spread across the agent root span, the
agentspan and thellmgeneration. Runs throughAgentModelCalladd that chain and itspromptspan, and each later turn that replays the file exports it again.The Langfuse SDK extracts only
data:URIs, and only while media upload is enabled. So raw base64, Bedrock byte buffers and, with upload off,data:URIs all go out as text.Change
prepareLangfuseSpanForExportgains a step between tool-output redaction and shaping.omitLangfuseSpanInlineMedia, in the newsrc/langfuseInlineMedia.ts, parseslangfuse.observation.inputandlangfuse.observation.outputand replaces each payload with a descriptor. The rest of the part is exported unchanged:{ "type": "input_file", "filename": "report.pdf", - "file_data": "data:application/pdf;base64,JVBERi0xLjQK… (3.8 MiB)" + "file_data": "[inline media omitted from trace: application/pdf, 3001128 bytes]" }Payloads are detected by content rather than by provider part shape, so current and future layouts are both covered:
mediaandinlineData, Anthropicsource.data,input_audiodata:<mime>;base64,URI:image_url,input_file,file.file_data,video_urlBuffer({ type: 'Buffer', data: number[] }): Bedrock document and image bytesThe MIME type comes from the
data:URI, or from a siblingmimeType,mime_type,media_typeormediaTypekey. The byte count is the decoded size.Cost on the export path:
AGENTS.mdlists the new module and adds the behavior to the trace invariants.Configuration
inlineMediaTracing: { enabled: true }on the run or agentLangfuseConfig, orLANGFUSE_TRACE_INLINE_MEDIA=true, restores verbatim export.toolOutputTracing.inlineMediaTracingjoins the processor cache key.LangfuseSpanProcessorresolves it: themediaUploadEnabledparam first, thenLANGFUSE_MEDIA_UPLOAD_ENABLED, where onlyfalseand0disable.What changes for hosts
Tests
src/specs/langfuse-inline-media.test.tsruns throughcreateLangfuseSpanProcessorwith a realLangfuseSpanProcessor,startObservationand an in-memory exporter. It covers:data:URIs with filenames while upload is disabled, and left alone while it is enabledWith the new step disabled, the six omission cases fail.
langfuse-instrumentation.test.ts: processors are not reused across inline media policies.npx jest langfuse deterministic-trace-id ToolNode.langfusepasses: 12 suites, 216 tests.npx tsc --noEmit, ESLint,sort-imports --checkandcheck:circular-depsare clean.Live export to a self-hosted Langfuse, with this build applied to 3.9.7: