Skip to content

feat(search): migrate Azure AI Search to the 2026-04-01 API and profile-based vector schema - #2604

Open
Rana Singh (ranadeepsingh) wants to merge 5 commits into
microsoft:masterfrom
ranadeepsingh:copilot/search-api-modernization
Open

feat(search): migrate Azure AI Search to the 2026-04-01 API and profile-based vector schema#2604
Rana Singh (ranadeepsingh) wants to merge 5 commits into
microsoft:masterfrom
ranadeepsingh:copilot/search-api-modernization

Conversation

@ranadeepsingh

@ranadeepsingh Rana Singh (ranadeepsingh) commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Related work

Problem

SynapseML defaulted to the deprecated 2023-07-01-Preview data-plane API. Moving to the stable 2026-04-01 API also requires adopting the profile-based vector schema without breaking the published Scala model or dropping valid service fields.

Changes

  • Default Azure AI Search requests to 2026-04-01.
  • Treat 2023-10-01-Preview and later as profile-based vector APIs:
    • vectorSearch.algorithms and vectorSearch.profiles
    • field-level vectorSearchProfile
    • searchable: true on vector fields
  • Keep the published VectorSearch and IndexField case-class constructor, companion, and extractor shapes unchanged.
  • Modernize REST payloads with lossless JSON-AST transformations that preserve algorithm parameters, vectorizers, compressions, and unknown future fields.
  • Upgrade caller-supplied legacy JSON when sending it to a modern API.
  • Reject lossy modern-to-legacy conversion with an actionable error; callers can still supply an explicit legacy definition with apiVersion=2023-07-01-Preview.
  • Detect an existing legacy index before document upload. createIfNoneExists validates the actual remote schema with one LIST plus one GET and fails early with migration guidance instead of implying that a no-op create migrated the index.
  • Use the selected API version consistently for index and document endpoints.
  • Update Search docs and samples, including the 2026 vector query shape:
    vectorQueries: [{"kind":"vector","vector":[...],"fields":"embeddings","k":5}].

Release compatibility

The Spark 4.1 replay needs the AAD authentication precursor from #2591, which is already on master but not yet on the release branch. The compatibility job now reads an ordered manifest of full target-branch commit SHAs, applies only their release-relevant paths, skips content already present, and then replays this PR. This keeps the check generic and removes the prerequisite automatically once the release branch contains the backport.

Existing-index behavior

This PR does not destructively rewrite existing indexes. If a legacy vector index is opened with a modern API version, SynapseML explains the two safe options:

  1. Continue temporarily with apiVersion=2023-07-01-Preview.
  2. Explicitly migrate the index with Azure AI Search Create or Update Index after reviewing the schema changes.

Modern API responses that normalize a legacy vector field to dimensions plus a null profile are still detected as legacy. The shared document-QA sample pins writes to 2023-07-01-Preview until its persistent index is explicitly migrated; its vector query remains on 2026-04-01.

Validation

Dependencies

No dependency changes.

Copilot AI lite review requested due to automatic review settings August 4, 2026 09:27
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Hey Rana Singh (@ranadeepsingh) 👋!
Thank you so much for contributing to our repository 🙌.
Someone from SynapseML Team will be reviewing this pull request soon.

We use semantic commit messages to streamline the release process.
Before your pull request can be merged, you should make sure your first commit and PR title start with a semantic prefix.
This helps us to create release messages and credit you for your hard work!

Examples of commit messages with semantic prefixes:

  • fix: Fix LightGBM crashes with empty partitions
  • feat: Make HTTP on Spark back-offs configurable
  • docs: Update Spark Serving usage
  • build: Add codecov support
  • perf: improve LightGBM memory usage
  • refactor: make python code generation rely on classes
  • style: Remove nulls from CNTKModel
  • test: Add test coverage for CNTKModel

To test your commit locally, please follow our guild on building from source.
Check out the developer guide for additional guidance on testing your change.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates SynapseML’s Azure AI Search integration to default to the 2026-04-01 data-plane API while preserving compatibility across the legacy (pre-2023-11-01) and modern vector index schema shapes by translating index definitions to the schema required by the selected api-version.

Changes:

  • Switch default Azure AI Search API version to 2026-04-01 and add an api-version gate for profile-based vector schemas.
  • Introduce vector schema alignment (legacy ⇄ modern), including dual parsing and a unified vectorReference accessor.
  • Update writer behavior so document upload uses the same resolved api-version as index operations; refresh docs/notebooks to “Azure AI Search” and current sample API versions.
Show a summary per file
File Description
docs/Quick Examples/transformers/cognitive/_AzureSearch.md Renames service heading to Azure AI Search.
docs/Explore Algorithms/OpenAI/Quickstart - Understand and Search Forms.ipynb Updates narrative + sample REST api-version to 2026-04-01.
docs/Explore Algorithms/AI Services/Quickstart - Document Question and Answering with PDFs.ipynb Updates naming + vector-store REST api-version to 2026-04-01.
docs/Explore Algorithms/AI Services/Quickstart - Create a Visual Search Engine.ipynb Updates naming + sample REST api-version to 2026-04-01.
docs/Explore Algorithms/AI Services/Overview.ipynb Updates Azure AI Search naming in overview and comments.
cognitive/src/test/scala/com/microsoft/azure/synapse/ml/services/search/VectorSchemaMigrationSuite.scala Adds secret-free tests validating schema migration + version gate behavior.
cognitive/src/test/scala/com/microsoft/azure/synapse/ml/services/search/split2/SearchWriterSuitePart2.scala Uses version-agnostic vectorReference assertion for vectors.
cognitive/src/test/scala/com/microsoft/azure/synapse/ml/services/search/split1/SearchWriterSuitePart1.scala Uses version-agnostic vectorReference assertions for vectors.
cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearchSchemas.scala Adds modern vector schema types (profiles/algorithms), vectorReference, and VectorSchema.align.
cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearchAuth.scala Updates user-facing auth error strings to “Azure AI Search”.
cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearchAPI.scala Defaults api-version to 2026-04-01; aligns schema pre-validation; updates vector validation to use vectorReference.
cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearch.scala Emits modern vector schema by default; pins AddDocuments endpoint to the selected api-version; switches vector detection to isVectorField.

Review details

Suppressed comments (1)

cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearchAPI.scala:160

  • validateIndexInfo aligns vector schemas but still allows vector fields to be sent without any vectorSearch.algorithms / legacy vectorSearch.algorithmConfigurations being defined (e.g., if a user supplies dimensions + vectorSearchProfile/config on fields but omits the vectorSearch section). That will pass current validation and fail later at request time with a less actionable service error. Consider rejecting this early with an explicit validation check after alignment.
  private def validateIndexInfo(indexJson: String, apiVersion: String): Try[IndexInfo] = {
    // Align first so the definition that is validated is exactly the one that gets sent.
    val schema = VectorSchema.align(parseIndexJson(indexJson), apiVersion)
    for {
      _ <- validName(schema.name.get)
      _ <- validIndexFields(schema.fields)
    } yield schema
  }
  • Files reviewed: 12/12 changed files
  • Comments generated: 0
  • Review effort level: Lite

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.00000% with 46 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.21%. Comparing base (0dfddd3) to head (bd75e92).

Files with missing lines Patch % Lines
...ynapse/ml/services/search/AzureSearchSchemas.scala 72.50% 33 Missing ⚠️
...re/synapse/ml/services/search/AzureSearchAPI.scala 78.00% 11 Missing ⚠️
...e/synapse/ml/services/search/AzureSearchAuth.scala 33.33% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2604      +/-   ##
==========================================
- Coverage   86.33%   86.21%   -0.12%     
==========================================
  Files         335      335              
  Lines       18007    18178     +171     
  Branches     1658     1706      +48     
==========================================
+ Hits        15546    15673     +127     
- Misses       2461     2505      +44     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI review requested due to automatic review settings August 7, 2026 04:46
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 12/12 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Rana Singh (ranadeepsingh) pushed a commit to ranadeepsingh/SynapseML that referenced this pull request Aug 7, 2026
## Summary
Preserve published Azure Search schema APIs while modernizing REST payloads losslessly, enforce the correct profile-schema version boundary, validate actual remote indexes, and update the 2026 vector-query sample.

## Prompting Intent
Rebase PR microsoft#2604 onto current master and resolve all review findings without destructive migrations or avoidable network calls. Keep public JVM/source behavior compatible, preserve unknown service fields, use the selected API version consistently, and retain a lean and performant Search writer path.

## Linked Sources
- Pull request: microsoft#2604
- Authentication precursor: microsoft#2591
- Azure AI Search API migration guidance: https://learn.microsoft.com/azure/search/search-api-migration
- Create or Update Index API: https://learn.microsoft.com/rest/api/searchservice/indexes/create-or-update

## Rationale
Public case-class shapes remain unchanged while JSON-AST transforms rename only schema-generation keys, preserving tuning, vectorizer, compression, and future fields. Existing legacy indexes fail with actionable guidance rather than being silently ignored or destructively rewritten. Explicit date parsing avoids lexical version bugs, and direct index creation validates the fetched remote schema with one list and one GET whose responses are always closed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 81d39bfc-927c-418a-90a8-e0f2cd8fc128
@ranadeepsingh
Rana Singh (ranadeepsingh) force-pushed the copilot/search-api-modernization branch from e161131 to 92d7f41 Compare August 7, 2026 08:12
Copilot AI review requested due to automatic review settings August 7, 2026 08:12
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (2)

cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearch.scala:368

  • When the index does not exist, prepareDF calls getExisting(...) and then calls SearchIndex.createIfNoneExists(...), which performs its own client.getExisting(...) list call. This results in two index LIST requests on the create path (extra latency + rate-limit pressure). Consider refactoring so the create path reuses the already-fetched index list (e.g., call the private[search] createIfNoneExists(..., client) overload with a client that returns the cached list).
    val existingIndexJsonOpt = if (getExisting(auth, serviceName, apiVersion).contains(indexName)) {
      if (indexJsonOpt.isDefined) {
        println(f"indexJsonOpt is specified, however an index for $indexName already exists," +
          f"we will use the index definition obtained from the existing index instead")
      }
      val existingIndexJson = IndexJsonReader.get(auth, serviceName, indexName, apiVersion)
      VectorSchema.requireCompatibleExistingIndex(existingIndexJson.parseJson, apiVersion)
      Some(existingIndexJson)
    } else {
      None
    }

    val (indexJson, preppedDF) = resolveIndexDefinition(
      existingIndexJsonOpt, indexJsonOpt, vectorColsInfo, df, indexName, keyCol, actionCol)

    // TODO: Support vector search in nested fields
    // Throws an exception if any nested field is a vector in the schema
    parseIndexJson(indexJson).fields.foreach(_.fields.foreach(assertNoNestedVectors))

    if (existingIndexJsonOpt.isEmpty) {
      SearchIndex.createIfNoneExists(auth, serviceName, indexJson, apiVersion)
    }

cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearch.scala:347

  • apiVersion is used in getExisting(...) before it is validated. If a caller supplies an invalid apiVersion, this will attempt a network request and only fail later, even though supportsVectorProfiles is intended to reject invalid versions before sending requests. Validate apiVersion right before the first request.

    val existingIndexJsonOpt = if (getExisting(auth, serviceName, apiVersion).contains(indexName)) {
  • Files reviewed: 12/12 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Rana Singh (ranadeepsingh) pushed a commit to ranadeepsingh/SynapseML that referenced this pull request Aug 7, 2026
## Summary
Teach the release-branch compatibility job to apply explicitly declared, release-relevant prerequisite commits before replaying the current PR, and cover the behavior with an executable isolated Git test.

## Prompting Intent
Prepare PR microsoft#2604 for merge after its Spark 4.1 validation exposed a dependency on the already-merged Azure AI Search authentication precursor. Keep the fix generic, deterministic, safe against arbitrary commit injection, and inexpensive for future release compatibility checks.

## Linked Sources
- Pull request: microsoft#2604
- Authentication precursor: microsoft#2591
- Spark 4.1 compatibility branch: https://github.com/microsoft/SynapseML/tree/spark4.1

## Rationale
A small ordered manifest avoids hard-coding PR-specific logic into the pipeline. Each full SHA must be an ancestor of the PR target, only release-relevant paths are replayed, and reverse application detects prerequisites already present on a release branch. Applying staged prerequisite patches before the target-relative PR patch preserves the exact compatibility scenario while avoiding rebases, network API lookups, and unrelated infrastructure changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 81d39bfc-927c-418a-90a8-e0f2cd8fc128
Copilot AI review requested due to automatic review settings August 7, 2026 09:03
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Rana Singh (ranadeepsingh) pushed a commit to ranadeepsingh/SynapseML that referenced this pull request Aug 7, 2026
## Summary
Detect legacy vector indexes whose modern API representation omits profile references, and keep the shared document-QA sample on the explicit legacy write path until that index is migrated.

## Prompting Intent
Audit and repair PR microsoft#2604 after Azure validation exposed a real Databricks notebook regression. Preserve the PR's non-destructive migration contract, keep new indexes on the 2026 API default, retain VectorUDT upload compatibility for the existing shared sample, and add focused regression coverage.

## Linked Sources
- Pull request: microsoft#2604
- Failed Azure build: https://msdata.visualstudio.com/_build/results?buildId=230161909
- Azure AI Search API migration guidance: https://learn.microsoft.com/azure/search/search-api-migration
- Create or Update Index API: https://learn.microsoft.com/rest/api/searchservice/indexes/create-or-update

## Rationale
Azure AI Search normalizes a legacy index queried through a modern API into algorithms plus a vector field with dimensions but a null profile. Detecting that semantic shape preserves the actionable migration error instead of reaching an unrelated schema-parity assertion. Pinning only the shared legacy sample to 2023-07-01-Preview avoids deleting or silently rewriting the persistent index, while newly created indexes continue to use the modern default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 81d39bfc-927c-418a-90a8-e0f2cd8fc128
Copilot AI review requested due to automatic review settings August 7, 2026 10:58
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (2)

tools/ci/tests/test_pipeline_yaml.py:360

  • This test is named as a format/validation check, but it hard-codes the exact prerequisite SHA list. That will cause unrelated breakages whenever the prerequisites file is updated (e.g., when the backport lands or additional prerequisites are added). Prefer validating that prerequisites are present, unique, and full 40-character SHAs.
    assert lines == ["04897bae9baa08f0d67855566f7bad235791d508"]
    assert all(re.fullmatch(r"[0-9a-fA-F]{40}", line) for line in lines)

cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearchSchemas.scala:284

  • In rewriteField, the thrown error says it cannot create a vector profile for an algorithm name, but this code path also handles modern vectorSearchProfile values (which are profile names). The message is misleading and makes debugging invalid modern schemas harder.
      val reference = selectAlias(fields, ModernFieldReferenceKey, LegacyFieldReferenceKey).map {
        case JsString(name) =>
          JsString(references.getOrElse(name, throw new IllegalArgumentException(
            s"Cannot find or create a vector profile for algorithm '$name'")))
  • Files reviewed: 15/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

… vector schema

SynapseML pinned `2023-07-01-Preview`, the only preview data-plane version Microsoft
explicitly tags "(deprecated)" — deprecated 2024-04-08 and out of support since
2024-07-08. This moves the default to the current stable version, `2026-04-01`.

`2023-11-01` introduced a breaking change to the vector index schema that SynapseML
never adopted, so a naive version bump would break every vector index:

  legacy (<= 2023-10-01-preview)   modern (>= 2023-11-01)
  vectorSearch.algorithmConfigurations -> vectorSearch.algorithms + .profiles
  field.vectorSearchConfiguration      -> field.vectorSearchProfile
  searchable not allowed on a vector   -> searchable: true is required

Rather than a hard cutover, `VectorSchema.align` translates a parsed index definition
in both directions to whatever shape the requested api-version expects, and runs
before validation so what is validated is exactly what is sent. Users who pass legacy
`indexJson`, and users who pin an older `apiVersion`, both keep working.

When upgrading legacy JSON each algorithm config is mirrored as a same-named profile,
so pre-existing `vectorSearchConfiguration: "vectorConfig"` field references resolve
unchanged. `getVectorColConf` reads back either spelling.

Also fixes a pre-existing inconsistency where `AddDocuments` hard-coded the default
api-version in its document endpoint, so an explicit `apiVersion` option applied to
index creation but silently not to document upload.

Public class names are deliberately unchanged; renaming `AzureSearch` /
`AzureSearchWriter` / `AddDocuments` would be a breaking API change.

Adds VectorSchemaMigrationSuite: 10 credential-free tests covering the version gate,
both translation directions, idempotency, round-tripping, dual parsing and nested
fields. Verified with cognitive/Test/compile, scalastyle, Test/scalastyle (0 errors)
and 65/65 passing search tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 06ab581d-5e25-497c-a1b5-95f94ed63b21
…fresh api-versions

The service was renamed to Azure AI Search; SynapseML docs still called it Azure
Cognitive Search. Sample `apiVersion` values were also stale (`2019-05-06` and the
deprecated `2023-07-01-Preview`) and are now `2026-04-01`, matching the new default.

Only prose and sample values change — the `AzureSearchWriter` / `AzureSearch` API
names are untouched. `website/versioned_docs/**` is intentionally left alone since
those are frozen release snapshots. All edited notebooks re-validated as parseable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 06ab581d-5e25-497c-a1b5-95f94ed63b21
## Summary
Preserve published Azure Search schema APIs while modernizing REST payloads losslessly, enforce the correct profile-schema version boundary, validate actual remote indexes, and update the 2026 vector-query sample.

## Prompting Intent
Rebase PR microsoft#2604 onto current master and resolve all review findings without destructive migrations or avoidable network calls. Keep public JVM/source behavior compatible, preserve unknown service fields, use the selected API version consistently, and retain a lean and performant Search writer path.

## Linked Sources
- Pull request: microsoft#2604
- Authentication precursor: microsoft#2591
- Azure AI Search API migration guidance: https://learn.microsoft.com/azure/search/search-api-migration
- Create or Update Index API: https://learn.microsoft.com/rest/api/searchservice/indexes/create-or-update

## Rationale
Public case-class shapes remain unchanged while JSON-AST transforms rename only schema-generation keys, preserving tuning, vectorizer, compression, and future fields. Existing legacy indexes fail with actionable guidance rather than being silently ignored or destructively rewritten. Explicit date parsing avoids lexical version bugs, and direct index creation validates the fetched remote schema with one list and one GET whose responses are always closed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 81d39bfc-927c-418a-90a8-e0f2cd8fc128
Teach the release-branch compatibility job to apply explicitly declared, release-relevant prerequisite commits before replaying the current PR, and cover the behavior with an executable isolated Git test.

Prepare PR microsoft#2604 for merge after its Spark 4.1 validation exposed a dependency on the already-merged Azure AI Search authentication precursor. Keep the fix generic, deterministic, safe against arbitrary commit injection, and inexpensive for future release compatibility checks.

- Pull request: microsoft#2604
- Authentication precursor: microsoft#2591
- Spark 4.1 compatibility branch: https://github.com/microsoft/SynapseML/tree/spark4.1

A small ordered manifest avoids hard-coding PR-specific logic into the pipeline. Each full SHA must be an ancestor of the PR target, only release-relevant paths are replayed, and reverse application detects prerequisites already present on a release branch. Applying staged prerequisite patches before the target-relative PR patch preserves the exact compatibility scenario while avoiding rebases, network API lookups, and unrelated infrastructure changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 81d39bfc-927c-418a-90a8-e0f2cd8fc128
## Summary
Detect legacy vector indexes whose modern API representation omits profile references, and keep the shared document-QA sample on the explicit legacy write path until that index is migrated.

## Prompting Intent
Audit and repair PR microsoft#2604 after Azure validation exposed a real Databricks notebook regression. Preserve the PR's non-destructive migration contract, keep new indexes on the 2026 API default, retain VectorUDT upload compatibility for the existing shared sample, and add focused regression coverage.

## Linked Sources
- Pull request: microsoft#2604
- Failed Azure build: https://msdata.visualstudio.com/_build/results?buildId=230161909
- Azure AI Search API migration guidance: https://learn.microsoft.com/azure/search/search-api-migration
- Create or Update Index API: https://learn.microsoft.com/rest/api/searchservice/indexes/create-or-update

## Rationale
Azure AI Search normalizes a legacy index queried through a modern API into algorithms plus a vector field with dimensions but a null profile. Detecting that semantic shape preserves the actionable migration error instead of reaching an unrelated schema-parity assertion. Pinning only the shared legacy sample to 2023-07-01-Preview avoids deleting or silently rewriting the persistent index, while newly created indexes continue to use the modern default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 81d39bfc-927c-418a-90a8-e0f2cd8fc128
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

Copilot AI review requested due to automatic review settings August 7, 2026 22:51
@ranadeepsingh
Rana Singh (ranadeepsingh) force-pushed the copilot/search-api-modernization branch from 28a7cfe to bd75e92 Compare August 7, 2026 22:51
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (2)

cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearchSchemas.scala:241

  • modernizeVectorSearch only auto-generates vectorSearch.profiles when upgradingLegacy (i.e., when only algorithmConfigurations is present). If a caller supplies a mixed schema (e.g., already-renamed vectorSearch.algorithms but still no profiles), rewriteField will fail with "Cannot find or create a vector profile..." even though default profiles can be generated losslessly from the algorithms list. Consider generating default profiles whenever profiles are absent, not only when upgrading legacy keys.
    val generatedProfiles = if (upgradingLegacy) {
      algorithms.toSeq.flatMap(asArray(_, ModernAlgorithmsKey)).flatMap { algorithm =>
        val algorithmName = objectString(algorithm, "name", ModernAlgorithmsKey)
        if (profileByAlgorithm.contains(algorithmName)) {
          None

cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/search/AzureSearch.scala:351

  • prepareDF calls getExisting(auth, serviceName, apiVersion) to determine whether the index exists, but when the index does not exist it then calls SearchIndex.createIfNoneExists(...), which performs another index LIST internally. This adds an extra network round-trip on the create path (latency + potential throttling). Consider refactoring to reuse the already-fetched index list (e.g., by plumbing a cached result into SearchIndex.createIfNoneExists / its SearchIndexClient).
    val existingIndexJsonOpt = if (getExisting(auth, serviceName, apiVersion).contains(indexName)) {
      if (indexJsonOpt.isDefined) {
        println(f"indexJsonOpt is specified, however an index for $indexName already exists," +
          f"we will use the index definition obtained from the existing index instead")
      }
  • Files reviewed: 15/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

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