LoginSignup
0
2

More than 1 year has passed since last update.

Spring Boot でストリーム(SSE)対応する Azure OpenAI Service の API サーバを実装する

Posted at

背景

  • 社内で ChatGPT のようなサービスを展開したい
  • OpenAI の API と互換性がある Azure OpenAI Service を使いたい
    • 以下 AOAI
  • フロントの UI がオープンソースで複数公開されているが、API キーを入力するものが多い
  • 社内で展開する場合、API キーは隠蔽したい
  • フロント>実装するAPIサーバ>AOAI API とう構成でバックエンドに API キーを隠蔽
    • 中継 API サーバを立てるイメージ
  • APIサーバを実装する際、ストリーム(SSE)対応したい
    • それにより、レスポンスが徐々に生成される UX を実現できる

手順

Spring Boot プロジェクトの新規作成

  • https://start.spring.io/ を開き、Dependencies に「Spring Reactive Web」を指定
    image.png

  • または build.gradle などに spring-boot-starter-webflux を指定

    dependencies {
    	implementation 'org.springframework.boot:spring-boot-starter-webflux'
    }
    

ストリーム対応する AOAI の API を実行するためのクライアント準備する Config を作成

Config.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class AppConfig {
	@Bean
	public WebClient webClient() {
		return WebClient.builder().build();
	}
}

フロントからのリクエストを受け取り、AOAI の API を実行するコントローラを作成

Controller.java
package jp.co.saison.chatbackend.controller;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

@RestController
@CrossOrigin(origins = "${app.allowedOrigins}")
public class CompletionsController {
	private final WebClient webClient;

	public CompletionsController(WebClient webClient) {
		this.webClient = webClient;
	}

	@PostMapping(value = "/api/completions", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
	public Flux<String> completionsForStream(@RequestBody String body) {
		Flux<String> responseFlux = webClient.post()
				.uri("Azure OpeanAI サービス API のエンドポイント")
				.contentType(MediaType.APPLICATION_JSON)
				.header("api-key", "APIキー")
				.bodyValue(body)
				.retrieve()
				.bodyToFlux(String.class);
		return responseFlux;
	}
}
0
2
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
2