3030import com .microsoft .semantickernel .contextvariables .ContextVariableTypes ;
3131import com .microsoft .semantickernel .exceptions .AIException ;
3232import com .microsoft .semantickernel .exceptions .AIException .ErrorCodes ;
33+ import com .microsoft .semantickernel .exceptions .SKCheckedException ;
3334import com .microsoft .semantickernel .exceptions .SKException ;
3435import com .microsoft .semantickernel .hooks .KernelHookEvent ;
3536import com .microsoft .semantickernel .hooks .KernelHooks ;
@@ -103,29 +104,33 @@ public Mono<List<ChatMessageContent<?>>> getChatMessageContentsAsync(
103104 messages ,
104105 kernel ,
105106 invocationContext )
106- .map (history -> {
107+ .flatMap (history -> {
108+ try {
109+ ChatHistory chatHistoryResult ;
107110
108- ChatHistory chatHistoryResult ;
111+ if (invocationContext != null
112+ && invocationContext .returnMode () == InvocationReturnMode .FULL_HISTORY ) {
113+ chatHistoryResult = new ChatHistory (chatHistory .getMessages ());
114+ } else {
115+ chatHistoryResult = new ChatHistory ();
116+ }
109117
110- if (invocationContext != null
111- && invocationContext .returnMode () == InvocationReturnMode .FULL_HISTORY ) {
112- chatHistoryResult = new ChatHistory (chatHistory .getMessages ());
113- } else {
114- chatHistoryResult = new ChatHistory ();
115- }
118+ chatHistoryResult .addAll (
119+ new ChatHistory (toOpenAIChatMessageContent (history .newMessages )));
120+ chatHistoryResult .addAll (new ChatHistory (history .newChatMessageContent ));
116121
117- chatHistoryResult .addAll (
118- new ChatHistory (toOpenAIChatMessageContent (history .newMessages )));
119- chatHistoryResult .addAll (new ChatHistory (history .newChatMessageContent ));
122+ if (invocationContext != null
123+ && invocationContext
124+ .returnMode () == InvocationReturnMode .LAST_MESSAGE_ONLY ) {
125+ chatHistoryResult = new ChatHistory (
126+ Collections .singletonList (
127+ CollectionUtil .getLastOrNull (chatHistory .getMessages ())));
128+ }
120129
121- if (invocationContext != null
122- && invocationContext .returnMode () == InvocationReturnMode .LAST_MESSAGE_ONLY ) {
123- chatHistoryResult = new ChatHistory (
124- Collections .singletonList (
125- CollectionUtil .getLastOrNull (chatHistory .getMessages ())));
130+ return Mono .just (chatHistoryResult .getMessages ());
131+ } catch (Exception e ) {
132+ return Mono .error (e );
126133 }
127-
128- return chatHistoryResult .getMessages ();
129134 });
130135 }
131136
@@ -142,19 +147,24 @@ public Mono<List<ChatMessageContent<?>>> getChatMessageContentsAsync(
142147 messages ,
143148 kernel ,
144149 invocationContext )
145- .map (m -> {
146- ChatHistory result = new ChatHistory (toOpenAIChatMessageContent (m .allMessages ));
150+ .flatMap (m -> {
151+ try {
152+ ChatHistory result = new ChatHistory (toOpenAIChatMessageContent (m .allMessages ));
147153
148- result .addAll (new ChatHistory (m .newChatMessageContent ));
154+ result .addAll (new ChatHistory (m .newChatMessageContent ));
149155
150- if (invocationContext != null
151- && invocationContext .returnMode () == InvocationReturnMode .LAST_MESSAGE_ONLY ) {
152- result = new ChatHistory (
153- Collections .singletonList (
154- CollectionUtil .getLastOrNull (result .getMessages ())));
155- }
156+ if (invocationContext != null
157+ && invocationContext
158+ .returnMode () == InvocationReturnMode .LAST_MESSAGE_ONLY ) {
159+ result = new ChatHistory (
160+ Collections .singletonList (
161+ CollectionUtil .getLastOrNull (result .getMessages ())));
162+ }
156163
157- return result .getMessages ();
164+ return Mono .just (result .getMessages ());
165+ } catch (SKCheckedException e ) {
166+ return Mono .error (e );
167+ }
158168 });
159169 }
160170
@@ -449,7 +459,7 @@ private Mono<FunctionResult<String>> invokeFunctionTool(
449459 .withArguments (arguments )
450460 .withResultType (contextVariableTypes .getVariableTypeForClass (String .class ));
451461 } catch (JsonProcessingException e ) {
452- return Mono .error (new SKException ("Failed to parse tool arguments" ));
462+ return Mono .error (new SKException ("Failed to parse tool arguments" , e ));
453463 }
454464 }
455465
@@ -466,7 +476,8 @@ private static <T extends KernelHookEvent> T executeHook(
466476
467477 @ SuppressWarnings ("StringSplitter" )
468478 private OpenAIFunctionToolCall extractOpenAIFunctionToolCall (
469- ChatCompletionsFunctionToolCall toolCall ) throws JsonProcessingException {
479+ ChatCompletionsFunctionToolCall toolCall )
480+ throws JsonProcessingException {
470481
471482 // Split the full name of a function into plugin and function name
472483 String name = toolCall .getFunction ().getName ();
@@ -495,7 +506,6 @@ private OpenAIFunctionToolCall extractOpenAIFunctionToolCall(
495506 pluginName ,
496507 fnName ,
497508 arguments );
498-
499509 }
500510
501511 private Mono <List <OpenAIChatMessageContent >> getChatMessageContentsAsync (
@@ -513,121 +523,144 @@ private Mono<List<OpenAIChatMessageContent>> getChatMessageContentsAsync(
513523 .collect (Collectors .toList ());
514524
515525 return Flux .fromIterable (responseMessages )
516- .map (response -> new OpenAIChatMessageContent (
517- AuthorRole .ASSISTANT ,
518- response .getContent (),
519- this .getModelId (),
520- null ,
521- null ,
522- completionMetadata ,
523- formOpenAiToolCalls (response )))
526+ .flatMap (response -> {
527+ try {
528+ return Mono .just (new OpenAIChatMessageContent (
529+ AuthorRole .ASSISTANT ,
530+ response .getContent (),
531+ this .getModelId (),
532+ null ,
533+ null ,
534+ completionMetadata ,
535+ formOpenAiToolCalls (response )));
536+ } catch (Exception e ) {
537+ return Mono .error (e );
538+ }
539+ })
524540 .collectList ();
525541 }
526542
527543 private List <ChatMessageContent <?>> toOpenAIChatMessageContent (
528- List <ChatRequestMessage > requestMessages ) {
529- return requestMessages
530- .stream ()
531- .map (message -> {
532- if (message instanceof ChatRequestUserMessage ) {
533- return new OpenAIChatMessageContent <>(
534- AuthorRole .USER ,
535- ((ChatRequestUserMessage ) message ).getContent ().toString (),
536- null ,
537- null ,
538- null ,
539- null ,
540- null );
541- } else if (message instanceof ChatRequestSystemMessage ) {
542- return new OpenAIChatMessageContent <>(
543- AuthorRole .SYSTEM ,
544- ((ChatRequestSystemMessage ) message ).getContent (),
545- null ,
546- null ,
547- null ,
548- null ,
549- null );
550- } else if (message instanceof ChatRequestAssistantMessage ) {
551- List <OpenAIFunctionToolCall > calls = getToolCalls (
552- ((ChatRequestAssistantMessage ) message ).getToolCalls ());
553- return new OpenAIChatMessageContent <>(
554- AuthorRole .ASSISTANT ,
555- ((ChatRequestAssistantMessage ) message ).getContent (),
556- null ,
557- null ,
558- null ,
559- null ,
560- calls );
561- } else if (message instanceof ChatRequestToolMessage ) {
562- return new OpenAIChatMessageContent <>(
563- AuthorRole .TOOL ,
564- ((ChatRequestToolMessage ) message ).getContent (),
565- null ,
566- null ,
567- null ,
568- FunctionResultMetadata .build (
569- ((ChatRequestToolMessage ) message ).getToolCallId (),
544+ List <ChatRequestMessage > requestMessages ) throws SKCheckedException {
545+ try {
546+ return requestMessages
547+ .stream ()
548+ .map (message -> {
549+ if (message instanceof ChatRequestUserMessage ) {
550+ return new OpenAIChatMessageContent <>(
551+ AuthorRole .USER ,
552+ ((ChatRequestUserMessage ) message ).getContent ().toString (),
570553 null ,
571- null ),
572- null );
573- }
554+ null ,
555+ null ,
556+ null ,
557+ null );
558+ } else if (message instanceof ChatRequestSystemMessage ) {
559+ return new OpenAIChatMessageContent <>(
560+ AuthorRole .SYSTEM ,
561+ ((ChatRequestSystemMessage ) message ).getContent (),
562+ null ,
563+ null ,
564+ null ,
565+ null ,
566+ null );
567+ } else if (message instanceof ChatRequestAssistantMessage ) {
568+ try {
569+ List <OpenAIFunctionToolCall > calls = getToolCalls (
570+ ((ChatRequestAssistantMessage ) message ).getToolCalls ());
571+ return new OpenAIChatMessageContent <>(
572+ AuthorRole .ASSISTANT ,
573+ ((ChatRequestAssistantMessage ) message ).getContent (),
574+ null ,
575+ null ,
576+ null ,
577+ null ,
578+ calls );
579+ } catch (SKCheckedException e ) {
580+ throw SKException .build ("Failed to form assistant message" , e );
581+ }
582+ } else if (message instanceof ChatRequestToolMessage ) {
583+ return new OpenAIChatMessageContent <>(
584+ AuthorRole .TOOL ,
585+ ((ChatRequestToolMessage ) message ).getContent (),
586+ null ,
587+ null ,
588+ null ,
589+ FunctionResultMetadata .build (
590+ ((ChatRequestToolMessage ) message ).getToolCallId (),
591+ null ,
592+ null ),
593+ null );
594+ }
574595
575- throw new SKException (
576- "Unknown message type: " + message .getClass ().getSimpleName ());
577- })
578- .collect (Collectors .toList ());
596+ throw new SKException (
597+ "Unknown message type: " + message .getClass ().getSimpleName ());
598+ })
599+ .collect (Collectors .toList ());
600+ } catch (SKException e ) {
601+ throw SKCheckedException .build ("Failed to form OpenAI chat message content" , e );
602+ }
579603 }
580604
581605 @ Nullable
582606 private List <OpenAIFunctionToolCall > getToolCalls (
583- @ Nullable List <ChatCompletionsToolCall > toolCalls ) {
607+ @ Nullable List <ChatCompletionsToolCall > toolCalls ) throws SKCheckedException {
584608 if (toolCalls == null || toolCalls .isEmpty ()) {
585609 return null ;
586610 }
587- return toolCalls
588- .stream ()
589- .map (call -> {
590- if (call instanceof ChatCompletionsFunctionToolCall ) {
591- try {
592- return extractOpenAIFunctionToolCall (
593- (ChatCompletionsFunctionToolCall ) call );
594- } catch (JsonProcessingException e ) {
595- throw new SKException ("Failed to parse tool arguments" , e );
611+
612+ try {
613+ return toolCalls
614+ .stream ()
615+ .map (call -> {
616+ if (call instanceof ChatCompletionsFunctionToolCall ) {
617+ try {
618+ return extractOpenAIFunctionToolCall (
619+ (ChatCompletionsFunctionToolCall ) call );
620+ } catch (JsonProcessingException e ) {
621+ throw SKException .build ("Failed to parse tool arguments" , e );
622+ }
623+ } else {
624+ return new OpenAIFunctionToolCall (
625+ call .getId (),
626+ null ,
627+ null ,
628+ null );
596629 }
597- } else {
598- return new OpenAIFunctionToolCall (
599- call .getId (),
600- null ,
601- null ,
602- null );
603- }
604- })
605- .collect (Collectors .toList ());
630+ })
631+ .collect (Collectors .toList ());
632+ } catch (SKException e ) {
633+ throw SKCheckedException .build ("Failed to form tool call" , e );
634+ }
606635 }
607636
608637 @ Nullable
609638 private List <OpenAIFunctionToolCall > formOpenAiToolCalls (
610- ChatResponseMessage response ) {
639+ ChatResponseMessage response ) throws SKCheckedException {
611640 if (response .getToolCalls () == null || response .getToolCalls ().isEmpty ()) {
612641 return null ;
613642 }
614- return response
615- .getToolCalls ()
616- .stream ()
617- .map (call -> {
618- if (call instanceof ChatCompletionsFunctionToolCall ) {
619- try {
620- return extractOpenAIFunctionToolCall (
621- (ChatCompletionsFunctionToolCall ) call );
622- } catch (JsonProcessingException e ) {
623- throw new SKException ("Failed to parse tool arguments" , e );
643+ try {
644+ return response
645+ .getToolCalls ()
646+ .stream ()
647+ .map (call -> {
648+ if (call instanceof ChatCompletionsFunctionToolCall ) {
649+ try {
650+ return extractOpenAIFunctionToolCall (
651+ (ChatCompletionsFunctionToolCall ) call );
652+ } catch (JsonProcessingException e ) {
653+ throw SKException .build ("Failed to parse tool arguments" , e );
654+ }
655+ } else {
656+ return null ;
624657 }
625- } else {
626- return null ;
627- }
628- })
629- . filter ( Objects :: nonNull )
630- . collect ( Collectors . toList ());
658+ })
659+ . filter ( Objects :: nonNull )
660+ . collect ( Collectors . toList ());
661+ } catch ( SKException e ) {
662+ throw SKCheckedException . build ( "Failed to form tool call" , e );
663+ }
631664 }
632665
633666 private static ChatCompletionsOptions getCompletionsOptions (
@@ -754,7 +787,7 @@ private static void configureToolCallBehaviorOptions(
754787 "{\" type\" :\" function\" ,\" function\" :{\" name\" :\" %s\" }}" , toolChoiceName );
755788 options .setToolChoice (BinaryData .fromObject (new ObjectMapper ().readTree (json )));
756789 } catch (JsonProcessingException e ) {
757- throw new RuntimeException ( e );
790+ throw SKException . build ( "Failed to parse tool choice" , e );
758791 }
759792 return ;
760793 }
@@ -889,7 +922,7 @@ private static ChatRequestAssistantMessage formAssistantMessage(
889922 : "{}" ;
890923
891924 String prefix = "" ;
892- if (toolCall .getPluginName () = = null ) {
925+ if (toolCall .getPluginName () ! = null ) {
893926 prefix = toolCall .getPluginName () + OpenAIFunction .getNameSeparator ();
894927 }
895928 String name = prefix + toolCall .getFunctionName ();
0 commit comments