HtmlRAG: HTML is Better Than Plain Text for Modeling Retrieved Knowledge in RAG Systemsの紹介

HtmlRAG: HTML is Better Than Plain Text for Modeling Retrieved Knowledge in RAG Systemsの紹介をします。

HtmlRAGの解説と実装例

1. 論文の概要

背景

Retrieval-Augmented Generation (RAG)は、外部の知識を利用して質問応答や文章生成の精度を向上させる方法論です。しかし、RAGシステムではHTML文書をプレーンテキストに変換して使用することが一般的で、HTML特有の構造や意味的情報(例: 見出し、表、リンク)が失われるという課題があります。

HtmlRAGの提案

HtmlRAGは、HTMLをそのままRAGシステムで利用する新しいアプローチを提案します。この方法では以下を実現します:

  1. HTMLクリーニング: 不要な情報(CSSやJavaScript)を削除し、必要な情報を簡潔化。
  2. HTMLプルーニング: クエリに関連の低いHTMLブロックを削除し、関連性の高い情報のみを保持。
  3. 生成性能の向上: HTMLの構造情報を保持することで、質問応答や文章生成の精度を向上。

2. 具体的な実装例

以下は、「映画レビューサイトを利用した質問応答システム」を例に、HtmlRAGの実装を説明します。

(1) HTMLクリーニング

HTML文書から不要な要素を削除して軽量化します。

from bs4 import BeautifulSoup

def clean_html(html_content):
    soup = BeautifulSoup(html_content, 'html.parser')
    for script_or_style in soup(["script", "style", "meta", "link"]):
        script_or_style.decompose()
    for tag in soup.find_all():
        if not tag.text.strip():
            tag.decompose()
        else:
            tag.attrs = {}
    return str(soup)

評価:


(2) ブロックツリーの構築

HTMLを「意味のあるブロック」に分割します。

def build_block_tree(html_content, max_words=50):
    soup = BeautifulSoup(html_content, 'html.parser')
    blocks = []

    def traverse(tag):
        text = tag.get_text(separator=" ", strip=True)
        if len(text.split()) > max_words:
            for child in tag.children:
                if child.name:
                    traverse(child)
        else:
            blocks.append((tag.name, text.strip()))

    traverse(soup.body)
    return blocks

評価:


(3) HTMLプルーニング

質問に関連するブロックのみを残します。

from sentence_transformers import SentenceTransformer, util

model = SentenceTransformer('all-MiniLM-L6-v2')

def prune_blocks(blocks, query, max_length=300):
    query_embedding = model.encode(query, convert_to_tensor=True)
    pruned_blocks = []

    for tag, text in blocks:
        block_embedding = model.encode(text, convert_to_tensor=True)
        score = util.pytorch_cos_sim(query_embedding, block_embedding).item()
        if score > 0.5:
            pruned_blocks.append((tag, text))

    total_length = 0
    result = []
    for tag, text in pruned_blocks:
        if total_length + len(text) <= max_length:
            result.append((tag, text))
            total_length += len(text)
        else:
            break
    return result

評価:


(4) 生成モデルによる回答

LLMを使用して回答を生成します。

from transformers import pipeline

def generate_answer(pruned_blocks, query):
    context = " ".join([text for _, text in pruned_blocks])
    llm = pipeline("text2text-generation", model="t5-small")
    prompt = f"質問: {query}\n\n文脈: {context}\n\n答え:"
    return llm(prompt, max_length=50)[0]['generated_text']

評価:


3. 論文手法の評価

(1) 論文内実験の要約

(2) 独自実装の評価


4. 独自の考察とまとめ

考察

  1. HTMLの潜在能力:
    HTMLにはプレーンテキストよりも多くの構造情報が含まれており、それを活用するHtmlRAGは理にかなっています。
  2. 実装の柔軟性:
    本手法は、多様なデータソース(例: PDFやWeb記事)に適用可能。HTML形式への変換を前提に汎用性が高い。
  3. 計算コスト:
    HTMLを保持する利点がある一方で、クリーニングやプルーニングの計算コストを抑える工夫が必要です。

まとめ

HtmlRAGは、RAGシステムにおける革新的な提案であり、特にWebベースの情報検索に強みを持つ手法です。実装例を通じて、その実用性と効率性が確認できました。今後、クリーニングやプルーニングのアルゴリズムを改良し、計算効率を向上させる研究がさらに進むことが期待されます。


関連ページ