著者 | フロリアン・ジューン 編纂者:岳陽 RAGシステムの実装は非常に困難な作業であり、特に非構造化文書内の表の解析と理解が必要な場合は困難です。スキャンされた文書や画像形式の文書の場合はさらに困難です。少なくとも3つの主要な課題があります。
本稿ではまず、検索拡張生成(RAG)モデルにおける表形式データの管理と処理方法を紹介します。次に、既存のオープンソースソリューションをいくつかレビューし、最後に、最新の技術に基づいて表形式データを管理するための新しい手法を設計・実装します。 01 RAGテーブルデータに関連するコア技術の紹介1.1 テーブル解析このモジュールの主な機能は、非構造化ドキュメントまたは画像から表構造を正確に抽出することです。 追加要件:理想的には、開発者がテーブル タイトルをテーブルに簡単に関連付けることができるように、対応するテーブル タイトルを抽出する必要があります。 私の現在の理解に基づくと、図 1 に示すように、いくつかの方法があります。 図1: テーブルパーサー。画像は原著者より提供。 (a)マルチモーダルLLM(GPT-4V[1]など)を使用して表を識別し、各PDFページから情報を抽出します。
(b)専門的な表検出モデル(Table Transformer[2]など)を使用して表の構造を識別する。
(c)オープンソースフレームワーク(非構造化[3]や、オブジェクト検出モデルを採用した他のフレームワークなど)を使用する(非構造化における表検出プロセスについては、この記事[4]で詳しく説明されている)。これらのフレームワークは、文書全体を完全に解析し、解析結果から表に関連するコンテンツを抽出することができる。
(d) Nougat[5]やDonut[6]などのエンドツーエンドモデルを用いて文書全体を解析し、表に関連するコンテンツを抽出します。この手法ではOCRモデルは必要ありません。
表情報の抽出方法に関わらず、表のタイトルも抽出する必要があることに注意が必要です。これは、ほとんどの場合、表のタイトルは文書または論文の著者による表の簡潔な説明であり、表全体の内容を概ね要約できるためです。 上記の4つの方法のうち、方法(d)はテーブルヘッダーを取得する最も便利な方法です。これは、テーブルヘッダーをテーブル自体に関連付けることができるため、開発者にとって非常に便利です。次の実験で、この点をさらに詳しく説明します。 1.2 インデックス構造: 表形式データのインデックス作成方法インデックスの作成方法には、おおよそ以下の種類があります。 (e)画像形式の表のみのインデックス。 (f)プレーンテキストまたは JSON 形式のテーブルのみをインデックスします。 (g) LaTeX形式の表のみの索引。 (h)表の概要のみを索引付けします。 (i).小規模から大規模へ(翻訳者注:これには、各行や表の要約をインデックスするなどの細粒度のインデックスと、画像、プレーンテキスト、LaTeXデータの表全体をインデックスするなどの粗粒度のインデックスの両方が含まれ、階層的な小規模から大規模までのインデックス構造を形成します。)または、図2に示すように、表の要約を使用してインデックス構造を構築します。 小さなチャンク(翻訳者注:細粒度インデックス レベルに対応するデータ ブロック)の内容は、たとえば、テーブルまたはサマリー情報の各行を独立した小さなデータ ブロックとして扱います。 大きなチャンク (翻訳者注: 粗粒度のインデックス レベルに対応するデータ ブロック) の内容は、画像形式、プレーン テキスト形式、または LaTeX 形式のテーブル全体である場合があります。 図2:小規模から大規模へのアプローチを用いた索引作成(上)と表要約を用いた索引作成(中と下)。画像は原著者提供。 前述のように、テーブル サマリーは通常、LLM 処理を使用して生成されます。
1.3 テーブルの解析、インデックスの作成、RAGテクノロジの使用を必要としない方法一部のアルゴリズムでは、表形式のデータの解析は必要ありません。 (j)関連する画像(PDF文書ページ)とユーザーのクエリをVQAモデル(DAN[7]など)またはマルチモーダルLLMに送信し、回答を返します。
(k)関連するテキスト形式の PDF ページとユーザーのクエリを LLM に送信し、回答を返します。
(l).関連する文書画像(PDF文書ページ)、テキストブロック、ユーザークエリをマルチモーダルLLM(GPT-4Vなど)に送信し、直接回答を返します。
さらに、図 3 と 4 に示すように、インデックス作成を必要としない方法もいくつかあります。 図3:カテゴリー(m)(訳者注:以下の第1段落で紹介されている内容を指す)。画像は原著者提供。 (m)まず、(a)から(d)のいずれかの手法を用いて、文書内のすべての表を画像形式に変換します。次に、すべての表画像とユーザーのクエリをマルチモーダルLLM(GPT-4Vなど)に直接送信し、回答を返します。
図4:カテゴリー(n)(訳者注:以下の最初の段落で紹介されている内容)。画像は原著者提供。 (n) (m)の方法で抽出した画像形式の表を使用し、OCRモデルを使用して表内のすべてのテキストを認識し、表内のすべてのテキストとユーザーのクエリを直接LLMに送信して回答を直接返します。
いくつかの方法では、ドキュメント内の表を処理するときに RAG (Retrieval-Augmented Generation) テクノロジを使用しないことに注意してください。
02 テーブル処理のための既存のオープンソースソリューション前のセクションでは、RAGシステムにおける表形式データ処理の主要なテクノロジーをまとめ、分類しました。この記事で実装するソリューションを提案する前に、オープンソースソリューションをいくつか見ていきましょう。 LlamaIndexは4つの方法[10]を提案しており、最初の3つはすべてマルチモーダルモデルを使用していました。
上記の 4 つの方法を要約すると次のようになります。
テストの結果、3番目の方法が全体的に最も優れたパフォーマンスを発揮することがわかりました。しかし、私のテストでは、3番目の方法は表の検査に苦労し、表のタイトルと内容を正しく抽出して結合することはなおさら困難でした。 Langchainは、半構造化データのための半構造化RAG[11]技術のソリューションもいくつか提案しており、その中核技術には以下が含まれます。
図5に示すように: 図5:Langchainの半構造化RAGスキーム。出典:半構造化RAG[11] 半構造化およびマルチモーダルRAG[12]は3つのソリューションを提案しており、そのアーキテクチャを図6に示す。 図6: Langchainの半構造化・マルチモーダルRAGスキーム。出典: 半構造化・マルチモーダルRAG[12]。 オプション1は、上記の方法(l)に似ています。この方法では、マルチモーダル埋め込み(CLIP[13]など)を用いて画像とテキストを埋め込みベクトルに変換し、類似性検索アルゴリズムを用いて両者を取得し、未処理の画像とテキストデータをマルチモーダルLLMに渡して一緒に処理し、質問への回答を生成します。 オプション2は、マルチモーダルLLM(GPT-4V[14]、LLaVA[15]、FUYU-8b[16]など)を用いて画像を処理することでテキスト要約を生成します。テキストデータは埋め込みベクトルに変換され、ユーザーのクエリに一致するテキストコンテンツを検索または取得するために使用され、これらのテキストコンテンツはLLMに渡されて回答を生成します。
オプション3は、マルチモーダルLLM(GPT-4V[14]、LLaVA[15]、FUYU-8b[16]など)を用いて画像データからテキスト要約を生成し、これらのテキスト要約をベクトルに埋め込みます。これらの埋め込みベクトルを用いることで、画像要約を効率的に取得することができます。取得された各画像要約には、生画像への参照が保持されます。これは上記のクラス(i)の手法に属します。最後に、未処理の画像データとテキストブロックをマルチモーダルLLMに渡して、回答を生成します。 03 この論文で提案された解決策これまでの文章では、主要な技術と既存のソリューションを要約、分類、議論してきました。これに基づき、図7に示すようなソリューションを提案します。図では、簡略化のため、再ランキングやクエリ書き換えなどの一部のRAGモジュールを省略しています。 図7:本論文で提案された解決策。画像は原著者提供。
この手法の利点は、表を効率的に解析し、表の要約と表の関係を包括的に考慮できることです。マルチモーダルLLMが不要になるため、コストを削減できます。 3.1 ヌガーの仕組みNougat[18]はDonut[19]アーキテクチャに基づいて開発されています。この手法で使用されるアルゴリズムは、OCR関連の入力やモジュールを必要とせずに、暗黙的にテキストを自動認識できます。 図8:Donut[19]に倣ったエンドツーエンドのアーキテクチャ。Swin Transformerエンコーダは文書画像を受け取り、それを潜在的埋め込みに変換し、さらに自己回帰的に一連のトークンに変換します。出典:Nougat: Neural Optical Understanding for Academic Documents[18] Nougatは数式解析能力に優れていますが[20]、表の解析にも優れています。図9に示すように、表のヘッダーを関連付けることができ、非常に便利です。 図9: Nougatの実行結果。結果ファイルはMathpix Markdown形式(VS Codeプラグインで開くことができます)で、表はLaTeX形式で表示されます。 12以上の論文で行ったテストでは、表のヘッダーが常に表の下の次の行に固定されていることがわかりました。この一貫性は、偶然ではないことを示唆しています。そのため、Nougatがこの機能をどのように実現しているのか、非常に興味があります。 これは中間結果のないエンドツーエンドのモデルであるため、そのパフォーマンスはトレーニング データに大きく依存する可能性があります。 コード分析に基づくと、テーブルヘッダーセクションの保存場所と方法は、トレーニングデータ内のテーブル構成形式と一致しているようです( デフフォーマット要素(
要素: 要素、keep_refs: bool = False、latex_env: bool = False
) -> リスト[str]:
「」
指定された要素をフォーマットされた文字列のリストにフォーマットします。
引数:
要素 (Element): フォーマットする要素。
keep_refs (bool, オプション): 書式設定で参照を保持するかどうか。デフォルトはFalseです。
latex_env (bool, オプション): LaTeX環境フォーマットを使用するかどうか。デフォルトはFalseです。
戻り値:
List[str]: フォーマットされた要素を表すフォーマットされた文字列のリスト。
「」
...
...isinstance(要素、テーブル)の場合:
parts = [ "[TABLE%s]\n\begin{table}\n"
% (str(uuid4())[:5]、element.idがNoneの場合、そうでない場合は ":" + str(element.id))
]
parts.extend(format_children(要素、keep_refs、latex_env))
caption_parts = format_element(element.caption, keep_refs, latex_env)
末尾の空白を削除(キャプション部分)
len(caption_parts) > 0 の場合、parts.append("\end{table}\n") を追加します。
parts.extend(caption_parts + ["\n"])
parts.append("[ENDTABLE]\n\n") 部品を返す
...
... 3.2 ヌガーの長所と短所アドバンテージ:
欠点:
3.3 コードの実装まず、関連する Python パッケージをインストールします。 pip で langchain をインストールし、pip で chromadbp をインストールし、pip で 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 作業環境を設定し、ソフトウェア パッケージをインポートします。 インポートOS os.environ["OPENAI_API_KEY"] = "YOUR_OPEN_AI_KEY" サブプロセスをインポートしてUUIDをインポートする langchain_core.output_parsers から StrOutputParser をインポートします langchain_core.promptsからChatPromptTemplateをインポートします langchain_openaiからChatOpenAIをインポート langchain.retrievers.multi_vector から MultiVectorRetriever をインポートします langchain.storageからInMemoryStoreをインポートする langchain_community.vectorstores から Chroma をインポート langchain_core.documentsからDocumentをインポートする langchain_openaiからOpenAIEmbeddingsをインポート langchain_core.runnables から RunnablePassthrough をインポートします 論文「Attention Is All You Need」[21]を june_run_nougat を定義します(ファイルパス、出力ディレクトリ):
# Nougat を実行し、結果を Mathpix Markdown として保存します。cmd = ["nougat", file_path, "-o", output_dir, "-m", "0.1.0-base", "--no-skipping"]
res = サブプロセス.run(cmd)
res.returncode != 0 の場合:
print("Nougat 実行中にエラーが発生しました。") return res.returncode else:
print("操作が完了しました!") return 0def june_get_tables_from_mmd(mmd_path): f = open(mmd_path)
行 = f.readlines()
解像度 = []
一時 = []
フラグ = ""
行内の行の場合: 行 == "\begin{table}\n" の場合:
フラグ = "開始可能"
elif 行 == "\end{table}\n":
フラグ = "ENDTABLE"
フラグ == "BEGINTABLE" の場合:
tmp.append(line) elif flag == "ENDTABLE":
tmp.append(行)
フラグ = "キャプション"
elifフラグ == "CAPTION":
tmp.append(行)
フラグ = "MARKDOWN"
印刷('-' * 100)
print(''.join(tmp))
res.append(''.join(tmp))
tmp = [] resを返す
file_path = "YOUR_PDF_PATH" output_dir = "YOUR_OUTPUT_DIR_PATH" june_run_nougat(file_path, output_dir) == 1の場合: sysをインポート
sys.exit(1)
mmd_path = output_dir + '/' + os.path.splitext(file_path)[0].split('/')[-1] + ".mmd" テーブル = june_get_tables_from_mmd(mmd_path) 関数 june_get_tables_from_mmd は、図 10 に示すように、mmd ファイルからすべてのコンテンツ ( 図10: Nougatの実行結果。結果ファイルはMathpix Markdown形式(VS Codeプラグインで開くことができます)で、解析された表の内容はLaTeX形式です。関数「june_get_tables_from_mmd」は、赤い枠で囲まれた表の情報を抽出します。画像は原著者提供。 しかし、表のヘッダーを表の下に配置する必要があることや、表は\begin{table}で始まり\end{table}で終わる必要があることを規定した公式ドキュメントは現時点では存在しません。そのため、june_get_tables_from_mmdはヒューリスティックなアプローチです。 以下は PDF ドキュメントからの表解析結果です。 操作が完了しました!--------------------------------------------------------------------------------------------------\begin{table}\begin{tabular}{l c c c} \hline \hline レイヤータイプ、レイヤーあたりの複雑さ、順次操作、最大パス長 \ \hline 自己注意 & (O(n^{2}\cdot d)) & (O(1)) & (O(n\cdot) \ 再帰 & (O(1)) d^{2})) & (O(n)) & (O(n)) \ 畳み込み & (O(k\cdot n\cdot d^{2})) & (O(1)) & (O(log_{k}(n))) \ 自己注意 (制限付き) & (O(r\cdot n\cdot d)) & (O(1)) & (O(n/r)) \ \hline \hline \end{tabular}\end{table}表 1: さまざまなレイヤー タイプの最大パス長、レイヤーごとの複雑さ、および最小の連続操作数。 (n) はシーケンス長、(d) は表現次元、(k) は畳み込みのカーネルサイズ、(r) は制限付き自己注意における近傍のサイズです。------------------------------------------------------------------------------------------------\begin{table}\begin{tabular}{l c c c c} \hline \hline \multirow{2}{*}{モデル} & \multicolumn{2}{c}{BLEU} & \multicolumn{2}{c}{トレーニングコスト (FLOP)} \ \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 アンサンブル [39] & & 40.4 & & (8.0\cdot 10^{20}) \ GNMT + RL アンサンブル [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 (基本モデル) & 27.3 & 38.1 & & (\mathbf{3.3\cdot 10^{18}}) \ Transformer (大規模) & **28.4** & **41.8** & & (2.3\cdot 10^{19}) \ \hline \hline \end{tabular}\end{table}表2: Transformerは、英語からドイツ語およびフランス語の翻訳において、従来の最先端モデルよりも優れたBLEUスコアを達成しています。英語からフランス語への newstest2014 テストをわずかなトレーニング コストで実行できます。----------------------------------------------------------------------------------------------\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}}) & (d_{\text{ff}}) & (h) & (d_{k}) & (d_{k}) & (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 & \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}表3:Transformerアーキテクチャのバリエーション。記載されていない値は基本モデルの値と同じです。すべてのメトリックは、英語からドイツ語への翻訳開発セットnewstest2013に基づいています。記載されているパープレキシティは、バイトペアエンコーディングに従った単語単位のものであり、単語単位のパープレキシティと比較すべきではありません。---------------------------------------------------------------------------------------------\begin{table}\begin{tabular}{c|c|c} \hline**Parser** & **Training** & **WSJ 23 F1** \ \hline Vinyals & Kaiser et al. (2014) [37] & WSJ only, discriminative & Petrov et al. (2006) discriminative & 90.4 \ Zhu et al. (2013) [40] & WSJ only, discriminative & 90.4 \ Dyer et al. (2016) [8] & WSJのみ、識別 & 91.7 \ \hline Transformer(4層) & WSJのみ、識別 & 91.3 \ \hline Zhu et al. (2013) [40] & 半教師あり & 91.3 \ Huang & Harper (2009) [14] & 半教師あり & 91.3 \ McClosky et (2006) [26] & 半教師あり & 92.1 \ Vinyals & Kaiser el al. (2014) [37] & 半教師あり & 92.1 \ \hline Transformer(4層) & 半教師あり & 92.7 \ \hline Luong et al. (2015) [23] & マルチタスク & 93.0 \ Dyer et al. (2016) [8] & 生成 & 93.3 \ \hline \end{tabular}\end{table}表4: Transformerは英語の構成構文解析によく一般化します(結果はWSJのセクション23にあります)* [5] Kyunghyun Cho、Bart van Merrienboer、Caglar Gulcehre、Fethi Bougares、Holger Schwenk、およびYoshua Bengio。統計的機械翻訳のためのrnnエンコーダー-デコーダーを使用したフレーズ表現の学習。_CoRR_、abs/1406.1078、2014。 次に、LLM を使用して表形式のデータを要約します。 # Promptprompt_text = """あなたは、表とテキストを要約する役割を担うアシスタントです。\
表またはテキストの簡潔な要約を記述してください。表はLaTeXでフォーマットされており、キャプションはプレーンテキスト形式です。{element} """prompt = ChatPromptTemplate.from_template(prompt_text)# Summary chainmodel = ChatOpenAI(temperature = 0, model = "gpt-3.5-turbo")
summarize_chain = {"element": lambda x: x} | prompt | model | StrOutputParser()# テーブルサマリーを取得table_summaries = summarize_chain.batch(tables, {"max_concurrency": 5})
print(table_summaries) 以下は図11に示すように、『Attention Is All You Need』[21]の4つの表の内容を要約したものです。 図11:「Attention Is All You Need」[21]の4つの表の内容の要約。 文書要約索引構造[17]は、マルチベクトルリトリーバー(文書の要約情報を格納し、必要に応じてこの要約情報を検索または照会できる索引構造の一種)を使用して構築される。 # 子チャンクのインデックスに使用するベクトルストアvectorstore = Chroma(collection_name = "summaries", embedding_function = OpenAIEmbeddings())# 親ドキュメントのストレージレイヤーstore = InMemoryStore()
id_key = "doc_id"# リトリーバー(最初は空)retriever = MultiVectorRetriever(
ベクターストア = ベクターストア、
ドキュメントストア = ストア、
id_key = id_key、
search_kwargs={"k": 1} # 要求された結果の数 4 がインデックス内の要素数より大きいため、n_results = 1 を更新します)# テーブルを追加しますtable_ids = [str(uuid.uuid4()) for _ in tables]
summary_tables = [
ドキュメント(ページコンテンツ = s、メタデータ = {id_key: table_ids[i]})
enumerate(table_summaries) の i, s について
]
retriever.vectorstore.add_documents(summary_tables)
retriever.docstore.mset(リスト(zip(テーブルID、テーブル))) すべての準備が整ったら、シンプルな RAG パイプラインを設定し、ユーザーのクエリを実行します。 # プロンプトテンプレートテンプレート = """次のコンテキストのみに基づいて質問に答えます。これにはテキストと表を含めることができ、LaTeX 形式の表とプレーンテキスト形式の表のキャプションがあります。
{コンテクスト}
質問: {質問}
"""prompt = ChatPromptTemplate.from_template(template)# LLMmodel = ChatOpenAI(temperature = 0, model = "gpt-3.5-turbo")# シンプルなRAGパイプラインchain = (
{"context": リトリーバー、「question": RunnablePassthrough()}
| プロンプト
| モデル
| StrOutputParser()
)
print(chain.invoke("レイヤータイプがSelf-Attentionの場合、レイヤーあたりの複雑度はどれくらいですか?")) # テーブル1に関するクエリprint(chain.invoke("BLEU EN-DEの場合、どのパーサーのパフォーマンスが最悪ですか?")) # テーブル2に関するクエリprint(chain.invoke("WSJ 23 F1の場合、どのパーサーのパフォーマンスが最良ですか?")) # テーブル4に関するクエリ結果は次のとおりです。図 12 に示すように、すべての質問に正確に回答しました。 図12: 3つのユーザークエリに対する回答結果。最初の行は「Attention Is All You Need」の表1、2行目は表2、3行目は表4に対応しています。 全体的なコードは次のとおりです。 インポートOS
os.environ["OPENAI_API_KEY"] = "YOUR_OPEN_AI_KEY" import subprocessimport uuidfrom langchain_core.output_parsers import StrOutputParserfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_openai import ChatOpenAIfrom langchain.retrievers.multi_vector import MultiVectorRetrieverfrom langchain.storage import InMemoryStorefrom langchain_community.vectorstores import Chromafrom langchain_core.documents import Documentfrom langchain_openai import OpenAIEmbeddingsfrom langchain_core.runnables import RunnablePassthroughdef 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 0def 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)# Promptprompt_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 chainmodel = ChatOpenAI(temperature = 0, model = "gpt-3.5-turbo")
summarize_chain = {"element": lambda x: x} | prompt | model | StrOutputParser()# Get table summariestable_summaries = summarize_chain.batch(tables, {"max_concurrency": 5})
print(table_summaries)# The vectorstore to use to index the child chunksvectorstore = Chroma(collection_name = "summaries", embedding_function = OpenAIEmbeddings())# The storage layer for the parent documentsstore = 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 tablestable_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 templatetemplate = """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)# LLMmodel = ChatOpenAI(temperature = 0, model = "gpt-3.5-turbo")# Simple RAG pipelinechain = (
{"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 1print(chain.invoke("Which parser performs worst for BLEU EN-DE")) # Query about table 2print(chain.invoke("Which parser performs best for WSJ 23 F1")) # Query about table 4 04 結論本文讨论了在 RAG 系统中表格处理操作的关键技术和现有解决方案,并提出了一种解决方案及其实现方法。 在本文中,我们使用了 Nougat 来解析表格。不过,如果有更快、更有效的解析工具可用,我们会考虑替换掉 Nougat 。我们对工具的态度是先有正确的 idea ,然后再找工具来实现它,而不是依赖于某个工具。 在本文中,我们将所有表格内容输入到 LLM 。但是,在实际场景中,我们需要考虑到表格大小超出 LLM 上下文长度的情况。我们可以通过使用有效的分块(chunking)方法来解决这个问题。 読んでくれてありがとう! —— フロリアン・ジューン An artificial intelligence researcher, mainly write articles about Large Language Models, data structures and algorithms, and NLP. 終わり 参考文献[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 |