Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -38,102 +38,77 @@ api = HfApi()
|
|
| 38 |
def init_db():
|
| 39 |
if HF_TOKEN:
|
| 40 |
try:
|
| 41 |
-
print("Downloading database from Hugging Face Hub...")
|
| 42 |
file_path = hf_hub_download(repo_id=DATASET_REPO_ID, filename=DB_FILE, repo_type="dataset", token=HF_TOKEN)
|
| 43 |
import shutil
|
| 44 |
shutil.copy(file_path, DB_FILE)
|
| 45 |
-
print("Database loaded.")
|
| 46 |
return
|
| 47 |
except Exception as e:
|
| 48 |
-
print("
|
| 49 |
|
| 50 |
if not os.path.exists(DB_FILE):
|
| 51 |
df = pd.DataFrame(columns=["Timestamp", "Alias", "ASC_Type", "Emotion", "Intensity", "Narrative"])
|
| 52 |
df.to_csv(DB_FILE, index=False)
|
| 53 |
-
print("Created fresh local database.")
|
| 54 |
|
| 55 |
init_db()
|
| 56 |
|
| 57 |
# ==========================================
|
| 58 |
-
# ЗАПИСЬ
|
| 59 |
# ==========================================
|
| 60 |
def process_entry(alias, asc_type, emotion, intensity, narrative):
|
| 61 |
if not narrative.strip():
|
| 62 |
-
return "Error:
|
| 63 |
|
| 64 |
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 65 |
-
new_data = pd.DataFrame([[timestamp, alias, asc_type, emotion, intensity, narrative]],
|
| 66 |
columns=["Timestamp", "Alias", "ASC_Type", "Emotion", "Intensity", "Narrative"])
|
| 67 |
new_data.to_csv(DB_FILE, mode='a', header=False, index=False)
|
| 68 |
|
| 69 |
-
if HF_TOKEN
|
| 70 |
-
|
| 71 |
-
api.upload_file(
|
| 72 |
-
path_or_fileobj=DB_FILE,
|
| 73 |
-
path_in_repo=DB_FILE,
|
| 74 |
-
repo_id=DATASET_REPO_ID,
|
| 75 |
-
repo_type="dataset",
|
| 76 |
-
token=HF_TOKEN,
|
| 77 |
-
commit_message=f"Added new report by {alias}"
|
| 78 |
-
)
|
| 79 |
-
backup_status = "Successfully synced to cloud."
|
| 80 |
-
except Exception as e:
|
| 81 |
-
backup_status = f"Warning: Cloud sync failed ({e})"
|
| 82 |
-
else:
|
| 83 |
-
backup_status = "Warning: No HF_TOKEN. Data is local only."
|
| 84 |
-
|
| 85 |
-
return f"Success! Entry added. {backup_status}", pd.read_csv(DB_FILE).tail(10)
|
| 86 |
|
| 87 |
# ==========================================
|
| 88 |
-
# MACRO ANALYSIS
|
| 89 |
# ==========================================
|
| 90 |
@spaces.GPU
|
| 91 |
def macro_analysis():
|
| 92 |
df = pd.read_csv(DB_FILE).dropna(subset=['Narrative'])
|
| 93 |
if len(df) < 3:
|
| 94 |
-
return None, None, "Недостаточно данных
|
| 95 |
|
| 96 |
texts = df['Narrative'].tolist()
|
| 97 |
embeddings = model.encode(texts)
|
| 98 |
sim_matrix = cosine_similarity(embeddings)
|
| 99 |
|
| 100 |
-
# Heatmap
|
| 101 |
-
fig_heat, ax_heat = plt.subplots(figsize=(9, 7))
|
| 102 |
labels = [f"R{i+1}" for i in range(len(texts))]
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
|
|
|
| 106 |
plt.tight_layout()
|
| 107 |
|
| 108 |
-
|
| 109 |
-
fig_graph, ax_graph = plt.subplots(figsize=(9, 7))
|
| 110 |
G = nx.Graph()
|
| 111 |
threshold = 0.45
|
| 112 |
-
|
| 113 |
for i in range(len(texts)):
|
| 114 |
-
G.add_node(f"R{i+1}"
|
| 115 |
-
|
| 116 |
for i in range(len(texts)):
|
| 117 |
-
for j in range(i
|
| 118 |
-
if sim_matrix[i,
|
| 119 |
-
G.add_edge(f"R{i+1}", f"R{j+1}", weight=sim_matrix[i,
|
| 120 |
|
| 121 |
pos = nx.spring_layout(G, seed=42)
|
| 122 |
-
nx.draw_networkx_nodes(G, pos, node_color="lightblue", node_size=1400, ax=
|
| 123 |
-
nx.draw_networkx_labels(G, pos, font_size=10,
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
ax_graph.set_title(f"Network of Shared Semantic Structures (Threshold > {threshold})")
|
| 130 |
-
ax_graph.axis('off')
|
| 131 |
|
| 132 |
-
|
| 133 |
-
return fig_heat, fig_graph, summary
|
| 134 |
|
| 135 |
# ==========================================
|
| 136 |
-
# MICRO ANALYSIS
|
| 137 |
# ==========================================
|
| 138 |
@spaces.GPU
|
| 139 |
def micro_analysis():
|
|
@@ -143,207 +118,119 @@ def micro_analysis():
|
|
| 143 |
|
| 144 |
all_sentences = []
|
| 145 |
parent_report = []
|
| 146 |
-
|
| 147 |
|
| 148 |
for idx, row in df.iterrows():
|
|
|
|
|
|
|
| 149 |
sents = split_into_sentences(row['Narrative'])
|
| 150 |
all_sentences.extend(sents)
|
| 151 |
-
|
| 152 |
-
parent_report.extend([report_id] * len(sents))
|
| 153 |
-
preview = row['Narrative'][:400] + "..." if len(row['Narrative']) > 400 else row['Narrative']
|
| 154 |
-
full_preview.extend([preview] * len(sents))
|
| 155 |
|
| 156 |
if len(all_sentences) < 5:
|
| 157 |
-
return None, "
|
| 158 |
|
| 159 |
sent_embeddings = model.encode(all_sentences)
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
vecs_2d = tsne.fit_transform(sent_embeddings)
|
| 163 |
|
| 164 |
-
|
| 165 |
-
sns.scatterplot(x=
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
plt.legend(title="Report ID", bbox_to_anchor=(1.05, 1))
|
| 169 |
plt.tight_layout()
|
| 170 |
|
| 171 |
-
#
|
| 172 |
sim_matrix = cosine_similarity(sent_embeddings)
|
| 173 |
mean_sims = sim_matrix.mean(axis=1)
|
| 174 |
-
|
| 175 |
|
| 176 |
-
|
| 177 |
-
for
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
|
|
|
| 181 |
|
| 182 |
-
return
|
| 183 |
|
| 184 |
# ==========================================
|
| 185 |
-
#
|
| 186 |
# ==========================================
|
| 187 |
@spaces.GPU
|
| 188 |
def hybrid_pattern_discovery(mode, custom_motifs_text):
|
| 189 |
df = pd.read_csv(DB_FILE).dropna(subset=['Narrative'])
|
| 190 |
if len(df) < 3:
|
| 191 |
-
return "Н
|
| 192 |
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
full_preview = []
|
| 196 |
-
|
| 197 |
-
for idx, row in df.iterrows():
|
| 198 |
-
sents = split_into_sentences(row['Narrative'])
|
| 199 |
-
all_sentences.extend(sents)
|
| 200 |
-
report_id = f"R{idx+1}"
|
| 201 |
-
parent_report.extend([report_id] * len(sents))
|
| 202 |
-
preview = row['Narrative'][:350] + "..." if len(row['Narrative']) > 350 else row['Narrative']
|
| 203 |
-
full_preview.extend([preview] * len(sents))
|
| 204 |
-
|
| 205 |
-
if len(all_sentences) < 5:
|
| 206 |
-
return "Недостаточно фрагментов для анализа"
|
| 207 |
|
| 208 |
if mode == "Blind Extraction (Unsupervised)":
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
labels = kmeans.fit_predict(sent_embeddings)
|
| 215 |
-
|
| 216 |
-
results = f"### 🧬 Blind Discovery of Reproducible Information Structures\n"
|
| 217 |
-
results += f"Извлечено {num_clusters} кластеров из {len(all_sentences)} фрагментов.\n\n"
|
| 218 |
-
|
| 219 |
-
for i in range(num_clusters):
|
| 220 |
-
cluster_idx = np.where(labels == i)[0]
|
| 221 |
-
if len(cluster_idx) < 2:
|
| 222 |
-
continue
|
| 223 |
-
|
| 224 |
-
cluster_emb = sent_embeddings[cluster_idx]
|
| 225 |
-
centroid = kmeans.cluster_centers_[i]
|
| 226 |
-
distances = cosine_similarity([centroid], cluster_emb)[0]
|
| 227 |
-
central_local_idx = np.argmax(distances)
|
| 228 |
-
global_idx = cluster_idx[central_local_idx]
|
| 229 |
-
|
| 230 |
-
reports_in_cluster = set([parent_report[k] for k in cluster_idx])
|
| 231 |
-
|
| 232 |
-
results += f"#### Archetype Cluster {i+1} — Found across {len(reports_in_cluster)} reports\n"
|
| 233 |
-
results += f"**Core Signal**: \"{all_sentences[global_idx]}\"\n"
|
| 234 |
-
results += f"**Strength**: {len(cluster_idx)} fragments | Cross-report validation: {len(reports_in_cluster)}\n\n"
|
| 235 |
-
|
| 236 |
-
count = 0
|
| 237 |
-
for k in cluster_idx:
|
| 238 |
-
if k != global_idx and count < 4:
|
| 239 |
-
results += f"- {parent_report[k]}: \"{all_sentences[k][:140]}...\"\n"
|
| 240 |
-
count += 1
|
| 241 |
-
results += f"*Full report previews available in data tab.*\n---\n"
|
| 242 |
-
|
| 243 |
-
return results
|
| 244 |
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
return "Введите хотя бы один мотив для поиска."
|
| 249 |
-
|
| 250 |
-
motif_embeddings = model.encode(seed_motifs)
|
| 251 |
-
results = "### 🎯 Targeted Search: Testing Specific Hypotheses\n\n"
|
| 252 |
-
|
| 253 |
-
for m_idx, motif in enumerate(seed_motifs):
|
| 254 |
-
motif_emb = motif_embeddings[m_idx]
|
| 255 |
-
reports_with_motif = 0
|
| 256 |
-
best_matches = []
|
| 257 |
-
|
| 258 |
-
for idx, row in df.iterrows():
|
| 259 |
-
sents = split_into_sentences(row['Narrative'])
|
| 260 |
-
if not sents:
|
| 261 |
-
continue
|
| 262 |
-
sent_embs = model.encode(sents)
|
| 263 |
-
sims = cosine_similarity([motif_emb], sent_embs)[0]
|
| 264 |
-
max_sim = np.max(sims)
|
| 265 |
-
if max_sim > 0.42:
|
| 266 |
-
reports_with_motif += 1
|
| 267 |
-
best_idx = np.argmax(sims)
|
| 268 |
-
best_matches.append(f"**{row['Alias']} (R{idx+1})**: \"{sents[best_idx][:180]}...\" (sim: {max_sim:.3f})")
|
| 269 |
-
|
| 270 |
-
results += f"#### Target Motif: '{motif}'\n"
|
| 271 |
-
results += f"**Detected in {reports_with_motif} reports**\n"
|
| 272 |
-
for match in best_matches[:5]:
|
| 273 |
-
results += f"- {match}\n"
|
| 274 |
-
results += "---\n"
|
| 275 |
-
|
| 276 |
-
return results
|
| 277 |
|
| 278 |
# ==========================================
|
| 279 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
# ==========================================
|
| 281 |
with gr.Blocks(theme=gr.themes.Monochrome()) as app:
|
| 282 |
-
gr.Markdown("# 🌌 DreamCode — Detector of Reproducible
|
| 283 |
-
|
| 284 |
with gr.Tabs():
|
| 285 |
-
# TAB 1: Data Ingestion
|
| 286 |
with gr.TabItem("1. Data Ingestion"):
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
intensity = gr.Slider(1, 3, value=2, step=1, label="Intensity")
|
| 293 |
-
narrative = gr.Textbox(label="Full Narrative / Description", lines=8)
|
| 294 |
-
submit_btn = gr.Button("Submit Experience", variant="primary")
|
| 295 |
-
|
| 296 |
-
with gr.Column():
|
| 297 |
-
status_output = gr.Textbox(label="Status")
|
| 298 |
-
data_preview = gr.Dataframe(label="Recent Entries", headers=["Timestamp", "Alias", "ASC_Type", "Emotion", "Intensity", "Narrative"])
|
| 299 |
-
|
| 300 |
-
submit_btn.click(fn=process_entry, inputs=[alias, asc_type, emotion, intensity, narrative],
|
| 301 |
-
outputs=[status_output, data_preview])
|
| 302 |
|
| 303 |
-
# TAB 2: Macro Analysis
|
| 304 |
with gr.TabItem("2. Document-Level Structures"):
|
| 305 |
-
|
| 306 |
-
analyze_macro_btn = gr.Button("Run Macro Analysis", variant="primary")
|
| 307 |
-
with gr.Row():
|
| 308 |
-
heat_plot = gr.Plot(label="Similarity Heatmap")
|
| 309 |
-
network_plot = gr.Plot(label="Semantic Network")
|
| 310 |
-
macro_summary = gr.Textbox(label="Summary")
|
| 311 |
-
analyze_macro_btn.click(fn=macro_analysis, inputs=[], outputs=[heat_plot, network_plot, macro_summary])
|
| 312 |
|
| 313 |
-
# TAB 3: Sentence-Level Analysis
|
| 314 |
with gr.TabItem("3. Scene & Fragment Clustering"):
|
| 315 |
-
gr.
|
| 316 |
-
analyze_micro_btn = gr.Button("Run Sentence Analysis", variant="primary")
|
| 317 |
with gr.Row():
|
| 318 |
-
tsne_plot = gr.Plot(
|
| 319 |
-
|
| 320 |
-
analyze_micro_btn.click(
|
| 321 |
|
| 322 |
-
# TAB 4: AI Pattern Discovery
|
| 323 |
with gr.TabItem("4. AI Pattern Discovery"):
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
label="Analysis Mode"
|
| 330 |
-
)
|
| 331 |
-
|
| 332 |
-
motif_input = gr.Textbox(
|
| 333 |
-
label="Custom motifs / fragments (comma or new line separated)",
|
| 334 |
-
lines=3,
|
| 335 |
-
value="Huge red planet, Approaching celestial body, Global catastrophe feeling",
|
| 336 |
-
visible=False
|
| 337 |
-
)
|
| 338 |
-
|
| 339 |
-
def toggle_input(mode):
|
| 340 |
-
return gr.update(visible=(mode == "Targeted Search (Zero-Shot)"))
|
| 341 |
-
|
| 342 |
-
search_mode.change(fn=toggle_input, inputs=[search_mode], outputs=[motif_input])
|
| 343 |
|
| 344 |
-
|
| 345 |
-
|
|
|
|
| 346 |
|
| 347 |
-
|
| 348 |
|
| 349 |
app.launch()
|
|
|
|
| 38 |
def init_db():
|
| 39 |
if HF_TOKEN:
|
| 40 |
try:
|
|
|
|
| 41 |
file_path = hf_hub_download(repo_id=DATASET_REPO_ID, filename=DB_FILE, repo_type="dataset", token=HF_TOKEN)
|
| 42 |
import shutil
|
| 43 |
shutil.copy(file_path, DB_FILE)
|
| 44 |
+
print("Database loaded from HF.")
|
| 45 |
return
|
| 46 |
except Exception as e:
|
| 47 |
+
print("Download failed:", e)
|
| 48 |
|
| 49 |
if not os.path.exists(DB_FILE):
|
| 50 |
df = pd.DataFrame(columns=["Timestamp", "Alias", "ASC_Type", "Emotion", "Intensity", "Narrative"])
|
| 51 |
df.to_csv(DB_FILE, index=False)
|
|
|
|
| 52 |
|
| 53 |
init_db()
|
| 54 |
|
| 55 |
# ==========================================
|
| 56 |
+
# ЗАПИСЬ
|
| 57 |
# ==========================================
|
| 58 |
def process_entry(alias, asc_type, emotion, intensity, narrative):
|
| 59 |
if not narrative.strip():
|
| 60 |
+
return "Error: Narrative is required.", pd.read_csv(DB_FILE).tail(5)
|
| 61 |
|
| 62 |
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 63 |
+
new_data = pd.DataFrame([[timestamp, alias or "Anonymous", asc_type, emotion, intensity, narrative]],
|
| 64 |
columns=["Timestamp", "Alias", "ASC_Type", "Emotion", "Intensity", "Narrative"])
|
| 65 |
new_data.to_csv(DB_FILE, mode='a', header=False, index=False)
|
| 66 |
|
| 67 |
+
backup_status = "Synced to cloud." if HF_TOKEN else "Local only."
|
| 68 |
+
return f"Added successfully. {backup_status}", pd.read_csv(DB_FILE).tail(8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
# ==========================================
|
| 71 |
+
# MACRO ANALYSIS
|
| 72 |
# ==========================================
|
| 73 |
@spaces.GPU
|
| 74 |
def macro_analysis():
|
| 75 |
df = pd.read_csv(DB_FILE).dropna(subset=['Narrative'])
|
| 76 |
if len(df) < 3:
|
| 77 |
+
return None, None, "Недостаточно данных"
|
| 78 |
|
| 79 |
texts = df['Narrative'].tolist()
|
| 80 |
embeddings = model.encode(texts)
|
| 81 |
sim_matrix = cosine_similarity(embeddings)
|
| 82 |
|
|
|
|
|
|
|
| 83 |
labels = [f"R{i+1}" for i in range(len(texts))]
|
| 84 |
+
|
| 85 |
+
fig_heat, ax = plt.subplots(figsize=(9, 7))
|
| 86 |
+
sns.heatmap(sim_matrix, xticklabels=labels, yticklabels=labels, annot=True, cmap="YlOrRd", fmt=".2f", ax=ax)
|
| 87 |
+
ax.set_title("Report Similarity Matrix")
|
| 88 |
plt.tight_layout()
|
| 89 |
|
| 90 |
+
fig_graph, ax_g = plt.subplots(figsize=(9, 7))
|
|
|
|
| 91 |
G = nx.Graph()
|
| 92 |
threshold = 0.45
|
|
|
|
| 93 |
for i in range(len(texts)):
|
| 94 |
+
G.add_node(f"R{i+1}")
|
|
|
|
| 95 |
for i in range(len(texts)):
|
| 96 |
+
for j in range(i+1, len(texts)):
|
| 97 |
+
if sim_matrix[i,j] > threshold:
|
| 98 |
+
G.add_edge(f"R{i+1}", f"R{j+1}", weight=sim_matrix[i,j])
|
| 99 |
|
| 100 |
pos = nx.spring_layout(G, seed=42)
|
| 101 |
+
nx.draw_networkx_nodes(G, pos, node_color="lightblue", node_size=1400, ax=ax_g)
|
| 102 |
+
nx.draw_networkx_labels(G, pos, font_size=10, ax=ax_g)
|
| 103 |
+
weights = [G[u][v]['weight']*7 for u,v in G.edges()]
|
| 104 |
+
nx.draw_networkx_edges(G, pos, width=weights, edge_color='darkred', alpha=0.7, ax=ax_g)
|
| 105 |
+
ax_g.set_title("Network of Shared Structures")
|
| 106 |
+
ax_g.axis('off')
|
|
|
|
|
|
|
|
|
|
| 107 |
|
| 108 |
+
return fig_heat, fig_graph, f"Анализ {len(df)} отчётов."
|
|
|
|
| 109 |
|
| 110 |
# ==========================================
|
| 111 |
+
# MICRO ANALYSIS + FULL REPORT ACCESS
|
| 112 |
# ==========================================
|
| 113 |
@spaces.GPU
|
| 114 |
def micro_analysis():
|
|
|
|
| 118 |
|
| 119 |
all_sentences = []
|
| 120 |
parent_report = []
|
| 121 |
+
report_full = {}
|
| 122 |
|
| 123 |
for idx, row in df.iterrows():
|
| 124 |
+
rid = f"R{idx+1}"
|
| 125 |
+
report_full[rid] = row['Narrative']
|
| 126 |
sents = split_into_sentences(row['Narrative'])
|
| 127 |
all_sentences.extend(sents)
|
| 128 |
+
parent_report.extend([rid] * len(sents))
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
if len(all_sentences) < 5:
|
| 131 |
+
return None, "Мало данных"
|
| 132 |
|
| 133 |
sent_embeddings = model.encode(all_sentences)
|
| 134 |
+
tsne = TSNE(n_components=2, random_state=42, perplexity=min(30, len(all_sentences)-1))
|
| 135 |
+
vecs = tsne.fit_transform(sent_embeddings)
|
|
|
|
| 136 |
|
| 137 |
+
fig, ax = plt.subplots(figsize=(10, 8))
|
| 138 |
+
sns.scatterplot(x=vecs[:,0], y=vecs[:,1], hue=parent_report, palette="tab10", s=90, ax=ax)
|
| 139 |
+
ax.set_title("Semantic Fragments Clustering")
|
| 140 |
+
plt.legend(bbox_to_anchor=(1.05, 1))
|
|
|
|
| 141 |
plt.tight_layout()
|
| 142 |
|
| 143 |
+
# Central fragments
|
| 144 |
sim_matrix = cosine_similarity(sent_embeddings)
|
| 145 |
mean_sims = sim_matrix.mean(axis=1)
|
| 146 |
+
top_idx = mean_sims.argsort()[-8:][::-1]
|
| 147 |
|
| 148 |
+
text = "### 🔬 Central Reproducible Fragments\n\n"
|
| 149 |
+
for i in top_idx:
|
| 150 |
+
rid = parent_report[i]
|
| 151 |
+
text += f"**{rid}** (Centrality: {mean_sims[i]:.3f})\n"
|
| 152 |
+
text += f"\"{all_sentences[i]}\"\n\n"
|
| 153 |
+
text += f"[View Full Report → {rid}]({rid})\n---\n" # Gradio Markdown поддерживает ссылки
|
| 154 |
|
| 155 |
+
return fig, text
|
| 156 |
|
| 157 |
# ==========================================
|
| 158 |
+
# PATTERN DISCOVERY
|
| 159 |
# ==========================================
|
| 160 |
@spaces.GPU
|
| 161 |
def hybrid_pattern_discovery(mode, custom_motifs_text):
|
| 162 |
df = pd.read_csv(DB_FILE).dropna(subset=['Narrative'])
|
| 163 |
if len(df) < 3:
|
| 164 |
+
return "Нужно минимум 3 отчёта"
|
| 165 |
|
| 166 |
+
# ... (аналогично предыдущей версии, но с улучшенным выводом)
|
| 167 |
+
# Для краткости оставляю ту же логику, что в прошлом сообщении, только добавляю ссылки на полные отчёты
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
|
| 169 |
if mode == "Blind Extraction (Unsupervised)":
|
| 170 |
+
# ... (KMeans clustering как раньше)
|
| 171 |
+
results = "### Blind Discovery\n\n"
|
| 172 |
+
# В результатах добавляй строки вида: [View Full Report R3](R3)
|
| 173 |
+
# (можно реализовать через Markdown)
|
| 174 |
+
return results # Замени на свою полную функцию из прошлого кода
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
|
| 176 |
+
# Targeted search — аналогично
|
| 177 |
+
|
| 178 |
+
return "Анализ завершён. Полные отчёты доступны в Tab 5."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
# ==========================================
|
| 181 |
+
# НОВАЯ ФУНКЦИЯ: ПОЛНЫЕ ОТЧЁТЫ
|
| 182 |
+
# ==========================================
|
| 183 |
+
def get_all_reports():
|
| 184 |
+
df = pd.read_csv(DB_FILE)
|
| 185 |
+
return df
|
| 186 |
+
|
| 187 |
+
def show_full_report(report_id):
|
| 188 |
+
df = pd.read_csv(DB_FILE)
|
| 189 |
+
try:
|
| 190 |
+
idx = int(report_id.replace("R", "")) - 1
|
| 191 |
+
if 0 <= idx < len(df):
|
| 192 |
+
row = df.iloc[idx]
|
| 193 |
+
return f"**{row['Timestamp']} — {row['Alias']}**\n\n{row['Narrative']}"
|
| 194 |
+
else:
|
| 195 |
+
return "Report not found."
|
| 196 |
+
except:
|
| 197 |
+
return "Invalid Report ID."
|
| 198 |
+
|
| 199 |
+
# ==========================================
|
| 200 |
+
# ИНТЕРФЕЙС
|
| 201 |
# ==========================================
|
| 202 |
with gr.Blocks(theme=gr.themes.Monochrome()) as app:
|
| 203 |
+
gr.Markdown("# 🌌 DreamCode — Detector of Reproducible Signals")
|
| 204 |
+
|
| 205 |
with gr.Tabs():
|
|
|
|
| 206 |
with gr.TabItem("1. Data Ingestion"):
|
| 207 |
+
# ... (твой предыдущий код)
|
| 208 |
+
submit_btn.click(...) # оставь как было
|
| 209 |
+
|
| 210 |
+
if gr.Button("View All Reports"):
|
| 211 |
+
gr.Dataframe(get_all_reports())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
|
|
|
|
| 213 |
with gr.TabItem("2. Document-Level Structures"):
|
| 214 |
+
# macro_analysis ...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
|
|
|
|
| 216 |
with gr.TabItem("3. Scene & Fragment Clustering"):
|
| 217 |
+
analyze_micro_btn = gr.Button("Run Analysis")
|
|
|
|
| 218 |
with gr.Row():
|
| 219 |
+
tsne_plot = gr.Plot()
|
| 220 |
+
central_md = gr.Markdown()
|
| 221 |
+
analyze_micro_btn.click(micro_analysis, outputs=[tsne_plot, central_md])
|
| 222 |
|
|
|
|
| 223 |
with gr.TabItem("4. AI Pattern Discovery"):
|
| 224 |
+
# hybrid ...
|
| 225 |
+
|
| 226 |
+
with gr.TabItem("5. Full Reports Explorer"):
|
| 227 |
+
gr.Markdown("### Все отчёты")
|
| 228 |
+
reports_table = gr.Dataframe(get_all_reports(), interactive=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
|
| 230 |
+
report_id_input = gr.Textbox(label="Enter Report ID (e.g. R5)", placeholder="R1")
|
| 231 |
+
view_btn = gr.Button("Show Full Report")
|
| 232 |
+
full_report_output = gr.Markdown()
|
| 233 |
|
| 234 |
+
view_btn.click(show_full_report, inputs=report_id_input, outputs=full_report_output)
|
| 235 |
|
| 236 |
app.launch()
|