11package com .back .domain .chatbot .dto ;
22
3- import lombok .Getter ;
4- import lombok .Setter ;
3+ import lombok .*;
54
65import java .util .List ;
76
109public class GeminiRequestDto {
1110
1211 private List <Content > contents ;
12+ private GenerationConfig generationConfig ;
13+ private List <SafetySetting > safetySettings ;
1314
1415 @ Getter
1516 @ Setter
@@ -31,7 +32,156 @@ public Part(String text) {
3132 }
3233 }
3334
35+ @ Getter
36+ @ Setter
37+ @ Builder
38+ @ NoArgsConstructor
39+ @ AllArgsConstructor
40+ public static class GenerationConfig { // 생성 설정
41+ /**
42+ * Temperature (0.0 ~ 2.0)
43+ * - 낮을수록 (0.0): 일관되고 예측 가능한 응답
44+ * - 높을수록 (2.0): 창의적이고 다양한 응답
45+ * - 권장값: 0.7 ~ 1.0
46+ */
47+ private Double temperature ;
48+
49+ /**
50+ * Top-P (0.0 ~ 1.0)
51+ * - 누적 확률 임계값
52+ * - 0.95 = 상위 95% 확률의 토큰만 고려
53+ * - 낮을수록 더 집중된 응답
54+ */
55+ private Double topP ;
56+
57+ /**
58+ * Top-K (1 ~ 40)
59+ * - 고려할 토큰의 최대 개수
60+ * - 40 = 상위 40개 토큰만 고려
61+ * - 낮을수록 더 결정적인 응답
62+ */
63+ private Integer topK ;
64+
65+ /**
66+ * Max Output Tokens
67+ * - 응답의 최대 토큰 수 (출력 길이 제한)
68+ * - Gemini 1.5 Flash: 최대 8192 토큰
69+ * - Gemini 1.5 Pro: 최대 8192 토큰
70+ * - 한글 1글자 ≈ 1-2 토큰, 영어 3-4글자 ≈ 1 토큰
71+ */
72+ private Integer maxOutputTokens ;
73+
74+ /**
75+ * Stop Sequences
76+ * - 이 문자열을 만나면 생성 중단
77+ * - 예: ["끝", "END", "\n\n"]
78+ */
79+ private List <String > stopSequences ;
80+
81+ /**
82+ * Candidate Count (1 ~ 8)
83+ * - 생성할 응답 후보의 개수
84+ * - 여러 개 생성 후 최적 선택 가능
85+ */
86+ private Integer candidateCount ;
87+ }
88+
89+ @ Getter
90+ @ Setter
91+ @ Builder
92+ @ NoArgsConstructor
93+ @ AllArgsConstructor
94+ public static class SafetySetting {
95+ private String category ;
96+ private String threshold ;
97+
98+ // 카테고리 상수
99+ public static final String HARM_CATEGORY_HARASSMENT = "HARM_CATEGORY_HARASSMENT" ;
100+ public static final String HARM_CATEGORY_HATE_SPEECH = "HARM_CATEGORY_HATE_SPEECH" ;
101+ public static final String HARM_CATEGORY_SEXUALLY_EXPLICIT = "HARM_CATEGORY_SEXUALLY_EXPLICIT" ;
102+ public static final String HARM_CATEGORY_DANGEROUS_CONTENT = "HARM_CATEGORY_DANGEROUS_CONTENT" ;
103+
104+ // 임계값 상수
105+ public static final String BLOCK_NONE = "BLOCK_NONE" ; // 차단 안함
106+ public static final String BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE" ; // 낮음 이상 차단
107+ public static final String BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE" ; // 중간 이상 차단
108+ public static final String BLOCK_HIGH = "BLOCK_ONLY_HIGH" ; // 높음만 차단
109+ }
110+
111+ // 기본 생성자 - 간단한 텍스트만
34112 public GeminiRequestDto (String message ) {
35113 this .contents = List .of (new Content (message ));
36114 }
115+
116+ // 파라미터 설정 포함 생성자
117+ public GeminiRequestDto (String message , GenerationConfig config ) {
118+ this .contents = List .of (new Content (message ));
119+ this .generationConfig = config ;
120+ }
121+
122+ // 전체 설정 포함 생성자
123+ public GeminiRequestDto (String message , GenerationConfig config , List <SafetySetting > safetySettings ) {
124+ this .contents = List .of (new Content (message ));
125+ this .generationConfig = config ;
126+ this .safetySettings = safetySettings ;
127+ }
128+
129+ public static GeminiRequestDto createForCocktailChat (String message , boolean isDetailedResponse ) {
130+ GenerationConfig config = GenerationConfig .builder ()
131+ .temperature (0.8 ) // 적당한 창의성
132+ .topP (0.95 ) // 상위 95% 토큰 고려
133+ .topK (40 ) // 상위 40개 토큰
134+ .maxOutputTokens (isDetailedResponse ? 300 : 150 ) // 상세 답변 vs 간단 답변
135+ .candidateCount (1 ) // 하나의 응답만
136+ .stopSequences (List .of ("끝." , "이상입니다." )) // 종료 구문
137+ .build ();
138+
139+ // 안전 설정 (칵테일 관련이므로 비교적 관대하게)
140+ List <SafetySetting > safetySettings = List .of (
141+ SafetySetting .builder ()
142+ .category (SafetySetting .HARM_CATEGORY_HARASSMENT )
143+ .threshold (SafetySetting .BLOCK_MEDIUM_AND_ABOVE )
144+ .build (),
145+ SafetySetting .builder ()
146+ .category (SafetySetting .HARM_CATEGORY_HATE_SPEECH )
147+ .threshold (SafetySetting .BLOCK_MEDIUM_AND_ABOVE )
148+ .build (),
149+ SafetySetting .builder ()
150+ .category (SafetySetting .HARM_CATEGORY_SEXUALLY_EXPLICIT )
151+ .threshold (SafetySetting .BLOCK_MEDIUM_AND_ABOVE )
152+ .build (),
153+ SafetySetting .builder ()
154+ .category (SafetySetting .HARM_CATEGORY_DANGEROUS_CONTENT )
155+ .threshold (SafetySetting .BLOCK_LOW_AND_ABOVE ) // 음주 관련이므로 더 엄격
156+ .build ()
157+ );
158+
159+ return new GeminiRequestDto (message , config , safetySettings );
160+ }
161+
162+ // 간결한 답변용 프리셋
163+ public static GeminiRequestDto createBriefResponse (String message ) {
164+ GenerationConfig config = GenerationConfig .builder ()
165+ .temperature (0.5 ) // 더 일관된 답변
166+ .topP (0.8 ) // 더 집중된 선택
167+ .topK (20 ) // 적은 선택지
168+ .maxOutputTokens (100 ) // 짧은 답변
169+ .candidateCount (1 )
170+ .build ();
171+
172+ return new GeminiRequestDto (message , config );
173+ }
174+
175+ // 창의적 답변용 프리셋
176+ public static GeminiRequestDto createCreativeResponse (String message ) {
177+ GenerationConfig config = GenerationConfig .builder ()
178+ .temperature (1.2 ) // 높은 창의성
179+ .topP (0.98 ) // 더 다양한 선택
180+ .topK (40 ) // 많은 선택지
181+ .maxOutputTokens (500 ) // 긴 답변 허용
182+ .candidateCount (1 )
183+ .build ();
184+
185+ return new GeminiRequestDto (message , config );
186+ }
37187}
0 commit comments