ロースペGPUでもOK! LM StudioのAPIを叩いてみた

この記事の内容

  • LM StudioはOpenAI互換のAPIを備えており、ローカルサーバーとして起動できます
  • curlやPythonのOpenAIライブラリをそのまま使ってローカルLLMにアクセスできます
  • 構造化出力(Structured Output)やツール使用(Tool Use)にも対応しています
  • GTX 1660(VRAM 6GB)というロースペックなGPUでも実用的に動作します
  • 既存のOpenAI APIベースのアプリをローカルモデルに切り替えることが容易にできます

はじめに

前回の記事では、LM StudioをNVIDIA GeForce GTX 1660(VRAM 6GB)という比較的ローエンドなGPU環境で動かし、J3-12Bモデルがそれなりに動作することを確認しました。

今回はLM Studioのもうひとつの大きな特徴である「OpenAI互換API」を実際に叩いてみます。LM Studioにはデベロッパー向けのOpenAIライクなAPIが用意されており、既存のOpenAI向けコードをほぼそのまま流用してローカルLLMを呼び出せます。


ローカルサーバーを起動する

LM Studioを起動しただけの初期状態では、ローカルサーバーは動いていません(「Not Running」と表示されます)。APIを使うには、まずサーバーを起動する必要があります。

LM Studioの画面でサーバーの起動ボタンを押すと、状態が「Running」に変わります。これだけで準備完了です。

サーバーはデフォルトで以下のエンドポイントで待ち受けます。

http://127.0.0.1:1234

モデル一覧を取得する(curl)

まずはAPIの動作確認として、利用可能なモデルの一覧を取得してみます。Windows 11にはデフォルトでcurlが含まれているため、特別なインストールは不要です。

curl http://127.0.0.1:1234/v1/models

実行すると、ロードされているモデルの情報がJSON形式で返ってきます。たとえば、J3-12Bモデルがロードされていれば、それがレスポンスに含まれます。

PowerShellを使う場合は以下のように書くこともできます。

Invoke-WebRequest -Uri "http://127.0.0.1:1234/v1/models"

チャット補完APIを叩く

次に、OpenAI互換のチャット補完エンドポイント(/v1/chat/completions)を呼び出してみます。LM Studioの公式ドキュメントにサンプルコマンドが掲載されているため、それをそのまま実行します。

ただし、Windowsのコマンドプロンプト(PowerShellコンソール)では改行の扱いに問題が出ることがあります。その場合はGit Bashを使うと正常に動作します。

curl http://127.0.0.1:1234/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ここにロード中のモデル名",
    "messages": [
      { "role": "system", "content": "Always answer in rhymes." },
      { "role": "user", "content": "Introduce yourself." }
    ],
    "temperature": 0.7,
    "max_tokens": -1,
    "stream": true
  }'
  • max_tokens: -1 は無制限を意味します
  • stream: true にするとストリーミング形式でレスポンスが返ってきます

ストリーミングレスポンスはコンソールでは見づらいため、stream: false にするとまとめて返ってきて確認しやすくなります。

また、このAPIに認証は不要です。ローカル環境のため、APIキーなしで直接呼び出せます。ただし、呼び出しはステートレスであり、会話履歴の管理は呼び出し側で行う必要があります。


構造化出力(Structured Output)を使う

レスポンスのフォーマットをJSONスキーマで指定する「Structured Output」も利用できます。以下はジョークをJSON形式で返させる例です。

curl http://127.0.0.1:1234/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ここにロード中のモデル名",
    "messages": [
      { "role": "system", "content": "You are a helpful joke starter." },
      { "role": "user", "content": "Tell me a joke." }
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "joke_response",
        "schema": {
          "type": "object",
          "properties": {
            "joke_type": { "type": "string" },
            "joke": { "type": "string" }
          }
        }
      }
    }
  }'

レスポンスのcontentフィールドに、指定したスキーマ通りのJSONが返ってきます。

なお、この機能はすべてのモデルが対応しているわけではありません。特に70億パラメーター程度の小さいモデルでは、スキーマ通りに返してくれないことがあるとドキュメントに記載されています。


PythonでTool Useを実装する(Wikipediaチャットボット)

LM Studioのドキュメントには、PythonのOpenAIライブラリを使ったTool Use(ツール使用)のサンプルが用意されています。ここでは、Wikipediaを検索できるチャットボットの例を試します。

前提条件

  • Pythonがインストール済みであること
  • openai Pythonパッケージがインストール済みであること

仮想環境のセットアップ

依存関係の競合を避けるため、Pythonの仮想環境を使うことをおすすめします。

# 仮想環境の作成
python -m venv venv

# 仮想環境の有効化(PowerShell)
.\venv\Scripts\Activate.ps1

# OpenAIパッケージのインストール
pip install openai

サンプルコードの仕組み

LM Studioのドキュメントから保存したサンプルスクリプト(tool_use_example.py)を見ると、以下の構造になっています。

from openai import OpenAI

# ローカルサーバーに接続するクライアントを作成
client = OpenAI(
    base_url="http://127.0.0.1:1234/v1",
    api_key="lm-studio"  # ダミーのAPIキーで可
)

OpenAIのクライアントライブラリをそのまま使い、base_urlをローカルのエンドポイントに向けるだけです。api_keyはダミーの文字列で問題ありません。

ツールの定義はJSON形式で行います。

wiki_tool = {
    "type": "function",
    "function": {
        "name": "fetch_wikipedia_content",
        "description": "Wikipediaに関係する質問には必ずこれを使う。タイポがあれば修正して検索する。",
        "parameters": {
            "type": "object",
            "properties": {
                "search_query": {
                    "type": "string",
                    "description": "検索クエリ"
                }
            },
            "required": ["search_query"]
        }
    }
}

LLM自体がWebを検索するわけではありません。LLMはツールの呼び出し指示(関数名と引数)をテキストとして出力し、クライアント側のPythonコードが実際にWikipediaへリクエストを送り、その結果をLLMに返すという仕組みです。

実行と動作確認

python tool_use_example.py

エラーなく起動したら、日本語で質問してみます。

:

LLMはまずWikipediaツールの呼び出しを指示し、クライアントがWikipediaから記事を取得して返します。その内容をもとにLLMが回答を生成します。LM Studioのデベロッパーログを見ると、ツール呼び出しと最終応答の2回のリクエストが走っていることが確認できます。


画像入力(Image Input)を使う

LM StudioのAPIは画像入力にも対応しています。Base64エンコードされた画像データをメッセージに含めて送ることで、画像についての質問ができます。

curl http://127.0.0.1:1234/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ここにロード中のモデル名",
    "messages": [
      {
        "role": "user",
        "content": [
          { "type": "text", "text": "What is this?" },
          {
            "type": "image_url",
            "image_url": {
              "url": "data:image/png;base64,ここにBase64エンコードした画像データ"
            }
          }
        ]
      }
    ]
  }'

試した結果、絵文字画像を正しく「パーティーハットをかぶった顔(Face with Party Hat)」と認識しました。複数画像の入力も可能とドキュメントに記載されています。


まとめ

LM StudioのOpenAI互換APIを使うことで、以下のことが実現できました。

  • curl一発でモデル一覧取得やチャット補完が可能
  • PythonのOpenAIライブラリをそのまま流用できるため、既存アプリの向き先をローカルに切り替えるだけで動く
  • Structured OutputでレスポンスをJSON形式に整形できる
  • Tool Useを使ってWikipedia検索などの外部ツールと連携できる
  • 画像入力にも対応しており、マルチモーダルな用途にも使える
  • GTX 1660(VRAM 6GB)でも動作し、まともなGPUであれば十分実用的なレスポンス速度が期待できる

認証不要でローカルから叩けるOpenAI互換APIは、プライバシーを確保しながらLLMを活用したい場面や、既存のOpenAI連携アプリをローカルで試したい場面で非常に有用です。次回は、VS CodeのClineなどのコーディング支援ツールとローカルモデルを組み合わせる方法を試してみたいと思います。