Skip to content
Merged

Test #721

Show file tree
Hide file tree
Changes from all commits
Commits
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
45 changes: 45 additions & 0 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Generate API docs

on:
push:
branches:
- main

permissions:
contents: write
pull-requests: write

jobs:
build-docs:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install dependencies
run: |
pip install pydoc-markdown

- name: Run pydoc-markdown
run: |
pydoc-markdown pydoc-markdown.yml

- name: Create Pull Request if docs changed
uses: peter-evans/create-pull-request@v7
with:
branch: docs/regenerate-api-docs
commit-message: "chore(docs): regenerate API docs"
title: "chore(docs): regenerate API docs"
body: |
This PR was automatically generated by the workflow to regenerate the API documentation.
add-paths: |
docs/api-reference/python/**
delete-branch: true
17 changes: 11 additions & 6 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
- main
# any branch other than main, will use the test key
- test
workflow_dispatch:
workflow_dispatch:

jobs:
setup-and-test:
Expand All @@ -31,7 +31,8 @@ jobs:
'finetune_v2',
'general_assets',
'apikey',
'agent_and_team_agent',
'agent',
'team_agent',
]
include:
- test-suite: 'unit'
Expand Down Expand Up @@ -79,9 +80,13 @@ jobs:
- test-suite: 'apikey'
path: 'tests/functional/apikey'
timeout: 45
- test-suite: 'agent_and_team_agent'
path: 'tests/functional/agent tests/functional/team_agent'
- test-suite: 'agent'
path: 'tests/functional/agent'
timeout: 45
- test-suite: 'team_agent'
path: 'tests/functional/team_agent'
timeout: 45

steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -91,7 +96,7 @@ jobs:
with:
python-version: "3.9"
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -112,7 +117,7 @@ jobs:
fi
echo "SLACK_TOKEN=${{ secrets.SLACK_TOKEN }}" >> $GITHUB_ENV
echo "HF_TOKEN=${{ secrets.HF_TOKEN }}" >> $GITHUB_ENV

- name: Run Tests
timeout-minutes: ${{ matrix.timeout }}
run: python -m pytest ${{ matrix.path }}
67 changes: 54 additions & 13 deletions aixplain/factories/agent_factory/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
__author__ = "lucaspavanelli"

"""
Copyright 2024 The aiXplain SDK authors
"""Copyright 2024 The aiXplain SDK authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -21,6 +18,8 @@
Agent Factory Class
"""

__author__ = "lucaspavanelli"

import json
import logging
import warnings
Expand Down Expand Up @@ -49,6 +48,19 @@
from aixplain.enums import DatabaseSourceType


def to_literal_text(x):
"""Convert value to literal text, escaping braces for string formatting.

Args:
x: Value to convert (dict, list, or any other type)

Returns:
str: Escaped string representation
"""
s = json.dumps(x, ensure_ascii=False, indent=2) if isinstance(x, (dict, list)) else str(x)
return s.replace("{", "{{").replace("}", "}}")


class AgentFactory:
"""Factory class for creating and managing agents in the aiXplain system.

Expand All @@ -63,7 +75,6 @@ def create(
description: Text,
instructions: Optional[Text] = None,
llm: Optional[Union[LLM, Text]] = None,
llm_id: Optional[Text] = None,
tools: Optional[List[Union[Tool, Model]]] = None,
api_key: Text = config.TEAM_API_KEY,
supplier: Union[Dict, Text, Supplier, int] = "aiXplain",
Expand All @@ -72,6 +83,7 @@ def create(
workflow_tasks: Optional[List[WorkflowTask]] = None,
output_format: Optional[OutputFormat] = None,
expected_output: Optional[Union[BaseModel, Text, dict]] = None,
**kwargs,
) -> Agent:
"""Create a new agent in the platform.

Expand All @@ -85,21 +97,32 @@ def create(
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[WorkflowTask], optional): Deprecated. Use workflow_tasks instead. Defaults to None.
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.
**kwargs: Additional keyword arguments.
Returns:
Agent: created Agent
"""
tools = [] if tools is None else list(tools)
workflow_tasks = [] if workflow_tasks is None else list(workflow_tasks)
from aixplain.utils.llm_utils import get_llm_instance

# Extract llm_id from kwargs if present (deprecated parameter)
llm_id = kwargs.get("llm_id", None)
if llm_id is not None:
warnings.warn(
"The 'llm_id' parameter is deprecated and will be removed in a future version. "
"Use the 'llm' parameter instead by passing the LLM ID or LLM instance directly.",
DeprecationWarning,
stacklevel=2,
)

if llm is None and llm_id is not None:
llm = get_llm_instance(llm_id, api_key=api_key, use_cache=True)
elif llm is None:
Expand All @@ -112,9 +135,7 @@ def create(
), "'expected_output' must be a Pydantic BaseModel or a JSON object when 'output_format' is JSON."

warnings.warn(
"Use `llm` to define the large language model (aixplain.modules.model.llm_model.LLM) to be used as agent. "
"Use `llm_id` to provide the model ID of the large language model to be used as agent. "
"Note: In upcoming releases, `llm` will become a required parameter.",
"Deprecating 'llm_id', use `llm` to define the large language model in agents.",
UserWarning,
)
from aixplain.factories.agent_factory.utils import (
Expand All @@ -133,7 +154,8 @@ def create(

if tasks is not None:
warnings.warn(
"The 'tasks' parameter is deprecated and will be removed in a future version. " "Use 'workflow_tasks' instead.",
"The 'tasks' parameter is deprecated and will be removed in a future version. "
"Use 'workflow_tasks' instead.",
DeprecationWarning,
stacklevel=2,
)
Expand All @@ -145,7 +167,7 @@ def create(
"name": name,
"assets": [build_tool_payload(tool) for tool in tools],
"description": description,
"instructions": instructions or description,
"instructions": instructions if instructions is not None else description,
"supplier": supplier,
"version": version,
"llmId": llm_id,
Expand Down Expand Up @@ -228,6 +250,17 @@ def create_workflow_task(
expected_output: Text,
dependencies: Optional[List[Text]] = None,
) -> WorkflowTask:
"""Create a new workflow task for an agent.

Args:
name (Text): Name of the task
description (Text): Description of what the task does
expected_output (Text): Expected output format or content
dependencies (Optional[List[Text]], optional): List of task names this task depends on. Defaults to None.

Returns:
WorkflowTask: Created workflow task object
"""
dependencies = [] if dependencies is None else list(dependencies)
return WorkflowTask(
name=name,
Expand All @@ -238,6 +271,11 @@ def create_workflow_task(

@classmethod
def create_task(cls, *args, **kwargs):
"""Create a workflow task (deprecated - use create_workflow_task instead).

.. deprecated::
Use :meth:`create_workflow_task` instead.
"""
warnings.warn(
"The 'create_task' method is deprecated and will be removed in a future version. "
"Use 'create_workflow_task' instead.",
Expand Down Expand Up @@ -351,7 +389,7 @@ def create_sql_tool(
tables: Optional[List[Text]] = None,
enable_commit: bool = False,
) -> SQLTool:
"""Create a new SQL tool
"""Create a new SQL tool.

Args:
name (Text): name of the tool
Expand All @@ -361,6 +399,7 @@ def create_sql_tool(
schema (Optional[Text], optional): database schema description
tables (Optional[List[Text]], optional): table names to work with (optional)
enable_commit (bool, optional): enable to modify the database (optional)

Returns:
SQLTool: created SQLTool

Expand Down Expand Up @@ -403,7 +442,9 @@ def create_sql_tool(
# Already the correct type, no conversion needed
pass
else:
raise SQLToolError(f"Source type must be either a string or DatabaseSourceType enum, got {type(source_type)}")
raise SQLToolError(
f"Source type must be either a string or DatabaseSourceType enum, got {type(source_type)}"
)

database_path = None # Final database path to pass to SQLTool

Expand Down
50 changes: 42 additions & 8 deletions aixplain/factories/team_agent_factory/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import json
import logging
import warnings
from typing import Dict, List, Optional, Text, Union
from urllib.parse import urljoin

Expand Down Expand Up @@ -54,15 +55,12 @@ def create(
cls,
name: Text,
agents: List[Union[Text, Agent]],
llm_id: Text = "669a63646eb56306647e1091",
llm: Optional[Union[LLM, Text]] = None,
supervisor_llm: Optional[Union[LLM, Text]] = None,
mentalist_llm: Optional[Union[LLM, Text]] = None,
description: Text = "",
api_key: Text = config.TEAM_API_KEY,
supplier: Union[Dict, Text, Supplier, int] = "aiXplain",
version: Optional[Text] = None,
use_mentalist: bool = True,
inspectors: List[Inspector] = [],
inspector_targets: List[Union[InspectorTarget, Text]] = [InspectorTarget.STEPS],
instructions: Optional[Text] = None,
Expand All @@ -75,24 +73,57 @@ def create(
Args:
name: The name of the team agent.
agents: A list of agents to be added to the team.
llm_id: The ID of the LLM to be used for the team agent.
llm (Optional[Union[LLM, Text]], optional): The LLM to be used for the team agent.
supervisor_llm (Optional[Union[LLM, Text]], optional): Main supervisor LLM. Defaults to None.
mentalist_llm (Optional[Union[LLM, Text]], optional): LLM for planning. Defaults to None.
description: The description of the team agent to be displayed in the aiXplain platform.
api_key: The API key to be used for the team agent.
supplier: The supplier of the team agent.
version: The version of the team agent.
use_mentalist: Whether to use the mentalist agent.
inspectors: A list of inspectors to be added to the team.
inspector_targets: Which stages to be inspected during an execution of the team agent. (steps, output)
use_mentalist_and_inspector: Whether to use the mentalist and inspector agents. (legacy)
instructions: The instructions to guide the team agent (i.e. appended in the prompt of the team agent).
output_format: The output format to be used for the team agent.
expected_output: The expected output to be used for the team agent.
Returns:
A new team agent instance.

Deprecated Args:
llm_id: DEPRECATED. Use 'llm' parameter instead. The ID of the LLM to be used for the team agent.
mentalist_llm: DEPRECATED. LLM for planning.
use_mentalist: DEPRECATED. Whether to use the mentalist agent.
"""
# Handle deprecated parameters from kwargs
if "llm_id" in kwargs:
llm_id = kwargs.pop("llm_id")
warnings.warn(
"Parameter 'llm_id' is deprecated and will be removed in a future version. "
"Please use 'llm' parameter instead.",
DeprecationWarning,
stacklevel=2,
)
else:
llm_id = "669a63646eb56306647e1091"

if "mentalist_llm" in kwargs:
mentalist_llm = kwargs.pop("mentalist_llm")
warnings.warn(
"Parameter 'mentalist_llm' is deprecated and will be removed in a future version.",
DeprecationWarning,
stacklevel=2,
)
else:
mentalist_llm = None

if "use_mentalist" in kwargs:
use_mentalist = kwargs.pop("use_mentalist")
warnings.warn(
"Parameter 'use_mentalist' is deprecated and will be removed in a future version.",
DeprecationWarning,
stacklevel=2,
)
else:
use_mentalist = True

# legacy params
if "use_mentalist_and_inspector" in kwargs:
logging.warning(
Expand Down Expand Up @@ -227,10 +258,13 @@ def _setup_llm_and_tool(
team_agent = build_team_agent(payload=internal_payload, agents=agent_list, api_key=api_key)
team_agent.validate(raise_exception=True)
response = "Unspecified error"
inspectors=team_agent.inspectors
inspector_targets=team_agent.inspector_targets
try:
payload["inspectors"] = [
inspector.model_dump(by_alias=True) for inspector in inspectors
] # convert Inspector object to dict
]
payload["inspectorTargets"] = inspector_targets
logging.debug(f"Start service for POST Create TeamAgent - {url} - {headers} - {json.dumps(payload)}")
r = _request_with_retry("post", url, headers=headers, json=payload)
response = r.json()
Expand Down
3 changes: 2 additions & 1 deletion aixplain/factories/team_agent_factory/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ def get_cached_model(model_id: str) -> any:
elif tool["description"] == "mentalist":
mentalist_llm = llm


team_agent = TeamAgent(
id=payload.get("id", ""),
name=payload.get("name", ""),
Expand Down Expand Up @@ -349,6 +350,6 @@ def build_team_agent_from_yaml(yaml_code: str, llm_id: str, api_key: str, team_i
agents=agent_objs,
llm=llm,
api_key=api_key,
use_mentalist=True,
inspectors=[],
use_mentalist=True, # Deprecated parameter
)
Loading
Loading