Nasafg / app_interface.py
Amirnaj's picture
Upload app_interface.py
f5a63f3 verified
Raw History Blame Contribute Delete
20.3 kB
# -*- coding: utf-8 -*-
"""🎨 Quran Interface v8.1 — With Code-to-App Workshop
✅ Visualizing the Invisible | ✅ Live Code Compiler | ✅ Auto-UI Generator
"""
import gradio as gr
import matplotlib.pyplot as plt
import numpy as np
import json, ast, re, tempfile, os
from datetime import datetime
# اتصال به موتور اصلی (از سلول قبل)
try:
orchestrator, parser, kb = get_analyzer()
CORE_LOADED = True
except NameError:
CORE_LOADED = False
print("❌ Error: core_engine.py must be run first!")
# ═══════════════════════════════════════════════════════════
# ۱. گزارش‌دهی فلسفی (همان قبلی)
# ═══════════════════════════════════════════════════════════
class NarrativeGenerator:
@staticmethod
def generate_philosophical_report(res):
md = ["# 🌌 گزارش جامع تحلیل قرآنی (نسخه ۸.۰)\n"]
md.append(f"**زمان:** {datetime.now().strftime('%H:%M:%S')}\n---\n")
fd = res['fractal_dim']
md.append(f"## ۱. هندسه معنا\n- بُعد فراکتالی: `{fd}`\n")
if fd > 1.5: md.append("> پیچیدگی ساختاری بالا (شبیه کریستال).\n")
elif fd < 1.2: md.append("> سادگی و خطی بودن نسبی.\n")
cb = res['cosmic_balance']
md.append(f"## ۲. ترازوی عدالت و رحمت\n- شاخص: `{cb['index']}` ({cb['state']})\n")
if cb['index'] > 0.3: md.append("💡 سیطره رحمت.\n")
elif cb['index'] < -0.3: md.append("💡 غلبه هشدار.\n")
sd = res['semantic_drift']
md.append(f"## ۳. مسیر حرکت معنا\n- زاویه رانش: `{sd['drift_magnitude']}°`\n")
if sd['drift_magnitude'] > 60: md.append("🔄 چرخش معنایی شدید.\n")
elif sd['drift_magnitude'] < 15: md.append("➡️ انسجام بالا.\n")
rd = res['rhetoric_density']
md.append(f"## ۴. نقشه زیبایی‌شناسی\n- میانگین تراکم: `{rd['average_density']}`\n")
if rd['peak_verse']:
pv = rd['peak_verse']
md.append(f"- اوج بلاغت: آیه `{pv['verse_id']}` ({', '.join(pv['features'])})\n")
th = res['theology']
md.append(f"## ۵. سامانه اعتقادی\n- موضوع غالب: `{th['dominant_theme']}`\n- انسجام: `{th['coherence_score']}`\n")
md.append("\n---\n## 💎 سنتز نهایی\n")
summary = []
if fd > 1.3: summary.append("پیچیده")
if cb['index'] > 0: summary.append("رحمت‌محور")
elif cb['index'] < 0: summary.append("هشدارمحور")
else: summary.append("متعادل")
md.append(f"> این قطعه {', '.join(summary)} است با تمرکز بر «{th['dominant_theme']}».\n")
return "\n".join(md)
def create_visualizations(res):
plots = {}
try:
# ۱. Gauge Chart
idx = res['cosmic_balance']['index']
plt.figure(figsize=(6, 3), facecolor='#1a1a2e')
ax = plt.subplot(111); ax.set_facecolor('#1a1a2e')
theta = np.linspace(0, np.pi, 100)
colors = ['#F44336' if x < -0.3 else ('#FFEB3B' if abs(x) <= 0.3 else '#4CAF50') for x in np.cos(theta)]
ax.fill_between(np.cos(theta)*1.0, np.sin(theta)*1.0, np.cos(theta)*0.7, np.sin(theta)*0.7, color=colors, alpha=0.5)
angle = (idx + 1) / 2 * np.pi
ax.plot([0, np.cos(angle)*0.9], [0, np.sin(angle)*0.9], 'w-', linewidth=3)
ax.scatter(np.cos(angle)*0.9, np.sin(angle)*0.9, c='white', s=100)
ax.set_xlim(-1.2, 1.2); ax.set_ylim(-0.2, 1.2); ax.axis('off')
ax.text(0, -0.1, f"Balance: {idx}", ha='center', color='white', fontsize=12, weight='bold')
plt.tight_layout(); p="/tmp/v8_cosmic.png"; plt.savefig(p, dpi=100, bbox_inches='tight', facecolor='#1a1a2e'); plt.close()
plots['cosmic'] = p
# ۲. Heatmap Strip
density_map = res['rhetoric_density']['map']
scores = [d['score'] for d in density_map]
labels = [d['verse_id'] for d in density_map]
plt.figure(figsize=(10, 2), facecolor='#1a1a2e')
ax = plt.gca(); ax.set_facecolor('#1a1a2e')
im = ax.imshow([scores], cmap='inferno', aspect='auto')
ax.set_xticks(range(len(labels))); ax.set_xticklabels(labels, rotation=45, ha='right', color='white', fontsize=7)
ax.set_yticks([]); ax.set_title('Rhetorical Density', color='white', fontsize=10)
plt.colorbar(im, ax=ax, shrink=0.8)
plt.tight_layout(); p="/tmp/v8_rhetoric.png"; plt.savefig(p, dpi=100, bbox_inches='tight', facecolor='#1a1a2e'); plt.close()
plots['rhetoric'] = p
# ۳. Radar
topics = res['theology']['topic_distribution']
if topics:
keys = list(topics.keys()); vals = list(topics.values())
plt.figure(figsize=(5, 5), facecolor='#1a1a2e')
ax = plt.subplot(111, projection='polar')
angles = np.linspace(0, 2*np.pi, len(keys), endpoint=False).tolist()
vals += vals[:1]; angles += angles[:1]
ax.plot(angles, vals, 'o-', linewidth=2, color='#FFD700')
ax.fill(angles, vals, alpha=0.25, color='#FFD700')
ax.set_thetagrids(np.degrees(angles[:-1]), keys, color='white')
ax.grid(color='gray', linestyle='--', alpha=0.3)
ax.set_title('Theological Radar', color='white', pad=20)
plt.tight_layout(); p="/tmp/v8_theology.png"; plt.savefig(p, dpi=100, bbox_inches='tight', facecolor='#1a1a2e'); plt.close()
plots['theology'] = p
except Exception as e:
log.error(f"Vis Error: {e}")
return plots
# ═══════════════════════════════════════════════════════════
# ۲. موتور کارگاه تبدیل کد به برنامه (Code-to-App Engine)
# ═══════════════════════════════════════════════════════════
class CodeWorkshopEngine:
@staticmethod
def analyze_and_wrap_code(raw_code):
"""
۱. کد را پارس می‌کند تا توابع را پیدا کند.
۲. یک اسکلت Gradio برای هر تابع می‌سازد.
۳. کد نهایی قابل اجرا را تولید می‌کند.
"""
try:
tree = ast.parse(raw_code)
except SyntaxError as e:
return None, f"❌ خطای سینتکس در کد شما:\n{e}"
functions = []
imports = set()
# استخراج import ها
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
imports.add(alias.name.split('.')[0])
elif isinstance(node, ast.ImportFrom):
if node.module:
imports.add(node.module.split('.')[0])
# استخراج توابع
if isinstance(node, ast.FunctionDef):
args = [arg.arg for arg in node.args.args]
returns_str = "str" # پیش‌فرض
if node.returns and isinstance(node.returns, ast.Name):
returns_str = node.returns.id
# تشخیص نوع ورودی بر اساس نام پارامتر
input_type = "textbox"
if any(k in a.lower() for a in args for k in ['num', 'int', 'float']):
input_type = "number"
elif any(k in a.lower() for a in args for k in ['img', 'image', 'pic']):
input_type = "image"
functions.append({
'name': node.name,
'args': args,
'return_type': returns_str,
'input_widget': input_type,
'source_code': ast.get_source_segment(raw_code, node) or ""
})
if not functions:
return None, "⚠️ هیچ تابعی (def ...) در کد یافت نشد. لطفاً حداقل یک تابع بنویسید."
# ساخت کد نهایی
header = "# Auto-generated by AI Studio Workshop\nimport gradio as gr\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport math\nimport random\nimport json\nimport re\nfrom datetime import datetime\n\n"
body = ""
ui_blocks = []
for func in functions:
# افزودن تابع اصلی
body += f"\n# --- Function: {func['name']} ---\n"
body += func['source_code'] + "\n\n"
# ساخت ویجت UI برای این تابع
widgets = []
for i, arg in enumerate(func['args']):
if func['input_widget'] == 'number':
widgets.append(f"gr.Number(label='{arg}')")
elif func['input_widget'] == 'image':
widgets.append(f"gr.Image(label='{arg}')")
else:
widgets.append(f"gr.Textbox(label='{arg}', lines=3)")
widget_list = ", ".join(widgets) if widgets else ""
output_widget = "gr.Textbox(label='Output')" if func['return_type'] == 'str' else "gr.JSON(label='Result JSON')"
ui_block = f"""
with gr.Tab("{func['name']}"):
with gr.Row():
inputs = [{widget_list}]
btn_{func['name']} = gr.Button("Run {func['name']}")
out_{func['name']} = {output_widget}
btn_{func['name']}.click(fn={func['name']}, inputs=inputs, outputs=out_{func['name']})
"""
ui_blocks.append(ui_block)
footer = f"""
demo = gr.Blocks(title="My Custom App")
with demo:
gr.Markdown("# 🛠️ My Personal Tool\\nGenerated automatically from your code.")
with gr.Tabs():
{''.join(ui_blocks)}
if __name__ == "__main__":
demo.launch(share=True)
"""
final_script = header + body + footer
return final_script, "✅ کد با موفقیت تجزیه و بسته‌بندی شد!"
@staticmethod
def execute_sandboxed(code_string):
"""
اجرای ایمن کد در یک محیط محدود (Sandbox-lite)
"""
local_env = {"__builtins__": {}}
allowed_modules = {'math', 'random', 'json', 're', 'datetime', 'numpy', 'pd', 'plt'}
# تزریق ماژول‌های مجاز
import builtins
safe_builtins = {k: getattr(builtins, k) for k in dir(builtins) if k not in ['open', 'exec', 'eval', '__import__', 'compile']}
local_env['__builtins__'] = safe_builtins
# ایمپورت ماژول‌های مجاز
for mod_name in allowed_modules:
try:
exec(f"import {mod_name}", local_env)
except ImportError:
pass
try:
exec(code_string, local_env)
return True, "Execution Successful", local_env
except Exception as e:
return False, f"Runtime Error: {str(e)}", None
# ═══════════════════════════════════════════════════════════
# ۳. رابط کاربری Gradio (با تب جدید کارگاه)
# ═══════════════════════════════════════════════════════════
SAMPLE_JSON = '[{"surah":1,"ayah":1,"text":"بسم الله الرحمن الرحيم"},{"surah":1,"ayah":2,"text":"الحمد لله رب العالمين"},{"surah":112,"ayah":1,"text":"قل هو الله احد"}]'
EXAMPLE_CODE_FOR_WORKSHOP = '''
def fibonacci(n):
"""Generate Fibonacci sequence up to n terms."""
if n <= 0: return []
fib_seq = [0, 1]
while len(fib_seq) < n:
next_val = fib_seq[-1] + fib_seq[-2]
fib_seq.append(next_val)
return str(fib_seq)
def calculate_area(radius):
"""Calculate area of circle."""
import math
area = math.pi * radius ** 2
return f"Area: {area:.2f}"
'''
if CORE_LOADED:
workshop_engine = CodeWorkshopEngine()
with gr.Blocks(title="Quran Analyzer v8.1 Ultimate") as demo:
gr.Markdown("""
### 📖 Quran Analyzer v8.1 — The Grand Unified Theory Edition
⚡ **۷ موتور تحلیلی** | 🧠 **تفسیر فلسفی** | 🏗️ **کارگاه تبدیل کد به اپلیکیشن**
""")
with gr.Tabs():
# --- تب ۱: تحلیل قرآن ---
with gr.TabItem("📖 Quran Analysis"):
with gr.Row():
with gr.Column(scale=1):
inp_quran = gr.Textbox(label="📄 Input Data", value=SAMPLE_JSON, lines=12)
btn_quran = gr.Button("🚀 RUN ANALYSIS", variant="primary", size="lg")
with gr.Column(scale=2):
stat_quran = gr.Textbox(label="📡 Status", interactive=False)
narrative_quran = gr.Markdown(label="🧠 Philosophical Report", height=400)
with gr.Row():
plot_cosmic = gr.Image(label="⚖️ Cosmic Balance", type="filepath")
plot_theology = gr.Image(label="🕸️ Theological Radar", type="filepath")
plot_rhetoric = gr.Image(label="🔥 Rhetorical Map", type="filepath")
# --- تب ۲: کارگاه تبدیل کد به برنامه (جدید!) ---
with gr.TabItem("🏗️ Code-to-App Workshop"):
gr.Markdown("""
### 🛠️ تبدیل خودکار کد پایتون به رابط کاربری
۱. کد پایتون خود را (حاوی توابع `def`) در کادر زیر Paste کنید.
۲. دکمه **«تبدیل و پیش‌نمایش»** را بزنید.
۳. سیستم به طور خودکار برای هر تابع، ورودی مناسب (متن، عدد، تصویر) ساخته و رابط گرافیکی می‌دهد.
۴. می‌توانید کد نهایی را دانلود کرده و روی کامپیوتر خود اجرا کنید.
""")
with gr.Row():
with gr.Column(scale=1):
code_input = gr.Code(label="Paste Your Python Code Here", language="python", lines=15, value=EXAMPLE_CODE_FOR_WORKSHOP)
convert_btn = gr.Button("🔄 Convert & Preview", variant="primary", size="lg")
with gr.Column(scale=1):
status_ws = gr.Textbox(label="Status", interactive=False, lines=2)
generated_app_preview = gr.Code(label="Generated App Script (.py)", language="python", lines=15)
download_btn = gr.DownloadButton(label="⬇️ Download Script", variant="secondary")
with gr.Accordion("🧪 Live Sandbox Test (Optional)", open=False):
gr.Markdown("*اجرای سریع تابع اول موجود در کد بالا برای تست عملکرد.*")
test_arg_1 = gr.Textbox(label="Argument 1 (String/Number)", value="10")
run_test_btn = gr.Button("▶️ Run First Function")
test_output = gr.Textbox(label="Function Output", interactive=False)
# --- Event Handlers for Workshop ---
def handle_conversion(code_str):
script, msg = workshop_engine.analyze_and_wrap_code(code_str)
if script:
# ذخیره موقت برای دانلود
tmp_path = tempfile.mktemp(suffix=".py")
with open(tmp_path, "w", encoding="utf-8") as f:
f.write(script)
return msg, script, tmp_path
else:
return msg, "", None
def handle_live_test(code_str, arg_str):
# تلاش برای استخراج اولین تابع
try:
tree = ast.parse(code_str)
first_func = None
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
first_func = node
break
if not first_func:
return "❌ No function found."
func_name = first_func.name
# اجرای ایمن
success, result_msg, env = workshop_engine.execute_sandboxed(code_str)
if success and func_name in env:
fn = env[func_name]
# سعی در تبدیل آرگومان
try:
# اگر آرگومان عددی است
if '.' in arg_str or arg_str.isdigit():
val = float(arg_str) if '.' in arg_str else int(arg_str)
else:
val = arg_str
res = fn(val)
return f"✅ Result of {func_name}({val}): {res}"
except TypeError:
# شاید چند آرگومان دارد یا نوع متفاوت
try:
res = fn(arg_str)
return f"✅ Result of {func_name}('{arg_str}'): {res}"
except Exception as e2:
return f"⚠️ Type Mismatch: {e2}"
else:
return f"❌ Exec Failed: {result_msg}"
except Exception as e:
return f"❌ Parse/Test Error: {str(e)}"
convert_btn.click(handle_conversion, inputs=[code_input], outputs=[status_ws, generated_app_preview, download_btn])
run_test_btn.click(handle_live_test, inputs=[code_input, test_arg_1], outputs=test_output)
# --- Bindings for Quran Tab ---
def run_quran_analysis(user_input):
yield "Processing...", None, None, None, ""
verses = parser(user_input)
if not verses:
yield "❌ Invalid Input.", None, None, None, ""
return
yield f"Parsing {len(verses)} verses...", None, None, None, ""
results = orchestrator.run_full_spectrum_analysis(verses)
yield "Generating Vis...", None, None, None, ""
vis_plots = create_visualizations(results)
report_md = NarrativeGenerator.generate_philosophical_report(results)
yield "✅ COMPLETE!", vis_plots.get('cosmic'), vis_plots.get('theology'), vis_plots.get('rhetoric'), report_md
btn_quran.click(fn=run_quran_analysis, inputs=[inp_quran], outputs=[stat_quran, plot_cosmic, plot_theology, plot_rhetoric, narrative_quran])
if __name__ == "__main__":
demo.launch(share=True)
else:
print("Please run the core_engine cell first.")