私有知识库 Coco AI 实战(七):摄入本地 PDF 文件

news2025/5/29 8:28:58

是否有些本地文件要检索?没问题。我们先对 PDF 类的文件进行处理,其他的文件往后稍。

Coco Server Token

创建一个 token 备用。

PDF_Reader

直接写个 python 程序解析 PDF 内容,上传到 Coco Server 就行了。还记得以前都是直接写入 Coco 后台的 Easysearch 的,这次我们走 Coco Server 的 API 写入数据。

程序逻辑

  1. 检查是否存在 id 为 local_pdf 的 connector 和 datasource,不存在就创建。
  2. 遍历一个目录中的所有 pdf 文件
  3. 把 pdf 文件的内容发送给 Coco Server 的 API

使用程序

  1. 修改 220 行替换成自己的 Coco server token
  2. 修改 221 行换成自己 Coco Server 的地址
  3. 修改 229 行换成自己 PDF 文件的目录
  4. 运行程序
from PyPDF2 import PdfReader
import os
import requests
from pathlib import Path


class PDFPage:

    def __init__(self, title: str, content: str, page_number: int):
        self.title = title
        self.content = content
        self.type = "pdf"
        self.page = page_number


def read_pdf(file_path: str) -> list[PDFPage]:
    """
    读取PDF文件并为每一页创建一个PDFPage对象
    
    Args:
        file_path (str): PDF文件的路径
    
    Returns:
        list[PDFPage]: 包含所有页面对象的列表
    """
    # 检查文件是否存在
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"找不到文件: {file_path}")

    # 检查文件是否为PDF
    if not file_path.lower().endswith('.pdf'):
        raise ValueError("文件必须是PDF格式")

    # 获取文件名(不包含路径)
    file_name = os.path.basename(file_path)

    # 创建PDF阅读器对象
    pdf_reader = PdfReader(file_path)
    pages = []

    # 遍历每一页
    for page_num in range(len(pdf_reader.pages)):
        # 获取当前页面
        page = pdf_reader.pages[page_num]
        # 提取文本内容
        content = page.extract_text()
        # 创建页面对象
        pdf_page = PDFPage(
            title=file_name,
            content=content,
            page_number=page_num + 1  # 页码从1开始
        )
        pages.append(pdf_page)

    return pages


def send_to_coco_server(page: PDFPage,
                        datasource_id: str,
                        api_token: str,
                        file_path: str,
                        server_url: str = "http://localhost:9000") -> dict:
    """
    将PDF页面内容发送到Coco Server
    
    Args:
        page (PDFPage): PDF页面对象
        datasource_id (str): Coco Server的数据源ID
        api_token (str): API Token
        file_path (str): PDF文件的完整路径
        server_url (str): Coco Server的URL
    
    Returns:
        dict: 服务器响应
    """
    headers = {'X-API-TOKEN': api_token, 'Content-Type': 'application/json'}

    # 将Windows路径转换为标准路径格式(使用正斜杠)
    file_url = file_path.replace('\\', '/')

    data = {
        'title': f"{page.title} - 第{page.page}页",
        'summary': f"PDF文档 {page.title} 的第{page.page}页内容",
        'content': page.content,
        'category': 'local_pdf',
        'url': file_url
    }

    url = f"{server_url}/datasource/{datasource_id}/_doc"
    response = requests.post(url, headers=headers, json=data)
    return response.json()


def process_directory(directory_path: str, api_token: str, datasource_id: str,
                      server_url: str) -> None:
    """
    处理指定目录下的所有PDF文件
    
    Args:
        directory_path (str): 目录路径
        api_token (str): API Token
        datasource_id (str): 数据源ID
        server_url (str): 服务器URL
    """
    # 确保目录存在
    if not os.path.exists(directory_path):
        raise FileNotFoundError(f"目录不存在: {directory_path}")

    # 获取所有PDF文件
    pdf_files = list(Path(directory_path).rglob("*.pdf"))
    total_files = len(pdf_files)

    print(f"找到 {total_files} 个PDF文件")

    # 处理每个PDF文件
    for file_index, pdf_file in enumerate(pdf_files, 1):
        print(f"\n处理文件 {file_index}/{total_files}: {pdf_file}")
        try:
            # 获取文件的绝对路径
            absolute_path = str(pdf_file.absolute())

            # 读取PDF文件
            pdf_pages = read_pdf(absolute_path)

            # 处理每一页
            for page in pdf_pages:
                print(f"  正在处理: {page.title} - 第{page.page}页")
                try:
                    result = send_to_coco_server(page, datasource_id,
                                                 api_token, absolute_path,
                                                 server_url)
                    print(f"  上传成功! 文档ID: {result.get('_id')}")
                except Exception as e:
                    print(f"  上传失败: {str(e)}")

        except Exception as e:
            print(f"处理文件 {pdf_file} 时出错: {str(e)}")
            continue


def create_connector_and_datasource(server_url: str, api_token: str) -> str:
    """
    创建connector和datasource
    
    Args:
        server_url (str): 服务器URL
        api_token (str): API Token
    
    Returns:
        str: 创建的datasource ID
    """
    headers = {'X-API-TOKEN': api_token, 'Content-Type': 'application/json'}

    # 检查connector是否存在
    connector_id = 'local_pdf'
    connector_url = f"{server_url}/connector/{connector_id}"

    try:
        response = requests.get(connector_url, headers=headers)
        if response.status_code == 404:
            # 创建connector
            connector = {
                'name': 'Local PDF Connector',
                'category': 'local_files',
                'icon': 'font_filetype-PDF'
            }
            print("创建 local_pdf connector...")
            response = requests.put(
                f"{server_url}/connector/local_pdf?replace=true",
                headers=headers,
                json=connector)
            # print(response.json())
            # print(response.status_code)
            if response.status_code == 200 and response.json().get(
                    'result') == 'updated':
                print("Connector创建成功")
            else:
                raise Exception(f"创建Connector失败: {response.text}")

        # 检查datasource是否存在
        datasource_url = f"{server_url}/datasource/local_pdf"
        response = requests.get(datasource_url, headers=headers)

        if response.status_code == 404:
            # 创建datasource
            datasource = {
                'name': 'Local PDF Datasource',
                'id': 'local_pdf',
                'type': 'connector',
                'connector': {
                    'id': 'local_pdf',
                },
                'sync_enabled': False,
                'enabled': True
            }
            print("创建 local_pdf datasource...")
            response = requests.put(
                f"{server_url}/datasource/local_pdf?replace=true",
                headers=headers,
                json=datasource)
            if response.status_code == 200 and response.json().get(
                    'result') == 'updated':
                print("Datasource创建成功")
            else:
                raise Exception(f"创建Datasource失败: {response.text}")

        return 'local_pdf'

    except Exception as e:
        print(f"创建过程中发生错误: {str(e)}")
        raise


def main():
    """
    主函数,处理指定目录下的所有PDF文件并发送到Coco Server
    """
    try:
        # Coco Server配置
        api_token = "d02rutog1maf0invql60130c0y8g4se4i5brurqa2k72r6ozysvxvzgda90cnbwg26bw4g7tv09zjfuw0c33"
        server_url = "http://192.168.10.3:9000"

        # 创建或获取datasource
        print("检查并创建必要的connector和datasource...")
        datasource_id = create_connector_and_datasource(server_url, api_token)
        print(f"使用datasource ID: {datasource_id}")

        # 指定要处理的目录
        directory_path = "D:/LangChain/infini-rag/easysearch"  # 替换为你的目录路径

        # 处理目录
        process_directory(directory_path, api_token, datasource_id, server_url)

        print("\n所有文件处理完成!")

    except Exception as e:
        print(f"发生错误: {str(e)}")


if __name__ == "__main__":
    main()

测试搜索

我的测试目录里有三个 PDF 文件。

通过程序采集内容后,就能对这些内容进行搜索了。

选择对应的条目回车就能直接打开 PDF 文件。

测试小助手

有了之前创建小助手的经验,我们很快也能打造一个本地 PDF 资源的小助手。

回答内容基本来自本地 PDF 文件内容,用这个来管理本地 PDF 知识,真是太方便了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2387185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Unity3D】将自动生成的脚本包含到C#工程文件中

我们知道,在用C#开发中,通过vs编辑器新建的脚本,会自动包含到vs工程中,而通过外部创建,比如复制别的工程或代码创建的C#脚本不会包含到vs工程。 在我们的日常开发中,通常会自动创建C#脚本,特别…

【Python 深度学习】1D~3D iou计算

一维iou 二维 import numpy as npdef iou_1d(set_a, set_b):# 获得集合A和B的边界 x1, x2 set_ay1, y2 set_b# 计算交集的上下界low max(x1,y1)high - min(x2, y2)# 计算交集if high - low < 0:inter 0else:inter high - low# 计算并集union (x2 -x1) (y2 - y1) - in…

java23

1.美化界面 添加背景图片 所以我们添加背景图片要放在后面添加 添加图片边框 绝对路径&#xff1a; 相对(模块)路径&#xff1a; 第一个是绝对路径&#xff0c;第二个是相对路径&#xff0c;但是斜杠的方向不对 总结&#xff1a; 2.图片移动 先实现KeyListener接口&#xf…

LitCTF2025 WEB

星愿信箱 使用的是python&#xff0c;那么大概率是ssti注入 测试{{5*5}} 发现需要包含文字&#xff0c;那么添加文字 可以看到被waf过滤了&#xff0c;直接抓包查看参数上fenjing 可以看到这里是json格式&#xff0c;其实fenjing也是支持json格式的 https://github.com/Marv…

Linux 下VS Code 的使用

这里以创建helloworld 为例。 Step 0:准备工作&#xff1a; Install Visual Studio Code. Install the C extension for VS Code. You can install the C/C extension by searching for c in the Extensions view (CtrlShiftX). Step 1: 创建工作目录 helloworld&#xff0…

Qt 布局管理器的层级关系

1、HomeWidget.h头文件&#xff1a; #ifndef HOMEWIDGET_H #define HOMEWIDGET_H#include <QWidget> #include <QPushButton> #include <QVBoxLayout> #include <QHBoxLayout>class HomeWidget : public QWidget {Q_OBJECTpublic:HomeWidget(QWidget …

maven模块化开发

使用方法 将项目安装到本地仓库 mvn install 的作用 运行 mvn install 时&#xff0c;Maven 会执行项目的整个构建生命周期&#xff08;包括 compile、test、package 等阶段&#xff09;&#xff0c;最终将构建的 artifact 安装到本地仓库&#xff08;默认路径为 ~/.m2/repos…

云原生安全之网络IP协议:从基础到实践指南

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 IP协议&#xff08;Internet Protocol&#xff09;是互联网通信的核心协议族之一&#xff0c;负责在设备间传递数据包。其核心特性包括&…

C++——QT 文件操作类

QFile 概述 QFile是Qt框架中用于文件操作的类&#xff08;位于QtCore模块&#xff09;&#xff0c;继承自 QIODevice&#xff0c;提供文件的读写、状态查询和路径管理功能。它与 QTextStream、QDataStream 配合使用&#xff0c;可简化文本和二进制数据的处理&#xff0c;并具备…

[spring] spring 框架、IOC和AOP思想

目录 传统Javaweb开发的困惑 loC、DI和AOP思想提出 Spring框架的诞生 传统Javaweb开发的困惑 问题一&#xff1a;层与层之间紧密耦合在了一起&#xff0c;接口与具体实现紧密耦合在了一起 解决思路&#xff1a;程序代码中不要手动new对象&#xff0c;第三方根据要求为程序提…

尚硅谷redis7 37-39 redis持久化之AOF简介

37 redis持久化之AOF简介 AOF 以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工…

GitLab 备份所有仓库(自动克隆)

一、准备工作 1. 环境要求 已安装 Git&#xff08;版本 2.10&#xff09;本地磁盘空间充足&#xff08;根据仓库总大小预估&#xff09;已配置 SSH 密钥到 GitLab&#xff08;推荐方式&#xff09; 2. 获取 GitLab API 访问权限 登录 GitLab&#xff0c;点击右上角头像 → …

[浏览器]缓存策略机制详解

在做页面性能优化的时候&#xff0c;有一个点容易被忽略&#xff0c;那就是资源缓存优化。 浏览器里缓存策略分为强缓存&#xff0c;协商缓存以及不缓存&#xff0c;每个缓存策略都有其适用的优化场景。 下面为大家详解何为强缓存&#xff0c;协商缓存 先说结论强缓>协商&g…

OpenCV CUDA 模块图像过滤-----创建一个计算图像导数的滤波器函数createDerivFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::createDerivFilter 是 OpenCV CUDA 模块中的一个工厂函数&#xff0c;用于创建一个计算图像导数的滤波器。这个滤波器可以用来计算图像…

AWS関連職種向け:日本語面接QA集

1. 自己紹介&#xff08;じこしょうかい&#xff09; Q&#xff1a;簡単に自己紹介をお願いします。 A&#xff1a; はい、〇〇と申します。これまで約4年間、主にAWSを基盤としたインフラ設計・構築・運用に従事してまいりました。VPCやEC2、RDS、S3などの基本サービスの設計…

(01)华为GaussDB((基于PostgreSQL))高斯数据库使用记录,dbeaver客户端配置高斯驱动,连接高斯数据库

高斯数据库是华为推出的一款基于PostgreSQL的企业级数据库产品&#xff0c;客户端使用通用的dbeaver dbeaver客户端配置高斯驱动 建议使用 dbeaver24.3.1及以上客户端&#xff0c;选择模式后执行sql会绑定模式名&#xff0c;如果使用dbeaver23.2版本&#xff0c;选择模式后执…

ARM Linux远程调试

准备 虚拟机既能ping通开发板,又能ping通外网,还要能ping通Windows主机(如果你有上位机通信(tftp、vsftp、ssh)的需求) VMware 添加网络适配器2用作桥接网卡,原有的网络适配器保持为NAT模式 打开虚拟网络编辑器,配置VMnet0为桥接模式,外部连接设置为Realtek PCIe G…

day24Node-node的Web框架Express

1. Express 基础 1.1 什么是Express node的web框架有Express 和 Koa。常用Express 。 Express 是一个基于 Node.js 的快速、极简的 Web 应用框架,用于构建 服务器端应用(如网站后端、RESTful API 等)。它是 Node.js 生态中最流行的框架之一,以轻量、灵活和易用著称。 …

让MySQL更快:EXPLAIN语句详尽解析

前言 在数据库性能调优中&#xff0c;SQL 查询的执行效率是影响系统整体性能的关键因素之一。MySQL 提供了强大的工具——EXPLAIN 语句&#xff0c;帮助开发者和数据库管理员深入分析查询的执行计划&#xff0c;从而发现潜在的性能瓶颈并进行针对性优化。 EXPLAIN 语句能够模…

[CSS3]rem移动适配

前言 什么是移动端适配? 让页面的元素在屏幕尺寸变化时, 同比放大或缩小 移动适配的方案 rem&#xff1a;目前多数企业在用的解决方案 vw/vh&#xff1a;未来的解决方案 rem 体验rem适配 目标: 能够使用rem单位设置网页元素的尺寸 网页效果: 屏幕宽度不同&#xff0c;网…