Closed8

ローカル推論フレームワーク「Nexa SDK」を試す

kun432kun432

GitHub

https://github.com/NexaAI/nexa-sdk

Nexa SDK - ローカルデバイス推論フレームワーク

Nexa SDKは、ONNXおよびGGMLモデル向けのローカルオンデバイス推論フレームワークで、テキスト生成、画像生成、視覚と言語の統合モデル(VLM)、音声と言語の統合モデル、音声認識(ASR)、および音声合成(TTS)機能をサポートします。Pythonパッケージまたは実行可能インストーラを通じてインストール可能です。

特徴

  • デバイスサポート: CPU、GPU(CUDA、Metal、ROCm)、iOS
  • サーバー: OpenAI互換API、関数呼び出し用JSONスキーマおよびストリーミング対応
  • ローカルUI: モデルのインタラクティブなデプロイとテスト用のStreamlit

差別化ポイント

以下に他の類似ツールとの違いを示します。

機能 Nexa SDK ollama Optimum LM Studio
GGMLサポート
ONNXサポート
テキスト生成
画像生成
視覚・言語モデル
音声合成
サーバー機能
ユーザーインターフェース

対応モデルとモデルハブ

オンデバイスモデルハブでは、量子化されたすべてのタイプのモデル(テキスト、画像、音声、マルチモーダル)を提供しており、RAM、ファイルサイズ、タスクなどのフィルタを用いて簡単に探索できます。オンデバイスモデルはモデルハブで探索可能です。

対応モデルの例(完全なリストはモデルハブをご覧ください):

モデル名 種類 フォーマット コマンド
omniaudio 音声LM GGUF nexa run omniaudio
qwen2audio 音声LM GGUF nexa run qwen2audio
octopus-v2 関数呼び出し GGUF nexa run octopus-v2
octo-net テキスト GGUF nexa run octo-net
omnivision マルチモーダル GGUF nexa run omnivision
nanollava マルチモーダル GGUF nexa run nanollava
llava-phi3 マルチモーダル GGUF nexa run llava-phi3
llava-llama3 マルチモーダル GGUF nexa run llava-llama3
llava1.6-mistral マルチモーダル GGUF nexa run llava1.6-mistral
llava1.6-vicuna マルチモーダル GGUF nexa run llava1.6-vicuna
llama3.2 テキスト GGUF nexa run llama3.2
llama3-uncensored テキスト GGUF nexa run llama3-uncensored
gemma2 テキスト GGUF nexa run gemma2
qwen2.5 テキスト GGUF nexa run qwen2.5
mathqwen テキスト GGUF nexa run mathqwen
codeqwen テキスト GGUF nexa run codeqwen
mistral テキスト GGUF/ONNX nexa run mistral
deepseek-coder テキスト GGUF nexa run deepseek-coder
phi3.5 テキスト GGUF nexa run phi3.5
openelm テキスト GGUF nexa run openelm
stable-diffusion-v2-1 画像生成 GGUF nexa run sd2-1
stable-diffusion-3-medium 画像生成 GGUF nexa run sd3
FLUX.1-schnell 画像生成 GGUF nexa run flux
lcm-dreamshaper 画像生成 GGUF/ONNX nexa run lcm-dreamshaper
whisper-large-v3-turbo 音声認識 BIN nexa run faster-whisper-large-turbo
whisper-tiny.en 音声認識 ONNX nexa run whisper-tiny.en
mxbai-embed-large-v1 埋め込み GGUF nexa embed mxbai
nomic-embed-text-v1.5 埋め込み GGUF nexa embed nomic
all-MiniLM-L12-v2 埋め込み GGUF nexa embed all-MiniLM-L12-v2:fp16
bark-small 音声合成 GGUF nexa run bark-small:fp16

その他もざっとリストアップ

  • インストール
    • Mac、Windows、Linux用のインストーラが用意されている
    • Pythonパッケージでのインストールも可能
      • ローカルで動くUI付き(インストーラにはない)
      • Pythonバージョン・プラットフォーム・バックエンドごとにバリエーションあり。
  • llama.cppが対応しているモデルであればHuggingFaceから直接モデルを実行可能
    • GGUFを直接実行可
    • モデルを変換可能(extrasで変換ツールを指定、変換コマンドで実施)
  • サーバあり
    • テキスト生成・チャット・Function Calling・text-to-image・image-to-image・STT・翻訳・埋め込み
    • OpenAIと多少は似ているっぽいが互換ではなさそう
  • CLIでモデルの評価も可能

既存のやつの足りないところをそれぞれ補って全部できるようにしてエコシステム化した、って感じかな?

kun432kun432

インストール

https://docs.nexa.ai/getting-started/installation

ローカルのMac上でやる。インストーラのほうが手軽なんだけど、ローカルUIのあるPythonパッケージでやってみる。

作業ディレクトリ+仮想環境を作成。自分はmiseを使っているけど、適宜。

mkdir nexa-sdk-test && cd nexa-sdk-test
mise use python@3.12
cat << 'EOS' >> .mise.toml

[env]
_.python.venv = { path = ".venv", create = true }
EOS
mise trust

パッケージインストール。ここはアーキテクチャやGPUによって異なる。Macの場合は以下。extrasもすべて有効にした。

CMAKE_ARGS="-DGGML_METAL=ON -DSD_METAL=ON" \
    pip install nexaai[onnx,eval,convert] \
    --prefer-binary \
    --index-url https://nexaai.github.io/nexa-sdk/whl/metal \
    --extra-index-url https://pypi.org/simple \
    --no-cache-dir

確認

pip show nexaai
出力
Name: nexaai
Version: 0.0.9.2
Summary: Nexa AI SDK
Home-page: https://github.com/NexaAI/nexa-sdk
Author:
Author-email: Nexa AI <octopus@nexa4ai.com>
License: MIT
Location: /Users/kun432/work/nexa-sdk-test/.venv/lib/python3.12/site-packages
Requires: cmake, diskcache, fastapi, faster_whisper, huggingface_hub, jinja2, librosa, numpy, pillow, prompt_toolkit, pydantic, python-multipart, streamlit, streamlit-audiorec, tabulate, tqdm, typing-extensions, uvicorn
Required-by:
kun432kun432

モデルの実行

ではnexa-sdkでモデルを実行してみる。

モデルハブ

nexa-sdkでは、各ユーザがモデルをアップロードし他のユーザが簡単にアクセスできる仕組みとして「モデルハブ」があり、ここからモデルをダウンロードして使う。モデルハブは以下URLにある。

https://nexa.ai/models

モデルハブには、2024/11/18時点で約130のモデルが用意されており、テキスト生成、画像生成、STTなどの用途、メモリ使用量やディスク使用量など、いろいろな条件で検索ができる。

試しにgennma-2-2b-instructのページを見てみる。

https://nexa.ai/google/gemma-2-2b-instruct/gguf-q4_K_M/readme

以下のようにモデルのフォーマットやメモリ・ファイル使用量が表示され、またnexa-sdkで実行する際のコマンドなども表示されている。

モデルのバリエーションも選択できるようになっている。

テキスト生成・チャット

ではgemma-2-2b-instruct:q4_K_Mを試してみる。GGUFモデルの実行はnexa runで行う。

nexa run gemma-2-2b-instruct:q4_K_M

モデルがダウンロードされる

出力
Downloading gemma-2-2b-instruct/q4_K_M.gguf...
q4_K_M.gguf:  49%|███████████████████████████████▉                                 | 800M/1.59G [01:36<00:12, 71.6MB/s]

ダウンロード完了すると対話モードになる。

出力
Successfully downloaded gemma-2-2b-instruct/q4_K_M.gguf to /Users/kun432/.cache/nexa/hub/official/gemma-2-2b-instruct/q4_K_M.gguf
Successfully pulled model gemma-2-2b-instruct:q4_K_M to /Users/kun432/.cache/nexa/hub/official/gemma-2-2b-instruct/q4_K_M.gguf, run_type: NLP
>>> Send a message ... (type "/exit" to quit)

こんな感じでやり取りできる。

出力
>>> おはよう!
assistant: おはよう! 😊

今日はどんな一日になりますか?


>>> 今日はいいお天気だね。
assistant: そうですね!☀️  良い天気ですね!

何か予定はありますか? 😊


>>> Send a message ... (type "/exit" to quit)

STT

他のモデルも見てみる。まず、STT。OpenAIのWhisper。

https://nexa.ai/openai/whisper-tiny/onnx-cpu-fp32/readme

こちらはONNXフォーマットとして提供されているので、少しコマンドが異なる。

nexa onnx whisper-tiny:onnx-cpu-fp32

STTの場合はオーディオファイルへのパスを指定する様子。

>>> /Users/kun432/Desktop/sample.m4a
出力
/Users/kun432/work/nexa-sdk-test/.venv/lib/python3.12/site-packages/nexa/onnx/nexa_inference_voice.py:90: UserWarning: PySoundFile failed. Trying audioread instead.
  audio, sr = librosa.load(audio_path, sr=self.params["sampling_rate"])
/Users/kun432/work/nexa-sdk-test/.venv/lib/python3.12/site-packages/librosa/core/audio.py:184: FutureWarning: librosa.core.audio.__audioread_load
	Deprecated as of librosa version 0.10.0.
	It will be removed in librosa version 1.0.
  y, sr_native = __audioread_load(path, offset, duration, dtype)
INFO:root:Generating transcription...
Due to a bug fix in https://github.com/huggingface/transformers/pull/28687 transcription using a multilingual Whisper will default to language detection followed by transcription instead of translation to English.This might be a breaking change for your use case. If you want to instead always translate your audio to English, make sure to pass `language='en'`.
The attention mask is not set and cannot be inferred from input because pad token is same as eos token. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
INFO:root:Transcription saved to: voice_output/transcription_1731891329.txt
Transcription: おはようございます。ウィスパーのテストです。ちゃんと聞き取れていますか。

ちょっとwarningは出ているもののSTTできている。

TTS

次にTTS。suno/barkを試す。

https://nexa.ai/suno/bark-small/gguf-fp16/readme

nexa run bark-small:fp16

テキストを入力

Enter text to generate audio: 
出力
2024-11-18 10:04:09,878 - INFO - Audio saved to /Users/kun432/work/nexa-sdk-test/tts

ファイルが出力されている。

出力
.
└── tts
    └── audio_1731892219.wav

生成されたものは以下

https://audio.com/kun432/audio/audio-1731892219

TTSは現時点で4モデルしかなくて、2つは出どころ不明、残り1つも自分の環境だと動かなかった。もう少しモデルが揃ってくれると嬉しいところ。

画像生成

画像生成。SDXL-Turboを試す。

https://nexa.ai/StabilityAI/sdxl-turbo/gguf-q8_0/readme

nexa run sdxl-turbo:q8_0

プロンプトの入力を求められる。

出力
>>> Enter your prompt:  (type "/exit" to quit)

テキストを入力

>>> Illustration of a cute llama wearing a red scarf

次にネガティブプロンプトの入力。今回はスキップした。

出力
>>> Enter your negative prompt (press Enter to skip):  (type "/exit" to quit)

生成中

出力
  |==============================>                   | 3/5 - 3.21s/it

出力された

出力
Image 1 saved to: /Users/kun432/work/nexa-sdk-test/generated_images/image_1_1731895781.png

FLUX.1 schnellもあるんだけどうまく生成されなかった

マルチモーダル

image+text-to-textとaudio+text-to-textがあるが、今回はimage+text-to-textで。Omnivisionを試す。

https://nexa.ai/NexaAI/omnivision/gguf-fp16/readme

nexa run omnivision:fp16

画像のパスを求められる。

出力
>>> Image Path (required):  (type "/exit" to quit)

1つ前で生成された画像を指定してみる。

>>> /Users/kun432/work/nexa-sdk-test/generated_images/image_1_1731895781.png

プロンプトを入力

>>> 何が写っていますか?説明して。
出力
Response: The image depicts a white and furry animal, possibly a lamb, wearing a red scarf around its neck. The scarf adds a playful and whimsical touch to the animal's appearance.

Embedding

日本語に対応したモデルがないので、とりあえずall-MiniLM-L6-v2を試す。

https://nexa.ai/sentence-transformers/all-MiniLM-L6-v2/gguf-fp16/readme

nexa run all-MiniLM-L6-v2:fp16

んー、これはCLIで使うものではないのかも?

出力
Unknown task: Text Embedding. Skipping inference.

CLIがちょっと違った。Embeddingの場合はnexa embedだった。

https://docs.nexa.ai/sdk/cli-reference#generate-text-embeddings

nexa embed all-MiniLM-L6-v2:fp16 "今日はいいお天気ですね。"
出力
{'embedding': [0.13919511437416077, 0.7973977327346802, 0.6253407001495361, 0.0001212097704410553, -0.12077240645885468, (snip)

その他

インストールしたモデルの一覧はnexa listで確認できる

nexa list
出力
+-------------------------------------+------+-----------------+-------------------------------------------------------------------------------+
| Model Name                          | Type | Run Type        | Location                                                                      |
+-------------------------------------+------+-----------------+-------------------------------------------------------------------------------+
| gemma-2-2b-instruct:q4_K_M          | gguf | NLP             | /Users/kun432/.cache/nexa/hub/official/gemma-2-2b-instruct/q4_K_M.gguf        |
| whisper-tiny:onnx-cpu-fp32          | onnx | Audio           | /Users/kun432/.cache/nexa/hub/official/whisper-tiny/onnx-cpu-fp32             |
| OuteAI/OuteTTS-0.1-350M:gguf-q4_K_M | gguf | TTS             | /Users/kun432/.cache/nexa/hub/OuteAI/OuteTTS-0.1-350M/gguf-q4_K_M/q4_K_M.gguf |
| bark-small:fp16                     | gguf | TTS             | /Users/kun432/.cache/nexa/hub/official/bark-small/fp16.gguf                   |
| FLUX.1-schnell:flux1-schnell-q4_0   | gguf | Computer Vision | /Users/kun432/.cache/nexa/hub/official/FLUX.1-schnell/flux1-schnell-q4_0.gguf |
| FLUX.1-schnell:t5xxl-q4_0           | gguf | Computer Vision | /Users/kun432/.cache/nexa/hub/official/FLUX.1-schnell/t5xxl-q4_0.gguf         |
| FLUX.1-schnell:ae-fp16              | gguf | Computer Vision | /Users/kun432/.cache/nexa/hub/official/FLUX.1-schnell/ae-fp16.gguf            |
| FLUX.1-schnell:clip_l-fp16          | gguf | Computer Vision | /Users/kun432/.cache/nexa/hub/official/FLUX.1-schnell/clip_l-fp16.gguf        |
| sdxl-turbo:q8_0                     | gguf | Computer Vision | /Users/kun432/.cache/nexa/hub/official/sdxl-turbo/q8_0.gguf                   |
| all-MiniLM-L6-v2:fp16               | gguf | Text Embedding  | /Users/kun432/.cache/nexa/hub/official/all-MiniLM-L6-v2/fp16.gguf             |
| omnivision:model-fp16               | gguf | Multimodal      | /Users/kun432/.cache/nexa/hub/official/omnivision/model-fp16.gguf             |
| omnivision:projector-fp16           | gguf | Multimodal      | /Users/kun432/.cache/nexa/hub/official/omnivision/projector-fp16.gguf         |
+-------------------------------------+------+-----------------+-------------------------------------------------------------------------------+

なるほど、モデルは$HOME/.cache/nexa以下にダウンロードされている様子。

kun432kun432

GUI

nexa-sdkではコマンドラインだけでなくGUIでも使える。nexaコマンドで実行する際に--streamlitをつける。

nexa run gemma-2-2b-instruct:q4_K_M --streamlit

こんな感じでStreamlitのUIでチャットできる。

画像生成も。

マルチモーダル

STTはうまくいかなかった。TTSは対応してないみたい。

kun432kun432

サーバ

nexa-sdkはサーバも建てれる。nexa serverを使う。

nexa server gemma-2-2b-instruct:q4_K_M 

8000番ポートで立ち上がる模様。

出力
INFO:     Started server process [65074]
INFO:     Waiting for application startup.
Model gemma-2-2b-instruct:q4_K_M already exists at /Users/kun432/.cache/nexa/hub/official/gemma-2-2b-instruct/q4_K_M.gguf
model_type: NLP
INFO:     Application startup complete.
INFO:     Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)

cURLで試す

curl http://localhost:8000/v1/completions \
    -H "Content-Type: application/json" \
    -d '{"prompt":"おはよう!今日はいい天気ですね!","stream":false}' \
| jq -r .
出力
{
  "id": "bc1a8f31-b545-4b8d-8243-187dd8b93789",
  "object": "text_completion",
  "created": 1731898137,
  "model": "gemma-2-2b-instruct:q4_K_M",
  "choices": [
    {
      "text": "☀️\n\n今日は何か楽しい予定はありますか?😊\n",
      "index": 0,
      "logprobs": null,
      "finish_reason": "stop"
    }
  ]
}

各エンドポイントはドキュメント参照

https://docs.nexa.ai/sdk/local-server

kun432kun432

🤗HuggingFaceモデルの実行

HuggingFaceでGGUFが公開されている場合は直接実行することができる。以下のモデルで試してみる。

https://huggingface.co/Qwen/Qwen2.5-Coder-1.5B-Instruct-GGUF

nexa run -hfでHuggingFaceのパスを指定する。

nexa run -hf Qwen/Qwen2.5-Coder-1.5B-Instruct-GGUF

GGUFのバリエーションが複数用意されている場合は選択する。

出力
Available gguf models in the repository:
1. qwen2.5-coder-1.5b-instruct-q2_k.gguf
2. qwen2.5-coder-1.5b-instruct-q3_k_m.gguf
3. qwen2.5-coder-1.5b-instruct-q4_0.gguf
4. qwen2.5-coder-1.5b-instruct-q4_k_m.gguf
5. qwen2.5-coder-1.5b-instruct-q5_0.gguf
6. qwen2.5-coder-1.5b-instruct-q5_k_m.gguf
7. qwen2.5-coder-1.5b-instruct-q6_k.gguf
8. qwen2.5-coder-1.5b-instruct-q8_0.gguf
Please enter the number of the model you want to download and use: 4
>>> 100以下のフィボナッチ数を計算するコードをpythonで生成して。
出力
assistant: 以下に、100以下のフィボナッチ数を計算するPythonコードを生成します:

```python
def fibonacci(n):
    if n <= 0:
        return []
    elif n == 1:
        return [0]
    elif n == 2:
        return [0, 1]
    else:
        fib_sequence = [0, 1]
        for i in range(2, n):
            fib_sequence.append(fib_sequence[i-1] + fib_sequence[i-2])
        return fib_sequence

n = 100
fib_sequence = fibonacci(n)
print(fib_sequence)
```

このコードは、以下のような機能を提供します:

1. 呼び元の`n`パラメータで指定した数値以下のフィボナッチ数列を生成します。
2. 生成されたフィボナッチ数列は、リストで返されます。

3. 最初に、`n`が0や1の場合に、空のリストを返します。
4. 最初に、`n`が1の場合に、[0]を返します。
5. 最初に、`n`が2の場合に、[0, 1]を返します。
6. それ以外の場合は、前两个数の和で新しい数を生成し、リストに追加します。

このコードは、フィボナッチ数列の生成が簡単で、適切な範囲でフィボナッチ数列を生成するための基本的な方法を提供します。

>>> Send a message ... (type "/exit" to quit)

またGGUFがない場合でもモデルをGGUF変換することができる。以下のモデルを使用してみる。

https://huggingface.co/HuggingFaceTB/SmolLM2-1.7B-Instruct

nexa convert HuggingFaceTB/SmolLM2-1.7B-Instruct

モデルの種別を入力する。現時点ではテキスト生成 or 画像生成だけなのかも。

出力

Select model type:
1. NLP (text generation)
2. COMPUTER_VISION (image generation)

Select model type (enter number): 1

量子化のバリエーションを指定する。

出力
Available quantization types:
1. q4_0
2. q4_1
3. q5_0
4. q5_1
5. q8_0
6. q2_k
7. q3_k_s
8. q3_k_m
9. q3_k_l
10. q4_k_s
11. q4_k_m
12. q5_k_s
13. q5_k_m
14. q6_k
15. iq2_xxs
16. iq2_xs
17. q2_k_s
18. iq3_xs
19. iq3_xxs
20. iq1_s
21. iq4_nl
22. iq3_s
23. iq3_m
24. iq2_s
25. iq2_m
26. iq4_xs
27. iq1_m
28. f16
29. f32
30. bf16
31. q4_0_4_4
32. q4_0_4_8
33. q4_0_8_8
34. tq1_0
35. tq2_0

Select quantization type (enter number): 11

モデルがダウンロードされ、変換が行われる。変換が終わると以下のように保存するかを確認される。

出力
Conversion completed successfully. Output file: /Users/kun432/work/nexa-sdk-test/SmolLM2-1.7B-Instruct-q4_k_m.gguf

You like to store this model in nexa list so you can run it with `nexa run <model_name>` anywhere and anytime? (y/N): y

その場で実行するかを聞かれる。試してみる。

出力
Would you like to run the converted model? (y/N): y
>>> おはよう!今日はいい天気だね!
出力
assistant: はい!今日の天気はとてもいいです!それで、晩ごはりにはお願いします!(Good morning! The weather today is very nice, dear! Please have a good night after dinner.)
kun432kun432

まとめ

強みとしては、やはりひとつのツールで、色々対応しているということだと思う。各OSやアーキテクチャに対応しているというのもある。

差別化ポイント

以下に他の類似ツールとの違いを示します。

機能 Nexa SDK ollama Optimum LM Studio
GGMLサポート
ONNXサポート
テキスト生成
画像生成
視覚・言語モデル
音声合成
サーバー機能
ユーザーインターフェース

とりあえず欲しい機能を全部網羅したものという印象で、あとはモデルハブがいかに取り揃うかというところになるかなぁ。今のところ、約130モデル、ollamaなどに比べると少ないと思うし、HuggingFaceのものが使えるというのはあるにしても、公式のハブで揃っているに越したことはない。

個人的には、バックエンドとして使いフロントエンドなどは別のものを使うという使い方もあると思うので、サーバモードがOpenAI互換とかだと嬉しい。ある程度ユーザが増えれば、フロントエンド側でも対応してくれるのかもしれないけど、OpenAI互換にすれば既存のものでもそのまま使えると思うので。

今後に期待。モデル作ってアップロードしてみたい。

このスクラップは10日前にクローズされました