服务器需要有docker,或者直接访问官方提供的demo: https://demo.ragflow.io/
docker-compose安装
- 需要确保
vm.max_map_count
不小于 262144 【更多】:
sysctl -w vm.max_map_count=262144
- 克隆仓库:
$ git clone https://github.com/infiniflow/ragflow.git
- 进入 docker 文件夹,利用提前编译好的 Docker 镜像启动服务器:
$ cd ragflow/docker $ docker compose -f docker-compose-CN.yml up -d
核心镜像文件大约 15 GB,可能需要一定时间拉取。请耐心等待。
体验
启动成功后,浏览器输入 http://服务器ip
或者直接访问官方demo https://demo.ragflow.io/
注册登录,进入后可以创建知识库,然后上传文档。
上传成功后,可以通过解析状态查看解析进度,也可以配置文档的parser解析方法,以更好的解析内容。
点击文档名称,可以进入文档详情,查看拆分的chunk,可以看到普通的文本是按照token拆分,还未实现按照段落语义拆分,差评。表格是单独抽取出来,独立存储的,将文档里的表格比较好的还原为了html表格,准确率尚可,这里好评。每个chunk有原文截图,点击后,右边的pdf预览,可以高亮当前的chunk所在区域,翻了下代码,使用的react-pdf-highlighter
,体验挺好的一个组件。
DeepDoc CV模型
DeepDoc的模型应该是基于paddleOCR的模型去微调训练的,开源出来的模型是onnx格式的。
OCR识别
主要代码在ocr.py里,代码定义TextRecognizer
做文字识别,TextDetector
做文本框检测,OCR整合检测和识别功能,对外提供调用。
OCR的核心流程:
- 创建 OCR 实例,load模型
- 调用
__call__
方法,传入图像数据。- 使用 TextDetector 进行文本检测,获取文本框坐标
- 对每个文本框,使用 get_rotate_crop_image 方法进行旋转和裁剪
- 使用 TextRecognizer 对裁剪后的图像进行文本识别
- 过滤掉置信度低于阈值(0.5)的识别结果。
- 返回最终的文本框坐标和识别结果。
版面分析
版面分析主要在recognizer.py和layout_recognizer.py
里,定义了一个名为LayoutRecognizer
继承Recognizer
的类,用于对文档图像进行板式分析,识别不同类型的区域,例如表格、标题、段落等。这里用的模型应该还是基于paddleocr里的版面分析模型去优化的。
先看Recognizer
的__call__
方法,传入图像列表和置信度阈值:
def __call__(self, image_list, thr=0.7, batch_size=16):
res = []
imgs = []
for i in range(len(image_list)):
if not isinstance(image_list[i], np.ndarray):
imgs.append(np.array(image_list[i]))
else: imgs.append(image_list[i])
batch_loop_cnt = math.ceil(float(len(imgs)) / batch_size)
for i in range(batch_loop_cnt):
start_index = i * batch_size
end_index = min((i + 1) * batch_size, len(imgs))
batch_image_list = imgs[start_index:end_index]
inputs = self.preprocess(batch_image_list)
print("preprocess")
for ins in inputs:
bb = self.postprocess(self.ort_sess.run(None, {k:v for k,v in ins.items() if k in self.input_names})[0], ins, thr)
res.append(bb)
#seeit.save_results(image_list, res, self.label_list, threshold=thr)
return res
- 先预处理,将图像列表转换为模型输入格式
- 然后调用ort_sess执行onnx推理,最后postprocess,提取模型返回的布局信息,包括区域类型、坐标和置信度。
再看LayoutRecognizer
的__call__
方法,这里是模型应用的工程代码部分,很多细节的小技巧,先上代码,里面加了一些注释:
def __call__(self, image_list, ocr_res, scale_factor=3,
thr=0.2, batch_size=16, drop=True):
# 可以过滤的垃圾数据
def __is_garbage(b):
patt = [r"^•+$", r"(版权归©|免责条款|地址[::])", r"\.{3,}", "^[0-9]{1,2} / ?[0-9]{1,2}$",
r"^[0-9]{1,2} of [0-9]{1,2}$", "^http://[^ ]{12,}",
"(资料|数据)来源[::]", "[0-9a-z._-]+@[a-z0-9-]+\\.[a-z]{2,3}",
"\\(cid *: *[0-9]+ *\\)"
]
return any([re.search(p, b["text"]) for p in patt])
# 调用父类的模型识别
layouts = super().__call__(image_list, thr, batch_size)
# save_results(image_list, layouts, self.labels, output_dir='output/', threshold=0.7)
assert len(image_list) == len(ocr_res)
# Tag layout type
boxes = []
assert len(image_list) == len(layouts)
garbages = {}
page_layout = []
for pn,