この記事では、Spring BootアプリケーションでChatGLM3-6bモデルと連携する方法について説明します。他のモデルとの接続方法も同様に応用できます。
モデルパラメータの確認
ここでは、アリクラウドから提供された文書に基づいて、モデルパラメータを設定します。HTTPリクエストを使用して非SDK方式でAPIを呼び出します。
以下のサンプルリクエストを見ていきます:
curl --location 'https://example.com/api/v1/services/aigc/text-generation' \
--header 'Authorization: Bearer <YOUR-API-KEY>' \
--header 'Content-Type: application/json' \
--header 'X-SSE-Enable: true' \
--data '{
"model": "chatglm3-6b",
"input": {
"messages": [
{
"role": "user",
"content": "こんにちは、東京タワーについて教えてください"
}
]
},
"parameters": {
"result_format": "message"
}
}'
コード実装
1. レスポンスクラスの作成
レスポンスデータをデシリアライズするためのJavaクラスを作成します。
import lombok.Data;
@Data
public class ChatResponse {
private Output output;
private Usage usage;
private String requestId;
@Data
public static class Output {
private Choice[] choices;
@Data
public static class Choice {
private Message message;
private String finishReason;
@Data
public static class Message {
private String content;
private String role;
}
}
}
@Data
public static class Usage {
private int totalTokens;
private int inputTokens;
private int outputTokens;
}
}
2. イベントリスナーの作成
イベントリスナーを定義し、SSE(サーバーサイドイベント)の受信処理を行います。
import com.alibaba.fastjson.JSONObject;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SSEEventListener extends EventSourceListener {
private static final Logger logger = LoggerFactory.getLogger(SSEEventListener.class);
private String clientId;
@Override
public void onEvent(EventSource eventSource, String id, String type, String data) {
logger.info("SSEEventListener onEvent invoke");
ChatResponse response = JSONObject.parseObject(data, ChatResponse.class);
for (ChatResponse.Output.Choice choice : response.getOutput().choices) {
if ("stop".equals(choice.finishReason)) {
eventSource.cancel();
logger.info("Stream completed.");
return;
}
logger.info("Message: {}", choice.message.content);
}
}
}
3. APIコントローラの作成
Spring BootのコントローラでAPIを定義します。
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@RestController
@RequestMapping("/api/chat")
public class ChatController {
@PostMapping("/send")
public SseEmitter sendMessage(@RequestParam String user, @RequestParam String text) {
SseEmitter emitter = new SseEmitter();
OkHttpClient client = new OkHttpClient();
// JSONオブジェクトの作成
JSONObject payload = new JSONObject();
payload.put("model", "chatglm3-6b");
payload.put("input", new JSONObject().put("messages",
new JSONArray().add(new JSONObject()
.put("role", "user")
.put("content", text)
)
));
payload.put("parameters", new JSONObject().put("result_format", "message"));
RequestBody body = RequestBody.create(MediaType.parse("application/json"), payload.toJSONString());
Request request = new Request.Builder()
.url("https://example.com/api/v1/services/aigc/text-generation")
.post(body)
.addHeader("Authorization", "Bearer YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.addHeader("X-SSE-Enable", "true")
.build();
EventSource.Factory factory = EventSources.createFactory(client);
EventSource.Listener listener = new SSEEventListener();
EventSource eventSource = factory.newEventSource(request, listener);
eventSource.request();
return emitter;
}
}
4. フロントエンドの実装
簡単なHTMLとJavaScriptを使用してフロントエンドを構築します。
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>SSEチャット</title>
</head>
<body>
<h1>チャット</h1>
<div id="chat-area"></div>
<form id="message-form">
<input type="text" id="message-input" placeholder="メッセージを入力">
<button type="submit">送信</button>
</form>
<script>
const chatArea = document.getElementById('chat-area');
const form = document.getElementById('message-form');
const input = document.getElementById('message-input');
form.addEventListener('submit', function(event) {
event.preventDefault();
const msg = input.value.trim();
if (msg) {
fetch('/api/chat/send?user=test&text=' + encodeURIComponent(msg), { method: 'POST' })
.then(response => response.text())
.then(data => displayMessage(data))
.catch(error => console.error('Error:', error));
input.value = '';
}
});
function displayMessage(message) {
const div = document.createElement('div');
div.textContent = message;
chatArea.appendChild(div);
}
</script>
</body>
</html>