Public Access
Update meeting summary agent UI
This commit is contained in:
@@ -22,6 +22,7 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
private readonly LiteLlmResponsesCompactionOptions? compactionOptions;
|
||||
private readonly ILogger? logger;
|
||||
private readonly Action? retrying;
|
||||
private readonly Action<string>? reasoningSummaryChanged;
|
||||
private int responsesRequestCount;
|
||||
|
||||
public LiteLlmResponsesChatClient(
|
||||
@@ -35,7 +36,8 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
LiteLlmResponsesCompactionOptions? compactionOptions = null,
|
||||
ILogger? logger = null,
|
||||
bool firstRequestIsUser = true,
|
||||
Action? retrying = null)
|
||||
Action? retrying = null,
|
||||
Action<string>? reasoningSummaryChanged = null)
|
||||
: this(
|
||||
new HttpClient { BaseAddress = NormalizeEndpoint(endpoint) },
|
||||
apiKey,
|
||||
@@ -47,7 +49,8 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
compactionOptions,
|
||||
logger,
|
||||
firstRequestIsUser,
|
||||
retrying)
|
||||
retrying,
|
||||
reasoningSummaryChanged)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -62,7 +65,8 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
LiteLlmResponsesCompactionOptions? compactionOptions = null,
|
||||
ILogger? logger = null,
|
||||
bool firstRequestIsUser = true,
|
||||
Action? retrying = null)
|
||||
Action? retrying = null,
|
||||
Action<string>? reasoningSummaryChanged = null)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
|
||||
@@ -74,6 +78,7 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
this.compactionOptions = compactionOptions;
|
||||
this.logger = logger;
|
||||
this.retrying = retrying;
|
||||
this.reasoningSummaryChanged = reasoningSummaryChanged;
|
||||
responsesRequestCount = firstRequestIsUser ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -90,7 +95,8 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
var payload = await CreateCompactedPayloadAsync(messages.ToList(), options, cancellationToken).ConfigureAwait(false);
|
||||
var responseJson = await PostWithRetryAsync(payload, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var response = ParseResponseJson(responseJson);
|
||||
var response = ParseResponseJson(responseJson, out var reasoningSummaries);
|
||||
ReportVisibleReasoningSummaries(reasoningSummaries);
|
||||
LogResponseDiagnostics(responseJson, response);
|
||||
ThrowIfResponseHasNoContent(responseJson, response);
|
||||
LogResponseUsage(response.Usage);
|
||||
@@ -122,10 +128,18 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
}
|
||||
|
||||
public static ChatResponse ParseResponseJson(string responseJson)
|
||||
{
|
||||
return ParseResponseJson(responseJson, out _);
|
||||
}
|
||||
|
||||
private static ChatResponse ParseResponseJson(
|
||||
string responseJson,
|
||||
out IReadOnlyList<string> reasoningSummaries)
|
||||
{
|
||||
using var document = JsonDocument.Parse(responseJson);
|
||||
var root = document.RootElement;
|
||||
var contents = new List<AIContent>();
|
||||
reasoningSummaries = ExtractVisibleReasoningSummaries(root);
|
||||
|
||||
if (root.TryGetProperty("output", out var output) && output.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
@@ -162,6 +176,54 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
};
|
||||
}
|
||||
|
||||
internal static IReadOnlyList<string> ExtractVisibleReasoningSummaries(string responseJson)
|
||||
{
|
||||
using var document = JsonDocument.Parse(responseJson);
|
||||
return ExtractVisibleReasoningSummaries(document.RootElement);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<string> ExtractVisibleReasoningSummaries(JsonElement root)
|
||||
{
|
||||
var summaries = new List<string>();
|
||||
|
||||
if (!root.TryGetProperty("output", out var output) || output.ValueKind != JsonValueKind.Array)
|
||||
{
|
||||
return summaries;
|
||||
}
|
||||
|
||||
foreach (var item in output.EnumerateArray())
|
||||
{
|
||||
if (GetString(item, "type") == "reasoning")
|
||||
{
|
||||
AddVisibleReasoningSummaryText(summaries, item);
|
||||
}
|
||||
}
|
||||
|
||||
return summaries;
|
||||
}
|
||||
|
||||
private void ReportVisibleReasoningSummaries(IReadOnlyList<string> summaries)
|
||||
{
|
||||
if (reasoningSummaryChanged is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var summary in summaries)
|
||||
{
|
||||
try
|
||||
{
|
||||
reasoningSummaryChanged(summary);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger?.LogWarning(
|
||||
exception,
|
||||
"Reasoning summary callback failed; continuing with the LiteLLM response.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<JsonObject> CreateCompactedPayloadAsync(
|
||||
IReadOnlyList<ChatMessage> messages,
|
||||
ChatOptions? options,
|
||||
@@ -660,6 +722,66 @@ public sealed class LiteLlmResponsesChatClient : IChatClient
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddVisibleReasoningSummaryText(List<string> summaries, JsonElement item)
|
||||
{
|
||||
AddVisibleReasoningSummaryText(summaries, item, "summary");
|
||||
AddVisibleReasoningSummaryText(summaries, item, "content");
|
||||
}
|
||||
|
||||
private static void AddVisibleReasoningSummaryText(
|
||||
List<string> summaries,
|
||||
JsonElement item,
|
||||
string propertyName)
|
||||
{
|
||||
if (!item.TryGetProperty(propertyName, out var property))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (property.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
AddNonEmpty(summaries, property.GetString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (property.ValueKind != JsonValueKind.Array)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var summaryItem in property.EnumerateArray())
|
||||
{
|
||||
if (summaryItem.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
AddNonEmpty(summaries, summaryItem.GetString());
|
||||
}
|
||||
else if (summaryItem.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
if (propertyName == "content" && !IsSummaryContent(summaryItem))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AddNonEmpty(summaries, GetString(summaryItem, "text"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsSummaryContent(JsonElement item)
|
||||
{
|
||||
var type = GetString(item, "type");
|
||||
return !string.IsNullOrWhiteSpace(type)
|
||||
&& type.Contains("summary", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static void AddNonEmpty(List<string> values, string? value)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
values.Add(value.Trim());
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, object?> ParseArguments(string? arguments)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(arguments))
|
||||
|
||||
Reference in New Issue
Block a user