17
17
*/
18
18
package org .opensearch .searchpipelines .questionanswering .generative .ext ;
19
19
20
+ import static org .opensearch .core .xcontent .XContentParserUtils .ensureExpectedToken ;
21
+
20
22
import java .io .IOException ;
21
23
import java .util .Objects ;
22
24
23
- import org .opensearch .core .ParseField ;
24
25
import org .opensearch .core .common .Strings ;
25
26
import org .opensearch .core .common .io .stream .StreamInput ;
26
27
import org .opensearch .core .common .io .stream .StreamOutput ;
27
28
import org .opensearch .core .common .io .stream .Writeable ;
28
- import org .opensearch .core .xcontent .ObjectParser ;
29
29
import org .opensearch .core .xcontent .ToXContentObject ;
30
30
import org .opensearch .core .xcontent .XContentBuilder ;
31
31
import org .opensearch .core .xcontent .XContentParser ;
32
- import org .opensearch .searchpipelines .questionanswering .generative .GenerativeQAProcessorConstants ;
33
32
34
33
import com .google .common .base .Preconditions ;
35
34
35
+ import lombok .Builder ;
36
36
import lombok .Getter ;
37
37
import lombok .NoArgsConstructor ;
38
38
import lombok .Setter ;
45
45
@ NoArgsConstructor
46
46
public class GenerativeQAParameters implements Writeable , ToXContentObject {
47
47
48
- private static final ObjectParser <GenerativeQAParameters , Void > PARSER ;
49
-
50
48
// Optional parameter; if provided, conversational memory will be used for RAG
51
49
// and the current interaction will be saved in the conversation referenced by this id.
52
- private static final ParseField CONVERSATION_ID = new ParseField ( "memory_id" ) ;
50
+ private static final String CONVERSATION_ID = "memory_id" ;
53
51
54
52
// Optional parameter; if an LLM model is not set at the search pipeline level, one must be
55
53
// provided at the search request level.
56
- private static final ParseField LLM_MODEL = new ParseField ( "llm_model" ) ;
54
+ private static final String LLM_MODEL = "llm_model" ;
57
55
58
56
// Required parameter; this is sent to LLMs as part of the user prompt.
59
57
// TODO support question rewriting when chat history is not used (conversation_id is not provided).
60
- private static final ParseField LLM_QUESTION = new ParseField ( "llm_question" ) ;
58
+ private static final String LLM_QUESTION = "llm_question" ;
61
59
62
60
// Optional parameter; this parameter controls the number of search results ("contexts") to
63
61
// include in the user prompt.
64
- private static final ParseField CONTEXT_SIZE = new ParseField ( "context_size" ) ;
62
+ private static final String CONTEXT_SIZE = "context_size" ;
65
63
66
64
// Optional parameter; this parameter controls the number of the interactions to include
67
65
// in the user prompt.
68
- private static final ParseField INTERACTION_SIZE = new ParseField ( "message_size" ) ;
66
+ private static final String INTERACTION_SIZE = "message_size" ;
69
67
70
68
// Optional parameter; this parameter controls how long the search pipeline waits for a response
71
69
// from a remote inference endpoint before timing out the request.
72
- private static final ParseField TIMEOUT = new ParseField ( "timeout" ) ;
70
+ private static final String TIMEOUT = "timeout" ;
73
71
74
72
// Optional parameter: this parameter allows request-level customization of the "system" (role) prompt.
75
- private static final ParseField SYSTEM_PROMPT = new ParseField ( GenerativeQAProcessorConstants . CONFIG_NAME_SYSTEM_PROMPT ) ;
73
+ private static final String SYSTEM_PROMPT = "system_prompt" ;
76
74
77
75
// Optional parameter: this parameter allows request-level customization of the "user" (role) prompt.
78
- private static final ParseField USER_INSTRUCTIONS = new ParseField ( GenerativeQAProcessorConstants . CONFIG_NAME_USER_INSTRUCTIONS ) ;
76
+ private static final String USER_INSTRUCTIONS = "user_instructions" ;
79
77
80
78
// Optional parameter; this parameter indicates the name of the field in the LLM response
81
79
// that contains the chat completion text, i.e. "answer".
82
- private static final ParseField LLM_RESPONSE_FIELD = new ParseField ( "llm_response_field" ) ;
80
+ private static final String LLM_RESPONSE_FIELD = "llm_response_field" ;
83
81
84
82
public static final int SIZE_NULL_VALUE = -1 ;
85
83
86
- static {
87
- PARSER = new ObjectParser <>("generative_qa_parameters" , GenerativeQAParameters ::new );
88
- PARSER .declareString (GenerativeQAParameters ::setConversationId , CONVERSATION_ID );
89
- PARSER .declareString (GenerativeQAParameters ::setLlmModel , LLM_MODEL );
90
- PARSER .declareString (GenerativeQAParameters ::setLlmQuestion , LLM_QUESTION );
91
- PARSER .declareStringOrNull (GenerativeQAParameters ::setSystemPrompt , SYSTEM_PROMPT );
92
- PARSER .declareStringOrNull (GenerativeQAParameters ::setUserInstructions , USER_INSTRUCTIONS );
93
- PARSER .declareIntOrNull (GenerativeQAParameters ::setContextSize , SIZE_NULL_VALUE , CONTEXT_SIZE );
94
- PARSER .declareIntOrNull (GenerativeQAParameters ::setInteractionSize , SIZE_NULL_VALUE , INTERACTION_SIZE );
95
- PARSER .declareIntOrNull (GenerativeQAParameters ::setTimeout , SIZE_NULL_VALUE , TIMEOUT );
96
- PARSER .declareStringOrNull (GenerativeQAParameters ::setLlmResponseField , LLM_RESPONSE_FIELD );
97
- }
98
-
99
84
@ Setter
100
85
@ Getter
101
86
private String conversationId ;
@@ -132,6 +117,7 @@ public class GenerativeQAParameters implements Writeable, ToXContentObject {
132
117
@ Getter
133
118
private String llmResponseField ;
134
119
120
+ @ Builder
135
121
public GenerativeQAParameters (
136
122
String conversationId ,
137
123
String llmModel ,
@@ -148,7 +134,7 @@ public GenerativeQAParameters(
148
134
149
135
// TODO: keep this requirement until we can extract the question from the query or from the request processor parameters
150
136
// for question rewriting.
151
- Preconditions .checkArgument (!Strings .isNullOrEmpty (llmQuestion ), LLM_QUESTION . getPreferredName () + " must be provided." );
137
+ Preconditions .checkArgument (!Strings .isNullOrEmpty (llmQuestion ), LLM_QUESTION + " must be provided." );
152
138
this .llmQuestion = llmQuestion ;
153
139
this .systemPrompt = systemPrompt ;
154
140
this .userInstructions = userInstructions ;
@@ -172,16 +158,45 @@ public GenerativeQAParameters(StreamInput input) throws IOException {
172
158
173
159
@ Override
174
160
public XContentBuilder toXContent (XContentBuilder xContentBuilder , Params params ) throws IOException {
175
- return xContentBuilder
176
- .field (CONVERSATION_ID .getPreferredName (), this .conversationId )
177
- .field (LLM_MODEL .getPreferredName (), this .llmModel )
178
- .field (LLM_QUESTION .getPreferredName (), this .llmQuestion )
179
- .field (SYSTEM_PROMPT .getPreferredName (), this .systemPrompt )
180
- .field (USER_INSTRUCTIONS .getPreferredName (), this .userInstructions )
181
- .field (CONTEXT_SIZE .getPreferredName (), this .contextSize )
182
- .field (INTERACTION_SIZE .getPreferredName (), this .interactionSize )
183
- .field (TIMEOUT .getPreferredName (), this .timeout )
184
- .field (LLM_RESPONSE_FIELD .getPreferredName (), this .llmResponseField );
161
+ xContentBuilder .startObject ();
162
+ if (this .conversationId != null ) {
163
+ xContentBuilder .field (CONVERSATION_ID , this .conversationId );
164
+ }
165
+
166
+ if (this .llmModel != null ) {
167
+ xContentBuilder .field (LLM_MODEL , this .llmModel );
168
+ }
169
+
170
+ if (this .llmQuestion != null ) {
171
+ xContentBuilder .field (LLM_QUESTION , this .llmQuestion );
172
+ }
173
+
174
+ if (this .systemPrompt != null ) {
175
+ xContentBuilder .field (SYSTEM_PROMPT , this .systemPrompt );
176
+ }
177
+
178
+ if (this .userInstructions != null ) {
179
+ xContentBuilder .field (USER_INSTRUCTIONS , this .userInstructions );
180
+ }
181
+
182
+ if (this .contextSize != null ) {
183
+ xContentBuilder .field (CONTEXT_SIZE , this .contextSize );
184
+ }
185
+
186
+ if (this .interactionSize != null ) {
187
+ xContentBuilder .field (INTERACTION_SIZE , this .interactionSize );
188
+ }
189
+
190
+ if (this .timeout != null ) {
191
+ xContentBuilder .field (TIMEOUT , this .timeout );
192
+ }
193
+
194
+ if (this .llmResponseField != null ) {
195
+ xContentBuilder .field (LLM_RESPONSE_FIELD , this .llmResponseField );
196
+ }
197
+
198
+ xContentBuilder .endObject ();
199
+ return xContentBuilder ;
185
200
}
186
201
187
202
@ Override
@@ -200,7 +215,67 @@ public void writeTo(StreamOutput out) throws IOException {
200
215
}
201
216
202
217
public static GenerativeQAParameters parse (XContentParser parser ) throws IOException {
203
- return PARSER .parse (parser , null );
218
+ String conversationId = null ;
219
+ String llmModel = null ;
220
+ String llmQuestion = null ;
221
+ String systemPrompt = null ;
222
+ String userInstructions = null ;
223
+ Integer contextSize = null ;
224
+ Integer interactionSize = null ;
225
+ Integer timeout = null ;
226
+ String llmResponseField = null ;
227
+
228
+ ensureExpectedToken (XContentParser .Token .START_OBJECT , parser .currentToken (), parser );
229
+ while (parser .nextToken () != XContentParser .Token .END_OBJECT ) {
230
+ String field = parser .currentName ();
231
+ parser .nextToken ();
232
+
233
+ switch (field ) {
234
+ case CONVERSATION_ID :
235
+ conversationId = parser .text ();
236
+ break ;
237
+ case LLM_MODEL :
238
+ llmModel = parser .text ();
239
+ break ;
240
+ case LLM_QUESTION :
241
+ llmQuestion = parser .text ();
242
+ break ;
243
+ case SYSTEM_PROMPT :
244
+ systemPrompt = parser .text ();
245
+ break ;
246
+ case USER_INSTRUCTIONS :
247
+ userInstructions = parser .text ();
248
+ break ;
249
+ case CONTEXT_SIZE :
250
+ contextSize = parser .intValue ();
251
+ break ;
252
+ case INTERACTION_SIZE :
253
+ interactionSize = parser .intValue ();
254
+ break ;
255
+ case TIMEOUT :
256
+ timeout = parser .intValue ();
257
+ break ;
258
+ case LLM_RESPONSE_FIELD :
259
+ llmResponseField = parser .text ();
260
+ break ;
261
+ default :
262
+ parser .skipChildren ();
263
+ break ;
264
+ }
265
+ }
266
+
267
+ return GenerativeQAParameters
268
+ .builder ()
269
+ .conversationId (conversationId )
270
+ .llmModel (llmModel )
271
+ .llmQuestion (llmQuestion )
272
+ .systemPrompt (systemPrompt )
273
+ .userInstructions (userInstructions )
274
+ .contextSize (contextSize )
275
+ .interactionSize (interactionSize )
276
+ .timeout (timeout )
277
+ .llmResponseField (llmResponseField )
278
+ .build ();
204
279
}
205
280
206
281
@ Override
0 commit comments