LLM之RAG實戰(五十一)| 使用python和Cypher解析PDF數據,并加載到Neo4j數據庫

一、必備條件:

  • python語言
  • Neo4j數據庫
  • python庫:neo4j、llmsherpa、glob、dotenv

二、代碼:

from llmsherpa.readers import LayoutPDFReaderfrom neo4j import GraphDatabaseimport uuidimport hashlibimport osimport globfrom datetime import datetimeimport timefrom dotenv import load_dotenv?# Load environment variablespath = "/home/QA/Neo4j_Stage1/.env"load_dotenv(path)?# Neo4j configurationNEO4J_URL = os.environ["NEO4J_URI"]NEO4J_USER = "neo4j"NEO4J_PASSWORD = os.environ["NEO4J_PASSWORD"]NEO4J_DATABASE = "neo4j"?# File location for PDFsfile_location = '/home/QA/Neo4j_Stage1/PDFs'?# Initialize Neo4jdef initialiseNeo4j():    cypher_schema = [        "CREATE CONSTRAINT sectionKey IF NOT EXISTS FOR (c:Section) REQUIRE (c.key) IS UNIQUE;",        "CREATE CONSTRAINT chunkKey IF NOT EXISTS FOR (c:Chunk) REQUIRE (c.key) IS UNIQUE;",        "CREATE CONSTRAINT documentKey IF NOT EXISTS FOR (c:Document) REQUIRE (c.url_hash) IS UNIQUE;",        "CREATE CONSTRAINT tableKey IF NOT EXISTS FOR (c:Table) REQUIRE (c.key) IS UNIQUE;",        "CALL db.index.vector.createNodeIndex('chunkVectorIndex', 'Embedding', 'value', 1536, 'COSINE');"    ]?    driver = GraphDatabase.driver(NEO4J_URL, database=NEO4J_DATABASE, auth=(NEO4J_USER, NEO4J_PASSWORD))    with driver.session() as session:        for cypher in cypher_schema:            session.run(cypher)    driver.close()?# Ingest document into Neo4jdef ingestDocumentNeo4j(doc, doc_location):    cypher_pool = [        "MERGE (d:Document {name: $doc_name_val}) ON CREATE SET d.url = $doc_url_val RETURN d;",        "MERGE (p:Section {key: $doc_name_val+'|'+$block_idx_val+'|'+$title_hash_val}) ON CREATE SET p.page_idx = $page_idx_val, p.title_hash = $title_hash_val, p.block_idx = $block_idx_val, p.title = $title_val, p.tag = $tag_val, p.level = $level_val RETURN p;",        "MATCH (d:Document {name: $doc_name_val}) MATCH (s:Section {key: $doc_name_val+'|'+$block_idx_val+'|'+$title_hash_val}) MERGE (d)<-[:HAS_DOCUMENT]-(s);",        "MATCH (s1:Section {key: $doc_name_val+'|'+$parent_block_idx_val+'|'+$parent_title_hash_val}) MATCH (s2:Section {key: $doc_name_val+'|'+$block_idx_val+'|'+$title_hash_val}) MERGE (s1)<-[:UNDER_SECTION]-(s2);",        "MERGE (c:Chunk {key: $doc_name_val+'|'+$block_idx_val+'|'+$sentences_hash_val}) ON CREATE SET c.sentences = $sentences_val, c.sentences_hash = $sentences_hash_val, c.block_idx = $block_idx_val, c.page_idx = $page_idx_val, c.tag = $tag_val, c.level = $level_val RETURN c;",        "MATCH (c:Chunk {key: $doc_name_val+'|'+$block_idx_val+'|'+$sentences_hash_val}) MATCH (s:Section {key:$doc_name_val+'|'+$parent_block_idx_val+'|'+$parent_hash_val}) MERGE (s)<-[:HAS_PARENT]-(c);",        "MERGE (t:Table {key: $doc_name_val+'|'+$block_idx_val+'|'+$name_val}) ON CREATE SET t.name = $name_val, t.doc_name = $doc_name_val, t.block_idx = $block_idx_val, t.page_idx = $page_idx_val, t.html = $html_val, t.rows = $rows_val RETURN t;",        "MATCH (t:Table {key: $doc_name_val+'|'+$block_idx_val+'|'+$name_val}) MATCH (s:Section {key: $doc_name_val+'|'+$parent_block_idx_val+'|'+$parent_hash_val}) MERGE (s)<-[:HAS_PARENT]-(t);",        "MATCH (t:Table {key: $doc_name_val+'|'+$block_idx_val+'|'+$name_val}) MATCH (s:Document {name: $doc_name_val}) MERGE (s)<-[:HAS_PARENT]-(t);"    ]?    driver = GraphDatabase.driver(NEO4J_URL, database=NEO4J_DATABASE, auth=(NEO4J_USER, NEO4J_PASSWORD))    with driver.session() as session:        doc_name_val = os.path.basename(doc_location)        doc_url_val = doc_location        cypher = cypher_pool[0]        session.run(cypher, doc_name_val=doc_name_val, doc_url_val=doc_url_val)?        for sec in doc.sections():            sec_title_val = sec.title            sec_title_hash_val = hashlib.md5(sec_title_val.encode("utf-8")).hexdigest()            sec_tag_val = sec.tag            sec_level_val = sec.level            sec_page_idx_val = sec.page_idx            sec_block_idx_val = sec.block_idx?            if sec_tag_val != 'table':                cypher = cypher_pool[1]                session.run(cypher, page_idx_val=sec_page_idx_val, title_hash_val=sec_title_hash_val, title_val=sec_title_val, tag_val=sec_tag_val, level_val=sec_level_val, block_idx_val=sec_block_idx_val, doc_name_val=doc_name_val)?                sec_parent_val = str(sec.parent.to_text())                if sec_parent_val == "None":                    cypher = cypher_pool[2]                    session.run(cypher, page_idx_val=sec_page_idx_val, title_hash_val=sec_title_hash_val, doc_name_val=doc_name_val, block_idx_val=sec_block_idx_val)                else:                    sec_parent_title_hash_val = hashlib.md5(sec_parent_val.encode("utf-8")).hexdigest()                    sec_parent_page_idx_val = sec.parent.page_idx                    sec_parent_block_idx_val = sec.parent.block_idx                    cypher = cypher_pool[3]                    session.run(cypher, page_idx_val=sec_page_idx_val, title_hash_val=sec_title_hash_val, block_idx_val=sec_block_idx_val, parent_page_idx_val=sec_parent_page_idx_val, parent_title_hash_val=sec_parent_title_hash_val, parent_block_idx_val=sec_parent_block_idx_val, doc_name_val=doc_name_val)?        for chk in doc.chunks():            chunk_block_idx_val = chk.block_idx            chunk_page_idx_val = chk.page_idx            chunk_tag_val = chk.tag            chunk_level_val = chk.level            chunk_sentences = "\n".join(chk.sentences)?            if chunk_tag_val != 'table':                chunk_sentences_hash_val = hashlib.md5(chunk_sentences.encode("utf-8")).hexdigest()                cypher = cypher_pool[4]                session.run(cypher, sentences_hash_val=chunk_sentences_hash_val, sentences_val=chunk_sentences, block_idx_val=chunk_block_idx_val, page_idx_val=chunk_page_idx_val, tag_val=chunk_tag_val, level_val=chunk_level_val, doc_name_val=doc_name_val)?                chk_parent_val = str(chk.parent.to_text())                if chk_parent_val != "None":                    chk_parent_hash_val = hashlib.md5(chk_parent_val.encode("utf-8")).hexdigest()                    chk_parent_page_idx_val = chk.parent.page_idx                    chk_parent_block_idx_val = chk.parent.block_idx                    cypher = cypher_pool[5]                    session.run(cypher, sentences_hash_val=chunk_sentences_hash_val, block_idx_val=chunk_block_idx_val, parent_hash_val=chk_parent_hash_val, parent_block_idx_val=chk_parent_block_idx_val, doc_name_val=doc_name_val)?        for tb in doc.tables():            page_idx_val = tb.page_idx            block_idx_val = tb.block_idx            name_val = 'block#' + str(block_idx_val) + '_' + tb.name            html_val = tb.to_html()            rows_val = len(tb.rows)            cypher = cypher_pool[6]            session.run(cypher, block_idx_val=block_idx_val, page_idx_val=page_idx_val, name_val=name_val, html_val=html_val, rows_val=rows_val, doc_name_val=doc_name_val)?            table_parent_val = str(tb.parent.to_text())            if table_parent_val != "None":                table_parent_hash_val = hashlib.md5(table_parent_val.encode("utf-8")).hexdigest()                table_parent_page_idx_val = tb.parent.page_idx                table_parent_block_idx_val = tb.parent.block_idx                cypher = cypher_pool[7]                session.run(cypher, name_val=name_val, block_idx_val=block_idx_val, parent_page_idx_val=table_parent_page_idx_val, parent_hash_val=table_parent_hash_val, parent_block_idx_val=table_parent_block_idx_val, doc_name_val=doc_name_val)            else:                cypher = cypher_pool[8]                session.run(cypher, name_val=name_val, block_idx_val=block_idx_val, doc_name_val=doc_name_val)?        print(f'\'{doc_name_val}\' Done! Summary: ')        print('#Sections: ' + str(len(doc.sections())))        print('#Chunks: ' + str(len(doc.chunks())))        print('#Tables: ' + str(len(doc.tables())))?    driver.close()?# Parse PDFs and ingest into Neo4jdef parseAndIngestPDFs():    pdf_files = glob.glob(file_location + '/*.pdf')    print(f'#PDF files found: {len(pdf_files)}!')?    pdf_reader = LayoutPDFReader("https://readers.llmsherpa.com/api/document/developer/parseDocument?renderFormat=all")?    startTime = datetime.now()?    for pdf_file in pdf_files:        doc = pdf_reader.read_pdf(pdf_file)        ingestDocumentNeo4j(doc, pdf_file)?    print(f'Total time: {datetime.now() - startTime}')?# Initialize Neo4jinitialiseNeo4j()?# Parse PDFs and ingest into Neo4jparseAndIngestPDFs()

三、代碼解釋

3.1 設置

  • 導入Neo4j環境變量
  • 設置Neo4j唯一key

3.2?初始化Neo4j

  • 建立與 Neo4j 的連接并創建必要的約束以確保數據完整性。

3.3?提取文檔內容

  • 抽取PDFsection、塊和表格數據
  • 使用 Cypher 查詢在 Neo4j 圖形中創建和鏈接節點

3.4 解析PDF內容

  1. 查找指定目錄中的所有 PDF 文件;

  2. 使用 LayoutPDFReader 解析每個 PDF;

  3. 將解析后的數據加入到Neo4j數據庫中;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/65595.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/65595.shtml
英文地址,請注明出處:http://en.pswp.cn/web/65595.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MLU上使用MagicMind GFPGANv1.4 onnx加速!

文章目錄 前言一、平臺環境準備二、環境準備1.GFPGAN代碼處理2.MagicMind轉換修改env.sh修改run.sh參數解析運行 3.修改后模型運行 前言 MagicMind是面向寒武紀MLU的推理加速引擎。MagicMind能將人工智能框架&#xff08;TensorFlow、PyTorch、Caffe與ONNX等&#xff09;訓練好…

關于大數據的基礎知識(一)——定義特征結構要素

成長路上不孤單&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///計算機愛好者&#x1f60a;///持續分享所學&#x1f60a;///如有需要歡迎收藏轉發///&#x1f60a;】 今日分享關于大數據的基礎知識&#xff08;一&a…

H5通過URL Scheme喚醒手機地圖APP

1.高德地圖 安卓URL Scheme&#xff1a;baidumap:// 官方文檔&#xff1a;https://lbs.amap.com/api/amap-mobile/guide/android/navigation IOS URL Scheme&#xff1a;iosamap:// 官方文檔&#xff1a;https://lbs.amap.com/api/amap-mobile/guide/ios/navi HarmonyOS NEXT U…

音視頻入門基礎:MPEG2-PS專題(5)——FFmpeg源碼中,解析PS流中的PES流的實現

音視頻入門基礎&#xff1a;MPEG2-PS專題系列文章&#xff1a; 音視頻入門基礎&#xff1a;MPEG2-PS專題&#xff08;1&#xff09;——MPEG2-PS官方文檔下載 音視頻入門基礎&#xff1a;MPEG2-PS專題&#xff08;2&#xff09;——使用FFmpeg命令生成ps文件 音視頻入門基礎…

國標GB28181-2022視頻平臺EasyGBS小知識:局域網ip地址不夠用怎么解決?

在局域網中&#xff0c;IP地址不足的問題通常不會在小型網絡中出現&#xff0c;但在擁有超過255臺設備的大型局域網中&#xff0c;就需要考慮如何解決IP地址不夠用的問題了。 在企業局域網中&#xff0c;經常會出現私有IP地址如192.168.1.x到192.168.1.255不夠用的情況。由于0…

spring boot啟動源碼分析(三)之Environment準備

上一篇《spring-boot啟動源碼分析&#xff08;二&#xff09;之SpringApplicationRunListener》 環境介紹&#xff1a; spring boot版本&#xff1a;2.7.18 主要starter:spring-boot-starter-web 本篇開始講啟動過程中Environment環境準備&#xff0c;Environment是管理所有…

springmvc前端傳參,后端接收

RequestMapping注解 Target({ElementType.METHOD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Mapping public interface RequestMapping {String name() default "";AliasFor("path")String[] value() default {};AliasFor(&quo…

分布式鎖 Redis vs etcd

為什么要實現分布式鎖?為什么需要分布式鎖,分布式鎖的作用是什么,哪些場景會使用到分布式鎖?分布式鎖的實現方式有哪些分布式鎖的核心原理是什么 如何實現分布式鎖redis(自旋鎖版本)etcd 的分布式鎖(互斥鎖(信號控制)版本) 分布式鎖對比redis vs etcd 總結 為什么要實現分布式…

【Excel/WPS】根據平均值,生成兩列/多列指定范圍的隨機數/隨機湊出兩列數據

原理就是通過隨機生成函數和平均值函數。 適用場景&#xff1a;在總體打分后&#xff0c;需要在小項中隨機生成小分數 第一列&#xff1a;固定的平均值A2第二列&#xff1a; RANDBETWEEN(A2-10,A210)第三列&#xff1a;根據第二列用平均值函數算除 A2*2-B2這是隨機值1的公式&am…

芯片詳細講解,從而區分CPU、MPU、DSP、GPU、FPGA、MCU、SOC、ECU

目錄 芯片的概念結構 芯片的派系劃分 通用芯片&#xff08;CPU&#xff0c;MPU&#xff0c;GPU&#xff0c;DSP&#xff09; 定制芯片&#xff08;FPGA&#xff0c;ASIC&#xff09; 芯片之上的集成&#xff08;MCU&#xff0c;SOC&#xff0c;ECU&#xff09; 軟硬件的匹…

運動相機拍攝的視頻打不開怎么辦

3-10 GoPro和大疆DJI運動相機的特點&#xff0c;小巧、高清、續航長、拍攝穩定&#xff0c;很多人會在一些重要場合用來拍攝視頻&#xff0c;比如可以用來拿在手里拍攝快速運動中的人等等。 但是畢竟是電子產品&#xff0c;有時候是會出點問題的&#xff0c;比如意外斷電、摔重…

智能化文檔開發(DI)

這個文檔涉及到多模態&#xff08;文本、發票、訂單、語音&#xff09; 對于普通的文本&#xff0c;我們希望對某些實體的某些屬性挖空生成文檔模版&#xff0c;并根據預設字段填空最后生成正式文件對于發票、訂單&#xff0c;我們想提取它的字段信息&#xff0c;寫入DB對于一些…

CSS語言的編程范式

CSS語言的編程范式 引言 在現代網頁開發中&#xff0c;CSS&#xff08;層疊樣式表&#xff09;作為一種樣式語言&#xff0c;承擔著網站前端呈現的重要角色。無論是簡單的靜態網頁還是復雜的單頁應用&#xff0c;CSS都在人機交互中發揮著至關重要的作用。掩蓋在美觀背后的&am…

【輕松學C:編程小白的大冒險】--- C語言簡介 02

在編程的藝術世界里&#xff0c;代碼和靈感需要尋找到最佳的交融點&#xff0c;才能打造出令人為之驚嘆的作品。而在這座秋知葉i博客的殿堂里&#xff0c;我們將共同追尋這種完美結合&#xff0c;為未來的世界留下屬于我們的獨特印記。 【輕松學C&#xff1a;編程小白的大冒險】…

零基礎 監控數據可視化 Spring Boot 2.x(Actuator + Prometheus + Grafana手把手) (上)

一、安裝Prometheus Releases prometheus/prometheus GitHubhttps://github.com/prometheus/prometheus/releases 或 https://prometheus.io/download/https://prometheus.io/download/ 1. 下載適用于 Windows 的二進制文件&#xff1a; 找到最新版本的發布頁面&#xf…

Idea日志亂碼

問題描述 前提&#xff1a;本人使用windows Idea運行sh文件&#xff0c;指定了utf-8編碼&#xff0c;但是運行過程中還是存在中文亂碼 Idea的相關配置都已經調整 字體調整為雅黑 文件編碼均調整為UTF-8 調整Idea配置文件 但是還是存在亂碼&#xff0c;既然Idea相關配置已經…

Linux 注冊線程化的中斷處理程序

1. 注冊線程化中斷處理函數 devmem_request_threaded_irq 是 Linux 內核中的一個函數&#xff0c;用于請求并注冊一個線程化的中斷處理程序。這個函數允許開發者注冊一個中斷處理函數&#xff0c;這個函數會在中斷發生時被調用&#xff0c;從而實現相應的中斷處理邏輯。它通過…

MySQL 數據表與索引設計藝術:打造高效數據存取架構

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《MySQL技術精粹》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、什么是MySQL 2、MySQL適用場景 二、MySQL的數據存儲與檢索 1、數據表…

安卓硬件加速hwui

安卓硬件加速 本文基于安卓11。 從 Android 3.0 (API 級別 11) 開始&#xff0c;Android 2D 渲染管道支持硬件加速&#xff0c;這意味著在 View 的畫布上執行的所有繪圖操作都使用 GPU。由于啟用硬件加速所需的資源增加&#xff0c;你的應用程序將消耗更多內存。 軟件繪制&am…

海信116英寸RGB-Mini LED:一朵綻放在科技穹頂的中國花火

東方古鎮的打鐵花&#xff0c;拉斯維加斯的煙花秀&#xff0c;盛大的花火表演總會在歲末年初的時候&#xff0c;吸引世界各地人們的目光。一年一度的科技展會&#xff0c;也起到煙花秀一樣的作用&#xff0c;讓人們提前望見未知的精彩。 CES還沒開始&#xff0c;CES 2025展會的…