hegelion 0.4.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.
- hegelion/__init__.py +45 -0
- hegelion/core/__init__.py +29 -0
- hegelion/core/agent.py +166 -0
- hegelion/core/autocoding_state.py +293 -0
- hegelion/core/backends.py +442 -0
- hegelion/core/cache.py +92 -0
- hegelion/core/config.py +276 -0
- hegelion/core/core.py +649 -0
- hegelion/core/engine.py +865 -0
- hegelion/core/logging_utils.py +67 -0
- hegelion/core/models.py +293 -0
- hegelion/core/parsing.py +271 -0
- hegelion/core/personas.py +81 -0
- hegelion/core/prompt_autocoding.py +353 -0
- hegelion/core/prompt_dialectic.py +414 -0
- hegelion/core/prompts.py +127 -0
- hegelion/core/schema.py +67 -0
- hegelion/core/validation.py +68 -0
- hegelion/council.py +254 -0
- hegelion/examples_data/__init__.py +6 -0
- hegelion/examples_data/glm4_6_examples.jsonl +2 -0
- hegelion/judge.py +230 -0
- hegelion/mcp/__init__.py +3 -0
- hegelion/mcp/server.py +918 -0
- hegelion/scripts/hegelion_agent_cli.py +90 -0
- hegelion/scripts/hegelion_bench.py +117 -0
- hegelion/scripts/hegelion_cli.py +497 -0
- hegelion/scripts/hegelion_dataset.py +99 -0
- hegelion/scripts/hegelion_eval.py +137 -0
- hegelion/scripts/mcp_setup.py +150 -0
- hegelion/search_providers.py +151 -0
- hegelion/training/__init__.py +7 -0
- hegelion/training/datasets.py +123 -0
- hegelion/training/generator.py +232 -0
- hegelion/training/mlx_scu_trainer.py +379 -0
- hegelion/training/mlx_trainer.py +181 -0
- hegelion/training/unsloth_trainer.py +136 -0
- hegelion-0.4.0.dist-info/METADATA +295 -0
- hegelion-0.4.0.dist-info/RECORD +43 -0
- hegelion-0.4.0.dist-info/WHEEL +5 -0
- hegelion-0.4.0.dist-info/entry_points.txt +8 -0
- hegelion-0.4.0.dist-info/licenses/LICENSE +21 -0
- hegelion-0.4.0.dist-info/top_level.txt +1 -0
hegelion/core/config.py
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"""Environment-driven configuration helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from functools import lru_cache
|
|
8
|
+
from typing import Any, Dict
|
|
9
|
+
|
|
10
|
+
from .backends import (
|
|
11
|
+
AnthropicLLMBackend,
|
|
12
|
+
CustomHTTPLLMBackend,
|
|
13
|
+
GoogleLLMBackend,
|
|
14
|
+
LLMBackend,
|
|
15
|
+
OllamaLLMBackend,
|
|
16
|
+
OpenAILLMBackend,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ConfigurationError(RuntimeError):
|
|
21
|
+
"""Raised when the server is misconfigured."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class EngineSettings:
|
|
26
|
+
"""Settings for the Hegelion engine."""
|
|
27
|
+
|
|
28
|
+
model: str
|
|
29
|
+
synthesis_threshold: float
|
|
30
|
+
max_tokens_per_phase: int
|
|
31
|
+
validate_results: bool
|
|
32
|
+
cache_enabled: bool
|
|
33
|
+
cache_ttl_seconds: int
|
|
34
|
+
cache_dir: str
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class Config:
|
|
39
|
+
"""Mutable runtime configuration for Hegelion."""
|
|
40
|
+
|
|
41
|
+
provider: str
|
|
42
|
+
model: str
|
|
43
|
+
synthesis_threshold: float
|
|
44
|
+
max_tokens_per_phase: int
|
|
45
|
+
validate_results: bool
|
|
46
|
+
cache_enabled: bool
|
|
47
|
+
cache_ttl_seconds: int
|
|
48
|
+
cache_dir: str
|
|
49
|
+
|
|
50
|
+
# Backend-specific settings
|
|
51
|
+
openai_key: str | None
|
|
52
|
+
openai_base_url: str | None
|
|
53
|
+
openai_org: str | None
|
|
54
|
+
anthropic_key: str | None
|
|
55
|
+
anthropic_base_url: str
|
|
56
|
+
google_key: str | None
|
|
57
|
+
google_base_url: str | None
|
|
58
|
+
moonshot_key: str | None
|
|
59
|
+
moonshot_base_url: str
|
|
60
|
+
ollama_url: str
|
|
61
|
+
custom_base_url: str | None
|
|
62
|
+
custom_api_key: str | None
|
|
63
|
+
custom_timeout: float
|
|
64
|
+
|
|
65
|
+
debug: bool = False
|
|
66
|
+
|
|
67
|
+
# Internal state
|
|
68
|
+
_initial_env: Dict[str, Any] = field(default_factory=dict, repr=False)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _get_env_float(name: str, default: float) -> float:
|
|
72
|
+
raw = os.getenv(name)
|
|
73
|
+
if raw is None:
|
|
74
|
+
return default
|
|
75
|
+
try:
|
|
76
|
+
return float(raw)
|
|
77
|
+
except ValueError as exc:
|
|
78
|
+
raise ConfigurationError(f"Environment variable {name} must be a float.") from exc
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _get_env_int(name: str, default: int) -> int:
|
|
82
|
+
raw = os.getenv(name)
|
|
83
|
+
if raw is None:
|
|
84
|
+
return default
|
|
85
|
+
try:
|
|
86
|
+
return int(raw)
|
|
87
|
+
except ValueError as exc:
|
|
88
|
+
raise ConfigurationError(f"Environment variable {name} must be an integer.") from exc
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _get_env_bool(name: str, default: bool) -> bool:
|
|
92
|
+
raw = os.getenv(name)
|
|
93
|
+
if raw is None:
|
|
94
|
+
return default
|
|
95
|
+
return raw.strip().lower() not in {"0", "false", "no"}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com"
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@lru_cache(maxsize=1)
|
|
102
|
+
def get_config() -> Config:
|
|
103
|
+
"""Return the global, mutable configuration object."""
|
|
104
|
+
return Config(
|
|
105
|
+
provider=os.getenv("HEGELION_PROVIDER", "anthropic").lower(),
|
|
106
|
+
model=os.getenv("HEGELION_MODEL", "claude-sonnet-4-5-20250929"),
|
|
107
|
+
synthesis_threshold=_get_env_float("HEGELION_SYNTHESIS_THRESHOLD", 0.85),
|
|
108
|
+
max_tokens_per_phase=_get_env_int("HEGELION_MAX_TOKENS_PER_PHASE", 10_000),
|
|
109
|
+
validate_results=_get_env_bool("HEGELION_VALIDATE_RESULTS", True),
|
|
110
|
+
cache_enabled=_get_env_bool("HEGELION_CACHE", True),
|
|
111
|
+
cache_ttl_seconds=_get_env_int("HEGELION_CACHE_TTL_SECONDS", 86_400),
|
|
112
|
+
cache_dir=os.path.expanduser(os.getenv("HEGELION_CACHE_DIR", "~/.cache/hegelion")),
|
|
113
|
+
openai_key=os.getenv("OPENAI_API_KEY"),
|
|
114
|
+
openai_base_url=os.getenv("OPENAI_BASE_URL"),
|
|
115
|
+
openai_org=os.getenv("OPENAI_ORG_ID"),
|
|
116
|
+
anthropic_key=os.getenv("ANTHROPIC_API_KEY"),
|
|
117
|
+
anthropic_base_url=os.getenv("ANTHROPIC_BASE_URL", DEFAULT_ANTHROPIC_BASE_URL),
|
|
118
|
+
google_key=os.getenv("GOOGLE_API_KEY"),
|
|
119
|
+
google_base_url=os.getenv("GOOGLE_API_BASE_URL"),
|
|
120
|
+
moonshot_key=os.getenv("MOONSHOT_API_KEY"),
|
|
121
|
+
moonshot_base_url=os.getenv("MOONSHOT_BASE_URL", "https://api.moonshot.ai/v1"),
|
|
122
|
+
ollama_url=os.getenv("OLLAMA_BASE_URL", "http://localhost:11434"),
|
|
123
|
+
custom_base_url=os.getenv("CUSTOM_API_BASE_URL"),
|
|
124
|
+
custom_api_key=os.getenv("CUSTOM_API_KEY"),
|
|
125
|
+
custom_timeout=_get_env_float("CUSTOM_API_TIMEOUT", 60.0),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def set_config_value(key: str, value: Any) -> None:
|
|
130
|
+
"""Update a value in the global configuration."""
|
|
131
|
+
config = get_config()
|
|
132
|
+
if hasattr(config, key):
|
|
133
|
+
setattr(config, key, value)
|
|
134
|
+
# When backend-related config changes, we must clear the backend cache
|
|
135
|
+
if key in {
|
|
136
|
+
"provider",
|
|
137
|
+
"model",
|
|
138
|
+
"openai_key",
|
|
139
|
+
"anthropic_key",
|
|
140
|
+
"google_key",
|
|
141
|
+
"moonshot_key",
|
|
142
|
+
}:
|
|
143
|
+
get_backend_from_env.cache_clear()
|
|
144
|
+
else:
|
|
145
|
+
raise AttributeError(f"'{type(config).__name__}' has no attribute '{key}'")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def resolve_backend_for_model(model: str) -> LLMBackend:
|
|
149
|
+
"""Resolve an LLM backend based on the model name."""
|
|
150
|
+
lowered = model.lower()
|
|
151
|
+
config = get_config()
|
|
152
|
+
|
|
153
|
+
if "claude" in lowered:
|
|
154
|
+
if not config.anthropic_key:
|
|
155
|
+
raise ConfigurationError("ANTHROPIC_API_KEY must be set.")
|
|
156
|
+
return AnthropicLLMBackend(
|
|
157
|
+
model=model,
|
|
158
|
+
api_key=config.anthropic_key,
|
|
159
|
+
base_url=config.anthropic_base_url,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
if lowered.startswith(("gpt-", "o1-")) or "glm" in lowered:
|
|
163
|
+
if not config.openai_key:
|
|
164
|
+
raise ConfigurationError("OPENAI_API_KEY must be set.")
|
|
165
|
+
return OpenAILLMBackend(
|
|
166
|
+
model=(
|
|
167
|
+
model if model != "gpt-5.1-chat-latest" else "gpt-5.1-chat-latest"
|
|
168
|
+
), # Ensure we use the exact model string
|
|
169
|
+
api_key=config.openai_key,
|
|
170
|
+
base_url=config.openai_base_url,
|
|
171
|
+
organization=config.openai_org,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if "gemini" in lowered or lowered.startswith("g-"):
|
|
175
|
+
if not config.google_key:
|
|
176
|
+
raise ConfigurationError("GOOGLE_API_KEY must be set.")
|
|
177
|
+
return GoogleLLMBackend(
|
|
178
|
+
model=(
|
|
179
|
+
model if "gemini" in model else "gemini-3-pro-preview"
|
|
180
|
+
), # Default to new model if generic g- prefix
|
|
181
|
+
api_key=config.google_key,
|
|
182
|
+
base_url=config.google_base_url,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
if "kimi" in lowered:
|
|
186
|
+
if not config.moonshot_key:
|
|
187
|
+
raise ConfigurationError("MOONSHOT_API_KEY must be set for Kimi models.")
|
|
188
|
+
return OpenAILLMBackend(
|
|
189
|
+
model=model,
|
|
190
|
+
api_key=config.moonshot_key,
|
|
191
|
+
base_url=config.moonshot_base_url,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
if lowered.startswith("local-"):
|
|
195
|
+
actual_model = model.split("local-", 1)[1] or "llama3.3"
|
|
196
|
+
return OllamaLLMBackend(model=actual_model, base_url=config.ollama_url)
|
|
197
|
+
|
|
198
|
+
raise ConfigurationError(f"Cannot infer backend for model '{model}'.")
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
@lru_cache(maxsize=1)
|
|
202
|
+
def get_backend_from_env() -> LLMBackend:
|
|
203
|
+
"""Instantiate the configured backend from the global config."""
|
|
204
|
+
config = get_config()
|
|
205
|
+
|
|
206
|
+
if config.provider in {"anthropic", "auto"} and config.anthropic_key:
|
|
207
|
+
return AnthropicLLMBackend(
|
|
208
|
+
model=config.model,
|
|
209
|
+
api_key=config.anthropic_key,
|
|
210
|
+
base_url=config.anthropic_base_url,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
if config.provider in {"openai", "auto"} and config.openai_key:
|
|
214
|
+
return OpenAILLMBackend(
|
|
215
|
+
model=config.model,
|
|
216
|
+
api_key=config.openai_key,
|
|
217
|
+
base_url=config.openai_base_url,
|
|
218
|
+
organization=config.openai_org,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
if config.provider in {"google", "auto"} and config.google_key:
|
|
222
|
+
return GoogleLLMBackend(
|
|
223
|
+
model=config.model,
|
|
224
|
+
api_key=config.google_key,
|
|
225
|
+
base_url=config.google_base_url,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
if config.provider in {"moonshot", "kimi", "auto"} and config.moonshot_key:
|
|
229
|
+
return OpenAILLMBackend(
|
|
230
|
+
model=config.model,
|
|
231
|
+
api_key=config.moonshot_key,
|
|
232
|
+
base_url=config.moonshot_base_url,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
if config.provider == "ollama":
|
|
236
|
+
return OllamaLLMBackend(model=config.model, base_url=config.ollama_url)
|
|
237
|
+
|
|
238
|
+
if config.provider == "custom_http":
|
|
239
|
+
if not config.custom_base_url:
|
|
240
|
+
raise ConfigurationError("CUSTOM_API_BASE_URL must be set for custom_http provider.")
|
|
241
|
+
return CustomHTTPLLMBackend(
|
|
242
|
+
model=config.model,
|
|
243
|
+
api_base_url=config.custom_base_url,
|
|
244
|
+
api_key=config.custom_api_key,
|
|
245
|
+
timeout=config.custom_timeout,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
raise ConfigurationError(
|
|
249
|
+
"Unable to configure LLM backend. Set HEGELION_PROVIDER and corresponding API keys."
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def get_engine_settings() -> EngineSettings:
|
|
254
|
+
"""Load engine configuration values from the global config."""
|
|
255
|
+
config = get_config()
|
|
256
|
+
return EngineSettings(
|
|
257
|
+
model=config.model,
|
|
258
|
+
synthesis_threshold=config.synthesis_threshold,
|
|
259
|
+
max_tokens_per_phase=config.max_tokens_per_phase,
|
|
260
|
+
validate_results=config.validate_results,
|
|
261
|
+
cache_enabled=config.cache_enabled,
|
|
262
|
+
cache_ttl_seconds=config.cache_ttl_seconds,
|
|
263
|
+
cache_dir=config.cache_dir,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
__all__ = [
|
|
268
|
+
"Config",
|
|
269
|
+
"EngineSettings",
|
|
270
|
+
"ConfigurationError",
|
|
271
|
+
"get_config",
|
|
272
|
+
"set_config_value",
|
|
273
|
+
"get_backend_from_env",
|
|
274
|
+
"get_engine_settings",
|
|
275
|
+
"resolve_backend_for_model",
|
|
276
|
+
]
|