Files
2026-08-16 14:58:47 +08:00

100 lines
3.4 KiB
TypeScript

import { parseWithMinerUCloud } from '@/lib/pdf/mineru-cloud';
import { parsePDF, parseWithMinerUDocument } from '@/lib/pdf/pdf-providers';
import { PDF_PROVIDERS } from '@/lib/pdf/constants';
import type { PDFProviderConfig, PDFProviderId } from '@/lib/pdf/types';
import {
ALIDOCMIND_MIMES,
DOCUMENT_MIME_TYPES,
MINERU_CLOUD_MIMES,
MINERU_SELFHOST_MIMES,
} from '../mime';
import { parsedPdfToDocumentArtifact } from '../pdf-compat';
import type {
DocumentExtractorCapabilities,
DocumentExtractorInput,
DocumentExtractorProvider,
} from '../types';
const PDF_MIME_TYPES = [DOCUMENT_MIME_TYPES.pdf];
function capabilitiesFromPdfProvider(
provider: PDFProviderConfig,
providerId: PDFProviderId,
): DocumentExtractorCapabilities {
const features = new Set(provider.features);
const isCloudAsync = providerId === 'mineru-cloud' || providerId === 'alidocmind';
const hasOcr =
providerId === 'mineru' || providerId === 'mineru-cloud' || providerId === 'alidocmind';
return {
text: features.has('text'),
images: features.has('images'),
tables: features.has('tables'),
formulas: features.has('formulas'),
layout: features.has('layout-analysis'),
ocr: hasOcr,
async: isCloudAsync,
};
}
function supportedMimeTypesForProvider(id: PDFProviderId): readonly string[] {
switch (id) {
case 'mineru':
return MINERU_SELFHOST_MIMES;
case 'mineru-cloud':
return MINERU_CLOUD_MIMES;
case 'alidocmind':
return ALIDOCMIND_MIMES;
default:
return PDF_MIME_TYPES;
}
}
function createPdfBackedDocumentExtractor(id: PDFProviderId): DocumentExtractorProvider {
const pdfProvider = PDF_PROVIDERS[id];
return {
id,
displayName: pdfProvider.name,
supportedMimeTypes: [...supportedMimeTypesForProvider(id)],
capabilities: capabilitiesFromPdfProvider(pdfProvider, id),
async extract(input: DocumentExtractorInput) {
const config = {
providerId: id,
apiKey: input.config.apiKey,
baseUrl: input.config.baseUrl,
accessKeyId: input.config.accessKeyId,
accessKeySecret: input.config.accessKeySecret,
allowEnvFallback: input.config.allowEnvFallback,
};
let parsed;
if (id === 'alidocmind') {
// AliDocMind handles pdf/docx/pptx/xlsx/images through one flow.
parsed = await parsePDF(config, input.buffer, {
fileName: input.fileName,
mimeType: input.mimeType,
});
} else if (id === 'mineru-cloud') {
parsed = await parseWithMinerUCloud(config, input.buffer, input.fileName);
} else if (id === 'mineru') {
// Self-host MinerU routes every type (incl. pdf) through /file_parse.
parsed = await parseWithMinerUDocument(config, input.buffer, {
fileName: input.fileName || 'document.pdf',
mimeType: input.mimeType,
});
} else if (input.mimeType === DOCUMENT_MIME_TYPES.pdf) {
parsed = await parsePDF(config, input.buffer);
} else {
parsed = await parseWithMinerUDocument(config, input.buffer, {
fileName: input.fileName || 'document',
mimeType: input.mimeType,
});
}
return parsedPdfToDocumentArtifact(parsed, input);
},
};
}
export const pdfDocumentExtractorProviders: DocumentExtractorProvider[] = Object.keys(
PDF_PROVIDERS,
).map((id) => createPdfBackedDocumentExtractor(id as PDFProviderId));