Compare commits

...
286 Commits
Author SHA1 Message Date
KaifAhmad1 957c122116 docs: add Docling integration guide, clear code example, and fix parser consistency issues 2026-01-08 21:27:48 +05:30
Mohd Kaif 31ca2e4446 Merge pull request #164 from Hawksight-AI/docs
docs: update changelog with model switching fixes
2026-01-08 19:38:01 +05:30
KaifAhmad1 b08c13364b docs: update changelog with model switching fixes and tests 2026-01-08 19:35:24 +05:30
Mohd Kaif 01dd0c97ab Merge pull request #163 from Hawksight-AI/embeddings
Fix Model Switching and Dynamic Dimension Detection
2026-01-08 19:00:12 +05:30
KaifAhmad1 2bd1d06eb2 fix: resolve model switching bug and implement intrinsic dimension detection in TextEmbedder 2026-01-08 18:56:42 +05:30
Mohd Kaif 9a2f2cd2d2 Merge pull request #162 from Hawksight-AI/kg
docs: update changelog with kg module fixes #159
2026-01-08 17:43:29 +05:30
KaifAhmad1 04a210232e docs: update changelog with kg module fixes #159 2026-01-08 17:42:19 +05:30
Mohd Kaif b3baeaa74e Merge pull request #161 from Hawksight-AI/kg
Fix 'unhashable type: Entity' in GraphAnalyzer (#159)
2026-01-08 17:29:31 +05:30
KaifAhmad1 58707ff721 fix(kg): resolve 'unhashable type: Entity' in GraphAnalyzer #159
- Robust ID extraction in CentralityCalculator, CommunityDetector, and ConnectivityAnalyzer
- Support for direct Entity objects and dictionaries as node identifiers
- Improved Entity hashability in utils/types.py
- Added integration test to verify fix and prevent regression
2026-01-08 17:23:31 +05:30
Mohd Kaif 9b18bc3da3 Merge pull request #158 from Hawksight-AI/dependabot/pip/protobuf-4.25.8
chore(deps): bump protobuf from 4.25.3 to 4.25.8
2026-01-07 19:13:13 +05:30
dependabot[bot] 5764a88d7e chore(deps): bump protobuf from 4.25.3 to 4.25.8
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 4.25.3 to 4.25.8.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Commits](https://github.com/protocolbuffers/protobuf/compare/v4.25.3...v4.25.8)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-version: 4.25.8
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-07 13:41:10 +00:00
Mohd Kaif cc69899b13 Merge pull request #157 from Hawksight-AI/utils
Dependency Fixes, GraphRAG Alignment, and Orchestrator Improvements
2026-01-07 19:07:26 +05:30
KaifAhmad1 e3b53998c3 Fix dependency issues, align GraphRAG notebook, and update changelog 2026-01-07 19:00:30 +05:30
Mohd Kaif de3441e76e Merge pull request #156 from Hawksight-AI/docs
Cookbook Fixes & Repository Optimization
2026-01-07 16:03:03 +05:30
KaifAhmad1 bd3c258458 chore: add .gitattributes to fix language statistics 2026-01-07 15:59:39 +05:30
Mohd Kaif 51cc445327 Merge pull request #155 from Hawksight-AI/docs
Cookbook Notebook Cleanup & Fixes
2026-01-07 15:43:37 +05:30
KaifAhmad1 04c4c9fb4c docs: clean and fix corrupted notebooks in cookbook 2026-01-07 15:41:13 +05:30
Mohd Kaif 010251ac35 Merge pull request #154 from Hawksight-AI/ontology
Fix KnowledgeGraph Documentation Mismatch
2026-01-07 15:05:48 +05:30
KaifAhmad1 dcd6f25f87 docs: fix KnowledgeGraph mismatch and update tests for issue #144 2026-01-07 15:01:47 +05:30
Mohd Kaif 55abd52b77 Merge pull request #153 from Hawksight-AI/docs
docs: improve robustness and data consistency in earnings analysis notebook
2026-01-07 14:11:41 +05:30
KaifAhmad1 960d7c5f8f docs: improve robustness and fix variable inconsistencies in earnings call notebook 2026-01-07 14:09:22 +05:30
Mohd Kaif 2489ce72b5 Delete GITHUB_ISSUE_LLM_EXTRACTION.md 2026-01-07 03:06:21 +05:30
Mohd Kaif f488dfb82a Delete PR_DESCRIPTION_LLM_EXTRACTION.md 2026-01-07 03:06:06 +05:30
Mohd Kaif 74fdd3330e Merge pull request #150 from Hawksight-AI/semantic-extract
Robust LLM Extraction - Auto-Chunking, Retries, and Diagnostics
2026-01-07 03:05:37 +05:30
KaifAhmad1 e712949872 Enhance LLM extraction methods with auto-chunking, robust parsing and improved diagnostics (#149) 2026-01-07 03:03:19 +05:30
Mohd Kaif c208f6b54e Delete PR_DESCRIPTION.md 2026-01-07 01:13:55 +05:30
Mohd Kaif d516ea69dc Merge pull request #148 from Hawksight-AI/semantic-extract
fix(semantic_extract): Pass API key to Groq LLM provider in extractio…
2026-01-07 01:11:21 +05:30
KaifAhmad1 2790132e8e fix(semantic_extract): Pass API key to Groq LLM provider in extraction methods
- Add API key handling in extract_entities_llm(), extract_relations_llm(), and extract_triplets_llm()
- Add explicit api_key handling in NERExtractor and RelationExtractor
- Add llm_model parameter support in extract_triplets_llm() for consistency
- Fix relation extraction bug with type checking for subject_text/object_text
- Add environment variable fallback for API keys
- Update notebook with standard API key pattern

Fixes #147
2026-01-07 01:07:56 +05:30
Mohd Kaif 1e22ff3a75 Merge pull request #146 from Hawksight-AI/semantic-extract
fix(semantic_extract): Pass API key to Groq LLM provider in extractio…
2026-01-06 22:43:59 +05:30
KaifAhmad1 9c59f97542 fix(semantic_extract): Pass API key to Groq LLM provider in extraction methods
- Add API key handling in extract_entities_llm(), extract_relations_llm(), and extract_triplets_llm()
- Add llm_model parameter support in extract_triplets_llm() for consistency
- Fix relation extraction bug with type checking for subject_text/object_text
- Add environment variable fallback for API keys
- Include providers.py for context (GroqProvider implementation)

Fixes #145
2026-01-06 22:37:57 +05:30
Mohd Kaif 4eb69e5048 Merge pull request #143 from Hawksight-AI/docs
Refreshed Metadata, Analytics & Community Links
2026-01-06 12:04:53 +05:30
KaifAhmad1 2b43fa4699 fix: update discord badge to a reliable static version 2026-01-06 12:00:23 +05:30
Mohd Kaif 9fb18e3ec6 Merge pull request #142 from Hawksight-AI/docs
Update Badges, Discord Links, and Version Metadata
2026-01-06 11:57:37 +05:30
KaifAhmad1 7f7c36f94d docs: update badges, discord links, and version mentions 2026-01-06 11:54:17 +05:30
Mohd Kaif 2e2f19f43d Merge pull request #141 from Hawksight-AI/docs
Release v0.1.1: Docling Integration & 2026 Sync
2026-01-06 00:28:15 +05:30
KaifAhmad1 d7b686f32a Release v0.1.1: Docling support, version bump, and documentation updates 2026-01-06 00:21:20 +05:30
Mohd Kaif e89e707e49 Merge pull request #140 from Hawksight-AI/utils
Fix DoclingParser Integration and Confirm Cross-Platform Compatibility
2026-01-05 22:31:57 +05:30
KaifAhmad1 a441e935f9 Fix DoclingParser integration and align with docling API
- Fix import logic in __init__.py to properly export DoclingParser
- Rewrite docling_parser.py to use docling's native API (direct attribute access)
- Remove unsupported features (table_extraction_mode, invalid format_options)
- Use doc.tables, doc.pictures, doc.pages directly instead of dict parsing
- Update notebook with improved code and documentation
- Add proper error handling for when docling is not available

Fixes #138
2026-01-05 22:27:15 +05:30
Mohd Kaif 3fb98aa0ed Merge pull request #139 from Hawksight-AI/utils
Resolve DoclingParser Exports, Windows Progress Encoding, and Finance Cookbook Update (#138)
2026-01-05 20:10:45 +05:30
KaifAhmad1 4e0c3bc361 Resolve DoclingParser exports, fix Windows progress encoding, and update finance cookbook #138 2026-01-05 20:04:59 +05:30
Mohd Kaif ef2c3dc841 Merge pull request #137 from Hawksight-AI/utils
feat: Add pipeline_id support and fix parsing table display
2026-01-05 18:17:24 +05:30
KaifAhmad1 96604ae398 feat: Add pipeline_id support and fix parsing table display
- Add pipeline_id parameter to all trackers, batch processors, parsers, and extractors
- Fix DoclingParser to show extraction counts in progress display
- Add 'Extracted' column showing tables, images, pages
- Emphasize Docling as core dependency in messages

Closes #136
2026-01-05 18:15:12 +05:30
Mohd Kaif 88a4b9f1d2 Merge pull request #134 from Hawksight-AI/parse
feat(parse): add progress tracking to DoclingParser and update earnin…
2026-01-05 14:46:12 +05:30
KaifAhmad1 ea02896617 feat(parse): add progress tracking to DoclingParser and update earnings call notebook
- Add 8-stage progress tracking (0-100%) with ETA to DoclingParser
- Update earnings call analysis notebook with MDA Space Q3 2025 example
- Simplify notebook code structure
- Add real-time progress visibility for PDF parsing

Closes #133
2026-01-05 14:42:12 +05:30
Mohd Kaif 01808728f4 Merge pull request #132 from Hawksight-AI/docs
[DOCS] Fix Discord invite link and reorganize README sections
2026-01-04 19:58:02 +05:30
KaifAhmad1 b03ab2458d docs: Fix Discord invite link and reorganize README sections
- Update Discord invite link from https://discord.gg/semantica to https://discord.gg/pMHguUzG
- Move Contributors section inside Contributing section (following open source best practices)
- Update Enterprise Support section to indicate future availability
- Add Evals to roadmap

Fixes #127
2026-01-04 19:56:10 +05:30
Mohd Kaif f8551c5dfb Merge pull request #131 from Hawksight-AI/utils
Fix: Handle OSError for Optional Dependencies and Make DoclingParser Standalone
2026-01-04 17:56:39 +05:30
KaifAhmad1 e7f713d43b Fix: Handle OSError for optional dependencies and make DoclingParser standalone
- Add safe_import utility in semantica/utils/helpers.py for graceful optional dependency handling
- Update all optional imports (spacy, docling, etc.) to handle OSError (Windows DLL issues)
- Make DoclingParser standalone with docling as core dependency
- Remove DoclingParser integration from DocumentParser
- Implement lazy initialization for DoclingParser (fails on parse(), not init())
- Fix DocumentConverter initialization (remove unsupported pipeline_options parameter)
- Preserve original error messages without modification
- Update semantic_extract, split, parse, embeddings, vector_store, visualization modules
- Fix OSError handling across entire codebase for Windows compatibility
- Update 60+ files with proper optional dependency handling
2026-01-04 17:44:14 +05:30
Mohd Kaif 6595f1918c Merge pull request #130 from Hawksight-AI/llms
Fix: Make PyTorch import lazy to avoid DLL errors on Windows
2026-01-03 20:43:43 +05:30
KaifAhmad1 47809f2ef9 Fix: Make PyTorch import lazy to avoid DLL errors on Windows
- Remove top-level torch import from providers.py
- Add lazy imports in HuggingFaceLLMProvider and HuggingFaceModelLoader
- Remove hardcoded API key from notebook
- PyTorch now only loads when HuggingFace providers are instantiated

Fixes #129
2026-01-03 20:39:37 +05:30
Mohd Kaif 40beea447e Merge pull request #128 from Hawksight-AI/parse
[FEATURE] Integrate Docling for Enhanced Document Parsing
2026-01-03 18:55:30 +05:30
KaifAhmad1 96a98fa037 [FEATURE] Integrate Docling for Enhanced Document Parsing
- Added DoclingParser class in semantica/parse/ module
- Created earnings call analysis notebook with Docling integration
- Added docling to pyproject.toml as optional dependency
- Maintained backward compatibility with existing parsers

Closes #124
2026-01-03 18:46:25 +05:30
Mohd Kaif 222f25b275 Merge pull request #126 from Hawksight-AI/utils
fix(utils): resolve Python 3.13 NameError in typing (#125)
2026-01-02 22:05:08 +05:30
KaifAhmad1 43c14e41fa fix(utils): resolve Python 3.13 NameError by deferring annotation evaluation
- Added 'from __future__ import annotations' to helpers.py and exceptions.py
- Replaced 'typing.Type' with built-in 'type' for PEP 585 compliance
- Cleaned up unused 'Type' imports

Fixes #125
2026-01-02 22:01:09 +05:30
Mohd Kaif ac942f7895 Update README.md 2026-01-01 18:27:55 +05:30
KaifAhmad1 fd916b15b5 chore: trigger documentation deployment for public site 2026-01-01 11:40:28 +05:30
KaifAhmad1 bc28c22ee0 docs: fix deployment workflow and site URL for GitHub Pages 2025-12-31 16:36:25 +05:30
Mohd Kaif 966692bafb Merge pull request #123 from Hawksight-AI/docs
Documentation Improvements: Code Reduction and Cookbook Integration
2025-12-31 15:26:03 +05:30
KaifAhmad1 04eea7e7eb Update documentation: reduce code examples, add cookbook links, improve structure
- Reduced code examples in all guide pages (getting-started, quickstart, concepts, modules, examples, use-cases, learning-more)
- Added comprehensive cookbook links with descriptions (topics, difficulty, time, use cases)
- Improved structure and organization across all guide pages
- Updated use-cases.md to only include use cases with corresponding cookbooks
- Removed 'Last Updated: 2024' from all documentation files
- Enhanced navigation with better 'Next Steps' sections
2025-12-31 15:19:08 +05:30
KaifAhmad1 35391382d3 docs: configure github pages deployment and fix broken links 2025-12-31 12:37:36 +05:30
KaifAhmad1 e916ab3f7a docs: update changelog and add release guide for v0.1.0 2025-12-31 12:29:14 +05:30
KaifAhmad1 aee046ec8b release: update version to 0.1.0 and add CLI, server, and worker entry points
Summary of changes:
- Update version to 0.1.0 in pyproject.toml and __init__.py files
- Add semantica/cli.py with click-based interface
- Add semantica/server.py with FastAPI-based REST API
- Add semantica/worker.py for background task processing
- Update documentation and changelog for v0.1.0
2025-12-31 12:12:20 +05:30
Mohd Kaif 5aa0bdb630 Remove Semantica Processing Flow and Cookbook Sections
Removed detailed processing flowchart and cookbook recipes from README.
2025-12-31 00:05:56 +05:30
KaifAhmad1 b44803dcae update readme 2025-12-30 23:57:34 +05:30
KaifAhmad1 7796cb5283 udate reamde 2025-12-30 23:49:34 +05:30
KaifAhmad1 8cde40d753 Remove trading notebooks and supply chain risk management notebook
- Deleted cookbook/use_cases/trading/01_Risk_Assessment.ipynb
- Deleted cookbook/use_cases/trading/02_News_Sentiment_Analysis.ipynb
- Deleted cookbook/use_cases/supply_chain/02_Supply_Chain_Risk_Management.ipynb
- Removed empty trading directory
- Updated documentation to reflect 14 cookbooks (down from 15)
- Removed all references from README.md, docs/cookbook.md, docs/use-cases.md, docs/index.md, and STRATEGIES_SUMMARY.md
2025-12-30 23:33:27 +05:30
KaifAhmad1 9ef8a7aa18 Update Energy Market Analysis notebook: simplify code, use Semantica effectively, remove redirect_stderr, fix entity/relationship extraction 2025-12-30 21:44:53 +05:30
KaifAhmad1 af17585087 Remove Smart Grid Management notebook and update cookbook count to 15 2025-12-30 20:20:11 +05:30
KaifAhmad1 7b9bd42790 Clean up intelligence analysis notebook: remove unnecessary imports and with blocks, use Semantica built-in methods properly 2025-12-30 20:10:02 +05:30
KaifAhmad1 d8f78cd49e Refactor Criminal Network Analysis notebook: simplify code, use Semantica modules effectively, add interactive visualization, fix GraphRAG queries 2025-12-30 18:19:57 +05:30
KaifAhmad1 f4016237bd Remove healthcare use case: Drug Interactions Analysis
- Deleted cookbook/use_cases/healthcare/02_Drug_Interactions_Analysis.ipynb
- Removed Healthcare section from README.md
- Removed Healthcare section from docs/cookbook.md
- Removed Drug Interactions references from STRATEGIES_SUMMARY.md
- Updated cookbook count from 18 to 17 in all documentation
- Updated docs/index.md to reflect 17 cookbooks
2025-12-30 15:27:21 +05:30
KaifAhmad1 0c5e12f5c9 Remove Clinical Reports Processing notebook and all references
- Delete cookbook/use_cases/healthcare/01_Clinical_Reports_Processing.ipynb
- Delete cookbook/use_cases/healthcare/data/clinical_report.txt
- Remove references from README.md Healthcare section
- Remove Medical Record Analysis card from docs/use-cases.md
- Remove Clinical Reports Processing card from docs/cookbook.md
- Remove entries from STRATEGIES_SUMMARY.md table and rationale
2025-12-30 14:32:55 +05:30
KaifAhmad1 9c97d3236c Fix Fraud Detection notebook: Add real data sources, fix errors, enhance GraphRAG with Context Graph
- Add real CSV and JSON data sources for transactions and accounts
- Fix ConflictDetector, TemporalGraphQuery, and Reasoner errors
- Simplify code to use Semantica modules properly
- Enhance GraphRAG section with Context Graph and Groq LLM
- Add temporal interactive visualization using TemporalVisualizer
- Fix CSV export to use CSVExporter instead of GraphExporter
- Update README.md to mention Context Graph and Context Retriever
2025-12-30 13:45:56 +05:30
KaifAhmad1 599372a50f Update financial data integration notebook:
- Switch entity and relation extraction to ML-based methods (spaCy)
- Fix conflict detection to use detect_temporal_conflicts directly
- Fix graph building to use correct Relation attributes (subject/object/predicate)
- Improve GraphRAG with LLM-based multi-hop reasoning
- Enhance graph analytics output to show all entity types
- Update markdown descriptions with concise bullet points
2025-12-29 23:09:20 +05:30
KaifAhmad1 9f31f825ff Fix Threat Intelligence Hybrid RAG notebook: Update conflict detection, GraphRAG queries, reasoning, and visualization 2025-12-29 22:32:30 +05:30
KaifAhmad1 a674e8c039 fix: resolve Entity TypeError by adding required start_char and end_char fields across cookbook notebooks 2025-12-29 21:35:30 +05:30
Mohd Kaif 1124a56a06 Merge pull request #122 from Hawksight-AI/utils
Optimized Deduplication Pipeline & Advanced Progress Tracking
2025-12-29 21:02:59 +05:30
KaifAhmad1 9ad1f574af feat(deduplication): optimize pipeline with blocking strategy, progress tracking, and object compatibility 2025-12-29 20:58:06 +05:30
Mohd Kaif b053602c7d Merge pull request #121 from Hawksight-AI/utils
Add Comprehensive Progress Tracking with Jupyter/Colab Support
2025-12-29 13:13:50 +05:30
KaifAhmad1 d2d6adafdb Add comprehensive progress tracking with Jupyter/Colab support
- Enhanced progress tracker with automatic Jupyter/Colab detection
- Added detailed progress tracking to all deduplication modules
- Added detailed progress tracking to all semantic_extract modules
- Progress tracker now always enabled automatically
- Shows remaining items, percentages, ETA, and processing rates
- Works in both Jupyter notebooks and Google Colab
- Dynamic update intervals based on dataset size
- Improved display handling for Colab compatibility
2025-12-29 13:11:22 +05:30
Mohd Kaif 0c27f0fcd9 Merge pull request #120 from Hawksight-AI/utils
Add Progress Tracker Enable Check to All Modules
2025-12-28 22:16:17 +05:30
KaifAhmad1 00575b135e Add progress tracker enable check to all modules
- Added enable check to normalize module (8 files)
- Added enable check to ontology module (16 files)
- Added enable check to ingest module (4 files)
- Added enable check to graph_store module (3 files)
- Ensures progress tracking is enabled by default in all modules
- Total: 112 files updated across the codebase
2025-12-28 22:13:11 +05:30
Mohd Kaif 9e0aa28eb1 Merge pull request #119 from Hawksight-AI/utils
Add Progress Tracking with ETA to Long-Running Operations
2025-12-28 20:36:46 +05:30
KaifAhmad1 53db5bbdc0 Add progress tracking with ETA to all long-running operations
- Fixed ConflictDetector to use update_progress() with counts/ETA for type, temporal, and logical conflict detection
- Fixed NERExtractor batch operations to show progress with ETA
- Fixed RelationExtractor batch operations to show progress with ETA
- All modules now display clear progress bars with percentage, counts, and estimated time remaining
2025-12-28 20:32:56 +05:30
Mohd Kaif 8313cd73a0 Merge pull request #118 from Hawksight-AI/utils
Add Progress Tracking with ETA to All Modules
2025-12-28 19:30:58 +05:30
KaifAhmad1 c7559afdc5 Add progress tracking with ETA to all modules
- Enhanced ProgressItem with ETA fields (progress_percentage, total_items, processed_items, estimated_remaining)
- Added update_progress() and _calculate_eta() methods to ProgressTracker
- Updated ConsoleProgressDisplay and JupyterProgressDisplay to show progress with ETA
- Added progress tracking to deduplication modules (DuplicateDetector, EntityMerger, SimilarityCalculator, ClusterBuilder)
- Added progress tracking to conflicts modules (ConflictDetector, ConflictResolver)
- Added progress tracking to ingest, parse, kg, core, embeddings, and triplet_store modules
- All modules now display progress percentage, item counts, ETA, and processing rate
2025-12-28 19:26:58 +05:30
KaifAhmad1 40e5c5110c Optimize GraphBuilder entity processing performance
- Add fast path for dictionary entities/relationships to bypass _process_item overhead
- Improve entity recognition to handle 'text' and 'type' fields directly
- Significantly improve processing speed from ~0.8/s to thousands/s
- Fixes performance bottleneck in knowledge graph building
2025-12-28 17:25:28 +05:30
KaifAhmad1 1719ff5832 Merge branch 'main' of https://github.com/Hawksight-AI/semantica 2025-12-27 23:33:08 +05:30
KaifAhmad1 2ecebf1003 Jpdate pytoml 2025-12-27 23:32:33 +05:30
Mohd Kaif 7be2d38bb1 Merge pull request #117 from Hawksight-AI/llms
Add LLM Providers Module and GraphRAG Reasoning Features
2025-12-27 23:27:49 +05:30
KaifAhmad1 c3555e0cfd Add LLM providers module and GraphRAG reasoning features
- Add semantica.llms module with Groq, OpenAI, HuggingFace, and LiteLLM providers
- Add query_with_reasoning() method for multi-hop reasoning with LLM-generated responses
- Update ContextRetriever and AgentContext with reasoning capabilities
- Add comprehensive documentation for LLM providers and GraphRAG reasoning
- Update README and docs with new features
- Update notebook examples to use new query_with_reasoning() method
2025-12-27 23:23:32 +05:30
KaifAhmad1 94ddcc4d33 Fix blockchain transaction network analysis notebook
- Fix TemporalGraphQuery: Change detect_temporal_patterns to query_temporal_pattern
- Fix GraphAnalyzer: Replace find_paths with direct relationship queries and BFS implementation
- Fix KGVisualizer: Change visualize() to visualize_network() with interactive visualization
- Fix GraphExporter: Remove unsupported CSV format, use export_csv for CSV export
- Add proper imports and improve error handling
- Enhance visualization with force-directed layout and better interactivity
2025-12-27 21:48:35 +05:30
KaifAhmad1 7a652cf227 Fix GraphBuilder progress tracking for list of dict sources
- Added support for detecting and merging list of dict sources with entities/relationships
- Progress tracking now shows ETA and remaining items when sources is a list
- Fixes issue where progress wasn't displayed when passing list of dicts to build()
2025-12-27 19:21:07 +05:30
KaifAhmad1 f53935e0a1 Add progress tracking and ETA to GraphBuilder
- Enhanced GraphBuilder with real-time progress updates showing percentage, ETA, and processing rate
- Added time tracking for entity processing, relationship processing, entity resolution, and graph structure building
- Added final summary with total build time
- Simplified notebook cell to rely on Semantica's built-in progress tracking instead of manual Python code
2025-12-27 18:46:27 +05:30
KaifAhmad1 b9ffba67ea Update DeFi Protocol Intelligence notebook:
- Use ML-only approach for entity extraction (spaCy)
- Improve knowledge graph visualization with interactive layout
- Fix ontology export to use RDFExporter for TTL format
- Enhance visualization with better interactivity and explanations
2025-12-27 16:57:24 +05:30
KaifAhmad1 d4f008a183 Fix AttributeError issues in TripletStore and ContextRetriever
- Fix LoadProgress attribute access in TripletStore (use loaded_triplets instead of processed_triplets)
- Fix None source handling in ContextRetriever RetrievedContext objects
- Add error handling for Blazegraph connection in notebook
- Ensure source field always has a default value in vector/memory retrieval
2025-12-27 15:34:04 +05:30
KaifAhmad1 f7fcfa3691 Fix LLM-based entity and relation extraction
- Updated extract_entities_llm to use custom entity_types in prompts
- Updated extract_relations_llm to use custom relation_types in prompts
- Made entity type filtering case-insensitive and flexible
- Added verbose mode to RelationExtractor for progress tracking
- Improved error handling and progress reporting in notebook
- Made prompts more flexible to accept variations of entity/relation types
2025-12-26 23:00:14 +05:30
KaifAhmad1 8289d56d89 Update notebook and other changes 2025-12-26 19:41:55 +05:30
KaifAhmad1 bde4ef18a3 Update Genomic Variant Analysis notebook and fix temporal query issues
- Fixed analyze_evolution metrics None handling in temporal_query.py
- Updated 02_Genomic_Variant_Analysis.ipynb with simplified code using Semantica effectively
- Added temporal visualization support
- Fixed GraphBuilder conflict resolution (set resolve_conflicts=False when conflicts already handled)
- Simplified pathway analysis and disease association cells
- Updated visualization to use interactive Plotly graphs instead of HTML
- Added temporal dashboard visualization
2025-12-26 19:01:32 +05:30
KaifAhmad1 1542b2dafb Improve GraphRAG accuracy with semantic matching and domain-agnostic query intent
- Replace keyword matching with semantic similarity using embeddings
- Add domain-agnostic query intent extraction
- Improve ranking with hybrid_alpha weighting and context boosting
- Enhance content generation from graph structures
- Update ContextRetriever documentation
- Fix KGVisualizer method call in notebook
2025-12-26 18:07:44 +05:30
KaifAhmad1 76def647d8 Fix Drug Discovery Pipeline notebook: resolve conflicts, simplify GraphBuilder, update documentation
- Fixed NameError: Changed merged_entities to all_entities in conflict detection and GraphBuilder cells
- Fixed TypeError: Updated conflict detection to use detect_relationship_conflicts() directly
- Simplified code: Reduced manual Python code, better utilize Semantica's built-in features
- Updated markdown: Converted to bullet points, reflect credibility-weighted strategy
- Improved GraphBuilder: Use automatic object handling instead of manual conversion
2025-12-26 13:13:23 +05:30
KaifAhmad1 c15ee40cdf feat: Diversify deduplication and conflict resolution across 16 use case notebooks
Implement domain-appropriate strategies for all notebooks:

Deduplication Methods (9): pairwise, batch, incremental, group, graph_based,
hierarchical, exact, semantic, fuzzy

Merge Strategies (5): keep_first, keep_last, keep_most_complete,
keep_highest_confidence, merge_all

Conflict Detection (6): value, type, entity, relationship, temporal, logical

Conflict Resolution (6): voting, credibility_weighted, most_recent,
first_seen, highest_confidence, expert_review

Key patterns:
- Real-time: pairwise + keep_first + first_seen
- Time-sensitive: temporal + most_recent
- Multi-source: batch + merge_all + voting
- Medical/Research: credibility_weighted
- Fraud/Security: graph_based + logical + expert_review

Added STRATEGIES_SUMMARY.md documentation.
Removed temporary update scripts.
2025-12-25 22:38:03 +05:30
KaifAhmad1 068d0d489a refactor(trading): rebuild risk assessment and sentiment analysis notebooks
- Refactor 01_Risk_Assessment.ipynb with GraphStore, DBIngestor, conflict detection
- Refactor 02_News_Sentiment_Analysis.ipynb with TripletStore, StreamIngestor, deduplication
- Complete all 8 phases in both notebooks with different module approaches
- Add comprehensive graph analytics, ontology generation, and export functionality
2025-12-25 16:54:35 +05:30
KaifAhmad1 7a82b7b597 docs(supply-chain): update risk management notebook 2025-12-25 16:30:23 +05:30
KaifAhmad1 96e784509e Refactor renewable energy notebooks: modular architecture with unique module combinations
- Rebuilt 01_Energy_Market_Analysis.ipynb with temporal pattern detection, trend prediction, and seed data integration
- Rebuilt 02_Smart_Grid_Management.ipynb with stream processing, real-time monitoring, and anomaly detection
- Removed core orchestrator usage, implemented cell-specific imports
- Added comprehensive data sources and Mermaid pipeline diagrams
- Minimal print statements, proper error handling with redirect_stderr
- Unique module combinations per use case for differentiation
2025-12-25 15:51:54 +05:30
KaifAhmad1 bd594f9c41 Refactor intelligence notebooks: Use modular architecture with unique approaches per use case
- Rebuilt 01_Criminal_Network_Analysis.ipynb with graph analytics and centrality focus (31 cells)
- Rebuilt 02_Intelligence_Analysis_Orchestrator_Worker.ipynb with multi-source integration and temporal analysis focus (31 cells)
- Added comprehensive data sources (OSINT feeds, threat intelligence, geospatial data, intelligence agency feeds)
- Implemented cell-specific imports and minimal print statements
- Each notebook uses different module combinations to showcase uniqueness:
  - Criminal Network: CentralityCalculator, CommunityDetector, GraphAnalyzer, entity-aware chunking
  - Intelligence Analysis: StreamIngestor, ConflictDetector, Reasoner, TemporalGraphQuery, sentence chunking
- Removed empty markdown cells
- Added Mermaid pipeline flow diagrams
- No phase/step numbers - descriptive section headers
2025-12-25 15:19:31 +05:30
KaifAhmad1 b5f895e289 Refactor healthcare notebooks: Use modular architecture with unique approaches per use case
- Rebuilt 01_Clinical_Reports_Processing.ipynb with EHR integration and triplet store focus (32 cells)
- Rebuilt 02_Drug_Interactions_Analysis.ipynb with ontology generation and reasoning focus (35 cells)
- Added comprehensive data sources (EHR APIs, HL7/FHIR feeds, FDA RSS, PubMed, drug databases)
- Implemented cell-specific imports and minimal print statements
- Each notebook uses different module combinations to showcase uniqueness:
  - Clinical Reports: TripletStore, SeedDataManager, TemporalGraphQuery, DocumentParser
  - Drug Interactions: OntologyGenerator, Reasoner, ConflictDetector, TemporalPatternDetector, CommunityDetector
- Removed empty markdown cells
- Added Mermaid pipeline flow diagrams
- No phase/step numbers - descriptive section headers
2025-12-25 14:40:58 +05:30
KaifAhmad1 7d07691d99 Refactor finance notebooks: Use modular architecture with unique approaches per use case
- Rebuilt 01_Financial_Data_Integration_MCP.ipynb with MCP and seed data focus (31 cells)
- Rebuilt 02_Fraud_Detection.ipynb with temporal analysis and pattern detection focus (38 cells)
- Added comprehensive data sources (APIs, RSS feeds, streams, databases)
- Implemented cell-specific imports and minimal print statements
- Each notebook uses different module combinations to showcase uniqueness:
  - Financial Data Integration: MCPIngestor, SeedDataManager, GraphAnalyzer, CentralityCalculator
  - Fraud Detection: StreamIngestor, TemporalGraphQuery, TemporalPatternDetector, ConflictDetector
- Removed empty markdown cells
- Added Mermaid pipeline flow diagrams
- No phase/step numbers - descriptive section headers
2025-12-25 14:12:27 +05:30
KaifAhmad1 8740379df6 Refactor cybersecurity notebooks: Use modular architecture with comprehensive data sources and all Semantica modules
- Rebuilt 01_Real_Time_Anomaly_Detection.ipynb with 20+ sections
- Rebuilt 02_Threat_Intelligence_Hybrid_RAG.ipynb with 20+ sections
- Added comprehensive data sources (RSS feeds, APIs, databases, IOC sources)
- Implemented cell-specific imports and minimal print statements
- Integrated all relevant Semantica modules (parse, embeddings, vector_store, graph_store, temporal queries, etc.)
- Removed empty markdown cells
- Added Mermaid pipeline flow diagrams
- No phase/step numbers - descriptive section headers
2025-12-25 13:38:35 +05:30
KaifAhmad1 5e220dc341 Refactor blockchain notebooks: Use modular architecture with comprehensive data sources and all Semantica modules
- Rebuilt 01_DeFi_Protocol_Intelligence.ipynb with 20+ sections
- Rebuilt 02_Transaction_Network_Analysis.ipynb with 21+ sections
- Added comprehensive data sources (RSS feeds, APIs, databases)
- Implemented cell-specific imports and minimal print statements
- Integrated all relevant Semantica modules (parse, embeddings, vector_store, graph_store, triplet_store, context, etc.)
- Removed empty markdown cells
- Added Mermaid pipeline flow diagrams
- No phase/step numbers - descriptive section headers
2025-12-25 13:08:13 +05:30
KaifAhmad1 3f74040509 Refactor biomedical notebooks: Use modular architecture with cell-specific imports and comprehensive data sources 2025-12-25 12:48:51 +05:30
KaifAhmad1 a54959d277 Refactor Drug Discovery Pipeline notebook: break down dense cells, remove unnecessary markdown headings, add bullet points 2025-12-25 00:20:06 +05:30
KaifAhmad1 7c5ee9fb10 Merge branch 'main' of https://github.com/Hawksight-AI/semantica 2025-12-24 18:02:34 +05:30
KaifAhmad1 6155a28d9f Update documentation layout and spacing adjustments 2025-12-24 18:02:16 +05:30
Mohd Kaif 2bbe36400a Delete cookbook/use_cases/USE_CASES_CATALOG.md 2025-12-24 16:48:07 +05:30
KaifAhmad1 106e817ad8 docs: Update all documentation with 18 enhanced domain-specific cookbooks
- Enhanced 18 cookbooks across 9 domains with real data sources, advanced chunking, temporal KGs, and GraphRAG
- Updated docs/cookbook.md with all 18 cookbook links and enhanced descriptions
- Updated docs/use-cases.md with corrected links and removed duplicates
- Updated README.md with comprehensive Industry Use Cases section
- Fixed all outdated notebook links and ensured consistency across all docs
- Added real data ingestion (RSS feeds, APIs, MCP servers, streams)
- Integrated advanced chunking strategies (entity-aware, relation-aware, ontology-aware, semantic_transformer, etc.)
- Added temporal knowledge graphs, GraphRAG, deduplication, conflict detection, and other Semantica modules
2025-12-24 16:33:36 +05:30
KaifAhmad1 d5ec639d3c Fix GraphRAG notebooks: update LLM model to llama-3.3-70b-versatile, fix embedding dimension check, fix file ingestion, fix graph metrics access, fix export methods, fix conflict detection, and add side-by-side comparison 2025-12-24 13:37:17 +05:30
KaifAhmad1 cd437a9cfb Fix GraphRAG notebook: embedding dimension check, update LLM model to llama-3.3-70b-versatile, fix file ingestion, graph metrics access, and export methods 2025-12-24 13:00:10 +05:30
KaifAhmad1 bd466b6016 Fix GraphRAG notebook issues: embedding dimension check, update LLM model to llama-3.3-70b-versatile, fix file ingestion, and fix graph metrics access 2025-12-24 12:52:55 +05:30
KaifAhmad1 ef0797e03e Fix semantic extraction pipeline errors and enhance LLM JSON parsing
Summary of changes:
- Fixed TripletExtractor method name (extract -> extract_triplets)
- Fixed Event attribute name (type -> event_type)
- Improved LLM JSON parsing in providers.py (handles trailing commas, unclosed structures)
- Fixed CentralityCalculator TypeError in GraphRAG notebook
- Corrected CommunityDetector logic and imports in notebook
2025-12-23 23:23:46 +05:30
KaifAhmad1 eaa1fbefa6 feat(reasoning): add dedicated reasoning tests and fix critical reasoning bugs
- Added tests/reasoning/ directory with unit and integration tests
- Fixed indentation bug in Reasoner.add_fact for dictionary-based relationships
- Fixed regex variable matching in Reasoner._match_pattern
- Fixed variable handling in SPARQLReasoner query expansion
- Cleaned up cookbook and documentation references
2025-12-23 21:26:26 +05:30
KaifAhmad1 9cc096dcd5 Refactor GraphRAG notebooks: remove empty cells, step numbers, reorganize imports, and make markdown concise 2025-12-23 18:19:23 +05:30
KaifAhmad1 07bd371e7d Expand GraphRAG notebooks with more cells, less dense code, and improved markdown documentation 2025-12-23 17:10:28 +05:30
Mohd Kaif e24ee50a0d Merge pull request #116 from Hawksight-AI/reasoning
Reasoning Module Refactor & Synchronization
2025-12-23 15:24:40 +05:30
KaifAhmad1 7046c92b3a Merge main and resolve conflicts by prioritizing audited reasoning refactor 2025-12-23 15:24:07 +05:30
KaifAhmad1 1ca83dd3c9 Comprehensive reasoning module cleanup: removed InferenceEngine, updated documentation, and synchronized cookbooks project-wide 2025-12-23 15:14:52 +05:30
Mohd Kaif b2925ed773 Delete restructure_utf8.py 2025-12-23 13:47:17 +05:30
Mohd Kaif 4524f071e1 Delete Traeresourcesappoutvsworkbenchcontribterminalcommonscriptssafe_rm_aliases.ps1 } catch{} ; Write-Output [Trae] Safe Rm alias is not enabled, try to fix it now. 2025-12-23 13:46:33 +05:30
KaifAhmad1 644314e976 feat: enhance GraphRAG notebooks with AgentContext and improve VectorStore API 2025-12-23 13:45:13 +05:30
KaifAhmad1 65cb229ed5 Update GraphRAG cookbook notebook 2025-12-23 00:22:41 +05:30
KaifAhmad1 ab4fa0e4c5 fix(cookbook): resolve AttributeError and update imports in GraphRAG notebook 2025-12-22 23:44:22 +05:30
KaifAhmad1 ab9624fb39 feat: expand real-world data sources and add web ingestion to advanced RAG notebooks 2025-12-22 23:11:28 +05:30
KaifAhmad1 323a788288 Remove hardcoded API keys and finalize Colab badges in notebooks 2025-12-22 22:11:08 +05:30
KaifAhmad1 e92bf0e872 Move Colab badges to the top of notebooks for better visibility 2025-12-22 22:06:10 +05:30
KaifAhmad1 995c1f27eb Add 'Open in Colab' badges to notebooks 2025-12-22 21:59:05 +05:30
KaifAhmad1 fcd61772b2 Update notebooks for local embeddings and interactive multi-hop queries, fix FalkorDB integration, and add docker-compose 2025-12-22 21:52:22 +05:30
KaifAhmad1 2cf2733d5b fix: Update ingestion URLs and logic in GraphRAG notebook and restructure script 2025-12-22 20:43:51 +05:30
KaifAhmad1 b07b1d58f7 feat: professional restructure of comparison notebook and core API enhancements 2025-12-22 20:22:05 +05:30
KaifAhmad1 e91cc315ec Cleanup temporary fix script 2025-12-22 20:09:17 +05:30
KaifAhmad1 5b14f1cc4a Fix Phase 5 config and cleanup debug scripts 2025-12-22 20:08:16 +05:30
KaifAhmad1 75fbeeb7e2 Implement GraphReasoner, fix KG validation and normalization, and update RAG cookbook 2025-12-22 19:46:59 +05:30
KaifAhmad1 1f45fe1197 Refactor GraphRAG notebook: prioritize data quality, modularize cells, and improve pipeline structure 2025-12-22 18:39:53 +05:30
KaifAhmad1 ef829ce0d5 Fix 0 entities/relations issue in GraphRAG notebook and improve GraphBuilder logic 2025-12-22 18:06:31 +05:30
KaifAhmad1 a8828741e1 Fix conflict detector input handling and add unified Reasoner 2025-12-22 17:15:12 +05:30
Mohd Kaif 8e3f06e3a3 Merge pull request #115 from Hawksight-AI/docs
docs: enhance GraphRAG notebooks with advanced features and update do…
2025-12-22 16:28:13 +05:30
KaifAhmad1 27e1d94290 Merge origin/main into docs and resolve conflicts 2025-12-22 16:27:42 +05:30
KaifAhmad1 6e0bb43d6c docs: enhance GraphRAG notebooks with advanced features and update documentation 2025-12-22 16:22:39 +05:30
KaifAhmad1 529f099ddd Fix AttributeError in WebIngestor and upgrade to KG-aware chunking in GraphRAG notebook 2025-12-22 15:45:33 +05:30
KaifAhmad1 0c9d6dad64 Refine notebooks: Removed all emojis for a cleaner, professional presentation 2025-12-22 15:02:27 +05:30
KaifAhmad1 7525f14e7f Enhance GraphRAG notebook: Expanded knowledge hub with 10+ sources and multi-source ingestion logic 2025-12-22 14:19:46 +05:30
KaifAhmad1 e96bd62ebf Enhance GraphRAG notebook: integrated all Semantica modules with real data sources 2025-12-22 14:14:03 +05:30
KaifAhmad1 0e2f1369dd fix: JSON syntax errors in GraphRAG notebook 2025-12-22 13:54:29 +05:30
KaifAhmad1 eb94b3a5ce Refactor GraphRAG notebook to use Semantica high-level API and add enterprise examples 2025-12-22 13:24:49 +05:30
KaifAhmad1 4166de2777 Fix GraphRAG notebook chunking logic and repo ingestor git options 2025-12-22 12:51:12 +05:30
KaifAhmad1 640315e287 Update GraphRAG notebook: Replace MCP with File/Repo ingestion and fix parsing logic 2025-12-22 12:17:18 +05:30
KaifAhmad1 a6fde080a9 Update GraphRAG notebook with real data sources and fix API usage 2025-12-22 11:29:01 +05:30
KaifAhmad1 6b4a5f1a89 Merge branch 'main' of https://github.com/Hawksight-AI/semantica 2025-12-21 19:10:20 +05:30
KaifAhmad1 ae3febfa05 Add RAG vs GraphRAG comparison notebook and update docs 2025-12-21 19:08:59 +05:30
Mohd Kaif a1674f6aa3 Merge pull request #114 from Hawksight-AI/vector-store
Fix Vector Store Cookbook Usage
2025-12-21 18:44:02 +05:30
KaifAhmad1 a408bc1958 Fix vector store usage in cookbooks and remove PR description 2025-12-21 18:40:31 +05:30
Mohd Kaif b817816d5d Merge pull request #113 from Hawksight-AI/ontology
Advanced Ontology Extraction & Notebook Fixes
2025-12-21 17:44:55 +05:30
KaifAhmad1 6582481a28 docs: remove Advanced_Triplet_Store notebook and references 2025-12-21 17:40:01 +05:30
Mohd Kaif 9a999c02cb Merge pull request #112 from Hawksight-AI/ontology
Advanced Ontology Extraction & Notebook Fixes
2025-12-21 17:29:25 +05:30
KaifAhmad1 409e8c3d5c feat: update unstructured to ontology notebook and cleanup 2025-12-21 17:26:54 +05:30
Mohd Kaif 88e16b8360 Merge pull request #111 from Hawksight-AI/context-engineering
feat: Context Engineering Improvements & Documentation Update
2025-12-21 16:53:44 +05:30
KaifAhmad1 a9bd3be689 Update context module docs, cleanup notebook, and refactor context files 2025-12-21 16:50:56 +05:30
KaifAhmad1 02a6f3fac2 Fix Temporal KG notebook: update query parameters, version keys, and enable Plotly 2025-12-21 15:53:56 +05:30
KaifAhmad1 34284077cf fix: resolve NameError for 'Type' in config_manager.py 2025-12-21 15:03:59 +05:30
KaifAhmad1 724d75afbc Enhance Temporal Knowledge Graph notebook with deep dive into modules and advanced visualization 2025-12-21 14:09:33 +05:30
KaifAhmad1 fe1d8c425c Fix TripletStore initialization and store method; update notebooks 2025-12-20 21:10:50 +05:30
Mohd Kaif 35760f97aa Merge pull request #110 from Hawksight-AI/ingest
Fix API Usage in Semantic Layer Construction Notebook
2025-12-20 20:43:34 +05:30
KaifAhmad1 d987abd7a9 fix: update notebook 09 with correct API usage and imports 2025-12-20 20:40:34 +05:30
Mohd Kaif 7e09892bc4 Merge pull request #109 from Hawksight-AI/ingest
Fix Multi-Source Integration Notebook & Remove Deprecated Pipeline Orchestration Notebook
2025-12-20 20:24:44 +05:30
KaifAhmad1 1fceb634ae chore: remove 07_Pipeline_Orchestration notebook and all references 2025-12-20 20:18:14 +05:30
Mohd Kaif 8705724b23 Merge pull request #108 from Hawksight-AI/ingest
Fix: Harden Notebook Integration & Resolve Community Detection Errors
2025-12-20 19:34:25 +05:30
KaifAhmad1 bd3bc7de7d fix(notebook): harden ingestion, fix community detection, update MCP URLs 2025-12-20 19:32:30 +05:30
KaifAhmad1 712abf0e7d Update multi-source integration notebook and dependencies 2025-12-19 23:03:01 +05:30
KaifAhmad1 d73bcd52c4 Update Multi-Source Integration notebook: separate install, add MCP, remove Advanced keyword 2025-12-19 22:33:15 +05:30
KaifAhmad1 859f4765fd Fix notebook content and enhance markdown formatting 2025-12-19 22:14:14 +05:30
KaifAhmad1 13a5c383c7 Enhance notebook markdown formatting and structure 2025-12-19 22:07:58 +05:30
Mohd Kaif b8f0f40d16 Merge pull request #107 from Hawksight-AI/export
feat: Add missing RDF export and ontology generation methods
2025-12-19 19:28:41 +05:30
KaifAhmad1 cbab6e4633 feat: Add missing RDF export and ontology generation methods
- Added generate_from_graph alias in OntologyGenerator
- Added export_knowledge_graph alias in RDFExporter
- Implemented convert_kg_to_rdf in RDFSerializer
- Implemented serialize_to_ntriples in RDFSerializer
2025-12-19 19:26:32 +05:30
Mohd Kaif 432e883ca9 Merge pull request #106 from Hawksight-AI/visualization
Temporal Visualization Enhancements
2025-12-19 18:24:02 +05:30
KaifAhmad1 c880984e40 feat: Enhance temporal visualization with comprehensive dashboard and network evolution 2025-12-19 18:20:14 +05:30
KaifAhmad1 ee56ca3829 Fix ProcessingError in temporal visualization by generating events 2025-12-19 17:10:00 +05:30
KaifAhmad1 e18b1cc123 Fix visualization notebook errors and update dependencies 2025-12-19 16:51:53 +05:30
KaifAhmad1 dc94526e9a Fix GraphValidator: Add missing details to dangling edge issues 2025-12-19 16:16:17 +05:30
Mohd Kaif 3f78d00c6b Merge pull request #105 from Hawksight-AI/kg
PR Title: Update Advanced Graph Analytics Notebook & Add Graph Validator
2025-12-19 13:29:58 +05:30
KaifAhmad1 52d94bb1d7 Update Advanced Graph Analytics notebook and validator 2025-12-19 13:28:01 +05:30
Mohd Kaif a9538a0ddd Merge pull request #104 from Hawksight-AI/semantic-extract
Refactor: Rename LLMEnhancer to LLMExtraction
2025-12-19 00:19:24 +05:30
KaifAhmad1 5fc188b9eb Refactor: Rename LLMEnhancer to LLMExtraction 2025-12-19 00:16:44 +05:30
KaifAhmad1 30e0dc81de Fix AttributeError in Event extraction examples and docs 2025-12-18 23:18:25 +05:30
KaifAhmad1 9e1aa64043 Update Triplet Store notebook with connection handling and path setup 2025-12-18 22:56:35 +05:30
KaifAhmad1 6eca6af7bc Merge branch 'main' of https://github.com/Hawksight-AI/semantica 2025-12-18 22:28:52 +05:30
KaifAhmad1 eb5980a1fb Finalize triplet store refactoring and documentation updates 2025-12-18 22:28:15 +05:30
KaifAhmad1 ec6cfdf304 Update docs: Enhance CONTRIBUTING.md with performance section & add Contributors widget to README 2025-12-18 22:14:02 +05:30
Mohd Kaif bb63faa1ec Merge pull request #103 from Hawksight-AI/triplet-store
Triplet Store Module: Unified Interface & New Backends
2025-12-18 21:42:56 +05:30
KaifAhmad1 38962d3d7a Refactor triplet_store: Unified TripletStore interface, removed Virtuoso/TripletManager, added Blazegraph/Jena/RDF4J support, updated docs and notebooks 2025-12-18 21:37:11 +05:30
Mohd Kaif fbe0ed1a41 Delete context_tutorial_data/saved_agent directory 2025-12-18 18:34:55 +05:30
Mohd Kaif affb16de9e Merge pull request #102 from Hawksight-AI/context-engineering
Context Engineering Module Overhaul & Advanced Documentation
2025-12-18 18:33:46 +05:30
KaifAhmad1 8d6b38d7da Refactor Context Engineering module, rebuild advanced notebook, and update README 2025-12-18 18:30:16 +05:30
Mohd Kaif a1ae001618 Merge pull request #101 from Hawksight-AI/context-engineering
feat(embeddings): Switch Default Embedding Engine to FastEmbed
2025-12-18 13:43:26 +05:30
KaifAhmad1 5cc0c7eac4 feat(embeddings): switch default to FastEmbed and update docs
Set FastEmbed as default embedding provider in TextEmbedder. Updated dependencies in pyproject.toml. Refreshed Context Module notebook and documentation to reflect changes. Added verification tests.
2025-12-18 13:40:39 +05:30
Mohd Kaif 734585ed92 Merge pull request #100 from Hawksight-AI/context-engineering
Feature: Context Engineering & Persistence Overhaul
2025-12-18 00:59:20 +05:30
KaifAhmad1 e45875f924 feat: enhance context module with persistence and FastEmbed
- Updated AgentContext, AgentMemory, and ContextGraph to support save/load persistence
- Integrated FastEmbed into VectorStore for high-performance local embeddings
- Replaced DemoVectorStore with production VectorStore in docs and examples
- Rebuilt 19_Context_Module.ipynb as a deep dive into context engineering
- Updated documentation and README to reflect new capabilities
2025-12-18 00:56:56 +05:30
KaifAhmad1 1620de371f Update cookbook/introduction/18_Deduplication.ipynb 2025-12-17 23:49:49 +05:30
Mohd Kaif ae4e93923e Merge pull request #99 from Hawksight-AI/conflicts
Improve Deduplication Logic: Jaro-Winkler Default & Disjoint Property Handling
2025-12-17 23:12:07 +05:30
KaifAhmad1 7297d46ac8 Fix deduplication logic: Jaro-Winkler default, disjoint property handling, and docs update 2025-12-17 23:08:38 +05:30
Mohd Kaif 1a124c7294 Merge pull request #98 from Hawksight-AI/conflicts
Refactor: Simplify Merge Strategy Syntax
2025-12-17 22:30:05 +05:30
KaifAhmad1 0a052b676d Refactor deduplication module to support simplified string-based merge strategies and update documentation 2025-12-17 22:27:16 +05:30
KaifAhmad1 0476950fdf Refactor Deduplication notebook to use cell-local imports for better clarity 2025-12-17 21:33:12 +05:30
KaifAhmad1 a467cb5af6 Fix deduplication notebook code cells and workflow 2025-12-17 21:11:45 +05:30
Mohd Kaif 89235d1f19 Merge pull request #97 from Hawksight-AI/conflicts
Fix conflict resolution metadata and notebook output
2025-12-17 20:20:09 +05:30
KaifAhmad1 3934c74300 Fix conflict resolution metadata and notebook output 2025-12-17 20:17:03 +05:30
Mohd Kaif 8f8e532114 Merge pull request #96 from Hawksight-AI/conflicts
Improve conflicts documentation & notebook; align examples with current APIs
2025-12-17 19:15:06 +05:30
KaifAhmad1 b091c870bc Improve conflicts docs and notebook; align conflicts APIs 2025-12-17 19:12:16 +05:30
KaifAhmad1 53f6aba967 refactor: distribute imports to relevant cells in conflict detection notebook 2025-12-17 16:35:57 +05:30
KaifAhmad1 0b67bfa998 fix: JSON syntax error in conflict detection notebook 2025-12-17 16:28:39 +05:30
Mohd Kaif 381de30cbd Merge pull request #95 from Hawksight-AI/conflicts
Update conflict resolution notebook and fix module errors
2025-12-17 14:38:15 +05:30
KaifAhmad1 999c490ba9 Update conflict resolution notebook and fix module errors 2025-12-17 14:33:09 +05:30
KaifAhmad1 00322d81c6 feat: enhance visualization and fix source tracker 2025-12-17 13:34:21 +05:30
KaifAhmad1 ad6dd1af4f Cleanup temporary and update scripts 2025-12-17 12:11:27 +05:30
KaifAhmad1 78a3b4a6cd Update export notebook and ontology files 2025-12-17 12:07:04 +05:30
Mohd Kaif 07208318ec Merge pull request #94 from Hawksight-AI/ontology
Fix Ontology Notebook and robustify Library Components
2025-12-17 01:28:15 +05:30
KaifAhmad1 ea6cfdf6a8 Fix Ontology notebook and related library bugs (missing entities, punctuation handling, imports key, version recursion) 2025-12-17 01:26:03 +05:30
KaifAhmad1 7439f31399 refactor: revamp ontology notebook with comprehensive module coverage 2025-12-17 00:34:59 +05:30
Mohd Kaif 8a25494f55 Merge pull request #93 from Hawksight-AI/ontology
PR: Update Ontology Module to 6-Stage Pipeline with Validation
2025-12-17 00:13:14 +05:30
KaifAhmad1 72d948972b Update ontology module: 6-stage pipeline, OntologyValidator integration, and documentation updates 2025-12-17 00:10:51 +05:30
KaifAhmad1 a62326a61f Manual update to 13_Vector_Store.ipynb 2025-12-16 22:46:50 +05:30
KaifAhmad1 e171e86daa Fix dimension mismatch and remove convenience functions section from 13_Vector_Store.ipynb 2025-12-16 22:36:24 +05:30
KaifAhmad1 6dc4f69c84 refactor: overhaul 13_Vector_Store.ipynb with mastery guide format and fix numpy truthiness bug in hybrid_search.py 2025-12-16 22:05:43 +05:30
Mohd Kaif 45205ad54d Merge pull request #92 from Hawksight-AI/vector-store
Refactor: Rename "Adapter" to "Store" & Fix Vector Store Bugs
2025-12-16 20:48:00 +05:30
KaifAhmad1 dd6b341fb9 Refactor: Rename Adapter to Store across Vector, Graph, and Triplet stores. Update docs and tests. 2025-12-16 20:45:11 +05:30
Mohd Kaif 77186a518d Merge pull request #91 from Hawksight-AI/conflicts
Refactor: Remove QA Components & Enforce Submodule Imports
2025-12-16 17:54:12 +05:30
KaifAhmad1 adabdd283f Refactor imports to use submodule-specific paths and remove generic exports 2025-12-16 17:49:41 +05:30
Mohd Kaif abe730891f Merge pull request #90 from Hawksight-AI/conflicts
Refactor: Remove Deferred QA Components and Cleanup References
2025-12-16 17:27:57 +05:30
KaifAhmad1 96702923de Remove QA components (OntologyValidator, ConflictDetector, etc) and fix residual references 2025-12-16 17:25:15 +05:30
KaifAhmad1 bfd4bd60e5 fix(split): add id field to Chunk class and update provenance tracking logic in notebook 2025-12-15 23:16:11 +05:30
KaifAhmad1 e211a7bf57 Fix Chunking Notebook errors and Windows Unicode encoding issues
- Fix AttributeError in SlidingWindowChunker notebook example by using correct chunk attributes (start_index/end_index).
- Update SlidingWindowChunker initialization in notebook (window_size->chunk_size, step_size->stride).
- Fix UnicodeEncodeError in progress_tracker.py by adding fallback encoding for Windows console output.
- Minor updates to chunk validator and table chunker.
2025-12-15 22:22:13 +05:30
KaifAhmad1 30e2645a98 Remove temporary output files 2025-12-15 21:18:39 +05:30
KaifAhmad1 e5e8823423 Fix relation extraction for dependency method 2025-12-15 21:14:08 +05:30
KaifAhmad1 b5c91a90a3 fix(split): populate entities/relations in chunk metadata and reload modules in notebook 2025-12-15 19:30:49 +05:30
KaifAhmad1 569fdc31f1 fix(kg): update GraphAnalyzer metrics keys and fix notebook usage 2025-12-15 19:11:04 +05:30
KaifAhmad1 bdcaab92b0 docs(cookbook): update Neo4j connection details in 09_Graph_Store.ipynb 2025-12-15 18:36:41 +05:30
KaifAhmad1 3f4e6f831f fix(cookbook): fix missing graph visualization in 08_Your_First_Knowledge_Graph.ipynb 2025-12-15 17:57:38 +05:30
KaifAhmad1 52aa1a6896 Enhance KG notebooks and fix GraphBuilder data processing bug 2025-12-15 17:10:35 +05:30
KaifAhmad1 d34731d687 fix(cookbook): resolve syntax and API usage errors in KG notebook
- Fix indentation error in GraphBuilder loop
- Update EntityResolver.resolve to resolve_entities
- Update GraphValidator result access to use dataclass attributes
- Fix deduplication logic to preserve unmerged entities
2025-12-15 16:33:42 +05:30
Mohd Kaif 8dace2f078 Merge pull request #89 from Hawksight-AI/triplet-store
Refactor: Standardize "Triple" to "Triplet" Terminology
2025-12-15 16:13:14 +05:30
KaifAhmad1 4fdc483935 Refactor terminology: Triple -> Triplet across codebase, docs, and notebooks 2025-12-15 16:09:20 +05:30
KaifAhmad1 d042054f9a Fix relation extraction methods and resolve AttributeError in Knowledge Graph notebook
- Fixed pattern-based relation extraction by using entity patterns for subjects to ensure validity.
- Improved dependency-based relation extraction to handle nested prepositional phrases and passive voice.
- Increased cooccurrence confidence threshold to meet defaults.
- Fixed AttributeError in 07_Building_Knowledge_Graphs.ipynb by replacing dict.get() with direct attribute access for Entity/Relation dataclasses.
2025-12-15 00:28:01 +05:30
KaifAhmad1 c2d7d92a53 Fix relation extraction methods: dependency and cooccurrence
- Fix cooccurrence method confidence score to meet default threshold (0.5 -> 0.6)
- Fix dependency method to handle passive voice and better token-to-entity mapping
2025-12-14 23:55:48 +05:30
KaifAhmad1 b6e27b7d71 Improve relation extraction: expand patterns and fix regex subject matching 2025-12-14 23:20:09 +05:30
KaifAhmad1 444746de02 fix(normalize): handle currency symbols in number normalizer 2025-12-14 22:41:59 +05:30
KaifAhmad1 e8655a97ed Fix NumberNormalizer suffix support and update Normalization cookbook 2025-12-14 20:51:25 +05:30
KaifAhmad1 f15ab2a327 Fix XMLData attribute error in Document Parsing notebook 2025-12-14 20:37:07 +05:30
KaifAhmad1 2f9ad467f0 Fix bugs in Ingestion module and update Data Ingestion cookbook 2025-12-14 18:03:25 +05:30
KaifAhmad1 253d35ee31 Fix NameError and enhance sample file generation in Data Ingestion cookbook 2025-12-14 15:31:52 +05:30
KaifAhmad1 09e7e61111 Fix GraphExporter to support output_path argument in export method 2025-12-14 14:53:00 +05:30
KaifAhmad1 05f553271d Fix TextSplitter error, GraphExporter usage, and general improvements 2025-12-14 14:16:49 +05:30
KaifAhmad1 ccb3f43104 Update cookbooks: remove version checks and ensure pip install 2025-12-13 23:03:29 +05:30
Mohd Kaif 6be868e067 Delete cookbook/introduction/welcome_docs directory 2025-12-13 21:56:01 +05:30
KaifAhmad1 7b7d3fa8ad Refactor modules for pipeline API compatibility and fix bugs 2025-12-13 21:54:48 +05:30
KaifAhmad1 c178b8dead Enhance Welcome notebook: validate pipeline, refine docs, and ensure full module coverage 2025-12-13 19:24:50 +05:30
KaifAhmad1 8b9f6dbd09 Update Welcome notebook: Fix opening issue and add comprehensive module reference tables 2025-12-13 18:52:12 +05:30
KaifAhmad1 096ad31f77 Add runnable Semantica install cells to cookbook notebooks 2025-12-13 17:13:43 +05:30
KaifAhmad1 4b7cc5a359 chore: sync cookbook notebook updates 2025-12-13 15:59:49 +05:30
Mohd Kaif c41f2951b2 Merge pull request #88 from Hawksight-AI/pipeline
Fix pipeline orchestration and add E2E tests
2025-12-13 15:09:53 +05:30
KaifAhmad1 a047ebf74f Merge main into pipeline and resolve visualization conflicts 2025-12-13 15:08:47 +05:30
KaifAhmad1 88c12b1867 Add pipeline orchestration fixes and E2E tests 2025-12-13 15:03:34 +05:30
KaifAhmad1 094bb8d82b Recommit pipeline orchestration and e2e tests 2025-12-13 15:01:37 +05:30
Mohd Kaif 7ff2fd9981 Merge pull request #87 from Hawksight-AI/visualization
Enhancement of Visualization Module & Comprehensive Testing Suite
2025-12-12 23:14:00 +05:30
KaifAhmad1 0a555145e4 Enhance visualization module with comprehensive testing and robust dependency handling 2025-12-12 23:10:17 +05:30
Mohd Kaif 994e58a170 Delete PR_DESCRIPTION.md 2025-12-12 20:24:25 +05:30
Mohd Kaif 244144dee3 Merge pull request #86 from Hawksight-AI/vector-store
Refactor: Remove Pinecone and Enhance Vector Store Backend Support
2025-12-12 20:23:51 +05:30
KaifAhmad1 5dfca85500 Merge branch 'main' into vector-store: Resolve PR_DESCRIPTION.md modify/delete conflict by keeping local version 2025-12-12 20:23:15 +05:30
KaifAhmad1 f3dd7a05bd Refactor: Remove Pinecone and enhance vector store backend support
- Removed all Pinecone references, adapters, and documentation to align with open-source, self-hosted focus.
- Removed PineconeAdapter and related dependencies.
- Updated VectorStore to enforce supported backends (FAISS, Weaviate, Qdrant, Milvus, InMemory).
- Updated cookbooks (e.g., 13_Vector_Store.ipynb) to use Weaviate/FAISS examples instead of Pinecone.
- Updated core documentation (modules.md, rchitecture.md, etc.) to reflect backend changes.
- Added new tests (	est_pinecone_removal.py, 	est_vector_store_deepdive.py) to verify removal and validate remaining backends.
- Verified all vector store tests pass.
2025-12-12 20:19:17 +05:30
Mohd Kaif d03a237278 Delete PR_DESCRIPTION.md 2025-12-12 18:50:33 +05:30
Mohd Kaif f3ac9fbffa Merge pull request #85 from Hawksight-AI/triplet-store
Refactor: Rename `triple_store` to `triplet_store`
2025-12-12 18:48:41 +05:30
KaifAhmad1 6856580a7a Refactor: Rename triple_store to triplet_store across codebase
- Renamed semantica/triple_store to semantica/triplet_store
- Updated all imports and class references in core modules and adapters
- Refactored Jupyter notebooks in cookbook/
- Updated documentation files (README, docs/, etc.)
- Updated tests and verified passing status
2025-12-12 18:45:00 +05:30
KaifAhmad1 4a282628ea Merge branch 'main' of https://github.com/Hawksight-AI/semantica 2025-12-12 16:31:43 +05:30
KaifAhmad1 c73e35a2fe docs: update chunking cookbook and PR description 2025-12-12 16:30:59 +05:30
Mohd Kaif a99f18b71b Merge pull request #84 from Hawksight-AI/split
Fix & Align Split Module with Documentation
2025-12-12 16:21:55 +05:30
KaifAhmad1 84b90b45a2 fix: align split methods with documentation and registry 2025-12-12 16:15:57 +05:30
Mohd Kaif d7d589f64e Merge pull request #83 from Hawksight-AI/semantic-extract
Refactor Semantic Extract Module to Class-Based Interfaces
2025-12-12 13:25:58 +05:30
KaifAhmad1 d3366bbcf0 Refactor Semantic Extract module: Update notebooks, docs, and implementation to use class-based interfaces 2025-12-12 13:23:37 +05:30
Mohd Kaif 95c5486d22 Merge pull request #82 from Hawksight-AI/seed
Enhance SeedDataManager with Robust CSV/JSON Support
2025-12-12 12:10:09 +05:30
498 changed files with 227099 additions and 44198 deletions
+20
View File
@@ -0,0 +1,20 @@
# Linguist documentation and generated files
# This ensures GitHub language statistics reflect the core Python code
# Mark the entire docs directory as documentation
docs/* linguist-documentation
# Mark the cookbook directory as documentation/examples
cookbook/* linguist-documentation
# Specifically ignore large generated HTML/JSON files in cookbook
cookbook/**/*.html linguist-documentation
cookbook/**/*.json linguist-documentation
cookbook/**/*.graphml linguist-documentation
cookbook/**/*.ttl linguist-documentation
# Ensure .ipynb files are treated as documentation/examples
cookbook/**/*.ipynb linguist-documentation
# Mark data directories as documentation or vendored
**/data/* linguist-vendored
+4
View File
@@ -8,7 +8,11 @@ on:
branches: [main]
paths:
- 'docs/**'
- 'semantica/**'
- 'mkdocs.yml'
- 'requirements-docs.txt'
- 'CHANGELOG.md'
- 'RELEASE.md'
workflow_dispatch:
# Permissions needed to deploy to GitHub Pages
+57 -2
View File
@@ -7,6 +7,61 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Fixed
- Fixed model switching bug in `TextEmbedder` where internal state was not cleared, preventing dynamic updates between `fastembed` and `sentence_transformers` (#160).
- Implemented model-intrinsic embedding dimension detection in `TextEmbedder` to ensure consistency between models and vector databases.
- Updated `set_model` to properly refresh configuration and dimensions during model switches.
### Added
- Added comprehensive unit test suite `tests/embeddings/test_model_switching.py` for verifying dynamic model transitions and dimension updates.
- Fixed `TypeError: unhashable type: 'Entity'` in `GraphAnalyzer` when processing graphs with raw `Entity` objects or dictionaries in relationships (#159).
- Robustified ID extraction across `CentralityCalculator`, `CommunityDetector`, and `ConnectivityAnalyzer` to handle various entity formats.
- Improved `Entity` class hashability and equality logic in `utils/types.py`.
- Added end-to-end integration test suite for Knowledge Graph pipeline validation (GraphBuilder -> EntityResolver -> GraphAnalyzer).
- Fixed orchestrator lazy property initialization and configuration normalization logic in `Orchestrator`.
- Resolved `AssertionError` in orchestrator tests by aligning test mocks with production component usage.
- Fixed dependency compatibility issues by pinning `protobuf==4.25.3` and `grpcio==1.67.1`.
- Added missing dependencies `GitPython` and `chardet` to `pyproject.toml`.
- Verified and aligned `FileObject.text` property usage in GraphRAG notebooks for consistent content decoding.
### Added
- **Semantic Extract Improvements**:
- Introduced `auto-chunking` for long text processing in LLM extraction methods (`extract_entities_llm`, `extract_relations_llm`, `extract_triplets_llm`).
- Added `silent_fail` parameter to LLM extraction methods for configurable error handling.
- Implemented robust JSON parsing and automatic retry logic (3 attempts with exponential backoff) in `BaseProvider` for all LLM providers.
- Enhanced `GroqProvider` with better diagnostics and connectivity testing.
- Added comprehensive entity, relation, and triplet deduplication for chunked extraction.
### Fixed
- Fixed a bug in `TripletExtractor` where the `validate_triplets` method was shadowed by an internal attribute.
- Fixed incorrect `TextSplitter` import path in the `semantic_extract.methods` module.
## [0.1.1] - 2026-01-05
### Added
- Exported `DoclingParser` and `DoclingMetadata` from `semantica.parse` for easier access.
- Added comprehensive `DoclingParser` usage examples to README and documentation.
- Added Windows-specific troubleshooting note for PyTorch DLL issues.
### Fixed
- Fixed `DoclingParser` import/export issues across platforms (Windows, Linux, Google Colab).
- Improved error messaging when optional `docling` dependency is missing.
- Fixed versioning inconsistencies across the framework.
## [0.1.0] - 2025-12-31
### Added
- New command-line interface (`semantica` CLI) with support for knowledge base building and info commands.
- Integrated FastAPI-based REST API server for remote access to framework functionality.
- Dedicated background worker component for scalable task processing and pipeline execution.
- Framework-level versioning configuration for PyPI distribution.
- Automated release workflow with Trusted Publishing support.
### Changed
- Updated versioning across the framework to 0.1.0.
- Refined entry point configurations in `pyproject.toml`.
- Improved lazy module loading for core framework components.
## [0.0.5] - 2025-11-26
### Changed
@@ -49,7 +104,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Core framework architecture
- Universal data ingestion (50+ file formats)
- Universal data ingestion (multiple file formats)
- Semantic intelligence engine (NER, relation extraction, event detection)
- Knowledge graph construction with entity resolution
- 6-stage ontology generation pipeline
@@ -58,7 +113,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Production-ready quality assurance modules
- Comprehensive documentation with MkDocs
- Cookbook with interactive tutorials
- Support for multiple vector stores (Pinecone, Weaviate, Qdrant, FAISS)
- Support for multiple vector stores (Weaviate, Qdrant, FAISS)
- Support for multiple graph databases (Neo4j, NetworkX, RDFLib)
- Temporal knowledge graph support
- Conflict detection and resolution
+15 -6
View File
@@ -326,14 +326,23 @@ def extract_entities(
## Types of Contributions
### Code Contributions
### 💻 Code Contributions
- Bug fixes
- New features
- Performance improvements
- Refactoring
- **Bug Fixes**: Resolving issues reported in the issue tracker.
- **New Features**: Implementing new capabilities (please discuss via an issue first!).
- **Refactoring**: Improving code structure and maintainability without changing behavior.
- **Algorithm Optimization**: Improving the efficiency of graph algorithms and vector search.
### Documentation Contributions
#### ⚡ Performance and Latency
We deeply value efficiency. Contributions that make Semantica faster and lighter are highly appreciated!
- **Latency Reduction**: Optimize critical paths and RAG pipeline response times.
- **Memory Optimization**: Reduce graph/vector processing memory footprint.
- **Throughput**: Improve operations per second (bulk ingestion, parallel queries).
- **Benchmarks**: Add performance benchmarks to track regressions.
- **Async/Concurrency**: Enhance asynchronous execution and concurrency.
### 📚 Documentation Contributions
- Fix typos and grammar
- Improve clarity
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2025 Hawksight AI
Copyright (c) 2026 Hawksight AI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+437 -140
View File
@@ -6,9 +6,10 @@
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![PyPI version](https://badge.fury.io/py/semantica.svg)](https://pypi.org/project/semantica/0.0.1/)
[![Downloads](https://pepy.tech/badge/semantica)](https://pepy.tech/project/semantica)
[![Discord](https://img.shields.io/discord/semantica?color=7289da&label=discord)](https://discord.gg/semantica)
[![PyPI version](https://badge.fury.io/py/semantica.svg)](https://pypi.org/project/semantica/)
[![Monthly Downloads](https://img.shields.io/pypi/dm/semantica)](https://pypi.org/project/semantica/)
[![Total Downloads](https://static.pepy.tech/badge/semantica)](https://pepy.tech/project/semantica)
[![Discord](https://img.shields.io/badge/Discord-Join%20Us-7289da?style=flat&logo=discord&logoColor=white)](https://discord.gg/pMHguUzG)
[![CI](https://github.com/Hawksight-AI/semantica/workflows/CI/badge.svg)](https://github.com/Hawksight-AI/semantica/actions)
<p align="center">
@@ -27,9 +28,9 @@
*The missing fabric between raw data and AI engineering. A comprehensive open-source framework for building semantic layers and knowledge engineering systems that transform unstructured data into AI-ready knowledge — powering Knowledge Graph-Powered RAG (GraphRAG), AI Agents, Multi-Agent Systems, and AI applications with structured semantic knowledge.*
**100% Open Source****MIT Licensed****Production Ready****Community Driven**
**100% Open Source****MIT Licensed** **Latest Version: 0.1.1** **Production Ready****Community Driven**
[**Discord**](https://discord.gg/semantica) • [**GitHub**](https://github.com/Hawksight-AI/semantica)
[**Discord**](https://discord.gg/pMHguUzG)
</div>
@@ -81,58 +82,16 @@ Organizations have **unstructured data** (PDFs, emails, logs), **messy data** (i
Semantica operates through three integrated layers that transform raw data into AI-ready knowledge:
**Input Layer** — Universal ingestion from 50+ data formats (PDFs, DOCX, HTML, JSON, CSV, databases, live feeds, APIs, streams, archives, multi-modal content) into a unified pipeline.
**Input Layer** — Universal ingestion from multiple data formats (PDFs, DOCX, HTML, JSON, CSV, databases, live feeds, APIs, streams, archives, multi-modal content) into a unified pipeline.
**Semantic Layer** — Core intelligence engine performing entity extraction, relationship mapping, ontology generation, context engineering, and quality assurance. This is where unstructured data transforms into structured knowledge.
**Semantic Layer** — Core intelligence engine performing entity extraction, relationship mapping, ontology generation, context engineering, and quality assurance. Includes **advanced entity deduplication** (Jaro-Winkler, disjoint property handling) to ensure a clean single source of truth.
**Output Layer** — Production-ready knowledge graphs, vector embeddings, and validated ontologies that power GraphRAG systems, AI agents, and multi-agent systems.
**Powers: GraphRAG, AI Agents, Multi-Agent Systems**
#### Semantica Processing Flow
<details>
<summary>View Interactive Flowchart</summary>
```mermaid
flowchart TD
A[Raw Data Sources<br/>PDFs, Emails, Logs, Databases<br/>50+ Formats] --> B[Input Layer<br/>Universal Data Ingestion]
B --> C[Format Detection<br/>& Parsing]
C --> D[Normalization<br/>& Preprocessing]
D --> E[Semantic Layer<br/>Core Intelligence]
E --> F[Entity Extraction<br/>NER + LLM Enhancement]
E --> G[Relationship Mapping<br/>Triple Generation]
E --> H[Ontology Generation<br/>6-Stage Pipeline]
E --> I[Context Engineering<br/>Semantic Enrichment]
E --> J[Quality Assurance<br/>Conflict Detection]
F --> K[Output Layer]
G --> K
H --> K
I --> K
J --> K
K --> L[Knowledge Graphs<br/>Production-Ready]
K --> M[Vector Embeddings<br/>Semantic Search]
K --> N[Ontologies<br/>OWL Validated]
L --> O[Application Layer]
M --> O
N --> O
O --> P[GraphRAG Engine<br/>91% Accuracy]
O --> Q[AI Agents<br/>Persistent Memory]
O --> R[Multi-Agent Systems<br/>Shared Models]
O --> S[Analytics & BI<br/>Graph Insights]
style A fill:#e1f5ff
style E fill:#fff4e1
style K fill:#e8f5e9
style O fill:#f3e5f5
```
</details>
### What Happens Without Semantics?
@@ -153,13 +112,15 @@ flowchart TD
### How Semantica Solves These Problems
**Universal Data Ingestion** — Handles 50+ formats (PDF, DOCX, HTML, JSON, CSV, databases, APIs, streams) with unified pipeline, no custom parsers needed.
**Efficient Embeddings** — Uses **FastEmbed** by default for high-performance, lightweight local embedding generation (faster than sentence-transformers).
**Automated Semantic Extraction** — NER, relationship extraction, and triple generation with LLM enhancement discovers entities and relationships automatically.
**Universal Data Ingestion** — Handles multiple formats (PDF, DOCX, HTML, JSON, CSV, databases, APIs, streams) with unified pipeline, no custom parsers needed.
**Automated Semantic Extraction** — NER, relationship extraction, and triplet generation with LLM enhancement. Includes **auto-chunking** for long documents and **robust error handling** with automatic retry logic.
**Knowledge Graph Construction** — Production-ready graphs with entity resolution, temporal support, and graph analytics. Queryable knowledge ready for AI applications.
**GraphRAG Engine** — Hybrid vector + graph retrieval achieves 91% accuracy (30% improvement) via semantic search + graph traversal for multi-hop reasoning.
**GraphRAG Engine** — Hybrid vector + graph retrieval achieves 91% accuracy (30% improvement) via semantic search + graph traversal for multi-hop reasoning. Features LLM-generated responses grounded in knowledge graph context with reasoning traces. [See Comparison Benchmark](cookbook/use_cases/advanced_rag/02_RAG_vs_GraphRAG_Comparison.ipynb)
**AI Agent Context Engineering** — Persistent memory with RAG + knowledge graphs enables context maintenance, action validation, and structured knowledge access.
@@ -173,12 +134,13 @@ flowchart TD
| **Feature Category** | **Capabilities** | **Key Benefits** |
|:---------------------|:-----------------|:------------------|
| **Data Ingestion** | 50+ formats (PDF, DOCX, HTML, JSON, CSV, databases, APIs, streams, archives) | Universal ingestion, no custom parsers needed |
| **Semantic Extraction** | NER, relationship extraction, triple generation, LLM enhancement | Automated discovery of entities and relationships |
| **Data Ingestion** | Multiple formats (PDF, DOCX, HTML, JSON, CSV, databases, APIs, streams, archives) | Universal ingestion, no custom parsers needed |
| **Semantic Extraction** | NER, relations, triplets, LLM enhancement, **auto-chunking** | Automated discovery with robust error handling |
| **Knowledge Graphs** | Entity resolution, temporal support, graph analytics, query interface | Production-ready, queryable knowledge structures |
| **Ontology Generation** | 6-stage LLM pipeline, OWL generation, HermiT/Pellet validation | Automated ontology creation from documents |
| **GraphRAG** | Hybrid vector + graph retrieval, multi-hop reasoning | 91% accuracy, 30% improvement over vector-only |
| **Agent Memory** | Persistent memory, RAG integration, MCP-compatible tools | Context-aware agents with semantic understanding |
| **GraphRAG** | Hybrid vector + graph retrieval, multi-hop reasoning, LLM-generated responses | 91% accuracy, 30% improvement over vector-only, reasoning traces |
| **LLM Providers** | Unified interface to 100+ LLMs (Groq, OpenAI, HuggingFace, LiteLLM) | Clean imports, multiple providers, structured output |
| **Agent Memory** | Persistent memory (Save/Load), Hybrid Retrieval (Vector+Graph), FastEmbed support | Context-aware agents with semantic understanding |
| **Pipeline Orchestration** | Parallel execution, custom steps, orchestrator-worker pattern | Scalable, flexible data processing |
| **Quality Assurance** | Conflict detection, deduplication, quality scoring, provenance | Trusted knowledge graphs ready for production |
@@ -210,6 +172,8 @@ Semantica is designed for **developers, data engineers, and organizations** buil
## 📦 Installation
> **✅ Available on PyPI!** Semantica is now published on PyPI. Install it with a single command: `pip install semantica`
**Prerequisites:** Python 3.8+ (3.9+ recommended) • pip (latest version)
### Install from PyPI (Recommended)
@@ -221,11 +185,19 @@ pip install semantica
# Or install with optional dependencies
pip install semantica[all]
# GitHub Workaround (if PyPI version has issues)
pip install git+https://github.com/Hawksight-AI/semantica.git@main
# Verify installation
python -c "import semantica; print(semantica.__version__)"
python -c "from semantica.parse import DoclingParser; DoclingParser(); print('✓ Semantica ready')"
```
**Current Version:** [![PyPI version](https://badge.fury.io/py/semantica.svg)](https://pypi.org/project/semantica/0.0.1/) • [View on PyPI](https://pypi.org/project/semantica/0.0.1/)
**Current Version:** [![PyPI version](https://badge.fury.io/py/semantica.svg)](https://pypi.org/project/semantica/) • [View on PyPI](https://pypi.org/project/semantica/)
!!! info "Windows PyTorch Note"
If you encounter PyTorch DLL errors on Windows, ensure you have the [Microsoft Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe) installed. This is a common environment-specific issue with PyTorch on Windows and not a bug in Semantica.
### Install from Source (Development)
@@ -246,7 +218,7 @@ pip install -e ".[dev]"
> **New to Semantica?** Check out the [**Cookbook**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook) for hands-on examples!
- [**Cookbook**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook) - 50+ interactive notebooks
- [**Cookbook**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook) - Interactive notebooks
- [Introduction](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction) - Getting started tutorials
- [Advanced](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced) - Advanced techniques
- [Use Cases](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/use_cases) - Real-world applications
@@ -255,15 +227,17 @@ pip install -e ".[dev]"
| **Data Ingestion** | **Semantic Extract** | **Knowledge Graphs** | **Ontology** |
|:--------------------:|:----------------------:|:----------------------:|:--------------:|
| [50+ Formats](#universal-data-ingestion) | [Entity & Relations](#semantic-intelligence-engine) | [Graph Analytics](#knowledge-graph-construction) | [Auto Generation](#ontology-generation--management) |
| **Context** | **GraphRAG** | **Pipeline** | **QA** |
| [Agent Memory](#context-engineering-for-ai-agents) | [Hybrid RAG](#knowledge-graph-powered-rag-graphrag) | [Parallel Workers](#pipeline-orchestration--parallel-processing) | [Conflict Resolution](#production-ready-quality-assurance) |
| [Multiple Formats](#universal-data-ingestion) | [Entity & Relations](#semantic-intelligence-engine) | [Graph Analytics](#knowledge-graph-construction) | [Auto Generation](#ontology-generation--management) |
| **Context** | **GraphRAG** | **LLM Providers** | **Pipeline** |
| [Agent Memory, Context Graph, Context Retriever](#context-engineering--memory-systems) | [Hybrid RAG](#knowledge-graph-powered-rag-graphrag) | [100+ LLMs](#llm-providers-module) | [Parallel Workers](#pipeline-orchestration--parallel-processing) |
| **QA** | **Reasoning** | | |
| [Conflict Resolution](#production-ready-quality-assurance) | [Rule-based Inference](#reasoning--inference-engine) | | |
---
### Universal Data Ingestion
> **50+ file formats** • PDF, DOCX, HTML, JSON, CSV, databases, feeds, archives
> **Multiple file formats** • PDF, DOCX, HTML, JSON, CSV, databases, feeds, archives
```python
from semantica.ingest import FileIngestor, WebIngestor, DBIngestor
@@ -280,21 +254,60 @@ sources.extend(db_ingestor.ingest(query="SELECT * FROM articles"))
print(f" Ingested {len(sources)} sources")
```
[**Cookbook: Data Ingestion**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/02_Data_Ingestion.ipynb) • [**Document Parsing**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/03_Document_Parsing.ipynb) • [**Data Normalization**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/04_Data_Normalization.ipynb) • [**Chunking & Splitting**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/11_Chunking_and_Splitting.ipynb)
[**Cookbook: Data Ingestion**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/02_Data_Ingestion.ipynb)
### Document Parsing & Processing
> **Multi-format parsing** • **Text normalization** • **Intelligent chunking**
```python
from semantica.parse import DocumentParser, DoclingParser
from semantica.normalize import TextNormalizer
from semantica.split import TextSplitter
# Standard parsing
parser = DocumentParser()
parsed = parser.parse("document.pdf", format="auto")
# Enhanced parsing with Docling (recommended for complex layouts/tables)
# Requires: pip install docling
docling_parser = DoclingParser(enable_ocr=True)
result = docling_parser.parse("complex_table.pdf")
print(f"Text (Markdown): {result['full_text'][:100]}...")
print(f"Extracted {len(result['tables'])} tables")
for i, table in enumerate(result['tables']):
print(f"Table {i+1} headers: {table.get('headers', [])}")
# Normalize text
normalizer = TextNormalizer()
normalized = normalizer.normalize(parsed, clean_html=True, normalize_entities=True)
# Split into chunks
splitter = TextSplitter(method="token", chunk_size=1000, chunk_overlap=200)
chunks = splitter.split(normalized)
```
[**Cookbook: Document Parsing**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/03_Document_Parsing.ipynb) • [**Data Normalization**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/04_Data_Normalization.ipynb) • [**Chunking & Splitting**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/11_Chunking_and_Splitting.ipynb)
### Semantic Intelligence Engine
> **Entity & Relation Extraction** • NER, Relationships, Events, Triples with LLM Enhancement
> **Entity & Relation Extraction** • NER, Relationships, Events, Triplets with LLM Enhancement
```python
from semantica import Semantica
from semantica.semantic_extract import NERExtractor, RelationExtractor
text = "Apple Inc., founded by Steve Jobs in 1976, acquired Beats Electronics for $3 billion."
core = Semantica(ner_model="transformer", relation_strategy="hybrid")
results = core.extract_semantics(text)
# Extract entities
ner_extractor = NERExtractor(method="ml", model="en_core_web_sm")
entities = ner_extractor.extract(text)
print(f"Entities: {len(results.entities)}, Relationships: {len(results.relationships)}")
# Extract relationships
relation_extractor = RelationExtractor(method="dependency", model="en_core_web_sm")
relationships = relation_extractor.extract(text, entities=entities)
print(f"Entities: {len(entities)}, Relationships: {len(relationships)}")
```
[**Cookbook: Entity Extraction**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/05_Entity_Extraction.ipynb) • [**Relation Extraction**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/06_Relation_Extraction.ipynb) • [**Advanced Extraction**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/01_Advanced_Extraction.ipynb)
@@ -304,77 +317,256 @@ print(f"Entities: {len(results.entities)}, Relationships: {len(results.relations
> **Production-Ready KGs** • Entity Resolution • Temporal Support • Graph Analytics
```python
from semantica import Semantica
from semantica.kg import GraphAnalyzer
from semantica.semantic_extract import NERExtractor, RelationExtractor
from semantica.kg import GraphBuilder
documents = ["doc1.txt", "doc2.txt", "doc3.txt"]
core = Semantica(graph_db="neo4j", merge_entities=True)
kg = core.build_knowledge_graph(documents, generate_embeddings=True)
# Extract entities and relationships
ner_extractor = NERExtractor(method="ml", model="en_core_web_sm")
relation_extractor = RelationExtractor(method="dependency", model="en_core_web_sm")
analyzer = GraphAnalyzer()
pagerank = analyzer.compute_centrality(kg, method="pagerank")
communities = analyzer.detect_communities(kg, method="louvain")
entities = ner_extractor.extract(text)
relationships = relation_extractor.extract(text, entities=entities)
result = kg.query("Who founded the company?", return_format="structured")
print(f"Nodes: {kg.node_count}, Answer: {result.answer}")
# Build knowledge graph
builder = GraphBuilder()
kg = builder.build({"entities": entities, "relationships": relationships})
print(f"Nodes: {len(kg.get('entities', []))}, Edges: {len(kg.get('relationships', []))}")
```
[**Cookbook: Building Knowledge Graphs**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/07_Building_Knowledge_Graphs.ipynb) • [**Graph Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/09_Graph_Store.ipynb) • [**Triple Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/20_Triple_Store.ipynb) • [**Visualization**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/16_Visualization.ipynb)
[**Cookbook: Building Knowledge Graphs**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/07_Building_Knowledge_Graphs.ipynb) • [**Graph Analytics**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/10_Graph_Analytics.ipynb)
[**Graph Analytics**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/10_Graph_Analytics.ipynb) • [**Advanced Graph Analytics**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/02_Advanced_Graph_Analytics.ipynb)
### Embeddings & Vector Store
> **FastEmbed by default** • **Multiple backends** • **Semantic search**
```python
from semantica.embeddings import EmbeddingGenerator
from semantica.vector_store import VectorStore
# Generate embeddings
embedding_gen = EmbeddingGenerator(model_name="sentence-transformers/all-MiniLM-L6-v2", dimension=384)
embeddings = embedding_gen.generate_embeddings(chunks, data_type="text")
# Store in vector database
vector_store = VectorStore(backend="faiss", dimension=384)
vector_store.store_vectors(vectors=embeddings, metadata=[{"text": chunk} for chunk in chunks])
# Search
results = vector_store.search(query="supply chain", top_k=5)
```
[**Cookbook: Embedding Generation**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/12_Embedding_Generation.ipynb) • [**Vector Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/13_Vector_Store.ipynb)
### Graph Store & Triplet Store
> **Neo4j, FalkorDB support** • **SPARQL queries** • **RDF triplets**
```python
from semantica.graph_store import GraphStore
from semantica.triplet_store import TripletStore
# Graph Store (Neo4j, FalkorDB)
graph_store = GraphStore(backend="neo4j", uri="bolt://localhost:7687", user="neo4j", password="password")
graph_store.add_nodes([{"id": "n1", "labels": ["Person"], "properties": {"name": "Alice"}}])
# Triplet Store (Blazegraph, Jena, RDF4J)
triplet_store = TripletStore(backend="blazegraph", endpoint="http://localhost:9999/blazegraph")
triplet_store.add_triplet({"subject": "Alice", "predicate": "knows", "object": "Bob"})
results = triplet_store.execute_query("SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 10")
```
[**Cookbook: Graph Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/09_Graph_Store.ipynb) • [**Triplet Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/20_Triplet_Store.ipynb)
### Ontology Generation & Management
> **6-Stage LLM Pipeline** • Automatic OWL Generation • HermiT/Pellet Validation
```python
from semantica.ontology import OntologyGenerator, OntologyValidator
from semantica.ontology import OntologyGenerator
generator = OntologyGenerator(llm_provider="openai", model="gpt-4")
ontology = generator.generate_from_documents(sources=["domain_docs/"])
validator = OntologyValidator(reasoner="hermit")
validation = validator.validate(ontology)
print(f"Classes: {len(ontology.classes)}, Valid: {validation.is_consistent}")
print(f"Classes: {len(ontology.classes)}")
```
[**Cookbook: Ontology**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/14_Ontology.ipynb)
### Context Engineering for AI Agents
### Context Engineering & Memory Systems
> **Persistent Memory** • RAG + Knowledge Graphs • MCP-Compatible Tools
> **Persistent Memory** • **Context Graph** • **Context Retriever** • **Hybrid Retrieval (Vector + Graph)** • **Production Graph Store (Neo4j)** • **Entity Linking** • **Multi-Hop Reasoning**
```python
from semantica.context import AgentMemory, ContextRetriever
from semantica.context import AgentContext, ContextGraph, ContextRetriever
from semantica.vector_store import VectorStore
from semantica.graph_store import GraphStore
from semantica.llms import Groq
memory = AgentMemory(vector_store=VectorStore(backend="faiss"), retention_policy="unlimited")
memory.store("User prefers technical docs", metadata={"user_id": "user_123"})
# Initialize Context with Hybrid Retrieval (Graph + Vector)
context = AgentContext(
vector_store=VectorStore(backend="faiss"),
knowledge_graph=GraphStore(backend="neo4j"), # Optional: Use persistent graph
hybrid_alpha=0.75 # 75% weight to Knowledge Graph, 25% to Vector
)
retriever = ContextRetriever(memory_store=memory)
context = retriever.retrieve("What are user preferences?", max_results=5)
# Build Context Graph from entities and relationships
graph_stats = context.build_graph(
entities=kg.get('entities', []),
relationships=kg.get('relationships', []),
link_entities=True
)
# Store memory with automatic entity linking
context.store(
"User is building a RAG system with Semantica",
metadata={"priority": "high", "topic": "rag"}
)
# Use Context Retriever for hybrid retrieval
retriever = context.retriever # Access underlying ContextRetriever
results = retriever.retrieve(
query="What is the user building?",
max_results=10,
use_graph_expansion=True
)
# Retrieve with context expansion
results = context.retrieve("What is the user building?", use_graph_expansion=True)
# Query with reasoning and LLM-generated responses
llm_provider = Groq(model="llama-3.1-8b-instant", api_key=os.getenv("GROQ_API_KEY"))
reasoned_result = context.query_with_reasoning(
query="What is the user building?",
llm_provider=llm_provider,
max_hops=2
)
```
[**Cookbook: Vector Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/13_Vector_Store.ipynb) • [**Embedding Generation**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/12_Embedding_Generation.ipynb) • [**Context Module**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/19_Context_Module.ipynb) • [**Advanced Vector Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/Advanced_Vector_Store_and_Search.ipynb)
**Core Components:**
- **ContextGraph**: Builds and manages context graphs from entities and relationships for enhanced retrieval
- **ContextRetriever**: Performs hybrid retrieval combining vector search, graph traversal, and memory for optimal context relevance
- **AgentContext**: High-level interface integrating Context Graph and Context Retriever for GraphRAG applications
**Core Notebooks:**
- [**Context Module Introduction**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/19_Context_Module.ipynb) - Basic memory and storage.
- [**Advanced Context Engineering**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/11_Advanced_Context_Engineering.ipynb) - Hybrid retrieval, graph builders, and custom memory policies.
- [**Fraud Detection**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/use_cases/finance/02_Fraud_Detection.ipynb) - Demonstrates Context Graph and Context Retriever for fraud detection with GraphRAG.
**Related Components:**
[**Vector Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/13_Vector_Store.ipynb) • [**Embedding Generation**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/12_Embedding_Generation.ipynb) • [**Advanced Vector Store**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/Advanced_Vector_Store_and_Search.ipynb)
### Knowledge Graph-Powered RAG (GraphRAG)
> **30% Accuracy Improvement** • Vector + Graph Hybrid Search • 91% Accuracy
> **30% Accuracy Improvement** • Vector + Graph Hybrid Search • 91% Accuracy • **Multi-Hop Reasoning** • **LLM-Generated Responses**
```python
from semantica.qa_rag import GraphRAGEngine
from semantica.context import AgentContext
from semantica.llms import Groq, OpenAI, LiteLLM
from semantica.vector_store import VectorStore
import os
graphrag = GraphRAGEngine(
# Initialize GraphRAG with hybrid retrieval
context = AgentContext(
vector_store=VectorStore(backend="faiss"),
knowledge_graph=kg
)
result = graphrag.query("Who founded the company?", top_k=5, expand_graph=True)
print(f"Answer: {result.answer} (Confidence: {result.confidence:.2f})")
# Configure LLM provider (supports Groq, OpenAI, HuggingFace, LiteLLM)
llm_provider = Groq(
model="llama-3.1-8b-instant",
api_key=os.getenv("GROQ_API_KEY")
)
# Query with multi-hop reasoning and LLM-generated responses
result = context.query_with_reasoning(
query="What IPs are associated with security alerts?",
llm_provider=llm_provider,
max_results=10,
max_hops=2
)
print(f"Response: {result['response']}")
print(f"Reasoning Path: {result['reasoning_path']}")
print(f"Confidence: {result['confidence']:.3f}")
```
[**Cookbook: GraphRAG**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/use_cases/advanced_rag/01_GraphRAG_Complete.ipynb)
**Key Features:**
- **Multi-Hop Reasoning**: Traverses knowledge graph up to N hops to find related entities
- **LLM-Generated Responses**: Natural language answers grounded in graph context
- **Reasoning Trace**: Shows entity relationship paths used in reasoning
- **Multiple LLM Providers**: Supports Groq, OpenAI, HuggingFace, and LiteLLM (100+ LLMs)
[**Cookbook: GraphRAG**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/use_cases/advanced_rag/01_GraphRAG_Complete.ipynb) • [**Real-Time Anomaly Detection**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/use_cases/cybersecurity/01_Real_Time_Anomaly_Detection.ipynb)
### LLM Providers Module
> **Unified LLM Interface** • **100+ LLM Support via LiteLLM** • **Clean Imports** • **Multiple Providers**
```python
from semantica.llms import Groq, OpenAI, HuggingFaceLLM, LiteLLM
import os
# Groq - Fast inference
groq = Groq(
model="llama-3.1-8b-instant",
api_key=os.getenv("GROQ_API_KEY")
)
response = groq.generate("What is AI?")
# OpenAI
openai = OpenAI(
model="gpt-4",
api_key=os.getenv("OPENAI_API_KEY")
)
response = openai.generate("What is AI?")
# HuggingFace - Local models
hf = HuggingFaceLLM(model_name="gpt2")
response = hf.generate("What is AI?")
# LiteLLM - Unified interface to 100+ LLMs
litellm = LiteLLM(
model="openai/gpt-4o", # or "anthropic/claude-sonnet-4-20250514", "groq/llama-3.1-8b-instant", etc.
api_key=os.getenv("OPENAI_API_KEY")
)
response = litellm.generate("What is AI?")
# Structured output
structured = groq.generate_structured("Extract entities from: Apple Inc. was founded by Steve Jobs.")
```
**Supported Providers:**
- **Groq**: Fast inference with Llama models
- **OpenAI**: GPT-3.5, GPT-4, and other OpenAI models
- **HuggingFace**: Local LLM inference with Transformers
- **LiteLLM**: Unified interface to 100+ LLM providers (OpenAI, Anthropic, Azure, Bedrock, Vertex AI, and more)
### Reasoning & Inference Engine
> **Rule-based Inference** • **Forward/Backward Chaining** • **Rete Algorithm** • **Explanation Generation**
```python
from semantica.reasoning import Reasoner
# Initialize Reasoner
reasoner = Reasoner()
# Define rules and facts
rules = ["IF Parent(?a, ?b) AND Parent(?b, ?c) THEN Grandparent(?a, ?c)"]
facts = ["Parent(Alice, Bob)", "Parent(Bob, Charlie)"]
# Infer new facts (Forward Chaining)
inferred = reasoner.infer_facts(facts, rules)
print(f"Inferred: {inferred}") # ['Grandparent(Alice, Charlie)']
# Explain reasoning
from semantica.reasoning import ExplanationGenerator
explainer = ExplanationGenerator()
# ... generate explanation for inferred facts
```
[**Cookbook: Reasoning**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/08_Reasoning_and_Inference.ipynb) • [**Rete Engine**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/09_Rete_Engine.ipynb)
### Pipeline Orchestration & Parallel Processing
@@ -392,7 +584,7 @@ pipeline = PipelineBuilder() \
result = ExecutionEngine().execute_pipeline(pipeline, parallel=True)
```
[**Cookbook: Pipeline Orchestration**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/07_Pipeline_Orchestration.ipynb)
### Production-Ready Quality Assurance
@@ -402,43 +594,87 @@ result = ExecutionEngine().execute_pipeline(pipeline, parallel=True)
from semantica.deduplication import DuplicateDetector
from semantica.conflicts import ConflictDetector
conflicts = ConflictDetector().detect_conflicts(kg)
duplicates = DuplicateDetector().find_duplicates(entities=kg.entities, similarity_threshold=0.85)
entities = kg.get("entities", [])
conflicts = ConflictDetector().detect_conflicts(entities)
duplicates = DuplicateDetector(similarity_threshold=0.85).detect_duplicates(entities)
print(f"Conflicts: {len(conflicts)} | Duplicates: {len(duplicates)}")
```
[**Cookbook: Conflict Detection**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/17_Conflict_Detection.ipynb) • [**Deduplication**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/18_Deduplication.ipynb) • [**Graph Quality**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/11_Graph_Quality.ipynb) • [**Conflict Resolution**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/04_Conflict_Resolution_Strategies.ipynb)
[**Cookbook: Conflict Detection & Resolution**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/17_Conflict_Detection_and_Resolution.ipynb) • [**Deduplication**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/18_Deduplication.ipynb)
### Export & Integration
### Visualization & Export
> **Multi-Format Export** • JSON, CSV, RDF, GraphML
> **Interactive graphs** • **Multi-format export** • **Graph analytics**
```python
from semantica.visualization import KGVisualizer
from semantica.export import GraphExporter
exporter = GraphExporter(kg)
exporter.export("graph.json", format="json")
exporter.export("graph.ttl", format="turtle")
# Visualize knowledge graph
viz = KGVisualizer(layout="force")
fig = viz.visualize_network(kg, output="interactive")
fig.show()
# Export to multiple formats
exporter = GraphExporter()
exporter.export(kg, format="json", output_path="graph.json")
exporter.export(kg, format="graphml", output_path="graph.graphml")
```
[**Cookbook: Export**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/15_Export.ipynb) • [**Multi-Format Export**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/05_Multi_Format_Export.ipynb) • [**Multi-Source Integration**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/06_Multi_Source_Data_Integration.ipynb)
[**Cookbook: Visualization**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/16_Visualization.ipynb) • [**Export**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/15_Export.ipynb)
### Seed Data Integration
> **Foundation data** • **Entity resolution** • **Domain knowledge**
```python
from semantica.seed import SeedDataManager
seed_manager = SeedDataManager()
seed_manager.seed_data.entities = [
{"id": "s1", "text": "Supplier A", "type": "Supplier", "source": "foundation", "verified": True}
]
# Use seed data for entity resolution
resolved = seed_manager.resolve_entities(extracted_entities)
```
[**Cookbook: Seed Data**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/advanced/07_Seed_Data_Integration.ipynb)
## 🚀 Quick Start
> **For comprehensive examples, see the [**Cookbook**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook) with 50+ interactive notebooks!**
> **For comprehensive examples, see the [**Cookbook**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook) with interactive notebooks!**
```python
from semantica import Semantica
from semantica.semantic_extract import NERExtractor, RelationExtractor
from semantica.kg import GraphBuilder
from semantica.context import AgentContext, ContextGraph
from semantica.vector_store import VectorStore
# Initialize and build knowledge graph
core = Semantica(ner_model="transformer", relation_strategy="hybrid")
documents = ["doc1.txt", "doc2.txt", "doc3.txt"]
kg = core.build_knowledge_graph(documents, merge_entities=True)
# Extract entities and relationships
ner_extractor = NERExtractor(method="ml", model="en_core_web_sm")
relation_extractor = RelationExtractor(method="dependency", model="en_core_web_sm")
# Query the graph
result = kg.query("Who founded the company?", return_format="structured")
print(f"Answer: {result.answer} | Nodes: {kg.node_count}, Edges: {kg.edge_count}")
text = "Apple Inc. was founded by Steve Jobs in 1976."
entities = ner_extractor.extract(text)
relationships = relation_extractor.extract(text, entities=entities)
# Build knowledge graph
builder = GraphBuilder()
kg = builder.build({"entities": entities, "relationships": relationships})
# Query using GraphRAG
vector_store = VectorStore(backend="faiss", dimension=384)
context_graph = ContextGraph()
context_graph.build_from_entities_and_relationships(
entities=kg.get('entities', []),
relationships=kg.get('relationships', [])
)
context = AgentContext(vector_store=vector_store, knowledge_graph=context_graph)
results = context.retrieve("Who founded Apple?", max_results=5)
print(f"Found {len(results)} results")
```
[**Cookbook: Your First Knowledge Graph**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/introduction/08_Your_First_Knowledge_Graph.ipynb)
@@ -449,7 +685,7 @@ print(f"Answer: {result.answer} | Nodes: {kg.node_count}, Edges: {kg.edge_count}
**AI Agents & Autonomous Systems** — Build agents with persistent memory and semantic understanding.
**Multi-Format Document Processing** — Process 50+ formats through a unified pipeline.
**Multi-Format Document Processing** — Process multiple formats through a unified pipeline.
**Data Pipeline Processing** — Build scalable pipelines with parallel execution.
@@ -457,19 +693,74 @@ print(f"Answer: {result.answer} | Nodes: {kg.node_count}, Edges: {kg.edge_count}
**Finance & Trading** — Fraud detection, market intelligence, risk assessment.
**Healthcare & Biomedical**Clinical reports, drug discovery, medical literature analysis.
**Biomedical**Drug discovery, medical literature analysis.
[**Explore Use Case Examples**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/use_cases) — See real-world implementations in finance, healthcare, cybersecurity, trading, and more.
## 🍳 Semantica Cookbook
> **Interactive Jupyter Notebooks** designed to take you from beginner to expert.
[**View Full Cookbook**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook)
### Featured Recipes
| **Recipe** | **Description** | **Link** |
|:-----------|:----------------|:---------|
| **GraphRAG Complete** | Build a production-ready **Graph Retrieval Augmented Generation** system. Features **Graph Validation**, **Hybrid Retrieval**, and **Logical Inference**. | [Open Notebook](cookbook/use_cases/advanced_rag/01_GraphRAG_Complete.ipynb) |
| **RAG vs. GraphRAG** | Side-by-side comparison. Demonstrates the **Reasoning Gap** and how GraphRAG solves it with **Inference Engines**. | [Open Notebook](cookbook/use_cases/advanced_rag/02_RAG_vs_GraphRAG_Comparison.ipynb) |
| **First Knowledge Graph** | Go from raw text to a queryable knowledge graph in 20 minutes. | [Open Notebook](cookbook/introduction/08_Your_First_Knowledge_Graph.ipynb) |
| **Real-Time Anomalies** | Detect anomalies in streaming data using temporal knowledge graphs and pattern detection. | [Open Notebook](cookbook/use_cases/cybersecurity/01_Real_Time_Anomaly_Detection.ipynb) |
### Core Tutorials
- [**Welcome to Semantica**](cookbook/introduction/01_Welcome_to_Semantica.ipynb) - Framework Overview
- [**Data Ingestion**](cookbook/introduction/02_Data_Ingestion.ipynb) - Universal Ingestion
- [**Entity Extraction**](cookbook/introduction/05_Entity_Extraction.ipynb) - NER & Relationships
- [**Building Knowledge Graphs**](cookbook/introduction/07_Building_Knowledge_Graphs.ipynb) - Graph Construction
### Industry Use Cases (14 Cookbooks)
**Domain-Specific Cookbooks** showcasing real-world applications with real data sources, advanced chunking strategies, temporal KGs, GraphRAG, and comprehensive Semantica module integration:
#### Biomedical
- [**Drug Discovery Pipeline**](cookbook/use_cases/biomedical/01_Drug_Discovery_Pipeline.ipynb) - PubMed RSS, entity-aware chunking, GraphRAG, vector similarity search
- [**Genomic Variant Analysis**](cookbook/use_cases/biomedical/02_Genomic_Variant_Analysis.ipynb) - bioRxiv RSS, temporal KGs, deduplication, pathway analysis
#### Finance
- [**Financial Data Integration MCP**](cookbook/use_cases/finance/01_Financial_Data_Integration_MCP.ipynb) - Alpha Vantage API, MCP servers, seed data, real-time ingestion
- [**Fraud Detection**](cookbook/use_cases/finance/02_Fraud_Detection.ipynb) - Transaction streams, temporal KGs, pattern detection, conflict resolution, **Context Graph**, **Context Retriever**, GraphRAG with Groq LLM
#### Blockchain
- [**DeFi Protocol Intelligence**](cookbook/use_cases/blockchain/01_DeFi_Protocol_Intelligence.ipynb) - CoinDesk RSS, ontology-aware chunking, conflict detection, ontology generation
- [**Transaction Network Analysis**](cookbook/use_cases/blockchain/02_Transaction_Network_Analysis.ipynb) - Blockchain APIs, deduplication, network analytics
#### Cybersecurity
- [**Real-Time Anomaly Detection**](cookbook/use_cases/cybersecurity/01_Real_Time_Anomaly_Detection.ipynb) - CVE RSS, Kafka streams, temporal KGs, sentence chunking
- [**Threat Intelligence Hybrid RAG**](cookbook/use_cases/cybersecurity/02_Threat_Intelligence_Hybrid_RAG.ipynb) - Security RSS, entity-aware chunking, enhanced GraphRAG, deduplication
#### Intelligence & Law Enforcement
- [**Criminal Network Analysis**](cookbook/use_cases/intelligence/01_Criminal_Network_Analysis.ipynb) - OSINT RSS, deduplication, network centrality, graph analytics
- [**Intelligence Analysis Orchestrator Worker**](cookbook/use_cases/intelligence/02_Intelligence_Analysis_Orchestrator_Worker.ipynb) - Pipeline orchestrator, multi-source integration, conflict detection
#### Renewable Energy
- [**Energy Market Analysis**](cookbook/use_cases/renewable_energy/01_Energy_Market_Analysis.ipynb) - Energy RSS, EIA API, temporal KGs, TemporalPatternDetector, trend prediction
#### Supply Chain
- [**Supply Chain Data Integration**](cookbook/use_cases/supply_chain/01_Supply_Chain_Data_Integration.ipynb) - Logistics RSS, deduplication, relationship mapping
[**Explore Use Case Examples**](https://github.com/Hawksight-AI/semantica/tree/main/cookbook/use_cases) — See real-world implementations in finance, biomedical, cybersecurity, and more. **14 comprehensive domain-specific cookbooks** with real data sources, advanced chunking strategies, temporal KGs, GraphRAG, and full Semantica module integration.
## 🔬 Advanced Features
**Incremental Updates** — Real-time stream processing with Kafka, RabbitMQ, Kinesis for live updates.
**Multi-Language Support** — Process 50+ languages with automatic detection.
**Multi-Language Support** — Process multiple languages with automatic detection.
**Custom Ontology Import** — Import and extend Schema.org and custom ontologies.
**Advanced Reasoning**Deductive, inductive, abductive reasoning with HermiT/Pellet.
**Advanced Reasoning**Forward/backward chaining, Rete-based pattern matching, and automated explanation generation.
**Graph Analytics** — Centrality, community detection, path finding, temporal analysis.
@@ -485,10 +776,11 @@ print(f"Answer: {result.answer} | Nodes: {kg.node_count}, Edges: {kg.edge_count}
- [x] Core framework (v1.0)
- [x] GraphRAG engine
- [x] 6-stage ontology pipeline
- [x] Advanced reasoning v2 (Rete, Forward/Backward Chaining)
- [ ] Quality assurance features and Quality Assurance module
- [ ] Enhanced multi-language support
- [ ] Evals
- [ ] Real-time streaming improvements
- [ ] Advanced reasoning v2
### Q2 2026
- [ ] Multi-modal processing
@@ -501,7 +793,7 @@ print(f"Answer: {result.answer} | Nodes: {kg.node_count}, Edges: {kg.edge_count}
| **Channel** | **Purpose** |
|:-----------:|:-----------|
| [**Discord**](https://discord.gg/semantica) | Real-time help, showcases |
| [**Discord**](https://discord.gg/pMHguUzG) | Real-time help, showcases |
| [**GitHub Discussions**](https://github.com/Hawksight-AI/semantica/discussions) | Q&A, feature requests |
### Learning Resources
@@ -509,14 +801,20 @@ print(f"Answer: {result.answer} | Nodes: {kg.node_count}, Edges: {kg.edge_count}
### Enterprise Support
| **Tier** | **Features** | **SLA** | **Price** |
|:--------:|:-----------|:-------:|:--------:|
| **Community** | Public support | Best effort | Free |
| **Professional** | Email support | 48h | Contact |
| **Enterprise** | 24/7 support | 4h | Contact |
| **Premium** | Phone, custom dev | 1h | Contact |
Enterprise support, professional services, and commercial licensing will be available in the future. For now, we offer community support through Discord and GitHub Discussions.
**Contact:** [GitHub Issues](https://github.com/Hawksight-AI/semantica/issues) with "[Enterprise]" prefix
**Current Support:**
- **Community Support** - Free support via [Discord](https://discord.gg/pMHguUzG) and [GitHub Discussions](https://github.com/Hawksight-AI/semantica/discussions)
- **Bug Reports** - [GitHub Issues](https://github.com/Hawksight-AI/semantica/issues)
**Future Enterprise Offerings:**
- Professional support with SLA
- Enterprise licensing
- Custom development services
- Priority feature requests
- Dedicated support channels
Stay tuned for updates!
## 🤝 Contributing
@@ -550,13 +848,12 @@ git push origin feature/your-feature
3. **Bug Reports** - [Create issue](https://github.com/Hawksight-AI/semantica/issues/new)
4. **Feature Requests** - [Request feature](https://github.com/Hawksight-AI/semantica/issues/new)
### Recognition
Contributors receive:
- Recognition in [CONTRIBUTORS.md](https://github.com/Hawksight-AI/semantica/blob/main/CONTRIBUTORS.md)
- GitHub badges
- Semantica swag
- Featured showcases
### Contributors
<a href="https://github.com/Hawksight-AI/semantica/graphs/contributors">
<img src="https://contrib.rocks/image?repo=Hawksight-AI/semantica" alt="Contributors" />
</a>
## 📜 License
@@ -566,6 +863,6 @@ Semantica is licensed under the **MIT License** - see the [LICENSE](https://gith
**Built by the Semantica Community**
[GitHub](https://github.com/Hawksight-AI/semantica) • [Discord](https://discord.gg/semantica)
[GitHub](https://github.com/Hawksight-AI/semantica) • [Discord](https://discord.gg/pMHguUzG)
</div>
+56
View File
@@ -0,0 +1,56 @@
# Release Process for Semantica
This document outlines the steps to release a new version of the Semantica framework.
## 1. Versioning Policy
Semantica follows [Semantic Versioning (SemVer)](https://semver.org/).
- **MAJOR** version for incompatible API changes.
- **MINOR** version for functionality added in a backwards compatible manner.
- **PATCH** version for backwards compatible bug fixes.
## 2. Pre-release Checklist
Before releasing, ensure:
- [ ] All tests pass: `pytest`
- [ ] Documentation is up to date in `docs/` and `MkDocs` config.
- [ ] `CHANGELOG.md` is updated with the latest changes.
- [ ] Version is updated in:
- `semantica/__init__.py`
- `pyproject.toml`
- `docs/citation.md` (BibTeX entry)
## 3. Release Steps
### Automated Release (Recommended)
The project uses GitHub Actions for automated releases to PyPI.
1. **Tag the commit**: Create a new git tag for the version (e.g., `v0.1.1`).
```bash
git tag -a v0.1.1 -m "Release v0.1.1"
git push origin v0.1.1
```
2. **GitHub Action**: The `Release` workflow will automatically trigger, build the package, create a GitHub Release, and publish to PyPI using Trusted Publishing.
### Manual Release
If you need to release manually:
1. **Build the package**:
```bash
python -m build
```
2. **Verify the build**:
```bash
twine check dist/*
```
3. **Upload to PyPI**:
```bash
twine upload dist/*
```
## 4. Post-release
- Verify the new version is available on [PyPI](https://pypi.org/project/semantica/).
- Check the [GitHub Releases](https://github.com/your-org/semantica/releases) page for the new release notes.
+3 -2
View File
@@ -6,8 +6,9 @@ We actively support the following versions of Semantica with security updates:
| Version | Supported |
| ------- | ------------------ |
| 0.0.1 | :white_check_mark: |
| < 0.0.1 | :x: |
| 0.1.1 | :white_check_mark: |
| 0.1.0 | :white_check_mark: |
| < 0.1.0 | :x: |
## Reporting a Vulnerability
+105
View File
@@ -0,0 +1,105 @@
# Deduplication & Conflict Resolution Strategies Summary
## Quick Reference by Use Case
| Use Case | Deduplication Method | Merge Strategy | Conflict Detection | Conflict Resolution |
|----------|---------------------|----------------|-------------------|---------------------|
| **Finance** |
| `01_Financial_Data_Integration_MCP` | `DuplicateDetector` (incremental) | `keep_highest_confidence` | `temporal` | `most_recent` |
| `02_Fraud_Detection` | `ClusterBuilder` (graph_based) | `merge_all` | `logical` | `expert_review` |
| **Biomedical** |
| `01_Drug_Discovery_Pipeline` | `EntityResolver` (semantic) | - | `relationship` | `voting` |
| `02_Genomic_Variant_Analysis` | `DuplicateDetector` (group) | `keep_most_complete` | `value` | `credibility_weighted` |
| **Cybersecurity** |
| `01_Real_Time_Anomaly_Detection` | `DuplicateDetector` (pairwise) | `keep_first` | `entity` | `first_seen` |
| `02_Threat_Intelligence_Hybrid_RAG` | `EntityResolver` (exact) | - | `type` | `highest_confidence` |
| **Blockchain** |
| `01_DeFi_Protocol_Intelligence` | `DuplicateDetector` (group) | `keep_last` | `relationship` | `voting` |
| `02_Transaction_Network_Analysis` | `ClusterBuilder` (hierarchical) | `keep_most_complete` | `temporal` | `most_recent` |
| **Intelligence** |
| `01_Criminal_Network_Analysis` | `EntityResolver` (fuzzy) | - | `value` | `credibility_weighted` |
| `02_Intelligence_Analysis_Orchestrator_Worker` | `DuplicateDetector` (batch) | `merge_all` | `entity` | `voting` |
| **Renewable Energy** |
| `01_Energy_Market_Analysis` | `DuplicateDetector` (pairwise) | `keep_highest_confidence` | `temporal` | `most_recent` |
| **Supply Chain** |
| `01_Supply_Chain_Data_Integration` | `DuplicateDetector` (incremental) | `keep_most_complete` | `value` | `credibility_weighted` |
---
## Strategy Rationale by Domain
### Finance
- **Financial Data Integration**: Incremental for streaming data; most_recent for time-sensitive financial data
- **Fraud Detection**: Graph-based clustering for fraud groups; expert_review for fraud assessment
### Biomedical
- **Drug Discovery**: Semantic matching for drug compounds; voting for research source aggregation
- **Genomic Variants**: Group method for related variants; credibility weighting for research sources
### Cybersecurity
- **Real-Time Anomaly**: Pairwise for real-time streams; keep_first for first detection priority
- **Threat Intelligence**: Exact matching for IOCs; highest_confidence for threat classification
### Blockchain
- **DeFi Protocols**: Group method for related protocols; keep_last for latest protocol info
- **Transaction Networks**: Hierarchical clustering for nested groups; temporal for time-sensitive data
### Intelligence
- **Criminal Networks**: Fuzzy matching for intelligence data; credibility weighting for intelligence sources
- **Intelligence Analysis**: Batch for multi-source integration; merge_all to combine all intelligence sources
### Renewable Energy
- **Energy Markets**: Pairwise for real-time market data; most_recent for time-sensitive energy data
### Supply Chain
- **Supply Chain Integration**: Incremental for continuous updates; credibility weighting for supply chain sources
---
## Method Distribution
### Deduplication Methods (9 total)
- `pairwise`: 2 notebooks (real-time processing)
- `batch`: 3 notebooks (large datasets)
- `incremental`: 2 notebooks (streaming/continuous)
- `group`: 2 notebooks (related entities)
- `graph_based` (ClusterBuilder): 2 notebooks (interconnected entities)
- `hierarchical` (ClusterBuilder): 1 notebook (nested groups)
- `exact` (EntityResolver): 1 notebook (exact matching)
- `semantic` (EntityResolver): 2 notebooks (semantic similarity)
- `fuzzy` (EntityResolver): 1 notebook (fuzzy matching)
### Merge Strategies (5 total)
- `keep_first`: 1 notebook (first detection priority)
- `keep_last`: 1 notebook (latest information)
- `keep_most_complete`: 5 notebooks (preserve all details)
- `keep_highest_confidence`: 2 notebooks (most reliable data)
- `merge_all`: 3 notebooks (combine all information)
### Conflict Detection Methods (6 total)
- `value`: 4 notebooks (property value conflicts)
- `type`: 2 notebooks (type/classification conflicts)
- `entity`: 2 notebooks (entity-wide conflicts)
- `relationship`: 3 notebooks (relationship conflicts)
- `temporal`: 3 notebooks (time-sensitive conflicts)
- `logical`: 2 notebooks (logical inconsistencies)
### Conflict Resolution Strategies (6 total)
- `voting`: 5 notebooks (majority vote)
- `credibility_weighted`: 4 notebooks (source credibility)
- `most_recent`: 3 notebooks (latest data)
- `first_seen`: 1 notebook (first detection)
- `highest_confidence`: 2 notebooks (most confident)
- `expert_review`: 1 notebook (manual review)
---
## Key Patterns
1. **Real-Time Systems**: Use `pairwise` + `keep_first` + `first_seen`
2. **Time-Sensitive Data**: Use `temporal` + `most_recent`
3. **Multi-Source Integration**: Use `batch` + `merge_all` + `voting`
4. **Medical/Research**: Use `credibility_weighted` for authoritative sources
5. **Fraud/Security**: Use `graph_based` + `logical` + `expert_review`
6. **Exact Matching Required**: Use `exact` strategy (IOCs, identifiers)
+1 -1
View File
@@ -27,7 +27,7 @@ Start with our comprehensive documentation:
**Best for**: Real-time chat and quick questions
- [Join Discord](https://discord.gg/semantica)
- [Join Discord](https://discord.gg/pMHguUzG)
#### GitHub Issues
+37 -14
View File
@@ -10,7 +10,7 @@
"\n",
"## Overview\n",
"\n",
"This notebook demonstrates advanced semantic extraction using EventDetector, CoreferenceResolver, TripleExtractor, SemanticAnalyzer, SemanticNetworkExtractor, LLMEnhancer, and ExtractionValidator.\n",
"This notebook demonstrates advanced semantic extraction using EventDetector, CoreferenceResolver, TripletExtractor, SemanticAnalyzer, SemanticNetworkExtractor, LLMEnhancer, and ExtractionValidator.\n",
"\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/semantic_extract/)\n",
@@ -19,7 +19,7 @@
"\n",
"- Use EventDetector to detect events\n",
"- Use CoreferenceResolver to resolve coreferences\n",
"- Use TripleExtractor to extract RDF triples\n",
"- Use TripletExtractor to extract RDF triplets\n",
"- Use SemanticAnalyzer for semantic analysis\n",
"- Use SemanticNetworkExtractor to extract semantic networks\n",
"- Use LLMEnhancer for LLM-based enhancement\n",
@@ -37,7 +37,16 @@
"\n",
"---\n",
"\n",
"## Workflow: Event Detection → Coreference Resolution → Triple Extraction → Semantic Analysis → Network Extraction → LLM Enhancement → Validation\n"
"## Workflow: Event Detection → Coreference Resolution → Triplet Extraction → Semantic Analysis → Network Extraction → LLM Enhancement → Validation\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install -q semantica"
]
},
{
@@ -47,7 +56,7 @@
"outputs": [],
"source": [
"from semantica.semantic_extract import (\n",
" EventDetector, CoreferenceResolver, TripleExtractor,\n",
" EventDetector, CoreferenceResolver, TripletExtractor,\n",
" SemanticAnalyzer, SemanticNetworkExtractor, LLMEnhancer, ExtractionValidator\n",
")\n",
"\n",
@@ -58,7 +67,7 @@
"\n",
"print(f\"Detected {len(events)} events\")\n",
"for event in events[:3]:\n",
" print(f\" Event: {event.get('type', 'Unknown')} - {event.get('text', '')[:50]}\")\n"
" print(f\" Event: {event.event_type} - {event.text[:50]}\")\n"
]
},
{
@@ -87,9 +96,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Triple Extraction\n",
"## Step 3: Triplet Extraction\n",
"\n",
"Extract RDF triples.\n"
"Extract RDF triplets.\n"
]
},
{
@@ -98,13 +107,13 @@
"metadata": {},
"outputs": [],
"source": [
"triple_extractor = TripleExtractor()\n",
"triplet_extractor = TripletExtractor()\n",
"\n",
"triples = triple_extractor.extract_triples(text)\n",
"triplets = triplet_extractor.extract_triplets(text)\n",
"\n",
"print(f\"Extracted {len(triples)} triples\")\n",
"for triple in triples[:3]:\n",
" print(f\" ({triple.get('subject', '')}, {triple.get('predicate', '')}, {triple.get('object', '')})\")\n"
"print(f\"Extracted {len(triplets)} triplets\")\n",
"for triplet in triplets[:3]:\n",
" print(f\" ({triplet.get('subject', '')}, {triplet.get('predicate', '')}, {triplet.get('object', '')})\")\n"
]
},
{
@@ -208,7 +217,7 @@
"\n",
"- **EventDetector**: Event detection and classification\n",
"- **CoreferenceResolver**: Coreference resolution\n",
"- **TripleExtractor**: RDF triple extraction\n",
"- **TripletExtractor**: RDF triplet extraction\n",
"- **SemanticAnalyzer**: Semantic analysis and role labeling\n",
"- **SemanticNetworkExtractor**: Semantic network extraction\n",
"- **LLMEnhancer**: LLM-based extraction enhancement\n",
@@ -217,8 +226,22 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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,
@@ -4,39 +4,30 @@
"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/advanced/02_Advanced_Graph_Analytics.ipynb)\n",
"# Graph Analytics \n",
"\n",
"# Advanced Graph Analytics\n",
"Welcome to the **comprehensive walkthrough** of Semantica's Graph Analytics capabilities. This notebook goes beyond simple graph construction to demonstrate a full-lifecycle production pipeline.\n",
"\n",
"## Overview\n",
"We will simulate a messy, real-world scenario involving a **Startup Ecosystem** (Investors, Startups, Founders) and guide you through every step of the process:\n",
"\n",
"This notebook demonstrates advanced graph analytics using GraphAnalyzer, CentralityCalculator, CommunityDetector, ConnectivityAnalyzer, GraphValidator, Deduplicator, and **GraphStore** for persistent storage.\n",
"1. **Validation**: Catching bad data before it enters the graph.\n",
"2. **Cleaning**: Deduplicating entities and resolving conflicts.\n",
"3. **Structural Analysis**: Understanding the shape and health of your network.\n",
"4. **Deep Analytics**: Centrality, Communities, and Path Finding.\n",
"5. **Temporal Analytics**: Time-traveling through your graph data.\n",
"6. **Provenance**: Tracking where your data came from.\n",
"\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/kg/)\n",
"\n",
"### Learning Objectives\n",
"\n",
"- Use GraphAnalyzer for comprehensive graph analysis\n",
"- Use CentralityCalculator for advanced centrality measures\n",
"- Use CommunityDetector for community detection\n",
"- Use ConnectivityAnalyzer for connectivity analysis\n",
"- Use GraphValidator and Deduplicator for graph quality\n",
"- **Use GraphStore to persist graphs to Neo4j or FalkorDB**\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---\n",
"\n",
"## Workflow: Graph Analysis → Centrality → Communities → Connectivity → Validation → Deduplication → **Persist to Graph Store**\n"
"Let's dive in!"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "695d435c",
"metadata": {},
"outputs": [],
"source": [
"!pip install -q semantica"
]
},
{
@@ -45,221 +36,360 @@
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphBuilder, GraphAnalyzer, CentralityCalculator, CommunityDetector, ConnectivityAnalyzer, GraphValidator\n",
"from semantica.deduplication import DuplicateDetector, EntityMerger, MergeStrategy\n",
"import logging\n",
"import json\n",
"from datetime import datetime\n",
"\n",
"builder = GraphBuilder()\n",
"analyzer = GraphAnalyzer()\n",
"# Set up logging to see what's happening under the hood\n",
"logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\n",
"\n",
"entities = [\n",
" {\"id\": \"e1\", \"type\": \"Organization\", \"name\": \"Apple Inc.\", \"properties\": {}},\n",
" {\"id\": \"e2\", \"type\": \"Person\", \"name\": \"Tim Cook\", \"properties\": {}},\n",
" {\"id\": \"e3\", \"type\": \"Location\", \"name\": \"Cupertino\", \"properties\": {}}\n",
"# Import all the powerful tools from Semantica\n",
"from semantica.kg import (\n",
" GraphBuilder,\n",
" GraphAnalyzer,\n",
" GraphValidator,\n",
" ConnectivityAnalyzer,\n",
" CentralityCalculator,\n",
" CommunityDetector,\n",
" TemporalGraphQuery,\n",
" ProvenanceTracker\n",
")\n",
"from semantica.deduplication import DuplicateDetector\n",
"from semantica.conflicts import ConflictDetector, ConflictResolver"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. The Scenario: A Messy Startup Ecosystem\n",
"\n",
"We have data from multiple sources (scrapers, news, user submissions). It's messy:\n",
"- **Duplicates**: \"TechFlow AI\" and \"TechFlow Inc.\"\n",
"- **Conflicts**: Different revenue numbers for the same company.\n",
"- **Errors**: Relationships pointing to non-existent nodes (dangling edges).\n",
"- **History**: Investment rounds happening at different times."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Our \"Raw\" Messy Data\n",
"raw_entities = [\n",
" {\"id\": \"startup_1\", \"type\": \"Startup\", \"name\": \"TechFlow AI\", \"revenue\": 1000000, \"founded\": \"2021-01-01\"},\n",
" {\"id\": \"startup_2\", \"type\": \"Startup\", \"name\": \"GreenEnergy Co\", \"revenue\": 500000, \"founded\": \"2020-05-15\"},\n",
" {\"id\": \"startup_1_dup\", \"type\": \"Startup\", \"name\": \"TechFlow Inc.\", \"revenue\": 1200000, \"founded\": \"2021-01-01\"}, # Duplicate!\n",
" {\"id\": \"investor_1\", \"type\": \"Investor\", \"name\": \"Venture Capital X\"},\n",
" {\"id\": \"founder_1\", \"type\": \"Person\", \"name\": \"Alice Chen\"},\n",
" {\"id\": \"founder_2\", \"type\": \"Person\", \"name\": \"Bob Smith\"}\n",
"]\n",
"\n",
"relationships = [\n",
" {\"source\": \"e2\", \"target\": \"e1\", \"type\": \"CEO_of\", \"properties\": {}},\n",
" {\"source\": \"e1\", \"target\": \"e3\", \"type\": \"located_in\", \"properties\": {}}\n",
"]\n",
"\n",
"kg = builder.build(entities, relationships)\n",
"\n",
"metrics = analyzer.compute_metrics(kg)\n",
"\n",
"print(f\"Graph metrics:\")\n",
"print(f\" Entities: {metrics.get('entity_count', 0)}\")\n",
"print(f\" Relationships: {metrics.get('relationship_count', 0)}\")\n",
"print(f\" Density: {metrics.get('density', 0):.3f}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Advanced Centrality Measures\n",
"\n",
"Calculate multiple centrality measures.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"centrality_calculator = CentralityCalculator()\n",
"\n",
"degree_centrality_result = centrality_calculator.calculate_degree_centrality(kg)\n",
"degree_centrality = degree_centrality_result.get('centrality', {})\n",
"betweenness_centrality_result = centrality_calculator.calculate_betweenness_centrality(kg)\n",
"betweenness_centrality = betweenness_centrality_result.get('centrality', {})\n",
"\n",
"print(f\"Degree centrality: {len(degree_centrality)} entities\")\n",
"print(f\"Betweenness centrality: {len(betweenness_centrality)} entities\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Community Detection\n",
"\n",
"Detect communities in the graph.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"community_detector = CommunityDetector()\n",
"\n",
"communities = community_detector.detect_communities(kg)\n",
"\n",
"print(f\"Detected {len(communities)} communities\")\n",
"for i, community in enumerate(communities[:3], 1):\n",
" print(f\" Community {i}: {len(community)} entities\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Connectivity Analysis\n",
"\n",
"Analyze graph connectivity.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"connectivity_analyzer = ConnectivityAnalyzer()\n",
"\n",
"connectivity = connectivity_analyzer.analyze_connectivity(kg)\n",
"\n",
"print(f\"Connectivity analysis:\")\n",
"print(f\" Is connected: {connectivity.get('is_connected', False)}\")\n",
"print(f\" Components: {len(connectivity.get('components', []))}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Graph Validation and Deduplication\n",
"\n",
"Validate and deduplicate the graph.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"graph_validator = GraphValidator()\n",
"\n",
"validation_result = graph_validator.validate(kg)\n",
"\n",
"print(f\"Graph validation: {validation_result.get('valid', False)}\")\n",
"print(f\"Issues found: {len(validation_result.get('issues', []))}\")\n",
"\n",
"# For deduplication, use semantica.deduplication module:\n",
"# from semantica.deduplication import DuplicateDetector, EntityMerger, MergeStrategy\n",
"# detector = DuplicateDetector(similarity_threshold=0.8)\n",
"# duplicate_groups = detector.detect_duplicate_groups(kg.get('entities', []))\n",
"# merger = EntityMerger()\n",
"# merge_operations = merger.merge_duplicates(kg.get('entities', []), strategy=MergeStrategy.KEEP_MOST_COMPLETE)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 6: Persist to Graph Store\n",
"\n",
"Store the analyzed graph in a persistent graph database using GraphStore.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.graph_store import GraphStore\n",
"\n",
"# Option 1: Neo4j (requires Neo4j server running)\n",
"graph_store = GraphStore(backend=\"neo4j\", uri=\"bolt://localhost:7687\", user=\"neo4j\", password=\"password\")\n",
"graph_store.connect()\n",
"\n",
"# Store entities as nodes and track node ID mapping\n",
"node_id_map = {}\n",
"for entity in entities:\n",
" node = graph_store.create_node(\n",
" labels=[entity[\"type\"]],\n",
" properties={\"name\": entity[\"name\"], \"original_id\": entity[\"id\"]}\n",
" )\n",
" node_id_map[entity[\"id\"]] = node.get(\"id\")\n",
" print(f\"Stored node: {entity['name']} (ID: {node.get('id')})\")\n",
"\n",
"# Store relationships using mapped node IDs\n",
"for rel in relationships:\n",
" source_id = node_id_map.get(rel[\"source\"])\n",
" target_id = node_id_map.get(rel[\"target\"])\n",
"raw_relationships = [\n",
" # Valid Relationships\n",
" {\"source\": \"founder_1\", \"target\": \"startup_1\", \"type\": \"FOUNDED\", \"valid_from\": \"2021-01-01\"},\n",
" {\"source\": \"investor_1\", \"target\": \"startup_1\", \"type\": \"INVESTED_IN\", \"amount\": 5000000, \"valid_from\": \"2023-06-01\"},\n",
" \n",
" if source_id is not None and target_id is not None:\n",
" relationship = graph_store.create_relationship(\n",
" start_node_id=source_id,\n",
" end_node_id=target_id,\n",
" rel_type=rel[\"type\"],\n",
" properties=rel.get(\"properties\", {})\n",
" )\n",
" print(f\"Stored relationship: {rel['source']} -{rel['type']}-> {rel['target']}\")\n",
" else:\n",
" print(f\"Warning: Could not find node IDs for relationship {rel['source']} -> {rel['target']}\")\n",
" # Dangling Edge (Error!)\n",
" {\"source\": \"founder_2\", \"target\": \"startup_999\", \"type\": \"FOUNDED\", \"valid_from\": \"2020-05-15\"}, \n",
" \n",
" # Temporal Data (History)\n",
" {\"source\": \"founder_1\", \"target\": \"startup_2\", \"type\": \"ADVISED\", \"valid_from\": \"2020-01-01\", \"valid_until\": \"2021-01-01\"}\n",
"]\n",
"\n",
"# Query using Cypher\n",
"results = graph_store.execute_query(\"MATCH (n) RETURN n.name, labels(n) LIMIT 10\")\n",
"print(f\"\\nQuery results: {len(results.get('records', []))} nodes\")\n",
"\n",
"# Get statistics\n",
"stats = graph_store.get_stats()\n",
"print(f\"\\nGraph store statistics:\")\n",
"print(f\" Node count: {stats.get('node_count', 'N/A')}\")\n",
"print(f\" Relationship count: {stats.get('relationship_count', 'N/A')}\")\n",
"print(f\" Label counts: {stats.get('label_counts', {})}\")\n",
"\n",
"graph_store.close()\n"
"print(f\"Loaded {len(raw_entities)} raw entities and {len(raw_relationships)} raw relationships.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"## 2. Phase 1: Validation (The Gatekeeper)\n",
"\n",
"You've learned advanced graph analytics:\n",
"Before we do anything, we must validate the graph. Bad data in = Bad insights out.\n",
"We use `GraphValidator` to check for:\n",
"- **Structural Integrity**: Are all relationship targets present?\n",
"- **Schema Compliance**: Do entities have required fields?\n",
"- **Consistency**: Are IDs unique?"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bd8fb13d",
"metadata": {},
"outputs": [],
"source": [
"# Initialize Validator\n",
"validator = GraphValidator()\n",
"\n",
"- **GraphAnalyzer**: Comprehensive graph analysis and metrics\n",
"- **CentralityCalculator**: Multiple centrality measures\n",
"- **CommunityDetector**: Community detection\n",
"- **ConnectivityAnalyzer**: Connectivity analysis\n",
"- **GraphValidator**: Graph validation\n",
"- **Deduplicator**: Graph deduplication\n",
"- **GraphStore**: Persist graphs to Neo4j or FalkorDB\n",
"# Create a temporary graph object for validation\n",
"temp_graph = {\"entities\": raw_entities, \"relationships\": raw_relationships}\n",
"\n",
"# Run Validation\n",
"print(\"Running Validation Check...\")\n",
"validation_result = validator.validate(temp_graph)\n",
"\n",
"if not validation_result.is_valid:\n",
" print(\"Validation Failed! Issues found:\")\n",
" for issue in validation_result.issues:\n",
" print(f\" - [{issue.severity.name}] {issue.message} (Code: {issue.code})\")\n",
" \n",
" # AUTOMATIC FIX: If it's a dangling edge, remove it\n",
" if issue.code == \"DANGLING_EDGE\":\n",
" print(\" Auto-Fixing: Removing invalid relationship...\")\n",
" raw_relationships = [r for r in raw_relationships \n",
" if r['target'] != issue.details.get('target_id')]\n",
"else:\n",
" print(\"Graph is valid!\")\n",
"\n",
"# Re-validate to confirm fix\n",
"print(\"\\nRe-validating after fixes...\")\n",
"temp_graph = {\"entities\": raw_entities, \"relationships\": raw_relationships}\n",
"if validator.validate(temp_graph).is_valid:\n",
" print(\"Graph is now clean and valid!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Phase 2: Deduplication & Conflict Resolution\n",
"\n",
"We have \"TechFlow AI\" and \"TechFlow Inc.\". These are likely the same company.\n",
"We also have conflicting revenue data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 1. Detect Duplicates\n",
"print(\"Scanning for duplicates...\")\n",
"deduper = DuplicateDetector(similarity_threshold=0.7) # 70% similarity threshold\n",
"duplicates = deduper.detect_duplicates(raw_entities)\n",
"\n",
"for candidate in duplicates:\n",
" print(f\"Found potential duplicate pair (Score: {candidate.similarity_score:.2f}):\")\n",
" print(f\" - {candidate.entity1['name']} (ID: {candidate.entity1['id']})\")\n",
" print(f\" - {candidate.entity2['name']} (ID: {candidate.entity2['id']})\")\n",
" \n",
" # MERGE STRATEGY: Keep entity1, merge data from entity2\n",
" print(\" Merging entities...\")\n",
" # (In a real app, you'd use EntityMerger, but here's the logic:)\n",
" # We keep startup_1 and discard startup_1_dup, but we note the conflict\n",
" \n",
"# 2. Detect Conflicts\n",
"print(\"\\nChecking for data conflicts...\")\n",
"conflict_detector = ConflictDetector()\n",
"\n",
"# Simulating a conflict check between the two versions of TechFlow\n",
"# To check conflicts, we treat them as the same entity (same ID)\n",
"entity_a = raw_entities[0].copy()\n",
"entity_b = raw_entities[2].copy()\n",
"entity_b['id'] = entity_a['id'] # Force same ID for conflict detection\n",
"\n",
"conflicts = conflict_detector.detect_conflicts([entity_a, entity_b])\n",
"\n",
"for conflict in conflicts:\n",
" print(f\" Conflict detected in field '{conflict.property_name}':\")\n",
" print(f\" Values: {conflict.conflicting_values}\")\n",
" \n",
" # RESOLUTION: Trust the higher number (optimistic!)\n",
" if conflict.property_name == \"revenue\":\n",
" # values are strings or ints, need to handle types\n",
" vals = [float(v) for v in conflict.conflicting_values if v is not None]\n",
" resolved_val = max(vals)\n",
" print(f\" Resolved to: {resolved_val}\")\n",
" raw_entities[0]['revenue'] = resolved_val\n",
"\n",
"# Final Cleanup: Remove the duplicate entity from our list\n",
"clean_entities = [e for e in raw_entities if e['id'] != 'startup_1_dup']\n",
"clean_relationships = raw_relationships # (We'd normally re-link relationships too)\n",
"\n",
"print(f\"\\nCleaned Data: {len(clean_entities)} entities remaining.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Phase 3: Building the Knowledge Graph\n",
"\n",
"Now that our data is clean, we build the official graph object."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Manual Graph Construction (since we already cleaned it)\n",
"kg = {\n",
" \"entities\": clean_entities,\n",
" \"relationships\": clean_relationships,\n",
" \"metadata\": {\n",
" \"created_at\": datetime.now().isoformat(),\n",
" \"source\": \"Manual Advanced Pipeline\"\n",
" }\n",
"}\n",
"print(\"Knowledge Graph Assembled Successfully!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Phase 4: Advanced Analytics\n",
"\n",
"This is where the magic happens. We'll use multiple analyzers to extract insights."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Initialize the Master Analyzer\n",
"analyzer = GraphAnalyzer(enable_temporal=True)\n",
"\n",
"# 1. Structural Analysis (Connectivity)\n",
"print(\"\\n--- Connectivity Analysis ---\")\n",
"connectivity = analyzer.analyze_connectivity(kg)\n",
"print(f\" • Graph Connected? {'Yes' if connectivity['is_connected'] else 'No'}\")\n",
"print(f\" • Connected Components: {connectivity['num_components']}\")\n",
"\n",
"# 2. Centrality (Who is important?)\n",
"print(\"\\n--- Centrality Analysis ---\")\n",
"centrality_result = analyzer.calculate_centrality(kg, centrality_type=\"degree\")\n",
"degree_data = centrality_result[\"centrality_measures\"][\"degree\"]\n",
"\n",
"# Get pre-calculated rankings\n",
"top_nodes = degree_data[\"rankings\"][:3]\n",
"\n",
"print(\" • Top Influencers (Degree Centrality):\")\n",
"for item in top_nodes:\n",
" print(f\" - {item['node']}: {item['score']:.2f}\")\n",
"\n",
"# 3. Community Detection (Clustering)\n",
"print(\"\\n--- Community Detection ---\")\n",
"community_result = analyzer.detect_communities(kg, algorithm=\"louvain\")\n",
"communities = community_result[\"communities\"]\n",
"\n",
"print(f\" • Detected {len(communities)} communities.\")\n",
"for i, comm in enumerate(communities):\n",
" # comm is a set of node IDs\n",
" members = list(comm)\n",
" print(f\" Community {i+1}: {', '.join(members)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Phase 5: Temporal Analytics (Time Travel)\n",
"\n",
"Static graphs are boring. Real worlds change. Let's analyze the **evolution** of our ecosystem."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"temporal_engine = TemporalGraphQuery(temporal_granularity=\"year\")\n",
"\n",
"# 1. Time Travel Query: What did the world look like in 2020?\n",
"print(\"\\n--- Time Travel: 2020 ---\")\n",
"snapshot_2020 = temporal_engine.query_at_time(kg, query=\"*\", at_time=\"2020-06-01\")\n",
"print(f\" Active Relationships in 2020: {len(snapshot_2020['relationships'])}\")\n",
"for rel in snapshot_2020['relationships']:\n",
" print(f\" - {rel['source']} --[{rel['type']}]--> {rel['target']}\")\n",
"\n",
"# 2. Time Travel Query: What about 2023?\n",
"print(\"\\n--- Time Travel: 2023 ---\")\n",
"snapshot_2023 = temporal_engine.query_at_time(kg, query=\"*\", at_time=\"2023-07-01\")\n",
"print(f\" Active Relationships in 2023: {len(snapshot_2023['relationships'])}\")\n",
"for rel in snapshot_2023['relationships']:\n",
" print(f\" - {rel['source']} --[{rel['type']}]--> {rel['target']}\")\n",
" \n",
"# Notice how 'ADVISED' might disappear if it ended, and 'INVESTED_IN' appears!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Phase 6: Provenance (Data Lineage)\n",
"\n",
"Finally, in a production system, you need to know **where** a fact came from. This is crucial for trust."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tracker = ProvenanceTracker()\n",
"\n",
"# Let's pretend we're tracking the source of our data\n",
"tracker.track_entity(\"startup_1\", source=\"Crunchbase_API_v2\", metadata={\"confidence\": 0.95})\n",
"tracker.track_entity(\"startup_1\", source=\"Manual_Entry_User_Bob\", metadata={\"confidence\": 1.0})\n",
"\n",
"print(\"\\n--- Provenance Report: TechFlow AI ---\")\n",
"lineage = tracker.get_lineage(\"startup_1\")\n",
"print(f\" Entity: startup_1\")\n",
"print(f\" First Seen: {lineage['first_seen']}\")\n",
"print(f\" Sources:\")\n",
"for src in lineage['sources']:\n",
" print(f\" - {src['source']} (at {src['timestamp']})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"You have just walked through a complete, advanced Knowledge Graph pipeline:\n",
"\n",
"1. **Validated** messy input data.\n",
"2. **Cleaned** duplicates and conflicts.\n",
"3. **Analyzed** structure and community dynamics.\n",
"4. **Queried** across time dimensions.\n",
"5. **Tracked** data lineage.\n",
"\n",
"This represents the state-of-the-art in modern KG Engineering using Semantica."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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
"nbformat_minor": 5
}
@@ -1,12 +1,5 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Notice**: The `semantica.kg_qa` module is temporarily unavailable and will be reintroduced in a future release. Any quality assessment examples in this notebook are disabled."
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -17,7 +10,7 @@
"\n",
"## Overview\n",
"\n",
"Comprehensive visualization capabilities: visualize knowledge graphs, embeddings, quality metrics, analytics, and temporal data.\n",
"Comprehensive visualization capabilities: visualize knowledge graphs, embeddings, analytics, and temporal data.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/visualization/)\n",
"\n",
@@ -32,6 +25,15 @@
"```\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install -qU semantica\n"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -40,14 +42,10 @@
"source": [
"from semantica.visualization import (\n",
" KGVisualizer,\n",
" EmbeddingVisualizer,\n",
" QualityVisualizer,\n",
" AnalyticsVisualizer,\n",
" TemporalVisualizer\n",
")\n",
"from semantica.kg import GraphBuilder, GraphAnalyzer\n",
"from semantica.embeddings import EmbeddingGenerator\n",
"import numpy as np\n"
]
},
@@ -96,59 +94,14 @@
"outputs": [],
"source": [
"kg_visualizer = KGVisualizer(layout=\"force\", color_scheme=\"vibrant\")\n",
"kg_visualizer.visualize_network(knowledge_graph, output=\"interactive\")\n"
"kg_visualizer.visualize_network(knowledge_graph, output=\"interactive\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Generate Embeddings and Visualize\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"embedding_generator = EmbeddingGenerator()\n",
"texts = [entity.get(\"name\", \"\") for entity in entities]\n",
"embeddings = embedding_generator.generate_embeddings(texts, data_type=\"text\")\n",
"\n",
"labels = [entity.get(\"type\", \"Unknown\") for entity in entities]\n",
"\n",
"embedding_visualizer = EmbeddingVisualizer()\n",
"embedding_visualizer.visualize_2d_projection(embeddings, labels, method=\"tsne\", output=\"interactive\", file_path=None)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Quality Metrics Visualization\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"quality_visualizer = QualityVisualizer()\n",
"quality_report = {\n",
" \"overall_score\": 0.85,\n",
" \"consistency_score\": 0.90,\n",
" \"completeness_score\": 0.80\n",
"}\n",
"quality_visualizer.visualize_dashboard(quality_report, output=\"interactive\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Graph Analytics Visualization\n"
"## Step 3: Graph Analytics Visualization\n"
]
},
{
@@ -206,7 +159,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 6: Temporal Data Visualization\n"
"## Step 5: Temporal Data Visualization\n"
]
},
{
@@ -215,50 +168,103 @@
"metadata": {},
"outputs": [],
"source": [
"import datetime\n",
"from semantica.visualization import TemporalVisualizer\n",
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"# 1. Setup Data: AI Research Lab Evolution (2020-2024)\n",
"# This dataset simulates a growing network of researchers, papers, and grants\n",
"\n",
"start_date = datetime.date(2020, 1, 1)\n",
"\n",
"# Entities with lifespans\n",
"entities = [\n",
" {\"id\": \"Lab_Alpha\", \"type\": \"Organization\", \"start\": \"2020-01-01\", \"end\": \"2024-12-31\", \"properties\": {\"budget\": \"High\"}},\n",
" {\"id\": \"Dr_Smith\", \"type\": \"Researcher\", \"start\": \"2020-01-15\", \"end\": \"2024-12-31\", \"properties\": {\"h_index\": 15}},\n",
" {\"id\": \"Dr_Jones\", \"type\": \"Researcher\", \"start\": \"2020-03-01\", \"end\": \"2024-12-31\", \"properties\": {\"h_index\": 12}},\n",
" {\"id\": \"Paper_X\", \"type\": \"Publication\", \"start\": \"2020-11-20\", \"end\": \"2024-12-31\", \"properties\": {\"citations\": 50}},\n",
" {\"id\": \"Grant_A\", \"type\": \"Funding\", \"start\": \"2021-01-01\", \"end\": \"2022-12-31\", \"properties\": {\"amount\": 1000000}},\n",
" {\"id\": \"Dr_Chen\", \"type\": \"Researcher\", \"start\": \"2021-06-01\", \"end\": \"2024-12-31\", \"properties\": {\"h_index\": 8}},\n",
" {\"id\": \"Paper_Y\", \"type\": \"Publication\", \"start\": \"2022-03-15\", \"end\": \"2024-12-31\", \"properties\": {\"citations\": 25}},\n",
" {\"id\": \"Startup_Beta\", \"type\": \"SpinOff\", \"start\": \"2023-01-01\", \"end\": \"2024-12-31\", \"properties\": {\"valuation\": \"5M\"}},\n",
"]\n",
"\n",
"# Relationships with timestamps\n",
"relationships = [\n",
" {\"source\": \"Dr_Smith\", \"target\": \"Lab_Alpha\", \"type\": \"WORKS_AT\", \"timestamp\": \"2020-01-15\"},\n",
" {\"source\": \"Dr_Jones\", \"target\": \"Lab_Alpha\", \"type\": \"WORKS_AT\", \"timestamp\": \"2020-03-01\"},\n",
" {\"source\": \"Dr_Smith\", \"target\": \"Paper_X\", \"type\": \"AUTHORED\", \"timestamp\": \"2020-11-20\"},\n",
" {\"source\": \"Dr_Jones\", \"target\": \"Paper_X\", \"type\": \"AUTHORED\", \"timestamp\": \"2020-11-20\"},\n",
" {\"source\": \"Lab_Alpha\", \"target\": \"Grant_A\", \"type\": \"RECEIVED\", \"timestamp\": \"2021-01-01\"},\n",
" {\"source\": \"Dr_Chen\", \"target\": \"Lab_Alpha\", \"type\": \"WORKS_AT\", \"timestamp\": \"2021-06-01\"},\n",
" {\"source\": \"Dr_Chen\", \"target\": \"Paper_Y\", \"type\": \"AUTHORED\", \"timestamp\": \"2022-03-15\"},\n",
" {\"source\": \"Dr_Smith\", \"target\": \"Paper_Y\", \"type\": \"AUTHORED\", \"timestamp\": \"2022-03-15\"},\n",
" {\"source\": \"Lab_Alpha\", \"target\": \"Startup_Beta\", \"type\": \"SPUN_OFF\", \"timestamp\": \"2023-01-01\"},\n",
" {\"source\": \"Dr_Jones\", \"target\": \"Startup_Beta\", \"type\": \"CTO\", \"timestamp\": \"2023-02-01\"},\n",
"]\n",
"\n",
"# Metrics over time\n",
"dates = pd.date_range(start=\"2020-01-01\", end=\"2024-01-01\", freq=\"M\")\n",
"metrics = {\n",
" \"dates\": [d.strftime(\"%Y-%m-%d\") for d in dates],\n",
" \"funding_usd\": [100000 + (i * 50000) + (np.random.randint(-10000, 10000)) for i in range(len(dates))],\n",
" \"team_size\": [2 + int(i/5) for i in range(len(dates))],\n",
" \"publications\": [int(i/4) for i in range(len(dates))]\n",
"}\n",
"\n",
"# 4. Generate Timestamps Map (Required for TemporalVisualizer)\n",
"# This maps each entity to the specific time points where it is \"active\" or relevant\n",
"timestamps = {}\n",
"\n",
"# Collect all relevant dates (monthly granularity)\n",
"all_dates = [d.strftime(\"%Y-%m-%d\") for d in dates]\n",
"\n",
"for entity in entities:\n",
" eid = entity[\"id\"]\n",
" start = entity.get(\"start\")\n",
" end = entity.get(\"end\")\n",
" \n",
" # In a real app, you'd calculate overlap. Here we'll just assign all dates \n",
" # that fall within the entity's lifespan\n",
" entity_times = [d for d in all_dates if start <= d <= end]\n",
" timestamps[eid] = entity_times\n",
" \n",
"temporal_kg = {\n",
" \"entities\": entities,\n",
" \"relationships\": relationships,\n",
" \"timestamps\": {\n",
" \"e1\": [2020, 2021, 2022],\n",
" \"e2\": [2020, 2021],\n",
" \"e3\": [2010, 2015, 2020, 2022],\n",
" }\n",
" \"metrics\": metrics,\n",
" \"timestamps\": timestamps\n",
"}\n",
"\n",
"entity_history = {\n",
" \"e1\": [\n",
" {\"timestamp\": 2020, \"properties\": {\"age\": 28}},\n",
" {\"timestamp\": 2021, \"properties\": {\"age\": 29}},\n",
" {\"timestamp\": 2022, \"properties\": {\"age\": 30}},\n",
" ]\n",
"}\n",
"# 2. Initialize Visualizer\n",
"viz = TemporalVisualizer()\n",
"\n",
"from semantica.kg import TemporalVersionManager\n",
"temporal_visualizer = TemporalVisualizer()\n",
"temporal_visualizer.visualize_timeline(temporal_kg, output=\"interactive\")\n",
"# Convert entity history to metrics for visualization\n",
"timestamps = [str(item[\"timestamp\"]) for item in entity_history[\"e1\"]]\n",
"age_values = [item[\"properties\"][\"age\"] for item in entity_history[\"e1\"]]\n",
"metrics_history = {\"age\": age_values}\n",
"temporal_visualizer.visualize_metrics_evolution(metrics_history, timestamps, output=\"interactive\")\n",
"print(\"1. Generating Temporal Dashboard...\")\n",
"# This creates a combined view of lifecycles, activity, and metrics\n",
"dashboard = viz.visualize_temporal_dashboard(\n",
" temporal_kg,\n",
" title=\"AI Research Lab Evolution (2020-2024)\",\n",
" output=\"interactive\"\n",
")\n",
"dashboard.show()\n",
"\n",
"# Create versions for snapshot comparison\n",
"version_manager = TemporalVersionManager()\n",
"v1 = version_manager.create_version(temporal_kg, timestamp=\"2020-01-01\", version_label=\"v2020\")\n",
"temporal_kg_v2 = {\n",
" \"entities\": temporal_kg.get(\"entities\", []),\n",
" \"relationships\": temporal_kg.get(\"relationships\", []) + [\n",
" {\"source\": \"e1\", \"target\": \"e2\", \"type\": \"collaborated_with\", \"valid_from\": \"2023-01-01\"}\n",
" ]\n",
"}\n",
"v2 = version_manager.create_version(temporal_kg_v2, timestamp=\"2023-01-01\", version_label=\"v2023\")\n",
"snapshots = {v1[\"timestamp\"]: v1, v2[\"timestamp\"]: v2}\n",
"temporal_visualizer.visualize_snapshot_comparison(snapshots, output=\"interactive\")\n",
"version_history = [\n",
" {\"version\": v1.get(\"label\"), \"timestamp\": v1.get(\"timestamp\")},\n",
" {\"version\": v2.get(\"label\"), \"timestamp\": v2.get(\"timestamp\")}\n",
"]\n",
"temporal_visualizer.visualize_version_history(version_history, output=\"interactive\")\n"
"print(\"2. Generating Network Evolution Animation...\")\n",
"# This creates a playable animation of the network graph\n",
"animation = viz.visualize_network_evolution(\n",
" temporal_kg,\n",
" title=\"Network Growth Over Time\",\n",
" output=\"interactive\"\n",
")\n",
"animation.show()\n",
"\n",
"print(\"3. Generating Timeline View...\")\n",
"timeline = viz.visualize_timeline(\n",
" temporal_kg,\n",
" title=\"Entity Lifecycles\",\n",
" output=\"interactive\"\n",
")\n",
"timeline.show()"
]
},
{
@@ -270,15 +276,28 @@
"All visualization types demonstrated:\n",
"- Knowledge Graph Visualization\n",
"- Embedding Visualization (t-SNE)\n",
"- Quality Metrics Visualization\n",
"- Graph Analytics Visualization (Centrality & Communities)\n",
"- Temporal Data Visualization (Timeline & Evolution)\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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,
@@ -1,254 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Notice**: The `semantica.kg_qa` module is temporarily unavailable and will be reintroduced in a future release. Any quality assessment examples in this notebook are disabled."
]
},
{
"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/advanced/04_Conflict_Resolution_Strategies.ipynb)\n",
"\n",
"# Conflict Resolution Strategies\n",
"\n",
"## Overview\n",
"\n",
"Detect conflicts in knowledge graphs, apply multiple resolution strategies, track sources, and maintain audit trails.\n",
"\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/conflicts/)\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"## Workflow: Detect Conflicts → Multiple Resolution Strategies → Track Sources → Audit\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from datetime import datetime\n",
"import json\n",
"from semantica.conflicts import ConflictDetector, ConflictResolver, SourceTracker\n",
"from semantica.conflicts.conflict_resolver import ResolutionStrategy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1: Define Entities with Conflicting Data\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"entities = [\n",
" {\n",
" \"id\": \"e1\",\n",
" \"type\": \"Person\",\n",
" \"name\": \"John Doe\",\n",
" \"age\": 30,\n",
" \"location\": \"New York\",\n",
" \"source\": \"source1\",\n",
" \"confidence\": 0.8,\n",
" \"metadata\": {\"timestamp\": datetime(2023, 1, 1)}\n",
" },\n",
" {\n",
" \"id\": \"e1\",\n",
" \"type\": \"Person\",\n",
" \"name\": \"John Doe\",\n",
" \"age\": 32,\n",
" \"location\": \"Boston\",\n",
" \"source\": \"source2\",\n",
" \"confidence\": 0.9,\n",
" \"metadata\": {\"timestamp\": datetime(2023, 6, 1)}\n",
" },\n",
" {\n",
" \"id\": \"e2\",\n",
" \"type\": \"Organization\",\n",
" \"name\": \"Tech Corp\",\n",
" \"founded\": 2010,\n",
" \"employees\": 100,\n",
" \"source\": \"source1\",\n",
" \"confidence\": 0.9,\n",
" \"metadata\": {\"timestamp\": datetime(2023, 1, 1)}\n",
" },\n",
" {\n",
" \"id\": \"e2\",\n",
" \"type\": \"Organization\",\n",
" \"name\": \"Tech Corp\",\n",
" \"founded\": 2012,\n",
" \"employees\": 150,\n",
" \"source\": \"source2\",\n",
" \"confidence\": 0.7,\n",
" \"metadata\": {\"timestamp\": datetime(2023, 3, 1)}\n",
" }\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Detect Conflicts\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Initialize detector\n",
"detector = ConflictDetector(track_provenance=True)\n",
"\n",
"# Detect conflicts across all properties\n",
"conflicts = detector.detect_entity_conflicts(entities)\n",
"\n",
"print(f\"Detected {len(conflicts)} conflicts:\")\n",
"for i, conflict in enumerate(conflicts, 1):\n",
" print(f\"\\nConflict {i}:\")\n",
" print(f\" ID: {conflict.conflict_id}\")\n",
" print(f\" Type: {conflict.conflict_type.value}\")\n",
" print(f\" Entity: {conflict.entity_id}\")\n",
" print(f\" Property: {conflict.property_name}\")\n",
" print(f\" Values: {conflict.conflicting_values}\")\n",
" print(f\" Severity: {conflict.severity}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Resolve Conflicts\n",
"\n",
"We can apply different strategies to resolve the conflicts:\n",
"- **Voting**: Selects the most frequent value\n",
"- **Most Recent**: Selects the value with the latest timestamp\n",
"- **Highest Confidence**: Selects the value from the source with highest confidence\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Initialize resolver\n",
"resolver = ConflictResolver()\n",
"\n",
"# Strategy 1: Voting\n",
"print(\"--- Strategy: Voting ---\")\n",
"results_voting = resolver.resolve_conflicts(conflicts, strategy=\"voting\")\n",
"for r in results_voting:\n",
" if r.resolved:\n",
" print(f\"Resolved {r.conflict_id}: {r.resolved_value} (Confidence: {r.confidence:.2f})\")\n",
"\n",
"# Strategy 2: Most Recent\n",
"print(\"\\n--- Strategy: Most Recent ---\")\n",
"results_recent = resolver.resolve_conflicts(conflicts, strategy=\"most_recent\")\n",
"for r in results_recent:\n",
" if r.resolved:\n",
" print(f\"Resolved {r.conflict_id}: {r.resolved_value}\")\n",
"\n",
"# Strategy 3: Highest Confidence\n",
"print(\"\\n--- Strategy: Highest Confidence ---\")\n",
"results_confidence = resolver.resolve_conflicts(conflicts, strategy=\"highest_confidence\")\n",
"for r in results_confidence:\n",
" if r.resolved:\n",
" print(f\"Resolved {r.conflict_id}: {r.resolved_value} (Confidence: {r.confidence:.2f})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Track Sources\n",
"\n",
"The `ConflictDetector` tracks source provenance when `track_provenance=True`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tracker = detector.source_tracker\n",
"\n",
"for conflict in conflicts:\n",
" print(f\"\\nConflict: {conflict.conflict_id}\")\n",
" # Get detailed source info for the property\n",
" sources = tracker.get_property_sources(conflict.entity_id, conflict.property_name)\n",
" if sources:\n",
" print(f\" Entity: {conflict.entity_id}, Property: {conflict.property_name}\")\n",
" print(f\" Sources found: {len(sources.sources)}\")\n",
" for src in sources.sources:\n",
" print(f\" - {src.document} (Confidence: {src.confidence})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Audit Trail\n",
"\n",
"The `ConflictResolver` maintains a history of all resolutions."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"history = resolver.get_resolution_history()\n",
"\n",
"print(f\"Resolution History ({len(history)} entries):\")\n",
"for entry in history:\n",
" print(f\"\\nConflict: {entry.conflict_id}\")\n",
" print(f\" Strategy: {entry.resolution_strategy}\")\n",
" print(f\" Resolved Value: {entry.resolved_value}\")\n",
" print(f\" Notes: {entry.resolution_notes}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"Conflict resolution workflow:\n",
"- Conflict Detection using `ConflictDetector`\n",
"- Multiple Resolution Strategies (Voting, Most Recent, Highest Confidence)\n",
"- Source Tracking with `SourceTracker`\n",
"- Complete Audit Trail via `ConflictResolver`"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
+15 -1
View File
@@ -48,6 +48,15 @@
"```\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -312,7 +321,7 @@
"- NumPy format\n",
"- Binary format\n",
"- FAISS format\n",
"- Vector store integration (Pinecone, Weaviate, Qdrant)\n"
"- Vector store integration (Weaviate, Qdrant)\n"
]
},
{
@@ -614,6 +623,11 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
}
File diff suppressed because it is too large Load Diff
@@ -1,233 +0,0 @@
{
"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/advanced/07_Pipeline_Orchestration.ipynb)\n",
"\n",
"# Pipeline Orchestration\n",
"\n",
"## Overview\n",
"\n",
"Build complex pipelines, execute them, handle failures, enable parallel processing, and monitor execution.\n",
"\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/pipeline/)\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"## Workflow: Build Pipelines → Execute → Handle Failures → Parallel Processing → Monitor\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.pipeline import (\n",
" PipelineBuilder,\n",
" ExecutionEngine,\n",
" FailureHandler,\n",
" ParallelismManager,\n",
" RetryPolicy,\n",
" RetryStrategy\n",
")\n",
"from semantica.ingest import FileIngestor\n",
"from semantica.parse import DocumentParser\n",
"from semantica.semantic_extract import NERExtractor\n",
"from semantica.kg import GraphBuilder\n",
"import time\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1: Build Complex Pipelines\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"builder = PipelineBuilder()\n",
"\n",
"file_ingestor = FileIngestor()\n",
"document_parser = DocumentParser()\n",
"ner_extractor = NERExtractor()\n",
"graph_builder = GraphBuilder()\n",
"\n",
"# Define handlers for each pipeline step\n",
"def ingest_handler(data, **config):\n",
" files = data.get(\"files\", [])\n",
" if files:\n",
" # Ingest first file as example\n",
" file_obj = file_ingestor.ingest_file(files[0], read_content=True)\n",
" return {**data, \"file\": file_obj}\n",
" return data\n",
"\n",
"def parse_handler(data, **config):\n",
" # If a file was ingested, try parsing; otherwise pass text through\n",
" file_obj = data.get(\"file\")\n",
" if file_obj and getattr(file_obj, \"path\", None):\n",
" parsed = document_parser.parse_document(file_obj.path)\n",
" text = parsed.get(\"text\") if isinstance(parsed, dict) else None\n",
" return {**data, \"text\": text or data.get(\"text\")}\n",
" return data\n",
"\n",
"def extract_handler(data, **config):\n",
" text = data.get(\"text\", \"\")\n",
" entities = ner_extractor.extract_entities(text)\n",
" # Normalize to dict list for graph builder\n",
" entity_dicts = [\n",
" {\"id\": f\"e{i}\", \"name\": e.text, \"type\": e.label} for i, e in enumerate(entities)\n",
" ]\n",
" return {**data, \"entities\": entity_dicts}\n",
"\n",
"def build_graph_handler(data, **config):\n",
" entities = data.get(\"entities\", [])\n",
" graph = graph_builder.build({\"entities\": entities})\n",
" return {**data, \"graph\": graph}\n",
"\n",
"# Build pipeline with proper handlers and dependencies\n",
"pipeline = (\n",
" builder\n",
" .add_step(\"ingest\", \"ingest\", handler=ingest_handler)\n",
" .add_step(\"parse\", \"parse\", dependencies=[\"ingest\"], handler=parse_handler)\n",
" .add_step(\"extract\", \"extract\", dependencies=[\"parse\"], handler=extract_handler)\n",
" .add_step(\"build_graph\", \"build_graph\", dependencies=[\"extract\"], handler=build_graph_handler)\n",
").build()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Execute Pipeline\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"engine = ExecutionEngine()\n",
"\n",
"input_data = {\n",
" \"text\": \"Alice works at Tech Corp. Bob is a friend of Alice.\",\n",
" \"files\": []\n",
"}\n",
"\n",
"start_time = time.time()\n",
"result = engine.execute_pipeline(pipeline, input_data)\n",
"execution_time = result.metrics.get(\"execution_time\", time.time() - start_time)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Handle Failures\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Configure retry policy for the 'extract' step type\n",
"engine.failure_handler.set_retry_policy(\n",
" \"extract\",\n",
" RetryPolicy(max_retries=3, backoff_factor=2.0, strategy=RetryStrategy.EXPONENTIAL)\n",
")\n",
"\n",
"result = engine.execute_pipeline(pipeline, input_data)\n",
"print(\"Pipeline executed with retry policy configured\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Parallel Processing\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"parallelism = ParallelismManager(max_workers=4)\n",
"\n",
"# Identify groups of steps that can run in parallel\n",
"groups = parallelism.identify_parallelizable_steps(pipeline)\n",
"\n",
"# Execute first parallelizable group as a demonstration\n",
"start_time = time.time()\n",
"parallel_results = []\n",
"for group in groups:\n",
" parallel_results.extend(parallelism.execute_pipeline_steps_parallel(group, input_data, max_workers=4))\n",
"parallel_time = time.time() - start_time\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Monitor Pipeline Execution\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Metrics from execution engine\n",
"metrics = result.metrics\n",
"progress = engine.get_progress(pipeline.name)\n",
"\n",
"print(f\"Duration: {metrics.get('execution_time', 0):.2f} seconds\")\n",
"print(f\"Steps Executed: {metrics.get('steps_executed', 0)}\")\n",
"print(f\"Steps Failed: {metrics.get('steps_failed', 0)}\")\n",
"print(f\"Progress: {progress.get('progress_percentage', 0):.1f}% (status: {progress.get('status')})\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"Pipeline orchestration workflow:\n",
"- Complex Pipeline Built\n",
"- Pipeline Executed\n",
"- Failure Handling Configured\n",
"- Parallel Processing Enabled\n",
"- Full Monitoring and Observability\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
+346 -334
View File
@@ -1,336 +1,348 @@
{
"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/advanced/08_Reasoning_and_Inference.ipynb)\n",
"\n",
"# Reasoning and Inference\n",
"\n",
"## Overview\n",
"\n",
"Build knowledge graphs, define rules, perform forward/backward chaining, and generate explanations for AI reasoning using the **Semantica Reasoning Module**.\n",
"\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/reasoning/)\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"## Workflow: Build KG → Define Rules → Forward/Backward Chaining → Generate Explanations\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphBuilder\n",
"from semantica.reasoning import InferenceEngine, RuleManager, ExplanationGenerator\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1: Build Knowledge Graph\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"builder = GraphBuilder()\n",
"\n",
"entities = [\n",
" {\"id\": \"alice\", \"type\": \"Person\", \"name\": \"Alice\"},\n",
" {\"id\": \"bob\", \"type\": \"Person\", \"name\": \"Bob\"},\n",
" {\"id\": \"charlie\", \"type\": \"Person\", \"name\": \"Charlie\"},\n",
" {\"id\": \"sf\", \"type\": \"Location\", \"name\": \"San Francisco\"},\n",
" {\"id\": \"california\", \"type\": \"Location\", \"name\": \"California\"},\n",
"]\n",
"\n",
"relationships = [\n",
" {\"source\": \"alice\", \"target\": \"bob\", \"type\": \"parent_of\"},\n",
" {\"source\": \"bob\", \"target\": \"charlie\", \"type\": \"parent_of\"},\n",
" {\"source\": \"sf\", \"target\": \"california\", \"type\": \"located_in\"},\n",
" {\"source\": \"alice\", \"target\": \"sf\", \"type\": \"lives_in\"},\n",
"]\n",
"\n",
"knowledge_graph = builder.build([{\"entities\": entities, \"relationships\": relationships}])\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Define Rules\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Initialize Inference Engine\n",
"engine = InferenceEngine()\n",
"\n",
"# Define rules using logic syntax\n",
"rules = [\n",
" \"IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)\",\n",
" \"IF lives_in(?x, ?y) AND located_in(?y, ?z) THEN lives_in(?x, ?z)\"\n",
"]\n",
"\n",
"for rule in rules:\n",
" engine.add_rule(rule)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Forward Chaining\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Load facts from relationships into the engine\n",
"for rel in relationships:\n",
" # Format: predicate(subject, object)\n",
" fact_str = f\"{rel['type']}({rel['source']}, {rel['target']})\"\n",
" engine.add_fact(fact_str)\n",
"\n",
"# Perform forward chaining to derive new facts\n",
"results = engine.forward_chain()\n",
"\n",
"print(f\"Inferred {len(results)} new facts:\")\n",
"for result in results:\n",
" print(f\" - {result.conclusion} (Rule: {result.rule_used.name})\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Backward Chaining\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Define a goal to prove\n",
"goal = \"grandparent_of(alice, charlie)\"\n",
"\n",
"# Perform backward chaining\n",
"proof = engine.backward_chain(goal)\n",
"\n",
"if proof:\n",
" print(f\"Goal '{goal}' proven successfully!\")\n",
"else:\n",
" print(f\"Could not prove goal '{goal}'.\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Generate Explanations\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"generator = ExplanationGenerator()\n",
"\n",
"# Explain the last forward chaining inference\n",
"if results:\n",
" explanation = generator.generate_explanation(results[0])\n",
" print(\"Explanation for first inferred fact:\")\n",
" print(explanation.natural_language)\n",
"\n",
"# If we have a proof from backward chaining, explain it\n",
"if proof:\n",
" proof_explanation = generator.generate_explanation(proof)\n",
" print(\"\\nExplanation for backward chaining proof:\")\n",
" print(proof_explanation.natural_language)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"Reasoning and inference workflow:\n",
"- Knowledge Graph Built\n",
"- Inference Rules Defined\n",
"- Facts Loaded into Engine\n",
"- Forward Chaining Performed\n",
"- Backward Chaining Performed\n",
"- Explanations Generated\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"### Deep Dive: Reasoning Module\n",
"\n",
"This section provides an in-depth guide to Semantica's reasoning capabilities. Learn rule syntax, fact formats, chaining strategies, and explanation generation with robust, reproducible examples.\n",
"\n",
"**What you'll practice**\n",
"- Defining rules with variables and predicates\n",
"- Loading facts in predicate form\n",
"- Running forward and backward chaining\n",
"- Generating human-readable explanations\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphBuilder\n",
"from semantica.reasoning import InferenceEngine, ExplanationGenerator\n",
"\n",
"builder = GraphBuilder()\n",
"engine = InferenceEngine()\n",
"explainer = ExplanationGenerator()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Rule Syntax\n",
"\n",
"Rules use predicate logic with variables prefixed by `?`.\n",
"\n",
"- Example: `IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)`\n",
"- Variables unify across predicates in the same rule\n",
"- Conclusions are added as new facts when conditions match\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"entities = [\n",
" {\"id\": \"alice\", \"type\": \"Person\", \"name\": \"Alice\"},\n",
" {\"id\": \"bob\", \"type\": \"Person\", \"name\": \"Bob\"},\n",
" {\"id\": \"charlie\", \"type\": \"Person\", \"name\": \"Charlie\"},\n",
" {\"id\": \"sf\", \"type\": \"Location\", \"name\": \"San Francisco\"},\n",
" {\"id\": \"california\", \"type\": \"Location\", \"name\": \"California\"}\n",
"]\n",
"\n",
"relationships = [\n",
" {\"source\": \"alice\", \"target\": \"bob\", \"type\": \"parent_of\"},\n",
" {\"source\": \"bob\", \"target\": \"charlie\", \"type\": \"parent_of\"},\n",
" {\"source\": \"sf\", \"target\": \"california\", \"type\": \"located_in\"},\n",
" {\"source\": \"alice\", \"target\": \"sf\", \"type\": \"lives_in\"}\n",
"]\n",
"\n",
"knowledge_graph = builder.build([{\"entities\": entities, \"relationships\": relationships}])\n",
"print(len(knowledge_graph.get(\"entities\", [])))\n",
"print(len(knowledge_graph.get(\"relationships\", [])))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rules = [\n",
" \"IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)\",\n",
" \"IF lives_in(?x, ?y) AND located_in(?y, ?z) THEN lives_in(?x, ?z)\"\n",
"]\n",
"for r in rules:\n",
" engine.add_rule(r)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for rel in relationships:\n",
" fact = f\"{rel['type']}({rel['source']}, {rel['target']})\"\n",
" engine.add_fact(fact)\n",
"\n",
"derived = engine.forward_chain()\n",
"print(len(derived))\n",
"for d in derived:\n",
" print(d.conclusion)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"goals = [\n",
" \"grandparent_of(alice, charlie)\",\n",
" \"lives_in(alice, california)\"\n",
"]\n",
"for g in goals:\n",
" proof = engine.backward_chain(g)\n",
" print(g)\n",
" print(bool(proof))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if derived:\n",
" exp = explainer.generate_explanation(derived[0])\n",
" print(exp.natural_language)\n",
"\n",
"goal = \"grandparent_of(alice, charlie)\"\n",
"proof = engine.backward_chain(goal)\n",
"if proof:\n",
" pexp = explainer.generate_explanation(proof)\n",
" print(pexp.natural_language)\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
"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/advanced/08_Reasoning_and_Inference.ipynb)\n",
"\n",
"# Reasoning and Inference\n",
"\n",
"## Overview\n",
"\n",
"Build knowledge graphs, define rules, perform forward/backward chaining, and generate explanations for AI reasoning using the **Semantica Reasoning Module**.\n",
"\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/reasoning/)\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"## Workflow: Build KG → Define Rules → Forward/Backward Chaining → Generate Explanations\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install -qU semantica\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphBuilder\n",
"from semantica.reasoning import Reasoner, ExplanationGenerator\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1: Build Knowledge Graph\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"builder = GraphBuilder()\n",
"\n",
"entities = [\n",
" {\"id\": \"alice\", \"type\": \"Person\", \"name\": \"Alice\"},\n",
" {\"id\": \"bob\", \"type\": \"Person\", \"name\": \"Bob\"},\n",
" {\"id\": \"charlie\", \"type\": \"Person\", \"name\": \"Charlie\"},\n",
" {\"id\": \"sf\", \"type\": \"Location\", \"name\": \"San Francisco\"},\n",
" {\"id\": \"california\", \"type\": \"Location\", \"name\": \"California\"},\n",
"]\n",
"\n",
"relationships = [\n",
" {\"source\": \"alice\", \"target\": \"bob\", \"type\": \"parent_of\"},\n",
" {\"source\": \"bob\", \"target\": \"charlie\", \"type\": \"parent_of\"},\n",
" {\"source\": \"sf\", \"target\": \"california\", \"type\": \"located_in\"},\n",
" {\"source\": \"alice\", \"target\": \"sf\", \"type\": \"lives_in\"},\n",
"]\n",
"\n",
"knowledge_graph = builder.build([{\"entities\": entities, \"relationships\": relationships}])\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Define Rules\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Initialize Reasoner\n",
"reasoner = Reasoner()\n",
"\n",
"# Define rules using logic syntax\n",
"rules = [\n",
" \"IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)\",\n",
" \"IF lives_in(?x, ?y) AND located_in(?y, ?z) THEN lives_in(?x, ?z)\"\n",
"]\n",
"\n",
"for rule in rules:\n",
" reasoner.add_rule(rule)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Forward Chaining\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Perform forward chaining to derive new facts\n",
"# The Reasoner can infer facts directly from the knowledge graph or a list of facts\n",
"inferred_facts = reasoner.infer_facts(knowledge_graph)\n",
"\n",
"print(f\"Inferred {len(inferred_facts)} new facts:\")\n",
"for fact in inferred_facts:\n",
" print(f\" - {fact}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Backward Chaining\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Define a goal to prove\n",
"goal = \"grandparent_of(alice, charlie)\"\n",
"\n",
"# Perform backward chaining\n",
"proof = reasoner.backward_chain(goal)\n",
"\n",
"if proof:\n",
" print(f\"Goal '{goal}' proven successfully!\")\n",
"else:\n",
" print(f\"Could not prove goal '{goal}'.\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Generate Explanations\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"generator = ExplanationGenerator()\n",
"\n",
"# If we have a proof from backward chaining, explain it\n",
"if proof:\n",
" proof_explanation = generator.generate_explanation(proof)\n",
" print(\"Explanation for backward chaining proof:\")\n",
" print(proof_explanation.natural_language)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"Reasoning and inference workflow:\n",
"- Knowledge Graph Built\n",
"- Inference Rules Defined\n",
"- Facts Loaded into Engine\n",
"- Forward Chaining Performed\n",
"- Backward Chaining Performed\n",
"- Explanations Generated\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"### Deep Dive: Reasoning Module\n",
"\n",
"This section provides an in-depth guide to Semantica's reasoning capabilities. Learn rule syntax, fact formats, chaining strategies, and explanation generation with robust, reproducible examples.\n",
"\n",
"**What you'll practice**\n",
"- Defining rules with variables and predicates\n",
"- Loading facts in predicate form\n",
"- Running forward and backward chaining\n",
"- Generating human-readable explanations\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphBuilder\n",
"from semantica.reasoning import Reasoner, ExplanationGenerator\n",
"\n",
"builder = GraphBuilder()\n",
"reasoner = Reasoner()\n",
"explainer = ExplanationGenerator()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Rule Syntax\n",
"\n",
"Rules use predicate logic with variables prefixed by `?`.\n",
"\n",
"- Example: `IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)`\n",
"- Variables unify across predicates in the same rule\n",
"- Conclusions are added as new facts when conditions match\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"entities = [\n",
" {\"id\": \"alice\", \"type\": \"Person\", \"name\": \"Alice\"},\n",
" {\"id\": \"bob\", \"type\": \"Person\", \"name\": \"Bob\"},\n",
" {\"id\": \"charlie\", \"type\": \"Person\", \"name\": \"Charlie\"},\n",
" {\"id\": \"sf\", \"type\": \"Location\", \"name\": \"San Francisco\"},\n",
" {\"id\": \"california\", \"type\": \"Location\", \"name\": \"California\"}\n",
"]\n",
"\n",
"relationships = [\n",
" {\"source\": \"alice\", \"target\": \"bob\", \"type\": \"parent_of\"},\n",
" {\"source\": \"bob\", \"target\": \"charlie\", \"type\": \"parent_of\"},\n",
" {\"source\": \"sf\", \"target\": \"california\", \"type\": \"located_in\"},\n",
" {\"source\": \"alice\", \"target\": \"sf\", \"type\": \"lives_in\"}\n",
"]\n",
"\n",
"knowledge_graph = builder.build([{\"entities\": entities, \"relationships\": relationships}])\n",
"print(len(knowledge_graph.get(\"entities\", [])))\n",
"print(len(knowledge_graph.get(\"relationships\", [])))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rules = [\n",
" \"IF parent_of(?a, ?b) AND parent_of(?b, ?c) THEN grandparent_of(?a, ?c)\",\n",
" \"IF lives_in(?x, ?y) AND located_in(?y, ?z) THEN lives_in(?x, ?z)\"\n",
"]\n",
"for r in rules:\n",
" reasoner.add_rule(r)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for rel in relationships:\n",
" fact = f\"{rel['type']}({rel['source']}, {rel['target']})\"\n",
" reasoner.add_fact(fact)\n",
"\n",
"derived = reasoner.forward_chain()\n",
"print(len(derived))\n",
"for d in derived:\n",
" print(d.conclusion)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"goals = [\n",
" \"grandparent_of(alice, charlie)\",\n",
" \"lives_in(alice, california)\"\n",
"]\n",
"for g in goals:\n",
" proof = reasoner.backward_chain(g)\n",
" print(g)\n",
" print(bool(proof))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if derived:\n",
" exp = explainer.generate_explanation(derived[0])\n",
" print(exp.natural_language)\n",
"\n",
"goal = \"grandparent_of(alice, charlie)\"\n",
"proof = reasoner.backward_chain(goal)\n",
"if proof:\n",
" pexp = explainer.generate_explanation(proof)\n",
" print(pexp.natural_language)\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
}
@@ -10,7 +10,7 @@
"\n",
"## Overview\n",
"\n",
"Build an enterprise semantic layer: construct knowledge graph, generate ontology, create semantic layer, export RDF, and store in triple store.\n",
"Build an enterprise semantic layer: construct knowledge graph, generate ontology, create semantic layer, export RDF, and store in triplet store.\n",
"\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/concepts/)\n",
@@ -25,7 +25,16 @@
"pip install semantica[all]\n",
"```\n",
"\n",
"## Workflow: Build KG → Generate Ontology → Create Semantic Layer → Export RDF → Triple Store\n"
"## Workflow: Build KG → Generate Ontology → Create Semantic Layer → Export RDF \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install -qU semantica\n"
]
},
{
@@ -37,7 +46,7 @@
"from semantica.kg import GraphBuilder\n",
"from semantica.ontology import OntologyGenerator\n",
"from semantica.export import RDFExporter\n",
"from semantica.triple_store import TripleStore\n"
"from semantica.triplet_store import TripletStore\n"
]
},
{
@@ -155,24 +164,9 @@
"outputs": [],
"source": [
"exporter = RDFExporter()\n",
"exporter.export(knowledge_graph, ontology, \"semantic_layer.rdf\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Store in Triple Store\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"triple_store = TripleStore()\n",
"triple_store.store(knowledge_graph, ontology)\n"
"# Export Knowledge Graph\n",
"exporter.export(knowledge_graph, \"knowledge_graph.ttl\", format=\"turtle\")\n",
"print(\"Exported knowledge graph to knowledge_graph.ttl\")\n"
]
},
{
@@ -185,14 +179,42 @@
"- Knowledge Graph Built\n",
"- Ontology Generated\n",
"- Semantic Layer Created with Mappings\n",
"- RDF Export Completed\n",
"- Triple Store Storage Completed\n"
"- RDF Export Completed\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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,
@@ -6,35 +6,29 @@
"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/advanced/10_Temporal_Knowledge_Graphs.ipynb)\n",
"\n",
"# Temporal Knowledge Graphs\n",
"# Deep Dive: Temporal Knowledge Graphs\n",
"\n",
"## Overview\n",
"\n",
"This notebook demonstrates advanced temporal knowledge graph capabilities using TemporalGraphQuery, TemporalPatternDetector, TemporalVersionManager, and TemporalVisualizer.\n",
"This notebook provides a comprehensive deep dive into **Temporal Knowledge Graphs (TKGs)** using Semantica. Unlike static KGs, TKGs capture the evolution of facts, relationships, and entities over time. This capability is crucial for applications like:\n",
"\n",
"- **Corporate History Analysis**: Tracking mergers, acquisitions, and leadership changes.\n",
"- **Supply Chain Monitoring**: Tracing product movement and status changes.\n",
"- **Financial Fraud Detection**: Analyzing sequences of transactions.\n",
"\n",
"We will build a rich scenario modeling the history of a tech ecosystem, covering 40 years of evolution.\n",
"\n",
"### Key Components Covered\n",
"\n",
"1. **`GraphBuilder` (Temporal Mode)**: Constructing KGs with time-aware properties.\n",
"2. **`TemporalGraphQuery`**: Performing point-in-time, interval, and path queries.\n",
"3. **`TemporalPatternDetector`**: Identifying sequences and cyclic patterns.\n",
"4. **`TemporalVersionManager`**: Managing snapshots and comparing graph states.\n",
"5. **`TemporalVisualizer`**: Interactive timelines and evolution plots.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/kg/)\n",
"\n",
"### Learning Objectives\n",
"\n",
"- Use TemporalGraphQuery for time-aware queries\n",
"- Use TemporalPatternDetector to detect temporal patterns\n",
"- Use TemporalVersionManager for temporal versioning and snapshots\n",
"- Use TemporalVisualizer to visualize temporal data\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---\n",
"\n",
"## Workflow: Build Temporal KG → Time-Aware Queries → Pattern Detection → Version Management → Visualization\n"
"## Installation\n"
]
},
{
@@ -43,33 +37,123 @@
"metadata": {},
"outputs": [],
"source": [
"# !pip install semantica[all]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"from datetime import datetime\n",
"from semantica.kg import GraphBuilder, TemporalGraphQuery, TemporalPatternDetector, TemporalVersionManager\n",
"from semantica.visualization import TemporalVisualizer\n",
"from datetime import datetime\n",
"import plotly.offline as pyo\n",
"pyo.init_notebook_mode(connected=True)\n",
"\n",
"builder = GraphBuilder()\n",
"# Ensure consistent output for reproducibility\n",
"import random\n",
"random.seed(42)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1: Scenario Definition & Data Preparation\n",
"\n",
"We define a dataset representing the history of \"TechCorp\" and \"InnovateInc\", including their founders, products, and eventual merger.\n",
"\n",
"**Temporal Properties**:\n",
"- Entities have `founded`, `born`, `released` dates.\n",
"- Relationships have `timestamp` (point event) or `valid_from`/`valid_to` (intervals).\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 1. Define Entities with Temporal Metadata\n",
"entities = [\n",
" {\"id\": \"e1\", \"type\": \"Organization\", \"name\": \"Apple Inc.\", \"properties\": {\"founded\": \"1976\"}},\n",
" {\"id\": \"e2\", \"type\": \"Person\", \"name\": \"Steve Jobs\", \"properties\": {\"born\": \"1955\"}}\n",
" # Organizations\n",
" {\"id\": \"org_1\", \"type\": \"Organization\", \"name\": \"TechCorp\", \"properties\": {\"founded\": \"1980-01-01\", \"industry\": \"Hardware\"}},\n",
" {\"id\": \"org_2\", \"type\": \"Organization\", \"name\": \"InnovateInc\", \"properties\": {\"founded\": \"1995-06-15\", \"industry\": \"Software\"}},\n",
" {\"id\": \"org_3\", \"type\": \"Organization\", \"name\": \"FutureSystems\", \"properties\": {\"founded\": \"2010-03-10\", \"industry\": \"AI\"}},\n",
" \n",
" # People\n",
" {\"id\": \"per_1\", \"type\": \"Person\", \"name\": \"Alice Founder\", \"properties\": {\"born\": \"1955-05-20\"}},\n",
" {\"id\": \"per_2\", \"type\": \"Person\", \"name\": \"Bob Coder\", \"properties\": {\"born\": \"1970-08-12\"}},\n",
" {\"id\": \"per_3\", \"type\": \"Person\", \"name\": \"Charlie CEO\", \"properties\": {\"born\": \"1980-02-28\"}},\n",
" \n",
" # Products\n",
" {\"id\": \"prod_1\", \"type\": \"Product\", \"name\": \"HomePC\", \"properties\": {\"released\": \"1985-11-20\"}},\n",
" {\"id\": \"prod_2\", \"type\": \"Product\", \"name\": \"SoftOS\", \"properties\": {\"released\": \"1998-07-25\"}},\n",
" {\"id\": \"prod_3\", \"type\": \"Product\", \"name\": \"SmartAI\", \"properties\": {\"released\": \"2015-01-10\"}}\n",
"]\n",
"\n",
"# 2. Define Temporal Relationships\n",
"relationships = [\n",
" {\"source\": \"e2\", \"target\": \"e1\", \"type\": \"founded\", \"properties\": {\"timestamp\": \"1976-04-01\"}}\n",
" # Founding Events (Point in time)\n",
" {\"source\": \"per_1\", \"target\": \"org_1\", \"type\": \"founded\", \"timestamp\": \"1980-01-01\", \"properties\": {\"timestamp\": \"1980-01-01\"}},\n",
" {\"source\": \"per_2\", \"target\": \"org_2\", \"type\": \"founded\", \"timestamp\": \"1995-06-15\", \"properties\": {\"timestamp\": \"1995-06-15\"}},\n",
" \n",
" # Employment (Intervals)\n",
" {\"source\": \"per_1\", \"target\": \"org_1\", \"type\": \"ceo_of\", \"valid_from\": \"1980-01-01\", \"valid_to\": \"2000-01-01\", \"properties\": {\"role\": \"CEO\"}},\n",
" {\"source\": \"per_3\", \"target\": \"org_1\", \"type\": \"ceo_of\", \"valid_from\": \"2000-01-02\", \"valid_to\": \"2023-01-01\", \"properties\": {\"role\": \"CEO\"}},\n",
" {\"source\": \"per_2\", \"target\": \"org_2\", \"type\": \"cto_of\", \"valid_from\": \"1995-06-15\", \"valid_to\": \"2010-05-01\", \"properties\": {\"role\": \"CTO\"}},\n",
" \n",
" # Product Launches\n",
" {\"source\": \"org_1\", \"target\": \"prod_1\", \"type\": \"launched\", \"timestamp\": \"1985-11-20\", \"properties\": {\"timestamp\": \"1985-11-20\"}},\n",
" {\"source\": \"org_2\", \"target\": \"prod_2\", \"type\": \"launched\", \"timestamp\": \"1998-07-25\", \"properties\": {\"timestamp\": \"1998-07-25\"}},\n",
" {\"source\": \"org_3\", \"target\": \"prod_3\", \"type\": \"launched\", \"timestamp\": \"2015-01-10\", \"properties\": {\"timestamp\": \"2015-01-10\"}},\n",
" \n",
" # Corporate Actions\n",
" {\"source\": \"org_1\", \"target\": \"org_2\", \"type\": \"acquired\", \"timestamp\": \"2010-05-01\", \"properties\": {\"amount\": \"$5B\", \"timestamp\": \"2010-05-01\"}},\n",
" {\"source\": \"org_1\", \"target\": \"org_3\", \"type\": \"invested_in\", \"timestamp\": \"2012-08-15\", \"properties\": {\"amount\": \"$100M\", \"timestamp\": \"2012-08-15\"}}\n",
"]\n",
"\n",
"print(f\"Defined {len(entities)} entities and {len(relationships)} temporal relationships.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Building the Temporal Graph\n",
"\n",
"We use `GraphBuilder` with `enable_temporal=True`. This instructs the builder to index temporal properties like `timestamp`, `valid_from`, and `valid_to`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"builder = GraphBuilder(\n",
" enable_temporal=True,\n",
" temporal_granularity=\"day\" # Can be 'year', 'month', 'day', 'hour'\n",
")\n",
"\n",
"temporal_kg = builder.build(entities, relationships)\n",
"\n",
"print(f\"Built temporal knowledge graph with {len(entities)} entities\")\n"
"# The graph object now contains temporal indices\n",
"print(\"Graph built successfully.\")\n",
"print(f\"Nodes: {len(temporal_kg['entities'])}\")\n",
"print(f\"Edges: {len(temporal_kg['relationships'])}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Time-Aware Queries\n",
"## Step 3: Advanced Temporal Querying\n",
"\n",
"Query the graph at specific time points.\n"
"We use `TemporalGraphQuery` to ask time-sensitive questions."
]
},
{
@@ -78,25 +162,48 @@
"metadata": {},
"outputs": [],
"source": [
"temporal_query = TemporalGraphQuery()\n",
"query_engine = TemporalGraphQuery()\n",
"\n",
"query_result = temporal_query.query_time_range(\n",
"# 1. Point-in-Time Query\n",
"# \"Who was the CEO of TechCorp in 1990?\"\n",
"ceo_1990 = query_engine.query_at_time(\n",
" temporal_kg,\n",
" query=\"Find the CEO of TechCorp\",\n",
" at_time=\"1990-06-01\"\n",
")\n",
"print(\"CEO in 1990:\", [e['id'] for e in ceo_1990.get('entities', [])])\n",
"\n",
"# \"Who was the CEO of TechCorp in 2015?\"\n",
"ceo_2015 = query_engine.query_at_time(\n",
" temporal_kg,\n",
" query=\"Find the CEO of TechCorp\",\n",
" at_time=\"2015-06-01\"\n",
")\n",
"print(\"CEO in 2015:\", [e['id'] for e in ceo_2015.get('entities', [])])\n",
"\n",
"# 2. Temporal Path Finding\n",
"# \"How did Alice (Founder) connect to SmartAI (Product released in 2015)?\"\n",
"# This requires traversing through time: Alice -> founded TechCorp -> invested in FutureSystems -> launched SmartAI\n",
"paths = query_engine.find_temporal_paths(\n",
" graph=temporal_kg,\n",
" query=\"Find entities founded in 1976\",\n",
" start_time=\"1976-01-01\",\n",
" end_time=\"1976-12-31\"\n",
" source=\"per_1\", # Alice\n",
" target=\"prod_3\", # SmartAI\n",
" start_time=\"1980-01-01\",\n",
" end_time=\"2020-01-01\"\n",
")\n",
"\n",
"print(f\"Time-aware query returned {len(query_result.get('entities', []))} entities\")\n"
"print(f\"\\nFound {len(paths)} temporal paths from Alice to SmartAI.\")\n",
"for i, path in enumerate(paths):\n",
" print(f\"Path {i+1}: {path}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Temporal Pattern Detection\n",
"## Step 4: Graph Evolution Analysis\n",
"\n",
"Detect temporal patterns in the graph.\n"
"We can analyze how the graph properties change over time using `analyze_evolution`."
]
},
{
@@ -105,24 +212,56 @@
"metadata": {},
"outputs": [],
"source": [
"pattern_detector = TemporalPatternDetector()\n",
"evolution_stats = query_engine.analyze_evolution(\n",
" temporal_kg,\n",
" start_time=\"1980-01-01\",\n",
" end_time=\"2025-01-01\",\n",
" metrics=[\"count\", \"diversity\", \"stability\"]\n",
")\n",
"\n",
"patterns = pattern_detector.detect_temporal_patterns(\n",
"print(\"\\nEvolution Statistics (1980-2025):\")\n",
"print(f\"Total Relationships: {evolution_stats.get('count', 'N/A')}\")\n",
"print(f\"Relationship Diversity: {evolution_stats.get('diversity', 'N/A')}\")\n",
"print(f\"Graph Stability: {evolution_stats.get('stability', 'N/A')}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Temporal Pattern Detection\n",
"\n",
"We use `TemporalPatternDetector` to automatically find recurring structures, such as sequences (A -> B -> C) or cycles."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"detector = TemporalPatternDetector()\n",
"\n",
"# Detect sequential patterns (e.g., Founded -> Launched -> Acquired)\n",
"sequences = detector.detect_temporal_patterns(\n",
" temporal_kg,\n",
" pattern_type=\"sequence\",\n",
" min_frequency=1\n",
")\n",
"\n",
"print(f\"Detected {len(patterns)} temporal patterns\")\n"
"print(f\"\\nDetected {len(sequences)} sequential patterns.\")\n",
"for seq in sequences[:3]: # Show top 3\n",
" print(f\"Pattern: {seq.get('pattern')}\")\n",
" print(f\"Support: {seq.get('support')}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Version Management\n",
"## Step 6: Version Management & Comparisons\n",
"\n",
"Manage temporal versions and snapshots.\n"
"In real-world scenarios, KGs are updated in batches. `TemporalVersionManager` handles these versions."
]
},
{
@@ -133,19 +272,25 @@
"source": [
"version_manager = TemporalVersionManager()\n",
"\n",
"snapshot = version_manager.create_snapshot(temporal_kg, timestamp=datetime.now())\n",
"# Create explicit versions\n",
"v1_1990 = version_manager.create_version(temporal_kg, timestamp=\"1990-01-01\", version_label=\"v1.0 (Early Days)\")\n",
"v2_2010 = version_manager.create_version(temporal_kg, timestamp=\"2010-01-01\", version_label=\"v2.0 (Post-Merger)\")\n",
"\n",
"print(f\"Created temporal snapshot at {snapshot.get('timestamp', 'N/A')}\")\n",
"print(f\"Snapshot contains {len(snapshot.get('entities', []))} entities\")\n"
"# Compare versions\n",
"diff = version_manager.compare_versions(v1_1990, v2_2010)\n",
"\n",
"print(f\"\\nComparing {v1_1990['label']} vs {v2_2010['label']}:\")\n",
"print(f\"New Entities: {diff.get('entities_added', 0)}\")\n",
"print(f\"New Relationships: {diff.get('relationships_added', 0)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Temporal Visualization\n",
"## Step 7: Visualizing the Timeline\n",
"\n",
"Visualize temporal data.\n"
"Finally, `TemporalVisualizer` brings the data to life. We will create an interactive timeline and a snapshot comparison."
]
},
{
@@ -154,9 +299,46 @@
"metadata": {},
"outputs": [],
"source": [
"temporal_visualizer = TemporalVisualizer()\n",
"visualizer = TemporalVisualizer()\n",
"\n",
"visualization = temporal_visualizer.visualize_timeline(temporal_kg, output=\"interactive\")\n"
"# 1. Interactive Timeline\n",
"# Prepare events for visualization (extract from KG)\n",
"def extract_events(graph):\n",
" events = []\n",
" for rel in graph['relationships']:\n",
" # Point events\n",
" if rel.get('timestamp'):\n",
" events.append({\n",
" 'timestamp': rel['timestamp'],\n",
" 'type': rel['type'],\n",
" 'label': f\"{rel['source']} -> {rel['target']}\",\n",
" 'entity': rel['source']\n",
" })\n",
" # Interval events (start)\n",
" if rel.get('valid_from'):\n",
" events.append({\n",
" 'timestamp': rel['valid_from'],\n",
" 'type': f\"{rel['type']} (start)\",\n",
" 'label': f\"{rel['source']} -> {rel['target']}\",\n",
" 'entity': rel['source']\n",
" })\n",
" return {'events': events}\n",
"\n",
"temporal_data = extract_events(temporal_kg)\n",
"timeline_fig = visualizer.visualize_timeline(temporal_data, output=\"interactive\")\n",
"# In a notebook, this would render a Plotly figure. \n",
"timeline_fig.show()\n",
"\n",
"# 2. Version History Visualization\n",
"history = [\n",
" {\"version\": \"v1.0\", \"timestamp\": \"1990-01-01\", \"changes\": \"Founding Era\"},\n",
" {\"version\": \"v2.0\", \"timestamp\": \"2010-01-01\", \"changes\": \"Expansion Era\"},\n",
" {\"version\": \"v3.0\", \"timestamp\": \"2020-01-01\", \"changes\": \"AI Era\"}\n",
"]\n",
"history_fig = visualizer.visualize_version_history(history, output=\"interactive\")\n",
"history_fig.show()\n",
"\n",
"print(\"Visualizations generated (render requires Jupyter environment).\")"
]
},
{
@@ -165,66 +347,38 @@
"source": [
"## Summary\n",
"\n",
"You've learned advanced temporal knowledge graph capabilities:\n",
"In this deep dive, we:\n",
"1. **modeled** a complex corporate history with temporal metadata.\n",
"2. **Built** a time-aware knowledge graph using `GraphBuilder`.\n",
"3. **Queried** specific time slices and intervals to reconstruct history.\n",
"4. **Traced** temporal paths to understand indirect connections.\n",
"5. **Analyzed** the graph's evolution metrics.\n",
"6. **Managed** versions and visualized the timeline.\n",
"7. **Visualized** the data with `TemporalVisualizer`.\n",
"\n",
"- **TemporalGraphQuery**: Time-aware graph querying\n",
"- **TemporalPatternDetector**: Temporal pattern detection\n",
"- **TemporalVersionManager**: Temporal versioning and snapshots\n",
"- **TemporalVisualizer**: Temporal data visualization\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Snapshot Comparison and Version History\n",
"\n",
"Compare graph snapshots across time and visualize version history."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create multiple versions\n",
"version_manager = TemporalVersionManager()\n",
"version_2020 = version_manager.create_version(temporal_kg, timestamp=\"2020-01-01\", version_label=\"v2020\")\n",
"# Simulate changes for 2023\n",
"temporal_kg_updated = {\n",
" \"entities\": temporal_kg.get(\"entities\", []),\n",
" \"relationships\": temporal_kg.get(\"relationships\", []) + [\n",
" {\"source\": \"e1\", \"target\": \"e2\", \"type\": \"collaborated_with\", \"valid_from\": \"2023-01-01\"}\n",
" ]\n",
"}\n",
"version_2023 = version_manager.create_version(temporal_kg_updated, timestamp=\"2023-01-01\", version_label=\"v2023\")\n",
"\n",
"# Build snapshots dict for comparison\n",
"snapshots = {\n",
" version_2020[\"timestamp\"]: version_2020,\n",
" version_2023[\"timestamp\"]: version_2023\n",
"}\n",
"\n",
"# Visualize snapshot comparison\n",
"fig_snapshots = temporal_visualizer.visualize_snapshot_comparison(snapshots, output=\"interactive\")\n",
"\n",
"# Build version history list\n",
"version_history = [\n",
" {\"version\": version_2020.get(\"label\", \"v2020\"), \"timestamp\": version_2020.get(\"timestamp\"), \"changes\": f\"Entities: {len(version_2020.get('entities', []))}, Relationships: {len(version_2020.get('relationships', []))}\"},\n",
" {\"version\": version_2023.get(\"label\", \"v2023\"), \"timestamp\": version_2023.get(\"timestamp\"), \"changes\": f\"Entities: {len(version_2023.get('entities', []))}, Relationships: {len(version_2023.get('relationships', []))}\"}\n",
"]\n",
"\n",
"# Visualize version history\n",
"fig_versions = temporal_visualizer.visualize_version_history(version_history, output=\"interactive\")\n"
"This workflow forms the backbone of temporal intelligence applications in Semantica."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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
"nbformat_minor": 4
}
@@ -4,222 +4,497 @@
"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/advanced/11_Advanced_Context_Engineering.ipynb)\n",
"# Advanced Context Engineering: The Agent's Brain\n",
"\n",
"# Advanced Context Engineering\n",
"Welcome to the **Master Class** on Semantica Context Engineering. This notebook demonstrates how to build a production-grade memory system for your AI agents.\n",
"\n",
"## Overview\n",
"Unlike simple chatbots that forget everything after a session, a **Context-Aware Agent** needs:\n",
"* **Long-term Memory**: To recall facts from weeks ago.\n",
"* **Structured Knowledge**: To understand how entities (People, Projects, Topics) are connected.\n",
"* **Hybrid Retrieval**: To combine fuzzy text search with precise graph traversal.\n",
"\n",
"This notebook covers advanced topics in context engineering using Semantica. We will explore custom memory management strategies, tuning hybrid retrieval, and extending the system with custom graph builders.\n",
"## Learning Objectives\n",
"\n",
"### Learning Objectives\n",
"In this walkthrough, we will:\n",
"1. **Initialize Production Stores**: Replace toy examples with real **Vector Stores** (FAISS) and **Graph Stores** (Neo4j).\n",
"2. **Build the Agent Context**: Configure the central brain that orchestrates memory.\n",
"3. **Ingest Knowledge**: Store complex documents and auto-extract entities.\n",
"4. **Inject Relationships**: Manually teach the agent about connections in the world.\n",
"5. **Perform GraphRAG**: Execute advanced queries that \"hop\" through the knowledge graph to find answers standard RAG misses.\n",
"6. **Manage Lifecycle**: Learn to prune old memories and keep the system healthy.\n",
"\n",
"- **Custom Memory Pruning**: Implement importance-based pruning instead of FIFO.\n",
"- **Hybrid Retrieval Tuning**: Optimize weights for vector, graph, and keyword search.\n",
"- **Custom Extensions**: Register custom graph building methods.\n",
"- **Performance Optimization**: Balance token limits and retrieval latency.\n",
"\n",
"---\n",
"\n",
"## 1. Setup\n",
"\n",
"We'll start by setting up a mock vector store and importing necessary components."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from typing import List, Dict, Any, Optional\n",
"from semantica.context import AgentMemory, AgentContext, ContextGraph, ContextRetriever, VectorStore\n",
"from semantica.context import registry\n",
"\n",
"# Mock Vector Store (same as in introduction)\n",
"class MockVectorStore(VectorStore):\n",
" def __init__(self):\n",
" self.items = {}\n",
" self.counter = 0\n",
" def add(self, texts, metadata=None, **kwargs):\n",
" ids = []\n",
" for i, text in enumerate(texts):\n",
" id_ = f\"id_{self.counter}\"\n",
" self.items[id_] = {\"text\": text, \"metadata\": metadata[i] if metadata else {}}\n",
" ids.append(id_)\n",
" self.counter += 1\n",
" return ids\n",
" def search(self, query, limit=5, **kwargs):\n",
" return [{\n",
" \"id\": k, \"content\": v[\"text\"], \"score\": 0.85, \"metadata\": v[\"metadata\"]\n",
" } for k, v in list(self.items.items())[:limit]]\n",
" def delete(self, ids, **kwargs):\n",
" return True\n",
"\n",
"vs = MockVectorStore()\n",
"kg = ContextGraph()"
"---"
]
},
{
"cell_type": "markdown",
"id": "2cf97cbc",
"metadata": {},
"source": [
"## 2. Custom Memory Pruning Strategy\n",
"## 1. Installation\n",
"\n",
"By default, `AgentMemory` uses a FIFO (First-In-First-Out) strategy combined with a token limit to prune short-term memory. However, you might want to keep \"important\" memories longer regardless of their age.\n",
"To get started, simply install the package:\n",
"\n",
"Let's subclass `AgentMemory` to implement an importance-based pruning strategy."
"```bash\n",
"pip install semantica\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "88491af5",
"metadata": {},
"outputs": [],
"source": [
"class ImportanceAwareMemory(AgentMemory):\n",
" def _prune_short_term_memory(self):\n",
" \"\"\"\n",
" Custom pruning: Always keep items marked as 'important' in metadata,\n",
" then prune others based on token limits.\n",
" \"\"\"\n",
" if not self.short_term_memory:\n",
" return\n",
"!pip install -qU semantica "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d6401d91",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"import os\n",
"import time\n",
"from typing import Any, List, Dict, Optional\n",
"\n",
" # Separate important items\n",
" important_items = [item for item in self.short_term_memory if item.metadata.get(\"important\")]\n",
" other_items = [item for item in self.short_term_memory if not item.metadata.get(\"important\")]\n",
" \n",
" # Calculate tokens used by important items\n",
" important_tokens = sum(self._count_tokens(item.content) for item in important_items)\n",
" \n",
" # Calculate remaining budget\n",
" remaining_tokens = max(0, self.token_limit - important_tokens)\n",
" \n",
" # Prune other items to fit remaining budget\n",
" kept_others = []\n",
" current_tokens = 0\n",
" \n",
" # Iterate in reverse (newest first) to keep recent items\n",
" for item in reversed(other_items):\n",
" item_tokens = self._count_tokens(item.content)\n",
" if current_tokens + item_tokens <= remaining_tokens:\n",
" kept_others.insert(0, item)\n",
" current_tokens += item_tokens\n",
" else:\n",
" break # Stop once we hit the limit\n",
" \n",
" # Reconstruct memory: Important items + kept recent items\n",
" # Sort by timestamp to maintain order\n",
" all_kept = sorted(important_items + kept_others, key=lambda x: x.timestamp)\n",
" self.short_term_memory = all_kept\n",
"# Add project root to path to import semantica\n",
"sys.path.append(os.path.abspath(os.path.join(os.getcwd(), \"../../\")))\n",
"\n",
"# Test the custom memory\n",
"memory = ImportanceAwareMemory(vector_store=vs, token_limit=100)\n",
"# Core Imports\n",
"from semantica.context import AgentContext, ContextGraph, AgentMemory\n",
"from semantica.vector_store import VectorStore\n",
"from semantica.graph_store import GraphStore\n",
"\n",
"# Add an old important memory\n",
"memory.store(\"IMPORTANT: User's name is Alice\", metadata={\"important\": True})\n",
"\n",
"# Fill with filler memories\n",
"for i in range(20):\n",
" memory.store(f\"Filler memory {i} \" * 5) # Consumes tokens\n",
"\n",
"print(f\"Short-term items: {len(memory.short_term_memory)}\")\n",
"print(\"First item (should be the important one):\", memory.short_term_memory[0].content)"
"print(\"Libraries imported successfully.\")"
]
},
{
"cell_type": "markdown",
"id": "7e263672",
"metadata": {},
"source": [
"## 3. Tuning Hybrid Retrieval\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "dbad46dd",
"metadata": {},
"source": [
"## 2. Initialize Storage Backends\n",
"\n",
"Hybrid retrieval combines scores from vector search and graph traversal. You can tune the `hybrid_alpha` parameter to weight these components.\n",
"We will now connect to our persistent storage layers. Semantica abstracts these behind unified interfaces, so you can swap backends (e.g., switch from FAISS to Weaviate) without changing your application logic.\n",
"\n",
"- `hybrid_alpha = 0.0`: Pure Vector Search\n",
"- `hybrid_alpha = 1.0`: Pure Graph Search\n",
"- `hybrid_alpha = 0.5`: Balanced (Default)\n",
"\n",
"Additionally, `max_expansion_hops` controls how far we traverse the graph from retrieved nodes."
"### Vector Store (The Library)\n",
"Holds the *content* of memories and documents, indexed by semantic meaning."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "812158a5",
"metadata": {},
"outputs": [],
"source": [
"# Populate graph with some structure\n",
"kg.add_node(\"python\", \"concept\", \"Python\")\n",
"kg.add_node(\"ml\", \"concept\", \"Machine Learning\")\n",
"kg.add_edge(\"python\", \"ml\", \"used_for\")\n",
"try:\n",
" # Initialize FAISS Vector Store\n",
" # You can also use: backend=\"weaviate\", backend=\"qdrant\", etc.\n",
" vs = VectorStore(backend=\"faiss\", dimension=768)\n",
" print(\"VectorStore initialized (Backend: FAISS)\")\n",
"except ImportError:\n",
" print(\"FAISS not installed. Using in-memory fallback (not persistent).\")\n",
" vs = VectorStore(backend=\"inmemory\", dimension=768)\n",
"except Exception as e:\n",
" print(f\"VectorStore Error: {e}\")\n",
" vs = None"
]
},
{
"cell_type": "markdown",
"id": "8933cfef",
"metadata": {},
"source": [
"### Graph Store (The Map)\n",
"Holds the *connections* between entities. This is crucial for reasoning."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7c2aa896",
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" # Initialize Neo4j Graph Store\n",
" # Ensure your Docker container is running!\n",
" gs = GraphStore(\n",
" backend=\"neo4j\",\n",
" uri=\"bolt://localhost:7687\",\n",
" user=\"neo4j\",\n",
" password=\"password\"\n",
" )\n",
" \n",
" # Test connection\n",
" if gs.connect():\n",
" print(\"GraphStore connected (Backend: Neo4j)\")\n",
" else:\n",
" raise ConnectionError(\"Could not connect to Neo4j\")\n",
"\n",
"retriever = ContextRetriever(\n",
" memory_store=memory,\n",
" knowledge_graph=kg,\n",
" vector_store=vs,\n",
" hybrid_alpha=0.7, # Favor graph connections\n",
" max_expansion_hops=2 # Traverse deeper\n",
"except Exception as e:\n",
" print(f\"GraphStore Connection Failed: {e}\")\n",
" print(\" Switching to in-memory ContextGraph (Non-persistent fallback)\")\n",
" gs = ContextGraph() # Fallback implementation"
]
},
{
"cell_type": "markdown",
"id": "e17b7765",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"id": "cebbe65f",
"metadata": {},
"source": [
"## 3. The Agent Context\n",
"\n",
"The `AgentContext` is the high-level orchestrator. It sits on top of the Vector and Graph stores and manages the flow of information.\n",
"\n",
"**Configuration for GraphRAG:**\n",
"* `use_graph_expansion=True`: When retrieving, don't just look at the doc, look at its neighbors.\n",
"* `max_expansion_hops=2`: How far to traverse? (e.g., A -> B -> C).\n",
"* `hybrid_alpha=0.6`: Weighting. 0.0 is pure Vector, 1.0 is pure Graph. 0.6 favors graph slightly."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3b2eff6",
"metadata": {},
"outputs": [],
"source": [
"if vs:\n",
" context = AgentContext(\n",
" vector_store=vs,\n",
" knowledge_graph=gs,\n",
" retention_days=90, # Remember things for 3 months\n",
" use_graph_expansion=True, # Enable GraphRAG\n",
" max_expansion_hops=2, # 2-Hop reasoning\n",
" hybrid_alpha=0.6 # Balanced retrieval\n",
" )\n",
" print(\"Agent Context is online and ready.\")\n",
"else:\n",
" print(\"Cannot proceed without VectorStore.\")"
]
},
{
"cell_type": "markdown",
"id": "2db1ef53",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"id": "b7efb347",
"metadata": {},
"source": [
"## 4. Ingestion: Teaching the Agent\n",
"\n",
"We can store different types of information. The system is smart enough to distinguish between a conversational memory and a factual document.\n",
"\n",
"### A. Episodic Memory (Conversations)\n",
"These are raw logs of interactions. They provide the \"personal\" history."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "71adf433",
"metadata": {},
"outputs": [],
"source": [
"user_id = \"user_123\"\n",
"session_id = \"session_alpha\"\n",
"\n",
"# Store a user preference\n",
"mem_id = context.store(\n",
" content=\"I am working on a new project called 'Project Apollo' which uses Python and React.\",\n",
" conversation_id=session_id,\n",
" user_id=user_id,\n",
" metadata={\"type\": \"user_preference\"}\n",
")\n",
"print(f\"Memory Stored: {mem_id}\")"
]
},
{
"cell_type": "markdown",
"id": "00179ec6",
"metadata": {},
"source": [
"### B. Semantic Knowledge (Documents)\n",
"When we feed documents, we want to **extract entities** and **link them**. \n",
"\n",
"*(Note: In a real setup, this uses an LLM to parse entities. Here we use the context module's native extraction capabilities.)*"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3a98ca53",
"metadata": {},
"outputs": [],
"source": [
"documents = [\n",
" {\n",
" \"content\": \"Project Apollo is a next-gen web framework designed for high scalability.\",\n",
" \"metadata\": {\"source\": \"internal_wiki\", \"category\": \"projects\"}\n",
" },\n",
" {\n",
" \"content\": \"Python 3.12 introduces significant performance improvements for async workloads.\",\n",
" \"metadata\": {\"source\": \"tech_news\", \"category\": \"languages\"}\n",
" }\n",
"]\n",
"\n",
"# Store documents and trigger graph build\n",
"stats = context.store(\n",
" documents,\n",
" extract_entities=True, # Extract entities from text\n",
" extract_relationships=True, # Infer relationships\n",
" link_entities=True # Connect to existing graph nodes\n",
")\n",
"\n",
"results = retriever.retrieve(\"Python\")\n",
"for res in results:\n",
" print(f\"Source: {res.source}, Score: {res.score:.2f}\")"
"print(\"Knowledge Ingestion Stats:\", stats)"
]
},
{
"cell_type": "markdown",
"id": "912bb201",
"metadata": {},
"source": [
"## 4. Extending with Custom Methods\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "c2632192",
"metadata": {},
"source": [
"## 5. Graph Engineering: Manual Injection\n",
"\n",
"Semantica's registry system allows you to plug in custom logic. Let's register a custom graph builder that creates a star graph topology."
"Sometimes automatic extraction isn't enough. You want to enforce specific business logic or relationships. We can use `build_graph` to manually inject nodes and edges.\n",
"\n",
"**We will define:**\n",
"* **User** (Alice)\n",
"* **Role** (Admin)\n",
"* **Project** (Apollo)\n",
"* **Relationship**: Alice *MANAGES* Project Apollo."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "970b605c",
"metadata": {},
"outputs": [],
"source": [
"def star_graph_builder(center_entity, satellites, **kwargs):\n",
" \"\"\"\n",
" Builds a star graph where all satellites connect to the center.\n",
" \"\"\"\n",
" nodes = []\n",
" edges = []\n",
"# 1. Define Nodes\n",
"entities = [\n",
" {\"id\": \"alice\", \"type\": \"PERSON\", \"text\": \"Alice\", \"properties\": {\"role\": \"Admin\"}},\n",
" {\"id\": \"project_apollo\", \"type\": \"PROJECT\", \"text\": \"Project Apollo\"},\n",
" {\"id\": \"python\", \"type\": \"TECH\", \"text\": \"Python\"},\n",
" {\"id\": \"react\", \"type\": \"TECH\", \"text\": \"React\"}\n",
"]\n",
"\n",
"# 2. Define Edges (The Knowledge)\n",
"relationships = [\n",
" {\"source\": \"alice\", \"target\": \"project_apollo\", \"type\": \"MANAGES\", \"weight\": 1.0},\n",
" {\"source\": \"project_apollo\", \"target\": \"python\", \"type\": \"USES_TECH\", \"weight\": 1.0},\n",
" {\"source\": \"project_apollo\", \"target\": \"react\", \"type\": \"USES_TECH\", \"weight\": 1.0}\n",
"]\n",
"\n",
"# 3. Inject into Graph\n",
"graph_stats = context.build_graph(\n",
" entities=entities,\n",
" relationships=relationships\n",
")\n",
"\n",
"print(\"Manual Graph Build Complete:\", graph_stats)"
]
},
{
"cell_type": "markdown",
"id": "bf04b4a0",
"metadata": {},
"source": [
"### Visualizing the Graph Logic\n",
"Let's query the graph directly to see what \"Project Apollo\" looks like."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dc61c324",
"metadata": {},
"outputs": [],
"source": [
"# Helper to print graph neighbors\n",
"def inspect_node(node_id):\n",
" if hasattr(gs, \"get_neighbors\"):\n",
" neighbors = gs.get_neighbors(node_id)\n",
" print(f\"\\nNeighbors of '{node_id}':\")\n",
" for n in neighbors:\n",
" # Handle different return formats between stores\n",
" rel_type = n.get('relationship') or n.get('type') or 'linked'\n",
" target = n.get('id') or n.get('node_id')\n",
" print(f\" └── [{rel_type}] ──> {target}\")\n",
" else:\n",
" print(\"Graph store does not support neighbor inspection.\")\n",
"\n",
"inspect_node(\"project_apollo\")"
]
},
{
"cell_type": "markdown",
"id": "a163434b",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"id": "51261f5f",
"metadata": {},
"source": [
"## 6. Hybrid Retrieval (GraphRAG)\n",
"\n",
"Now for the magic. We ask a question that requires connecting the dots.\n",
"\n",
"**Query**: *\"Who is responsible for the Python web framework project?\"*\n",
"\n",
"**Logic Flow:**\n",
"1. **Vector Search**: Finds \"Project Apollo\" (described as web framework).\n",
"2. **Graph Expansion**: Looks at \"Project Apollo\" in the graph.\n",
"3. **Discovery**: Sees `(Alice)-[MANAGES]->(Project Apollo)`.\n",
"4. **Result**: Returns Alice, even though her name wasn't in the project description text!"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "69381e8c",
"metadata": {},
"outputs": [],
"source": [
"query = \"Who is responsible for the Python web framework project?\"\n",
"print(f\"Asking: '{query}'...\\n\")\n",
"\n",
"results = context.retrieve(\n",
" query,\n",
" max_results=3,\n",
" use_graph=True, # Vital for finding Alice\n",
" expand_graph=True, # Hop to neighbors\n",
" include_entities=True # Return structured entity data\n",
")\n",
"\n",
"print(f\"Retrieved {len(results)} context items:\\n\")\n",
"\n",
"for i, res in enumerate(results, 1):\n",
" print(f\"{i}. [Score: {res['score']:.2f}] {res['content'][:120]}...\")\n",
" \n",
" # Center node\n",
" nodes.append({\"id\": \"center\", \"label\": center_entity, \"type\": \"CENTER\"})\n",
" \n",
" for i, sat in enumerate(satellites):\n",
" sat_id = f\"sat_{i}\"\n",
" nodes.append({\"id\": sat_id, \"label\": sat, \"type\": \"SATELLITE\"})\n",
" edges.append({\"source\": \"center\", \"target\": sat_id, \"relation\": \"connects_to\"})\n",
" \n",
" return {\"nodes\": nodes, \"edges\": edges}\n",
" # Did we find graph connections?\n",
" if 'related_entities' in res and res['related_entities']:\n",
" print(\" Graph Insights:\")\n",
" for ent in res['related_entities'][:3]:\n",
" print(f\" - {ent.get('text', 'Entity')} ({ent.get('type', 'Unknown')})\")\n",
" print(\"\")"
]
},
{
"cell_type": "markdown",
"id": "c21fbb00",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"id": "c18870af",
"metadata": {},
"source": [
"## 7. Lifecycle Management\n",
"\n",
"# Register the method\n",
"registry.method_registry.register(\"graph\", \"star_builder\", star_graph_builder)\n",
"A production system needs maintenance. You can query history, check health, and prune old data.\n",
"\n",
"# Verify registration\n",
"print(\"Available graph methods:\", registry.method_registry.list_all(\"graph\"))\n",
"### Conversation History"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0574b1b7",
"metadata": {},
"outputs": [],
"source": [
"# Get recent chat history for context window\n",
"history = context.conversation(\n",
" conversation_id=session_id,\n",
" limit=5\n",
")\n",
"\n",
"# Use it (conceptual - typically used via build_context_graph wrapper)\n",
"graph_data = star_graph_builder(\"Central Hub\", [\"Spoke 1\", \"Spoke 2\"])\n",
"print(f\"Created graph with {len(graph_data['nodes'])} nodes and {len(graph_data['edges'])} edges.\")"
"print(f\"Chat History for {session_id}:\")\n",
"for msg in history:\n",
" print(f\" - {msg['content']}\")"
]
},
{
"cell_type": "markdown",
"id": "a40483fc",
"metadata": {},
"source": [
"### System Health & Stats"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cd472495",
"metadata": {},
"outputs": [],
"source": [
"stats = context.stats()\n",
"print(\"System Vital Signs:\")\n",
"print(f\" - Total Memories: {stats.get('total_items', 0)}\")\n",
"print(f\" - Graph Nodes: {stats.get('graph_stats', {}).get('node_count', 'N/A')}\")\n",
"print(f\" - Graph Edges: {stats.get('graph_stats', {}).get('edge_count', 'N/A')}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Best Practices for Production\n",
"## Summary\n",
"\n",
"1. **Token Limits**: Align `token_limit` with your LLM's context window minus the prompt template size.\n",
"2. **Vector Store**: Use a production-grade vector store (e.g., Pinecone, Weaviate, Qdrant) instead of the mock store.\n",
"3. **Asynchronous Operations**: For high-throughput systems, consider wrapping storage operations in async tasks (though the core logic is synchronous for simplicity).\n",
"4. **Entity Resolution**: Implement a robust `EntityLinker` strategy to prevent graph fragmentation (e.g., \"Alice\" vs \"Alice S.\")."
"You have successfully built a **Context-Aware Agent** using Semantica's production modules.\n",
"\n",
"**Key Achievements:**\n",
"1. **Persistence**: Swapped in FAISS and Neo4j for real-world storage.\n",
"2. **GraphRAG**: Demonstrated how graph relationships improve retrieval accuracy.\n",
"3. **Entity Injection**: Manually taught the agent about business relationships.\n",
"\n",
"This architecture is ready to scale to millions of vectors and graph nodes."
]
}
],
@@ -1,286 +1,311 @@
{
"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/advanced/12_Unstructured_to_Ontology.ipynb)\n",
"\n",
"# Advanced: Unstructured Text to Ontology\n",
"\n",
"Welcome to the advanced guide on extracting structured ontologies from unstructured text. This notebook explores two powerful paradigms available in Semantica:\n",
"\n",
"1. **Classical NLP Pipeline**: Using Named Entity Recognition (NER) and Relation Extraction.\n",
"2. **Generative AI Pipeline**: Using Large Language Models (LLMs) for direct conceptual modeling.\n",
"\n",
"We will compare both approaches, visualize the results, and validate the generated ontologies.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/ontology/)\n",
"\n",
"## Setup and Installation\n",
"\n",
"Ensure you have Semantica installed with all dependencies."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# !pip install semantica[all]\n",
"\n",
"from semantica.utils.logging import get_logger\n",
"\n",
"logger = get_logger(\"unstructured_guide\")\n",
"print(\"Environment setup complete.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## The Input Text\n",
"\n",
"We will use a rich paragraph of text describing a technology company to test both extraction methods."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"text_corpus = \"\"\"\n",
"QuantumDynamics is a leading AI research lab founded by Dr. Elena Rostova in 2018. \n",
"The lab is headquartered in Zurich, Switzerland, and focuses on quantum computing algorithms. \n",
"Dr. Rostova serves as the Chief Scientist. \n",
"The lab has released products like the Q-1 Processor and the NeuralBridge SDK. \n",
"QuantumDynamics collaborates with major universities such as MIT and ETH Zurich.\n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Approach 1: The Classical NLP Pipeline\n",
"\n",
"This approach builds the ontology from the bottom up:\n",
"1. **Extract Entities**: Identify nouns/proper nouns (e.g., \"QuantumDynamics\", \"Zurich\").\n",
"2. **Extract Relations**: Identify verbs connecting them (e.g., \"headquartered in\").\n",
"3. **Generate Ontology**: Map these triplets to Classes and Properties.\n",
"\n",
"**Pros**: Deterministic, traceable, works offline.\n",
"**Cons**: Dependent on the underlying NLP model's vocabulary and flexibility."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.semantic_extract import NERExtractor, RelationExtractor\n",
"from semantica.ontology import OntologyGenerator, OntologyOptimizer\n",
"\n",
"# 1. Initialize Extractors\n",
"ner = NERExtractor()\n",
"re = RelationExtractor()\n",
"\n",
"# 2. Extract Entities\n",
"print(\"Extracting entities...\")\n",
"entities = ner.extract(text_corpus)\n",
"print(f\"Found {len(entities)} entities: {[e['text'] for e in entities]}\")\n",
"\n",
"# 3. Extract Relationships\n",
"print(\"Extracting relationships...\")\n",
"relationships = re.extract(text_corpus, entities)\n",
"for r in relationships:\n",
" print(f\" - {r['source']} -> {r['type']} -> {r['target']}\")\n",
"\n",
"# 4. Generate Structure\n",
"generator = OntologyGenerator()\n",
"nlp_ontology = generator.generate(entities, relationships, name=\"QuantumOntologyNLP\")\n",
"\n",
"# 5. Optimize (Clean up)\n",
"optimizer = OntologyOptimizer()\n",
"nlp_ontology = optimizer.optimize_ontology(nlp_ontology, remove_redundancy=True)\n",
"\n",
"print(f\"\\nGenerated NLP Ontology with {len(nlp_ontology['classes'])} classes and {len(nlp_ontology['properties'])} properties.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Approach 2: The Generative AI Pipeline (LLM)\n",
"\n",
"This approach uses a Large Language Model to \"read\" the text and directly propose a schema.\n",
"\n",
"**Pros**: Context-aware, can handle ambiguity, generates human-like class names.\n",
"**Cons**: Non-deterministic, requires API access.\n",
"\n",
"*Note: This step requires a configured LLM provider (e.g., OpenAI).* "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ontology import LLMOntologyGenerator\n",
"\n",
"try:\n",
" # Initialize LLM Generator (ensure OPENAI_API_KEY is set in env)\n",
" llm_gen = LLMOntologyGenerator(provider=\"openai\", model=\"gpt-4\")\n",
" \n",
" print(\"Generating ontology with LLM...\")\n",
" llm_ontology = llm_gen.generate_ontology_from_text(\n",
" text=text_corpus,\n",
" name=\"QuantumOntologyLLM\"\n",
" )\n",
" \n",
" print(f\"Generated LLM Ontology with {len(llm_ontology['classes'])} classes and {len(llm_ontology['properties'])} properties.\")\n",
" print(\"Classes detected:\", [c['name'] for c in llm_ontology['classes']])\n",
" \n",
"except Exception as e:\n",
" print(f\"Skipping LLM generation: {e}\")\n",
" llm_ontology = None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Comparing Results with Visualization\n",
"\n",
"Let's visualize both ontologies side-by-side (if available) to see the difference in structure. The NLP model tends to be more literal, while the LLM model tends to be more conceptual."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.visualization import OntologyVisualizer\n",
"\n",
"visualizer = OntologyVisualizer()\n",
"\n",
"print(\"--- NLP Approach Visualization ---\")\n",
"fig_nlp = visualizer.visualize_structure(nlp_ontology, output=\"interactive\")\n",
"if fig_nlp: fig_nlp.show()\n",
"\n",
"if llm_ontology:\n",
" print(\"--- LLM Approach Visualization ---\")\n",
" fig_llm = visualizer.visualize_structure(llm_ontology, output=\"interactive\")\n",
" if fig_llm: fig_llm.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Validation\n",
"\n",
"No matter the method, validation is crucial. We check for structural integrity and logical consistency."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ontology import OntologyValidator\n",
"\n",
"validator = OntologyValidator()\n",
"\n",
"def print_report(name, ont):\n",
" if not ont: return\n",
" res = validator.validate_ontology(ont)\n",
" print(f\"[{name}] Valid: {res.valid}, Errors: {len(res.errors)}\")\n",
" if res.metrics:\n",
" print(f\" Depth: {res.metrics.get('hierarchy_depth')}, Concepts: {res.metrics.get('class_count')}\")\n",
"\n",
"print_report(\"Classical NLP\", nlp_ontology)\n",
"print_report(\"Generative AI\", llm_ontology)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Export to OWL\n",
"\n",
"Finally, we choose the best model (or merge them using `ReuseManager`, covered in other guides) and export it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.export import OWLExporter\n",
"\n",
"exporter = OWLExporter()\n",
"\n",
"# Export the NLP ontology by default, or the LLM one if preferred\n",
"target_ontology = llm_ontology if llm_ontology else nlp_ontology\n",
"\n",
"output_file = \"quantum_ontology.ttl\"\n",
"exporter.export(target_ontology, output_file, format=\"turtle\")\n",
"print(f\"Successfully exported ontology to {output_file}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"You have learned to:\n",
"1. **Extract Ontologies Programmatically**: Using `NERExtractor` for reliable, data-driven modeling.\n",
"2. **Generate Ontologies with AI**: Using `LLMOntologyGenerator` for conceptual, high-level modeling.\n",
"3. **Visualize and Compare**: Using `OntologyVisualizer` to inspect the structural differences.\n",
"4. **Validate and Export**: Ensuring quality before saving to OWL standards."
]
}
],
"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.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
"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/advanced/12_Unstructured_to_Ontology.ipynb)\n",
"\n",
"# Unstructured Text to Ontology\n",
"\n",
"Welcome to the advanced guide on extracting structured ontologies from unstructured text. This notebook explores two powerful paradigms available in Semantica:\n",
"\n",
"1. **Classical NLP Pipeline**: Using Named Entity Recognition (NER) and Relation Extraction.\n",
"2. **Generative AI Pipeline**: Using Large Language Models (LLMs) for direct conceptual modeling.\n",
"\n",
"We will compare both approaches, visualize the results, and validate the generated ontologies.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/ontology/)\n",
"\n",
"## Setup and Installation\n",
"\n",
"Ensure you have Semantica installed with all dependencies."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9c21e116",
"metadata": {},
"outputs": [],
"source": [
"!pip install -qU semantica"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"\n",
"from semantica.utils.logging import get_logger\n",
"\n",
"logger = get_logger(\"unstructured_guide\")\n",
"print(\"Environment setup complete.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## The Input Text\n",
"\n",
"We will use a rich paragraph of text describing a technology company to test both extraction methods."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"text_corpus = \"\"\"\n",
"QuantumDynamics is a leading AI research lab founded by Dr. Elena Rostova in 2018. \n",
"The lab is headquartered in Zurich, Switzerland, and focuses on quantum computing algorithms. \n",
"Dr. Rostova serves as the Chief Scientist. \n",
"The lab has released products like the Q-1 Processor and the NeuralBridge SDK. \n",
"QuantumDynamics collaborates with major universities such as MIT and ETH Zurich.\n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Approach 1: The Classical NLP Pipeline\n",
"\n",
"This approach builds the ontology from the bottom up:\n",
"1. **Extract Entities**: Identify nouns/proper nouns (e.g., \"QuantumDynamics\", \"Zurich\").\n",
"2. **Extract Relations**: Identify verbs connecting them (e.g., \"headquartered in\").\n",
"3. **Generate Ontology**: Map these triplets to Classes and Properties.\n",
"\n",
"**Pros**: Deterministic, traceable, works offline.\n",
"**Cons**: Dependent on the underlying NLP model's vocabulary and flexibility."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "75f896b9",
"metadata": {},
"outputs": [],
"source": [
"from semantica.semantic_extract import NERExtractor, RelationExtractor\n",
"from semantica.ontology import OntologyGenerator, OntologyOptimizer\n",
"\n",
"# 1. Initialize Extractors\n",
"ner = NERExtractor()\n",
"re = RelationExtractor()\n",
"\n",
"# 2. Extract Entities\n",
"print(\"Extracting entities...\")\n",
"entities = ner.extract(text_corpus)\n",
"\n",
"# Note: entities are returned as Entity objects (dataclasses), not dictionaries.\n",
"# We access properties using dot notation (e.g., entity.text, entity.label).\n",
"print(f\"Found {len(entities)} entities.\")\n",
"for e in entities[:5]:\n",
" print(f\" - {e.text} ({e.label}) [Conf: {e.confidence}]\")\n",
"\n",
"# 3. Extract Relationships\n",
"print(\"\\nExtracting relationships...\")\n",
"relationships = re.extract(text_corpus, entities)\n",
"\n",
"# Note: relationships are returned as Relation objects.\n",
"print(f\"Found {len(relationships)} relationships.\")\n",
"for r in relationships:\n",
" print(f\" - {r.subject.text} -> {r.predicate} -> {r.object.text}\")\n",
"\n",
"# 4. Prepare Data for Ontology Generation\n",
"# The OntologyGenerator expects dictionaries, so we convert our objects.\n",
"# We also ensure we handle both object attributes and potential dictionary keys for robustness.\n",
"entities_data = []\n",
"for e in entities:\n",
" if hasattr(e, 'to_dict'):\n",
" entities_data.append(e.to_dict())\n",
" else:\n",
" # Manual conversion for dataclasses without to_dict\n",
" entities_data.append({\n",
" \"id\": getattr(e, \"text\", str(e)),\n",
" \"text\": getattr(e, \"text\", str(e)),\n",
" \"type\": getattr(e, \"label\", getattr(e, \"type\", \"Unknown\")),\n",
" \"confidence\": getattr(e, \"confidence\", 1.0)\n",
" })\n",
"\n",
"relationships_data = []\n",
"for r in relationships:\n",
" if hasattr(r, 'to_dict'):\n",
" relationships_data.append(r.to_dict())\n",
" else:\n",
" # Manual conversion for dataclasses without to_dict\n",
" # Handle nested Entity objects in subject/object fields\n",
" subj = r.subject\n",
" obj = r.object\n",
" subj_text = getattr(subj, \"text\", str(subj))\n",
" obj_text = getattr(obj, \"text\", str(obj))\n",
" \n",
" relationships_data.append({\n",
" \"source\": subj_text,\n",
" \"target\": obj_text,\n",
" \"type\": getattr(r, \"predicate\", getattr(r, \"type\", \"related_to\")),\n",
" \"confidence\": getattr(r, \"confidence\", 1.0)\n",
" })\n",
"\n",
"# 5. Generate Structure\n",
"generator = OntologyGenerator()\n",
"nlp_ontology = generator.generate_ontology(\n",
" {\"entities\": entities_data, \"relationships\": relationships_data},\n",
" name=\"QuantumOntologyNLP\"\n",
")\n",
"\n",
"# 6. Optimize (Clean up)\n",
"optimizer = OntologyOptimizer()\n",
"nlp_ontology = optimizer.optimize_ontology(nlp_ontology, remove_redundancy=True)\n",
"\n",
"print(f\"\\nGenerated NLP Ontology with {len(nlp_ontology['classes'])} classes and {len(nlp_ontology['properties'])} properties.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Approach 2: The Generative AI Pipeline (LLM)\n",
"\n",
"This approach uses a Large Language Model to \"read\" the text and directly propose a schema.\n",
"\n",
"**Pros**: Context-aware, can handle ambiguity, generates human-like class names.\n",
"**Cons**: Non-deterministic, requires API access.\n",
"\n",
"*Note: This step requires a configured LLM provider (e.g., OpenAI).* "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ontology import LLMOntologyGenerator\n",
"\n",
"try:\n",
" # Initialize LLM Generator (ensure OPENAI_API_KEY is set in env)\n",
" llm_gen = LLMOntologyGenerator(provider=\"openai\", model=\"gpt-4\")\n",
" \n",
" print(\"Generating ontology with LLM...\")\n",
" llm_ontology = llm_gen.generate_ontology_from_text(\n",
" text=text_corpus,\n",
" name=\"QuantumOntologyLLM\"\n",
" )\n",
" \n",
" print(f\"Generated LLM Ontology with {len(llm_ontology['classes'])} classes and {len(llm_ontology['properties'])} properties.\")\n",
" print(\"Classes detected:\", [c['name'] for c in llm_ontology['classes']])\n",
" \n",
"except Exception as e:\n",
" print(f\"Skipping LLM generation: {e}\")\n",
" llm_ontology = None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Comparing Results with Visualization\n",
"\n",
"Let's visualize both ontologies side-by-side (if available) to see the difference in structure. The NLP model tends to be more literal, while the LLM model tends to be more conceptual."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.visualization import OntologyVisualizer\n",
"\n",
"visualizer = OntologyVisualizer()\n",
"\n",
"print(\"--- NLP Approach Visualization ---\")\n",
"fig_nlp = visualizer.visualize_structure(nlp_ontology, output=\"interactive\")\n",
"if fig_nlp: fig_nlp.show()\n",
"\n",
"if llm_ontology:\n",
" print(\"--- LLM Approach Visualization ---\")\n",
" fig_llm = visualizer.visualize_structure(llm_ontology, output=\"interactive\")\n",
" if fig_llm: fig_llm.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Export to OWL\n",
"\n",
"Finally, we choose the best model (or merge them using `ReuseManager`, covered in other guides) and export it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.export import OWLExporter\n",
"\n",
"exporter = OWLExporter()\n",
"\n",
"# Export the NLP ontology by default, or the LLM one if preferred\n",
"target_ontology = llm_ontology if llm_ontology else nlp_ontology\n",
"\n",
"output_file = \"quantum_ontology.ttl\"\n",
"exporter.export(target_ontology, output_file, format=\"turtle\")\n",
"print(f\"Successfully exported ontology to {output_file}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"You have learned to:\n",
"1. **Extract Ontologies Programmatically**: Using `NERExtractor` for reliable, data-driven modeling.\n",
"2. **Generate Ontologies with AI**: Using `LLMOntologyGenerator` for conceptual, high-level modeling.\n",
"3. **Visualize and Compare**: Using `OntologyVisualizer` to inspect the structural differences.\n",
"4. **Validate and Export**: Ensuring quality before saving to OWL standards."
]
}
],
"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.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,371 +1,380 @@
{
"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/advanced/Advanced_Vector_Store_and_Search.ipynb)\n",
"\n",
"# Advanced Vector Store - Made Easy\n",
"\n",
"## What You'll Learn\n",
"\n",
"This notebook shows you **practical ways** to use vector stores in real applications. Each example is simple and ready to use.\n",
"\n",
"### Topics\n",
"\n",
"1. **Choosing the Right Index** - Which one to use and when\n",
"2. **Smart Filtering** - Find exactly what you need\n",
"3. **Combining Results** - Merge searches from different sources\n",
"4. **Organizing Data** - Keep different users' data separate\n",
"\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 0: Setup Embeddings\n",
"\n",
"First, let's select our embedding provider and model. Semantica supports multiple providers like Sentence Transformers and FastEmbed.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.embeddings import TextEmbedder\n",
"\n",
"# Choose provider and model\n",
"embedder = TextEmbedder(method=\"fastembed\", model_name=\"BAAI/bge-small-en-v1.5\")\n",
"dimension = embedder.get_embedding_dimension()\n",
"\n",
"print(f\"Selected model: {embedder.get_model_info()['model_name']}\")\n",
"print(f\"Embedding dimension: {dimension}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 1: Choosing the Right Index\n",
"\n",
"Think of an index like choosing a filing system:\n",
"- **Flat**: Like a small notebook - slow but perfect\n",
"- **HNSW**: Like a well-organized library - fast and accurate\n",
"- **IVF**: Like a warehouse with sections - very fast for huge collections\n",
"\n",
"### Simple Rule\n",
"- Less than 10,000 items? Use **Flat**\n",
"- Between 10,000 and 1 million? Use **HNSW** ✅ (recommended)\n",
"- More than 1 million? Use **IVF**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import FAISSAdapter\n",
"import numpy as np\n",
"\n",
"# Create some example vectors (like document embeddings)\n",
"vectors = np.random.rand(5000, 768).astype('float32')\n",
"query = np.random.rand(768).astype('float32')\n",
"\n",
"adapter = FAISSAdapter(dimension=768)\n",
"\n",
"# HNSW Index - Best for most cases\n",
"index = adapter.create_index(index_type=\"hnsw\", metric=\"L2\", m=16)\n",
"adapter.add_vectors(index, vectors, ids=[f\"doc_{i}\" for i in range(len(vectors))])\n",
"\n",
"# Search for similar vectors\n",
"distances, indices = adapter.search(index, query, k=5)\n",
"\n",
"print(\"Found 5 most similar documents:\")\n",
"for i, (dist, idx) in enumerate(zip(distances, indices), 1):\n",
" print(f\" {i}. Document {idx} (distance: {dist:.3f})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 2: Smart Filtering with Metadata\n",
"\n",
"Imagine searching for \"similar articles\" but only from 2024 and only in the \"Technology\" category. That's what metadata filtering does!\n",
"\n",
"### Real-World Example\n",
"You're building a document search where users want:\n",
"- Similar documents (vector search)\n",
"- From specific categories (metadata filter)\n",
"- From recent years (metadata filter)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import HybridSearch, MetadataFilter\n",
"import numpy as np\n",
"\n",
"# Create sample documents with metadata\n",
"documents = [\n",
" {\"id\": 0, \"text\": \"AI in Healthcare\", \"category\": \"Technology\", \"year\": 2024},\n",
" {\"id\": 1, \"text\": \"Machine Learning Basics\", \"category\": \"Technology\", \"year\": 2023},\n",
" {\"id\": 2, \"text\": \"Business Strategy\", \"category\": \"Business\", \"year\": 2024},\n",
" {\"id\": 3, \"text\": \"Data Science Guide\", \"category\": \"Technology\", \"year\": 2024},\n",
" {\"id\": 4, \"text\": \"Marketing Tips\", \"category\": \"Business\", \"year\": 2023},\n",
"]\n",
"\n",
"# Create vectors for each document\n",
"vectors = [np.random.rand(768) for _ in documents]\n",
"metadata = [{\"category\": d[\"category\"], \"year\": d[\"year\"]} for d in documents]\n",
"vector_ids = [f\"doc_{d['id']}\" for d in documents]\n",
"\n",
"# Create search\n",
"search = HybridSearch()\n",
"query = np.random.rand(768)\n",
"\n",
"# Example 1: Find Technology articles from 2024\n",
"filter1 = MetadataFilter().eq(\"category\", \"Technology\").eq(\"year\", 2024)\n",
"results = search.search(query, vectors, metadata, vector_ids, filter=filter1, k=10)\n",
"\n",
"print(\"Technology articles from 2024:\")\n",
"for r in results:\n",
" doc_id = int(r['id'].split('_')[1])\n",
" print(f\" - {documents[doc_id]['text']}\")\n",
"\n",
"# Example 2: Find any article from 2024\n",
"filter2 = MetadataFilter().eq(\"year\", 2024)\n",
"results2 = search.search(query, vectors, metadata, vector_ids, filter=filter2, k=10)\n",
"\n",
"print(\"\\nAll articles from 2024:\")\n",
"for r in results2:\n",
" doc_id = int(r['id'].split('_')[1])\n",
" print(f\" - {documents[doc_id]['text']} ({documents[doc_id]['category']})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 3: Combining Search Results\n",
"\n",
"Sometimes you want to search in multiple places and combine the results. Like searching both your email and documents, then showing the best matches from both.\n",
"\n",
"### When to Use This\n",
"- Searching multiple databases\n",
"- Combining different search strategies\n",
"- Giving more weight to certain sources"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import SearchRanker\n",
"\n",
"# Simulate two different searches\n",
"# Search 1: Recent documents\n",
"recent_results = [\n",
" {\"id\": \"doc_3\", \"score\": 0.95, \"source\": \"recent\"},\n",
" {\"id\": \"doc_0\", \"score\": 0.90, \"source\": \"recent\"},\n",
" {\"id\": \"doc_2\", \"score\": 0.85, \"source\": \"recent\"},\n",
"]\n",
"\n",
"# Search 2: Popular documents\n",
"popular_results = [\n",
" {\"id\": \"doc_1\", \"score\": 0.92, \"source\": \"popular\"},\n",
" {\"id\": \"doc_3\", \"score\": 0.88, \"source\": \"popular\"},\n",
" {\"id\": \"doc_4\", \"score\": 0.80, \"source\": \"popular\"},\n",
"]\n",
"\n",
"# Method 1: Fair combination (RRF)\n",
"ranker = SearchRanker(strategy=\"reciprocal_rank_fusion\")\n",
"combined = ranker.rank([recent_results, popular_results])\n",
"\n",
"print(\"Combined results (fair ranking):\")\n",
"for i, result in enumerate(combined[:3], 1):\n",
" doc_id = int(result['id'].split('_')[1])\n",
" print(f\" {i}. {documents[doc_id]['text']} (score: {result['score']:.3f})\")\n",
"\n",
"# Method 2: Prefer recent documents (70% recent, 30% popular)\n",
"weighted_ranker = SearchRanker(strategy=\"weighted_average\")\n",
"weighted_combined = weighted_ranker.rank(\n",
" [recent_results, popular_results],\n",
" weights=[0.7, 0.3]\n",
")\n",
"\n",
"print(\"\\nCombined results (prefer recent):\")\n",
"for i, result in enumerate(weighted_combined[:3], 1):\n",
" doc_id = int(result['id'].split('_')[1])\n",
" print(f\" {i}. {documents[doc_id]['text']} (score: {result['score']:.3f})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 4: Keeping User Data Separate\n",
"\n",
"If you're building an app with multiple users or companies, you need to keep their data separate. Namespaces do this automatically.\n",
"\n",
"### Real Example\n",
"You're building a SaaS app where:\n",
"- Company A has their documents\n",
"- Company B has their documents\n",
"- They should never see each other's data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import NamespaceManager\n",
"\n",
"# Create manager\n",
"manager = NamespaceManager()\n",
"\n",
"# Create separate spaces for each company\n",
"company_a = manager.create_namespace(\"company_a\", \"Company A's documents\")\n",
"company_b = manager.create_namespace(\"company_b\", \"Company B's documents\")\n",
"\n",
"# Add documents to Company A\n",
"for i in range(10):\n",
" manager.add_vector_to_namespace(f\"company_a_doc_{i}\", \"company_a\")\n",
"\n",
"# Add documents to Company B\n",
"for i in range(15):\n",
" manager.add_vector_to_namespace(f\"company_b_doc_{i}\", \"company_b\")\n",
"\n",
"# Get each company's documents\n",
"a_docs = manager.get_namespace_vectors(\"company_a\")\n",
"b_docs = manager.get_namespace_vectors(\"company_b\")\n",
"\n",
"print(f\"Company A has {len(a_docs)} documents\")\n",
"print(f\"Company B has {len(b_docs)} documents\")\n",
"\n",
"# Set permissions (who can access what)\n",
"company_a.set_access_control(\"admin@companya.com\", [\"read\", \"write\", \"delete\"])\n",
"company_a.set_access_control(\"user@companya.com\", [\"read\"]) # Read-only\n",
"\n",
"# Check permissions\n",
"print(f\"\\nAdmin can delete: {company_a.has_permission('admin@companya.com', 'delete')}\")\n",
"print(f\"User can delete: {company_a.has_permission('user@companya.com', 'delete')}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quick Reference Guide\n",
"\n",
"### Which Index Should I Use?\n",
"\n",
"```python\n",
"# Small dataset (< 10,000 items)\n",
"index = adapter.create_index(index_type=\"flat\", metric=\"L2\")\n",
"\n",
"# Medium dataset (10,000 - 1,000,000 items) ✅ RECOMMENDED\n",
"index = adapter.create_index(index_type=\"hnsw\", metric=\"L2\", m=16)\n",
"\n",
"# Large dataset (> 1,000,000 items)\n",
"index = adapter.create_index(index_type=\"ivf\", metric=\"L2\", nlist=100)\n",
"```\n",
"\n",
"### How Do I Filter Results?\n",
"\n",
"```python\n",
"# Single condition\n",
"filter = MetadataFilter().eq(\"category\", \"Technology\")\n",
"\n",
"# Multiple conditions (AND)\n",
"filter = MetadataFilter() \\\n",
" .eq(\"category\", \"Technology\") \\\n",
" .eq(\"year\", 2024)\n",
"\n",
"# Greater than / Less than\n",
"filter = MetadataFilter().gt(\"year\", 2020)\n",
"```\n",
"\n",
"### How Do I Combine Results?\n",
"\n",
"```python\n",
"# Fair combination\n",
"ranker = SearchRanker(strategy=\"reciprocal_rank_fusion\")\n",
"combined = ranker.rank([results1, results2])\n",
"\n",
"# Weighted combination (prefer first source)\n",
"ranker = SearchRanker(strategy=\"weighted_average\")\n",
"combined = ranker.rank([results1, results2], weights=[0.7, 0.3])\n",
"```\n",
"\n",
"### How Do I Separate User Data?\n",
"\n",
"```python\n",
"# Create namespace for each user/company\n",
"manager = NamespaceManager()\n",
"user_space = manager.create_namespace(\"user_123\", \"User 123's data\")\n",
"\n",
"# Add data to namespace\n",
"manager.add_vector_to_namespace(\"doc_1\", \"user_123\")\n",
"\n",
"# Get user's data\n",
"user_docs = manager.get_namespace_vectors(\"user_123\")\n",
"```\n",
"\n",
"---\n",
"\n",
"## Summary\n",
"\n",
"You've learned:\n",
"\n",
"1. ✅ **Index Selection**: Use HNSW for most cases\n",
"2. ✅ **Smart Filtering**: Combine vector search with metadata\n",
"3. ✅ **Result Fusion**: Merge searches from different sources\n",
"4. ✅ **Data Isolation**: Keep users' data separate\n",
"\n",
"### Next Steps\n",
"\n",
"- Try these examples with your own data\n",
"- Experiment with different filters\n",
"- Build a multi-user application\n",
"- Explore the [introduction notebook](../introduction/13_Vector_Store.ipynb) for more basics\n",
"\n",
"**Need Help?** Check our [documentation](https://semantica.readthedocs.io) or ask on [GitHub](https://github.com/Hawksight-AI/semantica)."
]
}
],
"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.10.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
"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/advanced/Advanced_Vector_Store_and_Search.ipynb)\n",
"\n",
"# Advanced Vector Store - Made Easy\n",
"\n",
"## What You'll Learn\n",
"\n",
"This notebook shows you **practical ways** to use vector stores in real applications. Each example is simple and ready to use.\n",
"\n",
"### Topics\n",
"\n",
"1. **Choosing the Right Index** - Which one to use and when\n",
"2. **Smart Filtering** - Find exactly what you need\n",
"3. **Combining Results** - Merge searches from different sources\n",
"4. **Organizing Data** - Keep different users' data separate\n",
"\n",
"---"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 0: Setup Embeddings\n",
"\n",
"First, let's select our embedding provider and model. Semantica supports multiple providers like Sentence Transformers and FastEmbed.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.embeddings import TextEmbedder\n",
"\n",
"# Choose provider and model\n",
"embedder = TextEmbedder(method=\"fastembed\", model_name=\"BAAI/bge-small-en-v1.5\")\n",
"dimension = embedder.get_embedding_dimension()\n",
"\n",
"print(f\"Selected model: {embedder.get_model_info()['model_name']}\")\n",
"print(f\"Embedding dimension: {dimension}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 1: Choosing the Right Index\n",
"\n",
"Think of an index like choosing a filing system:\n",
"- **Flat**: Like a small notebook - slow but perfect\n",
"- **HNSW**: Like a well-organized library - fast and accurate\n",
"- **IVF**: Like a warehouse with sections - very fast for huge collections\n",
"\n",
"### Simple Rule\n",
"- Less than 10,000 items? Use **Flat**\n",
"- Between 10,000 and 1 million? Use **HNSW** ✅ (recommended)\n",
"- More than 1 million? Use **IVF**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import FAISSStore\n",
"import numpy as np\n",
"\n",
"# Create some example vectors (like document embeddings)\n",
"vectors = np.random.rand(5000, 768).astype('float32')\n",
"query = np.random.rand(768).astype('float32')\n",
"\n",
"adapter = FAISSStore(dimension=768)\n",
"\n",
"# HNSW Index - Best for most cases\n",
"index = adapter.create_index(index_type=\"hnsw\", metric=\"L2\", m=16)\n",
"adapter.add_vectors(vectors, ids=[f\"doc_{i}\" for i in range(len(vectors))])\n",
"\n",
"# Search for similar vectors\n",
"results = adapter.search_similar(query, k=5)\n",
"\n",
"print(\"Found 5 most similar documents:\")\n",
"for i, result in enumerate(results, 1):\n",
" print(f\" {i}. Document {result['id']} (distance: {result['distance']:.3f})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 2: Smart Filtering with Metadata\n",
"\n",
"Imagine searching for \"similar articles\" but only from 2024 and only in the \"Technology\" category. That's what metadata filtering does!\n",
"\n",
"### Real-World Example\n",
"You're building a document search where users want:\n",
"- Similar documents (vector search)\n",
"- From specific categories (metadata filter)\n",
"- From recent years (metadata filter)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import HybridSearch, MetadataFilter\n",
"import numpy as np\n",
"\n",
"# Create sample documents with metadata\n",
"documents = [\n",
" {\"id\": 0, \"text\": \"AI in Healthcare\", \"category\": \"Technology\", \"year\": 2024},\n",
" {\"id\": 1, \"text\": \"Machine Learning Basics\", \"category\": \"Technology\", \"year\": 2023},\n",
" {\"id\": 2, \"text\": \"Business Strategy\", \"category\": \"Business\", \"year\": 2024},\n",
" {\"id\": 3, \"text\": \"Data Science Guide\", \"category\": \"Technology\", \"year\": 2024},\n",
" {\"id\": 4, \"text\": \"Marketing Tips\", \"category\": \"Business\", \"year\": 2023},\n",
"]\n",
"\n",
"# Create vectors for each document\n",
"vectors = [np.random.rand(768) for _ in documents]\n",
"metadata = [{\"category\": d[\"category\"], \"year\": d[\"year\"]} for d in documents]\n",
"vector_ids = [f\"doc_{d['id']}\" for d in documents]\n",
"\n",
"# Create search\n",
"search = HybridSearch()\n",
"query = np.random.rand(768)\n",
"\n",
"# Example 1: Find Technology articles from 2024\n",
"filter1 = MetadataFilter().eq(\"category\", \"Technology\").eq(\"year\", 2024)\n",
"results = search.search(query, vectors, metadata, vector_ids, filter=filter1, k=10)\n",
"\n",
"print(\"Technology articles from 2024:\")\n",
"for r in results:\n",
" doc_id = int(r['id'].split('_')[1])\n",
" print(f\" - {documents[doc_id]['text']}\")\n",
"\n",
"# Example 2: Find any article from 2024\n",
"filter2 = MetadataFilter().eq(\"year\", 2024)\n",
"results2 = search.search(query, vectors, metadata, vector_ids, filter=filter2, k=10)\n",
"\n",
"print(\"\\nAll articles from 2024:\")\n",
"for r in results2:\n",
" doc_id = int(r['id'].split('_')[1])\n",
" print(f\" - {documents[doc_id]['text']} ({documents[doc_id]['category']})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 3: Combining Search Results\n",
"\n",
"Sometimes you want to search in multiple places and combine the results. Like searching both your email and documents, then showing the best matches from both.\n",
"\n",
"### When to Use This\n",
"- Searching multiple databases\n",
"- Combining different search strategies\n",
"- Giving more weight to certain sources"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import SearchRanker\n",
"\n",
"# Simulate two different searches\n",
"# Search 1: Recent documents\n",
"recent_results = [\n",
" {\"id\": \"doc_3\", \"score\": 0.95, \"source\": \"recent\"},\n",
" {\"id\": \"doc_0\", \"score\": 0.90, \"source\": \"recent\"},\n",
" {\"id\": \"doc_2\", \"score\": 0.85, \"source\": \"recent\"},\n",
"]\n",
"\n",
"# Search 2: Popular documents\n",
"popular_results = [\n",
" {\"id\": \"doc_1\", \"score\": 0.92, \"source\": \"popular\"},\n",
" {\"id\": \"doc_3\", \"score\": 0.88, \"source\": \"popular\"},\n",
" {\"id\": \"doc_4\", \"score\": 0.80, \"source\": \"popular\"},\n",
"]\n",
"\n",
"# Method 1: Fair combination (RRF)\n",
"ranker = SearchRanker(strategy=\"reciprocal_rank_fusion\")\n",
"combined = ranker.rank([recent_results, popular_results])\n",
"\n",
"print(\"Combined results (fair ranking):\")\n",
"for i, result in enumerate(combined[:3], 1):\n",
" doc_id = int(result['id'].split('_')[1])\n",
" print(f\" {i}. {documents[doc_id]['text']} (score: {result['score']:.3f})\")\n",
"\n",
"# Method 2: Prefer recent documents (70% recent, 30% popular)\n",
"weighted_ranker = SearchRanker(strategy=\"weighted_average\")\n",
"weighted_combined = weighted_ranker.rank(\n",
" [recent_results, popular_results],\n",
" weights=[0.7, 0.3]\n",
")\n",
"\n",
"print(\"\\nCombined results (prefer recent):\")\n",
"for i, result in enumerate(weighted_combined[:3], 1):\n",
" doc_id = int(result['id'].split('_')[1])\n",
" print(f\" {i}. {documents[doc_id]['text']} (score: {result['score']:.3f})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 4: Keeping User Data Separate\n",
"\n",
"If you're building an app with multiple users or companies, you need to keep their data separate. Namespaces do this automatically.\n",
"\n",
"### Real Example\n",
"You're building a SaaS app where:\n",
"- Company A has their documents\n",
"- Company B has their documents\n",
"- They should never see each other's data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import NamespaceManager\n",
"\n",
"# Create manager\n",
"manager = NamespaceManager()\n",
"\n",
"# Create separate spaces for each company\n",
"company_a = manager.create_namespace(\"company_a\", \"Company A's documents\")\n",
"company_b = manager.create_namespace(\"company_b\", \"Company B's documents\")\n",
"\n",
"# Add documents to Company A\n",
"for i in range(10):\n",
" manager.add_vector_to_namespace(f\"company_a_doc_{i}\", \"company_a\")\n",
"\n",
"# Add documents to Company B\n",
"for i in range(15):\n",
" manager.add_vector_to_namespace(f\"company_b_doc_{i}\", \"company_b\")\n",
"\n",
"# Get each company's documents\n",
"a_docs = manager.get_namespace_vectors(\"company_a\")\n",
"b_docs = manager.get_namespace_vectors(\"company_b\")\n",
"\n",
"print(f\"Company A has {len(a_docs)} documents\")\n",
"print(f\"Company B has {len(b_docs)} documents\")\n",
"\n",
"# Set permissions (who can access what)\n",
"company_a.set_access_control(\"admin@companya.com\", [\"read\", \"write\", \"delete\"])\n",
"company_a.set_access_control(\"user@companya.com\", [\"read\"]) # Read-only\n",
"\n",
"# Check permissions\n",
"print(f\"\\nAdmin can delete: {company_a.has_permission('admin@companya.com', 'delete')}\")\n",
"print(f\"User can delete: {company_a.has_permission('user@companya.com', 'delete')}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quick Reference Guide\n",
"\n",
"### Which Index Should I Use?\n",
"\n",
"```python\n",
"# Small dataset (< 10,000 items)\n",
"index = adapter.create_index(index_type=\"flat\", metric=\"L2\")\n",
"\n",
"# Medium dataset (10,000 - 1,000,000 items) ✅ RECOMMENDED\n",
"index = adapter.create_index(index_type=\"hnsw\", metric=\"L2\", m=16)\n",
"\n",
"# Large dataset (> 1,000,000 items)\n",
"index = adapter.create_index(index_type=\"ivf\", metric=\"L2\", nlist=100)\n",
"```\n",
"\n",
"### How Do I Filter Results?\n",
"\n",
"```python\n",
"# Single condition\n",
"filter = MetadataFilter().eq(\"category\", \"Technology\")\n",
"\n",
"# Multiple conditions (AND)\n",
"filter = MetadataFilter() \\\n",
" .eq(\"category\", \"Technology\") \\\n",
" .eq(\"year\", 2024)\n",
"\n",
"# Greater than / Less than\n",
"filter = MetadataFilter().gt(\"year\", 2020)\n",
"```\n",
"\n",
"### How Do I Combine Results?\n",
"\n",
"```python\n",
"# Fair combination\n",
"ranker = SearchRanker(strategy=\"reciprocal_rank_fusion\")\n",
"combined = ranker.rank([results1, results2])\n",
"\n",
"# Weighted combination (prefer first source)\n",
"ranker = SearchRanker(strategy=\"weighted_average\")\n",
"combined = ranker.rank([results1, results2], weights=[0.7, 0.3])\n",
"```\n",
"\n",
"### How Do I Separate User Data?\n",
"\n",
"```python\n",
"# Create namespace for each user/company\n",
"manager = NamespaceManager()\n",
"user_space = manager.create_namespace(\"user_123\", \"User 123's data\")\n",
"\n",
"# Add data to namespace\n",
"manager.add_vector_to_namespace(\"doc_1\", \"user_123\")\n",
"\n",
"# Get user's data\n",
"user_docs = manager.get_namespace_vectors(\"user_123\")\n",
"```\n",
"\n",
"---\n",
"\n",
"## Summary\n",
"\n",
"You've learned:\n",
"\n",
"1. ✅ **Index Selection**: Use HNSW for most cases\n",
"2. ✅ **Smart Filtering**: Combine vector search with metadata\n",
"3. ✅ **Result Fusion**: Merge searches from different sources\n",
"4. ✅ **Data Isolation**: Keep users' data separate\n",
"\n",
"### Next Steps\n",
"\n",
"- Try these examples with your own data\n",
"- Experiment with different filters\n",
"- Build a multi-user application\n",
"- Explore the [introduction notebook](../introduction/13_Vector_Store.ipynb) for more basics\n",
"\n",
"**Need Help?** Check our [documentation](https://semantica.readthedocs.io) or ask on [GitHub](https://github.com/Hawksight-AI/semantica)."
]
}
],
"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.10.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
+20
View File
@@ -0,0 +1,20 @@
<e1> a <Person> ;
semantica:text "" ;
semantica:confidence 1.0 .
<e2> a <Person> ;
semantica:text "" ;
semantica:confidence 1.0 .
<e3> a <Organization> ;
semantica:text "" ;
semantica:confidence 1.0 .
<e4> a <Project> ;
semantica:text "" ;
semantica:confidence 1.0 .
<e1> <reports_to> <e2> .
<e1> <works_for> <e3> .
<e2> <works_for> <e3> .
<e1> <works_on> <e4> .
+21
View File
@@ -0,0 +1,21 @@
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ont: <https://semantica.dev/ontology/> .
<https://semantica.dev/ontology/> a owl:Ontology ;
rdfs:label "QuantumOntologyNLP" ;
owl:versionInfo "1.0" .
<> a owl:Class ;
rdfs:label "Org" .
rdfs:comment "Class representing org entities" .
<> a owl:Class ;
rdfs:label "Person" .
rdfs:comment "Class representing person entities" .
<> a owl:Class ;
rdfs:label "Gpe" .
rdfs:comment "Class representing gpe entities" .
File diff suppressed because it is too large Load Diff
+514 -429
View File
@@ -1,430 +1,515 @@
{
"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/introduction/02_Data_Ingestion.ipynb)\n",
"\n",
"# Data Ingestion - Comprehensive Guide\n",
"\n",
"## Overview\n",
"\n",
"This notebook provides a comprehensive guide to Semantica's data ingestion capabilities. It covers all submodules, classes, and helper functions available in the `semantica.ingest` module.\n",
"\n",
"**Documentation**: [Ingest API Reference](https://semantica.readthedocs.io/reference/ingest/)\n",
"\n",
"### Table of Contents\n",
"\n",
"1. **Unified Ingestion**: `ingest` function\n",
"2. **File Ingestion**: `FileIngestor`, `FileTypeDetector`, `CloudStorageIngestor`\n",
"3. **Web Ingestion**: `WebIngestor`, `ContentExtractor`, `SitemapCrawler`, `RobotsChecker`\n",
"4. **Feed Ingestion**: `FeedIngestor`, `FeedMonitor`\n",
"5. **Stream Ingestion**: `StreamIngestor`, `StreamMonitor`\n",
"6. **Repository Ingestion**: `RepoIngestor`, `CodeExtractor`, `GitAnalyzer`\n",
"7. **Email Ingestion**: `EmailIngestor`, `AttachmentProcessor`\n",
"8. **Database Ingestion**: `DBIngestor`, `DatabaseConnector`\n",
"9. **MCP Ingestion**: `MCPIngestor`\n",
"10. **Configuration**: `IngestConfig`\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica with all dependencies:\n",
"\n",
"```bash\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---\n",
"\n",
"## 1. Unified Ingestion\n",
"\n",
"The `ingest` function is the main entry point for quick data loading. It automatically detects the source type.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import ingest\n",
"import tempfile\n",
"import os\n",
"import json\n",
"\n",
"# Setup temporary directory for examples\n",
"temp_dir = tempfile.mkdtemp()\n",
"sample_file = os.path.join(temp_dir, \"sample.txt\")\n",
"with open(sample_file, 'w') as f:\n",
" f.write(\"Semantica Unified Ingestion Example\")\n",
"\n",
"# Auto-detect file source\n",
"result = ingest(sample_file)\n",
"print(f\"Ingested: {result.name} (Type: {result.file_type})\")\n",
"\n",
"# Explicit source type\n",
"result_explicit = ingest(sample_file, source_type=\"file\")\n",
"print(f\"Explicit Ingest: {result_explicit.name}\")\n",
"\n",
"# Ingest web URL (auto-detected)\n",
"# Note: This will fail if no internet connection\n",
"try:\n",
" result_web = ingest(\"https://example.com\")\n",
" print(f\"Ingested Web: {result_web.title}\")\n",
"except Exception as e:\n",
" print(f\"Web ingestion skipped: {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. File Ingestion\n",
"\n",
"Detailed control over file processing using `FileIngestor` and helper classes.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import FileIngestor, FileTypeDetector, CloudStorageIngestor\n",
"\n",
"# --- FileTypeDetector ---\n",
"detector = FileTypeDetector()\n",
"detected_type = detector.detect_type(sample_file)\n",
"print(f\"Detected Type: {detected_type}\")\n",
"\n",
"# --- FileIngestor ---\n",
"file_ingestor = FileIngestor()\n",
"\n",
"# Ingest Directory\n",
"subdir = os.path.join(temp_dir, \"docs\")\n",
"os.makedirs(subdir, exist_ok=True)\n",
"with open(os.path.join(subdir, \"note.md\"), 'w') as f:\n",
" f.write(\"# Note\\nThis is a markdown file.\")\n",
"\n",
"files = file_ingestor.ingest_directory(temp_dir, recursive=True)\n",
"print(f\"Ingested {len(files)} files from directory\")\n",
"\n",
"# --- CloudStorageIngestor (Mock Config) ---\n",
"s3_config = {\n",
" \"aws_access_key_id\": \"mock_key\",\n",
" \"aws_secret_access_key\": \"mock_secret\",\n",
" \"region_name\": \"us-east-1\"\n",
"}\n",
"cloud_ingestor = CloudStorageIngestor(provider=\"s3\", **s3_config)\n",
"\n",
"# Example call (will raise error without real credentials)\n",
"try:\n",
" result = cloud_ingestor.ingest(\"s3://my-bucket/data.csv\")\n",
" print(f\"Cloud Ingest: {result.name}\")\n",
"except Exception as e:\n",
" print(f\"Cloud ingestion skipped (Mock Config): {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Web Ingestion\n",
"\n",
"Scraping and crawling with `WebIngestor`, `ContentExtractor`, and `SitemapCrawler`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import WebIngestor, ContentExtractor, SitemapCrawler, RobotsChecker\n",
"\n",
"# --- ContentExtractor ---\n",
"extractor = ContentExtractor()\n",
"html_content = \"<html><body><h1>Hello World</h1><p>This is a test.</p><a href='/link'>Link</a></body></html>\"\n",
"text = extractor.extract_text(html_content)\n",
"links = extractor.extract_links(html_content, base_url=\"https://example.com\")\n",
"print(f\"Extracted Text: {text}\")\n",
"print(f\"Extracted Links: {links}\")\n",
"\n",
"# --- RobotsChecker ---\n",
"checker = RobotsChecker()\n",
"can_fetch = checker.can_fetch(\"https://www.google.com/search\", \"MyBot\")\n",
"print(f\"Can fetch google search? {can_fetch}\")\n",
"\n",
"# --- WebIngestor ---\n",
"web_ingestor = WebIngestor(delay=1.0)\n",
"try:\n",
" web_content = web_ingestor.ingest_url(\"https://example.com\")\n",
" print(f\"Web Content Title: {web_content.title}\")\n",
"except Exception as e:\n",
" print(f\"Web ingest failed: {e}\")\n",
"\n",
"# --- SitemapCrawler ---\n",
"crawler = SitemapCrawler()\n",
"try:\n",
" urls = crawler.parse_sitemap(\"https://www.google.com/sitemap.xml\")\n",
" print(f\"Found {len(urls)} URLs in sitemap\")\n",
"except Exception as e:\n",
" print(f\"Sitemap crawl failed: {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Feed Ingestion\n",
"\n",
"Consuming RSS/Atom feeds with `FeedIngestor` and monitoring with `FeedMonitor`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import FeedIngestor, FeedMonitor\n",
"import time\n",
"\n",
"# --- FeedIngestor ---\n",
"feed_ingestor = FeedIngestor()\n",
"try:\n",
" feed_data = feed_ingestor.ingest_feed(\"https://feeds.feedburner.com/oreilly/radar\")\n",
" print(f\"Feed Title: {feed_data.title}\")\n",
"except Exception as e:\n",
" print(f\"Feed ingest failed: {e}\")\n",
"\n",
"# --- FeedMonitor ---\n",
"def feed_callback(feed_data):\n",
" print(f\"Feed Updated: {feed_data.title} with {len(feed_data.items)} items\")\n",
"\n",
"monitor = FeedMonitor(check_interval=5)\n",
"try:\n",
" monitor.monitor(\"https://feeds.feedburner.com/oreilly/radar\", callback=feed_callback)\n",
" time.sleep(2) # Let it run briefly\n",
" monitor.stop()\n",
"except Exception as e:\n",
" print(f\"Feed monitor failed: {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Stream Ingestion\n",
"\n",
"Real-time processing with `StreamIngestor` and `StreamMonitor`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import StreamIngestor, StreamMonitor\n",
"\n",
"stream_ingestor = StreamIngestor()\n",
"\n",
"# --- Kafka Processor ---\n",
"kafka_config = {\"bootstrap_servers\": [\"localhost:9092\"]}\n",
"kafka_processor = stream_ingestor.ingest_kafka(\"my-topic\", **kafka_config)\n",
"\n",
"# --- RabbitMQ Processor ---\n",
"rabbitmq_processor = stream_ingestor.ingest_rabbitmq(\"my-queue\", \"amqp://guest:guest@localhost:5672/\")\n",
"\n",
"# --- Stream Monitor ---\n",
"monitor = stream_ingestor.monitor\n",
"health = monitor.check_health()\n",
"print(f\"Stream Health: {health['overall']}\")\n",
"print(f\"Processors: {list(health['processors'].keys())}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Repository Ingestion\n",
"\n",
"Analyzing codebases with `RepoIngestor`, `CodeExtractor`, and `GitAnalyzer`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import RepoIngestor, CodeExtractor, GitAnalyzer\n",
"\n",
"# --- CodeExtractor ---\n",
"code_extractor = CodeExtractor()\n",
"py_code = \"class MyClass:\\n def my_method(self):\\n pass\"\n",
"structure = code_extractor.extract_structure(py_code, language=\"python\")\n",
"print(f\"Classes: {structure.get('classes')}\")\n",
"print(f\"Functions: {structure.get('functions')}\")\n",
"\n",
"# --- RepoIngestor ---\n",
"repo_ingestor = RepoIngestor()\n",
"try:\n",
" repo_data = repo_ingestor.ingest_repository(\"https://github.com/Hawksight-AI/semantica.git\")\n",
" print(f\"Repo Name: {repo_data['name']}\")\n",
"except Exception as e:\n",
" print(f\"Repo ingest failed: {e}\")\n",
"\n",
"# --- GitAnalyzer ---\n",
"try:\n",
" analyzer = GitAnalyzer(\".\")\n",
" stats = analyzer.get_statistics()\n",
" print(f\"Commits in current repo: {stats.get('total_commits', 'N/A')}\")\n",
"except Exception as e:\n",
" print(f\"Git analysis failed: {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Email Ingestion\n",
"\n",
"Processing emails with `EmailIngestor` and `AttachmentProcessor`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import EmailIngestor, AttachmentProcessor\n",
"\n",
"# --- AttachmentProcessor ---\n",
"att_processor = AttachmentProcessor()\n",
"dummy_content = b\"PDF Content\"\n",
"saved_path = att_processor.save_attachment(dummy_content, \"doc.pdf\", temp_dir)\n",
"print(f\"Saved attachment to: {saved_path}\")\n",
"\n",
"# --- EmailIngestor ---\n",
"email_ingestor = EmailIngestor()\n",
"try:\n",
" email_ingestor.connect_imap(\"imap.gmail.com\", \"user\", \"pass\")\n",
" emails = email_ingestor.ingest_mailbox(\"INBOX\", max_emails=5)\n",
" print(f\"Fetched {len(emails)} emails\")\n",
"except Exception as e:\n",
" print(f\"Email ingest failed (Auth required): {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Database Ingestion\n",
"\n",
"Connecting to SQL databases with `DBIngestor` and `DatabaseConnector`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import DBIngestor, DatabaseConnector\n",
"import sqlite3\n",
"\n",
"# Setup SQLite DB\n",
"db_path = os.path.join(temp_dir, \"test.db\")\n",
"conn = sqlite3.connect(db_path)\n",
"conn.execute(\"CREATE TABLE items (id INT, name TEXT)\")\n",
"conn.execute(\"INSERT INTO items VALUES (1, 'Item 1'), (2, 'Item 2')\")\n",
"conn.commit()\n",
"conn.close()\n",
"\n",
"# --- DatabaseConnector ---\n",
"connector = DatabaseConnector()\n",
"engine = connector.create_engine(f\"sqlite:///{db_path}\")\n",
"print(f\"Connected to DB: {engine.name}\")\n",
"\n",
"# --- DBIngestor ---\n",
"db_ingestor = DBIngestor()\n",
"table_data = db_ingestor.ingest_database(f\"sqlite:///{db_path}\", table=\"items\")\n",
"print(f\"Table: {table_data.table_name}\")\n",
"print(f\"Rows: {table_data.row_count}\")\n",
"for row in table_data.rows:\n",
" print(f\" - {row}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. MCP Ingestion\n",
"\n",
"Integrating with Model Context Protocol servers using `MCPIngestor`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import MCPIngestor\n",
"\n",
"mcp_ingestor = MCPIngestor()\n",
"\n",
"try:\n",
" # Connect\n",
" mcp_ingestor.connect(\"weather_server\", url=\"http://localhost:8000/mcp\")\n",
"\n",
" # Ingest Resources\n",
" resources = mcp_ingestor.ingest_resources(\"weather_server\")\n",
" print(f\"Resources: {len(resources)}\")\n",
"\n",
" # Call Tool\n",
" result = mcp_ingestor.ingest_tool_output(\"weather_server\", \"get_forecast\", {\"city\": \"NYC\"})\n",
" print(f\"Tool Result: {result.content}\")\n",
"except Exception as e:\n",
" print(f\"MCP ingest failed (Server required): {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 10. Configuration\n",
"\n",
"Managing ingestion settings with `IngestConfig`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import IngestConfig, ingest_config\n",
"\n",
"# Global config\n",
"print(f\"Default Source Type: {ingest_config.get('default_source_type')}\")\n",
"\n",
"# Custom config instance\n",
"config = IngestConfig()\n",
"config.set(\"max_file_size\", 1024 * 1024) # 1MB\n",
"print(f\"Max File Size: {config.get('max_file_size')} bytes\")\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
"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/introduction/02_Data_Ingestion.ipynb)\n",
"\n",
"# Data Ingestion - Comprehensive Guide\n",
"\n",
"## Overview\n",
"\n",
"This notebook provides a comprehensive guide to Semantica's data ingestion capabilities. It covers all submodules, classes, and helper functions available in the `semantica.ingest` module.\n",
"\n",
"**Documentation**: [Ingest API Reference](https://semantica.readthedocs.io/reference/ingest/)\n",
"\n",
"### Table of Contents\n",
"\n",
"1. **Unified Ingestion**: `ingest` function\n",
"2. **File Ingestion**: `FileIngestor`, `FileTypeDetector`, `CloudStorageIngestor`\n",
"3. **Web Ingestion**: `WebIngestor`, `ContentExtractor`, `SitemapCrawler`, `RobotsChecker`\n",
"4. **Feed Ingestion**: `FeedIngestor`, `FeedMonitor`\n",
"5. **Stream Ingestion**: `StreamIngestor`, `StreamMonitor`\n",
"6. **Repository Ingestion**: `RepoIngestor`, `CodeExtractor`, `GitAnalyzer`\n",
"7. **Email Ingestion**: `EmailIngestor`, `AttachmentProcessor`\n",
"8. **Database Ingestion**: `DBIngestor`, `DatabaseConnector`\n",
"9. **MCP Ingestion**: `MCPIngestor`\n",
"10. **Configuration**: `IngestConfig`\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica with all dependencies:\n",
"\n",
"```bash\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---\n",
"\n",
"## 1. Unified Ingestion\n",
"\n",
"The `ingest` function is the main entry point for quick data loading. It automatically detects the source type.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. File Ingestion\n",
"\n",
"Detailed control over file processing using `FileIngestor` and helper classes.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import tempfile\n",
"from semantica.ingest import FileIngestor, FileTypeDetector, CloudStorageIngestor\n",
"\n",
"# Ensure dependencies from previous cells are available\n",
"if 'temp_dir' not in locals():\n",
" temp_dir = tempfile.mkdtemp()\n",
" print(f\"Created temporary directory: {temp_dir}\")\n",
"\n",
"if 'sample_file' not in locals():\n",
" sample_file = os.path.join(temp_dir, \"sample_large.txt\")\n",
"\n",
"if not os.path.exists(sample_file):\n",
" # Create a sample file with a lot of info\n",
" with open(sample_file, 'w') as f:\n",
" f.write(\"# Semantica Data Ingestion Guide\\n\\n\")\n",
" f.write(\"Semantica is a powerful framework for semantic data processing.\\n\")\n",
" # ... (more content) ...\n",
" print(f\"Created sample file: {sample_file}\")\n",
"\n",
"# --- FileTypeDetector ---\n",
"detector = FileTypeDetector()\n",
"detected_type = detector.detect_type(sample_file)\n",
"print(f\"Detected Type: {detected_type}\")\n",
"# ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Web Ingestion\n",
"\n",
"Scraping and crawling with `WebIngestor`, `ContentExtractor`, and `SitemapCrawler`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import requests\n",
"from semantica.ingest import WebIngestor, ContentExtractor, SitemapCrawler, RobotsChecker\n",
"\n",
"# --- ContentExtractor ---\n",
"# Demonstrating extraction from a real, content-rich web page\n",
"extractor = ContentExtractor()\n",
"url = \"https://en.wikipedia.org/wiki/Artificial_intelligence\"\n",
"try:\n",
" # Wikipedia requires a User-Agent header\n",
" headers = {'User-Agent': 'Semantica/1.0 (Education/Example)'}\n",
" response = requests.get(url, headers=headers)\n",
" html_content = response.text\n",
" print(f\"Fetched content from {url}\")\n",
"except Exception as e:\n",
" print(f\"Failed to fetch {url}: {e}\")\n",
" # Fallback content\n",
" html_content = \"<html><body><h1>Hello World</h1><p>This is a test.</p><a href='/link'>Link</a></body></html>\"\n",
"\n",
"text = extractor.extract_text(html_content)\n",
"links = extractor.extract_links(html_content, base_url=url)\n",
"print(f\"Extracted Text (excerpt): {text[:200]}...\")\n",
"print(f\"Found {len(links)} links\")\n",
"\n",
"# --- RobotsChecker ---\n",
"# Initialize with user agent\n",
"checker = RobotsChecker(user_agent=\"SemanticaBot\")\n",
"# Check if we can fetch a specific page (e.g. Wikipedia Special pages are often restricted)\n",
"check_url = \"https://en.wikipedia.org/wiki/Special:Search\"\n",
"can_fetch = checker.can_fetch(check_url)\n",
"print(f\"Can fetch {check_url}? {can_fetch}\")\n",
"\n",
"# --- WebIngestor ---\n",
"# Configure WebIngestor to be polite but allow the demo to run\n",
"web_ingestor = WebIngestor(\n",
" delay=1.0,\n",
" user_agent=\"Semantica/1.0 (Education/Example)\",\n",
" respect_robots=False # Disabled for this demo to ensure Wikipedia access\n",
")\n",
"try:\n",
" web_content = web_ingestor.ingest_url(url)\n",
" print(f\"Web Content Title: {web_content.title}\")\n",
"except Exception as e:\n",
" print(f\"Web ingest failed: {e}\")\n",
"\n",
"# --- SitemapCrawler ---\n",
"crawler = SitemapCrawler()\n",
"try:\n",
" # Using FastAPI documentation sitemap as a clean, technical example\n",
" sitemap_url = \"https://fastapi.tiangolo.com/sitemap.xml\"\n",
" urls = crawler.parse_sitemap(sitemap_url)\n",
" print(f\"Found {len(urls)} URLs in sitemap: {sitemap_url}\")\n",
"except Exception as e:\n",
" print(f\"Sitemap crawl failed: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Feed Ingestion\n",
"\n",
"Consuming RSS/Atom feeds with `FeedIngestor` and monitoring with `FeedMonitor`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import FeedIngestor, FeedMonitor\n",
"import time\n",
"\n",
"# --- FeedIngestor ---\n",
"feed_ingestor = FeedIngestor()\n",
"# Using Lilian Weng's AI Blog RSS feed as a reliable source\n",
"feed_url = \"https://lilianweng.github.io/index.xml\"\n",
"try:\n",
" feed_data = feed_ingestor.ingest_feed(feed_url)\n",
" print(f\"Feed Title: {feed_data.title}\")\n",
" if feed_data.items:\n",
" print(f\"Latest Post: {feed_data.items[0].title}\")\n",
"except Exception as e:\n",
" print(f\"Feed ingest failed: {e}\")\n",
"\n",
"# --- FeedMonitor ---\n",
"def feed_callback(feed_url, new_items):\n",
" print(f\"Feed Updated: {feed_url} with {len(new_items)} new items\")\n",
"\n",
"monitor = FeedMonitor(check_interval=5)\n",
"try:\n",
" monitor.add_feed(feed_url)\n",
" monitor.set_update_callback(feed_callback)\n",
" monitor.start_monitoring()\n",
" time.sleep(2) # Let it run briefly\n",
" monitor.stop_monitoring()\n",
"except Exception as e:\n",
" print(f\"Feed monitor failed: {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Stream Ingestion\n",
"\n",
"Real-time processing with `StreamIngestor` and `StreamMonitor`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import StreamIngestor, StreamMonitor\n",
"\n",
"stream_ingestor = StreamIngestor()\n",
"\n",
"# --- Kafka Processor ---\n",
"# Note: This requires a running Kafka instance. We wrap it in try-except for the demo.\n",
"kafka_config = {\"bootstrap_servers\": [\"localhost:9092\"]}\n",
"try:\n",
" kafka_processor = stream_ingestor.ingest_kafka(\"my-topic\", **kafka_config)\n",
" print(\"Kafka processor initialized.\")\n",
"except Exception as e:\n",
" print(f\"Kafka ingest skipped (requires active broker): {e}\")\n",
"\n",
"# --- RabbitMQ Processor ---\n",
"# Note: This requires a running RabbitMQ instance. We wrap it in try-except for the demo.\n",
"try:\n",
" rabbitmq_processor = stream_ingestor.ingest_rabbitmq(\"my-queue\", \"amqp://guest:guest@localhost:5672/\")\n",
" print(\"RabbitMQ processor initialized.\")\n",
"except Exception as e:\n",
" print(f\"RabbitMQ ingest skipped (requires active broker): {e}\")\n",
"\n",
"# --- Stream Monitor ---\n",
"monitor = stream_ingestor.monitor\n",
"health = monitor.check_health()\n",
"print(f\"Stream Health: {health['overall']}\")\n",
"print(f\"Processors: {list(health['processors'].keys())}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Repository Ingestion\n",
"\n",
"Analyzing codebases with `RepoIngestor`, `CodeExtractor`, and `GitAnalyzer`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import RepoIngestor, CodeExtractor, GitAnalyzer\n",
"from pathlib import Path\n",
"import os\n",
"\n",
"# --- CodeExtractor ---\n",
"code_extractor = CodeExtractor()\n",
"py_code = \"class MyClass:\\n def my_method(self):\\n pass\"\n",
"# Note: Using internal method _extract_structure for demonstration on string input\n",
"structure = code_extractor._extract_structure(py_code, language=\"python\")\n",
"print(f\"Classes: {structure.get('classes')}\")\n",
"print(f\"Functions: {structure.get('functions')}\")\n",
"\n",
"# --- RepoIngestor ---\n",
"repo_ingestor = RepoIngestor()\n",
"try:\n",
" # Ingesting a public repository (requests) for reliable demonstration\n",
" repo_data = repo_ingestor.ingest_repository(\"https://github.com/psf/requests.git\")\n",
" # Accessing repo info from the returned dictionary\n",
" repo_info = repo_data.get('repository_info', {})\n",
" print(f\"Ingested Repo URL: {repo_info.get('url')}\")\n",
" print(f\"Branches: {repo_info.get('branches')[:5]}...\") # Show first 5 branches\n",
" repo_ingestor.cleanup() # Clean up temp files\n",
"except Exception as e:\n",
" print(f\"Repo ingest failed: {e}\")\n",
"\n",
"# --- GitAnalyzer ---\n",
"try:\n",
" # Initialize analyzer\n",
" analyzer = GitAnalyzer()\n",
" \n",
" # Use current directory for demonstration\n",
" current_path = Path(\".\")\n",
" \n",
" # Metrics calculation\n",
" metrics = analyzer.calculate_metrics(current_path)\n",
" print(f\"Total Files (recursive): {metrics.get('total_files')}\")\n",
" print(f\"Total Lines: {metrics.get('total_lines')}\")\n",
"except Exception as e:\n",
" print(f\"Git analysis failed: {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Email Ingestion\n",
"\n",
"Processing emails with `EmailIngestor` and `AttachmentProcessor`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import EmailIngestor, AttachmentProcessor\n",
"import tempfile\n",
"import os\n",
"\n",
"# Create a temporary directory if not exists (though AttachmentProcessor handles its own temp dir)\n",
"temp_dir = tempfile.gettempdir()\n",
"\n",
"# --- AttachmentProcessor ---\n",
"att_processor = AttachmentProcessor()\n",
"dummy_content = b\"PDF Content\"\n",
"# Use the correct method 'process_attachment' instead of 'save_attachment'\n",
"# This method saves the file and returns metadata including the saved path\n",
"att_info = att_processor.process_attachment(dummy_content, \"doc.pdf\", \"application/pdf\")\n",
"print(f\"Saved attachment to: {att_info.get('saved_path')}\")\n",
"\n",
"# --- EmailIngestor ---\n",
"email_ingestor = EmailIngestor()\n",
"try:\n",
" # Note: This will fail without real credentials, identifying it as an example\n",
" # We wrap it in a try-block to allow the notebook to proceed\n",
" email_ingestor.connect_imap(\"imap.gmail.com\", \"user\", \"pass\")\n",
" emails = email_ingestor.ingest_mailbox(\"INBOX\", max_emails=5)\n",
" print(f\"Fetched {len(emails)} emails\")\n",
"except Exception as e:\n",
" print(f\"Email ingest skipped (Auth required): {e}\")\n",
"\n",
"# Cleanup any temp files creation by attachment processor\n",
"att_processor.cleanup_attachments()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Database Ingestion\n",
"\n",
"Connecting to SQL databases with `DBIngestor` and `DatabaseConnector`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import DBIngestor, DatabaseConnector\n",
"import sqlite3\n",
"import os\n",
"import tempfile\n",
"\n",
"# Setup SQLite DB in temp dir\n",
"temp_dir = tempfile.gettempdir()\n",
"db_path = os.path.join(temp_dir, \"test.db\")\n",
"if os.path.exists(db_path):\n",
" os.remove(db_path)\n",
"\n",
"conn = sqlite3.connect(db_path)\n",
"conn.execute(\"CREATE TABLE items (id INT, name TEXT)\")\n",
"conn.execute(\"INSERT INTO items VALUES (1, 'Item 1'), (2, 'Item 2')\")\n",
"conn.commit()\n",
"conn.close()\n",
"\n",
"# --- DatabaseConnector ---\n",
"connector = DatabaseConnector()\n",
"# Fix: Use 'connect' method, not 'create_engine'\n",
"engine = connector.connect(f\"sqlite:///{db_path}\")\n",
"# engine.name for sqlite is 'sqlite'\n",
"print(f\"Connected to DB Driver: {engine.name}\")\n",
"connector.disconnect()\n",
"\n",
"# --- DBIngestor ---\n",
"db_ingestor = DBIngestor()\n",
"# Fix: Use 'export_table' to get a single TableData object, matching the variable usage\n",
"table_data = db_ingestor.export_table(f\"sqlite:///{db_path}\", table_name=\"items\")\n",
"print(f\"Table: {table_data.table_name}\")\n",
"print(f\"Rows: {table_data.row_count}\")\n",
"print(f\"Data: {table_data.rows}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. MCP Ingestion\n",
"\n",
"Integrating with Model Context Protocol servers using `MCPIngestor`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import MCPIngestor\n",
"import logging\n",
"\n",
"# --- MCPIngestor ---\n",
"mcp_ingestor = MCPIngestor()\n",
"\n",
"# Public Daemon MCP Server\n",
"# Source: https://danielmiessler.com/p/daemon-mcp-server\n",
"mcp_server_url = \"https://mcp.daemon.danielmiessler.com\"\n",
"\n",
"try:\n",
" print(f\"Connecting to public MCP server: {mcp_server_url}...\")\n",
" \n",
" # This server supports standard JSON-RPC over HTTP\n",
" mcp_ingestor.connect(\"daemon_server\", url=mcp_server_url)\n",
"\n",
" # 1. List Available Tools\n",
" print(\"\\n--- Available Tools ---\")\n",
" tools = mcp_ingestor.list_available_tools(\"daemon_server\")\n",
" for tool in tools:\n",
" # Print first 5 tools to avoid clutter\n",
" if tools.index(tool) < 5:\n",
" print(f\"- {tool.name}: {tool.description or 'No description'}\")\n",
" if len(tools) > 5:\n",
" print(f\"... and {len(tools) - 5} more.\")\n",
"\n",
" # 2. Call Tool (get_about)\n",
" tool_name = \"get_about\"\n",
" print(f\"\\n--- Calling Tool '{tool_name}' ---\")\n",
" \n",
" result = mcp_ingestor.ingest_tool_output(\"daemon_server\", tool_name, {})\n",
" \n",
" # Parse content\n",
" content = result.content.get('content', [])\n",
" if content and isinstance(content, list):\n",
" for block in content:\n",
" if block.get('type') == 'text':\n",
" # Truncate if too long\n",
" text = block.get('text', '')\n",
" preview = text[:200] + \"...\" if len(text) > 200 else text\n",
" print(f\"Result: {preview}\")\n",
" else:\n",
" print(f\"Raw Result: {result.content}\")\n",
"\n",
"except Exception as e:\n",
" print(f\"MCP Ingestion failed: {e}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 10. Configuration\n",
"\n",
"Managing ingestion settings with `IngestConfig`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import IngestConfig, ingest_config\n",
"\n",
"# Global config\n",
"print(f\"Default Source Type: {ingest_config.get('default_source_type')}\")\n",
"\n",
"# Custom config instance\n",
"config = IngestConfig()\n",
"config.set(\"max_file_size\", 1024 * 1024) # 1MB\n",
"print(f\"Max File Size: {config.get('max_file_size')} bytes\")\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
}
@@ -38,6 +38,15 @@
"Parse various document formats using the general DocumentParser.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -163,7 +172,7 @@
"\n",
"xml_data = xml_parser.parse(xml_file)\n",
"\n",
"print(f\"Parsed XML with {len(xml_data.elements)} elements\")\n",
"print(f\"Parsed XML with {len(xml_data.root.children)} elements\")\n",
"print(f\"Root element: {xml_data.root.tag if xml_data.root else 'None'}\")\n"
]
},
@@ -251,6 +260,11 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
}
@@ -40,6 +40,15 @@
"Normalize text content for consistency.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -127,6 +136,10 @@
"metadata": {},
"outputs": [],
"source": [
"import importlib\n",
"import semantica.normalize.number_normalizer\n",
"importlib.reload(semantica.normalize.number_normalizer)\n",
"\n",
"from semantica.normalize import NumberNormalizer\n",
"\n",
"number_normalizer = NumberNormalizer()\n",
@@ -225,6 +238,11 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
}
@@ -52,6 +52,15 @@
"---"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -204,7 +213,7 @@
"metadata": {},
"outputs": [],
"source": [
"from semantica.semantic_extract.methods import get_entity_method\n",
"from semantica.semantic_extract import NERExtractor\n",
"\n",
"sample_text = \"Apple Inc. was founded by Steve Jobs in Cupertino, California in 1976.\"\n",
"\n",
@@ -219,8 +228,8 @@
" print(f\"\\n Method: {method_name.upper()}\")\n",
" print(\"-\" * 40)\n",
" \n",
" method = get_entity_method(method_name)\n",
" entities = method(sample_text)\n",
" extractor = NERExtractor(method=method_name)\n",
" entities = extractor.extract(sample_text)\n",
" \n",
" print(f\"Found {len(entities)} entities:\")\n",
" for entity in entities[:5]: # Show first 5\n",
@@ -633,9 +642,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.0"
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
}
@@ -10,7 +10,7 @@
"\n",
"## Overview\n",
"\n",
"This notebook provides a **comprehensive guide** to extracting relationships between entities and building RDF triples using Semantica's relation extraction modules. You'll learn to identify connections, extract structured triples, and prepare data for knowledge graphs.\n",
"This notebook provides a **comprehensive guide** to extracting relationships between entities and building RDF triplets using Semantica's relation extraction modules. You'll learn to identify connections, extract structured triplets, and prepare data for knowledge graphs.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/semantic_extract/)\n",
"\n",
@@ -21,21 +21,17 @@
"- Extract relationships using `RelationExtractor`\n",
"- Understand different extraction methods (pattern, dependency, co-occurrence, HuggingFace, LLM)\n",
"- Configure extraction parameters for optimal results\n",
"- Extract RDF triples with `TripleExtractor`\n",
"- Validate triples using `TripleValidator`\n",
"- Serialize triples to RDF formats with `RDFSerializer`\n",
"- Assess triple quality with `TripleQualityChecker`\n",
"- Build complete entity → relation → triple pipelines\n",
"- Extract RDF triplets with `TripletExtractor`\n",
"- Serialize triplets to RDF formats with `RDFSerializer`\n",
"- Build complete entity → relation → triplet pipelines\n",
"\n",
"### What You'll Learn\n",
"\n",
"| Component | Purpose | When to Use |\n",
"|-----------|---------|-------------|\n",
"| `RelationExtractor` | Extract entity relationships | Finding connections |\n",
"| `TripleExtractor` | Extract RDF triples | Building knowledge graphs |\n",
"| `TripleValidator` | Validate triple quality | Quality assurance |\n",
"| `TripletExtractor` | Extract RDF triplets | Building knowledge graphs |\n",
"| `RDFSerializer` | Serialize to RDF formats | Data export |\n",
"| `TripleQualityChecker` | Assess triple quality | Quality metrics |\n",
"\n",
"---\n",
"\n",
@@ -52,6 +48,15 @@
"---"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -180,7 +185,7 @@
"metadata": {},
"outputs": [],
"source": [
"from semantica.semantic_extract.methods import get_relation_method\n",
"from semantica.semantic_extract import RelationExtractor\n",
"\n",
"sample_text = \"Apple Inc. was founded by Steve Jobs in Cupertino, California.\"\n",
"sample_entities = ner_extractor.extract(sample_text)\n",
@@ -196,8 +201,8 @@
" print(f\"\\n Method: {method_name.upper()}\")\n",
" print(\"-\" * 40)\n",
" \n",
" method = get_relation_method(method_name)\n",
" relations = method(sample_text, sample_entities)\n",
" extractor = RelationExtractor(method=method_name)\n",
" relations = extractor.extract(sample_text, sample_entities)\n",
" \n",
" print(f\"Found {len(relations)} relations:\")\n",
" for rel in relations[:3]: # Show first 3\n",
@@ -327,20 +332,20 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Triple Extraction\n",
"## Step 5: Triplet Extraction\n",
"\n",
"Extract RDF triples using `TripleExtractor`. Triples are the foundation of knowledge graphs.\n",
"Extract RDF triplets using `TripletExtractor`. Triplets are the foundation of knowledge graphs.\n",
"\n",
"### What are RDF Triples?\n",
"### What are RDF Triplets?\n",
"\n",
"RDF (Resource Description Framework) triples are statements with three parts:\n",
"RDF (Resource Description Framework) triplets are statements with three parts:\n",
"- **Subject**: What we're talking about\n",
"- **Predicate**: The property or relationship\n",
"- **Object**: The value or target\n",
"\n",
"Example: `(Apple Inc., founded_by, Steve Jobs)`\n",
"\n",
"### Why Use Triples?\n",
"### Why Use Triplets?\n",
"\n",
"- **Standardized format** for knowledge representation\n",
"- **Compatible** with RDF databases and semantic web\n",
@@ -354,37 +359,37 @@
"metadata": {},
"outputs": [],
"source": [
"from semantica.semantic_extract import TripleExtractor\n",
"from semantica.semantic_extract import TripletExtractor\n",
"\n",
"# Initialize triple extractor\n",
"triple_extractor = TripleExtractor(\n",
"# Initialize triplet extractor\n",
"triplet_extractor = TripletExtractor(\n",
" include_temporal=True, # Include temporal information\n",
" include_provenance=True # Track source sentences\n",
")\n",
"\n",
"# Sample text\n",
"triple_text = \"\"\"\n",
"triplet_text = \"\"\"\n",
"Apple Inc. was founded by Steve Jobs in 1976. The company is based in Cupertino, California.\n",
"Tim Cook became CEO in 2011. Apple develops the iPhone and MacBook products.\n",
"\"\"\"\n",
"\n",
"# Extract triples\n",
"triples = triple_extractor.extract_triples(triple_text)\n",
"# Extract triplets\n",
"triplets = triplet_extractor.extract_triplets(triplet_text)\n",
"\n",
"print(f\" Extracted {len(triples)} RDF Triples:\\n\")\n",
"print(f\" Extracted {len(triplets)} RDF Triplets:\\n\")\n",
"print(\"=\" * 80)\n",
"\n",
"for i, triple in enumerate(triples, 1):\n",
" subject = triple.get('subject', '') if isinstance(triple, dict) else triple.subject\n",
" predicate = triple.get('predicate', '') if isinstance(triple, dict) else triple.predicate\n",
" obj = triple.get('object', '') if isinstance(triple, dict) else triple.object\n",
" confidence = triple.get('confidence', 1.0) if isinstance(triple, dict) else getattr(triple, 'confidence', 1.0)\n",
"for i, triplet in enumerate(triplets, 1):\n",
" subject = triplet.get('subject', '') if isinstance(triplet, dict) else triplet.subject\n",
" predicate = triplet.get('predicate', '') if isinstance(triplet, dict) else triplet.predicate\n",
" obj = triplet.get('object', '') if isinstance(triplet, dict) else triplet.object\n",
" confidence = triplet.get('confidence', 1.0) if isinstance(triplet, dict) else getattr(triplet, 'confidence', 1.0)\n",
" \n",
" print(f\"{i:2d}. ({subject}, {predicate}, {obj})\")\n",
" print(f\" Confidence: {confidence:.2f}\")\n",
" \n",
" # Show temporal info if available\n",
" metadata = triple.get('metadata', {}) if isinstance(triple, dict) else getattr(triple, 'metadata', {})\n",
" metadata = triplet.get('metadata', {}) if isinstance(triplet, dict) else getattr(triplet, 'metadata', {})\n",
" if metadata.get('temporal'):\n",
" print(f\" Temporal: {metadata['temporal']}\")\n",
" print()\n",
@@ -396,69 +401,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 6: Triple Validation\n",
"## Step 6: RDF Serialization\n",
"\n",
"Validate extracted triples using `TripleValidator` and assess quality with `TripleQualityChecker`.\n",
"\n",
"### Why Validate Triples?\n",
"\n",
"- **Ensure completeness**: All parts (subject, predicate, object) present\n",
"- **Check confidence**: Filter low-quality extractions\n",
"- **Verify consistency**: No contradictory statements\n",
"- **Assess quality**: Overall extraction quality metrics"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.semantic_extract import TripleValidator, TripleQualityChecker\n",
"\n",
"# Initialize validator and quality checker\n",
"validator = TripleValidator()\n",
"quality_checker = TripleQualityChecker()\n",
"\n",
"print(\" Triple Validation:\\n\")\n",
"print(\"=\" * 80)\n",
"\n",
"# Validate triples\n",
"valid_triples = validator.validate_triples(triples, min_confidence=0.5)\n",
"\n",
"print(f\"\\n Validation Results:\")\n",
"print(f\" Total triples: {len(triples)}\")\n",
"print(f\" Valid triples: {len(valid_triples)}\")\n",
"print(f\" Filtered out: {len(triples) - len(valid_triples)}\")\n",
"\n",
"# Check quality\n",
"quality_scores = quality_checker.calculate_quality_scores(valid_triples)\n",
"\n",
"print(f\"\\n Quality Metrics:\")\n",
"print(\"-\" * 40)\n",
"for metric, value in quality_scores.items():\n",
" if isinstance(value, float):\n",
" print(f\" {metric}: {value:.2f}\")\n",
" else:\n",
" print(f\" {metric}: {value}\")\n",
"\n",
"# Check consistency\n",
"consistency_report = validator.check_triple_consistency(valid_triples)\n",
"\n",
"print(f\"\\n Consistency Check:\")\n",
"print(f\" Consistent: {consistency_report.get('consistent', True)}\")\n",
"print(f\" Issues found: {len(consistency_report.get('issues', []))}\")\n",
"\n",
"print(\"\\n\" + \"=\" * 80)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 7: RDF Serialization\n",
"\n",
"Serialize triples to various RDF formats using `RDFSerializer`.\n",
"Serialize triplets to various RDF formats using `RDFSerializer`.\n",
"\n",
"### Supported Formats:\n",
"\n",
@@ -492,7 +437,7 @@
" print(\"-\" * 40)\n",
" \n",
" try:\n",
" serialized = serializer.serialize_to_rdf(valid_triples[:3], format=fmt) # Show first 3\n",
" serialized = serializer.serialize_to_rdf(triplets[:3], format=fmt) # Show first 3\n",
" \n",
" # Show preview (first 300 chars)\n",
" preview = serialized[:300] + \"...\" if len(serialized) > 300 else serialized\n",
@@ -508,9 +453,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 8: Complete Extraction Pipeline\n",
"## Step 7: Complete Extraction Pipeline\n",
"\n",
"Let's build a complete pipeline: **Entities → Relations → Triples**\n",
"Let's build a complete pipeline: **Entities → Relations → Triplets**\n",
"\n",
"This demonstrates the full workflow for knowledge graph construction."
]
@@ -529,7 +474,7 @@
" text: Input text\n",
" \n",
" Returns:\n",
" dict: Extracted entities, relations, and triples\n",
" dict: Extracted entities, relations, and triplets\n",
" \"\"\"\n",
" # Step 1: Extract entities\n",
" entities = ner_extractor.extract(text)\n",
@@ -537,16 +482,13 @@
" # Step 2: Extract relations\n",
" relations = relation_extractor.extract(text, entities)\n",
" \n",
" # Step 3: Extract triples\n",
" triples = triple_extractor.extract_triples(text, entities=entities, relationships=relations)\n",
" \n",
" # Step 4: Validate triples\n",
" valid_triples = validator.validate_triples(triples)\n",
" # Step 3: Extract triplets\n",
" triplets = triplet_extractor.extract_triplets(text, entities=entities, relationships=relations)\n",
" \n",
" return {\n",
" 'entities': entities,\n",
" 'relations': relations,\n",
" 'triples': valid_triples\n",
" 'triplets': triplets\n",
" }\n",
"\n",
"# Sample knowledge-rich text\n",
@@ -567,13 +509,13 @@
"print(\"-\" * 40)\n",
"print(f\"Entities extracted: {len(result['entities'])}\")\n",
"print(f\"Relations extracted: {len(result['relations'])}\")\n",
"print(f\"Triples extracted: {len(result['triples'])}\")\n",
"print(f\"Triplets extracted: {len(result['triplets'])}\")\n",
"\n",
"print(f\"\\n Sample Triples:\")\n",
"for i, triple in enumerate(result['triples'][:5], 1):\n",
" subject = triple.get('subject', '') if isinstance(triple, dict) else triple.subject\n",
" predicate = triple.get('predicate', '') if isinstance(triple, dict) else triple.predicate\n",
" obj = triple.get('object', '') if isinstance(triple, dict) else triple.object\n",
"print(f\"\\n Sample Triplets:\")\n",
"for i, triplet in enumerate(result['triplets'][:5], 1):\n",
" subject = triplet.get('subject', '') if isinstance(triplet, dict) else triplet.subject\n",
" predicate = triplet.get('predicate', '') if isinstance(triplet, dict) else triplet.predicate\n",
" obj = triplet.get('object', '') if isinstance(triplet, dict) else triplet.object\n",
" print(f\" {i}. ({subject}, {predicate}, {obj})\")\n",
"\n",
"print(\"\\n\" + \"=\" * 80)"
@@ -583,7 +525,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 9: Best Practices & Tips\n",
"## Step 8: Best Practices & Tips\n",
"\n",
"### Choosing the Right Method\n",
"\n",
@@ -597,32 +539,27 @@
"- **Set confidence thresholds** (0.6-0.7 for production)\n",
"- **Specify relation_types** to focus extraction\n",
"- **Adjust max_distance** based on text structure\n",
"- **Validate triples** before using in knowledge graphs\n",
"\n",
"### Common Pitfalls to Avoid\n",
"\n",
"- **Don't** skip entity extraction (relations need entities)\n",
"- **Don't** use very low confidence thresholds\n",
"- **Don't** ignore relation validation\n",
"- **Don't** forget to serialize triples for storage\n",
"- **Don't** forget to serialize triplets for storage\n",
"\n",
"### When to Use Each Component\n",
"\n",
"| Use Case | Recommended Component |\n",
"|----------|----------------------|\n",
"| Find entity connections | `RelationExtractor` |\n",
"| Build knowledge graphs | `TripleExtractor` |\n",
"| Quality assurance | `TripleValidator` |\n",
"| Build knowledge graphs | `TripletExtractor` |\n",
"| Export to RDF | `RDFSerializer` |\n",
"| Assess extraction quality | `TripleQualityChecker` |\n",
"\n",
"### Performance Tips\n",
"\n",
"1. **Extract entities once**, reuse for relations and triples\n",
"1. **Extract entities once**, reuse for relations and triplets\n",
"2. **Batch process** multiple documents together\n",
"3. **Cache extractors** instead of recreating\n",
"4. **Filter early** with confidence thresholds\n",
"5. **Validate incrementally** rather than all at once"
"4. **Filter early** with confidence thresholds"
]
},
{
@@ -638,25 +575,22 @@
" **Extract relationships** using `RelationExtractor` \n",
" **Compare extraction methods** (pattern, dependency, co-occurrence, HuggingFace, LLM) \n",
" **Configure extraction parameters** for optimal results \n",
" **Extract RDF triples** with `TripleExtractor` \n",
" **Validate triples** using `TripleValidator` \n",
" **Extract RDF triplets** with `TripletExtractor` \n",
" **Serialize to RDF formats** with `RDFSerializer` \n",
" **Assess quality** with `TripleQualityChecker` \n",
" **Build complete pipelines** from entities to triples \n",
" **Build complete pipelines** from entities to triplets \n",
"\n",
"### Key Takeaways\n",
"\n",
"1. **Relations connect entities**: They form the backbone of knowledge graphs\n",
"2. **Multiple methods available**: Choose based on accuracy vs speed needs\n",
"3. **Configuration is powerful**: Tune parameters for your domain\n",
"4. **Triples are standardized**: Use RDF for interoperability\n",
"5. **Validation is essential**: Ensure quality before using triples\n",
"6. **Pipelines are efficient**: Extract entities → relations → triples in sequence\n",
"4. **Triplets are standardized**: Use RDF for interoperability\n",
"5. **Pipelines are efficient**: Extract entities → relations → triplets in sequence\n",
"\n",
"### Next Steps\n",
"\n",
" **Next Notebook**: [07_Building_Knowledge_Graphs.ipynb](./07_Building_Knowledge_Graphs.ipynb) \n",
"Learn how to build complete knowledge graphs from your extracted triples!\n",
"Learn how to build complete knowledge graphs from your extracted triplets!\n",
"\n",
" **Further Reading**:\n",
"- [Semantic Extract API Reference](https://semantica.readthedocs.io/reference/semantic_extract/)\n",
@@ -690,4 +624,4 @@
},
"nbformat": 4,
"nbformat_minor": 2
}
}
@@ -10,7 +10,7 @@
"\n",
"## Overview\n",
"\n",
"This notebook demonstrates how to build knowledge graphs from entities and relationships using Semantica's graph building modules. You'll learn to use `GraphBuilder`, `EntityResolver`, and `GraphValidator`.\n",
"This notebook demonstrates how to build knowledge graphs from entities and relationships using Semantica's graph building modules. You'll learn to use `GraphBuilder` and `EntityResolver`.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/kg/)\n",
"\n",
@@ -18,7 +18,6 @@
"\n",
"- Use `GraphBuilder` to construct knowledge graphs\n",
"- Use `EntityResolver` to resolve entity conflicts\n",
"- Use `GraphValidator` to validate graph structure\n",
"**Note**: For deduplication, use the `semantica.deduplication` module.\n",
"\n",
"## Installation\n",
@@ -38,6 +37,15 @@
"Construct a knowledge graph from entities and relationships.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -60,8 +68,8 @@
"for i, entity in enumerate(entities_list[:5], 1):\n",
" entities.append({\n",
" \"id\": f\"e{i}\",\n",
" \"type\": entity.get(\"type\", \"Entity\"),\n",
" \"name\": entity.get(\"text\", entity.get(\"entity\", \"\")),\n",
" \"type\": entity.label,\n",
" \"name\": entity.text,\n",
" \"properties\": {}\n",
" })\n",
"\n",
@@ -70,14 +78,14 @@
" relationships.append({\n",
" \"source\": f\"e{1}\",\n",
" \"target\": f\"e{i+1}\",\n",
" \"type\": rel.get(\"type\", \"related_to\"),\n",
" \"type\": rel.predicate,\n",
" \"properties\": {}\n",
" })\n",
"\n",
"knowledge_graph = builder.build(entities, relationships)\n",
"\n",
"print(f\"Built knowledge graph with {len(knowledge_graph.get('entities', []))} entities\")\n",
"print(f\"Relationships: {len(knowledge_graph.get('relationships', []))}\")\n"
"print(f\"Relationships: {len(knowledge_graph.get('relationships', []))}\")"
]
},
{
@@ -99,42 +107,17 @@
"\n",
"entity_resolver = EntityResolver()\n",
"\n",
"resolved_entities = entity_resolver.resolve(entities)\n",
"resolved_entities = entity_resolver.resolve_entities(entities)\n",
"\n",
"print(f\"Original entities: {len(entities)}\")\n",
"print(f\"Resolved entities: {len(resolved_entities)}\")\n"
"print(f\"Resolved entities: {len(resolved_entities)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Graph Validation\n",
"\n",
"Validate the knowledge graph structure.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphValidator\n",
"\n",
"graph_validator = GraphValidator()\n",
"\n",
"validation_result = graph_validator.validate(knowledge_graph)\n",
"\n",
"print(f\"Graph validation: {validation_result.get('valid', False)}\")\n",
"print(f\"Issues: {len(validation_result.get('issues', []))}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Deduplication\n",
"## Step 3: Deduplication\n",
"\n",
"Remove duplicate entities from the graph.\n"
]
@@ -174,7 +157,6 @@
"\n",
"- **GraphBuilder**: Construct knowledge graphs from entities and relationships\n",
"- **EntityResolver**: Resolve entity conflicts and duplicates\n",
"- **GraphValidator**: Validate graph structure and quality\n",
"- **Deduplication**: Use `semantica.deduplication` module for removing duplicate entities\n",
"\n",
"Next: Learn how to analyze graphs in the Graph_Analytics notebook.\n"
@@ -182,8 +164,22 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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,
@@ -1,289 +1,319 @@
{
"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/introduction/09_Your_First_Knowledge_Graph.ipynb)\n",
"\n",
"# 🚀 Your First Knowledge Graph\n",
"\n",
"## Overview\n",
"\n",
"This notebook walks you through creating your first knowledge graph from a simple document. You'll learn the complete end-to-end workflow from ingesting a file to visualizing the resulting knowledge graph.\n",
"\n",
"> [!TIP]\n",
"> This is the perfect starting point if you are new to Semantica. No prior knowledge of knowledge graphs is required!\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/kg/)\n",
"\n",
"### 🎯 Learning Objectives\n",
"\n",
"- **Understand the Workflow**: Learn the `File → Parse → Extract → Graph` pipeline\n",
"- **Ingest Data**: Load documents using `FileIngestor`\n",
"- **Parse Content**: Extract text using `DocumentParser`\n",
"- **Extract Knowledge**: Identify entities using `NERExtractor`\n",
"- **Build Graph**: Construct a graph using `GraphBuilder`\n",
"- **Visualize**: See your graph come to life with `KGVisualizer`\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---\n",
"\n",
"## 🔄 Simple End-to-End Workflow\n",
"\n",
"The complete workflow consists of four main steps:\n",
"\n",
"1. **📥 Ingest** - Load data from files or other sources\n",
"2. **📄 Parse** - Extract and structure content from documents\n",
"3. **⛏️ Extract** - Identify entities and relationships\n",
"4. **🕸️ Build Graph** - Construct the knowledge graph\n",
"\n",
"Each step is demonstrated in the code cells below.\n",
"\n",
"> [!TIP]\n",
"> **Alternative: Using Semantica Framework**\n",
"> \n",
"> For a simpler, high-level approach, you can use the `Semantica` framework class which orchestrates all these steps:\n",
"> \n",
"> ```python\n",
"> from semantica.core import Semantica\n",
"> \n",
"> framework = Semantica()\n",
"> framework.initialize()\n",
"> \n",
"> result = framework.build_knowledge_base(\n",
"> sources=[\"sample_document.txt\"],\n",
"> embeddings=True,\n",
"> graph=True\n",
"> )\n",
"> \n",
"> framework.shutdown()\n",
"> ```\n",
"> \n",
"> This notebook shows the step-by-step approach for learning. See [Core Module Usage Guide](../../../semantica/core/core_usage.md) for more details.\n",
"\n",
"---\n",
"\n",
"## 📂 Step 1: Ingest a File\n",
"\n",
"In this step, we'll use `FileIngestor` to load a document. The ingestor supports various file formats including PDF, DOCX, TXT, and more.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import FileIngestor\n",
"from pathlib import Path\n",
"\n",
"# Initialize the ingestor\n",
"ingestor = FileIngestor()\n",
"\n",
"# Create a sample document for demonstration\n",
"sample_text = \"\"\"\n",
"Apple Inc. is a technology company founded by Steve Jobs, Steve Wozniak, and Ronald Wayne in 1976.\n",
"The company is headquartered in Cupertino, California.\n",
"Tim Cook is the current CEO of Apple Inc.\n",
"Apple designs and manufactures consumer electronics, software, and online services.\n",
"\"\"\"\n",
"\n",
"sample_file = Path(\"sample_document.txt\")\n",
"sample_file.write_text(sample_text)\n",
"\n",
"print(f\"File: {sample_file}\")\n",
"print(f\"Content length: {len(sample_text)} characters\")\n",
"\n",
"# Ingest the file\n",
"file_object = ingestor.ingest_file(sample_file, read_content=True)\n",
"print(f\" File name: {file_object.name}\")\n",
"print(f\" File type: {file_object.file_type}\")\n",
"print(f\" Content available: {file_object.content is not None}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 📄 Step 2: Parse the Document\n",
"\n",
"After ingesting the file, we need to parse it to extract the text content. The `DocumentParser` handles various file formats and extracts structured content.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.parse import DocumentParser\n",
"\n",
"parser = DocumentParser()\n",
"\n",
"# Parse the document to extract text\n",
"parsed_content = parser.parse_document(str(sample_file))\n",
"print(f\" Parsed content length: {len(parsed_content) if parsed_content else 0} characters\")\n",
"print(f\" Preview: {parsed_content[:200] if parsed_content else 'N/A'}...\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ⛏️ Step 3: Extract Entities\n",
"\n",
"Now we'll extract entities from the parsed text using Named Entity Recognition (NER). This identifies people, organizations, locations, dates, and other entities in the text.\n",
"\n",
"> [!NOTE]\n",
"> In a real scenario, you would use `NERExtractor` with an LLM or model backend. Here we simulate the output for demonstration purposes.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.semantic_extract import NamedEntityRecognizer, NERExtractor\n",
"\n",
"ner = NamedEntityRecognizer()\n",
"extractor = NERExtractor()\n",
"\n",
"print(f\"\\nText: {parsed_content[:100]}...\")\n",
"\n",
"# Simulated extraction results\n",
"expected_entities = [\n",
" {\"text\": \"Apple Inc.\", \"type\": \"Organization\", \"start\": 0, \"end\": 10},\n",
" {\"text\": \"Steve Jobs\", \"type\": \"Person\", \"start\": 50, \"end\": 60},\n",
" {\"text\": \"Steve Wozniak\", \"type\": \"Person\", \"start\": 62, \"end\": 75},\n",
" {\"text\": \"Ronald Wayne\", \"type\": \"Person\", \"start\": 81, \"end\": 93},\n",
" {\"text\": \"1976\", \"type\": \"Date\", \"start\": 97, \"end\": 101},\n",
" {\"text\": \"Cupertino, California\", \"type\": \"Location\", \"start\": 130, \"end\": 151},\n",
" {\"text\": \"Tim Cook\", \"type\": \"Person\", \"start\": 153, \"end\": 161},\n",
"]\n",
"\n",
"for entity in expected_entities:\n",
" print(f\" - {entity['text']} ({entity['type']})\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 🕸️ Step 4: Build the Knowledge Graph\n",
"\n",
"Using the extracted entities and relationships, we'll construct a knowledge graph. The graph represents entities as nodes and relationships as edges.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphBuilder\n",
"import networkx as nx\n",
"\n",
"builder = GraphBuilder()\n",
"\n",
"# Prepare data for graph construction\n",
"entities_data = [\n",
" {\"id\": f\"entity_{i}\", \"name\": entity[\"text\"], \"type\": entity[\"type\"]}\n",
" for i, entity in enumerate(expected_entities)\n",
"]\n",
"\n",
"relationships_data = [\n",
" {\"source\": \"entity_0\", \"target\": \"entity_1\", \"type\": \"founded_by\"},\n",
" {\"source\": \"entity_0\", \"target\": \"entity_2\", \"type\": \"founded_by\"},\n",
" {\"source\": \"entity_0\", \"target\": \"entity_3\", \"type\": \"founded_by\"},\n",
" {\"source\": \"entity_0\", \"target\": \"entity_4\", \"type\": \"founded_in\"},\n",
" {\"source\": \"entity_0\", \"target\": \"entity_5\", \"type\": \"located_in\"},\n",
" {\"source\": \"entity_6\", \"target\": \"entity_0\", \"type\": \"ceo_of\"},\n",
"]\n",
"\n",
"# Build the graph using NetworkX\n",
"kg = nx.DiGraph()\n",
"\n",
"for entity in entities_data:\n",
" kg.add_node(entity[\"id\"], name=entity[\"name\"], type=entity[\"type\"])\n",
"\n",
"for rel in relationships_data:\n",
" source_name = entities_data[int(rel[\"source\"].split(\"_\")[1])][\"name\"]\n",
" target_name = entities_data[int(rel[\"target\"].split(\"_\")[1])][\"name\"]\n",
" kg.add_edge(rel[\"source\"], rel[\"target\"], type=rel[\"type\"])\n",
"\n",
"print(f\" Nodes (entities): {len(kg.nodes)}\")\n",
"print(f\" Edges (relationships): {len(kg.edges)}\")\n",
"\n",
"for node_id in kg.nodes():\n",
" node_data = kg.nodes[node_id]\n",
" print(f\" Node: {node_data['name']} ({node_data['type']})\")\n",
"\n",
"for source, target, data in kg.edges(data=True):\n",
" source_name = kg.nodes[source]['name']\n",
" target_name = kg.nodes[target]['name']\n",
" print(f\" {source_name} --[{data['type']}]--> {target_name}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 📊 Step 5: Visualize and Analyze\n",
"\n",
"Finally, we'll visualize the knowledge graph and analyze its structure. This helps you understand the relationships and entities in your data.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.visualization import KGVisualizer\n",
"\n",
"visualizer = KGVisualizer()\n",
"\n",
"print(f\" Total entities: {len(kg.nodes)}\")\n",
"print(f\" Total relationships: {len(kg.edges)}\")\n",
"\n",
"entity_types = {}\n",
"for node_id in kg.nodes():\n",
" entity_type = kg.nodes[node_id]['type']\n",
" entity_types[entity_type] = entity_types.get(entity_type, 0) + 1\n",
"\n",
"for etype, count in entity_types.items():\n",
" print(f\" - {etype}: {count}\")\n",
"\n",
"rel_types = {}\n",
"for _, _, data in kg.edges(data=True):\n",
" rel_type = data.get('type', 'unknown')\n",
" rel_types[rel_type] = rel_types.get(rel_type, 0) + 1\n",
"\n",
"for rtype, count in rel_types.items():\n",
" print(f\" - {rtype}: {count}\")\n",
"\n",
"# Cleanup\n",
"if sample_file.exists():\n",
" sample_file.unlink()\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
"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/introduction/09_Your_First_Knowledge_Graph.ipynb)\n",
"\n",
"# 🚀 Your First Knowledge Graph\n",
"\n",
"## Overview\n",
"\n",
"This notebook walks you through creating your first knowledge graph from a simple document. You'll learn the complete end-to-end workflow from ingesting a file to visualizing the resulting knowledge graph.\n",
"\n",
"> [!TIP]\n",
"> This is the perfect starting point if you are new to Semantica. No prior knowledge of knowledge graphs is required!\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/kg/)\n",
"\n",
"### 🎯 Learning Objectives\n",
"\n",
"- **Understand the Workflow**: Learn the `File → Parse → Extract → Graph` pipeline\n",
"- **Ingest Data**: Load documents using `FileIngestor`\n",
"- **Parse Content**: Extract text using `DocumentParser`\n",
"- **Extract Knowledge**: Identify entities using `NERExtractor`\n",
"- **Build Graph**: Construct a graph using `GraphBuilder`\n",
"- **Visualize**: See your graph come to life with `KGVisualizer`\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---\n",
"\n",
"## 🔄 Simple End-to-End Workflow\n",
"\n",
"The complete workflow consists of four main steps:\n",
"\n",
"1. **📥 Ingest** - Load data from files or other sources\n",
"2. **📄 Parse** - Extract and structure content from documents\n",
"3. **⛏️ Extract** - Identify entities and relationships\n",
"4. **🕸️ Build Graph** - Construct the knowledge graph\n",
"\n",
"Each step is demonstrated in the code cells below.\n",
"\n",
"> [!TIP]\n",
"> **Alternative: Using Semantica Framework**\n",
"> \n",
"> For a simpler, high-level approach, you can use the `Semantica` framework class which orchestrates all these steps:\n",
"> \n",
"> ```python\n",
"> from semantica.core import Semantica\n",
"> \n",
"> framework = Semantica()\n",
"> framework.initialize()\n",
"> \n",
"> result = framework.build_knowledge_base(\n",
"> sources=[\"sample_document.txt\"],\n",
"> embeddings=True,\n",
"> graph=True\n",
"> )\n",
"> \n",
"> framework.shutdown()\n",
"> ```\n",
"> \n",
"> This notebook shows the step-by-step approach for learning. See [Core Module Usage Guide](../../../semantica/core/core_usage.md) for more details.\n",
"\n",
"---\n",
"\n",
"## 📂 Step 1: Ingest a File\n",
"\n",
"In this step, we'll use `FileIngestor` to load a document. The ingestor supports various file formats including PDF, DOCX, TXT, and more.\n"
]
},
"nbformat": 4,
"nbformat_minor": 2
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.ingest import FileIngestor\n",
"from pathlib import Path\n",
"\n",
"# Initialize the ingestor\n",
"ingestor = FileIngestor()\n",
"\n",
"# Create a sample document for demonstration\n",
"sample_text = \"\"\"\n",
"Apple Inc. is a technology company founded by Steve Jobs, Steve Wozniak, and Ronald Wayne in 1976.\n",
"The company is headquartered in Cupertino, California.\n",
"Tim Cook is the current CEO of Apple Inc.\n",
"Apple designs and manufactures consumer electronics, software, and online services.\n",
"\"\"\"\n",
"\n",
"sample_file = Path(\"sample_document.txt\")\n",
"sample_file.write_text(sample_text)\n",
"\n",
"print(f\"File: {sample_file}\")\n",
"print(f\"Content length: {len(sample_text)} characters\")\n",
"\n",
"# Ingest the file\n",
"file_object = ingestor.ingest_file(sample_file, read_content=True)\n",
"print(f\" File name: {file_object.name}\")\n",
"print(f\" File type: {file_object.file_type}\")\n",
"print(f\" Content available: {file_object.content is not None}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 📄 Step 2: Parse the Document\n",
"\n",
"After ingesting the file, we need to parse it to extract the text content. The `DocumentParser` handles various file formats and extracts structured content.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.parse import DocumentParser\n",
"\n",
"parser = DocumentParser()\n",
"# Parse the document to extract text\n",
"parsed_document = parser.parse_document(str(sample_file))\n",
"parsed_content = parsed_document.get(\"content\", \"\")\n",
"print(f\" Parsed content length: {len(parsed_content) if parsed_content else 0} characters\")\n",
"print(f\" Preview: {parsed_content[:200] if parsed_content else 'N/A'}...\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ⛏️ Step 3: Extract Entities\n",
"\n",
"Now we'll extract entities from the parsed text using Named Entity Recognition (NER). This identifies people, organizations, locations, dates, and other entities in the text.\n",
"\n",
"> [!NOTE]\n",
"> In a real scenario, you would use `NERExtractor` with an LLM or model backend. Here we simulate the output for demonstration purposes.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.semantic_extract import NamedEntityRecognizer, NERExtractor\n",
"\n",
"ner = NamedEntityRecognizer()\n",
"extractor = NERExtractor()\n",
"\n",
"print(f\"\\nText: {parsed_content[:100]}...\")\n",
"\n",
"# Simulated extraction results\n",
"expected_entities = [\n",
" {\"text\": \"Apple Inc.\", \"type\": \"Organization\", \"start\": 0, \"end\": 10},\n",
" {\"text\": \"Steve Jobs\", \"type\": \"Person\", \"start\": 50, \"end\": 60},\n",
" {\"text\": \"Steve Wozniak\", \"type\": \"Person\", \"start\": 62, \"end\": 75},\n",
" {\"text\": \"Ronald Wayne\", \"type\": \"Person\", \"start\": 81, \"end\": 93},\n",
" {\"text\": \"1976\", \"type\": \"Date\", \"start\": 97, \"end\": 101},\n",
" {\"text\": \"Cupertino, California\", \"type\": \"Location\", \"start\": 130, \"end\": 151},\n",
" {\"text\": \"Tim Cook\", \"type\": \"Person\", \"start\": 153, \"end\": 161},\n",
"]\n",
"\n",
"for entity in expected_entities:\n",
" print(f\" - {entity['text']} ({entity['type']})\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 🕸️ Step 4: Build the Knowledge Graph\n",
"\n",
"Using the extracted entities and relationships, we'll construct a knowledge graph. The graph represents entities as nodes and relationships as edges.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphBuilder\n",
"import networkx as nx\n",
"\n",
"builder = GraphBuilder()\n",
"\n",
"# Prepare data for graph construction\n",
"entities_data = [\n",
" {\"id\": f\"entity_{i}\", \"name\": entity[\"text\"], \"type\": entity[\"type\"]}\n",
" for i, entity in enumerate(expected_entities)\n",
"]\n",
"\n",
"relationships_data = [\n",
" {\"source\": \"entity_0\", \"target\": \"entity_1\", \"type\": \"founded_by\"},\n",
" {\"source\": \"entity_0\", \"target\": \"entity_2\", \"type\": \"founded_by\"},\n",
" {\"source\": \"entity_0\", \"target\": \"entity_3\", \"type\": \"founded_by\"},\n",
" {\"source\": \"entity_0\", \"target\": \"entity_4\", \"type\": \"founded_in\"},\n",
" {\"source\": \"entity_0\", \"target\": \"entity_5\", \"type\": \"located_in\"},\n",
" {\"source\": \"entity_6\", \"target\": \"entity_0\", \"type\": \"ceo_of\"},\n",
"]\n",
"\n",
"# Build the graph using NetworkX\n",
"kg = nx.DiGraph()\n",
"\n",
"for entity in entities_data:\n",
" kg.add_node(entity[\"id\"], name=entity[\"name\"], type=entity[\"type\"])\n",
"\n",
"for rel in relationships_data:\n",
" source_name = entities_data[int(rel[\"source\"].split(\"_\")[1])][\"name\"]\n",
" target_name = entities_data[int(rel[\"target\"].split(\"_\")[1])][\"name\"]\n",
" kg.add_edge(rel[\"source\"], rel[\"target\"], type=rel[\"type\"])\n",
"\n",
"print(f\" Nodes (entities): {len(kg.nodes)}\")\n",
"print(f\" Edges (relationships): {len(kg.edges)}\")\n",
"\n",
"for node_id in kg.nodes():\n",
" node_data = kg.nodes[node_id]\n",
" print(f\" Node: {node_data['name']} ({node_data['type']})\")\n",
"\n",
"for source, target, data in kg.edges(data=True):\n",
" source_name = kg.nodes[source]['name']\n",
" target_name = kg.nodes[target]['name']\n",
" print(f\" {source_name} --[{data['type']}]--> {target_name}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 📊 Step 5: Visualize and Analyze\n",
"\n",
"Finally, we'll visualize the knowledge graph and analyze its structure. This helps you understand the relationships and entities in your data.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.visualization import KGVisualizer\n",
"\n",
"visualizer = KGVisualizer()\n",
"\n",
"print(f\" Total entities: {len(kg.nodes)}\")\n",
"print(f\" Total relationships: {len(kg.edges)}\")\n",
"\n",
"entity_types = {}\n",
"for node_id in kg.nodes():\n",
" entity_type = kg.nodes[node_id]['type']\n",
" entity_types[entity_type] = entity_types.get(entity_type, 0) + 1\n",
"\n",
"for etype, count in entity_types.items():\n",
" print(f\" - {etype}: {count}\")\n",
"\n",
"rel_types = {}\n",
"for _, _, data in kg.edges(data=True):\n",
" rel_type = data.get('type', 'unknown')\n",
" rel_types[rel_type] = rel_types.get(rel_type, 0) + 1\n",
"\n",
"for rtype, count in rel_types.items():\n",
" print(f\" - {rtype}: {count}\")\n",
"\n",
"# Cleanup\n",
"if sample_file.exists():\n",
" sample_file.unlink()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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
}
+29 -14
View File
@@ -54,7 +54,6 @@
"# For Neo4j (requires Neo4j server)\n",
"pip install neo4j\n",
"\n",
"# For FalkorDB (requires Redis/FalkorDB server)\n",
"pip install falkordb\n",
"```\n",
@@ -81,6 +80,15 @@
"**Recommendation**: Use **Neo4j** for enterprise production systems or **FalkorDB** for high-performance real-time applications.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -98,25 +106,18 @@
"source": [
"from semantica.graph_store import GraphStore\n",
"\n",
"# Option 1: Neo4j (requires Neo4j server running)\n",
"# Neo4j AuraDB Connection Details\n",
"# Replace these values with your actual AuraDB credentials\n",
"store = GraphStore(\n",
" backend=\"neo4j\",\n",
" uri=\"bolt://localhost:7687\",\n",
" uri=\"Your URI\", # Your AuraDB Instance URI\n",
" user=\"neo4j\",\n",
" password=\"password\"\n",
" password=\"Your Password\" # Please enter your password here\n",
")\n",
"\n",
"# Option 2: FalkorDB (requires Redis/FalkorDB server)\n",
"# store = GraphStore(\n",
"# backend=\"falkordb\",\n",
"# host=\"localhost\",\n",
"# port=6379,\n",
"# graph_name=\"demo_graph\"\n",
"# )\n",
"\n",
"# Connect to the database\n",
"store.connect()\n",
"print(\"Connected to graph database successfully!\")\n"
"print(\"Connected to graph database successfully!\")"
]
},
{
@@ -592,8 +593,22 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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,
+31 -4
View File
@@ -39,6 +39,15 @@
"Analyze graph structure and properties.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -118,11 +127,15 @@
"\n",
"community_detector = CommunityDetector()\n",
"\n",
"communities = community_detector.detect_communities(kg)\n",
"# Get detection result\n",
"result = community_detector.detect_communities(kg)\n",
"\n",
"# Extract communities list from result dictionary\n",
"communities = result.get(\"communities\", [])\n",
"\n",
"print(f\"Detected {len(communities)} communities\")\n",
"for i, community in enumerate(communities[:3], 1):\n",
" print(f\" Community {i}: {len(community)} entities\")\n"
" print(f\" Community {i}: {len(community)} entities\")"
]
},
{
@@ -164,13 +177,27 @@
"- **CommunityDetector**: Detect communities in graphs\n",
"- **ConnectivityAnalyzer**: Analyze graph connectivity\n",
"\n",
"Next: Learn how to assess graph quality in the Graph_Quality notebook.\n"
"Next: Learn how to deduplicate entities in the Deduplication notebook.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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,
File diff suppressed because it is too large Load Diff
@@ -1,178 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Notice**: The `semantica.kg_qa` module is temporarily unavailable and will be reintroduced in a future release. The quality assessment examples in this notebook are disabled."
]
},
{
"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/introduction/12_Graph_Quality.ipynb)\n",
"\n",
"# Graph Quality\n",
"\n",
"## Overview\n",
"\n",
"This notebook demonstrates how to assess and improve knowledge graph quality using Semantica's quality assurance modules. You'll learn to use `KGQualityAssessor`, `ConsistencyChecker`, `CompletenessValidator`, and `QualityMetrics`.\n",
"\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/kg_qa/)\n",
"\n",
"### Learning Objectives\n",
"\n",
"- Use `KGQualityAssessor` for overall quality assessment\n",
"- Use `ConsistencyChecker` to validate consistency\n",
"- Use `CompletenessValidator` to check completeness\n",
"- Use `QualityMetrics` to calculate quality metrics\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---\n",
"\n",
"## Step 1: Quality Assessment\n",
"\n",
"Assess overall graph quality.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.kg import GraphBuilder\n",
"\n",
"builder = GraphBuilder()\n",
"\n",
"entities = [\n",
" {\"id\": \"e1\", \"type\": \"Organization\", \"name\": \"Apple Inc.\", \"properties\": {}}\n",
"]\n",
"\n",
"relationships = []\n",
"\n",
"kg = builder.build(entities, relationships)\n",
"\n",
"quality_score = assessor.assess_overall_quality(kg)\n",
"\n",
"print(f\"Overall quality score: {quality_score.get('overall_score', 0):.3f}\")\n",
"print(f\"Completeness: {quality_score.get('completeness', 0):.3f}\")\n",
"print(f\"Consistency: {quality_score.get('consistency', 0):.3f}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Consistency Checking\n",
"\n",
"Check graph consistency.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"consistency_checker = ConsistencyChecker()\n",
"\n",
"consistency_result = consistency_checker.check_consistency(kg)\n",
"\n",
"print(f\"Consistency check:\")\n",
"print(f\" Is consistent: {consistency_result.get('is_consistent', False)}\")\n",
"print(f\" Issues: {len(consistency_result.get('issues', []))}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Completeness Validation\n",
"\n",
"Validate graph completeness.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"completeness_validator = CompletenessValidator()\n",
"\n",
"completeness_result = completeness_validator.validate_completeness(kg)\n",
"\n",
"print(f\"Completeness validation:\")\n",
"print(f\" Is complete: {completeness_result.get('is_complete', False)}\")\n",
"print(f\" Missing properties: {len(completeness_result.get('missing_properties', []))}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Quality Metrics\n",
"\n",
"Calculate detailed quality metrics.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"quality_metrics = QualityMetrics()\n",
"\n",
"metrics = quality_metrics.calculate_metrics(kg)\n",
"\n",
"print(f\"Quality metrics:\")\n",
"print(f\" Entity coverage: {metrics.get('entity_coverage', 0):.3f}\")\n",
"print(f\" Relationship coverage: {metrics.get('relationship_coverage', 0):.3f}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"You've learned how to assess graph quality:\n",
"\n",
"- **KGQualityAssessor**: Overall quality assessment\n",
"- **ConsistencyChecker**: Consistency validation\n",
"- **CompletenessValidator**: Completeness validation\n",
"- **QualityMetrics**: Detailed quality metrics\n",
"\n",
"Next: Learn how to deduplicate entities in the Deduplication notebook.\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@@ -39,6 +39,15 @@
"Generate embeddings using EmbeddingGenerator.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica\n"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -133,6 +142,11 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+31 -22
View File
@@ -74,6 +74,15 @@
"- `export_relationships()` - Export relationships to JSON\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install semantica"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -166,7 +175,7 @@
"rdf_exporter = RDFExporter()\n",
"\n",
"# Export to RDF format (Turtle by default)\n",
"rdf_exporter.export_knowledge_graph(kg, \"output.ttl\", format=\"turtle\")\n"
"rdf_exporter.export(kg, \"output.ttl\", format=\"turtle\")"
]
},
{
@@ -237,10 +246,14 @@
"generator = OntologyGenerator()\n",
"\n",
"# Generate ontology from entities and relationships\n",
"ontology = generator.generate(entities, relationships)\n",
"# Note: Pass data as a dictionary to generate_ontology\n",
"ontology = generator.generate_ontology({\n",
" \"entities\": entities,\n",
" \"relationships\": relationships\n",
"})\n",
"\n",
"# Export ontology to OWL\n",
"owl_exporter.export(ontology, \"output.owl\")\n"
"owl_exporter.export(ontology, \"output.owl\")"
]
},
{
@@ -295,24 +308,6 @@
"- `json` - JSON report\n",
"- `text` - Plain text report\n",
"\n",
"## Step 7: Method Registry\n",
"\n",
"Register and use custom export methods using the MethodRegistry system:\n",
"\n",
"```python\n",
"from semantica.export import MethodRegistry, method_registry, JSONExporter\n",
"\n",
"# Register custom method\n",
"def my_custom_export(data, file_path, **kwargs):\n",
" # Custom export logic\n",
" pass\n",
"\n",
"MethodRegistry.register(\"json\", \"custom\", my_custom_export)\n",
"\n",
"# List available methods\n",
"methods = method_registry.list_all()\n",
"print(methods)\n",
"```\n",
"\n",
"## Summary\n",
"\n",
@@ -348,8 +343,22 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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,
+44 -42
View File
@@ -37,6 +37,15 @@
"Visualize knowledge graphs.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install -q semantica"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -82,11 +91,14 @@
"from semantica.ontology import OntologyGenerator\n",
"\n",
"ontology_visualizer = OntologyVisualizer()\n",
"generator = OntologyGenerator()\n",
"# Initialize generator with min_occurrences=1 to allow single-instance classes\n",
"generator = OntologyGenerator(min_occurrences=1)\n",
"\n",
"ontology = generator.generate(entities, relationships)\n",
"# Generate ontology using the correct method signature (dictionary input)\n",
"ontology = generator.generate_ontology({\"entities\": entities, \"relationships\": relationships})\n",
"\n",
"visualization = ontology_visualizer.visualize_hierarchy(ontology, output=\"interactive\")\n"
"# Visualize the hierarchy\n",
"visualization = ontology_visualizer.visualize_hierarchy(ontology, output=\"interactive\")"
]
},
{
@@ -135,50 +147,26 @@
"source": [
"from semantica.visualization import SemanticNetworkVisualizer\n",
"\n",
"# Initialize (uses new defaults: Vibrant colors, Kamada-Kawai layout)\n",
"viz = SemanticNetworkVisualizer()\n",
"\n",
"# Your semantic network data\n",
"semantic_network = {\n",
" \"nodes\": [\n",
" {\"id\": \"n1\", \"label\": \"Node 1\", \"type\": \"Entity\"},\n",
" {\"id\": \"n2\", \"label\": \"Node 2\", \"type\": \"Entity\"}\n",
" {\"id\": \"n1\", \"label\": \"Python\", \"type\": \"Language\"},\n",
" {\"id\": \"n2\", \"label\": \"Code\", \"type\": \"Concept\"}\n",
" ],\n",
" \"edges\": [\n",
" {\"source\": \"n1\", \"target\": \"n2\", \"label\": \"related_to\"}\n",
" {\"source\": \"n1\", \"target\": \"n2\", \"label\": \"writes\"}\n",
" ]\n",
"}\n",
"\n",
"sem_viz = SemanticNetworkVisualizer()\n",
"sem_viz.visualize_network(semantic_network, output=\"interactive\")\n",
"sem_viz.visualize_node_types(semantic_network, output=\"interactive\")\n",
"sem_viz.visualize_edge_types(semantic_network, output=\"interactive\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Advanced Embedding Visualization\n",
"\n",
"Compare multi-modal embeddings and assess embedding quality."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from semantica.visualization import EmbeddingVisualizer\n",
"\n",
"# Synthetic multi-modal embeddings (text, image, audio)\n",
"text_emb = np.random.rand(50, 128)\n",
"image_emb = np.random.rand(50, 128)\n",
"audio_emb = np.random.rand(50, 128)\n",
"\n",
"emb_viz = EmbeddingVisualizer()\n",
"emb_viz.visualize_multimodal_comparison(text_emb, image_emb, audio_emb, output=\"interactive\")\n",
"\n",
"# Embedding quality metrics\n",
"quality_fig = emb_viz.visualize_quality_metrics(text_emb, output=\"interactive\")\n"
"# This will now display the interactive graph in the notebook cell\n",
"viz.visualize_network(\n",
" semantic_network, \n",
" output=\"html\", \n",
" file_path=\"network_graph.html\"\n",
")"
]
},
{
@@ -191,7 +179,7 @@
"\n",
"- **KGVisualizer**: Visualize knowledge graphs\n",
"- **OntologyVisualizer**: Visualize ontologies\n",
"- **EmbeddingVisualizer**: Visualize embeddings, multi-modal and quality metrics\n",
"- **EmbeddingVisualizer**: Visualize embeddings, multi-modal\n",
"- **SemanticNetworkVisualizer**: Visualize semantic network structure and type distributions\n",
"\n",
"Next: Learn how to detect conflicts in the Conflict_Detection notebook.\n"
@@ -199,8 +187,22 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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,
@@ -1,604 +0,0 @@
{
"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/introduction/18_Conflict_Detection.ipynb)\n",
"\n",
"# Conflict Detection\n",
"\n",
"## Overview\n",
"\n",
"This notebook demonstrates how to detect and resolve conflicts in knowledge graphs using Semantica's conflict modules. You'll learn to use `ConflictDetector`, `SourceTracker`, and `ConflictResolver`.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/conflicts/)\n",
"\n",
"### Learning Objectives\n",
"\n",
"- Use `ConflictDetector` to detect conflicts\n",
"- Use `SourceTracker` to track data sources\n",
"- Use `ConflictResolver` to resolve conflicts\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---\n",
"\n",
"## Step 1: Conflict Detection\n",
"\n",
"Detect conflicts in entities.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import ConflictDetector\n",
"from datetime import datetime\n",
"\n",
"# Initialize detector with configuration\n",
"detector = ConflictDetector(\n",
" confidence_threshold=0.7,\n",
" track_provenance=True,\n",
" conflict_fields={\"Company\": [\"name\", \"founded\", \"revenue\"]}\n",
")\n",
"\n",
"# Sample entities from multiple sources\n",
"entities = [\n",
" {\"id\": \"e1\", \"name\": \"Apple Inc.\", \"founded\": 1976, \"type\": \"Company\", \n",
" \"source\": \"wikipedia\", \"confidence\": 0.9},\n",
" {\"id\": \"e1\", \"name\": \"Apple Incorporated\", \"founded\": 1976, \"type\": \"Company\",\n",
" \"source\": \"official_site\", \"confidence\": 0.95},\n",
" {\"id\": \"e1\", \"name\": \"Apple Inc.\", \"founded\": 1977, \"type\": \"Company\",\n",
" \"source\": \"news\", \"confidence\": 0.7},\n",
" {\"id\": \"e2\", \"name\": \"Microsoft\", \"type\": \"Company\", \"founded\": 1975, \"source\": \"source1\"},\n",
" {\"id\": \"e2\", \"name\": \"Microsoft Corporation\", \"type\": \"Organization\", \n",
" \"founded\": 1975, \"source\": \"source2\"},\n",
"]\n",
"\n",
"# 1.1 Value Conflict Detection\n",
"value_conflicts = detector.detect_value_conflicts(entities, \"name\")\n",
"\n",
"# 1.2 Type Conflict Detection\n",
"type_conflicts = detector.detect_type_conflicts(entities)\n",
"\n",
"# 1.3 Temporal Conflict Detection\n",
"temporal_conflicts = detector.detect_temporal_conflicts(entities)\n",
"\n",
"# 1.4 Logical Conflict Detection\n",
"logical_entities = [\n",
" {\"id\": \"e3\", \"type\": \"Person\", \"name\": \"John Doe\", \"source\": \"source1\"},\n",
" {\"id\": \"e3\", \"type\": \"Organization\", \"name\": \"John Doe\", \"source\": \"source2\"},\n",
"]\n",
"logical_conflicts = detector.detect_logical_conflicts(logical_entities)\n",
"\n",
"# 1.5 Relationship Conflict Detection\n",
"relationships = [\n",
" {\"id\": \"rel1\", \"source_id\": \"e1\", \"target_id\": \"e2\", \"type\": \"competes_with\", \"source\": \"source1\"},\n",
" {\"id\": \"rel1\", \"source_id\": \"e1\", \"target_id\": \"e2\", \"type\": \"partners_with\", \"source\": \"source2\"},\n",
"]\n",
"rel_conflicts = detector.detect_relationship_conflicts(relationships)\n",
"\n",
"# 1.6 General Conflict Detection (all types)\n",
"all_conflicts = detector.detect_conflicts(entities)\n",
"\n",
"# Get conflict report\n",
"report = detector.get_conflict_report()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Source Tracking\n",
"\n",
"Track data sources.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import SourceTracker, SourceReference\n",
"from datetime import datetime\n",
"\n",
"# Initialize source tracker\n",
"tracker = SourceTracker()\n",
"\n",
"# Create source references with metadata\n",
"source1 = SourceReference(\n",
" document=\"wikipedia\",\n",
" page=1,\n",
" section=\"Company Information\",\n",
" timestamp=datetime(2023, 1, 15),\n",
" confidence=0.9\n",
")\n",
"\n",
"source2 = SourceReference(\n",
" document=\"official_site\",\n",
" section=\"About Us\",\n",
" timestamp=datetime(2023, 3, 20),\n",
" confidence=0.95\n",
")\n",
"\n",
"# Track property sources\n",
"tracker.track_property_source(\"e1\", \"name\", \"Apple Inc.\", source1)\n",
"tracker.track_property_source(\"e1\", \"name\", \"Apple Incorporated\", source2)\n",
"tracker.track_property_source(\"e1\", \"founded\", 1976, source1)\n",
"\n",
"# Track entity sources\n",
"tracker.track_entity_source(\"e1\", source1)\n",
"\n",
"# Set source credibility scores\n",
"tracker.set_source_credibility(\"wikipedia\", 0.85)\n",
"tracker.set_source_credibility(\"official_site\", 0.95)\n",
"\n",
"# Retrieve property sources\n",
"prop_source = tracker.get_property_sources(\"e1\", \"name\")\n",
"\n",
"# Get entity sources\n",
"entity_sources = tracker.get_entity_sources(\"e1\")\n",
"\n",
"# Get all source credibilities\n",
"all_credibilities = tracker.get_all_source_credibilities()\n",
"\n",
"# Generate traceability chain\n",
"chain = tracker.generate_traceability_chain(\"e1\", \"name\")\n",
"\n",
"# Generate source report\n",
"report = tracker.generate_source_report(\"e1\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Conflict Resolution\n",
"\n",
"Resolve conflicts using ConflictResolver.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import ConflictResolver\n",
"\n",
"# Initialize resolver with source tracker\n",
"resolver = ConflictResolver(\n",
" default_strategy=\"voting\",\n",
" source_tracker=tracker\n",
")\n",
"\n",
"# Resolve conflicts using different strategies\n",
"if value_conflicts:\n",
" # Voting strategy\n",
" voting_results = resolver.resolve_conflicts(value_conflicts, strategy=\"voting\")\n",
" \n",
" # Credibility-weighted strategy\n",
" credibility_results = resolver.resolve_conflicts(value_conflicts, strategy=\"credibility_weighted\")\n",
" \n",
" # Most recent strategy\n",
" recent_results = resolver.resolve_conflicts(value_conflicts, strategy=\"most_recent\")\n",
" \n",
" # Highest confidence strategy\n",
" confidence_results = resolver.resolve_conflicts(value_conflicts, strategy=\"highest_confidence\")\n",
" \n",
" # First seen strategy\n",
" first_seen_results = resolver.resolve_conflicts(value_conflicts, strategy=\"first_seen\")\n",
" \n",
" # Manual review strategy\n",
" manual_results = resolver.resolve_conflicts(value_conflicts, strategy=\"manual_review\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"You've learned how to detect and resolve conflicts:\n",
"\n",
"- **ConflictDetector**: Detect conflicts in entities\n",
"- **SourceTracker**: Track data sources\n",
"- **ConflictResolver**: Resolve conflicts using various strategies\n",
"\n",
"Next: Learn about configuration in the Configuration notebook.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import ConflictAnalyzer\n",
"\n",
"# Initialize analyzer\n",
"analyzer = ConflictAnalyzer()\n",
"\n",
"# Comprehensive analysis\n",
"analysis = analyzer.analyze_conflicts(all_conflicts)\n",
"\n",
"# Analysis by type, severity, and source\n",
"by_type = analysis['by_type']['counts']\n",
"by_severity = analysis['by_severity']['counts']\n",
"by_source = analysis['by_source']['counts']\n",
"\n",
"# Top entities and properties\n",
"top_entities = analysis['by_entity']['top_entities']\n",
"top_properties = analysis['by_property']['top_properties']\n",
"\n",
"# Patterns and recommendations\n",
"patterns = analysis['patterns']\n",
"recommendations = analysis['recommendations']\n",
"\n",
"# Trend analysis\n",
"trends = analyzer.analyze_trends(all_conflicts)\n",
"\n",
"# Generate insights report\n",
"insights = analyzer.generate_insights_report(all_conflicts)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 5: Investigation Guides\n",
"\n",
"`InvestigationGuideGenerator` creates guides for manual review.\n",
"\n",
"**Guide Components:**\n",
"- Conflict summary, investigation steps, recommended actions\n",
"- Source information, context, severity assessment\n",
"\n",
"**Use Cases:** High-severity conflicts, ambiguous cases, compliance, QA workflows\n",
"\n",
"**Export Formats:** Markdown checklists, detailed reports, structured context\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import InvestigationGuideGenerator\n",
"\n",
"# Initialize guide generator\n",
"guide_generator = InvestigationGuideGenerator(source_tracker=tracker)\n",
"\n",
"# Generate guide for a conflict\n",
"if value_conflicts:\n",
" guide = guide_generator.generate_guide(value_conflicts[0])\n",
"\n",
"# Generate guides for multiple conflicts\n",
"guides = guide_generator.generate_guides(value_conflicts[:3])\n",
"\n",
"# Export checklist\n",
"checklist = guide_generator.export_investigation_checklist(guide, format=\"markdown\")\n",
"\n",
"# Generate conflict report\n",
"conflict_report = guide_generator.generate_conflict_report(value_conflicts, format=\"detailed\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 6: Methods Module\n",
"\n",
"`semantica.conflicts.methods` provides convenience functions for functional-style access.\n",
"\n",
"**Functions:**\n",
"- `detect_conflicts()`: Methods: `value`, `type`, `temporal`, `logical`, `relationship`\n",
"- `resolve_conflicts()`: Methods: `voting`, `credibility_weighted`, `most_recent`, `highest_confidence`, `first_seen`, `manual_review`\n",
"- `analyze_conflicts()`: Methods: `pattern`, `type`, `severity`, `source`, `trend`\n",
"- `track_sources()`: Methods: `property`, `entity`, `relationship`\n",
"- `generate_investigation_guide()`: Methods: `guide`, `checklist`, `context`\n",
"- `list_available_methods()`: List all methods by task type\n",
"- `get_conflict_method()`: Retrieve specific method function\n",
"\n",
"**Benefits:** Simpler API, method discovery, consistent interface, extensible\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts.methods import (\n",
" detect_conflicts,\n",
" resolve_conflicts,\n",
" analyze_conflicts,\n",
" track_sources,\n",
" generate_investigation_guide,\n",
" list_available_methods,\n",
" get_conflict_method\n",
")\n",
"\n",
"# Detection methods\n",
"value_conflicts_method = detect_conflicts(entities, method=\"value\", property_name=\"name\")\n",
"type_conflicts_method = detect_conflicts(entities, method=\"type\")\n",
"temporal_conflicts_method = detect_conflicts(entities, method=\"temporal\")\n",
"logical_conflicts_method = detect_conflicts(logical_entities, method=\"logical\")\n",
"\n",
"# Resolution methods\n",
"if value_conflicts_method:\n",
" voting_results = resolve_conflicts(value_conflicts_method, method=\"voting\")\n",
" credibility_results = resolve_conflicts(value_conflicts_method, method=\"credibility_weighted\")\n",
"\n",
"# Analysis methods\n",
"pattern_analysis = analyze_conflicts(all_conflicts, method=\"pattern\")\n",
"type_analysis = analyze_conflicts(all_conflicts, method=\"type\")\n",
"severity_analysis = analyze_conflicts(all_conflicts, method=\"severity\")\n",
"source_analysis = analyze_conflicts(all_conflicts, method=\"source\")\n",
"trend_analysis = analyze_conflicts(all_conflicts, method=\"trend\")\n",
"\n",
"# Source tracking methods\n",
"source_ref = SourceReference(document=\"test_source\", confidence=0.9)\n",
"track_sources(\"e1\", method=\"property\", property_name=\"name\", value=\"Test\", source=source_ref)\n",
"track_sources(\"e1\", method=\"entity\", source=source_ref)\n",
"\n",
"# Investigation guide methods\n",
"if value_conflicts_method:\n",
" guide_method = generate_investigation_guide(value_conflicts_method[0], method=\"guide\")\n",
" checklist_method = generate_investigation_guide(value_conflicts_method[0], method=\"checklist\")\n",
" context_method = generate_investigation_guide(value_conflicts_method[0], method=\"context\")\n",
"\n",
"# List available methods\n",
"all_methods = list_available_methods()\n",
"\n",
"# Get specific method\n",
"voting_method = get_conflict_method(\"resolution\", \"voting\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 7: Method Registry\n",
"\n",
"`method_registry` provides a plugin system for custom methods.\n",
"\n",
"**Registration:** Task type (`detection`, `resolution`, `analysis`, `tracking`, `investigation`), method name, function\n",
"\n",
"**Use Cases:**\n",
"- Domain-specific resolution logic\n",
"- External system integration\n",
"- A/B testing strategies\n",
"- ML model integration\n",
"- Hybrid resolution approaches\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import method_registry, ResolutionResult\n",
"\n",
"# Register custom resolution method\n",
"def custom_resolution(conflicts, **kwargs):\n",
" \"\"\"Custom resolution that always picks the first value.\"\"\"\n",
" results = []\n",
" for conflict in conflicts:\n",
" if conflict.conflicting_values:\n",
" result = ResolutionResult(\n",
" conflict_id=conflict.conflict_id,\n",
" resolved=True,\n",
" resolved_value=conflict.conflicting_values[0],\n",
" resolution_strategy=\"custom_first\",\n",
" confidence=0.8,\n",
" resolution_notes=\"Custom: Always use first value\"\n",
" )\n",
" results.append(result)\n",
" return results\n",
"\n",
"# Register the custom method\n",
"method_registry.register(\"resolution\", \"custom_first\", custom_resolution)\n",
"\n",
"# List registered methods\n",
"registered = method_registry.list_all(\"resolution\")\n",
"\n",
"# Use custom method\n",
"if value_conflicts:\n",
" custom_results = resolve_conflicts(value_conflicts, method=\"custom_first\")\n",
"\n",
"# Unregister method\n",
"method_registry.unregister(\"resolution\", \"custom_first\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 8: Configuration\n",
"\n",
"`ConflictsConfig` manages settings programmatically, via environment variables, or method-specific.\n",
"\n",
"**Global Settings:**\n",
"- `confidence_threshold`, `default_strategy`, `auto_resolve`, `track_provenance`\n",
"\n",
"**Method-Specific:** Voting (`min_sources`, `tie_breaker`), credibility-weighted (`min_credibility`), most_recent (`time_field`), etc.\n",
"\n",
"**Priority:** Method-specific → Global → Environment variables → Defaults\n",
"\n",
"**Best Practices:** Set source credibility early, configure conflict fields, use method-specific configs\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import ConflictsConfig, conflicts_config\n",
"\n",
"# Using global config instance\n",
"conflicts_config.set(\"confidence_threshold\", 0.8)\n",
"conflicts_config.set(\"default_strategy\", \"credibility_weighted\")\n",
"threshold = conflicts_config.get(\"confidence_threshold\", default=0.7)\n",
"\n",
"# Method-specific configuration\n",
"conflicts_config.set_method_config(\"voting\", min_sources=2, tie_breaker=\"confidence\")\n",
"conflicts_config.set_method_config(\"credibility_weighted\", min_credibility=0.5)\n",
"voting_config = conflicts_config.get_method_config(\"voting\")\n",
"\n",
"# Create custom config instance\n",
"custom_config = ConflictsConfig()\n",
"custom_config.set(\"confidence_threshold\", 0.9)\n",
"custom_config.set(\"auto_resolve\", True)\n",
"all_config = custom_config.get_all()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 9: Complete Workflow\n",
"\n",
"End-to-end example: integrating company data from multiple sources.\n",
"\n",
"**Workflow:** Initialize → Track Sources → Detect → Resolve → Analyze → Generate Guides → Build Final Entity\n",
"\n",
"**Scenario:** Three sources (Wikipedia, Official Site, Financial DB) with conflicts in name, founding year, and type classifications.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Complete workflow: Company data integration from multiple sources\n",
"from semantica.conflicts import (\n",
" ConflictDetector, ConflictResolver, ConflictAnalyzer,\n",
" SourceTracker, InvestigationGuideGenerator, SourceReference\n",
")\n",
"\n",
"# Sample company data from multiple sources\n",
"company_data = [\n",
" {\"id\": \"company_1\", \"name\": \"Apple Inc.\", \"founded\": 1976, \"revenue\": 394328000000,\n",
" \"headquarters\": \"Cupertino, California\", \"type\": \"Company\",\n",
" \"source\": \"wikipedia\", \"confidence\": 0.85, \"timestamp\": datetime(2023, 1, 15)},\n",
" {\"id\": \"company_1\", \"name\": \"Apple Inc.\", \"founded\": 1976, \"revenue\": 394328000000,\n",
" \"headquarters\": \"Cupertino, CA\", \"type\": \"Company\",\n",
" \"source\": \"official_site\", \"confidence\": 0.95, \"timestamp\": datetime(2023, 3, 20)},\n",
" {\"id\": \"company_1\", \"name\": \"Apple Incorporated\", \"founded\": 1977, \"revenue\": 394328000000,\n",
" \"headquarters\": \"Cupertino\", \"type\": \"Organization\",\n",
" \"source\": \"financial_db\", \"confidence\": 0.80, \"timestamp\": datetime(2023, 2, 10)},\n",
"]\n",
"\n",
"# Initialize all components\n",
"detector = ConflictDetector(\n",
" confidence_threshold=0.7,\n",
" track_provenance=True,\n",
" conflict_fields={\"Company\": [\"name\", \"founded\", \"revenue\", \"headquarters\"]}\n",
")\n",
"\n",
"tracker = SourceTracker()\n",
"tracker.set_source_credibility(\"wikipedia\", 0.85)\n",
"tracker.set_source_credibility(\"official_site\", 0.95)\n",
"tracker.set_source_credibility(\"financial_db\", 0.80)\n",
"\n",
"resolver = ConflictResolver(default_strategy=\"credibility_weighted\", source_tracker=tracker)\n",
"analyzer = ConflictAnalyzer()\n",
"guide_generator = InvestigationGuideGenerator(source_tracker=tracker)\n",
"\n",
"# Step 1: Track sources\n",
"for entity in company_data:\n",
" source_ref = SourceReference(\n",
" document=entity[\"source\"],\n",
" confidence=entity[\"confidence\"],\n",
" timestamp=entity[\"timestamp\"]\n",
" )\n",
" tracker.track_property_source(entity[\"id\"], \"name\", entity[\"name\"], source_ref)\n",
" tracker.track_property_source(entity[\"id\"], \"founded\", entity[\"founded\"], source_ref)\n",
"\n",
"# Step 2: Detect conflicts\n",
"detected_conflicts = detector.detect_entity_conflicts(company_data, entity_type=\"Company\")\n",
"\n",
"# Step 3: Resolve conflicts\n",
"resolved_data = {}\n",
"for conflict in detected_conflicts:\n",
" results = resolver.resolve_conflicts([conflict], strategy=\"credibility_weighted\")\n",
" if results[0].resolved:\n",
" resolved_data[conflict.property_name] = results[0].resolved_value\n",
"\n",
"# Step 4: Analyze\n",
"analysis = analyzer.analyze_conflicts(detected_conflicts)\n",
"\n",
"# Step 5: Generate guides for unresolved conflicts\n",
"unresolved = [c for c in detected_conflicts if c.property_name not in resolved_data]\n",
"if unresolved:\n",
" guides = guide_generator.generate_guides(unresolved)\n",
"\n",
"# Final resolved entity\n",
"final_entity = {\"id\": \"company_1\", \"type\": \"Company\", **resolved_data}\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"### Key Features\n",
"\n",
"✅ **Detection**: Value, type, temporal, logical, relationship conflicts \n",
"✅ **Resolution**: 6 strategies (voting, credibility-weighted, most_recent, first_seen, highest_confidence, manual_review) \n",
"✅ **Source Tracking**: Provenance, credibility, traceability chains \n",
"✅ **Analysis**: Patterns, trends, recommendations \n",
"✅ **Investigation Guides**: Automated guides and checklists \n",
"✅ **Methods Module**: Convenience functions for all operations \n",
"✅ **Method Registry**: Custom method registration \n",
"✅ **Configuration**: Global and method-specific settings\n",
"\n",
"### Best Practices\n",
"\n",
"1. Set source credibility before detection\n",
"2. Choose strategies based on data characteristics\n",
"3. Enable provenance tracking for audits\n",
"4. Analyze patterns before resolving\n",
"5. Use guides for high-severity conflicts\n",
"6. Configure conflict fields to focus on critical properties\n",
"\n",
"### Common Patterns\n",
"\n",
"- **Integration**: Track → Detect → Resolve → Analyze\n",
"- **QA**: Detect → Analyze → Generate guides → Review\n",
"- **Auto**: Detect → Resolve → Analyze\n",
"- **Assessment**: Track → Analyze → Adjust credibility\n",
"\n",
"### Next Steps\n",
"\n",
"- `04_Conflict_Resolution_Strategies.ipynb` - Advanced strategies\n",
"- `06_Multi_Source_Data_Integration.ipynb` - Integration workflows\n",
"- [API Reference](https://semantica.readthedocs.io/reference/conflicts/)\n",
"- [Usage Guide](../semantica/conflicts/conflicts_usage.md)\n"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@@ -0,0 +1,439 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Conflict Detection and Resolution\n",
"\n",
"## Overview\n",
"\n",
"In modern data pipelines, especially those building Knowledge Graphs, data is often ingested from multiple heterogeneous sources (e.g., internal databases, third-party APIs, web scrapes). Discrepancies are inevitable. \n",
"\n",
"The **Semantica Conflict Resolution Module** (`semantica.conflicts`) provides a robust framework for managing these data inconsistencies. It is designed to ensure that your downstream applications consume only high-quality, reconciled data.\n",
"\n",
"### What counts as a \"conflict\"?\n",
"\n",
"- A conflict happens when **multiple records for the same entity** disagree on a field.\n",
"- Semantica typically assumes each record is a dictionary with:\n",
" - `id` (or `entity_id`): stable identifier for the entity being described\n",
" - one or more attributes (e.g., `name`, `birth_date`, `department`)\n",
" - `source`: where the value came from (db, scrape, api, file)\n",
" - optional `timestamp`: when the value was observed\n",
"- The module is source-aware: it can record **which sources contributed which values**, then resolve using strategies like voting or credibility.\n",
"\n",
"### Practical API notes (to avoid common mismatches)\n",
"\n",
"- Use `ConflictDetector.detect_value_conflicts(entities, property_name=...)` when you want to check one field.\n",
"- Use `ConflictDetector.detect_conflicts(entities)` when you want a broader scan (value/type/temporal/etc.).\n",
"- If you're starting from a Knowledge Graph dictionary (built via `GraphBuilder`), pull entities via `kg.get(\"entities\", [])`.\n",
"\n",
"### Key Capabilities\n",
"\n",
"1. **Multi-Dimensional Conflict Detection**\n",
" * **Value Conflicts**: Different values for the same property (e.g., `\"Google\"` vs `\"Google Inc.\"`).\n",
" * **Type Conflicts**: Data type mismatches (e.g., string vs integer).\n",
" * **Temporal Conflicts**: Chronological inconsistencies (e.g., a `start_date` after an `end_date`).\n",
"\n",
"2. **Provenance & Source Tracking**\n",
" * **Granular Tracking**: Trace every property value back to its specific source document, page, or API call.\n",
" * **Credibility Scoring**: Assign trust scores to sources (e.g., `0.95` for internal HR DB vs `0.60` for web scrapes).\n",
"\n",
"3. **Automated Resolution Strategies**\n",
" * **Voting**: Majority rules (useful for multiple equal-weight sources).\n",
" * **Credibility Weighted**: Values from higher-trust sources override others.\n",
" * **Recency**: The most recent data point wins.\n",
" * **Expert Review**: Flag complex conflicts for human intervention.\n",
"\n",
"4. **Investigation & Auditing**\n",
" * **Investigation Guides**: Auto-generate step-by-step guides for human analysts to resolve sticky conflicts.\n",
" * **Audit Trails**: Keep a record of how every conflict was resolved for compliance.\n",
"\n",
"## Installation\n",
"\n",
"Ensure Semantica is installed in your environment:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"```\n",
"\n",
"- If you're running this notebook inside the Semantica repo, prefer an editable install (so changes in code are reflected immediately):\n",
" - `pip install -e .`\n",
"- If you're using a hosted notebook environment, `%pip install semantica` is often more reliable than `!pip install ...` because it installs into the active kernel."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install -q semantica "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"from datetime import datetime"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1: Simulating Multi-Source Data\n",
"\n",
"To demonstrate the framework, we will simulate a realistic scenario involving employee data.\n",
"\n",
"**The Scenario:**\n",
"We have received records for **Employee 001** from three distinct sources:\n",
"\n",
"- **HR Database**: Highly trusted internal source.\n",
"- **LinkedIn Scrape**: Less reliable external source.\n",
"- **Public Directory**: Outdated public API.\n",
"\n",
"**The record shape (what Semantica expects):**\n",
"\n",
"- Each record is a dictionary describing the same entity (`id`: `emp_001`).\n",
"- Each record includes a `source` key so conflicts can be attributed.\n",
"- A `timestamp` lets you apply time-based resolution strategies (e.g., most recent wins).\n",
"\n",
"**The Conflicts:**\n",
"* **`birth_date`**: The Public Directory lists a different year.\n",
"* **`department`**: LinkedIn uses a more specific name (\"Software Engineering\") vs the generic \"Engineering\" in the HR DB."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 1. Define source metadata\n",
"sources_metadata = {\n",
" \"hr_db\": {\"credibility\": 0.95, \"type\": \"internal_database\"},\n",
" \"linkedin_scrape\": {\"credibility\": 0.60, \"type\": \"web_scrape\"},\n",
" \"public_dir\": {\"credibility\": 0.40, \"type\": \"public_api\"}\n",
"}\n",
"\n",
"# 2. Define entity records from these sources\n",
"entity_records = [\n",
" {\n",
" \"id\": \"emp_001\",\n",
" \"name\": \"John Doe\",\n",
" \"birth_date\": \"1980-05-15\",\n",
" \"department\": \"Engineering\",\n",
" \"source\": \"hr_db\",\n",
" \"timestamp\": \"2023-01-01T10:00:00\"\n",
" },\n",
" {\n",
" \"id\": \"emp_001\",\n",
" \"name\": \"Jonathan Doe\",\n",
" \"birth_date\": \"1980-05-15\",\n",
" \"department\": \"Software Engineering\",\n",
" \"source\": \"linkedin_scrape\",\n",
" \"timestamp\": \"2023-06-15T14:30:00\"\n",
" },\n",
" {\n",
" \"id\": \"emp_001\",\n",
" \"name\": \"John Doe\",\n",
" \"birth_date\": \"1982-05-15\", # Conflict: Different year\n",
" \"department\": \"Engineering\",\n",
" \"source\": \"public_dir\",\n",
" \"timestamp\": \"2022-12-01T09:00:00\"\n",
" }\n",
"]\n",
"\n",
"print(f\"Loaded {len(entity_records)} records for Employee 001\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Registering and Tracking Sources\n",
"\n",
"Before we can effectively resolve conflicts based on trust, we must register our sources with the `SourceTracker`.\n",
"\n",
"The `SourceTracker` acts as a central registry for:\n",
"\n",
"- **Credibility Scores**: How much you trust the source.\n",
"- **Metadata**: Helpful context (e.g., source type, system of record vs scrape).\n",
"\n",
"**How to think about credibility scores:**\n",
"\n",
"- Use scores as a *relative ordering* (the exact decimals matter less than the ranking).\n",
"- Start simple: `internal_db > vendor_api > web_scrape`.\n",
"- Revisit scores later using analytics (e.g., \"which sources are frequently wrong?\").\n",
"\n",
"We iterate through our simulated sources and register them."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import SourceTracker\n",
"\n",
"source_tracker = SourceTracker()\n",
"\n",
"print(\"Registering sources...\")\n",
"for source_id, metadata in sources_metadata.items():\n",
" source_tracker.register_source(\n",
" source_id=source_id,\n",
" source_type=metadata[\"type\"],\n",
" credibility_score=metadata[\"credibility\"]\n",
" )\n",
" print(f\" - Registered '{source_id}' with credibility {metadata['credibility']}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: Detecting Conflicts\n",
"\n",
"We use the `ConflictDetector` to scan our records for discrepancies. \n",
"\n",
"The detector is flexible and can be configured to check:\n",
"\n",
"- **Specific properties**: Check only critical fields like `birth_date`.\n",
"- **Entity-wide scans**: Scan many properties (or all) for an entity.\n",
"\n",
"**What you get back:**\n",
"\n",
"- A list of `Conflict` objects.\n",
"- Useful fields youll typically inspect:\n",
" - `conflict_type` (e.g., `value_conflict`)\n",
" - `entity_id`, `property_name`\n",
" - `conflicting_values` and `sources`\n",
" - `severity` and `confidence`\n",
"\n",
"Here, we explicitly check `birth_date` and `department`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import ConflictDetector\n",
"\n",
"# Initialize detector with our populated source tracker\n",
"detector = ConflictDetector(source_tracker=source_tracker)\n",
"\n",
"conflicts = []\n",
"\n",
"# 1. Check birth_date\n",
"dob_conflicts = detector.detect_value_conflicts(entity_records, \"birth_date\")\n",
"conflicts.extend(dob_conflicts)\n",
"\n",
"# 2. Check department\n",
"dept_conflicts = detector.detect_value_conflicts(entity_records, \"department\")\n",
"conflicts.extend(dept_conflicts)\n",
"\n",
"print(f\"Detected {len(conflicts)} conflicts:\")\n",
"for conflict in conflicts:\n",
" print(f\"- {conflict.conflict_type.value}: {conflict.property_name} for {conflict.entity_id}\")\n",
" print(f\" Values: {conflict.conflicting_values}\")\n",
" print(f\" Severity: {conflict.severity}\")\n",
" print(\"--- \")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: Analyzing Conflict Patterns\n",
"\n",
"When dealing with large datasets, individual conflicts are less important than systemic patterns. The `ConflictAnalyzer` helps answer questions like:\n",
"\n",
"- \"Is one specific source responsible for most conflicts?\"\n",
"- \"Are conflicts concentrated in a specific entity type or property?\"\n",
"- \"What is the distribution of conflict severity and conflict types?\"\n",
"\n",
"**How to use this in a pipeline:**\n",
"\n",
"- Run analysis to identify noisy sources.\n",
"- Use results to adjust credibility scores (Step 2) or refine ingestion/cleaning rules.\n",
"- Track trends over time to catch regressions in upstream systems."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import ConflictAnalyzer\n",
"\n",
"analyzer = ConflictAnalyzer()\n",
"analysis = analyzer.analyze_conflicts(conflicts)\n",
"\n",
"print(\"Conflict Analysis Summary:\")\n",
"print(f\"Total Conflicts: {analysis['total_conflicts']}\")\n",
"print(f\"By Type: {analysis.get('by_type', {}).get('counts')}\")\n",
"print(f\"By Severity: {analysis.get('by_severity', {}).get('counts')}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Resolving Conflicts\n",
"\n",
"This is the critical step where we decide which value to trust. Semantica offers flexible resolution strategies.\n",
"\n",
"### Strategy A: Voting (Majority Rules)\n",
"This strategy selects the value that appears most frequently. It is simple but treats all sources as equal.\n",
"\n",
"- Best when you have many independent sources of similar quality.\n",
"- Less suitable if you have a single system-of-record that should always dominate.\n",
"\n",
"### Strategy B: Credibility Weighted\n",
"This strategy calculates a weighted score for each value based on the `credibility` of its source. \n",
"\n",
"**Example:**\n",
"* `hr_db` (0.95) says \"1980-05-15\"\n",
"* `public_dir` (0.40) says \"1982-05-15\"\n",
"\n",
"Even if multiple low-quality sources agreed on the wrong date, the high-credibility source would likely win.\n",
"\n",
"**What the resolver returns:**\n",
"\n",
"- A list of resolution results where each item typically includes:\n",
" - whether it was resolved\n",
" - the chosen value (`resolved_value`)\n",
" - a confidence score\n",
" - metadata (like the property name) to support audit trails\n",
"\n",
"Run the next cell to compare voting vs credibility-weighted outcomes."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import ConflictResolver\n",
"\n",
"resolver = ConflictResolver()\n",
"\n",
"# CRITICAL: Link the source tracker to the resolver.\n",
"# This allows the resolver to look up the credibility scores we registered in Step 2.\n",
"resolver.set_source_tracker(source_tracker)\n",
"\n",
"print(\"--- Resolution: Voting ---\")\n",
"voting_results = resolver.resolve_conflicts(conflicts, strategy=\"voting\")\n",
"for res in voting_results:\n",
" print(f\"Property: {res.metadata.get('property_name'):<15} | Resolved Value: {res.resolved_value}\")\n",
"\n",
"print(\"\\n--- Resolution: Credibility Weighted ---\")\n",
"# Notice how the HR DB's value is preferred due to higher credibility\n",
"credibility_results = resolver.resolve_conflicts(conflicts, strategy=\"credibility_weighted\")\n",
"for res in credibility_results:\n",
" print(f\"Property: {res.metadata.get('property_name'):<15} | Resolved Value: {res.resolved_value} (Confidence: {res.confidence:.2f})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 6: Generating Investigation Guides\n",
"\n",
"Not all conflicts can be resolved automatically. High-stakes or low-confidence resolutions require human review.\n",
"\n",
"The `InvestigationGuideGenerator` produces a structured \"flight plan\" for an analyst, detailing:\n",
"\n",
"- **What** is in conflict (entity + field + competing values).\n",
"- **Who** is involved (which sources produced which values).\n",
"- **How** to verify the correct data (actionable steps an analyst can follow).\n",
"\n",
"**When to generate guides:**\n",
"\n",
"- Low-confidence resolutions.\n",
"- Conflicts on critical fields (identity, legal names, compliance attributes).\n",
"- Any time you want a human-in-the-loop checkpoint before writing back to the graph."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.conflicts import InvestigationGuideGenerator\n",
"\n",
"guide_generator = InvestigationGuideGenerator()\n",
"\n",
"# Generate a guide for the first conflict (birth_date)\n",
"guide = guide_generator.generate_guide(conflicts[0])\n",
"\n",
"print(f\"=== {guide.title} ===\")\n",
"print(f\"Summary: {guide.conflict_summary}\\n\")\n",
"\n",
"print(\"Investigation Steps:\")\n",
"for i, step in enumerate(guide.investigation_steps, 1):\n",
" print(f\"{i}. {step.description}\")\n",
" print(f\" Action: {step.action}\")\n",
"\n",
"print(\"\\nRecommended Actions:\")\n",
"for action in guide.recommended_actions:\n",
" print(f\"[ ] {action}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"You have successfully built a conflict resolution pipeline using Semantica! \n",
"\n",
"**Recap of what we achieved:**\n",
"\n",
"- **Simulated** multi-source entity records with realistic disagreements.\n",
"- **Registered** sources with credibility scores to create a trust hierarchy.\n",
"- **Detected** value conflicts for specific properties.\n",
"- **Analyzed** conflicts to understand distribution by type and severity.\n",
"- **Resolved** conflicts using voting and credibility-weighted strategies.\n",
"- **Generated** an investigation guide to support human review.\n",
"\n",
"**Suggested next steps in a real project:**\n",
"\n",
"- Integrate with your ingestion layer so each extracted value includes a `source` and (ideally) a `timestamp`.\n",
"- Expand detection beyond value conflicts using `ConflictDetector.detect_conflicts(...)`.\n",
"- Store resolutions and guide outputs to build an audit trail for downstream consumers."
]
}
],
"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": 4
}
+236 -617
View File
@@ -6,134 +6,17 @@
"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/introduction/18_Deduplication.ipynb)\n",
"\n",
"# Deduplication Module\n",
"# Deduplication in Semantica\n",
"\n",
"## What is the Deduplication Module?\n",
"Welcome to the **Deduplication** walkthrough! In any Knowledge Graph, data often comes from multiple sources, leading to duplicate entities (e.g., \"Apple Inc.\" vs. \"Apple Inc\"). \n",
"\n",
"The Deduplication Module is a comprehensive system for identifying and merging duplicate entities in knowledge graphs. It helps maintain data quality by detecting semantically similar entities, calculating similarity scores, and merging duplicates into canonical representations while preserving provenance and handling conflicts.\n",
"Semantica provides a robust **Deduplication Module** to help you:\n",
"1. **Calculate Similarity**: Compare entities using strings, properties, and embeddings.\n",
"2. **Detect Duplicates**: Find pairs or groups of entities that represent the same real-world object.\n",
"3. **Cluster Entities**: Group similar entities together.\n",
"4. **Merge Entities**: Combine duplicates into a single, canonical entity while resolving conflicts.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/deduplication/)\n",
"\n",
"## Module Capabilities\n",
"\n",
"### Core Functionality\n",
"\n",
"1. **Similarity Calculation**\n",
" - Multiple algorithms: Exact matching, Levenshtein distance, Jaro-Winkler, Cosine similarity, Jaccard similarity\n",
" - Multi-factor aggregation: Combines string, property, relationship, and embedding similarity\n",
" - Configurable weights for different similarity components\n",
" - Batch processing for efficient pairwise comparisons\n",
"\n",
"2. **Duplicate Detection**\n",
" - Pairwise comparison: Compare all entity pairs for duplicates\n",
" - Group detection: Find clusters of duplicates using Union-Find algorithm\n",
" - Incremental detection: Efficiently detect duplicates between new and existing entities\n",
" - Confidence scoring: Multi-factor confidence calculation (similarity + name match + property matches)\n",
" - Relationship duplicate detection: Identify duplicate relationships\n",
"\n",
"3. **Entity Merging**\n",
" - Multiple merge strategies: Keep first, last, most complete, highest confidence, or merge all\n",
" - Automatic duplicate detection before merging\n",
" - Conflict resolution: Handle property and relationship conflicts\n",
" - Provenance preservation: Track which entities were merged\n",
" - Merge history: Maintain record of all merge operations\n",
" - Quality validation: Validate merged entities for completeness\n",
"\n",
"4. **Clustering**\n",
" - Graph-based clustering: Union-Find algorithm for connected components\n",
" - Hierarchical clustering: Agglomerative clustering for large datasets\n",
" - Cluster quality metrics: Cohesion and separation measures\n",
" - Incremental updates: Update clusters with new entities\n",
"\n",
"5. **Advanced Features**\n",
" - Property-specific merge rules: Different strategies for different properties\n",
" - Custom conflict resolution: Define custom functions for resolving conflicts\n",
" - Method registry: Register and use custom deduplication methods\n",
" - Configuration management: Centralized configuration from multiple sources\n",
" - Extensibility: Add custom similarity, detection, merge, and clustering methods\n",
"\n",
"## Module Architecture\n",
"\n",
"### Main Components\n",
"\n",
"**Core Classes:**\n",
"- `DuplicateDetector`: Detects duplicate entities and relationships\n",
"- `EntityMerger`: Merges duplicate entities with configurable strategies\n",
"- `SimilarityCalculator`: Calculates multi-factor similarity between entities\n",
"- `ClusterBuilder`: Builds clusters for efficient batch deduplication\n",
"- `MergeStrategyManager`: Manages merge strategies and conflict resolution\n",
"- `MethodRegistry`: Registry for custom deduplication methods\n",
"- `DeduplicationConfig`: Centralized configuration management\n",
"\n",
"**Data Structures:**\n",
"- `DuplicateCandidate`: Duplicate pair with confidence scores\n",
"- `DuplicateGroup`: Group of duplicate entities\n",
"- `MergeOperation`: Merge operation record with metadata\n",
"- `SimilarityResult`: Similarity calculation result with components\n",
"- `Cluster`: Entity cluster representation\n",
"- `ClusterResult`: Cluster building result with quality metrics\n",
"- `MergeResult`: Merge operation result with conflicts\n",
"- `MergeStrategy`: Enumeration of merge strategies\n",
"\n",
"**Convenience Functions:**\n",
"- `detect_duplicates()`: Duplicate detection wrapper\n",
"- `merge_entities()`: Entity merging wrapper\n",
"- `calculate_similarity()`: Similarity calculation wrapper\n",
"- `build_clusters()`: Cluster building wrapper\n",
"- `get_deduplication_method()`: Get method by name\n",
"- `list_available_methods()`: List all available methods\n",
"\n",
"## Algorithms Used\n",
"\n",
"**Similarity Calculation:**\n",
"- Levenshtein Distance: Dynamic programming for edit distance\n",
"- Jaro Similarity: Character-based similarity with match window\n",
"- Jaro-Winkler: Jaro with prefix bonus (up to 4 characters)\n",
"- Cosine Similarity: Vector dot product for embeddings\n",
"- Jaccard Similarity: Intersection over union for sets\n",
"- Multi-factor Aggregation: Weighted sum of similarity components\n",
"\n",
"**Duplicate Detection:**\n",
"- Pairwise Comparison: O(n²) all-pairs similarity calculation\n",
"- Union-Find Algorithm: Disjoint set union for group formation\n",
"- Confidence Scoring: Multi-factor confidence calculation\n",
"- Incremental Processing: O(n×m) efficient new vs existing comparison\n",
"\n",
"**Clustering:**\n",
"- Union-Find (DSU): Connected component detection\n",
"- Hierarchical Clustering: Agglomerative bottom-up clustering\n",
"- Similarity Graph: Graph construction from similarity scores\n",
"\n",
"**Entity Merging:**\n",
"- Strategy Pattern: Multiple merge strategies\n",
"- Conflict Resolution: Voting, credibility-weighted, temporal, confidence-based\n",
"- Property Merging: Rule-based property combination\n",
"- Provenance Tracking: Metadata preservation during merges\n",
"\n",
"## Installation\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"## Table of Contents\n",
"\n",
"1. [Module Overview](#module-overview)\n",
"2. [Setup and Sample Data](#setup)\n",
"3. [Similarity Calculation](#similarity)\n",
"4. [Duplicate Detection](#detection)\n",
"5. [Entity Merging](#merging)\n",
"6. [Clustering](#clustering)\n",
"7. [Advanced Features](#advanced)\n",
"8. [Complete Workflow](#workflow)\n",
"\n",
"---\n",
"\n",
"## Module Overview {#module-overview}\n",
"\n",
"The deduplication module provides a complete solution for maintaining clean knowledge graphs by identifying and merging duplicate entities. It supports multiple similarity algorithms, detection methods, merge strategies, and clustering approaches, making it suitable for various use cases from simple exact matching to advanced semantic deduplication.\n"
"This notebook will guide you through each step with clear examples."
]
},
{
@@ -142,101 +25,93 @@
"metadata": {},
"outputs": [],
"source": [
"# Import all deduplication classes\n",
"from semantica.deduplication import (\n",
" # Main Classes\n",
" DuplicateDetector,\n",
" EntityMerger,\n",
" SimilarityCalculator,\n",
" ClusterBuilder,\n",
" MergeStrategyManager,\n",
" MethodRegistry,\n",
" DeduplicationConfig,\n",
" # Data Classes\n",
" DuplicateCandidate,\n",
" DuplicateGroup,\n",
" MergeOperation,\n",
" SimilarityResult,\n",
" Cluster,\n",
" ClusterResult,\n",
" MergeResult,\n",
" MergeStrategy,\n",
" # Global Instances\n",
" method_registry,\n",
" dedup_config,\n",
")\n",
"# Install Semantica\n",
"!pip install -q semantica"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Preparing Sample Data\n",
"\n",
"# Create sample entities with potential duplicates\n",
"Let's create a dataset with some intentional duplicates. We'll simulate data coming from different sources (e.g., a CRM and a public database).\n",
"\n",
"**Our Entities:**\n",
"- **Apple**: Variations like \"Apple Inc.\", \"Apple Inc\", and just \"Apple\".\n",
"- **Microsoft**: Variations like \"Microsoft Corp\" and \"Microsoft\".\n",
"- **Google**: A unique entity for control."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"entities = [\n",
" # Apple Variations\n",
" {\n",
" \"id\": \"e1\",\n",
" \"name\": \"Apple Inc.\",\n",
" \"type\": \"Company\",\n",
" \"founded\": 1976,\n",
" \"properties\": {\"industry\": \"Technology\", \"headquarters\": \"Cupertino\"},\n",
" \"relationships\": [{\"subject\": \"e1\", \"predicate\": \"founded_by\", \"object\": \"Steve Jobs\"}],\n",
" \"properties\": {\"industry\": \"Technology\", \"hq\": \"Cupertino\", \"founded\": 1976},\n",
" \"relationships\": [{\"predicate\": \"founded_by\", \"object\": \"Steve Jobs\"}]\n",
" },\n",
" {\n",
" \"id\": \"e2\",\n",
" \"name\": \"Apple Inc\",\n",
" \"type\": \"Company\",\n",
" \"founded\": 1976,\n",
" \"properties\": {\"industry\": \"Tech\", \"headquarters\": \"Cupertino, CA\"},\n",
" \"relationships\": [{\"subject\": \"e2\", \"predicate\": \"founded_by\", \"object\": \"Steve Jobs\"}],\n",
" \"properties\": {\"industry\": \"Tech\", \"hq\": \"Cupertino, CA\"}, # Slightly different properties\n",
" \"relationships\": []\n",
" },\n",
" {\n",
" \"id\": \"e3\",\n",
" \"name\": \"Microsoft Corporation\",\n",
" \"name\": \"Apple\",\n",
" \"type\": \"Company\",\n",
" \"founded\": 1975,\n",
" \"properties\": {\"industry\": \"Technology\", \"headquarters\": \"Redmond\"},\n",
" \"properties\": {\"industry\": \"Consumer Electronics\"}, \n",
" \"relationships\": [{\"predicate\": \"ceo\", \"object\": \"Tim Cook\"}]\n",
" },\n",
" \n",
" # Microsoft Variations\n",
" {\n",
" \"id\": \"e4\",\n",
" \"name\": \"Microsoft\",\n",
" \"name\": \"Microsoft Corp\",\n",
" \"type\": \"Company\",\n",
" \"founded\": 1975,\n",
" \"properties\": {\"industry\": \"Tech\", \"headquarters\": \"Redmond, WA\"},\n",
" \"properties\": {\"industry\": \"Software\", \"hq\": \"Redmond\"}\n",
" },\n",
" {\n",
" \"id\": \"e5\",\n",
" \"name\": \"Microsoft\",\n",
" \"type\": \"Company\",\n",
" \"properties\": {\"industry\": \"Tech\", \"hq\": \"Redmond, WA\"}\n",
" },\n",
" \n",
" # Unique Entity\n",
" {\n",
" \"id\": \"e6\",\n",
" \"name\": \"Google LLC\",\n",
" \"type\": \"Company\",\n",
" \"founded\": 1998,\n",
" \"properties\": {\"industry\": \"Technology\"},\n",
" },\n",
" \"properties\": {\"industry\": \"Internet\"}\n",
" }\n",
"]\n",
"\n",
"print(f\"Created {len(entities)} sample entities\")\n",
"print(\"\\nEntity names:\")\n",
"for e in entities:\n",
" print(f\" - {e['name']} (ID: {e['id']})\")\n"
"print(f\"Created {len(entities)} sample entities.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"## 2. Similarity Calculation\n",
"\n",
"## Similarity Calculation {#similarity}\n",
"The `SimilarityCalculator` is the core engine. It compares two entities and returns a score between 0 and 1. It looks at:\n",
"- **String Similarity**: Names and text fields.\n",
"- **Property Similarity**: Overlap in key-value pairs.\n",
"- **Relationship Similarity**: Connections to other entities.\n",
"- **Embeddings**: Semantic vector similarity (if available).\n",
"\n",
"The module provides multiple algorithms for calculating similarity between entities. Similarity is the foundation of duplicate detection.\n",
"\n",
"### Available Similarity Methods\n",
"\n",
"1. **Exact Matching**: Binary match/no-match for identical strings\n",
"2. **Levenshtein Distance**: Edit distance between strings (insertions, deletions, substitutions)\n",
"3. **Jaro-Winkler**: Character-based similarity with prefix bonus for common prefixes\n",
"4. **Cosine Similarity**: Vector similarity for embeddings using dot product\n",
"5. **Jaccard Similarity**: Set-based similarity (intersection over union)\n",
"6. **Property Similarity**: Weighted comparison of property values\n",
"7. **Relationship Similarity**: Jaccard similarity of relationship sets\n",
"8. **Multi-factor Similarity**: Weighted aggregation of all components\n",
"\n",
"### SimilarityCalculator Class\n",
"\n",
"The `SimilarityCalculator` class provides a unified interface for all similarity calculations with configurable weights for different components.\n"
"You can customize the weights for each factor."
]
},
{
@@ -245,144 +120,39 @@
"metadata": {},
"outputs": [],
"source": [
"### Example: Duplicate Detection\n",
"\n",
"# Initialize DuplicateDetector\n",
"detector = DuplicateDetector(\n",
" similarity_threshold=0.7,\n",
" confidence_threshold=0.6,\n",
" use_clustering=True,\n",
")\n",
"\n",
"# Detect duplicate candidates (pairwise)\n",
"candidates = detector.detect_duplicates(entities)\n",
"print(f\"Found {len(candidates)} duplicate candidate(s)\")\n",
"for candidate in candidates:\n",
" print(f\" {candidate.entity1['name']} <-> {candidate.entity2['name']}\")\n",
" print(f\" Similarity: {candidate.similarity_score:.3f}, Confidence: {candidate.confidence:.3f}\")\n",
"\n",
"# Detect duplicate groups\n",
"duplicate_groups = detector.detect_duplicate_groups(entities)\n",
"print(f\"\\nFound {len(duplicate_groups)} duplicate group(s)\")\n",
"for i, group in enumerate(duplicate_groups, 1):\n",
" print(f\" Group {i}: {[e['name'] for e in group.entities]} (confidence: {group.confidence:.3f})\")\n",
"\n",
"# Incremental detection\n",
"existing_entities = entities[:3]\n",
"new_entities = entities[3:]\n",
"incremental_candidates = detector.incremental_detect(new_entities, existing_entities, threshold=0.7)\n",
"print(f\"\\nFound {len(incremental_candidates)} incremental duplicate(s)\")\n",
"for candidate in incremental_candidates:\n",
" print(f\" {candidate.entity1['name']} duplicates {candidate.entity2['name']} (confidence: {candidate.confidence:.3f})\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Duplicate Detection {#detection}\n",
"\n",
"The module detects duplicate entities using similarity metrics and confidence scoring. Detection can be performed pairwise, in groups, or incrementally.\n",
"\n",
"### Detection Methods\n",
"\n",
"1. **Pairwise Detection**: Compare all entity pairs (O(n²) complexity)\n",
"2. **Group Detection**: Find clusters of duplicates using Union-Find algorithm\n",
"3. **Incremental Detection**: Efficiently detect duplicates between new and existing entities (O(n×m))\n",
"4. **Relationship Detection**: Identify duplicate relationships\n",
"\n",
"### Confidence Scoring\n",
"\n",
"The module calculates confidence scores using multiple factors:\n",
"- Similarity score between entities\n",
"- Name matching (exact or fuzzy)\n",
"- Property value matches\n",
"- Entity type matches\n",
"- Relationship overlap\n",
"\n",
"### DuplicateDetector Class\n",
"\n",
"The `DuplicateDetector` class provides all duplicate detection capabilities with configurable thresholds and clustering options.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"### Example: Similarity Calculation\n",
"\n",
"# Initialize SimilarityCalculator\n",
"from semantica.deduplication import SimilarityCalculator, SimilarityResult\n",
"# Initialize calculator with custom weights\n",
"calculator = SimilarityCalculator(\n",
" string_weight=0.4,\n",
" property_weight=0.3,\n",
" relationship_weight=0.2,\n",
" embedding_weight=0.1,\n",
" string_weight=0.5, # High importance on name\n",
" property_weight=0.3, # Medium importance on properties\n",
" relationship_weight=0.2 # Lower importance on relationships\n",
")\n",
"\n",
"# Calculate overall similarity (multi-factor)\n",
"entity1, entity2 = entities[0], entities[1]\n",
"result = calculator.calculate_similarity(entity1, entity2)\n",
"print(f\"Overall Similarity: {result.score:.3f}\")\n",
"print(f\"Components: {result.components}\")\n",
"# Compare \"Apple Inc.\" (e1) vs \"Apple Inc\" (e2)\n",
"score_e1_e2 = calculator.calculate_similarity(entities[0], entities[1])\n",
"\n",
"# String similarity methods\n",
"str1, str2 = \"Apple Inc.\", \"Apple Inc\"\n",
"for method in [\"levenshtein\", \"jaro_winkler\", \"cosine\"]:\n",
" score = calculator.calculate_string_similarity(str1, str2, method=method)\n",
" print(f\"{method}: {score:.3f}\")\n",
"print(f\"Similarity between '{entities[0]['name']}' and '{entities[1]['name']}':\")\n",
"print(f\" Total Score: {score_e1_e2.score:.4f}\")\n",
"print(f\" Breakdown: {score_e1_e2.components}\")\n",
"\n",
"# Property and relationship similarity\n",
"prop_score = calculator.calculate_property_similarity(entity1, entity2)\n",
"rel_score = calculator.calculate_relationship_similarity(entity1, entity2)\n",
"print(f\"\\nProperty Similarity: {prop_score:.3f}\")\n",
"print(f\"Relationship Similarity: {rel_score:.3f}\")\n",
"# Compare \"Apple Inc.\" (e1) vs \"Microsoft\" (e5)\n",
"score_e1_e5 = calculator.calculate_similarity(entities[0], entities[4])\n",
"\n",
"# Batch similarity calculation\n",
"similarity_pairs = calculator.batch_calculate_similarity(entities, threshold=0.5)\n",
"print(f\"\\nFound {len(similarity_pairs)} similar pairs (threshold >= 0.5)\")\n",
"for e1, e2, score in similarity_pairs:\n",
" print(f\" {e1['name']} <-> {e2['name']}: {score:.3f}\")\n"
"print(f\"\\nSimilarity between '{entities[0]['name']}' and '{entities[4]['name']}':\")\n",
"print(f\" Total Score: {score_e1_e5.score:.4f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"## 3. Duplicate Detection\n",
"\n",
"## Entity Merging {#merging}\n",
"The `DuplicateDetector` uses the similarity calculator to scan your dataset for duplicates. It can find:\n",
"- **Pairs**: Simple A matches B.\n",
"- **Groups**: A matches B, and B matches C.\n",
"\n",
"The module merges duplicate entities into single canonical representations using configurable strategies. Merging preserves provenance, handles conflicts, and maintains merge history.\n",
"\n",
"### Merge Strategies\n",
"\n",
"1. **KEEP_FIRST**: Preserve the first entity encountered, merge others into it\n",
"2. **KEEP_LAST**: Preserve the last entity encountered, merge others into it\n",
"3. **KEEP_MOST_COMPLETE**: Preserve entity with most properties and relationships\n",
"4. **KEEP_HIGHEST_CONFIDENCE**: Preserve entity with highest confidence score\n",
"5. **MERGE_ALL**: Create new entity combining all properties and relationships\n",
"6. **CUSTOM**: User-defined merge logic\n",
"\n",
"### Conflict Resolution\n",
"\n",
"When merging entities with conflicting property values, the module supports:\n",
"- Voting: Majority value selection\n",
"- Credibility-weighted: Weighted by source credibility\n",
"- Temporal: Most recent value\n",
"- Confidence-based: Highest confidence value\n",
"- Custom functions: User-defined resolution logic\n",
"\n",
"### EntityMerger Class\n",
"\n",
"The `EntityMerger` class provides entity merging with automatic duplicate detection, provenance preservation, and merge history tracking.\n",
"\n",
"### MergeStrategyManager Class\n",
"\n",
"The `MergeStrategyManager` class provides advanced merge management with property-specific rules and custom conflict resolution functions.\n"
"It uses a `similarity_threshold` to decide what counts as a match."
]
},
{
@@ -391,145 +161,29 @@
"metadata": {},
"outputs": [],
"source": [
"### Example: Entity Merging\n",
"# Import specific classes for Duplicate Detection\n",
"from semantica.deduplication import DuplicateDetector, DuplicateCandidate, DuplicateGroup\n",
"from semantica.deduplication import DeduplicationConfig\n",
"\n",
"# Initialize EntityMerger\n",
"merger = EntityMerger(preserve_provenance=True)\n",
"\n",
"# Merge duplicates (automatic detection)\n",
"merge_operations = merger.merge_duplicates(entities)\n",
"print(f\"Original entities: {len(entities)}\")\n",
"print(f\"Merge operations: {len(merge_operations)}\")\n",
"for i, op in enumerate(merge_operations, 1):\n",
" print(f\" Operation {i}: Merged {len(op.source_entities)} entities → {op.merged_entity.get('name')}\")\n",
" if op.merge_result.conflicts:\n",
" print(f\" Conflicts: {len(op.merge_result.conflicts)}\")\n",
"\n",
"# Merge with specific strategy\n",
"operations = merger.merge_duplicates(entities, strategy=MergeStrategy.KEEP_MOST_COMPLETE)\n",
"print(f\"\\nMerged using KEEP_MOST_COMPLETE: {len(operations)} operations\")\n",
"\n",
"# Merge specific group\n",
"duplicate_entities = [entities[0], entities[1]]\n",
"operation = merger.merge_entity_group(duplicate_entities, strategy=MergeStrategy.KEEP_FIRST)\n",
"print(f\"\\nMerged group: {[e['name'] for e in operation.source_entities]} → {operation.merged_entity['name']}\")\n",
"\n",
"# Get merge history\n",
"history = merger.get_merge_history()\n",
"print(f\"\\nTotal merge operations in history: {len(history)}\")\n",
"\n",
"# Validate merge quality\n",
"if operations:\n",
" validation = merger.validate_merge_quality(operations[0])\n",
" print(f\"\\nValidation: Valid={validation['valid']}, Quality={validation['quality_score']:.3f}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Clustering {#clustering}\n",
"\n",
"The module provides clustering capabilities for efficient batch deduplication of large datasets. Clustering groups similar entities together before deduplication.\n",
"\n",
"### Clustering Methods\n",
"\n",
"1. **Graph-Based Clustering**: Union-Find algorithm for connected components\n",
" - Builds similarity graph from pairwise similarities\n",
" - Uses Union-Find (Disjoint Set Union) for efficient component detection\n",
" - Suitable for medium-sized datasets\n",
"\n",
"2. **Hierarchical Clustering**: Agglomerative bottom-up clustering\n",
" - Builds cluster hierarchy by merging similar clusters\n",
" - Suitable for large datasets\n",
" - Provides cluster quality metrics (cohesion, separation)\n",
"\n",
"### Cluster Quality Metrics\n",
"\n",
"- **Cohesion**: Average similarity within clusters\n",
"- **Separation**: Average similarity between clusters\n",
"- **Cluster Quality Score**: Combined metric for cluster evaluation\n",
"\n",
"### ClusterBuilder Class\n",
"\n",
"The `ClusterBuilder` class provides clustering with configurable thresholds, quality metrics, and incremental update capabilities.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"### Example: Advanced Merge Strategies\n",
"\n",
"# Initialize MergeStrategyManager\n",
"strategy_manager = MergeStrategyManager(default_strategy=\"keep_most_complete\")\n",
"\n",
"# Add property-specific rules\n",
"strategy_manager.add_property_rule(\"name\", MergeStrategy.KEEP_FIRST, priority=1)\n",
"strategy_manager.add_property_rule(\"description\", MergeStrategy.MERGE_ALL, priority=1)\n",
"\n",
"# Custom conflict resolution\n",
"def resolve_longest(values):\n",
" return max(values, key=len)\n",
"\n",
"strategy_manager.add_property_rule(\n",
" \"headquarters\", MergeStrategy.CUSTOM, conflict_resolution=resolve_longest, priority=2\n",
"detector = DuplicateDetector(\n",
" similarity_threshold=0.7, \n",
" confidence_threshold=0.6 \n",
")\n",
"\n",
"print(\"Added merge rules: name=KEEP_FIRST, description=MERGE_ALL, headquarters=CUSTOM\")\n",
"# Detect pairs\n",
"candidates = detector.detect_duplicates(entities)\n",
"\n",
"# Merge entities with property rules\n",
"duplicate_pair = [entities[0], entities[1]]\n",
"merge_result = strategy_manager.merge_entities(duplicate_pair)\n",
"print(f\"\\nMerged Entity: {merge_result.merged_entity.get('name')}\")\n",
"print(f\"Conflicts: {len(merge_result.conflicts)}\")\n",
"\n",
"# Validate merge quality\n",
"validation = strategy_manager.validate_merge(merge_result)\n",
"print(f\"Validation: Valid={validation['valid']}, Quality={validation['quality_score']:.3f}\")\n"
"print(f\"Found {len(candidates)} duplicate pairs:\")\n",
"for c in candidates:\n",
" print(f\" - {c.entity1['name']} <==> {c.entity2['name']} (Score: {c.similarity_score:.2f})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Advanced Features {#advanced}\n",
"\n",
"The module provides advanced features for extensibility, configuration, and custom method registration.\n",
"\n",
"### Configuration Management\n",
"\n",
"The `DeduplicationConfig` class provides centralized configuration from multiple sources:\n",
"- Programmatic configuration (via `set()` method)\n",
"- Environment variables\n",
"- Configuration files (YAML, JSON, TOML)\n",
"- Default values\n",
"\n",
"Configuration can be set globally or per-method for fine-grained control.\n",
"\n",
"### Method Registry\n",
"\n",
"The `MethodRegistry` class allows registration of custom deduplication methods:\n",
"- Custom similarity calculation methods\n",
"- Custom duplicate detection methods\n",
"- Custom entity merging methods\n",
"- Custom clustering methods\n",
"\n",
"Registered methods can be used throughout the module via the registry.\n",
"\n",
"### Property-Specific Merge Rules\n",
"\n",
"The `MergeStrategyManager` supports property-specific merge rules:\n",
"- Different merge strategies for different properties\n",
"- Custom conflict resolution functions per property\n",
"- Priority-based rule application\n",
"- Flexible rule composition\n"
"### Incremental Detection\n",
"If you have an existing database and ingest new data, you don't want to re-compare everything. Use `incremental_detect`."
]
},
{
@@ -538,47 +192,106 @@
"metadata": {},
"outputs": [],
"source": [
"### Example: Clustering\n",
"existing_db = entities[:3] # The Apple entities\n",
"new_data = [entities[4]] # Microsoft\n",
"# Check if new data matches anything in existing DB\n",
"inc_candidates = detector.incremental_detect(new_data, existing_db)\n",
"\n",
"# Initialize ClusterBuilder\n",
"cluster_builder = ClusterBuilder(\n",
" similarity_threshold=0.7,\n",
" min_cluster_size=2,\n",
" max_cluster_size=100,\n",
" use_hierarchical=False,\n",
"print(f\"New matches found: {len(inc_candidates)}\")\n",
"# Expected: 0, because Microsoft is not Apple."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Clustering\n",
"\n",
"Sometimes pairs aren't enough. `ClusterBuilder` groups related entities into clusters. This is useful for understanding the full scope of a duplicated entity."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import specific classes for Clustering\n",
"from semantica.deduplication import ClusterBuilder, Cluster, ClusterResult\n",
"cluster_builder = ClusterBuilder(threshold=0.7)\n",
"result = cluster_builder.build_clusters(entities)\n",
"\n",
"print(f\"Found {len(result.clusters)} clusters:\")\n",
"for i, cluster in enumerate(result.clusters):\n",
" names = [e['name'] for e in cluster.entities]\n",
" print(f\" Cluster {i+1}: {names}\")\n",
"\n",
"cluster_builder = ClusterBuilder(threshold=0.7)\n",
"result = cluster_builder.build_clusters(entities)\n",
"\n",
"print(f\"Found {len(result.clusters)} clusters:\")\n",
"for i, cluster in enumerate(result.clusters):\n",
" names = [e['name'] for e in cluster.entities]\n",
" print(f\" Cluster {i+1}: {names}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Entity Merging\n",
"\n",
"Once duplicates are found, `EntityMerger` combines them. You need to choose a **Merge Strategy**:\n",
"\n",
"- `KEEP_FIRST` / `KEEP_LAST`: Based on order.\n",
"- `KEEP_MOST_COMPLETE`: Keeps the entity with the most data (properties + relationships).\n",
"- `KEEP_HIGHEST_CONFIDENCE`: Uses internal confidence scores.\n",
"- `MERGE_ALL`: Combines everything (arrays are concatenated, conflicts resolved by voting)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import specific classes for Entity Merging\n",
"from semantica.deduplication import EntityMerger, MergeStrategy, MergeStrategyManager, MergeOperation, MergeResult"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"merger = EntityMerger()\n",
"\n",
"# We will use the 'KEEP_MOST_COMPLETE' strategy\n",
"# This ensures we don't lose valuable information from richer entities\n",
"merge_ops = merger.merge_duplicates(\n",
" entities, \n",
" strategy=MergeStrategy.KEEP_MOST_COMPLETE\n",
")\n",
"\n",
"# Graph-based clustering\n",
"cluster_result = cluster_builder.build_clusters(entities)\n",
"print(f\"Clusters: {len(cluster_result.clusters)}, Unclustered: {len(cluster_result.unclustered)}\")\n",
"print(f\"Quality Metrics: {cluster_result.quality_metrics}\")\n",
"for cluster in cluster_result.clusters:\n",
" print(f\" {cluster.cluster_id}: {len(cluster.entities)} entities (quality: {cluster.quality_score:.3f})\")\n",
"print(f\"Performed {len(merge_ops)} merge operations.\")\n",
"\n",
"# Hierarchical clustering\n",
"hierarchical_builder = ClusterBuilder(similarity_threshold=0.7, use_hierarchical=True)\n",
"hierarchical_result = hierarchical_builder.build_clusters(entities)\n",
"print(f\"\\nHierarchical Clustering: {len(hierarchical_result.clusters)} clusters\")\n",
"print(f\"Quality Metrics: {hierarchical_result.quality_metrics}\")\n"
"print(\"\\n--- Merged Results ---\")\n",
"for op in merge_ops:\n",
" final_ent = op.merged_entity\n",
" original_count = len(op.source_entities)\n",
" print(f\"Merged {original_count} entities into: '{final_ent['name']}'\")\n",
" print(f\" - Final Properties: {final_ent['properties']}\")\n",
" print(f\" - Final Relationships: {len(final_ent.get('relationships', []))}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"## 6. Complete Workflow\n",
"\n",
"## Complete Workflow {#workflow}\n",
"\n",
"A typical deduplication workflow involves:\n",
"1. Configuration: Set similarity thresholds and method preferences\n",
"2. Clustering: Build clusters of similar entities (optional, for large datasets)\n",
"3. Detection: Identify duplicate entities within clusters or entire dataset\n",
"4. Merging: Merge duplicate entities using appropriate strategies\n",
"5. Validation: Validate merge quality and completeness\n",
"6. History: Track merge operations for audit and rollback\n",
"\n",
"The module provides both class-based and function-based interfaces for flexibility.\n"
"Let's wrap this up into a clean function that takes dirty data and returns clean data."
]
},
{
@@ -587,172 +300,78 @@
"metadata": {},
"outputs": [],
"source": [
"### Example: Configuration and Method Registry\n",
"\n",
"# Configuration management\n",
"threshold = dedup_config.get(\"similarity_threshold\", default=0.7)\n",
"confidence = dedup_config.get(\"confidence_threshold\", default=0.6)\n",
"print(f\"Current: similarity_threshold={threshold}, confidence_threshold={confidence}\")\n",
"\n",
"# Set configuration programmatically\n",
"dedup_config.set(\"similarity_threshold\", 0.8)\n",
"dedup_config.set(\"confidence_threshold\", 0.7)\n",
"print(f\"Updated: similarity_threshold={dedup_config.get('similarity_threshold')}\")\n",
"\n",
"# Method-specific configuration\n",
"dedup_config.set_method_config(\"levenshtein\", case_sensitive=False)\n",
"levenshtein_config = dedup_config.get_method_config(\"levenshtein\")\n",
"print(f\"Method config (levenshtein): {levenshtein_config}\")\n",
"\n",
"# Custom method registration\n",
"def word_overlap_similarity(entity1, entity2, **kwargs):\n",
" \"\"\"Custom similarity based on word overlap.\"\"\"\n",
" name1 = entity1.get(\"name\", \"\").lower().split()\n",
" name2 = entity2.get(\"name\", \"\").lower().split()\n",
"def deduplicate_dataset(raw_entities):\n",
" print(\"1. Detecting duplicates...\")\n",
" # Step 1: Detect\n",
" detector = DuplicateDetector(similarity_threshold=0.75)\n",
" # We can skip explicit detection calls if we just want to merge, \n",
" # as EntityMerger calls detection internally, but doing it manually allows inspection.\n",
" \n",
" if not name1 or not name2:\n",
" return SimilarityResult(score=0.0, method=\"word_overlap\")\n",
" print(\"2. Merging entities...\")\n",
" # Step 2: Merge\n",
" merger = EntityMerger()\n",
" ops = merger.merge_duplicates(raw_entities, strategy=MergeStrategy.KEEP_MOST_COMPLETE)\n",
" \n",
" set1, set2 = set(name1), set(name2)\n",
" intersection = len(set1 & set2)\n",
" union = len(set1 | set2)\n",
" score = intersection / union if union > 0 else 0.0\n",
" return SimilarityResult(score=score, method=\"word_overlap\")\n",
" # Let's collect all final IDs to see what remains\n",
" merged_entities = [op.merged_entity for op in ops]\n",
" \n",
" # Find entities that were NOT part of any merge (singletons)\n",
" merged_ids = set()\n",
" for op in ops:\n",
" for source in op.source_entities:\n",
" merged_ids.add(source['id'])\n",
" \n",
" singletons = [e for e in raw_entities if e['id'] not in merged_ids]\n",
" \n",
" final_dataset = merged_entities + singletons\n",
" return final_dataset\n",
"\n",
"# Register custom method\n",
"method_registry.register(\"similarity\", \"word_overlap\", word_overlap_similarity)\n",
"print(\"\\nRegistered 'word_overlap' similarity method\")\n",
"# Run the workflow\n",
"clean_data = deduplicate_dataset(entities)\n",
"\n",
"# Use custom method\n",
"custom_method = method_registry.get(\"similarity\", \"word_overlap\")\n",
"if custom_method:\n",
" result = custom_method(entities[0], entities[1])\n",
" print(f\"Word Overlap Similarity: {result.score:.3f}\")\n",
"\n",
"# List all registered methods\n",
"all_registered = method_registry.list_all()\n",
"print(f\"\\nRegistered Methods: {all_registered}\")\n"
"print(f\"\\nOriginal Size: {len(entities)}\")\n",
"print(f\"Cleaned Size: {len(clean_data)}\")\n",
"print(\"\\nFinal Entity Names:\")\n",
"for e in clean_data:\n",
" print(f\" - {e['name']}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"## Summary\n",
"\n",
"## Practical Examples\n",
"You've learned how to:\n",
"1. **Import** the necessary Deduplication classes.\n",
"2. **Calculate Similarity** between entities.\n",
"3. **Detect Duplicates** using configurable thresholds.\n",
"4. **Cluster** similar entities.\n",
"5. **Merge** duplicates into a clean, canonical dataset.\n",
"\n",
"The following sections demonstrate practical usage of the module components.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"### Example: Complete Workflow\n",
"\n",
"# Complete deduplication workflow\n",
"\n",
"# Step 1: Configure\n",
"dedup_config.set(\"similarity_threshold\", 0.75)\n",
"dedup_config.set(\"confidence_threshold\", 0.65)\n",
"\n",
"# Step 2: Build clusters\n",
"cluster_builder = ClusterBuilder(similarity_threshold=0.75, min_cluster_size=2, max_cluster_size=50)\n",
"cluster_result = cluster_builder.build_clusters(entities)\n",
"print(f\"Step 1: Created {len(cluster_result.clusters)} clusters\")\n",
"\n",
"# Step 3: Detect duplicates\n",
"detector = DuplicateDetector(similarity_threshold=0.75, confidence_threshold=0.65)\n",
"all_duplicate_groups = []\n",
"for cluster in cluster_result.clusters:\n",
" groups = detector.detect_duplicate_groups(cluster.entities)\n",
" all_duplicate_groups.extend(groups)\n",
"print(f\"Step 2: Found {len(all_duplicate_groups)} duplicate groups\")\n",
"\n",
"# Step 4: Merge duplicates\n",
"merger = EntityMerger(preserve_provenance=True)\n",
"merge_operations = merger.merge_duplicates(entities, strategy=MergeStrategy.KEEP_MOST_COMPLETE)\n",
"print(f\"Step 3: Performed {len(merge_operations)} merge operations\")\n",
"\n",
"# Step 5: Extract results\n",
"merged_entities = [op.merged_entity for op in merge_operations]\n",
"print(f\"\\nResults:\")\n",
"print(f\" Original: {len(entities)} entities\")\n",
"print(f\" Merged: {len(merged_entities)} entities\")\n",
"print(f\" Reduction: {len(entities) - len(merged_entities)} entities\")\n",
"\n",
"# Step 6: Validate merge quality\n",
"for i, op in enumerate(merge_operations, 1):\n",
" validation = merger.validate_merge_quality(op)\n",
" print(f\" Merge {i}: Valid={validation['valid']}, Quality={validation['quality_score']:.3f}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: Similarity Calculation\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Complete deduplication workflow\n",
"\n",
"# Step 1: Configure\n",
"dedup_config.set(\"similarity_threshold\", 0.75)\n",
"dedup_config.set(\"confidence_threshold\", 0.65)\n",
"\n",
"# Step 2: Build clusters\n",
"cluster_builder = ClusterBuilder(similarity_threshold=0.75, min_cluster_size=2, max_cluster_size=50)\n",
"cluster_result = cluster_builder.build_clusters(entities)\n",
"print(f\"Step 1: Created {len(cluster_result.clusters)} clusters\")\n",
"\n",
"# Step 3: Detect duplicates\n",
"detector = DuplicateDetector(similarity_threshold=0.75, confidence_threshold=0.65)\n",
"all_duplicate_groups = []\n",
"for cluster in cluster_result.clusters:\n",
" groups = detector.detect_duplicate_groups(cluster.entities)\n",
" all_duplicate_groups.extend(groups)\n",
"print(f\"Step 2: Found {len(all_duplicate_groups)} duplicate groups\")\n",
"\n",
"# Step 4: Merge duplicates\n",
"merger = EntityMerger(preserve_provenance=True)\n",
"merge_operations = merger.merge_duplicates(entities, strategy=MergeStrategy.KEEP_MOST_COMPLETE)\n",
"print(f\"Step 3: Performed {len(merge_operations)} merge operations\")\n",
"\n",
"# Step 5: Extract results\n",
"merged_entities = [op.merged_entity for op in merge_operations]\n",
"print(f\"\\nResults:\")\n",
"print(f\" Original: {len(entities)} entities\")\n",
"print(f\" Merged: {len(merged_entities)} entities\")\n",
"print(f\" Reduction: {len(entities) - len(merged_entities)} entities\")\n",
"\n",
"# Step 6: Validate merge quality\n",
"for i, op in enumerate(merge_operations, 1):\n",
" validation = merger.validate_merge_quality(op)\n",
" print(f\" Merge {i}: Valid={validation['valid']}, Quality={validation['quality_score']:.3f}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: Duplicate Detection\n"
"This module is essential for maintaining high-quality Knowledge Graphs, especially when ingesting data from multiple, potentially messy sources."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
"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
"nbformat_minor": 4
}
+328 -167
View File
@@ -2,256 +2,417 @@
"cells": [
{
"cell_type": "markdown",
"id": "c21e9c8d",
"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/introduction/19_Context_Module.ipynb)\n",
"\n",
"# Context Engineering Module\n",
"# Context Module — Practical Guide\n",
"\n",
"## Overview\n",
"Semanticas `context` module is the layer that makes an agent “stateful”. It combines:\n",
"\n",
"This notebook provides a comprehensive guide to Semantica's **Context Engineering Module** - a powerful system for building context graphs, managing agent memory, retrieving context, and linking entities. You'll learn how to use the new synchronous Architecture 2.0 features, including hierarchical memory with token management.\n",
"- **Memory** (short-term + long-term) via `AgentMemory`\n",
"- **Graph context** via `ContextGraph`\n",
"- **Hybrid retrieval** (vector + memory + graph) via `ContextRetriever`\n",
"- **High-level UX** via `AgentContext` (recommended entry point)\n",
"- **Entity linking** via `EntityLinker`\n",
"- **Extensibility + config** via `registry` and `config`\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/context/)\n",
"\n",
"### Learning Objectives\n",
"\n",
"- **Hierarchical Memory**: Manage short-term (token-buffered) and long-term (vector-stored) memory\n",
"- **Context Graph**: Build and query dynamic knowledge graphs\n",
"- **Hybrid Retrieval**: Combine vector search, graph traversal, and keyword matching\n",
"- **Entity Linking**: Resolve entities across conversations\n",
"- **Configuration**: Customize behavior via YAML or environment variables\n",
"\n",
"---\n",
"\n",
"## Installation\n",
"\n",
"```bash\n",
"pip install semantica\n",
"```"
"This notebook focuses on small, runnable examples and keeps imports scoped to each cell."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "257bad40",
"metadata": {},
"outputs": [],
"source": [
"# Setup: Create a mock vector store for demonstration\n",
"from typing import List, Dict, Any, Optional\n",
"from semantica.context import VectorStore\n",
"\n",
"class MockVectorStore(VectorStore):\n",
" def __init__(self):\n",
" self.items = {}\n",
" self.counter = 0\n",
" \n",
" def add(self, texts: List[str], metadata: Optional[List[Dict[str, Any]]] = None, **kwargs) -> List[str]:\n",
" ids = []\n",
" for i, text in enumerate(texts):\n",
" id_ = f\"id_{self.counter}\"\n",
" self.items[id_] = {\"text\": text, \"metadata\": metadata[i] if metadata else {}}\n",
" ids.append(id_)\n",
" self.counter += 1\n",
" return ids\n",
" \n",
" def search(self, query: str, limit: int = 5, **kwargs) -> List[Dict[str, Any]]:\n",
" # Simple keyword match for mock\n",
" results = []\n",
" for id_, item in self.items.items():\n",
" if any(w.lower() in item[\"text\"].lower() for w in query.split()):\n",
" results.append({\n",
" \"id\": id_,\n",
" \"content\": item[\"text\"],\n",
" \"score\": 0.9,\n",
" \"metadata\": item[\"metadata\"]\n",
" })\n",
" return results[:limit]\n",
" \n",
" def delete(self, ids: List[str], **kwargs) -> bool:\n",
" for id_ in ids:\n",
" self.items.pop(id_, None)\n",
" return True\n",
"\n",
"vs = MockVectorStore()"
"!pip install -q semantica"
]
},
{
"cell_type": "markdown",
"id": "a48e0f10",
"metadata": {},
"source": [
"## 1. High-Level Interface: AgentContext\n",
"## 1) Vector store (for long-term memory)\n",
"\n",
"The `AgentContext` class is the easiest way to get started. It unifies vector storage, knowledge graphs, and memory management."
"The `VectorStore` can generate embeddings via its internal embedder. If no embedder is available in your environment, it falls back to random vectors so the API stays usable for demos."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8c845a94",
"metadata": {},
"outputs": [],
"source": [
"from semantica.vector_store import VectorStore\n",
"\n",
"vs = VectorStore(backend=\"inmemory\", dimension=384)\n",
"\n",
"if getattr(vs, \"embedder\", None) and hasattr(vs.embedder, \"set_text_model\"):\n",
" vs.embedder.set_text_model(method=\"fastembed\", model_name=\"BAAI/bge-small-en-v1.5\")\n",
"\n",
"vs.backend, vs.dimension"
]
},
{
"cell_type": "markdown",
"id": "c1b1ba34",
"metadata": {},
"source": [
"## 2) Quick start with `AgentContext` (recommended)\n",
"\n",
"`AgentContext` is the user-friendly interface that ties memory, vector store, and graph together. If you pass a `ContextGraph`, the system can do GraphRAG-style retrieval."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f4d788b5",
"metadata": {},
"outputs": [],
"source": [
"from semantica.context import AgentContext, ContextGraph\n",
"\n",
"# Initialize with vector store and a new in-memory knowledge graph\n",
"kg = ContextGraph()\n",
"context = AgentContext(\n",
" vector_store=vs,\n",
" knowledge_graph=kg,\n",
" token_limit=2000, # Max tokens in short-term memory\n",
" short_term_limit=10 # Max items in short-term memory\n",
")\n",
"context = AgentContext(vector_store=vs, knowledge_graph=kg)\n",
"\n",
"# Store a memory (automatically goes to short-term and long-term)\n",
"context.store(\n",
" \"The user, Alice, is a data scientist interested in Python.\",\n",
"context.config"
]
},
{
"cell_type": "markdown",
"id": "638bdbc8",
"metadata": {},
"source": [
"## 3) Store and retrieve memory\n",
"\n",
"A single string is treated as a memory item. You can attach `conversation_id` and `user_id` through metadata-friendly parameters."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5d65eb00",
"metadata": {},
"outputs": [],
"source": [
"memory_id = context.store(\n",
" \"User prefers short answers about Python.\",\n",
" conversation_id=\"conv_1\",\n",
" user_id=\"alice_01\"\n",
" user_id=\"user_1\",\n",
" metadata={\"type\": \"preference\"},\n",
")\n",
"\n",
"# Retrieve context (automatically uses hybrid retrieval)\n",
"results = context.retrieve(\"What does Alice do?\")\n",
"\n",
"for res in results:\n",
" print(f\"Found: {res['content']} (Score: {res['score']})\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Hierarchical Memory Management\n",
"\n",
"Semantica uses a two-tier memory system:\n",
"1. **Short-Term Memory**: A fast, in-memory buffer limited by tokens (to fit in LLM context windows) and item count.\n",
"2. **Long-Term Memory**: Persistent storage backed by the vector store.\n",
"\n",
"Let's observe how the token limit works."
"context.get_memory(memory_id)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3c1be718",
"metadata": {},
"outputs": [],
"source": [
"from semantica.context import AgentMemory\n",
"\n",
"# Initialize memory with strict limits for demonstration\n",
"memory = AgentMemory(\n",
" vector_store=vs,\n",
" token_limit=50, # Very small token limit\n",
" short_term_limit=5 # Max 5 items\n",
"context.store(\n",
" \"User is working on Semantica context module examples.\",\n",
" conversation_id=\"conv_1\",\n",
" user_id=\"user_1\",\n",
" metadata={\"type\": \"note\"},\n",
")\n",
"\n",
"# Add memories\n",
"for i in range(10):\n",
" memory.store(f\"Memory item {i}: This is a sentence with some tokens.\")\n",
" print(f\"Added item {i}. Short-term size: {len(memory.short_term_memory)}\")\n",
"\n",
"print(\"\\nFinal short-term memory content:\")\n",
"for item in memory.short_term_memory:\n",
" print(f\"- {item.content}\")\n",
" \n",
"# Notice that older items are pruned to respect the token limit and item count."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Context Graph & GraphRAG\n",
"\n",
"The `ContextGraph` allows you to structure information as nodes and edges, enabling \"GraphRAG\" - retrieving information based on relationships rather than just semantic similarity."
"context.retrieve(\"Python answers\", max_results=3)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "485acf33",
"metadata": {},
"outputs": [],
"source": [
"from semantica.context import ContextGraph\n",
"\n",
"graph = ContextGraph()\n",
"\n",
"# Manually building a graph\n",
"graph.add_node(\"n1\", \"person\", \"Alice\")\n",
"graph.add_node(\"n2\", \"language\", \"Python\")\n",
"graph.add_node(\"n3\", \"library\", \"Semantica\")\n",
"\n",
"graph.add_edge(\"n1\", \"n2\", \"uses\")\n",
"graph.add_edge(\"n2\", \"n3\", \"powers\")\n",
"\n",
"# Query the graph\n",
"neighbors = graph.get_neighbors(\"n2\", hops=1)\n",
"print(\"Neighbors of Python:\", neighbors)\n",
"\n",
"# Using the graph in AgentContext\n",
"context = AgentContext(vector_store=vs, knowledge_graph=graph)\n",
"\n",
"# Retrieve with graph expansion\n",
"results = context.retrieve(\n",
" \"Alice\",\n",
" use_graph=True,\n",
" expand_graph=True # Will pull in 'Python' because Alice uses it\n",
")\n",
"\n",
"print(\"\\nGraph-enhanced Retrieval:\")\n",
"for res in results:\n",
" print(f\"- {res['content']}\")"
"context.conversation(\"conv_1\", max_items=10)"
]
},
{
"cell_type": "markdown",
"id": "1e43cddd",
"metadata": {},
"source": [
"## 4. Entity Linking\n",
"## 4) Export, save, load\n",
"\n",
"The `EntityLinker` helps ensure that \"Alice\", \"Alice Smith\", and \"she\" (in context) refer to the same entity ID."
"`AgentContext` includes simple persistence helpers. This example uses a temporary directory."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a264ef4d",
"metadata": {},
"outputs": [],
"source": [
"export_json = context.export(conversation_id=\"conv_1\", format=\"json\")\n",
"export_json[:300]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b62d1859",
"metadata": {},
"outputs": [],
"source": [
"import tempfile\n",
"\n",
"with tempfile.TemporaryDirectory() as d:\n",
" context.save(d)\n",
" context.load(d)\n",
"\n",
"context.conversation_summary(\"conv_1\")"
]
},
{
"cell_type": "markdown",
"id": "3b8bf553",
"metadata": {},
"source": [
"## 5) Store documents and build a context graph\n",
"\n",
"If you store a list, `AgentContext.store(...)` treats it as documents. To keep this notebook lightweight and deterministic, we pass pre-extracted entities and relationships per document."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "72930ae7",
"metadata": {},
"outputs": [],
"source": [
"documents = [\n",
" {\n",
" \"id\": \"doc_1\",\n",
" \"content\": \"Python is used for machine learning.\",\n",
" \"metadata\": {\"source\": \"docs\"},\n",
" \"entities\": [\n",
" {\"id\": \"e_python\", \"text\": \"Python\", \"type\": \"PROGRAMMING_LANGUAGE\"},\n",
" {\"id\": \"e_ml\", \"text\": \"Machine Learning\", \"type\": \"CONCEPT\"},\n",
" ],\n",
" \"relationships\": [\n",
" {\n",
" \"source_id\": \"e_python\",\n",
" \"target_id\": \"e_ml\",\n",
" \"type\": \"used_for\",\n",
" \"confidence\": 0.9,\n",
" }\n",
" ],\n",
" },\n",
" {\n",
" \"id\": \"doc_2\",\n",
" \"content\": \"PyTorch is a machine learning framework.\",\n",
" \"metadata\": {\"source\": \"docs\"},\n",
" \"entities\": [\n",
" {\"id\": \"e_pytorch\", \"text\": \"PyTorch\", \"type\": \"FRAMEWORK\"},\n",
" {\"id\": \"e_ml\", \"text\": \"Machine Learning\", \"type\": \"CONCEPT\"},\n",
" ],\n",
" \"relationships\": [\n",
" {\n",
" \"source_id\": \"e_pytorch\",\n",
" \"target_id\": \"e_ml\",\n",
" \"type\": \"implements\",\n",
" \"confidence\": 0.95,\n",
" }\n",
" ],\n",
" },\n",
"]\n",
"\n",
"stats = context.store(\n",
" documents,\n",
" extract_entities=False,\n",
" extract_relationships=False,\n",
" link_entities=True,\n",
")\n",
"\n",
"stats"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "24f8dba8",
"metadata": {},
"outputs": [],
"source": [
"kg.stats()"
]
},
{
"cell_type": "markdown",
"id": "f4671f2a",
"metadata": {},
"source": [
"## 6) Explore the graph with `ContextGraph`\n",
"\n",
"The graph supports keyword querying and neighbor expansion."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "df2e5fcd",
"metadata": {},
"outputs": [],
"source": [
"kg.query(\"machine learning\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0836feeb",
"metadata": {},
"outputs": [],
"source": [
"kg.get_neighbors(\"e_python\", hops=2)"
]
},
{
"cell_type": "markdown",
"id": "1be1adf1",
"metadata": {},
"source": [
"## 7) Entity linking with `EntityLinker`\n",
"\n",
"`EntityLinker` assigns stable URIs and can link related or duplicate entities across sources."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "24b011c0",
"metadata": {},
"outputs": [],
"source": [
"from semantica.context import EntityLinker\n",
"\n",
"linker = EntityLinker()\n",
"linker = EntityLinker(knowledge_graph={\"entities\": [{\"id\": \"e_py\", \"text\": \"Python\", \"type\": \"PROGRAMMING_LANGUAGE\"}]})\n",
"\n",
"# Generate a canonical URI\n",
"uri = linker.generate_uri(\"Python Programming Language\")\n",
"print(f\"Canonical URI: {uri}\")\n",
"entities = [\n",
" {\"id\": \"e1\", \"text\": \"Python\", \"type\": \"PROGRAMMING_LANGUAGE\"},\n",
" {\"id\": \"e2\", \"text\": \"PyTorch\", \"type\": \"FRAMEWORK\"},\n",
"]\n",
"\n",
"# Check similarity\n",
"score = linker._calculate_text_similarity(\"Python\", \"Python Lang\")\n",
"print(f\"Similarity Score: {score}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Configuration\n",
"\n",
"You can configure the context module using the `config` object or environment variables."
"linked = linker.link(\"Python and PyTorch\", entities=entities)\n",
"[(e.entity_id, e.uri, len(e.linked_entities)) for e in linked]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a282de3a",
"metadata": {},
"outputs": [],
"source": [
"from semantica.context import config\n",
"linker.link_entities(\"e1\", \"e2\", link_type=\"related_to\", confidence=0.8)\n",
"linker.get_entity_links(\"e1\")[:2]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2d11f87f",
"metadata": {},
"outputs": [],
"source": [
"linker.build_entity_web()[\"statistics\"]"
]
},
{
"cell_type": "markdown",
"id": "072efafd",
"metadata": {},
"source": [
"## 8) Low-level building blocks: `AgentMemory` and `ContextRetriever`\n",
"\n",
"# Set global configuration\n",
"config.context_config.set(\"token_limit\", 4096)\n",
"config.context_config.set(\"retention_days\", 30)\n",
"If you want more control than `AgentContext`, you can wire the parts directly."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3791d6c6",
"metadata": {},
"outputs": [],
"source": [
"from semantica.context import AgentMemory, ContextRetriever\n",
"\n",
"print(f\"Current Token Limit: {config.context_config.get('token_limit')}\")"
"memory = AgentMemory(vector_store=vs, knowledge_graph=kg, retention_policy=\"unlimited\")\n",
"memory.store(\"Python powers Semantica.\", metadata={\"type\": \"fact\", \"conversation_id\": \"conv_2\"})\n",
"\n",
"retriever = ContextRetriever(memory_store=memory, knowledge_graph=kg, vector_store=vs)\n",
"results = retriever.retrieve(\"Python Semantica\", max_results=5)\n",
"\n",
"[(r.content, r.source, round(r.score, 3)) for r in results]"
]
},
{
"cell_type": "markdown",
"id": "92060402",
"metadata": {},
"source": [
"## 9) Methods, registry, and configuration\n",
"\n",
"The `methods` layer exposes convenience functions, while `registry` lets you plug in your own implementations. `config` provides runtime configuration."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "896e7001",
"metadata": {},
"outputs": [],
"source": [
"from semantica.context.config import context_config\n",
"\n",
"context_config.set(\"retention_policy\", \"7_days\")\n",
"context_config.get(\"retention_policy\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e925a2e0",
"metadata": {},
"outputs": [],
"source": [
"from semantica.context.methods import build_context_graph\n",
"from semantica.context.registry import method_registry\n",
"\n",
"def custom_graph_method(entities, relationships, conversations=None, **kwargs):\n",
" return {\n",
" \"nodes\": [],\n",
" \"edges\": [],\n",
" \"statistics\": {\"node_count\": 0, \"edge_count\": 0},\n",
" }\n",
"\n",
"method_registry.register(\"graph\", \"custom_demo\", custom_graph_method)\n",
"method_registry.list_all(\"graph\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "21fa6cb3",
"metadata": {},
"outputs": [],
"source": [
"build_context_graph(\n",
" entities=[{\"id\": \"e1\", \"text\": \"Python\", \"type\": \"PROGRAMMING_LANGUAGE\"}],\n",
" relationships=[{\"source_id\": \"e1\", \"target_id\": \"e2\", \"type\": \"related_to\"}],\n",
" method=\"custom_demo\",\n",
")"
]
}
],
@@ -271,7 +432,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
"version": "3.11.9"
}
},
"nbformat": 4,
-774
View File
@@ -1,774 +0,0 @@
{
"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/introduction/20_Triple_Store.ipynb)\n",
"\n",
"# Triple Store - Comprehensive Guide\n",
"\n",
"## Overview\n",
"\n",
"This notebook provides a **comprehensive walkthrough** of Semantica's triple_store module, demonstrating RDF triple storage, SPARQL querying, and multi-backend support for knowledge graph persistence.\n",
"\n",
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/triple_store/)\n",
"\n",
"### Learning Objectives\n",
"\n",
"By the end of this notebook, you will be able to:\n",
"\n",
"- Register and manage triple stores (Blazegraph, Jena, RDF4J, Virtuoso)\n",
"- Perform CRUD operations on RDF triples\n",
"- Execute SPARQL queries with optimization\n",
"- Use bulk loading for large datasets\n",
"- Work with multiple store backends\n",
"- Validate and track triple operations\n",
"- Choose the right backend for your use case\n",
"\n",
"### What You'll Learn\n",
"\n",
"| Component | Purpose | When to Use |\n",
"|-----------|---------|-------------|\n",
"| `TripleManager` | Store coordination | All triple operations |\n",
"| `QueryEngine` | SPARQL execution | Query optimization |\n",
"| `BulkLoader` | High-volume loading | Large datasets |\n",
"| `BlazegraphAdapter` | Blazegraph backend | High performance |\n",
"| `JenaAdapter` | Jena backend | Java integration |\n",
"| `RDF4JAdapter` | RDF4J backend | Transaction support |\n",
"| `VirtuosoAdapter` | Virtuoso backend | Enterprise scale |\n",
"\n",
"---\n",
"\n",
"## Installation\n",
"\n",
"Install Semantica from PyPI:\n",
"\n",
"```bash\n",
"pip install semantica\n",
"# Or with all optional dependencies:\n",
"pip install semantica[all]\n",
"```\n",
"\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1: Basic Triple Store Operations\n",
"\n",
"Let's start with the `TripleManager` for basic triple store operations.\n",
"\n",
"### What is TripleManager?\n",
"\n",
"`TripleManager` is the main coordinator for triple store operations:\n",
"- **Store Registration**: Register multiple backends\n",
"- **CRUD Operations**: Add, get, update, delete triples\n",
"- **Multi-Store**: Manage multiple stores simultaneously"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import TripleManager\n",
"from semantica.semantic_extract.triple_extractor import Triple\n",
"\n",
"# Create triple manager\n",
"manager = TripleManager()\n",
"\n",
"# Register a Blazegraph store (in-memory for demo)\n",
"store = manager.register_store(\n",
" store_id=\"demo\",\n",
" store_type=\"blazegraph\",\n",
" endpoint=\"http://localhost:9999/blazegraph/sparql\"\n",
")\n",
"\n",
"print(f\"Registered store: {store.store_id}\")\n",
"print(f\"Store type: {store.store_type}\")\n",
"print(f\"Endpoint: {store.endpoint}\")\n",
"\n",
"# Create a triple\n",
"triple = Triple(\n",
" subject=\"http://example.org/Alice\",\n",
" predicate=\"http://example.org/knows\",\n",
" object=\"http://example.org/Bob\",\n",
" confidence=0.95\n",
")\n",
"\n",
"# Add triple to store\n",
"result = manager.add_triple(triple, store_id=\"demo\")\n",
"print(f\"\\nTriple added: {result['success']}\")\n",
"print(f\"Triple: {triple.subject} -> {triple.predicate} -> {triple.object}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2: Store Registration and Management\n",
"\n",
"Register multiple stores and manage them.\n",
"\n",
"### Supported Backends\n",
"\n",
"| Backend | Best For | Performance | Features |\n",
"|---------|----------|-------------|----------|\n",
"| **Blazegraph** | Large datasets | Excellent | GPU acceleration, full-text |\n",
"| **Jena** | Java apps | Good | SHACL, inference |\n",
"| **RDF4J** | Transactions | Good | ACID, federation |\n",
"| **Virtuoso** | Enterprise | Excellent | SQL integration, clustering |"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import register_store\n",
"\n",
"# Register multiple stores using convenience function\n",
"blazegraph_store = register_store(\n",
" \"blazegraph_main\",\n",
" \"blazegraph\",\n",
" \"http://localhost:9999/blazegraph/sparql\"\n",
")\n",
"\n",
"jena_store = register_store(\n",
" \"jena_backup\",\n",
" \"jena\",\n",
" \"http://localhost:3030/ds\"\n",
")\n",
"\n",
"# List all registered stores\n",
"stores = manager.list_stores()\n",
"print(f\"Registered stores: {stores}\")\n",
"\n",
"# Get specific store\n",
"store = manager.get_store(\"blazegraph_main\")\n",
"print(f\"\\nStore details:\")\n",
"print(f\" ID: {store.store_id}\")\n",
"print(f\" Type: {store.store_type}\")\n",
"print(f\" Endpoint: {store.endpoint}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3: CRUD Operations\n",
"\n",
"Perform Create, Read, Update, Delete operations on triples.\n",
"\n",
"### Operations Overview\n",
"\n",
"- **Create**: `add_triple()`, `add_triples()`\n",
"- **Read**: `get_triple()`\n",
"- **Update**: `update_triple()`\n",
"- **Delete**: `delete_triple()`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import add_triple, add_triples, get_triples, update_triple, delete_triple\n",
"\n",
"# Create - Add single triple\n",
"triple1 = Triple(\n",
" subject=\"http://example.org/Alice\",\n",
" predicate=\"http://example.org/hasAge\",\n",
" object=\"30\"\n",
")\n",
"result = add_triple(triple1, store_id=\"demo\")\n",
"print(f\"Added single triple: {result['success']}\")\n",
"\n",
"# Create - Add multiple triples\n",
"triples = [\n",
" Triple(\"http://example.org/Alice\", \"http://example.org/hasCity\", \"New York\"),\n",
" Triple(\"http://example.org/Bob\", \"http://example.org/hasAge\", \"25\"),\n",
" Triple(\"http://example.org/Bob\", \"http://example.org/hasCity\", \"Boston\")\n",
"]\n",
"result = add_triples(triples, store_id=\"demo\")\n",
"print(f\"\\nAdded {result['total_triples']} triples in {result['batches']} batches\")\n",
"\n",
"# Read - Get triples for a subject\n",
"alice_triples = get_triples(\n",
" subject=\"http://example.org/Alice\",\n",
" store_id=\"demo\"\n",
")\n",
"print(f\"\\nFound {len(alice_triples)} triples for Alice\")\n",
"\n",
"# Update - Change Alice's age\n",
"old_triple = Triple(\"http://example.org/Alice\", \"http://example.org/hasAge\", \"30\")\n",
"new_triple = Triple(\"http://example.org/Alice\", \"http://example.org/hasAge\", \"31\")\n",
"result = update_triple(old_triple, new_triple, store_id=\"demo\")\n",
"print(f\"\\nUpdated triple: {result['success']}\")\n",
"\n",
"# Delete - Remove a triple\n",
"triple_to_delete = Triple(\"http://example.org/Bob\", \"http://example.org/hasCity\", \"Boston\")\n",
"result = delete_triple(triple_to_delete, store_id=\"demo\")\n",
"print(f\"Deleted triple: {result['success']}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4: SPARQL Query Execution\n",
"\n",
"Execute SPARQL queries with the QueryEngine.\n",
"\n",
"### Query Types\n",
"\n",
"- **SELECT**: Retrieve variable bindings\n",
"- **ASK**: Boolean queries\n",
"- **CONSTRUCT**: Build RDF graphs\n",
"- **DESCRIBE**: Describe resources"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import QueryEngine, BlazegraphAdapter\n",
"\n",
"# Create query engine with caching\n",
"engine = QueryEngine(enable_caching=True, enable_optimization=True)\n",
"\n",
"# Create adapter\n",
"adapter = BlazegraphAdapter(endpoint=\"http://localhost:9999/blazegraph/sparql\")\n",
"\n",
"# SELECT query\n",
"select_query = \"\"\"\n",
"PREFIX ex: <http://example.org/>\n",
"\n",
"SELECT ?person ?age ?city\n",
"WHERE {\n",
" ?person ex:hasAge ?age .\n",
" ?person ex:hasCity ?city .\n",
"}\n",
"ORDER BY DESC(?age)\n",
"LIMIT 10\n",
"\"\"\"\n",
"\n",
"result = engine.execute_query(select_query, adapter)\n",
"\n",
"print(f\"Query Results:\")\n",
"print(f\" Variables: {result.variables}\")\n",
"print(f\" Results: {len(result.bindings)}\")\n",
"print(f\" Execution time: {result.execution_time:.2f}s\")\n",
"print(f\" Cached: {result.metadata.get('cached', False)}\")\n",
"\n",
"print(\"\\nResults:\")\n",
"for binding in result.bindings:\n",
" person = binding.get('person', {}).get('value', '')\n",
" age = binding.get('age', {}).get('value', '')\n",
" city = binding.get('city', {}).get('value', '')\n",
" print(f\" {person}: Age {age}, City {city}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 5: Query Optimization\n",
"\n",
"Optimize SPARQL queries for better performance.\n",
"\n",
"### Optimization Features\n",
"\n",
"- **Query Planning**: Analyze execution steps\n",
"- **Cost Estimation**: Estimate query cost\n",
"- **Query Rewriting**: Optimize query structure\n",
"- **Caching**: Cache query results"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import optimize_query, plan_query\n",
"\n",
"# Original query\n",
"query = \"\"\"\n",
"SELECT ?s ?p ?o\n",
"WHERE {\n",
" ?s ?p ?o .\n",
"}\n",
"\"\"\"\n",
"\n",
"# Optimize query (adds LIMIT if missing)\n",
"optimized = optimize_query(query, add_limit=True, default_limit=1000)\n",
"print(\"Optimized Query:\")\n",
"print(optimized)\n",
"\n",
"# Create query plan\n",
"plan = plan_query(query)\n",
"print(f\"\\nQuery Plan:\")\n",
"print(f\" Original length: {len(plan.query)}\")\n",
"print(f\" Optimized length: {len(plan.optimized_query)}\")\n",
"print(f\" Estimated cost: {plan.estimated_cost}\")\n",
"print(f\" Execution steps:\")\n",
"for i, step in enumerate(plan.execution_steps, 1):\n",
" print(f\" {i}. {step}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 6: Bulk Loading\n",
"\n",
"Load large datasets efficiently with progress tracking.\n",
"\n",
"### Bulk Loading Features\n",
"\n",
"- **Batch Processing**: Process in configurable batches\n",
"- **Progress Tracking**: Monitor loading progress\n",
"- **Retry Mechanism**: Handle failures gracefully\n",
"- **Validation**: Validate before loading"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import BulkLoader, LoadProgress\n",
"\n",
"# Create bulk loader\n",
"loader = BulkLoader(\n",
" batch_size=1000,\n",
" max_retries=3\n",
")\n",
"\n",
"# Generate sample triples\n",
"large_dataset = [\n",
" Triple(\n",
" f\"http://example.org/entity{i}\",\n",
" \"http://example.org/hasName\",\n",
" f\"Entity {i}\"\n",
" )\n",
" for i in range(5000)\n",
"]\n",
"\n",
"# Progress callback\n",
"def progress_callback(progress: LoadProgress):\n",
" print(f\"Progress: {progress.progress_percentage:.1f}% \"\n",
" f\"({progress.loaded_triples}/{progress.total_triples}) \"\n",
" f\"Batch {progress.current_batch}/{progress.total_batches}\")\n",
"\n",
"# Load triples with progress tracking\n",
"adapter = BlazegraphAdapter(endpoint=\"http://localhost:9999/blazegraph/sparql\")\n",
"progress = loader.load_triples(\n",
" large_dataset,\n",
" adapter,\n",
" progress_callback=progress_callback\n",
")\n",
"\n",
"print(f\"\\nLoading Complete:\")\n",
"print(f\" Loaded: {progress.loaded_triples}/{progress.total_triples}\")\n",
"print(f\" Failed: {progress.failed_triples}\")\n",
"print(f\" Elapsed time: {progress.elapsed_time:.2f}s\")\n",
"print(f\" Throughput: {progress.metadata.get('throughput', 0):.0f} triples/sec\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 7: Store Adapters\n",
"\n",
"Work with different triple store backends.\n",
"\n",
"### Blazegraph Adapter\n",
"\n",
"High-performance triple store with GPU acceleration."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import BlazegraphAdapter\n",
"\n",
"# Create Blazegraph adapter\n",
"blazegraph = BlazegraphAdapter(\n",
" endpoint=\"http://localhost:9999/blazegraph/sparql\",\n",
" namespace=\"kb\",\n",
" timeout=30\n",
")\n",
"\n",
"# Add triples\n",
"triples = [\n",
" Triple(\"http://example.org/Alice\", \"http://example.org/hasSkill\", \"Python\")\n",
"]\n",
"result = blazegraph.add_triples(triples)\n",
"print(f\"Blazegraph - Added: {result['success']}\")\n",
"\n",
"# Execute SPARQL query\n",
"query = \"SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 5\"\n",
"result = blazegraph.execute_sparql(query)\n",
"print(f\"Blazegraph - Found {len(result['bindings'])} results\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Jena Adapter\n",
"\n",
"Full-featured RDF framework with inference support."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import JenaAdapter\n",
"\n",
"# Create Jena adapter (in-memory)\n",
"jena = JenaAdapter()\n",
"\n",
"# Or connect to Fuseki endpoint\n",
"# jena = JenaAdapter(\n",
"# endpoint=\"http://localhost:3030/ds\",\n",
"# dataset=\"default\",\n",
"# enable_inference=True\n",
"# )\n",
"\n",
"# Add triples with inference\n",
"triples = [\n",
" Triple(\n",
" \"http://example.org/Dog\",\n",
" \"http://www.w3.org/2000/01/rdf-schema#subClassOf\",\n",
" \"http://example.org/Animal\"\n",
" ),\n",
" Triple(\n",
" \"http://example.org/Fido\",\n",
" \"http://www.w3.org/1999/02/22-rdf-syntax-ns#type\",\n",
" \"http://example.org/Dog\"\n",
" )\n",
"]\n",
"result = jena.add_triples(triples)\n",
"print(f\"Jena - Added: {result['success']}\")\n",
"\n",
"# Query with inference (Fido is inferred to be an Animal)\n",
"query = \"\"\"\n",
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n",
"PREFIX ex: <http://example.org/>\n",
"SELECT ?animal WHERE {\n",
" ?animal rdf:type ex:Animal .\n",
"}\n",
"\"\"\"\n",
"result = jena.query(query)\n",
"print(f\"Jena - Found {len(result)} animals (with inference)\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### RDF4J Adapter\n",
"\n",
"Java-based RDF framework with transaction support."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import RDF4JAdapter\n",
"\n",
"# Create RDF4J adapter\n",
"rdf4j = RDF4JAdapter(\n",
" server_url=\"http://localhost:8080/rdf4j-server\",\n",
" repository_id=\"test\"\n",
")\n",
"\n",
"# Add triples with transaction\n",
"rdf4j.begin_transaction()\n",
"try:\n",
" triple = Triple(\n",
" \"http://example.org/Alice\",\n",
" \"http://example.org/hasEmail\",\n",
" \"alice@example.org\"\n",
" )\n",
" rdf4j.add_triple(\n",
" subject=triple.subject,\n",
" predicate=triple.predicate,\n",
" object_literal=triple.object\n",
" )\n",
" rdf4j.commit_transaction()\n",
" print(\"RDF4J - Transaction committed\")\n",
"except Exception as e:\n",
" rdf4j.rollback_transaction()\n",
" print(f\"RDF4J - Transaction rolled back: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Virtuoso Adapter\n",
"\n",
"Enterprise-grade RDF store with SQL integration."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import VirtuosoAdapter\n",
"\n",
"# Create Virtuoso adapter\n",
"virtuoso = VirtuosoAdapter(\n",
" host=\"localhost\",\n",
" port=1111,\n",
" user=\"dba\",\n",
" password=\"dba\"\n",
")\n",
"\n",
"# Create named graph\n",
"graph_uri = \"http://example.org/graph1\"\n",
"virtuoso.create_graph(graph_uri)\n",
"\n",
"# Add triples to named graph\n",
"triple = Triple(\n",
" \"http://example.org/Alice\",\n",
" \"http://example.org/worksAt\",\n",
" \"http://example.org/Company1\"\n",
")\n",
"virtuoso.add_triple(\n",
" subject=triple.subject,\n",
" predicate=triple.predicate,\n",
" object=triple.object,\n",
" graph=graph_uri\n",
")\n",
"\n",
"print(f\"Virtuoso - Added triple to graph: {graph_uri}\")\n",
"\n",
"# Query specific graph\n",
"query = f\"\"\"\n",
"PREFIX ex: <http://example.org/>\n",
"SELECT ?person ?company\n",
"FROM <{graph_uri}>\n",
"WHERE {{\n",
" ?person ex:worksAt ?company .\n",
"}}\n",
"\"\"\"\n",
"result = virtuoso.query(query)\n",
"print(f\"Virtuoso - Found {len(result)} results in graph\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 8: Triple Validation\n",
"\n",
"Validate triples before adding them to the store.\n",
"\n",
"### Validation Checks\n",
"\n",
"- **Required Fields**: Subject, predicate, object\n",
"- **Confidence Range**: 0-1 if provided\n",
"- **URI Format**: Valid URIs\n",
"- **Empty Components**: No empty values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.triple_store import validate_triples\n",
"\n",
"# Create triples (some invalid)\n",
"triples_to_validate = [\n",
" Triple(\"http://example.org/Alice\", \"http://example.org/knows\", \"http://example.org/Bob\"), # Valid\n",
" Triple(\"\", \"http://example.org/knows\", \"http://example.org/Charlie\"), # Invalid (empty subject)\n",
" Triple(\"http://example.org/Dave\", \"\", \"http://example.org/Eve\"), # Invalid (empty predicate)\n",
" Triple(\"http://example.org/Frank\", \"http://example.org/knows\", \"http://example.org/Grace\", confidence=1.5), # Invalid (confidence > 1)\n",
"]\n",
"\n",
"# Validate triples\n",
"validation = validate_triples(triples_to_validate)\n",
"\n",
"print(\"Validation Results:\")\n",
"print(f\" Valid: {validation['valid']}\")\n",
"print(f\" Valid triples: {validation['valid_triples']}/{validation['total_triples']}\")\n",
"print(f\"\\nErrors: {len(validation['errors'])}\")\n",
"for error in validation['errors']:\n",
" print(f\" - {error}\")\n",
"print(f\"\\nWarnings: {len(validation['warnings'])}\")\n",
"for warning in validation['warnings']:\n",
" print(f\" - {warning}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 9: Multi-Store Operations\n",
"\n",
"Work with multiple stores simultaneously.\n",
"\n",
"### Use Cases\n",
"\n",
"- **Primary/Backup**: Replicate to backup store\n",
"- **Read/Write Split**: Separate read and write stores\n",
"- **Multi-Tenant**: Different stores for different tenants"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Register multiple stores\n",
"manager = TripleManager()\n",
"\n",
"primary = manager.register_store(\n",
" \"primary\",\n",
" \"blazegraph\",\n",
" \"http://localhost:9999/blazegraph/sparql\"\n",
")\n",
"\n",
"backup = manager.register_store(\n",
" \"backup\",\n",
" \"jena\",\n",
" \"http://localhost:3030/ds\"\n",
")\n",
"\n",
"# Add to primary store\n",
"triple = Triple(\n",
" \"http://example.org/Document1\",\n",
" \"http://example.org/hasAuthor\",\n",
" \"http://example.org/Alice\"\n",
")\n",
"manager.add_triple(triple, store_id=\"primary\")\n",
"print(\"Added to primary store\")\n",
"\n",
"# Replicate to backup store\n",
"manager.add_triple(triple, store_id=\"backup\")\n",
"print(\"Replicated to backup store\")\n",
"\n",
"# List all stores\n",
"stores = manager.list_stores()\n",
"print(f\"\\nActive stores: {stores}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 10: Best Practices\n",
"\n",
"### Choosing the Right Backend\n",
"\n",
"1. **Blazegraph**: High-performance, large datasets, GPU acceleration\n",
"2. **Jena**: Java integration, SHACL validation, inference\n",
"3. **RDF4J**: Transaction support, ACID guarantees, federation\n",
"4. **Virtuoso**: Enterprise scale, SQL integration, clustering\n",
"\n",
"### Performance Tips\n",
"\n",
"- **Batch Operations**: Use `add_triples()` for multiple triples\n",
"- **Query Optimization**: Enable optimization and caching\n",
"- **Bulk Loading**: Use `BulkLoader` for large datasets\n",
"- **Validation**: Validate before loading to avoid errors\n",
"\n",
"### Configuration\n",
"\n",
"- **Batch Size**: 1000-10000 for bulk loading\n",
"- **Cache Size**: 1000-5000 for query caching\n",
"- **Timeout**: 30-60 seconds for queries\n",
"- **Retries**: 3-5 for bulk operations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"### What You've Learned\n",
"\n",
"In this notebook, you've learned how to:\n",
"\n",
"- Register and manage triple stores\n",
"- Perform CRUD operations on RDF triples\n",
"- Execute and optimize SPARQL queries\n",
"- Use bulk loading for large datasets\n",
"- Work with multiple store backends\n",
"- Validate triples before operations\n",
"- Choose the right backend for your use case\n",
"\n",
"### Key Takeaways\n",
"\n",
"1. **Multi-Backend Support**: Choose the right backend for your needs\n",
"2. **SPARQL Power**: Full SPARQL 1.1 support with optimization\n",
"3. **Bulk Loading**: Efficient loading with progress tracking\n",
"4. **Query Optimization**: Automatic query optimization and caching\n",
"5. **Validation**: Pre-load validation prevents errors\n",
"6. **Multi-Store**: Manage multiple stores simultaneously\n",
"\n",
"### Next Steps\n",
"\n",
"**Further Reading**:\n",
"- [Triple Store API Reference](https://semantica.readthedocs.io/reference/triple_store/)\n",
"- [SPARQL 1.1 Specification](https://www.w3.org/TR/sparql11-query/)\n",
"- [Knowledge Graph Building](../use_cases/advanced_rag/01_GraphRAG_Complete.ipynb)\n",
"\n",
"---\n",
"\n",
"**Questions or Issues?** Check out our [GitHub repository](https://github.com/Hawksight-AI/semantica) or [documentation](https://semantica.readthedocs.io)."
]
}
],
"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.10.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@@ -0,0 +1,235 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Getting Started with Triplet Store\n",
"\n",
"This notebook introduces the **Semantica Triplet Store** module, which allows you to store and query knowledge graph data using industry-standard RDF Triple Stores.\n",
"\n",
"## What is a Triplet Store?\n",
"\n",
"A Triplet Store (or RDF Store) is a database optimized for storing and retrieving triples: **Subject - Predicate - Object**.\n",
"For example: `Alice` (Subject) `knows` (Predicate) `Bob` (Object).\n",
"\n",
"Semantica supports:\n",
"- **Blazegraph** (Default, High Performance)\n",
"- **Apache Jena** (Great for inference)\n",
"- **RDF4J** (Standard Java framework)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"import os\n",
"\n",
"# Add the project root to the path so we can import the local version of semantica\n",
"sys.path.append(os.path.abspath('../../'))\n",
"\n",
"# If running in Google Colab, uncomment the following line to install dependencies\n",
"# !pip install -q semantica"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import the TripletStore class\n",
"from semantica.triplet_store import TripletStore\n",
"from semantica.semantic_extract.triplet_extractor import Triplet"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Connecting to a Store\n",
"\n",
"To use the Triplet Store, you need a backend running. In this example, we assume a Blazegraph instance is running locally.\n",
"\n",
"> **Note:** If you don't have a store running, the code below shows how you *would* connect."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Connect to a Blazegraph instance\n",
"# You can also use backend=\"jena\" or backend=\"rdf4j\"\n",
"store = TripletStore(\n",
" backend=\"blazegraph\",\n",
" endpoint=\"http://localhost:9999/blazegraph\"\n",
")\n",
"\n",
"# Check connection status\n",
"if hasattr(store._store_backend, 'connected') and store._store_backend.connected:\n",
" print(f\"Successfully connected to {store.backend_type} store at {store.endpoint}\")\n",
"else:\n",
" print(f\"Warning: Could not connect to {store.backend_type} at {store.endpoint}\")\n",
" print(\"Operations requiring a live store connection will be skipped or fail.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Creating Triplets\n",
"\n",
"We use the `Triplet` class to define our data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Define a single triplet\n",
"triplet1 = Triplet(\n",
" subject=\"http://example.org/Alice\",\n",
" predicate=\"http://xmlns.com/foaf/0.1/knows\",\n",
" object=\"http://example.org/Bob\"\n",
")\n",
"\n",
"print(f\"Created triplet: {triplet1.subject} -> {triplet1.predicate} -> {triplet1.object}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Adding Data\n",
"\n",
"You can add triplets one by one or in bulk."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from semantica.utils.exceptions import ProcessingError\n",
"\n",
"try:\n",
" # Add a single triplet\n",
" store.add_triplet(triplet1)\n",
" print(\"Added single triplet successfully.\")\n",
"\n",
" # Create more triplets\n",
" triplets = [\n",
" Triplet(\n",
" subject=\"http://example.org/Bob\",\n",
" predicate=\"http://xmlns.com/foaf/0.1/knows\",\n",
" object=\"http://example.org/Charlie\"\n",
" ),\n",
" Triplet(\n",
" subject=\"http://example.org/Charlie\",\n",
" predicate=\"http://xmlns.com/foaf/0.1/knows\",\n",
" object=\"http://example.org/David\"\n",
" )\n",
" ]\n",
"\n",
" # Bulk add\n",
" store.add_triplets(triplets)\n",
" print(\"Added bulk triplets successfully.\")\n",
"\n",
"except ProcessingError as e:\n",
" print(f\"Operation skipped: {e}\")\n",
"except Exception as e:\n",
" print(f\"An error occurred: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Querying Data (SPARQL)\n",
"\n",
"Use SPARQL queries to retrieve data from the store."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Simple query to get all triplets (limited to 10)\n",
"query = \"\"\"\n",
"SELECT ?s ?p ?o\n",
"WHERE {\n",
" ?s ?p ?o\n",
"}\n",
"LIMIT 10\n",
"\"\"\"\n",
"\n",
"try:\n",
" results = store.execute_query(query)\n",
" print(\"Query Results:\", results)\n",
"except ProcessingError as e:\n",
" print(f\"Query skipped: {e}\")\n",
"except Exception as e:\n",
" print(f\"An error occurred: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Deleting Data\n",
"\n",
"Remove triplets when they are no longer needed."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"store.delete_triplet(triplet1)\n",
"print(\"Deleted triplet1\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Next Steps\n",
"\n",
"Check out the **Advanced Triplet Store** guide in the `cookbook/advanced` folder for more complex operations like bulk loading optimization, transactions, and advanced SPARQL features."
]
}
],
"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.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+10
View File
@@ -0,0 +1,10 @@
api_keys:
openai: your_key_here
anthropic: your_key_here
embedding:
provider: openai
model: text-embedding-3-large
dimensions: 3072
knowledge_graph:
backend: networkx
temporal: true
@@ -0,0 +1,63 @@
@prefix : <https://docs.semantica.dev/ontology/v1.0> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<https://docs.semantica.dev/ontology/founded> a owl:DatatypeProperty ;
rdfs:label "founded" ;
rdfs:domain <https://docs.semantica.dev/ontology/Company> ;
rdfs:range xsd:string .
<https://docs.semantica.dev/ontology/leads> a owl:ObjectProperty ;
rdfs:label "leads" ;
rdfs:domain <https://docs.semantica.dev/ontology/OwlThing> ;
rdfs:range <https://docs.semantica.dev/ontology/OwlThing> .
<https://docs.semantica.dev/ontology/manages> a owl:ObjectProperty ;
rdfs:label "manages" ;
rdfs:domain <https://docs.semantica.dev/ontology/OwlThing> ;
rdfs:range <https://docs.semantica.dev/ontology/OwlThing> .
<https://docs.semantica.dev/ontology/name> a owl:DatatypeProperty ;
rdfs:label "name" ;
rdfs:domain <https://docs.semantica.dev/ontology/Company>,
<https://docs.semantica.dev/ontology/Department>,
<https://docs.semantica.dev/ontology/Person>,
<https://docs.semantica.dev/ontology/Project> ;
rdfs:range xsd:string .
<https://docs.semantica.dev/ontology/partOf> a owl:ObjectProperty ;
rdfs:label "partOf" ;
rdfs:domain <https://docs.semantica.dev/ontology/OwlThing> ;
rdfs:range <https://docs.semantica.dev/ontology/OwlThing> .
<https://docs.semantica.dev/ontology/role> a owl:DatatypeProperty ;
rdfs:label "role" ;
rdfs:domain <https://docs.semantica.dev/ontology/Person> ;
rdfs:range xsd:string .
: a owl:Ontology ;
rdfs:label "CorporateOntology" ;
owl:versionInfo "1.0" .
<https://docs.semantica.dev/ontology/worksOn> a owl:ObjectProperty ;
rdfs:label "worksOn" ;
rdfs:domain <https://docs.semantica.dev/ontology/OwlThing> ;
rdfs:range <https://docs.semantica.dev/ontology/OwlThing> .
<https://docs.semantica.dev/ontology/Department> a owl:Class ;
rdfs:label "Department" ;
rdfs:comment "Class representing department entities" .
<https://docs.semantica.dev/ontology/Project> a owl:Class ;
rdfs:label "Project" ;
rdfs:comment "Class representing project entities" .
<https://docs.semantica.dev/ontology/Company> a owl:Class ;
rdfs:label "Company" ;
rdfs:comment "Class representing company entities" .
<https://docs.semantica.dev/ontology/Person> a owl:Class ;
rdfs:label "Person" ;
rdfs:comment "Class representing person entities" .
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
Graph Retrieval-Augmented Generation (GraphRAG): A New Era for Intelligent Search
GraphRAG is an advanced technique that combines the retrieval capabilities of vector databases with the structural reasoning of knowledge graphs. Unlike traditional RAG, which relies solely on vector similarity, GraphRAG leverages the relationships between entities to provide more contextually accurate and comprehensive answers.
Key Components:
1. Knowledge Graph: A structured representation of data where nodes represent entities and edges represent relationships.
2. Vector Search: Finds semantically similar text chunks.
3. Graph Traversal: Navigates the knowledge graph to find related entities that might not be semantically similar but are structurally relevant.
Benefits:
- Improved Context: By following relationships, the system can understand the broader context of a query.
- Multi-hop Reasoning: Can answer complex questions that require connecting multiple pieces of information.
- Reduced Hallucinations: Grounding answers in a verified knowledge structure reduces the likelihood of generating false information.
@@ -0,0 +1,5 @@
RETINOL CLINICAL GUIDE
Mechanism: Binds to retinoic acid receptors to increase cellular turnover.
Precautions: Should not be used with high-concentration AHA/BHA exfoliants.
Synergy: Highly effective when paired with Niacinamide to offset potential erythema.
@@ -0,0 +1,6 @@
RETINOL CLINICAL GUIDE v2.1
Mechanism: Binds to retinoic acid receptors (RAR) to increase cellular turnover.
Precautions: Should not be used with high-concentration AHA/BHA exfoliants.
Synergy: Highly effective when paired with Niacinamide to offset potential erythema.
Target: Stratum corneum thickening and dermal collagen synthesis.
@@ -0,0 +1,254 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="type" for="node" attr.name="type" attr.type="string"/>
<key id="confidence" for="node" attr.name="confidence" attr.type="double"/>
<graph id="G" edgedefault="directed">
<node id="makeup_and_beauty_blog">
<data key="label">Makeup and Beauty Blog</data>
<data key="type">ORG</data>
<data key="confidence">1.0</data>
</node>
<node id="monday_poll">
<data key="label">Monday Poll</data>
<data key="type">EVENT</data>
<data key="confidence">1.0</data>
</node>
<node id="2007">
<data key="label">2007</data>
<data key="type">DATE</data>
<data key="confidence">1.0</data>
</node>
<node id="rosacea">
<data key="label">Rosacea</data>
<data key="type">CONCEPT</data>
<data key="confidence">1.0</data>
</node>
<node id="dr._bailey">
<data key="label">Dr. Bailey</data>
<data key="type">PERSON</data>
<data key="confidence">1.0</data>
</node>
<node id="green_tea_antioxidant_skin_therapy">
<data key="label">Green Tea Antioxidant Skin Therapy</data>
<data key="type">PRODUCT</data>
<data key="confidence">1.0</data>
</node>
<node id="vol._892">
<data key="label">Vol. 892</data>
<data key="type">EVENT</data>
<data key="confidence">1.0</data>
</node>
<node id="laneige">
<data key="label">Laneige</data>
<data key="type">ORG</data>
<data key="confidence">1.0</data>
</node>
<node id="sausalito">
<data key="label">Sausalito</data>
<data key="type">GPE</data>
<data key="confidence">1.0</data>
</node>
<node id="ulta">
<data key="label">Ulta</data>
<data key="type">ORG</data>
<data key="confidence">1.0</data>
</node>
<node id="december_15,_2025">
<data key="label">December 15, 2025</data>
<data key="type">DATE</data>
<data key="confidence">1.0</data>
</node>
<node id="jo_malone">
<data key="label">Jo Malone</data>
<data key="type">ORG</data>
<data key="confidence">1</data>
</node>
<node id="trader_joe">
<data key="label">Trader Joe</data>
<data key="type">ORG</data>
<data key="confidence">1</data>
</node>
<node id="hawaii">
<data key="label">hawaii</data>
<data key="type">GPE</data>
<data key="confidence">1.0</data>
</node>
<node id="benzoyl_peroxide_cream">
<data key="label">Benzoyl Peroxide Cream</data>
<data key="type">PRODUCT</data>
<data key="confidence">1</data>
</node>
<node id="facial_dandruff">
<data key="label">Facial dandruff</data>
<data key="type">CONCEPT</data>
<data key="confidence">1</data>
</node>
<node id="calming_zinc_soap">
<data key="label">Calming Zinc Soap</data>
<data key="type">PRODUCT</data>
<data key="confidence">1</data>
</node>
<node id="hydrate">
<data key="label">Hydrate</data>
<data key="type">CONCEPT</data>
<data key="confidence">1.0</data>
</node>
<node id="daily_moisturizing_face_cream">
<data key="label">Daily Moisturizing Face Cream</data>
<data key="type">PRODUCT</data>
<data key="confidence">1.0</data>
</node>
<node id="omega_enriched_face_booster_oil">
<data key="label">Omega Enriched Face Booster Oil</data>
<data key="type">PRODUCT</data>
<data key="confidence">1.0</data>
</node>
<edge source="Makeup and Beauty Blog" target="Monday Poll">
<data key="label">hosts</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Monday Poll" target="December 15, 2025">
<data key="label">occurs on</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Makeup and Beauty Blog Monday Poll, Vol. 893">
<data key="label">publishes</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Monday">
<data key="label">has</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="2007">
<data key="label">has</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Monday Poll">
<data key="label">hosts</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Makeup and Beauty Blog Monday Poll">
<data key="label">posts</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Vol. 892">
<data key="label">posts</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="2007">
<data key="label">has been active since</data>
<data key="confidence">0.9</data>
</edge>
<edge source="MBB" target="Makeup and Beauty Blog">
<data key="label">related_to</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Makeup and Beauty Blog">
<data key="label">related_to</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Monday Poll">
<data key="label">hosts</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Vol. 891">
<data key="label">posts</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Makeup and Beauty Blog" target="Monday Poll">
<data key="label">posts</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Cavallo Point" target="Sausalito">
<data key="label">located_in</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Dr. Bailey" target="Green Tea Antioxidant Skin Therapy">
<data key="label">prescribes</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Green Tea Antioxidant Skin Therapy" target="Rosacea Therapy Skin Care Kit">
<data key="label">part of</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Dr. Bailey" target="Rosacea Therapy Skin Care Kit">
<data key="label">uses</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Rosacea Therapy Skin Care Kit" target="rosacea treatment routine">
<data key="label">part of</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Dr. Bailey" target="rosacea treatment routine">
<data key="label">uses</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Facial dandruff" target="rosacea">
<data key="label">often occurs with</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Facial dandruff" target="rosacea">
<data key="label">needs to be addressed</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Calming Zinc Soap" target="Facial dandruff">
<data key="label">is often sufficient to control</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Calming Zinc Soap" target="rosacea">
<data key="label">is often sufficient to control</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Green Tea Antioxidant Skin Therapy" target="Facial dandruff">
<data key="label">is often sufficient to control</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Green Tea Antioxidant Skin Therapy" target="rosacea">
<data key="label">is often sufficient to control</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Dr. Bailey's Skincare" target="Calming Zinc Soap">
<data key="label">produces</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Dr. Bailey's Skincare" target="Green Tea Antioxidant Skin Therapy">
<data key="label">produces</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Dr. Bailey" target="Calming Zinc Soap">
<data key="label">prescribes</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Dr. Bailey" target="Green Tea Antioxidant Skin Therapy">
<data key="label">prescribes</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Hydrate" target="Daily Moisturizing Face Cream">
<data key="label">is_achieved_by</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Daily Moisturizing Face Cream" target="Omega Enriched Face Booster Oil">
<data key="label">can_be_combined_with</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Omega Enriched Face Booster Oil" target="castor seed oil">
<data key="label">contains</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Omega Enriched Face Booster Oil" target="sea buckthorn">
<data key="label">contains</data>
<data key="confidence">0.9</data>
</edge>
<edge source="Daily Moisturizing Face Cream" target="Omega Enriched Face Booster Oil">
<data key="label">can_be_replaced_with</data>
<data key="confidence">0.9</data>
</edge>
</graph>
</graphml>
@@ -0,0 +1,678 @@
{
"nodes": [
{
"id": "makeup_and_beauty_blog",
"label": "Makeup and Beauty Blog",
"type": "ORG",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "makeup_and_beauty_blog",
"name": "Makeup and Beauty Blog",
"source": null
},
{
"id": "makeup_and_beauty_blog",
"name": "Makeup and Beauty Blog",
"source": null
},
{
"id": "makeup_and_beauty_blog_monday_poll,_vol._893",
"name": "Makeup and Beauty Blog Monday Poll, Vol. 893",
"source": null
},
{
"id": "makeup_and_beauty_blog_monday_poll",
"name": "Makeup and Beauty Blog Monday Poll",
"source": null
},
{
"id": "mbb",
"name": "MBB",
"source": null
}
],
"merge_count": 5
}
}
},
{
"id": "monday_poll",
"label": "Monday Poll",
"type": "EVENT",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "monday_poll",
"name": "Monday Poll",
"source": null
},
{
"id": "monday_poll",
"name": "Monday Poll",
"source": null
},
{
"id": "monday",
"name": "Monday",
"source": null
},
{
"id": "holiday",
"name": "holiday",
"source": null
},
{
"id": "holiday",
"name": "holiday",
"source": null
}
],
"merge_count": 5
}
}
},
{
"id": "2007",
"label": "2007",
"type": "DATE",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "2007",
"name": "2007",
"source": null
},
{
"id": "2007",
"name": "2007",
"source": null
},
{
"id": "2024",
"name": "2024",
"source": null
}
],
"merge_count": 3
}
}
},
{
"id": "rosacea",
"label": "Rosacea",
"type": "CONCEPT",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "rosacea",
"name": "Rosacea",
"source": null
},
{
"id": "rosacea",
"name": "rosacea",
"source": null
},
{
"id": "rosacea_treatment_routine",
"name": "rosacea treatment routine",
"source": null
},
{
"id": "rosie",
"name": "Rosie",
"source": null
},
{
"id": "rosacea_therapy_skin_care_kit",
"name": "Rosacea Therapy Skin Care Kit",
"source": null
},
{
"id": "marnie",
"name": "Marnie",
"source": null
},
{
"id": "cavallo_point",
"name": "Cavallo Point",
"source": null
},
{
"id": "castor_seed_oil",
"name": "castor seed oil",
"source": null
}
],
"merge_count": 8
}
}
},
{
"id": "dr._bailey",
"label": "Dr. Bailey",
"type": "PERSON",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "dr._bailey",
"name": "Dr. Bailey",
"source": null
},
{
"id": "dr._bailey",
"name": "Dr. Bailey",
"source": null
},
{
"id": "dr._bailey's_skincare",
"name": "Dr. Bailey's Skincare",
"source": null
},
{
"id": "dr._bailey's_skincare",
"name": "Dr. Bailey's Skincare",
"source": null
}
],
"merge_count": 4
}
}
},
{
"id": "green_tea_antioxidant_skin_therapy",
"label": "Green Tea Antioxidant Skin Therapy",
"type": "PRODUCT",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "green_tea_antioxidant_skin_therapy",
"name": "Green Tea Antioxidant Skin Therapy",
"source": null
},
{
"id": "green_tea_antioxidant_skin_therapy",
"name": "Green Tea Antioxidant Skin Therapy",
"source": null
}
],
"merge_count": 2
}
}
},
{
"id": "vol._892",
"label": "Vol. 892",
"type": "EVENT",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "vol._892",
"name": "Vol. 892",
"source": null
},
{
"id": "vol._891",
"name": "Vol. 891",
"source": null
}
],
"merge_count": 2
}
}
},
{
"id": "laneige",
"label": "Laneige",
"type": "ORG",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "laneige",
"name": "Laneige",
"source": null
},
{
"id": "lanikai",
"name": "Lanikai",
"source": null
}
],
"merge_count": 2
}
}
},
{
"id": "sausalito",
"label": "Sausalito",
"type": "GPE",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "sausalito",
"name": "Sausalito",
"source": null
},
{
"id": "sea_buckthorn",
"name": "sea buckthorn",
"source": null
}
],
"merge_count": 2
}
}
},
{
"id": "ulta",
"label": "Ulta",
"type": "ORG",
"attributes": {
"confidence": 1.0,
"provenance": {
"merged_from": [
{
"id": "ulta",
"name": "Ulta",
"source": null
},
{
"id": "clotrimazole",
"name": "clotrimazole",
"source": null
}
],
"merge_count": 2
}
}
},
{
"id": "december_15,_2025",
"label": "December 15, 2025",
"type": "DATE",
"attributes": {
"confidence": 1.0
}
},
{
"id": "jo_malone",
"label": "Jo Malone",
"type": "ORG",
"attributes": {
"confidence": 1
}
},
{
"id": "trader_joe",
"label": "Trader Joe",
"type": "ORG",
"attributes": {
"confidence": 1
}
},
{
"id": "hawaii",
"label": "hawaii",
"type": "GPE",
"attributes": {
"confidence": 1.0
}
},
{
"id": "benzoyl_peroxide_cream",
"label": "Benzoyl Peroxide Cream",
"type": "PRODUCT",
"attributes": {
"confidence": 1
}
},
{
"id": "facial_dandruff",
"label": "Facial dandruff",
"type": "CONCEPT",
"attributes": {
"confidence": 1
}
},
{
"id": "calming_zinc_soap",
"label": "Calming Zinc Soap",
"type": "PRODUCT",
"attributes": {
"confidence": 1
}
},
{
"id": "hydrate",
"label": "Hydrate",
"type": "CONCEPT",
"attributes": {
"confidence": 1.0
}
},
{
"id": "daily_moisturizing_face_cream",
"label": "Daily Moisturizing Face Cream",
"type": "PRODUCT",
"attributes": {
"confidence": 1.0
}
},
{
"id": "omega_enriched_face_booster_oil",
"label": "Omega Enriched Face Booster Oil",
"type": "PRODUCT",
"attributes": {
"confidence": 1.0
}
}
],
"edges": [
{
"source": "Makeup and Beauty Blog",
"target": "Monday Poll",
"type": "hosts",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Monday Poll",
"target": "December 15, 2025",
"type": "occurs on",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Makeup and Beauty Blog Monday Poll, Vol. 893",
"type": "publishes",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Monday",
"type": "has",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "2007",
"type": "has",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Monday Poll",
"type": "hosts",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Makeup and Beauty Blog Monday Poll",
"type": "posts",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Vol. 892",
"type": "posts",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "2007",
"type": "has been active since",
"attributes": {
"confidence": 0.9
}
},
{
"source": "MBB",
"target": "Makeup and Beauty Blog",
"type": "related_to",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Makeup and Beauty Blog",
"type": "related_to",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Monday Poll",
"type": "hosts",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Vol. 891",
"type": "posts",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Makeup and Beauty Blog",
"target": "Monday Poll",
"type": "posts",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Cavallo Point",
"target": "Sausalito",
"type": "located_in",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Dr. Bailey",
"target": "Green Tea Antioxidant Skin Therapy",
"type": "prescribes",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Green Tea Antioxidant Skin Therapy",
"target": "Rosacea Therapy Skin Care Kit",
"type": "part of",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Dr. Bailey",
"target": "Rosacea Therapy Skin Care Kit",
"type": "uses",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Rosacea Therapy Skin Care Kit",
"target": "rosacea treatment routine",
"type": "part of",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Dr. Bailey",
"target": "rosacea treatment routine",
"type": "uses",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Facial dandruff",
"target": "rosacea",
"type": "often occurs with",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Facial dandruff",
"target": "rosacea",
"type": "needs to be addressed",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Calming Zinc Soap",
"target": "Facial dandruff",
"type": "is often sufficient to control",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Calming Zinc Soap",
"target": "rosacea",
"type": "is often sufficient to control",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Green Tea Antioxidant Skin Therapy",
"target": "Facial dandruff",
"type": "is often sufficient to control",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Green Tea Antioxidant Skin Therapy",
"target": "rosacea",
"type": "is often sufficient to control",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Dr. Bailey's Skincare",
"target": "Calming Zinc Soap",
"type": "produces",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Dr. Bailey's Skincare",
"target": "Green Tea Antioxidant Skin Therapy",
"type": "produces",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Dr. Bailey",
"target": "Calming Zinc Soap",
"type": "prescribes",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Dr. Bailey",
"target": "Green Tea Antioxidant Skin Therapy",
"type": "prescribes",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Hydrate",
"target": "Daily Moisturizing Face Cream",
"type": "is_achieved_by",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Daily Moisturizing Face Cream",
"target": "Omega Enriched Face Booster Oil",
"type": "can_be_combined_with",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Omega Enriched Face Booster Oil",
"target": "castor seed oil",
"type": "contains",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Omega Enriched Face Booster Oil",
"target": "sea buckthorn",
"type": "contains",
"attributes": {
"confidence": 0.9
}
},
{
"source": "Daily Moisturizing Face Cream",
"target": "Omega Enriched Face Booster Oil",
"type": "can_be_replaced_with",
"attributes": {
"confidence": 0.9
}
}
],
"metadata": {
"num_entities": 20,
"num_relationships": 35,
"temporal_enabled": false,
"timestamp": "2025-12-24T12:46:41.535755",
"entity_resolution_applied": true
}
}
@@ -0,0 +1 @@
{"entities": [{"id": "python_org", "name": "Python Software Foundation", "type": "Organization"}, {"id": "guido_van_rossum", "name": "Guido van Rossum", "type": "Person"}], "relationships": [{"source": "guido_van_rossum", "target": "python_org", "type": "FOUNDED"}]}
@@ -0,0 +1,38 @@
{
"entities": [
{
"id": "hyaluronic_acid",
"name": "Hyaluronic Acid",
"type": "Ingredient",
"properties": {
"role": "Humectant"
}
},
{
"id": "retinol",
"name": "Retinol",
"type": "Ingredient",
"properties": {
"role": "Anti-aging actives"
}
},
{
"id": "niacinamide",
"name": "Niacinamide",
"type": "Ingredient",
"properties": {
"role": "Barrier repair"
}
}
],
"relationships": [
{
"source": "hyaluronic_acid",
"target": "niacinamide",
"type": "COMPLEMENTS",
"properties": {
"benefit": "Hydration + Barrier"
}
}
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1 @@
Apoptotic signatures allow early and rapid screening of drug-induced liver injury to accelerate drug discovery
@@ -0,0 +1 @@
SynergyGraph: predicting cell line specific drug combination synergy scores using knowledge graph representation and hypergraph modeling
@@ -0,0 +1 @@
Unraveling the mechanism of curcumin in coronary slow flow phenomenon through network pharmacology and molecular docking
@@ -0,0 +1 @@
Penicillium chrysogenum originated chloro-diydropyridyl-oxopropanimidic acid derivative as a potent EPSP synthase-targeted bioherbicide against invasive weed species
@@ -0,0 +1 @@
Enhancing the anti-cancer potential of resveratrol through cocrystal technology in colorectal cancerous rats
@@ -0,0 +1 @@
Synthesis, spectral, thermal, and biological characterization of Se(IV) nanocomplexes derived from vitamin E and amino acid mixed ligands as a metal-drug model
@@ -0,0 +1 @@
BT-11 targets the LANCL2 pathway to attenuate cognitive deficits and hippocampal pathology in Alzheimers transgenic rats
@@ -0,0 +1 @@
Saffron as a natural modulator of reverse cholesterol transport genes in atherosclerotic rabbits, with molecular docking insights
@@ -0,0 +1 @@
Simultaneous targeting of KRAS and CDK4 synergistically induces durable growth arrest in pancreatic cancer cells
@@ -0,0 +1 @@
Antiproliferative activity of Moringa oleifera (L.) Lam. and Moringa stenopetala (Bak.) Cufod. leaves extract against selected cancer cells in primary cell culture
@@ -0,0 +1 @@
Applications of Sombor topological indices and entropy measures for QSPR modeling of anticancer drugs: a Python-based methodology
@@ -0,0 +1 @@
In-silico studies, synthesis, and pharmacological screening of novel multitarget diphenylpyrazole scaffold as EGFR/BRAF and cyclooxygenase-2 inhibitors
@@ -0,0 +1 @@
Rational design and in silico characterization of a multiepitope mRNA vaccine candidate against human metapneumovirus (hMPV) using reverse vaccinology and immunoinformatics approaches
@@ -0,0 +1 @@
Unveiling novel potential drug targets for lung cancer through Mendelian randomization analysis
@@ -0,0 +1 @@
Comparative analysis of OECD guideline data and Tox21 assays to improve reproductive and developmental toxicity prediction
@@ -0,0 +1 @@
High-throughput triazole-based combinatorial click chemistry for the synthesis and identification of functional metal complexes
@@ -0,0 +1 @@
Efficacy and safety assessment of gelatin hemostatic matrix in a burr hole neurosurgical beagle model
@@ -0,0 +1 @@
Biological and computer-aided evaluation of 3-methoxy-13α-estrone-16α-diphenylphosphine oxide as a new antiestrogenic agent
@@ -0,0 +1 @@
Design and optimization of intranasal aripiprazole-loaded nanostructured lipid carriers for enhanced brain targeting in schizophrenia: in vitro and ex vivo evaluation
@@ -0,0 +1 @@
Endosome-phagophore linking assemblies for the degradation of membrane/extracellular proteins
@@ -0,0 +1 @@
Protodioscin enhances Methotrexate-induced senescence and senolytic activity in HepG2 liver cancer spheroids by modulating cell cycle regulators and the TGF-β/p-Smad2-4 signaling pathway
@@ -0,0 +1 @@
Morpholino-RNA duplex exhibits robust, sustained, and safe steric-block antisense activity by intracerebroventricular and intrathecal injection
@@ -0,0 +1 @@
Pushing the limits of hydrogen/deuterium exchange mass spectrometry to study protein:fragment low affinity interactions
@@ -0,0 +1 @@
Cannabidiol perturbs macrophage polarization by interfering with the metabolic flux and PI3K/Akt pathway
@@ -0,0 +1 @@
Bidirectional reinforcement learning neural network for constrained molecular design
@@ -0,0 +1 @@
Phytochemical investigation and antibacterial activities of Cordia africana roots extracts
@@ -0,0 +1 @@
Similar short-term efficacy of oral levosulpiride and intravitreal ranibizumab in patients with diabetic macular oedema
@@ -0,0 +1 @@
SIMD: Synergistic integration mutualistic platform based on single-cell and proteotranscriptomics for drug repositioning
@@ -0,0 +1 @@
Elucidating the anti-fibrotic mechanisms of Abrus cantoniensis in hepatic fibrosis using network pharmacology and proteomics
@@ -0,0 +1 @@
Identification of bioactive phytoconstituents as promising ABL2 inhibitors using virtual screening and molecular dynamics simulation
+9
View File
@@ -0,0 +1,9 @@
Aspirin (acetylsalicylic acid) is a medication used to reduce pain, fever, or inflammation.
It targets cyclooxygenase enzymes COX-1 and COX-2. Aspirin is commonly used for cardiovascular protection.
Ibuprofen is a nonsteroidal anti-inflammatory drug (NSAID) that targets COX-1 and COX-2 enzymes.
Metformin is an antidiabetic medication that targets AMP-activated protein kinase (AMPK).
Insulin targets the insulin receptor (INSR) to regulate glucose metabolism.
Warfarin is an anticoagulant that targets vitamin K epoxide reductase complex subunit 1 (VKORC1).
Atorvastatin is a statin medication that targets HMG-CoA reductase.
+11
View File
@@ -0,0 +1,11 @@
Variant rs699 is located in the AGT gene and associated with hypertension.
Variant rs7412 in APOE gene is linked to Alzheimer's disease risk.
BRCA1 variant c.5266dupC increases breast cancer susceptibility.
CFTR variant F508del causes cystic fibrosis.
Variant rs1800566 in NAT2 gene affects drug metabolism.
Variant rs1042713 in ADRB2 gene is associated with asthma response.
TP53 variant R273H is linked to multiple cancer types.
Variant rs1799853 in CYP2C9 gene affects warfarin metabolism.
Variant rs1057910 in CYP2C9 affects phenytoin metabolism.
Variant rs9923231 in VKORC1 gene influences warfarin dosing.
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="type" for="node" attr.name="type" attr.type="string"/>
<key id="confidence" for="node" attr.name="confidence" attr.type="double"/>
<graph id="G" edgedefault="directed">
</graph>
</graphml>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="type" for="node" attr.name="type" attr.type="string"/>
<key id="confidence" for="node" attr.name="confidence" attr.type="double"/>
<graph id="G" edgedefault="directed">
</graph>
</graphml>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+9
View File
@@ -0,0 +1,9 @@
Transaction 0x123 transfers 1000 ETH from wallet 0xABC to wallet 0xDEF at block 18500000.
Transaction 0x456 transfers 500 BTC from wallet 0xGHI to wallet 0xJKL at block 18500001.
Large transaction 0x789 moves 10000 ETH (whale movement) from wallet 0xMNO to wallet 0xPQR at block 18500002.
Transaction 0xabc transfers 200 USDT from wallet 0xSTU to wallet 0xVWX at block 18500003.
Transaction 0xdef transfers 5000 ETH from wallet 0xYZA to wallet 0xBCD at block 18500004.
Transaction 0x111 transfers 3000 DAI from wallet 0xEFG to wallet 0xHIJ at block 18500005.
Transaction 0x222 transfers 1500 USDC from wallet 0xKLM to wallet 0xNOP at block 18500006.

Some files were not shown because too many files have changed in this diff Show More