lerev 2.6.0__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.
- adapters/__init__.py +14 -0
- adapters/base.py +104 -0
- adapters/claude_code/__init__.py +5 -0
- adapters/claude_code/adapter.py +44 -0
- adapters/codex/__init__.py +5 -0
- adapters/codex/adapter.py +42 -0
- adapters/generic/__init__.py +5 -0
- adapters/generic/adapter.py +43 -0
- adapters/opencode/__init__.py +5 -0
- adapters/opencode/adapter.py +44 -0
- core/__init__.py +17 -0
- core/adaptation/__init__.py +7 -0
- core/adaptation/base.py +85 -0
- core/evaluator/__init__.py +7 -0
- core/evaluator/base.py +91 -0
- core/interfaces.py +21 -0
- core/knowledge/__init__.py +7 -0
- core/knowledge/base.py +108 -0
- core/learner/__init__.py +7 -0
- core/learner/base.py +89 -0
- core/learner/calibration/__init__.py +1 -0
- core/learner/calibration/calibrator.py +181 -0
- core/learner/calibration/dataset.py +537 -0
- core/learner/calibration/estimator.py +378 -0
- core/learner/calibration/metrics.py +260 -0
- core/learner/confidence.py +501 -0
- core/learner/conflict.py +415 -0
- core/learner/fastembed_encoder.py +96 -0
- core/learner/feature_extractor.py +310 -0
- core/learner/hybrid_memory.py +427 -0
- core/learner/knowledge_ops.py +753 -0
- core/learner/learner_v1.py +459 -0
- core/learner/learner_v2.py +1188 -0
- core/learner/lifecycle.py +284 -0
- core/learner/lifecycle_manager.py +1078 -0
- core/learner/memory.py +245 -0
- core/learner/predict_result.py +230 -0
- core/learner/retrieval_scorer.py +172 -0
- core/learner/semantic_encoder.py +95 -0
- core/learner/similarity.py +94 -0
- core/memory/__init__.py +7 -0
- core/memory/base.py +109 -0
- core/routing/__init__.py +106 -0
- core/routing/cache.py +319 -0
- core/routing/context.py +151 -0
- core/routing/contracts.py +105 -0
- core/routing/cost.py +104 -0
- core/routing/decision.py +178 -0
- core/routing/destinations.py +128 -0
- core/routing/efficiency.py +237 -0
- core/routing/information.py +199 -0
- core/routing/integration.py +190 -0
- core/routing/pipeline.py +521 -0
- core/routing/priority.py +101 -0
- core/routing/protocol.py +172 -0
- core/routing/provenance.py +205 -0
- core/routing/router.py +391 -0
- core/routing/security.py +221 -0
- core/routing/telemetry.py +144 -0
- core/routing/v26/__init__.py +98 -0
- core/routing/v26/background.py +23 -0
- core/routing/v26/consolidation.py +277 -0
- core/routing/v26/experience.py +243 -0
- core/routing/v26/factory.py +13 -0
- core/routing/v26/factory_tools.py +33 -0
- core/routing/v26/identity.py +298 -0
- core/routing/v26/memory_bridge.py +186 -0
- core/routing/v26/memory_manager.py +449 -0
- core/routing/v26/memory_store.py +230 -0
- core/routing/v26/memory_types.py +251 -0
- core/routing/v26/orchestrator.py +55 -0
- core/routing/v26/persistence.py +331 -0
- core/routing/v26/security.py +242 -0
- core/routing/v26/semantic_retrieval.py +100 -0
- core/routing/v26/tools/__init__.py +12 -0
- core/routing/v26/tools/base.py +97 -0
- core/routing/v26/tools/confidence.py +112 -0
- core/routing/v26/tools/conflict.py +97 -0
- core/routing/v26/tools/deduplicate.py +89 -0
- core/routing/v26/tools/diagnose.py +49 -0
- core/routing/v26/tools/knowledge.py +54 -0
- core/routing/v26/tools/lifecycle.py +161 -0
- core/routing/v26/tools/recall.py +91 -0
- core/routing/v26/tools/remember.py +92 -0
- core/routing/v26/tools/semantic_search.py +73 -0
- core/routing/v26/tools/status.py +102 -0
- lerev/__init__.py +6 -0
- lerev/__main__.py +8 -0
- lerev/bridge.py +339 -0
- lerev/cli.py +246 -0
- lerev/config.py +77 -0
- lerev/discovery.py +90 -0
- lerev/plugin_source.py +662 -0
- lerev-2.6.0.dist-info/METADATA +124 -0
- lerev-2.6.0.dist-info/RECORD +106 -0
- lerev-2.6.0.dist-info/WHEEL +4 -0
- lerev-2.6.0.dist-info/entry_points.txt +2 -0
- lerev-2.6.0.dist-info/licenses/LICENSE +21 -0
- storage/__init__.py +8 -0
- storage/base.py +77 -0
- web/__init__.py +28 -0
- web/documentation/base.py +53 -0
- web/fetch/base.py +53 -0
- web/github/base.py +83 -0
- web/search/base.py +51 -0
- web/source_evaluation/base.py +52 -0
adapters/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Harness adapter registry.
|
|
2
|
+
|
|
3
|
+
Provides the central registry for discovering and instantiating
|
|
4
|
+
harness adapters that connect the learning engine to various
|
|
5
|
+
AI coding assistants.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from adapters.base import HarnessAdapter, AdapterConfig, AdapterCapability
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"HarnessAdapter",
|
|
12
|
+
"AdapterConfig",
|
|
13
|
+
"AdapterCapability",
|
|
14
|
+
]
|
adapters/base.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Abstract harness adapter interface.
|
|
2
|
+
|
|
3
|
+
The core contract that all harness adapters must implement to communicate
|
|
4
|
+
with the learning engine. Each adapter bridges a specific AI coding
|
|
5
|
+
assistant (OpenCode, Claude Code, Codex, etc.) to the engine's unified
|
|
6
|
+
learning pipeline.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from enum import Enum, auto
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AdapterCapability(Enum):
|
|
16
|
+
"""Capabilities an adapter may advertise."""
|
|
17
|
+
|
|
18
|
+
CODE_GENERATION = auto()
|
|
19
|
+
CODE_EXPLANATION = auto()
|
|
20
|
+
FILE_EDITING = auto()
|
|
21
|
+
TERMINAL_ACCESS = auto()
|
|
22
|
+
WEB_SEARCH = auto()
|
|
23
|
+
CONTEXT_INJECTION = auto()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class AdapterConfig:
|
|
28
|
+
"""Configuration for a harness adapter."""
|
|
29
|
+
|
|
30
|
+
name: str
|
|
31
|
+
enabled: bool = True
|
|
32
|
+
options: dict[str, Any] = field(default_factory=dict)
|
|
33
|
+
capabilities: list[AdapterCapability] = field(default_factory=list)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class AdapterResponse:
|
|
38
|
+
"""Standardised response from an adapter interaction."""
|
|
39
|
+
|
|
40
|
+
content: str
|
|
41
|
+
success: bool = True
|
|
42
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class HarnessAdapter(ABC):
|
|
46
|
+
"""Abstract base class for harness adapters.
|
|
47
|
+
|
|
48
|
+
Each concrete adapter wraps a specific AI coding assistant and
|
|
49
|
+
translates between the engine's learning events and the assistant's
|
|
50
|
+
native interface.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def name(self) -> str:
|
|
56
|
+
"""Unique identifier for this adapter (e.g. 'opencode', 'claude_code')."""
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def capabilities(self) -> list[AdapterCapability]:
|
|
62
|
+
"""Capabilities supported by this adapter."""
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
async def configure(self, config: AdapterConfig) -> None:
|
|
67
|
+
"""Apply configuration to the adapter.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
config: The adapter configuration.
|
|
71
|
+
"""
|
|
72
|
+
...
|
|
73
|
+
|
|
74
|
+
@abstractmethod
|
|
75
|
+
async def send_prompt(self, prompt: str, context: dict[str, Any] | None = None) -> AdapterResponse:
|
|
76
|
+
"""Send a prompt to the underlying harness and return the response.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
prompt: The prompt text.
|
|
80
|
+
context: Optional context (file state, prior conversation, etc.).
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
An AdapterResponse with the harness output.
|
|
84
|
+
"""
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
@abstractmethod
|
|
88
|
+
async def inject_context(self, context: dict[str, Any]) -> None:
|
|
89
|
+
"""Inject learning context into the harness session.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
context: Context data (e.g. relevant docs, code snippets).
|
|
93
|
+
"""
|
|
94
|
+
...
|
|
95
|
+
|
|
96
|
+
@abstractmethod
|
|
97
|
+
async def health_check(self) -> bool:
|
|
98
|
+
"""Return True if the underlying harness is reachable and ready."""
|
|
99
|
+
...
|
|
100
|
+
|
|
101
|
+
@abstractmethod
|
|
102
|
+
async def shutdown(self) -> None:
|
|
103
|
+
"""Cleanly shut down the adapter and release resources."""
|
|
104
|
+
...
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Claude Code harness adapter stub."""
|
|
2
|
+
|
|
3
|
+
from adapters.base import HarnessAdapter, AdapterConfig, AdapterCapability, AdapterResponse
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ClaudeCodeAdapter(HarnessAdapter):
|
|
8
|
+
"""Adapter for the Claude Code harness.
|
|
9
|
+
|
|
10
|
+
Bridges the learning engine to Claude Code's interface.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def name(self) -> str:
|
|
15
|
+
return "claude_code"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def capabilities(self) -> list[AdapterCapability]:
|
|
19
|
+
return [
|
|
20
|
+
AdapterCapability.CODE_GENERATION,
|
|
21
|
+
AdapterCapability.CODE_EXPLANATION,
|
|
22
|
+
AdapterCapability.FILE_EDITING,
|
|
23
|
+
AdapterCapability.WEB_SEARCH,
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
async def configure(self, config: AdapterConfig) -> None:
|
|
27
|
+
"""Apply configuration to the adapter."""
|
|
28
|
+
raise NotImplementedError
|
|
29
|
+
|
|
30
|
+
async def send_prompt(self, prompt: str, context: dict[str, Any] | None = None) -> AdapterResponse:
|
|
31
|
+
"""Send a prompt to Claude Code and return the response."""
|
|
32
|
+
raise NotImplementedError
|
|
33
|
+
|
|
34
|
+
async def inject_context(self, context: dict[str, Any]) -> None:
|
|
35
|
+
"""Inject learning context into the Claude Code session."""
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
|
|
38
|
+
async def health_check(self) -> bool:
|
|
39
|
+
"""Return True if Claude Code is reachable."""
|
|
40
|
+
raise NotImplementedError
|
|
41
|
+
|
|
42
|
+
async def shutdown(self) -> None:
|
|
43
|
+
"""Cleanly shut down the adapter."""
|
|
44
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Codex harness adapter stub."""
|
|
2
|
+
|
|
3
|
+
from adapters.base import HarnessAdapter, AdapterConfig, AdapterCapability, AdapterResponse
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CodexAdapter(HarnessAdapter):
|
|
8
|
+
"""Adapter for the Codex harness.
|
|
9
|
+
|
|
10
|
+
Bridges the learning engine to OpenAI Codex's interface.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def name(self) -> str:
|
|
15
|
+
return "codex"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def capabilities(self) -> list[AdapterCapability]:
|
|
19
|
+
return [
|
|
20
|
+
AdapterCapability.CODE_GENERATION,
|
|
21
|
+
AdapterCapability.CODE_EXPLANATION,
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
async def configure(self, config: AdapterConfig) -> None:
|
|
25
|
+
"""Apply configuration to the adapter."""
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
|
|
28
|
+
async def send_prompt(self, prompt: str, context: dict[str, Any] | None = None) -> AdapterResponse:
|
|
29
|
+
"""Send a prompt to Codex and return the response."""
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
|
|
32
|
+
async def inject_context(self, context: dict[str, Any]) -> None:
|
|
33
|
+
"""Inject learning context into the Codex session."""
|
|
34
|
+
raise NotImplementedError
|
|
35
|
+
|
|
36
|
+
async def health_check(self) -> bool:
|
|
37
|
+
"""Return True if Codex is reachable."""
|
|
38
|
+
raise NotImplementedError
|
|
39
|
+
|
|
40
|
+
async def shutdown(self) -> None:
|
|
41
|
+
"""Cleanly shut down the adapter."""
|
|
42
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Generic harness adapter stub."""
|
|
2
|
+
|
|
3
|
+
from adapters.base import HarnessAdapter, AdapterConfig, AdapterCapability, AdapterResponse
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class GenericAdapter(HarnessAdapter):
|
|
8
|
+
"""Adapter for generic or custom harnesses.
|
|
9
|
+
|
|
10
|
+
A fallback adapter that can be configured to talk to any harness
|
|
11
|
+
exposing a simple prompt/response interface.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def name(self) -> str:
|
|
16
|
+
return "generic"
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def capabilities(self) -> list[AdapterCapability]:
|
|
20
|
+
return [
|
|
21
|
+
AdapterCapability.CODE_GENERATION,
|
|
22
|
+
AdapterCapability.CODE_EXPLANATION,
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
async def configure(self, config: AdapterConfig) -> None:
|
|
26
|
+
"""Apply configuration to the adapter."""
|
|
27
|
+
raise NotImplementedError
|
|
28
|
+
|
|
29
|
+
async def send_prompt(self, prompt: str, context: dict[str, Any] | None = None) -> AdapterResponse:
|
|
30
|
+
"""Send a prompt to the generic harness and return the response."""
|
|
31
|
+
raise NotImplementedError
|
|
32
|
+
|
|
33
|
+
async def inject_context(self, context: dict[str, Any]) -> None:
|
|
34
|
+
"""Inject learning context into the generic harness session."""
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
37
|
+
async def health_check(self) -> bool:
|
|
38
|
+
"""Return True if the generic harness is reachable."""
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
async def shutdown(self) -> None:
|
|
42
|
+
"""Cleanly shut down the adapter."""
|
|
43
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""OpenCode harness adapter stub."""
|
|
2
|
+
|
|
3
|
+
from adapters.base import HarnessAdapter, AdapterConfig, AdapterCapability, AdapterResponse
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OpenCodeAdapter(HarnessAdapter):
|
|
8
|
+
"""Adapter for the OpenCode harness.
|
|
9
|
+
|
|
10
|
+
Bridges the learning engine to OpenCode's CLI and API surface.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def name(self) -> str:
|
|
15
|
+
return "opencode"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def capabilities(self) -> list[AdapterCapability]:
|
|
19
|
+
return [
|
|
20
|
+
AdapterCapability.CODE_GENERATION,
|
|
21
|
+
AdapterCapability.CODE_EXPLANATION,
|
|
22
|
+
AdapterCapability.FILE_EDITING,
|
|
23
|
+
AdapterCapability.TERMINAL_ACCESS,
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
async def configure(self, config: AdapterConfig) -> None:
|
|
27
|
+
"""Apply configuration to the adapter."""
|
|
28
|
+
raise NotImplementedError
|
|
29
|
+
|
|
30
|
+
async def send_prompt(self, prompt: str, context: dict[str, Any] | None = None) -> AdapterResponse:
|
|
31
|
+
"""Send a prompt to OpenCode and return the response."""
|
|
32
|
+
raise NotImplementedError
|
|
33
|
+
|
|
34
|
+
async def inject_context(self, context: dict[str, Any]) -> None:
|
|
35
|
+
"""Inject learning context into the OpenCode session."""
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
|
|
38
|
+
async def health_check(self) -> bool:
|
|
39
|
+
"""Return True if OpenCode is reachable."""
|
|
40
|
+
raise NotImplementedError
|
|
41
|
+
|
|
42
|
+
async def shutdown(self) -> None:
|
|
43
|
+
"""Cleanly shut down the adapter."""
|
|
44
|
+
raise NotImplementedError
|
core/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Core interfaces for the AI Learning Engine.
|
|
2
|
+
|
|
3
|
+
This package defines the abstract base classes and type definitions
|
|
4
|
+
for the learning engine system. It is implementation-agnostic and
|
|
5
|
+
does not depend on any specific harness (OpenCode, Claude, etc.).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
__version__: str = "0.1.0"
|
|
11
|
+
__all__: list[str] = [
|
|
12
|
+
"Learner",
|
|
13
|
+
"MemoryStore",
|
|
14
|
+
"Evaluator",
|
|
15
|
+
"AdaptationEngine",
|
|
16
|
+
"KnowledgeBase",
|
|
17
|
+
]
|
core/adaptation/base.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Abstract base class for the AdaptationEngine component.
|
|
2
|
+
|
|
3
|
+
An AdaptationEngine modifies learner behaviour based on evaluation
|
|
4
|
+
feedback. It bridges evaluation results and parameter updates,
|
|
5
|
+
enabling curriculum adjustments, hyperparameter tuning, or
|
|
6
|
+
meta-learning strategies.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from enum import Enum, auto
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# Enums
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
class AdaptationStrategy(Enum):
|
|
21
|
+
"""High-level adaptation strategy."""
|
|
22
|
+
|
|
23
|
+
GRADIENT = auto()
|
|
24
|
+
LerevLUTIONARY = auto()
|
|
25
|
+
META_LEARNING = auto()
|
|
26
|
+
HEURISTIC = auto()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
# Data models
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True, slots=True)
|
|
34
|
+
class AdaptationSignal:
|
|
35
|
+
"""Feedback signal fed into an AdaptationEngine."""
|
|
36
|
+
|
|
37
|
+
metric_name: str
|
|
38
|
+
current_value: float
|
|
39
|
+
target_value: float | None = None
|
|
40
|
+
context: dict[str, Any] = field(default_factory=dict)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True, slots=True)
|
|
44
|
+
class AdaptationAction:
|
|
45
|
+
"""An action that the AdaptationEngine recommends."""
|
|
46
|
+
|
|
47
|
+
parameter: str
|
|
48
|
+
old_value: Any
|
|
49
|
+
new_value: Any
|
|
50
|
+
reason: str = ""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
# Abstract interface
|
|
55
|
+
# ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
class AdaptationEngine(ABC):
|
|
58
|
+
"""Interface that every adaptation strategy must implement."""
|
|
59
|
+
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def propose(self, signals: list[AdaptationSignal]) -> list[AdaptationAction]:
|
|
62
|
+
"""Analyse signals and propose parameter changes.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
signals: Current feedback signals.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
A list of recommended actions.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
@abstractmethod
|
|
72
|
+
def apply(self, actions: list[AdaptationAction]) -> dict[str, Any]:
|
|
73
|
+
"""Apply a set of actions and return the outcome.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
actions: Actions to execute.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
A dict describing what was actually applied.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
@abstractmethod
|
|
84
|
+
def strategy(self) -> AdaptationStrategy:
|
|
85
|
+
"""Return the underlying adaptation strategy."""
|
core/evaluator/base.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Abstract base class for the Evaluator component.
|
|
2
|
+
|
|
3
|
+
An Evaluator assesses the quality of learner outputs, policies, or
|
|
4
|
+
behaviours against one or more metrics. Concrete implementations may
|
|
5
|
+
wrap statistical tests, LLM-as-judge scoring, or domain-specific
|
|
6
|
+
benchmarks.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from enum import Enum, auto
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# Enums
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
class EvalScale(Enum):
|
|
21
|
+
"""Scale used by an evaluation metric."""
|
|
22
|
+
|
|
23
|
+
BINARY = auto()
|
|
24
|
+
CONTINUOUS = auto()
|
|
25
|
+
ORDINAL = auto()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# Data models
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True, slots=True)
|
|
33
|
+
class EvalMetric:
|
|
34
|
+
"""Definition of a single evaluation metric."""
|
|
35
|
+
|
|
36
|
+
name: str
|
|
37
|
+
scale: EvalScale = EvalScale.CONTINUOUS
|
|
38
|
+
range_min: float = 0.0
|
|
39
|
+
range_max: float = 1.0
|
|
40
|
+
higher_is_better: bool = True
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True, slots=True)
|
|
44
|
+
class EvalResult:
|
|
45
|
+
"""Outcome of evaluating a single sample against a set of metrics."""
|
|
46
|
+
|
|
47
|
+
scores: dict[str, float]
|
|
48
|
+
details: dict[str, Any] = field(default_factory=dict)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass(frozen=True, slots=True)
|
|
52
|
+
class EvalReport:
|
|
53
|
+
"""Aggregated results across many samples."""
|
|
54
|
+
|
|
55
|
+
results: list[EvalResult]
|
|
56
|
+
summary: dict[str, float] = field(default_factory=dict)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
# Abstract interface
|
|
61
|
+
# ---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
class Evaluator(ABC):
|
|
64
|
+
"""Interface that every evaluator must implement."""
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def evaluate(self, sample: dict[str, Any]) -> EvalResult:
|
|
68
|
+
"""Evaluate a single sample.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
sample: The data to evaluate.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
An ``EvalResult`` with per-metric scores.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def aggregate(self, results: list[EvalResult]) -> EvalReport:
|
|
79
|
+
"""Aggregate multiple evaluation results.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
results: Individual results to aggregate.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
A summary ``EvalReport``.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
@abstractmethod
|
|
90
|
+
def metrics(self) -> list[EvalMetric]:
|
|
91
|
+
"""Return the list of metrics this evaluator uses."""
|
core/interfaces.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Centralized exports for all core interfaces.
|
|
2
|
+
|
|
3
|
+
Re-exports every abstract base class and data model so consumers can
|
|
4
|
+
do ``from core.interfaces import Learner, Evaluator, ...``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from core.adaptation.base import AdaptationEngine
|
|
10
|
+
from core.evaluator.base import Evaluator
|
|
11
|
+
from core.knowledge.base import KnowledgeBase
|
|
12
|
+
from core.learner.base import Learner
|
|
13
|
+
from core.memory.base import MemoryStore
|
|
14
|
+
|
|
15
|
+
__all__: list[str] = [
|
|
16
|
+
"Learner",
|
|
17
|
+
"MemoryStore",
|
|
18
|
+
"Evaluator",
|
|
19
|
+
"AdaptationEngine",
|
|
20
|
+
"KnowledgeBase",
|
|
21
|
+
]
|
core/knowledge/base.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Abstract base class for the KnowledgeBase component.
|
|
2
|
+
|
|
3
|
+
A KnowledgeBase maintains structured knowledge (rules, facts,
|
|
4
|
+
ontologies) that can be queried and updated. Concrete implementations
|
|
5
|
+
may use graph databases, semantic stores, or simple dictionaries.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from abc import ABC, abstractmethod
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from enum import Enum, auto
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# Enums
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
class KnowledgeType(Enum):
|
|
21
|
+
"""Type of knowledge entry."""
|
|
22
|
+
|
|
23
|
+
FACT = auto()
|
|
24
|
+
RULE = auto()
|
|
25
|
+
HYPOTHESIS = auto()
|
|
26
|
+
METADATA = auto()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
# Data models
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True, slots=True)
|
|
34
|
+
class KnowledgeEntry:
|
|
35
|
+
"""A single piece of knowledge."""
|
|
36
|
+
|
|
37
|
+
subject: str
|
|
38
|
+
predicate: str
|
|
39
|
+
obj: Any
|
|
40
|
+
knowledge_type: KnowledgeType = KnowledgeType.FACT
|
|
41
|
+
confidence: float = 1.0
|
|
42
|
+
source: str = ""
|
|
43
|
+
created_at: datetime = field(default_factory=datetime.now)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True, slots=True)
|
|
47
|
+
class KnowledgeQuery:
|
|
48
|
+
"""Parameters for querying the knowledge base."""
|
|
49
|
+
|
|
50
|
+
subject: str | None = None
|
|
51
|
+
predicate: str | None = None
|
|
52
|
+
knowledge_type: KnowledgeType | None = None
|
|
53
|
+
min_confidence: float = 0.0
|
|
54
|
+
limit: int = 100
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
# Abstract interface
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
class KnowledgeBase(ABC):
|
|
62
|
+
"""Interface that every knowledge store must implement."""
|
|
63
|
+
|
|
64
|
+
@abstractmethod
|
|
65
|
+
def add(self, entry: KnowledgeEntry) -> None:
|
|
66
|
+
"""Insert a new knowledge entry.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
entry: The knowledge to add.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
@abstractmethod
|
|
73
|
+
def query(self, query: KnowledgeQuery) -> list[KnowledgeEntry]:
|
|
74
|
+
"""Retrieve entries matching *query*.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
query: Search parameters.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
A list of matching entries.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
@abstractmethod
|
|
84
|
+
def update(self, entry: KnowledgeEntry) -> bool:
|
|
85
|
+
"""Update an existing entry (matched by subject + predicate).
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
entry: Updated knowledge.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
``True`` if the entry existed and was updated.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
@abstractmethod
|
|
95
|
+
def remove(self, subject: str, predicate: str) -> bool:
|
|
96
|
+
"""Remove entries matching the given subject/predicate pair.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
``True`` if at least one entry was removed.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
@abstractmethod
|
|
103
|
+
def count(self) -> int:
|
|
104
|
+
"""Return the total number of knowledge entries."""
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def clear(self) -> None:
|
|
108
|
+
"""Remove all entries from the knowledge base."""
|