【Dify】Transformersを使って質問文を生成してみた

# はじめに
本ブログでは、Transformersを使用して質問文を生成する方法を紹介していきます。DifyのナレッジにCSVファイルをインポートする際、質問文があるとより正確な回答が得られるのではないかと考え、Google Colab上で質問文生成を実装しました。実際の実装手順やポイントについても詳しく解説していきます。

# Difyとは
Difyは、ナレッジベースを活用した対話AIを構築・運用できるツールです。ユーザーが持つナレッジ（FAQや各種情報）をCSVや他の形式でインポートし、AIが質問に応じて適切な回答を提供できるようにします。ビジネスシーンでのカスタマーサポートや社内FAQの自動化に適しており、効率的な情報管理と活用が可能です。

# なぜ質問文を生成するのか
質問文をナレッジに追加すると、AIが質問の意図や背景を理解しやすくなります。これにより、回答がユーザーの期待により近いものになる可能性があります。また質問文が追加されていると、過去の質問と一致するかどうかが判定しやすくなります。これにより、類似質問があった際に自動で適切な回答を提供することができるかもしれません。

# 今回使用するデータ
今回はいくつかの国の食に関するpptxファイル（自作）を使用していきます。

![スクリーンショット 2024-11-06 165602.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816986/559e30ef-57b3-2fe7-6d77-2c49808671cb.png)

# 手順
以下の手順で実装していきます。

①pptxファイルを読み込む
②①で読み込んだファイルをページごとに分割し、テキストを取得
③取得したテキストをDataFrameにする
④Transfomersを使い、テキストから質問文を生成する。
⑤生成した質問文をDataFrameに追加
⑥csvファイルを出力

# 実装
python-pptxをインストールします。
これはPythonでPowerPoint（PPTX）ファイルを生成、編集、操作するためのライブラリです。
```python
pip install python-pptx
```
必要なライブラリーをインポート
```python
from pptx import Presentation
import pandas as pd
from io import BytesIO
from transformers import T5ForConditionalGeneration, T5Tokenizer
```
pptxファイルを読み込み、各ページごとのテキストを取得していきます。
```python
def merge_pptx(input_file, output_file):
    # バイトデータをBytesIOオブジェクトに変換して読み込む
    if isinstance(input_file, bytes):
        input_stream = BytesIO(input_file)
    else:
        input_stream = input_file  # ファイルパスが与えられた場合

    # 元のPowerPointファイルを読み込む
    prs = Presentation(input_stream)

    # 新しいプレゼンテーションを作成
    writer = Presentation()

    slide_texts = []

    # 全スライドを新しいプレゼンテーションに追加
    for slide in prs.slides:
        slide_layout = writer.slide_layouts[0]  # デフォルトのレイアウトを使用
        new_slide = writer.slides.add_slide(slide_layout)
        slide_text = []

        # スライドの内容をコピー（形状やテキスト）
        for shape in slide.shapes:
            if shape.has_text_frame:
                textbox = new_slide.shapes.add_textbox(shape.left, shape.top, shape.width, shape.height)
                textbox.text = shape.text_frame.text
                for paragraph in shape.text_frame.paragraphs:
                    slide_text.append(paragraph.text)  # 各段落のテキストを取得
            elif shape.shape_type == 13:  # 画像の場合
                # 画像の追加
                img_stream = BytesIO(shape.image.blob)  # 画像データをBytesIOでラップ
                new_slide.shapes.add_picture(img_stream, shape.left, shape.top, shape.width, shape.height)
        slide_texts.append("\n".join(slide_text))

    # すべてのスライドを含む新しいPowerPointファイルとして保存
    writer.save(output_file)
    print(f"Created: {output_file}")
    return slide_texts

input_pptx = "file_path"
# 分割後のPowerPointファイルの保存先フォルダ
output_pptx = os.path.join(path,"merge.pptx")

pptx = merge_pptx(input_pptx, output_pptx)
```
pptxの中身
```python
['\n\nアメリカ\nアメリカは農業大国であるため、トウモロコシやトマト、小麦、大豆、オレンジ、リンゴ、牛乳、チーズなどさまざまな種類の農作物を作っています。牛肉は世界1位の生産量です。\n野菜や果物くだものなどの生産量が多い分、輸出ゆしゅつ量も多い農業大国。',
 '\n\nブラジル\nブラジルでは世界で生産されるコーヒー豆の約3割わりを作っていて、生産量は世界ナンバーワン。本のコーヒーも約3割わりがブラジルからの輸入ゆにゅうです。',
 '\n\n\nガーナ共和国\nガーナはチョコレートの原料になるカカオの産地です。ラグビーボールよりひと回りほど小さい実の中に30〜50つぶのカカオ豆が入っています。ガーナは、世界第2位のカカオ生産国です。\n\n',
 '\n\nイギリス\nイギリスは紅茶こうちゃの国ともいわれ、朝にはモーニングティー、午後にはアフタヌーンティーやクリームティーなど、1日の中にお茶を楽しむ時間がいろいろあります。\x0b3段だん重ねのトレイに盛もり付けられたサンドイッチやスコーン、いろいろなケーキやタルトを食べながら、紅茶こうちゃを飲むのが「アフタヌーンティー」です。',
 '\n\n\nオランダ王国\n山羊乳やぎにゅうを使ったチーズやスモークチーズ、クミンやクローブといったスパイス入りのチーズなど、オランダ全土でさまざまなチーズが作られています。\n\n',
 '\nフランス共和国\n\n歴史をふり返ってみると、14世紀のはじめに書かれた料理書には「とり肉のシナモンソース」など、今食べてもおいしそうな料理のレシ現在げんざいのフランス料理の名声を築きずいたのは、19世紀のはじめのカレームという料理人です。']
```
pptxを整形してDataFrameにしていきます。
```python
country = []
food_info = []
for content in pptx:
  content = content.split("\n")
  content = [i for i in content if i != ""]
  country.append(content[0])
  food_info.append(content[1])

df = pd.DataFrame({
    "country":country,
    "food_info":food_info
})
```
dfの中身
![スクリーンショット 2024-11-06 170932.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816986/de1c8637-37d5-e380-1349-6a1629b6faca.png)

ではここからTransfomersを使って質問文を生成していきます。
モデルのダウンロードし、質問文を生成していきます。
```python
model = T5ForConditionalGeneration.from_pretrained("sonoisa/t5-base-japanese-question-generation")
tokenizer = T5Tokenizer.from_pretrained("sonoisa/t5-base-japanese")

lists = []
for input_text in df["food_info"]:
  input_ids = tokenizer.encode(f"質問を生成: {input_text}", return_tensors="pt")
  outputs = model.generate(input_ids)
  question = tokenizer.decode(outputs[0], skip_special_tokens=True)
  lists.append(question)
```
結果の確認
```python
lists[0]
---------------------
アメリカはどのような種類の農業製品を作っていますか?
```
質問文の追加とcsvファイルの出力
```python
df["questions] = lists
df.to_csv("output.csv")
```
# おわりに
今回は、Transformersを使って質問文を生成する方法をご紹介しました。これからも、AIの活用を通してナレッジ管理を改善し、効率的な情報提供を目指していきます。