> ## 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.

> Jeu de données contenant plus de 28 millions de publications Hacker News et leurs embeddings vectoriels

# Jeu de données Hacker News pour la recherche vectorielle

<div id="introduction">
  ## Introduction
</div>

Le [jeu de données Hacker News](https://news.ycombinator.com/) contient 28,74 millions
de publications et leurs embeddings vectoriels. Les embeddings ont été générés à l’aide du modèle [SentenceTransformers](https://sbert.net/) [all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2). La dimension de chaque vecteur d’embedding est de `384`.

Ce jeu de données peut être utilisé pour explorer les aspects de conception, de dimensionnement et de performances d’une application de recherche vectorielle à grande échelle,
en conditions réelles, construite à partir de données textuelles générées par les utilisateurs.

<div id="dataset-details">
  ## Détails du jeu de données
</div>

Le jeu de données complet avec des embeddings vectoriels est mis à disposition par ClickHouse sous la forme d’un seul fichier `Parquet` dans un [bucket S3](https://clickhouse-datasets.s3.amazonaws.com/hackernews-miniLM/hackernews_part_1_of_1.parquet)

Nous recommandons de commencer par un exercice de dimensionnement afin d’estimer les besoins en stockage et en mémoire de ce jeu de données en consultant la [documentation](/fr/reference/engines/table-engines/mergetree-family/annindexes).

<div id="steps">
  ## Étapes
</div>

<Steps>
  <Step>
    ### Créer la table

    Créez la table `hackernews` pour stocker les publications & leurs embeddings, ainsi que les attributs associés :

    ```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;
    ```

    L’`id` est simplement un entier auto-incrémenté. Les attributs supplémentaires peuvent être utilisés dans des prédicats pour mieux comprendre
    la recherche de similarité vectorielle combinée au post-filtrage/pré-filtrage, comme expliqué dans la [documentation](/fr/reference/engines/table-engines/mergetree-family/annindexes)
  </Step>

  <Step>
    ### Charger les données

    Pour charger le jeu de données à partir du fichier `Parquet`, exécutez l’instruction SQL suivante :

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

    L’insertion de 28,74 millions de lignes dans la table va prendre quelques minutes.
  </Step>

  <Step>
    ### Créer un index de similarité vectorielle

    Exécutez la requête SQL suivante pour définir et créer un index de similarité vectorielle sur la colonne `vector` de la table `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;
    ```

    Les paramètres et les considérations de performance liés à la création d’index et à la recherche sont décrits dans la [documentation](/fr/reference/engines/table-engines/mergetree-family/annindexes).
    L’instruction ci-dessus utilise respectivement les valeurs 64 et 512 pour les hyperparamètres HNSW `M` et `ef_construction`.
    Vous devez sélectionner avec soin les valeurs optimales de ces paramètres en évaluant le temps de construction de l’index et la qualité des résultats de recherche
    associés aux valeurs retenues.

    La construction et l’enregistrement de l’index peuvent même prendre quelques minutes, voire une heure, pour l’ensemble du jeu de données de 28,74 millions, selon le nombre de cœurs CPU disponibles et la bande passante du stockage.
  </Step>

  <Step>
    ### Effectuer une recherche ANN

    Une fois l’index de similarité vectorielle construit, les requêtes de recherche vectorielle utiliseront automatiquement cet index :

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

    ```

    Le chargement initial de l’index vectoriel en mémoire peut prendre de quelques secondes à quelques minutes.
  </Step>

  <Step>
    ### Générer des embeddings pour la requête de recherche

    [Sentence Transformers](https://www.sbert.net/) proposent des modèles d'embedding locaux et faciles à utiliser pour capturer le sens sémantique des phrases et des paragraphes.

    Le jeu de données HackerNews contient des embeddings vectoriels générés à partir du modèle
    [all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2).

    Un exemple de script Python est fourni ci-dessous pour illustrer la génération programmatique
    de vecteurs d'embedding à l'aide du package Python `sentence_transformers`. Le vecteur d'embedding de recherche
    est ensuite passé en argument à la fonction [`cosineDistance()`](/fr/reference/functions/regular-functions/distance-functions#cosineDistance) dans la requête \`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:
        # Take the search query from user
        print("Enter a search query :")
        input_query = sys.stdin.readline();
        texts = [input_query]

        # Run the model and obtain search vector
        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("---------")

    ```

    Voici un exemple d'exécution du script Python ci-dessus et des résultats de la recherche par similarité
    (seuls 100 caractères de chacun des 20 premiers posts sont affichés) :

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

    Enter a search query :
    Are OLAP cubes useful

    Generating the embedding for  "Are OLAP cubes useful"

    Querying ClickHouse...

    Results :

    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
    ---------
    ```

    ## Application de démonstration de résumé

    L'exemple ci-dessus a illustré la recherche sémantique et la récupération de documents avec ClickHouse.

    Un exemple d'application d'IA générative très simple mais à fort potentiel est présenté ci-dessous.

    L'application effectue les étapes suivantes :

    1. Accepte un *sujet* saisi par l’utilisateur
    2. Génère un vecteur d’embedding pour le *sujet* à l’aide de `SentenceTransformers` avec le modèle `all-MiniLM-L6-v2`
    3. Récupère des publications/commentaires très pertinents via une recherche par similarité vectorielle dans la table `hackernews`
    4. Utilise `LangChain` et l’API Chat OpenAI `gpt-3.5-turbo` pour **résumer** le contenu récupéré à l’étape #3.
       Les publications/commentaires récupérés à l’étape #3 sont transmis comme *contexte* à l’API Chat et constituent le maillon essentiel de Generative AI.

    Un exemple d'exécution de l'application de résumé est présenté ci-dessous, suivi du code de l'application. L'exécution de l'application nécessite qu'une clé API OpenAI soit définie dans la variable d'environnement `OPENAI_API_KEY`. La clé API OpenAI peut être obtenue après inscription sur [https://platform.openai.com](https://platform.openai.com).

    Cette application illustre un cas d'usage d'IA générative applicable à de multiples domaines métier, tels que :
    l'analyse du sentiment client, l'automatisation du support technique, l'exploitation des conversations utilisateurs, les documents juridiques, les dossiers médicaux,
    les comptes rendus de réunions, les états financiers, 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.
    ```

    Code de l'application ci-dessus :

    ```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) # ClickHouse credentials here

    while True:
        # Take the search query from user
        print("Enter a search topic :")
        input_query = sys.stdin.readline();
        texts = [input_query]

        # Run the model and obtain search or reference vector
        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)

        # Just join all the search results
        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>
