Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -75,12 +75,11 @@ def run_query(start_node, relation, end_node, limit):
|
|
| 75 |
Runs an efficient query by filtering on text paths first,
|
| 76 |
then joining by indexed IDs.
|
| 77 |
|
| 78 |
-
|
| 79 |
-
and the `relation.label` column
|
| 80 |
"""
|
| 81 |
print(f"Running query: start='{start_node}', rel='{relation}', end='{end_node}'")
|
| 82 |
|
| 83 |
-
# --- FIX: Select the `id` column (which has the path) ---
|
| 84 |
select_clause = """
|
| 85 |
SELECT
|
| 86 |
e.id AS edge_id,
|
|
@@ -106,26 +105,20 @@ def run_query(start_node, relation, end_node, limit):
|
|
| 106 |
params = []
|
| 107 |
|
| 108 |
try:
|
| 109 |
-
# --- FIX: Query `node.id` for nodes, `relation.label` for relations ---
|
| 110 |
if start_node:
|
| 111 |
-
# We add a wildcard to the front to match the full http://... ID
|
| 112 |
-
# unless the user has already added their own wildcard.
|
| 113 |
param_val = start_node if "%" in start_node else f"%{start_node}"
|
| 114 |
where_conditions.append(f"e.start_id IN (SELECT id FROM node WHERE id LIKE ?)")
|
| 115 |
params.append(param_val)
|
| 116 |
|
| 117 |
if relation:
|
| 118 |
-
# Relation table uses `label` which is a direct match (e.g., /r/IsA)
|
| 119 |
op = "LIKE" if "%" in relation else "="
|
| 120 |
where_conditions.append(f"e.rel_id IN (SELECT id FROM relation WHERE label {op} ?)")
|
| 121 |
params.append(relation)
|
| 122 |
|
| 123 |
if end_node:
|
| 124 |
-
# We add a wildcard to the front to match the full http://... ID
|
| 125 |
param_val = end_node if "%" in end_node else f"%{end_node}"
|
| 126 |
where_conditions.append(f"e.end_id IN (SELECT id FROM node WHERE id LIKE ?)")
|
| 127 |
params.append(param_val)
|
| 128 |
-
# --- End of Fix ---
|
| 129 |
|
| 130 |
if not where_conditions:
|
| 131 |
where_clause = " WHERE 1=1" # Get random edges if no filter
|
|
@@ -176,6 +169,73 @@ def run_raw_query(sql_query):
|
|
| 176 |
traceback.print_exc()
|
| 177 |
return pd.DataFrame(), f"**Query Failed!**\n\n`{e}`"
|
| 178 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
# --- 3. Build the Gradio UI ---
|
| 181 |
|
|
@@ -184,6 +244,15 @@ with gr.Blocks(title="ConceptNet SQLite Explorer") as demo:
|
|
| 184 |
gr.Markdown(f"**Note:** Initial query might take a few seconds as the database warms up.")
|
| 185 |
|
| 186 |
with gr.Tabs():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
with gr.TabItem("Query Builder"):
|
| 188 |
gr.Markdown(
|
| 189 |
"**Run a query against the database.**\n"
|
|
@@ -191,7 +260,6 @@ with gr.Blocks(title="ConceptNet SQLite Explorer") as demo:
|
|
| 191 |
"Use the *path part* of the ID (e.g., `/c/en/dog` or `/r/Is%`)."
|
| 192 |
)
|
| 193 |
with gr.Row():
|
| 194 |
-
# --- FIX: Updated labels for clarity ---
|
| 195 |
start_input = gr.Textbox(label="Start Node Path", placeholder="/c/en/dog")
|
| 196 |
rel_input = gr.Textbox(label="Relation Path", placeholder="/r/IsA")
|
| 197 |
end_input = gr.Textbox(label="End Node Path", placeholder="/c/en/animal")
|
|
@@ -204,10 +272,9 @@ with gr.Blocks(title="ConceptNet SQLite Explorer") as demo:
|
|
| 204 |
|
| 205 |
with gr.TabItem("Raw SQL Query"):
|
| 206 |
gr.Markdown("**Danger Zone:** Run a raw `SELECT` query against the database. Use the Schema Explorer tab to see table/column names.")
|
| 207 |
-
# --- FIX: Updated placeholder to a useful, correct query ---
|
| 208 |
raw_sql_input = gr.Textbox(
|
| 209 |
label="Raw SQL Query",
|
| 210 |
-
placeholder="SELECT id, label, language
|
| 211 |
lines=5
|
| 212 |
)
|
| 213 |
raw_query_btn = gr.Button("Run Raw SQL", variant="secondary")
|
|
@@ -220,6 +287,13 @@ with gr.Blocks(title="ConceptNet SQLite Explorer") as demo:
|
|
| 220 |
schema_output = gr.Markdown("Schema will appear here...")
|
| 221 |
|
| 222 |
# --- 4. Connect UI Elements to Functions ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
query_btn.click(
|
| 224 |
fn=run_query,
|
| 225 |
inputs=[start_input, rel_input, end_input, limit_slider],
|
|
@@ -242,5 +316,4 @@ with gr.Blocks(title="ConceptNet SQLite Explorer") as demo:
|
|
| 242 |
)
|
| 243 |
|
| 244 |
if __name__ == "__main__":
|
| 245 |
-
# Removed experimental ssr_mode=False
|
| 246 |
demo.launch(ssr_mode=False)
|
|
|
|
| 75 |
Runs an efficient query by filtering on text paths first,
|
| 76 |
then joining by indexed IDs.
|
| 77 |
|
| 78 |
+
This now queries the `node.id` column (which contains the full path)
|
| 79 |
+
and the `relation.label` column.
|
| 80 |
"""
|
| 81 |
print(f"Running query: start='{start_node}', rel='{relation}', end='{end_node}'")
|
| 82 |
|
|
|
|
| 83 |
select_clause = """
|
| 84 |
SELECT
|
| 85 |
e.id AS edge_id,
|
|
|
|
| 105 |
params = []
|
| 106 |
|
| 107 |
try:
|
|
|
|
| 108 |
if start_node:
|
|
|
|
|
|
|
| 109 |
param_val = start_node if "%" in start_node else f"%{start_node}"
|
| 110 |
where_conditions.append(f"e.start_id IN (SELECT id FROM node WHERE id LIKE ?)")
|
| 111 |
params.append(param_val)
|
| 112 |
|
| 113 |
if relation:
|
|
|
|
| 114 |
op = "LIKE" if "%" in relation else "="
|
| 115 |
where_conditions.append(f"e.rel_id IN (SELECT id FROM relation WHERE label {op} ?)")
|
| 116 |
params.append(relation)
|
| 117 |
|
| 118 |
if end_node:
|
|
|
|
| 119 |
param_val = end_node if "%" in end_node else f"%{end_node}"
|
| 120 |
where_conditions.append(f"e.end_id IN (SELECT id FROM node WHERE id LIKE ?)")
|
| 121 |
params.append(param_val)
|
|
|
|
| 122 |
|
| 123 |
if not where_conditions:
|
| 124 |
where_clause = " WHERE 1=1" # Get random edges if no filter
|
|
|
|
| 169 |
traceback.print_exc()
|
| 170 |
return pd.DataFrame(), f"**Query Failed!**\n\n`{e}`"
|
| 171 |
|
| 172 |
+
def get_semantic_profile(word, lang='en'):
|
| 173 |
+
"""
|
| 174 |
+
NEW FUNCTION: Gets a convenient profile of a single word,
|
| 175 |
+
querying for its most important semantic relations.
|
| 176 |
+
"""
|
| 177 |
+
if not word:
|
| 178 |
+
return "Please enter a word."
|
| 179 |
+
|
| 180 |
+
word = word.strip().lower().replace(' ', '_')
|
| 181 |
+
like_path = f"%/c/{lang}/{word}"
|
| 182 |
+
print(f"Getting semantic profile for: {like_path}")
|
| 183 |
+
|
| 184 |
+
# These are the relations we learned about from relations.py
|
| 185 |
+
relations_to_check = [
|
| 186 |
+
"/r/IsA", "/r/PartOf", "/r/HasA", "/r/UsedFor", "/r/CapableOf",
|
| 187 |
+
"/r/Causes", "/r/HasProperty", "/r/Synonym", "/r/Antonym",
|
| 188 |
+
"/r/AtLocation", "/r/RelatedTo"
|
| 189 |
+
]
|
| 190 |
+
|
| 191 |
+
output_md = f"# Semantic Profile for '{word}'\n\n"
|
| 192 |
+
|
| 193 |
+
try:
|
| 194 |
+
with get_db_connection() as conn:
|
| 195 |
+
for rel in relations_to_check:
|
| 196 |
+
output_md += f"## {rel}\n\n"
|
| 197 |
+
|
| 198 |
+
# Query 1: Word as the start node
|
| 199 |
+
query1 = """
|
| 200 |
+
SELECT en.id, en.label
|
| 201 |
+
FROM edge e
|
| 202 |
+
JOIN node s ON e.start_id = s.id
|
| 203 |
+
JOIN node en ON e.end_id = en.id
|
| 204 |
+
JOIN relation r ON e.rel_id = r.id
|
| 205 |
+
WHERE s.id LIKE ? AND r.label = ?
|
| 206 |
+
ORDER BY e.weight DESC LIMIT 7
|
| 207 |
+
"""
|
| 208 |
+
cursor1 = conn.execute(query1, (like_path, rel))
|
| 209 |
+
results1 = cursor1.fetchall()
|
| 210 |
+
|
| 211 |
+
# Query 2: Word as the end node
|
| 212 |
+
query2 = """
|
| 213 |
+
SELECT s.id, s.label
|
| 214 |
+
FROM edge e
|
| 215 |
+
JOIN node s ON e.start_id = s.id
|
| 216 |
+
JOIN node en ON e.end_id = en.id
|
| 217 |
+
JOIN relation r ON e.rel_id = r.id
|
| 218 |
+
WHERE en.id LIKE ? AND r.label = ?
|
| 219 |
+
ORDER BY e.weight DESC LIMIT 7
|
| 220 |
+
"""
|
| 221 |
+
cursor2 = conn.execute(query2, (like_path, rel))
|
| 222 |
+
results2 = cursor2.fetchall()
|
| 223 |
+
|
| 224 |
+
if not results1 and not results2:
|
| 225 |
+
output_md += "- (No results)\n\n"
|
| 226 |
+
else:
|
| 227 |
+
for r_id, r_label in results1:
|
| 228 |
+
output_md += f"- `{word}` {rel} `{r_label}` *({r_id})*\n"
|
| 229 |
+
for r_id, r_label in results2:
|
| 230 |
+
output_md += f"- `{r_label}` {rel} `{word}` *({r_id})*\n"
|
| 231 |
+
output_md += "\n"
|
| 232 |
+
|
| 233 |
+
return output_md
|
| 234 |
+
|
| 235 |
+
except Exception as e:
|
| 236 |
+
print(f"Error in get_semantic_profile: {e}")
|
| 237 |
+
traceback.print_exc()
|
| 238 |
+
return f"**An error occurred while building the profile:**\n\n`{e}`"
|
| 239 |
|
| 240 |
# --- 3. Build the Gradio UI ---
|
| 241 |
|
|
|
|
| 244 |
gr.Markdown(f"**Note:** Initial query might take a few seconds as the database warms up.")
|
| 245 |
|
| 246 |
with gr.Tabs():
|
| 247 |
+
with gr.TabItem("Semantic Profile"):
|
| 248 |
+
gr.Markdown(
|
| 249 |
+
"**Get a simple semantic profile for a single English word.**\n"
|
| 250 |
+
"This will query for common relations like `/r/IsA`, `/r/HasA`, `/r/UsedFor`, etc."
|
| 251 |
+
)
|
| 252 |
+
word_input = gr.Textbox(label="Word", placeholder="dog")
|
| 253 |
+
semantic_btn = gr.Button("Get Profile", variant="primary")
|
| 254 |
+
semantic_output = gr.Markdown("Profile will appear here...")
|
| 255 |
+
|
| 256 |
with gr.TabItem("Query Builder"):
|
| 257 |
gr.Markdown(
|
| 258 |
"**Run a query against the database.**\n"
|
|
|
|
| 260 |
"Use the *path part* of the ID (e.g., `/c/en/dog` or `/r/Is%`)."
|
| 261 |
)
|
| 262 |
with gr.Row():
|
|
|
|
| 263 |
start_input = gr.Textbox(label="Start Node Path", placeholder="/c/en/dog")
|
| 264 |
rel_input = gr.Textbox(label="Relation Path", placeholder="/r/IsA")
|
| 265 |
end_input = gr.Textbox(label="End Node Path", placeholder="/c/en/animal")
|
|
|
|
| 272 |
|
| 273 |
with gr.TabItem("Raw SQL Query"):
|
| 274 |
gr.Markdown("**Danger Zone:** Run a raw `SELECT` query against the database. Use the Schema Explorer tab to see table/column names.")
|
|
|
|
| 275 |
raw_sql_input = gr.Textbox(
|
| 276 |
label="Raw SQL Query",
|
| 277 |
+
placeholder="SELECT id, label, language FROM node WHERE id LIKE '%/c/en/dog' LIMIT 5",
|
| 278 |
lines=5
|
| 279 |
)
|
| 280 |
raw_query_btn = gr.Button("Run Raw SQL", variant="secondary")
|
|
|
|
| 287 |
schema_output = gr.Markdown("Schema will appear here...")
|
| 288 |
|
| 289 |
# --- 4. Connect UI Elements to Functions ---
|
| 290 |
+
semantic_btn.click(
|
| 291 |
+
fn=get_semantic_profile,
|
| 292 |
+
inputs=[word_input],
|
| 293 |
+
outputs=[semantic_output],
|
| 294 |
+
api_name="get_semantic_profile"
|
| 295 |
+
)
|
| 296 |
+
|
| 297 |
query_btn.click(
|
| 298 |
fn=run_query,
|
| 299 |
inputs=[start_input, rel_input, end_input, limit_slider],
|
|
|
|
| 316 |
)
|
| 317 |
|
| 318 |
if __name__ == "__main__":
|
|
|
|
| 319 |
demo.launch(ssr_mode=False)
|