Skip to content

Commit 03f9bcb

Browse files
HavenDVclaude
andcommitted
feat: Enhance IChatClient with structured output, stop sequences, and AdditionalProperties
- Fix StopSequences to use proper StopConfiguration union type instead of string.Join - Add ChatResponseFormatText, ChatResponseFormatJson, and ChatResponseFormatJson with schema support - Add AdditionalProperties pass-through from ChatOptions to request - Map logprobs and top_logprobs to native typed fields Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ae18c13 commit 03f9bcb

1 file changed

Lines changed: 57 additions & 4 deletions

File tree

src/libs/tryAGI.OpenAI/Extensions/OpenAiClient.ChatClient.cs

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,21 +167,49 @@ private CreateChatCompletionRequest CreateRequest(
167167

168168
if (options.StopSequences is { Count: > 0 } stops)
169169
{
170-
variant2.Stop = string.Join(",", stops);
170+
variant2.Stop = stops.Count == 1
171+
? new StopConfiguration(stops[0])
172+
: new StopConfiguration(value1: null, value2: stops.ToList());
171173
}
172174

173175
if (options.Tools is { Count: > 0 } tools)
174176
{
175177
variant2.Tools = ConvertTools(tools);
176178
}
177179

178-
if (options.ResponseFormat is Meai.ChatResponseFormatJson)
180+
if (options.ResponseFormat is Meai.ChatResponseFormatText)
179181
{
180-
variant2.ResponseFormat = new ResponseFormatJsonObject
182+
variant2.ResponseFormat = new ResponseFormatText
181183
{
182-
Type = ResponseFormatJsonObjectType.JsonObject,
184+
Type = ResponseFormatTextType.Text,
183185
};
184186
}
187+
else if (options.ResponseFormat is Meai.ChatResponseFormatJson jsonFormat)
188+
{
189+
if (jsonFormat.Schema is System.Text.Json.JsonElement schema &&
190+
schema.ValueKind is not System.Text.Json.JsonValueKind.Null
191+
and not System.Text.Json.JsonValueKind.Undefined)
192+
{
193+
variant2.ResponseFormat = new ResponseFormatJsonSchema
194+
{
195+
Type = ResponseFormatJsonSchemaType.JsonSchema,
196+
JsonSchema = new ResponseFormatJsonSchemaJsonSchema
197+
{
198+
Name = jsonFormat.SchemaName ?? "response",
199+
Description = jsonFormat.SchemaDescription,
200+
Schema = JsonSerializer.Deserialize<object>(schema.GetRawText()),
201+
Strict = true,
202+
},
203+
};
204+
}
205+
else
206+
{
207+
variant2.ResponseFormat = new ResponseFormatJsonObject
208+
{
209+
Type = ResponseFormatJsonObjectType.JsonObject,
210+
};
211+
}
212+
}
185213

186214
if (options.Temperature is { } temperature)
187215
{
@@ -200,6 +228,31 @@ private CreateChatCompletionRequest CreateRequest(
200228
variant2.AdditionalProperties ??= new Dictionary<string, object>();
201229
variant2.AdditionalProperties["seed"] = seed;
202230
}
231+
232+
if (options.AdditionalProperties is { Count: > 0 } additionalProps)
233+
{
234+
// Map known properties to native typed fields
235+
if (additionalProps.TryGetValue("logprobs", out var logprobsVal) && logprobsVal is bool logprobs)
236+
{
237+
variant2.Logprobs = logprobs;
238+
}
239+
240+
if (additionalProps.TryGetValue("top_logprobs", out var topLogprobsVal) && topLogprobsVal is int topLogprobs)
241+
{
242+
variant2.TopLogprobs = topLogprobs;
243+
}
244+
245+
// Forward remaining properties
246+
variant2.AdditionalProperties ??= new Dictionary<string, object>();
247+
foreach (var kvp in additionalProps)
248+
{
249+
if (kvp.Value is not null &&
250+
kvp.Key is not "logprobs" and not "top_logprobs")
251+
{
252+
variant2.AdditionalProperties[kvp.Key] = kvp.Value;
253+
}
254+
}
255+
}
203256
}
204257

205258
if (stream)

0 commit comments

Comments
 (0)