Ubuntu日和

【第89回】インターネット老人会御用達のRSSリーダーをLM Studio+Qwenで生成してみた

今回生成したRSSリーダー

そうだ。RSSリーダー、作ろう

 プッシュ型、プル型なんてもはや死語のような気もするが、伝えたい相手に伝えたいことを伝えるということは今も昔も難しい。伝えたいことがブログという形式でまとまっているのであれば、RSSは未だに有効である。問題は、このWikipediaにもあるようにRSSは今となっては古い技術で、サポートしているアプリケーションがあまり多くない。Ubuntuならまだいくつか著名なパッケージがあるが、Windowsは窓の杜を見てもなかなかに厳しい。

 では、Windowsで動くRSSリーダーをLLMで生成させればいいのではないか? と筆者は考えた。Pythonで開発させれば、筆者も多少は読み書きできる上、Ubuntuで開発してWindowsで動作させるということも簡単にできる。

 そんな最初のWindows向けRSSリーダーの生成はこれでうまくいったのだが、続けてこれとは別の自分用RSSリーダーを生成させることにした。そして5月の連休中に原稿を書きながら別のPCで生成させていたら、生成している様子を記事にしてほしいという劉デスクからの依頼があり、本稿の執筆を決意した次第である。

 しかし、筆者のLLMに開発させた様子をそのまま記事にすると短期連載規模の記事になってしまうのと、かなり使い勝手が悪いので、LM Studioをベースにして、1回の記事で済ませられ例として、もう1つRSSリーダーを新たに生成してみることにした。

 「LLMで何かのプログラムを書かせたい」と思うことはあるものの、「実際に何を作らせればいいのか」は難しいところ。その点、RSSリーダーであれば規格に沿ったものを表示させるだけなのでゴールが見えやすい。

 これをきっかけに、さまざまな独自アプリケーションを生成してもらえれば幸いである。

方針

 LLMでRSSリーダーを作成するにあたり、次の方針を掲げることとした。

  • 誰でも容易に実行できるよう、LM Studioを使用する
  • 最上位のハードウェアでなくても、それなりに快適に生成できる
  • RSSリーダーという特性上、単独でインターネットに接続できる必要があるので、何らかの方策を取る
  • いちいちソースコードをエディタにコピペして保存するのが面倒なので、ローカルのファイルに直接アクセスできるようにする

 いわゆるコーディングエージェントなどは使用せず、あくまでLM Studioで完結させるのが今回の主旨。ツールの使い方を紹介するのではなく、RSSリーダーを作成するのが主眼であり、また実際にとっつきやすいので、このような方針を採った。

ハードウェアとドライバ、ソフトウェア環境構築

 今回使用するハードウェアは次の通りだ。

メーカー型番備考
CPUAMDRyzen 7 7950X
マザーボードMSIMPG B850I EDGE TI WIFI
メモリCrucialCP2K32G56C46U564GB
ビデオカードMSIGeForce RTX 5060 Ti 16G VENTUS 2X OC PLUS
SSDCFDCSSD-S6L512MGAX512GB
ホットスワップケースSilverStoneSST-FS202B
CPUクーラーDeepCoolAK620
ケースファンARCTICP12 MAX実質CPUファンとして使用
電源ユニット玄人志向KRPW-GA750W/90+
PCケースSilverStoneSUGO 14

 Ubuntuのバージョンは24.04 LTSでも26.04 LTSでも構わないが、今回は後者とする。NVIDIAのプロプライエタリなドライバをインストールされていることを確認しよう。第88回でも紹介したように「追加のドライバ」はインストールされなくなったので、ここではコマンドで確認する方法を紹介する。

 まずは次のコマンドを実行する。

$ ubuntu-drivers
ubuntu-driversコマンドを実行したところ

 この時点で何かしらのドライバがインストールされている場合はそれでいい。

 もしインストールされていなければ、次のコマンドを実行してインストールできるドライバのバージョンを確認する。

$ ubuntu-drivers list
ubuntu-drivers listコマンドを実行したところ

 GeForce RTX 50シリーズは「-open」がついている最も新しいもの、GeForce RTX 30シリーズは数字で終わっているものの最も新しいバージョンにするといいと思われるが、今回後者の動作確認は行なっていない。

 インストールするバージョンを決めたら、次のコマンドを実行する。

$ sudo ubuntu-drivers install (インストールするバージョン)

 インストール完了後、再起動して再ログインする。

LM Studioのインストール

 LM Studioの実行バイナリは、AppImage形式とDebianパッケージで公開されているが、今回はダウンロードからDebianパッケージ(.deb)をダウンロードしてインストールする。今回試したバージョンは0.4.13だ。

 インストール方法は何でもいい。26.04 LTSではダウンロードしたパッケージをダブルクリックすると「アプリセンター」が起動して、「インストール」をクリックするとインストールできる。

もちろんコマンドでもいいが、「アプリセンター」経由でもインストールできる

SearXNG

 LM StudioからWeb検索できるようにするため、SearXNGを設定する。

 SearXNGはDockerのコンテナで動作するため、Dockerを使用していない場合は次のコマンドを実行してインストールする。

$ sudo apt install docker.io docker-compose-v2 curl
$ sudo usermod -aG docker $USER

 ここで再起動する。

 再ログイン後、SearXNGのコンテナを起動する。

$ mkdir -p ./searxng/core-config/
$ cd ./searxng/
$ curl -fsSL -O https://raw.githubusercontent.com/searxng/searxng/master/container/docker-compose.yml \
    -O https://raw.githubusercontent.com/searxng/searxng/master/container/.env.example
$ cp -i .env.example .env

 SearXNGはデフォルトではポート8080で動作する。これはよく使われているポートであり、かつLM StudioのSearXNGプラグインではポート8081がデフォルトになっているため、.envを開き最終行を編集する。もちろん8081が使用中の場合は、ほかのものに変更する。

SearXNGで使用するポートはデフォルトで8081になっている

 続けて次のコマンドを実行し、いったんDockerイメージとして動作させ、すぐに終了させる。

docker compose up -d
docker compose down

 すると、先ほどまでなかった「~/searxng/core-config/settings.yml」が生成される。LM Studioから使用するためには、このファイルの設定を変更する必要がある。編集するためには管理者権限が必要なので、sudo editorなどのコマンドでファイルを開く。

 85行目付近がこうなっている。

  formats:
    - html

 ここに1行追加してこのようにする。すなわちJSONでのアクセスも許容するということだ。

  formats:
    - html
    - json

 終わったら、Dockerイメージ起動する。

$ docker compose up -d

LM Studioでの設定

 ようやくLM Studioを起動するところまでたどり着いた。

 LM Studioの初回起動のウィザードは特に気にするところはないものの、「Developer Mode」はオンにしておいたほうがいい。

Developer Modeはオンにしておく

 続けて左下のApp Settingsをクリックし、「General」をクリックして「Language」を「日本語」にする。

言語は日本語にする

 さらに「Model Defaults」を開き、「Default Context Length」を「65535」にしておく。

コンテキスト長は、ひとまず65535にしておく。今回の分であればこの半分でも構わないが

 設定を閉じ、左側のバーにある上から4つ目(サイドバーを閉じるアイコンを含めると上から5つ目)をクリックする。ここではモデルの検索とインストールができる。今回使用するのは「Qwen 3.6 35B A3B」なので、「Download」をクリックしてダウンロードする。22GBくらいあるので、回線によっては時間がかかる。

今回使用するモデルはQwen 3.6 35B A3B

 さて、現時点でLM StudioのUIにはプラグインを管理する機能がないので勘違いしがちだが、実はプラグイン機能が存在している。今回はファイルシステムへのアクセスを実現するプラグイン「taderich73/filesystem-access」と、Web検索を行なうプラグイン「rzk/searxng-search」を使う。それぞれのページから、「Run in LM Studio」をクリックするとWebブラウザからLM Studioが呼び出され、さらに「Download」をクリックするとインストールできる。

プラグインのページのDownloadをクリックするとLM Studioでダイアログが表示されるのでDownloadをクリックする

 SearXNGに関しては特に設定の変更は不要だが、ポートを8081ではないものにしている場合は、ここで変更する。filesystem-accessはローカルのフォルダを指定する必要がある。今回は例として「/home/ikuya/Downloads/source」とする。

右ペインでプラグインの設定が完了したところ

RSSリーダーの生成

 RSSリーダーの生成を実施するが、いくつか注意点がある。例として最初に筆者のブログのRSSを利用する。理由としてはWordpressが出力するのが一般的なRSS(RSS 2.0形式)だからなのだが、注意点としては、時刻にタイムゾーンの情報が含まれない点が挙げられる。よって、タイムゾーンの情報がない場合は時差は考慮せず、タイムゾーンの情報がある場合のみ時差を考慮する、というプロンプトを用意しなければならない。ちなみにPC Watchが出力するRSSにはこのような問題はない。

 最初にモデルを読み込むが、デフォルトの設定では少しGPUの負荷が軽すぎるので、GPUオフロードの値を調整する。Altキーを押しながらモデルをクリックすると値の調整ができるので、Estimated Memory Usageを見ながらGPUオフロードの値を調整する。今回は20から25まで増やすことができた。

GPUオフロードを25まで増やした

 コンテキスト長は65,535にしてあるが、徹底的に作り込むとなったらこれでは少なくなる。しかし、コンテキストはいきなり多くを取るのではなく、必要になったら少しずつ増やしていき、GPUオフロードの値を可能な限り高くするのが、待たずに処理ができるコツだ。

 モデルの読み込み後、左側の歯車アイコンをクリックする。「CPUスレッドプールサイズ」は割り当てるCPUのスレッド数なので、今回のように16コア32スレッドのCPUを使用している場合は、値を直接入力して32を入力する。16コアまでであればスライダーの調整だけで済む。

12スレッド以上あるCPUを使用している場合はスレッドプールサイズを増やしたほうがいい

 実際に入力するプロンプトは次の通りだ。

tkinterを使用し、https://ikuya.info/wp/feed/から取得したフィードのタイトルと更新時間を表示し、フィードをダブルクリックするとWebブラウザが開いてその記事を表示するプログラムを作成してください。タイトルと更新日時は分けて2列で表示するようにして下さい。Pythonのバージョンは3.12以降にして下さい。コメントやメニューの言語は日本語にして下さい。ただし取得したRSSに含まれるブログのタイトルは原文のままとして下さい。

個々のエントリーの上部にブログのタイトルを表示するスペースを用意して下さい。ブログのタイトルはRSSに含まれているので、それを使用して下さい。

更新時間はJSTでYYYY/MM/DD HH:MM:SSで表示するように変更して下さい。特例でタイムゾーンが+0000となっている場合は時差を考慮せず、書式だけ変えて表示するようにして下さい。きちんとタイムゾーンが設定されている場合にはそれに従って下さい。

使用するライブラリは可能な限りPython標準ライブラリに限定して下さい。GUIライブラリはあとから容易に変更できるよう、関数で抽象化して下さい。必要な情報はWeb検索して取得して下さい。

生成されるプログラムは可能な限り1つのファイルにして下さい。そして適切な名前をつけて下さい。

 見ての通り、記事にするためにあたってプロンプトはかなり調整している。3分クッキングで半完成品を提示する所業だがご容赦いただきたい。

 時々「Proceed Ctrl + Enter」というのが表示されるが、これはプラグインの機能を使用するかどうかを尋ねているところだ。今回の場合はWeb検索とファイルの保存だが、指示通り「Proceed Ctrl + Enter」をクリックすればいい。

プラグインを使用する際の確認

 自動的に保存までするかどうかは時と場合によるが、保存した場合はそれを起動する。プロンプトにもあるようにPython標準ライブラリを使用しているので、あとはGUIのtkinterをインストールすれば起動する。パッケージ名は「python3-tk」だ。コマンドにすると次のようになる。

$ cd ~/Downloads/source
$ sudo apt install python3-tk
$ python3 ./rss_reader.py

 Pythonはインタープリタ型の言語なので、Pythonをインストールした環境であれば、出力されたソースコードをそのまま実行できる。ポイントは(Ubuntuでは)Pythonコマンドが「python」ではなく「python3」のところであろうか。

 あとは見た目が気に入るものが生成されるまで繰り返す。今回は一発でこのUIになったので、これでよしとする。場合によってはタイトルと更新時刻の左右が逆になっていたこともあった。

最初にできた、基準となるRSSリーダー

 続けてPC WatchのRSSも取得できるように次のプロンプトを入力する。

https://pc.watch.impress.co.jp/data/rss/1.0/pcw/feed.rdf のフィードを確認し、正しく表示できるようにプログラムを改変し、ブログのタイトルをプルダウンメニューにして表示を切り替えられるようにして下さい

 こちらのRSSの形式(RDF)はちょっと難しいらしく、一発で表示できるものが作られることはなかった。何度か生成させる必要がある。単純にやり直させるでもいいし、端末にエラーが表示される場合はそれを入力してもいい。

うまく表示できない例
うまくいかないときに入力するプロンプト例

 そして何度かやり直していけば、いずれ正しく表示できるようになるだろう。

正しく表示できるようになった

 何度も処理を繰り返し終了しないという事態に見舞われる場合には、容赦なく入力欄の右下にある停止ボタンをクリックして処理を止め、やり直すようにしよう。Qwen系のモデルを使用するとしばしば起こることだ。

拡張のアイデア

 RSSリーダー生成手順の紹介するのはここまででおしまいだが、まだまだやりたいことはある。拡張のアイデアをいくつか紹介するので、手元でいろいろと試してみてほしい。

テーマをもう少しUbuntuに沿ったものにする

 先ほどのスクリーンショットを見ての通り、Ubuntuのアプリケーションとしては違和感がある。これは、まったく何のテーマも適用していないからで、ttkthemesを使用するようにすれば親和性が上がる。

ttkthemesの適用例

異なるGUIライブラリを使用する

 今回はPython標準のライブラリということでtkinterを採用した。WindowsでもUbuntuでも全く同一のソースコードで動作するというメリットはあるが、Ubuntuでしか使わないということであれば、特にtkinterにこだわる必要はない。UbuntuだとPyGObjectを採用することが多いので、これにするのもいいだろう。

 手元で試した限りでは、直接PyGObjectを使用したコードを生成させるとうまくいかないことが多く、一旦tkinterを経由するとうまく動くことが多かった。今回は特にプロンプトで抽象化しているので、高い確率でうまくいくだろう。

PyGObjectに変更した例

 通知トレイにアイコンを表示したい場合、tkinterだとかなり難しいが、PyGObjectだとtkinterほどは難しくないので、起動時に通知トレイにアイコンを表示したい場合はPyGObjectに変更するといいだろう。

 もちろんほかにもGUIライブラリはあるので、そちらにするのもいい。PyQt6などが考えられる。

設定メニューをつける

 現状はRSSを使いするためにコードを生成する必要があるのでやや面倒だ。よってRSSの管理をするUIをつけるのは理にかなっている。URLとタイトルは別途JSON形式のファイルで管理させるのがいい。

 RSSはOPMLという形式でやり取りされることが多いため、インポート/エクスポート機能をつけるのもオススメだ。

設定を追加した例

一定時間に更新

 現在のRSSリーダーは起動時に最新情報を取得しており、自動更新する機能はないので、これを付けるのもいいだろう。一定の時間以内更新があった場合は色を変えて分かりやすくするのもいい。

実行形式にする

 Pythonスクリプトは動作させるのにPythonの実行環境が必要だが、PyInstallerを使用すれば、必要なライブラリを含んだ実行形式ができる。いろんな環境で動作させる必要がある場合には、採用を検討したい。