> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Conjunto de datos con más de 28 millones de publicaciones de Hacker News y sus embeddings vectoriales

# Conjunto de datos para búsqueda vectorial de Hacker News

<div id="introduction">
  ## Introducción
</div>

El [conjunto de datos de Hacker News](https://news.ycombinator.com/) contiene 28.74 millones de
publicaciones y sus embeddings vectoriales. Los embeddings se generaron con el modelo [all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2) de [SentenceTransformers](https://sbert.net/). La dimensión de cada vector de embedding es `384`.

Este conjunto de datos puede usarse para analizar los aspectos de diseño, dimensionamiento y rendimiento de una aplicación de búsqueda vectorial a gran escala,
en un entorno real, construida sobre datos textuales generados por los usuarios.

<div id="dataset-details">
  ## Detalles del conjunto de datos
</div>

ClickHouse pone a disposición el conjunto de datos completo con embeddings vectoriales como un único archivo `Parquet` en un [bucket de S3](https://clickhouse-datasets.s3.amazonaws.com/hackernews-miniLM/hackernews_part_1_of_1.parquet)

Recomendamos a los usuarios realizar primero un ejercicio de dimensionamiento para estimar los requisitos de almacenamiento y memoria de este conjunto de datos consultando la [documentación](/es/reference/engines/table-engines/mergetree-family/annindexes).

<div id="steps">
  ## Pasos
</div>

<Steps>
  <Step>
    ### Crear la tabla

    Cree la tabla `hackernews` para almacenar las publicaciones & sus embeddings, así como los atributos asociados:

    ```sql theme={null}
    CREATE TABLE hackernews
    (
        `id` Int32,
        `doc_id` Int32,
        `text` String,
        `vector` Array(Float32),
        `node_info` Tuple(
            start Nullable(UInt64),
            end Nullable(UInt64)),
        `metadata` String,
        `type` Enum8('story' = 1, 'comment' = 2, 'poll' = 3, 'pollopt' = 4, 'job' = 5),
        `by` LowCardinality(String),
        `time` DateTime,
        `title` String,
        `post_score` Int32,
        `dead` UInt8,
        `deleted` UInt8,
        `length` UInt32
    )
    ENGINE = MergeTree
    ORDER BY id;
    ```

    El `id` es solo un entero que se incrementa. Los atributos adicionales pueden usarse en predicados para entender
    la búsqueda por similitud vectorial combinada con posfiltrado/prefiltrado, como se explica en la [documentación](/es/reference/engines/table-engines/mergetree-family/annindexes)
  </Step>

  <Step>
    ### Cargar datos

    Para cargar los datos desde el archivo `Parquet`, ejecute la siguiente sentencia SQL:

    ```sql theme={null}
    INSERT INTO hackernews SELECT * FROM s3('https://clickhouse-datasets.s3.amazonaws.com/hackernews-miniLM/hackernews_part_1_of_1.parquet');
    ```

    Insertar 28,74 millones de filas en la tabla llevará unos minutos.
  </Step>

  <Step>
    ### Crear un índice de similitud vectorial

    Ejecute la siguiente instrucción SQL para definir y crear un índice de similitud vectorial en la columna `vector` de la tabla `hackernews`:

    ```sql theme={null}
    ALTER TABLE hackernews ADD INDEX vector_index vector TYPE vector_similarity('hnsw', 'cosineDistance', 384, 'bf16', 64, 512);

    ALTER TABLE hackernews MATERIALIZE INDEX vector_index SETTINGS mutations_sync = 2;
    ```

    Los parámetros y las consideraciones de rendimiento para la creación y la búsqueda de índices se describen en la [documentación](/es/reference/engines/table-engines/mergetree-family/annindexes).
    La instrucción anterior usa los valores 64 y 512, respectivamente, para los hiperparámetros HNSW `M` y `ef_construction`.
    Debe seleccionar cuidadosamente los valores óptimos de estos parámetros evaluando el tiempo de construcción del índice y la calidad de los resultados de búsqueda
    en función de los valores seleccionados.

    La construcción y el almacenamiento del índice podrían tardar incluso unos minutos o hasta una hora para el conjunto de datos completo de 28,74 millones, según la cantidad de núcleos de CPU disponibles y el ancho de banda del almacenamiento.
  </Step>

  <Step>
    ### Realizar una búsqueda ANN

    Una vez creado el índice de similitud vectorial, las consultas de búsqueda vectorial usarán automáticamente el índice:

    ```sql title="Query" theme={null}
    SELECT id, title, text
    FROM hackernews
    ORDER BY cosineDistance( vector, <search vector>)
    LIMIT 10

    ```

    La primera carga del índice vectorial en memoria podría tardar unos segundos o minutos.
  </Step>

  <Step>
    ### Generar embeddings para la consulta de búsqueda

    [Sentence Transformers](https://www.sbert.net/) ofrece modelos de embedding locales y fáciles de usar para capturar el significado semántico de oraciones y párrafos.

    El conjunto de datos de HackerNews contiene embeddings vectoriales generados con el modelo
    [all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2).

    A continuación se incluye un script de Python de ejemplo para mostrar cómo generar
    vectores de embedding de forma programática usando el paquete de Python `sentence_transformers`. El vector de embedding de búsqueda se pasa luego como argumento a la función [`cosineDistance()`](/es/reference/functions/regular-functions/distance-functions#cosineDistance) en la consulta \`SELECT\`.

    ```python theme={null}
    from sentence_transformers import SentenceTransformer
    import sys

    import clickhouse_connect

    print("Initializing...")

    model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')

    chclient = clickhouse_connect.get_client() # ClickHouse credentials here

    while True:
        # Obtener la consulta de búsqueda del usuario
        print("Enter a search query :")
        input_query = sys.stdin.readline();
        texts = [input_query]

        # Ejecutar el modelo y obtener el vector de búsqueda
        print("Generating the embedding for ", input_query);
        embeddings = model.encode(texts)

        print("Querying ClickHouse...")
        params = {'v1':list(embeddings[0]), 'v2':20}
        result = chclient.query("SELECT id, title, text FROM hackernews ORDER BY cosineDistance(vector, %(v1)s) LIMIT %(v2)s", parameters=params)
        print("Results :")
        for row in result.result_rows:
            print(row[0], row[2][:100])
            print("---------")
    ```

    A continuación se muestra un ejemplo de la ejecución del script de Python anterior junto con los resultados de búsqueda por similitud
    (solo se imprimen 100 caracteres de cada uno de los 20 posts principales):

    ```text theme={null}
    Inicializando...

    Ingrese una consulta de búsqueda :
    Are OLAP cubes useful

    Generando el embedding para  "Are OLAP cubes useful"

    Consultando ClickHouse...

    Resultados :

    27742647 smartmic:
    slt2021: OLAP Cube is not dead, as long as you use some form of:<p>1. GROUP BY multiple fi
    ---------
    27744260 georgewfraser:A data mart is a logical organization of data to help humans understand the schema. Wh
    ---------
    27761434 mwexler:&quot;We model data according to rigorous frameworks like Kimball or Inmon because we must r
    ---------
    28401230 chotmat:
    erosenbe0: OLAP database is just a copy, replica, or archive of data with a schema designe
    ---------
    22198879 Merick:+1 for Apache Kylin, it&#x27;s a great project and awesome open source community. If anyone i
    ---------
    27741776 crazydoggers:I always felt the value of an OLAP cube was uncovering questions you may not know to as
    ---------
    22189480 shadowsun7:
    _Codemonkeyism: After maintaining an OLAP cube system for some years, I&#x27;m not that
    ---------
    27742029 smartmic:
    gengstrand: My first exposure to OLAP was on a team developing a front end to Essbase that
    ---------
    22364133 irfansharif:
    simo7: I&#x27;m wondering how this technology could work for OLAP cubes.<p>An OLAP cube
    ---------
    23292746 scoresmoke:When I was developing my pet project for Web analytics (<a href="https:&#x2F;&#x2F;github
    ---------
    22198891 js8:It seems that the article makes a categorical error, arguing that OLAP cubes were replaced by co
    ---------
    28421602 chotmat:
    7thaccount: Is there any advantage to OLAP cube over plain SQL (large historical database r
    ---------
    22195444 shadowsun7:
    lkcubing: Thanks for sharing. Interesting write up.<p>While this article accurately capt
    ---------
    22198040 lkcubing:Thanks for sharing. Interesting write up.<p>While this article accurately captures the issu
    ---------
    3973185 stefanu:
    sgt: Interesting idea. Ofcourse, OLAP isn't just about the underlying cubes and dimensions,
    ---------
    22190903 shadowsun7:
    js8: It seems that the article makes a categorical error, arguing that OLAP cubes were r
    ---------
    28422241 sradman:OLAP Cubes have been disrupted by Column Stores. Unless you are interested in the history of
    ---------
    28421480 chotmat:
    sradman: OLAP Cubes have been disrupted by Column Stores. Unless you are interested in the
    ---------
    27742515 BadInformatics:
    quantified: OP posts with inverted condition: “OLAP != OLAP Cube” is the actual titl
    ---------
    28422935 chotmat:
    rstuart4133: I remember hearing about OLAP cubes donkey&#x27;s years ago (probably not far
    ---------
    ```

    ## Aplicación demo de resumen

    El ejemplo anterior ilustró la búsqueda semántica y la recuperación de documentos con ClickHouse.

    A continuación se presenta una aplicación de ejemplo de IA generativa muy sencilla pero con gran potencial.

    La aplicación realiza los siguientes pasos:

    1. Acepta un *topic* introducido por el usuario
    2. Genera un vector de embedding para el *topic* mediante `SentenceTransformers` con el modelo `all-MiniLM-L6-v2`
    3. Recupera publicaciones/comentarios muy relevantes mediante búsqueda por similitud vectorial en la tabla `hackernews`
    4. Usa `LangChain` y la API de Chat `gpt-3.5-turbo` de OpenAI para **resumir** el contenido recuperado en el paso n.º 3.
       Las publicaciones y los comentarios recuperados en el paso n.º 3 se pasan como *contexto* a la API de Chat y son el nexo clave en Generative AI.

    A continuación se muestra primero un ejemplo de la ejecución de la aplicación de resumen, seguido del código
    de dicha aplicación. Para ejecutar la aplicación es necesario establecer una API key de OpenAI en la variable
    de entorno `OPENAI_API_KEY`. La API key de OpenAI se puede obtener tras registrarse en [https://platform.openai.com](https://platform.openai.com).

    Esta aplicación demuestra un caso de uso de Generative AI aplicable a múltiples dominios empresariales como:
    análisis de sentimiento de clientes, automatización del soporte técnico, extracción de información de conversaciones de usuarios, documentos legales, registros médicos,
    transcripciones de reuniones, estados financieros, etc.

    ```shell theme={null}
    $ python3 summarize.py

    Enter a search topic :
    ClickHouse performance experiences

    Generating the embedding for ---->  ClickHouse performance experiences

    Querying ClickHouse to retrieve relevant articles...

    Initializing chatgpt-3.5-turbo model...

    Summarizing search results retrieved from ClickHouse...

    Summary from chatgpt-3.5:
    The discussion focuses on comparing ClickHouse with various databases like TimescaleDB, Apache Spark,
    AWS Redshift, and QuestDB, highlighting ClickHouse's cost-efficient high performance and suitability
    for analytical applications. Users praise ClickHouse for its simplicity, speed, and resource efficiency
    in handling large-scale analytics workloads, although some challenges like DMLs and difficulty in backups
    are mentioned. ClickHouse is recognized for its real-time aggregate computation capabilities and solid
    engineering, with comparisons made to other databases like Druid and MemSQL. Overall, ClickHouse is seen
    as a powerful tool for real-time data processing, analytics, and handling large volumes of data
    efficiently, gaining popularity for its impressive performance and cost-effectiveness.
    ```

    Código para la aplicación anterior:

    ```python theme={null}
    print("Initializing...")

    import sys
    import json
    import time
    from sentence_transformers import SentenceTransformer

    import clickhouse_connect

    from langchain.docstore.document import Document
    from langchain.text_splitter import CharacterTextSplitter
    from langchain.chat_models import ChatOpenAI
    from langchain.prompts import PromptTemplate
    from langchain.chains.summarize import load_summarize_chain
    import textwrap
    import tiktoken

    def num_tokens_from_string(string: str, encoding_name: str) -> int:
        encoding = tiktoken.encoding_for_model(encoding_name)
        num_tokens = len(encoding.encode(string))
        return num_tokens

    model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')

    chclient = clickhouse_connect.get_client(compress=False) # Credenciales de ClickHouse aquí

    while True:
        # Obtener la consulta de búsqueda del usuario
        print("Enter a search topic :")
        input_query = sys.stdin.readline();
        texts = [input_query]

        # Ejecutar el modelo y obtener el vector de búsqueda o de referencia
        print("Generating the embedding for ----> ", input_query);
        embeddings = model.encode(texts)

        print("Querying ClickHouse...")
        params = {'v1':list(embeddings[0]), 'v2':100}
        result = chclient.query("SELECT id,title,text FROM hackernews ORDER BY cosineDistance(vector, %(v1)s) LIMIT %(v2)s", parameters=params)

        # Concatenar todos los resultados de búsqueda
        doc_results = ""
        for row in result.result_rows:
            doc_results = doc_results + "\n" + row[2]

        print("Initializing chatgpt-3.5-turbo model")
        model_name = "gpt-3.5-turbo"

        text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
            model_name=model_name
        )

        texts = text_splitter.split_text(doc_results)

        docs = [Document(page_content=t) for t in texts]

        llm = ChatOpenAI(temperature=0, model_name=model_name)

        prompt_template = """
    Write a concise summary of the following in not more than 10 sentences:

    {text}

    CONSCISE SUMMARY :
    """

        prompt = PromptTemplate(template=prompt_template, input_variables=["text"])

        num_tokens = num_tokens_from_string(doc_results, model_name)

        gpt_35_turbo_max_tokens = 4096
        verbose = False

        print("Summarizing search results retrieved from ClickHouse...")

        if num_tokens <= gpt_35_turbo_max_tokens:
            chain = load_summarize_chain(llm, chain_type="stuff", prompt=prompt, verbose=verbose)
        else:
            chain = load_summarize_chain(llm, chain_type="map_reduce", map_prompt=prompt, combine_prompt=prompt, verbose=verbose)

        summary = chain.run(docs)

        print(f"Summary from chatgpt-3.5: {summary}")
    ```
  </Step>
</Steps>
