へんてこのブログ

日々気づいたことや、最近やっていることを書いています

AIを使って会議の要約をしたい

オンラインなどの会議で録音されたデータを使って、話した内容についてざっくり箇条書きで要約を作って欲しかったので、やってみました。

結論

こちらのGoogle Colaboratoryファイルをコピーして使えば、誰でも録音データから要約を作れます。多分無料アカウントでもできると思いますが、有料プランの方が無難です。Colab Pro+だとバックグラウンド実行できるのでより安全です。

要約の手順

今回はWhisperOpenAI API(gpt-3.5-turbo)を利用します。ざっくりと以下の流れです。

  1. 録音データからWhisperでテキスト化
  2. テキストをOpenAI APIに投げて要約

WhisperはOpenAI APIでも提供されているんですが、あえてOSS版のものを利用しています。理由は制限がないからです。このためにGoogle Colaboratoryを使ってGPUをぶん回しています。 OpenAI APIの方のWhisperは音声データが25MBまでなので、長い会議などでは利用ができません。(分割するのも現実的ではないと判断しました)

2では、OpenAI API(gpt-3.5-turbo)にはToken制限があるため、テキスト化したものを分割してAPIに投げています。今回は安全のために3000 Tokenくらいで分割をしています。

分割についてはもっといい方法あるかと思いますが、GPT-4の32k版がAPIで利用できるようになれば解決する問題なので、とりあえずこれでいいでしょうという感じです。

まずは準備

まずは準備です。ノートブックの設定を以下のようにし、GPUを使えるようにしましょう。メモリはハイメモリじゃなくても動くかもしれません。(検証してません)

そして以下のコードを実行します。Google Driveのマウントと、必要なライブラリとミドルウェアのインストールをしています。

!nvidia-smi

from google.colab import drive
drive.mount("/content/drive")

!pip install -U openai-whisper
!pip install openai tiktoken
!apt-get update && apt-get install -y ffmpeg

録音データをテキスト化

準備ができたので、次は録音データをテキスト化しましょう。Whisperを使ってGPUを使っていきます。

import whisper
import os

input_file_path = "" # @param {type: "string"}
output_dir_path = "" # @param {type: "string"}
model_name = "large"  # @param {type: "string"}
language = "ja" # @param {type: "string"}

model = whisper.load_model(model_name)
result = model.transcribe(input_file_path, language=language, verbose=True)

text_list = []
for segment in result["segments"]:
  text_list.append(segment["text"] + '\n')

output_file_name = os.path.splitext(os.path.basename(input_file_path))[0]
f = open(os.path.join(output_dir_path, output_file_name + ".txt"), 'w', newline='\n')
f.writelines(text_list)
f.close()

Google Colaboratoryの方では以下のような画面になっています。

input_file_pathとoutput_dir_pathには適するGoogle Driveへのpathを指定しましょう。 左のツールから、Google Driveのファイルを閲覧することができるので、そこからpathを取得してください。

これで実行すると、録音データがテキスト化され、output_dir_pathに指定した場所にtxtファイルが生成されます。

ちなみに今回はこんなテキストをChatGPTに生成させて、自分で録音したデータを利用しています。

デモ用テキスト

人生にはさまざまな選択肢がある。どの選択肢を選ぶかによって、その人の人生が大きく変わることもある。たとえば、進路選択や結婚相手の選択など、一生に一度の大きな決断がある。しかし、そうした決断は人生のすべてを決定するわけではない。人生には多くの機会があり、いくつかの失敗や誤った選択肢もあるかもしれないが、それでも進むべき方向がある。

人生の進路については、誰しも悩むものである。子どもの頃から将来の夢や目標を持っている人もいれば、成人してからでも見つける人もいる。しかし、自分に合った進路を見つけるには、努力や試行錯誤が必要である。あきらめずに挑戦することが大切である。

また、人生においては、結婚相手を選ぶことも重要な決断の一つである。結婚は一生に一度のことであり、相手を選ぶことで自分の人生が大きく変わることもある。しかし、相手を選ぶ際には、外見や経済的な条件だけでなく、性格や価値観なども考慮することが大切である。

人生においては、失敗や誤った選択肢もある。しかし、それらを乗り越えることが人生を豊かにすることにもつながる。失敗から学び、前向きに進むことが大切である。

人生には多くの機会があり、いくつかの選択肢もある。人生は決して一筋縄ではいかないものであり、人生を歩む上でさまざまな試練が待ち受けているかもしれない。しかし、前向きに考え、自分に合った進路や相手を選び、失敗を乗り越えていくことが、充実した人生を送る秘訣である。

人生には、様々な選択肢があり、自分で決めることができることが多い。しかし、選択をすることで得られるものや失うものもあり、悩んでしまうこともあるかもしれない。そんなときは、自分自身と向き合い、自分が本当に求めているものを見つけることが大切である。

自分自身と向き合うことは、自分自身を理解することでもある。自分自身を理解することができれば、自分が求めるものや、選択すべき方向性が見えてくることがある。自分が本当に求めるものを見つけるためには、自分の内側を探ることが必要である。自分自身と対話することで、自分自身の考え方や価値観を見つけることができるかもしれない。

また、人生には色々な人との出会いがある。友達や恋人、同僚や上司、さまざまな人たちと関わりを持つことができる。これらの出会いは、自分自身を成長させるための貴重な経験となることもある。そのため、出会いを大切にし、誠実に接することが大切である。

しかし、人生にはトラブルも起こりうる。トラブルが起こってしまったときは、自分自身と向き合い、冷静に考えることが必要である。自分自身の考え方や行動が問題の原因である場合もあるため、反省し、改善することが大切である。また、トラブルを解決するためには、相手とのコミュニケーションを大切にすることも必要である。

人生には、自分自身や他人に対して、様々な感情を抱くことがある。悲しみや怒り、喜びや幸せなど、さまざまな感情がある。これらの感情は、人生をより豊かにするためのものである。自分自身の感情に正直に向き合い、それを表現することが大切である。また、他人の感情にも敏感になり、相手の立場に立って考えることが必要である。

最後に、人生は短いものである。限られた時間の中で、自分自身が本当にやりたいことや、やるべきことを見つけることが大切である。自分自身のやりたいことに集中し、それに向けて努力することが、充実した人生を送る秘訣である。

また、人生は常に変化しているものである。時には、思いもよらないことが起こることもある。そんなときは、前向きに捉え、変化に対応することが必要である。変化に対応するためには、柔軟性や創造性を持ち、チャレンジ精神を持って挑戦することが大切である。

以上のように、人生にはさまざまな選択肢がある。自分自身と向き合い、自分自身を理解し、自分自身が本当に求めるものを見つけることが大切である。出会いを大切にし、トラブルを解決するために相手とのコミュニケーションを大切にし、感情に正直に向き合うことが必要である。そして、人生は短いものであるため、自分自身のやりたいことに集中し、常に前向きに変化に対応することが大切である。

録音データから書き起こされたテキストはこんな感じです。結構精度いいですね。

書き起こされたテキスト

人生には様々な選択肢がある。どの選択肢を選ぶかによって、その人の人生が大きく変わることもある。
例えば、進路選択や結婚相手の選択など、一生に一度の大きな決断がある。
しかし、そうした決断は人生のすべてを否定するわけではない。
人生には多くの機会があり、いくつかの失敗や誤った選択肢もあるかもしれないが、それでも進むべき方向がある。
人生の進路については誰しも悩むものである。子供の頃から将来の夢や目標を持っている人もいれば、成人してからでも見つける人もいる。
しかし、自分に合った進路を見つけるには、努力や試行錯誤は必要である。諦めずに挑戦することが大切である。
また、人生においては、結婚相手を選ぶことも重大な重要な決断の一つである。
結婚は一生に一度のことであり、相手を選ぶことで自分の人生が大きく変わることもある。
しかし、相手を選ぶ際には、外見や経済的な条件だけではなく、性格や価値観なども考慮することが大切である。
人生においては、失敗や誤った選択肢もある。しかし、それらを乗り越えることが人生を豊かにすることにもつながる。
失敗から学び、前向きに進むことが大切である。
人生には多くの機会があり、いくつかの選択肢もある。
人生は決して一筋縄では行かないものであり、人生を歩む上で様々な試練が待ち受けているかもしれない。
しかし、前向きに考え、自分に合った信頼や相手を選び、失敗を乗り越えていくことが充実した人生を送る秘訣である。
人生には様々な選択肢があり、自分で決めることができることが多い。
しかし、選択をすることを得られるものや失うものもあり、悩んでしまうこともあるかもしれない。
そんな時は、自分自身と向き合い、自分が本当に求めているものを見つけることが大切である。
自分自身と向き合うことは、自分自身を理解することでもある。
自分自身を理解することができれば、自分が求めるものや選択すべき方向性が見えてくることがある。
自分が本当に求めるものを見つけるためには、自分の内側を探ることが必要である。
自分自身と対話することで、自分自身の考え方や価値観を見つけることができるかもしれない。
また、人生にはいろいろな人との出会いがある。
友達や恋人、同僚や女子、様々な人たちと関わりを持つことができる。
これらの出会いは、自分自身を成長させるための貴重な経験となることもある。
そのため、出会いを大切にし、誠実に接することが大切である。
しかし、人生にはトラブルも起こり得る。
トラブルが起こってしまったときは、自分自身と向き合い、冷静に考えることが必要である。
自分自身の考え方や行動の原因、問題の原因である場合もあるため、反省し、改善することが大切である。
また、トラブルを解決するためには、相手とのコミュニケーションを大切にすることも必要である。
人生には、自分自身や他人に対して様々な感情を抱くことがある。
悲しみや怒り、喜びや幸せなど、様々な感情がある。
これらの感情は、人生をより豊かにするためのものである。
自分自身の感情に正直に向き合い、それを表現することが大切である。
また、他人の感情にも敏感になり、相手の立場に立って考えることが必要である。
最後に、人生は短いものである。
限られた時間の中で、自分自身が本当にやりたいことや、やるべきことを見つけることが大切である。
自分自身のやりたいことに集中し、それに向けて努力することが、充実した人生を送る秘訣である。
また、人生は常に変化しているものである。
時には、思いもよらないことが起きることもある。
そんな時は、前向きに捉え、変化に対応することが必要である。
変化に対応するためには、柔軟性や創造性を持ち、チャレンジ精神を持って挑戦することが大切である。
以上のように、人生には様々な選択肢がある。
自分自身と向き合い、自分自身を理解し、自分自身が本当に求めるものを見つけることが大切である。
出会いを大切にし、トラブルを解決するための相手とのコミュニケーションを大切にし、
感情に正直に向き合うことが必要である。
そして、人生は短いものであるため、自分自身のやりたいことに集中し、
常に前向きに変化に対応することが大切である。

要約する

最後に要約です。

import os
import openai
import tiktoken
from tiktoken.core import Encoding

openai_api_key = "" # @param {type: "string"}
input_text_file_path = "" # @param {type: "string"}
output_dir_path = "" # @param {type: "string"}

openai.api_key = openai_api_key

f = open(input_text_file_path, 'r')
data = f.read()
f.close()

def split_data(data):
  encoding: Encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
  split_strings = []

  tokens = encoding.encode(data)
  if len(tokens) <= 3000:
    return [data]

  text = ""
  for s in data.split("\n"):
    text += s
    tokens = encoding.encode(text)
    if len(tokens) > 3000:
      split_strings.append(text)
      text = ""
  return split_strings

messages = [ {"role": "system", "content": "あなたは優秀なアシスタントです。ユーザーから提供される文章から、何を話したのかを要約して箇条書きにしてください。"} ]
contents = []
data_list = split_data(data)
for index in range(len(data_list)):
  s = data_list[index]
  if len(s) < 50:
    break

  local_messages = messages.copy()
  local_messages.append({"role": "user", "content": s})

  response = openai.ChatCompletion.create(
      model="gpt-3.5-turbo",
      messages=local_messages,
  )
  content = response.choices[0]["message"]["content"].strip()
  contents.append(content)
  print(content)

output_file_name = os.path.splitext(os.path.basename(input_text_file_path))[0]
f = open(os.path.join(output_dir_path, output_file_name + "-summary.txt"), 'w')
f.write('\n'.join(contents))
f.close()

Google Colaboratoryの方では以下のような画面になっています。

openai_api_keyのところに、自分のOpenAI API Keyを指定してください。 またinput_text_file_pathには先ほど生成されたtxtファイルを指定しましょう。output_dir_pathも同じく指定してください。

これで実行すると、要約が完成します。

- 人生には多くの選択肢があり、その選択で人生が大きく変わることもある
- 進路選択や結婚相手の選択は人生で大きな決断である
- 失敗や誤った選択肢もあるが、それらを乗り越えて前向きに進むことが大切である
- 自分自身と向き合い、自分自身を理解し、自分自身が本当に求めるものを見つけることが大切である
- 出会いを大切にし、トラブルを解決するための相手とのコミュニケーションを大切にする
- 感情に正直に向き合い、自分自身のやりたいことに集中し、前向きに変化に対応することが大切である
- 人生は短いものなので、自分自身が本当にやりたいことを見つけて活躍することが大切である

かなり精度いいんじゃないでしょうか。

さいごに

この1ヶ月ちょっと育休を取っていたんですが、この要約システムで育休期間中に開催された会議をざっくり理解することができる気がします。ざっくりあたりをつけられるので、結構有用だなと思っています。

この要約に加えて、会議の議事録を読めば時間節約しつつ理解できるんじゃないかなと思います。