Spaces:
Sleeping
Sleeping
Commit
ยท
41387a4
1
Parent(s):
71fa3d9
app
Browse files- .gitignore +3 -0
- app-webshell.py +114 -0
- app.py +279 -101
.gitignore
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
venv-xor-tanakh2
|
2 |
+
__pycache__
|
3 |
+
.gradio
|
app-webshell.py
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# app.py
|
2 |
+
|
3 |
+
import gradio as gr
|
4 |
+
import subprocess
|
5 |
+
|
6 |
+
# --- SICHERHEITSHINWEIS ---
|
7 |
+
# Diese Webshell fรผhrt beliebigen Code auf dem Server aus.
|
8 |
+
# Machen Sie diesen Space NICHT รถffentlich, es sei denn, Sie verstehen die Risiken.
|
9 |
+
# Jeder, der Zugriff auf diesen Space hat, kann Befehle ausfรผhren.
|
10 |
+
# Am besten nur fรผr private oder organisatorische Spaces verwenden.
|
11 |
+
# -------------------------
|
12 |
+
|
13 |
+
WARNING_MESSAGE = """
|
14 |
+
โ ๏ธ **SICHERHEITSWARNUNG** โ ๏ธ
|
15 |
+
|
16 |
+
Dies ist eine funktionierende Web-Shell. Jeder Befehl, den Sie hier eingeben,
|
17 |
+
wird direkt auf dem Server des Hugging Face Space ausgefรผhrt.
|
18 |
+
|
19 |
+
- **Machen Sie diesen Space nicht รถffentlich!** Fremde kรถnnten ihn missbrauchen, um den Container zu beschรคdigen, Angriffe zu starten oder Ihre Daten (falls vorhanden) zu kompromittieren.
|
20 |
+
- Nutzen Sie diesen Space nur fรผr private Zwecke oder innerhalb Ihrer Organisation.
|
21 |
+
- Seien Sie vorsichtig mit den Befehlen, die Sie ausfรผhren (z. B. `rm -rf /`).
|
22 |
+
"""
|
23 |
+
|
24 |
+
def execute_command(command):
|
25 |
+
"""
|
26 |
+
Fรผhrt einen Shell-Befehl sicher aus und gibt stdout und stderr zurรผck.
|
27 |
+
"""
|
28 |
+
if not command:
|
29 |
+
return "Bitte geben Sie einen Befehl ein.", ""
|
30 |
+
|
31 |
+
try:
|
32 |
+
# Fรผhre den Befehl aus.
|
33 |
+
# shell=True ist notwendig, um eine "echte" Shell-Umgebung zu haben
|
34 |
+
# (z.B. fรผr Pipes | oder cd), aber es ist auch ein Sicherheitsrisiko.
|
35 |
+
# Deswegen die groรe Warnung oben!
|
36 |
+
process = subprocess.run(
|
37 |
+
command,
|
38 |
+
shell=True,
|
39 |
+
capture_output=True,
|
40 |
+
text=True,
|
41 |
+
timeout=600 # Timeout von 60 Sekunden, um Endlos-Prozesse zu verhindern
|
42 |
+
)
|
43 |
+
|
44 |
+
# Kombiniere Standardausgabe und Standardfehler fรผr die Anzeige
|
45 |
+
stdout = process.stdout
|
46 |
+
stderr = process.stderr
|
47 |
+
|
48 |
+
# Gib eine informative Nachricht zurรผck, wenn kein Output kam
|
49 |
+
if not stdout and not stderr:
|
50 |
+
return "Befehl ausgefรผhrt, keine Ausgabe.", ""
|
51 |
+
|
52 |
+
return stdout, stderr
|
53 |
+
|
54 |
+
except subprocess.TimeoutExpired:
|
55 |
+
return "", "Fehler: Der Befehl hat das Zeitlimit von 60 Sekunden รผberschritten."
|
56 |
+
except Exception as e:
|
57 |
+
return "", f"Ein unerwarteter Fehler ist aufgetreten: {str(e)}"
|
58 |
+
|
59 |
+
# Wir definieren das Gradio Interface
|
60 |
+
with gr.Blocks(theme=gr.themes.Monochrome(), css=".gradio-container {background-color: #1a1a1a;}") as demo:
|
61 |
+
gr.Markdown(f"# ๐ Python Web-Shell fรผr Hugging Face Spaces")
|
62 |
+
gr.Markdown(WARNING_MESSAGE)
|
63 |
+
|
64 |
+
with gr.Row():
|
65 |
+
command_input = gr.Textbox(
|
66 |
+
label="Shell-Befehl eingeben",
|
67 |
+
placeholder="z.B. ls -l, whoami, pwd, pip list"
|
68 |
+
)
|
69 |
+
|
70 |
+
execute_button = gr.Button("๐ Ausfรผhren")
|
71 |
+
|
72 |
+
with gr.Row():
|
73 |
+
with gr.Column(scale=2):
|
74 |
+
gr.Markdown("### โ
Standardausgabe (stdout)")
|
75 |
+
# KORREKTUR: Der Parameter `language="bash"` wurde entfernt.
|
76 |
+
output_stdout = gr.Code(label="stdout", interactive=False)
|
77 |
+
|
78 |
+
with gr.Column(scale=1):
|
79 |
+
gr.Markdown("### โ Standardfehler (stderr)")
|
80 |
+
# KORREKTUR: Der Parameter `language="bash"` wurde entfernt.
|
81 |
+
output_stderr = gr.Code(label="stderr", interactive=False)
|
82 |
+
|
83 |
+
# Verknรผpfe die Button-Klicks und die Eingabe mit der Funktion
|
84 |
+
execute_button.click(
|
85 |
+
fn=execute_command,
|
86 |
+
inputs=command_input,
|
87 |
+
outputs=[output_stdout, output_stderr]
|
88 |
+
)
|
89 |
+
command_input.submit(
|
90 |
+
fn=execute_command,
|
91 |
+
inputs=command_input,
|
92 |
+
outputs=[output_stdout, output_stderr]
|
93 |
+
)
|
94 |
+
|
95 |
+
gr.Markdown("---")
|
96 |
+
gr.Markdown("### Nรผtzliche Beispielbefehle:")
|
97 |
+
gr.Examples(
|
98 |
+
examples=[
|
99 |
+
"ls -la",
|
100 |
+
"pwd",
|
101 |
+
"whoami",
|
102 |
+
"env",
|
103 |
+
"pip list",
|
104 |
+
"df -h",
|
105 |
+
"cat /proc/cpuinfo",
|
106 |
+
"uname -a"
|
107 |
+
],
|
108 |
+
inputs=command_input
|
109 |
+
)
|
110 |
+
|
111 |
+
|
112 |
+
# Starte die App
|
113 |
+
if __name__ == "__main__":
|
114 |
+
demo.launch()
|
app.py
CHANGED
@@ -1,114 +1,292 @@
|
|
1 |
-
# app.py
|
2 |
-
|
3 |
import gradio as gr
|
4 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
-
# ---
|
7 |
-
#
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
# -------------------------
|
12 |
|
13 |
-
|
14 |
-
โ ๏ธ **SICHERHEITSWARNUNG** โ ๏ธ
|
15 |
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
"""
|
28 |
-
if
|
29 |
-
return "
|
|
|
|
|
|
|
30 |
|
31 |
try:
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
# Deswegen die groรe Warnung oben!
|
36 |
-
process = subprocess.run(
|
37 |
-
command,
|
38 |
-
shell=True,
|
39 |
-
capture_output=True,
|
40 |
-
text=True,
|
41 |
-
timeout=600 # Timeout von 60 Sekunden, um Endlos-Prozesse zu verhindern
|
42 |
-
)
|
43 |
-
|
44 |
-
# Kombiniere Standardausgabe und Standardfehler fรผr die Anzeige
|
45 |
-
stdout = process.stdout
|
46 |
-
stderr = process.stderr
|
47 |
-
|
48 |
-
# Gib eine informative Nachricht zurรผck, wenn kein Output kam
|
49 |
-
if not stdout and not stderr:
|
50 |
-
return "Befehl ausgefรผhrt, keine Ausgabe.", ""
|
51 |
-
|
52 |
-
return stdout, stderr
|
53 |
-
|
54 |
-
except subprocess.TimeoutExpired:
|
55 |
-
return "", "Fehler: Der Befehl hat das Zeitlimit von 60 Sekunden รผberschritten."
|
56 |
except Exception as e:
|
57 |
-
return
|
58 |
-
|
59 |
-
# Wir definieren das Gradio Interface
|
60 |
-
with gr.Blocks(theme=gr.themes.Monochrome(), css=".gradio-container {background-color: #1a1a1a;}") as demo:
|
61 |
-
gr.Markdown(f"# ๐ Python Web-Shell fรผr Hugging Face Spaces")
|
62 |
-
gr.Markdown(WARNING_MESSAGE)
|
63 |
-
|
64 |
-
with gr.Row():
|
65 |
-
command_input = gr.Textbox(
|
66 |
-
label="Shell-Befehl eingeben",
|
67 |
-
placeholder="z.B. ls -l, whoami, pwd, pip list"
|
68 |
-
)
|
69 |
-
|
70 |
-
execute_button = gr.Button("๐ Ausfรผhren")
|
71 |
-
|
72 |
-
with gr.Row():
|
73 |
-
with gr.Column(scale=2):
|
74 |
-
gr.Markdown("### โ
Standardausgabe (stdout)")
|
75 |
-
# KORREKTUR: Der Parameter `language="bash"` wurde entfernt.
|
76 |
-
output_stdout = gr.Code(label="stdout", interactive=False)
|
77 |
-
|
78 |
-
with gr.Column(scale=1):
|
79 |
-
gr.Markdown("### โ Standardfehler (stderr)")
|
80 |
-
# KORREKTUR: Der Parameter `language="bash"` wurde entfernt.
|
81 |
-
output_stderr = gr.Code(label="stderr", interactive=False)
|
82 |
-
|
83 |
-
# Verknรผpfe die Button-Klicks und die Eingabe mit der Funktion
|
84 |
-
execute_button.click(
|
85 |
-
fn=execute_command,
|
86 |
-
inputs=command_input,
|
87 |
-
outputs=[output_stdout, output_stderr]
|
88 |
-
)
|
89 |
-
command_input.submit(
|
90 |
-
fn=execute_command,
|
91 |
-
inputs=command_input,
|
92 |
-
outputs=[output_stdout, output_stderr]
|
93 |
-
)
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
"
|
102 |
-
"
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
|
112 |
-
# Starte die App
|
113 |
if __name__ == "__main__":
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
+
import json
|
3 |
+
import logging
|
4 |
+
import argparse
|
5 |
+
import sys
|
6 |
+
import os
|
7 |
+
import math
|
8 |
+
import pickle
|
9 |
+
from deep_translator import GoogleTranslator
|
10 |
+
from gematria import calculate_gematria
|
11 |
+
from collections import defaultdict
|
12 |
+
from typing import Dict, List, Any, Optional
|
13 |
|
14 |
+
# --- Configuration ---
|
15 |
+
# Logging is kept for file-based or production logging, but we'll use print() for immediate console debug
|
16 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
17 |
+
BOOK_RANGE = range(1, 40)
|
18 |
+
CACHE_FILE = "tanakh_phrasedict.cache"
|
|
|
19 |
|
20 |
+
# --- Core Logic Functions ---
|
|
|
21 |
|
22 |
+
def get_power_result(total_sum: int, query_value: int) -> int:
|
23 |
+
"""Calculates the power or root result."""
|
24 |
+
if total_sum <= 0 or query_value <= 1:
|
25 |
+
return 1
|
26 |
+
if query_value <= total_sum:
|
27 |
+
try:
|
28 |
+
exponent = int(math.floor(math.log(total_sum, query_value)))
|
29 |
+
return query_value ** exponent
|
30 |
+
except (ValueError, OverflowError):
|
31 |
+
return 1
|
32 |
+
else:
|
33 |
+
for n in range(2, 65):
|
34 |
+
try:
|
35 |
+
root_result = query_value ** (1.0 / n)
|
36 |
+
if root_result <= total_sum:
|
37 |
+
return math.ceil(root_result)
|
38 |
+
except (ValueError, OverflowError):
|
39 |
+
return 1
|
40 |
+
return 1
|
41 |
|
42 |
+
def find_all_matching_phrases(target_sum: int, phrase_dictionary: Dict[int, List[Dict]]) -> List[Dict]:
|
43 |
+
"""Finds all phrases matching a target Gematria."""
|
44 |
+
return phrase_dictionary.get(int(target_sum), [])
|
45 |
+
|
46 |
+
# --- Global State: Load dictionary once at startup ---
|
47 |
+
try:
|
48 |
+
if not os.path.exists(CACHE_FILE):
|
49 |
+
raise FileNotFoundError(f"ERROR: Cache file '{CACHE_FILE}' not found. Please run 'build_indices.py' first.")
|
50 |
+
logging.info(f"Loading phrase dictionary from cache: {CACHE_FILE}")
|
51 |
+
with open(CACHE_FILE, 'rb') as f:
|
52 |
+
phrase_dictionary: Optional[Dict[int, List[Dict]]] = pickle.load(f)
|
53 |
+
logging.info("Phrase dictionary loaded successfully for the Gradio app.")
|
54 |
+
except (FileNotFoundError, IOError, pickle.UnpicklingError) as e:
|
55 |
+
logging.error(str(e))
|
56 |
+
phrase_dictionary = None
|
57 |
|
58 |
+
# --- Main Analysis Function for Gradio ---
|
59 |
+
|
60 |
+
def run_analysis(query: str, translate: bool, process_verses: int, results_per_verse: int, xor_depth: int, progress=gr.Progress(track_tqdm=True)):
|
61 |
+
"""The main analysis function called by the Gradio interface."""
|
62 |
+
if phrase_dictionary is None:
|
63 |
+
return "## Fatal Error\nCould not start analysis. The phrase dictionary cache file (`tanakh_phrasedict.cache`) is missing or corrupt. Please run `build_indices.py` and restart the app."
|
64 |
+
|
65 |
+
print("\n--- NEW ANALYSIS RUN ---") # Console Debug
|
66 |
+
output_lines = []
|
67 |
|
68 |
try:
|
69 |
+
query_value = calculate_gematria(query)
|
70 |
+
if query_value <= 1 and query:
|
71 |
+
return f"## Error\nQuery '{query}' has an invalid Gematria value ({query_value}). Please enter a valid query."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
except Exception as e:
|
73 |
+
return f"## Error\nCould not calculate Gematria for query '{query}'. Details: {e}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
+
progress(0, desc="Initializing...")
|
76 |
+
translator = None
|
77 |
+
if translate:
|
78 |
+
try:
|
79 |
+
translator = GoogleTranslator(source='iw', target='en')
|
80 |
+
except Exception as e:
|
81 |
+
logging.error(f"Could not initialize translator: {e}")
|
82 |
+
output_lines.append(f"**Warning:** Could not initialize translator: {e}")
|
83 |
+
|
84 |
+
output_lines.append(f"## XOR Gematria Resonance Analysis for: `{query}`")
|
85 |
+
|
86 |
+
verses_processed = 0
|
87 |
+
resonance_count = 0
|
88 |
+
|
89 |
+
# Using a generator to handle the nested loops cleanly and break out
|
90 |
+
def get_verses():
|
91 |
+
for book_num in BOOK_RANGE:
|
92 |
+
filepath = f"texts/torah/{book_num:02}.json"
|
93 |
+
if not os.path.exists(filepath): continue
|
94 |
+
with open(filepath, 'r', encoding='utf-8') as f:
|
95 |
+
data = json.load(f)
|
96 |
+
for chap_idx, chapter in enumerate(data.get("text", []), start=1):
|
97 |
+
for verse_idx, verse_text in enumerate(chapter, start=1):
|
98 |
+
yield (book_num, chap_idx, verse_idx, verse_text)
|
99 |
+
|
100 |
+
for book_num, chap_idx, verse_idx, verse_text in get_verses():
|
101 |
+
# Correctly handle the processing limit
|
102 |
+
if process_verses and verses_processed >= process_verses:
|
103 |
+
print(f"DEBUG: Processing limit of {process_verses} verses reached. Stopping analysis.")
|
104 |
+
break
|
105 |
+
verses_processed += 1
|
106 |
+
progress(verses_processed / process_verses, desc=f"Analyzing Verse {verses_processed}/{process_verses}")
|
107 |
+
|
108 |
+
verse_sum = calculate_gematria(verse_text)
|
109 |
+
if verse_sum <= 1: continue
|
110 |
+
|
111 |
+
power_result = get_power_result(verse_sum, query_value)
|
112 |
+
main_target_sum = verse_sum ^ power_result
|
113 |
+
main_matches = find_all_matching_phrases(main_target_sum, phrase_dictionary)
|
114 |
+
|
115 |
+
verse_ref = f"B{book_num:02d}, C{chap_idx}, V{verse_idx}"
|
116 |
+
print(f"DEBUG: Analyzing [{verse_ref}] | Verse Sum: {verse_sum}, Power/Root: {power_result}, Main Target: {main_target_sum}") # Console Debug
|
117 |
+
|
118 |
+
if not main_matches:
|
119 |
+
print("DEBUG: No main resonance found. Skipping.") # Console Debug
|
120 |
+
continue
|
121 |
+
|
122 |
+
resonance_count += 1
|
123 |
+
print(f"DEBUG: Found Resonance #{resonance_count}!") # Console Debug
|
124 |
+
|
125 |
+
output_lines.append("\n---\n")
|
126 |
+
output_lines.append(f"### Resonance #{resonance_count} in [{verse_ref}]")
|
127 |
+
output_lines.append(f"> {verse_text.strip()}\n")
|
128 |
+
|
129 |
+
output_lines.append("```")
|
130 |
+
output_lines.append(f"Verse Sum (X) : {verse_sum} | Query: \"{query}\" (G: {query_value}) | Power/Root (Y): {power_result}")
|
131 |
+
output_lines.append("```\n")
|
132 |
+
|
133 |
+
def format_matches(matches: List[Dict], title: str, calculation_str: str):
|
134 |
+
if not matches: return
|
135 |
+
|
136 |
+
matches.sort(key=lambda p: (p.get('freq', 0) / p.get('words', 99)), reverse=True)
|
137 |
+
matches_to_show = matches[:results_per_verse]
|
138 |
|
139 |
+
output_lines.append(f"**{title}:** `{calculation_str}`")
|
140 |
+
|
141 |
+
for match in matches_to_show:
|
142 |
+
translation_str = ""
|
143 |
+
if translator:
|
144 |
+
try:
|
145 |
+
translation_str = translator.translate(match['text'])
|
146 |
+
except Exception:
|
147 |
+
translation_str = "[Translation failed]"
|
148 |
+
|
149 |
+
score = (p.get('freq', 0) / p.get('words', 99)) if (p:=match).get('words') else 0
|
150 |
+
gematria_val = calculate_gematria(match['text'])
|
151 |
+
|
152 |
+
output_lines.append(f" * **{match['text']}**")
|
153 |
+
output_lines.append(f" `G: {gematria_val}, Words: {match.get('words', 'N/A')}, Freq: {match.get('freq', 'N/A')}, Score: {score:.2f}`")
|
154 |
+
if translation_str:
|
155 |
+
output_lines.append(f"\n*Translation: \"{translation_str}\"*")
|
156 |
+
output_lines.append("")
|
157 |
+
|
158 |
+
calc_str = f"[{verse_sum}] ^ [{power_result}] โ [G_target:{main_target_sum}]"
|
159 |
+
format_matches(main_matches, "Main Resonance", calc_str)
|
160 |
+
|
161 |
+
if xor_depth > 0:
|
162 |
+
output_lines.append(f"**Bitplane Variations of the Result ({main_target_sum}):**")
|
163 |
+
for depth in range(xor_depth):
|
164 |
+
bit_flip = 1 << depth
|
165 |
+
target_sum = main_target_sum ^ bit_flip
|
166 |
+
bitplane_matches = find_all_matching_phrases(target_sum, phrase_dictionary)
|
167 |
+
|
168 |
+
if bitplane_matches:
|
169 |
+
bitplane_calc_str = f"[{main_target_sum}] ^ [Bit {depth+1}] โ [G_target:{target_sum}]"
|
170 |
+
format_matches(bitplane_matches, f"Variation (Depth {depth + 1})", bitplane_calc_str)
|
171 |
+
|
172 |
+
if resonance_count == 0:
|
173 |
+
output_lines.append("\n**No resonances found. Consider increasing 'Verses to Process' or trying a different query.**")
|
174 |
+
|
175 |
+
print("--- ANALYSIS COMPLETE ---") # Console Debug
|
176 |
+
return "\n".join(output_lines)
|
177 |
+
|
178 |
+
# --- Gradio UI Definition ---
|
179 |
+
# Custom CSS for a professional dark theme inspired by the screenshot
|
180 |
+
custom_css = """
|
181 |
+
#output_markdown h3 {
|
182 |
+
color: #f97316; /* Vibrant orange for main resonance headers */
|
183 |
+
border-bottom: 2px solid #374151;
|
184 |
+
padding-bottom: 8px;
|
185 |
+
margin-top: 24px;
|
186 |
+
}
|
187 |
+
#output_markdown blockquote {
|
188 |
+
background-color: #1f2937;
|
189 |
+
border-left: 5px solid #f97316;
|
190 |
+
padding: 12px;
|
191 |
+
font-style: italic;
|
192 |
+
color: #d1d5db;
|
193 |
+
}
|
194 |
+
#output_markdown code {
|
195 |
+
background-color: #374151;
|
196 |
+
color: #e5e7eb;
|
197 |
+
padding: 3px 6px;
|
198 |
+
border-radius: 5px;
|
199 |
+
font-size: 0.9em;
|
200 |
+
}
|
201 |
+
"""
|
202 |
+
|
203 |
+
# Using the robust Default theme and customizing it for the desired dark look
|
204 |
+
dark_theme = gr.themes.Default(
|
205 |
+
primary_hue=gr.themes.colors.orange,
|
206 |
+
secondary_hue=gr.themes.colors.blue,
|
207 |
+
neutral_hue=gr.themes.colors.slate
|
208 |
+
).set(
|
209 |
+
body_background_fill="#0f172a",
|
210 |
+
background_fill_primary="#1e293b",
|
211 |
+
background_fill_secondary="#334155",
|
212 |
+
body_text_color="#e2e8f0",
|
213 |
+
color_accent_soft="#1e293b",
|
214 |
+
border_color_accent="#334155",
|
215 |
+
border_color_primary="#334155",
|
216 |
+
button_primary_background_fill="#f97316",
|
217 |
+
button_primary_text_color="#ffffff",
|
218 |
+
button_secondary_background_fill="#334155",
|
219 |
+
button_secondary_text_color="#e2e8f0",
|
220 |
+
)
|
221 |
+
|
222 |
+
with gr.Blocks(theme=dark_theme, css=custom_css, title="Tanakh XOR Gematria Resonance") as demo:
|
223 |
+
gr.Markdown("# ๐ Tanakh XOR Gematria Resonance")
|
224 |
+
|
225 |
+
with gr.Tabs():
|
226 |
+
with gr.TabItem("XOR Gematria Resonance"):
|
227 |
+
with gr.Row():
|
228 |
+
with gr.Column(scale=1):
|
229 |
+
query = gr.Textbox(
|
230 |
+
label="Query Phrase",
|
231 |
+
placeholder="e.g., ืืืื, ืืืืื, light...",
|
232 |
+
)
|
233 |
+
run_button = gr.Button("๐ฎ Divine Resonance", variant="primary")
|
234 |
+
|
235 |
+
with gr.Accordion("Advanced Parameters", open=False):
|
236 |
+
process_verses = gr.Slider(
|
237 |
+
label="Verses to Process", minimum=1, maximum=35000, step=1, value=10,
|
238 |
+
info="How many verses to analyze from the start of the Tanakh."
|
239 |
+
)
|
240 |
+
results_per_verse = gr.Slider(
|
241 |
+
label="Results per Resonance", minimum=1, maximum=10, step=1, value=1,
|
242 |
+
info="How many top phrases to show for each found resonance type."
|
243 |
+
)
|
244 |
+
xor_depth = gr.Slider(
|
245 |
+
label="Bitplane Variation Depth", minimum=0, maximum=16, step=1, value=2,
|
246 |
+
info="How many bit-levels of the main result to vary and analyze."
|
247 |
+
)
|
248 |
+
translate = gr.Checkbox(label="Translate to English", value=True)
|
249 |
+
|
250 |
+
gr.Examples(
|
251 |
+
examples=[
|
252 |
+
["ืืืื"], ["ืืืืื"], ["ืฉืืื ื"],
|
253 |
+
["ืืฉืื ืืฉืืขืื"], ["ืืื ืฉืืืฉืื ืืฉืืข"], ["ืฆืืง ืืืฉืคื"]
|
254 |
+
],
|
255 |
+
inputs=[query]
|
256 |
+
)
|
257 |
+
|
258 |
+
with gr.Column(scale=3):
|
259 |
+
output_markdown = gr.Markdown(label="Resonances", elem_id="output_markdown")
|
260 |
+
|
261 |
+
with gr.TabItem("About & Help"):
|
262 |
+
gr.Markdown(
|
263 |
+
"""
|
264 |
+
### How It Works
|
265 |
+
This tool explores the numerological and structural connections within the Tanakh based on Gematria and bitwise XOR operations. It is an instrument for textual exploration, not a historical or theological authority.
|
266 |
+
|
267 |
+
1. **Gematria Calculation:** The Gematria (numerical value) of your **Query Phrase** and each **Verse** in the Tanakh is calculated.
|
268 |
+
2. **Power/Root Operator (Y):** To create a non-obvious link, the Query's Gematria is transformed. If it's smaller than the Verse's Gematria, its highest possible power is taken. If larger, its n-th root is taken. This becomes the "Operator" (Y).
|
269 |
+
3. **Main Resonance:** The core operation is `Verse_Gematria (X) ^ Operator (Y)`. The result is a **Target Gematria**. The app then finds all phrases in the Tanakh with this exact numerical value. This is the "Main Resonance".
|
270 |
+
4. **Bitplane Variations:** To explore the "fractal neighborhood" of the Main Resonance, the app then "flips" each bit of the result, one by one. For each flipped bit (`depth`), it calculates a new Target Gematria (`Main_Result ^ 2^depth`) and finds corresponding phrases. This reveals concepts that are numerologically "close" to the main result.
|
271 |
+
5. **Scoring:** Results are sorted by a relevance score calculated as `Frequency / Word_Count` to prioritize short, common phrases.
|
272 |
+
|
273 |
+
### Parameters
|
274 |
+
- **Verses to Process:** Limits how many verses the script analyzes. Higher numbers take longer.
|
275 |
+
- **Results per Resonance:** Limits how many phrases are shown for the main resonance and each variation.
|
276 |
+
- **Bitplane Variation Depth:** Controls how many "bit-flips" are tested. A depth of 5 will test flipping Bit 1, Bit 2, Bit 3, Bit 4, and Bit 5.
|
277 |
+
"""
|
278 |
+
)
|
279 |
+
|
280 |
+
run_button.click(
|
281 |
+
fn=run_analysis,
|
282 |
+
inputs=[query, translate, process_verses, results_per_verse, xor_depth],
|
283 |
+
outputs=[output_markdown]
|
284 |
+
)
|
285 |
|
|
|
286 |
if __name__ == "__main__":
|
287 |
+
if phrase_dictionary is None:
|
288 |
+
print("CRITICAL: Phrase dictionary could not be loaded. The application cannot start.")
|
289 |
+
print("Please ensure 'tanakh_phrasedict.cache' exists and is valid. Run 'build_indices.py' if necessary.")
|
290 |
+
else:
|
291 |
+
# The share=True argument creates a public link for easy sharing. Remove it if you only want local access.
|
292 |
+
demo.launch()
|