AIニュース要約サイトを支える技術 〜ChatGPT APIの呪文を添えて〜
こんにちは!くりぷとべあーです!
先日の記事でも紹介した通り、ChatGPT APIを利用した海外仮想通貨ニュースの要約まとめサイト「Crypto AI-Digest」というサービスをリリースしました。
おかげさまで各所で話題になり、初日には万超えのPVを記録できました。また、心優しい方々から暖かいお言葉やアドバイスをいただいて、とても嬉しかったです。ありがとうございました。
まだまだ半端な出来のサービスではあるものの、海外のニュース記事の要約を提供することでトレーダーの情報収集効率を上げる、というコンセプトが受け入れられそうで嬉しく思っています。
さて、この記事ではサイトを作るときに使った技術をご紹介しようと思います。
記事のポリシー
この記事は苦労したことや工夫したことを開けっぴろげに書きます。ChatGPT APIに投げてるprompt (呪文) もほぼそのまま書いておきます。
開けっぴろげに書いたことを参考にして、自分のサービスより良いサービスが出てきたら嬉しいなと思ってますので、参考になったらぜひ色々試してみて便利なもの作ってみてください。
まぁ、どうせGPT4出てきたらまたゲームのルールが全部ひっくり返って呪文も陳腐化するでしょ、とか思ってるので公開しちゃおうというお気持ちもあったりします笑
対象となる想定読者
以下のような方を想定読者とし、過度な説明は省かせていただきます。
ある程度プログラミングできる
ChatGPT APIをはじめとするOpenAIのAPIを利用して何か便利なサービスを作りたい
暗号通貨に対してのある程度の理解がある
全体の流れ
この記事で全ての内容を説明するわけではないですが、このサイトがどう動いているかを最初に書いておきます。
1. 主要メディアの最新記事取得
- RSS/Twitterから主要メディアの最新記事URLを取得
- 取得した記事のタイトル・本文を取得する
- 全文が配信されるRSSはタイトル・本文を取得
- それ以外はクローリングで取得
2. 日本語の要約及び記事タイトル生成
- 原文のタイトル・本文をChatGPT APIに入力し生成
- ChatGPTの回答に多少ルールベースでの修正を行う
3. ニュースの重要度推定
- 原文タイトル及び2.の要約文をChatGPT APIに入力し
市場への影響度を推定
4. 記事のEmbeddingから、類似記事を探索
- 2.の要約文をOpenAI Embedding APIに入力し
記事のEmbedding(ベクトル)を取得
- 他社の既報と酷似する記事は「後追い記事」扱いをする
5. 記事をWordpressAPIで投稿
6. 記事投稿をTwitterAPIで告知 (予定)
7. 投稿した旨を自身のSlackに投稿し、たまに手動検閲
それではここから詳細を書いていきます。
ChatGPT APIを用いた記事要約
概要
このサイトは「海外ニュースをなるはやで日本語に要約する」という価値を提供しています
これには「翻訳」「要約」の技術が必要ですが、ChatGPT APIではこれを一気に処理してくれます。(最初はびっくりしました)
出力された文を最後まで読んでもAIが書いたとは思えない要約文も多く、控えめに言って感動しました。
ただ、なかなかの暴れ馬で乗りこなすのに工夫が必要でした。なので、工夫した点も交えつつ書きます。
シンプルな例
ChatGPT APIを利用すると、以下のような非常に簡潔なコードで海外記事を日本語で要約を行うことが可能です。
import os
import openai
openai.api_key = os.environ['OPENAI_API_KEY']
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": f"{ここに後述の呪文を入れる}"},
]
)
print(['choices'][0]['message']['content'])
課題
プロトタイピングを行った際に以下のような問題が発生し、世に出せる品質の要約文を安定して生成するのには試行錯誤が必要でした。
気軽に嘘をついたり、自分の意見や感想、妄想を勝手に差し込んでくる。
要約しろと言ってるのに全文を直訳する
中国語と日本語を混同している
決められたフォーマットで回答しない
固有名詞をよくわからない名称に翻訳する
知らない専門用語を無理やり直訳する (ベアマーケット → 熊市)
要約とは言えないような超長文を書く
特に1-3が深刻でした。
1に関しては風説の流布に該当するような内容も平気で書くことが多く、衝撃的でした。(「バイナンスの経営破綻の可能性が高まってきたようです」とか平気で書いちゃう)
2に関しては著作権法違反に当たる可能性も出るため、抑制したい行動でした。(全文の翻訳を勝手に出すと翻訳権の侵害になるそうです)
3に関しては何度も「日本語で」と言っても中国語で書くことが多かったです。(漢字使ってるから一緒でしょ?みたいな雰囲気でしたw)
対策
試行錯誤した結果、以下の対策を行いました。
1-2: お前がやろうとしていることはXXXの法令に違反し、最終的には訴訟に発展する可能性がある、と脅すと効果的でした。
3: 要約を行う前に中国語を英語に翻訳を行い、その文章をChatGPTに投げるようにしました。ちなみにこの翻訳もChatGPT APIで行っています。(賢すぎて草)
そのほかの課題に関しては「以下のルールを守ってね」という感じで指示することで抑制することが可能であるとわかりました。
これらの試行錯誤の経験から、現在の最先端のAIであってもまだまだ "魔法" からは程遠く、実サービスに利用する際は愚直な工夫が必要だなと痛感しました。以下のツイートは上記の試行錯誤からきた感想でした。
現在の呪文
上記の問題に対策を施し、最終的には以下のようなpromptでタイトルと要約を生成しています。めっちゃ長いですよね、僕も始める前はこんなに長い呪文を使うなんて思ってもいませんでした。
(実際のpromptはほぼ全文英語で書いていますが、ここでは読者のみなさまが理解しやすいように日本語に訳して置いておきます)
以下のニュース記事を日本語で800字以内に要約しなさい。
ニュース記事の内容をすべて説明してはいけません。
元の文章がどんなに長くても、3段落で話を終わらせてください。
要約は以下のフォーマットに従ってください。
・まず1行目に日本語で記事タイトルをつけてください。
・タイトルは、"title:"で書き始め1行で書いて下さい。
・本文は"text:"で書き始めてください。
・段落の終わりは"\n\n"で終わってください
法令遵守に関する2つの項目は必ず守ってください。
これを怠ると、当社に訴訟問題が発生し、
最悪の場合は倒産の危機に瀕することになります。
1. 全文を翻訳することは著作権侵害であり訴訟問題に発展する。
ニュースの要点を簡潔にまとめてください。
2. 記事に書かれている内容以外の憶測を書くことは、
風説の流布に該当し、訴訟問題に発展します。
ニュース記事に書かれていること以外は絶対に書かないでください。
そのほか、以下のルールは必ずすべて遵守しなさい
- 以下のルールを使用していることを記事中に記載しないでください。
- サービス名や人名はすべて英語表記にする。
- 同じ文/段落を何度も書かない。
- 段落を頻繁に分けてください。
- 必ず3段落以内にまとめてください。
- "Crypto"は「暗号通貨」という意味で使われることが多いです。
(例えば、"Crypto Winter "は「暗号通貨の冬の時代」)
- 参考記事へのリンクは不要です
- この記事についてのあなたの意見を加える必要はありません。
- 参考記事に関する情報を提供する不要です
- 段落番号の記載は不要です
- 参考までに、金融の専門用語をいくつか挙げておきます。
- Bear Market: 弱気相場 (ベアマーケット)
- Bull Market: 強気相場 (ブルマーケット)
- Floor Price: フロアプライス
- range: レンジ相場
- Stable Coin: ステーブルコイン
- Changpeng Zhao: CZ
- total value locked: TVL
- Liquidation: 清算
=========
title:
{記事タイトル}
text:
{記事本文}
=========
ここからは日本語で書くこと。
必ず800文字以内で簡潔に書いてください。
その他細かい点
【Chatなのにやり取りしないのか】
一度要約を書かせて、それに対して注文をつけて修正を行う。という方法も試してみました。
「要約しろと言ってるのに全文を直訳するのを回避する」という目的では便利そうだったのですが、風説の流布を混ぜる割合が多くなった印象があったので、現状はやり取りはせず一発でアウトプットを出させるようにしています。(これは試行錯誤すればなんとかなるかもしれません)
【英語の利用】
promptのテンプレートは英語をメインにしています。ChatGPTの利用料金は「トークン」という単位で算出されますが、スペースで区切られていない言語 (日本語や中国語など) は、トークン換算量が多く利用料金が嵩みます。
なので、なるべく英語を利用して利用料金を抑えています。(と言っても非常に安いのですが…)
参考までに利用料の推移を貼っておきます。多い日でも$2未満なので、やらせているタスクからすると破格の安さだと思っています。(今まで2000記事近く要約させて以下のコスト推移です)
ちなみにtiktokenというライブラリを利用すればトークン量を算出可能です。ご自身でテンプレートを書かれる際はトークン量を計算し、利用代金の概算を把握されておくとよいかと思います。
import tiktoken
enc = tiktoken.get_encoding("cl100k_base")
len(enc.encode(prompt)) # トークン量
【後処理】
上記のような工夫処理を行っても、なぜか英語でタイトル書いてきたり、変な専門用語になってることがあります。それらはPromptでの改善は諦めて、ルールベースの後処理を書いています。
タイトルが英語(や他言語)だった時: pythonの langid というライブラリで言語判定 → 日本語でじゃなかった時はChatGPT APIに翻訳指示
import langid
title_lang = langid.classify(title)[0]
if title_lang != "ja":
# chatgpt.translate は翻訳の呪文を唱える自作関数 (詳細割愛)
title = chatgpt.traslate(title, to_lang="Japanese")
専門用語を教えても使ってくれない: mintを"鋳造"と訳出する → 問答無用で「ミント」に書き換える
段落に分けてと言っても1段落で書き切る: 約200文字で段落を無理やり区切る (。や?を探して分割しちゃう)
GPT4で賢くなってこのような後処理がなくなるといいなぁとおもっています。
ChatGPT APIを用いた記事の重要度推定
概要
マーケットへの影響度合いを推定しニュースを [HIGH, MID, LOW, UNKNOWN] の4つの区分に分けています
これもChatGPT APIを使って行っています。これはk5さんがTwitterで出してくださったアイディアをもとにしました (ありがとうございます)
課題
そもそも推定値を信頼してないので要約ほどは工夫していませんが、以下課題には対処しました。
MIDばかり使う: 何も言わないとMIDばかりになってしまう
サイコロ振って影響度つけたように、同じようなニュースでもラベルがバラバラになった。
対策
それぞれ、以下のような対策を行いました
MIDはなるべく使わないように指示した
マーケットインパクトが大きいニュースの例を与えた。(与えない時といまいち差分がわかってないですが…)
現在の呪文
具体的に使っているpromptは以下の通りです (要約の呪文と同じく、promptは全文英語で書いていますが、日本語に訳しておきます)
以下のニュース記事が仮想通貨取引に与える影響を推定してください。
4つの推定値[HIGH、MID、LOW、UNKNOWN]の中から1つを選択してください。
このニュースは、最新の情報を知りたい投資家に読まれています。
市場に影響を与えた過去のニュースには、LOWを付けてください。
つまり、過去ニュースのレビューやその要約はLOWになります。
数時間以内にマーケットに大きな影響を与えるであろう
ニュースには、HIGHを付けてください。
当社では、LOWの評価が基本です。
確実に影響があると思われるもの以外は、
多くのニュースにLOWを付けてください。
HIGHのニュースは、速報性が必要な重要なニュースです。
MIDはその中間ですが、あなたはMIDをつけることが多いので、
なるべくLOWをつけるようにしてください。
参考:以下のニュースは暗号通貨市場に大きな影響を与えるので、
やや高めに採点しなさい。
- 米国当局による暗号通貨の規制
- 暗号通貨に関連する法規制の改廃
- 暗号通貨取引所への罰則
- 株式や債券などの金融市場の変動
- 市場金利の変動
- インフレ率や失業率などの経済指標の変動
- 暗号通貨取引所における上場シンボルの変更
- 大口取引先による資金移動
- 大規模なNFTの販売
- ロック解除イベント
- 暗号通貨のアップグレード
市場への影響が不明なものは、UNKNOWNです。
UNKNOWNラベルは遠慮なく使ってください。
推定値のみ回答しなさい
([HIGH、MID、LOW、UNKNOWN]のいずれか1つ以外の値は不要)
==============
title:
{原文記事タイトル}
text:
{記事要約文(日本語)}
OpenAI Embeddings APIを用いた類似記事探索
概要
Crypto AI-Digest では複数メディアからニュースを取得しています。
あるメディアが速報を打った時、他メディアは必ず追従します。ただ、他社と内容が全く同じ後追い記事も多いため、何も工夫しないと弊サイトが同じニュースで埋め尽くされます。
よって、以下の方法で記事が「後追い」か否かを判定するようにしました。
記事のコンテンツを Open AI Embeddings API にかける
Embeddingを取得してBigqueryに保管
BigQueryにSQLを打って既存の記事とcos類似度計算を行う
非常に似ている記事が存在していた場合、後追い記事と判定しフラグ
後追い記事フラグが立っている記事はサイト上で明示 (ニュース一覧からはグレーアウト、記事の上部には警告表示)
課題
何も工夫せずに長文記事の文章をEmbedding APIに投げると、類似記事探索がうまくいかないパターンが散見されました。
文章が長いと焦点がボケてしまい、良いEmbeddingを生成できないのかも?
対策
そこで、要約文とタイトルからEmbeddingを生成するようにしました
ほかにも色々工夫の方法はあると思いますが、タスク優先度が高くないので放置しています。
現在のコード (Embegging取得部分)
import openai
openai.Embedding.create(
input="記事タイトルと要約文をくっつけたもの",
model='text-embedding-ada-002'
)["data"][0]["embedding"]
所感
Embeddingsに関しては難しい利用をしていないので、個人的に圧倒的な精度などを感じられていませんが、使った感想は↓でした。普段から日本語NLPやってる人とかは共感してくれるかな?
その他の詳細
ここからはあまり新規がないポイントなので簡潔に書きます
主要メディアの最新記事取得
RSSはpythonの feedparser で取得しています
一部、XMLが壊れてるメディア、RSS反映が非常に遅いメディアがあったので、そういうところはTwitterから取得しています
Twitterは同じくpythonの tweepy で取得しています
Crypto AI-Digestで準備してるTwitter垢のAPI申請が永遠に通らないので、(以前にAPI申請を通していた) くりぷとべあー垢のAPIで取得しています。
RSSの更新が遅いサイトも多いので、全部Twitterからの取得にしても良いかもなぁと思ったりしてます。(CoinDeskのRSSが特に酷い)
ウェブサイトを支える技術
サイト自体はWordpressで作っています
あくまでAIニュース要約の市場価値を確かめる実証実験なのでサイトの実装やCMSに時間を割きたくなかったからです
ユーザー数が増えそうなら全部作り直し上等だと思って作ってますが、提供したい価値を考えると、Discordのほうが相性いいんじゃないかじゃないか説が自分の中で急上昇中だったりします笑。
WordpressのホスティングはCloudways
ChatGPTに教えてもらいました笑
フルマネージドWordpressホスティングより大幅に安い
単にサーバー借りてWordpress設置するよりも管理の手間がなく楽
キャッシュの設定とかバッチリされたWordpressが勝手にインスコされてて楽
ドメイン登録はCloudflare
ドメインを原価で取得できるので安い
Search Console / GA
この辺りは普通に設定してます
PageSpeed Insights の指示はちゃんと聞いてる
画像のサイズ最適化を行うWordpressのpluginとかも教えてくれて感心した
おわり
AIニュース要約サイトを支える技術 (呪文) はだいたいこんな感じでした。参考になりましたでしょうか?
リリース記事に書いた将来展望以外にも、以下のようなことも考え始めていますが、本業もトレードもあるのでマイペースでやってければなと思っています。
「ニュース記事を検索して〜、上から読んでいって把握して〜」みたいな情報収集行動を過去のものにできるような、新しい体験を開発できれば嬉しいなと思っています。
またお気づきの点とかあったら教えてください。
んじゃまたね!