1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Google Colab上で動かす!Hugging Face埋め込み × Azure OpenAIで高精度PDF要約 (PyMuPDF対応)

Posted at

user:

前回、次のようなPython関数を作っていただきました。

!pip install pymupdf openai requests

import fitz  # PyMuPDF
from openai import AzureOpenAI
import requests, json, os
from google.colab import drive

def summarize_pdf_with_pymupdf(pdf_url, config_path="/content/drive/MyDrive/AOAI/config.json"):
    drive.mount('/content/drive')  # Google Driveマウント

    with open(config_path, "r") as f:
        config = json.load(f)

    client = AzureOpenAI(
        api_key=config["OPENAI_API_KEY"],
        api_version=config["OPENAI_API_VERSION"],
        azure_endpoint=config["OPENAI_API_BASE"]
    )
    model = config["OPENAI_API_ENGINE"]

    # PDF取得
    response = requests.get(pdf_url)
    with open("temp.pdf", "wb") as f:
        f.write(response.content)

    doc = fitz.open("temp.pdf")
    page_summaries = []

    for i, page in enumerate(doc):
        text = page.get_text("text").strip()
        if not text or len(text) < 30:
            continue

        prompt = f"""
以下はPDFの第{i+1}ページの内容です。日本語でわかりやすく要約してください:

\"\"\"
{text[:3000]}
\"\"\"
"""

        print(f"{i+1}ページを要約中...")
        res = client.chat.completions.create(
            model=model,
            messages=[
                {"role": "system", "content": "あなたは優秀な日本語の要約アシスタントです。"},
                {"role": "user", "content": prompt}
            ],
            temperature=0.4,
            max_tokens=700
        )

        summary = res.choices[0].message.content.strip()
        page_summaries.append(f"{i+1}ページの要約:\n{summary}")

    # ページごとの要約を統合して、全体の要約を生成
    combined = "\n\n".join(page_summaries)

    final_prompt = f"""
以下は各ページの要約です。これらを元に、PDF全体の内容を日本語で簡潔にまとめてください:

\"\"\"
{combined[:12000]}
\"\"\"
"""

    print("全体要約を生成中...")
    final_res = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": "あなたは優秀な日本語の要約アシスタントです。"},
            {"role": "user", "content": final_prompt}
        ],
        temperature=0.3,
        max_tokens=1000
    )

    final_summary = final_res.choices[0].message.content.strip()
    print("\n✅ PDF全体の要約:\n")
    print(final_summary)

これはRAGを使ってないと思いますが、RAGを使ったバージョンに書き換えていただくことはできますか?
実行環境はGoogle Colaboratoryを想定します。
AOAI(Azure OpenAI)の エンドポイントとAPIキーは、Google Drive 中の AOAI/config.json に次のような形で記載されているものとします。

{
    "OPENAI_API_TYPE": …,
    "OPENAI_API_VERSION": …,
    "OPENAI_API_BASE": …,
    "OPENAI_API_KEY": …,
    "OPENAI_API_ENGINE": …
}

assistant:

ありがとうございます。ご指摘のとおり、以前のスクリプトは Retrieval-Augmented Generation(RAG)を使っていませんでした。ただの逐次要約+全体要約の形式でした。

RAG(Retrieval-Augmented Generation)を導入するには、次の要素を追加する必要があります:

  • PDFから全ページのテキストを抽出
  • テキストをチャンク(分割)して、ベクトル化
  • ベクトルをFAISSなどのベクトルストアに格納
  • クエリに対して類似チャンクを検索(=「検索ベースの補助」)
  • OpenAIのChat Completionに、検索結果をプロンプトに加えて回答を生成

以下は、Google Colab + AOAI 環境でRAGを使ったPDF要約バージョンです。


✅ RAGを使ったPDF要約スクリプト(Google Colab用)

!pip install pymupdf openai faiss-cpu tiktoken langchain

import fitz  # PyMuPDF
import requests, json, os
from google.colab import drive
from openai import AzureOpenAI
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.docstore.document import Document

def rag_summarize_pdf(pdf_url, config_path="/content/drive/MyDrive/AOAI/config.json"):
    # Google Driveをマウントして設定ファイルを読み込む
    drive.mount('/content/drive')
    with open(config_path, "r") as f:
        config = json.load(f)

    # Azure OpenAIクライアント
    client = AzureOpenAI(
        api_key=config["OPENAI_API_KEY"],
        api_version=config["OPENAI_API_VERSION"],
        azure_endpoint=config["OPENAI_API_BASE"]
    )
    model = config["OPENAI_API_ENGINE"]

    # PDFのダウンロードとテキスト抽出
    response = requests.get(pdf_url)
    with open("temp.pdf", "wb") as f:
        f.write(response.content)

    doc = fitz.open("temp.pdf")
    all_text = ""
    for page in doc:
        text = page.get_text("text")
        if text:
            all_text += text + "\n"

    # テキストをチャンクに分割
    splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    texts = splitter.split_text(all_text)
    documents = [Document(page_content=t) for t in texts]

    # ベクトルストア作成(OpenAI Embeddings + FAISS)
    embeddings = OpenAIEmbeddings(
        deployment=config["OPENAI_API_ENGINE"],
        openai_api_key=config["OPENAI_API_KEY"],
        openai_api_base=config["OPENAI_API_BASE"],
        openai_api_version=config["OPENAI_API_VERSION"],
        openai_api_type=config["OPENAI_API_TYPE"]
    )

    vectorstore = FAISS.from_documents(documents, embedding=embeddings)

    # クエリを設定し、類似チャンクを検索
    query = "このPDF全体の内容を日本語で要約してください。"
    docs = vectorstore.similarity_search(query, k=5)
    context = "\n\n".join([doc.page_content for doc in docs])

    # プロンプトを作成して要約生成
    prompt = f"""
以下はPDFから抽出された関連情報です。内容を踏まえ、日本語でわかりやすく要約してください:

\"\"\"
{context}
\"\"\"
"""

    print("🔍 検索したコンテキストに基づき要約を生成中...")
    res = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": "あなたは優秀な日本語の要約アシスタントです。"},
            {"role": "user", "content": prompt}
        ],
        temperature=0.4,
        max_tokens=800
    )

    summary = res.choices[0].message.content.strip()
    print("\n✅ RAGによる要約:\n")
    print(summary)

🔧 このスクリプトのポイント

  • チャンク分割RecursiveCharacterTextSplitter を使用し、文脈が途切れにくい形で分割。
  • 埋め込みモデル:Azure OpenAI の OpenAIEmbeddings を使って埋め込み生成(deployment 指定に注意)。
  • ベクトル検索FAISS によって類似コンテキストを取得。
  • RAG形式のプロンプト:検索結果から得た文脈を元に要約を生成。

✅ 実行前に必要なもの

  • config.json(Azure OpenAI 設定)を次のようにGoogle Driveに格納しておく必要があります:
{
  "OPENAI_API_TYPE": "azure",
  "OPENAI_API_VERSION": "2023-05-15",
  "OPENAI_API_BASE": "https://<your-resource-name>.openai.azure.com/",
  "OPENAI_API_KEY": "<your-key>",
  "OPENAI_API_ENGINE": "<your-deployment-name>"
}

必要に応じて、要約だけでなくQAに応用する形にも拡張できます。
「クエリを変えれば任意の質問に対応可能」というのがRAGの大きな強みです。


ご希望があれば:

  • 全文要約+章別要約の併用
  • 複数PDFをまとめて処理
  • LangChainのRetrievalQAによるQA対応

なども拡張可能です。ご希望があればお知らせください。

user:

ありがとうございます。次のエラーが生じました。

---------------------------------------------------------------------------
NotFoundError                             Traceback (most recent call last)
/tmp/ipython-input-59-254423325.py in <cell line: 0>()
----> 1 rag_summarize_pdf("https://arxiv.org/pdf/2507.07935v2", config_path="/content/drive/MyDrive/path_config/config.json")

8 frames
/tmp/ipython-input-58-3000613427.py in rag_summarize_pdf(pdf_url, config_path)
     50     )
     51 
---> 52     vectorstore = FAISS.from_documents(documents, embedding=embeddings)
     53 
     54     # クエリを設定し、類似チャンクを検索

/usr/local/lib/python3.11/dist-packages/langchain_core/vectorstores/base.py in from_documents(cls, documents, embedding, **kwargs)
    846                 kwargs["ids"] = ids
    847 
--> 848         return cls.from_texts(texts, embedding, metadatas=metadatas, **kwargs)
    849 
    850     @classmethod

/usr/local/lib/python3.11/dist-packages/langchain_community/vectorstores/faiss.py in from_texts(cls, texts, embedding, metadatas, ids, **kwargs)
   1041                 faiss = FAISS.from_texts(texts, embeddings)
   1042         """
-> 1043         embeddings = embedding.embed_documents(texts)
   1044         return cls.__from(
   1045             texts,

/usr/local/lib/python3.11/dist-packages/langchain_community/embeddings/openai.py in embed_documents(self, texts, chunk_size)
    669         #       than the maximum context and use length-safe embedding function.
    670         engine = cast(str, self.deployment)
--> 671         return self._get_len_safe_embeddings(
    672             texts, engine=engine, chunk_size=chunk_size
    673         )

/usr/local/lib/python3.11/dist-packages/langchain_community/embeddings/openai.py in _get_len_safe_embeddings(self, texts, engine, chunk_size)
    495         batched_embeddings: List[List[float]] = []
    496         for i in _iter:
--> 497             response = embed_with_retry(
    498                 self,
    499                 input=tokens[i : i + _chunk_size],

/usr/local/lib/python3.11/dist-packages/langchain_community/embeddings/openai.py in embed_with_retry(embeddings, **kwargs)
    118     """Use tenacity to retry the embedding call."""
    119     if is_openai_v1():
--> 120         return embeddings.client.create(**kwargs)
    121     retry_decorator = _create_retry_decorator(embeddings)
    122 

/usr/local/lib/python3.11/dist-packages/openai/resources/embeddings.py in create(self, input, model, dimensions, encoding_format, user, extra_headers, extra_query, extra_body, timeout)
    130             return obj
    131 
--> 132         return self._post(
    133             "/embeddings",
    134             body=maybe_transform(params, embedding_create_params.EmbeddingCreateParams),

/usr/local/lib/python3.11/dist-packages/openai/_base_client.py in post(self, path, cast_to, body, options, files, stream, stream_cls)
   1254             method="post", url=path, json_data=body, files=to_httpx_files(files), **options
   1255         )
-> 1256         return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
   1257 
   1258     def patch(

/usr/local/lib/python3.11/dist-packages/openai/_base_client.py in request(self, cast_to, options, stream, stream_cls)
   1042 
   1043                 log.debug("Re-raising status error")
-> 1044                 raise self._make_status_error_from_response(err.response) from None
   1045 
   1046             break

NotFoundError: Error code: 404 - {'error': {'code': '404', 'message': 'Resource not found'}}

assistant:

ありがとうございます。
このエラー:

NotFoundError: Error code: 404 - {'error': {'code': '404', 'message': 'Resource not found'}}

は、Azure OpenAI の Embedding モデルが存在しない or 正しく指定されていないことが原因です。


✅ 原因と対処方法

🔍 原因

LangChain の OpenAIEmbeddingsembedding モデル専用のデプロイメント を使う必要があります。

エラーメッセージを見ると、次の行で失敗しています:

embeddings = OpenAIEmbeddings(
    deployment=config["OPENAI_API_ENGINE"],  # ← これは "text-davinci-003" など、chat用かも?

おそらくこの config["OPENAI_API_ENGINE"]chatモデル(GPT-4など)用のエンジン名であり、embeddingモデル(例:text-embedding-ada-002)用ではないため、404エラーになっています。


✅ 解決策:config.jsonを2つのエンジンに対応させる

あなたの config.json に以下のように Embedding用のエンジン名も追加してください:

{
  "OPENAI_API_TYPE": "azure",
  "OPENAI_API_VERSION": "2023-05-15",
  "OPENAI_API_BASE": "https://<your-resource-name>.openai.azure.com/",
  "OPENAI_API_KEY": "<your-key>",
  "OPENAI_API_ENGINE": "<chat-engine>",         // 例: "gpt-35-turbo"
  "OPENAI_EMBEDDING_ENGINE": "<embedding-engine>"  // 例: "text-embedding-ada-002"
}

📌 注意

  • OPENAI_API_ENGINE → GPT系チャットモデル用
  • OPENAI_EMBEDDING_ENGINE → 埋め込みベクトルモデル用(例: text-embedding-ada-002

✅ コードの修正箇所

以下のように該当箇所を修正してください:

# 追加:埋め込み用エンジン名を取得
embedding_model = config["OPENAI_EMBEDDING_ENGINE"]

# Embeddingsの初期化
embeddings = OpenAIEmbeddings(
    deployment=embedding_model,
    openai_api_key=config["OPENAI_API_KEY"],
    openai_api_base=config["OPENAI_API_BASE"],
    openai_api_version=config["OPENAI_API_VERSION"],
    openai_api_type=config["OPENAI_API_TYPE"]
)

✅ Embeddingモデルのデプロイ状況を確認する方法(Azureポータル)

  1. Azure OpenAI Studio にログイン
  2. モデルのデプロイ メニューを確認
  3. text-embedding-ada-002 がデプロイされていること
  4. 名前(デプロイ名)が config.json"OPENAI_EMBEDDING_ENGINE" に一致していること

✅ 修正後に動作するはずのコード一部抜粋

    # Embedding用エンジンを使ってFAISSインデックス構築
    embeddings = OpenAIEmbeddings(
        deployment=config["OPENAI_EMBEDDING_ENGINE"],
        openai_api_key=config["OPENAI_API_KEY"],
        openai_api_base=config["OPENAI_API_BASE"],
        openai_api_version=config["OPENAI_API_VERSION"],
        openai_api_type=config["OPENAI_API_TYPE"]
    )

    vectorstore = FAISS.from_documents(documents, embedding=embeddings)

🔚 まとめ

  • ❌ Embedding に GPT系エンジンを使おうとして 404 エラー
  • ✅ Embedding専用のエンジン名(例:text-embedding-ada-002)を明記
  • config.json"OPENAI_EMBEDDING_ENGINE" を追加し、コードも修正

必要であれば、修正済みの全体コードもお渡しできます。ご希望でしょうか?

user:

エンべディングはGPT系エンジンではなく、たとえば次のようなエンジンを用いてほしいです。

!pip install langchain-community
from langchain_community.embeddings import HuggingFaceBgeEmbeddings

model_name = "BAAI/bge-small-en"
model_kwargs = {"device": "cpu"}
encode_kwargs = {"normalize_embeddings": True}
embedding = HuggingFaceBgeEmbeddings(
    model_name=model_name, model_kwargs=model_kwargs, encode_kwargs=encode_kwargs
)

assistant:

了解しました!
Azure OpenAI の Embedding API を使わず、代わりに Hugging Face の BAAI/bge-small-en を使う構成に切り替えるということですね。
この構成なら **RAG処理はすべてローカル完結(無料)**で行えます。


✅ 修正方針(要約)

以下のように構成を変更します:

  • ❌ Azure OpenAI の埋め込み → ✅ HuggingFaceBgeEmbeddings に差し替え
  • ✅ PDFの取得・チャンク化 → 変更なし
  • ✅ FAISSによる検索 → 変更なし
  • ✅ Chat要約 → Azure OpenAI を継続使用

✅ 修正済みコード(RAG要約:Hugging Face埋め込み + AOAI GPT)

!pip install pymupdf openai faiss-cpu tiktoken langchain langchain-community

import fitz  # PyMuPDF
import requests, json
from google.colab import drive

from openai import AzureOpenAI
from langchain.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.docstore.document import Document
from langchain_community.embeddings import HuggingFaceBgeEmbeddings

def rag_summarize_pdf(pdf_url, config_path="/content/drive/MyDrive/AOAI/config.json"):
    # Google Driveをマウントして設定ファイルを読み込む
    drive.mount('/content/drive')
    with open(config_path, "r") as f:
        config = json.load(f)

    # Azure OpenAI クライアント
    client = AzureOpenAI(
        api_key=config["OPENAI_API_KEY"],
        api_version=config["OPENAI_API_VERSION"],
        azure_endpoint=config["OPENAI_API_BASE"]
    )
    model = config["OPENAI_API_ENGINE"]

    # PDFを取得してテキスト抽出
    response = requests.get(pdf_url)
    with open("temp.pdf", "wb") as f:
        f.write(response.content)

    doc = fitz.open("temp.pdf")
    all_text = ""
    for page in doc:
        text = page.get_text("text")
        if text:
            all_text += text + "\n"

    # テキストをチャンクに分割
    splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    texts = splitter.split_text(all_text)
    documents = [Document(page_content=t) for t in texts]

    # ✅ HuggingFace BGE Embeddings を使用(GPU環境なら "cuda" に変更可能)
    print("🔧 BGE埋め込みモデルをロード中...")
    embedding = HuggingFaceBgeEmbeddings(
        model_name="BAAI/bge-small-en",
        model_kwargs={"device": "cpu"},
        encode_kwargs={"normalize_embeddings": True}
    )

    # ベクトルストア作成
    vectorstore = FAISS.from_documents(documents, embedding=embedding)

    # クエリを設定して検索
    query = "このPDF全体の内容を日本語で要約してください。"
    docs = vectorstore.similarity_search(query, k=5)
    context = "\n\n".join([doc.page_content for doc in docs])

    # 要約プロンプトを作成し、Azure OpenAI で生成
    prompt = f"""
以下はPDFから抽出された関連情報です。内容を踏まえ、日本語でわかりやすく要約してください:

\"\"\"
{context}
\"\"\"
"""

    print("💬 RAGに基づいてAzure OpenAIで要約中...")
    res = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": "あなたは優秀な日本語の要約アシスタントです。"},
            {"role": "user", "content": prompt}
        ],
        temperature=0.4,
        max_tokens=800
    )

    summary = res.choices[0].message.content.strip()
    print("\n✅ RAGによる要約:\n")
    print(summary)

✅ 利用パターンまとめ

機能 モデル 備考
🔍 ベクトル検索 BAAI/bge-small-en 無料・ローカルで高速
🧠 要約生成 Azure OpenAI (GPT-4 など) 精度重視・料金注意

✅ 補足:日本語PDF対応について

BAAI/bge-small-en英語ベクトルに特化しています。
もし日本語PDFの内容をより正確に扱いたいなら、次のようなモデルを代わりに指定できます:

モデル名 対応言語 メモ
intfloat/multilingual-e5-small 日本語含む多言語対応 軽量で広く使える
sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 多言語対応 精度良好・高速

例:

embedding = HuggingFaceBgeEmbeddings(
    model_name="intfloat/multilingual-e5-small",
    model_kwargs={"device": "cpu"},
    encode_kwargs={"normalize_embeddings": True}
)

🔚 まとめ

  • ✅ BGE埋め込みを使うように変更しました
  • ✅ Azure OpenAI は引き続き要約に利用
  • ✅ 日本語PDFなら多言語Embeddingモデルの利用がおすすめ

ご希望があれば:

  • 🔁 PDFからのQA対応(質問→検索→回答)
  • 📂 複数PDFまとめ処理
  • 📦 FAISSインデックスの保存/再利用

なども対応可能です!ご要望があればお知らせください。

user:

ありがとうございます。実行できました。

次のようなワーニングが出ているので、解消できますか?

/tmp/ipython-input-60-3138781942.py:46: LangChainDeprecationWarning: The class `HuggingFaceBgeEmbeddings` was deprecated in LangChain 0.2.2 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-huggingface package and should be used instead. To use it run `pip install -U :class:`~langchain-huggingface` and import as `from :class:`~langchain_huggingface import HuggingFaceEmbeddings``.
  embedding = HuggingFaceBgeEmbeddings(
/usr/local/lib/python3.11/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: 
The secret `HF_TOKEN` does not exist in your Colab secrets.
To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.
You will be able to reuse this secret in all of your notebooks.
Please note that authentication is recommended but still optional to access public models or datasets.
  warnings.warn(

assistant:

実行成功&詳細なワーニング報告ありがとうございます!
以下、出ている2つのワーニングの原因と、安全かつ推奨される対応策を説明します。


✅ 1. HuggingFaceBgeEmbeddings の非推奨(Deprecation Warning)

⚠️ ワーニング内容(要約)

HuggingFaceBgeEmbeddings は非推奨です。langchain-huggingface に移行してください。

✅ 解決策(推奨)

langchain-community ではなく、langchain-huggingface パッケージに移行する必要があります。

🔧 インストール(1回だけ実行)

!pip install -U langchain-huggingface

🧩 コード変更

# 変更前(deprecated)
from langchain_community.embeddings import HuggingFaceBgeEmbeddings

# 変更後(推奨)
from langchain_huggingface import HuggingFaceEmbeddings

そして埋め込みの初期化も以下のように変更:

embedding = HuggingFaceEmbeddings(
    model_name="BAAI/bge-small-en",
    model_kwargs={"device": "cpu"},
    encode_kwargs={"normalize_embeddings": True}
)

🔁 HuggingFaceEmbeddings は BGE 系も含む汎用的な埋め込みクラスです。
bge-small-en, e5-multilingual, MiniLM などすべて扱えます。


✅ 2. Hugging Face Token に関するワーニング

The secret `HF_TOKEN` does not exist in your Colab secrets.

⚠️ 意味

  • Hugging Face Hub でトークン(認証)を設定していないため、Colab側が警告している。
  • ただし、公開モデルを使う分には問題なし(現時点で動作OK)

✅ 解決策(任意・セキュリティ向上)

  1. Hugging Face にログイン: https://huggingface.co/settings/tokens
  2. アクセストークンを「read パーミッション」で発行
  3. Colab に以下のように設定:
import os
os.environ["HUGGINGFACEHUB_API_TOKEN"] = "hf_xxx_your_token"

または、Colab の「シークレット」に設定して以下で参照:

from google.colab import userdata
os.environ["HUGGINGFACEHUB_API_TOKEN"] = userdata.get("HF_TOKEN")

🔚 修正後のコード例(要点)

!pip install -U langchain-huggingface

from langchain_huggingface import HuggingFaceEmbeddings

embedding = HuggingFaceEmbeddings(
    model_name="BAAI/bge-small-en",
    model_kwargs={"device": "cpu"},
    encode_kwargs={"normalize_embeddings": True}
)

✅ 結論

項目 状態 対処
HuggingFaceBgeEmbeddings の非推奨 ⚠️ 出ている HuggingFaceEmbeddings に変更
Hugging Face 認証トークンなし ⚠️ 任意の警告 ✅ 無視してOK(ただし後で設定すると安全)

必要であれば、全体コードを langchain-huggingface 対応に書き換えてご提供も可能です。ご希望でしょうか?

user:

はい、全体コードを langchain-huggingface 対応に書き換えてご提供お願いします!

assistant:

承知しました!
以下は、**langchain-huggingface に完全対応した RAG要約コード(Google Colab 用)**です。
Hugging Face の BAAI/bge-small-en モデルを使用し、要約には Azure OpenAI を使う構成です。


✅ langchain-huggingface 対応版:PDF要約RAGコード

# 必要なパッケージをインストール
!pip install pymupdf openai faiss-cpu tiktoken langchain langchain-huggingface

import fitz  # PyMuPDF
import requests, json
from google.colab import drive

from openai import AzureOpenAI
from langchain.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.docstore.document import Document
from langchain_huggingface import HuggingFaceEmbeddings

def rag_summarize_pdf(pdf_url, config_path="/content/drive/MyDrive/AOAI/config.json"):
    # ✅ Google Drive をマウントして config を読み込む
    drive.mount('/content/drive')
    with open(config_path, "r") as f:
        config = json.load(f)

    # ✅ Azure OpenAI クライアント
    client = AzureOpenAI(
        api_key=config["OPENAI_API_KEY"],
        api_version=config["OPENAI_API_VERSION"],
        azure_endpoint=config["OPENAI_API_BASE"]
    )
    model = config["OPENAI_API_ENGINE"]

    # ✅ PDF をダウンロードしてテキスト抽出
    response = requests.get(pdf_url)
    with open("temp.pdf", "wb") as f:
        f.write(response.content)

    doc = fitz.open("temp.pdf")
    all_text = ""
    for page in doc:
        text = page.get_text("text")
        if text:
            all_text += text + "\n"

    # ✅ テキストをチャンクに分割
    splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    texts = splitter.split_text(all_text)
    documents = [Document(page_content=t) for t in texts]

    # ✅ HuggingFace の埋め込みモデル(BGE-small)を使用
    print("🔧 BGE-small (HuggingFace) 埋め込みをロード中...")
    embedding = HuggingFaceEmbeddings(
        model_name="BAAI/bge-small-en",
        model_kwargs={"device": "cpu"},
        encode_kwargs={"normalize_embeddings": True}
    )

    # ✅ FAISS ベクトルストアを作成
    vectorstore = FAISS.from_documents(documents, embedding=embedding)

    # ✅ クエリを設定して類似チャンクを検索
    query = "このPDF全体の内容を日本語で要約してください。"
    docs = vectorstore.similarity_search(query, k=5)
    context = "\n\n".join([doc.page_content for doc in docs])

    # ✅ 要約プロンプトを生成し、Azure OpenAI で要約実行
    prompt = f"""
以下はPDFから抽出された関連情報です。内容を踏まえ、日本語でわかりやすく要約してください:

\"\"\"
{context}
\"\"\"
"""

    print("💬 RAG に基づいて Azure OpenAI で要約中...")
    res = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": "あなたは優秀な日本語の要約アシスタントです。"},
            {"role": "user", "content": prompt}
        ],
        temperature=0.4,
        max_tokens=800
    )

    summary = res.choices[0].message.content.strip()
    print("\n✅ RAGによる要約結果:\n")
    print(summary)

✅ 利用前の準備まとめ

1. config.json の中身(例)

{
  "OPENAI_API_TYPE": "azure",
  "OPENAI_API_VERSION": "2023-05-15",
  "OPENAI_API_BASE": "https://<your-resource-name>.openai.azure.com/",
  "OPENAI_API_KEY": "<your-key>",
  "OPENAI_API_ENGINE": "<your-deployment-name>"
}

2. トークン設定(任意・Hugging Face 認証)

  • 公開モデル (BAAI/bge-small-en) を使うだけなら トークン設定は不要です。
  • Private モデルを使う場合はトークンが必要になります。

✅ 実行例

rag_summarize_pdf(
    "https://arxiv.org/pdf/2507.07935v2",
    config_path="/content/drive/MyDrive/AOAI/config.json"
)

✅ オプションでの拡張例

  • 📌 intfloat/multilingual-e5-small に変更して日本語のPDFにも対応
  • 📌 FAISSを保存・読み込みして高速化
  • 📌 質問応答対応(任意のクエリ → RAG → 回答生成)

ご希望であれば上記のような拡張も対応いたします。
必要に応じてお知らせください!

user:

ありがとうございます!ワーニングもなく動作しました!ここまでの内容をブログに記したいので、タイトル案をいくつか提案していただけますか?

assistant:

素晴らしいですね!
ブログにまとめる際のタイトル案を、以下のようなカテゴリでいくつかご提案します:


🔧 技術的な内容を強調するタイトル

  1. 「LangChain + FAISS + Hugging Face で構築するRAG型PDF要約システム」
  2. 「Google Colab上で動かす!Hugging Face埋め込み × Azure OpenAIで高精度PDF要約」
  3. 「RAGで実現するPDFドキュメントの要約自動化【LangChain活用】」

🧠 読者の問題解決にフォーカスしたタイトル

  1. 「大量のPDFを効率よく要約したい?LangChain × Hugging Face × Azure OpenAIで解決!」
  2. 「GPTを使ったPDF要約、でもEmbeddingは無料で!そんな方法、あります。」
  3. 「GPTだけに頼らない!無料の埋め込みモデルで始めるRAG要約」

🚀 シンプルでキャッチーなタイトル

  1. 「PDFを要約してくれるAIをColabで作った話」
  2. 「Azure OpenAI × Hugging Face × LangChainでRAGしてみた」
  3. 「GPTでPDF要約してみたけどEmbeddingはタダにしたかった」

📚 実践・チュートリアル風タイトル

  1. 「【完全チュートリアル】Colabで動かすRAG型PDF要約(LangChain + Hugging Face + AOAI)」
  2. 「無料と有料のいいとこ取り!PDF要約AIをColabで構築する方法」
  3. 「LangChainを使ってRAGでPDF要約する手順【2025年版】」

ご希望のトーンや読者層(初心者向け/エンジニア向け/ビジネス向け)に合わせて、調整もできます。
「○○な雰囲気のタイトルにしたい」といったご希望があれば、さらに絞ってご提案します!

user:

「Google Colab上で動かす!Hugging Face埋め込み × Azure OpenAIで高精度PDF要約」でいきたいと思います。このタイトルに沿って、今回の内容を詳しくまとめてください。

assistant:

了解しました!
以下に、「Google Colab上で動かす!Hugging Face埋め込み × Azure OpenAIで高精度PDF要約」というタイトルに沿った、技術ブログ記事の構成と本文をご提案します。


Google Colab上で動かす!Hugging Face埋め込み × Azure OpenAIで高精度PDF要約


はじめに

PDFファイルを読み込んで、内容を自動で要約したい――そんなニーズは研究やビジネス、教育の現場で日に日に高まっています。
しかし、大規模言語モデル(LLM)にすべてのページを投げるには、トークン制限コストの問題が立ちはだかります。

そこで登場するのが RAG(Retrieval-Augmented Generation) というアプローチです。
今回は、以下の技術スタックを用いて、高精度かつ無料で動かせるRAGベースのPDF要約システムを構築します。


技術スタック

  • 実行環境:Google Colaboratory(無料)
  • 埋め込みモデルBAAI/bge-small-en(Hugging Face公開モデル・無料)
  • 要約生成モデル:Azure OpenAI(GPT系チャットモデルを使用)
  • ベクトル検索:FAISS
  • フレームワーク:LangChain

仕組みの概要(RAGとは?)

RAG(Retrieval-Augmented Generation)は、以下の手順で情報を処理します:

  1. PDFからテキストを抽出
  2. テキストをチャンク(分割)してベクトル化(Embedding)
  3. クエリ(今回は「要約して」)に対して類似チャンクを検索(Retrieval)
  4. 検索結果をもとに LLM が回答を生成(Generation)

このアプローチにより、すべてのページを直接 LLM に送る必要がなくなり、効率よく正確な要約が可能になります。


手順

1. ライブラリのインストール

!pip install pymupdf openai faiss-cpu tiktoken langchain langchain-huggingface

2. Azure OpenAI の設定ファイル(config.json)

Google Drive 内に以下のような JSON ファイルを保存しておきます:

{
  "OPENAI_API_TYPE": "azure",
  "OPENAI_API_VERSION": "2023-05-15",
  "OPENAI_API_BASE": "https://<your-resource-name>.openai.azure.com/",
  "OPENAI_API_KEY": "<your-key>",
  "OPENAI_API_ENGINE": "<your-deployment-name>"
}

3. 要約処理コード(全文)

import fitz  # PyMuPDF
import requests, json
from google.colab import drive

from openai import AzureOpenAI
from langchain.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.docstore.document import Document
from langchain_huggingface import HuggingFaceEmbeddings

def rag_summarize_pdf(pdf_url, config_path="/content/drive/MyDrive/AOAI/config.json"):
    # Google Drive をマウントして config を読み込む
    drive.mount('/content/drive')
    with open(config_path, "r") as f:
        config = json.load(f)

    # Azure OpenAI クライアント
    client = AzureOpenAI(
        api_key=config["OPENAI_API_KEY"],
        api_version=config["OPENAI_API_VERSION"],
        azure_endpoint=config["OPENAI_API_BASE"]
    )
    model = config["OPENAI_API_ENGINE"]

    # PDFをダウンロードしてテキスト抽出
    response = requests.get(pdf_url)
    with open("temp.pdf", "wb") as f:
        f.write(response.content)

    doc = fitz.open("temp.pdf")
    all_text = ""
    for page in doc:
        text = page.get_text("text")
        if text:
            all_text += text + "\n"

    # チャンク分割
    splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    texts = splitter.split_text(all_text)
    documents = [Document(page_content=t) for t in texts]

    # Hugging Face の埋め込みモデル(bge-small)
    print("🔧 BGE-small (HuggingFace) 埋め込みをロード中...")
    embedding = HuggingFaceEmbeddings(
        model_name="BAAI/bge-small-en",
        model_kwargs={"device": "cpu"},
        encode_kwargs={"normalize_embeddings": True}
    )

    # FAISS ベクトルストア
    vectorstore = FAISS.from_documents(documents, embedding=embedding)

    # 類似文書を検索
    query = "このPDF全体の内容を日本語で要約してください。"
    docs = vectorstore.similarity_search(query, k=5)
    context = "\n\n".join([doc.page_content for doc in docs])

    # 要約プロンプトを作成
    prompt = f"""
以下はPDFから抽出された関連情報です。内容を踏まえ、日本語でわかりやすく要約してください:

\"\"\"
{context}
\"\"\"
"""

    print("💬 RAG に基づいて Azure OpenAI で要約中...")
    res = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": "あなたは優秀な日本語の要約アシスタントです。"},
            {"role": "user", "content": prompt}
        ],
        temperature=0.4,
        max_tokens=800
    )

    summary = res.choices[0].message.content.strip()
    print("\n✅ RAGによる要約結果:\n")
    print(summary)

4. 実行例

rag_summarize_pdf(
    "https://arxiv.org/pdf/2507.07935v2",
    config_path="/content/drive/MyDrive/AOAI/config.json"
)

補足:埋め込みモデルを日本語対応にしたい場合

今回使った BAAI/bge-small-en は英語向けですが、日本語を含む多言語に強いモデルもあります:

# 例:日本語PDF対応モデルに切り替え
embedding = HuggingFaceEmbeddings(
    model_name="intfloat/multilingual-e5-small",
    model_kwargs={"device": "cpu"},
    encode_kwargs={"normalize_embeddings": True}
)

おわりに

この方法を使えば、Azure OpenAIの高精度な生成能力を活かしつつ、埋め込み処理は無料・ローカルで完結させることができます。
LangChainの力を借りることで、RAG構成も非常に簡潔に構築できるのが魅力です。


次のステップ(応用編)

  • ✅ 質問応答(QA)機能の追加
  • ✅ 複数PDFのまとめ要約
  • ✅ FAISSの保存/再利用
  • ✅ StreamlitやGradioでUI化

これらの応用についても、ご希望があれば別記事でご紹介します!


必要であれば、この内容をMarkdownファイルやColabノートブック形式に整形してお渡しすることも可能です。お気軽にお申し付けください。

user:

素晴らしいまとめ、ありがとうございました!

assistant:

どういたしまして!そう言っていただけてとても嬉しいです 😊
ブログ記事の執筆、応援しています!もし後日:

  • QA機能を追加したい
  • 要約精度を改善したい
  • 日本語特化のモデルに切り替えたい
  • Web UI(Streamlitなど)で公開したい

といったご要望があれば、いつでもご相談ください!

引き続き、創造的なアウトプットを楽しんでくださいね 💡✍️

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?