File size: 4,250 Bytes
f0743f4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | import { Providers } from '@librechat/agents';
import { isOpenAILikeProvider, isDocumentSupportedProvider } from 'librechat-data-provider';
import type { IMongoFile } from '@librechat/data-schemas';
import type {
AnthropicDocumentBlock,
StrategyFunctions,
DocumentResult,
ServerRequest,
} from '~/types';
import { getFileStream, getConfiguredFileSizeLimit } from './utils';
import { validatePdf } from '~/files/validation';
/**
* Processes and encodes document files for various providers
* @param req - Express request object
* @param files - Array of file objects to process
* @param params - Object containing provider, endpoint, and other options
* @param params.provider - The provider name
* @param params.endpoint - Optional endpoint name for file config lookup
* @param params.useResponsesApi - Whether to use responses API format
* @param getStrategyFunctions - Function to get strategy functions
* @returns Promise that resolves to documents and file metadata
*/
export async function encodeAndFormatDocuments(
req: ServerRequest,
files: IMongoFile[],
params: { provider: Providers; endpoint?: string; useResponsesApi?: boolean },
getStrategyFunctions: (source: string) => StrategyFunctions,
): Promise<DocumentResult> {
const { provider, endpoint, useResponsesApi } = params;
if (!files?.length) {
return { documents: [], files: [] };
}
const encodingMethods: Record<string, StrategyFunctions> = {};
const result: DocumentResult = { documents: [], files: [] };
const documentFiles = files.filter(
(file) => file.type === 'application/pdf' || file.type?.startsWith('application/'),
);
if (!documentFiles.length) {
return result;
}
const results = await Promise.allSettled(
documentFiles.map((file) => {
if (file.type !== 'application/pdf' || !isDocumentSupportedProvider(provider)) {
return Promise.resolve(null);
}
return getFileStream(req, file, encodingMethods, getStrategyFunctions);
}),
);
for (const settledResult of results) {
if (settledResult.status === 'rejected') {
console.error('Document processing failed:', settledResult.reason);
continue;
}
const processed = settledResult.value;
if (!processed) continue;
const { file, content, metadata } = processed;
if (!content || !file) {
if (metadata) result.files.push(metadata);
continue;
}
if (file.type === 'application/pdf' && isDocumentSupportedProvider(provider)) {
const pdfBuffer = Buffer.from(content, 'base64');
/** Extract configured file size limit from fileConfig for this endpoint */
const configuredFileSizeLimit = getConfiguredFileSizeLimit(req, {
provider,
endpoint,
});
const validation = await validatePdf(
pdfBuffer,
pdfBuffer.length,
provider,
configuredFileSizeLimit,
);
if (!validation.isValid) {
throw new Error(`PDF validation failed: ${validation.error}`);
}
if (provider === Providers.ANTHROPIC) {
const document: AnthropicDocumentBlock = {
type: 'document',
source: {
type: 'base64',
media_type: 'application/pdf',
data: content,
},
citations: { enabled: true },
};
if (file.filename) {
document.context = `File: "${file.filename}"`;
}
result.documents.push(document);
} else if (useResponsesApi) {
result.documents.push({
type: 'input_file',
filename: file.filename,
file_data: `data:application/pdf;base64,${content}`,
});
} else if (provider === Providers.GOOGLE || provider === Providers.VERTEXAI) {
result.documents.push({
type: 'media',
mimeType: 'application/pdf',
data: content,
});
} else if (isOpenAILikeProvider(provider) && provider != Providers.AZURE) {
result.documents.push({
type: 'file',
file: {
filename: file.filename,
file_data: `data:application/pdf;base64,${content}`,
},
});
}
result.files.push(metadata);
}
}
return result;
}
|