From f59daaeecc6299a3f432cf552d92a4159be5f278 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Thu, 16 Oct 2025 23:24:14 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=84=20feat:=20Context=20Field=20for=20?= =?UTF-8?q?Anthropic=20Documents=20(PDF)=20(#10148)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Remove ephemeral cache control from document encoding function * refactor: Improve document encoding types and add file context for anthropic messages api - Added AnthropicDocumentBlock interface to define the structure for documents from the Anthropic provider. - Updated encodeAndFormatDocuments function to utilize the new type and include optional context for filenames. - Refactored DocumentResult to use a union type for various document formats, improving type safety and clarity. --- packages/api/src/files/encode/document.ts | 13 +++-- packages/api/src/types/files.ts | 66 +++++++++++++++-------- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/packages/api/src/files/encode/document.ts b/packages/api/src/files/encode/document.ts index bc1396958c..338a4ddea6 100644 --- a/packages/api/src/files/encode/document.ts +++ b/packages/api/src/files/encode/document.ts @@ -2,7 +2,7 @@ import { Providers } from '@librechat/agents'; import { isOpenAILikeProvider, isDocumentSupportedProvider } from 'librechat-data-provider'; import type { IMongoFile } from '@librechat/data-schemas'; import type { Request } from 'express'; -import type { StrategyFunctions, DocumentResult } from '~/types/files'; +import type { StrategyFunctions, DocumentResult, AnthropicDocumentBlock } from '~/types/files'; import { validatePdf } from '~/files/validation'; import { getFileStream } from './utils'; @@ -69,16 +69,21 @@ export async function encodeAndFormatDocuments( } if (provider === Providers.ANTHROPIC) { - result.documents.push({ + const document: AnthropicDocumentBlock = { type: 'document', source: { type: 'base64', media_type: 'application/pdf', data: content, }, - cache_control: { type: 'ephemeral' }, citations: { enabled: true }, - }); + }; + + if (file.filename) { + document.context = `File: "${file.filename}"`; + } + + result.documents.push(document); } else if (useResponsesApi) { result.documents.push({ type: 'input_file', diff --git a/packages/api/src/types/files.ts b/packages/api/src/types/files.ts index dc37410050..5b25f0b3e9 100644 --- a/packages/api/src/types/files.ts +++ b/packages/api/src/types/files.ts @@ -46,29 +46,51 @@ export interface VideoResult { }>; } +/** Anthropic document block format */ +export interface AnthropicDocumentBlock { + type: 'document'; + source: { + type: string; + media_type: string; + data: string; + }; + context?: string; + title?: string; + cache_control?: { type: string }; + citations?: { enabled: boolean }; +} + +/** Google document block format */ +export interface GoogleDocumentBlock { + type: 'document'; + mimeType: string; + data: string; +} + +/** OpenAI file block format */ +export interface OpenAIFileBlock { + type: 'file'; + file: { + filename: string; + file_data: string; + }; +} + +/** OpenAI Responses API file format */ +export interface OpenAIInputFileBlock { + type: 'input_file'; + filename: string; + file_data: string; +} + +export type DocumentBlock = + | AnthropicDocumentBlock + | GoogleDocumentBlock + | OpenAIFileBlock + | OpenAIInputFileBlock; + export interface DocumentResult { - documents: Array<{ - type: 'document' | 'file' | 'input_file'; - /** Anthropic File Format, `document` */ - source?: { - type: string; - media_type: string; - data: string; - }; - cache_control?: { type: string }; - citations?: { enabled: boolean }; - /** Google File Format, `document` */ - mimeType?: string; - data?: string; - /** OpenAI File Format, `file` */ - file?: { - filename?: string; - file_data?: string; - }; - /** OpenAI Responses API File Format, `input_file` */ - filename?: string; - file_data?: string; - }>; + documents: DocumentBlock[]; files: Array<{ file_id?: string; temp_file_id?: string;