ragit 0.3__py3-none-any.whl → 0.10.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.
- ragit/__init__.py +128 -2
- ragit/assistant.py +757 -0
- ragit/config.py +204 -0
- ragit/core/__init__.py +5 -0
- ragit/core/experiment/__init__.py +22 -0
- ragit/core/experiment/experiment.py +577 -0
- ragit/core/experiment/results.py +131 -0
- ragit/exceptions.py +271 -0
- ragit/loaders.py +401 -0
- ragit/logging.py +194 -0
- ragit/monitor.py +307 -0
- ragit/providers/__init__.py +35 -0
- ragit/providers/base.py +147 -0
- ragit/providers/function_adapter.py +237 -0
- ragit/providers/ollama.py +670 -0
- ragit/utils/__init__.py +105 -0
- ragit/version.py +5 -0
- ragit-0.10.1.dist-info/METADATA +153 -0
- ragit-0.10.1.dist-info/RECORD +22 -0
- {ragit-0.3.dist-info → ragit-0.10.1.dist-info}/WHEEL +1 -1
- ragit-0.10.1.dist-info/licenses/LICENSE +201 -0
- ragit/main.py +0 -384
- ragit-0.3.dist-info/METADATA +0 -163
- ragit-0.3.dist-info/RECORD +0 -6
- {ragit-0.3.dist-info → ragit-0.10.1.dist-info}/top_level.txt +0 -0
ragit/config.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright RODMENA LIMITED 2025
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
"""
|
|
6
|
+
Ragit configuration management with Pydantic validation.
|
|
7
|
+
|
|
8
|
+
Loads configuration from environment variables and .env files.
|
|
9
|
+
Validates all configuration values at startup.
|
|
10
|
+
|
|
11
|
+
Note: As of v0.8.0, ragit no longer has default LLM or embedding models.
|
|
12
|
+
Users must explicitly configure providers.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
from dotenv import load_dotenv
|
|
19
|
+
from pydantic import BaseModel, Field, field_validator
|
|
20
|
+
|
|
21
|
+
# Note: We define ConfigValidationError locally to avoid circular imports,
|
|
22
|
+
# but ragit.exceptions.ConfigurationError can be used elsewhere
|
|
23
|
+
|
|
24
|
+
# Load .env file from current working directory or project root
|
|
25
|
+
_env_path = Path.cwd() / ".env"
|
|
26
|
+
if _env_path.exists():
|
|
27
|
+
load_dotenv(_env_path)
|
|
28
|
+
else:
|
|
29
|
+
# Try to find .env in parent directories
|
|
30
|
+
for parent in Path.cwd().parents:
|
|
31
|
+
_env_path = parent / ".env"
|
|
32
|
+
if _env_path.exists():
|
|
33
|
+
load_dotenv(_env_path)
|
|
34
|
+
break
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ConfigValidationError(Exception):
|
|
38
|
+
"""Raised when configuration validation fails."""
|
|
39
|
+
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class RagitConfig(BaseModel):
|
|
44
|
+
"""Validated ragit configuration.
|
|
45
|
+
|
|
46
|
+
All configuration values are validated at startup. Invalid values
|
|
47
|
+
raise ConfigValidationError with a descriptive message.
|
|
48
|
+
|
|
49
|
+
Attributes
|
|
50
|
+
----------
|
|
51
|
+
ollama_base_url : str
|
|
52
|
+
Ollama server URL (default: http://localhost:11434)
|
|
53
|
+
ollama_embedding_url : str
|
|
54
|
+
Embedding API URL (defaults to ollama_base_url)
|
|
55
|
+
ollama_api_key : str | None
|
|
56
|
+
API key for authentication
|
|
57
|
+
ollama_timeout : int
|
|
58
|
+
Request timeout in seconds (1-600)
|
|
59
|
+
default_llm_model : str | None
|
|
60
|
+
Default LLM model name
|
|
61
|
+
default_embedding_model : str | None
|
|
62
|
+
Default embedding model name
|
|
63
|
+
log_level : str
|
|
64
|
+
Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
ollama_base_url: str = Field(default="http://localhost:11434")
|
|
68
|
+
ollama_embedding_url: str | None = None
|
|
69
|
+
ollama_api_key: str | None = None
|
|
70
|
+
ollama_timeout: int = Field(default=120, gt=0, le=600)
|
|
71
|
+
default_llm_model: str | None = None
|
|
72
|
+
default_embedding_model: str | None = None
|
|
73
|
+
log_level: str = Field(default="INFO")
|
|
74
|
+
|
|
75
|
+
@field_validator("ollama_base_url", "ollama_embedding_url", mode="before")
|
|
76
|
+
@classmethod
|
|
77
|
+
def validate_url(cls, v: str | None) -> str | None:
|
|
78
|
+
"""Validate URL format."""
|
|
79
|
+
if v is None:
|
|
80
|
+
return v
|
|
81
|
+
v = str(v).strip().rstrip("/")
|
|
82
|
+
if not v:
|
|
83
|
+
return None
|
|
84
|
+
if not v.startswith(("http://", "https://")):
|
|
85
|
+
raise ValueError(f"URL must start with http:// or https://: {v}")
|
|
86
|
+
return v
|
|
87
|
+
|
|
88
|
+
@field_validator("log_level", mode="before")
|
|
89
|
+
@classmethod
|
|
90
|
+
def validate_log_level(cls, v: str) -> str:
|
|
91
|
+
"""Validate log level is a valid Python logging level."""
|
|
92
|
+
valid_levels = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
|
|
93
|
+
v = str(v).upper().strip()
|
|
94
|
+
if v not in valid_levels:
|
|
95
|
+
raise ValueError(f"Invalid log level: {v}. Must be one of {valid_levels}")
|
|
96
|
+
return v
|
|
97
|
+
|
|
98
|
+
@field_validator("ollama_api_key", mode="before")
|
|
99
|
+
@classmethod
|
|
100
|
+
def validate_api_key(cls, v: str | None) -> str | None:
|
|
101
|
+
"""Treat empty string as None."""
|
|
102
|
+
if v is not None and not str(v).strip():
|
|
103
|
+
return None
|
|
104
|
+
return v
|
|
105
|
+
|
|
106
|
+
@field_validator("ollama_timeout", mode="before")
|
|
107
|
+
@classmethod
|
|
108
|
+
def validate_timeout(cls, v: int | str) -> int:
|
|
109
|
+
"""Parse and validate timeout value."""
|
|
110
|
+
try:
|
|
111
|
+
timeout = int(v)
|
|
112
|
+
except (ValueError, TypeError) as e:
|
|
113
|
+
raise ValueError(f"Invalid timeout value '{v}': must be an integer") from e
|
|
114
|
+
return timeout
|
|
115
|
+
|
|
116
|
+
model_config = {"extra": "forbid"}
|
|
117
|
+
|
|
118
|
+
# Uppercase aliases for backwards compatibility
|
|
119
|
+
@property
|
|
120
|
+
def OLLAMA_BASE_URL(self) -> str:
|
|
121
|
+
return self.ollama_base_url
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def OLLAMA_EMBEDDING_URL(self) -> str:
|
|
125
|
+
return self.ollama_embedding_url or self.ollama_base_url
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def OLLAMA_API_KEY(self) -> str | None:
|
|
129
|
+
return self.ollama_api_key
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def OLLAMA_TIMEOUT(self) -> int:
|
|
133
|
+
return self.ollama_timeout
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def DEFAULT_LLM_MODEL(self) -> str | None:
|
|
137
|
+
return self.default_llm_model
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def DEFAULT_EMBEDDING_MODEL(self) -> str | None:
|
|
141
|
+
return self.default_embedding_model
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def LOG_LEVEL(self) -> str:
|
|
145
|
+
return self.log_level
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _safe_get_env(key: str, default: str | None = None) -> str | None:
|
|
149
|
+
"""Get environment variable, returning None for empty strings."""
|
|
150
|
+
value = os.getenv(key, default)
|
|
151
|
+
if value is not None and not value.strip():
|
|
152
|
+
return default
|
|
153
|
+
return value
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _safe_get_int_env(key: str, default: int) -> int | str:
|
|
157
|
+
"""Get environment variable as int, returning raw string if invalid."""
|
|
158
|
+
value = os.getenv(key)
|
|
159
|
+
if value is None:
|
|
160
|
+
return default
|
|
161
|
+
try:
|
|
162
|
+
return int(value)
|
|
163
|
+
except ValueError:
|
|
164
|
+
# Return the raw string so Pydantic can give a better error message
|
|
165
|
+
return value
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def load_config() -> RagitConfig:
|
|
169
|
+
"""Load and validate configuration from environment variables.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
RagitConfig
|
|
174
|
+
Validated configuration object.
|
|
175
|
+
|
|
176
|
+
Raises
|
|
177
|
+
------
|
|
178
|
+
ConfigValidationError
|
|
179
|
+
If configuration validation fails.
|
|
180
|
+
"""
|
|
181
|
+
try:
|
|
182
|
+
return RagitConfig(
|
|
183
|
+
ollama_base_url=_safe_get_env("OLLAMA_BASE_URL", "http://localhost:11434") or "http://localhost:11434",
|
|
184
|
+
ollama_embedding_url=_safe_get_env("OLLAMA_EMBEDDING_URL") or _safe_get_env("OLLAMA_BASE_URL"),
|
|
185
|
+
ollama_api_key=_safe_get_env("OLLAMA_API_KEY"),
|
|
186
|
+
ollama_timeout=_safe_get_int_env("OLLAMA_TIMEOUT", 120),
|
|
187
|
+
default_llm_model=_safe_get_env("RAGIT_DEFAULT_LLM_MODEL"),
|
|
188
|
+
default_embedding_model=_safe_get_env("RAGIT_DEFAULT_EMBEDDING_MODEL"),
|
|
189
|
+
log_level=_safe_get_env("RAGIT_LOG_LEVEL", "INFO") or "INFO",
|
|
190
|
+
)
|
|
191
|
+
except Exception as e:
|
|
192
|
+
raise ConfigValidationError(f"Configuration error: {e}") from e
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# Singleton instance - validates configuration at import time
|
|
196
|
+
try:
|
|
197
|
+
config = load_config()
|
|
198
|
+
except ConfigValidationError as e:
|
|
199
|
+
# Re-raise with clear message
|
|
200
|
+
raise ConfigValidationError(str(e)) from e
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# Backwards compatibility alias
|
|
204
|
+
Config = RagitConfig
|
ragit/core/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright RODMENA LIMITED 2025
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
"""Ragit experiment module."""
|
|
6
|
+
|
|
7
|
+
from ragit.core.experiment.experiment import (
|
|
8
|
+
BenchmarkQuestion,
|
|
9
|
+
Document,
|
|
10
|
+
RAGConfig,
|
|
11
|
+
RagitExperiment,
|
|
12
|
+
)
|
|
13
|
+
from ragit.core.experiment.results import EvaluationResult, ExperimentResults
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"RagitExperiment",
|
|
17
|
+
"Document",
|
|
18
|
+
"BenchmarkQuestion",
|
|
19
|
+
"RAGConfig",
|
|
20
|
+
"EvaluationResult",
|
|
21
|
+
"ExperimentResults",
|
|
22
|
+
]
|