APIテスト
APIの利用設定
APIを使用するためには「LM Studio」のサーバー機能を次の様に有効化します。
画面右上の4つのアイコンから「Developer」を選択して設定を開始します。
一番上の「Local Server」を選択します。
「 + Load Model」ボタンを押して使用するモデルをロードします。
「Status Stoppend」スイッチを「ON」としてサーバーを起動します。
Developer Logsにログが出て来るので動作を確認してください。
テスト用のiOSアプリの制作
LLMサーバーと通信する簡単なチャットアプリを制作します。
アプリは、単純にメッセージを送信して結果を受け取るというシンプルな物です。
以下は今回制作したテストアプリのコードです。
iOS 26.0でビルドしてにiOS 26.4のシミュレータで動作確認しています。
ソースコード全ソースコード
//
// ContentView.swift
// ML ClientTest
//
// Created by Masahiko Tani on 2026/04/05.
//
import SwiftUI
import Foundation
struct ContentView: View {
@State private var message = "" // 入力テキストを保持するステート変数
@State private var chatMessages: [ContentView.ChatMessage] = []
var body: some View {
VStack {
// テキストフィールド (入力欄)
TextField("Enter message...", text: $message)
.padding()
// 送信ボタン
Button("送信") {
sendMessage()
}
.padding()
// チャットメッセージの表示
ScrollView { // 縦にスクロールできるようにScrollViewを追加
LazyVStack { // 効率的な表示のためにLazyVStackを使用
ForEach(chatMessages) { message in
// let markdown = message.text
// Text(try! AttributedString(markdown: markdown))
Text(.init(message.text)) // markdown
}
}
}
}
}
func sendMessage() {
guard !message.isEmpty else { return } // 空のメッセージは送信しない
let url = URL(string: "http://127.0.0.1:1234/api/v1/chat")! // LM StudioのAPIエンドポイント
var request = URLRequest(url: url)
request.httpMethod = "POST" // POSTメソッドを使用
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let chat = ChatRequest(input: message)
do {
request.httpBody = try JSONEncoder().encode(chat)
} catch {
// エンコード失敗時はここで処理
print("JSONエンコードに失敗しました: \(error)")
}
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
do {
handleServerResponse(data: data)
// let json = try JSONDecoder().decode(String.self, from: data!) // サーバーからのJSON文字列をデコード
// DispatchQueue.main.async {
// let message = ContentView.ChatMessage(text: "You: \(json)", isUser: true)
// self.chatMessages.append(message)
// }
} catch {
DispatchQueue.main.async {
let errorMsg = ContentView.ChatMessage(
text: "Error: \(error.localizedDescription)",
isUser: false // エラーは「Bot」側として扱う
)
self.chatMessages.append(errorMsg)
debugPrint(errorMsg.text)
}
}
}
task.resume()
// 入力テキストをクリア
message = ""
}
// data はサーバーから受け取った `Data`(URLSession などで取得)
func handleServerResponse(data: Data?) {
guard let data = data else { return }
do {
// ① JSON を `ChatResponse` にデコード
let chatResp = try JSONDecoder().decode(ChatResponse.self, from: data)
// ② type が "message" の要素を取得
if let messageOutput = chatResp.output.first(where: { $0.type == "message" }) {
let serverMessage = messageOutput.content
// ③ UI スレッドへ渡す
DispatchQueue.main.async {
let message = ContentView.ChatMessage(text: "You: \(serverMessage)", isUser: true)
self.chatMessages.append(message)
}
} else {
// "message" が見つからない場合のフォールバック
let errorMsg = ContentView.ChatMessage(
text: "⚠️ 返答に message がありませんでした",
isUser: false // エラーは「Bot」側として扱う
)
self.chatMessages.append(errorMsg)
debugPrint(errorMsg.text)
}
} catch {
DispatchQueue.main.async {
let errorMsg = ContentView.ChatMessage(
text: "Error: \(error.localizedDescription)",
isUser: false // エラーは「Bot」側として扱う
)
self.chatMessages.append(errorMsg)
debugPrint(errorMsg.text)
}
}
}
struct ChatMessage: Identifiable {
let id = UUID()
let text: String
let isUser: Bool // true なら「You」、false なら「Bot」
}
// 2. JSON オブジェクトに包む
struct ChatRequest: Codable {
let input: String
// let temperature: number // 任意(デフォルト 1.0) -生成のランダム性を調整 (0〜2)
// let max_tokens: integer // 任意(デフォルト 512) -生成テキストの最大トークン数
var model: String = "openai/gpt-oss-20b"
}
/// 最外層
struct ChatResponse: Codable {
let model_instance_id: String
let output: [ChatOutput]
let stats: ChatStats
let response_id: String
}
/// output 配列の要素
struct ChatOutput: Codable {
let type: String // "reasoning" / "message"
let content: String
}
/// stats の情報(必要なら取り込めます)
struct ChatStats: Codable {
let input_tokens: Int
let total_output_tokens: Int
let reasoning_output_tokens: Int
let tokens_per_second: Double
let time_to_first_token_seconds: Double
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
コードの説明
bodyでは、大まかなUIを定義しています。
テキストフィールド (入力欄)/送信ボタン/チャットメッセージの表示などです。
var body: some View
送信ボタンが押されるとsendMessageが呼ばれ、入力されたメッセージをJSONエンコードしてhttpのPOSTで送ります。
func sendMessage()





