Effectuer une analyse avancée des données d’événements Facebook avec une base de données vectorielle

Dans l’ère numérique d’aujourd’hui, les professionnels de tous les secteurs doivent rester à jour avec les événements à venir, les conférences et les ateliers. Cependant, trouver efficacement des événements qui correspondent à ses intérêts au milieu de l’immense océan d’informations en ligne présente un défi significatif.

Ce blog présente une solution innovante à ce défi : une application complète conçue pour récupérer des données d’événements à partir de Facebook et analyser les données récupérées en utilisant MyScale. Bien que MyScale soit généralement associé à la pile technologique RAG ou utilisé comme base de données vectorielle, ses capacités dépassent ces domaines. Nous allons l’utiliser pour l’analyse des données, en tirant parti de sa fonctionnalité de recherche vectorielle pour analyser les événements qui sont sémantiquement similaires, fournissant ainsi de meilleurs résultats et des insights.

Vous remarquerez peut-être que Grok AI a utilisé la base de données vectorielle Qdrant comme moteur de recherche pour récupérer des informations en temps réel à partir de X (anciennement connue sous le nom de Twitter) données. Vous pouvez également évaluer la puissance des bases de données vectorielles de cette façon avec MyScale en intégrant MyScale avec d’autres plateformes comme Apify pour améliorer les tâches quotidiennes grâce au développement d’applications personnalisées simples.

Alors dans ce blog, développons une application qui n’accepte que le nom d’une ville en entrée et récupère tous les événements connexes à partir de Facebook. Ensuite, nous procéderons à l’analyse des données et à la recherche sémantique en utilisant les capacités vectorielles SQL avancées de MyScale.

Outils et Technologies

Nous utiliserons plusieurs outils, y compris Apify, MyScale et OpenAI, pour développer cette application utile.

  • Apify: Une plateforme populaire de web scraping et d’automatisation qui simplifie considérablement le processus de collecte de données. Elle offre la capacité de récupérer des données et de les alimenter ensuite dans les LLMs. Cela nous permet de former des LLMs sur des données en temps réel et de développer des applications.
  • MyScale: MyScale est une base de données vectorielle SQL que nous utilisons pour stocker et traiter à la fois des données structurées et non structurées de manière optimisée.
  • OpenAI: Nous utiliserons le modèle text-embedding-3-small d’OpenAI pour obtenir les embeddings du texte, puis enregistrer ces embeddings dans MyScale pour l’analyse des données et la recherche sémantique.

Comment configurer MyScale et Apify

Pour commencer à configurer MyScale et Apify, vous devrez créer un nouveau répertoire et un fichier Python. Vous pouvez le faire en ouvrant votre terminal ou ligne de commande et en entrant les commandes suivantes:

Shell

 

mkdir MyScale
cd MyScale
touch main.ipynb

Installons les packages. Copiez la commande ci-dessous et collez-la dans votre terminal. Ces packages fourniront les outils et les bibliothèques dont nous avons besoin pour développer notre application.

Shell

 

pip install openai apify-client clickhouse-connect pandas numpy

Cela devrait installer toutes les dépendances dans votre système. Pour confirmer que tout est installé correctement, vous pouvez entrer la commande suivante dans votre terminal.

Shell

 

pip freeze | egrep '(openai|apify-client|clickhouse-connect|pandas|numpy)'

Ceci doit inclure toutes les dépendances installées avec leurs versions. Si vous remarquez des dépendances manquantes, vous devrez peut-être réexécuter la commande d’installation pour ce package spécifique. Maintenant, nous sommes prêts à écrire notre code après les installations.

Remarque: Nous travaillerons dans un notebook Python. Considérez chaque bloc de code comme une cellule de notebook.

Comment Scraper des Données avec Apify

À présent, nous utiliserons l’API Apify pour scraper les données d’événements de la ville de New York à l’aide de scraper d’événements Facebook

Python

 

     import pandas as pd
from apify_client import ApifyClient
# Initialiser le ApifyClient avec votre token API
client = ApifyClient("Enter_your_apify_key_here")

# Préparer l'entrée de l'Actor
run_input = {
    "searchQueries": ["Sport New York"],
    "startUrls": [],
    "maxEvents": 50,
}

# Exécuter l'Actor et attendre qu'il se termine
run = client.actor("UZBnerCFBo5FgGouO").call(run_input=run_input)

df_columns = ['Name', 'Datetime', 'Description', 'Users_Going', 'Users_Interested', 'Users_Responded', 'City', 'Organized_By', 'Street_Address']
dataframe1 = pd.DataFrame(columns=df_columns)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    # Utiliser une compréhension de dictionnaire pour remplacer les valeurs None par une chaîne vide
    row = {
        'Name': item.get('name', ''),
        'Datetime': item.get('dateTimeSentence', ''),
        'Description': item.get('description', ''),
        'Users_Going': item.get('usersGoing', ''),
        'Users_Interested': item.get('usersInterested', ''),
        'Users_Responded': item.get('usersResponded', ''),
        'City': item.get('location', {}).get('city', '') if item.get('location') else '',
        'Organized_By': item.get('organizedBy', ''),
        'Street_Address': item.get('location', {}).get('streetAddress', '') if item.get('location') else ''
    }
    # Assurer que toutes les valeurs None sont remplacées par une chaîne vide
    row = {k: (v if v is not None else '') for k, v in row.items()}
    dataframe1 = dataframe1._append(row, ignore_index=True)

# Nettoyage des données
dataframe1['Description'] = dataframe1['Description'].replace('\\n', '', regex=True)

Ce script nous donne les détails des événements à venir sous la forme d’un DataFrame pandas.

Note: N’oubliez pas d’ajouter votre clé API Apify dans le script ci-dessus. Vous pouvez trouver votre jeton API sur la page Intégrations dans la console Apify.

Prétraitement des données

Lorsque nous rassemblons des données brutes, elles sont disponibles dans divers formats. Dans ce script, nous allons convertir les dates d’événements en un format unique afin que notre filtrage de données puisse être effectué de manière plus efficace.

Python

 

     # Importation des bibliothèques nécessaires pour la manipulation de données et la conversion de dates
import pandas as pd
import numpy as np
from datetime import datetime
from dateutil import parser

# Fonction pour convertir des chaînes de dates qui peuvent représenter une plage ou une seule date
def parse_dates(date_str):
    # Vérifier si la chaîne de date contient un trait d'union, indiquant une plage
    if '-' in date_str:
        parts = date_str.split('-')
        # Si la chaîne se divise en deux parties, c'est une plage valide
        if len(parts) == 2:
            try:
                # Convertir les dates de début et de fin, les formatant en un format lisible
                start_date = parser.parse(parts[0], fuzzy=True).strftime('%a, %b %d')
                end_date = parser.parse(parts[1], fuzzy=True).strftime('%a, %b %d')
                return start_date, end_date
            except ValueError:
                # En cas d'erreur de conversion, ne rien faire (traitement ci-dessous)
                pass  
    # Si ce n'est pas une plage ou si la conversion de la plage a échoué, essayer de convertir en une seule date
    try:
        parsed_date = parser.parse(date_str, fuzzy=True)
        # Formater la date unique pour Start_Date et différemment pour End_Date
        start_date = parsed_date.strftime('%a, %b %d AT %I:%M %p EDT')
        end_date = parsed_date.strftime('%a, %b %d')  # Omitting time for end_date
        return start_date, end_date
    except ValueError:
        # Retourner NaN pour les deux dates si la conversion échoue
        return np.nan, np.nan  

# Fonction pour extraire les détails de date, heure et jour d'une chaîne de date
def extract_date_time_day(date_str):
    try:
        # Convertir la chaîne de date, permettant une certaine flexibilité dans le format d'entrée
        parsed_date = parser.parse(date_str, fuzzy=True)
        # Extraire et formater les parties de date, heure et jour
        date = parsed_date.strftime('%Y-%m-%d')
        day = parsed_date.strftime('%a')
        # Déterminer si la chaîne d'origine incluait un composant horaire
        time_component = parsed_date.strftime('%I:%M %p') not in date_str
        time = parsed_date.strftime('%H:%M:%S') if not time_component else np.nan
    except ValueError:
        # Si la conversion échoue, mettre date, heure et jour à NaN
        date, time, day = np.nan, np.nan, np.nan
    
    return date, time, day

# Appliquer la fonction parse_dates à travers le dataframe, créant de nouvelles colonnes pour les dates de début et de fin
dataframe1[['Start_Date', 'End_Date']] = dataframe1.apply(lambda row: pd.Series(parse_dates(row['Datetime'])), axis=1)

# Supprimer les lignes où Start_Date est NaN, indiquant un échec de conversion
dataframe = dataframe1.dropna(subset=['Start_Date'])

# Appliquer extract_date_time_day pour diviser les dates de début et de fin en colonnes distinctes pour date, heure et jour
dataframe['Start_Date'], dataframe['Start_Time'], dataframe['Start_Day'] = zip(*dataframe['Start_Date'].apply(extract_date_time_day))
dataframe['End_Date'], _, dataframe['End_Day'] = zip(*dataframe['End_Date'].apply(extract_date_time_day))

# Supprimer la colonne 'Datetime' d'origine car elle n'est plus nécessaire
dataframe=dataframe.drop(['Datetime'], axis=1)

# Convertir 'Start_Date' et 'End_Date' en format datetime, extrayant uniquement la partie date
dataframe['Start_Date'] = pd.to_datetime(dataframe['Start_Date']).dt.date
dataframe['End_Date'] = pd.to_datetime(dataframe['End_Date']).dt.date

# Convertir 'Start_Time' en format datetime, conservant l'information horaire
dataframe['Start_Time'] = pd.to_datetime(dataframe['Start_Time'])

Ce code utilise pandas avec les packages datetime et dateutil de Python pour formater les données.

Génération d’Embraquements

Pour comprendre et rechercher en profondeur les événements, nous générerons des embeddings à partir de leurs descriptions en utilisant text-embedding-3-small. Ces embeddings capturent l’essence sémantique de chaque événement, aidant l’application à retourner de meilleurs résultats.

Python

 

     # Importer la bibliothèque OpenAI pour l'accès à l'API.
from openai import OpenAI 
# Initialiser le client OpenAI avec une clé API.
openai_client = OpenAI(api_key="your_openai_api_key_here")
# Fonction pour obtenir des embeddings textuels 
def get_embedding(text, model="text-embedding-3-small"):
    return openai_client.embeddings.create(input=text, model=model).data
embeddings = get_embedding(dataframe["Description"].tolist())
# Extraire les vecteurs d'embedding de l'objet embeddings
vectors = [embedding.embedding for embedding in embeddings]
array = np.array(vectors)
embeddings_series = pd.Series(list(array))
# Ajouter les embeddings en tant que nouvelle colonne dans le DataFrame.
dataframe['Description_Embeddings'] = embeddings_series

Maintenant, nous insérerons le nouveau DataFrame avec les embeddings dans MyScale.

Connexion avec MyScale

Comme discuté au début, nous utiliserons MyScale en tant que base de données vectorielle pour stocker et gérer les données. Ici, nous nous connecterons à MyScale en préparation du stockage des données.

Python

 

     import clickhouse_connect
client = clickhouse_connect.get_client(
    host='host_name_here',
    port=443,
    username='username_here',
    password='passwd_here'
)

Cette configuration de connexion garantit que notre application peut communiquer avec MyScale et utiliser la puissance de SQL pour la manipulation et l’analyse des données.

Note: Voir Détails de la connexion pour plus d’informations sur la manière de se connecter au cluster MyScale.

Créer des tables et des index en utilisant MyScale

Nous créons maintenant une table selon notre DataFrame. Toutes les données seront stockées dans cette table, y compris les embeddings.

Python

 

     client.command("""
    CREATE TABLE default.Events (
    Name String,
    Description String,
    Users_Going Int64,
    Users_Interested Int64,
    Users_Responded Int64,
    City String,
    Organized_By String,
    Street_Address String,
    Start_Date Date32,
    End_Date Nullable(Date32),
    Start_Time Nullable(DateTime64),
    Start_Day String,
    End_Day String,
    Description_Embeddings Array(Float32),
    CONSTRAINT check_data_length CHECK length(Description_Embeddings) = 1536
    ) ENGINE = MergeTree()
    ORDER BY (Name);
    """)

Les instructions SQL ci-dessus créent une table nommée Events sur le cluster. La CONSTRAINT garantit que tous les vecteurs d’embedding ont la même longueur 1536.

Stockage des données et création d’un index dans MyScale

Dans cette étape, nous insérons les données traitées dans MyScale. Cela implique l’insertion par lots des données pour assurer un stockage et une récupération efficaces.

Python

 

     batch_size = 10  # Adjust based on your needs

num_batches = len(dataframe) // batch_size

for i in range(num_batches):
    start_idx = i * batch_size
    end_idx = start_idx + batch_size
    batch_data = dataframe[start_idx:end_idx]
    # print(batch_data["Description_Embeddings"])
    client.insert("default.Events", batch_data.to_records(index=False).tolist(), column_names=batch_data.columns.tolist())
    print(f"Batch {i+1}/{num_batches} inserted.")

client.command("""
ALTER TABLE default.Events
    ADD VECTOR INDEX vector_index Description_Embeddings
    TYPE MSTG
""")

En utilisant pandas, le code ci-dessus transfère efficacement notre jeu de données préparé dans la base de données MyScale.

Analyse des données à l’aide de MyScale

Enfin, nous utilisons les capacités analytiques de MyScale pour effectuer des analyses et activer la recherche sémantique. En exécutant des requêtes SQL, nous pouvons analyser les événements en fonction des sujets, des lieux et des dates. Donc, essayons d’écrire quelques requêtes.

Requête SQL simple

Essayons d’abord d’obtenir les 10 premiers résultats de la table.

Python

 

     results=client.query("""
        SELECT Name,Description FROM default.Events LIMIT 10
    """)
for row in results.named_results():
        print(row["Name"])
        print(row['Description'])

Cette requête retournera simplement les 10 premiers résultats de la table events.

Découvrir des événements par pertinence sémantique

Essayons de trouver les 10 prochains événements ayant une ambiance similaire à un événement de référence, comme ceci : « L’un des spectacles les plus longs en cours dans le pays – En opération depuis 1974… MAINTENANT notre 50ème ANNÉE !!! Notre Schenectady ». Ceci est réalisé en comparant les embeddings sémantiques des descriptions des événements, assurant un match sur les thèmes et les émotions.

Python

 

embeddings=get_embedding(["One of the Longest Running Shows in the Country - Operating since 1974 ...NOW our 50th YEAR !!!Our Schenectady"])
embedding=embeddings[0].embedding
results = client.query(f"""
        SELECT Name, Description,
        distance(Description_Embeddings, {embedding}) as dist FROM default.Events ORDER BY dist LIMIT 10
    """)
for row in results.named_results():
        print("Title of the event  ", row["Name"])
        print("Description of the event  ", row['Description'])
        print("Distance : ", row["dist"])

Événements en tendance par popularité

Cette requête classe les 10 meilleurs événements en fonction du nombre de participants et d’utilisateurs intéressés, mettant en évidence des événements populaires allant des festivals de grandes villes aux conférences majeures. Elle est idéale pour ceux qui cherchent à rejoindre de grandes assemblées animées.

Python

 

     results = client.query(f"""
        SELECT Name, City, Users_Going, Users_Interested, Users_Responded
        FROM default.Events
        ORDER BY Users_Going DESC, Users_Interested DESC
        LIMIT 10
    """)
for row in results.named_results():
        print("Event Name  ", row["Name"])
        print("City ", row["City"])
        print("Users Going ", row["Users_Going"])
        print("Interested Users ", row["Users_Interested"])

Événements locaux populaires à New York

En combinant pertinence et popularité, cette requête identifie des événements similaires à New York liés à un événement spécifique et les classe par participation, offrant une liste sélectionnée d’événements qui reflète la culture vibrante de la ville et attirent l’intérêt local.

Python

 

     embeddings=get_embedding(["One of the Longest Running Shows in the Country - Operating since 1974 ...NOW our 50th YEAR !!!Our Schenectady"])
embeddi=embeddings[0].embedding
results = client.query(f"""
        SELECT Name,City, Description, Users_Going,distance(Description_Embeddings, {embeddi}) as dist
        FROM default.Events
        WHERE City LIKE '%New York%' and dist < 1.5
        ORDER BY Users_Going DESC,dist
        LIMIT 10
    """)
for row in results.named_results():
        print("Event Name  ", row["Name"])
        print("Description ", row["Description"])
        print("Users Going ", row["Users_Going"])

Organisateurs d’événements de premier plan

Cette requête classe les 10 meilleurs organisateurs d’événements en fonction du nombre total de participants et d’utilisateurs intéressés, mettant en avant ceux qui s’illustrent dans la création d’événements captivants et l’attraction de grandes audiences. Elle fournit des informations pour les planificateurs d’événements et les participants intéressés par les événements de haut niveau.

Python

 

     # Quel client a attiré le plus grand nombre d'utilisateurs 
results = client.query(f"""
       SELECT Organized_By, SUM(Users_Going + Users_Interested) AS Total_Users
        FROM default.Events
        GROUP BY Organized_By
        ORDER BY Total_Users DESC
        Limit 10
    """)
for row in results.named_results():
        print("Event Name  ", row["Organized_By"])
        print("Total_Users ", row["Total_Users"])

Mettre en œuvre RAG

Auparavant, nous avons exploré MyScale pour l’analyse des données, soulignant ses capacités à améliorer nos workflows de données. Ensuite, nous allons franchir une étape supplémentaire en mettant en œuvre la Génération Augmentée par Récupération (RAG), un cadre innovant qui combine une base de connaissances externe avec des LLMs. Cette étape vous aidera à mieux comprendre vos données et à trouver des insights plus détaillés. Ensuite, vous verrez comment utiliser RAG avec MyScale, ce qui rendra le travail avec les données plus intéressant et productif.

Python

 

     from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

query="Can you please suggest me some events related to basketball"
# Utilisez la méthode get_embedding définie ci-dessus, elle accepte une liste de phrases
embeddings=get_embedding([query])
embeddings=embeddings[0].embedding
results = client.query(f"""
        SELECT Name, City, Users_Going, Description, distance(Description_Embeddings, {embeddings}) as dist
        FROM default.Events
        ORDER BY Users_Going DESC,dist
        LIMIT 5
    """)
PROMPT_TEMPLATE = """
Your objective is to formulate a response to a question using only the information provided below:
{context}
---
Your task is to carefully analyze the provided context and provide an answer to the following question based solely on the information given:
{question}
"""
# Combinez les descriptions des résultats principaux. 
descriptions = [row["Description"] for row in results.named_results()]
context_text = "\n\n---\n\n".join(descriptions)
prompt_template = ChatPromptTemplate.from_template(PROMPT_TEMPLATE)
prompt = prompt_template.format(context=context_text, question=query)
model = ChatOpenAI(openai_api_key="your_api_key_here")
response_text = model.predict(prompt)
formatted_response = f"Response: {response_text}\n"
print(formatted_response)

Tout au long de ce blog, nous avons constaté que MyScale est bien plus qu’une base de données vectorielle pouvant être utilisée pour développer toutes sortes d’applications. Nous pouvons l’utiliser comme une base de données SQL simple ou pour des applications d’IA avancées, couvrant la majorité du domaine de développement. Nous vous encourageons à l’essayer et à explorer les fonctionnalités avancées en vous inscrivant au forfait gratuit et en obtenant 5 millions de stockage vectoriel gratuit.

Conclusion

Nous avons exploré les capacités et les fonctionnalités de MyScale avec Apify Scraper à travers le processus de développement d’une application d’analyse d’événements. MyScale a démontré ses capacités exceptionnelles en matière de recherche vectorielle haute performance tout en conservant toutes les fonctionnalités des bases de données SQL, ce qui aide les développeurs à effectuer des recherches sémantiques à l’aide d’une syntaxe SQL familière avec une bien meilleure vitesse et précision.

Les capacités de MyScale ne se limitent pas à cette application : vous pouvez l’adopter pour développer n’importe quelle application IA en utilisant la méthode RAG

Si vous avez des commentaires ou des suggestions, n’hésitez pas à nous contacter.

Source:
https://dzone.com/articles/performing-advanced-facebook-event-data-analysis-w