Paolo De Gasperis commited on
Commit
46b2f94
·
verified ·
1 Parent(s): 5ea5453

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +123 -120
app.py CHANGED
@@ -1,120 +1,123 @@
1
- import json
2
- import numpy as np
3
- import gradio as gr
4
- import logging
5
- from openai import OpenAI
6
- from tenacity import retry, wait_random_exponential, stop_after_attempt
7
- import os
8
-
9
- client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
10
-
11
-
12
- # Configurazione del logging per errori
13
- logging.basicConfig(filename="error.log", level=logging.ERROR,
14
- format='%(asctime)s - %(levelname)s - %(message)s')
15
-
16
- # Funzione per ottenere l'embedding da OpenAI con la nuova sintassi
17
- @retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6))
18
- def get_embedding(text, model="text-embedding-3-small"):
19
- if not isinstance(text, str) or not text.strip():
20
- raise ValueError("Il testo di input deve essere una stringa non vuota.")
21
- text = text.replace("\n", " ")
22
- response = client.embeddings.create(input=[text], model=model)
23
- return response.data[0].embedding
24
-
25
- # Funzione per calcolare la similarità coseno
26
- def cosine_similarity(vec_a, vec_b):
27
- dot_product = np.dot(vec_a, vec_b)
28
- norm_a = np.linalg.norm(vec_a)
29
- norm_b = np.linalg.norm(vec_b)
30
- if norm_a == 0 or norm_b == 0:
31
- return 0.0
32
- return dot_product / (norm_a * norm_b)
33
-
34
- # Funzione per caricare gli embeddings dal file JSON
35
- def load_embeddings(file_path):
36
- try:
37
- with open(file_path, 'r', encoding='utf-8') as file:
38
- data = json.load(file)
39
- return data
40
- except UnicodeDecodeError as e:
41
- logging.error(f"Errore di codifica nel caricamento del file JSON: {e}")
42
- return f"Errore: {e}"
43
- except json.JSONDecodeError as e:
44
- logging.error(f"Errore di parsing JSON: {e}")
45
- return f"Errore: {e}"
46
- except Exception as e:
47
- logging.error(f"Errore generico nel caricamento del file JSON: {e}")
48
- return f"Errore: {e}"
49
-
50
- # Funzione per trovare gli articoli simili a partire da una frase chiave
51
- def find_similar_articles_from_query(query, embeddings_data):
52
- try:
53
- query_embedding = get_embedding(query)
54
- except Exception as e:
55
- error_message = f"Errore nel calcolo dell'embedding per la query: {e}"
56
- logging.error(error_message)
57
- return None, None, error_message
58
-
59
- similarities = []
60
- # Calcola la similarità tra l'embedding della query e ciascun articolo
61
- for article in embeddings_data:
62
- try:
63
- similarity = cosine_similarity(query_embedding, article['embedding'])
64
- except Exception as e:
65
- logging.error(f"Errore nel calcolo della similarità per l'articolo {article.get('titolo_articolo', 'Sconosciuto')}: {e}")
66
- similarity = 0.0
67
- # Costruzione del link per il download del PDF
68
- pdf_url = f"https://storiadellarterivista.it/data/pdf/{article['testo_pdf']}"
69
- pdf_link = f'<a href="{pdf_url}" download>{article["testo_pdf"]}</a>'
70
- similarities.append({
71
- "titolo_articolo": article['titolo_articolo'],
72
- "similarity": similarity,
73
- "pdf_link": pdf_link
74
- })
75
-
76
- # Ordina gli articoli in ordine decrescente per similarità
77
- similarities_sorted = sorted(similarities, key=lambda x: x['similarity'], reverse=True)
78
- top_5 = similarities_sorted[:5]
79
- # Ordina in ordine crescente per ottenere i 5 articoli con minore similarità
80
- bottom_5 = sorted(similarities, key=lambda x: x['similarity'])[:5]
81
- return top_5, bottom_5, None
82
-
83
- # Funzione per generare una tabella HTML a partire da una lista di articoli
84
- def generate_html_table(articles, title):
85
- html = f"<h3>{title}</h3>"
86
- html += '<table border="1" style="border-collapse: collapse; width:100%;">'
87
- html += "<tr><th>Titolo Articolo</th><th>Similarità</th><th>PDF</th></tr>"
88
- for art in articles:
89
- html += f"<tr><td>{art['titolo_articolo']}</td><td>{art['similarity']:.3f}</td><td>{art['pdf_link']}</td></tr>"
90
- html += "</table>"
91
- return html
92
-
93
- # Funzione principale chiamata dall'interfaccia GRADIO
94
- def search_articles(query):
95
- top_5, bottom_5, error = find_similar_articles_from_query(query, embeddings_data)
96
- if error:
97
- return error, error
98
- top_table = generate_html_table(top_5, "Top 5 Articoli più simili")
99
- bottom_table = generate_html_table(bottom_5, "Bottom 5 Articoli meno simili")
100
- return top_table, bottom_table
101
-
102
- # Caricamento degli embeddings dal file JSON
103
- file_path = 'embedded_articles.json' # Percorso del file JSON contenente gli embeddings
104
- embeddings_data = load_embeddings(file_path)
105
-
106
- # Controllo di eventuali errori nel caricamento degli embeddings
107
- if isinstance(embeddings_data, str):
108
- logging.error(embeddings_data)
109
- print(embeddings_data)
110
- else:
111
- iface = gr.Interface(
112
- fn=search_articles,
113
- inputs=gr.Textbox(label="Inserisci una frase chiave", placeholder="Scrivi qui la tua frase di ricerca..."),
114
- outputs=[gr.HTML(label="Articoli più simili"), gr.HTML(label="Articoli meno simili")],
115
- title="Ricerca Articoli Simili da Frase Chiave",
116
- description=("Inserisci una frase chiave per trovare gli articoli semanticamente simili. "
117
- "Vengono mostrati i 5 articoli con maggiore similarità e i 5 con minore similarità, "
118
- "con il coefficiente di similarità e un link per il download del PDF.")
119
- )
120
- iface.launch(share=True)
 
 
 
 
1
+ import json
2
+ import numpy as np
3
+ import gradio as gr
4
+ import logging
5
+ from openai import OpenAI
6
+ from tenacity import retry, wait_random_exponential, stop_after_attempt
7
+ import os
8
+
9
+ # Recupero della chiave API dalla variabile d'ambiente "api"
10
+ api_key = os.environ.get("api")
11
+ if not api_key:
12
+ raise ValueError("La variabile d'ambiente 'api' non è stata impostata. Verifica la configurazione dei secrets.")
13
+ client = OpenAI(api_key=api_key)
14
+
15
+ # Configurazione del logging per errori
16
+ logging.basicConfig(filename="error.log", level=logging.ERROR,
17
+ format='%(asctime)s - %(levelname)s - %(message)s')
18
+
19
+ # Funzione per ottenere l'embedding da OpenAI con la nuova sintassi
20
+ @retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6))
21
+ def get_embedding(text, model="text-embedding-3-small"):
22
+ if not isinstance(text, str) or not text.strip():
23
+ raise ValueError("Il testo di input deve essere una stringa non vuota.")
24
+ text = text.replace("\n", " ")
25
+ response = client.embeddings.create(input=[text], model=model)
26
+ return response.data[0].embedding
27
+
28
+ # Funzione per calcolare la similarità coseno
29
+ def cosine_similarity(vec_a, vec_b):
30
+ dot_product = np.dot(vec_a, vec_b)
31
+ norm_a = np.linalg.norm(vec_a)
32
+ norm_b = np.linalg.norm(vec_b)
33
+ if norm_a == 0 or norm_b == 0:
34
+ return 0.0
35
+ return dot_product / (norm_a * norm_b)
36
+
37
+ # Funzione per caricare gli embeddings dal file JSON
38
+ def load_embeddings(file_path):
39
+ try:
40
+ with open(file_path, 'r', encoding='utf-8') as file:
41
+ data = json.load(file)
42
+ return data
43
+ except UnicodeDecodeError as e:
44
+ logging.error(f"Errore di codifica nel caricamento del file JSON: {e}")
45
+ return f"Errore: {e}"
46
+ except json.JSONDecodeError as e:
47
+ logging.error(f"Errore di parsing JSON: {e}")
48
+ return f"Errore: {e}"
49
+ except Exception as e:
50
+ logging.error(f"Errore generico nel caricamento del file JSON: {e}")
51
+ return f"Errore: {e}"
52
+
53
+ # Funzione per trovare gli articoli simili a partire da una frase chiave
54
+ def find_similar_articles_from_query(query, embeddings_data):
55
+ try:
56
+ query_embedding = get_embedding(query)
57
+ except Exception as e:
58
+ error_message = f"Errore nel calcolo dell'embedding per la query: {e}"
59
+ logging.error(error_message)
60
+ return None, None, error_message
61
+
62
+ similarities = []
63
+ # Calcola la similarità tra l'embedding della query e ciascun articolo
64
+ for article in embeddings_data:
65
+ try:
66
+ similarity = cosine_similarity(query_embedding, article['embedding'])
67
+ except Exception as e:
68
+ logging.error(f"Errore nel calcolo della similarità per l'articolo {article.get('titolo_articolo', 'Sconosciuto')}: {e}")
69
+ similarity = 0.0
70
+ # Costruzione del link per il download del PDF
71
+ pdf_url = f"https://storiadellarterivista.it/data/pdf/{article['testo_pdf']}"
72
+ pdf_link = f'<a href="{pdf_url}" download>{article["testo_pdf"]}</a>'
73
+ similarities.append({
74
+ "titolo_articolo": article['titolo_articolo'],
75
+ "similarity": similarity,
76
+ "pdf_link": pdf_link
77
+ })
78
+
79
+ # Ordina gli articoli in ordine decrescente per similarità
80
+ similarities_sorted = sorted(similarities, key=lambda x: x['similarity'], reverse=True)
81
+ top_5 = similarities_sorted[:5]
82
+ # Ordina in ordine crescente per ottenere i 5 articoli con minore similarità
83
+ bottom_5 = sorted(similarities, key=lambda x: x['similarity'])[:5]
84
+ return top_5, bottom_5, None
85
+
86
+ # Funzione per generare una tabella HTML a partire da una lista di articoli
87
+ def generate_html_table(articles, title):
88
+ html = f"<h3>{title}</h3>"
89
+ html += '<table border="1" style="border-collapse: collapse; width:100%;">'
90
+ html += "<tr><th>Titolo Articolo</th><th>Similarità</th><th>PDF</th></tr>"
91
+ for art in articles:
92
+ html += f"<tr><td>{art['titolo_articolo']}</td><td>{art['similarity']:.3f}</td><td>{art['pdf_link']}</td></tr>"
93
+ html += "</table>"
94
+ return html
95
+
96
+ # Funzione principale chiamata dall'interfaccia GRADIO
97
+ def search_articles(query):
98
+ top_5, bottom_5, error = find_similar_articles_from_query(query, embeddings_data)
99
+ if error:
100
+ return error, error
101
+ top_table = generate_html_table(top_5, "Top 5 Articoli più simili")
102
+ bottom_table = generate_html_table(bottom_5, "Bottom 5 Articoli meno simili")
103
+ return top_table, bottom_table
104
+
105
+ # Caricamento degli embeddings dal file JSON
106
+ file_path = 'embedded_articles.json' # Percorso del file JSON contenente gli embeddings
107
+ embeddings_data = load_embeddings(file_path)
108
+
109
+ # Controllo di eventuali errori nel caricamento degli embeddings
110
+ if isinstance(embeddings_data, str):
111
+ logging.error(embeddings_data)
112
+ print(embeddings_data)
113
+ else:
114
+ iface = gr.Interface(
115
+ fn=search_articles,
116
+ inputs=gr.Textbox(label="Inserisci una frase chiave", placeholder="Scrivi qui la tua frase di ricerca..."),
117
+ outputs=[gr.HTML(label="Articoli più simili"), gr.HTML(label="Articoli meno simili")],
118
+ title="Ricerca Articoli Simili da Frase Chiave",
119
+ description=("Inserisci una frase chiave per trovare gli articoli semanticamente simili. "
120
+ "Vengono mostrati i 5 articoli con maggiore similarità e i 5 con minore similarità, "
121
+ "con il coefficiente di similarità e un link per il download del PDF.")
122
+ )
123
+ iface.launch(share=True)