Skip to content

Commit 22ecdab

Browse files
committed
Version 1.4.67
1 parent 2e4c66d commit 22ecdab

336 files changed

Lines changed: 3870 additions & 142 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

abacusai/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from .application_connector import ApplicationConnector
2222
from .audio_gen_settings import AudioGenSettings
2323
from .audio_url_result import AudioUrlResult
24+
from .audit_log import AuditLog
2425
from .batch_prediction import BatchPrediction
2526
from .batch_prediction_version import BatchPredictionVersion
2627
from .batch_prediction_version_logs import BatchPredictionVersionLogs
@@ -83,6 +84,7 @@
8384
from .document_retriever import DocumentRetriever
8485
from .document_retriever_lookup_result import DocumentRetrieverLookupResult
8586
from .document_retriever_version import DocumentRetrieverVersion
87+
from .document_retriever_version_logs import DocumentRetrieverVersionLogs
8688
from .drift_distribution import DriftDistribution
8789
from .drift_distributions import DriftDistributions
8890
from .eda import Eda
@@ -266,6 +268,7 @@
266268
from .use_case_requirements import UseCaseRequirements
267269
from .user import User
268270
from .user_exception import UserException
271+
from .user_group_object_permission import UserGroupObjectPermission
269272
from .video_gen_costs import VideoGenCosts
270273
from .video_gen_model import VideoGenModel
271274
from .video_gen_model_options import VideoGenModelOptions
@@ -282,4 +285,4 @@
282285
from .workflow_node_template import WorkflowNodeTemplate
283286

284287

285-
__version__ = "1.4.66"
288+
__version__ = "1.4.67"

abacusai/api_class/ai_agents.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@
99
MIN_AGENT_SLEEP_TIME = 300
1010

1111

12-
def validate_input_dict_param(dict_object, friendly_class_name, must_contain=[]):
12+
def validate_input_dict_param(dict_object, friendly_class_name, must_contain=[], schema={}):
1313
if not isinstance(dict_object, dict):
1414
raise ValueError(friendly_class_name, 'Invalid argument. Provided argument should be a dictionary.')
1515
if any(field not in dict_object for field in must_contain):
1616
raise ValueError(friendly_class_name, f'One or more keys are missing in the argument provided. Must contain keys - {must_contain}.')
17+
for key, value_type in schema.items():
18+
value = dict_object.get(key)
19+
if value and not isinstance(value, value_type):
20+
raise ValueError(friendly_class_name, f'Invalid parameter "{key}". It should be of type {value_type.__name__}.')
1721

1822

1923
@dataclasses.dataclass
@@ -766,7 +770,7 @@ def to_dict(self):
766770

767771
@classmethod
768772
def from_dict(cls, graph: dict):
769-
validate_input_dict_param(graph, friendly_class_name='workflow_graph')
773+
validate_input_dict_param(graph, friendly_class_name='workflow_graph', schema={'nodes': list, 'edges': list, 'primary_start_node': str, 'common_source_code': str, 'specification_type': str})
770774
if graph.get('__return_filter'):
771775
for node in graph.get('nodes', []):
772776
node['__return_filter'] = True

abacusai/api_class/model.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ class ChatLLMTrainingConfig(TrainingConfig):
486486
data_prompt_column_context (Dict[str, str]): Dict of 'table_name.column_name' and 'column_context' pairs to provide column context for some selected columns in the selected structured data table. This replaces the default auto-generated information about the column data.
487487
hide_sql_and_code (bool): When running data queries, this will hide the generated SQL and Code in the response.
488488
disable_data_summarization (bool): After executing a query summarize the reponse and reply back with only the table and query run.
489+
disable_data_fetch_for_training (bool): Train using only table and column schema metadata without fetching sample data. This speeds up training but may result in less context for the model.
489490
data_columns_to_ignore (List[str]): Columns to ignore while encoding information about structured data tables in context for the LLM. A list of strings of format "<table_name>.<column_name>"
490491
search_score_cutoff (float): Minimum search score to consider a document as a valid search result.
491492
include_bm25_retrieval (bool): Combine BM25 search score with vector search using reciprocal rank fusion.
@@ -525,6 +526,7 @@ class ChatLLMTrainingConfig(TrainingConfig):
525526
data_prompt_column_context: Dict[str, str] = dataclasses.field(default=None)
526527
hide_sql_and_code: bool = dataclasses.field(default=None)
527528
disable_data_summarization: bool = dataclasses.field(default=None)
529+
disable_data_fetch_for_training: bool = dataclasses.field(default=None)
528530
data_columns_to_ignore: List[str] = dataclasses.field(default=None)
529531
search_score_cutoff: float = dataclasses.field(default=None)
530532
include_bm25_retrieval: bool = dataclasses.field(default=None)

abacusai/api_endpoint.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ class ApiEndpoint(AbstractApiClass):
1414
externalChatEndpoint (str): The URI that can be used to access the external chat
1515
dashboardEndpoint (str): The URI that the external chat will use to go back to the dashboard
1616
hostingDomain (str): The domain for hosted app deployments
17+
publicHostingDomain (str): The domain for publicly hosted app deployments
1718
"""
1819

19-
def __init__(self, client, apiEndpoint=None, predictEndpoint=None, proxyEndpoint=None, llmEndpoint=None, externalChatEndpoint=None, dashboardEndpoint=None, hostingDomain=None):
20+
def __init__(self, client, apiEndpoint=None, predictEndpoint=None, proxyEndpoint=None, llmEndpoint=None, externalChatEndpoint=None, dashboardEndpoint=None, hostingDomain=None, publicHostingDomain=None):
2021
super().__init__(client, None)
2122
self.api_endpoint = apiEndpoint
2223
self.predict_endpoint = predictEndpoint
@@ -25,11 +26,12 @@ def __init__(self, client, apiEndpoint=None, predictEndpoint=None, proxyEndpoint
2526
self.external_chat_endpoint = externalChatEndpoint
2627
self.dashboard_endpoint = dashboardEndpoint
2728
self.hosting_domain = hostingDomain
29+
self.public_hosting_domain = publicHostingDomain
2830
self.deprecated_keys = {}
2931

3032
def __repr__(self):
31-
repr_dict = {f'api_endpoint': repr(self.api_endpoint), f'predict_endpoint': repr(self.predict_endpoint), f'proxy_endpoint': repr(self.proxy_endpoint), f'llm_endpoint': repr(
32-
self.llm_endpoint), f'external_chat_endpoint': repr(self.external_chat_endpoint), f'dashboard_endpoint': repr(self.dashboard_endpoint), f'hosting_domain': repr(self.hosting_domain)}
33+
repr_dict = {f'api_endpoint': repr(self.api_endpoint), f'predict_endpoint': repr(self.predict_endpoint), f'proxy_endpoint': repr(self.proxy_endpoint), f'llm_endpoint': repr(self.llm_endpoint), f'external_chat_endpoint': repr(
34+
self.external_chat_endpoint), f'dashboard_endpoint': repr(self.dashboard_endpoint), f'hosting_domain': repr(self.hosting_domain), f'public_hosting_domain': repr(self.public_hosting_domain)}
3335
class_name = "ApiEndpoint"
3436
repr_str = ',\n '.join([f'{key}={value}' for key, value in repr_dict.items(
3537
) if getattr(self, key, None) is not None and key not in self.deprecated_keys])
@@ -43,5 +45,5 @@ def to_dict(self):
4345
dict: The dict value representation of the class parameters
4446
"""
4547
resp = {'api_endpoint': self.api_endpoint, 'predict_endpoint': self.predict_endpoint, 'proxy_endpoint': self.proxy_endpoint, 'llm_endpoint': self.llm_endpoint,
46-
'external_chat_endpoint': self.external_chat_endpoint, 'dashboard_endpoint': self.dashboard_endpoint, 'hosting_domain': self.hosting_domain}
48+
'external_chat_endpoint': self.external_chat_endpoint, 'dashboard_endpoint': self.dashboard_endpoint, 'hosting_domain': self.hosting_domain, 'public_hosting_domain': self.public_hosting_domain}
4749
return {key: value for key, value in resp.items() if value is not None and key not in self.deprecated_keys}

abacusai/audit_log.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from .return_class import AbstractApiClass
2+
3+
4+
class AuditLog(AbstractApiClass):
5+
"""
6+
An audit log entry
7+
8+
Args:
9+
client (ApiClient): An authenticated API Client instance
10+
createdAt (str): The timestamp when the audit log entry was created
11+
userId (str): The hashed ID of the user who performed the action
12+
objectId (str): The hashed ID of the object that was affected by the action
13+
action (str): The action performed (create, modify, start, stop, delete, share, hide, credential_change, login)
14+
source (str): The source of the action (api, ui, pipeline, cli, system)
15+
refreshPolicyId (str): The hashed ID of the refresh policy if applicable
16+
pipelineId (str): The hashed ID of the pipeline if applicable
17+
"""
18+
19+
def __init__(self, client, createdAt=None, userId=None, objectId=None, action=None, source=None, refreshPolicyId=None, pipelineId=None):
20+
super().__init__(client, None)
21+
self.created_at = createdAt
22+
self.user_id = userId
23+
self.object_id = objectId
24+
self.action = action
25+
self.source = source
26+
self.refresh_policy_id = refreshPolicyId
27+
self.pipeline_id = pipelineId
28+
self.deprecated_keys = {}
29+
30+
def __repr__(self):
31+
repr_dict = {f'created_at': repr(self.created_at), f'user_id': repr(self.user_id), f'object_id': repr(self.object_id), f'action': repr(
32+
self.action), f'source': repr(self.source), f'refresh_policy_id': repr(self.refresh_policy_id), f'pipeline_id': repr(self.pipeline_id)}
33+
class_name = "AuditLog"
34+
repr_str = ',\n '.join([f'{key}={value}' for key, value in repr_dict.items(
35+
) if getattr(self, key, None) is not None and key not in self.deprecated_keys])
36+
return f"{class_name}({repr_str})"
37+
38+
def to_dict(self):
39+
"""
40+
Get a dict representation of the parameters in this class
41+
42+
Returns:
43+
dict: The dict value representation of the class parameters
44+
"""
45+
resp = {'created_at': self.created_at, 'user_id': self.user_id, 'object_id': self.object_id, 'action': self.action,
46+
'source': self.source, 'refresh_policy_id': self.refresh_policy_id, 'pipeline_id': self.pipeline_id}
47+
return {key: value for key, value in resp.items() if value is not None and key not in self.deprecated_keys}

abacusai/client.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@
180180
from .use_case import UseCase
181181
from .use_case_requirements import UseCaseRequirements
182182
from .user import User
183+
from .user_group_object_permission import UserGroupObjectPermission
183184
from .web_page_response import WebPageResponse
184185
from .web_search_response import WebSearchResponse
185186
from .webhook import Webhook
@@ -218,17 +219,20 @@ async def sse_asynchronous_generator(endpoint: str, headers: dict, body: dict):
218219
async with aiohttp.request('POST', endpoint, json=body, headers=headers, timeout=aiohttp.ClientTimeout(total=0)) as response:
219220
async for line in response.content:
220221
if line:
221-
streamed_responses = line.decode('utf-8').split('\n\n')
222+
streamed_responses = line.decode('utf-8').split('\n')
222223
for resp in streamed_responses:
223224
if resp:
224225
resp = resp.strip()
225226
if resp:
226-
resp = json.loads(resp)
227-
resp = {snake_case(
228-
key): value for key, value in resp.items()}
229-
if 'ping' in resp:
230-
continue
231-
yield resp
227+
try:
228+
resp = json.loads(resp)
229+
resp = {snake_case(
230+
key): value for key, value in resp.items()}
231+
if 'ping' in resp:
232+
continue
233+
yield resp
234+
except Exception:
235+
pass
232236

233237

234238
def _requests_retry_session(retries=5, backoff_factor=0.1, status_forcelist=(502, 503, 504), session=None, retry_500: bool = False):
@@ -663,7 +667,7 @@ class BaseApiClient:
663667
client_options (ClientOptions): Optional API client configurations
664668
skip_version_check (bool): If true, will skip checking the server's current API version on initializing the client
665669
"""
666-
client_version = '1.4.66'
670+
client_version = '1.4.67'
667671

668672
def __init__(self, api_key: str = None, server: str = None, client_options: ClientOptions = None, skip_version_check: bool = False, include_tb: bool = False):
669673
self.api_key = api_key
@@ -2777,6 +2781,14 @@ def get_deployment_conversation(self, deployment_conversation_id: str = None, ex
27772781
DeploymentConversation: The deployment conversation."""
27782782
return self._proxy_request('getDeploymentConversation', 'GET', query_params={'deploymentConversationId': deployment_conversation_id, 'externalSessionId': external_session_id, 'deploymentId': deployment_id, 'filterIntermediateConversationEvents': filter_intermediate_conversation_events, 'getUnusedDocumentUploads': get_unused_document_uploads, 'start': start, 'limit': limit, 'includeAllVersions': include_all_versions}, parse_type=DeploymentConversation, is_sync=True)
27792783

2784+
def get_deployment_conversation_file(self, deployment_conversation_id: str, file_path: str) -> io.BytesIO:
2785+
"""Gets a deployment conversation file.
2786+
2787+
Args:
2788+
deployment_conversation_id (str): Unique ID of the conversation.
2789+
file_path (str): The path of the file to get."""
2790+
return self._proxy_request('getDeploymentConversationFile', 'GET', query_params={'deploymentConversationId': deployment_conversation_id, 'filePath': file_path}, is_sync=True, streamable_response=True)
2791+
27802792
def list_deployment_conversations(self, deployment_id: str = None, external_application_id: str = None, conversation_type: Union[DeploymentConversationType, str] = None, fetch_last_llm_info: bool = False, limit: int = None, search: str = None) -> List[DeploymentConversation]:
27812793
"""Lists all conversations for the given deployment and current user.
27822794

@@ -2803,6 +2815,16 @@ def export_deployment_conversation(self, deployment_conversation_id: str = None,
28032815
DeploymentConversationExport: The deployment conversation html export."""
28042816
return self._proxy_request('exportDeploymentConversation', 'GET', query_params={'deploymentConversationId': deployment_conversation_id, 'externalSessionId': external_session_id}, parse_type=DeploymentConversationExport, is_sync=True)
28052817

2818+
def list_user_group_object_permissions(self) -> List[UserGroupObjectPermission]:
2819+
"""List all user groups permissions associated with the objects in the organization.
2820+
2821+
If no associated user groups, the object is public among developers and admins.
2822+
2823+
2824+
Returns:
2825+
list[UserGroupObjectPermission]: List of user group object permissions in the organization."""
2826+
return self._call_api('listUserGroupObjectPermissions', 'GET', query_params={}, parse_type=UserGroupObjectPermission)
2827+
28062828
def get_app_user_group(self, user_group_id: str) -> AppUserGroup:
28072829
"""Gets an App User Group.
28082830

@@ -7691,6 +7713,14 @@ def get_conversation_response_with_binary_data(self, deployment_id: str, deploym
76917713
deployment_id, deployment_token) if deployment_token else None
76927714
return self._call_api('getConversationResponseWithBinaryData', 'POST', query_params={'deploymentId': deployment_id, 'deploymentToken': deployment_token}, data={'message': json.dumps(message) if (message is not None and not isinstance(message, str)) else message, 'deploymentConversationId': json.dumps(deployment_conversation_id) if (deployment_conversation_id is not None and not isinstance(deployment_conversation_id, str)) else deployment_conversation_id, 'externalSessionId': json.dumps(external_session_id) if (external_session_id is not None and not isinstance(external_session_id, str)) else external_session_id, 'llmName': json.dumps(llm_name) if (llm_name is not None and not isinstance(llm_name, str)) else llm_name, 'numCompletionTokens': json.dumps(num_completion_tokens) if (num_completion_tokens is not None and not isinstance(num_completion_tokens, str)) else num_completion_tokens, 'systemMessage': json.dumps(system_message) if (system_message is not None and not isinstance(system_message, str)) else system_message, 'temperature': json.dumps(temperature) if (temperature is not None and not isinstance(temperature, str)) else temperature, 'filterKeyValues': json.dumps(filter_key_values) if (filter_key_values is not None and not isinstance(filter_key_values, str)) else filter_key_values, 'searchScoreCutoff': json.dumps(search_score_cutoff) if (search_score_cutoff is not None and not isinstance(search_score_cutoff, str)) else search_score_cutoff, 'chatConfig': json.dumps(chat_config) if (chat_config is not None and not isinstance(chat_config, str)) else chat_config}, files=attachments, server_override=prediction_url)
76937715

7716+
def get_deep_agent_response(self, message: str, deployment_conversation_id: str = None) -> Dict:
7717+
"""Return a DeepAgent response with generated files if any, based on the input message.
7718+
7719+
Args:
7720+
message (str): The user's message/task for DeepAgent to complete
7721+
deployment_conversation_id (str): The unique identifier of a deployment conversation to continue. If not specified, a new one will be created."""
7722+
return self._proxy_request('getDeepAgentResponse', 'POST', query_params={}, body={'message': message, 'deploymentConversationId': deployment_conversation_id}, is_sync=True)
7723+
76947724
def get_search_results(self, deployment_token: str, deployment_id: str, query_data: dict, num: int = 15) -> Dict:
76957725
"""Return the most relevant search results to the search query from the uploaded documents.
76967726

abacusai/deployment_conversation.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ def get(self, external_session_id: str = None, deployment_id: str = None, filter
118118
"""
119119
return self.client.get_deployment_conversation(self.deployment_conversation_id, external_session_id, deployment_id, filter_intermediate_conversation_events, get_unused_document_uploads, start, limit, include_all_versions)
120120

121+
def get_file(self, file_path: str):
122+
"""
123+
Gets a deployment conversation file.
124+
125+
Args:
126+
file_path (str): The path of the file to get.
127+
"""
128+
return self.client.get_deployment_conversation_file(self.deployment_conversation_id, file_path)
129+
121130
def delete(self, deployment_id: str = None):
122131
"""
123132
Delete a Deployment Conversation.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from .return_class import AbstractApiClass
2+
3+
4+
class DocumentRetrieverVersionLogs(AbstractApiClass):
5+
"""
6+
Logs from document retriever version.
7+
8+
Args:
9+
client (ApiClient): An authenticated API Client instance
10+
logs (list[str]): List of logs from document retriever version.
11+
"""
12+
13+
def __init__(self, client, logs=None):
14+
super().__init__(client, None)
15+
self.logs = logs
16+
self.deprecated_keys = {}
17+
18+
def __repr__(self):
19+
repr_dict = {f'logs': repr(self.logs)}
20+
class_name = "DocumentRetrieverVersionLogs"
21+
repr_str = ',\n '.join([f'{key}={value}' for key, value in repr_dict.items(
22+
) if getattr(self, key, None) is not None and key not in self.deprecated_keys])
23+
return f"{class_name}({repr_str})"
24+
25+
def to_dict(self):
26+
"""
27+
Get a dict representation of the parameters in this class
28+
29+
Returns:
30+
dict: The dict value representation of the class parameters
31+
"""
32+
resp = {'logs': self.logs}
33+
return {key: value for key, value in resp.items() if value is not None and key not in self.deprecated_keys}

0 commit comments

Comments
 (0)