Skip to content

Commit 01dce72

Browse files
committed
Version 1.4.30
1 parent d3d6087 commit 01dce72

304 files changed

Lines changed: 4733 additions & 819 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: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
from .chat_session import ChatSession
3030
from .chatllm_computer import ChatllmComputer
3131
from .chatllm_referral_invite import ChatllmReferralInvite
32+
from .chatllm_task import ChatllmTask
3233
from .client import AgentResponse, ApiClient, ApiException, ClientOptions, ReadOnlyClient, _request_context
34+
from .code_agent_response import CodeAgentResponse
3335
from .code_autocomplete_response import CodeAutocompleteResponse
3436
from .code_bot import CodeBot
3537
from .code_edit import CodeEdit
@@ -119,6 +121,7 @@
119121
from .holdout_analysis import HoldoutAnalysis
120122
from .holdout_analysis_version import HoldoutAnalysisVersion
121123
from .hosted_model_token import HostedModelToken
124+
from .hume_voice import HumeVoice
122125
from .image_gen_settings import ImageGenSettings
123126
from .indexing_config import IndexingConfig
124127
from .inferred_database_column_to_feature_mappings import InferredDatabaseColumnToFeatureMappings
@@ -224,6 +227,7 @@
224227
from .user_exception import UserException
225228
from .video_gen_settings import VideoGenSettings
226229
from .video_search_result import VideoSearchResult
230+
from .voice_gen_details import VoiceGenDetails
227231
from .web_page_response import WebPageResponse
228232
from .web_search_response import WebSearchResponse
229233
from .web_search_result import WebSearchResult
@@ -232,4 +236,4 @@
232236
from .workflow_node_template import WorkflowNodeTemplate
233237

234238

235-
__version__ = "1.4.28"
239+
__version__ = "1.4.30"

abacusai/agent.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ def list_versions(self, limit: int = 100, start_after_version: str = None):
102102
"""
103103
return self.client.list_agent_versions(self.agent_id, limit, start_after_version)
104104

105+
def copy(self, project_id: str = None):
106+
"""
107+
Creates a copy of the input agent
108+
109+
Args:
110+
project_id (str): Project id to create the new agent to. By default it picks up the source agent's project id.
111+
112+
Returns:
113+
Agent: The newly generated agent.
114+
"""
115+
return self.client.copy_agent(self.agent_id, project_id)
116+
105117
@property
106118
def description(self) -> str:
107119
"""

abacusai/api_class/ai_agents.py

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -594,27 +594,33 @@ class WorkflowGraph(ApiClass):
594594
nodes (List[WorkflowGraphNode]): A list of nodes in the workflow graph.
595595
edges (List[WorkflowGraphEdge]): A list of edges in the workflow graph, where each edge is a tuple of source, target, and details.
596596
primary_start_node (Union[str, WorkflowGraphNode]): The primary node to start the workflow from.
597+
common_source_code (str): Common source code that can be used across all nodes.
597598
"""
598599
nodes: List[WorkflowGraphNode] = dataclasses.field(default_factory=list)
599600
edges: List[Union[WorkflowGraphEdge, Tuple[WorkflowGraphNode, WorkflowGraphNode, dict], Tuple[str, str, dict]]] = dataclasses.field(default_factory=list)
600601
primary_start_node: Union[str, WorkflowGraphNode] = dataclasses.field(default=None)
601602
common_source_code: str = dataclasses.field(default=None)
603+
specification_type: str = dataclasses.field(default='data_flow')
602604

603605
def __post_init__(self):
604606
if self.edges:
605-
for index, edge in enumerate(self.edges):
606-
if isinstance(edge, Tuple):
607-
source = edge[0] if isinstance(edge[0], str) else edge[0].name
608-
target = edge[1] if isinstance(edge[1], str) else edge[1].name
609-
details = edge[2] if len(edge) > 2 and isinstance(edge[2], dict) else None
610-
self.edges[index] = WorkflowGraphEdge(source=source, target=target, details=details)
607+
if self.specification_type == 'execution_flow':
608+
for index, edge in enumerate(self.edges):
609+
if isinstance(edge, Tuple):
610+
source = edge[0] if isinstance(edge[0], str) else edge[0].name
611+
target = edge[1] if isinstance(edge[1], str) else edge[1].name
612+
details = edge[2] if len(edge) > 2 and isinstance(edge[2], dict) else None
613+
self.edges[index] = WorkflowGraphEdge(source=source, target=target, details=details)
614+
else:
615+
raise ValueError('workflow_graph', 'Workflow Graph no longer supports explicit edges. They are inferred from data flow dependencies.')
611616

612617
def to_dict(self):
613618
return {
614619
'nodes': [node.to_dict() for node in self.nodes],
615-
'edges': [edge.to_dict() for edge in self.edges],
620+
**({'edges': [edge.to_dict() for edge in self.edges]} if self.specification_type == 'execution_flow' else {}),
616621
'primary_start_node': self.primary_start_node.name if isinstance(self.primary_start_node, WorkflowGraphNode) else self.primary_start_node,
617-
'common_source_code': self.common_source_code
622+
'common_source_code': self.common_source_code,
623+
'specification_type': self.specification_type
618624
}
619625

620626
@classmethod
@@ -625,19 +631,45 @@ def from_dict(cls, graph: dict):
625631
node['__return_filter'] = True
626632
nodes = [WorkflowGraphNode.from_dict(node) for node in graph.get('nodes', [])]
627633
edges = [WorkflowGraphEdge.from_dict(edge) for edge in graph.get('edges', [])]
628-
if graph.get('primary_start_node') not in [node.name for node in nodes]:
629-
non_primary_nodes = set()
630-
for edge in edges:
631-
non_primary_nodes.add(edge.target)
632-
primary_nodes = set([node.name for node in nodes]) - non_primary_nodes
633-
graph['primary_start_node'] = primary_nodes.pop() if primary_nodes else None
634+
primary_start_node = graph.get('primary_start_node')
635+
non_primary_nodes = set()
636+
specification_type = graph.get('specification_type', 'execution_flow')
634637

635-
return cls(
636-
nodes=nodes,
637-
edges=edges,
638-
primary_start_node=graph.get('primary_start_node', None),
639-
common_source_code=graph.get('common_source_code', None)
640-
)
638+
if specification_type == 'execution_flow':
639+
if primary_start_node not in [node.name for node in nodes]:
640+
for edge in edges:
641+
non_primary_nodes.add(edge.target)
642+
primary_nodes = set([node.name for node in nodes]) - non_primary_nodes
643+
graph['primary_start_node'] = primary_nodes.pop() if primary_nodes else None
644+
645+
return cls(
646+
nodes=nodes,
647+
edges=edges,
648+
primary_start_node=graph.get('primary_start_node', None),
649+
common_source_code=graph.get('common_source_code', None),
650+
specification_type='execution_flow'
651+
)
652+
else:
653+
if edges:
654+
raise ValueError('workflow_graph', 'Workflow Graph no longer supports explicit edges. They are inferred from data flow dependencies.')
655+
656+
if primary_start_node not in [node.name for node in nodes]:
657+
for node in nodes:
658+
is_primary_eligible = True
659+
for mapping in node.input_mappings:
660+
if mapping.variable_type == enums.WorkflowNodeInputType.WORKFLOW_VARIABLE:
661+
is_primary_eligible = False
662+
break
663+
if not is_primary_eligible:
664+
non_primary_nodes.add(node.name)
665+
primary_nodes = set([node.name for node in nodes]) - non_primary_nodes
666+
primary_start_node = primary_nodes.pop() if primary_nodes else None
667+
return cls(
668+
nodes=nodes,
669+
primary_start_node=primary_start_node,
670+
common_source_code=graph.get('common_source_code', None),
671+
specification_type='data_flow'
672+
)
641673

642674

643675
@dataclasses.dataclass

abacusai/api_class/enums.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ class LLMName(ApiEnum):
470470
OPENAI_GPT4_128K_LATEST = 'OPENAI_GPT4_128K_LATEST'
471471
OPENAI_GPT4O = 'OPENAI_GPT4O'
472472
OPENAI_GPT4O_MINI = 'OPENAI_GPT4O_MINI'
473+
OPENAI_O1_MINI = 'OPENAI_O1_MINI'
473474
OPENAI_GPT3_5 = 'OPENAI_GPT3_5'
474475
OPENAI_GPT3_5_TEXT = 'OPENAI_GPT3_5_TEXT'
475476
LLAMA3_1_405B = 'LLAMA3_1_405B'
@@ -485,6 +486,7 @@ class LLMName(ApiEnum):
485486
GEMINI_1_5_PRO = 'GEMINI_1_5_PRO'
486487
GEMINI_2_FLASH = 'GEMINI_2_FLASH'
487488
GEMINI_2_FLASH_THINKING = 'GEMINI_2_FLASH_THINKING'
489+
GEMINI_2_PRO = 'GEMINI_2_PRO'
488490
ABACUS_SMAUG3 = 'ABACUS_SMAUG3'
489491
ABACUS_DRACARYS = 'ABACUS_DRACARYS'
490492
QWEN_2_5_32B = 'QWEN_2_5_32B'

abacusai/api_class/segments.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import dataclasses
2+
import uuid
23
from typing import Any, List
34

45
from . import enums
@@ -18,8 +19,11 @@ class ResponseSection(ApiClass):
1819
type: enums.ResponseSectionType
1920
id: str
2021

22+
def __post_init__(self):
23+
self.message_id = str(uuid.uuid4())
24+
2125
def to_dict(self):
22-
return {k: v.value if isinstance(v, enums.Enum) else v for k, v in dataclasses.asdict(self).items()}
26+
return {**{k: v.value if isinstance(v, enums.Enum) else v for k, v in dataclasses.asdict(self).items() if not k.startswith('_')}, 'message_id': self.message_id}
2327

2428

2529
Segment = ResponseSection

abacusai/api_client_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44
import re
55
import string
6+
import uuid
67
from enum import Enum
78
from itertools import groupby
89
from typing import IO, Callable, List
@@ -104,7 +105,7 @@ def process_streaming_data(cls, value, context, section_key, data_type, is_trans
104105
break
105106
if not entry_exists:
106107
context.streamed_section_response.append(
107-
{'id': section_key, 'type': data_type, 'mime_type': 'text/plain', 'contents': value})
108+
{'id': section_key, 'type': data_type, 'mime_type': 'text/plain', 'contents': value, 'message_id': str(uuid.uuid4())})
108109
else:
109110
context.streamed_response.append(str(value))
110111
elif data_type == 'segment':

abacusai/api_key.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class ApiKey(AbstractApiClass):
1111
apiKey (str): The unique API key scoped to a specific organization. Value will be partially obscured.
1212
apiKeySuffix (str): The last 4 characters of the API key.
1313
tag (str): A user-friendly tag for the API key.
14-
type (str): The type of the API key, either 'default' or 'code-llm'.
14+
type (str): The type of the API key, either 'default', 'code-llm', or 'computer-use'.
1515
createdAt (str): The timestamp when the API key was created.
1616
expiresAt (str): The timestamp when the API key will expire.
1717
isExpired (bool): Whether the API key has expired.

abacusai/batch_prediction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def __init__(self, client, batchPredictionId=None, createdAt=None, name=None, de
8484
BatchPredictionArgs, globalPredictionArgs)
8585
self.batch_prediction_args = client._build_class(getattr(
8686
api_class, batchPredictionArgsType, BatchPredictionArgs) if batchPredictionArgsType else BatchPredictionArgs, batchPredictionArgs)
87-
self.deprecated_keys = {'global_prediction_args', 'explanations'}
87+
self.deprecated_keys = {'explanations', 'global_prediction_args'}
8888

8989
def __repr__(self):
9090
repr_dict = {f'batch_prediction_id': repr(self.batch_prediction_id), f'created_at': repr(self.created_at), f'name': repr(self.name), f'deployment_id': repr(self.deployment_id), f'file_connector_output_location': repr(self.file_connector_output_location), f'database_connector_id': repr(self.database_connector_id), f'database_output_configuration': repr(self.database_output_configuration), f'file_output_format': repr(self.file_output_format), f'connector_type': repr(self.connector_type), f'legacy_input_location': repr(self.legacy_input_location), f'output_feature_group_id': repr(self.output_feature_group_id), f'feature_group_table_name': repr(self.feature_group_table_name), f'output_feature_group_table_name': repr(self.output_feature_group_table_name), f'summary_feature_group_table_name': repr(self.summary_feature_group_table_name), f'csv_input_prefix': repr(

abacusai/batch_prediction_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def __init__(self, client, batchPredictionVersion=None, batchPredictionId=None,
100100
BatchPredictionArgs, globalPredictionArgs)
101101
self.batch_prediction_args = client._build_class(getattr(
102102
api_class, batchPredictionArgsType, BatchPredictionArgs) if batchPredictionArgsType else BatchPredictionArgs, batchPredictionArgs)
103-
self.deprecated_keys = {'global_prediction_args', 'explanations'}
103+
self.deprecated_keys = {'explanations', 'global_prediction_args'}
104104

105105
def __repr__(self):
106106
repr_dict = {f'batch_prediction_version': repr(self.batch_prediction_version), f'batch_prediction_id': repr(self.batch_prediction_id), f'status': repr(self.status), f'drift_monitor_status': repr(self.drift_monitor_status), f'deployment_id': repr(self.deployment_id), f'model_id': repr(self.model_id), f'model_version': repr(self.model_version), f'predictions_started_at': repr(self.predictions_started_at), f'predictions_completed_at': repr(self.predictions_completed_at), f'database_output_error': repr(self.database_output_error), f'total_predictions': repr(self.total_predictions), f'failed_predictions': repr(self.failed_predictions), f'database_connector_id': repr(self.database_connector_id), f'database_output_configuration': repr(self.database_output_configuration), f'file_connector_output_location': repr(self.file_connector_output_location), f'file_output_format': repr(self.file_output_format), f'connector_type': repr(self.connector_type), f'legacy_input_location': repr(self.legacy_input_location), f'error': repr(self.error), f'drift_monitor_error': repr(self.drift_monitor_error), f'monitor_warnings': repr(self.monitor_warnings), f'csv_input_prefix': repr(

abacusai/chatllm_task.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from .return_class import AbstractApiClass
2+
3+
4+
class ChatllmTask(AbstractApiClass):
5+
"""
6+
A chatllm task
7+
8+
Args:
9+
client (ApiClient): An authenticated API Client instance
10+
chatllmTaskId (str): The id of the chatllm task.
11+
name (str): The name of the chatllm task.
12+
instructions (str): The instructions of the chatllm task.
13+
lifecycle (str): The lifecycle of the chatllm task.
14+
scheduleInfo (dict): The schedule info of the chatllm task.
15+
externalApplicationId (str): The external application id associated with the chatllm task.
16+
deploymentConversationId (str): The deployment conversation id associated with the chatllm task.
17+
enableEmailAlerts (bool): Whether email alerts are enabled for the chatllm task.
18+
email (str): The email to send alerts to.
19+
"""
20+
21+
def __init__(self, client, chatllmTaskId=None, name=None, instructions=None, lifecycle=None, scheduleInfo=None, externalApplicationId=None, deploymentConversationId=None, enableEmailAlerts=None, email=None):
22+
super().__init__(client, chatllmTaskId)
23+
self.chatllm_task_id = chatllmTaskId
24+
self.name = name
25+
self.instructions = instructions
26+
self.lifecycle = lifecycle
27+
self.schedule_info = scheduleInfo
28+
self.external_application_id = externalApplicationId
29+
self.deployment_conversation_id = deploymentConversationId
30+
self.enable_email_alerts = enableEmailAlerts
31+
self.email = email
32+
self.deprecated_keys = {}
33+
34+
def __repr__(self):
35+
repr_dict = {f'chatllm_task_id': repr(self.chatllm_task_id), f'name': repr(self.name), f'instructions': repr(self.instructions), f'lifecycle': repr(self.lifecycle), f'schedule_info': repr(
36+
self.schedule_info), f'external_application_id': repr(self.external_application_id), f'deployment_conversation_id': repr(self.deployment_conversation_id), f'enable_email_alerts': repr(self.enable_email_alerts), f'email': repr(self.email)}
37+
class_name = "ChatllmTask"
38+
repr_str = ',\n '.join([f'{key}={value}' for key, value in repr_dict.items(
39+
) if getattr(self, key, None) is not None and key not in self.deprecated_keys])
40+
return f"{class_name}({repr_str})"
41+
42+
def to_dict(self):
43+
"""
44+
Get a dict representation of the parameters in this class
45+
46+
Returns:
47+
dict: The dict value representation of the class parameters
48+
"""
49+
resp = {'chatllm_task_id': self.chatllm_task_id, 'name': self.name, 'instructions': self.instructions, 'lifecycle': self.lifecycle, 'schedule_info': self.schedule_info,
50+
'external_application_id': self.external_application_id, 'deployment_conversation_id': self.deployment_conversation_id, 'enable_email_alerts': self.enable_email_alerts, 'email': self.email}
51+
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)