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]
## [0.2.0] - 2026-01-10
### Added
- **Amazon Neptune Support**:
- 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.*
**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)
+3 -3
View File
@@ -26,10 +26,10 @@ Before releasing, ensure:
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
git tag -a v0.1.1 -m "Release v0.1.1"
git push origin v0.1.1
git tag -a v0.2.0 -m "Release v0.2.0"
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.
+1
View File
@@ -6,6 +6,7 @@ We actively support the following versions of Semantica with security updates:
| Version | Supported |
| ------- | ------------------ |
| 0.2.0 | :white_check_mark: |
| 0.1.1 | :white_check_mark: |
| 0.1.0 | :white_check_mark: |
| < 0.1.0 | :x: |
+5 -5
View File
@@ -12,22 +12,22 @@ How to cite Semantica in academic papers and research.
author = {Hawksight AI},
year = {2026},
url = {https://github.com/Hawksight-AI/semantica},
version = {0.1.1},
version = {0.2.0},
doi = {10.5281/zenodo.XXXXXXX}
}
```
### 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
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
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
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]
name = "semantica"
version = "0.1.1"
version = "0.2.0"
description = "🧠 Semantica - An Open Source Framework for building Semantic Layers and Knowledge Engineering "
readme = "README.md"
license = {text = "MIT"}
+1 -1
View File
@@ -10,7 +10,7 @@ Main exports:
- Config: Configuration management
"""
__version__ = "0.1.1"
__version__ = "0.2.0"
__author__ = "Semantica Contributors"
__license__ = "MIT"
@@ -453,7 +453,6 @@ class RelationExtractor:
def _extract_last_resort_relations(self, text: str, entities: List[Entity]) -> List[Relation]:
"""Last resort relation extraction based on simple adjacency."""
print(f"DEBUG: Last Resort Relations - {len(entities)} entities")
relations = []
# Connect adjacent entities
for i in range(len(entities) - 1):
@@ -482,7 +481,6 @@ class RelationExtractor:
metadata={"extraction_method": "last_resort_adjacency"}
)
relations.append(rel)
print(f"DEBUG: Created relation {rel.subject.text} -> {rel.object.text}")
return relations
def _extract_with_patterns(
+2 -1
View File
@@ -32,7 +32,8 @@ class TestModelSelection(unittest.TestCase):
def test_generator_switching(self):
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
self.assertEqual(generator.get_text_method(), "sentence_transformers")
@@ -92,8 +92,8 @@ class TestSemanticExtractBatch(unittest.TestCase):
self.assertEqual(len(results), 1)
self.assertEqual(results[0]["batch_index"], 0)
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]["document_id"], "doc_1")
self.assertEqual(results[0]["semantic_roles"][0]["metadata"]["batch_index"], 0)
self.assertEqual(results[0]["semantic_roles"][0]["metadata"]["document_id"], "doc_1")
def test_coreference_resolver_batch(self):
print("Running test_coreference_resolver_batch")
+57 -91
View File
@@ -1,7 +1,7 @@
import unittest
from unittest.mock import MagicMock, patch
from semantica.triplet_store.triplet_manager import TripletManager, TripletStore
from semantica.triplet_store.query_engine import QueryEngine, QueryResult
from semantica.triplet_store.triplet_store import TripletStore
from semantica.triplet_store.query_engine import QueryEngine
from semantica.semantic_extract.triplet_extractor import Triplet
class TestTripletStore(unittest.TestCase):
@@ -10,125 +10,91 @@ class TestTripletStore(unittest.TestCase):
self.mock_logger = MagicMock()
self.mock_tracker = MagicMock()
self.logger_patcher = patch('semantica.triplet_store.triplet_manager.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.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 = patch('semantica.triplet_store.triplet_store.get_logger', return_value=self.mock_logger)
self.tracker_patcher = patch('semantica.triplet_store.triplet_store.get_progress_tracker', return_value=self.mock_tracker)
self.logger_patcher.start()
self.tracker_patcher.start()
self.logger_patcher_qe.start()
self.tracker_patcher_qe.start()
def tearDown(self):
self.logger_patcher.stop()
self.tracker_patcher.stop()
self.logger_patcher_qe.stop()
self.tracker_patcher_qe.stop()
def test_triplet_manager_init(self):
manager = TripletManager(default_store="main")
self.assertEqual(manager.default_store_id, "main")
self.assertEqual(manager.stores, {})
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")
@patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_triplet_store_init(self, mock_blazegraph_store):
store = TripletStore(backend="blazegraph", endpoint="http://localhost:9999")
self.assertEqual(store.backend_type, "blazegraph")
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')
def test_add_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.add_triplet.return_value = {"status": "success"}
@patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_add_triplet(self, mock_blazegraph_store):
# Setup mock backend
mock_backend_instance = MagicMock()
mock_blazegraph_store.return_value = mock_backend_instance
mock_backend_instance.add_triplet.return_value = {"status": "success"}
store = TripletStore(backend="blazegraph")
triplet = Triplet(subject="s", predicate="p", object="o")
result = manager.add_triplet(triplet, store_id="main")
self.assertTrue(result["success"])
self.assertEqual(result["store_id"], "main")
mock_store.add_triplet.assert_called_once_with(triplet)
result = store.add_triplet(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')
def test_add_triplets(self, mock_get_store_backend):
manager = TripletManager()
manager.register_store("main", "blazegraph", "http://localhost:9999")
@patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_add_triplets(self, mock_blazegraph_store):
# Setup mock backend and bulk loader
mock_backend_instance = MagicMock()
mock_blazegraph_store.return_value = mock_backend_instance
mock_store = MagicMock()
mock_get_store_backend.return_value = mock_store
mock_store.add_triplets.return_value = {"status": "success"}
store = TripletStore(backend="blazegraph")
# 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 = [
Triplet(subject="s1", predicate="p1", object="o1"),
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.assertEqual(result["store_id"], "main")
mock_store.add_triplets.assert_called()
self.assertEqual(result["total"], 2)
mock_loader.load_triplets.assert_called_once()
@patch('semantica.triplet_store.triplet_manager.TripletManager._get_store_backend')
def test_get_triplets(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
@patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_get_triplets(self, mock_blazegraph_store):
mock_backend_instance = MagicMock()
mock_blazegraph_store.return_value = mock_backend_instance
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)
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')
def test_delete_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"}
@patch('semantica.triplet_store.blazegraph_store.BlazegraphStore')
def test_delete_triplet(self, mock_blazegraph_store):
mock_backend_instance = MagicMock()
mock_blazegraph_store.return_value = mock_backend_instance
mock_backend_instance.delete_triplet.return_value = {"success": True}
store = TripletStore(backend="blazegraph")
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"])
mock_store.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()
mock_backend_instance.delete_triplet.assert_called_once_with(triplet)