JavaScript용 Azure AI Search 클라이언트 라이브러리 - 버전 12.0.0

Azure AI Search(이전의 "Azure Cognitive Search")는 개발자가 대규모 언어 모델을 엔터프라이즈 데이터와 결합하는 풍부한 검색 환경 및 생성 AI 앱을 빌드하는 데 도움이 되는 AI 기반 정보 검색 플랫폼입니다.

Azure AI Search는 다음 애플리케이션 시나리오에 적합합니다.

  • 다양한 콘텐츠 형식을 검색 가능한 단일 인덱스로 통합합니다. 인덱스 채우기를 위해 콘텐츠가 포함된 JSON 문서를 푸시하거나 데이터가 이미 Azure에 있는 경우 데이터를 자동으로 끌어올 인덱서를 만들 수 있습니다.
  • 인덱서에 기술 세트를 연결하여 이미지 및 큰 텍스트 문서에서 검색 가능한 콘텐츠를 만듭니다. 기술 세트는 기본 제공 OCR, 엔터티 인식, 핵심 구 추출, 언어 감지, 텍스트 번역 및 감정 분석을 위해 AI 서비스의 API를 활용합니다. 사용자 지정 기술을 추가하여 데이터 수집 중에 콘텐츠의 외부 처리를 통합할 수도 있습니다.
  • 검색 클라이언트 애플리케이션에서 상용 웹 검색 엔진과 유사한 쿼리 논리 및 사용자 환경을 구현합니다.

클라이언트 라이브러리를 @azure/search-documents 사용하여 다음을 수행합니다.

  • 벡터, 키워드(keyword) 및 하이브리드 쿼리 양식을 사용하여 쿼리를 제출합니다.
  • 메타데이터, 지리 공간적 검색, 패싯 탐색 또는 필터 조건에 따라 결과의 범위를 좁히기 위해 필터링된 쿼리를 구현합니다.
  • 검색 인덱스를 만들고 관리합니다.
  • 검색 인덱스에서 문서를 업로드하고 업데이트합니다.
  • Azure에서 인덱스로 데이터를 끌어오는 인덱서를 만들고 관리합니다.
  • 데이터 수집에 AI 보강을 추가하는 기술 세트를 만들고 관리합니다.
  • 고급 텍스트 분석 또는 다국어 콘텐츠를 위한 분석기를 만들고 관리합니다.
  • 점수 매기기 프로필을 통해 결과를 최적화하여 비즈니스 논리 또는 새로 고침을 고려합니다.

주요 링크:

시작

@azure/search-documents 패키지를 설치합니다.

npm install @azure/search-documents

현재 지원되는 환경

자세한 내용은 지원 정책을 참조하세요.

필수 구성 요소

새 검색 서비스를 만들려면 Azure Portal, Azure PowerShell 또는 Azure CLI를 사용할 수 있습니다. 다음은 Azure CLI를 사용하여 시작하기 위한 무료 instance 만드는 예제입니다.

az search service create --name <mysearch> --resource-group <mysearch-rg> --sku free --location westus

사용 가능한 옵션에 대한 자세한 내용은 가격 책정 계층 선택을 참조하세요.

클라이언트 인증

검색 서비스와 상호 작용하려면 적절한 클라이언트 클래스 SearchClient 의 instance 만들어야 합니다. 인덱싱된 문서 검색, SearchIndexClient 인덱스 관리 또는 SearchIndexerClient 데이터 원본 크롤링 및 인덱스에 검색 문서 로드용입니다.

클라이언트 개체를 인스턴스화하려면 엔드포인트Azure 역할 또는 API 키가 필요합니다. 검색 서비스에서 지원되는 인증 방법에 대한 자세한 내용은 설명서를 참조하세요.

API 키 가져오기

API 키는 기존 역할 할당이 필요하지 않으므로 더 쉽게 시작할 수 있습니다.

Azure Portal의 검색 서비스에서 엔드포인트API 키를 가져올 수 있습니다. API 키를 가져오는 방법에 대한 지침은 설명서를 참조하세요.

또는 다음 Azure CLI 명령을 사용하여 검색 서비스에서 API 키를 검색할 수 있습니다.

az search admin-key show --service-name <mysearch> --resource-group <mysearch-rg>

api-key가 있으면 다음과 같이 사용할 수 있습니다.

const {
  SearchClient,
  SearchIndexClient,
  SearchIndexerClient,
  AzureKeyCredential,
} = require("@azure/search-documents");

// To query and manipulate documents
const searchClient = new SearchClient(
  "<endpoint>",
  "<indexName>",
  new AzureKeyCredential("<apiKey>")
);

// To manage indexes and synonymmaps
const indexClient = new SearchIndexClient("<endpoint>", new AzureKeyCredential("<apiKey>"));

// To manage indexers, datasources and skillsets
const indexerClient = new SearchIndexerClient("<endpoint>", new AzureKeyCredential("<apiKey>"));

국가별 클라우드에서 인증

National Cloud에서 인증하려면 클라이언트 구성에 다음을 추가해야 합니다.

  • 에서 설정 AudienceSearchClientOptions
const {
  SearchClient,
  SearchIndexClient,
  SearchIndexerClient,
  AzureKeyCredential,
  KnownSearchAudience,
} = require("@azure/search-documents");

// To query and manipulate documents
const searchClient = new SearchClient(
  "<endpoint>",
  "<indexName>",
  new AzureKeyCredential("<apiKey>"),
  {
    audience: KnownSearchAudience.AzureChina,
  }
);

// To manage indexes and synonymmaps
const indexClient = new SearchIndexClient("<endpoint>", new AzureKeyCredential("<apiKey>"), {
  audience: KnownSearchAudience.AzureChina,
});

// To manage indexers, datasources and skillsets
const indexerClient = new SearchIndexerClient("<endpoint>", new AzureKeyCredential("<apiKey>"), {
  audience: KnownSearchAudience.AzureChina,
});

주요 개념

Azure AI Search Service JSON 문서 형식으로 검색 가능한 데이터의 영구 스토리지를 제공하는 하나 이상의 인덱스를 포함합니다. 검색을 처음 접하는 경우 인덱스와 데이터베이스 테이블 간에 매우 대략적인 비유를 만들 수 있습니다. 클라이언트 라이브러리는 @azure/search-documents 세 가지 기본 클라이언트 유형을 통해 이러한 리소스에 대한 작업을 노출합니다.

참고: 호출하는 API는 CORS(원본 간 리소스 공유)를 지원하지 않으므로 이러한 클라이언트는 브라우저에서 작동할 수 없습니다.

TypeScript/JavaScript 관련 개념

문서

검색 인덱스 내에 저장된 항목입니다. 이 문서의 모양은 를 사용하여 Field인덱스에서 설명합니다. 각 필드에는 이름, 데이터 형식 및 검색 가능하거나 필터링 가능한 경우와 같은 추가 메타데이터가 있습니다.

페이지 매김

일반적으로 한 번에 사용자에게 검색 결과의 하위 집합만 표시 하려고 합니다. 이를 지원하기 위해 , skipincludeTotalCount 매개 변수를 top사용하여 검색 결과 위에 페이징된 환경을 제공할 수 있습니다.

문서 필드 인코딩

인덱스에서 지원되는 데이터 형식은 API 요청/응답의 JSON 형식에 매핑됩니다. JS 클라이언트 라이브러리는 다음과 같은 몇 가지 예외를 제외하고 대부분 동일하게 유지합니다.

  • Edm.DateTimeOffset 는 JS 로 변환됩니다 Date.
  • Edm.GeographyPoint 는 클라이언트 라이브러리에서 GeographyPoint 내보낸 형식으로 변환됩니다.
  • 형식의 number 특수 값(NaN, Infinity, -Infinity)은 REST API에서 문자열로 직렬화되지만 클라이언트 라이브러리에서 로 다시 number 변환됩니다.

참고: 데이터 형식은 인덱스 스키마의 필드 형식이 아니라 값을 기준으로 변환됩니다. 즉, 필드 값으로 ISO8601 Date 문자열(예: "2020-03-06T18:48:27.896Z")이 있는 경우 스키마에 저장한 방법에 관계없이 날짜로 변환됩니다.

예제

다음 예제에서는 기본 사항을 보여 줍니다. 샘플을 훨씬 더 검사.

인덱스 만들기

const { SearchIndexClient, AzureKeyCredential } = require("@azure/search-documents");

const client = new SearchIndexClient("<endpoint>", new AzureKeyCredential("<apiKey>"));

async function main() {
  const result = await client.createIndex({
    name: "example-index",
    fields: [
      {
        type: "Edm.String",
        name: "id",
        key: true,
      },
      {
        type: "Edm.Double",
        name: "awesomenessLevel",
        sortable: true,
        filterable: true,
        facetable: true,
      },
      {
        type: "Edm.String",
        name: "description",
        searchable: true,
      },
      {
        type: "Edm.ComplexType",
        name: "details",
        fields: [
          {
            type: "Collection(Edm.String)",
            name: "tags",
            searchable: true,
          },
        ],
      },
      {
        type: "Edm.Int32",
        name: "hiddenWeight",
        hidden: true,
      },
    ],
  });

  console.log(result);
}

main();

인덱스에서 특정 문서 검색

특정 문서는 기본 키 값으로 검색할 수 있습니다.

const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");

const client = new SearchClient("<endpoint>", "<indexName>", new AzureKeyCredential("<apiKey>"));

async function main() {
  const result = await client.getDocument("1234");
  console.log(result);
}

main();

인덱스로 문서 추가

여러 문서를 일괄 처리 내의 인덱스로 업로드할 수 있습니다.

const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");

const client = new SearchClient("<endpoint>", "<indexName>", new AzureKeyCredential("<apiKey>"));

async function main() {
  const uploadResult = await client.uploadDocuments([
    // JSON objects matching the shape of the client's index
    {},
    {},
    {},
  ]);
  for (const result of uploadResult.results) {
    console.log(`Uploaded ${result.key}; succeeded? ${result.succeeded}`);
  }
}

main();

문서에 대한 검색 수행

특정 쿼리의 모든 결과를 나열하려면 간단한 쿼리 구문을 사용하는 검색 문자열과 함께 를 사용할 search 수 있습니다.

const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");

const client = new SearchClient("<endpoint>", "<indexName>", new AzureKeyCredential("<apiKey>"));

async function main() {
  const searchResults = await client.search("wifi -luxury");
  for await (const result of searchResults.results) {
    console.log(result);
  }
}

main();

Lucene 구문을 사용하는 고급 검색의 경우 을 로 지정 queryType 합니다full.

const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");

const client = new SearchClient("<endpoint>", "<indexName>", new AzureKeyCredential("<apiKey>"));

async function main() {
  const searchResults = await client.search('Category:budget AND "recently renovated"^3', {
    queryType: "full",
    searchMode: "all",
  });
  for await (const result of searchResults.results) {
    console.log(result);
  }
}

main();

TypeScript를 사용하여 쿼리

TypeScript에서 는 SearchClient 인덱스 문서의 모델 셰이프인 제네릭 매개 변수를 사용합니다. 이렇게 하면 결과에 반환된 필드의 강력한 형식 조회를 수행할 수 있습니다. TypeScript는 매개 변수를 지정할 때 반환되는 필드에 대해 검사 수 있습니다select.

import { SearchClient, AzureKeyCredential, SelectFields } from "@azure/search-documents";

// An example schema for documents in the index
interface Hotel {
  hotelId?: string;
  hotelName?: string | null;
  description?: string | null;
  descriptionVector?: Array<number> | null;
  parkingIncluded?: boolean | null;
  lastRenovationDate?: Date | null;
  rating?: number | null;
  rooms?: Array<{
    beds?: number | null;
    description?: string | null;
  } | null>;
}

const client = new SearchClient<Hotel>(
  "<endpoint>",
  "<indexName>",
  new AzureKeyCredential("<apiKey>")
);

async function main() {
  const searchResults = await client.search("wifi -luxury", {
    // Only fields in Hotel can be added to this array.
    // TS will complain if one is misspelled.
    select: ["hotelId", "hotelName", "rooms/beds"],
  });

  // These are other ways to declare the correct type for `select`.
  const select = ["hotelId", "hotelName", "rooms/beds"] as const;
  // This declaration lets you opt out of narrowing the TypeScript type of your documents,
  // though the AI Search service will still only return these fields.
  const selectWide: SelectFields<Hotel>[] = ["hotelId", "hotelName", "rooms/beds"];
  // This is an invalid declaration. Passing this to `select` will result in a compiler error
  // unless you opt out of including the model in the client constructor.
  const selectInvalid = ["hotelId", "hotelName", "rooms/beds"];

  for await (const result of searchResults.results) {
    // result.document has hotelId, hotelName, and rating.
    // Trying to access result.document.description would emit a TS error.
    console.log(result.document.hotelName);
  }
}

main();

OData 필터를 사용하여 쿼리

쿼리 매개 변수를 filter 사용하면 OData $filter 식의 구문을 사용하여 인덱스를 쿼리할 수 있습니다.

const { SearchClient, AzureKeyCredential, odata } = require("@azure/search-documents");

const client = new SearchClient("<endpoint>", "<indexName>", new AzureKeyCredential("<apiKey>"));

async function main() {
  const baseRateMax = 200;
  const ratingMin = 4;
  const searchResults = await client.search("WiFi", {
    filter: odata`Rooms/any(room: room/BaseRate lt ${baseRateMax}) and Rating ge ${ratingMin}`,
    orderBy: ["Rating desc"],
    select: ["hotelId", "hotelName", "rating"],
  });
  for await (const result of searchResults.results) {
    // Each result will have "HotelId", "HotelName", and "Rating"
    // in addition to the standard search result property "score"
    console.log(result);
  }
}

main();

벡터를 사용하여 쿼리

검색 매개 변수를 사용하여 텍스트 포함을 vector 쿼리할 수 있습니다.

const { SearchClient, AzureKeyCredential, odata } = require("@azure/search-documents");

const searchClient = new SearchClient("<endpoint>", "<indexName>", new AzureKeyCredential("<apiKey>"));

async function main() {
  const queryVector = [...]
  const searchResults = await searchClient.search("*", {
    vector: {
      fields: ["descriptionVector"],
      kNearestNeighborsCount: 3,
      value: queryVector,
    },
  });
  for await (const result of searchResults.results) {
    // These results are the nearest neighbors to the query vector
    console.log(result);
  }
}

main();

패싯을 사용하여 쿼리

패싯 은 애플리케이션 사용자가 미리 구성된 차원을 따라 검색을 구체화하는 데 사용됩니다. 패싯 구문 은 패싯 값을 정렬하고 버킷하는 옵션을 제공합니다.

const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");

const client = new SearchClient("<endpoint>", "<indexName>", new AzureKeyCredential("<apiKey>"));

async function main() {
  const searchResults = await client.search("WiFi", {
    facets: ["category,count:3,sort:count", "rooms/baseRate,interval:100"],
  });
  console.log(searchResults.facets);
  // Output will look like:
  // {
  //   'rooms/baseRate': [
  //     { count: 16, value: 0 },
  //     { count: 17, value: 100 },
  //     { count: 17, value: 200 }
  //   ],
  //   category: [
  //     { count: 5, value: 'Budget' },
  //     { count: 5, value: 'Luxury' },
  //     { count: 5, value: 'Resort and Spa' }
  //   ]
  // }
}

main();

결과를 facets 검색할 때 각 패싯 버킷에 속하는 결과 수를 나타내는 속성을 사용할 수 있습니다. 구체화를 구동하는 데 사용할 수 있습니다(예: 3보다 크거나 같거나 4보다 작은 것을 필터링 Rating 하는 후속 검색 실행).

문제 해결

로깅

로깅을 사용하도록 설정하면 실패에 대한 유용한 정보를 파악하는 데 도움이 될 수 있습니다. HTTP 요청 및 응답 로그를 보려면 AZURE_LOG_LEVEL 환경 변수를 info로 설정합니다. 또는 @azure/logger에서 setLogLevel을 호출하여 런타임에 로깅을 사용하도록 설정할 수 있습니다.

import { setLogLevel } from "@azure/logger";

setLogLevel("info");

로그를 사용하는 방법에 대한 자세한 내용은 @azure/logger package docs를 참조하세요.

다음 단계

참여

이 라이브러리에 기여하려면 기여 가이드 를 참조하여 코드를 빌드하고 테스트하는 방법에 대해 자세히 알아보세요.

이 프로젝트에 대한 기여와 제안을 환영합니다. 대부분의 경우 기여하려면 권한을 부여하며 실제로 기여를 사용할 권한을 당사에 부여한다고 선언하는 CLA(기여자 라이선스 계약)에 동의해야 합니다. 자세한 내용은 cla.microsoft.com.

이 프로젝트는 Microsoft 오픈 소스 행동 강령을 채택했습니다. 자세한 내용은 행동 강령 FAQ 를 참조하거나 추가 질문 또는 의견을 문의 opencode@microsoft.com 하세요.

Impressions