Spaces:
No application file
No application file
PDF 解析系统
提供统一接口支持多种 PDF 解析提供商。
支持的提供商
1. unpdf (内置)
- 成本: 免费,内置
- 特性: 基础文本提取、图片提取
- 要求: 无
- 使用: 直接上传 PDF 文件
2. MinerU (本地部署)
- 成本: 免费(需要自己部署)
- 特性:
- 高级文本提取(保留 Markdown 布局)
- 表格识别
- 公式提取(LaTeX)
- 更好的 OCR 支持
- 多种输出格式(markdown, JSON, docx, html, latex)
- 要求:
- 部署 MinerU 服务(Docker 或源码)
- 配置服务器地址
- 优势: 数据隐私、无文件大小限制
快速开始
部署 MinerU(可选)
# Docker 部署(推荐)
docker pull opendatalab/mineru:latest
docker run -d --name mineru -p 8080:8080 opendatalab/mineru:latest
# 验证
curl http://localhost:8080/api/health
API 使用
使用 unpdf(文件上传)
const formData = new FormData();
formData.append('pdf', pdfFile);
formData.append('providerId', 'unpdf');
const response = await fetch('/api/parse-pdf', {
method: 'POST',
body: formData,
});
const result = await response.json();
// result.data: ParsedPdfContent
使用 MinerU(本地服务)
const formData = new FormData();
formData.append('pdf', pdfFile);
formData.append('providerId', 'mineru');
formData.append('baseUrl', 'http://localhost:8080');
const response = await fetch('/api/parse-pdf', {
method: 'POST',
body: formData,
});
const result = await response.json();
// result.data: ParsedPdfContent with imageMapping
响应格式
interface ParsedPdfContent {
text: string; // 提取的文本(MinerU 为 Markdown)
images: string[]; // Base64 图片数组
// 扩展特性(MinerU)
tables?: Array<{
page: number;
data: string[][];
caption?: string;
}>;
formulas?: Array<{
page: number;
latex: string;
position?: { x: number; y: number; width: number; height: number };
}>;
layout?: Array<{
page: number;
type: 'title' | 'text' | 'image' | 'table' | 'formula';
content: string;
position?: { x: number; y: number; width: number; height: number };
}>;
metadata?: {
pageCount: number;
parser: 'unpdf' | 'mineru';
fileName?: string;
fileSize?: number;
processingTime?: number;
// 用于内容生成流程(MinerU)
imageMapping?: Record<string, string>; // img_1 -> base64 URL
pdfImages?: Array<{
id: string; // img_1, img_2, etc.
src: string; // base64 data URL
pageNumber: number; // PDF 页码
description?: string; // 图片描述
}>;
};
}
与内容生成集成
MinerU 解析器与内容生成流程无缝集成:
// 1. 解析 PDF
const parseResult = await parsePDF(
{
providerId: 'mineru',
baseUrl: 'http://localhost:8080',
},
buffer,
);
// 2. 提取数据
const pdfText = parseResult.text; // Markdown(含 img_1 引用)
const pdfImages = parseResult.metadata.pdfImages; // 图片数组
const imageMapping = parseResult.metadata.imageMapping; // 图片映射
// 3. 生成场景大纲
await generateSceneOutlinesFromRequirements(
requirements,
pdfText, // Markdown 内容
pdfImages, // 带页码的图片
aiCall,
);
// 4. 生成场景(含图片)
await buildSceneFromOutline(
outline,
aiCall,
stageId,
assignedImages, // 从 pdfImages 筛选
imageMapping, // 用于解析 img_1 到实际 URL
);
图片处理流程
MinerU 的图片处理:
- 提取: PDF → MinerU → Markdown + 图片
- 转换:
→ - 映射: 创建
{ "img_1": "data:image/png;base64,..." } - 生成: AI 使用
img_1引用生成幻灯片 - 解析:
resolveImageIds()替换为实际 URL - 渲染: 幻灯片显示图片
配置
全局设置
import { useSettingsStore } from '@/lib/store/settings';
useSettingsStore.setState({
pdfProviderId: 'mineru',
pdfProvidersConfig: {
mineru: {
baseUrl: 'http://localhost:8080',
apiKey: 'optional-if-needed',
},
},
});
请求级配置
// 在 API 调用时覆盖全局设置
formData.append('providerId', 'mineru');
formData.append('baseUrl', 'http://your-server:8080');
formData.append('apiKey', 'optional');
添加新的提供商
1. 定义提供商
lib/pdf/constants.ts:
export const PDF_PROVIDERS = {
myProvider: {
id: 'myProvider',
name: 'My Provider',
requiresApiKey: true,
features: ['text', 'images'],
},
};
2. 实现解析器
lib/pdf/pdf-providers.ts:
async function parseWithMyProvider(
config: PDFParserConfig,
pdfBuffer: Buffer
): Promise<ParsedPdfContent> {
// 实现解析逻辑
return {
text: '...',
images: [...],
metadata: {
pageCount: 0,
parser: 'myProvider',
},
};
}
3. 添加到路由
switch (config.providerId) {
case 'unpdf':
result = await parseWithUnpdf(pdfBuffer);
break;
case 'mineru':
result = await parseWithMinerU(config, pdfBuffer);
break;
case 'myProvider':
result = await parseWithMyProvider(config, pdfBuffer);
break;
}
调试工具
访问 http://localhost:3000/debug/pdf-parser 测试解析功能:
- 切换提供商(unpdf/MinerU)
- 上传 PDF 文件
- 配置服务器地址
- 查看解析结果
- 检查图片映射
常见问题
Q: MinerU 服务无法连接?
A: 检查:
# 服务状态
docker ps | grep mineru
# 网络连通性
curl http://localhost:8080/api/health
# 日志
docker logs mineru
Q: 图片不显示?
A: 确保:
imageMapping正确传递到 scene-stream API- 图片 ID 格式正确(img_1, img_2)
- Base64 编码完整
Q: 解析速度慢?
A: 优化:
# 增加 Docker 资源
docker run -d \
--name mineru \
-p 8080:8080 \
--memory=4g \
--cpus=2 \
opendatalab/mineru:latest
Q: unpdf vs MinerU 如何选择?
A: 选择建议:
| 场景 | 推荐 |
|---|---|
| 简单 PDF(纯文本) | unpdf |
| 包含表格、公式 | MinerU |
| 需要保留布局 | MinerU |
| 快速测试 | unpdf |
| 生产环境 | MinerU |
| 无法部署服务 | unpdf |
性能建议
MinerU 并发处理
const files = [file1, file2, file3];
const results = await Promise.all(
files.map((file) => {
const formData = new FormData();
formData.append('pdf', file);
formData.append('providerId', 'mineru');
return fetch('/api/parse-pdf', {
method: 'POST',
body: formData,
}).then((r) => r.json());
}),
);
结果缓存
// 考虑缓存解析结果
const cacheKey = `pdf_${fileHash}`;
const cached = localStorage.getItem(cacheKey);
if (cached) {
return JSON.parse(cached);
}
参考资源
- MinerU GitHub: https://github.com/opendatalab/MinerU
- 快速开始:
/MINERU_QUICKSTART.md - 变更说明:
/MINERU_LOCAL_DEPLOYMENT.md - 调试工具: http://localhost:3000/debug/pdf-parser
最后更新: 2026-02-11 模式: 本地自托管 状态: 生产就绪