Skip to content

Add direct-text semantic SearchParameter MVP with Foundry - #5803

Open
Brendan Kowitz (brendankowitz) wants to merge 5 commits into
feature/sql-semantic-search-stack/layer-1-foundationsfrom
feature/sql-semantic-search-stack/layer-2-mvp
Open

Add direct-text semantic SearchParameter MVP with Foundry#5803
Brendan Kowitz (brendankowitz) wants to merge 5 commits into
feature/sql-semantic-search-stack/layer-1-foundationsfrom
feature/sql-semantic-search-stack/layer-2-mvp

Conversation

@brendankowitz

Copy link
Copy Markdown
Member

Description

Layer 2 of the SQL semantic-search stack. Depends on #5802.

Implements metadata-driven special SearchParameters and vector-search configuration, direct FHIRPath text extraction to synchronous Foundry embeddings, and transactional vector writes. Covers activation, reindexing, empty-text cleanup, awaited heartbeat lifetime through failures and cancellation, model-compatible tokenization with strict Unicode-safe caps, ordered Foundry input/token batching, ordinary filters and authorization, cosine ranking with deduplication, stable pagination, and standard Bundle.entry.search.score.

The feature is SQL-only and off by default. Binary, PDF, and semantic chains are rejected before embedding. Layer 3 evidence, the Patient operation, Binary/PDF support, and refresh functionality remain unpublished. Extraction commits were authored by Anna Gornyitzki; adaptations are separate. Source: #5780.

Documentation: Semantic Search and ADR 2608.

Related issues

Addresses #5780.

Testing

Recorded prior evidence: the Layer 2 solution build succeeded; Core and SQL unit suites plus targeted Shared R4, API, Azure, and schema tests passed; tokenizer Unicode/overlap/default-override tests passed; Foundry failure/cancellation/cardinality/batching tests passed; and the final isolated Layer 2 semantic E2E suite (5 tests) passed, including heartbeat coverage. No live Foundry testing was performed.

FHIR Team Checklist

  • Update the title of the PR to be succinct and less than 65 characters
  • Add a milestone to the PR for the sprint that it is merged (i.e. add S47) — intentionally not set; no milestone was guessed.
  • Tag the PR with the type of update: Bug, Build, Dependencies, Enhancement, New-Feature or Documentation — intended: New-Feature.
  • Tag the PR with Open source, Azure API for FHIR (CosmosDB or common code) or Azure Healthcare APIs (SQL or common code) to specify where this change is intended to be released — intended: Azure Healthcare APIs.
  • Tag the PR with Schema Version backward compatible or Schema Version backward incompatible or Schema Version unchanged if this adds or updates Sql script which is/is not backward compatible with the code — intended: Schema Version backward compatible.
  • When changing or adding behavior, if your code modifies the system design or changes design assumptions, please create and include an ADR.
  • CI is green before merge Build Status
  • Review squash-merge requirements

Semver Change (docs)

Feature

@brendankowitz
Brendan Kowitz (brendankowitz) added this pull request to stack #5804 September 11, 2026 01:22
Anna Gornyitzki and others added 5 commits September 10, 2026 18:26
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Anna Gornyitzki <t-annag@microsoft.com>

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Anna Gornyitzki <t-annag@microsoft.com>

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Anna Gornyitzki <t-annag@microsoft.com>

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Anna Gornyitzki <t-annag@microsoft.com>

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@brendankowitz
Brendan Kowitz (brendankowitz) force-pushed the feature/sql-semantic-search-stack/layer-2-mvp branch from 077c543 to 2f7c976 Compare September 11, 2026 01:33
throw new InvalidDefinitionException($"Vector SearchParameter distanceMetric must be '{VectorSearchConfiguration.SupportedDistanceMetric}'.");
}

configuration.DistanceMetric = distanceMetric.ToLowerInvariant();
{
var bundle = context.Object as Hl7.Fhir.Model.Bundle;
resource = bundle;
bool hasExtendedSearchMetadata = bundle.Entry
if (isVectorSearch && sqlSearchOptions.SemanticContinuationDistance.HasValue)
{
object distanceParameter = Parameters.AddParameter(sqlSearchOptions.SemanticContinuationDistance.Value, includeInHash: false);
object resourceTypeParameter = Parameters.AddParameter(sqlSearchOptions.SemanticContinuationResourceTypeId.Value, includeInHash: false);
{
object distanceParameter = Parameters.AddParameter(sqlSearchOptions.SemanticContinuationDistance.Value, includeInHash: false);
object resourceTypeParameter = Parameters.AddParameter(sqlSearchOptions.SemanticContinuationResourceTypeId.Value, includeInHash: false);
object surrogateIdParameter = Parameters.AddParameter(sqlSearchOptions.SemanticContinuationResourceSurrogateId.Value, includeInHash: false);
await _initializationLock.WaitAsync(cancellationToken);
try
{
if (_embeddingModelId.HasValue)
Comment on lines +318 to +326
if (eTag.HasValue)
{
// You can't update a resource with a specified version if the resource does not exist
if (weakETag != null)
{
results.Add(resourceExt.GetIdentifier(), new DataStoreOperationOutcome(new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundByIdAndVersion, resource.ResourceTypeName, resource.ResourceId, weakETag.VersionId))));
continue;
}
}
Comment on lines +533 to +535
catch (OperationCanceledException) when (heartbeatCancellationSource.IsCancellationRequested)
{
}
Comment on lines +556 to +558
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
}
{
var projectDir = GetProjectPath("src", startupType);
var testConfigPath = Path.GetFullPath("testconfiguration.json");
var testConfigPath = Path.Combine(AppContext.BaseDirectory, "testconfiguration.json");

configuration["ASPNETCORE_FORWARDEDHEADERS_ENABLED"] = "true";
configuration["TestAuthEnvironment:FilePath"] = "testauthenvironment.json";
configuration["TestAuthEnvironment:FilePath"] = Path.Combine(AppContext.BaseDirectory, "testauthenvironment.json");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants