ページを自動要約するプラグインを作成してみる
こんにちは。ネクストビートでエンジニアをしている菅野です。
普段は”保育園・幼稚園の『タイヘン』を『カンタン』に”をテーマに保育士バンク!コネクトの開発をしています。
ChatGPTのAPIを使う練習として、開いているWebサイトを自動要約するChromeプラグインを作成してみたので、ご紹介致します。
使用する技術スタックは下記になります。
- Node: v20.5.1
- Python: 3.9.13
- ChatGPT
流れとしては、下記になります。
Nodeで開いているページの情報を取得
↓
Pythonに送り情報を加工
↓
ChatGPTのAPIに送信
では実際に作っていきます!
Chromeプラグインを作成する準備
自作のChromeプラグインを実行できる環境を整えます。
プラグインの作成は非常に簡単で、2ステップで完了します。
はじめに、最小構成のプラグインに必要なファイルを作成します。
適当なディレクトリを作成して、manifest.jsonとmain.jsを作成します。
src
┣ manifest.json
┗ main.js
manifest.jsonには下記のように書いておきます。
{
"name": "AutoSummary",
"version": "1.0.0",
"manifest_version": 2,
"description": "自動要約",
"content_scripts": [{
"matches": ["https://*/*"],
"js": [
"main.js"
]
}]
}
main.jsの中身は適当で大丈夫です。
window.alert('Hello World')
次に、プラグインをChromeに登録していきます。
chrome://extensions にアクセスして、下記の手順で登録します。
右上にあるデベロッパーモードをonにします。
左上にある「パッケージ化されていない…」から先ほどのファイルが置いてあるディレクトリを指定します。
これだけで自作のプラグインを動かすことができます!
Pythonでローカルサーバーの準備
Nodeで取得したデータを受け取る先を用意します。
今回は簡易的に、PythonのBottleを使用してローカルサーバーを作成します。
Bottleは軽量Webフレームワークで、こういった小さいものを作る際に重宝します。
from bottle import *
@post('/')
def index():
return 'ok'
try:
run(host='0.0.0.0', port=8000, reloader=True)
except KeyboardInterrupt:
pass
curl -Xpost http://localhost:8000
などで疎通確認すると ok が返ってきます!
ChatGPTのAPIを使う準備
公式サイトを参考に、APIトークンの取得と、openai のインストールを完了しておきます。
APIに適当な文字列を送信して、疎通確認を行います。
下記のようにPythonで記述して、何かしらの返答がChatGPTから返ってきたら成功です!
import openai
# xxxxxxx に取得したAPIトークンを記載
openai.api_key = 'xxxxxxxxxxxxxxxxxx'
def message(role, text):
return { 'role': role, 'content': text }
system = message('system', """
適当なHTMLファイルから抜き出した文字列を渡すため、概要を抽出して簡潔に内容を日本語で説明をしてください。
""")
# ChatGPTにテキストを送信する
def gpt(text):
response = openai.ChatCompletion.create(
model='gpt-3.5-turbo',
messages=[system] + [message('user', text)]
)
return response['choices'][0]['message']['content']
print(gpt('このページはHTMLのサンプルです。'))
HTMLファイルの加工
適当なWebサイトからそのままダウンロードしたHTMLファイルには、scriptやstyleなどの余分な情報も含まれています。
そのため、それらを省くために、PythonのBeautifulSoupを使って、文字列のみに変換します。
BeautifulSoupは、HTMLやXMLの解析ライブラリです。
スクレイピングする際は重宝します。
from bs4 import BeautifulSoup
# 適当なHTMLファイルを読み込む 後でNodeから送られてきたデータと入れ替える
with open('sample.html', 'r') as f:
html = f.read()
def html_to_text(html):
soup = BeautifulSoup(html, 'html.parser')
return '/n'.join(soup.stripped_strings)
print(html_to_text(html))
タグ内の文字列を改行繋ぎに変換します。
非常にシンプルに行うことができます!
全てを繋げます!
ここまでで全ての準備が完了しました。
細かな修正を加えて、Chrome拡張を完成させましょう!
- Chromeプラグインを整理
localhostにリクエストを投げる処理と、リクエストを送るためのボタンを追加します。
下記を追加した後、Chromeからプラグインの再読み込みを行なって、適当なページにアクセスすると左下に要約ボタンが表示されるかと思います。
const postHTML = async () => {
// ローカルホストにPOSTリクエストを送信
const res = await fetch('http://localhost:8000/', {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
// 開いているページのHTMLを送信
page: document.querySelector('html').innerHTML
})
});
data = await res.text()
return data;
}
// 毎回要約されると面倒なので、要約ボタンを作成
const button = createButton()
buddton.addEventListener('click', () => {
postHTML().then(ret => console.log(ret));
})
document.body.appendChild(button);
function createButton() {
const button = document.createElement('button')
button.textContent = '要約'
// 画面左下に固定
button.style.position = 'fixed'
button.style.bottom = '10px'
button.style.left = '10px'
// add style
button.style.zIndex = '100000'
button.style.bgcolor = 'white'
button.style.padding = '4px'
return button
}
- Python側の処理を繋ぎこむ
indexの中身を下記のように修正します。
中で使用しているメソッドは、上記の準備で作成したものです。
@post('/')
def index():
page_text = html_to_text(request.json['page'])
description = gpt(page_text)
return description
CORSに対応するために、indexの上あたりに下記を追加します。
CORSの対応は下記を参考にさせていただきました。
https://qiita.com/rysk_lunch/items/d7cc7cd8ab5fa1714312
# --- CORSへの対応 https://qiita.com/rysk_lunch/items/d7cc7cd8ab5fa1714312
@hook('after_request')
def enable_cors():
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = '*'
response.headers['Access-Control-Allow-Headers'] = '*'
@route('/', method='OPTIONS')
def response_for_options(**kwargs):
return {}
# --- CORSへの対応ここまで
# index ...
ファイルの全体像は下記になります。
api = 'xxxxxxxxxxxxxx'
# *** 1. Pythonでローカルサーバーの準備
from bottle import *
# --- CORSへの対応 https://qiita.com/rysk_lunch/items/d7cc7cd8ab5fa1714312
# ...
# --- CORSへの対応ここまで
# index ...
# *** 2. ChatGPTのAPIを使う準備
# ...
# *** 3. HTMLファイルの加工
# ...
# run localhost
try:
run(host='0.0.0.0', port=8000, reloader=True)
except KeyboardInterrupt:
pass
完成版をまとめたものが下記GitHubになります。
https://github.com/RkKnn/AutoSummaryPlugin
完了したら python main.py でサーバーを起動させておきましょう。
サーバーの起動を完了した後、要約ボタンを押すと開発者ツールのコンソールログにページの要約が書き出されているかと思います!
お試しで、弊社が運営している保育士バンク!コネクトの職員アプリの機能紹介サイトを要約してみます。
https://kidsna-connect.com/site/feature/staffapp
以上で一連の流れが完了です!
Chromeプラグインを使うと色々できそうな予感が高まります!
最後まで読んでいただき、ありがとうございました。
We are hiring!
本記事をご覧いただき、ネクストビートの技術や組織についてもっと話を聞いてみたいと思われた方、カジュアルにお話しませんか?
・今後のキャリアについて悩んでいる
・記事だけでなく、より詳しい内容について知りたい
・実際に働いている人の声を聴いてみたい
など、まだ転職を決められていない方でも、ネクストビートに少しでもご興味をお持ちいただけましたら、ぜひカジュアルにお話しましょう!
🔽申し込みはこちら
https://hrmos.co/pages/nextbeat/jobs/1000008
また、ネクストビートについてはこちらもご覧ください。