Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -114,6 +114,68 @@ def to_turtle(df: pd.DataFrame, base_ns: str) -> str:
|
|
| 114 |
ttl = g.serialize(format="turtle")
|
| 115 |
return ttl.decode("utf-8") if hasattr(ttl, "decode") else ttl
|
| 116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
# ---- Gradio UI (tiny) ----
|
| 118 |
EXAMPLE = (
|
| 119 |
"Yas Etessam is a content architect who works with large enterprises. "
|
|
@@ -145,6 +207,11 @@ with gr.Blocks(title="Relationship Helper — Minimal") as demo:
|
|
| 145 |
|
| 146 |
turtle_out = gr.Code(label="RDF/Turtle", value="") # ✅ safe initial value
|
| 147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
def on_extract(text: str):
|
| 149 |
rows = extract_triples(text) if text.strip() else []
|
| 150 |
return pd.DataFrame(rows, columns=["subject", "relation", "object", "confidence"])
|
|
@@ -157,10 +224,16 @@ with gr.Blocks(title="Relationship Helper — Minimal") as demo:
|
|
| 157 |
return "# (No rows to export)"
|
| 158 |
return to_turtle(data, base or "https://example.org/")
|
| 159 |
|
|
|
|
|
|
|
|
|
|
| 160 |
btn.click(on_extract, inputs=text_in, outputs=df)
|
| 161 |
btn_clear.click(on_clear, outputs=[text_in, df, turtle_out])
|
| 162 |
btn_export.click(on_export, inputs=[df, base_ns], outputs=turtle_out)
|
| 163 |
|
|
|
|
|
|
|
|
|
|
| 164 |
# For Hugging Face Spaces, expose on 0.0.0.0 and allow shareable link
|
| 165 |
if __name__ == "__main__":
|
| 166 |
demo.launch(server_name="0.0.0.0", server_port=7860, share=True)
|
|
|
|
| 114 |
ttl = g.serialize(format="turtle")
|
| 115 |
return ttl.decode("utf-8") if hasattr(ttl, "decode") else ttl
|
| 116 |
|
| 117 |
+
# ---------- NEW: RDF → rainbow graph (PyVis) ----------
|
| 118 |
+
import hashlib, tempfile, pathlib, html
|
| 119 |
+
|
| 120 |
+
def _rainbow_color(idx: int) -> str:
|
| 121 |
+
# 12-color rainbow palette (hex)
|
| 122 |
+
palette = [
|
| 123 |
+
"#e6194b","#ffa31a","#ffe119","#bfef45","#3cb44b","#42d4f4",
|
| 124 |
+
"#4363d8","#911eb4","#f032e6","#a9a9a9","#fabed4","#ffd8b1"
|
| 125 |
+
]
|
| 126 |
+
return palette[idx % len(palette)]
|
| 127 |
+
|
| 128 |
+
def _color_for_label(label: str) -> str:
|
| 129 |
+
# deterministic color from label
|
| 130 |
+
h = int(hashlib.sha1(label.encode("utf-8")).hexdigest(), 16)
|
| 131 |
+
return _rainbow_color(h)
|
| 132 |
+
|
| 133 |
+
def turtle_to_pyvis_html(ttl_text: str):
|
| 134 |
+
try:
|
| 135 |
+
from pyvis.network import Network
|
| 136 |
+
except Exception:
|
| 137 |
+
# friendly guidance if pyvis isn't installed
|
| 138 |
+
msg = (
|
| 139 |
+
"<div style='padding:12px;border:1px solid #eee'>"
|
| 140 |
+
"<b>PyVis not installed.</b> Add <code>pyvis</code> to requirements.txt to enable the interactive graph preview."
|
| 141 |
+
"</div>"
|
| 142 |
+
)
|
| 143 |
+
return msg
|
| 144 |
+
|
| 145 |
+
if not ttl_text.strip():
|
| 146 |
+
return "<div style='padding:12px;border:1px solid #eee'>No Turtle to render. Export RDF first.</div>"
|
| 147 |
+
|
| 148 |
+
g = Graph()
|
| 149 |
+
try:
|
| 150 |
+
g.parse(data=ttl_text, format="turtle")
|
| 151 |
+
except Exception as e:
|
| 152 |
+
return f"<pre style='white-space:pre-wrap;color:#b00'>Parse error: {html.escape(str(e))}</pre>"
|
| 153 |
+
|
| 154 |
+
net = Network(height="620px", width="100%", directed=True, notebook=False, cdn_resources="remote")
|
| 155 |
+
net.toggle_physics(True)
|
| 156 |
+
|
| 157 |
+
def compact(term):
|
| 158 |
+
try:
|
| 159 |
+
return g.namespace_manager.normalizeUri(term)
|
| 160 |
+
except Exception:
|
| 161 |
+
return str(term)
|
| 162 |
+
|
| 163 |
+
nodes_seen = set()
|
| 164 |
+
for s, p, o in g:
|
| 165 |
+
sn, pn, on = compact(s), compact(p), compact(o)
|
| 166 |
+
if sn not in nodes_seen:
|
| 167 |
+
net.add_node(sn, label=sn, color=_color_for_label(sn), shape="dot")
|
| 168 |
+
nodes_seen.add(sn)
|
| 169 |
+
if on not in nodes_seen:
|
| 170 |
+
net.add_node(on, label=on, color=_color_for_label(on), shape="dot")
|
| 171 |
+
nodes_seen.add(on)
|
| 172 |
+
net.add_edge(sn, on, label=pn, color=_color_for_label(pn), arrows="to")
|
| 173 |
+
|
| 174 |
+
tmpdir = pathlib.Path(tempfile.mkdtemp())
|
| 175 |
+
out_html = tmpdir / "graph.html"
|
| 176 |
+
net.show(str(out_html))
|
| 177 |
+
return f'<iframe src="file/{out_html}" style="width:100%;height:640px;border:0" allowfullscreen></iframe>'
|
| 178 |
+
|
| 179 |
# ---- Gradio UI (tiny) ----
|
| 180 |
EXAMPLE = (
|
| 181 |
"Yas Etessam is a content architect who works with large enterprises. "
|
|
|
|
| 207 |
|
| 208 |
turtle_out = gr.Code(label="RDF/Turtle", value="") # ✅ safe initial value
|
| 209 |
|
| 210 |
+
# ---------- NEW: preview controls at the bottom ----------
|
| 211 |
+
with gr.Row():
|
| 212 |
+
btn_preview = gr.Button("Preview Graph 🌈")
|
| 213 |
+
graph_html = gr.HTML(label="Knowledge Graph Preview (rainbow)")
|
| 214 |
+
|
| 215 |
def on_extract(text: str):
|
| 216 |
rows = extract_triples(text) if text.strip() else []
|
| 217 |
return pd.DataFrame(rows, columns=["subject", "relation", "object", "confidence"])
|
|
|
|
| 224 |
return "# (No rows to export)"
|
| 225 |
return to_turtle(data, base or "https://example.org/")
|
| 226 |
|
| 227 |
+
def on_preview(ttl_text: str):
|
| 228 |
+
return turtle_to_pyvis_html(ttl_text)
|
| 229 |
+
|
| 230 |
btn.click(on_extract, inputs=text_in, outputs=df)
|
| 231 |
btn_clear.click(on_clear, outputs=[text_in, df, turtle_out])
|
| 232 |
btn_export.click(on_export, inputs=[df, base_ns], outputs=turtle_out)
|
| 233 |
|
| 234 |
+
# NEW: wire up preview
|
| 235 |
+
btn_preview.click(on_preview, inputs=turtle_out, outputs=graph_html)
|
| 236 |
+
|
| 237 |
# For Hugging Face Spaces, expose on 0.0.0.0 and allow shareable link
|
| 238 |
if __name__ == "__main__":
|
| 239 |
demo.launch(server_name="0.0.0.0", server_port=7860, share=True)
|