Skip to content

Commit

Permalink
Version 1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon Lefore committed Jan 19, 2024
1 parent b026817 commit c411357
Show file tree
Hide file tree
Showing 260 changed files with 3,298 additions and 1,029 deletions.
2 changes: 1 addition & 1 deletion abacusai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from .streaming_client import StreamingClient


__version__ = "1.0.5"
__version__ = "1.1.0"
1 change: 1 addition & 0 deletions abacusai/api_class/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .ai_agents import *
from .ai_chat import *
from .batch_prediction import *
from .blob_input import *
from .dataset import *
Expand Down
11 changes: 6 additions & 5 deletions abacusai/api_class/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ class _ApiClassFactory(ABC):
@classmethod
def from_dict(cls, config: dict) -> ApiClass:
support_kwargs = cls.config_abstract_class and cls.config_abstract_class._support_kwargs
config_class_key = cls.config_class_key if (cls.config_abstract_class and not cls.config_abstract_class._upper_snake_case_keys) else camel_case(cls.config_class_key)
not_upper_snake_case_keys = cls.config_abstract_class and not cls.config_abstract_class._upper_snake_case_keys
config_class_key = cls.config_class_key if (not_upper_snake_case_keys) else camel_case(cls.config_class_key)
if not_upper_snake_case_keys and config_class_key not in config and camel_case(config_class_key) in config:
config_class_key = camel_case(config_class_key)
if not support_kwargs and config_class_key not in (config or {}):
if camel_case(config_class_key) in (config or {}):
config_class_key = camel_case(config_class_key)
else:
raise KeyError(f'Could not find {config_class_key} in {config}')
raise KeyError(f'Could not find {config_class_key} in {config}')
config_class_type = config.get(config_class_key, None)
if isinstance(config_class_type, str):
config_class_type = config_class_type.upper()
Expand All @@ -186,4 +186,5 @@ def from_dict(cls, config: dict) -> ApiClass:
raise ValueError(f'Invalid type {config_class_type}')
if not config_class._upper_snake_case_keys:
config = {snake_case(k): v for k, v in config.items()}
config.pop(snake_case(config_class_key), None)
return config_class(**config)
16 changes: 16 additions & 0 deletions abacusai/api_class/ai_chat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import dataclasses

from .abstract import ApiClass


@dataclasses.dataclass
class HotkeyPrompt(ApiClass):
"""
A config class for a Data Science Co-Pilot Hotkey
Args:
prompt (str): The prompt to send to Data Science Co-Pilot
title (str): A short, descriptive title for the prompt. If not provided, one will be automatically generated.
"""
prompt: str
title: str = dataclasses.field(default=None)
4 changes: 2 additions & 2 deletions abacusai/api_class/batch_prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class BatchPredictionArgs(ApiClass):
_support_kwargs: bool = dataclasses.field(default=True, repr=False, init=False)

kwargs: dict = dataclasses.field(default_factory=dict)
problem_type: enums.ProblemType = dataclasses.field(default=None)
problem_type: enums.ProblemType = dataclasses.field(default=None, repr=False, init=False)

@classmethod
def _get_builder(cls):
Expand Down Expand Up @@ -223,7 +223,7 @@ def __post_init__(self):
@dataclasses.dataclass
class _BatchPredictionArgsFactory(_ApiClassFactory):
config_abstract_class = BatchPredictionArgs
config_class_key = 'problemType'
config_class_key = 'problem_type'
config_class_map = {
enums.ProblemType.ANOMALY_DETECTION: AnomalyDetectionBatchPredictionArgs,
enums.ProblemType.ANOMALY_OUTLIERS: AnomalyOutliersBatchPredictionArgs,
Expand Down
4 changes: 2 additions & 2 deletions abacusai/api_class/dataset_application_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@dataclasses.dataclass
class DatasetConfig(ApiClass):
application_connector_type: enums.ApplicationConnectorType = dataclasses.field(default=None, repr=False)
application_connector_type: enums.ApplicationConnectorType = dataclasses.field(default=None, repr=False, init=False)

@classmethod
def _get_builder(cls):
Expand Down Expand Up @@ -145,7 +145,7 @@ def __post_init__(self):
@dataclasses.dataclass
class _DatasetConfigFactory(_ApiClassFactory):
config_abstract_class = DatasetConfig
config_class_key = 'applicationConnectorType'
config_class_key = 'application_connector_type'
config_class_map = {
enums.ApplicationConnectorType.CONFLUENCE: ConfluenceDatasetConfig,
enums.ApplicationConnectorType.GOOGLEANALYTICS: GoogleAnalyticsDatasetConfig,
Expand Down
1 change: 1 addition & 0 deletions abacusai/api_class/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class ProblemType(ApiEnum):
OPTIMIZATION = 'optimization'
PRETRAINED_MODELS = 'pretrained'
THEME_ANALYSIS = 'theme_analysis'
TS_ANOMALY = 'ts_anomaly'


class RegressionObjective(ApiEnum):
Expand Down
20 changes: 16 additions & 4 deletions abacusai/api_class/feature_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SamplingConfig(ApiClass):
"""
An abstract class for the sampling config of a feature group
"""
sampling_method: enums.SamplingMethodType = dataclasses.field(default=None, repr=False, init=False)

@classmethod
def _get_builder(cls):
Expand All @@ -32,7 +33,9 @@ class NSamplingConfig(SamplingConfig):
"""
sample_count: int
key_columns: List[str] = dataclasses.field(default_factory=list)
sampling_method: enums.SamplingMethodType = enums.SamplingMethodType.N_SAMPLING

def __post_init__(self):
self.sampling_method = enums.SamplingMethodType.N_SAMPLING


@dataclasses.dataclass
Expand All @@ -47,12 +50,15 @@ class PercentSamplingConfig(SamplingConfig):
"""
sample_percent: float
key_columns: List[str] = dataclasses.field(default_factory=list)
sampling_method: enums.SamplingMethodType = enums.SamplingMethodType.PERCENT_SAMPLING

def __post_init__(self):
self.sampling_method = enums.SamplingMethodType.PERCENT_SAMPLING


@dataclasses.dataclass
class _SamplingConfigFactory(_ApiClassFactory):
config_class_key = 'sampling_method'
config_abstract_class = SamplingConfig
config_class_map = {
enums.SamplingMethodType.N_SAMPLING: NSamplingConfig,
enums.SamplingMethodType.PERCENT_SAMPLING: PercentSamplingConfig,
Expand All @@ -64,6 +70,7 @@ class MergeConfig(ApiClass):
"""
An abstract class for the merge config of a feature group
"""
merge_mode: enums.MergeMode = dataclasses.field(default=None, repr=False, init=False)

@classmethod
def _get_builder(self):
Expand All @@ -84,7 +91,9 @@ class LastNMergeConfig(MergeConfig):
num_versions (int): The number of versions to merge. num_versions == 0 means merge all versions.
"""
num_versions: int
merge_mode: enums.MergeMode = enums.MergeMode.LAST_N

def __post_init__(self):
self.merge_mode = enums.MergeMode.LAST_N


@dataclasses.dataclass
Expand All @@ -99,12 +108,15 @@ class TimeWindowMergeConfig(MergeConfig):
"""
feature_name: str
time_window_size_ms: int
merge_mode: enums.MergeMode = enums.MergeMode.TIME_WINDOW

def __post_init__(self):
self.merge_mode = enums.MergeMode.TIME_WINDOW


@dataclasses.dataclass
class _MergeConfigFactory(_ApiClassFactory):
config_class_key = 'merge_mode'
config_abstract_class = MergeConfig
config_class_map = {
enums.MergeMode.LAST_N: LastNMergeConfig,
enums.MergeMode.TIME_WINDOW: TimeWindowMergeConfig,
Expand Down
24 changes: 23 additions & 1 deletion abacusai/api_class/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ class ChatLLMTrainingConfig(TrainingConfig):
max_search_results (int): Maximum number of search results in the retrieval augmentation step. If we know that the questions are likely to have snippets which are easily matched in the documents, then a lower number will help with accuracy.
data_feature_group_ids: (List[str]): List of feature group ids to use to possibly query for the chatllm.
data_prompt_context (str): Prompt context for the data feature group ids.
hide_generated_sql (bool): When running data queries, hides the generated SQL in the response and will just return the table.
"""
document_retrievers: List[str] = None
num_completion_tokens: int = None
Expand All @@ -456,6 +457,7 @@ class ChatLLMTrainingConfig(TrainingConfig):
max_search_results: int = None
data_feature_group_ids: List[str] = None
data_prompt_context: str = None
hide_generated_sql: bool = None

def __post_init__(self):
self.problem_type = enums.ProblemType.CHAT_LLM
Expand Down Expand Up @@ -612,6 +614,25 @@ def __post_init__(self):
self.problem_type = enums.ProblemType.EVENT_ANOMALY


@dataclasses.dataclass
class TimeseriesAnomalyTrainingConfig(TrainingConfig):
"""
Training config for the TS_ANOMALY problem type
Args:
type_of_split: Type of data splitting into train/test.
test_start (str): Limit training data to dates before the given test start.
test_split (int): Percent of dataset to use for test data. We support using a range between 5 ( i.e. 5% ) to 20 ( i.e. 20% ) of your dataset.
"""
type_of_split: str = dataclasses.field(default=None)
test_start: str = dataclasses.field(default=None)
test_split: int = dataclasses.field(default=None)

def __post_init__(self):
self.problem_type = enums.ProblemType.TS_ANOMALY


@dataclasses.dataclass
class CumulativeForecastingTrainingConfig(TrainingConfig):
"""
Expand Down Expand Up @@ -776,7 +797,8 @@ class _TrainingConfigFactory(_ApiClassFactory):
enums.ProblemType.SENTIMENT_DETECTION: SentimentDetectionTrainingConfig,
enums.ProblemType.THEME_ANALYSIS: ThemeAnalysisTrainingConfig,
enums.ProblemType.CUSTOM_ALGORITHM: CustomAlgorithmTrainingConfig,
enums.ProblemType.OPTIMIZATION: OptimizationTrainingConfig
enums.ProblemType.OPTIMIZATION: OptimizationTrainingConfig,
enums.ProblemType.TS_ANOMALY: TimeseriesAnomalyTrainingConfig,
}


Expand Down
25 changes: 23 additions & 2 deletions abacusai/api_class/monitor_alert.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

@dataclasses.dataclass
class AlertConditionConfig(ApiClass):
alert_type: enums.MonitorAlertType = dataclasses.field(default=None, init=True)
alert_type: enums.MonitorAlertType = dataclasses.field(default=None, repr=False, init=False)

@classmethod
def _get_builder(cls):
Expand Down Expand Up @@ -149,7 +149,7 @@ class _AlertConditionConfigFactory(_ApiClassFactory):

@dataclasses.dataclass
class AlertActionConfig(ApiClass):
action_type: enums.AlertActionType = dataclasses.field(default=None, repr=False, init=True)
action_type: enums.AlertActionType = dataclasses.field(default=None, repr=False, init=False)

@classmethod
def _get_builder(cls):
Expand Down Expand Up @@ -179,3 +179,24 @@ class _AlertActionConfigFactory(_ApiClassFactory):
config_class_map = {
enums.AlertActionType.EMAIL: EmailActionConfig,
}


@dataclasses.dataclass
class MonitorThresholdConfig(ApiClass):
"""
Monitor Threshold Config for Monitor Alerts
Args:
drift_type (FeatureDriftType): Feature drift type to apply the threshold on to determine whether a column has drifted significantly enough to be a violation.
threshold_config (ThresholdConfigs): Thresholds for when to consider a column to be in violation. The alert will only fire when the drift value is strictly greater than the threshold.
"""
drift_type: enums.FeatureDriftType = dataclasses.field(default=None)
at_risk_threshold: float = dataclasses.field(default=None)
severely_drifting_threshold: float = dataclasses.field(default=None)

def to_dict(self):
return {
'drift_type': self.drift_type,
'at_risk_threshold': self.at_risk_threshold,
'severely_drifting_threshold': self.severely_drifting_threshold,
}
11 changes: 8 additions & 3 deletions abacusai/api_class/refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

@dataclasses.dataclass
class FeatureGroupExportConfig(ApiClass):
connector_type: enums.ConnectorType = dataclasses.field(default=None)
connector_type: enums.ConnectorType = dataclasses.field(default=None, repr=False, init=False)

@classmethod
def _get_builder(cls):
Expand All @@ -16,10 +16,12 @@ def _get_builder(cls):

@dataclasses.dataclass
class FileConnectorExportConfig(FeatureGroupExportConfig):
connector_type: enums.ConnectorType = dataclasses.field(default=enums.ConnectorType.FILE, repr=False)
location: str = dataclasses.field(default=None)
export_file_format: str = dataclasses.field(default=None)

def __post_init__(self):
self.connector_type = enums.ConnectorType.FILE

def to_dict(self):
return {
'connector_type': self.connector_type,
Expand All @@ -38,6 +40,9 @@ class DatabaseConnectorExportConfig(FeatureGroupExportConfig):
additional_id_columns: List[str] = dataclasses.field(default=None)
data_columns: Dict[str, str] = dataclasses.field(default=None)

def __post_init__(self):
self.connector_type = enums.ConnectorType.DATABASE

def to_dict(self):
return {
'connector_type': self.connector_type,
Expand All @@ -53,7 +58,7 @@ def to_dict(self):
@dataclasses.dataclass
class _FeatureGroupExportConfigFactory(_ApiClassFactory):
config_abstract_class = FeatureGroupExportConfig
config_class_key = 'connectorType'
config_class_key = 'connector_type'
config_class_map = {
enums.ConnectorType.FILE: FileConnectorExportConfig,
enums.ConnectorType.DATABASE: DatabaseConnectorExportConfig,
Expand Down
12 changes: 7 additions & 5 deletions abacusai/chat_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,22 @@ class ChatMessage(AbstractApiClass):
isUseful (bool): Whether this message was marked as useful or not
feedback (str): The feedback provided for the message
docIds (list): A list of IDs of the uploaded document if the message has
hotkeyTitle (str): The title of the hotkey prompt if the message has one
"""

def __init__(self, client, role=None, text=None, timestamp=None, isUseful=None, feedback=None, docIds=None):
def __init__(self, client, role=None, text=None, timestamp=None, isUseful=None, feedback=None, docIds=None, hotkeyTitle=None):
super().__init__(client, None)
self.role = role
self.text = text
self.timestamp = timestamp
self.is_useful = isUseful
self.feedback = feedback
self.doc_ids = docIds
self.hotkey_title = hotkeyTitle

def __repr__(self):
repr_dict = {f'role': repr(self.role), f'text': repr(self.text), f'timestamp': repr(
self.timestamp), f'is_useful': repr(self.is_useful), f'feedback': repr(self.feedback), f'doc_ids': repr(self.doc_ids)}
repr_dict = {f'role': repr(self.role), f'text': repr(self.text), f'timestamp': repr(self.timestamp), f'is_useful': repr(
self.is_useful), f'feedback': repr(self.feedback), f'doc_ids': repr(self.doc_ids), f'hotkey_title': repr(self.hotkey_title)}
class_name = "ChatMessage"
repr_str = ',\n '.join([f'{key}={value}' for key, value in repr_dict.items(
) if getattr(self, key, None) is not None])
Expand All @@ -39,6 +41,6 @@ def to_dict(self):
Returns:
dict: The dict value representation of the class parameters
"""
resp = {'role': self.role, 'text': self.text, 'timestamp': self.timestamp,
'is_useful': self.is_useful, 'feedback': self.feedback, 'doc_ids': self.doc_ids}
resp = {'role': self.role, 'text': self.text, 'timestamp': self.timestamp, 'is_useful': self.is_useful,
'feedback': self.feedback, 'doc_ids': self.doc_ids, 'hotkey_title': self.hotkey_title}
return {key: value for key, value in resp.items() if value is not None}
Loading

0 comments on commit c411357

Please sign in to comment.