Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
92aad6a
Merge to prod (#530)
ikxplain May 19, 2025
056482e
merge to test (#553)
hadi-aix Jun 18, 2025
f1f3d29
removed cache pipeline test
Jun 19, 2025
f6232da
merge to test (#557)
hadi-aix Jun 19, 2025
41d3f23
Development (#562)
hadi-aix Jun 20, 2025
6540afe
Add HF_TOKEN to github workflow (#563)
lucas-aixplain Jun 20, 2025
a0e184f
Trigger functional tests
hadi-aix Jun 22, 2025
6678ab1
Merge branch 'test'
hadi-aix Jun 24, 2025
892a803
Hotfix: removed extra indent (#566)
shreyasXplain Jun 24, 2025
e24fe9c
fixing the tests (#568)
Muhammad-Elmallah Jun 25, 2025
7ec42e8
updated requirements and documentation (#572)
ahmetgunduz Jun 27, 2025
d1fd676
Update pyproject.toml (#573)
ahmetgunduz Jun 27, 2025
69b9c29
Update pyproject.toml (#574)
ahmetgunduz Jun 27, 2025
1c2dd59
Update README.md (#576)
ahmetgunduz Jun 27, 2025
5ece05b
Merge to test (#580)
hadi-aix Jul 7, 2025
30f21f3
Merge to test (#584)
hadi-aix Jul 14, 2025
8cbcd00
Development (#586)
hadi-aix Jul 15, 2025
f58b009
Development (#588)
hadi-aix Jul 15, 2025
fb1359e
push to production (#591)
hadi-aix Jul 17, 2025
fef8f28
Development (#593)
hadi-aix Jul 17, 2025
350c7e4
Development (#595)
hadi-aix Jul 17, 2025
cfd25b1
Merge branch 'main' into test
hadi-aix Jul 17, 2025
cbb1962
Resolve merge conflicts by accepting current changes
ahmetgunduz Aug 15, 2025
2e1be99
Custom inspector policy (#620)
yunsukim86 Aug 15, 2025
5f25c3f
Merge branch 'development' of https://github.com/aixplain/aiXplain in…
ahmetgunduz Aug 18, 2025
6ff939a
non_existent_llm error fix
ahmetgunduz Aug 19, 2025
f004944
mentalist initialization fix
ahmetgunduz Aug 19, 2025
3261d6c
adde claude model instead of yi-large for search test with model ids
ahmetgunduz Aug 19, 2025
b7c9032
remove unnecessary model tests (#634)
hadi-aix Aug 20, 2025
ed66573
Update utils.py (#612)
hadi-aix Aug 20, 2025
0146a9a
Mark inspector as private beta (#636)
yunsukim86 Aug 21, 2025
4efabbb
ENG-2411 Replaced AgentTask with WorkflowTask while keeping the backw…
ahmetgunduz Aug 22, 2025
8b67b64
PROD-1840: Evolver v2 (#454)
thiago-aixplain Aug 26, 2025
314284d
Update agent_task.py
ahmetgunduz Aug 26, 2025
d5c9b34
added pagination t get model by ids
ahmetgunduz Aug 27, 2025
5717ad6
added pagination t get model by ids
ahmetgunduz Aug 27, 2025
7b69b4b
Eng 2281 Add file parsing for Index (#551)
basitanees Aug 28, 2025
7ccccd5
HOTFIX: remove model deletion for index tests (#645)
basitanees Aug 28, 2025
c13838f
add utility model support and add test (#642)
basitanees Aug 28, 2025
66e0f1c
updated code parse undecorated (#647)
ahmetgunduz Aug 28, 2025
a38ace1
ENG-2501 evolver params renaming (#649)
ahmetgunduz Aug 31, 2025
86284f3
ENG-2501-Evolver-Resolve-given-comments-for-standardization (#650)
ahmetgunduz Aug 31, 2025
e5a22fc
ENG-2501-Evolver-Resolve-given-comments-for-standardization (#651)
ahmetgunduz Sep 1, 2025
3f982bc
added supported tools for failure cases (#652)
ahmetgunduz Sep 1, 2025
7a520ea
fix tasks duplication in create team from yaml (#653)
ahmetgunduz Sep 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,26 @@ repos:
pass_filenames: false
types: [python]
always_run: true

- repo: https://github.com/psf/black
rev: 22.10.0
rev: 25.1.0
hooks:
- id: black
language_version: python3
args: # arguments to configure black
- --line-length=128

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.0.0 # Use the latest version
rev: v5.0.0 # Use the latest version
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
- id: check-added-large-files

- repo: https://github.com/pycqa/flake8
rev: 7.2.0
hooks:
- id: flake8
args: # arguments to configure flake8
- --ignore=E402,E501,E203,W503
- --ignore=E402,E501,E203,W503
1 change: 1 addition & 0 deletions aixplain/enums/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
from .asset_status import AssetStatus
from .index_stores import IndexStores
from .function_type import FunctionType
from .evolve_type import EvolveType
from .code_interpreter import CodeInterpreterModel
6 changes: 6 additions & 0 deletions aixplain/enums/evolve_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from enum import Enum


class EvolveType(str, Enum):
TEAM_TUNING = "team_tuning"
INSTRUCTION_TUNING = "instruction_tuning"
51 changes: 30 additions & 21 deletions aixplain/factories/agent_factory/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

from aixplain.enums.function import Function
from aixplain.enums.supplier import Supplier
from aixplain.modules.agent import Agent, AgentTask, Tool
from aixplain.modules.agent import Agent, Tool, WorkflowTask
from aixplain.modules.agent.output_format import OutputFormat
from aixplain.modules.agent.tool.model_tool import ModelTool
from aixplain.modules.agent.tool.pipeline_tool import PipelineTool
Expand Down Expand Up @@ -67,7 +67,8 @@ def create(
api_key: Text = config.TEAM_API_KEY,
supplier: Union[Dict, Text, Supplier, int] = "aiXplain",
version: Optional[Text] = None,
tasks: List[AgentTask] = [],
tasks: List[WorkflowTask] = None,
workflow_tasks: List[WorkflowTask] = [],
output_format: Optional[OutputFormat] = None,
expected_output: Optional[Union[BaseModel, Text, dict]] = None,
) -> Agent:
Expand All @@ -80,15 +81,15 @@ def create(

Args:
name (Text): name of the agent
description (Text): description of the agent role.
description (Text): description of the agent instructions.
instructions (Text): instructions of the agent.
llm (Optional[Union[LLM, Text]], optional): LLM instance to use as an object or as an ID.
llm_id (Optional[Text], optional): ID of LLM to use if no LLM instance provided. Defaults to None.
tools (List[Union[Tool, Model]], optional): list of tool for the agent. Defaults to [].
api_key (Text, optional): team/user API key. Defaults to config.TEAM_API_KEY.
supplier (Union[Dict, Text, Supplier, int], optional): owner of the agent. Defaults to "aiXplain".
version (Optional[Text], optional): version of the agent. Defaults to None.
tasks (List[AgentTask], optional): list of tasks for the agent. Defaults to [].
workflow_tasks (List[WorkflowTask], optional): list of tasks for the agent. Defaults to [].
output_format (OutputFormat, optional): default output format for agent responses. Defaults to OutputFormat.TEXT.
expected_output (Union[BaseModel, Text, dict], optional): expected output. Defaults to None.
Returns:
Expand Down Expand Up @@ -127,6 +128,16 @@ def create(
elif isinstance(supplier, Supplier):
supplier = supplier.value["code"]

if tasks is not None:
warnings.warn(
"The 'tasks' parameter is deprecated and will be removed in a future version. " "Use 'workflow_tasks' instead.",
DeprecationWarning,
stacklevel=2,
)
workflow_tasks = tasks if workflow_tasks is None or workflow_tasks == [] else workflow_tasks

workflow_tasks = workflow_tasks or []

payload = {
"name": name,
"assets": [build_tool_payload(tool) for tool in tools],
Expand All @@ -136,7 +147,7 @@ def create(
"version": version,
"llmId": llm_id,
"status": "draft",
"tasks": [task.to_dict() for task in tasks],
"tasks": [task.to_dict() for task in workflow_tasks],
"tools": [],
}

Expand Down Expand Up @@ -206,32 +217,30 @@ def create_from_dict(cls, dict: Dict) -> Agent:
return agent

@classmethod
def create_task(
def create_workflow_task(
cls,
name: Text,
description: Text,
expected_output: Text,
dependencies: Optional[List[Text]] = None,
) -> AgentTask:
"""Create a new task for an agent.

Args:
name (Text): Name of the task.
description (Text): Description of what the task should accomplish.
expected_output (Text): Description of the expected output format.
dependencies (Optional[List[Text]], optional): List of task names that must
complete before this task can start. Defaults to None.

Returns:
AgentTask: Created task object.
"""
return AgentTask(
dependencies: Optional[List[Text]] = [],
) -> WorkflowTask:
return WorkflowTask(
name=name,
description=description,
expected_output=expected_output,
dependencies=dependencies,
)

@classmethod
def create_task(cls, *args, **kwargs):
warnings.warn(
"The 'create_task' method is deprecated and will be removed in a future version. "
"Use 'create_workflow_task' instead.",
DeprecationWarning,
stacklevel=2,
)
return cls.create_workflow_task(*args, **kwargs)

@classmethod
def create_model_tool(
cls,
Expand Down
61 changes: 53 additions & 8 deletions aixplain/factories/model_factory/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,14 @@ def create_model_from_response(response: Dict) -> Model:
additional_kwargs = {}
attributes = response.get("attributes", None)
if attributes:
embedding_model = next((item["code"] for item in attributes if item["name"] == "embeddingmodel"), None)
embedding_model = next(
(item.get("code") for item in attributes if item.get("name") == "embeddingmodel" and "code" in item), None
)
if embedding_model:
additional_kwargs["embedding_model"] = embedding_model
embedding_size = next((item["value"] for item in attributes if item["name"] == "embeddingSize"), None)
embedding_size = next(
(item.get("value") for item in attributes if item.get("name") == "embeddingSize" and "value" in item), None
)
if embedding_size:
additional_kwargs["embedding_size"] = embedding_size

Expand All @@ -87,7 +91,7 @@ def create_model_from_response(response: Dict) -> Model:
ModelClass = IndexModel
elif function_type == FunctionType.INTEGRATION:
ModelClass = Integration
elif function_type == FunctionType.CONNECTION :
elif function_type == FunctionType.CONNECTION:
ModelClass = ConnectionTool
elif function_type == FunctionType.MCP_CONNECTION:
ModelClass = MCPConnection
Expand Down Expand Up @@ -297,11 +301,52 @@ def get_model_from_ids(model_ids: List[str], api_key: Optional[str] = None) -> L
raise Exception(f"{message}")
if 200 <= r.status_code < 300:
models = []
for item in resp["items"]:
item["api_key"] = config.TEAM_API_KEY
if api_key is not None:
item["api_key"] = api_key
models.append(create_model_from_response(item))

def process_items(items):
"""Helper function to process model items and add API key"""
for item in items:
item["api_key"] = config.TEAM_API_KEY
if api_key is not None:
item["api_key"] = api_key
models.append(create_model_from_response(item))

# Check if pagination is needed ( pageNumber: 0 indicates pagination required)
if "pageTotal" in resp:
# Handle paginated response - need to fetch all pages
page_number = 1
total_fetched = resp.get("pageTotal", 0)
page_items = resp.get("items", [])
total_items = resp.get("total", 0)
process_items(page_items)

while True:
# Make request for current page
paginated_url = urljoin(config.BACKEND_URL, f"sdk/models?ids={','.join(model_ids)}&pageNumber={page_number}")
logging.info(f"Fetching page {page_number} - {paginated_url}")
page_r = _request_with_retry("get", paginated_url, headers=headers)
page_resp = page_r.json()

if not (200 <= page_r.status_code < 300):
error_message = f"Model GET Error: Failed to retrieve models page {page_number}. Status Code: {page_r.status_code}. Error: {page_resp}"
logging.error(error_message)
raise Exception(error_message)

# Process items from current page
page_items = page_resp.get("items", [])
if not page_items:
break

process_items(page_items)
total_fetched += len(page_items)

if total_fetched >= total_items:
break

page_number += 1
else:
# Handle non-paginated response (original logic)
process_items(resp["items"])

return models
else:
error_message = f"Model GET Error: Failed to retrieve models {model_ids}. Status Code: {r.status_code}. Error: {resp}"
Expand Down
33 changes: 18 additions & 15 deletions aixplain/factories/team_agent_factory/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,35 +145,39 @@ def _get_llm_safely(llm_id: str, llm_type: str) -> LLM:
try:
return get_llm_instance(llm_id, api_key=api_key)
except Exception:
raise Exception(f"TeamAgent Onboarding Error: LLM {llm_id} does not exist for {llm_type}. To resolve this, set the following LLM parameters to a valid LLM object or LLM ID: llm, supervisor_llm, mentalist_llm.")
raise Exception(
f"TeamAgent Onboarding Error: LLM {llm_id} does not exist for {llm_type}. To resolve this, set the following LLM parameters to a valid LLM object or LLM ID: llm, supervisor_llm, mentalist_llm."
)

def _setup_llm_and_tool(llm_param: Optional[Union[LLM, Text]],
default_id: Text,
llm_type: str,
description: str,
tools: List[Dict]) -> LLM:
def _setup_llm_and_tool(
llm_param: Optional[Union[LLM, Text]], default_id: Text, llm_type: str, description: str, tools: List[Dict]
) -> LLM:
"""Helper to set up an LLM and add its tool configuration."""
llm_instance = None
# Set up LLM
if llm_param is None:
llm_instance = _get_llm_safely(default_id, llm_type)
else:
llm_instance = _get_llm_safely(llm_param, llm_type) if isinstance(llm_param, str) else llm_param

# Add tool configuration
if llm_instance is not None:
tools.append({
"type": "llm",
"description": description,
"parameters": llm_instance.get_parameters().to_list() if llm_instance.get_parameters() else None,
})
tools.append(
{
"type": "llm",
"description": description,
"parameters": llm_instance.get_parameters().to_list() if llm_instance.get_parameters() else None,
}
)
return llm_instance, tools

# Set up LLMs and their tools
tools = []
llm, tools = _setup_llm_and_tool(llm, llm_id, "Main LLM", "main", tools)
supervisor_llm, tools = _setup_llm_and_tool(supervisor_llm, llm_id, "Supervisor LLM", "supervisor", tools)
mentalist_llm, tools = _setup_llm_and_tool(mentalist_llm, llm_id, "Mentalist LLM", "mentalist", tools) if use_mentalist else None
mentalist_llm, tools = (
_setup_llm_and_tool(mentalist_llm, llm_id, "Mentalist LLM", "mentalist", tools) if use_mentalist else (None, [])
)

team_agent = None
url = urljoin(config.BACKEND_URL, "sdk/agent-communities")
Expand Down Expand Up @@ -201,9 +205,8 @@ def _setup_llm_and_tool(llm_param: Optional[Union[LLM, Text]],
"supplier": supplier,
"version": version,
"status": "draft",
"tools": [],
"instructions": instructions,
"tools": tools,
"instructions": instructions,
}
# Store the LLM objects directly in the payload for build_team_agent
internal_payload = payload.copy()
Expand Down
28 changes: 14 additions & 14 deletions aixplain/factories/team_agent_factory/inspector_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
and monitor team agent operations. Inspectors can be created from existing models
or using automatic configurations.

WARNING: This feature is currently in private beta.

Example:
Create an inspector from a model with adaptive policy::

Expand All @@ -19,7 +21,7 @@
"""

import logging
from typing import Dict, Optional, Text, Union
from typing import Dict, Optional, Text, Union, Callable
from urllib.parse import urljoin

from aixplain.enums.asset_status import AssetStatus
Expand All @@ -31,7 +33,7 @@
from aixplain.utils.file_utils import _request_with_retry


INSPECTOR_SUPPORTED_FUNCTIONS = [Function.GUARDRAILS, Function.TEXT_GENERATION]
INSPECTOR_SUPPORTED_FUNCTIONS = [Function.GUARDRAILS, Function.TEXT_GENERATION, Function.UTILITIES]


class InspectorFactory:
Expand All @@ -48,7 +50,7 @@ def create_from_model(
name: Text,
model: Union[Text, Model],
model_config: Optional[Dict] = None,
policy: InspectorPolicy = InspectorPolicy.ADAPTIVE, # default: doing something dynamically
policy: Union[InspectorPolicy, Callable] = InspectorPolicy.ADAPTIVE, # default: doing something dynamically
) -> Inspector:
"""Create a new inspector agent from an onboarded model.

Expand All @@ -62,11 +64,10 @@ def create_from_model(
to use for the inspector.
model_config (Optional[Dict], optional): Configuration parameters for
the inspector model (e.g., prompts, thresholds). Defaults to None.
policy (InspectorPolicy, optional): Action to take upon negative feedback:
- WARN: Log warning but continue execution
- ABORT: Stop execution on negative feedback
- ADAPTIVE: Dynamically decide based on context
Defaults to InspectorPolicy.ADAPTIVE.
policy: Action to take upon negative feedback (WARN/ABORT/ADAPTIVE)
or a callable function. If callable, must have name "process_response",
arguments "model_response" and "input_content" (both strings), and
return InspectorAction. Defaults to ADAPTIVE.

Returns:
Inspector: Created and configured inspector agent.
Expand Down Expand Up @@ -124,7 +125,7 @@ def create_auto(
cls,
auto: InspectorAuto,
name: Optional[Text] = None,
policy: InspectorPolicy = InspectorPolicy.ADAPTIVE,
policy: Union[InspectorPolicy, Callable] = InspectorPolicy.ADAPTIVE,
) -> Inspector:
"""Create a new inspector agent using automatic configuration.

Expand All @@ -136,11 +137,10 @@ def create_auto(
auto (InspectorAuto): Pre-configured automatic inspector instance.
name (Optional[Text], optional): Name for the inspector. If not provided,
uses the name from the auto configuration. Defaults to None.
policy (InspectorPolicy, optional): Action to take upon negative feedback:
- WARN: Log warning but continue execution
- ABORT: Stop execution on negative feedback
- ADAPTIVE: Dynamically decide based on context
Defaults to InspectorPolicy.ADAPTIVE.
policy: Action to take upon negative feedback (WARN/ABORT/ADAPTIVE)
or a callable function. If callable, must have name "process_response",
arguments "model_response" and "input_content" (both strings), and
return InspectorAction. Defaults to ADAPTIVE.

Returns:
Inspector: Created and configured inspector agent using automatic
Expand Down
Loading