mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-21 03:35:36 +00:00
pdf parse doc (#3990)
This commit is contained in:
BIN
docSite/assets/imgs/image copy.png
Normal file
BIN
docSite/assets/imgs/image copy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 329 KiB |
BIN
docSite/assets/imgs/marker2.png
Normal file
BIN
docSite/assets/imgs/marker2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 216 KiB |
BIN
docSite/assets/imgs/marker3.png
Normal file
BIN
docSite/assets/imgs/marker3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 85 KiB |
@@ -25,7 +25,52 @@ weight: 707
|
||||
"qaMaxProcess": 15, // 问答拆分线程数量
|
||||
"vlmMaxProcess": 15, // 图片理解模型最大处理进程
|
||||
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
||||
"pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||
"pgHNSWEfSearch": 100, // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||
"customPdfParse": { // 4.9.0 新增配置
|
||||
"url": "", // 自定义 PDF 解析服务地址
|
||||
"key": "", // 自定义 PDF 解析服务密钥
|
||||
"doc2xKey": "", // doc2x 服务密钥
|
||||
"price": 0 // PDF 解析服务价格
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 自定义 PDF 解析配置
|
||||
|
||||
自定义 PDF 服务解析的优先级高于 Doc2x 服务,所以如果使用 Doc2x 服务,请勿配置自定义 PDF 服务。
|
||||
|
||||
### 使用 Sealos PDF 解析服务
|
||||
|
||||
#### 1. 申请 Sealos AI proxy API Key
|
||||
|
||||
[点击打开 Sealos Pdf parser 官网](https://cloud.sealos.run/?uid=fnWRt09fZP&openapp=system-aiproxy),并进行对应 API Key 的申请。
|
||||
|
||||
#### 2. 修改 FastGPT 配置文件
|
||||
|
||||
`systemEnv.customPdfParse.url`填写成`https://aiproxy.hzh.sealos.run/v1/parse/pdf?model=parse-pdf`
|
||||
`systemEnv.customPdfParse.key`填写成在 Sealos AI proxy 中申请的 API Key。
|
||||
|
||||

|
||||
|
||||
### 使用 Doc2x 解析 PDF 文件
|
||||
|
||||
`Doc2x`是一个国内提供专业 PDF 解析。
|
||||
|
||||
#### 1. 申请 Doc2x 服务
|
||||
|
||||
[点击打开 Doc2x 官网](https://doc2x.noedgeai.com?inviteCode=9EACN2),并进行对应 API Key 的申请。
|
||||
|
||||
#### 2. 修改 FastGPT 配置文件
|
||||
|
||||
开源版用户在 `config.json` 文件中添加 `systemEnv.customPdfParse.doc2xKey` 配置,并填写上申请到的 API Key。并重启服务。
|
||||
|
||||
商业版用户在 Admin 后台根据表单指引填写 Doc2x 服务密钥。
|
||||
|
||||
#### 3. 开始使用
|
||||
|
||||
在知识库导入数据或应用文件上传配置中,可以勾选`PDF 增强解析`,则在对 PDF 解析时候,会使用 Doc2x 服务进行解析。
|
||||
|
||||
### 使用 Marker 解析 PDF 文件
|
||||
|
||||
[点击查看 Marker 接入教程](/docs/development/custom-models/marker)
|
@@ -11,13 +11,13 @@ weight: 909
|
||||
|
||||
PDF 是一个相对复杂的文件格式,在 FastGPT 内置的 pdf 解析器中,依赖的是 pdfjs 库解析,该库基于逻辑解析,无法有效的理解复杂的 pdf 文件。所以我们在解析 pdf 时候,如果遇到图片、表格、公式等非简单文本内容,会发现解析效果不佳。
|
||||
|
||||
市面上目前有多种解析 PDF 的方法,比如使用 [Marker](https://github.com/VikParuchuri/marker),该项目使用了 Surya 模型,基于视觉解析,可以有效提取图片、表格、公式等复杂内容。为了可以让 Marker 快速接入 FastGPT,我们做了一个自定义解析的拓展 Demo。
|
||||
市面上目前有多种解析 PDF 的方法,比如使用 [Marker](https://github.com/VikParuchuri/marker),该项目使用了 Surya 模型,基于视觉解析,可以有效提取图片、表格、公式等复杂内容。
|
||||
|
||||
在 FastGPT 4.8.15 版本中,你可以通过增加一个环境变量,来替换掉 FastGPT 系统内置解析器,实现自定义的文档解析服务。该功能只是 Demo 阶段,后期配置模式和交互规则会发生改动。
|
||||
在 `FastGPT v4.9.0` 版本中,开源版用户可以在`config.json`文件中添加`systemEnv.customPdfParse`配置,来使用 Marker 解析 PDF 文件。商业版用户直接在 Admin 后台根据表单指引填写即可。需重新拉取 Marker 镜像,接口格式已变动。
|
||||
|
||||
## 使用教程
|
||||
|
||||
### 1. 按照 Marker
|
||||
### 1. 安装 Marker
|
||||
|
||||
参考文档 [Marker 安装教程](https://github.com/labring/FastGPT/tree/main/plugins/model/pdf-marker),安装 Marker 模型。封装的 API 已经适配了 FastGPT 自定义解析服务。
|
||||
|
||||
@@ -28,22 +28,35 @@ docker pull crpi-h3snc261q1dosroc.cn-hangzhou.personal.cr.aliyuncs.com/marker11/
|
||||
docker run --gpus all -itd -p 7231:7231 --name model_pdf_v1 crpi-h3snc261q1dosroc.cn-hangzhou.personal.cr.aliyuncs.com/marker11/marker_images:latest
|
||||
```
|
||||
|
||||
### 2. 添加 FastGPT 环境变量
|
||||
### 2. 添加 FastGPT 文件配置
|
||||
|
||||
```
|
||||
CUSTOM_READ_FILE_URL=http://xxxx.com/v1/parse/file
|
||||
CUSTOM_READ_FILE_EXTENSION=pdf
|
||||
```json
|
||||
{
|
||||
xxx
|
||||
"systemEnv": {
|
||||
xxx
|
||||
"customPdfParse": {
|
||||
"url": "http://xxxx.com/v1/parse/file", // 自定义 PDF 解析服务地址
|
||||
"key": "", // 自定义 PDF 解析服务密钥
|
||||
"doc2xKey": "", // doc2x 服务密钥
|
||||
"price": 0 // PDF 解析服务价格
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* CUSTOM_READ_FILE_URL - 自定义解析服务的地址, host改成解析服务的访问地址,path 不能变动。
|
||||
* CUSTOM_READ_FILE_EXTENSION - 支持的文件后缀,多个文件类型,可用逗号隔开。
|
||||
需要重启服务。
|
||||
|
||||
### 3. 测试效果
|
||||
|
||||
通过知识库上传一个 pdf 文件,并确认上传,可以在日志中看到 LOG (LOG_LEVEL需要设置 info 或者 debug):
|
||||
通过知识库上传一个 pdf 文件,并勾选上 `PDF 增强解析`。
|
||||
|
||||

|
||||
|
||||
确认上传后,可以在日志中看到 LOG (LOG_LEVEL需要设置 info 或者 debug):
|
||||
|
||||
```
|
||||
[Info] 2024-12-05 15:04:42 Parsing files from an external service
|
||||
[Info] 2024-12-05 15:04:42 Parsing files from an external service
|
||||
[Info] 2024-12-05 15:07:08 Custom file parsing is complete, time: 1316ms
|
||||
```
|
||||
|
||||
@@ -51,6 +64,10 @@ CUSTOM_READ_FILE_EXTENSION=pdf
|
||||
|
||||

|
||||
|
||||
同样的,在应用中,你可以在文件上传配置里,勾选上 `PDF 增强解析`。
|
||||
|
||||

|
||||
|
||||
|
||||
## 效果展示
|
||||
|
||||
|
@@ -4,7 +4,7 @@ description: 'FastGPT V4.9.0 更新说明'
|
||||
icon: 'upgrade'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 803
|
||||
weight: 801
|
||||
---
|
||||
|
||||
|
||||
@@ -32,9 +32,10 @@ curl --location --request POST 'https://{{host}}/api/admin/initv490' \
|
||||
|
||||
## 兼容 & 弃用
|
||||
|
||||
1. 弃用 - 弃用旧版本地文件上传 API:/api/core/dataset/collection/create/file(以前仅商业版可用的 API,该接口已放切换成:/api/core/dataset/collection/create/localFile)
|
||||
2. 停止维护,即将弃用 - 外部文件库相关 API,可通过 API 文件库替代。
|
||||
3. API更新 - 上传文件至知识库、创建连接集合、API 文件库、推送分块数据等带有 `trainingType` 字段的接口,`trainingType`字段未来仅支持`chunk`和`QA`两种模式。增强索引模式将设置单独字段:`autoIndexes`,目前仍有适配旧版`trainingType=auto`代码,但请尽快变更成新接口类型。具体可见:[知识库 OpenAPI 文档](/docs/development/openapi/dataset.md)
|
||||
1. 弃用 - 之前私有化部署的自定义文件解析方案,请同步更新到最新的配置方案。[点击查看 PDF 增强解析配置](/docs/development/configuration/#使用-doc2x-解析-pdf-文件)
|
||||
2. 弃用 - 弃用旧版本地文件上传 API:/api/core/dataset/collection/create/file(以前仅商业版可用的 API,该接口已放切换成:/api/core/dataset/collection/create/localFile)
|
||||
3. 停止维护,即将弃用 - 外部文件库相关 API,可通过 API 文件库替代。
|
||||
4. API更新 - 上传文件至知识库、创建连接集合、API 文件库、推送分块数据等带有 `trainingType` 字段的接口,`trainingType`字段未来仅支持`chunk`和`QA`两种模式。增强索引模式将设置单独字段:`autoIndexes`,目前仍有适配旧版`trainingType=auto`代码,但请尽快变更成新接口类型。具体可见:[知识库 OpenAPI 文档](/docs/development/openapi/dataset.md)
|
||||
|
||||
## 🚀 新增内容
|
||||
|
||||
|
@@ -81,13 +81,9 @@ export const readRawContentByFileBuffer = async ({
|
||||
filename: `file.${extension}`
|
||||
});
|
||||
const { data: response } = await axios.post<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
data: {
|
||||
page?: number; // abandon
|
||||
pages: number;
|
||||
markdown: string;
|
||||
};
|
||||
pages: number;
|
||||
markdown: string;
|
||||
error?: Object | string;
|
||||
}>(url, data, {
|
||||
timeout: 600000,
|
||||
headers: {
|
||||
@@ -96,15 +92,19 @@ export const readRawContentByFileBuffer = async ({
|
||||
}
|
||||
});
|
||||
|
||||
if (response.error) {
|
||||
return Promise.reject(response.error);
|
||||
}
|
||||
|
||||
addLog.info(`Custom file parsing is complete, time: ${Date.now() - start}ms`);
|
||||
|
||||
const rawText = response.data.markdown;
|
||||
const rawText = response.markdown;
|
||||
const { text, imageList } = matchMdImgTextAndUpload(rawText);
|
||||
|
||||
createPdfParseUsage({
|
||||
teamId,
|
||||
tmbId,
|
||||
pages: response.data.page || response.data.pages
|
||||
pages: response.pages
|
||||
});
|
||||
|
||||
return {
|
||||
|
@@ -8,6 +8,12 @@
|
||||
"qaMaxProcess": 10, // 问答拆分线程数量
|
||||
"vlmMaxProcess": 10, // 图片理解模型最大处理进程
|
||||
"tokenWorkers": 30, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
||||
"pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||
"pgHNSWEfSearch": 100, // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||
"customPdfParse": {
|
||||
"url": "", // 自定义 PDF 解析服务地址
|
||||
"key": "", // 自定义 PDF 解析服务密钥
|
||||
"doc2xKey": "", // doc2x 服务密钥
|
||||
"price": 0 // PDF 解析服务价格
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -127,31 +127,33 @@ const PreviewData = () => {
|
||||
{t('dataset:preview_chunk_intro')}
|
||||
</Box>
|
||||
</Flex>
|
||||
<MyBox isLoading={isLoading} flex={'1 0 0'} overflowY={'auto'} px={5} py={3}>
|
||||
{previewFile ? (
|
||||
<>
|
||||
{data.map((item, index) => (
|
||||
<Box
|
||||
key={index}
|
||||
fontSize={'sm'}
|
||||
color={'myGray.600'}
|
||||
_notLast={{
|
||||
mb: 3,
|
||||
pb: 3,
|
||||
borderBottom: 'base'
|
||||
}}
|
||||
_hover={{
|
||||
bg: 'myGray.100'
|
||||
}}
|
||||
>
|
||||
<Markdown source={item.q} />
|
||||
<Markdown source={item.a} />
|
||||
</Box>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<EmptyTip text={t('dataset:preview_chunk_not_selected')} />
|
||||
)}
|
||||
<MyBox isLoading={isLoading} flex={'1 0 0'} h={0}>
|
||||
<Box h={'100%'} overflowY={'auto'} px={5} py={3}>
|
||||
{previewFile ? (
|
||||
<>
|
||||
{data.map((item, index) => (
|
||||
<Box
|
||||
key={index}
|
||||
fontSize={'sm'}
|
||||
color={'myGray.600'}
|
||||
_notLast={{
|
||||
mb: 3,
|
||||
pb: 3,
|
||||
borderBottom: 'base'
|
||||
}}
|
||||
_hover={{
|
||||
bg: 'myGray.100'
|
||||
}}
|
||||
>
|
||||
<Markdown source={item.q} />
|
||||
<Markdown source={item.a} />
|
||||
</Box>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<EmptyTip text={t('dataset:preview_chunk_not_selected')} />
|
||||
)}
|
||||
</Box>
|
||||
</MyBox>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
Reference in New Issue
Block a user