0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LM Studio + OpenWebUI そして Javaプログラムからの接続

Last updated at Posted at 2025-10-25

LM Studio

今回はMacBookPro(m5) メモリ32GBの環境での実験
LM Studio は普通にインストールして、サーバ起動、ローカルネット接続の設定を実施します

image.png

ちなみにモデルは「llama-3-elyza-jp-8b」でやってみました

image.png

Open WebUI

あらかじめDockerを入れておいてから、ターミナルで以下を実行

docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main

localhost:3000 にアクセスして、

左下の名前をクリックして設定を選んで以下の管理者設定を選ぶ

image.png

接続タブの以下のあたりを設定する
image.png

この設定でこんな感じでチャットできるようになります
image.png

(おまけ)Javaからアクセス

LM StudioにJavaプログラムからアクセスするサンプルです

pom.xml

	    <dependency>
	        <groupId>com.squareup.okhttp3</groupId>
	        <artifactId>okhttp</artifactId>
	        <version>4.12.0</version>
	    </dependency>
	    <dependency>
	        <groupId>com.fasterxml.jackson.core</groupId>
	        <artifactId>jackson-databind</artifactId>
	    </dependency>

Javaソース

package com.example.demo;

import java.io.IOException;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

@SpringBootApplication
public class LmStudio1Application {

	// LM StudioのローカルサーバーURLとエンドポイント TODO:IPアドレスは設定する
    private static final String API_BASE_URL = "http://x.x.x.x:1234/v1/chat/completions";
    // LM Studioでロードしているモデルの識別子を設定
    private static final String MODEL_NAME = "llama-3-elyza-jp-8b";
    
	public static void main(String[] args) {

		String prompt = "Javaで、引数として渡された整数が素数かどうかを判定する関数を作成してください。";
        try {
            String responseText = getLlmResponse(prompt);
            System.out.println("--- LLMからの応答 ---");
            System.out.println(responseText);
        } catch (IOException e) {
            System.err.println("API呼び出し中にエラーが発生しました: " + e.getMessage());
            e.printStackTrace();
        }		
	}

	/**
     * LM StudioのOpenAI互換APIにリクエストを送信し、応答を解析する
     * @param userPrompt ユーザーからの質問や指示
     * @return モデルが生成したテキスト
     * @throws IOException ネットワークまたはI/Oエラーが発生した場合
     */
    private static String getLlmResponse(String userPrompt) throws IOException {
        // 1. OkHttpクライアントの準備
        OkHttpClient client = new OkHttpClient.Builder()
        		.connectTimeout(100, TimeUnit.SECONDS)	//タイムアウト設定
        		.readTimeout(100, TimeUnit.SECONDS)
        		.writeTimeout(100, TimeUnit.SECONDS)
        		.build();
        ObjectMapper mapper = new ObjectMapper();

        // 2. リクエストボディ (JSON) の構築
        // OpenAI Chat Completions API の形式: { "model": "...", "messages": [ { "role": "user", "content": "..." } ] }
        ObjectNode requestBody = mapper.createObjectNode();
        requestBody.put("model", MODEL_NAME); 
        // LM StudioはAPIキーを要求しないことが多いですが、互換性のためにダミーを送信しても問題ありません
        // requestBody.put("api_key", "dummy-key"); 

        ArrayNode messages = requestBody.putArray("messages");
        
        // システムプロンプト(必要に応じて。モデルの振る舞いを定義)
        ObjectNode systemMessage = messages.addObject();
        systemMessage.put("role", "system");
        systemMessage.put("content", "あなたは誠実で優秀なJavaプログラミングアシスタントです。常にコードブロックと日本語で回答してください。");

        // ユーザーからのプロンプト
        ObjectNode userMessage = messages.addObject();
        userMessage.put("role", "user");
        userMessage.put("content", userPrompt);
        
        // その他のパラメータ (任意)
        requestBody.put("temperature", 0.7);
        requestBody.put("max_tokens", 500);

        // 3. HTTPリクエストの作成
        RequestBody body = RequestBody.create(
            mapper.writeValueAsString(requestBody),
            MediaType.get("application/json; charset=utf-8")
        );

        Request request = new Request.Builder()
            .url(API_BASE_URL)
            .post(body)
            .build();

        // 4. リクエストの実行と応答の受信
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("予期しない応答コード: " + response + "\n応答本文: " + response.body().string());
            }

            // 5. 応答JSONの解析
            String jsonString = response.body().string();
            ObjectNode jsonResponse = (ObjectNode) mapper.readTree(jsonString);

            // LLMの応答テキストを抽出
            // 応答は "choices[0].message.content" に含まれている
            String content = jsonResponse
                .path("choices")
                .get(0)
                .path("message")
                .path("content")
                .asText();
            
            return content;
        }
    }	
}

実行結果

--- LLMからの応答 ---
以下は、Javaで整数が素数かどうかを判定する関数です。

```java
public class Main {
    public static void main(String[] args) {
        System.out.println(isPrime(25)); // false
        System.out.println(isPrime(23)); // true
    }

    public static boolean isPrime(int num) {
        if (num <= 1) {
            return false;
        }
        for (int i = 2; i * i <= num; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }
}
```

この関数 `isPrime(int num)` は、引数として渡された整数が素数かどうかを判定し、ブール値で返します。素数とは、1とその数自身以外に割り切れることがない自然数のことです。

`main(String[] args)` メソッドでは、テスト用に `isPrime(25)` と `isPrime(23)` を呼び出しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?