=================
== The Archive ==
=================

[Spring AI] ChatClient Responses

|

AI Summary

  • Spring AI ChatClient API는 ChatResponse 반환, 엔티티 반환, 스트리밍 응답의 세 가지 응답 방식을 제공한다.
  • ChatResponse는 메타데이터와 생성 결과를 포함하는 기본 응답 타입으로, 간단한 호출로 결과와 메타데이터를 확인할 수 있다.
  • entity() 메서드를 사용하면 AI 출력 결과를 Kotlin 데이터 클래스 같은 엔티티에 매핑하여 반환할 수 있으며, 제네릭 타입도 ParameterizedTypeReference로 처리 가능하다.
  • stream() 메서드를 활용하면 비동기 스트리밍 방식으로 문자열이나 ChatResponse 객체를 실시간으로 받아 처리할 수 있다.
  • 스트리밍 응답은 서버에서 텍스트 이벤트 스트림 형식으로 전송되며, 컨트롤러에서 MediaType.TEXT_EVENT_STREAM_VALUE로 처리한다.
  • 이 세 가지 방식은 각각의 상황에 맞게 응답 데이터를 구조화하거나 실시간으로 처리하는 데 유용하게 활용할 수 있다.
Updated: 2025-11-22 15:37 UTC

Introduction

ChatResponse 을 반환

1
2
3
4
5
6
fun returningAChatResponse(userInput: String): ChatResponse =
    chatClientAutoconfigured
        .prompt()
        .user(userInput)
        .call()
        .chatResponse()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
  "result": {
    "output": {
      "messageType": "ASSISTANT",
      "metadata": {
        "refusal": "",
        "finishReason": "STOP",
        "index": 0,
        "id": "chatcmpl-AAi19k1lzSFPpCSnJJp0vuEoeKOHl",
        "role": "ASSISTANT",
        "messageType": "ASSISTANT"
      },
      "toolCalls": [],
      "content": "Sure! Here's a light-hearted joke for you:\n\nWhy don’t skeletons fight each other?\n\nThey don’t have the guts!"
    },
    "metadata": {
      "finishReason": "STOP",
      "contentFilterMetadata": null
    }
  },
  "metadata": {
    "id": "chatcmpl-AAi19k1lzSFPpCSnJJp0vuEoeKOHl",
    "model": "gpt-4o-2024-05-13",
    "rateLimit": {
      "requestsLimit": 500,
      "requestsRemaining": 499,
      "tokensLimit": 30000,
      "tokensRemaining": 29979,
      "requestsReset": "PT0.12S",
      "tokensReset": "PT0.042S"
    },
    "usage": {
      "promptTokens": 11,
      "generationTokens": 26,
      "totalTokens": 37
    },
    "promptMetadata": [],
    "empty": false
  },
  "results": [
    {
      "output": {
        "messageType": "ASSISTANT",
        "metadata": {
          "refusal": "",
          "finishReason": "STOP",
          "index": 0,
          "id": "chatcmpl-AAi19k1lzSFPpCSnJJp0vuEoeKOHl",
          "role": "ASSISTANT",
          "messageType": "ASSISTANT"
        },
        "toolCalls": [],
        "content": "Sure! Here's a light-hearted joke for you:\n\nWhy don’t skeletons fight each other?\n\nThey don’t have the guts!"
      },
      "metadata": {
        "finishReason": "STOP",
        "contentFilterMetadata": null
      }
    }
  ]
}

Entity 를 반환

1
2
3
4
data class MathematicianPublications(
    val mathematician: String = "",
    val papers: List<String> = emptyList(),
)
1
2
3
4
5
6
fun returningAnEntity(): MathematicianPublications =
    chatClientAutoconfigured
        .prompt()
        .user("Generate the publications for a random mathematician.")
        .call()
        .entity(MathematicianPublications::class.java)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "mathematician": "Dr. John Doe",
  "papers": [
    "On the Convergence of Series in Hilbert Spaces",
    "A New Approach to Nonlinear Differential Equations",
    "Topological Methods in Algebraic Geometry",
    "The Role of Symmetry in Partial Differential Equations",
    "An Introduction to Modular Forms and Their Applications",
    "Advanced Techniques in Combinatorial Optimization",
    "Conformal Invariance and Critical Phenomena in Statistical Mechanics",
    "Stochastic Processes and Their Applications in Finance",
    "An Algebraic Perspective on Knot Theory",
    "Geometric Group Theory and Low-Dimensional Topology"
  ]
}

제네릭 타입의 엔티티를 반환

스트리밍 응답을 반환

기본적인 비동기 응답

스트리밍된 ChatResponse 응답

엔티티 응답

Categories:

Tags: