はじめに(動機)
arXivの最新論文、
「気になるけど毎日チェックするのは無理」
「英語読むのがつらい」
という人、多いのではないでしょうか。
自分もその一人で、
- 論文は追いたい
- でも時間がない
- 英語を読む気力もない
という状態だった。
そこで、arXivの最新論文を自動で取得し、要約&翻訳してQiitaに投稿する仕組みを作った。
githubのコードは以下の通り(一応、Codespacesで回すことも可能)
上記をRaspberry Pi 4で実行し、投稿された例が以下の通りである。
何を作ったのか
作ったものを一言で言うと、
「arXiv論文サーベイの自動化パイプライン」
処理の流れはこんな感じ👇
arXiv APIで最新論文データ(サマリなど)取得(カテゴリ指定)
↓
NLM(Natural Language model)でさらに落合陽一フォーマットに要約
↓
要約した項目毎にNLMで翻訳
↓
Markdown生成
↓
Qiita APIで自動投稿
これを週1回くらい回す想定。
技術スタック
- Python 3.12
- LLM :Ollama(軽量モデル)
- Raspberry Pi 4(4GBモデル)
- cron(定期実行)
- arXiv API(論文情報取得)
- Qiita API(投稿用)
制約
- Raspberry Pi 4のような低スペPCで、週1回ほど自動で回すことを想定
(筆者のPCが故障しているため、開発はiPad Pro(2020)からCodespacesを利用) - ChatGPT等のような大規模LLMではなく、ローカルで運用できる小規模NLM
(クラウドとか、LLM APIとかお金が掛かかるもん(T ^ T))
上記を元に、大まかなポイントを解説する。
arXiv 論文の取得
arXiv API を使って、特定カテゴリの論文を取得する。
- 対象カテゴリ:
cs.CV - 期間:直近1週間
- 件数:上位5件
タイトル・著者・abstract は API からそのまま取得可能。
要約・翻訳まわりの工夫
Qiitaで読む前提なので、要約は以下の要約は落合陽一フォーマット構造で出力し、流し読み出来るようにしている。
- この論文は何を解決する?
- 提案手法の概要
- 何が新しい?
- どうやって評価した?
- 議論や課題は?
また、一度に日本語で要約させるのではなく、1.英語で要約&構造化→2.構造毎に翻訳という形でタスクを切り分けることで、モデルからの出力を安定させている。
実装時の課題(辛かった点)と対策
課題1:Raspberry Pi 4のスペックが貧弱で、プロセスが落ちる
Raspberry Pi 4は元々IoTに活用するレベルのため、CPUやメモリが貧弱である。そのため、何かしら負荷が高まるとPi上でのモデル起動が遅くなり、Ollamaがモデルをメモリにロードしきれずrunnner起動待ちが終わらない状態→タイムアウトエラーとなることが多発した。
raise ResponseError(e.response.text, e.response.status_code) from None
ollama._types.ResponseError: timed out waiting for llama runner to start - progress 1.00 - (status code: 500)
対策:warm upメソッドを追加
プログラム起動直後に1回だけ、空生成をいれて、runnerを事前起動しておくことで解消した。
ちなみに解決方法はChatGPTに頼ったが、
『車と同じで、起動直後にいきなりエンジンを全開で回すな!💢』
って怒られた...素直に上手いなと思った...
MODEL = "phi3:mini" # 軽量モデル
def warmup_model():
print("Start warmup models")
try:
res=ollama.generate(
model=MODEL,
prompt=".",
options={"num_predict": 1} #1トークン出力して終了
)
except:
pass
print("Finish warm up models")
通常PCならばスペックが十分に足りているので今回の事象は起こらず、Raspberry Piなどの低スペック特有のエラーといえる。
課題2:メモリ不足(Out of memory)
課題1とも被るが、純粋にRaspberryPiのメモリが4GBしかない(Codespacesだと3.2GB)であるため、モデルがメモリに乗り切らない場合がある。
対策:軽量モデルへの変更 & SWAPファイルサイズを変更
出力結果とトレードオフであるが、そもそもサイズが小さいモデルを使う。
今回は以下のモデルを利用している
- 要約モデル:"phi3:mini" (約1.5GB)
- 翻訳モデル:"qwen2.5:1.5b" (約3GB)
qwen系は日本語につよいらしいので、翻訳タスクに活用したく、いくつかモデルががある中で、上記モデルがRaspberryPiでギリ動かせた。
(x.x:2.5b 以上はout of memoryでダメだった)
ちなみにCodespacesではまだメモリ不足でロードできなかったため、phi3に要約と翻訳タスクどちらも一任している。
また、SWAPメモリサイズを広げる手もある。
あまり大きくすると不安定になる(しかも遅い)ため、どこまでできるか検証していないが、筆者はデフォ100MBから2GBまで領域は広げた。(安定はした気がする)
参考:
課題3:モデルの出力結果に、同じ言葉が繰り返されることがある。
上記でモデルを下げたからか、出力に同じ言葉がすごく繰り返される事象が発生した。怖い...
例:
昔々あるところに、おじいさんとおばあさんが住んでいた。 昔は昔々あるところに、おじいさんとおばあさんが住んでいた。 昔は昔々あるところに、おじいさんとおばあさんが住んでいた。 昔は
対策:temperatureを見直し
元々は出力に一貫性を持たせるハイパラと考えていたため、出力にブレが無いよう0や0.1の値を設定していた。
しかし、値が0や近い値だとGreedy Search(貪欲法)の状態となり、毎回最大の条件付き確率の単語のみを取ってくるという状況となる。
つまり、AIからすると同じ言葉を連発した方がスコアが高い(と思っている)状態になっている。
(小さいモデルほど顕著に感じる)
一貫性とトレードオフになるが、temperatureを0.2〜0.3に見直ししたところ、上記事象は無くなった。
(追記:まだ発生しているので、少なくなったが正しいかも...要解決方法を検討)
res = ollama.generate(
# model=MODEL_TRANSLATE,
model = MODEL,
prompt =prompt,
stream =True,
options ={"temperature": 0.2, # 0.0→0.2
"num_predict":900 # 同トークン連続生成時の安全装置
}
)
result = progress_display(res)
return result
詳細は以下の記事を読むのが早い
未解決:テキストが翻訳されずに出力されることがある。
そのままの意。AI君が翻訳をサボることがある。
対策?プロンプトを見直し
プロンプト内に"STRIC RULES"(厳格なルール)という蘭を設け、“日本語だけでちゃんと出力してね”と記載しているがはたして...
def translate_text_ja(text: str) -> str:
if not text.strip():
return ""
prompt = f"""
You are a translation engine.
Your task is to translate English into Japanese.
STRICT RULES:
- Output Japanese ONLY
- Do NOT summarize
- Do NOT explain
- Do NOT output JSON
- Do NOT keep English words
TEXT:
{text}
"""
res = ollama.generate(
model = MODEL, # Codespaces等の軽量環境向けに軽量モデルを使用
prompt =prompt,
stream =True,
options ={"temperature": 0.2,
"num_predict":900
}
)
result = progress_display(res)
return result
感じたこと
ChatGPT/Copilot/Gemini等のLLMは、プロンプトに誤字脱字がある状態で投稿しても、いい感じにモデルが汲み取って出力してくれるため、今回のような簡単なタスクであれば、プロンプトエンジニアリングは不要と囁かれている(気がする)。
一方、今回のような小さいモデルでは、簡単なタスクであっても、プロンプトやハイパラ調整をしっかりやらないと、そもそも意図しない生成結果(同じトークンの連続生成、翻訳サボリ)となるため、プロンプトエンジニアリングは不要とは言い難い。
個人的には、LLMもエンドユーザーコンピューティング(サーバに投げず、手元で処理)の時代が来てると考えているので、小さくてハイスペックモデルが登場するまでは、プロンプトエンジニアリングはまだ必要かなと思った。
まとめ
今回は、arXivの最新論文を自動で取得し、要約&翻訳してQiitaに投稿する仕組みをRaspberry Pi環境で動かせるように作った。
これによりollamaの使い方や、Raspberry Piなどの低スペック環境で発生する課題とその解決策をいくつか実装した。
今後、毎週日曜などにこの仕組みを活用した論文要約記事を本チャンネルで投稿するため、同じように論文を追いかけたいがダルいと考えている人はチェックしてもらえればと考える。
以上