2525import io .micrometer .observation .contextpropagation .ObservationThreadLocalAccessor ;
2626import org .slf4j .Logger ;
2727import org .slf4j .LoggerFactory ;
28- import org .springframework .ai .chat .messages .UserMessage ;
28+ import org .springframework .ai .chat .messages .* ;
2929import org .springframework .ai .hunyuan .api .HunYuanApi ;
3030import org .springframework .ai .hunyuan .api .HunYuanApi .*;
3131import org .springframework .ai .hunyuan .api .HunYuanApi .ChatCompletionMessage .*;
3535import reactor .core .publisher .Flux ;
3636import reactor .core .publisher .Mono ;
3737
38- import org .springframework .ai .chat .messages .AssistantMessage ;
39- import org .springframework .ai .chat .messages .MessageType ;
40- import org .springframework .ai .chat .messages .ToolResponseMessage ;
4138import org .springframework .ai .chat .metadata .ChatGenerationMetadata ;
4239import org .springframework .ai .chat .metadata .ChatResponseMetadata ;
4340import org .springframework .ai .chat .metadata .EmptyUsage ;
@@ -100,17 +97,17 @@ public class HunYuanChatModel extends AbstractToolCallSupport implements ChatMod
10097
10198 /**
10299 * Initializes a new instance of the HunYuanChatModel.
103- * @param hunYuanApi The HunYuan instance to be used for interacting with the
104- * HunYuan Chat API.
100+ * @param hunYuanApi The HunYuan instance to be used for interacting with the HunYuan
101+ * Chat API.
105102 */
106103 public HunYuanChatModel (HunYuanApi hunYuanApi ) {
107104 this (hunYuanApi , HunYuanChatOptions .builder ().model (HunYuanApi .DEFAULT_CHAT_MODEL ).build ());
108105 }
109106
110107 /**
111108 * Initializes a new instance of the HunYuanChatModel.
112- * @param hunYuanApi The HunYuan instance to be used for interacting with the
113- * HunYuan Chat API.
109+ * @param hunYuanApi The HunYuan instance to be used for interacting with the HunYuan
110+ * Chat API.
114111 * @param options The HunYuanChatOptions to configure the chat client.
115112 */
116113 public HunYuanChatModel (HunYuanApi hunYuanApi , HunYuanChatOptions options ) {
@@ -119,31 +116,31 @@ public HunYuanChatModel(HunYuanApi hunYuanApi, HunYuanChatOptions options) {
119116
120117 /**
121118 * Initializes a new instance of the HunYuanChatModel.
122- * @param hunYuanApi The HunYuan instance to be used for interacting with the
123- * HunYuan Chat API.
119+ * @param hunYuanApi The HunYuan instance to be used for interacting with the HunYuan
120+ * Chat API.
124121 * @param options The HunYuanChatOptions to configure the chat client.
125122 * @param functionCallbackResolver The function callback resolver to resolve the
126123 * function by its name.
127124 * @param retryTemplate The retry template.
128125 */
129126 public HunYuanChatModel (HunYuanApi hunYuanApi , HunYuanChatOptions options ,
130- FunctionCallbackResolver functionCallbackResolver , RetryTemplate retryTemplate ) {
127+ FunctionCallbackResolver functionCallbackResolver , RetryTemplate retryTemplate ) {
131128 this (hunYuanApi , options , functionCallbackResolver , List .of (), retryTemplate , ObservationRegistry .NOOP );
132129 }
133130
134131 /**
135132 * Initializes a new instance of the HunYuanChatModel.
136- * @param hunYuanApi The HunYuan instance to be used for interacting with the
137- * HunYuan Chat API.
133+ * @param hunYuanApi The HunYuan instance to be used for interacting with the HunYuan
134+ * Chat API.
138135 * @param options The HunYuanChatOptions to configure the chat client.
139136 * @param functionCallbackResolver resolves the function by its name.
140137 * @param toolFunctionCallbacks The tool function callbacks.
141138 * @param retryTemplate The retry template.
142139 * @param observationRegistry The ObservationRegistry used for instrumentation.
143140 */
144141 public HunYuanChatModel (HunYuanApi hunYuanApi , HunYuanChatOptions options ,
145- FunctionCallbackResolver functionCallbackResolver , List <FunctionCallback > toolFunctionCallbacks ,
146- RetryTemplate retryTemplate , ObservationRegistry observationRegistry ) {
142+ FunctionCallbackResolver functionCallbackResolver , List <FunctionCallback > toolFunctionCallbacks ,
143+ RetryTemplate retryTemplate , ObservationRegistry observationRegistry ) {
147144 super (functionCallbackResolver , options , toolFunctionCallbacks );
148145 Assert .notNull (hunYuanApi , "HunYuanApi must not be null" );
149146 Assert .notNull (options , "Options must not be null" );
@@ -167,7 +164,7 @@ private static Generation buildGeneration(Choice choice, Map<String, Object> met
167164 .toList ();
168165
169166 var assistantMessage = new AssistantMessage (choice .message ().content (), metadata , toolCalls );
170- String finishReason = (choice .finishReason () != null ? choice .finishReason (): "" );
167+ String finishReason = (choice .finishReason () != null ? choice .finishReason () : "" );
171168 var generationMetadata = ChatGenerationMetadata .builder ().finishReason (finishReason ).build ();
172169 return new Generation (assistantMessage , generationMetadata );
173170 }
@@ -213,7 +210,8 @@ public ChatResponse call(Prompt prompt) {
213210 return buildGeneration (choice , metadata );
214211 }).toList ();
215212
216- ChatResponse chatResponse = new ChatResponse (generations , from (request ,completionEntity .getBody ().response ()));
213+ ChatResponse chatResponse = new ChatResponse (generations ,
214+ from (request , completionEntity .getBody ().response ()));
217215
218216 observationContext .setResponse (chatResponse );
219217
@@ -292,8 +290,9 @@ public Flux<ChatResponse> stream(Prompt prompt) {
292290 }));
293291
294292 Flux <ChatResponse > flux = chatResponse .flatMap (response -> {
295- if (!isProxyToolCalls (prompt , this .defaultOptions ) && isToolCall (response ,
296- Set .of (ChatCompletionFinishReason .TOOL_CALLS .getJsonValue (), ChatCompletionFinishReason .STOP .getJsonValue ()))) {
293+ if (!isProxyToolCalls (prompt , this .defaultOptions )
294+ && isToolCall (response , Set .of (ChatCompletionFinishReason .TOOL_CALLS .getJsonValue (),
295+ ChatCompletionFinishReason .STOP .getJsonValue ()))) {
297296 var toolCallConversation = handleToolCalls (prompt , response );
298297 // Recursively call the stream method with the tool call message
299298 // conversation that contains the call responses.
@@ -325,21 +324,22 @@ private ChatResponseMetadata from(ChatCompletionRequest request, ChatCompletion
325324 * @return the ChatCompletion
326325 */
327326 private ChatCompletion chunkToChatCompletion (ChatCompletionChunk chunk ) {
328- List <ChatCompletion .Choice > choices = chunk .choices ()
329- .stream ()
330- .map (chunkChoice -> {
331- ChatCompletionMessage chatCompletionMessage = null ;
332- ChatCompletionDelta delta = chunkChoice .delta ();
333- if (delta == null ) {
334- chatCompletionMessage = new ChatCompletionMessage ("" , Role .assistant );
335- }else {
336- chatCompletionMessage = new ChatCompletionMessage (delta .content (), delta .role (),delta .toolCalls ());
337- }
338- return new ChatCompletion .Choice (chunkChoice .index (), chatCompletionMessage , chunkChoice .finishReason (),delta );
339- })
340- .toList ();
327+ List <ChatCompletion .Choice > choices = chunk .choices ().stream ().map (chunkChoice -> {
328+ ChatCompletionMessage chatCompletionMessage = null ;
329+ ChatCompletionDelta delta = chunkChoice .delta ();
330+ if (delta == null ) {
331+ chatCompletionMessage = new ChatCompletionMessage ("" , Role .assistant );
332+ }
333+ else {
334+ chatCompletionMessage = new ChatCompletionMessage (delta .content (), delta .role (), delta .toolCalls ());
335+ }
336+ return new ChatCompletion .Choice (chunkChoice .index (), chatCompletionMessage , chunkChoice .finishReason (),
337+ delta );
338+ }).toList ();
341339
342- return new ChatCompletion (chunk .id (), chunk .errorMsg (), chunk .created (), chunk .note (), choices , chunk .usage (), chunk .moderationLevel (), chunk .searchInfo (), chunk .replaces (), chunk .recommendedQuestions (), chunk .requestId ());
340+ return new ChatCompletion (chunk .id (), chunk .errorMsg (), chunk .created (), chunk .note (), choices , chunk .usage (),
341+ chunk .moderationLevel (), chunk .searchInfo (), chunk .replaces (), chunk .recommendedQuestions (),
342+ chunk .requestId ());
343343 }
344344
345345 /**
@@ -362,22 +362,22 @@ public HunYuanApi.ChatCompletionRequest createRequest(Prompt prompt, boolean str
362362 List <ChatContent > contentList = new ArrayList <>(List .of (new ChatContent (message .getText ())));
363363
364364 contentList .addAll (userMessage .getMedia ()
365- .stream ()
366- .map (media -> new ChatContent ( new ImageUrl (
367- this .fromMediaData (media .getMimeType (), media .getData ()))))
368- .toList ());
369- return List .of (new ChatCompletionMessage (Role .user ,contentList ));
365+ .stream ()
366+ .map (media -> new ChatContent (
367+ new ImageUrl ( this .fromMediaData (media .getMimeType (), media .getData ()))))
368+ .toList ());
369+ return List .of (new ChatCompletionMessage (Role .user , contentList ));
370370 }
371371 }
372- return List .of (new ChatCompletionMessage (content ,Role .user ));
372+ return List .of (new ChatCompletionMessage (content , Role .user ));
373373 }
374374 else if (message .getMessageType () == MessageType .ASSISTANT ) {
375375 var assistantMessage = (AssistantMessage ) message ;
376376 List <ToolCall > toolCalls = null ;
377377 if (!CollectionUtils .isEmpty (assistantMessage .getToolCalls ())) {
378378 toolCalls = assistantMessage .getToolCalls ().stream ().map (toolCall -> {
379379 var function = new ChatCompletionFunction (toolCall .name (), toolCall .arguments ());
380- return new ToolCall (toolCall .id (), toolCall .type (),null , function );
380+ return new ToolCall (toolCall .id (), toolCall .type (), null , function );
381381 }).toList ();
382382 }
383383 return List .of (new ChatCompletionMessage (assistantMessage .getText (),
@@ -438,6 +438,7 @@ else if (message.getMessageType() == MessageType.TOOL) {
438438
439439 return request ;
440440 }
441+
441442 private String fromMediaData (MimeType mimeType , Object mediaContentData ) {
442443 if (mediaContentData instanceof byte [] bytes ) {
443444 // Assume the bytes are an image. So, convert the bytes to a base64 encoded
@@ -453,12 +454,13 @@ else if (mediaContentData instanceof String text) {
453454 "Unsupported media data type: " + mediaContentData .getClass ().getSimpleName ());
454455 }
455456 }
457+
456458 private ChatOptions buildRequestOptions (HunYuanApi .ChatCompletionRequest request ) {
457459 return ChatOptions .builder ()
458460 .model (request .model ())
459- // .frequencyPenalty(request.frequencyPenalty())
460- // .maxTokens(request.maxTokens())
461- // .presencePenalty(request.presencePenalty())
461+ // .frequencyPenalty(request.frequencyPenalty())
462+ // .maxTokens(request.maxTokens())
463+ // .presencePenalty(request.presencePenalty())
462464 .stopSequences (request .stop ())
463465 .temperature (request .temperature ())
464466 .topP (request .topP ())
0 commit comments