aleph-rlm 0.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.
- aleph/__init__.py +49 -0
- aleph/cache/__init__.py +6 -0
- aleph/cache/base.py +20 -0
- aleph/cache/memory.py +27 -0
- aleph/cli.py +1044 -0
- aleph/config.py +154 -0
- aleph/core.py +874 -0
- aleph/mcp/__init__.py +30 -0
- aleph/mcp/local_server.py +3527 -0
- aleph/mcp/server.py +20 -0
- aleph/prompts/__init__.py +5 -0
- aleph/prompts/system.py +45 -0
- aleph/providers/__init__.py +14 -0
- aleph/providers/anthropic.py +253 -0
- aleph/providers/base.py +59 -0
- aleph/providers/openai.py +224 -0
- aleph/providers/registry.py +22 -0
- aleph/repl/__init__.py +5 -0
- aleph/repl/helpers.py +1068 -0
- aleph/repl/sandbox.py +777 -0
- aleph/sub_query/__init__.py +166 -0
- aleph/sub_query/api_backend.py +166 -0
- aleph/sub_query/cli_backend.py +327 -0
- aleph/types.py +216 -0
- aleph/utils/__init__.py +6 -0
- aleph/utils/logging.py +79 -0
- aleph/utils/tokens.py +43 -0
- aleph_rlm-0.6.0.dist-info/METADATA +358 -0
- aleph_rlm-0.6.0.dist-info/RECORD +32 -0
- aleph_rlm-0.6.0.dist-info/WHEEL +4 -0
- aleph_rlm-0.6.0.dist-info/entry_points.txt +3 -0
- aleph_rlm-0.6.0.dist-info/licenses/LICENSE +21 -0
aleph/config.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""Configuration management for Aleph.
|
|
2
|
+
|
|
3
|
+
AlephConfig can be instantiated directly, loaded from env vars, or loaded from a
|
|
4
|
+
YAML/JSON config file.
|
|
5
|
+
|
|
6
|
+
The goal is to make it easy to go from *configuration* -> a ready-to-run Aleph
|
|
7
|
+
instance.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
from collections.abc import Mapping
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Any, Literal, cast
|
|
18
|
+
|
|
19
|
+
from .types import Budget
|
|
20
|
+
from .repl.sandbox import DEFAULT_ALLOWED_IMPORTS, SandboxConfig
|
|
21
|
+
from .providers.registry import get_provider
|
|
22
|
+
from .core import Aleph
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(slots=True)
|
|
26
|
+
class AlephConfig:
|
|
27
|
+
"""Complete configuration for an Aleph instance."""
|
|
28
|
+
|
|
29
|
+
# Provider / models
|
|
30
|
+
provider: str = "anthropic"
|
|
31
|
+
root_model: str = "claude-sonnet-4-20250514"
|
|
32
|
+
sub_model: str | None = None
|
|
33
|
+
api_key: str | None = None
|
|
34
|
+
|
|
35
|
+
# Budget defaults
|
|
36
|
+
max_tokens: int | None = None
|
|
37
|
+
max_iterations: int = 100
|
|
38
|
+
max_depth: int = 2
|
|
39
|
+
max_wall_time_seconds: float = 300.0
|
|
40
|
+
max_sub_queries: int = 100
|
|
41
|
+
|
|
42
|
+
# Sandbox
|
|
43
|
+
enable_code_execution: bool = True
|
|
44
|
+
allowed_imports: list[str] = field(default_factory=lambda: list(DEFAULT_ALLOWED_IMPORTS))
|
|
45
|
+
sandbox_timeout_seconds: float = 60.0
|
|
46
|
+
max_output_chars: int = 50_000
|
|
47
|
+
|
|
48
|
+
# REPL
|
|
49
|
+
context_var_name: str = "ctx"
|
|
50
|
+
|
|
51
|
+
# Caching
|
|
52
|
+
enable_caching: bool = True
|
|
53
|
+
cache_backend: Literal["memory"] = "memory"
|
|
54
|
+
|
|
55
|
+
# Observability
|
|
56
|
+
log_trajectory: bool = True
|
|
57
|
+
log_level: str = "INFO"
|
|
58
|
+
|
|
59
|
+
# Custom prompt
|
|
60
|
+
system_prompt: str | None = None
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def from_file(cls, path: str | Path) -> "AlephConfig":
|
|
64
|
+
"""Load config from YAML or JSON."""
|
|
65
|
+
|
|
66
|
+
path = Path(path)
|
|
67
|
+
content = path.read_text(encoding="utf-8")
|
|
68
|
+
|
|
69
|
+
if path.suffix.lower() in {".yaml", ".yml"}:
|
|
70
|
+
try:
|
|
71
|
+
import yaml
|
|
72
|
+
except Exception as e: # pragma: no cover
|
|
73
|
+
raise RuntimeError(
|
|
74
|
+
"YAML support requires PyYAML. Install aleph[yaml] or `pip install pyyaml`."
|
|
75
|
+
) from e
|
|
76
|
+
data = yaml.safe_load(content) or {}
|
|
77
|
+
else:
|
|
78
|
+
data = json.loads(content) if content.strip() else {}
|
|
79
|
+
|
|
80
|
+
if not isinstance(data, dict):
|
|
81
|
+
raise ValueError(f"Config file must parse to an object/dict, got: {type(data)}")
|
|
82
|
+
return cls(**cast(dict[str, Any], data))
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def from_env(cls) -> "AlephConfig":
|
|
86
|
+
"""Load config from environment variables."""
|
|
87
|
+
|
|
88
|
+
def getenv_int(name: str, default: int | None) -> int | None:
|
|
89
|
+
v = os.getenv(name)
|
|
90
|
+
if v is None or v == "":
|
|
91
|
+
return default
|
|
92
|
+
return int(v)
|
|
93
|
+
|
|
94
|
+
return cls(
|
|
95
|
+
provider=os.getenv("ALEPH_PROVIDER", os.getenv("RLM_PROVIDER", "anthropic")),
|
|
96
|
+
root_model=os.getenv("ALEPH_MODEL", os.getenv("RLM_MODEL", "claude-sonnet-4-20250514")),
|
|
97
|
+
sub_model=os.getenv("ALEPH_SUB_MODEL", os.getenv("RLM_SUB_MODEL")),
|
|
98
|
+
api_key=os.getenv("ALEPH_API_KEY", os.getenv("RLM_API_KEY")),
|
|
99
|
+
max_tokens=getenv_int("ALEPH_MAX_TOKENS", None),
|
|
100
|
+
max_iterations=int(os.getenv("ALEPH_MAX_ITERATIONS", "100")),
|
|
101
|
+
max_depth=int(os.getenv("ALEPH_MAX_DEPTH", "2")),
|
|
102
|
+
max_wall_time_seconds=float(os.getenv("ALEPH_MAX_WALL_TIME", "300")),
|
|
103
|
+
max_sub_queries=int(os.getenv("ALEPH_MAX_SUB_QUERIES", "100")),
|
|
104
|
+
enable_caching=os.getenv("ALEPH_ENABLE_CACHING", "true").lower() in {"1", "true", "yes"},
|
|
105
|
+
log_trajectory=os.getenv("ALEPH_LOG_TRAJECTORY", "true").lower() in {"1", "true", "yes"},
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def to_budget(self) -> Budget:
|
|
109
|
+
"""Convert this config to a :class:`~aleph.types.Budget` instance."""
|
|
110
|
+
return Budget(
|
|
111
|
+
max_tokens=self.max_tokens,
|
|
112
|
+
max_iterations=self.max_iterations,
|
|
113
|
+
max_depth=self.max_depth,
|
|
114
|
+
max_wall_time_seconds=self.max_wall_time_seconds,
|
|
115
|
+
max_sub_queries=self.max_sub_queries,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def to_sandbox_config(self) -> SandboxConfig:
|
|
119
|
+
"""Convert this config to a :class:`~aleph.repl.sandbox.SandboxConfig` instance."""
|
|
120
|
+
return SandboxConfig(
|
|
121
|
+
allowed_imports=self.allowed_imports,
|
|
122
|
+
max_output_chars=self.max_output_chars,
|
|
123
|
+
timeout_seconds=self.sandbox_timeout_seconds,
|
|
124
|
+
enable_code_execution=self.enable_code_execution,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def create_aleph(config: AlephConfig | Mapping[str, object] | str | Path | None = None) -> Aleph:
|
|
129
|
+
"""Factory to create Aleph from config sources."""
|
|
130
|
+
|
|
131
|
+
if config is None:
|
|
132
|
+
cfg = AlephConfig.from_env()
|
|
133
|
+
elif isinstance(config, AlephConfig):
|
|
134
|
+
cfg = config
|
|
135
|
+
elif isinstance(config, Mapping):
|
|
136
|
+
cfg = AlephConfig(**cast(dict[str, Any], dict(config)))
|
|
137
|
+
elif isinstance(config, (str, Path)):
|
|
138
|
+
cfg = AlephConfig.from_file(config)
|
|
139
|
+
else:
|
|
140
|
+
raise TypeError(f"Invalid config type: {type(config)}")
|
|
141
|
+
|
|
142
|
+
# Provider instance
|
|
143
|
+
provider = get_provider(cfg.provider, api_key=cfg.api_key)
|
|
144
|
+
|
|
145
|
+
return Aleph(
|
|
146
|
+
provider=provider,
|
|
147
|
+
root_model=cfg.root_model,
|
|
148
|
+
sub_model=cfg.sub_model or cfg.root_model,
|
|
149
|
+
budget=cfg.to_budget(),
|
|
150
|
+
sandbox_config=cfg.to_sandbox_config(),
|
|
151
|
+
system_prompt=cfg.system_prompt,
|
|
152
|
+
enable_caching=cfg.enable_caching,
|
|
153
|
+
log_trajectory=cfg.log_trajectory,
|
|
154
|
+
)
|