Wyomike commited on
Commit
c1f0153
·
1 Parent(s): 273764c

Cleaned up some files

Browse files
database_maintenance/pruner_2.py CHANGED
@@ -1,5 +1,6 @@
1
  from tqdm import tqdm
2
  from supabase import create_client, Client
 
3
 
4
  # --- Configuration ---
5
  SECRETS_PATH = "secrets.json" # Adjust path if needed
 
1
  from tqdm import tqdm
2
  from supabase import create_client, Client
3
+ import os
4
 
5
  # --- Configuration ---
6
  SECRETS_PATH = "secrets.json" # Adjust path if needed
modelUpdating/bulkLabelByCentroid_2.py CHANGED
@@ -1,112 +1,3 @@
1
- # import chromadb
2
- # from bertopic import BERTopic
3
- # import numpy as np
4
- # import time
5
- # import os
6
- # import supabase
7
-
8
- # # --- CONFIGURATION ---
9
- # CHROMA_PATH = "/home/wyomike/topicBuzz/my_mastodon_db"
10
- # COLLECTION_NAME = "mastodon_posts"
11
- # MODEL_PATH = "my_mastodon_model_reduced" # Using the clean/reduced model
12
- # BATCH_SIZE = 2000 # Conservative batch size for read/write operations
13
-
14
- # # --- CONFIGURATION ---
15
- # SUPABASE_URL = os.environ.get("SUPABASE_URL") # Ensure these are in your .bashrc or .env
16
- # SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
17
- # LABELS_PATH = "topic_labels.json"
18
- # MODEL_FILE = "my_online_mastodon_model.pkl"
19
- # BUCKET = "topic_assets"
20
-
21
- # EMBEDDING_MODEL_NAME = "all-MiniLM-L6-v2"
22
-
23
- # def load_remote_model():
24
- # try:
25
- # print("☁️ Downloading model from Supabase Storage...")
26
- # with open(MODEL_FILE, 'wb') as f:
27
- # res = supabase.storage.from_(BUCKET).download(MODEL_FILE)
28
- # f.write(res)
29
- # return BERTopic.load(MODEL_FILE)
30
- # except Exception as e:
31
- # print(f"⚠️ Could not load remote model (first run?): {e}")
32
- # return None
33
-
34
- # # --- SETUP ---
35
- # print(f"Connecting to ChromaDB at {CHROMA_PATH}...")
36
- # client = chromadb.PersistentClient(path=CHROMA_PATH)
37
- # collection = client.get_collection(COLLECTION_NAME)
38
-
39
- # print(f"Loading BERTopic model from {MODEL_PATH}...")
40
- # topic_model = BERTopic.load(MODEL_PATH)
41
-
42
- # # Get total count to track progress
43
- # total_docs = collection.count()
44
- # print(f"Total documents to process: {total_docs}")
45
-
46
- # # --- MAIN LOOP ---
47
- # print("Starting bulk topic assignment...")
48
- # start_time = time.time()
49
-
50
- # for offset in range(0, total_docs, BATCH_SIZE):
51
- # try:
52
- # # 1. Fetch Batch (Include metadatas so we don't overwrite/lose existing ones!)
53
- # batch_data = collection.get(
54
- # limit=BATCH_SIZE,
55
- # offset=offset,
56
- # include=["documents", "embeddings", "metadatas"]
57
- # )
58
-
59
- # ids = batch_data['ids']
60
- # docs = batch_data['documents']
61
- # embeddings = batch_data['embeddings']
62
- # metadatas = batch_data['metadatas']
63
-
64
- # if not ids:
65
- # break
66
-
67
- # # 2. Predict Topics
68
- # # We pass embeddings to speed this up massively (skips re-calculating them)
69
- # # Note: We convert to numpy array as BERTopic expects it
70
- # topics, _ = topic_model.transform(docs, np.array(embeddings))
71
-
72
- # # 3. Prepare Metadata Updates
73
- # updated_metadatas = []
74
-
75
- # for i, topic_id in enumerate(topics):
76
- # # Get existing metadata or create empty dict if None
77
- # meta = metadatas[i] if metadatas[i] is not None else {}
78
-
79
- # # Add the new cluster ID
80
- # # We convert to int just to be safe for JSON serialization
81
- # meta['cluster_id'] = int(topic_id)
82
-
83
- # # OPTIONAL: Add the topic label string if you want it readable in DB
84
- # meta['cluster_label'] = topic_model.get_topic_info(topic_id).Name.values[0]
85
-
86
- # updated_metadatas.append(meta)
87
-
88
- # # 4. Update ChromaDB
89
- # # We ONLY update metadatas. Documents and embeddings remain untouched.
90
- # collection.update(
91
- # ids=ids,
92
- # metadatas=updated_metadatas
93
- # )
94
-
95
- # # Progress Log
96
- # processed_count = offset + len(ids)
97
- # percent = (processed_count / total_docs) * 100
98
- # elapsed = time.time() - start_time
99
- # print(f"[{percent:.1f}%] Processed {processed_count}/{total_docs} docs... (Time: {elapsed:.0f}s)")
100
-
101
- # except Exception as e:
102
- # print(f"❌ Error processing batch starting at offset {offset}: {e}")
103
- # # Optional: Decide if you want to 'continue' or 'break' here
104
- # # continue
105
-
106
- # print("✅ Done! All documents have been assigned a 'cluster_id'.")
107
-
108
-
109
-
110
  import os
111
  import time
112
  import numpy as np
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import time
3
  import numpy as np
modelUpdating/modelUpdater_1.py CHANGED
@@ -1,238 +1,3 @@
1
- # import os
2
- # import json
3
- # import shutil
4
- # import numpy as np
5
- # import datetime
6
- # from supabase import create_client, Client
7
- # from bertopic import BERTopic
8
- # from sentence_transformers import SentenceTransformer
9
- # from sklearn.cluster import MiniBatchKMeans
10
- # from sklearn.decomposition import IncrementalPCA
11
- # from bertopic.vectorizers import OnlineCountVectorizer
12
- # import gzip
13
-
14
- # # --- CONFIGURATION ---
15
- # SUPABASE_URL = os.environ.get("SUPABASE_URL") # Ensure these are in your .bashrc or .env
16
- # SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
17
-
18
- # # MODEL_PATH = "my_online_mastodon_model.pkl"
19
- # LABELS_PATH = "topic_labels.json"
20
- # STATE_FILE = "training_state.json" # Tracks the last timestamp we processed
21
-
22
- # MODEL_FILE = "my_online_mastodon_model.pkl"
23
- # COMPRESSED_FILE = "my_online_mastodon_model.pkl.gz" # New filename for cloud
24
- # BUCKET = "topic_assets"
25
-
26
- # # IMPORTANT: This MUST match the model used to create your original embeddings!
27
- # EMBEDDING_MODEL_NAME = "all-MiniLM-L6-v2"
28
-
29
-
30
- # def load_remote_model():
31
- # # Check if we already have the raw model
32
- # if os.path.exists(MODEL_FILE):
33
- # return BERTopic.load(MODEL_FILE)
34
-
35
- # print(f"☁️ Downloading {COMPRESSED_FILE} from Supabase...")
36
- # try:
37
- # # 1. Download the compressed file
38
- # with open(COMPRESSED_FILE, 'wb') as f:
39
- # res = supabase.storage.from_(BUCKET).download(COMPRESSED_FILE)
40
- # f.write(res)
41
-
42
- # # 2. Decompress it
43
- # print(" -> Decompressing...")
44
- # with gzip.open(COMPRESSED_FILE, 'rb') as f_in:
45
- # with open(MODEL_FILE, 'wb') as f_out:
46
- # shutil.copyfileobj(f_in, f_out)
47
-
48
- # # 3. Load the raw model
49
- # return BERTopic.load(MODEL_FILE)
50
-
51
- # except Exception as e:
52
- # print(f"⚠️ Could not load remote model: {e}")
53
- # return None
54
-
55
- # def save_remote_model(model):
56
- # print("💾 Saving and compressing model...")
57
- # # 1. Save locally as raw pickle
58
- # model.save(MODEL_FILE, serialization="pickle")
59
-
60
- # # 2. Compress it (Raw 95MB -> Compressed ~30MB)
61
- # with open(MODEL_FILE, 'rb') as f_in:
62
- # with gzip.open(COMPRESSED_FILE, 'wb') as f_out:
63
- # shutil.copyfileobj(f_in, f_out)
64
-
65
- # # 3. Upload the COMPRESSED file
66
- # print(f"☁️ Uploading {COMPRESSED_FILE} to Supabase...")
67
- # with open(COMPRESSED_FILE, 'rb') as f:
68
- # supabase.storage.from_(BUCKET).upload(
69
- # path=COMPRESSED_FILE,
70
- # file=f,
71
- # file_options={"x-upsert": "true"}
72
- # )
73
-
74
- # # Clean up local files to save space
75
- # if os.path.exists(MODEL_FILE): os.remove(MODEL_FILE)
76
- # if os.path.exists(COMPRESSED_FILE): os.remove(COMPRESSED_FILE)
77
-
78
-
79
- # # --- 1. Setup Connections ---
80
- # if not SUPABASE_URL or not SUPABASE_KEY:
81
- # raise ValueError("Missing Supabase credentials in environment variables.")
82
-
83
- # supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
84
- # embedding_model = SentenceTransformer(EMBEDDING_MODEL_NAME)
85
-
86
- # # --- 2. Load State (Incremental Logic) ---
87
- # last_processed_ts = 0
88
- # if os.path.exists(STATE_FILE):
89
- # with open(STATE_FILE, 'r') as f:
90
- # state = json.load(f)
91
- # last_processed_ts = state.get('last_timestamp', 0)
92
-
93
- # print(f"📅 Looking for posts newer than timestamp: {last_processed_ts}")
94
-
95
-
96
- # print("📥 Checking for previous state in cloud...")
97
- # last_processed_ts = 0
98
-
99
- # try:
100
- # # Try to download state file from Supabase
101
- # with open(STATE_FILE, 'wb') as f:
102
- # res = supabase.storage.from_(BUCKET).download(STATE_FILE)
103
- # f.write(res)
104
-
105
- # # If successful, read it
106
- # with open(STATE_FILE, 'r') as f:
107
- # state = json.load(f)
108
- # last_processed_ts = state.get('last_timestamp', 0)
109
- # print(f" -> Resuming from timestamp: {last_processed_ts}")
110
-
111
- # except Exception as e:
112
- # print(f" -> No remote state found (or error: {e}). Starting from 0.")
113
- # last_processed_ts = 0
114
-
115
-
116
- # # --- 3. Load or Initialize BERTopic ---
117
- # # if os.path.exists(MODEL_PATH):
118
- # print(f"🔄 Loading existing model from supabase...")
119
- # topic_model = load_remote_model()
120
- # if topic_model is None:
121
- # print("✨ Creating NEW model structure...")
122
- # umap_model = IncrementalPCA(n_components=5)
123
- # cluster_model = MiniBatchKMeans(n_clusters=200, random_state=42)
124
- # vectorizer_model = OnlineCountVectorizer(stop_words="english", min_df=10)
125
-
126
- # topic_model = BERTopic(
127
- # embedding_model=None, # We pass embeddings manually
128
- # umap_model=umap_model,
129
- # hdbscan_model=cluster_model,
130
- # vectorizer_model=vectorizer_model
131
- # )
132
-
133
- # # --- 4. Fetch Data from Supabase ---
134
- # BATCH_SIZE = 1000
135
- # total_processed = 0
136
- # new_max_ts = last_processed_ts
137
-
138
- # while True:
139
- # # Fetch batch of new posts
140
- # # We select 'content' and 'post_timestamp'. Adjust column names if yours differ.
141
- # try:
142
- # response = supabase.table("posts") \
143
- # .select("content, post_timestamp") \
144
- # .gt("post_timestamp", last_processed_ts) \
145
- # .order("post_timestamp", desc=False) \
146
- # .limit(BATCH_SIZE) \
147
- # .execute()
148
-
149
- # posts = response.data
150
- # except Exception as e:
151
- # print(f"❌ Supabase Error: {e}")
152
- # break
153
-
154
- # if not posts:
155
- # print("✅ No more new data to process.")
156
- # break
157
-
158
- # # Extract text and update timestamp tracker
159
- # batch_docs = [p['content'] for p in posts if p['content']]
160
- # batch_timestamps = [p['post_timestamp'] for p in posts]
161
-
162
- # if not batch_docs:
163
- # continue
164
-
165
- # # Update our cursor for the next batch
166
- # current_batch_max = max(batch_timestamps)
167
- # last_processed_ts = current_batch_max
168
- # new_max_ts = max(new_max_ts, current_batch_max)
169
-
170
- # print(f"🧠 Generating embeddings for {len(batch_docs)} posts...")
171
-
172
- # # Generate Embeddings locally
173
- # embeddings = embedding_model.encode(batch_docs, show_progress_bar=False)
174
-
175
- # # Train the Model
176
- # topic_model.partial_fit(batch_docs, np.array(embeddings).astype(np.float64))
177
-
178
- # total_processed += len(batch_docs)
179
- # print(f" -> Processed batch. Total new: {total_processed}")
180
-
181
- # if total_processed > 0:
182
- # print(f"💾 Saving updated assets to Supabase (Bucket: {BUCKET})...")
183
-
184
- # # ---------------------------
185
- # # A. Regenerate Labels Map
186
- # # ---------------------------
187
- # labels_map = {}
188
- # info_df = topic_model.get_topic_info()
189
- # for index, row in info_df.iterrows():
190
- # topic_id = row['Topic']
191
- # # Handle outlier topic -1 (JSON keys must be strings)
192
- # if topic_id == -1:
193
- # labels_map[f"Topic_{topic_id}"] = "Outliers"
194
- # else:
195
- # labels_map[f"Topic_{topic_id}"] = row['Name']
196
-
197
- # # ---------------------------
198
- # # B. Upload All Artifacts
199
- # # ---------------------------
200
-
201
- # # 1. Upload Model (using the helper function defined earlier)
202
- # save_remote_model(topic_model)
203
-
204
- # # 2. Upload Labels
205
- # print(" -> Uploading labels...")
206
- # with open(LABELS_PATH, "w") as f:
207
- # json.dump(labels_map, f)
208
-
209
- # with open(LABELS_PATH, "rb") as f:
210
- # supabase.storage.from_(BUCKET).upload(
211
- # LABELS_PATH,
212
- # f,
213
- # file_options={"x-upsert": "true"}
214
- # )
215
-
216
- # # 3. Upload State (Crucial for Hugging Face!)
217
- # # We must save the new timestamp to the cloud, or the bot will forget it processed these posts.
218
- # print(f" -> Updating state to timestamp {new_max_ts}...")
219
- # state_data = {"last_timestamp": new_max_ts}
220
-
221
- # with open(STATE_FILE, "w") as f:
222
- # json.dump(state_data, f)
223
-
224
- # with open(STATE_FILE, "rb") as f:
225
- # supabase.storage.from_(BUCKET).upload(
226
- # STATE_FILE,
227
- # f,
228
- # file_options={"x-upsert": "true"}
229
- # )
230
-
231
- # print(f"✅ Success! Trained on {total_processed} new posts and synced to cloud.")
232
-
233
- # else:
234
- # print("💤 No new data found. Model untouched.")
235
-
236
  import os
237
  import json
238
  import shutil
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import json
3
  import shutil
modelUpdating/naturalLanguageTopics_3.py CHANGED
@@ -1,145 +1,3 @@
1
- # import google.genai as genai
2
- # from bertopic import BERTopic
3
- # import json
4
- # import os
5
- # import time
6
- # from tqdm import tqdm
7
-
8
- # NSFW_KEYWORDS = {
9
- # "nsfw", "porn", "nude", "naked", "sex", "18+", "xxx",
10
- # "cum", "dick", "pussy", "hentai", "erotic", "onlyfans",
11
- # "boobs", "tits", "cock", "slut", "whore", "bitch", "incest",
12
- # "lewd", "horny", "sensual", "fetish", "bondage"
13
- # }
14
-
15
- # def get_safe_topic_ids(model, nsfw_set):
16
- # """
17
- # Returns a list of Topic IDs that do NOT contain any blocklisted words
18
- # in their top 10 keywords.
19
- # """
20
- # safe_ids = []
21
- # unsafe_ids = []
22
-
23
- # # get_topics() returns a dictionary: {topic_id: [(word, score), ...]}
24
- # all_topics = model.get_topics()
25
-
26
- # print(f"Scanning {len(all_topics)} topics for NSFW content...")
27
-
28
- # for topic_id, words_with_scores in all_topics.items():
29
- # # Topic -1 is outliers. We usually keep it, but check its content too.
30
-
31
- # # Extract just the words from the tuples
32
- # topic_words = {word for word, score in words_with_scores}
33
-
34
- # # Check for intersection
35
- # # If the intersection is NOT empty, it contains a bad word
36
- # intersection = topic_words.intersection(nsfw_set)
37
-
38
- # if intersection:
39
- # print(f" [BLOCKED] Topic {topic_id}")
40
- # unsafe_ids.append(topic_id)
41
- # else:
42
- # safe_ids.append(topic_id)
43
-
44
- # print(f"\nResult: {len(safe_ids)} Safe, {len(unsafe_ids)} Unsafe.")
45
- # return safe_ids
46
-
47
- # # --- CONFIGURATION ---
48
- # MODEL_PATH = "my_mastodon_model_reduced"
49
- # OUTPUT_JSON = "topic_labels.json"
50
- # API_KEY = json.load(open("config.json"))["googleKey"] # Replace or set env var
51
-
52
- # # --- SETUP ---
53
- # client = genai.Client(api_key=API_KEY)
54
- # # model = client.models.get() # Fast and cheap
55
-
56
- # def generate_labels():
57
- # if not os.path.exists(MODEL_PATH):
58
- # print("Model not found!")
59
- # return
60
-
61
- # print("Loading BERTopic model...")
62
- # topic_model = BERTopic.load(MODEL_PATH)
63
-
64
- # # Get the master table of topic info
65
- # info = topic_model.get_topic_info()
66
- # print(f"Found {len(info)} topics.")
67
- # safe_topics = get_safe_topic_ids(topic_model, nsfw_set=NSFW_KEYWORDS)
68
-
69
- # # Dictionary to map "Topic_5" -> "Nature Photography"
70
- # labels_map = {}
71
-
72
- # print("Asking Gemini to label topics...")
73
-
74
- # for index, row in tqdm(info.iterrows(), total=len(info)):
75
- # if row['Topic'] not in safe_topics:
76
- # labels_map[f"Topic_{row['Topic']}"] = "NSFW" # TODO - check if this is actually the bag of words
77
- # continue
78
- # topic_id = row['Topic']
79
-
80
- # # Handle Outliers
81
- # if topic_id == 0:
82
- # labels_map[f"Topic_{topic_id}"] = "Outliers / Noise"
83
- # continue
84
-
85
- # # 1. Get Bag of Words
86
- # # row['Representation'] is a list of keywords like ['cat', 'meow', 'feline']
87
- # keywords = row['Representation']
88
-
89
- # # 2. Get Representative Docs
90
- # # row['Representative_Docs'] is a list of actual posts
91
- # docs = row['Representative_Docs']
92
-
93
- # # 3. Construct Prompt
94
- # # We take top 10 keywords and top 3 docs to save tokens
95
- # prompt = f"""
96
- # I have a cluster of social media posts from Mastodon.
97
-
98
- # Keywords: {', '.join(keywords[:10])}
99
-
100
- # Representative Posts:
101
- # {chr(10).join([f"- {d[:300]}..." for d in docs[:3]])}
102
-
103
- # Based on this, provide a short, specific, natural language label (max 5 words) for this topic.
104
- # Do not use quotes. Just the label.
105
- # """
106
-
107
- # try:
108
- # # 4. Call Gemini
109
- # response = client.models.generate_content(
110
- # model='gemini-2.5-flash',
111
- # contents=prompt
112
- # )
113
- # label = response.text.strip()
114
-
115
- # # 5. Store result
116
- # labels_map[f"Topic_{topic_id}"] = label
117
-
118
- # # Sleep briefly to respect rate limits if needed
119
- # time.sleep(1.0)
120
-
121
- # except Exception as e:
122
- # print(f"Error labeling Topic {topic_id}: {e}")
123
- # labels_map[f"Topic_{topic_id}"] = f"Topic {topic_id}"
124
-
125
- # # Save to JSON
126
- # with open("topic_labels.json", "w") as f:
127
- # json.dump(labels_map, f)
128
-
129
- # with open("topic_labels.json", "rb") as f:
130
- # supabase.storage.from_("topic_assets").upload(
131
- # "topic_labels.json",
132
- # f,
133
- # file_options={"x-upsert": "true"}
134
- # )
135
- # print("☁️ Labels uploaded to cloud.")
136
-
137
- # print(f"Success! Labels saved to {OUTPUT_JSON}")
138
-
139
- # if __name__ == "__main__":
140
- # generate_labels()
141
-
142
-
143
  import os
144
  import json
145
  import time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import json
3
  import time
pages/TopicWeb.py CHANGED
@@ -1,6 +1,3 @@
1
-
2
-
3
-
4
  import streamlit as st
5
  import networkx as nx
6
  import pickle
 
 
 
 
1
  import streamlit as st
2
  import networkx as nx
3
  import pickle