https://doi.org/10.1038/s41586-025-09127-3 によると、脳表面に設置した電極(ECoG)から取得したデータを使ってリアルタイムに音声を合成できるようになったらしい。Supplementary Videoを見る限り、速度はまだまだではあるものの、イントネーションも変えられるし、強調もできるような発声ができている。
ここまで出来るようになっているので、普通に発話できるようになるのも時間の問題だと思われる。 一方、ECoGではこのレベルで動くようになっているものの、EEGで同じことをするのはまだまだ難しいのだろう。2025/08/17
2025/04/05
OpenHandsをローカルLLMで動かす
OpenHandsをローカルLLMで動かしてみます。
OpenHandsの準備
https://github.com/All-Hands-AI/OpenHands/のQuick Startに従って、dockerを動かすだけです。 Rootless dockerでも動作します。 /var/run/docker.sockを使ってOpenHandsがdockerを制御するようでしたので、今回は、KVM上でUbuntu24.04を動作させ、その中でAllHandsを動作させました。
ollamaの準備
ローカルLLMについてはollamaで動作させます。 ollamaもdockerイメージがhttps://hub.docker.com/r/ollama/ollamaで配布されているのでそれをそのまま利用します。 こちらもrootless dockerでも動作します。
$ docker run -d --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollamaを実行するとollamaが立ち上がります。
$ docker exec -it ollama bashでdocker内に入って、ollamaを実行すると
root@xxxxxxxx:/# ollama Usage: ollama [flags] ollama [command] Available Commands: serve Start ollama create Create a model from a Modelfile show Show information for a model run Run a model stop Stop a running model pull Pull a model from a registry push Push a model to a registry list List models ps List running models cp Copy a model rm Remove a model help Help about any command Flags: -h, --help help for ollama -v, --version Show version information Use "ollama [command] --help" for more information about a command.となり、ollamaが実行できることが確認できます。
ollamaのモデルの準備
試している環境ではGPUメモリが8GBなので、小さめのLLMを探してきます。 以下のものを試してみましたが、hhao/qwen2.5-coder-tools:7bがかろうじて動く程度で、ほかはOpenHandsで使うには適切ではないLLMでした。
hhao/qwen2.5-coder-tools:7b 1fbf62f22cd4 4.7 GB codegemma:7b 0c96700aaada 5.0 GB llama3.2:3b a80c4f17acd5 2.0 GB codellama:7b 8fdf8f752f6e 3.8 GB qwen2.5-coder:3b e7149271c296 1.9 GB opencoder:1.5b 8573dfc23c16 1.4 GB opencoder:8b cd882db52297 4.7 GBもっと良いLLMがあるかもしれませんが、ここではhhao/qwen2.5-coder-tools:7bを使って進めます。runすると
/# ollama run hhao/qwen2.5-coder-tools:7b >>> Send a message (/? for help)と表示され、OpenHandsからアクセスできる状態になりました。試しにメッセージを入れてみると、
>>> Pythonでhelloと出力するスクリプトを作成してください ```python print("hello") ```とか
>>> rustでhelloと出力するコードを書いて、ビルドして実行する方法を書いてください ```json { "name": "create_file", "arguments": { "filename": "main.rs", "content": "fn main() {\n println!(\"Hello\");\n}" } } ```のように出力されました。日本語でも動きそうです。OpenHandsから呼び出すときにollama runが実行されている必要はありません。
OpenHandsの設定
KVM内からollamaにアクセスできることを確認します。
curl http://host.ip.address:11434/api/generate -d '{ "model": "hhao/qwen2.5-coder-tools:7b", "prompt":"Write a bash script that prints hello" }'json形式の応答が返ってくれば、動作しています。
docker run -it --rm -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.29-nikolaik \ -e LOG_ALL_EVENTS=true \ -e LOG_JSON=false \ -e LOG_LEVEL=DEBUG \ -e DEBUG=true \ -e OLLAMA_API_BASE=http://host.ip.address:11434 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ~/.openhands-state:/.openhands-state \ -p 3000:3000 \ --add-host host.docker.internal:host-gateway \ --name openhands-app \ docker.all-hands.dev/all-hands-ai/openhands:0.29host.ip.addressは適切な値に書き換えてください。 KVM内のブラウザでlocalhost:3000にアクセスします。 左下の⚙アイコンをクリックして、
Custom model: ollama/hhao/qwen2.5-coder-tools:7b Base URL: http://host.ip.address:11434 API Key: なんでもOK Agent: CodeActAgentと設定します。 これで動くようになります。指示として例えば
Could you write a bash script that just prints "こんにちは" ?を入力すると動き始め、下図のようになりました。 ただ、ファイルはつくれたもののその後はうまく動作しなくなってしまいました。 OpenHandsを活用するには、もっと賢いLLMが必要なようです。
投稿者
bluewidz
0
コメント
2025/02/22
FLUX.1で画像生成
時刻
17:46
FLUX.1のSchnellモデルを使った画像生成をしてみます。
FLUXのオリジナルの実装
オリジナルの実装はこちらです。 モデル: https://huggingface.co/black-forest-labs/FLUX.1-schnell
コード: https://github.com/black-forest-labs/flux 指示にしたがって環境を設定し、実行すると、44.5GBのダウンロードがはじまります。 これは src/flux/util.py を読むと google/t5-v1_1-xxl をロードするようになっており、 https://huggingface.co/google/t5-v1_1-xxl/tree/main を見るとちょうどモデルサイズが44.5GBなので、おそらくこれをダウンロードしようとしているのだと思われます。 https://huggingface.co/black-forest-labs/FLUX.1-schnell/tree/main に配置されているテキストエンコーダが使われない理由は謎です。 ダウンロードサイズは大きいですが https://github.com/black-forest-labs/flux/issues/7 によると、16GBくらいVRAMがあればよさそうです。sequential offloadをすれば2GBくらいらしいのですが、cli.pyのオプションを見てもそれらしきものを見つけることができませんでした。
量子化版
とはいえもう少し小さいモデルでまずは動かしてみたいので、量子化済みのモデルで試してみます。いくつかHuggingFaceにアップロードされていますが、今回はhttps://huggingface.co/aifoundry-org/FLUX.1-schnell-Quantizedを使ってみます。 現時点では[WIP]と書かれているものの動かし方がいちおうは記載されているので、そのとおりに実行してみます。 最初に table-diffusion.cpp をダウンロードしてビルドします。 次に、 Schnell-Q2_K と Autoencoder と CLIP_L と T5XXL をダウンロードして、models/以下に配置します。 これで準備は完了です。先ほどダウンロードした一番小さいモデル(Q2_K)で試してみます。
./build/bin/sd --diffusion-model models/flux1-schnell-Q2_K.gguf --vae models/ae.safetensors --clip_l models/clip_l.safetensors --t5xxl models/t5xxl_fp16.safetensors -p "a frog holding a sign saying 'hi' " -o ../frog.png -v --cfg-scale 1.0 --sampling-method euler -v --seed 42 --steps 4を実行します。 以下の様な蛙の画像が出力されます。 他にも
./build/bin/sd --diffusion-model models/flux1-schnell-Q2_K.gguf --vae models/ae.safetensors --clip_l models/clip_l.safetensors --t5xxl models/t5xxl_fp16.safetensors -p "Photo-realistic Rabbit running in meadow" -o ../frog.png -v --cfg-scale 1.0 --sampling-method euler -v --seed 10 --steps 20を実行すると となります。 T5XXLはモデルサイズは大きいもののGPUメモリはあまり必要ないようで、デフォルトの512x512のサイズの画像生成時に観測できた範囲ではGPUメモリの使用量は4.7GBくらいでした。
./build/bin/sd --diffusion-model models/flux1-schnell-Q4_K.gguf --vae models/ae.safetensors --clip_l models/clip_l.safetensors --t5xxl models/t5xxl_fp16.safetensors -p "Photo-realistic Rabbit running in meadow" -o ../frog.png -v --cfg-scale 1.0 --sampling-method euler -v --seed 13 --steps 20のようにQ2_KではなくQ4_Kを使ってみると となります。 Q2_KではなくQ4_Kのモデルの方を使った場合、デフォルトの512x512のサイズの画像生成時に観測できた範囲ではGPUメモリの使用量は7.4GBくらいでした。 試した範囲では実行結果に再現性があり、コマンドの引数が同じであれば同じ結果が出力されるようです。
投稿者
bluewidz
0
コメント
2025/02/10
Landlockによる制限をかけるときにGPUを使うには
Landlock (を使ったsandboxer) による制限をかけるときにnvidia-smiを実行するには、次のパスを許可すれば良いようです。
LL_FS_RW=$(ls /dev/nvidia* | tr '\n' ':' | sed 's/:$//') LL_FS_RO="/usr/lib:/usr/bin" ./sandboxer nvidia-smiRO側はもう少し制限をかけることができるかもしれません。 nvidia-smiだけでなく、NVidiaのGPUを計算に利用するには、
LL_FS_RW="/proc:"$(ls /dev/nvidia* | tr '\n' ':' | sed 's/:$//') LL_FS_RO="/usr/lib:/usr/bin" ./sandboxer /path/to/appのように/procを読み書き権限で追加する必要があるようです。 アプリケーション依存かもしれませんので、必ずしもこれだけで使えるようになるとは限りません。
投稿者
bluewidz
0
コメント
2025/02/02
uvのインストール
最近のUbuntuやDebianのシステムに入っているPythonでpip installしようとすると、
error: externally-managed-environmentと言われ、venv環境を作れと言ってきます。 全体で使いたいパッケージをいちいちvenv環境に入ってインストールして、というのは手間なので、 エラーメッセージに書かれているとおり、Debian/Ubuntuのパッケージにある pipx をインストールします。 そのうえで、
$ pipx install uvとすると、uvをインストールできて、全体でuvが使えるようになります。
投稿者
bluewidz
0
コメント
編集距離の計算
編集距離(Edit Distance, Levenshtein Distance)の計算のライブラリは今となってはたくさんありそうですが、 いい感じに表示できる jiwer (https://jitsi.github.io/jiwer/) というPythonのライブラリがあったので、メモ。
こんな感じで書けます。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import jiwer import jaconv def main(): reference = "hello world" hypothesis = "hello duck" error = jiwer.wer(reference, hypothesis) print(error) error = jiwer.cer(reference, hypothesis) print(error) print("--------------") output = jiwer.process_characters(reference, hypothesis) print(jiwer.visualize_alignment(output)) print("--------------") output = jiwer.process_characters("あいうえお", "あううお") prev_hyp = False for line in jiwer.visualize_alignment(output).split("\n"): zen = False if prev_hyp: prev_hyp = False zen = True if line[:4] == "REF:": zen = True if line[:4] == "HYP:": zen = True prev_hyp = True if zen: line = jaconv.h2z(line, kana=True, digit=True, ascii=True) print(line) if __name__ == "__main__": main() |
0.5 0.45454545454545453 -------------- sentence 1 REF: hello world HYP: hello duck* SSSSD number of sentences: 1 substitutions=4 deletions=1 insertions=0 hits=6 cer=45.45% -------------- sentence 1 REF: あいうえお HYP: あうう*お S D number of sentences: 1 substitutions=1 deletions=1 insertions=0 hits=3 cer=40.00%のようになります。
投稿者
bluewidz
0
コメント
2024/07/14
話者ベクトル
時刻
13:30
話者ベクトルをhttps://github.com/speechbrain/speechbrain.gitで取得してみます。
話者ベクトルの計算にはEncoderClassifier.encode_batchを使います。サンプリング周波数16kHzの音声データをこの関数に入力すると話者ベクトルが得られます。 それ以外の部分は音声の読み込みとt-SNEによる2Dベクトル化、散布図描画のための色の選択と、散布図の作成をしているだけです。 35行目でEncoderClassifierを作成して、52行目で話者ベクトルを取得します。 audio-16k.listは1行ごとに.wavファイルへのパスが書かれていることを想定しています。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | import sys
from collections import defaultdict
import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
import torchaudio
sys.path.append("speechbrain")
from speechbrain.inference import EncoderClassifier
def make_colormap(label_list, min_count):
color_map = defaultdict(int)
for label in label_list:
color_map[label] += 1
color_map_sorted = []
for k, v in color_map.items():
color_map_sorted.append((v, k))
color_map_sorted = reversed(sorted(color_map_sorted))
colors = ["b", "g", "r", "c", "m", "y", "k", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9"]
cindex = 0
for v, k in color_map_sorted:
if v < min_count:
color_map[k] = None
continue
color_map[k] = colors[cindex] if cindex < len(colors) else "grey"
cindex += 1
color_list = []
for i in range(len(label_list)):
color_list.append(color_map[label_list[i]])
return color_list
def main(wav_list):
ec = EncoderClassifier.from_hparams(
source="speechbrain/spkrec-ecapa-voxceleb",
savedir="cache",
run_opts={"device": "cuda"},
use_auth_token=False
)
ec.hparams.label_encoder.ignore_len()
embed_list = []
label_list = []
with open(wav_list) as wavs:
i = 0
for line in wavs:
i += 1
line = line.strip()
signal, fs = torchaudio.load(line)
assert fs == 16000
# Get a speaker vector
embed_list.append(ec.encode_batch(signal, wav_lens=None).squeeze(dim=1).cpu().numpy())
label_list.append(line.split("/")[1].split("_")[0]) # Get speaker name
if i % 100 == 0:
print(i)
label_list = make_colormap(label_list, min_count=100)
# Filter speaker vectors
embed_list = [embed_list[i] for i in range(len(label_list)) if label_list[i] is not None]
label_list = [label_list[i] for i in range(len(label_list)) if label_list[i] is not None]
embed_list = np.concatenate(embed_list)
tsne = TSNE(n_components=2, random_state=123)
vec_2d = tsne.fit_transform(embed_list)
plt.figure(figsize=(10, 8))
plt.scatter(vec_2d[:,0], vec_2d[:,1], alpha=0.7, c=label_list)
plt.title("t-SNE visualization of speaker vectors")
plt.xlabel("t-SNE feature 1")
plt.ylabel("t-SNE feature 2")
plt.grid(True, linestyle="--", alpha=0.7)
plt.savefig("spk_distribution.png", dpi=300, bbox_inches="tight")
plt.close()
if __name__ == "__main__":
main("audio-16k.list")
|
投稿者
bluewidz
0
コメント
2024/07/06
moreの挙動が変化した
時刻
14:08
Debianを11から12にアップグレードしたところ、moreコマンドのデフォルトの挙動が変化しました。
具体的には、表示するテキストの行が画面の行数よりも短いときは、単にcatで出力される状態であったのに、画面をクリアして画面の上部に表示されるようになりました。 lessでいうと、less -Fの挙動をしていたものが、less -cに似た挙動に変更されてしまいました。しかも、元の画面を削除して復旧しないという挙動です。 less -Fが手間なのでmoreを使っていたのに、これは困ったことになってしまいました。 PerplexityによるとLinuxのmoreコマンドの動作変更は、util-linux パッケージのバージョン2.38で導入されました。この変更により、表示する内容が端末の画面高さよりも少ない行数の場合でも、画面の上部から表示されるようになりました。 この変更は、より一貫性のある動作を提供し、ユーザーエクスペリエンスを向上させることを目的としています。以前のバージョンでは、内容が短い場合に画面の下部に表示されることがあり、これが一部のユーザーにとって混乱を招く原因となっていました。 util-linux 2.38は2022年4月にリリースされており、この版で上記の動作変更が実装されました。したがって、util-linux 2.37.2と2.38.1の間で発生したこの変更は、正確には2.38で導入されたものです。とのこと。 moreコマンドが含まれているlinux-utilのバージョンは、Debian 11では2.36.1、Debian 12では2.38.1です。また、Ubuntu 22.04のmoreはDebian 11と挙動が同じで、そのバージョンは2.37.2です。 そこで、linux-utilのログを調べてみると、
2021-06-01 build-sys: release++ (v2.37)v2.37 2022-01-31 build-sys: release++ (v2.38-rc1)v2.38-rc1 2022-03-28 build-sys: release++ (v2.38)v2.38でした。これらの間のどこかに変更が含まれているはずです。 調べてみると
commit df6b29d3b8e9a55d2bfa69c593e17da4d11a3fac AuthorDate: Wed Sep 29 14:50:14 2021 +0200 CommitDate: Wed Sep 29 14:50:14 2021 +0200 more: POSIX compliance patch preventing exit on EOF without -eで-eオプションが導入されて、デフォルトの挙動が変わっていました。とても煩わしいです。 さらにその後のコミットをたどっていくと、なんと、
commit 28b391ce7e58f8327c092b3911c05f526d0ad586 AuthorDate: Wed Jun 15 10:03:44 2022 +0200 CommitDate: Wed Jun 15 10:03:44 2022 +0200 more: restore exit-on-eof if POSIXLY_CORRECT is not set In version 2.38, exit-on-eof has been disabled by default. This change is annoying for users and forces many users to use 'alias more="more -e"'. It seems better to force POSIX lovers to use POSIXLY_CORRECT env. variable and stay backwardly compatible by default. Addresses: https://github.com/util-linux/util-linux/issues/1703 Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2088493がコミットされていて、POSIXでないとやだ!っていう人は環境変数POSIXLY_CORRECTを使いなさいという形に戻っていました。 Debian 12のパッケージ更新タイミングの運のなさよ。とりあえず、alias more="more -e"で回避するしか無さそうです。
投稿者
bluewidz
0
コメント
登録:
投稿
(
Atom
)