精品欧美一区二区三区在线观看 _久久久久国色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富婆露脸刺激对白| 欧美在线免费看视频| 欧美+日本+国产+在线a∨观看| 欧美在线啊v一区| 亚洲精品一区二区毛豆| 国产乱码精品一区二三区蜜臂| 天天做天天爱天天综合网| 亚洲成人黄色影院| 欧洲一区二区在线| 97国产成人无码精品久久久| 国产一区二区三区四区老人| 亚洲色图五月天| 国产在线观看中文字幕| 水蜜桃在线视频| 国产精品伊人色| 欧美在线视频观看| 九九精品视频免费| 九一成人免费视频| 日韩欧美国产综合| 黄色片在线免费| 蜜臀av在线播放| 久久精品一区蜜桃臀影院| 91在线免费看网站| 国产精品免费精品一区| 欧美日本不卡高清| 日韩中文在线中文网三级| 国产偷人妻精品一区| 99在线播放| 久久久午夜精品理论片中文字幕| 亚洲一区二区中文| 毛片aaaaaa| 黑人久久a级毛片免费观看| 欧美撒尿777hd撒尿| 91成人在线观看喷潮教学| 麻豆视频在线观看免费| 91麻豆成人久久精品二区三区| 91亚洲精品一区| 中文字幕乱码人妻二区三区| 在线视频精品| 欧美激情亚洲激情| 欧美精品入口蜜桃| 天堂美国久久| 日韩一区视频在线| 亚洲欧美日韩第一页| 久久99青青| 日韩风俗一区 二区| 97精品人妻一区二区三区蜜桃| 成人污版视频| 亚洲精品免费看| 亚洲国产一区二区三区在线| 欧美成人综合在线| 91亚洲精华国产精华精华液| julia一区二区中文久久94| 国产精品久久久久久久久久久久久久久久久久 | 久久中文字幕人妻| 欧美jizz19性欧美| 精品嫩草影院久久| 波多野结衣办公室双飞| 亚洲一二av| 欧美变态凌虐bdsm| 中文在线观看免费视频| 久久久久观看| 亚洲激情中文字幕| 毛茸茸多毛bbb毛多视频| 美女视频亚洲色图| 日韩精品中文字幕视频在线| 无码任你躁久久久久久老妇| 国语一区二区三区| 亚洲男人的天堂网站| 中国美女乱淫免费看视频| 欧美激情极品| 亚洲精品在线看| 国产传媒国产传媒| 色综合五月天| 欧美国产日本高清在线| 久草国产在线视频| 在线亚洲免费| 国产精品久久久久久久7电影| 无码人妻丰满熟妇区五十路| 日产国产高清一区二区三区| 国产精品爽黄69| 国产精品无码天天爽视频| 激情深爱一区二区| 2019中文字幕免费视频| 老熟妇仑乱一区二区av| 蜜臀av性久久久久蜜臀aⅴ| 成人亚洲综合色就1024| 懂色av成人一区二区三区| 亚洲欧美日韩精品一区二区| 欧美中文字幕在线观看| 最近中文字幕在线免费观看| 国产真实乱对白精彩久久| 99热99热| 久久手机免费观看| 亚洲视频你懂的| 日韩欧美亚洲天堂| 亚洲青青久久| 亚洲成在人线av| 日本高清黄色片| 极品中文字幕一区| 久久成人免费视频| 日韩少妇裸体做爰视频| 日韩中文欧美在线| 国产精品一区二区欧美| 久久这里精品| 亚洲国产精品久久人人爱| 毛葺葺老太做受视频| 精品捆绑调教一区二区三区| 欧美性色aⅴ视频一区日韩精品| 天天操夜夜操很很操| 亚洲免费福利一区| 欧美精品www| 一级全黄少妇性色生活片| 99国产精品久| 裸体裸乳免费看| 超碰国产在线观看| 亚洲福利电影网| 污污的网站免费| 亚洲男人都懂第一日本| 欧美二区在线播放| 一级黄色大片网站| 久久久久久久久免费| 国产真实老熟女无套内射| 青青伊人久久| 91精品国产综合久久精品| 青青草福利视频| 欧美激情视频一区二区三区免费| 日韩免费观看在线观看| 三级视频在线看| 亚洲最新在线观看| 男女视频在线观看网站| 成人中文在线| 国产精品扒开腿做爽爽爽视频| 天堂网av在线播放| 一区二区三区 在线观看视频| 一区二区xxx| 精品大片一区二区| 欧美与欧洲交xxxx免费观看| 精品国产亚洲AV| 亚洲欧美另类小说| 成年人网站av| 99精品在线| 91精品久久久久久久久久久久久久 | 欧美3p在线观看| 国产mv久久久| 玖玖综合伊人| 色悠久久久久综合欧美99| www.四虎成人| 麻豆一区二区| 97精品视频在线播放| 丰满肉肉bbwwbbww| 亚洲香蕉伊在人在线观| 精品人妻二区中文字幕| 欧美精品福利| 国产精品免费一区二区三区四区| 污污网站在线观看| 精品国产一区二区三区四区四| 日韩欧美123区| 国产成a人无v码亚洲福利| 4444亚洲人成无码网在线观看| 精品视频在线观看免费观看| 欧美精品一区二区三区高清aⅴ| 1024手机在线视频| 成人一区二区三区中文字幕| 青草青青在线视频| 亚洲春色h网| 国产成人一区三区| 午夜免费视频在线国产| 制服丝袜av成人在线看| 国产精品白嫩白嫩大学美女| 懂色中文一区二区在线播放| 国产自产在线视频| 精品国产精品久久一区免费式| 国产精品久久久久久久久久| 在线视频三区| 555夜色666亚洲国产免| 久久综合亚洲色hezyo国产| 日韩va欧美va亚洲va久久| 亚洲欧美电影在线观看| 久久av偷拍| 97香蕉久久超级碰碰高清版| 美女欧美视频在线观看免费 | 久久久久久有精品国产| 香蕉国产在线视频| 欧美日韩亚洲丝袜制服| 少妇久久久久久被弄高潮| 不卡av免费在线观看| 爱情岛论坛成人| 伊人情人综合网| 精品高清视频| 久久精品国产精品亚洲毛片| 久久99精品久久久久久琪琪| 日韩a在线观看| 91麻豆精品国产综合久久久久久| 国产一级片播放| 久久99国产精品久久99| 日韩精品一区二区免费| 九九久久婷婷| 91超碰在线免费观看| 欲香欲色天天天综合和网| 深夜福利91大全| 日韩专区第一页| 欧美年轻男男videosbes| 日本中文字幕免费| 中文字幕色av一区二区三区| 亚洲精品中文字幕在线播放| 精品一区二区三区免费视频| av免费观看国产| 国产精品国内免费一区二区三区| 国内欧美视频一区二区| 国产欧美日韩中文久久| 色综合网站在线| 美女av一区二区| 精品国产一区a| 大伊香蕉精品视频在线| 国产成人精品三级高清久久91| 久久av中文字幕| 欧美日韩国产综合视频| 91精品国产色综合久久不卡电影 | www.国产三级| 欧美少妇性性性| 久久国产黄色片| 一区二区三区日韩欧美| 男人天堂资源网| 91美女片黄在线观看91美女| 丰满人妻一区二区三区53视频| 视频在线在亚洲| 国产白丝袜美女久久久久| 欧美成人tv| 欧美日韩视频免费在线观看| 国产区精品区| 免费久久久一本精品久久区| 激情av综合| 国产精品大全| 欧美激情三级| 亚洲xxx视频| 成人自拍视频| 国产精品中文字幕在线| 久久久成人av毛片免费观看| 国产91精品青草社区| sm久久捆绑调教精品一区| 久久91亚洲精品中文字幕奶水| 麻豆视频网站在线观看| 最近2019中文字幕大全第二页| 毛片免费在线观看| 亚洲人成在线观看| 久久天堂电影| 中文字幕少妇一区二区三区| 六十路在线观看| 亚洲欧美国产精品久久久久久久 | 中文字幕欧美日韩一区二区| 看片一区二区| 国产精品午夜视频| 日日夜夜亚洲精品| 91精品久久久久久久久不口人| 亚洲精品伦理| 亚洲a一级视频| 久久亚洲精精品中文字幕| 7777奇米亚洲综合久久| 国产精品欧美一区二区三区不卡| 成人激情av在线| 激情视频亚洲| 国产精品视频入口| 欧洲vs亚洲vs国产| 日本一区免费| 99久久99热这里只有精品| 免费国产成人看片在线| 激情综合自拍| 激情综合在线观看| 日本欧美一区二区| 午夜一区二区视频| 风流少妇一区二区| 素人fc2av清纯18岁| 国产精品水嫩水嫩| 欧美黑人性猛交xxx| 亚洲二区视频在线| 香蕉污视频在线观看| 欧美日韩情趣电影| 午夜免费福利视频| 亚洲欧美变态国产另类| 久久99精品久久| 国产做受高潮69| 国产成人精品一区二三区在线观看 | 欧美精品一区二区精品网| 欧美日韩视频精品二区| 视频直播国产精品| 超碰中文在线| 国产精品视频午夜| 视频成人永久免费视频| 国产精品一二三视频| 久久久久久久久久久久电影| 国产偷国产偷亚洲高清97cao| 欧美男男gaytwinkfreevideos| 亚洲一区二区在线免费观看| 欧美aa国产视频| 黑鬼大战白妞高潮喷白浆| 国产精品chinese| 国产精品欧美激情在线观看| 久久国产精品第一页| 中文字幕人妻一区| 国产精品情趣视频| 国产一级做a爱片久久毛片a| 欧美美女黄视频| 手机福利小视频在线播放| 日韩一区二区精品葵司在线| 日本福利片在线| 色综合久久天天综线观看| 日本免费久久| 国产乱码精品一区二区三区卡| 欧美在线色图| 欧美污视频网站| 国产成人av电影在线| 日本成人免费视频| 天天综合天天做天天综合| 国产色综合视频| 国产小视频91| 丝袜老师在线| 国产在线精品日韩| 自拍欧美日韩| 老司机久久精品| 国产午夜精品理论片a级大结局 | 国产69精品久久app免费版| 欧美高清视频一区二区| 日韩欧美激情| 日韩电影免费观看在| 国产一区二区三区四区五区 | 女人黄色免费在线观看| 国产日韩欧美自拍| 精品国产一区二区三区噜噜噜 | 日韩vs国产vs欧美| 欧美 日本 国产| 精品久久久视频| 免费观看国产精品| 欧美激情第一页xxx| 精品国产伦一区二区三区观看说明| 青青草成人网| 久久国产日本精品| 丰满少妇在线观看资源站| 欧美日韩国产精品一区二区三区四区| 亚洲精品成av人片天堂无码 | 精品一区二区三区影院在线午夜 | 一区二区三区精品视频在线| 97精品人妻一区二区三区香蕉| 中文字幕v亚洲ⅴv天堂| gogo亚洲高清大胆美女人体| 免费中文日韩| 欧美亚洲在线| 国产成人福利在线| 欧美亚洲一区二区在线观看| yjizz视频网站在线播放| 国产精品美女999| 日韩精品一卡| 亚洲精品免费一区亚洲精品免费精品一区 | 国产精品a久久久久久| jiujiure精品视频播放| 亚洲免费av一区二区三区| 亚洲国产精品黑人久久久| 在线观看亚洲国产| 久久夜色精品国产| 日韩区欧美区| 国产中文字幕二区| 久久亚洲一区二区三区四区| 9i看片成人免费看片| 伊人久久久久久久久久| 国产成人午夜性a一级毛片| 自拍另类欧美| 国产精品综合在线视频| 久久黄色小视频| 日韩精品免费综合视频在线播放| 黑人巨大精品| 亚洲永久一区二区三区在线| 狠狠色丁香久久婷婷综| 免费在线观看国产精品| 亚洲精品久久久久久久久久久久久 | 成人看的羞羞网站| 国产成人强伦免费视频网站| 亚洲中国最大av网站| 五月婷婷丁香花| 国产精品久久久久免费a∨大胸| 日本久久综合| 久久久久99人妻一区二区三区| 精品久久久久久久久国产字幕| 精品视频三区| 亚洲综合中文字幕在线| 99国产精品| 蜜桃av免费观看| 亚洲高清色综合| 日本欧美韩国| 久久亚洲a v| 久久精品人人做人人综合 | 精品无码久久久久| 精品亚洲一区二区三区在线观看| 91在线成人| 野外做受又硬又粗又大视频√| 久久久精品欧美丰满| av高清一区二区| 国产成人91久久精品| 欧美日韩国产精品一区二区亚洲| 亚洲国产精品无码久久久久高潮| 欧美日韩亚洲综合在线 欧美亚洲特黄一级|