Add grounded unified search answers and live verification

This commit is contained in:
master
2026-03-07 03:55:51 +02:00
parent 2ff0e1f86b
commit edb947d602
19 changed files with 1180 additions and 32 deletions

View File

@@ -379,6 +379,18 @@ public static class UnifiedSearchEndpoints
CurrentRoute = string.IsNullOrWhiteSpace(ambient.CurrentRoute) ? null : ambient.CurrentRoute.Trim(),
SessionId = string.IsNullOrWhiteSpace(ambient.SessionId) ? null : ambient.SessionId.Trim(),
ResetSession = ambient.ResetSession,
LastAction = ambient.LastAction is null || string.IsNullOrWhiteSpace(ambient.LastAction.Action)
? null
: new AmbientAction
{
Action = ambient.LastAction.Action.Trim(),
Source = string.IsNullOrWhiteSpace(ambient.LastAction.Source) ? null : ambient.LastAction.Source.Trim(),
QueryHint = string.IsNullOrWhiteSpace(ambient.LastAction.QueryHint) ? null : ambient.LastAction.QueryHint.Trim(),
Domain = string.IsNullOrWhiteSpace(ambient.LastAction.Domain) ? null : ambient.LastAction.Domain.Trim().ToLowerInvariant(),
EntityKey = string.IsNullOrWhiteSpace(ambient.LastAction.EntityKey) ? null : ambient.LastAction.EntityKey.Trim(),
Route = string.IsNullOrWhiteSpace(ambient.LastAction.Route) ? null : ambient.LastAction.Route.Trim(),
OccurredAt = ambient.LastAction.OccurredAt
},
VisibleEntityKeys = ambient.VisibleEntityKeys is { Count: > 0 }
? ambient.VisibleEntityKeys
.Where(static value => !string.IsNullOrWhiteSpace(value))
@@ -462,6 +474,31 @@ public static class UnifiedSearchEndpoints
}).ToArray();
}
UnifiedSearchApiContextAnswer? contextAnswer = null;
if (response.ContextAnswer is not null)
{
contextAnswer = new UnifiedSearchApiContextAnswer
{
Status = response.ContextAnswer.Status,
Code = response.ContextAnswer.Code,
Summary = response.ContextAnswer.Summary,
Reason = response.ContextAnswer.Reason,
Evidence = response.ContextAnswer.Evidence,
Citations = response.ContextAnswer.Citations?.Select(static citation => new UnifiedSearchApiContextAnswerCitation
{
EntityKey = citation.EntityKey,
Title = citation.Title,
Domain = citation.Domain,
Route = citation.Route
}).ToArray(),
Questions = response.ContextAnswer.Questions?.Select(static question => new UnifiedSearchApiContextAnswerQuestion
{
Query = question.Query,
Kind = question.Kind
}).ToArray()
};
}
return new UnifiedSearchApiResponse
{
Query = response.Query,
@@ -470,6 +507,7 @@ public static class UnifiedSearchEndpoints
Synthesis = synthesis,
Suggestions = suggestions,
Refinements = refinements,
ContextAnswer = contextAnswer,
Diagnostics = new UnifiedSearchApiDiagnostics
{
FtsMatches = response.Diagnostics.FtsMatches,
@@ -696,6 +734,25 @@ public sealed record UnifiedSearchApiAmbientContext
public string? SessionId { get; init; }
public bool ResetSession { get; init; }
public UnifiedSearchApiAmbientAction? LastAction { get; init; }
}
public sealed record UnifiedSearchApiAmbientAction
{
public string Action { get; init; } = string.Empty;
public string? Source { get; init; }
public string? QueryHint { get; init; }
public string? Domain { get; init; }
public string? EntityKey { get; init; }
public string? Route { get; init; }
public DateTimeOffset? OccurredAt { get; init; }
}
public sealed record UnifiedSearchApiFilter
@@ -751,6 +808,8 @@ public sealed record UnifiedSearchApiResponse
public IReadOnlyList<UnifiedSearchApiRefinement>? Refinements { get; init; }
public UnifiedSearchApiContextAnswer? ContextAnswer { get; init; }
public UnifiedSearchApiDiagnostics Diagnostics { get; init; } = new();
public IReadOnlyList<UnifiedSearchApiFederationDiagnostic>? Federation { get; init; }
@@ -839,6 +898,41 @@ public sealed record UnifiedSearchApiRefinement
public string Source { get; init; } = string.Empty;
}
public sealed record UnifiedSearchApiContextAnswer
{
public string Status { get; init; } = string.Empty;
public string Code { get; init; } = string.Empty;
public string Summary { get; init; } = string.Empty;
public string Reason { get; init; } = string.Empty;
public string Evidence { get; init; } = string.Empty;
public IReadOnlyList<UnifiedSearchApiContextAnswerCitation>? Citations { get; init; }
public IReadOnlyList<UnifiedSearchApiContextAnswerQuestion>? Questions { get; init; }
}
public sealed record UnifiedSearchApiContextAnswerCitation
{
public string EntityKey { get; init; } = string.Empty;
public string Title { get; init; } = string.Empty;
public string Domain { get; init; } = string.Empty;
public string? Route { get; init; }
}
public sealed record UnifiedSearchApiContextAnswerQuestion
{
public string Query { get; init; } = string.Empty;
public string Kind { get; init; } = "follow_up";
}
public sealed record UnifiedSearchApiDiagnostics
{
public int FtsMatches { get; init; }