# 意味的類似性による文書の検索

{% openapi src="<https://3282965451-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FK09NlRK7lXZsjqCNQsEe%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media&token=dd73efa7-56a8-4350-88ab-85d7586fb7b8>" path="/documents/search/" method="get" %}
[rememberizer\_openapi.yml](https://3282965451-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FK09NlRK7lXZsjqCNQsEe%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media\&token=dd73efa7-56a8-4350-88ab-85d7586fb7b8)
{% endopenapi %}

## 例リクエスト

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

```bash
curl -X GET \
  "https://api.rememberizer.ai/api/v1/documents/search/?q=Rememberizer%20を%20カスタム%20アプリケーションと%20統合する%20方法&n=5&from=2023-01-01T00:00:00Z&to=2023-12-31T23:59:59Z" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
```

{% hint style="info" %}
`YOUR_JWT_TOKEN` を実際のJWTトークンに置き換えてください。
{% 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('Rememberizerをカスタムアプリケーションと統合する方法', 5);
```

{% hint style="info" %}
`YOUR_JWT_TOKEN` を実際のJWTトークンに置き換えてください。
{% 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("Rememberizerをカスタムアプリケーションと統合する方法", 5)
```

{% hint style="info" %}
`YOUR_JWT_TOKEN` を実際のJWTトークンに置き換えてください。
{% 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("Rememberizerをカスタムアプリケーションと統合する方法", 5)
```

{% hint style="info" %}
`YOUR_JWT_TOKEN` を実際のJWTトークンに置き換えてください。
{% endhint %}
{% endtab %}
{% endtabs %}

## クエリパラメータ

| パラメータ        | タイプ | 説明                                              |
| ------------ | --- | ----------------------------------------------- |
| q            | 文字列 | **必須。** 検索クエリテキスト（最大400語）。                      |
| n            | 整数  | 返す結果の数。デフォルト: 3。より包括的な結果を得るために高い値（例: 10）を使用します。 |
| from         | 文字列 | 検索対象の文書の時間範囲の開始、ISO 8601形式。                     |
| to           | 文字列 | 検索対象の文書の時間範囲の終了、ISO 8601形式。                     |
| prev\_chunks | 整数  | コンテキストのために含める前のチャンクの数。デフォルト: 2。                 |
| next\_chunks | 整数  | コンテキストのために含める後のチャンクの数。デフォルト: 2。                 |

## レスポンスフォーマット

```json
{
  "data_sources": [
    {
      "name": "Google Drive",
      "documents": 3
    },
    {
      "name": "Slack",
      "documents": 2
    }
  ],
  "matched_chunks": [
    {
      "document": {
        "id": 12345,
        "document_id": "1aBcD2efGhIjK3lMnOpQrStUvWxYz",
        "name": "Rememberizer API Documentation.pdf",
        "type": "application/pdf",
        "path": "/Documents/Rememberizer/API Documentation.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": "Rememberizerをカスタムアプリケーションと統合するには、OAuth2認証フローを使用して、アプリケーションがユーザーのRememberizerデータにアクセスするための認可を取得できます。認可されると、アプリケーションはRememberizer APIを使用して、ドキュメントを検索したり、コンテンツを取得したりできます。",
      "distance": 0.123
    },
    // ... さらにマッチしたチャンク
  ],
  "message": "検索が成功裏に完了しました",
  "code": "success"
}
```

## 検索最適化のヒント

### 質問応答のために

質問への答えを探すときは、理想的な答えのようにクエリを構成してみてください。例えば：

代わりに: "ベクトル埋め込みとは何ですか？" 試してみてください: "ベクトル埋め込みは、テキストを高次元空間の数値ベクトルに変換する技術です。"

{% hint style="info" %}
ベクトル埋め込みがどのように機能し、この検索アプローチがなぜ効果的であるかをより深く理解するには、[ベクトル埋め込みとベクトルデータベースとは？](https://docs.rememberizer.ai/ja/background/what-are-vector-embeddings-and-vector-databases)を参照してください。
{% endhint %}

### 結果数の調整

* 高い関連性のある結果を迅速に得るために `n=3` から始める
* より包括的な情報を得るために `n=10` 以上に増やす
* 検索結果が不十分な場合は、`n` パラメータを増やしてみる

### 時間ベースのフィルタリング

`from` および `to` パラメータを使用して、特定の期間の文書に焦点を当てます：

* 最近の文書：`from` を最近の日付に設定
* 歴史的分析：特定の日付範囲を指定
* 古い情報を除外：適切な `to` 日付を設定

## バッチ操作

大量の検索クエリを効率的に処理するために、Rememberizerはパフォーマンスを最適化し、APIコールのオーバーヘッドを削減するためのバッチ操作をサポートしています。

### バッチ検索

{% 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):
    """
    複数のクエリを使用してバッチ検索を実行します
    
    引数:
        queries: 検索クエリ文字列のリスト
        num_results: クエリごとに返す結果の数
        batch_size: 並行処理するクエリの数
    
    戻り値:
        各クエリの検索結果のリスト
    """
    headers = {
        "Authorization": "Bearer YOUR_JWT_TOKEN",
        "Content-Type": "application/json"
    }
    
    results = []
    
    # クエリをバッチで処理
    for i in range(0, len(queries), batch_size):
        batch = queries[i:i+batch_size]
        
        # リクエストを並行して送信するためのスレッドプールを作成
        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)
            
            # 完了した結果を収集
            for future in futures:
                response = future.result()
                results.append(response.json())
        
        # レート制限 - APIのスロットリングを避けるためにバッチ間で一時停止
        if i + batch_size < len(queries):
            time.sleep(1)
    
    return results

# 使用例
queries = [
    "RememberizerでOAuthを使用する方法",
    "ベクターデータベースの設定オプション",
    "セマンティック検索のベストプラクティス",
    # 必要に応じてクエリを追加
]

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

{% endtab %}

{% tab title="JavaScript" %}

```javascript
/**
 * 複数のクエリでバッチ検索を実行する
 * 
 * @param {string[]} queries - 検索クエリ文字列のリスト
 * @param {number} numResults - クエリごとに返す結果の数
 * @param {number} batchSize - 並行処理するクエリの数
 * @param {number} delayBetweenBatches - バッチ間で待機するミリ秒
 * @returns {Promise<Array>} - 各クエリの検索結果のリスト
 */
async function batchSearchDocuments(queries, numResults = 5, batchSize = 10, delayBetweenBatches = 1000) {
  const results = [];
  
  // クエリをバッチで処理
  for (let i = 0; i < queries.length; i += batchSize) {
    const batch = queries.slice(i, i + batchSize);
    
    // 同時リクエストのためのプロミスの配列を作成
    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());
    });
    
    // バッチ内のすべてのリクエストが完了するのを待つ
    const batchResults = await Promise.all(batchPromises);
    results.push(...batchResults);
    
    // レート制限 - APIのスロットリングを避けるためにバッチ間で一時停止
    if (i + batchSize < queries.length) {
      await new Promise(resolve => setTimeout(resolve, delayBetweenBatches));
    }
  }
  
  return results;
}

// 使用例
const queries = [
  "RememberizerでOAuthを使用する方法",
  "ベクターデータベースの設定オプション",
  "セマンティック検索のベストプラクティス",
  // 必要に応じてクエリを追加
];

batchSearchDocuments(queries, 3, 5)
  .then(results => console.log(results))
  .catch(error => console.error('バッチ検索中のエラー:', error));
```

{% endtab %}

{% tab title="Ruby" %}

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

# 複数のクエリを使用してバッチ検索を実行する
#
# @param queries [Array<String>] 検索クエリ文字列のリスト
# @param num_results [Integer] クエリごとに返す結果の数
# @param batch_size [Integer] 並行して処理するクエリの数
# @param delay_between_batches [Float] バッチ間の待機時間（秒）
# @return [Array] 各クエリの検索結果のリスト
def batch_search_documents(queries, num_results = 5, batch_size = 10, delay_between_batches = 1.0)
  results = []
  
  # バッチでクエリを処理する
  queries.each_slice(batch_size).with_index do |batch, batch_index|
    # 同時リクエストのためのスレッドプールを作成
    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
    
    # すべてのスレッドから結果を収集
    batch_results = futures.map(&:value)
    results.concat(batch_results)
    
    # レート制限 - APIのスロットリングを避けるためにバッチ間で一時停止
    if batch_index < (queries.length / batch_size.to_f).ceil - 1
      sleep(delay_between_batches)
    end
  end
  
  pool.shutdown
  results
end

# 使用例
queries = [
  "RememberizerでOAuthを使用する方法",
  "ベクターデータベースの設定オプション",
  "セマンティック検索のベストプラクティス",
  # 必要に応じてクエリを追加
]

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

{% endtab %}
{% endtabs %}

### パフォーマンスの考慮事項

バッチ操作を実装する際は、以下のベストプラクティスを考慮してください。

1. **最適なバッチサイズ**: 5-10 クエリのバッチサイズから始め、アプリケーションのパフォーマンス特性に基づいて調整します。
2. **レート制限**: API のスロットリングを防ぐために、バッチ間に遅延を含めます。バッチ間に 1 秒の遅延を設けるのが良い出発点です。
3. **エラーハンドリング**: バッチ内の失敗したリクエストを管理するために、堅牢なエラーハンドリングを実装します。
4. **リソース管理**: 特に大きなバッチサイズの場合、クライアント側のリソース使用状況を監視し、過剰なメモリ消費を防ぎます。
5. **レスポンス処理**: 可能な限り非同期でバッチ結果を処理し、ユーザーエクスペリエンスを向上させます。

高ボリュームのアプリケーションでは、大量の検索リクエストを効率的に管理するためにキューシステムの実装を検討してください。

このエンドポイントは、あなたの知識ベース全体にわたる強力なセマンティック検索機能を提供します。意味に基づいてコンテンツを見つけるためにベクトル埋め込みを使用し、正確なキーワード一致ではなく意味に基づいています。
