Importante
Una capa de almacenamiento en caché para LLM que explota Elasticsearch, totalmente compatible con el almacenamiento en caché de Langchain, tanto para los modelos de chat como de incrustaciones.
pip install llm-elasticsearch-cacheEl caché Langchain se puede usar de manera similar a las otras integraciones de caché.
from langchain . globals import set_llm_cache
from llmescache . langchain import ElasticsearchCache
from elasticsearch import Elasticsearch
es_client = Elasticsearch ( hosts = "http://localhost:9200" )
set_llm_cache (
ElasticsearchCache (
es_client = es_client ,
es_index = "llm-chat-cache" ,
metadata = { "project" : "my_chatgpt_project" }
)
) El parámetro es_index también puede tomar alias. Esto permite usar el ILM: administre el ciclo de vida del índice que sugerimos considerar para administrar la retención y controlar el crecimiento del caché.
Mire el documento de clase para todos los parámetros.
Los datos en caché no se pueden buscar de forma predeterminada. El desarrollador puede personalizar la construcción del documento Elasticsearch para agregar campos de texto indexados, dónde poner, por ejemplo, el texto generado por el LLM.
Esto se puede hacer subclasificando los métodos de anulación de extremo. La nueva clase de caché se puede aplicar también a un índice de caché preexistente:
from llmescache . langchain import ElasticsearchCache
from elasticsearch import Elasticsearch
from langchain_core . caches import RETURN_VAL_TYPE
from typing import Any , Dict , List
from langchain . globals import set_llm_cache
import json
class SearchableElasticsearchCache ( ElasticsearchCache ):
@ property
def mapping ( self ) -> Dict [ str , Any ]:
mapping = super (). mapping
mapping [ "mappings" ][ "properties" ][ "parsed_llm_output" ] = { "type" : "text" , "analyzer" : "english" }
return mapping
def build_document ( self , prompt : str , llm_string : str , return_val : RETURN_VAL_TYPE ) -> Dict [ str , Any ]:
body = super (). build_document ( prompt , llm_string , return_val )
body [ "parsed_llm_output" ] = self . _parse_output ( body [ "llm_output" ])
return body
@ staticmethod
def _parse_output ( data : List [ str ]) -> List [ str ]:
return [ json . loads ( output )[ "kwargs" ][ "message" ][ "kwargs" ][ "content" ] for output in data ]
es_client = Elasticsearch ( hosts = "http://localhost:9200" )
set_llm_cache ( SearchableElasticsearchCache ( es_client = es_client , es_index = "llm-chat-cache" ))Los incrustaciones de almacenamiento en caché se obtienen utilizando CacheBackedEmbeddings, de una manera ligeramente diferente a la documentación oficial.
from llmescache . langchain import ElasticsearchStore
from elasticsearch import Elasticsearch
from langchain . embeddings import CacheBackedEmbeddings
from langchain_openai import OpenAIEmbeddings
es_client = Elasticsearch ( hosts = "http://localhost:9200" )
underlying_embeddings = OpenAIEmbeddings ( model = "text-embedding-3-small" )
store = ElasticsearchStore (
es_client = es_client ,
es_index = "llm-embeddings-cache" ,
namespace = underlying_embeddings . model ,
metadata = { "project" : "my_llm_project" }
)
cached_embeddings = CacheBackedEmbeddings (
underlying_embeddings ,
store
) De manera similar al caché de chat, se puede subclase ElasticsearchStore para indexar vectores para la búsqueda.
from llmescache . langchain import ElasticsearchStore
from typing import Any , Dict , List
class SearchableElasticsearchStore ( ElasticsearchStore ):
@ property
def mapping ( self ) -> Dict [ str , Any ]:
mapping = super (). mapping
mapping [ "mappings" ][ "properties" ][ "vector" ] = { "type" : "dense_vector" , "dims" : 1536 , "index" : True , "similarity" : "dot_product" }
return mapping
def build_document ( self , llm_input : str , vector : List [ float ]) -> Dict [ str , Any ]:
body = super (). build_document ( llm_input , vector )
body [ "vector" ] = vector
return body Tenga en cuenta que CacheBackedEmbeddings actualmente no es compatible con consultas en caché, esto significa que las consultas de texto, para las búsquedas vectoriales, no se almacenarán en caché. Sin embargo, al anular el método embed_query , uno debe poder implementarlo fácilmente.