Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -335,6 +335,42 @@ def build_knowledge_graph(entities_data):
|
|
335 |
|
336 |
return pil_image
|
337 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
338 |
def build_kg(url_or_text):
|
339 |
"""Main function to build knowledge graph from URL or text.
|
340 |
|
@@ -342,7 +378,7 @@ def build_kg(url_or_text):
|
|
342 |
url_or_text: URL to analyze or direct text input
|
343 |
|
344 |
Returns:
|
345 |
-
String: JSON containing entities, relationships, and
|
346 |
"""
|
347 |
try:
|
348 |
if not url_or_text or len(url_or_text.strip()) == 0:
|
@@ -357,100 +393,61 @@ def build_kg(url_or_text):
|
|
357 |
# Step 2: Extract entities
|
358 |
entities_data = extract_entities(content)
|
359 |
|
360 |
-
# Step 3: Create
|
361 |
-
|
362 |
-
|
|
|
|
|
|
|
|
|
|
|
363 |
|
364 |
summary = f"""Knowledge Graph Analysis Complete!
|
365 |
|
366 |
Statistics:
|
367 |
-
- Entities
|
368 |
-
- Relationships
|
369 |
- Content length: {len(content)} characters
|
370 |
|
371 |
-
|
372 |
|
373 |
-
for entity in
|
374 |
name = entity.get('name', 'Unknown')
|
375 |
entity_type = entity.get('type', 'UNKNOWN')
|
376 |
-
|
377 |
-
summary += f"\nβ’ {name} ({entity_type}): {desc}"
|
378 |
|
379 |
-
if len(
|
380 |
-
summary += f"\n... and {len(
|
381 |
|
382 |
-
# Create
|
383 |
response = {
|
384 |
"success": True,
|
385 |
-
"entities":
|
386 |
-
"relationships":
|
|
|
387 |
"summary": summary,
|
388 |
-
"
|
389 |
"entity_count": num_entities,
|
390 |
"relationship_count": num_relationships,
|
391 |
"content_length": len(content)
|
392 |
}
|
393 |
}
|
394 |
|
395 |
-
return json.dumps(response,
|
396 |
|
397 |
except Exception as e:
|
398 |
error_msg = f"Analysis failed: {str(e)}"
|
399 |
-
print(f"Function error: {error_msg}")
|
400 |
return json.dumps({"success": False, "error": error_msg})
|
401 |
|
402 |
# Create Gradio interface with error handling
|
403 |
try:
|
404 |
-
def parse_kg_output(json_result):
|
405 |
-
"""Parse the JSON result and return separate components for UI"""
|
406 |
-
try:
|
407 |
-
data = json.loads(json_result) if isinstance(json_result, str) else json_result
|
408 |
-
if data.get("success"):
|
409 |
-
entities_json = {
|
410 |
-
"entities": data.get("entities", []),
|
411 |
-
"relationships": data.get("relationships", [])
|
412 |
-
}
|
413 |
-
summary = data.get("summary", "No summary available")
|
414 |
-
return json.dumps(entities_json, indent=2), summary
|
415 |
-
else:
|
416 |
-
error_msg = data.get("error", "Unknown error")
|
417 |
-
return json.dumps({"error": error_msg}), f"Error: {error_msg}"
|
418 |
-
except Exception as e:
|
419 |
-
return json.dumps({"error": str(e)}), f"Parse error: {str(e)}"
|
420 |
-
|
421 |
-
def kg_interface(url_or_text):
|
422 |
-
"""Interface wrapper for the knowledge graph builder"""
|
423 |
-
result = build_kg(url_or_text)
|
424 |
-
return parse_kg_output(result)
|
425 |
-
|
426 |
demo = gr.Interface(
|
427 |
-
fn=
|
428 |
-
inputs=
|
429 |
-
|
430 |
-
label="URL or Text Input",
|
431 |
-
placeholder="Enter a URL (https://example.com) or paste text directly...",
|
432 |
-
lines=3,
|
433 |
-
info="Enter a website URL to analyze, or paste text content directly"
|
434 |
-
)
|
435 |
-
],
|
436 |
-
outputs=[
|
437 |
-
gr.JSON(label="Extracted Entities & Relationships"),
|
438 |
-
gr.Markdown(label="Analysis Summary")
|
439 |
-
],
|
440 |
title="π§ KG Builder",
|
441 |
-
description=""
|
442 |
-
|
443 |
-
|
444 |
-
This tool:
|
445 |
-
1. π Extracts content from URLs or analyzes your text
|
446 |
-
2. π€ Uses AI to identify entities and relationships
|
447 |
-
3. π Provides detailed analysis summaries
|
448 |
-
|
449 |
-
**Try with:** news articles, Wikipedia pages, or any text content
|
450 |
-
""",
|
451 |
-
theme=gr.themes.Soft(),
|
452 |
-
allow_flagging="never",
|
453 |
-
cache_examples=False # Disable example caching to prevent startup errors
|
454 |
)
|
455 |
|
456 |
except Exception as e:
|
|
|
335 |
|
336 |
return pil_image
|
337 |
|
338 |
+
def build_ascii_diagram(entities, relationships):
|
339 |
+
"""Create simple ASCII diagram of knowledge graph"""
|
340 |
+
if not entities:
|
341 |
+
return "No entities to visualize"
|
342 |
+
|
343 |
+
diagram = "KNOWLEDGE GRAPH DIAGRAM:\n"
|
344 |
+
diagram += "=" * 50 + "\n\n"
|
345 |
+
|
346 |
+
# Show entities by type
|
347 |
+
entity_types = {}
|
348 |
+
for entity in entities[:10]: # Limit to 10
|
349 |
+
etype = entity.get("type", "UNKNOWN")
|
350 |
+
if etype not in entity_types:
|
351 |
+
entity_types[etype] = []
|
352 |
+
entity_types[etype].append(entity.get("name", "Unknown"))
|
353 |
+
|
354 |
+
for etype, names in entity_types.items():
|
355 |
+
diagram += f"π {etype}:\n"
|
356 |
+
for name in names:
|
357 |
+
diagram += f" β’ {name}\n"
|
358 |
+
diagram += "\n"
|
359 |
+
|
360 |
+
# Show relationships
|
361 |
+
if relationships:
|
362 |
+
diagram += "π RELATIONSHIPS:\n"
|
363 |
+
for rel in relationships[:8]: # Limit to 8
|
364 |
+
source = rel.get("source", "?")
|
365 |
+
target = rel.get("target", "?")
|
366 |
+
relation = rel.get("relation", "related")
|
367 |
+
diagram += f" {source} --[{relation}]--> {target}\n"
|
368 |
+
|
369 |
+
if len(relationships) > 8:
|
370 |
+
diagram += f" ... and {len(relationships) - 8} more relationships\n"
|
371 |
+
|
372 |
+
return diagram
|
373 |
+
|
374 |
def build_kg(url_or_text):
|
375 |
"""Main function to build knowledge graph from URL or text.
|
376 |
|
|
|
378 |
url_or_text: URL to analyze or direct text input
|
379 |
|
380 |
Returns:
|
381 |
+
String: JSON containing entities, relationships, and simple diagram
|
382 |
"""
|
383 |
try:
|
384 |
if not url_or_text or len(url_or_text.strip()) == 0:
|
|
|
393 |
# Step 2: Extract entities
|
394 |
entities_data = extract_entities(content)
|
395 |
|
396 |
+
# Step 3: Create simple ASCII diagram
|
397 |
+
entities = entities_data.get("entities", [])
|
398 |
+
relationships = entities_data.get("relationships", [])
|
399 |
+
ascii_diagram = build_ascii_diagram(entities, relationships)
|
400 |
+
|
401 |
+
# Step 4: Create summary
|
402 |
+
num_entities = len(entities)
|
403 |
+
num_relationships = len(relationships)
|
404 |
|
405 |
summary = f"""Knowledge Graph Analysis Complete!
|
406 |
|
407 |
Statistics:
|
408 |
+
- Entities: {num_entities}
|
409 |
+
- Relationships: {num_relationships}
|
410 |
- Content length: {len(content)} characters
|
411 |
|
412 |
+
Top Entities:"""
|
413 |
|
414 |
+
for entity in entities[:5]: # Show first 5
|
415 |
name = entity.get('name', 'Unknown')
|
416 |
entity_type = entity.get('type', 'UNKNOWN')
|
417 |
+
summary += f"\nβ’ {name} ({entity_type})"
|
|
|
418 |
|
419 |
+
if len(entities) > 5:
|
420 |
+
summary += f"\n... and {len(entities) - 5} more"
|
421 |
|
422 |
+
# Create MCP-friendly response
|
423 |
response = {
|
424 |
"success": True,
|
425 |
+
"entities": entities,
|
426 |
+
"relationships": relationships,
|
427 |
+
"diagram": ascii_diagram,
|
428 |
"summary": summary,
|
429 |
+
"stats": {
|
430 |
"entity_count": num_entities,
|
431 |
"relationship_count": num_relationships,
|
432 |
"content_length": len(content)
|
433 |
}
|
434 |
}
|
435 |
|
436 |
+
return json.dumps(response, ensure_ascii=True)
|
437 |
|
438 |
except Exception as e:
|
439 |
error_msg = f"Analysis failed: {str(e)}"
|
|
|
440 |
return json.dumps({"success": False, "error": error_msg})
|
441 |
|
442 |
# Create Gradio interface with error handling
|
443 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
444 |
demo = gr.Interface(
|
445 |
+
fn=build_kg,
|
446 |
+
inputs="text",
|
447 |
+
outputs="text",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
448 |
title="π§ KG Builder",
|
449 |
+
description="Transform text or URLs into knowledge graphs for AI agents.",
|
450 |
+
allow_flagging="never"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
451 |
)
|
452 |
|
453 |
except Exception as e:
|