{
 "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/supply_chain/01_Supply_Chain_Data_Integration.ipynb)\n",
    "\n",
    "# Supply Chain Data Integration - Multi-Source Ingestion & Relationship Mapping\n",
    "\n",
    "## Overview\n",
    "\n",
    "This notebook demonstrates **supply chain data integration** using Semantica with focus on **multi-source ingestion**, **relationship mapping**, and **logistics tracking**. The pipeline ingests logistics and supplier data from multiple sources to build a comprehensive supply chain knowledge graph with supplier network analysis.\n",
    "\n",
    "### Key Features\n",
    "\n",
    "- **Multi-Source Ingestion**: Ingests data from multiple logistics and supplier sources (RSS, web APIs, files)\n",
    "- **Relationship Mapping**: Maps supplier relationships and logistics routes using relation extraction\n",
    "- **Logistics Tracking**: Tracks products, routes, locations, and warehouses\n",
    "- **Supplier Network Analysis**: Analyzes supplier centrality and community clusters\n",
    "- **Seed Data Integration**: Uses supplier foundation data for entity resolution\n",
    "- **KG Construction**: Builds comprehensive supply chain knowledge graphs\n",
    "\n",
    "### Learning Objectives\n",
    "\n",
    "- Understand how to ingest data from multiple sources for supply chain integration\n",
    "- Learn to map complex supplier relationships and logistics routes\n",
    "- Master supplier network analysis using centrality and community detection\n",
    "- Explore relationship extraction for supply chain entities\n",
    "- Practice multi-source data integration and deduplication\n",
    "- Analyze supplier networks and logistics connections\n",
    "\n",
    "### Pipeline Flow\n",
    "\n",
    "```mermaid\n",
    "graph TD\n",
    "    A[Multi-Source Ingestion] --> B[Seed Data Loading]\n",
    "    A --> C[Document Parsing]\n",
    "    B --> D[Text Processing]\n",
    "    C --> D\n",
    "    D --> E[Entity Extraction]\n",
    "    E --> F[Relationship Extraction]\n",
    "    F --> G[Deduplication]\n",
    "    G --> H[KG Construction]\n",
    "    H --> I[Embedding Generation]\n",
    "    I --> J[Vector Store]\n",
    "    H --> K[Network Analysis]\n",
    "    H --> L[Community Detection]\n",
    "    J --> M[GraphRAG Queries]\n",
    "    K --> N[Visualization]\n",
    "    L --> N\n",
    "    H --> 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 supply chain data integration 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",
    "## Multi-Source Data Ingestion\n",
    "\n",
    "Ingest supply chain data from multiple sources including RSS feeds, web APIs, and local files. This section emphasizes multi-source ingestion capabilities.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.ingest import FeedIngestor, WebIngestor, FileIngestor\n",
    "import os\n",
    "\n",
    "os.makedirs(\"data\", exist_ok=True)\n",
    "\n",
    "documents = []\n",
    "\n",
    "# Ingest from logistics RSS feeds\n",
    "logistics_feeds = [\n",
    "    (\"Supply Chain Dive\", \"https://www.supplychaindive.com/rss\"),\n",
    "    (\"Logistics Management\", \"https://www.logisticsmgmt.com/rss\"),\n",
    "    (\"SCMR\", \"https://www.scmr.com/rss\"),\n",
    "    (\"DC Velocity\", \"https://www.dcvelocity.com/rss\"),\n",
    "    (\"Inbound Logistics\", \"https://www.inboundlogistics.com/rss\"),\n",
    "    (\"Supply Chain Brain\", \"https://www.supplychainbrain.com/rss\"),\n",
    "    (\"MHL News\", \"https://www.mhlnews.com/rss\")\n",
    "]\n",
    "\n",
    "feed_ingestor = FeedIngestor()\n",
    "print(f\"Ingesting from {len(logistics_feeds)} RSS feed sources...\")\n",
    "for i, (feed_name, feed_url) in enumerate(logistics_feeds, 1):\n",
    "    try:\n",
    "        feed_data = feed_ingestor.ingest_feed(feed_url, validate=False)\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_name\n",
    "                documents.append(item)\n",
    "                feed_count += 1\n",
    "        if feed_count > 0:\n",
    "            print(f\"  [{i}/{len(logistics_feeds)}] {feed_name}: {feed_count} documents\")\n",
    "    except Exception as e:\n",
    "        print(f\"  [{i}/{len(logistics_feeds)}] {feed_name}: Failed - {str(e)[:50]}\")\n",
    "\n",
    "# Web ingestion from supply chain data sources\n",
    "web_sources = [\n",
    "    (\"Supply Chain Dive News\", \"https://www.supplychaindive.com/news\"),\n",
    "    (\"Logistics Management News\", \"https://www.logisticsmgmt.com/news\"),\n",
    "    (\"SCMR Articles\", \"https://www.scmr.com/articles\"),\n",
    "    (\"DC Velocity Articles\", \"https://www.dcvelocity.com/articles\")\n",
    "]\n",
    "\n",
    "web_ingestor = WebIngestor(respect_robots=True, delay=1.0)\n",
    "print(f\"\\nIngesting from {len(web_sources)} web sources...\")\n",
    "for i, (source_name, web_url) in enumerate(web_sources, 1):\n",
    "    try:\n",
    "        web_content = web_ingestor.ingest_url(web_url)\n",
    "        if web_content.text:\n",
    "            # Create a document-like object from WebContent\n",
    "            class WebDoc:\n",
    "                def __init__(self, content, title, url, source):\n",
    "                    self.content = content\n",
    "                    self.title = title\n",
    "                    self.url = url\n",
    "                    self.metadata = {'source': source}\n",
    "            doc = WebDoc(web_content.text, web_content.title, web_content.url, source_name)\n",
    "            documents.append(doc)\n",
    "            print(f\"  [{i}/{len(web_sources)}] {source_name}: 1 document\")\n",
    "    except Exception as e:\n",
    "        print(f\"  [{i}/{len(web_sources)}] {source_name}: Failed - {str(e)[:50]}\")\n",
    "\n",
    "print(f\"\\nIngested {len(documents)} documents from multiple sources\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.seed import SeedDataManager\n",
    "\n",
    "seed_manager = SeedDataManager()\n",
    "\n",
    "# Load supplier foundation seed data\n",
    "supplier_foundation = {\n",
    "    \"suppliers\": [\"Supplier A\", \"Supplier B\", \"Supplier C\", \"Global Suppliers Inc\"],\n",
    "    \"warehouses\": [\"Warehouse W1\", \"Warehouse W2\", \"Warehouse W3\"],\n",
    "    \"locations\": [\"City C1\", \"City C2\", \"Region R1\", \"Region R2\"],\n",
    "    \"products\": [\"Product X\", \"Product Y\", \"Product Z\"],\n",
    "    \"routes\": [\"Route R1\", \"Route R2\", \"Route R3\"]\n",
    "}\n",
    "\n",
    "# Convert dictionary to entity records\n",
    "entity_records = []\n",
    "for entity_type, entity_names in supplier_foundation.items():\n",
    "    for name in entity_names:\n",
    "        entity_records.append({\n",
    "            \"id\": name.replace(\" \", \"_\").lower(),\n",
    "            \"text\": name,\n",
    "            \"name\": name,\n",
    "            \"entity_type\": entity_type.rstrip(\"s\").capitalize(),  # Remove plural and capitalize\n",
    "            \"type\": entity_type.rstrip(\"s\").capitalize(),\n",
    "            \"source\": \"supplier_foundation\",\n",
    "            \"verified\": True\n",
    "        })\n",
    "\n",
    "# Add entities to seed data\n",
    "seed_manager.seed_data.entities = entity_records\n",
    "\n",
    "print(f\"Loaded seed data with {len(entity_records)} entities\")\n",
    "print(f\"Entity types: {set(e['type'] for e in entity_records)}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Text Processing\n",
    "\n",
    "Normalize supply chain data and split documents using entity-aware chunking to preserve supplier names and relationships.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.normalize import TextNormalizer\n",
    "from semantica.split import TextSplitter\n",
    "\n",
    "normalizer = TextNormalizer()\n",
    "normalized_docs = []\n",
    "\n",
    "for doc in documents:\n",
    "    try:\n",
    "        doc_content = doc.content if hasattr(doc, 'content') else str(doc)\n",
    "        normalized = normalizer.normalize(\n",
    "            doc_content,\n",
    "            clean_html=True,\n",
    "            normalize_entities=True,\n",
    "            normalize_numbers=True,\n",
    "            remove_extra_whitespace=True\n",
    "        )\n",
    "        normalized_docs.append(normalized)\n",
    "    except Exception:\n",
    "        normalized_docs.append(doc.content if hasattr(doc, 'content') else str(doc))\n",
    "\n",
    "# Use entity-aware chunking to preserve supplier names and relationships\n",
    "entity_splitter = TextSplitter(\n",
    "    method=\"entity_aware\",\n",
    "    chunk_size=CHUNK_SIZE,\n",
    "    chunk_overlap=CHUNK_OVERLAP\n",
    ")\n",
    "\n",
    "chunked_docs = []\n",
    "for doc_text in normalized_docs:\n",
    "    try:\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",
    "\n",
    "print(f\"Processed {len(chunked_docs)} entity-aware chunks\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.semantic_extract import NERExtractor\n",
    "\n",
    "# Use ML-based approach (spaCy) for entity extraction\n",
    "extractor = NERExtractor(\n",
    "    method=\"ml\",\n",
    "    model=\"en_core_web_sm\"\n",
    ")\n",
    "\n",
    "entity_types = [\n",
    "    \"Supplier\", \"Product\", \"Route\", \"Location\", \"Logistics\", \"Warehouse\", \"Makinson\"\n",
    "]\n",
    "\n",
    "all_entities = []\n",
    "chunks_to_process = chunked_docs  # Process all chunks\n",
    "print(f\"Extracting entities from {len(chunks_to_process)} chunks using ML-based approach...\")\n",
    "for i, chunk in enumerate(chunks_to_process, 1):\n",
    "    try:\n",
    "        entities = extractor.extract(\n",
    "            chunk,\n",
    "            entity_types=entity_types\n",
    "        )\n",
    "        all_entities.extend(entities)\n",
    "    except Exception as e:\n",
    "        print(f\"  Error processing chunk {i}: {str(e)[:50]}\")\n",
    "        pass\n",
    "    \n",
    "    if i % 5 == 0 or i == len(chunks_to_process):\n",
    "        print(f\"  Processed {i}/{len(chunks_to_process)} chunks ({len(all_entities)} entities found)\")\n",
    "\n",
    "print(f\"Extracted {len(all_entities)} entities\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Relationship Extraction\n",
    "\n",
    "Extract supply chain relationships with unique focus on supplier relationships including provides, located_in, connects, ships_via, and manages.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.semantic_extract import RelationExtractor, NERExtractor\n",
    "\n",
    "# Use ML-based approach (dependency parsing with spaCy) for relation extraction\n",
    "relation_extractor = RelationExtractor(\n",
    "    method=\"dependency\",  # ML-based dependency parsing\n",
    "    model=\"en_core_web_sm\"\n",
    ")\n",
    "\n",
    "# Create NER extractor once for efficiency\n",
    "ner = NERExtractor(method=\"ml\", model=\"en_core_web_sm\")\n",
    "\n",
    "relation_types = [\n",
    "    \"provides\", \"located_in\", \"connects\",\n",
    "    \"ships_via\", \"manages\"\n",
    "]\n",
    "\n",
    "all_relationships = []\n",
    "chunks_to_process = chunked_docs  # Process all chunks\n",
    "print(f\"Extracting relationships from {len(chunks_to_process)} chunks using ML-based approach...\")\n",
    "for i, chunk in enumerate(chunks_to_process, 1):\n",
    "    try:\n",
    "        # Extract entities from chunk first (dependency parsing needs entities)\n",
    "        chunk_entities = ner.extract(chunk)\n",
    "        \n",
    "        # Extract relationships using dependency parsing\n",
    "        relationships = relation_extractor.extract(\n",
    "            chunk,\n",
    "            entities=chunk_entities,\n",
    "            relation_types=relation_types\n",
    "        )\n",
    "        all_relationships.extend(relationships)\n",
    "    except Exception as e:\n",
    "        print(f\"  Error processing chunk {i}: {str(e)[:50]}\")\n",
    "        pass\n",
    "    \n",
    "    if i % 5 == 0 or i == len(chunks_to_process):\n",
    "        print(f\"  Processed {i}/{len(chunks_to_process)} chunks ({len(all_relationships)} relationships found)\")\n",
    "\n",
    "print(f\"Extracted {len(all_relationships)} relationships\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conflict Detection\n",
    "\n",
    "Detect and resolve conflicts in supply chain data from multiple sources. Supply chain sources have different credibility levels.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.conflicts import ConflictDetector, ConflictResolver\n",
    "\n",
    "detector = ConflictDetector()\n",
    "resolver = ConflictResolver()\n",
    "\n",
    "entity_dicts = [{\"id\": e.text, \"text\": e.text, \"type\": e.label, \"confidence\": e.confidence, \"metadata\": e.metadata} for e in all_entities]\n",
    "relationship_dicts = [{\"id\": f\"{r.subject.text}_{r.predicate}_{r.object.text}\", \"source_id\": r.subject.text, \"target_id\": r.object.text, \"type\": r.predicate, \"confidence\": r.confidence, \"metadata\": r.metadata} for r in all_relationships] if all_relationships else []\n",
    "\n",
    "conflicts = detector.detect_entity_conflicts(entity_dicts)\n",
    "if relationship_dicts:\n",
    "    conflicts.extend(detector.detect_relationship_conflicts(relationship_dicts))\n",
    "\n",
    "print(f\"Detected {len(conflicts)} conflicts\")\n",
    "if conflicts:\n",
    "    resolver.resolve_conflicts(conflicts, strategy=\"credibility_weighted\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Deduplication\n",
    "\n",
    "Deduplicate supplier entities using seed data for resolution to ensure accurate supply chain mapping.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import EntityResolver\n",
    "from semantica.semantic_extract import Entity\n",
    "\n",
    "entity_dicts = [{\"name\": e.text, \"type\": e.label, \"confidence\": e.confidence} for e in all_entities]\n",
    "resolved = EntityResolver(strategy=\"fuzzy\", similarity_threshold=0.85).resolve_entities(entity_dicts)\n",
    "all_entities = [Entity(text=e[\"name\"], label=e[\"type\"], start_char=0, end_char=0, confidence=e.get(\"confidence\", 1.0)) for e in resolved]\n",
    "print(f\"Deduplicated {len(entity_dicts)} entities to {len(all_entities)} unique entities\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Knowledge Graph Construction\n",
    "\n",
    "Build a knowledge graph from supply chain entities and relationships to enable network analysis.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import GraphBuilder\n",
    "\n",
    "kg = GraphBuilder().build({\"entities\": all_entities, \"relationships\": all_relationships})\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 supply chain 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",
    "gen = EmbeddingGenerator(model_name=EMBEDDING_MODEL, dimension=EMBEDDING_DIMENSION)\n",
    "embeddings = gen.generate_embeddings(chunked_docs, data_type=\"text\")\n",
    "\n",
    "vector_store = VectorStore(backend=\"faiss\", dimension=EMBEDDING_DIMENSION)\n",
    "metadata = [{\"text\": chunk[:100]} for chunk in chunked_docs]\n",
    "vector_store.store_vectors(vectors=embeddings, metadata=metadata)\n",
    "\n",
    "print(f\"Generated {len(embeddings)} embeddings and stored in vector database\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Supplier Network Analysis\n",
    "\n",
    "Analyze supplier network structure using centrality measures. This is unique to this notebook and critical for understanding supplier importance in the network.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import CentralityCalculator\n",
    "\n",
    "calc = CentralityCalculator()\n",
    "degree_centrality = calc.calculate_degree_centrality(kg)\n",
    "betweenness_centrality = calc.calculate_betweenness_centrality(kg)\n",
    "print(f\"Degree centrality: {len(degree_centrality.get('centrality', {}))} nodes\")\n",
    "print(f\"Betweenness centrality: {len(betweenness_centrality.get('centrality', {}))} nodes\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Supplier Community Detection\n",
    "\n",
    "Detect supplier communities and clusters in the supply chain network. This is unique to this notebook and helps identify supplier groups.\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, algorithm=\"louvain\")\n",
    "overlapping = detector.detect_overlapping_communities(kg)\n",
    "print(f\"Detected {len(communities.get('communities', []))} communities and {len(overlapping.get('communities', []))} overlapping communities\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## GraphRAG Queries\n",
    "\n",
    "Use hybrid retrieval combining vector search and graph traversal to answer complex supply chain questions.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.context import AgentContext, ContextGraph, ContextRetriever\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=kg.get('relationships', [])\n",
    ")\n",
    "\n",
    "retriever = ContextRetriever(vector_store=vector_store, knowledge_graph=context_graph, hybrid_alpha=0.6, max_expansion_hops=2)\n",
    "context = AgentContext(vector_store=vector_store, knowledge_graph=context_graph, use_graph_expansion=True, max_expansion_hops=2)\n",
    "\n",
    "llm = Groq(model=\"llama-3.1-8b-instant\", api_key=os.getenv(\"GROQ_API_KEY\"))\n",
    "\n",
    "queries = [\n",
    "    \"Which suppliers provide products to Warehouse W1?\",\n",
    "    \"What routes connect warehouses to distribution centers?\",\n",
    "    \"Where is Supplier A located?\",\n",
    "    \"What products are shipped via Route R1?\"\n",
    "]\n",
    "\n",
    "for query in queries:\n",
    "    result = context.query_with_reasoning(query, llm_provider=llm, max_results=10, max_hops=2)\n",
    "    print(f\"Query: {query}\")\n",
    "    print(f\"Response: {result.get('response', 'No response generated')}\")\n",
    "    print(f\"Confidence: {result.get('confidence', 0):.3f} | Sources: {result.get('num_sources', 0)} | Paths: {result.get('num_reasoning_paths', 0)}\\n\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Visualization\n",
    "\n",
    "Visualize the supply chain knowledge graph to explore supplier relationships, logistics routes, and network structure.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.visualization import KGVisualizer\n",
    "\n",
    "viz = KGVisualizer(layout=\"force\")\n",
    "fig = viz.visualize_network(kg, output=\"interactive\")\n",
    "fig.show() if fig else None\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Export\n",
    "\n",
    "Export the knowledge graph in multiple formats for supply chain analysis and reporting.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.export import GraphExporter\n",
    "\n",
    "exporter = GraphExporter()\n",
    "exporter.export(kg, format=\"json\", output_path=\"supply_chain_kg.json\")\n",
    "exporter.export(kg, format=\"graphml\", output_path=\"supply_chain_kg.graphml\")\n",
    "print(\"Exported knowledge graph in JSON, GraphML, 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
}
