SimilarMistral / app.py
Paolo De Gasperis
Rename sa-similar-url-mistral.py to app.py
6c6f691 verified
import json
import numpy as np
import gradio as gr
import logging
# Configurazione del logging per errori
logging.basicConfig(filename="error.log", level=logging.ERROR,
format='%(asctime)s - %(levelname)s - %(message)s')
# Funzione per calcolare la similarità coseno
def cosine_similarity(vec_a, vec_b):
dot_product = np.dot(vec_a, vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
return dot_product / (norm_a * norm_b)
# Funzione per caricare gli embeddings dal file JSON
def load_embeddings(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as file:
data = json.load(file)
return data
except UnicodeDecodeError as e:
logging.error(f"Errore di codifica nel caricamento del file JSON: {e}")
return f"Errore: {e}"
except json.JSONDecodeError as e:
logging.error(f"Errore di parsing JSON: {e}")
return f"Errore: {e}"
except Exception as e:
logging.error(f"Errore generico nel caricamento del file JSON: {e}")
return f"Errore: {e}"
# Funzione per trovare gli articoli simili
def find_similar_articles(input_title, embeddings_data):
input_embedding = None
# Trova l'embedding dell'articolo di riferimento
for article in embeddings_data:
if article['titolo_articolo'] == input_title:
input_embedding = article['embedding']
break
if input_embedding is None:
error_message = f"Articolo '{input_title}' non trovato."
logging.error(error_message)
return None, None, error_message
similarities = []
# Calcola la similarità per ogni articolo (diverso dall'articolo di riferimento)
for article in embeddings_data:
if article['titolo_articolo'] != input_title:
try:
similarity = cosine_similarity(input_embedding, article['embedding'])
except Exception as e:
logging.error(f"Errore nel calcolo della similarità per l'articolo {article['titolo_articolo']}: {e}")
similarity = 0.0
# Costruzione del link per il download del PDF
pdf_url = f"https://storiadellarterivista.it/data/pdf/{article['testo_pdf']}"
pdf_link = f'<a href="{pdf_url}" download>{article["testo_pdf"]}</a>'
similarities.append({
"titolo_articolo": article['titolo_articolo'],
"similarity": similarity,
"pdf_link": pdf_link
})
# Ordina gli articoli in ordine decrescente per similarità
similarities_sorted = sorted(similarities, key=lambda x: x['similarity'], reverse=True)
top_5 = similarities_sorted[:5]
# Ordina in ordine crescente per ottenere i 5 articoli con minore similarità
bottom_5 = sorted(similarities, key=lambda x: x['similarity'])[:5]
return top_5, bottom_5, None
# Funzione per generare una tabella HTML a partire da una lista di articoli
def generate_html_table(articles, title):
html = f"<h3>{title}</h3>"
html += '<table border="1" style="border-collapse: collapse; width:100%;">'
html += "<tr><th>Titolo Articolo</th><th>Similarità</th><th>PDF</th></tr>"
for art in articles:
html += f"<tr><td>{art['titolo_articolo']}</td><td>{art['similarity']:.3f}</td><td>{art['pdf_link']}</td></tr>"
html += "</table>"
return html
# Funzione principale chiamata dall'interfaccia GRADIO
def search_articles(input_title):
top_5, bottom_5, error = find_similar_articles(input_title, embeddings_data)
if error:
return error, error
top_table = generate_html_table(top_5, "Top 5 Articoli più simili")
bottom_table = generate_html_table(bottom_5, "Bottom 5 Articoli meno simili")
return top_table, bottom_table
# Funzione per ottenere l'elenco dei titoli (per l'autocompletamento)
def get_titles(embeddings_data):
return [article['titolo_articolo'] for article in embeddings_data]
# Caricamento degli embeddings
file_path = 'all_embeddings.json' # Percorso del file JSON contenente gli embeddings
embeddings_data = load_embeddings(file_path)
# Controllo di eventuali errori nel caricamento
if isinstance(embeddings_data, str):
logging.error(embeddings_data)
print(embeddings_data)
else:
title_choices = get_titles(embeddings_data)
iface = gr.Interface(
fn=search_articles,
inputs=gr.Dropdown(label="Titolo dell'articolo", choices=title_choices, type="value"),
outputs=[gr.HTML(label="Articoli più simili"), gr.HTML(label="Articoli meno simili")],
title="Ricerca Articoli Simili",
description=("Seleziona il titolo di un articolo per trovare quelli semanticamente simili. "
"Vengono mostrati i 5 articoli con maggiore similarità e i 5 con minore similarità, "
"con il coefficiente di similarità e un link per il download del PDF.")
)
iface.launch(share=True)