LMStudio APIを試す|Go言語でローカルLLMを呼び出す方法

LMStudioは、ローカルLLM(大規模言語モデル)を手軽に利用できる便利ツールで、OpenAI互換のAPI経由でのアクセスが可能です。この機能を活用することで、Visual Studio Codeなどのエディタや、他のアプリケーションからもローカルLLMを呼び出すことができます。この記事では、LMStudioのAPI機能をGo言語から利用する方法を詳しく解説します。
はじめに
LMStudioは、ローカル環境で大規模言語モデル(LLM)を手軽に試すことができるツールです。LMStudioを使うことで、最新のローカルLLMを簡単に検索してダウンロードし、すぐに試すことができます。

私も新しいモデルが登場するたびに、すぐにダウンロードして試しています。バージョンアップも頻繁に行われ、新しいモデルへの対応も非常に早いです。
最近では、ローカルLLMでも十分に会話や応答が可能になり、実用性が高まっています。クラウドベースのLLMを利用するのも選択肢としてはありますが、会話内容が外部に送信されない点は、特にプライバシーを重視する場面では大きな魅力です。
さらに、LMStudioは、OpenAIのAPIに似た言語モデルサーバーの機能も備えており、これを利用することで、外部のプログラムからLMStudioで読み込んだローカルLLMにAPI経由でアクセスすることができます。
今回は、LMStudioにロードしたgemma-3-4b-it
を、Go言語から呼び出して使ってみましたので、その手順を解説します。
プログラム
LMStudioが用意しているサーバーは、OpenAI互換のAPIでアクセスすることが可能です。今回は、「ChatGPT API(gpt-3.5-turbo)を GoLang から使ってみる」という記事を参考にして、LMStudioへのアクセスを実装してみました。

主な変更はapiKeyが必要ないので削除したこと、Markdown形式の出力に対応させたことです
LMStudio側の設定
LMStudio側では、モデルをロードして、右側の開発者タブで、Status:をRunning
に設定するだけです。これでサーバーが起動します。

この画面にアクセスのURLが書かれています。デフォルトでは以下になります。
http://127.0.0.1:1234
パッケージのインポート
Markdown表示を可能にするために、github.com/charmbracelet/glamour
をインポートしています。Go言語のパッケージインポートについては以下の記事を参考にしてください。

基本的には、以下のコマンドでモジュールを取得すればOKです。
go get github.com/charmbracelet/glamour
うまくいかない場合は、go mod init xxx
後に、go mod tidy
を試してみてください。
プログラムリスト
以下は、プログラムリストになります。
package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"github.com/charmbracelet/glamour"
)
// JSONフォーマットを定義
type OpenaiRequest struct {
Model string `json:"model"`
Messages []Message `json:"messages"`
}
type OpenaiResponse struct {
ID string `json:"id"`
Object string `json:"object"`
Created int `json:"created"`
Choices []Choice `json:"choices"`
Usages Usage `json:"usage"`
}
type Choice struct {
Index int `json:"index"`
Messages Message `json:"message"`
FinishReason string `json:"finish_reason"`
}
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
}
type Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
}
// LMStudioのURLを設定
const openaiURL = "http://localhost:1234/v1/chat/completions"
// APIによるやり取りのためのスライス
var messages []Message
// APIを使ってアクセスする関数
func getOpenAIResponse(apiKey string) OpenaiResponse {
requestBody := OpenaiRequest{
Model: "gemma-3-4b-it",
Messages: messages,
}
requestJSON, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", openaiURL, bytes.NewBuffer(requestJSON))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
// req.Header.Set("Authorization", "Bearer "+apiKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
panic(err)
}
}(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
// fmt.Println(string(body))
var response OpenaiResponse
err = json.Unmarshal(body, &response)
if err != nil {
println("Error: ", err.Error())
return OpenaiResponse{}
}
messages = append(messages, Message{
Role: "assistant",
Content: response.Choices[0].Messages.Content,
})
return response
}
// main関数
func main() {
apiKey := "YOUR_API_KEY" // openAIに繋ぐときはAPI_KEYを入れる。
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print("Ask a question: ")
question, _ := reader.ReadString('\n')
question = strings.TrimSpace(question)
if question == "exit" {
break
}
messages = append(messages, Message{
Role: "user",
Content: question,
})
// fmt.Println(messages)
response := getOpenAIResponse(apiKey)
out, err := glamour.Render(response.Choices[0].Messages.Content, "dark")
if err != nil {
panic(err.Error())
}
fmt.Println(out)
}
}
以下、主要な部分の解説です
JSONフォーマットを定義
サーバーとの通信はJSON形式で行うため、そのフォーマットを定義しています。Goでは、構造体のフィールド名の先頭が大文字でなければエラーが発生しますので、注意が必要です。
OpenaiRequest:
Model
: 使用する言語モデルを指定します(例:gemma-3-4b-it
)。Messages
: 送信するメッセージの配列。ユーザーとアシスタントの対話履歴を格納します。
OpenaiResponse:
- APIから返されるレスポンスの形式。レスポンスには、選択肢やメッセージの内容が含まれます
Choice:
- レスポンス内での選択肢の詳細。メッセージ内容と終了理由を格納します
Message:
- 会話の1回分のメッセージ。
Role
(役割)とContent
(内容)を含んでいます
Usage:
- APIのトークン使用状況を管理します。
PromptTokens
やCompletionTokens
が含まれます
この部分は、基本的にOpenAIのAPIに準拠したフォーマットを設定してているだけです。
getOpenAIResponse
OpenAI互換のAPIを使ってLMStudioと通信する部分です。ユーザーとの対話ログからメッセージを作成し、サーバーに送信しています
リクエストの作成:
OpenaiRequest
構造体に、使用するモデル名と送信するメッセージを設定します- その後、
json.Marshal
でJSON形式に変換し、POSTリクエストとして送信します
HTTPリクエストの処理:
http.NewRequest
を使用して、POST
リクエストを作成します- ヘッダーには
Content-Type
をapplication/json
に設定し、ボディにJSONデータを含めます
レスポンスの受信と処理:
- サーバーからのレスポンスを読み取り、JSONとしてデコードします
- 取得した応答内容を次のメッセージに追加します
応答した内容を追加する点がポイントです。APIを経由して会話を行う場合、それまでの会話は記録されていないので、これまでの会話を全て含めて送信する必要があります。
main
この部分は、実際の会話の処理を行う部分です。無限ループを使用してユーザーからの入力を受け取り、その都度APIにリクエストを送信して応答を得ます。得られた応答は、glamour
ライブラリを使ってMarkdown形式で整形し、表示します。
その他
apiKeyの部分は、コメントアウトで残しています。apiKeyの部分を追加し、URLを変更すればOpenAIのモデルへアクセスさせることも可能です。ローカルLLMを使って、初期のデバッグを行い、ある程度完成してからOpenAIなどに接続といった開発フローを行うことを想定して残しました。
実行方法
実行は以下のコマンドでバイナリを作成してからchat
を実行します。
go build -o chat main.go
./chat
または、go run
を使って実行します。
go run main.go
実行結果
実行すると、Ask a question
と聞いてきますので、ここに質問を入力します。すると、しばらく待って回答が返ってきます。

終了する場合は、CTRL-C
でプログラムを中断させます。
まとめ
LMStudioをサーバーとして起動して、Go言語でアクセスする方法について解説しました。やってみると案外簡単です。自分のプログラムでLLMを利用したサービスをちょっと作る場合などに便利かもと思いました。