# Tìm kiếm tài liệu theo sự tương đồng ngữ nghĩa

{% openapi src="<https://4187618229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fwbxu0T4faQnPtKbPzrD5%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media&token=b77a395b-ed7b-4546-9ec7-182d4939fd1b>" path="/documents/search/" method="get" %}
[rememberizer\_openapi.yml](https://4187618229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fwbxu0T4faQnPtKbPzrD5%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media\&token=b77a395b-ed7b-4546-9ec7-182d4939fd1b)
{% endopenapi %}

## Ví dụ Yêu cầu

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET \
  "https://api.rememberizer.ai/api/v1/documents/search/?q=How%20to%20integrate%20Rememberizer%20with%20custom%20applications&n=5&from=2023-01-01T00:00:00Z&to=2023-12-31T23:59:59Z" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
```

{% hint style="info" %}
Thay thế `YOUR_JWT_TOKEN` bằng mã thông báo JWT thực tế của bạn.
{% endhint %}
{% endtab %}

{% tab title="JavaScript" %}

```javascript
const searchDocuments = async (query, numResults = 5, from = null, to = null) => {
  const url = new URL('https://api.rememberizer.ai/api/v1/documents/search/');
  url.searchParams.append('q', query);
  url.searchParams.append('n', numResults);
  
  if (from) {
    url.searchParams.append('from', from);
  }
  
  if (to) {
    url.searchParams.append('to', to);
  }
  
  const response = await fetch(url.toString(), {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer YOUR_JWT_TOKEN'
    }
  });
  
  const data = await response.json();
  console.log(data);
};

searchDocuments('How to integrate Rememberizer with custom applications', 5);
```

{% hint style="info" %}
Thay thế `YOUR_JWT_TOKEN` bằng mã thông báo JWT thực tế của bạn.
{% endhint %}
{% endtab %}

{% tab title="Python" %}

```python
import requests

def search_documents(query, num_results=5, from_date=None, to_date=None):
    headers = {
        "Authorization": "Bearer YOUR_JWT_TOKEN"
    }
    
    params = {
        "q": query,
        "n": num_results
    }
    
    if from_date:
        params["from"] = from_date
    
    if to_date:
        params["to"] = to_date
    
    response = requests.get(
        "https://api.rememberizer.ai/api/v1/documents/search/",
        headers=headers,
        params=params
    )
    
    data = response.json()
    print(data)

search_documents("How to integrate Rememberizer with custom applications", 5)
```

{% hint style="info" %}
Thay thế `YOUR_JWT_TOKEN` bằng mã thông báo JWT thực tế của bạn.
{% endhint %}
{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'net/http'
require 'uri'
require 'json'

def search_documents(query, num_results=5, from_date=nil, to_date=nil)
  uri = URI('https://api.rememberizer.ai/api/v1/documents/search/')
  params = {
    q: query,
    n: num_results
  }
  
  params[:from] = from_date if from_date
  params[:to] = to_date if to_date
  
  uri.query = URI.encode_www_form(params)
  
  request = Net::HTTP::Get.new(uri)
  request['Authorization'] = 'Bearer YOUR_JWT_TOKEN'
  
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  
  response = http.request(request)
  data = JSON.parse(response.body)
  puts data
end

search_documents("How to integrate Rememberizer with custom applications", 5)
```

{% hint style="info" %}
Thay thế `YOUR_JWT_TOKEN` bằng mã thông báo JWT thực tế của bạn.
{% endhint %}
{% endtab %}
{% endtabs %}

## Tham số truy vấn

| Tham số      | Loại      | Mô tả                                                                                                  |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------ |
| q            | chuỗi     | **Bắt buộc.** Văn bản truy vấn tìm kiếm (tối đa 400 từ).                                               |
| n            | số nguyên | Số lượng kết quả trả về. Mặc định: 3. Sử dụng giá trị cao hơn (ví dụ: 10) để có kết quả toàn diện hơn. |
| from         | chuỗi     | Bắt đầu khoảng thời gian cho các tài liệu được tìm kiếm, theo định dạng ISO 8601.                      |
| to           | chuỗi     | Kết thúc khoảng thời gian cho các tài liệu được tìm kiếm, theo định dạng ISO 8601.                     |
| prev\_chunks | số nguyên | Số lượng đoạn trước đó để bao gồm cho ngữ cảnh. Mặc định: 2.                                           |
| next\_chunks | số nguyên | Số lượng đoạn tiếp theo để bao gồm cho ngữ cảnh. Mặc định: 2.                                          |

## Định dạng Phản hồi

```json
{
  "data_sources": [
    {
      "name": "Google Drive",
      "documents": 3
    },
    {
      "name": "Slack",
      "documents": 2
    }
  ],
  "matched_chunks": [
    {
      "document": {
        "id": 12345,
        "document_id": "1aBcD2efGhIjK3lMnOpQrStUvWxYz",
        "name": "Tài liệu API của Rememberizer.pdf",
        "type": "application/pdf",
        "path": "/Documents/Rememberizer/Tài liệu API.pdf",
        "url": "https://drive.google.com/file/d/1aBcD2efGhIjK3lMnOpQrStUvWxYz/view",
        "size": 250000,
        "created_time": "2023-05-10T14:30:00Z",
        "modified_time": "2023-06-15T09:45:00Z",
        "indexed_on": "2023-06-15T10:30:00Z",
        "integration": {
          "id": 101,
          "integration_type": "google_drive"
        }
      },
      "matched_content": "Để tích hợp Rememberizer với các ứng dụng tùy chỉnh, bạn có thể sử dụng quy trình xác thực OAuth2 để ủy quyền cho ứng dụng của bạn truy cập dữ liệu Rememberizer của người dùng. Khi đã được ủy quyền, ứng dụng của bạn có thể sử dụng các API của Rememberizer để tìm kiếm tài liệu, lấy nội dung và nhiều hơn nữa.",
      "distance": 0.123
    },
    // ... nhiều khối phù hợp hơn
  ],
  "message": "Tìm kiếm hoàn tất thành công",
  "code": "success"
}
```

## Mẹo Tối Ưu Hóa Tìm Kiếm

### Đối với Trả Lời Câu Hỏi

Khi tìm kiếm câu trả lời cho một câu hỏi, hãy cố gắng diễn đạt truy vấn của bạn như thể đó là một câu trả lời lý tưởng. Ví dụ:

Thay vì: "Vector embedding là gì?" Hãy thử: "Vector embedding là một kỹ thuật chuyển đổi văn bản thành các vector số trong một không gian nhiều chiều."

{% hint style="info" %}
Để hiểu sâu hơn về cách hoạt động của vector embeddings và tại sao phương pháp tìm kiếm này hiệu quả, hãy xem [Vector Embeddings và Cơ sở Dữ liệu Vector là gì?](https://docs.rememberizer.ai/vi/background/what-are-vector-embeddings-and-vector-databases)
{% endhint %}

### Điều Chỉnh Số Lượng Kết Quả

* Bắt đầu với `n=3` để có kết quả nhanh, có độ liên quan cao
* Tăng lên `n=10` hoặc cao hơn để có thông tin toàn diện hơn
* Nếu tìm kiếm trả về thông tin không đủ, hãy thử tăng tham số `n`

### Lọc Dữ Liệu Theo Thời Gian

Sử dụng các tham số `from` và `to` để tập trung vào các tài liệu từ các khoảng thời gian cụ thể:

* Tài liệu gần đây: Đặt `from` thành một ngày gần đây
* Phân tích lịch sử: Xác định một khoảng thời gian cụ thể
* Loại trừ thông tin lỗi thời: Đặt một ngày `to` phù hợp

## Các hoạt động theo lô

Để xử lý hiệu quả một khối lượng lớn các truy vấn tìm kiếm, Rememberizer hỗ trợ các hoạt động theo lô nhằm tối ưu hóa hiệu suất và giảm thiểu chi phí gọi API.

### Tìm kiếm theo lô

{% tabs %}
{% tab title="Python" %}

```python
import requests
import time
import json
from concurrent.futures import ThreadPoolExecutor

def batch_search_documents(queries, num_results=5, batch_size=10):
    """
    Thực hiện tìm kiếm theo lô với nhiều truy vấn
    
    Args:
        queries: Danh sách các chuỗi truy vấn tìm kiếm
        num_results: Số lượng kết quả trả về cho mỗi truy vấn
        batch_size: Số lượng truy vấn để xử lý song song
    
    Returns:
        Danh sách các kết quả tìm kiếm cho mỗi truy vấn
    """
    headers = {
        "Authorization": "Bearer YOUR_JWT_TOKEN",
        "Content-Type": "application/json"
    }
    
    results = []
    
    # Xử lý các truy vấn theo lô
    for i in range(0, len(queries), batch_size):
        batch = queries[i:i+batch_size]
        
        # Tạo một nhóm luồng để gửi yêu cầu song song
        with ThreadPoolExecutor(max_workers=batch_size) as executor:
            futures = []
            
            for query in batch:
                params = {
                    "q": query,
                    "n": num_results
                }
                
                future = executor.submit(
                    requests.get,
                    "https://api.rememberizer.ai/api/v1/documents/search/",
                    headers=headers,
                    params=params
                )
                futures.append(future)
            
            # Thu thập kết quả khi chúng hoàn thành
            for future in futures:
                response = future.result()
                results.append(response.json())
        
        # Giới hạn tốc độ - tạm dừng giữa các lô để tránh bị giới hạn API
        if i + batch_size < len(queries):
            time.sleep(1)
    
    return results

# Ví dụ sử dụng
queries = [
    "Cách sử dụng OAuth với Rememberizer",
    "Tùy chọn cấu hình cơ sở dữ liệu vector",
    "Các thực tiễn tốt nhất cho tìm kiếm ngữ nghĩa",
    # Thêm nhiều truy vấn nếu cần
]

results = batch_search_documents(queries, num_results=3, batch_size=5)
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
/**
 * Thực hiện tìm kiếm theo lô với nhiều truy vấn
 * 
 * @param {string[]} queries - Danh sách các chuỗi truy vấn tìm kiếm
 * @param {number} numResults - Số lượng kết quả trả về cho mỗi truy vấn
 * @param {number} batchSize - Số lượng truy vấn để xử lý song song
 * @param {number} delayBetweenBatches - Số mili giây để chờ giữa các lô
 * @returns {Promise<Array>} - Danh sách kết quả tìm kiếm cho mỗi truy vấn
 */
async function batchSearchDocuments(queries, numResults = 5, batchSize = 10, delayBetweenBatches = 1000) {
  const results = [];
  
  // Xử lý các truy vấn theo lô
  for (let i = 0; i < queries.length; i += batchSize) {
    const batch = queries.slice(i, i + batchSize);
    
    // Tạo một mảng các promise cho các yêu cầu đồng thời
    const batchPromises = batch.map(query => {
      const url = new URL('https://api.rememberizer.ai/api/v1/documents/search/');
      url.searchParams.append('q', query);
      url.searchParams.append('n', numResults);
      
      return fetch(url.toString(), {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_JWT_TOKEN'
        }
      }).then(response => response.json());
    });
    
    // Chờ tất cả các yêu cầu trong lô hoàn thành
    const batchResults = await Promise.all(batchPromises);
    results.push(...batchResults);
    
    // Giới hạn tốc độ - tạm dừng giữa các lô để tránh bị giới hạn API
    if (i + batchSize < queries.length) {
      await new Promise(resolve => setTimeout(resolve, delayBetweenBatches));
    }
  }
  
  return results;
}

// Ví dụ sử dụng
const queries = [
  "Cách sử dụng OAuth với Rememberizer",
  "Tùy chọn cấu hình cơ sở dữ liệu vector",
  "Các thực tiễn tốt nhất cho tìm kiếm ngữ nghĩa",
  // Thêm nhiều truy vấn nếu cần
];

batchSearchDocuments(queries, 3, 5)
  .then(results => console.log(results))
  .catch(error => console.error('Lỗi trong tìm kiếm theo lô:', error));
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'net/http'
require 'uri'
require 'json'
require 'concurrent'

# Thực hiện tìm kiếm theo lô với nhiều truy vấn
#
# @param queries [Array<String>] Danh sách các chuỗi truy vấn tìm kiếm
# @param num_results [Integer] Số lượng kết quả trả về cho mỗi truy vấn
# @param batch_size [Integer] Số lượng truy vấn để xử lý song song
# @param delay_between_batches [Float] Số giây để chờ giữa các lô
# @return [Array] Danh sách kết quả tìm kiếm cho mỗi truy vấn
def batch_search_documents(queries, num_results = 5, batch_size = 10, delay_between_batches = 1.0)
  results = []
  
  # Xử lý các truy vấn theo lô
  queries.each_slice(batch_size).with_index do |batch, batch_index|
    # Tạo một nhóm luồng cho các yêu cầu đồng thời
    pool = Concurrent::FixedThreadPool.new(batch_size)
    futures = []
    
    batch.each do |query|
      futures << Concurrent::Future.execute(executor: pool) do
        uri = URI('https://api.rememberizer.ai/api/v1/documents/search/')
        params = {
          q: query,
          n: num_results
        }
        
        uri.query = URI.encode_www_form(params)
        
        request = Net::HTTP::Get.new(uri)
        request['Authorization'] = 'Bearer YOUR_JWT_TOKEN'
        
        http = Net::HTTP.new(uri.host, uri.port)
        http.use_ssl = true
        
        response = http.request(request)
        JSON.parse(response.body)
      end
    end
    
    # Thu thập kết quả từ tất cả các luồng
    batch_results = futures.map(&:value)
    results.concat(batch_results)
    
    # Giới hạn tốc độ - tạm dừng giữa các lô để tránh bị giới hạn API
    if batch_index < (queries.length / batch_size.to_f).ceil - 1
      sleep(delay_between_batches)
    end
  end
  
  pool.shutdown
  results
end

# Ví dụ sử dụng
queries = [
  "Cách sử dụng OAuth với Rememberizer",
  "Tùy chọn cấu hình cơ sở dữ liệu vector",
  "Thực tiễn tốt nhất cho tìm kiếm ngữ nghĩa",
  # Thêm nhiều truy vấn nếu cần
]

results = batch_search_documents(queries, 3, 5)
puts results
```

{% endtab %}
{% endtabs %}

### Cân nhắc về Hiệu suất

Khi triển khai các thao tác theo lô, hãy xem xét những thực tiễn tốt nhất sau:

1. **Kích thước Lô Tối Ưu**: Bắt đầu với kích thước lô từ 5-10 truy vấn và điều chỉnh dựa trên đặc điểm hiệu suất của ứng dụng của bạn.
2. **Giới Hạn Tốc Độ**: Bao gồm các khoảng thời gian giữa các lô để ngăn chặn việc giới hạn API. Một điểm khởi đầu tốt là 1 giây giữa các lô.
3. **Xử Lý Lỗi**: Triển khai xử lý lỗi mạnh mẽ để quản lý các yêu cầu không thành công trong các lô.
4. **Quản Lý Tài Nguyên**: Giám sát việc sử dụng tài nguyên phía khách, đặc biệt với kích thước lô lớn, để ngăn chặn việc tiêu thụ bộ nhớ quá mức.
5. **Xử Lý Phản Hồi**: Xử lý kết quả lô một cách không đồng bộ khi có thể để cải thiện trải nghiệm người dùng.

Đối với các ứng dụng có khối lượng lớn, hãy xem xét triển khai một hệ thống hàng đợi để quản lý hiệu quả số lượng lớn các yêu cầu tìm kiếm.

Điểm cuối này cung cấp khả năng tìm kiếm ngữ nghĩa mạnh mẽ trên toàn bộ cơ sở tri thức của bạn. Nó sử dụng các nhúng vector để tìm nội dung dựa trên ý nghĩa thay vì các khớp từ khóa chính xác.
