chore: Prepare release v0.2.0

This commit is contained in:
KaifAhmad1
2026-01-10 23:32:10 +05:30
parent 1a2604255f
commit 87a08e0240
11 changed files with 75 additions and 107 deletions
+2
View File
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [0.2.0] - 2026-01-10
### Added ### Added
- **Amazon Neptune Support**: - **Amazon Neptune Support**:
- Added `AmazonNeptuneStore` providing Amazon Neptune graph database integration via Bolt protocol and OpenCypher. - Added `AmazonNeptuneStore` providing Amazon Neptune graph database integration via Bolt protocol and OpenCypher.
+1 -1
View File
@@ -28,7 +28,7 @@
*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.* *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****Latest Version: 0.1.1****Production Ready****Community Driven** **100% Open Source****MIT Licensed****Latest Version: 0.2.0****Production Ready****Community Driven**
[**Discord**](https://discord.gg/pMHguUzG) [**Discord**](https://discord.gg/pMHguUzG)
+3 -3
View File
@@ -26,10 +26,10 @@ Before releasing, ensure:
The project uses GitHub Actions for automated releases to PyPI. 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`). 1. **Tag the commit**: Create a new git tag for the version (e.g., `v0.2.0`).
```bash ```bash
git tag -a v0.1.1 -m "Release v0.1.1" git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.1.1 git push origin v0.2.0
``` ```
2. **GitHub Action**: The `Release` workflow will automatically trigger, build the package, create a GitHub Release, and publish to PyPI using Trusted Publishing. 2. **GitHub Action**: The `Release` workflow will automatically trigger, build the package, create a GitHub Release, and publish to PyPI using Trusted Publishing.
+1
View File
@@ -6,6 +6,7 @@ We actively support the following versions of Semantica with security updates:
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ------- | ------------------ |
| 0.2.0 | :white_check_mark: |
| 0.1.1 | :white_check_mark: | | 0.1.1 | :white_check_mark: |
| 0.1.0 | :white_check_mark: | | 0.1.0 | :white_check_mark: |
| < 0.1.0 | :x: | | < 0.1.0 | :x: |
+5 -5
View File
@@ -12,22 +12,22 @@ How to cite Semantica in academic papers and research.
author = {Hawksight AI}, author = {Hawksight AI},
year = {2026}, year = {2026},
url = {https://github.com/Hawksight-AI/semantica}, url = {https://github.com/Hawksight-AI/semantica},
version = {0.1.1}, version = {0.2.0},
doi = {10.5281/zenodo.XXXXXXX} doi = {10.5281/zenodo.XXXXXXX}
} }
``` ```
### APA ### APA
Hawksight AI. (2026). *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering* (Version 0.1.1) [Computer software]. https://github.com/Hawksight-AI/semantica Hawksight AI. (2026). *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering* (Version 0.2.0) [Computer software]. https://github.com/Hawksight-AI/semantica
### MLA ### MLA
Hawksight AI. *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering*. Version 0.1.1, GitHub, 2026, https://github.com/Hawksight-AI/semantica. Hawksight AI. *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering*. Version 0.2.0, GitHub, 2026, https://github.com/Hawksight-AI/semantica.
### Chicago ### Chicago
Hawksight AI. *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering*. Version 0.1.1. GitHub, 2026. https://github.com/Hawksight-AI/semantica. Hawksight AI. *Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering*. Version 0.2.0. GitHub, 2026. https://github.com/Hawksight-AI/semantica.
### IEEE ### IEEE
Hawksight AI, "Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering," Version 0.1.1, GitHub, 2026. [Online]. Available: https://github.com/Hawksight-AI/semantica Hawksight AI, "Semantica: An Open Source Framework for Semantic Layers and Knowledge Engineering," Version 0.2.0, GitHub, 2026. [Online]. Available: https://github.com/Hawksight-AI/semantica
--- ---
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "semantica" name = "semantica"
version = "0.1.1" version = "0.2.0"
description = "🧠 Semantica - An Open Source Framework for building Semantic Layers and Knowledge Engineering " description = "🧠 Semantica - An Open Source Framework for building Semantic Layers and Knowledge Engineering "
readme = "README.md" readme = "README.md"
license = {text = "MIT"} license = {text = "MIT"}
+1 -1
View File
@@ -10,7 +10,7 @@ Main exports:
- Config: Configuration management - Config: Configuration management
""" """
__version__ = "0.1.1" __version__ = "0.2.0"
__author__ = "Semantica Contributors" __author__ = "Semantica Contributors"
__license__ = "MIT" __license__ = "MIT"
@@ -453,7 +453,6 @@ class RelationExtractor:
def _extract_last_resort_relations(self, text: str, entities: List[Entity]) -> List[Relation]: def _extract_last_resort_relations(self, text: str, entities: List[Entity]) -> List[Relation]:
"""Last resort relation extraction based on simple adjacency.""" """Last resort relation extraction based on simple adjacency."""
print(f"DEBUG: Last Resort Relations - {len(entities)} entities")
relations = [] relations = []
# Connect adjacent entities # Connect adjacent entities
for i in range(len(entities) - 1): for i in range(len(entities) - 1):
@@ -482,7 +481,6 @@ class RelationExtractor:
metadata={"extraction_method": "last_resort_adjacency"} metadata={"extraction_method": "last_resort_adjacency"}
) )
relations.append(rel) relations.append(rel)
print(f"DEBUG: Created relation {rel.subject.text} -> {rel.object.text}")
return relations return relations
def _extract_with_patterns( def _extract_with_patterns(
+2 -1
View File
@@ -32,7 +32,8 @@ class TestModelSelection(unittest.TestCase):
def test_generator_switching(self): def test_generator_switching(self):
print("\nTesting EmbeddingGenerator Switching...") print("\nTesting EmbeddingGenerator Switching...")
generator = EmbeddingGenerator() # Initialize with explicit method to ensure consistent starting state for test
generator = EmbeddingGenerator(text={"method": "sentence_transformers"})
# Default check # Default check
self.assertEqual(generator.get_text_method(), "sentence_transformers") self.assertEqual(generator.get_text_method(), "sentence_transformers")
@@ -92,8 +92,8 @@ class TestSemanticExtractBatch(unittest.TestCase):
self.assertEqual(len(results), 1) self.assertEqual(len(results), 1)
self.assertEqual(results[0]["batch_index"], 0) self.assertEqual(results[0]["batch_index"], 0)
self.assertEqual(results[0]["document_id"], "doc_1") self.assertEqual(results[0]["document_id"], "doc_1")
self.assertEqual(results[0]["semantic_roles"][0]["batch_index"], 0) self.assertEqual(results[0]["semantic_roles"][0]["metadata"]["batch_index"], 0)
self.assertEqual(results[0]["semantic_roles"][0]["document_id"], "doc_1") self.assertEqual(results[0]["semantic_roles"][0]["metadata"]["document_id"], "doc_1")
def test_coreference_resolver_batch(self): def test_coreference_resolver_batch(self):
print("Running test_coreference_resolver_batch") print("Running test_coreference_resolver_batch")
+57 -91
View File
@@ -1,7 +1,7 @@
import unittest import unittest
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from semantica.triplet_store.triplet_manager import TripletManager, TripletStore from semantica.triplet_store.triplet_store import TripletStore
from semantica.triplet_store.query_engine import QueryEngine, QueryResult from semantica.triplet_store.query_engine import QueryEngine
from semantica.semantic_extract.triplet_extractor import Triplet from semantica.semantic_extract.triplet_extractor import Triplet
class TestTripletStore(unittest.TestCase): class TestTripletStore(unittest.TestCase):
@@ -10,125 +10,91 @@ class TestTripletStore(unittest.TestCase):
self.mock_logger = MagicMock() self.mock_logger = MagicMock()
self.mock_tracker = MagicMock() self.mock_tracker = MagicMock()
self.logger_patcher = patch('semantica.triplet_store.triplet_manager.get_logger', return_value=self.mock_logger) self.logger_patcher = patch('semantica.triplet_store.triplet_store.get_logger', return_value=self.mock_logger)
self.tracker_patcher = patch('semantica.triplet_store.triplet_manager.get_progress_tracker', return_value=self.mock_tracker) self.tracker_patcher = patch('semantica.triplet_store.triplet_store.get_progress_tracker', return_value=self.mock_tracker)
self.logger_patcher_qe = patch('semantica.triplet_store.query_engine.get_logger', return_value=self.mock_logger)
self.tracker_patcher_qe = patch('semantica.triplet_store.query_engine.get_progress_tracker', return_value=self.mock_tracker)
self.logger_patcher.start() self.logger_patcher.start()
self.tracker_patcher.start() self.tracker_patcher.start()
self.logger_patcher_qe.start()
self.tracker_patcher_qe.start()
def tearDown(self): def tearDown(self):
self.logger_patcher.stop() self.logger_patcher.stop()
self.tracker_patcher.stop() self.tracker_patcher.stop()
self.logger_patcher_qe.stop()
self.tracker_patcher_qe.stop()
def test_triplet_manager_init(self): @patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
manager = TripletManager(default_store="main") def test_triplet_store_init(self, mock_blazegraph_store):
self.assertEqual(manager.default_store_id, "main") store = TripletStore(backend="blazegraph", endpoint="http://localhost:9999")
self.assertEqual(manager.stores, {}) self.assertEqual(store.backend_type, "blazegraph")
def test_register_store(self):
manager = TripletManager()
store = manager.register_store("main", "blazegraph", "http://localhost:9999")
self.assertIsInstance(store, TripletStore)
self.assertEqual(store.store_id, "main")
self.assertEqual(store.store_type, "blazegraph")
self.assertEqual(store.endpoint, "http://localhost:9999") self.assertEqual(store.endpoint, "http://localhost:9999")
self.assertIn("main", manager.stores) mock_blazegraph_store.assert_called_once()
@patch('semantica.triplet_store.triplet_manager.TripletManager._get_store_backend') @patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_add_triplet(self, mock_get_store_backend): def test_add_triplet(self, mock_blazegraph_store):
manager = TripletManager() # Setup mock backend
manager.register_store("main", "blazegraph", "http://localhost:9999") mock_backend_instance = MagicMock()
mock_blazegraph_store.return_value = mock_backend_instance
mock_store = MagicMock() mock_backend_instance.add_triplet.return_value = {"status": "success"}
mock_get_store_backend.return_value = mock_store
mock_store.add_triplet.return_value = {"status": "success"}
store = TripletStore(backend="blazegraph")
triplet = Triplet(subject="s", predicate="p", object="o") triplet = Triplet(subject="s", predicate="p", object="o")
result = manager.add_triplet(triplet, store_id="main")
self.assertTrue(result["success"]) result = store.add_triplet(triplet)
self.assertEqual(result["store_id"], "main")
mock_store.add_triplet.assert_called_once_with(triplet) self.assertEqual(result, {"status": "success"})
mock_backend_instance.add_triplet.assert_called_once_with(triplet)
@patch('semantica.triplet_store.triplet_manager.TripletManager._get_store_backend') @patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_add_triplets(self, mock_get_store_backend): def test_add_triplets(self, mock_blazegraph_store):
manager = TripletManager() # Setup mock backend and bulk loader
manager.register_store("main", "blazegraph", "http://localhost:9999") mock_backend_instance = MagicMock()
mock_blazegraph_store.return_value = mock_backend_instance
mock_store = MagicMock() store = TripletStore(backend="blazegraph")
mock_get_store_backend.return_value = mock_store
mock_store.add_triplets.return_value = {"status": "success"} # Mock bulk loader
mock_loader = MagicMock()
store.bulk_loader = mock_loader
mock_progress = MagicMock()
mock_progress.metadata = {"success": True}
mock_progress.total_triplets = 2
mock_progress.loaded_triplets = 2
mock_progress.failed_triplets = 0
mock_progress.total_batches = 1
mock_loader.load_triplets.return_value = mock_progress
triplets = [ triplets = [
Triplet(subject="s1", predicate="p1", object="o1"), Triplet(subject="s1", predicate="p1", object="o1"),
Triplet(subject="s2", predicate="p2", object="o2") Triplet(subject="s2", predicate="p2", object="o2")
] ]
result = manager.add_triplets(triplets, store_id="main", batch_size=2) result = store.add_triplets(triplets, batch_size=2)
self.assertTrue(result["success"]) self.assertTrue(result["success"])
self.assertEqual(result["store_id"], "main") self.assertEqual(result["total"], 2)
mock_store.add_triplets.assert_called() mock_loader.load_triplets.assert_called_once()
@patch('semantica.triplet_store.triplet_manager.TripletManager._get_store_backend') @patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_get_triplets(self, mock_get_store_backend): def test_get_triplets(self, mock_blazegraph_store):
manager = TripletManager() mock_backend_instance = MagicMock()
manager.register_store("main", "blazegraph", "http://localhost:9999") mock_blazegraph_store.return_value = mock_backend_instance
mock_store = MagicMock()
mock_get_store_backend.return_value = mock_store
expected_triplets = [Triplet(subject="s", predicate="p", object="o")] expected_triplets = [Triplet(subject="s", predicate="p", object="o")]
mock_store.get_triplets.return_value = expected_triplets mock_backend_instance.get_triplets.return_value = expected_triplets
result = manager.get_triplets(subject="s", store_id="main") store = TripletStore(backend="blazegraph")
result = store.get_triplets(subject="s")
self.assertEqual(result, expected_triplets) self.assertEqual(result, expected_triplets)
mock_store.get_triplets.assert_called_once_with("s", None, None) mock_backend_instance.get_triplets.assert_called_once_with(subject="s", predicate=None, object=None)
@patch('semantica.triplet_store.triplet_manager.TripletManager._get_store_backend') @patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_delete_triplet(self, mock_get_store_backend): def test_delete_triplet(self, mock_blazegraph_store):
manager = TripletManager() mock_backend_instance = MagicMock()
manager.register_store("main", "blazegraph", "http://localhost:9999") mock_blazegraph_store.return_value = mock_backend_instance
mock_backend_instance.delete_triplet.return_value = {"success": True}
mock_store = MagicMock()
mock_get_store_backend.return_value = mock_store
mock_store.delete_triplet.return_value = {"status": "deleted"}
store = TripletStore(backend="blazegraph")
triplet = Triplet(subject="s", predicate="p", object="o") triplet = Triplet(subject="s", predicate="p", object="o")
result = manager.delete_triplet(triplet, store_id="main")
result = store.delete_triplet(triplet)
self.assertTrue(result["success"]) self.assertTrue(result["success"])
mock_store.delete_triplet.assert_called_once_with(triplet) mock_backend_instance.delete_triplet.assert_called_once_with(triplet)
@patch('semantica.triplet_store.triplet_manager.TripletManager._get_store_backend')
def test_update_triplet(self, mock_get_store_backend):
manager = TripletManager()
manager.register_store("main", "blazegraph", "http://localhost:9999")
mock_store = MagicMock()
mock_get_store_backend.return_value = mock_store
mock_store.delete_triplet.return_value = {"status": "deleted"}
mock_store.add_triplet.return_value = {"status": "added"}
old_triplet = Triplet(subject="s", predicate="p", object="o_old")
new_triplet = Triplet(subject="s", predicate="p", object="o_new")
result = manager.update_triplet(old_triplet, new_triplet, store_id="main")
self.assertTrue(result["success"])
mock_store.delete_triplet.assert_called_once_with(old_triplet)
mock_store.add_triplet.assert_called_once_with(new_triplet)
def test_query_engine_init(self):
engine = QueryEngine(enable_caching=True)
self.assertTrue(engine.enable_caching)
self.assertEqual(engine.query_cache, {})
if __name__ == '__main__':
unittest.main()