@@ -71,15 +71,13 @@ public async Task<ChatResponse> GetResponseAsync(
71
71
throw new ArgumentNullException ( nameof ( messages ) ) ;
72
72
}
73
73
74
- ConverseRequest request = new ( )
75
- {
76
- ModelId = options ? . ModelId ?? _modelId ,
77
- Messages = CreateMessages ( messages ) ,
78
- System = CreateSystem ( messages ) ,
79
- ToolConfig = CreateToolConfig ( options ) ,
80
- InferenceConfig = CreateInferenceConfiguration ( options ) ,
81
- AdditionalModelRequestFields = CreateAdditionalModelRequestFields ( options ) ,
82
- } ;
74
+ ConverseRequest request = options ? . RawRepresentationFactory ? . Invoke ( this ) as ConverseRequest ?? new ( ) ;
75
+ request . ModelId ??= options ? . ModelId ?? _modelId ;
76
+ request . Messages = CreateMessages ( request . Messages , messages ) ;
77
+ request . System = CreateSystem ( request . System , messages , options ) ;
78
+ request . ToolConfig = CreateToolConfig ( request . ToolConfig , options ) ;
79
+ request . InferenceConfig = CreateInferenceConfiguration ( request . InferenceConfig , options ) ;
80
+ request . AdditionalModelRequestFields = CreateAdditionalModelRequestFields ( request . AdditionalModelRequestFields , options ) ;
83
81
84
82
var response = await _runtime . ConverseAsync ( request , cancellationToken ) . ConfigureAwait ( false ) ;
85
83
@@ -162,15 +160,13 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
162
160
throw new ArgumentNullException ( nameof ( messages ) ) ;
163
161
}
164
162
165
- ConverseStreamRequest request = new ( )
166
- {
167
- ModelId = options ? . ModelId ?? _modelId ,
168
- Messages = CreateMessages ( messages ) ,
169
- System = CreateSystem ( messages ) ,
170
- ToolConfig = CreateToolConfig ( options ) ,
171
- InferenceConfig = CreateInferenceConfiguration ( options ) ,
172
- AdditionalModelRequestFields = CreateAdditionalModelRequestFields ( options ) ,
173
- } ;
163
+ ConverseStreamRequest request = options ? . RawRepresentationFactory ? . Invoke ( this ) as ConverseStreamRequest ?? new ( ) ;
164
+ request . ModelId ??= options ? . ModelId ?? _modelId ;
165
+ request . Messages = CreateMessages ( request . Messages , messages ) ;
166
+ request . System = CreateSystem ( request . System , messages , options ) ;
167
+ request . ToolConfig = CreateToolConfig ( request . ToolConfig , options ) ;
168
+ request . InferenceConfig = CreateInferenceConfiguration ( request . InferenceConfig , options ) ;
169
+ request . AdditionalModelRequestFields = CreateAdditionalModelRequestFields ( request . AdditionalModelRequestFields , options ) ;
174
170
175
171
var result = await _runtime . ConverseStreamAsync ( request , cancellationToken ) . ConfigureAwait ( false ) ;
176
172
@@ -356,11 +352,21 @@ private static ChatFinishReason GetChatFinishReason(StopReason stopReason) =>
356
352
} ;
357
353
358
354
/// <summary>Creates a list of <see cref="SystemContentBlock"/> from the system messages in the provided <paramref name="messages"/>.</summary>
359
- private static List < SystemContentBlock > CreateSystem ( IEnumerable < ChatMessage > messages ) =>
360
- messages
355
+ private static List < SystemContentBlock > CreateSystem ( List < SystemContentBlock > ? rawMessages , IEnumerable < ChatMessage > messages , ChatOptions ? options )
356
+ {
357
+ List < SystemContentBlock > system = rawMessages ?? [ ] ;
358
+
359
+ if ( options ? . Instructions is { } instructions )
360
+ {
361
+ system . Add ( new SystemContentBlock ( ) { Text = instructions } ) ;
362
+ }
363
+
364
+ system . AddRange ( messages
361
365
. Where ( m => m . Role == ChatRole . System && m . Contents . Any ( c => c is TextContent ) )
362
- . Select ( m => new SystemContentBlock ( ) { Text = string . Concat ( m . Contents . OfType < TextContent > ( ) ) } )
363
- . ToList ( ) ;
366
+ . Select ( m => new SystemContentBlock ( ) { Text = string . Concat ( m . Contents . OfType < TextContent > ( ) ) } ) ) ;
367
+
368
+ return system ;
369
+ }
364
370
365
371
/// <summary>Parses JSON tool input into a <see cref="Dictionary{String, Object}"/>.</summary>
366
372
private static Dictionary < string , object ? > ? ParseToolInputs ( string ? jsonInput , out Exception ? parseError )
@@ -382,9 +388,9 @@ private static List<SystemContentBlock> CreateSystem(IEnumerable<ChatMessage> me
382
388
}
383
389
384
390
/// <summary>Creates a list of <see cref="Message"/> from the provided <paramref name="chatMessages"/>.</summary>
385
- private static List < Message > CreateMessages ( IEnumerable < ChatMessage > chatMessages )
391
+ private static List < Message > CreateMessages ( List < Message > ? rawMessages , IEnumerable < ChatMessage > chatMessages )
386
392
{
387
- List < Message > messages = [ ] ;
393
+ List < Message > messages = rawMessages ?? [ ] ;
388
394
389
395
foreach ( ChatMessage chatMessage in chatMessages )
390
396
{
@@ -681,100 +687,110 @@ private static Document ToDocument(JsonElement json)
681
687
}
682
688
683
689
/// <summary>Creates an <see cref="ToolConfiguration"/> from the specified options.</summary>
684
- private static ToolConfiguration ? CreateToolConfig ( ChatOptions ? options )
690
+ private static ToolConfiguration ? CreateToolConfig ( ToolConfiguration ? toolConfig , ChatOptions ? options )
685
691
{
686
- List < Tool > ? tools = options ? . Tools ? . OfType < AIFunction > ( ) . Select ( f =>
692
+ if ( options ? . Tools is { Count : > 0 } tools )
687
693
{
688
- Document inputs = default ;
689
- List < Document > required = [ ] ;
690
-
691
- if ( f . JsonSchema . TryGetProperty ( "properties" , out JsonElement properties ) )
694
+ foreach ( AITool tool in tools )
692
695
{
693
- foreach ( JsonProperty parameter in properties . EnumerateObject ( ) )
696
+ if ( tool is not AIFunction f )
694
697
{
695
- inputs . Add ( parameter . Name , ToDocument ( parameter . Value ) ) ;
698
+ continue ;
696
699
}
697
- }
698
700
699
- if ( f . JsonSchema . TryGetProperty ( "required" , out JsonElement requiredProperties ) )
700
- {
701
- foreach ( JsonElement requiredProperty in requiredProperties . EnumerateArray ( ) )
701
+ Document inputs = default ;
702
+ List < Document > required = [ ] ;
703
+
704
+ if ( f . JsonSchema . TryGetProperty ( "properties" , out JsonElement properties ) )
702
705
{
703
- required . Add ( requiredProperty . GetString( ) ) ;
706
+ foreach ( JsonProperty parameter in properties . EnumerateObject ( ) )
707
+ {
708
+ inputs . Add ( parameter . Name , ToDocument ( parameter . Value ) ) ;
709
+ }
704
710
}
705
- }
706
711
707
- var schemaDictionary = new Dictionary < string , Document > ( )
708
- {
709
- [ "type" ] = new Document ( "object" ) ,
710
- } ;
712
+ if ( f . JsonSchema . TryGetProperty ( "required" , out JsonElement requiredProperties ) )
713
+ {
714
+ foreach ( JsonElement requiredProperty in requiredProperties . EnumerateArray ( ) )
715
+ {
716
+ required . Add ( requiredProperty . GetString( ) ) ;
717
+ }
718
+ }
711
719
712
- if ( inputs != default )
713
- {
714
- schemaDictionary [ "properties "] = inputs ;
715
- }
720
+ Dictionary < string , Document > schemaDictionary = new ( )
721
+ {
722
+ [ "type "] = new Document ( "object" ) ,
723
+ } ;
716
724
717
- if ( required . Count > 0 )
718
- {
719
- schemaDictionary [ "required " ] = new Document ( required ) ;
720
- }
725
+ if ( inputs != default )
726
+ {
727
+ schemaDictionary [ "properties " ] = inputs ;
728
+ }
721
729
722
- return new Tool ( )
723
- {
724
- ToolSpec = new ToolSpecification ( )
730
+ if ( required . Count > 0 )
731
+ {
732
+ schemaDictionary [ "required" ] = new Document ( required ) ;
733
+ }
734
+
735
+ toolConfig ??= new ( ) ;
736
+ toolConfig . Tools ??= [ ] ;
737
+ toolConfig . Tools . Add ( new ( )
725
738
{
726
- Name = f . Name ,
727
- Description = ! string . IsNullOrEmpty ( f . Description ) ? f . Description : f . Name ,
728
- InputSchema = new ( )
739
+ ToolSpec = new ToolSpecification ( )
729
740
{
730
- Json = new ( schemaDictionary )
741
+ Name = f . Name ,
742
+ Description = ! string . IsNullOrEmpty ( f . Description ) ? f . Description : f . Name ,
743
+ InputSchema = new ( )
744
+ {
745
+ Json = new ( schemaDictionary )
746
+ } ,
731
747
} ,
732
- } ,
733
- } ;
734
- } ) . ToList ( ) ;
748
+ } ) ;
749
+ }
750
+ }
735
751
736
- ToolChoice ? choice = null ;
737
- if ( tools is { Count : > 0 } )
752
+ if ( toolConfig ? . Tools is { Count : > 0 } && toolConfig . ToolChoice is null )
738
753
{
739
754
switch ( options ! . ToolMode )
740
755
{
741
- case AutoChatToolMode :
742
- case null :
743
- choice = new ToolChoice ( ) { Auto = new ( ) } ;
744
- break ;
745
-
746
756
case RequiredChatToolMode r :
747
- choice = ! string . IsNullOrWhiteSpace ( r . RequiredFunctionName ) ?
757
+ toolConfig . ToolChoice = ! string . IsNullOrWhiteSpace ( r . RequiredFunctionName ) ?
748
758
new ToolChoice ( ) { Tool = new ( ) { Name = r . RequiredFunctionName } } :
749
759
new ToolChoice ( ) { Any = new ( ) } ;
750
760
break ;
751
761
}
752
-
753
- return new ( )
754
- {
755
- ToolChoice = choice ,
756
- Tools = tools ,
757
- } ;
758
762
}
759
763
760
- return null ;
764
+ return toolConfig ;
761
765
}
762
766
763
767
/// <summary>Creates an <see cref="InferenceConfiguration"/> from the specified options.</summary>
764
- private static InferenceConfiguration CreateInferenceConfiguration ( ChatOptions ? options ) =>
765
- new ( )
768
+ private static InferenceConfiguration CreateInferenceConfiguration ( InferenceConfiguration config , ChatOptions ? options )
769
+ {
770
+ config ??= new ( ) ;
771
+
772
+ config . MaxTokens ??= options ? . MaxOutputTokens ;
773
+ config . Temperature ??= options ? . Temperature ;
774
+ config . TopP ??= options ? . TopP ;
775
+
776
+ if ( options ? . StopSequences is { Count : > 0 } stopOptions )
766
777
{
767
- MaxTokens = options ? . MaxOutputTokens ,
768
- StopSequences = options ? . StopSequences ? . ToList ( ) ,
769
- Temperature = options ? . Temperature ,
770
- TopP = options ? . TopP ,
771
- } ;
778
+ if ( config . StopSequences is null )
779
+ {
780
+ config . StopSequences = stopOptions . ToList ( ) ;
781
+ }
782
+ else
783
+ {
784
+ config . StopSequences . AddRange ( stopOptions ) ;
785
+ }
786
+ }
787
+
788
+ return config ;
789
+ }
772
790
773
791
/// <summary>Creates a <see cref="Document"/> from the specified options to use as the additional model request options.</summary>
774
- private static Document CreateAdditionalModelRequestFields ( ChatOptions ? options )
792
+ private static Document CreateAdditionalModelRequestFields ( Document d , ChatOptions ? options )
775
793
{
776
- Document d = default ;
777
-
778
794
if ( options is not null )
779
795
{
780
796
if ( options . TopK is int topK )
0 commit comments