🕌

DifyでナレッジAPIを活用して15MBを超えるPPTX資料を効率的に登録する方法

2024/12/06に公開

DifyでナレッジAPIを活用して15MBを超えるPPTX資料を効率的に登録する方法

背景

クラウド版のDifyでは、1ファイルの登録上限が15MBという制約があります。しかし、業務で使用するPPTX資料はこれを超える大容量ファイルであることが珍しくありません。この制約を解消するためには、画像圧縮やファイル分割などの手作業が必要になり、非常に面倒です。

そこで、Difyが提供するナレッジAPIを活用し、大容量のPPTX資料を効率的に処理・登録する仕組みを使用しました。この方法では、PPTXをスライドごとに分割してテキスト化し、チャンク分けを考慮した形で自動的にDifyのナレッジへ登録できます。


Difyとは?

Dify(https://dify.ai/jp) は、ChatGPTやLLM(大規模言語モデル)を簡単に活用できるアプリケーション開発プラットフォームです。ナレッジを登録することで、企業内の情報などを効果的に活用したQAや検索が可能になります。しかし、クラウド版ではファイルのアップロードに各15MBの制限があるため、大容量の資料を取り扱うには工夫が必要です。


今回使用するDifyのナレッジAPIについて

今回使用するDifyのナレッジAPIは以下の機能です:

  • ナレッジの作成: 空のナレッジ(Knowledge Base)を作成するエンドポイント。
  • ドキュメントの登録: テキストやファイル形式でドキュメントを登録。
  • セグメンテーション: チャンクをスライドやセクション単位で区切るカスタムルールを設定可能。

主なエンドポイント

  1. ナレッジの作成
    • URL: POST /datasets
    • 必須項目: ナレッジ名

すでに作成されているナレッジに追加することもできますが、今回は新規作成から行います。

  1. ドキュメントの登録

    • URL: POST /datasets/{dataset_id}/document/create-by-text
    • 必須項目: ドキュメント名、内容(テキスト形式)、セグメンテーション設定。
  2. セグメンテーション設定

    • カスタムモードを利用することで、区切り文字(例: @@@SLIDE_SEPARATOR@@@)を指定し、スライドやセクション単位でチャンクを生成可能。

詳細なAPIリファレンスは 公式ドキュメント を参照してください。


APIキーの取得方法

DifyのAPIを利用するには、APIキーが必要です。以下の手順でAPIキーを取得してください。

手順

  1. Difyのアカウントにログイン
    Difyの管理画面にログインします。

  2. APIキーの発行画面に移動

    • 画面中央上の「ナレッジ」を選択します。
    • 画面左上の「ナレッジ」タブを「API」タブに切り替えます。
    • 画面右上の「APIキー」を選択します。

  1. APIキーを作成
    • 「APIキー」を選択すると、新しくキーが生成できるため、作成します。
    • 生成されたAPIキーをコピーします。

注意事項

  • キーを公開しない: 生成したAPIキーは第三者に公開しないように注意してください。ソースコードに直接記述する場合は、プライベートリポジトリで管理するか、公開する際に削除してください。

必要な環境

1. Python環境

  • バージョン: 3.10
  • 必要なパッケージ:
    python-pptx, requests

2. フォルダ・ファイル構造

以下のフォルダ・ファイル構造を準備してください:

/workspace
│
├── pptx_to_dify.py  # 実行するPythonスクリプト
│
├── pptx/            # PPTXファイルを配置するフォルダ
│   ├── example1.pptx
│   ├── example2.pptx
│
├── txt/             # 出力されるテキストファイルが保存されるフォルダ

解決策

以下の手順で大容量のPPTXファイルを効率的に登録します:

  1. PPTXをスライドごとにテキストファイルに変換
    pptx/フォルダ内に格納されている全てのpptxファイルを対象とします。
    各スライドを「スライド番号」「スライドタイトル」「スライド内容」という構造でテキストファイルとして出力します。

  2. DifyのナレッジAPIを使用して自動登録
    テキストファイルをDifyのナレッジに登録し、スライドごとにチャンク分けを行います。

  3. チャンク分けルールをカスタマイズ
    スライド間の区切りを明確にし、検索やLLMによる応答が最適化されるよう調整します。

実装方法

以下がpptx_to_dify.py の全コードです:

import os
from pptx import Presentation
import requests

# === PPTXファイルをテキストに変換 ===
def pptx_to_single_text_file(input_file, output_dir):
    """PPTXファイルをスライドごとにテキスト化し、番号付きのチャンクを作成"""
    prs = Presentation(input_file)
    base_name = os.path.splitext(os.path.basename(input_file))[0]
    output_file = os.path.join(output_dir, f"{base_name}.txt")
    
    with open(output_file, "w", encoding="utf-8") as f:
        for i, slide in enumerate(prs.slides, start=1):
            # 区切り文字とスライド番号を設定
            slide_header = f"@@@SLIDE_SEPARATOR@@@\nSlide_num:{i}\n"
            f.write(slide_header)
            
            # スライドのタイトルを取得して最初に記述
            title = slide.shapes.title.text if slide.shapes.title else "No Title"
            f.write(f"Title: {title}\n\n")
            
            # スライド内のその他のテキストを追記
            for shape in slide.shapes:
                if hasattr(shape, "text") and shape.text.strip() and shape != slide.shapes.title:
                    f.write(shape.text + "\n")
            f.write("\n")  # スライド間の空行
    print(f"Converted {input_file} to {output_file}")
    return output_file

# === 空のデータセットを作成 ===
def create_dataset(api_key, dataset_name):
    api_url = "https://api.dify.ai/v1/datasets"
    headers = {"Authorization": f"Bearer {api_key}"}
    payload = {"name": dataset_name}
    
    response = requests.post(api_url, headers=headers, json=payload)
    if response.status_code == 200:
        dataset_id = response.json()["id"]
        print(f"Dataset created: {dataset_id}")
        return dataset_id
    else:
        print(f"Failed to create dataset: {response.content}")
        return None

# === データセットにテキストファイルを登録(チャンク設定付き) ===
def add_document_to_dataset(api_key, dataset_id, text_file):
    """DifyのAPIを使ってテキストファイルをデータセットに登録(チャンク設定付き)"""
    api_url = f"https://api.dify.ai/v1/datasets/{dataset_id}/document/create-by-text"
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    
    # テキストファイルを読み込む
    with open(text_file, "r", encoding="utf-8") as f:
        content = f.read()
    
    # APIに送信するペイロード
    payload = {
        "name": os.path.basename(text_file),
        "text": content,
        "indexing_technique": "high_quality",
        "process_rule": {
            "mode": "custom",
            "rules": {
                "pre_processing_rules": [
                    {"id": "remove_extra_spaces", "enabled": True},
                    {"id": "remove_urls_emails", "enabled": True}
                ],
                "segmentation": {
                    "separator": "@@@SLIDE_SEPARATOR@@@",  # 区切り文字を指定
                    "max_tokens": 1000
                }
            }
        }
    }
    
    # リクエストを送信
    response = requests.post(api_url, headers=headers, json=payload)
    
    if response.status_code == 200:
        print(f"Successfully added {text_file} to dataset {dataset_id}")
    else:
        print(f"Failed to add document: {response.status_code} - {response.content}")

# === メイン処理 ===
def process_and_upload_pptx_files(api_key, dataset_name, working_dir):
    input_dir = os.path.join(working_dir, "pptx")
    output_dir = os.path.join(working_dir, "txt")
    os.makedirs(input_dir, exist_ok=True)
    os.makedirs(output_dir, exist_ok=True)
    
    dataset_id = create_dataset(api_key, dataset_name)
    if not dataset_id:
        return
    
    for file_name in os.listdir(input_dir):
        if file_name.endswith(".pptx"):
            input_file = os.path.join(input_dir, file_name)
            text_file = pptx_to_single_text_file(input_file, output_dir)
            add_document_to_dataset(api_key, dataset_id, text_file)

# === 実行設定 ===
if __name__ == "__main__":
    API_KEY = "your_api_key"  # ナレッジベースAPIのAPIキー
    DATASET_NAME = "My New Dataset"  # 作成するナレッジ(データセット)の名前
    WORKING_DIR = os.path.dirname(os.path.abspath(__file__))
    process_and_upload_pptx_files(API_KEY, DATASET_NAME, WORKING_DIR)

APIキーの設定

取得したAPIキーを以下のコード内に設定してください:

API_KEY = "your_api_key"  # ここに取得したAPIキーを貼り付ける

コードの実行

python pptx_to_dify.py

実行結果

出力例

以下のようにスライドごとに分割され、スライド番号やスライドタイトルが追記された状態でDifyのナレッジに登録されます。

まとめ

この方法を利用することで、Difyのクラウド版で大容量のPPTX資料を効率的に登録できるようになります。15MB超の制約を回避しつつ、スライド単位での検索性や利便性も向上します。

また今回はナレッジを一から登録しましたが、すでにあるナレッジにAPIからドキュメントを追加することも出来るので、運用時にも有用かと思います。ぜひ活用してみてください!

Aidemy Tech Blog

Discussion