Spring AI 사용해보기

Garam·2024년 9월 18일

참고 - Spring AI 공식문서

dependencies

  • 아직 snapshot ver.
  • Chat Client가 openAI로 autoconfigured된 버전
repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
    maven { url 'https://repo.spring.io/snapshot' }
}

dependencies {
    implementation platform("org.springframework.ai:spring-ai-bom:1.0.0-SNAPSHOT")
    implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'
}

  • application.properties for OpenAI

https://docs.spring.io/spring-ai/reference/api/chat/openai-chat.html

// API KEY 설정
spring.ai.openai.api-key=SECRET_KEY

// 기타 옵션 설정
spring.ai.openai.chat.options.model
spring.ai.openai.chat.options.temperature
spring.ai.openai.chat.options.frequencyPenalty
...



Chat Client API

  • 프롬프트 생성 API
  • AI Model과 소통하기 위한 fluent API를 제공한다.
    • fluent API란 메소드 체이닝에 기반한 객체 지향 API 설계 메소드
    • Builder 생성자를 떠올려보면 쉽다
    • 이 fluent API는 프롬프트의 구성 요소를 빌드하는 메소드를 제공한다.
  • 프롬프트는 메시지들의 Collection으로 이루어져 있다. 메시지의 메인 유형 2가지는 다음과 같다.
    • user message: 사용자로부터 직접 입력받은 메시지
    • system message: 시스템으로부터 생성된 대화 방식의 가이드라인
  • 프롬프트에는 AI model의 이름이나 temperature등의 옵션을 세팅 할 수 있다.

autoconfigured ChatClient.Builder

@RestController
class MyController {

    private final ChatClient chatClient;

    public MyController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @GetMapping("/ai")
    String generation(String userInput) {
        return this.chatClient.prompt()
            .user(userInput)
            .call()                // AI 모델에게 request룰 보낸다
            .content();            // AI 모델의 response를 String으로 리턴한다
    }
}

기본 셋팅된 ChatClient.Builder 대신 커스텀 생성하기

  • spring.ai.chat.client.enabled=false 추가
  • 보통 여러 모델을 한번에 사용해야 할 때 유용하다
ChatModel myChatModel = ... // usually autowired
ChatClient.Builder builder = ChatClient.builder(myChatModel);

// or create a ChatClient with the default builder settings:
ChatClient chatClient = ChatClient.create(myChatModel);

응답 반환받기

  • .call()로 응답받기

    • 응답의 content를 String으로 반환받음
  • ChatResponse 객체로 응답받기

ChatResponse chatResponse = chatClient.prompt()
    .user("Tell me a joke")
    .call()
    .chatResponse()
// 하나의 프롬프트에서 생성된 1개 이상의 output을 포함한 Generation 인스턴스들로 이루어짐
// 또한 AI 모델의 reponse의 ChatResponseMetadata를 포함하고 있음 (예: 생성된 토큰 수)
public class ChatResponse implements ModelResponse<Generation> {

  private final ChatResponseMetadata chatResponseMetadata;
	private final List<Generation> generations;

	@Override
	public ChatResponseMetadata getMetadata() {...}

  @Override
	public List<Generation> getResults() {...}

  // other methods omitted
}
// assistant message와 metadata를 가지고 있음
public class Generation implements ModelResult<AssistantMessage> {

	private AssistantMessage assistantMessage;
	private ChatGenerationMetadata chatGenerationMetadata;

	@Override
	public AssistantMessage getOutput() {...}

	@Override
	public ChatGenerationMetadata getMetadata() {...}

  // other methods omitted
}
  • 엔티티로 반환받기
    • 자동으로 파싱해서 넣어준다는 의미로 추정
record ActorFilms(String actor, List<String> movies) {
}

ActorFilms actorFilms = chatClient.prompt()
    .user("Generate the filmography for a random actor.")
    .call()
    .entity(ActorFilms.class);

Config

@Configuration
class Config {

    @Bean
    ChatClient chatClient(ChatClient.Builder builder) {
        return builder.defaultSystem("You are a friendly chat bot that answers question in the voice of a Pirate")
                .build();
    }
}
  • defaultOptions - ChatOptions 설정



Chat Model API

  • 사전 학습된 언어 모델을 애플리케이션에 적용할 수 있도록 해주는 API
  • 다양한 모델들과 통합된 방식으로 소통할 수 있도록 지원함
  • prompt나 대화의 일부분을 AI model에게 보내고 생성된 completion이나 대화를 ChatResponse를 통해 애플리케이션으로 끌어온다.
    • Prompt for input
    • ChatResponse for output
  • request를 준비하거나 reponse를 파싱하는 데에 드는 시간과 비용을 줄여준다.
public interface ChatModel extends Model<Prompt, ChatResponse> {

	default String call(String message) {// implementation omitted
	}

  @Override
	ChatResponse call(Prompt prompt);
}


Runtime Options

ChatResponse response = chatModel.call(
    new Prompt(
        "Generate the names of 5 famous pirates.",
        OpenAiChatOptions.builder()
            .withModel("gpt-4-o")
            .withTemperature(0.4)
        .build()
    ));



0개의 댓글