Spaces:
Sleeping
Sleeping
File size: 8,876 Bytes
f5bdf65 44471e2 f5bdf65 37e5a6d f5bdf65 37e5a6d 44471e2 37e5a6d 44471e2 37e5a6d 44471e2 37e5a6d 44471e2 37e5a6d 44471e2 37e5a6d 44471e2 f5bdf65 44471e2 37e5a6d 44471e2 37e5a6d 44471e2 37e5a6d 44471e2 f5bdf65 44471e2 f5bdf65 44471e2 f5bdf65 44471e2 37e5a6d f5bdf65 37e5a6d f5bdf65 44471e2 f5bdf65 44471e2 f5bdf65 44471e2 f5bdf65 44471e2 f5bdf65 44471e2 f5bdf65 44471e2 f5bdf65 44471e2 f5bdf65 44471e2 f5bdf65 37e5a6d f5bdf65 44471e2 37e5a6d f5bdf65 44471e2 37e5a6d f5bdf65 37e5a6d f5bdf65 44471e2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
import gradio as gr
import requests
import spacy
import re
import time
import os # Import the 'os' module
import base64 # Import base64
# Try to load the spaCy model, download if it's not available
try:
nlp = spacy.load("en_core_web_sm")
except OSError:
print("Downloading en_core_web_sm model...")
import spacy.cli
spacy.cli.download("en_core_web_sm")
nlp = spacy.load("en_core_web_sm")
def text_to_diagram(text_description):
"""Convert process description into Mermaid.js flowchart."""
doc = nlp(text_description.lower())
steps = []
conditions = []
loops = []
complex_flow = []
sentences = [sent.text.strip() for sent in doc.sents]
for sentence in sentences:
sentence = sentence.replace("2, conditional branch", "").replace("3 loop start", "").replace("4 complex flow", "").strip()
if "then" in sentence:
tokens = sentence.split("then")
for token in tokens:
token = token.strip()
if token:
step = token.strip().replace(",", "").replace(".", "")
if step and step not in ["conditional branch", "loop start", "complex flow"]:
if "flowchart that shows" in step:
continue
steps.append(step)
cond_match = re.search(r"if ([a-z\s]+), (?:go to|proceed to) ([a-z\s]+); otherwise, (?:go to|proceed to) ([a-z\s]+)", sentence)
if not cond_match:
cond_match = re.search(r"if ([a-z\s]+), ([a-z\s]+); otherwise, ([a-z\s]+)", sentence)
if cond_match:
condition, true_action, false_action = cond_match.groups()
conditions.append((condition.strip(), true_action.strip(), false_action.strip()))
loop_match = re.search(r"(?:do|perform) (?:action )?([a-z]), repeat ([a-z]) until ([a-z]) is true", sentence)
if not loop_match:
loop_match = re.search(r"loop: ([a-z\s]+), repeat ([a-z\s]+) until ([a-z\s]+)", sentence)
if loop_match:
action, repeat_action, condition = loop_match.groups()
loops.append((action.strip(), condition.strip()))
if "flowchart that shows" in sentence:
flow_part = sentence.split("flowchart that shows")[1]
flow_steps = flow_part.split("then")
for step in flow_steps:
step = step.replace("and finally", "").replace(".", "").replace(",", "").strip()
if step:
complex_flow.append(step)
elif "then" in sentence and not steps:
tokens = sentence.split("then")
for token in tokens:
token = token.strip()
if token and token not in steps:
step = token.replace(",", "").replace(".", "").strip()
if step:
complex_flow.append(step)
if not complex_flow:
complex_flow = steps[1:] if steps else []
steps = steps[:1] if steps else []
diagram_code = "graph TD\n"
node_counter = 0
node_map = {}
def get_node_id(label):
nonlocal node_counter
if label not in node_map:
node_map[label] = chr(65 + node_counter)
node_counter += 1
return node_map[label]
if steps:
for i in range(len(steps)):
step = steps[i]
node_id = get_node_id(step)
diagram_code += f"{node_id}[{step.capitalize()}]\n"
if i > 0:
prev_node_id = get_node_id(steps[i - 1])
diagram_code += f"{prev_node_id} --> {node_id}\n"
else:
start_node = get_node_id("start")
diagram_code += f"{start_node}[Start]\n"
last_node = steps[-1] if steps else "start"
last_node_id = get_node_id(last_node)
for condition, true_action, false_action in conditions:
cond_node = get_node_id(f"cond_{condition}")
true_node = get_node_id(true_action)
false_node = get_node_id(false_action)
diagram_code += f"{last_node_id} --> {cond_node}{{{condition.capitalize()}?}}\n"
diagram_code += f"{cond_node} -->|Yes| {true_node}[{true_action.capitalize()}]\n"
diagram_code += f"{cond_node} -->|No| {false_node}[{false_action.capitalize()}]\n"
last_node = true_action
last_node_id = true_node
false_node_id = false_node
for action, condition in loops:
loop_node = get_node_id(f"loop_{action}")
cond_node = get_node_id(f"cond_{condition}")
finish_node = get_node_id(f"finish_{action}")
diagram_code += f"{last_node_id} --> {loop_node}[Loop: Perform {action.capitalize()}]\n"
diagram_code += f"{loop_node} --> {cond_node}{{{condition.capitalize()} is True?}}\n"
diagram_code += f"{cond_node} -->|No| {loop_node}\n"
diagram_code += f"{cond_node} -->|Yes| {finish_node}[Finish Loop]\n"
last_node_id = finish_node
for i in range(len(complex_flow)):
step = complex_flow[i]
node_id = get_node_id(f"flow_{i}_{step}")
diagram_code += f"{node_id}[{step.capitalize()}]\n"
if i == 0:
diagram_code += f"{last_node_id} --> {node_id}\n"
else:
prev_node_id = get_node_id(f"flow_{i - 1}_{complex_flow[i - 1]}")
diagram_code += f"{prev_node_id} --> {node_id}\n"
last_node_id = node_id
end_node = get_node_id("end")
diagram_code += f"{end_node}[End Process]\n"
diagram_code += f"{last_node_id} --> {end_node}\n"
if conditions:
diagram_code += f"{false_node_id} --> {end_node}\n"
try:
img_url = render_mermaid_to_url(diagram_code)
response = requests.get(img_url, timeout=10)
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
image_data = response.content
temp_img_path = f"temp_diagram_{int(time.time())}.png"
with open(temp_img_path, "wb") as f:
f.write(image_data)
return diagram_code, temp_img_path
except requests.exceptions.RequestException as e:
print(f"Error rendering diagram (network): {e}")
return diagram_code, None
except Exception as e:
print(f"Error rendering diagram: {e}")
return diagram_code, None
def render_mermaid_to_url(mermaid_code):
"""Render Mermaid code to an image URL using Mermaid.ink."""
try:
encoded_code = base64.urlsafe_b64encode(mermaid_code.encode()).decode()
return f"https://mermaid.ink/img/{encoded_code}"
except Exception as e:
print(f"Error encoding Mermaid code: {e}")
return None
def gradio_interface(text_input):
"""Process user input and return diagram output for Gradio."""
try:
diagram_code, img_path = text_to_diagram(text_input)
print("Generated Mermaid Code:")
print(diagram_code)
return diagram_code, img_path if img_path else None
except Exception as e:
print(f"Error in Gradio interface: {e}")
return f"Error: {str(e)}", None
iface = gr.Interface(
fn=gradio_interface,
inputs=gr.Textbox(lines=5, placeholder="Describe your process (e.g., 'User logs in, then enters details...')"),
outputs=[
gr.Textbox(label="Generated Mermaid Code"),
gr.Image(label="Diagram Visualization", type="filepath"),
],
title="Text-to-Diagram Converter (Napkin AI Style)",
description="Convert process descriptions into structured flowcharts like Napkin AI.",
examples=[
["Developer writes code, then tests code. If tests pass, proceed to deploy; otherwise, debug code. Then release software to production."],
["Customer browses products, then adds to cart, then proceeds to checkout. If payment is verified, confirm order; otherwise, request payment again. Loop: Validate payment, repeat until successful. Then ship order and notify customer."],
["HR posts job opening, then reviews applications, then conducts interviews. If candidate is selected, offer job; otherwise, reject candidate. Then onboard new employee."],
["Student registers for exam, then studies material. If prepared, proceed to take exam; otherwise, study more. If exam is passed, receive certificate; otherwise, retake exam. Then celebrate success."],
["Customer places order, then kitchen prepares food. Loop: Check food quality, repeat until perfect. Then serve food and collect payment."],
["Traveler searches for flights, then selects flight, then books ticket. If booking is confirmed, proceed to payment; otherwise, search again. If payment is successful, receive itinerary; otherwise, cancel booking. Then plan trip."],
["User signs up, then verifies email, then logs in."],
],
allow_flagging="never",
)
if __name__ == "__main__":
iface.launch(share=True) |