精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路 原創 精華

發布于 2024-5-15 10:25
瀏覽
1收藏

編者按: 目前,檢索增強生成(RAG)系統成為了將海量知識賦能于大模型的關鍵技術之一。然而,如何高效地處理半結構化和非結構化數據,尤其是文檔中的表格數據,仍然是 RAG 系統面臨的一大難題。

本文作者針對這一痛點,提出了一種處理表格數據的新穎解決方案。作者首先系統性地梳理了RAG系統中表格處理的核心技術,包括表格解析、索引結構設計等,并評述了現有的一些開源解決方案。在此基礎上,作者提出了自己的創新之處——利用Nougat工具準確高效地解析文檔中的表格內容,使用語言模型對表格及其標題進行內容摘要,最后構建一種新型的document summary索引結構,并給出了完整的代碼實現細節。

這種方法的優點是既能有效解析表格,又能全面考慮表格摘要與表格之間的關系,且無須使用多模態 LLM ,能夠節省解析成本。讓我們拭目以待該方案在實踐中的進一步應用和發展。

作者 | Florian June

編譯 | 岳揚

RAG 系統的實現是一項極具挑戰性的任務,特別是需要解析和理解非結構化文檔中的表格時。而對于經過掃描操作數字化的文檔(scanned documents)或圖像格式的文檔(documents in image format)來說,實現這些操作就更加困難了。至少有三個方面的挑戰:

  • 經過掃描操作數字化的文檔(scanned documents)或圖像格式的文檔(documents in image format)比較復雜,如文檔結構的多樣性、文檔中可能包含一些非文本元素(non-text elements)以及文檔中可能同時存在手寫和印刷內容,都會為表格信息的準確自動化提取帶來挑戰。不準確的文檔解析會破壞表格結構,將不完整的表格信息轉換為向量表征(embedding)不僅無法有效捕捉表格的語義信息,還很容易導致 RAG 的最終輸出結果出現問題。
  • 如何提取每個表格的標題,如何將它們與對應的那個具體表格關聯起來。
  • 如何通過合理的索引結構設計,將表格中的關鍵語義信息高效組織和存儲起來。

本文首先介紹了如何在檢索增強生成(Retrieval Augmented Generation, RAG)模型中管理和處理表格數據。然后回顧了一些現有的開源解決方案,最后在當前的技術基礎上,設計和實現了一種新穎的表格數據管理方法。

01 RAG表格數據相關核心技術介紹

1.1 Table Parsing 表格數據的解析

該模塊的主要功能是從非結構化文檔或圖像中準確提取表格結構(table structure)。

附加需求: 最好能提取出相應的表格標題,方便開發人員將表格標題與表格關聯起來。

根據我目前的理解,有以下幾種方法,如圖 1 所示:

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 1:Table parser(表格解析器)。圖片由原文作者提供。

(a).  利用多模態LLM(如GPT-4V[1])識別表格,并從每個 PDF 頁面中提取信息。

  • 輸入:圖像格式的 PDF 頁面
  • 輸出:JSON或其他格式的表格數據。如果多模態 LLM 無法提取表格數據,則應對 PDF 圖像進行總結并返回內容摘要。

(b). 利用專業的表格檢測模型(如Table Transformer[2])來識別表格結構。

  • 輸入:PDF 頁面圖像
  • 輸出:表格圖像

(c).  使用開源框架,如 unstructured[3] 或其他也采用目標檢測模型(object detection models)的框架(這篇文章[4]詳細介紹了 unstructured 的表格檢測過程)。這些框架可以對整個文檔進行全面解析,并從解析結果中提取與表格相關的內容。

  • 輸入:PDF或圖像格式的文檔
  • 輸出:純文本或 HTML 格式的表格(從整個文檔的解析結果中獲得)

(d).  使用 Nougat[5]、Donut[6] 等端到端模型(end-to-end models),解析整個文檔并提取與表格相關的內容。這種方法不需要 OCR 模型。

  • 輸入:PDF 或圖像格式的文檔
  • 輸出:LaTeX 或 JSON 格式的表格(從整個文檔的解析結果中獲得)

需要說明的是,無論使用哪種方法提取表格信息,都應同時提取出表格標題。因為在大多數情況下,表格標題是文檔作者或論文作者對表格的簡要描述,可以在很大程度上概括整個表格的內容。

在上述四種方法中,方法(d)可以較為方便地檢索表格標題。 這對開發人員來說大有裨益,因為他們可以將表格標題與表格關聯起來。下面的實驗將對此作進一步說明。

1.2 Index Structure 如何索引表格數據

大致有以下幾類建立索引的方法:

(e).  只為圖像格式的表格建立索引。

(f).  只為純文本或JSON格式的表格建立索引。

(g).  只為LaTeX格式的表格建立索引。

(h).  只為表格的摘要建立索引。

(i).  Small-to-big(譯者注:既包含細粒度索引,比如對每一行或表格摘要建立索引,也包含粗粒度索引,比如索引整個表格的圖像、純文本或 LaTeX 類型數據,形成一種分層的、從小到大的索引結構。) 或使用表格摘要建立索引結構,如圖2所示。

The content of the small chunk(譯者注:細粒度索引層級對應的數據塊)比如將表格的每一行或摘要信息作為一個獨立的小數據塊。

The content of the big chunk(譯者注:粗粒度索引層級對應的數據塊)可能是圖像格式、純文本格式或LaTeX格式的整個表格。

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 2:以 small-to-big 的方式建立索引(上)和使用表格摘要建立索引(中、下)。圖片由原文作者提供。

如上所述,表格摘要通常是使用 LLM 處理生成的:

  • 輸入:圖像格式、文本格式或 LaTeX 格式的表格
  • 輸出:表格摘要

1.3 無需解析表格、建立索引或使用 RAG 技術的方法

有些算法不需要進行表格數據的解析。

(j).  將相關圖像(PDF文檔頁)和用戶的 query 發送給 VQA 模型(如 DAN[7] 等)(譯者注:視覺問答(Visual Question Answering)模型的簡稱。是一種結合了計算機視覺和自然語言處理技術的模型,可用于回答關于圖像內容的自然語言問題。)或多模態 LLM,并返回答案。

  • 要被索引的內容: 圖像格式的文檔
  • 發送給 VQA 模型或多模態 LLM 的內容:Query + 圖像形式的相應文檔頁面

(k).  向 LLM 發送相關文本格式的 PDF 頁面和用戶的 query ,然后返回答案。

  • 要被索引的內容: 文本格式文檔
  • 發送給 LLM 的內容:Query + 文本格式的相應文檔頁面

(l).  向多模態 LLM(如 GPT-4V 等)發送相關文檔圖像(PDF 文檔頁面)、文本塊和用戶的 Query,然后直接返回答案。

  • 要被索引的內容: 圖像格式的文檔和文本格式的文檔塊(document chunks)
  • 發送給多模態 LLM 的內容:Query + 相應圖像格式的文檔 + 相應文本塊(text chunks)

此外,下面還有一些不需要建立索引的方法,如圖 3 和圖 4 所示:

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 3:Category (m)(譯者注:下面第一段介紹的內容)。圖片由原文作者提供。

(m).  首先,使用(a)至(d)中的任何一種方法,將文檔中的所有表格解析為圖像形式。然后,將所有表格圖像和用戶的 query 直接發送給多模態 LLM(如 GPT-4V 等),并返回答案。

  • 要被索引的內容: 無
  • 發送給多模態 LLM 的內容:Query + 所有已經轉換為圖像格式的表格

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 4:Ctegory (n)(譯者注:下面第一段介紹的內容)。圖片由原文作者提供。

(n).  使用通過(m)方法提取到的圖像格式的表格,然后使用 OCR 模型識別表格中的所有文本,然后直接將表格中的所有文本和用戶的 Query 發送到 LLM,并直接返回答案。

  • 需要索引的內容: 無
  • 發送給 LLM 的內容:用戶的 Query + 所有表格內容(以文本格式發送)

值得注意的是,在處理文檔中的表格時,有些方法并沒有使用 RAG(Retrieval-Augmented Generation)技術:

  • 第一類方法沒有使用 LLM,而是在特定數據集上進行訓練,使得 AI 模型(如基于 Transformer 架構并受到 BERT 啟發的其他語言模型)來更好地支持表格理解任務的處理,比如 TAPAS [8]。
  • 第二類方法是使用 LLM,采用預訓練、微調方法或提示詞工程,使得 LLM 能夠完成表格理解任務,如 GPT4Table[9]。

02 現有的表格處理開源解決方案

上一節總結并歸類了 RAG 系統中表格數據處理的關鍵技術。在提出本文要實現的解決方案之前,我們先來探索一些開源解決方案。

LlamaIndex 提出了四種方法[10],其中前三種均使用了多模態模型(multimodal models)。

  • 檢索相關的PDF 頁面圖像并將其發送給 GPT-4V 響應用戶 Query 。
  • 將每個 PDF 頁面均轉換為圖像格式,讓 GPT-4V 對每個頁面進行圖像推理(image reasoning)。為圖像推理過程建立 Text Vector Store index(譯者注:將從圖像中推理出的文本信息轉換成向量形式,并建立索引),然后根據 Image Reasoning Vector Store(譯者注:應當就是前面的索引,對前文建立的 Text Vector Store index 進行查詢。) 查詢答案。
  • 使用 Table Transformer 從檢索到的圖像中裁剪表格信息,然后將這些裁剪后的表格圖像發送到 GPT-4V 獲取 query responses (譯者注:向模型發送 Query 并獲取模型返回的答案)。
  • 在裁剪后的表格圖像上應用 OCR,并將數據發送給 GPT4/ GPT-3.5 來回答用戶的 query 。

總結一下上述四種方法:

  • 第一種方法類似于本文中介紹的(j)方法,不需要進行表格解析。但結果表明,即使答案就在圖像中,也無法產生正確答案。
  • 第二種方法涉及到表格的解析,對應于方法(a)。索引內容可能是表格內容或內容摘要,完全取決于 GPT-4V 返回的結果,可能對應于方法 (f) 或 (h)。這種方法的缺點是,GPT-4V 從文檔圖像中識別表格并提取其內容的能力不穩定,尤其是當文檔圖像中包含表格、文本和其他圖像(在 PDF 文檔中這種情況很常見)時。
  • 第三種方法與方法(m)類似,不需要編制索引。
  • 第四種方法與方法(n)相似,也不需要編制索引。其結果表明,產生錯誤答案的原因是無法從圖像中有效提取表格信息。

通過進行測試發現,第三種方法的整體效果最好。不過,根據我進行的測試,第三種方法在檢測表格這方面就很吃力,更不用說正確提取并關聯合并表格標題和表格內容了。

Langchain 也對半結構化數據的 RAG(Semi-structured RAG)[11] 技術提出了一些解決方案,核心技術包括:

  • 使用 unstructured 進行表格解析,這屬于(c)類方法。
  • 索引方法是 document summary index (譯者注:將文檔摘要信息作為索引內容),屬于(i)類方法。細粒度索引層級對應的數據塊:表格摘要內容,粗粒度索引層級對應的數據塊:原始表格內容(文本格式)。

如圖 5 所示:

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 5 :Langchain 的 Semi-structured RAG 方案 。Source: Semi-structured RAG[11]

Semi-structured and Multi-modal RAG[12] 提出了三種解決方案,其架構如圖 6 所示。

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 6:Langchain 的 semi-structured and multi-modal RAG 方案。Source: Semi-structured and Multi-modal RAG[12].

Option 1 類似于前文的方法(l)。這種方法涉及使用多模態嵌入(multimodal embeddings)(如CLIP[13]),將圖像和文本轉換為嵌入向量,然后使用相似性搜索算法(similarity search)檢索兩者,并將未經處理的圖像和文本數據傳遞給多模態 LLM ,讓它們一起處理并生成問題答案。

Option 2 利用多模態 LLM (如 GPT-4V[14] 、LLaVA[15] 或 FUYU-8b[16]),處理圖像生成文本摘要(text summaries)。然后,將文本數據轉換為嵌入向量,再使用這些向量來搜索或檢索與用戶提出的 Query 相匹配的文本內容,并將這些文本內容傳遞給 LLM 生成答案。

  • 表格數據的解析使用 unstructured,屬于(d)類方法。
  • 索引方法是 document summary index (譯者注:將文檔摘要信息作為索引內容),屬于(i)類方法,細粒度索引層級對應的數據塊:表格摘要內容,粗粒度索引層級對應的數據塊:文本格式的表格內容。

Option 3 使用多模態 LLM (如 GPT-4V[14] 、LLaVA[15] 或 FUYU-8b[16])從圖像數據中生成文本摘要,然后將這些文本摘要嵌入向量化,利用這些嵌入向量,可以對圖像摘要進行高效檢索(retrieve),在檢索到的每個圖像摘要中,都保留有一個對應的原始圖像的引用(reference to the raw image),這屬于上文的 (i) 類方法,最后將未經處理的圖像數據和文本塊傳遞給多模態 LLM 以便生成答案。

03 本文提出的解決方案

前文對關鍵技術和現有解決方案進行了總結、分類和討論。在此基礎上,我們提出了以下解決方案,如圖 7 所示。為簡化起見,圖中省略了一些 RAG 模塊,如 Re-ranking 和 query rewriting 。

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 7:本文提出的解決方案。圖片由原文作者提供。

  • 表格解析技術:使用 Nougat ( (d) 類方法)。根據我的測試,這種工具的表格檢測能力比 unstructured( (c) 類技術)更有效。此外,Nougat 還能很好地提取表格標題,非常方便與表格進行關聯。
  • 用于索引和檢索文檔摘要的索引結構( (i) 類方法):細粒度索引層級對應的內容包括表格內容摘要,粗粒度索引層級對應的內容包括 LaTeX 格式的相應表格和文本格式的表格標題。我們使用 multi-vector retriever[17] (譯者注:一種用于檢索文檔摘要索引中內容的檢索器,該檢索器可以同時處理多個向量,以便有效地檢索與 Query 相關的文檔摘要。)來實現。
  • 表格內容摘要的獲取方法:將表格和表格標題發送給 LLM 進行內容摘要。

這種方法的優點是既能有效解析表格,又能全面考慮表格摘要與表格之間的關系。省去了使用多模態 LLM 的需求,從而節省了成本。

3.1 Nougat 的工作原理

Nougat[18] 基于 Donut[19] 架構開發,這種方法使用的算法能夠在沒有任何與 OCR 相關的輸入或模塊的情況下,通過隱式的方式自動識別文本。

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 8 :遵循 Donut[19] 的端到端架構(End-to-end architecture)。 Swin Transformer 編碼器接收文檔圖像并將其轉換為 latent embeddings (譯者注:在一個潛在空間中編碼了圖像的信息),然后以自回歸的方式將其轉換為一系列 tokens 。來源:Nougat: Neural Optical Understanding for Academic Documents.[18]

Nougat 在解析公式方面的能力令人印象深刻[20],但它解析表格的能力也非常出色。如圖 9 所示,它可以關聯表格標題,非常方便:

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 9 :Nougat 的運行結果,結果文件為 Mathpix Markdown 格式(可通過 vscode 插件打開),表格以 LaTeX 格式呈現。

在我對十幾篇論文進行的一項測試中,我發現表格標題總是固定在表格的下一行。這種一致性表明這并非偶然。因此,我們比較感興趣 Nougat 是如何實現這種功能的。

鑒于這是一個缺乏中間結果的端到端模型,它的效果很可能嚴重依賴于其訓練數據。

根據代碼分析,表格標題部分的存儲位置和方式,似乎與訓練數據中表格的組織格式是相符的(緊隨 ??\end{table}??? 之后就是 ??caption_parts?? )。

def format_element(
    element: Element, keep_refs: bool = False, latex_env: bool = False
) -> List[str]:
 """
    Formats a given Element into a list of formatted strings.

    Args:
        element (Element): The element to be formatted.
        keep_refs (bool, optional): Whether to keep references in the formatting. Default is False.
        latex_env (bool, optional): Whether to use LaTeX environment formatting. Default is False.

    Returns:
        List[str]: A list of formatted strings representing the formatted element.
    """
 ...
 ...
 if isinstance(element, Table):
        parts = [
 "[TABLE%s]\n\begin{table}\n"
 % (str(uuid4())[:5] if element.id is None else ":" + str(element.id))
 ]
        parts.extend(format_children(element, keep_refs, latex_env))
        caption_parts = format_element(element.caption, keep_refs, latex_env)
        remove_trailing_whitespace(caption_parts)
        parts.append("\end{table}\n")
 if len(caption_parts) > 0:
            parts.extend(caption_parts + ["\n"])
        parts.append("[ENDTABLE]\n\n")
 return parts
 ...
 ...

3.2 Nougat 的優點和缺點

優點:

  • Nougat 可以將以前的解析工具難以解析的部分(如公式和表格)準確地解析為 LaTeX 源代碼。
  • Nougat 的解析結果是一種類似于 Markdown 的半結構化文檔。
  • 能夠輕松獲取表格標題,并方便地與表格進行關聯。

缺點:

  • Nougat 的解析速度較慢,這一點可能會在大規模應用時造成困難。
  • 由于 Nougat 的訓練數據集基本上都是科學論文,因此在具有類似結構的文檔上這種技術表現出色。而在處理非拉丁文本文檔時,其性能就會下降。
  • Nougat 模型每一次只訓練一篇科學論文的一頁,缺乏對其他頁面的了解。這可能會導致解析內容中存在一些前后不一致的現象。因此,如果識別效果不佳,可以考慮將 PDF 分成單獨的幾頁,然后逐頁進行解析。
  • 雙欄論文(two-column papers)中的表格解析不如單欄論文(single-column papers)的解析效果好。

3.3 代碼實現

首先,安裝相關的 Python 軟件包:

pip install langchain
pip install chromadb
pip install nougat-ocr

安裝完成后,需要檢查 Python 軟件包的版本:

langchain                                0.1.12
langchain-community                      0.0.28
langchain-core                           0.1.31
langchain-openai                         0.0.8
langchain-text-splitters                 0.0.1

chroma-hnswlib                           0.7.3
chromadb                                 0.4.24

nougat-ocr                               0.1.17

建立工作環境并導入軟件包:

import os
os.environ["OPENAI_API_KEY"] = "YOUR_OPEN_AI_KEY"

import subprocess
import uuid

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain.retrievers.multi_vector import MultiVectorRetriever
from langchain.storage import InMemoryStore
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings
from langchain_core.runnables import RunnablePassthrough

將論文 《Attention Is All You Need》[21] 下載到路徑 ??YOUR_PDF_PATH??,運行 nougat 來解析 PDF 文件,并從解析結果中獲取 latex 格式的表格數據和文本格式的表格標題。第一次執行該程序會下載必要的模型文件到本地環境。

def june_run_nougat(file_path, output_dir):
 # Run Nougat and store results as Mathpix Markdown
    cmd = ["nougat", file_path, "-o", output_dir, "-m", "0.1.0-base", "--no-skipping"]
    res = subprocess.run(cmd) 
 if res.returncode != 0:
 print("Error when running nougat.")
 return res.returncode
 else:
 print("Operation Completed!")
 return 0

def june_get_tables_from_mmd(mmd_path):
    f = open(mmd_path)
    lines = f.readlines()
    res = []
    tmp = []
    flag = ""
 for line in lines:
 if line == "\begin{table}\n":
            flag = "BEGINTABLE"
 elif line == "\end{table}\n":
            flag = "ENDTABLE"
 
 if flag == "BEGINTABLE":
            tmp.append(line)
 elif flag == "ENDTABLE":
            tmp.append(line)
            flag = "CAPTION"
 elif flag == "CAPTION":
            tmp.append(line)
            flag = "MARKDOWN"
 print('-' * 100)
 print(''.join(tmp))
            res.append(''.join(tmp))
            tmp = []

 return res

file_path = "YOUR_PDF_PATH"
output_dir = "YOUR_OUTPUT_DIR_PATH"

if june_run_nougat(file_path, output_dir) == 1:
 import sys
    sys.exit(1)

mmd_path = output_dir + '/' + os.path.splitext(file_path)[0].split('/')[-1] + ".mmd" 
tables = june_get_tables_from_mmd(mmd_path)

函數 june_get_tables_from_mmd 用于從一個 mmd 文件中提取所有內容(從 ??\begin{table}??? 到 ??\end{table}???,還包括 ??\end{table}?? 后的第一行),如圖10所示。

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 10:Nougat 的運行結果,結果文件為 Mathpix Markdown 格式(可通過 vscode 插件打開),解析出來的表格內容為 latex 格式。函數 june_get_tables_from_mmd 的功能是提取紅框中的表格信息。圖片由原文作者提供。

不過,目前還沒有官方文件規定表格標題必須放在表格下方,或者表格應以 \begin{table} 開始,以 \end{table} 結束。因此,june_get_tables_from_mmd 是一種啟發式的方法(heuristic)。

以下是對 PDF 文檔的表格解析結果:

Operation Completed!
----------------------------------------------------------------------------------------------------
\begin{table}
\begin{tabular}{l c c c} \hline \hline Layer Type & Complexity per Layer & Sequential Operations & Maximum Path Length \ \hline Self-Attention & (O(n^{2}\cdot d)) & (O(1)) & (O(1)) \ Recurrent & (O(n\cdot d^{2})) & (O(n)) & (O(n)) \ Convolutional & (O(k\cdot n\cdot d^{2})) & (O(1)) & (O(log_{k}(n))) \ Self-Attention (restricted) & (O(r\cdot n\cdot d)) & (O(1)) & (O(n/r)) \ \hline \hline \end{tabular}
\end{table}
Table 1: Maximum path lengths, per-layer complexity and minimum number of sequential operations for different layer types. (n) is the sequence length, (d) is the representation dimension, (k) is the kernel size of convolutions and (r) the size of the neighborhood in restricted self-attention.

----------------------------------------------------------------------------------------------------
\begin{table}
\begin{tabular}{l c c c c} \hline \hline \multirow{2}{*}{Model} & \multicolumn{2}{c}{BLEU} & \multicolumn{2}{c}{Training Cost (FLOPs)} \ \cline{2-5}  & EN-DE & EN-FR & EN-DE & EN-FR \ \hline ByteNet [18] & 23.75 & & & \ Deep-Att + PosUnk [39] & & 39.2 & & (1.0\cdot 10^{20}) \ GNMT + RL [38] & 24.6 & 39.92 & (2.3\cdot 10^{19}) & (1.4\cdot 10^{20}) \ ConvS2S [9] & 25.16 & 40.46 & (9.6\cdot 10^{18}) & (1.5\cdot 10^{20}) \ MoE [32] & 26.03 & 40.56 & (2.0\cdot 10^{19}) & (1.2\cdot 10^{20}) \ \hline Deep-Att + PosUnk Ensemble [39] & & 40.4 & & (8.0\cdot 10^{20}) \ GNMT + RL Ensemble [38] & 26.30 & 41.16 & (1.8\cdot 10^{20}) & (1.1\cdot 10^{21}) \ ConvS2S Ensemble [9] & 26.36 & **41.29** & (7.7\cdot 10^{19}) & (1.2\cdot 10^{21}) \ \hline Transformer (base model) & 27.3 & 38.1 & & (\mathbf{3.3\cdot 10^{18}}) \ Transformer (big) & **28.4** & **41.8** & & (2.3\cdot 10^{19}) \ \hline \hline \end{tabular}
\end{table}
Table 2: The Transformer achieves better BLEU scores than previous state-of-the-art models on the English-to-German and English-to-French newstest2014 tests at a fraction of the training cost.

----------------------------------------------------------------------------------------------------
\begin{table}
\begin{tabular}{c|c c c c c c c c|c c c c} \hline \hline  & (N) & (d_{\text{model}}) & (d_{\text{ff}}) & (h) & (d_{k}) & (d_{v}) & (P_{drop}) & (\epsilon_{ls}) & train steps & PPL & BLEU & params \ \hline base & 6 & 512 & 2048 & 8 & 64 & 64 & 0.1 & 0.1 & 100K & 4.92 & 25.8 & 65 \ \hline \multirow{4}{*}{(A)} & \multicolumn{1}{c}{} & & 1 & 512 & 512 & & & & 5.29 & 24.9 & \  & & & & 4 & 128 & 128 & & & & 5.00 & 25.5 & \  & & & & 16 & 32 & 32 & & & & 4.91 & 25.8 & \  & & & & 32 & 16 & 16 & & & & 5.01 & 25.4 & \ \hline (B) & \multicolumn{1}{c}{} & & \multicolumn{1}{c}{} & & 16 & & & & & 5.16 & 25.1 & 58 \  & & & & & 32 & & & & & 5.01 & 25.4 & 60 \ \hline \multirow{4}{*}{(C)} & 2 & \multicolumn{1}{c}{} & & & & & & & & 6.11 & 23.7 & 36 \  & 4 & & & & & & & & 5.19 & 25.3 & 50 \  & 8 & & & & & & & & 4.88 & 25.5 & 80 \  & & 256 & & 32 & 32 & & & & 5.75 & 24.5 & 28 \  & 1024 & & 128 & 128 & & & & 4.66 & 26.0 & 168 \  & & 1024 & & & & & & 5.12 & 25.4 & 53 \  & & 4096 & & & & & & 4.75 & 26.2 & 90 \ \hline \multirow{4}{*}{(D)} & \multicolumn{1}{c}{} & & & & & 0.0 & & 5.77 & 24.6 & \  & & & & & & 0.2 & & 4.95 & 25.5 & \  & & & & & & & 0.0 & 4.67 & 25.3 & \  & & & & & & & 0.2 & 5.47 & 25.7 & \ \hline (E) & \multicolumn{1}{c}{} & \multicolumn{1}{c}{} & & \multicolumn{1}{c}{} & & & & & 4.92 & 25.7 & \ \hline big & 6 & 1024 & 4096 & 16 & & 0.3 & 300K & **4.33** & **26.4** & 213 \ \hline \hline \end{tabular}
\end{table}
Table 3: Variations on the Transformer architecture. Unlisted values are identical to those of the base model. All metrics are on the English-to-German translation development set, newstest2013. Listed perplexities are per-wordpiece, according to our byte-pair encoding, and should not be compared to per-word perplexities.

----------------------------------------------------------------------------------------------------
\begin{table}
\begin{tabular}{c|c|c} \hline
**Parser** & **Training** & **WSJ 23 F1** \ \hline Vinyals & Kaiser et al. (2014) [37] & WSJ only, discriminative & 88.3 \ Petrov et al. (2006) [29] & WSJ only, discriminative & 90.4 \ Zhu et al. (2013) [40] & WSJ only, discriminative & 90.4 \ Dyer et al. (2016) [8] & WSJ only, discriminative & 91.7 \ \hline Transformer (4 layers) & WSJ only, discriminative & 91.3 \ \hline Zhu et al. (2013) [40] & semi-supervised & 91.3 \ Huang & Harper (2009) [14] & semi-supervised & 91.3 \ McClosky et al. (2006) [26] & semi-supervised & 92.1 \ Vinyals & Kaiser el al. (2014) [37] & semi-supervised & 92.1 \ \hline Transformer (4 layers) & semi-supervised & 92.7 \ \hline Luong et al. (2015) [23] & multi-task & 93.0 \ Dyer et al. (2016) [8] & generative & 93.3 \ \hline \end{tabular}
\end{table}
Table 4: The Transformer generalizes well to English constituency parsing (Results are on Section 23 of WSJ)* [5] Kyunghyun Cho, Bart van Merrienboer, Caglar Gulcehre, Fethi Bougares, Holger Schwenk, and Yoshua Bengio. Learning phrase representations using rnn encoder-decoder for statistical machine translation. _CoRR_, abs/1406.1078, 2014.

然后使用 LLM 對表格數據進行總結:

# Prompt
prompt_text = """You are an assistant tasked with summarizing tables and text. \ 
Give a concise summary of the table or text. The table is formatted in LaTeX, and its caption is in plain text format: {element}  """
prompt = ChatPromptTemplate.from_template(prompt_text)

# Summary chain
model = ChatOpenAI(temperature = 0, model = "gpt-3.5-turbo")
summarize_chain = {"element": lambda x: x} | prompt | model | StrOutputParser()
# Get table summaries
table_summaries = summarize_chain.batch(tables, {"max_concurrency": 5})
print(table_summaries)

以下是對《Attention Is All You Need》[21]中四個表格的內容摘要,如圖11所示:

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 11:《Attention Is All You Need》[21]中四個表格的內容摘要。

使用 Multi-Vector Retriever (譯者注:一種用于檢索文檔摘要索引中內容的檢索器,該檢索器可以同時處理多個向量,以便有效地檢索與 Query 相關的文檔摘要。)構建 document summary index structure [17](譯者注:一種索引結構,用于存儲文檔的摘要信息,并可根據需要檢索或查詢這些摘要信息)。

# The vectorstore to use to index the child chunks
vectorstore = Chroma(collection_name = "summaries", embedding_function = OpenAIEmbeddings())

# The storage layer for the parent documents
store = InMemoryStore()
id_key = "doc_id"

# The retriever (empty to start)
retriever = MultiVectorRetriever(
    vectorstore = vectorstore,
    docstore = store,
    id_key = id_key,
    search_kwargs={"k": 1} # Solving Number of requested results 4 is greater than number of elements in index..., updating n_results = 1
)

# Add tables
table_ids = [str(uuid.uuid4()) for _ in tables]
summary_tables = [
    Document(page_content = s, metadata = {id_key: table_ids[i]})
 for i, s in enumerate(table_summaries)
]
retriever.vectorstore.add_documents(summary_tables)
retriever.docstore.mset(list(zip(table_ids, tables)))

一切準備就緒后,建立一個簡單的 RAG pipeline 并執行用戶的 queries :

# Prompt template
template = """Answer the question based only on the following context, which can include text and tables, there is a table in LaTeX format and a table caption in plain text format:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)

# LLM
model = ChatOpenAI(temperature = 0, model = "gpt-3.5-turbo")


# Simple RAG pipeline
chain = (
 {"context": retriever, "question": RunnablePassthrough()}
 | prompt
 | model
 | StrOutputParser()
)


print(chain.invoke("when layer type is Self-Attention, what is the Complexity per Layer?")) # Query about table 1

print(chain.invoke("Which parser performs worst for BLEU EN-DE")) # Query about table 2

print(chain.invoke("Which parser performs best for WSJ 23 F1")) # Query about table 4

運行結果如下,這幾個問題都得到了準確的回答,如圖 12 所示:

Advanced RAG 07:在 RAG 系統中進行表格數據處理的新思路-AI.x社區

圖 12 :對三個用戶 queries 的回答結果。第一行對應于《Attention Is All You Need》中的表 1,第二行對應于表 2,第三行對應于表 4。

總體代碼如下:

import os
os.environ["OPENAI_API_KEY"] = "YOUR_OPEN_AI_KEY"

import subprocess
import uuid

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain.retrievers.multi_vector import MultiVectorRetriever
from langchain.storage import InMemoryStore
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings
from langchain_core.runnables import RunnablePassthrough


def june_run_nougat(file_path, output_dir):
 # Run Nougat and store results as Mathpix Markdown
    cmd = ["nougat", file_path, "-o", output_dir, "-m", "0.1.0-base", "--no-skipping"]
    res = subprocess.run(cmd) 
 if res.returncode != 0:
 print("Error when running nougat.")
 return res.returncode
 else:
 print("Operation Completed!")
 return 0

def june_get_tables_from_mmd(mmd_path):
    f = open(mmd_path)
    lines = f.readlines()
    res = []
    tmp = []
    flag = ""
 for line in lines:
 if line == "\begin{table}\n":
            flag = "BEGINTABLE"
 elif line == "\end{table}\n":
            flag = "ENDTABLE"
 
 if flag == "BEGINTABLE":
            tmp.append(line)
 elif flag == "ENDTABLE":
            tmp.append(line)
            flag = "CAPTION"
 elif flag == "CAPTION":
            tmp.append(line)
            flag = "MARKDOWN"
 print('-' * 100)
 print(''.join(tmp))
            res.append(''.join(tmp))
            tmp = []

 return res

file_path = "YOUR_PDF_PATH"
output_dir = "YOUR_OUTPUT_DIR_PATH"

if june_run_nougat(file_path, output_dir) == 1:
 import sys
    sys.exit(1)

mmd_path = output_dir + '/' + os.path.splitext(file_path)[0].split('/')[-1] + ".mmd" 
tables = june_get_tables_from_mmd(mmd_path)


# Prompt
prompt_text = """You are an assistant tasked with summarizing tables and text. \ 
Give a concise summary of the table or text. The table is formatted in LaTeX, and its caption is in plain text format: {element}  """
prompt = ChatPromptTemplate.from_template(prompt_text)

# Summary chain
model = ChatOpenAI(temperature = 0, model = "gpt-3.5-turbo")
summarize_chain = {"element": lambda x: x} | prompt | model | StrOutputParser()
# Get table summaries
table_summaries = summarize_chain.batch(tables, {"max_concurrency": 5})
print(table_summaries)

# The vectorstore to use to index the child chunks
vectorstore = Chroma(collection_name = "summaries", embedding_function = OpenAIEmbeddings())

# The storage layer for the parent documents
store = InMemoryStore()
id_key = "doc_id"

# The retriever (empty to start)
retriever = MultiVectorRetriever(
    vectorstore = vectorstore,
    docstore = store,
    id_key = id_key,
    search_kwargs={"k": 1} # Solving Number of requested results 4 is greater than number of elements in index..., updating n_results = 1
)

# Add tables
table_ids = [str(uuid.uuid4()) for _ in tables]
summary_tables = [
    Document(page_content = s, metadata = {id_key: table_ids[i]})
 for i, s in enumerate(table_summaries)
]
retriever.vectorstore.add_documents(summary_tables)
retriever.docstore.mset(list(zip(table_ids, tables)))


# Prompt template
template = """Answer the question based only on the following context, which can include text and tables, there is a table in LaTeX format and a table caption in plain text format:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)

# LLM
model = ChatOpenAI(temperature = 0, model = "gpt-3.5-turbo")

# Simple RAG pipeline
chain = (
 {"context": retriever, "question": RunnablePassthrough()}
 | prompt
 | model
 | StrOutputParser()
)

print(chain.invoke("when layer type is Self-Attention, what is the Complexity per Layer?")) # Query about table 1

print(chain.invoke("Which parser performs worst for BLEU EN-DE")) # Query about table 2

print(chain.invoke("Which parser performs best for WSJ 23 F1")) # Query about table 4

04 Conclusion

本文討論了在 RAG 系統中表格處理操作的關鍵技術和現有解決方案,并提出了一種解決方案及其實現方法。

在本文中,我們使用了 Nougat 來解析表格。不過,如果有更快、更有效的解析工具可用,我們會考慮替換掉 Nougat 。我們對工具的態度是先有正確的 idea ,然后再找工具來實現它,而不是依賴于某個工具。

在本文中,我們將所有表格內容輸入到 LLM 。但是,在實際場景中,我們需要考慮到表格大小超出 LLM 上下文長度的情況。我們可以通過使用有效的分塊(chunking)方法來解決這個問題。

Thanks for reading!

——

Florian June

An artificial intelligence researcher, mainly write articles about Large Language Models, data structures and algorithms, and NLP.

END

參考資料

[1]??https://openai.com/research/gpt-4v-system-card??

[2]??https://github.com/microsoft/table-transformer??

[3]??https://unstructured-io.github.io/unstructured/best_practices/table_extraction_pdf.html??

[4]??https://pub.towardsai.net/advanced-rag-02-unveiling-pdf-parsing-b84ae866344e??

[5]??https://github.com/facebookresearch/nougat??

[6]??https://github.com/clovaai/donut/??

[7]??https://arxiv.org/pdf/1611.00471.pdf??

[8]??https://aclanthology.org/2020.acl-main.398.pdf??

[9]??https://arxiv.org/pdf/2305.13062.pdf??

[10]??https://docs.llamaindex.ai/en/stable/examples/multi_modal/multi_modal_pdf_tables.html??

[11]??https://github.com/langchain-ai/langchain/blob/master/cookbook/Semi_Structured_RAG.ipynb?ref=blog.langchain.dev??

[12]??https://github.com/langchain-ai/langchain/blob/master/cookbook/Semi_structured_and_multi_modal_RAG.ipynb??

[13]??https://openai.com/research/clip??

[14]??https://openai.com/research/gpt-4v-system-card??

[15]??https://llava.hliu.cc/??

[16]??https://www.adept.ai/blog/fuyu-8b??

[17]??https://python.langchain.com/docs/modules/data_connection/retrievers/multi_vector??

[18]??https://arxiv.org/pdf/2308.13418.pdf??

[19]??https://arxiv.org/pdf/2111.15664.pdf??

[20]??https://medium.com/@florian_algo/unveiling-pdf-parsing-how-to-extract-formulas-from-scientific-pdf-papers-a8f126f3511d??

[21]??https://arxiv.org/pdf/1706.03762.pdf??

本文經原作者授權,由 Baihai IDP 編譯。如需轉載譯文,請聯系獲取授權。

原文鏈接:

??https://ai.plainenglish.io/advanced-rag-07-exploring-rag-for-tables-5c3fc0de7af6??


?著作權歸作者所有,如需轉載,請注明出處,否則將追究法律責任
1
收藏 1
回復
舉報
回復
相關推薦
欧美日本一区二区三区四区| 国产91精品在线观看| 亚洲欧美制服另类日韩| 日本美女高潮视频| 日本网站在线免费观看视频| 久久精品国产77777蜜臀| 久久99国产精品久久久久久久久| av av在线| 中文字幕日本一区二区| 一区二区三区日韩精品视频| 久久综合九色综合网站| 一区二区不卡视频在线观看| 亚洲国产网站| 中文字幕精品av| 中文字幕99页| 国产精品久久久久久吹潮| 中文字幕综合网| 欧美视频观看一区| 国产女人18毛片18精品| 久久精品人人做人人爽电影蜜月| 久热精品在线视频| 亚洲一区二区自偷自拍| 亚洲精品一二三**| 欧美色图在线观看| 男女猛烈激情xx00免费视频| 欧美边添边摸边做边爱免费| 成人黄色一级视频| 成人在线观看视频网站| 狠狠人妻久久久久久综合| 欧美福利一区| 中文字幕av日韩| 短视频在线观看| 国产精品调教视频| 日韩欧美在线综合网| 婷婷丁香激情网| 在线高清av| 亚洲午夜一区二区三区| 久久免费看毛片| 搞黄视频在线观看| 久久理论电影网| 精品午夜一区二区| 亚洲精品.www| 国产精品羞羞答答xxdd| 国产精品欧美日韩| av手机天堂网| 久久影院亚洲| 日本久久久a级免费| 国产第一页第二页| 国模大胆一区二区三区| 久操成人在线视频| 538精品在线观看| 中文字幕免费一区二区| 久久视频在线免费观看| xxxx日本少妇| 欧美喷水视频| 欧美高清视频在线播放| 国产女人18水真多毛片18精品| 91青青国产在线观看精品| 最新91在线视频| 亚洲人做受高潮| 91精品国产91久久久久久黑人| 日韩视频免费中文字幕| 日韩欧美国产成人精品免费| 久久久久国产精品| 久热99视频在线观看| 免费一级片视频| 亚洲国产婷婷| 国产成+人+综合+亚洲欧美丁香花| 欧美精品韩国精品| 日韩激情一区二区| 成人国产精品av| 国产xxxx在线观看| av亚洲精华国产精华精| 免费成人av网站| 992tv免费直播在线观看| 国产精品久久久久久久裸模| 裸体大乳女做爰69| 俄罗斯一级**毛片在线播放| 午夜国产不卡在线观看视频| 日本黄色三级大片| 四虎国产精品成人免费影视| 日韩色视频在线观看| 国产激情第一页| av在线不卡顿| 久久久精品在线观看| 国产精品18p| 免费一区视频| 91久久国产精品91久久性色| 日韩在线视频第一页| 久久久久久久免费视频了| 在线看视频不卡| 免费网站在线观看人| 91久久国产最好的精华液| 国产一级免费大片| 网曝91综合精品门事件在线| 日韩中文在线中文网三级| 久久9999久久免费精品国产| 久久久成人网| 99高清视频有精品视频| 毛片在线播放网站| 一区二区三区丝袜| www日韩视频| xxxx日韩| 色诱女教师一区二区三区| 国产午夜福利片| 久久精品国产免费| 久久久精品动漫| 9191在线播放| 色国产综合视频| 精品国产免费久久久久久婷婷| 精品午夜久久| 性欧美视频videos6一9| 国产精品一级二级| 久久精品无码一区二区三区 | 午夜精品福利影院| 久久九九全国免费精品观看| 日本一区二区三区精品| 国产一区在线看| 亚欧精品在线| 在线看片福利| 亚洲第一福利网| 一区二区在线观看免费视频| 毛片av一区二区| 免费久久久一本精品久久区| 波多野结衣在线高清| 制服丝袜成人动漫| 国产精品视频在| 久久中文欧美| 另类视频在线观看+1080p| 青春草视频在线观看| 3d成人h动漫网站入口| 亚洲精品国产一区黑色丝袜| 国产视频一区在线观看一区免费| 97碰碰视频| 亚洲国产精品精华素| 欧美精品色一区二区三区| 天天操天天干天天操天天干| 久久激情视频| 欧美精品欧美精品系列c| caoporn视频在线| 精品国产伦一区二区三区免费| www.av免费| 国产中文字幕一区| 在线视频91| 996久久国产精品线观看| 最近2019好看的中文字幕免费| 毛片在线免费播放| 国产欧美精品国产国产专区| 国产第一页视频| 亚洲大片精品免费| 国产91免费观看| 第一页在线观看| 在线观看日韩电影| 变态另类ts人妖一区二区| 日韩国产欧美一区二区三区| 亚洲7777| 3d动漫一区二区三区在线观看| 久久精品国产2020观看福利| 99er热精品视频| 亚洲欧美日韩国产一区二区三区 | 国产aⅴ综合色| 4444亚洲人成无码网在线观看| 亚洲91网站| 韩日欧美一区二区| 久热av在线| 欧美日韩高清影院| 欧美成人精品欧美一级私黄| 成人午夜av电影| av观看免费在线| 成人在线电影在线观看视频| 成人免费视频在线观看超级碰| 中文字幕有码在线视频| 精品少妇一区二区三区在线视频| 亚洲一区 视频| 久久久精品中文字幕麻豆发布| 国产又大又黄又粗又爽| 欧美xxx在线观看| 国产亚洲精品美女久久久m| 在线免费日韩片| 久久精品视频va| 手机在线观看毛片| 欧洲一区二区三区在线| 日韩一级片大全| av爱爱亚洲一区| 一区二区三区 日韩| 欧美片第1页综合| 日本在线观看不卡| 国产日韩在线观看视频| 97成人超碰免| 久操视频在线观看| 国产午夜精品久久久| 在线观看色网站| 亚洲国产视频一区| 色欲AV无码精品一区二区久久 | 久操视频在线| 亚洲精品国产精品自产a区红杏吧| 日韩xxx视频| 亚洲图片自拍偷拍| 欧美巨胸大乳hitomi| jvid福利写真一区二区三区| 玖玖爱视频在线| 亚洲一区二区动漫| 欧美 日韩 国产 在线观看| 视频小说一区二区| 7777精品久久久大香线蕉小说| 色在线中文字幕| 欧美成人国产va精品日本一级| 欧美日韩伦理片| 精品精品欲导航| 一个人看的www日本高清视频| 五月天中文字幕一区二区| 亚洲av无一区二区三区| 久久久噜噜噜久久中文字幕色伊伊| 国产性生活一级片| 日韩黄色免费网站| 国产高清精品在线观看| 欧美一区二区三区久久精品| 色噜噜一区二区| 久久香蕉网站| julia一区二区中文久久94| 欧美aaaaaa| 国产精品黄视频| 激情国产在线| 久久久视频精品| 深夜国产在线播放| 久久久精品一区二区| 日本精品在线| 中文字幕亚洲在线| 国产高清视频在线播放| 日韩精品亚洲视频| 秋霞网一区二区| 欧美一区二区三区啪啪| 国产又粗又猛又爽又黄的| 欧美自拍偷拍午夜视频| 怡红院av久久久久久久| 欧美小视频在线观看| 日韩成人av毛片| 亚洲www啪成人一区二区麻豆| 日韩影院一区二区| 亚洲乱码国产乱码精品精的特点 | 国产 高清 精品 在线 a| 国产精品一区二区三区四区在线观看| 国产精品视频中文字幕91| 成人国产网站| 国产美女精品免费电影| 久久亚洲国产精品尤物| 成人h视频在线观看播放| 国产亚洲人成a在线v网站| 国产久一一精品| 亚洲综合视频| 亚洲一区二区三区四区视频 | 久久影视中文粉嫩av| 任你躁在线精品免费| 老牛影视免费一区二区| 国产一区二区三区四区二区| 日韩欧美一区二区三区久久婷婷| 国产影视一区| 中文字幕乱码一区二区三区| 外国成人激情视频| 91精品一区二区三区四区| 欧美三级乱码| 看av免费毛片手机播放| 久久综合图片| 一本一道久久a久久综合蜜桃| 国产一区二区三区香蕉| 日批视频免费看| 91免费观看视频| 免费一级黄色录像| 亚洲人成在线播放网站岛国| 精品无码免费视频| 色综合久久久久久久久| 中文字幕人妻丝袜乱一区三区| 91精品国产aⅴ一区二区| 好吊色一区二区三区| 精品中文视频在线| 日本亚洲精品| 国外成人在线直播| 精品亚洲美女网站| 91视频婷婷| 亚洲毛片免费看| 在线观看亚洲视频啊啊啊啊| 激情婷婷亚洲| 黑人粗进入欧美aaaaa| 国产在线一区二区| av无码av天天av天天爽| 中文字幕亚洲不卡| 国产精品6666| 欧美久久婷婷综合色| 欧美一级特黄aaaaaa| 一道本无吗dⅴd在线播放一区| 伊人电影在线观看| 国产成人激情视频| 亚洲不卡在线| 亚洲高清在线观看一区| 精品电影一区| 校园春色 亚洲色图| 成人精品一区二区三区中文字幕| 中国女人特级毛片| 亚洲一区欧美一区| 中文字幕一区二区在线视频| 精品美女被调教视频大全网站| 国产高清视频在线| 97视频免费看| 精品欧美视频| 午夜老司机精品| 99热免费精品| 自拍一级黄色片| 国产欧美va欧美不卡在线| 天天插天天操天天干| 欧美一级片在线| av在线三区| 欧美影院在线播放| 91精品国产自产在线丝袜啪| 一本色道久久99精品综合| 欧美一级二区| 久久久久亚洲AV成人无码国产| 亚洲欧美自拍偷拍色图| 日本视频www色| 亚洲精品一区中文| 98色花堂精品视频在线观看| 亚洲一区中文字幕| 99久久夜色精品国产亚洲狼 | 粉嫩aⅴ一区二区三区| 欧美一级日韩不卡播放免费| 777电影在线观看| 国产91久久婷婷一区二区| 欧美wwwsss9999| 蜜臀av色欲a片无码精品一区| 国产在线视频一区二区三区| 亚洲熟女毛茸茸| 欧美日韩黄视频| 在线观看黄av| 国产精品午夜视频| jlzzjlzz亚洲女人| 成年人小视频网站| 久久亚洲影视婷婷| 国产免费av一区| 日韩精品www| 最新欧美色图| 蜜桃91精品入口| 性色av一区二区怡红| 黄色短视频在线观看| 天天综合日日夜夜精品| 人妻与黑人一区二区三区| 久久久久久久电影一区| 97青娱国产盛宴精品视频| 国产一二三区在线播放| 国产91精品在线观看| 国产精品9191| 日韩国产精品一区| 三上悠亚激情av一区二区三区 | 国产激情一区二区三区在线观看| 午夜国产欧美理论在线播放| 久久精品无码一区二区三区毛片| 亚洲精品老司机| 黄色一级大片在线免费看国产一 | 老汉色影院首页| 国产丶欧美丶日本不卡视频| 国产亚洲精品久久久久久打不开| 欧美va在线播放| 高清毛片在线观看| 免费一区二区三区| 奇米一区二区三区av| 91传媒免费观看| 欧美videossexotv100| 黄色视屏在线免费观看| 日韩免费av电影| 国产在线精品一区二区三区不卡| 久草网站在线观看| 亚洲精品美女久久| 国产精品videossex撒尿| 中日韩在线视频| 成人av在线资源| 国产又粗又猛又爽又| 美女精品视频一区| 久久亚州av| 日本不卡一区二区在线观看| 亚洲图片有声小说| fc2在线中文字幕| 成人免费在线看片| 久久精品人人| 亚洲欧美小视频| 亚洲精选一区二区| 999精品嫩草久久久久久99| 国产精品www在线观看| 国产色产综合产在线视频| aaa国产视频| 欧美综合第一页| 正在播放日韩欧美一页| aa片在线观看视频在线播放| 欧美日韩国产区一| 9999精品成人免费毛片在线看| 亚洲精品无人区| 不卡一区二区在线| 亚洲综合精品国产一区二区三区| 久久久久女教师免费一区| 日韩极品一区| 亚洲av无码一区二区三区网址| 欧美日韩高清一区二区不卡| 韩日毛片在线观看|