Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Palantir 제공 모델로 의미 기반 검색 구성

플랫폼 인스턴스(Enrollment)에 AIP가 활성화되어 있고 AIP 개발 기능을 사용할 권한이 있어야 합니다. 문서와 질의를 같은 임베딩 모델(Embedding model)로 처리하고 벡터를 객체 속성(Property)에 저장합니다.

문서 임베딩과 객체 유형

Pipeline Builder의 Text to embeddings 표현식은 문자열을 선택한 모델의 벡터로 변환합니다. 이 예제는 문서와 질의를 모두 text-embedding-ada-002로 처리하며 벡터 길이는 1,536입니다. 모델을 교체하면 문서 전체를 다시 처리하고 질의 모델도 함께 바꿉니다.

출력 벡터를 객체 유형(Object type)의 vector 속성으로 매핑합니다. 청크 구성의 결과를 사용한다면 아래와 같은 가상 Chunk 유형을 만들 수 있습니다. 코드의 Chunk와 속성 이름은 이 스키마를 전제로 하므로 자신의 유형 이름과 다르면 함께 바꿉니다.

데이터 열속성 API 이름용도
chunk_idid문자열 기본 키(Primary key)
chunktext검색 근거가 될 원문 텍스트
embeddingembedding모델이 반환한 벡터

이 예제의 벡터 속성은 차원을 1,536으로 설정합니다. 문자열 질의를 자동으로 임베딩하는 검색에서는 속성에 지정한 모델도 문서 생성에 사용한 text-embedding-ada-002와 같아야 합니다. 다른 모델을 사용한다면 실제 출력 길이에 맞춰 차원을 정하고 검색 인터페이스의 한도도 확인합니다. Python 변환에서 모델을 호출하면 임베딩 생성 과정을 코드로 제어할 수 있습니다.

Workshop의 코드 없는 KNN 검색

K-최근접 이웃(K-nearest neighbors, KNN)은 질의 벡터와 가까운 객체를 고르는 검색입니다.

  1. Workshop에서 객체 집합(Object set) 변수를 만들고 임베딩 속성이 있는 유형을 선택합니다.
  2. 필터의 + On a property에서 임베딩 속성을 선택합니다.
  3. KNN 설정이 나타나지 않으면 선택한 속성이 임베딩 속성인지 확인합니다.

K-value는 반환할 객체 수이며 1부터 100까지 설정합니다. Query에는 검색 문자열 변수를 연결합니다. Text Input 위젯의 출력 변수를 Query로 지정하고 Object Table 위젯의 입력에는 방금 만든 KNN 객체 집합을 연결합니다.

이 코드 없는 KNN 객체 집합은 관련도 순으로 정렬할 수 없습니다. 순서가 필요한 결과에는 아래 TypeScript 함수의 관련도 정렬을 사용합니다.

AIP Chatbot에서 검색

AIP Chatbot Studio에서 챗봇을 만든 뒤 Ontology context를 추가하거나 Ontology semantic search 도구를 추가합니다. 이렇게 객체 검색 범위를 연결하면 챗봇에 관련 객체를 자연어로 찾아 달라고 요청할 수 있습니다. 검색 전후 처리나 필터를 직접 제어하려면 검색 함수를 만들어 사용합니다.

함수 저장소 준비

사용할 객체 유형을 저장소의 Resource imports에 추가합니다. TypeScript v1에서는 Models에서 text-embedding-ada-002를 가져옵니다. 아래 코드는 이 모델의 레거시 바인딩인 TextEmbeddingAda_002를 사용합니다. 모델 선택 후 생성한 바인딩의 이름과 호출 예는 사이드바에서 확인합니다.

TypeScript v1 저장소의 functions-typescript/functions.json에서는 다른 기존 설정을 유지하고 다음 값을 반영한 뒤 변경을 커밋합니다.

{
  "enableVectorProperties": true
}

TypeScript v2와 Python에는 이 TypeScript v1 설정 파일을 적용하지 않습니다. 두 버전은 가져온 객체 유형으로 Ontology SDK를 생성하고 설치합니다. 벡터 설정을 마쳤는데 KNN 호출이 실패하면 저장소 버전에 맞는 구성과 모델 접근을 확인하고 Palantir 담당자에게 문의합니다.

TypeScript v1

functions-typescript/src/index.ts에서 내보내는 클래스의 메서드에 @Function()을 붙입니다. 질의를 모델에 보내 벡터를 얻고 nearestNeighbors에 전달합니다. kValue 범위는 1부터 100까지이며 검색 벡터는 최대 2,048차원입니다. 인덱싱한 벡터와 검색 벡터의 차원도 같아야 합니다. 모델 호출이 실패하거나 벡터가 없으면 검색을 진행하지 않고 오류를 반환합니다.

import { Function, Integer } from "@foundry/functions-api";
import { Objects, Chunk } from "@foundry/ontology-api";
import { TextEmbeddingAda_002 } from "@foundry/models-api/language-models";

export class SemanticSearch {
    @Function()
    public async findRelevantObjects(query: string, kValue: Integer): Promise<Chunk[]> {
        if (query.length === 0) {
            return [];
        }
        const response = await TextEmbeddingAda_002.createEmbeddings({ inputs: [query] });
        const embedding = response.embeddings[0];
        if (embedding === undefined) {
            throw new Error("The embedding model returned no vector");
        }
        return Objects.search()
            .chunk()
            .nearestNeighbors(obj => obj.embedding.near(embedding, { kValue }))
            .orderByRelevance()
            .takeAsync(kValue);
    }
}

레거시 임베딩 호출은 response.embeddings를 반환합니다. 새 모델 바인딩의 태그가 있는 응답과는 반환 형식이 다릅니다.

TypeScript v2

typescript-functions/src/functions/findRelevantObjects.ts에 기본 내보내기 함수를 둡니다. 파일 이름과 함수 이름이 같아야 합니다. 첫 매개변수로 받는 Ontology SDK 클라이언트가 질의를 실행합니다.

nearestNeighbors는 문자열을 받으면 속성에 지정한 모델로 임베딩합니다. 이 경로에는 별도 임베딩 호출이 필요하지 않습니다. numNeighbors에 해당하는 kValue 범위는 1부터 500까지입니다. fetchPage의 $orderBy를 relevance로 지정하여 순서를 요청합니다.

import { Client, Osdk } from "@osdk/client";
import { Integer } from "@osdk/functions";
import { Chunk } from "@ontology/sdk";

export default async function findRelevantObjects(
    client: Client,
    query: string,
    kValue: Integer,
): Promise<Osdk.Instance<Chunk>[]> {
    if (query.length === 0) {
        return [];
    }
    const page = await client(Chunk)
        .nearestNeighbors(query, kValue, "embedding")
        .fetchPage({ $pageSize: kValue, $orderBy: "relevance" });
    return page.data;
}

Python

Python 함수 모듈에서 @function(beta=True)를 사용합니다. nearest_neighbors는 베타 기능이며 문자열 질의를 자동으로 임베딩합니다. 반환 객체에는 _score가 포함됩니다. 이 예는 이웃 개수로 결과를 제한하며 TypeScript의 정렬 메서드를 Python에 옮겨 쓰지 않습니다.

from functions.api import function, Integer
from ontology_sdk import FoundryClient
from ontology_sdk.ontology.objects import Chunk


@function(beta=True)
def find_relevant_objects(query: str, k_value: Integer) -> list[Chunk]:
    if len(query) == 0:
        return []
    client = FoundryClient()
    return list(
        client.ontology.objects.Chunk.nearest_neighbors(
            query=query,
            num_neighbors=k_value,
            vector_property=Chunk.object_type.embedding,
        )
    )

함수를 저장소에서 게시하면 다른 Foundry 앱이 사용할 수 있습니다. 각 저장소에서 생성된 객체 이름, 속성 및 함수 입력 형식에 맞춰 호출합니다.

Workshop과 AIP Logic에 연결

Workshop 앱에 Text Input을 추가하고 검색 함수의 query 입력에 연결합니다. Object List의 입력 객체 집합은 함수 기반 변수로 구성합니다. 이웃 수는 TypeScript의 kValue 또는 Python의 k_value에 전달합니다.

AIP Logic에서는 게시한 함수를 도구로 추가합니다. TypeScript 예제의 함수라면 다음과 같이 사용을 지시할 수 있습니다.

관련 객체를 찾을 때 findRelevantObjects를 사용합니다. kValue는 5로 지정하고 query에는 검색할 문장을 문자열로 전달합니다. 도구 입력에서 query 문자열을 큰따옴표로 감쌉니다.

Python 함수를 선택했다면 실제 게시된 함수 이름과 k_value 매개변수에 맞춰 지시문을 바꿉니다.