{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Hawksight-AI/semantica/blob/main/cookbook/use_cases/intelligence/01_Criminal_Network_Analysis.ipynb)\n",
    "\n",
    "# Criminal Network Analysis - Graph Analytics & Centrality\n",
    "\n",
    "## Overview\n",
    "\n",
    "This notebook demonstrates **criminal network analysis** using Semantica with focus on **network centrality**, **community detection**, and **relationship mapping**. The pipeline processes OSINT feeds, police reports, and court records to build knowledge graphs for analyzing criminal networks and identifying key players and communities.\n",
    "\n",
    "### Key Features\n",
    "\n",
    "- **Network Centrality**: Uses centrality measures (degree, betweenness, closeness, eigenvector) to identify key players\n",
    "- **Community Detection**: Detects criminal communities and groups using Louvain and Leiden algorithms\n",
    "- **Relationship Mapping**: Maps relationships between persons, organizations, and events\n",
    "- **Graph Analytics**: Comprehensive graph analysis including path finding and connectivity\n",
    "- **Intelligence Reporting**: Generates intelligence reports from network analysis\n",
    "\n",
    "### Learning Objectives\n",
    "\n",
    "- Understand how to analyze criminal networks using graph analytics\n",
    "- Learn to identify key players using centrality measures\n",
    "- Master community detection algorithms for criminal group identification\n",
    "- Explore relationship mapping and path finding in networks\n",
    "- Practice graph analytics for intelligence reporting\n",
    "- Analyze network structure and connectivity patterns\n",
    "\n",
    "### Pipeline Flow\n",
    "\n",
    "```mermaid\n",
    "graph TD\n",
    "    A[Data Ingestion] --> B[Document Parsing]\n",
    "    B --> C[Text Processing]\n",
    "    C --> D[Entity Extraction]\n",
    "    D --> E[Relationship Extraction]\n",
    "    E --> F[Deduplication]\n",
    "    F --> G[KG Construction]\n",
    "    G --> H[Embedding Generation]\n",
    "    H --> I[Vector Store]\n",
    "    G --> J[Centrality Analysis]\n",
    "    G --> K[Community Detection]\n",
    "    G --> L[Graph Analytics]\n",
    "    I --> M[GraphRAG Queries]\n",
    "    J --> N[Visualization]\n",
    "    K --> N\n",
    "    L --> N\n",
    "    G --> O[Export]\n",
    "```\n",
    "\n",
    "\n",
    "---\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install -qU semantica networkx matplotlib plotly pandas faiss-cpu beautifulsoup4 groq sentence-transformers scikit-learn\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Configuration & Setup\n",
    "\n",
    "Configure API keys and set up constants for the criminal network analysis pipeline.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"GROQ_API_KEY\"] = os.getenv(\"GROQ_API_KEY\", \"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\")\n",
    "\n",
    "# Configuration constants\n",
    "EMBEDDING_DIMENSION = 384\n",
    "EMBEDDING_MODEL = \"sentence-transformers/all-MiniLM-L6-v2\"\n",
    "CHUNK_SIZE = 1000\n",
    "CHUNK_OVERLAP = 200\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Data Ingestion\n",
    "\n",
    "Ingest intelligence data from multiple sources including OSINT RSS feeds, web APIs, and local files.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.ingest import FeedIngestor, WebIngestor, FileIngestor\n",
    "from contextlib import redirect_stderr\n",
    "from io import StringIO\n",
    "import os\n",
    "\n",
    "os.makedirs(\"data\", exist_ok=True)\n",
    "\n",
    "documents = []\n",
    "\n",
    "# Ingest from OSINT RSS feeds\n",
    "osint_feeds = [\n",
    "    \"https://www.us-cert.gov/ncas/alerts.xml\",\n",
    "    \"https://www.europol.europa.eu/rss.xml\",\n",
    "    \"https://www.treasury.gov/resource-center/sanctions/OFAC-Enforcement/Pages/rss.xml\",\n",
    "    \"https://feeds.feedburner.com/oreilly/radar\",\n",
    "    \"https://krebsonsecurity.com/feed/\",\n",
    "    \"https://www.schneier.com/feed/\",\n",
    "    \"https://www.darkreading.com/rss.xml\",\n",
    "    \"https://threatpost.com/feed/\",\n",
    "    \"https://www.bleepingcomputer.com/feed/\",\n",
    "    \"https://www.securityweek.com/rss\",\n",
    "    \"https://www.infosecurity-magazine.com/rss/news/\",\n",
    "    \"https://www.csoonline.com/index.rss\"\n",
    "]\n",
    "\n",
    "feed_ingestor = FeedIngestor()\n",
    "for i, feed_url in enumerate(osint_feeds, 1):\n",
    "    try:\n",
    "        with redirect_stderr(StringIO()):\n",
    "            feed_data = feed_ingestor.ingest_feed(feed_url, validate=False)\n",
    "            \n",
    "            feed_count = 0\n",
    "            for item in feed_data.items:\n",
    "                if not item.content:\n",
    "                    item.content = item.description or item.title or \"\"\n",
    "                if item.content:\n",
    "                    if not hasattr(item, 'metadata'):\n",
    "                        item.metadata = {}\n",
    "                    item.metadata['source'] = feed_url\n",
    "                    documents.append(item)\n",
    "                    feed_count += 1\n",
    "            \n",
    "            if feed_count > 0:\n",
    "                print(f\"  [{i}/{len(osint_feeds)}] Feed: {feed_count} documents\")\n",
    "    except Exception as e:\n",
    "        print(f\"  [{i}/{len(osint_feeds)}] Feed failed: {str(e)[:50]}\")\n",
    "        pass\n",
    "\n",
    "# Web ingestion from various intelligence and security sources\n",
    "web_links = [\n",
    "    \"https://www.interpol.int/en/How-we-work/Notices/View-Red-Notices\",\n",
    "    \"https://www.unodc.org/unodc/en/data-and-analysis/index.html\",\n",
    "    \"https://www.cisa.gov/news-events/cybersecurity-advisories\",\n",
    "    \"https://www.us-cert.gov/ncas/alerts\",\n",
    "    \"https://www.europol.europa.eu/newsroom\",\n",
    "    \"https://www.ncsc.gov.uk/news\",\n",
    "    \"https://www.cyber.gov.au/news\"\n",
    "]\n",
    "\n",
    "web_ingestor = WebIngestor(respect_robots=False, delay=1.0)\n",
    "for i, web_url in enumerate(web_links, 1):\n",
    "    try:\n",
    "        with redirect_stderr(StringIO()):\n",
    "            web_content = web_ingestor.ingest_url(web_url)\n",
    "            if web_content and web_content.text:\n",
    "                # Add content attribute for compatibility with parser\n",
    "                web_content.content = web_content.text\n",
    "                if not hasattr(web_content, 'metadata'):\n",
    "                    web_content.metadata = {}\n",
    "                web_content.metadata['source'] = web_url\n",
    "                documents.append(web_content)\n",
    "                print(f\"  [{i}/{len(web_links)}] Web: {len(web_content.text)} characters\")\n",
    "    except Exception as e:\n",
    "        print(f\"  [{i}/{len(web_links)}] Web failed: {str(e)[:50]}\")\n",
    "        pass\n",
    "\n",
    "# Example: Web ingestion from FBI API (commented - requires authentication)\n",
    "# web_ingestor = WebIngestor()\n",
    "# fbi_docs = web_ingestor.ingest_url(\"https://api.fbi.gov/wanted/v1/list\")\n",
    "\n",
    "print(f\"Ingested {len(documents)} documents\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.parse import DocumentParser\n",
    "from contextlib import redirect_stderr\n",
    "from io import StringIO\n",
    "\n",
    "parser = DocumentParser()\n",
    "\n",
    "print(f\"Parsing {len(documents)} documents...\")\n",
    "parsed_documents = []\n",
    "for i, doc in enumerate(documents, 1):\n",
    "    try:\n",
    "        with redirect_stderr(StringIO()):\n",
    "            parsed = parser.parse(\n",
    "                doc.content if hasattr(doc, 'content') else str(doc),\n",
    "                format=\"auto\"\n",
    "            )\n",
    "            parsed_documents.append(parsed)\n",
    "    except Exception:\n",
    "        parsed_documents.append(doc.content if hasattr(doc, 'content') else str(doc))\n",
    "    if i % 50 == 0 or i == len(documents):\n",
    "        print(f\"  Parsed {i}/{len(documents)} documents...\")\n",
    "\n",
    "print(f\"Parsed {len(parsed_documents)} documents\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Text Processing\n",
    "\n",
    "Normalize entity names and split documents using entity-aware chunking to preserve network relationships.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.normalize import TextNormalizer\n",
    "from semantica.split import TextSplitter\n",
    "from contextlib import redirect_stderr\n",
    "from io import StringIO\n",
    "\n",
    "normalizer = TextNormalizer()\n",
    "print(f\"Normalizing {len(parsed_documents)} documents...\")\n",
    "normalized_docs = []\n",
    "\n",
    "for i, doc in enumerate(parsed_documents, 1):\n",
    "    try:\n",
    "        with redirect_stderr(StringIO()):\n",
    "            normalized = normalizer.normalize(\n",
    "                doc if isinstance(doc, str) else str(doc),\n",
    "                clean_html=True,\n",
    "                normalize_entities=True,\n",
    "                remove_extra_whitespace=True\n",
    "            )\n",
    "            normalized_docs.append(normalized)\n",
    "    except Exception:\n",
    "        normalized_docs.append(doc if isinstance(doc, str) else str(doc))\n",
    "    if i % 50 == 0 or i == len(parsed_documents):\n",
    "        print(f\"  Normalized {i}/{len(parsed_documents)} documents...\")\n",
    "\n",
    "# Use entity-aware chunking to preserve network relationships\n",
    "entity_splitter = TextSplitter(\n",
    "    method=\"entity_aware\",\n",
    "    chunk_size=CHUNK_SIZE,\n",
    "    chunk_overlap=CHUNK_OVERLAP\n",
    ")\n",
    "\n",
    "print(f\"Chunking {len(normalized_docs)} documents...\")\n",
    "chunked_docs = []\n",
    "for i, doc_text in enumerate(normalized_docs, 1):\n",
    "    try:\n",
    "        with redirect_stderr(StringIO()):\n",
    "            chunks = entity_splitter.split(doc_text)\n",
    "            chunked_docs.extend([chunk.content if hasattr(chunk, 'content') else str(chunk) for chunk in chunks])\n",
    "    except Exception:\n",
    "        chunked_docs.append(doc_text)\n",
    "    if i % 50 == 0 or i == len(normalized_docs):\n",
    "        print(f\"  Chunked {i}/{len(normalized_docs)} documents ({len(chunked_docs)} chunks so far)\")\n",
    "\n",
    "print(f\"Created {len(chunked_docs)} chunks from {len(normalized_docs)} documents\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Entity Extraction\n",
    "\n",
    "Extract criminal network entities including persons, organizations, events, locations, and relationships.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.semantic_extract import NERExtractor\n",
    "\n",
    "extractor = NERExtractor(method=\"ml\", model=\"en_core_web_sm\")\n",
    "chunks_to_process = chunked_docs[:10]\n",
    "entity_results = extractor.extract(chunks_to_process)\n",
    "\n",
    "all_entities = []\n",
    "relevant_types = [\"PERSON\", \"ORG\", \"GPE\", \"LOC\", \"EVENT\", \"DATE\"]\n",
    "for entities in entity_results:\n",
    "    all_entities.extend([e for e in entities if e.label in relevant_types])\n",
    "\n",
    "print(f\"Extracted {len(all_entities)} entities\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Relationship Extraction\n",
    "\n",
    "Extract network relationships between entities such as associations, connections, involvement, and location relationships.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.semantic_extract import RelationExtractor\n",
    "\n",
    "relation_extractor = RelationExtractor(\n",
    "    method=[\"dependency\", \"pattern\", \"cooccurrence\"],\n",
    "    model=\"en_core_web_sm\",\n",
    "    confidence_threshold=0.5,\n",
    "    max_distance=100\n",
    ")\n",
    "\n",
    "relevant_types = [\"PERSON\", \"ORG\", \"GPE\", \"LOC\", \"EVENT\", \"DATE\"]\n",
    "chunk_entities_list = [[e for e in entities if e.label in relevant_types] for entities in entity_results]\n",
    "relation_results = relation_extractor.extract(chunks_to_process, chunk_entities_list)\n",
    "\n",
    "all_relationships = []\n",
    "seen = set()\n",
    "for relationships in relation_results:\n",
    "    for rel in relationships:\n",
    "        key = (rel.subject.text, rel.predicate, rel.object.text)\n",
    "        if key not in seen:\n",
    "            seen.add(key)\n",
    "            all_relationships.append(rel)\n",
    "\n",
    "print(f\"Extracted {len(all_relationships)} relationships\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conflict Detection\n",
    "\n",
    "Detect and resolve conflicts in intelligence data from multiple sources. Intelligence sources have different credibility levels.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.conflicts import ConflictDetector, ConflictResolver\n",
    "\n",
    "conflict_detector = ConflictDetector()\n",
    "conflict_resolver = ConflictResolver()\n",
    "\n",
    "entity_dicts = [\n",
    "    {\n",
    "        \"id\": getattr(e, \"text\", str(e)),\n",
    "        \"text\": getattr(e, \"text\", str(e)),\n",
    "        \"label\": getattr(e, \"label\", \"\"),\n",
    "        \"metadata\": getattr(e, \"metadata\", {})\n",
    "    }\n",
    "    for e in all_entities\n",
    "]\n",
    "\n",
    "print(f\"Detecting conflicts in {len(entity_dicts)} entities...\")\n",
    "conflicts = conflict_detector.detect_entity_conflicts(entity_dicts)\n",
    "\n",
    "if all_relationships:\n",
    "    relationship_dicts = [\n",
    "        {\n",
    "            \"source_id\": getattr(rel.subject, \"text\", str(rel.subject)),\n",
    "            \"target_id\": getattr(rel.object, \"text\", str(rel.object)),\n",
    "            \"type\": rel.predicate,\n",
    "            \"confidence\": rel.confidence,\n",
    "            \"metadata\": rel.metadata\n",
    "        }\n",
    "        for rel in all_relationships\n",
    "    ]\n",
    "    relationship_conflicts = conflict_detector.detect_relationship_conflicts(relationship_dicts)\n",
    "    conflicts.extend(relationship_conflicts)\n",
    "\n",
    "print(f\"Detected {len(conflicts)} conflicts\")\n",
    "\n",
    "if conflicts:\n",
    "    resolved = conflict_resolver.resolve_conflicts(\n",
    "        conflicts,\n",
    "        strategy=\"credibility_weighted\"\n",
    "    )\n",
    "    print(f\"Resolved {len(resolved)} conflicts\")\n",
    "else:\n",
    "    print(\"No conflicts detected\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Knowledge Graph Construction\n",
    "\n",
    "Build the criminal network knowledge graph from extracted entities and relationships.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import GraphBuilder\n",
    "\n",
    "builder = GraphBuilder()\n",
    "\n",
    "print(f\"Building knowledge graph...\")\n",
    "kg = builder.build(\n",
    "    sources=all_entities,\n",
    "    relationships=all_relationships\n",
    ")\n",
    "\n",
    "print(f\"Built KG with {len(kg.get('entities', []))} entities and {len(kg.get('relationships', []))} relationships\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Embedding Generation & Vector Store\n",
    "\n",
    "Generate embeddings for intelligence documents and store them in a vector database for semantic search.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.embeddings import EmbeddingGenerator\n",
    "from semantica.vector_store import VectorStore\n",
    "\n",
    "embedding_gen = EmbeddingGenerator(model_name=EMBEDDING_MODEL, dimension=EMBEDDING_DIMENSION)\n",
    "chunks_to_embed = chunked_docs[:20]\n",
    "\n",
    "embeddings = embedding_gen.generate_embeddings(chunks_to_embed)\n",
    "\n",
    "vector_store = VectorStore(backend=\"faiss\", dimension=EMBEDDING_DIMENSION)\n",
    "for i, (chunk, embedding) in enumerate(zip(chunks_to_embed, embeddings)):\n",
    "    vector_store.add(str(i), embedding, {\"text\": chunk[:100]})\n",
    "\n",
    "print(f\"Generated {len(embeddings)} embeddings and stored in vector database\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Network Centrality Analysis\n",
    "\n",
    "Calculate centrality measures to identify key players in the criminal network. This is unique to this notebook and critical for intelligence analysis.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import CentralityCalculator\n",
    "\n",
    "calculator = CentralityCalculator()\n",
    "all_centrality = calculator.calculate_all_centrality(kg)\n",
    "\n",
    "degree = all_centrality[\"centrality_measures\"][\"degree\"]\n",
    "betweenness = all_centrality[\"centrality_measures\"][\"betweenness\"]\n",
    "\n",
    "print(f\"Top 5 key players: {[p['node'] for p in degree['rankings'][:5]]}\")\n",
    "print(f\"Top 5 brokers: {[b['node'] for b in betweenness['rankings'][:5]]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Community Detection\n",
    "\n",
    "Detect criminal communities and groups in the network. This is unique to this notebook and helps identify organized crime structures.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import CommunityDetector\n",
    "\n",
    "detector = CommunityDetector()\n",
    "communities = detector.detect_communities(kg, \"louvain\")\n",
    "overlapping = detector.detect_communities(kg, \"overlapping\")\n",
    "\n",
    "print(f\"Detected {len(communities.get('communities', []))} communities\")\n",
    "print(f\"Detected {len(overlapping.get('communities', []))} overlapping communities\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Graph Analytics\n",
    "\n",
    "Perform comprehensive graph analytics including path finding and connectivity analysis to understand network structure.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import GraphAnalyzer\n",
    "\n",
    "analyzer = GraphAnalyzer()\n",
    "results = analyzer.analyze_graph(kg)\n",
    "\n",
    "stats = results.get(\"metrics\", {})\n",
    "connectivity = results.get(\"connectivity\", {})\n",
    "\n",
    "print(f\"Graph: {stats.get('num_nodes', 0)} nodes, {stats.get('num_edges', 0)} edges\")\n",
    "print(f\"Connected components: {len(connectivity.get('components', []))}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## GraphRAG Queries\n",
    "\n",
    "Use hybrid retrieval combining vector search and graph traversal to answer complex intelligence questions.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.context import AgentContext, ContextGraph\n",
    "from semantica.llms import Groq\n",
    "import os\n",
    "\n",
    "context_graph = ContextGraph()\n",
    "context_graph.build_from_entities_and_relationships(\n",
    "    entities=kg.get('entities', []),\n",
    "    relationships=[{**r, 'source_id': r.get('source_id') or r.get('source'), 'target_id': r.get('target_id') or r.get('target')} for r in kg.get('relationships', [])]\n",
    ")\n",
    "\n",
    "graph_stats = context_graph.stats()\n",
    "print(f\"Intelligence Context Graph: {graph_stats['node_count']} nodes, {graph_stats['edge_count']} edges\")\n",
    "\n",
    "context = AgentContext(\n",
    "    vector_store=vector_store,\n",
    "    knowledge_graph=context_graph,\n",
    "    hybrid_alpha=0.7,\n",
    "    use_graph_expansion=True,\n",
    "    max_expansion_hops=3\n",
    ")\n",
    "\n",
    "for chunk in chunked_docs[:30]:\n",
    "    if chunk and chunk.strip():\n",
    "        context.store(\n",
    "            content=chunk,\n",
    "            metadata={'source': 'criminal_intelligence'},\n",
    "            extract_entities=True,\n",
    "            link_entities=True\n",
    "        )\n",
    "\n",
    "llm = Groq(model=\"llama-3.1-8b-instant\", api_key=os.getenv(\"GROQ_API_KEY\"))\n",
    "\n",
    "intelligence_queries = [\n",
    "    \"Who are the key players and central nodes in the criminal network?\",\n",
    "    \"What are the operational relationships between criminal organizations?\"\n",
    "]\n",
    "\n",
    "print(\"\\n\" + \"=\" * 80)\n",
    "print(\"Criminal Intelligence Analysis - GraphRAG with Multi-Hop Reasoning\")\n",
    "print(\"=\" * 80)\n",
    "\n",
    "for query in intelligence_queries:\n",
    "    print(f\"\\n{'='*80}\")\n",
    "    print(f\"Intelligence Query: {query}\")\n",
    "    print(f\"{'='*80}\\n\")\n",
    "    \n",
    "    result = context.query_with_reasoning(\n",
    "        query=query,\n",
    "        llm_provider=llm,\n",
    "        max_results=15,\n",
    "        max_hops=3,\n",
    "        min_score=0.2\n",
    "    )\n",
    "    \n",
    "    print(f\"Generated Response:\\n{result.get('response', 'No response available')}\\n\")\n",
    "    \n",
    "    if result.get('reasoning_path'):\n",
    "        print(f\"Reasoning Path:\\n{result.get('reasoning_path')}\\n\")\n",
    "    \n",
    "    print(f\"Confidence: {result.get('confidence', 0):.3f}\")\n",
    "    print(f\"Sources: {result.get('num_sources', 0)}\")\n",
    "    print(f\"Reasoning Paths: {result.get('num_reasoning_paths', 0)}\")\n",
    "    print()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Visualization\n",
    "\n",
    "Visualize the criminal network to explore relationships, communities, and key players.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.visualization import KGVisualizer\n",
    "\n",
    "visualizer = KGVisualizer(layout=\"force\", color_scheme=\"vibrant\")\n",
    "visualizer.visualize_network(kg, output=\"interactive\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Export\n",
    "\n",
    "Export the knowledge graph in multiple formats for intelligence reporting and further analysis.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.export import GraphExporter, JSONExporter, CSVExporter\n",
    "\n",
    "GraphExporter().export_knowledge_graph(kg, \"criminal_network.graphml\", format=\"graphml\")\n",
    "JSONExporter().export_knowledge_graph(kg, \"criminal_network.json\")\n",
    "CSVExporter().export_knowledge_graph(kg, \"criminal_network.csv\")\n",
    "\n",
    "print(\"Exported knowledge graph in JSON, GraphML, and CSV formats\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
