milvus-logo
LFAI
홈페이지
  • 통합

밀버스와 허깅 페이스를 사용한 질문 답변하기

Open In Colab GitHub Repository

시맨틱 검색을 기반으로 하는 질문 답변 시스템은 주어진 쿼리 질문에 대한 질문-답변 쌍의 데이터 세트에서 가장 유사한 질문을 찾는 방식으로 작동합니다. 가장 유사한 질문이 식별되면 데이터 세트의 해당 답변이 쿼리에 대한 답변으로 간주됩니다. 이 접근 방식은 의미론적 유사성 측정값을 사용하여 질문 간의 유사성을 결정하고 관련 답변을 검색합니다.

이 튜토리얼에서는 데이터 처리를 위한 데이터 로더 및 임베딩 생성기로 Hugging Face를, 시맨틱 검색을 위한 벡터 데이터베이스로 Milvus를 사용하여 질문 답변 시스템을 구축하는 방법을 보여드립니다.

시작하기 전에

필요한 모든 종속성이 설치되어 있는지 확인해야 합니다:

  • pymilvus파이썬 패키지는 Milvus 또는 Zilliz Cloud에서 제공하는 벡터 데이터베이스 서비스와 함께 작동합니다.
  • datasets, transformers: Hugging Face 패키지는 데이터를 관리하고 모델을 활용합니다.
  • torch강력한 라이브러리는 효율적인 텐서 연산과 딥 러닝 도구를 제공합니다.
$ pip install --upgrade pymilvus transformers datasets torch

Google Colab을 사용하는 경우 방금 설치한 종속성을 활성화하려면 런타임을 다시 시작해야 할 수 있습니다. (화면 상단의 '런타임' 메뉴를 클릭하고 드롭다운 메뉴에서 '세션 다시 시작'을 선택하세요.)

데이터 준비

이 섹션에서는 포옹하는 얼굴 데이터 세트에서 예시 질문-답변 쌍을 로드하겠습니다. 데모에서는 SQuAD의 유효성 검사 분할에서 일부 데이터만 가져옵니다.

from datasets import load_dataset


DATASET = "squad"  # Name of dataset from HuggingFace Datasets
INSERT_RATIO = 0.001  # Ratio of example dataset to be inserted

data = load_dataset(DATASET, split="validation")
# Generates a fixed subset. To generate a random subset, remove the seed.
data = data.train_test_split(test_size=INSERT_RATIO, seed=42)["test"]
# Clean up the data structure in the dataset.
data = data.map(
    lambda val: {"answer": val["answers"]["text"][0]},
    remove_columns=["id", "answers", "context"],
)

# View summary of example data
print(data)
Dataset({
    features: ['title', 'question', 'answer'],
    num_rows: 11
})

질문에 대한 임베딩을 생성하려면 포옹하는 얼굴 모델에서 텍스트 임베딩 모델을 선택할 수 있습니다. 이 튜토리얼에서는 작은 문장 임베딩 모델인 all-MiniLM-L6-v2를 예로 사용합니다.

from transformers import AutoTokenizer, AutoModel
import torch

MODEL = (
    "sentence-transformers/all-MiniLM-L6-v2"  # Name of model from HuggingFace Models
)
INFERENCE_BATCH_SIZE = 64  # Batch size of model inference

# Load tokenizer & model from HuggingFace Hub
tokenizer = AutoTokenizer.from_pretrained(MODEL)
model = AutoModel.from_pretrained(MODEL)


def encode_text(batch):
    # Tokenize sentences
    encoded_input = tokenizer(
        batch["question"], padding=True, truncation=True, return_tensors="pt"
    )

    # Compute token embeddings
    with torch.no_grad():
        model_output = model(**encoded_input)

    # Perform pooling
    token_embeddings = model_output[0]
    attention_mask = encoded_input["attention_mask"]
    input_mask_expanded = (
        attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
    )
    sentence_embeddings = torch.sum(
        token_embeddings * input_mask_expanded, 1
    ) / torch.clamp(input_mask_expanded.sum(1), min=1e-9)

    # Normalize embeddings
    batch["question_embedding"] = torch.nn.functional.normalize(
        sentence_embeddings, p=2, dim=1
    )
    return batch


data = data.map(encode_text, batched=True, batch_size=INFERENCE_BATCH_SIZE)
data_list = data.to_list()

데이터 삽입하기

이제 질문 임베딩으로 질문-답변 쌍이 준비되었습니다. 다음 단계는 이를 벡터 데이터베이스에 삽입하는 것입니다.

먼저 Milvus 서비스에 연결하여 Milvus 컬렉션을 생성해야 합니다.

from pymilvus import MilvusClient


MILVUS_URI = "./huggingface_milvus_test.db"  # Connection URI
COLLECTION_NAME = "huggingface_test"  # Collection name
DIMENSION = 384  # Embedding dimension depending on model

milvus_client = MilvusClient(MILVUS_URI)
if milvus_client.has_collection(collection_name=COLLECTION_NAME):
    milvus_client.drop_collection(collection_name=COLLECTION_NAME)
milvus_client.create_collection(
    collection_name=COLLECTION_NAME,
    dimension=DIMENSION,
    auto_id=True,  # Enable auto id
    enable_dynamic_field=True,  # Enable dynamic fields
    vector_field_name="question_embedding",  # Map vector field name and embedding column in dataset
    consistency_level="Strong",  # To enable search with latest data
)

MilvusClient 의 인수는 다음과 같습니다:

  • uri 를 로컬 파일(예:./milvus.db)로 설정하는 것이 가장 편리한 방법인데, Milvus Lite를 자동으로 활용하여 모든 데이터를 이 파일에 저장하기 때문입니다.
  • 데이터 규모가 큰 경우, 도커나 쿠버네티스에 더 고성능의 Milvus 서버를 설정할 수 있습니다. 이 설정에서는 서버 URL(예:http://localhost:19530)을 uri 으로 사용하세요.
  • 밀버스의 완전 관리형 클라우드 서비스인 질리즈 클라우드를 사용하려면, 질리즈 클라우드의 퍼블릭 엔드포인트와 API 키에 해당하는 uritoken 을 조정하세요.

모든 데이터를 수집에 삽입합니다:

milvus_client.insert(collection_name=COLLECTION_NAME, data=data_list)
{'insert_count': 11,
 'ids': [450072488481390592, 450072488481390593, 450072488481390594, 450072488481390595, 450072488481390596, 450072488481390597, 450072488481390598, 450072488481390599, 450072488481390600, 450072488481390601, 450072488481390602],
 'cost': 0}

질문하기

모든 데이터가 Milvus에 삽입되면 질문을 하고 가장 가까운 답을 확인할 수 있습니다.

questions = {
    "question": [
        "What is LGM?",
        "When did Massachusetts first mandate that children be educated in schools?",
    ]
}

# Generate question embeddings
question_embeddings = [v.tolist() for v in encode_text(questions)["question_embedding"]]

# Search across Milvus
search_results = milvus_client.search(
    collection_name=COLLECTION_NAME,
    data=question_embeddings,
    limit=3,  # How many search results to output
    output_fields=["answer", "question"],  # Include these fields in search results
)

# Print out results
for q, res in zip(questions["question"], search_results):
    print("Question:", q)
    for r in res:
        print(
            {
                "answer": r["entity"]["answer"],
                "score": r["distance"],
                "original question": r["entity"]["question"],
            }
        )
    print("\n")
Question: What is LGM?
{'answer': 'Last Glacial Maximum', 'score': 0.956273078918457, 'original question': 'What does LGM stands for?'}
{'answer': 'coordinate the response to the embargo', 'score': 0.2120140939950943, 'original question': 'Why was this short termed organization created?'}
{'answer': '"Reducibility Among Combinatorial Problems"', 'score': 0.1945795714855194, 'original question': 'What is the paper written by Richard Karp in 1972 that ushered in a new era of understanding between intractability and NP-complete problems?'}


Question: When did Massachusetts first mandate that children be educated in schools?
{'answer': '1852', 'score': 0.9709997177124023, 'original question': 'In what year did Massachusetts first require children to be educated in schools?'}
{'answer': 'several regional colleges and universities', 'score': 0.34164726734161377, 'original question': 'In 1890, who did the university decide to team up with?'}
{'answer': '1962', 'score': 0.1931006908416748, 'original question': 'When were stromules discovered?'}

번역DeepL

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
피드백

이 페이지가 도움이 되었나요?