ラズパイ5で日本語入力

vimで日本語入力できないなと思ったら、そもそも今までラズパイで日本語入力使ったことがなかったのだ、

ツールとしてはfcitx-mozcを使うと日本語は入力できるようにはなる、ただし使い勝手はイマイチ感あるから、Macのエディタで作成したものを貼り付けるのが実用的だな、と思ったから非常手段かもしれない

 

admin

 

 

Difyをローカルで動かす(さわり)

ローカルで動かせて、かつカスタマイズが簡単(ノーコードで実現可能)なLLM(モデルプロバイダを設定)が使えるプラットホームです、Webページのこのメッセージが全てかもしれません、一番特徴的なのはRAGエンジンじゃないかと思いますね

============

DifyはオープンソースのLLMアプリ開発プラットフォームです。RAGエンジンを使用して、エージェントから複雑なAIワークフローまでLLMアプリを編成します。

============

<インストール>

・ターゲット:M4 MacBook Pro 14

・Docker :Engine: 28.0.1/Compose: v2.33.1-desktop.1

わざわざカスタムインストの意味はないから、Docker使って素直にインストします、以下にはRancher Desktopでインスト時のメモも残ってますが、ともかく4行のコマンド実行でDockerで動くようになります

% git clone https://github.com/langgenius/dify.git
% cd dify/docker
% cp .env.example .env	# 環境変数のコピー

# Rancher Desktopの場合には、
# Docker-compose.yamlの修正、ブラウザポートの重複回避のためにポート番号を変更(8888に)、661行目でした(@2015/3/16)

      - '${EXPOSE_NGINX_PORT:-8888}:${NGINX_PORT:-80}'

# 注)Rancher Desktopで再インストするとアクセスできない(8888開かない?)

% docker compose up -d
# デタッチモードでバックグランドで起動させる

Dify自体にLLM機能はなく外部サービスを利用する形態なので、モデルプロバイダーはGeminiを設定しています

DockerとRancher  Desktop両方を動かす時の切り替え方法と再インストール他のコマンド

% docker compose up --build
# imageの再ビルドを行う

% docker compose down
# containerを停止すると共に削除する

% docker compose down --rmi all
# これはimageを削除する

% docker compose stop(コンテナ停止)、start(コンテナ起動)


# Dockerの切り替え(Baker link. Env用にrancher desktopを優先させる)

% docker context use rancher-desktop

% docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT                                       ERROR
default             Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                           
desktop-linux       Docker Desktop                            unix:///Users/usamiryuuichi/.docker/run/docker.sock   
rancher-desktop *   Rancher Desktop moby context              unix:///Users/usamiryuuichi/.rd/docker.sock           


% docker context use desktop-linux 	# change to Docker

インストールから基本的な操作(応答を変化させるオーケストレーションとか)は以下のリンクで、

https://weel.co.jp/media/dify-local/

 

<Pythonから使う>

RAGはとりあえず置いといて、Pythonからの使い方

クラウドのDify使う時には、

https://zenn.dev/fa18kouki/articles/579ef29527a5d9

が参考になりますが、これをローカルに置き換えてます

APIキーは、以下の「APIアクセス」から取得します、また具体的なAPIの使い方ドキュメントも含まれます

import requests
import json
from typing import Dict

# Dify APIの認証キー
API_KEY = 'your API key'  # 取得したAPIキーに置き換えてください
# Dify APIのベースURL(ポート番号を含む)
BASE_URL = 'http://localhost/v1/chat-messages'

def get_dify_response(query: str, user: str) -> str:
    headers = {
        'Authorization': f'Bearer {API_KEY}',
        'Content-Type': 'application/json'
    }

    data: Dict[str, any] = {
        "inputs": {},
        "query": query,
        "response_mode": "streaming",
        "conversation_id": "",
        "user": user,
        "files": [
            {
                "type": "image",
                "transfer_method": "remote_url",
                "url": "https://cloud.dify.ai/logo/logo-site.png"
            }
        ]
    }

    try:
        response = requests.post(BASE_URL, headers=headers, json=data, stream=True)
        response.raise_for_status()

        # ここでエンコーディングを明示的に指定
        response.encoding = 'utf-8'

        full_response = ""
        for line in response.iter_lines():
            if line:
                decoded_line = line.decode('utf-8')
                if decoded_line.startswith("data: "):
                    json_data = json.loads(decoded_line[6:])
                    if json_data.get('event') == 'message':
                        raw_answer = json_data.get('answer', '')

                        # Unicodeエスケープのデコードを削除(不要)
                        print(raw_answer, end='', flush=True)
                        full_response += raw_answer

        print()
        return full_response
    except requests.RequestException as e:
        print(f"リクエストエラー: {e}")
        return str(e)
    except json.JSONDecodeError as e:
        print(f"JSON解析エラー: {e}")
        return "JSONの解析に失敗しました"
    except Exception as e:
        print(f"予期せぬエラー: {e}")
        return str(e)

def main():
    query = "Difyでできることは?"
    user = "user0"

    print("Difyへのクエリ:", query)
    answer = get_dify_response(query, user)
    print("\nDifyからの完全な応答:")
    print(answer)

if __name__ == "__main__":
    main()

エンドポイント(サービスの種類)はいくつかありますが、ここではBASE_URL = 'http://localhost/v1/chat-messages'を使っています

レスポンスは、以下のような内容で返ってきます

Difyへのクエリ: Difyでできることは?
Difyって、すごい魔法のツールなんだ!  

Difyは、色々なことができるよ。たとえば、

* **お話を書く**  
  Difyに「お姫様とドラゴンのお話を作って」ってお願いすると、面白いお話を作ってくれるんだ!  
* **絵を描く**  
  Difyに「虹色の猫の絵を描いて」ってお願いすると、カラフルな猫の絵を描いてくれるよ!
* **音楽を作る**  
  Difyに「楽しい音楽を作って」ってお願いすると、リズムの良い音楽を作ってくれるんだ!  
* **ゲームを作る**  
  Difyに「宝探しゲームを作って」ってお願いすると、楽しい宝探しゲームを作ってくれるよ!

Difyは、まだ成長中だけど、たくさんのことができるようになるんだって!  
Difyをもっと知りたい?  もっと詳しいことを教えてあげるよ!  
他にどんなことができるか、聞いてみてね! 


Difyからの完全な応答:
Difyって、すごい魔法のツールなんだ!  

Difyは、色々なことができるよ。たとえば、

* **お話を書く**  
  Difyに「お姫様とドラゴンのお話を作って」ってお願いすると、面白いお話を作ってくれるんだ!  
* **絵を描く**  
  Difyに「虹色の猫の絵を描いて」ってお願いすると、カラフルな猫の絵を描いてくれるよ!
* **音楽を作る**  
  Difyに「楽しい音楽を作って」ってお願いすると、リズムの良い音楽を作ってくれるんだ!  
* **ゲームを作る**  
  Difyに「宝探しゲームを作って」ってお願いすると、楽しい宝探しゲームを作ってくれるよ!

Difyは、まだ成長中だけど、たくさんのことができるようになるんだって!  
Difyをもっと知りたい?  もっと詳しいことを教えてあげるよ!  
他にどんなことができるか、聞いてみてね! 

モデルプロバイダーからのレスポンスをオーケストレーション設定で「子供に話すような回答」と設定しているので、Dify内で加工されたレスポンスになっています

 

admin

 

Docker, Podman and Rancher Desktop

いつしかコンテナも三種類インスト、

Dockerも去年一時期Macでうまく動かない時期に不完全にアンインストールしたものを、ちゃんと関連ディレクトリ削除して再度インストールしたから

それぞれの目的は、

Docker:個人使用は無償なので再度インスト、大概のアプリは純正Dockerを前提にしているし

Podman:Rustのcross使ってラズパイ用のクロスコンパイルのためにroot権限じゃなくとも使えるコンテナでインスト、Podmanはバックグランドで動作しないのでpodman machine startのようcliで起動しないといけない

Rancher Desktop:Baker Link. EnvでラズパイpicoでRust動かすためのクロス環境用にインスト、Dockerをインストするとデフォルトのコンテナ指定をしないとBaker Link. Envからコンテナを呼び出せなくなります

% docker context use rancher-desktop

でコンテナを明に指定します、dockerに戻すには、

% docker context use desktop-linux 

コンテクストの見え方は、

% docker context ls
desktop-linux 
rancher-desktop * 

(関連部分だけ抜き出し)

ここで(*)が付加されているのが現在選択されているコンテクスト(コンテナ)

 

コンテナ三つ動かすとメモリの占有状況はこんな感じでトップスリーはコンテナになってます(vfkitはPodman、limactlはRancher Desktopが使っています)

コンテナではVMと違いある程度のリソース競合は起こるだろうから、同時立ち上げは望ましくはないだろうとは思う

 

admin

Mac2台の売却(1台はTrade in)

MacBookは相対的に下取り価格は高めなのだろうけど、それでもやはり古くなれば価格は落ちていく

 

今回の2台の買取価格、

① Intel MacBook Pro 2019モデル(購入は2020年夏、16GB、SSD:512GB、USキーボード

-> 4.2万円(Apple Trade inで、Intel MacのOSアップデートもそろそろ怪しいしね)

 

② M1 MacBook Air late 2020(購入は2022年夏、16GB、SSD:512GB、USキーボード

-> 7.1万円(ネットで調べて評判はよくなかったけど、パソコン工房の土日10%アップで依頼)

M4 MacBook Proの三分の一ぐらいは補填の計算になります、まあ16GB時代は使い方にもよるけど、個人的には終わってます

 

admin

比較のついでにラズパイzeroの実行速度も測定してみた

ラズパイzeroは段違いに遅いことはわかっていたけれども、どれだけ遅いのかをみてみた、ソースコードは共通ですがzeroはシングルコアなのでマルチスレッドの数値はなし

コンパイルもzeroでは実質的にはできないからMac上でクロスでバイナリ作成してます

比較してみると、他に比べて絶望的に遅いことがわかります、まあアプリケーションによって使い分けるわけではありますが

 

admin

ラズパイ5とApple Siliconの速度比較

Apple Siliconとの比較でラズパイ5で実行時間も測定してみた、Apple Siliconの数値は以下のリンクから

https://isehara-3lv.sakura.ne.jp/blog/2025/03/10/m1-vs-m4の性能比較(非常に限定的な場合で)/

<ラズパイ5の実行結果>

ラズパイ5のRustでの実行速度

<シングルスレッド>

pi@rasp5:~/rust/prime_single_thread/src $ cargo run --release
    Finished `release` profile [optimized] target(s) in 0.00s
     Running `/home/pi/rust/prime_single_thread/target/release/prime_single_thread`
2から1000000までの素数:
Elapsed time: 81.208438ms
number of primes: 78498

<マルチスレッド>

pi@rasp5:~/rust/prime/src $ cargo run --release
    Finished `release` profile [optimized] target(s) in 0.01s
     Running `/home/pi/rust/prime/target/release/prime`
2から1000000までの素数:
Elapsed time: 25.209907ms
number of primes: 78498

<Apple siliconとの比較>

予想外にラズパイ5が早いというべきか、Mxが遅いというべきか、概ねM1 Macとラズパイzeroだと概ね速度差は60倍ぐらいあったのが、ラズパイ5だとその差は3倍ぐらい、ということはラズパイzeroと5で実行速度は20倍ぐらいの差があるということになるから、ちょうど2018年ごろのMacBook Air(Intel CPU)の速度ぐらいは出ているということになるだろう、体感速度というのはCPU速度だけではなくファイルアクセスも重要だからSDカードで動かしているラズパイ5はかなりハンディはあるだろう

ラズパイzeroでRustやGolangのコンパイルは実用的な速度で実行できないけど、ラズパイ5なら問題なくできるから、言い換えれば一桁以上の性能差があるということだから、体感というのは概ね当たっているようだ

P.S. 2025/3/12

ラズパイzeroの実行時間は次の記事で追加、予想のさらに下でした

 

admin

M1 vs M4の性能比較(非常に限定的な場合で)

M1 MacBook AirとM4 MacBook Pro 14inchの性能差ということですが、以下のリンクは素数計算をPerplexityでRustコード発生させて実行した時のもの

https://isehara-3lv.sakura.ne.jp/blog/2024/10/23/生成a-igeminiでコード生成rust/

<Geminiで生成したシングルスレッド版 : release mode>
2から1000000までの素数:
Elapsed time: 37.51125ms

<Geminiで生成したマルチスレッド版 : release mode>
2から1000000までの素数:
Elapsed time: 7.397958ms

以上はM1 MacBook Airでの結果


M4 MacBook Proで実行してみると(実行ごとにばらつくから5回実行してベストタイム)

<シングルスレッド版>
2から1000000までの素数:
Elapsed time: 27.473ms(1.36倍)

<マルチスレッド版>
2から1000000までの素数:
Elapsed time: 6.449875ms(1.15倍)

シングルスレッド(マルチコア対応)はそんなものかと思うけど、マルチコア対応のコードの実行速度はイマイチ、考えられる可能性は計算量に比較してオーバーヘッドが大きいせいじゃ無いかと思う

FusionやiMovieなどの立ち上げや書き出しは、はっきりわかるほどの差があるからね、非常に限定的なアプリではありますが、体感ではシングルスレッドの時の速度差ということになります、自分の使い方ではCPU速度よりもメモリとSSDの絶対量確保の方が重要

 

admin

M4 MacBook Pro 14ファーストインプ

M1 MacBook Airのリソース不足(メモリ16GB/SSD 512GB)で買い換えたM4 MacBook Pro 14(メモリ32GBにアップ、SSDは1TB、キーボードはUSモデル)が昨日到着したのでその感想、購入している間にM4 MacBook Airも発表されましたが、まあ欲しい時に買うのがベスト

個人的にAirに比較したProのアドバンテージは、

① Youtubeで音楽流してもスピーカーの音はかなりまとも、Airは音がしょぼい

② 拡張性:Appleの微妙なヒエラルキーでもありますが、HDMIとSDカードスロットはポートレプリケータなくても外出先で使えるのは便利

③ LCD表示品質:Airのような表示のケバケバしさはなくて自然な色合いと感じます、狭ベゼルでもあるのでスペースも有効活用

M4 Pro以上のチップは値段と性能のバランスから考えたら無い選択、使い方からしてもM4で良いかな

<移行>

同じApple siliconなのでM1 MacBook Airからそのままデータ移行、メールアカウントやアプリの認証だけは再設定必要

バックアップ(timemachine)はAirを引き継いでそのまま何の設定もなしにできた、ただしAirの最終状態からの差分ではなくてAirを初回にバックアップしてからの差分をバックアップしたようです

<使用感>

① ブラウザ(Safari, Chorme)、VScode、コンテナ(Podman, Rancher Desktop)立ち上げた状態で、LLM(ollamaの80億モデル)動かした時にメモリ使用量は26GBぐらいで頭打ち、M1 Macではかなりスワップが発生してイエローマークだったけど、今のところ32GBあれば何とかなる

② 速度的にはアプリの立ち上げは高速化されている、特にAutodesk Fusionなどを立ち上げるとよくわかる

③ キーボードのタッチ感(音)が説明は難しいけど微妙に異なるんだよね、箱(筐体)が違うせいかも知れない

④ 電池の充電をきっちり80%で打ち切るような設定になっている、M1 Macまでは充電抑止ロジックがよく分からなかったけれど

⑤ M4からでも無いだろうけど、IPhone15は既に切り替わり、ACアダプタのケーブルが柔軟性があるものに変わっているいるから取り回しが楽になっているのとMagSafeは安全面からもおすすめだと思う

普通にM1 Macの資源引き継いで使えるというありきたりの感想、まだファンは一度も回ってないから、ファンが付いていることすら気づいてない

 

admin

目玉モデルを作る(ラズパイ5+カメラ)

視覚相当機能はラズパイ5の標準カメラで実現しますが、ロボットなので目玉風に格納したい

目玉の中心部にカメラ、カメラを覆うような形でサーボモーターで瞼を動かしてみる

<瞼側>

<眼球側>

サーボモーターを取り付け部分はそのままだと造形できないので、仮にサポートを立てて、後でハンダゴテで溶かしてニッパーで切り落とし、最初からニッパーだとストレスで割れます

 

<カメラ取り付け>

<カメラの外観>

<可動部分>

<動作の動画>

マイムービー – SD 480p

カメラからの画像をどう扱うかはこれから、YOLOとか有力だと思うけど

 

<サーボモーター駆動のコード>

PWM機能はgpiodにないのでソフトでPWM作成

import gpiod
import time

CHIP = 'gpiochip4'  # Raspberry Pi 5では'gpiochip4'を使用
PIN = 18  

chip = gpiod.Chip(CHIP)
line = chip.get_line(PIN)
line.request(consumer="Servo", type=gpiod.LINE_REQ_DIR_OUT)

def set_servo_angle(angle):
    duty_cycle = (angle / 18) + 2.5
    pulse_width = duty_cycle / 100 * 20000  # 20ms周期

    line.set_value(1)
    time.sleep(pulse_width / 1000000)
    line.set_value(0)
    time.sleep((20000 - pulse_width) / 1000000)

try:
    while True:
        for angle in range(80,141, 5):
            for _ in range(10):  # 各角度でn回パルスを送信
                set_servo_angle(angle)
            time.sleep(0.1)
except KeyboardInterrupt:
    pass
finally:
    line.release()

 

admin

 

Mac OSでもWSL相当機能(Lima)があるんだ、

Rancher Desktopを起動しているときにQEMUがメモリを4GB程度消費するので代替え手段あるかと調べてみたら、Rancher DesktopではQEMU以外にmacOSの標準機能であるVirtualization.Frameworkというのがあるようです、その名の通りでMac上でLinuxのVMを動作させることができます

Rancher  DesktopではQEMUとVZ(Virtualization.Framework)の選択ができるようになっていて、

これは切り替えた状態、メモリ消費量(2.7GBとかになってます)は多少緩和されてる模様、ただし速度的にはmacOS nativeの機能だろうから高速化は期待できそうです

WSL相当(使ったことはないけど)ならば、個人の使用でそこそこVMwareの代替えとして使えそうです

多少紛らわしいのですが、Rancher DesktopではLimaを直接呼んでいるわけではなくて、仮想化のためにQEMUあるいはVZを選択しているだけで、Lima自体に仮想化の機能は持たないので、実際の仮想化処理はLimaからQEMUもしくはVZを呼び出します

MacでLimaをインストするならば、

% brew install lima

helpで見てみるとLimaはlimactlのaliasだよと言われます、その名の通りですね

% lima --help
Usage: lima [COMMAND...]

lima is an alias for "limactl shell default".

 

admin