# Buscar documentos por similitud semántica

{% openapi src="<https://983989491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeFTiuIsKOMpUEE73g7bP%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media&token=03079f98-60fe-4914-9e1b-443e008fd108>" path="/documents/search/" method="get" %}
[rememberizer\_openapi.yml](https://983989491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeFTiuIsKOMpUEE73g7bP%2Fuploads%2Fgit-blob-77b6137eeb641262ec8e531c78123c02b825b865%2Frememberizer_openapi.yml?alt=media\&token=03079f98-60fe-4914-9e1b-443e008fd108)
{% endopenapi %}

## Ejemplos de Solicitudes

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

```bash
curl -X GET \
  "https://api.rememberizer.ai/api/v1/documents/search/?q=Cómo%20integrar%20Rememberizer%20con%20aplicaciones%20personalizadas&n=5&from=2023-01-01T00:00:00Z&to=2023-12-31T23:59:59Z" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
```

{% hint style="info" %}
Reemplace `YOUR_JWT_TOKEN` con su token JWT real.
{% 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('Cómo integrar Rememberizer con aplicaciones personalizadas', 5);
```

{% hint style="info" %}
Reemplace `YOUR_JWT_TOKEN` con su token JWT real.
{% 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("Cómo integrar Rememberizer con aplicaciones personalizadas", 5)
```

{% hint style="info" %}
Reemplace `YOUR_JWT_TOKEN` con su token JWT real.
{% 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("Cómo integrar Rememberizer con aplicaciones personalizadas", 5)
```

{% hint style="info" %}
Reemplace `YOUR_JWT_TOKEN` con su token JWT real.
{% endhint %}
{% endtab %}
{% endtabs %}

## Parámetros de Consulta

| Parámetro    | Tipo   | Descripción                                                                                                                            |
| ------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| q            | cadena | **Requerido.** El texto de la consulta de búsqueda (hasta 400 palabras).                                                               |
| n            | entero | Número de resultados a devolver. Predeterminado: 3. Utilice valores más altos (por ejemplo, 10) para obtener resultados más completos. |
| from         | cadena | Inicio del rango de tiempo para los documentos a buscar, en formato ISO 8601.                                                          |
| to           | cadena | Fin del rango de tiempo para los documentos a buscar, en formato ISO 8601.                                                             |
| prev\_chunks | entero | Número de fragmentos anteriores a incluir para contexto. Predeterminado: 2.                                                            |
| next\_chunks | entero | Número de fragmentos siguientes a incluir para contexto. Predeterminado: 2.                                                            |

## Formato de Respuesta

```json
{
  "data_sources": [
    {
      "name": "Google Drive",
      "documents": 3
    },
    {
      "name": "Slack",
      "documents": 2
    }
  ],
  "matched_chunks": [
    {
      "document": {
        "id": 12345,
        "document_id": "1aBcD2efGhIjK3lMnOpQrStUvWxYz",
        "name": "Documentación de la API de Rememberizer.pdf",
        "type": "application/pdf",
        "path": "/Documents/Rememberizer/Documentación de la 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": "Para integrar Rememberizer con aplicaciones personalizadas, puedes usar el flujo de autenticación OAuth2 para autorizar tu aplicación a acceder a los datos de Rememberizer de un usuario. Una vez autorizado, tu aplicación puede usar las APIs de Rememberizer para buscar documentos, recuperar contenido y más.",
      "distance": 0.123
    },
    // ... más fragmentos coincidentes
  ],
  "message": "Búsqueda completada con éxito",
  "code": "success"
}
```

## Consejos de Optimización de Búsqueda

### Para Responder Preguntas

Al buscar una respuesta a una pregunta, intenta formular tu consulta como si fuera una respuesta ideal. Por ejemplo:

En lugar de: "¿Qué es la incrustación vectorial?" Intenta: "La incrustación vectorial es una técnica que convierte texto en vectores numéricos en un espacio de alta dimensión."

{% hint style="info" %}
Para una comprensión más profunda de cómo funcionan las incrustaciones vectoriales y por qué este enfoque de búsqueda es efectivo, consulta [¿Qué son las Incrustaciones Vectoriales y las Bases de Datos Vectoriales?](https://docs.rememberizer.ai/es/background/what-are-vector-embeddings-and-vector-databases)
{% endhint %}

### Ajustando la Cantidad de Resultados

* Comienza con `n=3` para resultados rápidos y de alta relevancia
* Aumenta a `n=10` o más para información más completa
* Si la búsqueda devuelve información insuficiente, intenta aumentar el parámetro `n`

### Filtrado Basado en el Tiempo

Utiliza los parámetros `from` y `to` para centrarte en documentos de períodos de tiempo específicos:

* Documentos recientes: Establece `from` en una fecha reciente
* Análisis histórico: Especifica un rango de fechas específico
* Excluyendo información desactualizada: Establece una fecha `to` apropiada

## Operaciones por Lotes

Para manejar de manera eficiente grandes volúmenes de consultas de búsqueda, Rememberizer admite operaciones por lotes para optimizar el rendimiento y reducir la sobrecarga de llamadas a la API.

### Búsqueda por Lotes

{% 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):
    """
    Realizar búsquedas por lotes con múltiples consultas
    
    Args:
        queries: Lista de cadenas de consulta de búsqueda
        num_results: Número de resultados a devolver por consulta
        batch_size: Número de consultas a procesar en paralelo
    
    Returns:
        Lista de resultados de búsqueda para cada consulta
    """
    headers = {
        "Authorization": "Bearer YOUR_JWT_TOKEN",
        "Content-Type": "application/json"
    }
    
    results = []
    
    # Procesar consultas en lotes
    for i in range(0, len(queries), batch_size):
        batch = queries[i:i+batch_size]
        
        # Crear un grupo de hilos para enviar solicitudes en paralelo
        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)
            
            # Recoger resultados a medida que se completan
            for future in futures:
                response = future.result()
                results.append(response.json())
        
        # Limitación de tasa - pausa entre lotes para evitar la limitación de la API
        if i + batch_size < len(queries):
            time.sleep(1)
    
    return results

# Ejemplo de uso
queries = [
    "Cómo usar OAuth con Rememberizer",
    "Opciones de configuración de la base de datos vectorial",
    "Mejores prácticas para la búsqueda semántica",
    # Agregar más consultas según sea necesario
]

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

{% endtab %}

{% tab title="JavaScript" %}

```javascript
/**
 * Realizar búsquedas por lotes con múltiples consultas
 * 
 * @param {string[]} queries - Lista de cadenas de consulta de búsqueda
 * @param {number} numResults - Número de resultados a devolver por consulta
 * @param {number} batchSize - Número de consultas a procesar en paralelo
 * @param {number} delayBetweenBatches - Milisegundos a esperar entre lotes
 * @returns {Promise<Array>} - Lista de resultados de búsqueda para cada consulta
 */
async function batchSearchDocuments(queries, numResults = 5, batchSize = 10, delayBetweenBatches = 1000) {
  const results = [];
  
  // Procesar consultas en lotes
  for (let i = 0; i < queries.length; i += batchSize) {
    const batch = queries.slice(i, i + batchSize);
    
    // Crear un array de promesas para solicitudes concurrentes
    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());
    });
    
    // Esperar a que todas las solicitudes en el lote se completen
    const batchResults = await Promise.all(batchPromises);
    results.push(...batchResults);
    
    // Limitación de tasa - pausa entre lotes para evitar la limitación de la API
    if (i + batchSize < queries.length) {
      await new Promise(resolve => setTimeout(resolve, delayBetweenBatches));
    }
  }
  
  return results;
}

// Ejemplo de uso
const queries = [
  "Cómo usar OAuth con Rememberizer",
  "Opciones de configuración de la base de datos vectorial",
  "Mejores prácticas para la búsqueda semántica",
  // Agregar más consultas según sea necesario
];

batchSearchDocuments(queries, 3, 5)
  .then(results => console.log(results))
  .catch(error => console.error('Error en la búsqueda por lotes:', error));
```

{% endtab %}

{% tab title="Ruby" %}

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

# Realizar búsquedas por lotes con múltiples consultas
#
# @param queries [Array<String>] Lista de cadenas de consulta de búsqueda
# @param num_results [Integer] Número de resultados a devolver por consulta
# @param batch_size [Integer] Número de consultas a procesar en paralelo
# @param delay_between_batches [Float] Segundos a esperar entre lotes
# @return [Array] Lista de resultados de búsqueda para cada consulta
def batch_search_documents(queries, num_results = 5, batch_size = 10, delay_between_batches = 1.0)
  results = []
  
  # Procesar consultas en lotes
  queries.each_slice(batch_size).with_index do |batch, batch_index|
    # Crear un grupo de hilos para solicitudes concurrentes
    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
    
    # Recopilar resultados de todos los hilos
    batch_results = futures.map(&:value)
    results.concat(batch_results)
    
    # Limitación de tasa - pausa entre lotes para evitar la limitación de la API
    if batch_index < (queries.length / batch_size.to_f).ceil - 1
      sleep(delay_between_batches)
    end
  end
  
  pool.shutdown
  results
end

# Ejemplo de uso
queries = [
  "Cómo usar OAuth con Rememberizer",
  "Opciones de configuración de base de datos vectorial",
  "Mejores prácticas para la búsqueda semántica",
  # Agregar más consultas según sea necesario
]

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

{% endtab %}
{% endtabs %}

### Consideraciones de Rendimiento

Al implementar operaciones por lotes, considera estas mejores prácticas:

1. **Tamaño Óptimo del Lote**: Comienza con tamaños de lote de 5-10 consultas y ajusta según las características de rendimiento de tu aplicación.
2. **Limitación de Tasa**: Incluye retrasos entre lotes para prevenir la limitación de la API. Un buen punto de partida es 1 segundo entre lotes.
3. **Manejo de Errores**: Implementa un manejo de errores robusto para gestionar solicitudes fallidas dentro de los lotes.
4. **Gestión de Recursos**: Monitorea el uso de recursos del lado del cliente, particularmente con tamaños de lote grandes, para prevenir un consumo excesivo de memoria.
5. **Procesamiento de Respuestas**: Procesa los resultados de los lotes de manera asíncrona cuando sea posible para mejorar la experiencia del usuario.

Para aplicaciones de alto volumen, considera implementar un sistema de cola para gestionar grandes cantidades de solicitudes de búsqueda de manera eficiente.

Este endpoint proporciona potentes capacidades de búsqueda semántica en toda tu base de conocimientos. Utiliza incrustaciones vectoriales para encontrar contenido basado en el significado en lugar de coincidencias exactas de palabras clave.
