Esta serie explica cómo búsqueda de leyesun motor de búsqueda neuronal para la ley holandesa, emplea deepset Alpaca para ofrecer resultados de búsqueda superiores. Parte 4: probando diferentes bases de datos vectoriales, Weaviate vs ElasticSearch
Han pasado casi nueve meses desde el último artículo, y desde entonces el espacio de PNL, Wetzoek y Haystack han visto un gran progreso. En Wetzoek, hemos añadido un funcionalidad de configuración de filtro automatizado basado en las etiquetas identificadas a través de la teoría de grafos. Un informe en profundidad probablemente seguirá en un próximo artículo.
Una de las razones para establecer filtros antes hacer búsqueda neuronal (o cualquier búsqueda) es que acelera la recuperación significativamente. Después de todo, si le dice a la máquina que solo mire, por ejemplo, el derecho civil, ¡entonces reduce el alcance del documento en aproximadamente un tercio! Ahora imagine hacer esto para dominios aún más pequeños.
Esto solo es necesario si la búsqueda ya es lenta, como lo ha sido en Wetzoek. Los registros de Haystack le indican de manera muy útil cuánto tiempo se tarda en devolver una consulta:
También te puede interesarCómo funciona el paso de mensajes en el aprendizaje automático parte 3En algunos de los peores casos, ¡esto podría llevar casi un minuto! Y eso es usando una instancia habilitada para GPU (g4dn en AWS) creada para inferencia…
La búsqueda neuronal no funciona bien en documentos grandes, porque contienen demasiados tokens. Por lo tanto, la base de datos de Wetzoek de ~600.000 documentos se ha dividido en una enorme 18 millones de documentos divididos de alrededor de 100 tokens cada uno. Como puede imaginar, esto plantea un gran desafío para la recuperación rápida de búsquedas y explicaría por qué algunas búsquedas pueden demorar hasta un minuto.
Para ralentizar las cosas aún más, cada documento tiene una incrustación. Recuerde, estamos usando la búsqueda neuronal y, por lo tanto, estamos buscando similitudes semánticas, no palabras clave. Eso significa que, bajo el capó, nuestra consulta se convierte en un vector. Luego, este vector se compara con las representaciones vectoriales de los documentos incrustados, para encontrar el más similar en el espacio vectorial. Este es un tipo especializado de búsqueda que requiere bases de datos especializadas.
Si bien ElasticSearch tiene funcionalidad para incrustaciones de vectores, no se creó completamente con ese propósito en mente. Afortunadamente, hay muchas bases de datos vectoriales disponible. Hay varios enumerados en la página DocumentStores de Haystack, incluidos Weaviate, PineCone y Qdrant. Otro que no aparece en la lista es Chroma.
También te puede interesarCómo funciona el paso de mensajes en Machine Learning parte 2En ese momento, elegí Weaviate principalmente porque su integración con Haystack permitía filtrar. Esto aún no era posible para Faiss o PineCone, y aún no existía una integración con Qdrant. Da la casualidad de que, al momento de escribir este artículo, Weaviate acaba de recaudar $ 50 millones en fondos de la serie B, ¡así que este manual es bastante oportuno!
Al configurar Weaviate a través de Haystack, este artículo me resultó inmensamente útil. En este caso, usé weaviate 1.17.3. Seguir los pasos del artículo fue suficiente para configurar Weaviate, después de corregir algunos errores. Las comunidades de Haystack y Weaviate en Discord y Slack, respectivamente, fueron de gran ayuda. ¡Los miembros de C-suite de ambas compañías fueron a menudo los primeros en responder a las preguntas!
No obstante, hubo algunos desafíos que enfrenté todavía. En particular, Weaviate solo acepta documentos que ya están incrustados. Esto no es un problema si usa la canalización de carga de Haystack, como se describe en el artículo mencionado anteriormente. Pero en mi caso, estaba acostumbrado a actualizar incrustaciones periódicamente así:
document_store = ElasticsearchDocumentStore(analyzer=language, index=doc_index, timeout=300, similarity="cosine")
tic = time.perf_counter()
retriever = EmbeddingRetriever(
document_store=document_store,
embedding_model="jegormeister/bert-base-dutch-cased-snli",
model_format="sentence_transformers",
)
print("Updating embeddings")document_store.update_embeddings(retriever,update_existing_embeddings=False)
También te puede interesarAgentes, LLM y respuesta a preguntas de múltiples saltos
Por lo tanto, tuve que actualizar mi tubería de carga de datos para incrustar documentos antes escribiéndolos en el DocumentStore. Mi solución fue crear una función de «preincrustación» en la que tienes que alimentar los documentos de Haystack:
def pre_embedder(docs):
print('Running the pre-embedding')
retriever = EmbeddingRetriever(
document_store=split_document_store, # the name used for the Weaviate DS
embedding_model=embedding_model, # in practice, this was the jegormeister Dutch transformers
model_format=model_format, # in practice, sentence_transformers again
)
embeds = retriever.embed_documents(docs)
for doc, emb in zip(docs,embeds):
try:
doc.embedding = emb
except Exception as e:
print(e)
return docs
Esto funcionó bien y, de hecho, no me sorprendería si la última iteración de Haystack (esto se creó en 1.10, Haystack actualmente en 1.15.1) ya no requiere esto.
Para probar el rendimiento de la canalización que configuré anteriormente, consulté tanto ElasticSearch como Weaviate diez veces, en diferentes cantidades de documentos totales. Capturé el resultado en una tabla de Excel para documentos de 1k, 10k y ~100k. Recuerde: ¡cada documento representa ~60 veces más documentos cuando se divide en partes manejables! El tiempo mostrado son segundos.
Como es de esperar, para una pequeña cantidad de documentos, Weaviate y Haystack están aproximadamente al mismo nivel en términos de velocidad. Sin embargo, a medida que aumenta la cantidad de documentos, realmente vemos brillar a Weaviate. Mientras que ElasticSearch puede tardar hasta un minuto en algunas consultas, Weaviate tarda constantemente menos de un minuto en devolver los resultados.
También te puede interesarReel VS Real: Revisión de literatura parte 2(Otra cosa interesante que he notado es que las primeras consultas toman más tiempo, casi como si el motor se estuviera ‘calentando’. Como también he visto que esto sucede con otras consultas, no creo que tenga que ver con las consultas específicas usado aquí).
Llegar a los 100k documentos en Weaviate no fue tarea fácil. ¡Mi instancia seguía fallando mientras escribía nuevos documentos en Weaviate! Muy amablemente, la gente de Weaviate me explicó que necesitaba más RAM, y mucha. Afortunadamente, pude mostrar mi instancia EC2 y actualizarla. Descubrí que necesitaba una instancia g4dn.8xlarge para escribir 100k documentos en Weaviate con éxito.
Para mi propósitos con Wetzoek en este momento, esto era excesivo (y demasiado caro). Sin embargo, para un equipo profesional, puedo imaginar que el rendimiento de Weaviate vale la pena.
Si bien me llevó un poco de discusión, me complació lo fácil que fue migrar mi configuración de Haystack en ElasticSearch a Weaviate. La capa Haystack realmente agrega muchos beneficios aquí, ya que hace que sea mucho más fácil para los principiantes como yo agregar metadatos, establecer filtros, etc. que cuando usan los formatos de la tecnología de búsqueda subyacente.
El interés en la búsqueda semántica ha estado en auge últimamente, ya que no solo Weaviate sino también Pinecone han recaudado dinero. Sin embargo, como usuario de la búsqueda, Creo en el poder de la búsqueda simbólica no debe ser subestimado. A menudo, emparejar algunos palabras clave exactas es lo que quiere el usuario; no la similitud semántica.
Sin duda, esta es una característica que agregaré a Wetzoek, que permite a los usuarios realizar búsquedas semánticas o simbólicas. En el futuro, puedo imaginar una nueva forma de escribir consultas de búsqueda: donde el usuario especifica qué parte de la consulta debe tratarse ‘semánticamente’ y qué parte debe tratarse ‘simbólicamente’; por ejemplo: (logros de) [julius caesar] (como emperador), donde [julius caesar] instruye la búsqueda simbólica, pero (logros de) y (como emperador) instruye la búsqueda semántica.