asterinis 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
asterinis/__init__.py ADDED
@@ -0,0 +1,33 @@
1
+ from .config import AsterinisConfig
2
+ from .connectors import Connector, EchoConnector
3
+ from .context import NexusContext
4
+ from .exceptions import (
5
+ AsterinisError,
6
+ ConnectorError,
7
+ PipelineError,
8
+ RoutingError,
9
+ )
10
+ from .hooks import HookManager
11
+ from .nexus import Nexus
12
+ from .pipeline import Pipeline
13
+ from .result import NexusResult
14
+ from .router import Router
15
+
16
+
17
+ __version__ = "0.0.1"
18
+
19
+ __all__ = [
20
+ "AsterinisConfig",
21
+ "AsterinisError",
22
+ "Connector",
23
+ "ConnectorError",
24
+ "EchoConnector",
25
+ "HookManager",
26
+ "Nexus",
27
+ "NexusContext",
28
+ "NexusResult",
29
+ "Pipeline",
30
+ "PipelineError",
31
+ "Router",
32
+ "RoutingError",
33
+ ]
asterinis/config.py ADDED
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class AsterinisConfig:
6
+ default_route: str = "llm"
7
+ enable_rag: bool = True
8
+ enable_nlp: bool = True
9
+ enable_agents: bool = True
10
+ debug: bool = False
@@ -0,0 +1,27 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any
3
+
4
+
5
+ class Connector(ABC):
6
+ """
7
+ Base connector interface.
8
+
9
+ Connectors allow Asterinis to communicate with
10
+ external NLP, RAG, agent, or LLM systems.
11
+ """
12
+
13
+ name: str = "connector"
14
+
15
+ @abstractmethod
16
+ def execute(self, payload: Any) -> Any:
17
+ raise NotImplementedError
18
+
19
+
20
+ class EchoConnector(Connector):
21
+ name = "echo"
22
+
23
+ def execute(self, payload: Any) -> Any:
24
+ return {
25
+ "connector": self.name,
26
+ "payload": payload,
27
+ }
asterinis/context.py ADDED
@@ -0,0 +1,15 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Any
3
+
4
+
5
+ @dataclass
6
+ class NexusContext:
7
+ input_text: str
8
+ metadata: dict[str, Any] = field(default_factory=dict)
9
+ state: dict[str, Any] = field(default_factory=dict)
10
+
11
+ def set(self, key: str, value: Any) -> None:
12
+ self.state[key] = value
13
+
14
+ def get(self, key: str, default: Any = None) -> Any:
15
+ return self.state.get(key, default)
@@ -0,0 +1,14 @@
1
+ class AsterinisError(Exception):
2
+ """Base exception for Asterinis."""
3
+
4
+
5
+ class RoutingError(AsterinisError):
6
+ """Raised when routing cannot be completed."""
7
+
8
+
9
+ class ConnectorError(AsterinisError):
10
+ """Raised when a connector fails."""
11
+
12
+
13
+ class PipelineError(AsterinisError):
14
+ """Raised when a pipeline step fails."""
asterinis/hooks.py ADDED
@@ -0,0 +1,18 @@
1
+ from collections import defaultdict
2
+ from collections.abc import Callable
3
+ from typing import Any
4
+
5
+
6
+ Hook = Callable[..., Any]
7
+
8
+
9
+ class HookManager:
10
+ def __init__(self):
11
+ self._hooks: dict[str, list[Hook]] = defaultdict(list)
12
+
13
+ def register(self, event: str, callback: Hook) -> None:
14
+ self._hooks[event].append(callback)
15
+
16
+ def emit(self, event: str, **kwargs: Any) -> None:
17
+ for callback in self._hooks.get(event, []):
18
+ callback(**kwargs)
@@ -0,0 +1,3 @@
1
+ from .flair import FlairConnector
2
+
3
+ __all__ = ["FlairConnector"]
@@ -0,0 +1,49 @@
1
+ # src/asterinis/integrations/flair.py
2
+
3
+ from typing import Any
4
+
5
+ from asterinis.connectors import Connector
6
+
7
+
8
+ class FlairConnector(Connector):
9
+ name = "flair"
10
+
11
+ def __init__(self, model_name: str = "ner"):
12
+ try:
13
+ from flair.nn import Classifier
14
+ except ImportError as exc:
15
+ raise ImportError(
16
+ "Flair is not installed. "
17
+ 'Install it with: pip install "asterinis[flair]"'
18
+ ) from exc
19
+
20
+ self.model_name = model_name
21
+ self.model = Classifier.load(model_name)
22
+
23
+ def execute(self, payload: Any) -> Any:
24
+ from flair.data import Sentence
25
+
26
+ text = payload["text"]
27
+
28
+ sentence = Sentence(text)
29
+ self.model.predict(sentence)
30
+
31
+ entities = []
32
+
33
+ for entity in sentence.get_spans("ner"):
34
+ label = entity.get_label("ner")
35
+
36
+ entities.append(
37
+ {
38
+ "text": entity.text,
39
+ "label": label.value,
40
+ "confidence": label.score,
41
+ }
42
+ )
43
+
44
+ return {
45
+ "provider": "flair",
46
+ "model": self.model_name,
47
+ "text": text,
48
+ "entities": entities,
49
+ }
@@ -0,0 +1,23 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any
3
+
4
+
5
+ class Middleware(ABC):
6
+
7
+ def before(self, context: Any) -> Any:
8
+ return context
9
+
10
+ def after(self, result: Any) -> Any:
11
+ return result
12
+
13
+
14
+ class TimingMiddleware(Middleware):
15
+
16
+ def before(self, context):
17
+ import time
18
+
19
+ context.set("_start_time", time.perf_counter())
20
+ return context
21
+
22
+ def after(self, result):
23
+ return result
asterinis/nexus.py ADDED
@@ -0,0 +1,76 @@
1
+ from collections.abc import Callable
2
+
3
+
4
+ RouteRule = Callable[[str], bool]
5
+
6
+
7
+ class Router:
8
+ def __init__(self, default_route: str = "llm"):
9
+ self.default_route = default_route
10
+ self._rules: list[tuple[str, RouteRule]] = []
11
+
12
+ self._register_default_rules()
13
+
14
+ def _register_default_rules(self) -> None:
15
+ self.add_route(
16
+ "rag",
17
+ lambda text: any(
18
+ word in text.lower()
19
+ for word in (
20
+ "document",
21
+ "source",
22
+ "retrieve",
23
+ "search",
24
+ )
25
+ ),
26
+ )
27
+
28
+ self.add_route(
29
+ "nlp",
30
+ lambda text: any(
31
+ word in text.lower()
32
+ for word in (
33
+ "entity",
34
+ "ner",
35
+ "language",
36
+ "nlp",
37
+ )
38
+ ),
39
+ )
40
+
41
+ self.add_route(
42
+ "agent",
43
+ lambda text: any(
44
+ word in text.lower()
45
+ for word in (
46
+ "agent",
47
+ "tool",
48
+ "workflow",
49
+ )
50
+ ),
51
+ )
52
+
53
+ def add_route(
54
+ self,
55
+ name: str,
56
+ rule: RouteRule,
57
+ *,
58
+ first: bool = False,
59
+ ) -> None:
60
+ route = (name, rule)
61
+
62
+ if first:
63
+ self._rules.insert(0, route)
64
+ else:
65
+ self._rules.append(route)
66
+
67
+ def route(self, text: str) -> str:
68
+ for name, rule in self._rules:
69
+ if rule(text):
70
+ return name
71
+
72
+ return self.default_route
73
+
74
+ @property
75
+ def routes(self) -> list[str]:
76
+ return [name for name, _ in self._rules]
asterinis/pipeline.py ADDED
@@ -0,0 +1,33 @@
1
+ from collections.abc import Callable
2
+ from typing import Any
3
+
4
+ from .context import NexusContext
5
+ from .exceptions import PipelineError
6
+
7
+
8
+ PipelineStep = Callable[[NexusContext], NexusContext]
9
+
10
+
11
+ class Pipeline:
12
+ def __init__(self, name: str):
13
+ self.name = name
14
+ self._steps: list[PipelineStep] = []
15
+
16
+ def add(self, step: PipelineStep) -> "Pipeline":
17
+ self._steps.append(step)
18
+ return self
19
+
20
+ def run(self, context: NexusContext) -> NexusContext:
21
+ try:
22
+ for step in self._steps:
23
+ context = step(context)
24
+
25
+ return context
26
+
27
+ except Exception as exc:
28
+ raise PipelineError(
29
+ f"Pipeline '{self.name}' failed."
30
+ ) from exc
31
+
32
+ def __len__(self) -> int:
33
+ return len(self._steps)
asterinis/registry.py ADDED
@@ -0,0 +1,31 @@
1
+ from typing import Dict
2
+
3
+ from .connectors import Connector
4
+
5
+
6
+ class ConnectorRegistry:
7
+ def __init__(self):
8
+ self._connectors: Dict[str, Connector] = {}
9
+
10
+ def register(self, name: str, connector: Connector) -> None:
11
+ if not name:
12
+ raise ValueError("Connector name cannot be empty.")
13
+
14
+ self._connectors[name] = connector
15
+
16
+ def get(self, name: str) -> Connector:
17
+ if name not in self._connectors:
18
+ raise KeyError(
19
+ f"Connector '{name}' is not registered."
20
+ )
21
+
22
+ return self._connectors[name]
23
+
24
+ def remove(self, name: str) -> None:
25
+ self._connectors.pop(name, None)
26
+
27
+ def exists(self, name: str) -> bool:
28
+ return name in self._connectors
29
+
30
+ def list(self) -> list[str]:
31
+ return list(self._connectors.keys())
asterinis/result.py ADDED
@@ -0,0 +1,9 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any
3
+
4
+
5
+ @dataclass
6
+ class NexusResult:
7
+ route: str
8
+ payload: Any
9
+ confidence: float = 1.0
asterinis/router.py ADDED
@@ -0,0 +1,76 @@
1
+ from collections.abc import Callable
2
+
3
+
4
+ RouteRule = Callable[[str], bool]
5
+
6
+
7
+ class Router:
8
+ def __init__(self, default_route: str = "llm"):
9
+ self.default_route = default_route
10
+ self._rules: list[tuple[str, RouteRule]] = []
11
+
12
+ self._register_default_rules()
13
+
14
+ def _register_default_rules(self) -> None:
15
+ self.add_route(
16
+ "rag",
17
+ lambda text: any(
18
+ word in text.lower()
19
+ for word in (
20
+ "document",
21
+ "source",
22
+ "retrieve",
23
+ "search",
24
+ )
25
+ ),
26
+ )
27
+
28
+ self.add_route(
29
+ "nlp",
30
+ lambda text: any(
31
+ word in text.lower()
32
+ for word in (
33
+ "entity",
34
+ "ner",
35
+ "language",
36
+ "nlp",
37
+ )
38
+ ),
39
+ )
40
+
41
+ self.add_route(
42
+ "agent",
43
+ lambda text: any(
44
+ word in text.lower()
45
+ for word in (
46
+ "agent",
47
+ "tool",
48
+ "workflow",
49
+ )
50
+ ),
51
+ )
52
+
53
+ def add_route(
54
+ self,
55
+ name: str,
56
+ rule: RouteRule,
57
+ *,
58
+ first: bool = False,
59
+ ) -> None:
60
+ route = (name, rule)
61
+
62
+ if first:
63
+ self._rules.insert(0, route)
64
+ else:
65
+ self._rules.append(route)
66
+
67
+ def route(self, text: str) -> str:
68
+ for name, rule in self._rules:
69
+ if rule(text):
70
+ return name
71
+
72
+ return self.default_route
73
+
74
+ @property
75
+ def routes(self) -> list[str]:
76
+ return [name for name, _ in self._rules]
@@ -0,0 +1,187 @@
1
+ Metadata-Version: 2.4
2
+ Name: asterinis
3
+ Version: 0.0.1
4
+ Summary: Python framework for AI orchestration, RAG, NLP integration, agent routing, and explainable AI.
5
+ Author: Irena Popova
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/irenapopova/asterinis
8
+ Project-URL: Repository, https://github.com/irenapopova/asterinis
9
+ Project-URL: Issues, https://github.com/irenapopova/asterinis/issues
10
+ Keywords: ai,rag,nlp,agents,llm,orchestration,flair,machine-learning,python
11
+ Classifier: Development Status :: 2 - Pre-Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Provides-Extra: flair
26
+ Requires-Dist: flair>=0.15; extra == "flair"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=8.0; extra == "dev"
29
+ Requires-Dist: build>=1.2; extra == "dev"
30
+ Requires-Dist: twine>=5.0; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # asterinis
34
+ # Asterinis
35
+
36
+ **Asterinis** is an early-stage Python framework for connecting NLP, retrieval-augmented generation (RAG), AI agents, routing logic, explainability, and LLM services through a unified backend nexus.
37
+
38
+ The project is designed as a lightweight orchestration layer that can connect different AI and NLP components without locking an application to a single model provider or framework.
39
+
40
+ ## Current Status
41
+
42
+ Asterinis is currently in an early development stage.
43
+
44
+ The first public release focuses on the core framework structure, including:
45
+
46
+ * Nexus orchestration
47
+ * Rule-based routing
48
+ * Connector interfaces
49
+ * Processing context
50
+ * Pipelines
51
+ * Hooks
52
+ * Result objects
53
+ * Optional NLP integrations
54
+
55
+ More advanced RAG, agent orchestration, adaptive routing, evaluation, and explainability features are planned for future releases.
56
+
57
+ ## Installation
58
+
59
+ The package will be installable from PyPI:
60
+
61
+ ```bash
62
+ pip install asterinis
63
+ ```
64
+
65
+ For optional Flair NLP support:
66
+
67
+ ```bash
68
+ pip install "asterinis[flair]"
69
+ ```
70
+
71
+ ## Basic Usage
72
+
73
+ ```python
74
+ from asterinis import Nexus
75
+
76
+ nexus = Nexus()
77
+
78
+ result = nexus.process(
79
+ "Search documents about multilingual NLP."
80
+ )
81
+
82
+ print(result.route)
83
+ print(result.payload)
84
+ ```
85
+
86
+ Asterinis can route requests toward different processing paths such as:
87
+
88
+ ```text
89
+ rag
90
+ nlp
91
+ agent
92
+ llm
93
+ ```
94
+
95
+ ## Flair Integration
96
+
97
+ Asterinis supports Flair as an optional NLP connector.
98
+
99
+ ```python
100
+ from asterinis import Nexus
101
+ from asterinis.integrations import FlairConnector
102
+
103
+ nexus = Nexus()
104
+
105
+ nexus.register_connector(
106
+ "nlp",
107
+ FlairConnector("ner")
108
+ )
109
+
110
+ result = nexus.process(
111
+ "Deutsche Bank is based in Frankfurt."
112
+ )
113
+
114
+ print(result.to_dict())
115
+ ```
116
+
117
+ Flair is an independent open-source NLP framework and is not part of Asterinis. Asterinis provides an integration layer that allows Flair models to participate in a broader orchestration pipeline.
118
+
119
+ ## Architecture
120
+
121
+ ```text
122
+ Application
123
+ ↓
124
+ Asterinis Nexus
125
+ ↓
126
+ Router
127
+ ↓
128
+ ┌──────────┬──────────┬──────────┬──────────┐
129
+ │ NLP │ RAG │ Agents │ LLM │
130
+ └──────────┴──────────┴──────────┴──────────┘
131
+ ↓
132
+ Connectors / Integrations
133
+ ```
134
+
135
+ The goal is to allow developers to plug different AI systems into a consistent interface.
136
+
137
+ ## Project Structure
138
+
139
+ ```text
140
+ src/
141
+ └── asterinis/
142
+ ├── __init__.py
143
+ ├── nexus.py
144
+ ├── router.py
145
+ ├── connectors.py
146
+ ├── context.py
147
+ ├── pipeline.py
148
+ ├── hooks.py
149
+ ├── result.py
150
+ ├── config.py
151
+ ├── exceptions.py
152
+ └── integrations/
153
+ ├── __init__.py
154
+ └── flair.py
155
+ ```
156
+
157
+ ## Roadmap
158
+
159
+ Future development may include:
160
+
161
+ * advanced RAG routing
162
+ * retrieval quality evaluation
163
+ * agent orchestration
164
+ * adaptive routing policies
165
+ * explainability
166
+ * confidence-aware decision logic
167
+ * additional NLP integrations
168
+ * LLM provider connectors
169
+ * evaluation tools
170
+ * persistent context and memory
171
+ * asynchronous pipelines
172
+
173
+ ## Version
174
+
175
+ Current development version:
176
+
177
+ ```text
178
+ 0.0.1
179
+ ```
180
+
181
+ ## License
182
+
183
+ Asterinis is released under the MIT License. See the [LICENSE](LICENSE) file for details.
184
+
185
+ ## Author
186
+
187
+ Created and maintained by **Irena Popova**, Full-Stack Developer and AI/NLP, RAG, and adaptive systems researcher.
@@ -0,0 +1,19 @@
1
+ asterinis/__init__.py,sha256=hMJeKRJK7bPM0otmtxyiogzLZ0EKn1yCAYr8XLLspVE,655
2
+ asterinis/config.py,sha256=OLY86vKoxOI6ai2vc7vliLnrBiLcHvXBzJKRxugBXng,211
3
+ asterinis/connectors.py,sha256=AsgISf0Fi8wRvtQu8yhysVLnJclNunzvK4gHLQKX6u0,546
4
+ asterinis/context.py,sha256=Y1XsRFMpWxLWh2Wbcggo5GtgNEj3moz9il8TgXfSpTI,415
5
+ asterinis/exceptions.py,sha256=VMLZ7htmz7iYqzXh0rPlLfPFF9Ye8zZMVx3mk3cvFqc,326
6
+ asterinis/hooks.py,sha256=9YpxamjY4IOh2GidswpKE2C74TWA4Z_zr1e3lnXIBN0,475
7
+ asterinis/middleware.py,sha256=frOkSuPzkjSiPECDjIX2uHslvDnErCeHpzfFVKnKwoU,436
8
+ asterinis/nexus.py,sha256=FnpJOxnrAY1-WBaBeciJTpNBoMMCspUhuVJYnoNdC80,1749
9
+ asterinis/pipeline.py,sha256=j4mJt6MTo1WD3tyddNdxZDZBfQToOAoLnSeYzTZX9mY,798
10
+ asterinis/registry.py,sha256=netKS2mqzheM7oPfG9Y2GkXKAP0Mhc-i2Dii0u6zG9o,823
11
+ asterinis/result.py,sha256=veAt85irgORqy569koSJfBAEBe6HDmfWmY1m_9RgEX0,148
12
+ asterinis/router.py,sha256=FnpJOxnrAY1-WBaBeciJTpNBoMMCspUhuVJYnoNdC80,1749
13
+ asterinis/integrations/__init__.py,sha256=OZuBTN7moQFY-nsw8dYi479nloKkCsVJaBaegSbhSrI,63
14
+ asterinis/integrations/flair.py,sha256=7nD77Hy9EneNzpC0jctGFkMYRPadGj9clOY2pR00d48,1226
15
+ asterinis-0.0.1.dist-info/licenses/LICENSE,sha256=G5hhhkfBQ-iZDlxWVKruoyUFZe_htD-Yg2Cgypy4Jh4,1068
16
+ asterinis-0.0.1.dist-info/METADATA,sha256=9N6Ize0IoiWvQy-hRsLoAzm6Ind9l7IMy_pvnlJhv4c,4795
17
+ asterinis-0.0.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
18
+ asterinis-0.0.1.dist-info/top_level.txt,sha256=qHE8M453PvQJanXy0EkcUnlUnxB56DT8jsH0oIhWFZY,10
19
+ asterinis-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Irena Popova
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ asterinis