Type something to search...
利用 Docling、Ollama、Phi-4 | ExtractThinker 构建企业内部文档智能堆栈

利用 Docling、Ollama、Phi-4 | ExtractThinker 构建企业内部文档智能堆栈

在这个大型语言模型(LLM)的新时代,银行和金融机构在某种程度上处于劣势,因为前沿模型由于其硬件要求几乎无法在本地使用。然而,银行数据的敏感性带来了显著的隐私问题,尤其是当这些模型仅作为云服务提供时。为了解决这些挑战,组织可以转向**本地或小型语言模型(SLM)**设置,以将数据保留在内部,避免敏感信息的潜在泄露。这种方法使您能够利用先进的LLM(本地或通过最少的外部调用),同时确保严格遵守GDPR、HIPAA或各种金融指令等法规。

本文展示了如何通过结合以下内容构建一个完全本地的文档智能解决方案

  • ExtractThinker — 一个开源框架,用于协调OCR、分类和数据提取管道,以支持LLM
  • Ollama — 一个本地部署解决方案,适用于Phi-4或Llama 3.x等语言模型
  • Docling MarkItDown — 灵活的库,用于处理文档加载、OCR和布局解析

无论您是在严格的保密规则下操作,处理扫描的PDF,还是仅仅想要先进的基于视觉的提取,这个端到端的堆栈都提供了一个完全在您自己基础设施内的安全、高性能管道。

1. 选择合适的模型(文本与视觉)

在构建文档智能堆栈时,首先要决定您需要仅文本模型还是具备视觉能力的模型。仅文本模型通常更适合本地解决方案,因为它们广泛可用且限制较少。然而,具备视觉能力的模型在高级分割任务中可能至关重要,特别是当文档依赖于视觉线索时——例如布局、配色方案或独特格式。

在某些情况下,您可以为不同阶段配对不同的模型。例如,一个较小的 moondream 模型(0.5B 参数)可能负责分割,而 Phi-4 14B 模型则管理分类和提取。许多大型机构更倾向于部署单一、更强大的模型(例如,70B 范围内的 Llama 3.3 或 Qwen 2.5)以覆盖所有用例。如果您只需要以英语为中心的 IDP,您可以简单地使用Phi4来处理大多数任务,并保持一个轻量级的 moondream 模型以应对边缘案例分割。这一切都取决于您的具体需求和可用基础设施。

2. 处理文档:MarkItDown 与 Docling

对于文档解析,有两个流行的库脱颖而出:

MarkItDown

  • 更简单、直接,广泛支持微软
  • 非常适合直接的基于文本的任务,无需多个OCR引擎
  • 易于安装和集成

Docling

  • 更高级,支持多种OCR(Tesseract、AWS Textract、Google Document AI等)
  • 非常适合扫描工作流程或从图像PDF中进行强大的提取
  • 详细的文档,灵活适应复杂布局

ExtractThinker 让您可以根据需求选择 DocumentLoaderMarkItDownDocumentLoaderDocling,无论是简单的数字PDF还是多引擎OCR。

3. 运行本地模型

虽然 Ollama 是一个流行的本地托管 LLM 的工具,但现在有 几种解决方案 可用于与 ExtractThinker 无缝集成的本地部署:

  • LocalAI — 一个开源平台,可以在本地模拟 OpenAI 的 API。它可以在消费级硬件(甚至仅 CPU)上运行 LLM,比如 Llama 2 或 Mistral,并提供一个简单的端点进行连接。
  • OpenLLM — BentoML 的一个项目,通过与 OpenAI 兼容的 API 暴露 LLM。它针对吞吐量和低延迟进行了优化,适用于本地和云端,并支持多种开源 LLM。
  • Llama.cpp — 一种更低级别的方法,用于运行 Llama 模型,并具有高级自定义配置。适合细粒度控制或高性能计算设置,尽管管理上更复杂。

Ollama 通常是首选,因为它易于设置且 CLI 简单。然而,对于企业或高性能计算场景,Llama.cpp 服务器部署、OpenLLM 或像 LocalAI 这样的解决方案可能更为合适。所有这些都可以通过简单地将本地 LLM 端点指向代码中的环境变量或基础 URL 来与 ExtractThinker 集成。

4. 处理小上下文窗口

在使用具有有限上下文窗口的本地模型(例如,~8K tokens 或更少)时,管理这两者变得至关重要:

拆分文档

为了避免超过模型的输入容量,懒惰拆分是理想的选择。与其一次性处理整个文档:

  • 逐步比较页面(例如,页面 1–2,然后 2–3),决定它们是否属于同一子文档。
  • 如果是,你将它们保留在一起以便下一步。如果不是,你开始一个新段落。
  • 这种方法对内存友好,并通过一次只加载和分析几页来适应非常大的 PDF。

注意: 当你有更高的令牌限制时,连接是理想的选择;在窗口有限的情况下,分页更为优先。

处理部分响应

对于较小的本地模型,如果提示较大,每个响应也有被截断的风险。PaginationHandler 优雅地解决了这个问题:

  • 将文档的页面拆分为单独的请求(每个请求一页)。
  • 在最后合并页面级结果,如果页面在某些字段上存在分歧,则可选择进行冲突解决。

注意: 当您有更高的令牌限制时,连接是理想的;对于有限的窗口,分页是首选。

快速示例流程

  1. 懒惰分割 PDF,使每个块/页面保持在模型限制之下。
  2. 分页:每个块的结果单独返回。
  3. 合并 部分页面结果为最终结构化数据。

这种最小化的方法确保您永远不会超过本地模型的上下文窗口——无论是在喂入 PDF 的方式上,还是在处理多页响应时。

5. ExtractThinker: 构建堆栈

下面是一个最小的代码片段,展示如何集成这些组件。首先,安装 ExtractThinker

pip install extract-thinker

文档加载器

如上所述,我们可以使用 MarkitDown 或 Docling。

from extract_thinker import DocumentLoaderMarkItDown, DocumentLoaderDocling

## DocumentLoaderDocling or DocumentLoaderMarkItDown
document_loader = DocumentLoaderDocling()

定义合同

我们使用 Pydantic-based Contracts 来指定我们想要提取的数据结构。例如,发票和驾驶执照:

from extract_thinker.models.contract import Contract
from pydantic import Field

class InvoiceContract(Contract):
    invoice_number: str = Field(description="Unique invoice identifier")
    invoice_date: str = Field(description="Date of the invoice")
    total_amount: float = Field(description="Overall total amount")

class DriverLicense(Contract):
    name: str = Field(description="Full name on the license")
    age: int = Field(description="Age of the license holder")
    license_number: str = Field(description="License number")

分类

如果您有多个文档类型,请定义 Classification 对象。您可以指定:

  • 每个分类的名称(例如,“发票”)。
  • 描述。
  • 它映射到的合同。
from extract_thinker import Classification

TEST_CLASSIFICATIONS = [
    Classification(
        name="Invoice",
        description="This is an invoice document",
        contract=InvoiceContract
    ),
    Classification(
        name="Driver License",
        description="This is a driver license document",
        contract=DriverLicense
    )
]

整合所有内容:本地提取过程

下面,我们创建一个 Extractor,它使用我们选择的 document_loader 和一个 本地模型(Ollama、LocalAI 等)。然后,我们构建一个 Process 来在单个管道中加载、分类、拆分和提取。

import os
from dotenv import load_dotenv

from extract_thinker import (
    Extractor,
    Process,
    Classification,
    SplittingStrategy,
    ImageSplitter,
    TextSplitter
)

## 加载环境变量(如果您在 .env 中存储 LLM 端点/API_BASE 等)
load_dotenv()

## 多页文档的示例路径
MULTI_PAGE_DOC_PATH = "path/to/your/multi_page_doc.pdf"

def setup_local_process():
    """
    辅助函数,用于设置使用本地 LLM 端点(例如,Ollama、LocalAI、OnPrem.LLM 等)的 ExtractThinker 过程
    """

    # 1) 创建一个 Extractor
    extractor = Extractor()

    # 2) 附加我们选择的 DocumentLoader(Docling 或 MarkItDown)
    extractor.load_document_loader(document_loader)

    # 3) 配置您的本地 LLM
    #    对于 Ollama,您可以这样做:
    os.environ["API_BASE"] = "http://localhost:11434"  # 替换为您的本地端点
    extractor.load_llm("ollama/phi4")  # 或 "ollama/llama3.3" 或您的本地模型
    
    # 4) 将提取器附加到每个分类
    TEST_CLASSIFICATIONS[0].extractor = extractor
    TEST_CLASSIFICATIONS[1].extractor = extractor

    # 5) 构建过程
    process = Process()
    process.load_document_loader(document_loader)
    return process

def run_local_idp_workflow():
    """
    演示加载、分类、拆分和提取
    使用本地 LLM 的多页文档。
    """
    # 初始化过程
    process = setup_local_process()

    # (可选)您可以使用 ImageSplitter(model="ollama/moondream:v2") 进行拆分
    process.load_splitter(TextSplitter(model="ollama/phi4"))

    # 1) 加载文件
    # 2) 使用 EAGER 策略拆分为子文档
    # 3) 使用我们的 TEST_CLASSIFICATIONS 对每个子文档进行分类
    # 4) 根据匹配的合同(发票或驾驶执照)提取字段
    result = (
        process
        .load_file(MULTI_PAGE_DOC_PATH)
        .split(TEST_CLASSIFICATIONS, strategy=SplittingStrategy.LAZY)
        .extract(vision=False, completion_strategy=CompletionStrategy.PAGINATE)
    )

    # 'result' 是提取对象的列表(InvoiceContract 或 DriverLicense)
    for item in result:
        # 打印或存储每个提取的数据模型
        if isinstance(item, InvoiceContract):
            print("[提取的发票]")
            print(f"编号: {item.invoice_number}")
            print(f"日期: {item.invoice_date}")
            print(f"总额: {item.total_amount}")
        elif isinstance(item, DriverLicense):
            print("[提取的驾驶执照]")
            print(f"姓名: {item.name}, 年龄: {item.age}")
            print(f"执照编号: {item.license_number}")

## 快速测试,只需调用 run_local_idp_workflow()
if __name__ == "__main__":
    run_local_idp_workflow()

6. 隐私和个人身份信息:云中的大型语言模型

并非每个组织都能——或想要——运行本地硬件。有些组织更喜欢先进的基于云的大型语言模型。如果是这样,请记住:

  • 数据隐私风险:将敏感数据发送到云端可能会引发合规性问题。
  • GDPR/HIPAA:法规可能会限制数据完全离开您的场所。
  • VPC + 防火墙:您可以在私有网络中隔离云资源,但这会增加复杂性。

注意*:许多大型语言模型API(例如,OpenAI)确实提供GDPR合规性。但如果您受到严格监管或希望能够轻松切换提供商,请考虑本地或掩码云的方法。*

个人身份信息掩码一个强有力的方法是建立一个个人身份信息掩码管道。像Presidio这样的工具可以在发送到大型语言模型之前自动检测和删除个人标识符。这样,您可以保持与模型无关,同时保持合规性。

7. 结论

通过将 ExtractThinker本地 LLM(如 Ollama、LocalAI 或 OnPrem.LLM)以及灵活的 DocumentLoader(Docling 或 MarkItDown)结合起来,您可以从零开始构建一个 安全的本地文档智能工作流程。如果监管要求需要完全隐私或最小的外部调用,这个堆栈可以在不牺牲现代 LLM 功能的情况下,将您的数据保留在内部。

Related Posts

使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
10 个强大的 Perplexity AI 提示,让您的营销任务自动化

10 个强大的 Perplexity AI 提示,让您的营销任务自动化

在当今快速变化的数字世界中,营销人员总是在寻找更智能的方法来简化他们的工作。想象一下,有一个个人助理可以为您创建受众档案,建议营销策略,甚至为您撰写广告文案。这听起来像是一个梦想? 多亏了像 Perplexity 这样的 AI 工具,这个梦想现在成为现实。通过正确的提示,您可以将 AI 转变为您的 个人营销助理。在本文中,我将分享 10 个强大的提示,帮助您自动

阅读更多
10+ 面向 UI/UX 设计师的顶级 ChatGPT 提示

10+ 面向 UI/UX 设计师的顶级 ChatGPT 提示

人工智能技术,如机器学习、自然语言处理和数据分析,正在重新定义传统设计方法。从自动化重复任务到实现个性化用户体验,人工智能使设计师能够更加专注于战略思维和创造力。随着这一趋势的不断增长,UI/UX 设计师越来越多地采用 AI 驱动的工具来促进他们的工作。利用人工智能不仅能提供基于数据的洞察,还为满足多样化用户需求的创新设计解决方案开辟了机会。 1. 用户角色开发 目的

阅读更多
在几分钟内完成数月工作的 100 种人工智能工具

在几分钟内完成数月工作的 100 种人工智能工具

人工智能(AI)的快速发展改变了企业的运作方式,使人们能够在短短几分钟内完成曾经需要几周或几个月的任务。从内容创作到网站设计,AI工具帮助专业人士节省时间,提高生产力,专注于创造力。以下是按功能分类的100个AI工具的全面列表,以及它们在现实世界中的使用实例。 1. 研究工具 研究可能耗时,但人工智能工具使查找、分析和组织数据变得更加容易。**ChatGPT, Cop

阅读更多
你从未知道的 17 个令人惊叹的 GitHub 仓库

你从未知道的 17 个令人惊叹的 GitHub 仓库

Github 隐藏的宝石!! 立即收藏的代码库 学习编程相对简单,但掌握编写更好代码的艺术要困难得多。GitHub 是开发者的宝藏,那里“金子”是其他人分享的精心编写的代码。通过探索 GitHub,您可以发现如何编写更清晰的代码,理解高质量代码的样子,并学习成为更熟练开发者的基本步骤。 1. notwaldorf/emoji-translate *谁需

阅读更多