+3

QuickStart và một vài cách custom nhanh giúp cải thiện Azure AI Search (phần 2)

Ở phần trước chúng ta đã đi qua các mục giới thiệu về Azure AI Search và cách Indexing. Trong phần này chúng ta sẽ đi vào các cách Querying và một số mẹo tinh chỉnh chúng.

Cùng bắt đầu nào!

Nội dung

3. Querying

Azure AI Search hỗ trợ các cấu trúc truy vấn cho nhiều tình huống khác nhau, từ tìm kiếm văn bản dạng tự do đến các mẫu truy vấn được chỉ định cụ thể đến tìm kiếm vectơ. Tất cả các truy vấn chỉ được thực thi trên một index được chỉ định trước. Có 3 kiểu search trên Azure AI Search:

  • Full-text search
  • Vector search
  • Hybrid search: Full-text search + Vector search Chúng ta sẽ bắt đầu đi vào chi tiết từng phần luôn.

3.1. Vector search

Vector search thực hiện truy vấn trên các trường biểu diễn nội dung bằng vector số. Vì nội dung là vector số chứ không phải văn bản thuần túy nên việc so khớp dựa trên các vectơ giống nhất với vectơ truy vấn: tính toán độ tương đồng giữa các vector (Cosine, Euclidean, ...).

Những để thực hiện được vector search thì cần phải có các trường chứa nội dung là vector bên trong index và cách khai báo các trường này ở Indexing cũng sẽ hơi khác một chút:

SearchField(
    name='embedding_text', type=SearchFieldDataType.Collection(SearchFieldDataType.Single),
    searchable=True, vector_search_dimensions=1024, vector_search_profile='myHnswProfile',
)

Nếu bạn sử dụng thiết lập mặc định thì khi bạn gửi 1 vector qua client, Azure Search sẽ sử dụng thuật toán CosineSimilarity để tính toán độ tương đồng giữa vector của bạn với các vector trong index. Từ đó trả về top các kết quả có score cao nhất.

Sau đây là ví dụ về cách thực hiện truy vấn:

vectors = [
    RawVectorQuery(
        vector=vector_embedding,
        k=topk,
        fields=fields,
    ),
]
 search_client.search(
    search_text=None,
    vector_queries=vectors,
    select=select_fields,
    top=topk,
)        

Những parameters cần được khai báo là:

  • vector: vector của bạn để thực hiện truy vấn
  • top: số lượng kết quả bạn muốn nhận về
  • fields: tên của các trường mà bạn thực hiện truy vấn trên đó
  • select: những trường bạn muốn kết quả trả ra
  • search_text: do chúng ta thực hiện search trên vector nhưng vẫn phải khai báo parameter này nên sẽ để None

Vector thường sẽ là vector embedding của các văn bạn được lưu trữ và của câu hỏi/tài liệu cần search. Trong trường hợp văn bản quá dài, bạn có thể cân nhắc tóm tắt trước khi thực hiện embedding để việc search đạt hiệu quả cao nhất.

3.2. Full-text search

Full-text search là là một cách tiếp cận trong việc truy xuất thông tin khớp với văn bản thuần túy được lưu trữ trong index. Để quét hiệu quả hơn, các chuỗi truy vấn phải trải qua quá trình phân tích từ vựng: viết thường tất cả các thuật ngữ, loại bỏ các stop-words và rút gọn các thuật ngữ. Khi tìm thấy các cụm từ phù hợp, công cụ tìm kiếm sẽ truy xuất tài liệu, xếp hạng chúng theo thứ tự mức độ liên quan và trả về kết quả hàng đầu.

Đây là code cho Full-text search:

search_client.search(
    search_text=search_query,
    vector_queries=None,
    select=select_fields,
    search_fields=['text'],
    top=topk,
    search_mode='all',
    query_language='vi-vn',
)

Có thể thấy với full-text search sẽ đảo ngược với vector search khi vector_queries được set về None còn search_text sẽ được truyền dữ liệu. Còn lại những parameter khác sẽ khá tương đồng nhau.

Full-text search tính điểm và ranking dựa theo thuật toán BM25Similarity. BM25 tính điểm dựa theo tần suất thuật ngữ và độ dài tài liệu. Bạn có thể tùy chỉnh trọng số của các thuộc tính này nếu các trọng số mặc định không phù hợp với nội dung của bạn.

  • k1 (float): giá trị thường là 0,0 đến 3,0, với 1,2 là mặc định. Giá trị 0,0 thể hiện sự đóng góp của một thuật ngữ là giống nhau cho tất cả các tài liệu, bất kể thuật ngữ đó xuất hiện bao nhiêu lần trong văn bản. Giá trị k1 lớn hơn cho phép điểm tiếp tục tăng khi một thuật ngữ xuất hiện nhiều lần trong tài liệu. Có thể hiểu là k1 càng lớn thì: số lần xuất hiện của thuật ngữ càng nhiều, điểm của tài liệu đó càng cao.
  • b (float): giá trị thường là 0,0 đến 1,0, với 0,75 là mặc định. Giá trị 0,0 có nghĩa là độ dài của tài liệu không ảnh hưởng đến điểm số. Giá trị 1,0 có nghĩa là ảnh hưởng của tần suất thuật ngữ đến điểm liên quan được chuẩn hóa theo độ dài của tài liệu (2 tài liệu có cùng tuần suất xuất hiện thuật ngữ thì tài liệu nào ngắn hơn sẽ có điểm cao hơn).

Để điều chỉnh 2 tham số này, chúng ta sẽ cần khai báo ngay từ khi tạo index:

from azure.search.documents.indexes.models import BM25Similarity

index.similarity = (BM25Similarity(k1=2, b=0))

Ngoài search bằng 1 câu văn dài, chúng ta còn có thể search bằng các keywords để tăng hiệu quả tìm kiếm. Sau đây sẽ là cách tìm kiếm bằng keywords:

search_query = ('|'.join([f'\"{i}\" ' for i in keywords]))

'|' nghĩa là or, sửa dụng kí tự này nếu bạn chỉ cần 1 số keywords xuất hiện trong tài liệu là được, không cần phải là tất cả. Còn nếu bắt buộc phải xuất hiện tất cả keywords mới trả về thì cần thay thế bằng '+'.

Trên đây là những điều cơ bản về Full-text search, nếu muốn tìm hiểu chi tiết hơn về cách hoạt động bên trong nó, các bạn có thể tham khảo 2 bài viết sau của bạn Trần Trung Đức:

3.3. Hybrid Search

Hybrid search là phương pháp thực hiện song song cả full-text và vector search sau đó combine 2 kết quả bằng thuật toán xếp hạng đối ứng (RRF). Đây là cách thực hiện truy vấn:

search_client.search(
    search_text=search_query,
    vector_queries=vectors,
    select=select_fields,
    search_fields=['text'],
    top=topk,
    search_mode='all',
    query_language='vi-vn',
)

Lúc này cả search_text và vector_queries đều sẽ được truyền giá trị.

Tiếp theo cùng đi sâu vào thuật toán combine. RRF là thuật toán được tính theo công thức:

score = 1 / (rank + k) với rank là thứ tự của tài liệu trong từng kết quả search, k là 1 tham số ngẫu nhiên, được thiết lập bằng 60.

Thuật toán sẽ tiến hành tính toán lại toàn bộ điểm theo rank của 2 kết quả full-text và vector. Sau đó tiến hành gộp 2 kết quả với nhau dựa theo điểm đã được chuẩn hóa, tài liệu xuất hiện ở cả 2 kết quả có có điểm mới bằng tổng ở cả 2 bên kết quả. Lí do k = 60 là vì khi thực hiện search sẽ lấy tối đa 50 kết quả cao nhất ở mỗi phương pháp search cho nên k luôn lơn hơn rank. Do đó khi tính toán lại điểm mới sẽ đảm bảo được rằng nếu có 1 tài liệu xuất hiện ở cả 2 kết quả search thì sẽ luôn có điểm cao hơn tài liệu chỉ xuất hiện ở 1 kết quả search.

Có thể dễ dàng nhận thấy nhược điểm của kết quả search này là nếu có 1 tài liệu nằm ở top 1 của vector search nhưng không nằm ở kết quả search của full-text search thì sau khi combine vẫn sẽ có điểm thấp hơn tài liệu nằm ở cả 2 kết quả nhưng ở top 20-30. Điều này không thực sự hợp lý.

Để giải quyết vẫn đề này, chúng ta có thể tự thực hiện search 2 lần trên full-text và vector. Sau đó tự combine bằng thuật toán của riêng mình. Hoặc có thể sử dụng chính ý tưởng combine của hybrid nhưng tự viết lại và điều chỉnh cho k nhỏ bớt lại tùy theo yêu cầu bài toán của các bạn.

Kết luận

Trên đây là toàn bộ cái nhìn sơ lược và tổng qua nhất về Azure AI Search.

Hy vọng rằng những thông tin tôi chia sẻ trong bài viết này sẽ giúp ích cho các bạn, đặc biệt là những ai đang tìm kiếm giải pháp tìm kiếm thông minh và hiệu quả cho các tổ chức của mình. Việc hiểu rõ các tính năng và lợi ích của Azure AI Search có thể giúp các bạn ra quyết định tốt hơn khi lựa chọn nền tảng tìm kiếm phù hợp.

Cuối cùng, tôi xin chân thành cảm ơn tất cả các bạn đã đọc bài viết này. Nếu có ý kiến đóng góp hay câu hỏi gì thì đừng ngần ngại để lại comment nhé!

References


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí