長い文章を読むときに一旦要約を読んでから中身を深く読みたい時がある。そのような時にChatGPTを使って要約できると便利だ。しかしGPT-3.5を利用しているとトークン数上限は4096であり、大体4000文字を超えた文章を要約しようとするとエラーとなってしまう。今回はそのような時でも要約するスクリプトを書いたのでメモしておく。
できたもの
STDINに入力した文章を要約するスクリプトを作った。
たとえば締め切りが厳しいプロジェクトで、プロジェクト初期にまずやっておきたいこと - $shibayu36->blog;は4800文字程度の文章量がある。この長さだとインプット + 文章 + アウトプットの合計はトークン数の上限を超えてしまうため一度のAPIリクエストでは要約ができない。しかし、このスクリプトを通せばうまくやってくれる。
$ pbpaste | OPENAI_API_KEY=... python summarize-text.py
締め切りが厳しいプロジェクトでは、全員が同じ目標に向かえるようにする
ために、ゴールイメージを共有し、プロダクトバックログをスプリントで分解
し、タスクの見積もりを全員で行い、ベロシティ測定とバーンアップチャート
の作成が必要である。タスク管理ツールで全ユーザーストーリーを管理するこ
とも重要である。スプリントごとのベロシティを測定し、バーンアップチャー
トを作成することで、タスクの進捗状況を把握しやすくなる。タスク管理を効
率化するために、タスクの追加/分割/やらない判断フローを作成し、短いスパ
ンで改善フローを用意することが重要である。朝会に相談コーナーを用意する
などの工夫も紹介されている。
仕組み
基本的にはlangchainのSummarization examplesに書かれている内容をそのまま使っただけだが、もう少しその仕組みを見てみる。
トークン数を超えるインプットを与えたい時、分割で処理し情報圧縮をした後にまとめるという方式がある。要約はこのやり方と相性が良く、要約自体が情報圧縮となるので、次の流れで実現できる。
- (1) テキストを適切なサイズにチャンク分割する
- (2) それぞれのチャンクに対して要約をする
- (3) すべての要約を結合して、その内容に対して要約をし、最終結果とする
今回のスクリプトではこの作業をCharacterTextSplitterとload_summarize_chainを用いて自動化しているだけだ1。このスクリプトにVERBOSE=1を与えるといろんなログが出るようにしているのだが、こんな感じの出力が出てくる。内容を2つのチャンクに分割し、それぞれの要約を作った後、最終要約を作る様子が見える。
$ pbpaste | VERBOSE=1 python summarize-text.py > Entering new MapReduceDocumentsChain chain... > Entering new LLMChain chain... Prompt after formatting: Write a concise summary of the following text in Japanese: 締め切りが厳しいプロジェクトで、プロジェクト初期にまずやっておきたいこと tech これまで僕は締切がかなり厳しいプロジェクトを数回経験してきた。その経験から、締切が厳しいという特性を持ったプロジェクトの初期にまずこれだけはやったほうが良いということがいくつか見つかったので、今回はそれらを紹介していこうと思う。 ... Prompt after formatting: Write a concise summary of the following text in Japanese: 個人的にはバーンアップチャートの方が好みである。なぜなら、タスクの消化具合だけでなく新規タスクが増えている状況も可視化できるため、遅れている原因が新規タスクが増えているためなのか、速度に問題があるからなのかがひと目で切り分けられるからだ。 ... > Entering new LLMChain chain... Prompt after formatting: Write a concise summary of the following text in Japanese: 締め切りが厳しいプロジェクトの初期には、全員が同じ目標に向かえるようにすることが重要である。具体的には、全員でゴールイメージを共有し、プロダクトバックログをスプリントで終わる単位に分解し、タスクの見積もりを全員で行い、ベロシティ測定とバーンアップチャートの作成を行うことが必要である。また、タスク管理ツールで全ユーザーストーリーを管理することも重要である。 締切が厳しいプロジェクトにおいて、タスク管理におけるバーンアップチャートの利用やタスクの追加・分割・やらない判断フローの作成、短いスパンの改善フローの用意が重要であると紹介されている。また、スプリント会やKPT会、相 談コーナーの設置などの工夫も紹介されている。 ... INTERMEDIATE DETAIL: { "intermediate_steps": [ "締め切りが厳しいプロジェクトの初期には、全員が同じ目標に向かえるようにすることが重要である。具体的には、全員でゴールイメージを共有し、プロダクトバックログをスプリントで終わる単位に分解し、タスクの見積もりを全 員で行い、ベロシティ測定とバーンアップチャートの作成を行うことが必要である。また、タスク管理ツールで全ユーザーストーリーを管理することも重要である。", "締切が厳しいプロジェクトにおいて、タスク管理におけるバーンアップチャートの利用やタスクの追加・分割・やらない判断フローの作成、短いスパンの改善フローの用意が重要であると紹介されている。また、スプリント会やKPT会、相談コーナーの設置などの工夫も紹介されている。" ], "output_text": "締め切りが厳しいプロジェクトでは、全員が同じ目標に向かうために、ゴールイメージを共有し、プロダクトバックログをスプリントで分解し、タスクの見積もりを全員で行い、ベロシティ測定とバーンアップチャートの作成が必要である。また、タスク管理ツールで全ユーザーストーリーを管理することも重要である。さらに、バーンアップチャートの利用やタスクの追加・分割・やらない判断フローの作成、短いスパンの改善フローの用意が重要であり、スプリント会やKPT会、相談コーナーの設置などの工夫も必要である。" }
今後の発展
今回はシンプルに文字数ベースでテキスト分割してそれぞれ要約するという手法を行った。これである程度はうまくいくが、うまくいかない例も多い。たとえばChatGPTを使って自分のブログ風回答を生成する仕組みを学ぶ - $shibayu36->blog;の記事を使った場合、うまくいかない。
INTERMEDIATE DETAIL: { "intermediate_steps": [ "ChatGPTを使って自分のブログ風回答を生成する方法を学ぶため、他の人が実際に試した手順を参考に自分でも動かしてみた。具体的には、はてなブログをChatGPTに接続する方法を学び、自分のブログが言いそうな回答を出してもら うことができた。また、仕組みを理解するために、make_index.pyで保存されるデータについて調べた。", "ask.pyは、質問文をembeddings APIに投げて、数値ベクトルをもらい、類似する本文データを抽出する。その後、ChatGPTのプロンプトの先頭に類似する本文データをつけ、回答するように命令する。", "このテキストは、コードコンプリートやコードレビュー、ペアプログラミングなどについての話題が含まれています。コードレビューについては、レビュータイムの導入や消滅、再導入、段階的に行う方法などが述べられています。 また、コードレビューのやり方についても触れられており、チームによってケースバイケースだということが述べられています。", "このテキストでは、コードやドキュメントを書く際に、いつ突然会社を辞めても問題ない基準で書くことが重要であると述べられている。また、コードやドキュメントを他の人が理解できるようにするために、経緯のコメントを書い たり、シンプルなコードを追求することが必要であると説明されている。さらに、PullRequestを送る前に自分自身でレビューすることが重要であると述べられている。属人性を排除するためには、知識を伝搬させる仕組みを考えることや ペアプロをすることが必要であるが、個人で対処する方法として、コードやドキュメントを書く際に他の人が理解できるかを基準にすることが挙げられている。" ], "output_text": "このテキストでは、ChatGPTを使って自分のブログ風回答を生成する方法を学ぶための手順や、コードコンプリートやコードレビュー、ペアプログラミングなどについての話題が含まれています。また、コードやドキュ メントを書く際に、いつ突然会社を辞めても問題ない基準で書くことが重要であると述べられています。" } SUMMARY: このテキストでは、ChatGPTを使って自分のブログ風回答を生成する方法を学ぶための 手順や、コードコンプリートやコードレビュー、ペアプログラミングなどについての話 題が含まれています。また、コードやドキュメントを書く際に、 いつ突然会社を辞めて も問題ない基準で書くことが重要であると述べられています。
本来ならChatGPTを使って自分のブログ風回答がなぜできるかの要約を作ってほしいのに、コードレビューの話などが書かれてしまっている。これは「例えば最初に試してみた質問だと、自分のブログの以下の本文が利用されていた」という部分にあるpre.code
に入っている大量の文字を要約してしまっているためだ。
こういう場合にもなんとかするためには、入れる文章をpre-processingしたり、目次構造を意識して要約をさせたり、など別の対応が必要だと思う。あえてHTML構造のまま入れた方が扱いやすいなどもありそうだ。
その他にも長文から論点を抽出して、その論点を軸に文章の要約を試みる|mah_lab / 西見 公宏|noteでは、文章のチャンクをクラスタリングして大きいクラスタはその文章の重要な要点であるとみなし、その情報をもとに要約する手法を試していた。すごく巨大な文章、かつ、文章の並び順を要約に反映しなくても良い場合、うまくいくように感じる。
このように単純に要約といってもどんな文章にでも同じ手法を使えるわけではなく、いろんな前処理の工夫をする必要があるのだろう。
- langchainの例通りに行うと、text-davinci-003のモデルが使われて課金額がすごいことになるため、OpenAI()の初期化部分をChatOpenAI()にすることをお勧めする↩