Nell’era digitale di oggi, i professionisti in tutti i settori devono rimanere aggiornati su eventi imminenti, conferenze e workshop. Tuttavia, trovare efficientemente eventi che corrispondono ai propri interessi nel vasto oceano di informazioni online rappresenta una sfida significativa.
Questo blog introduce una soluzione innovativa a questa sfida: un’applicazione completa progettata per estrarre dati sugli eventi da Facebook e analizzare i dati estratti utilizzando MyScale. Mentre MyScale è comunemente associato alla pila tecnologica RAG o utilizzato come database vettoriale, le sue capacità si estendono oltre questi ambiti. Utilizzeremo MyScale per l’analisi dei dati, sfruttando la sua funzionalità di ricerca vettoriale per analizzare eventi semanticamente simili, fornendo così risultati e insight migliori.
Potreste notare che Grok AI ha utilizzato il database vettoriale Qdrant come motore di ricerca per recuperare informazioni in tempo reale da X (precedentemente conosciuto come Twitter). Potete anche valutare il potere dei database vettoriali in questo modo con MyScale integrando MyScale con altre piattaforme come Apify per migliorare le attività quotidiane attraverso lo sviluppo di semplici applicazioni personalizzate.
Quindi in questo blog, sviluppiamo un’applicazione che accetta solo il nome di una città come input e estrae tutti gli eventi correlati da Facebook. Successivamente, condurremo un’analisi dei dati e una ricerca semantica utilizzando le avanzate funzionalità SQL vettoriali di MyScale.
Strumenti e Tecnologie
Utilizzeremo diversi strumenti, tra cui Apify, MyScale e OpenAI, per sviluppare questa utile applicazione.
- Apify: Una popolare piattaforma web scraping e di automazione che semplifica notevolmente il processo di raccolta dei dati. Offre la capacità di estrarre dati e successivamente iniettarli nei LLMs. Ciò ci consente di addestrare i LLMs su dati in tempo reale e sviluppare applicazioni.
- MyScale: MyScale è un database vettoriale SQL che utilizziamo per memorizzare e elaborare sia dati strutturati che non strutturati in modo ottimizzato.
- OpenAI: Utilizzeremo il modello
text-embedding-3-small
di OpenAI per ottenere gli embedding del testo e poi salvarli in MyScale per l’analisi dei dati e la ricerca semantica.
Come Configurare MyScale e Apify
Per iniziare a configurare MyScale e Apify, dovrai creare una nuova directory e un file Python. Puoi fare ciò aprendo il tuo terminale o linea di comando ed immettendo i seguenti comandi:
mkdir MyScale
cd MyScale
touch main.ipynb
Installiamo i pacchetti. Copia il comando seguente e incollalo nel tuo terminale. Questi pacchetti forniranno gli strumenti e le librerie di cui abbiamo bisogno per sviluppare la nostra applicazione.
pip install openai apify-client clickhouse-connect pandas numpy
Questo dovrebbe installare tutte le dipendenze nel tuo sistema. Per confermare che tutto sia installato correttamente, puoi inserire il seguente comando nel terminale.
pip freeze | egrep '(openai|apify-client|clickhouse-connect|pandas|numpy)'
Ciò dovrebbe includere tutte le dipendenze installate con le loro versioni. Se noti alcune dipendenze mancanti, potrebbe essere necessario ri-eseguire il comando di installazione per quel pacchetto specifico. Ora siamo pronti a scrivere il nostro codice dopo le installazioni.
Nota: Stiamo lavorando in un notebook Python. Considerare ogni blocco di codice come una cella del notebook.
Come Estrarre Dati con Apify
Ora, utilizzeremo l’API di Apify per estrarre i dati degli eventi di New York City usando Raccoglitore di Eventi Facebook.
import pandas as pd
from apify_client import ApifyClient
# Inizializza l'ApifyClient con il tuo token API
client = ApifyClient("Enter_your_apify_key_here")
# Prepara l'input per l'Actor
run_input = {
"searchQueries": ["Sport New York"],
"startUrls": [],
"maxEvents": 50,
}
# Esegui l'Actor e attendi che finisca
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():
# Usa una comprensione di dizionario per sostituire i valori None con una stringa vuota
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 ''
}
# Assicurati che tutti i valori None siano sostituiti da una stringa vuota
row = {k: (v if v is not None else '') for k, v in row.items()}
dataframe1 = dataframe1._append(row, ignore_index=True)
# Pulizia dei dati
dataframe1['Description'] = dataframe1['Description'].replace('\\n', '', regex=True)
Questo script ci fornisce i dettagli degli eventi futuri sotto forma di DataFrame pandas
.
Nota: Non dimenticare di aggiungere la tua chiave API di Apify nello script indicato. Puoi trovare il tuo token API sulla pagina Integrazioni nella Console Apify.
Pre-elaborazione dei dati
Quando raccolgiamo dati grezzi, questi arrivano in vari formati. In questo script, trasformeremo le date degli eventi in un formato unico per facilitare la filtrazione dei dati in modo più efficiente.
# Importa i necessari moduli per la manipolazione dei dati e la parsing delle date
import pandas as pd
import numpy as np
from datetime import datetime
from dateutil import parser
# Funzione per parsificare stringhe di date che possono rappresentare un range o una singola data
def parse_dates(date_str):
# Verifica se la stringa di data contiene un trattino, indicando un range
if '-' in date_str:
parts = date_str.split('-')
# Se la stringa si divide in due parti, è un range valido
if len(parts) == 2:
try:
# Parsifica le date di inizio e fine, formattandole in un formato leggibile
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:
# In caso di errore di parsificazione, non fare nulla (verrà gestito di seguito)
pass
# Se non è un range o se la parsificazione del range ha fallito, prova a parsificare come data singola
try:
parsed_date = parser.parse(date_str, fuzzy=True)
# Formatta la data singola per Start_Date e formattare diversamente per 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:
# Restituisci NaN per entrambe le date se la parsificazione fallisce
return np.nan, np.nan
# Funzione per estrarre data dettagliata, ora e giorno da una stringa di data
def extract_date_time_day(date_str):
try:
# Parsifica la stringa di data, permettendo una certa flessibilità nel formato di input
parsed_date = parser.parse(date_str, fuzzy=True)
# Estrai e formattare le parti di data, ora e giorno
date = parsed_date.strftime('%Y-%m-%d')
day = parsed_date.strftime('%a')
# Determina se la stringa originale includeva una componente temporale
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:
# Se la parsificazione fallisce, imposta data, ora e giorno su NaN
date, time, day = np.nan, np.nan, np.nan
return date, time, day
# Applica la funzione parse_dates attraverso il dataframe, creando nuove colonne per le date di inizio e fine
dataframe1[['Start_Date', 'End_Date']] = dataframe1.apply(lambda row: pd.Series(parse_dates(row['Datetime'])), axis=1)
# Elimina le righe in cui Start_Date è NaN, indicando che la parsificazione non è riuscita
dataframe = dataframe1.dropna(subset=['Start_Date'])
# Applica extract_date_time_day per dividere le date di inizio e fine in colonne separate per data, ora e giorno
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))
# Rimuovi la colonna originale 'Datetime' poiché non è più necessaria
dataframe=dataframe.drop(['Datetime'], axis=1)
# Converti 'Start_Date' e 'End_Date' in formato datetime, estraendo solo la parte della data
dataframe['Start_Date'] = pd.to_datetime(dataframe['Start_Date']).dt.date
dataframe['End_Date'] = pd.to_datetime(dataframe['End_Date']).dt.date
# Converti 'Start_Time' in formato datetime, mantenendo le informazioni temporali
dataframe['Start_Time'] = pd.to_datetime(dataframe['Start_Time'])
Questo frammento di codice utilizza pandas
insieme ai pacchetti datetime
e dateutil
di Python per formattare i dati.
Generazione di Inbeddings
Per comprendere a fondo e ricercare eventi, genereremo embedding dalle loro descrizioni utilizzando il text-embedding-3-small
. Questi embedding catturano l’essenza semantica di ogni evento, aiutando l’applicazione a restituire risultati migliori.
# Importa la libreria OpenAI per l'accesso all'API.
from openai import OpenAI
# Inizializza il client OpenAI con una chiave API.
openai_client = OpenAI(api_key="your_openai_api_key_here")
# Funzione per ottenere embedding di testo
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())
# Estrai i vettori di embedding dall'oggetto embedding
vectors = [embedding.embedding for embedding in embeddings]
array = np.array(vectors)
embeddings_series = pd.Series(list(array))
# Aggiungi gli embedding come nuova colonna nel DataFrame.
dataframe['Description_Embeddings'] = embeddings_series
Ora, inseriremo il nuovo DataFrame
con gli embedding in MyScale.
Connessione con MyScale
Come discusso all’inizio, utilizzeremo MyScale come database vettoriale per memorizzare e gestire i dati. Qui, ci connetteremo a MyScale in preparazione per la memorizzazione dei dati.
import clickhouse_connect
client = clickhouse_connect.get_client(
host='host_name_here',
port=443,
username='username_here',
password='passwd_here'
)
Questa configurazione della connessione garantisce che il nostro applicazione possa comunicare con MyScale e utilizzare il potere di SQL per la manipolazione e l’analisi dei dati.
Nota: Consulta Dettagli della Connessione per ulteriori informazioni su come connettersi al cluster MyScale.
Creare Tabelle e Indici Utilizzando MyScale
Ora creiamo una tabella secondo il nostro DataFrame. Tutti i dati saranno memorizzati in questa tabella, compresi gli embedding.
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);
""")
Le dichiarazioni SQL sopra creano una tabella chiamata Eventi
nel cluster. Il vincolo CONSTRAINT
si assicura che tutti i vettori di embedding siano della stessa lunghezza 1536
.
Memorizzazione dei dati e creazione di un indice in MyScale
In questo passaggio, inseriamo i dati elaborati in MyScale. Ciò comporta l’inserimento batch dei dati per garantire una memorizzazione e un recupero efficienti.
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
""")
Utilizzando pandas
, il codice sopra trasferisce efficientemente il nostro dataset preparato nel database MyScale.
Analisi dei dati utilizzando MyScale
Infine, utilizziamo le capacità analitiche di MyScale per eseguire analisi e abilitare la ricerca semantica. Eseguendo query SQL, possiamo analizzare eventi basati su argomenti, luoghi e date. Quindi, proviamo a scrivere alcune query.
Query SQL semplice
Proviamo prima a ottenere i primi 10 risultati dalla tabella.
results=client.query("""
SELECT Name,Description FROM default.Events LIMIT 10
""")
for row in results.named_results():
print(row["Name"])
print(row['Description'])
Questa query restituirà semplicemente i primi 10 risultati dalla tabella eventi
.
Scoprire eventi per rilevanza semantica
Proviamo a trovare i primi 10 eventi imminenti con un’atmosfera simile a un evento di riferimento, come questo: “Uno degli spettacoli più longevi del paese – Attivo dal 1974 … ORA il nostro 50° ANNO!!! Il nostro Schenectady”. Ciò viene realizzato confrontando gli embedding semantici delle descrizioni degli eventi, garantendo una corrispondenza nei temi e nelle emozioni.
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"])
Eventi in tendenza per popolarità
Questa query classifica i primi 10 eventi per numero di partecipanti e utenti interessati, evidenziando eventi popolari dai grandi festival cittadini alle principali conferenze. È ideale per coloro che cercano di partecipare a raduni grandi ed energici.
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"])
Eventi Locali Popolari a New York
Combinando rilevanza e popolarità, questa query identifica eventi simili a New York City legati a un evento specifico e li classifica per partecipanti, offrendo un elenco curato di eventi che riflettono la vibrante cultura della città e attirano l’interesse locale.
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"])
Principali Organizzatori di Eventi
Questa query classifica i primi 10 organizzatori di eventi per il numero totale di partecipanti e utenti interessati, evidenziando coloro che eccellono nella creazione di eventi coinvolgenti e nell’attrarre grandi pubblici. Fornisce spunti per pianificatori di eventi e partecipanti interessati agli eventi di alto livello.
# Quale cliente ha attirato il maggior numero di utenti
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"])
Implementare RAG;
In precedenza, abbiamo esplorato MyScale per l’analisi dei dati, evidenziando le sue capacità nel migliorare i nostri flussi di lavoro con i dati. Andando avanti, faremo un passo in più implementando Retrieval-Augmented Generation (RAG), un innovativo framework che combina una base di conoscenza esterna con modelli di linguaggio di grandi dimensioni (LLM). Questo passo aiuterà a comprendere meglio i dati e a trovare intuizioni più dettagliate. Successivamente, vedremo come utilizzare RAG con MyScale, rendendo il lavoro con i dati più interessante e produttivo.
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
query="Can you please suggest me some events related to basketball"
# Usa il metodo get_embedding definito in precedenza, accetta una lista di frasi
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}
"""
# Combina le descrizioni dei risultati principali.
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)
In tutto questo blog, abbiamo osservato che MyScale è molto più di un database vettoriale che può essere utilizzato per sviluppare ogni tipo di applicazione. Possiamo usarlo come un semplice database SQL o per applicazioni AI avanzate, coprendo la maggior parte del dominio dello sviluppo. Ci incoraggiamo a provarlo e ad esplorare le funzionalità avanzate iscrivendosi al livello gratuito e ottenendo 5 milioni di archiviazione vettoriale gratuita.
Conclusione
Abbiamo esplorato le capacità e le funzionalità di MyScale con Apify Scraper attraverso il processo di sviluppo di un’applicazione di analisi degli eventi. MyScale ha dimostrato le sue eccezionali capacità nella ricerca vettoriale ad alta prestazione pur mantenendo tutte le funzionalità dei database SQL, il che aiuta gli sviluppatori a effettuare ricerche semantiche utilizzando la sintassi SQL familiare con una velocità e precisione molto superiori.
Le capacità di MyScale non si limitano a questa applicazione: puoi adottarla per sviluppare qualsiasi applicazione AI utilizzando il metodo RAG.
Se hai feedback o suggerimenti, non esitare a contattarci.
Source:
https://dzone.com/articles/performing-advanced-facebook-event-data-analysis-w