Loren commited on
Commit
040fa4e
·
verified ·
1 Parent(s): ff865ff

Upload 5 files

Browse files
app/database.py CHANGED
@@ -1,61 +1,77 @@
1
- import sqlite3
2
- from typing import List, Dict
3
  import os
 
 
4
  from huggingface_hub import hf_hub_download
5
 
6
- # Télécharger le fichier SQLite depuis le dataset
7
- # Créer un dossier temporaire pour le cache
8
- # Répertoire writable dans le Space
9
  cache_dir = "/tmp"
10
  os.makedirs(cache_dir, exist_ok=True)
11
- REPO_ID = "Loren/articles_db" # dataset HF
12
- DB_NAME = 'articles.db'
13
- hf_token = os.environ["API_HF_TOKEN"]
14
- sqlite_path = hf_hub_download(
 
 
 
 
15
  repo_id=REPO_ID,
16
- filename=DB_NAME,
17
  repo_type="dataset",
18
- token=hf_token,
19
- cache_dir=cache_dir
20
- )
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- def get_connection(sqlite_path):
23
- conn = sqlite3.connect(sqlite_path)
24
- conn.row_factory = sqlite3.Row
25
- return conn
26
 
27
  def fetch_tags() -> List[str]:
28
- """Retourne tous les tags"""
29
- conn = get_connection()
30
- cur = conn.cursor()
31
- cur.execute("SELECT tag_name FROM tags ORDER BY tag_name")
32
- tags = [row["tag_name"] for row in cur.fetchall()]
33
- conn.close()
34
- return tags
35
 
 
 
 
 
 
 
36
 
37
  def fetch_articles_by_tags(tags: List[str]) -> List[Dict]:
38
  """
39
- Retourne les articles correspondant aux tags.
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  """
41
  if not tags:
42
  return []
43
 
44
- conn = get_connection()
45
- conn.row_factory = sqlite3.Row
46
- cur = conn.cursor()
47
-
48
- # Créer la liste de placeholders "?" dynamiquement
49
  placeholders = ",".join(["?"] * len(tags))
50
-
51
- query = ("""SELECT a.article_id, a.article_title, a.article_url
52
- FROM tags t, articles a, tag_article ta
53
- WHERE ta.tag_id = t.tag_id
54
  AND ta.article_id = a.article_id
55
- AND t.tag_name IN (""" + placeholders + """)"""
56
- )
57
-
58
- cur.execute(query, tags)
59
- results = [dict(row) for row in cur.fetchall()]
60
- conn.close()
61
- return results
 
 
 
1
  import os
2
+ from typing import List, Dict
3
+ import duckdb
4
  from huggingface_hub import hf_hub_download
5
 
6
+ # Initialisations
7
+ REPO_ID = "Loren/articles_db"
 
8
  cache_dir = "/tmp"
9
  os.makedirs(cache_dir, exist_ok=True)
10
+
11
+ # Téléchargement des fichiers Parquet depuis Hugging Face
12
+ articles_parquet = hf_hub_download(
13
+ repo_id=REPO_ID,
14
+ filename="articles.parquet",
15
+ repo_type="dataset",
16
+ cache_dir=cache_dir)
17
+ tags_parquet = hf_hub_download(
18
  repo_id=REPO_ID,
19
+ filename="tags.parquet",
20
  repo_type="dataset",
21
+ cache_dir=cache_dir)
22
+ tag_article_parquet = hf_hub_download(
23
+ repo_id=REPO_ID,
24
+ filename="tag_article.parquet",
25
+ repo_type="dataset",
26
+ cache_dir=cache_dir)
27
+
28
+ # Connexion DuckDB en mémoire
29
+ con = duckdb.connect()
30
+
31
+ # Créer des tables DuckDB directement à partir des fichiers Parquet
32
+ con.execute(f"CREATE VIEW articles AS SELECT * FROM parquet_scan('{articles_parquet}')")
33
+ con.execute(f"CREATE VIEW tags AS SELECT * FROM parquet_scan('{tags_parquet}')")
34
+ con.execute(f"CREATE VIEW tag_article AS SELECT * FROM parquet_scan('{tag_article_parquet}')")
35
 
36
+ # Fonctions d'accès aux données
 
 
 
37
 
38
  def fetch_tags() -> List[str]:
39
+ """
40
+ Récupère la liste de tous les tags disponibles dans la base de données.
 
 
 
 
 
41
 
42
+ Returns:
43
+ List[str]: Une liste de chaînes de caractères correspondant aux noms des tags, triés par ordre alphabétique.
44
+ """
45
+ query = "SELECT tag_name FROM tags ORDER BY tag_name"
46
+ result = con.execute(query).fetchall()
47
+ return [row[0] for row in result]
48
 
49
  def fetch_articles_by_tags(tags: List[str]) -> List[Dict]:
50
  """
51
+ Récupère les articles associés à un ou plusieurs tags.
52
+
53
+ Args:
54
+ tags (List[str]): Une liste de noms de tags pour filtrer les articles.
55
+
56
+ Returns:
57
+ List[Dict]: Une liste de dictionnaires, chacun représentant un article avec les clés:
58
+ - 'article_id': ID de l'article
59
+ - 'article_title': Titre de l'article
60
+ - 'article_url': URL de l'article
61
+
62
+ Notes:
63
+ - Si la liste `tags` est vide, la fonction retourne une liste vide.
64
+ - Les résultats incluent uniquement les articles correspondant à au moins un des tags fournis.
65
  """
66
  if not tags:
67
  return []
68
 
 
 
 
 
 
69
  placeholders = ",".join(["?"] * len(tags))
70
+ query = f"""SELECT distinct a.article_id, a.article_title, a.article_url
71
+ FROM tags t, tag_article ta, articles a
72
+ WHERE t.tag_id = ta.tag_id
 
73
  AND ta.article_id = a.article_id
74
+ AND t.tag_name IN ({placeholders})
75
+ """
76
+ result = con.execute(query, tags).fetchdf()
77
+ return result.to_dict(orient="records")
 
 
 
script/create_dataset.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ##############################################################################################
2
+ ### Script de création des fichiers Parquet compressés à partir de la base de données SQLite
3
+ ### et upload dans un nouveau dataset HF : Loren/articles_database
4
+ ### 👉 Peuvent alors être utilisés par un space Hugging Face
5
+ ##############################################################################################
6
+
7
+ import sqlite3
8
+ import pandas as pd
9
+ from pathlib import Path
10
+ from huggingface_hub import upload_file
11
+ import os
12
+ from dotenv import load_dotenv
13
+
14
+ # Initialisations
15
+ print("Initialisations ...")
16
+ load_dotenv()
17
+ HF_TOKEN = os.environ["API_HF_TOKEN"]
18
+ DATA_DIR = Path("../../Data") # dossier local contenant articles.db
19
+ SQLITE_FILE = DATA_DIR / "articles.db"
20
+ REPO_ID = "Loren/articles_database" # nouveau dataset HF
21
+
22
+ # Connexion SQLite
23
+ conn = sqlite3.connect(SQLITE_FILE)
24
+
25
+ # Extraction des tables et conversion en Parquet compressé
26
+ print("Création des fichiers Parquet compressés ...")
27
+ tables = ["articles", "tags", "tag_article"]
28
+ parquet_dir = DATA_DIR / "parquet_tables"
29
+ parquet_dir.mkdir(exist_ok=True)
30
+
31
+ parquet_files = []
32
+
33
+ for table in tables:
34
+ df = pd.read_sql_query(f"SELECT * FROM {table}", conn)
35
+ parquet_path = parquet_dir / f"{table}.parquet"
36
+ df.to_parquet(parquet_path, engine="pyarrow", index=False, compression="snappy")
37
+ parquet_files.append(parquet_path)
38
+
39
+ conn.close()
40
+
41
+ # Upload des fichiers Parquet vers HF
42
+ print("Upload des fichiers Parquet vers HF ...")
43
+ for parquet_file in parquet_files:
44
+ print(f"Uploading {parquet_file.name} ...")
45
+ upload_file(
46
+ path_or_fileobj=parquet_file,
47
+ path_in_repo=parquet_file.name,
48
+ repo_id=REPO_ID,
49
+ repo_type="dataset",
50
+ token=HF_TOKEN
51
+ )
52
+
53
+ print("Upload terminé ✅")
script/create_sqlite_db.py CHANGED
@@ -6,7 +6,7 @@
6
  ### df.to_parquet("medium_articles.parquet", engine="pyarrow", compression="snappy")
7
  ###
8
  ### Le fichier a été uploadé dans un dataset HF : Loren/articles_db
9
- ### Le script crée la base SQLite articles.db et l'upload dans le dataset
10
  ##############################################################################################
11
 
12
  import sqlite3
@@ -80,14 +80,10 @@ print("Extraction des tags en une liste unique ...")
80
  df['list_tags'] = df['tags'].apply(lambda x: ast.literal_eval(x) if isinstance(x, str) else [])
81
  # Extraire tous les tags uniques
82
  all_tags = list(set(itertools.chain.from_iterable(df['list_tags'])))
83
- # Exclusion de certains tags pour question de volume de la database (il faut= 1 Go)
84
- list_exclude = ['Politics', 'Startup', 'Covid 19', 'JavaScript', 'Business', 'Blockchain',
85
- 'Cryptocurrency', 'Bitcoin']
86
- list_tags = [t for t in all_tags if t not in list_exclude]
87
 
88
  # Insertion des tags dans la table
89
  print("Insertion des tags dans la table ...")
90
- cur.executemany("INSERT INTO tags (tag_name) VALUES (?)", [(tag,) for tag in list_tags])
91
 
92
  # Récupération des correspondances tag_name -> tag_id
93
  print("Récupération des correspondances tag_name -> tag_id ...")
@@ -108,23 +104,20 @@ for _, row in df.iterrows():
108
  except Exception:
109
  date_value = None
110
 
 
 
 
 
 
 
111
  # Association aux tags
112
- ind_ok = True
113
  for tag_name in row['list_tags']:
114
- try:
115
- tag_id = dict_tag_map[tag_name]
116
- cur.execute("INSERT INTO tag_article (article_id, tag_id) VALUES (?, ?)",
117
- (article_id, tag_id))
118
- except:
119
- ind_ok = False
120
-
121
- if ind_ok:
122
- # Insertion dans la table Articles
123
- cur.execute("""
124
- INSERT INTO articles (article_id, article_title, article_text, article_url, article_authors, article_date)
125
- VALUES (?, ?, ?, ?, ?, ?)""",
126
- (article_id, row["title"], row["text"], row["url"], row["authors"], date_value))
127
 
 
 
128
  conn.commit()
129
  conn.close()
130
 
 
6
  ### df.to_parquet("medium_articles.parquet", engine="pyarrow", compression="snappy")
7
  ###
8
  ### Le fichier a été uploadé dans un dataset HF : Loren/articles_db
9
+ ### Le script crée la base SQLite articles.db et l'upload dans le dataset HF
10
  ##############################################################################################
11
 
12
  import sqlite3
 
80
  df['list_tags'] = df['tags'].apply(lambda x: ast.literal_eval(x) if isinstance(x, str) else [])
81
  # Extraire tous les tags uniques
82
  all_tags = list(set(itertools.chain.from_iterable(df['list_tags'])))
 
 
 
 
83
 
84
  # Insertion des tags dans la table
85
  print("Insertion des tags dans la table ...")
86
+ cur.executemany("INSERT INTO tags (tag_name) VALUES (?)", [(tag,) for tag in all_tags])
87
 
88
  # Récupération des correspondances tag_name -> tag_id
89
  print("Récupération des correspondances tag_name -> tag_id ...")
 
104
  except Exception:
105
  date_value = None
106
 
107
+ # Insertion dans la table Articles
108
+ cur.execute("""
109
+ INSERT INTO articles (article_id, article_title, article_text, article_url, article_authors, article_date)
110
+ VALUES (?, ?, ?, ?, ?, ?)""",
111
+ (article_id, row["title"], row["text"], row["url"], row["authors"], date_value))
112
+
113
  # Association aux tags
 
114
  for tag_name in row['list_tags']:
115
+ tag_id = dict_tag_map[tag_name]
116
+ cur.execute("INSERT INTO tag_article (article_id, tag_id) VALUES (?, ?)",
117
+ (article_id, tag_id))
 
 
 
 
 
 
 
 
 
 
118
 
119
+ # Commit et fermeture de la connexion
120
+ print("Commit et fermeture de la connexion ...")
121
  conn.commit()
122
  conn.close()
123