Skip to content
Merged

Test #240

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
1b67aed
Create bounds for FineTune hyperparameters (#103)
lucas-aixplain Jan 15, 2024
61359d8
Fixing pipeline general asset test (#106)
thiago-aixplain Jan 15, 2024
c293a69
Merge dev to test (#107)
lucas-aixplain Jan 16, 2024
572750c
Development to Test (#109)
thiago-aixplain Jan 17, 2024
adfe272
Merge to test (#111)
ikxplain Jan 24, 2024
8365218
Update Finetuner functional tests (#112)
lucas-aixplain Jan 29, 2024
43a2b00
Merge branch 'test' into development
thiago-aixplain Jan 29, 2024
846e300
Merge dev to test (#113)
lucas-aixplain Jan 29, 2024
359209a
Hf deployment test (#114)
mikelam-us-aixplain Jan 29, 2024
74af040
Hf deployment test (#115)
mikelam-us-aixplain Jan 29, 2024
ffddc00
Hf deployment test (#118)
mikelam-us-aixplain Jan 30, 2024
7adfddd
Hf deployment test (#117)
mikelam-us-aixplain Jan 30, 2024
367ad74
Merge branch 'main' into test
ikxplain Jan 31, 2024
4c5358c
Do not download textual URLs (#120)
thiago-aixplain Feb 1, 2024
cb14b5a
Enable api key parameter in data asset creation (#122)
thiago-aixplain Feb 5, 2024
607852e
Merge to test (#124)
ikxplain Feb 6, 2024
66a043b
Update Finetuner hyperparameters (#125)
lucas-aixplain Feb 7, 2024
3b7f8b7
Merge dev to test (#126)
lucas-aixplain Feb 7, 2024
3bc04d3
Add new LLMs finetuner models (mistral and solar) (#128)
lucas-aixplain Feb 13, 2024
5954b63
Merge dev to test (#129)
lucas-aixplain Feb 13, 2024
58855c1
Enabling dataset ID and model ID as parameters for finetuner creation…
thiago-aixplain Feb 15, 2024
426213e
Fix supplier representation of a model (#132)
thiago-aixplain Feb 16, 2024
d62ad83
Fixing indentation in documentation sample code (#134)
thiago-aixplain Feb 21, 2024
7593033
Merge to test (#135)
ikxplain Feb 28, 2024
2f107e7
Update FineTune unit and functional tests (#136)
lucas-aixplain Mar 1, 2024
b5112dc
Merge branch 'test' into development
lucas-aixplain Mar 1, 2024
e6f1f02
Merge dev to test (#137)
lucas-aixplain Mar 1, 2024
32179d6
Click fix (#140)
mikelam-us-aixplain Mar 5, 2024
501e27b
Merge branch 'main' into test
thiago-aixplain Mar 7, 2024
94cf5f0
Merge branch 'test' into development
lucas-aixplain Mar 12, 2024
e0e260c
Merge to test (#142)
ikxplain Mar 12, 2024
34861a3
M 5905660469 enhance benchmark job response (#145)
shreyasXplain Mar 18, 2024
6fc9646
M 5905660469 enhance benchmark job response (#146)
shreyasXplain Mar 19, 2024
b4e5b67
New pipeline functional tests (#143)
thiago-aixplain Mar 19, 2024
873cb6a
M 6107719447 check finetuner status (#133)
thiago-aixplain Mar 21, 2024
c2a2cfd
Update metric.py (#147)
shreyasXplain Mar 22, 2024
88ab478
Dev 2 Test version 0.2.11 (#149)
thiago-aixplain Mar 22, 2024
e4b076b
Fixing finetune checker test and doc (#150)
thiago-aixplain Mar 22, 2024
84bd827
Development to Test (#151)
thiago-aixplain Mar 22, 2024
451f309
Skip model onboard and deployment tests (#153)
thiago-aixplain Mar 25, 2024
8df2bd0
Saving/Update Pipeline Services (#154)
thiago-aixplain Mar 26, 2024
bdf33b1
Merge to test. (#156)
ikxplain Mar 27, 2024
28f3092
Do not run service mode tests for specific pipelines (#159)
thiago-aixplain Apr 3, 2024
b86cf45
Merge branch 'test' into development
thiago-aixplain Apr 3, 2024
d1debf5
Development 2 Test (#160)
thiago-aixplain Apr 3, 2024
b45f12e
Fix on Metadata (#162)
thiago-aixplain Apr 9, 2024
dc45128
Merge to test (#163)
ikxplain Apr 10, 2024
5d75317
Interval label new structures (#157)
thiago-aixplain Apr 15, 2024
b43e7ec
Development 2 Test - Release 0.2.11 (#165)
thiago-aixplain Apr 15, 2024
da84847
Merge branch 'main' into test
ikxplain Apr 16, 2024
e4b2b22
Support text labels (#167)
thiago-aixplain Apr 17, 2024
4ccaa36
SDK's UML diagram (#169)
thiago-aixplain Apr 19, 2024
b1997cf
Merge remote-tracking branch 'origin/development' into test
ikxplain Apr 29, 2024
d3da2d2
Merge remote-tracking branch 'origin/test' into test
ikxplain Apr 29, 2024
d66d7d9
Merge dev to test (#173)
lucas-aixplain May 2, 2024
9d6f009
Merge to test (#177)
ikxplain May 8, 2024
ff6e204
Merge to test (#183)
ikxplain May 28, 2024
6ac5e63
Michael dev merge (#190)
mikelam-us-aixplain Jun 11, 2024
e9aa472
Merge to test (#188)
ikxplain Jun 11, 2024
662104f
Merge branch 'main' into test
thiago-aixplain Jun 18, 2024
d342800
Merge to test (#199)
ikxplain Jun 26, 2024
ff688c2
Fix pipeline functional test (#201)
lucas-aixplain Jul 3, 2024
815dde8
Merge branch 'main' into test
lucas-aixplain Jul 4, 2024
93f57bd
Merge to test. (#203)
ikxplain Jul 11, 2024
78c3bd9
Merge dev to test (#205)
lucas-aixplain Jul 13, 2024
a532df2
Merge to test (#209)
hadi-aix Jul 24, 2024
d8031c8
Merge to test (#217)
ikxplain Aug 13, 2024
024381f
Development 2 Test (#223)
thiago-aixplain Aug 13, 2024
d77fb93
Solving conflicts
thiago-aixplain Aug 14, 2024
419eed3
Removing duplicated test
thiago-aixplain Aug 14, 2024
348eead
Merge to test (#236)
ikxplain Aug 22, 2024
a3b19e5
Merge branch 'main' into test
thiago-aixplain Aug 27, 2024
93d0e11
Development 2 Test (#239)
thiago-aixplain Aug 27, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,4 @@ dmypy.json

# Vscode
.vscode
.DS_Store
1 change: 1 addition & 0 deletions aixplain/factories/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@
from .model_factory import ModelFactory
from .pipeline_factory import PipelineFactory
from .finetune_factory import FinetuneFactory
from .wallet_factory import WalletFactory
33 changes: 29 additions & 4 deletions aixplain/factories/agent_factory/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from aixplain.utils import config
from typing import Dict, List, Optional, Text, Union

from aixplain.factories.agent_factory.utils import build_agent
from aixplain.factories.agent_factory.utils import build_agent, validate_llm
from aixplain.utils.file_utils import _request_with_retry
from urllib.parse import urljoin

Expand All @@ -50,8 +50,30 @@ def create(
api_key: Text = config.TEAM_API_KEY,
supplier: Union[Dict, Text, Supplier, int] = "aiXplain",
version: Optional[Text] = None,
use_mentalist_and_inspector: bool = False,
) -> Agent:
"""Create a new agent in the platform."""
"""Create a new agent in the platform.

Args:
name (Text): name of the agent
llm_id (Text): aiXplain ID of the large language model to be used as agent.
tools (List[Tool], optional): list of tool for the agent. Defaults to [].
description (Text, optional): description of the agent role. 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.
use_mentalist_and_inspector (bool, optional): flag to enable mentalist and inspector agents (which only works when a supervisor is enabled). Defaults to False.

Returns:
Agent: created Agent
"""
# validate LLM ID
validate_llm(llm_id)

orchestrator_llm_id, mentalist_and_inspector_llm_id = llm_id, None
if use_mentalist_and_inspector is True:
mentalist_and_inspector_llm_id = llm_id

try:
agent = None
url = urljoin(config.BACKEND_URL, "sdk/agents")
Expand All @@ -65,6 +87,7 @@ def create(
tool_payload = []
for tool in tools:
if isinstance(tool, ModelTool):
tool.validate()
tool_payload.append(
{
"function": tool.function.value if tool.function is not None else None,
Expand All @@ -76,6 +99,7 @@ def create(
}
)
elif isinstance(tool, PipelineTool):
tool.validate()
tool_payload.append(
{
"assetId": tool.pipeline,
Expand All @@ -92,9 +116,10 @@ def create(
"description": description,
"supplier": supplier,
"version": version,
"llmId": llm_id,
"supervisorId": orchestrator_llm_id,
"plannerId": mentalist_and_inspector_llm_id,
}
if llm_id is not None:
payload["llmId"] = llm_id

logging.info(f"Start service for POST Create Agent - {url} - {headers} - {json.dumps(payload)}")
r = _request_with_retry("post", url, headers=headers, json=payload)
Expand Down
10 changes: 10 additions & 0 deletions aixplain/factories/agent_factory/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,13 @@ def build_agent(payload: Dict, api_key: Text = config.TEAM_API_KEY) -> Agent:
)
agent.url = urljoin(config.BACKEND_URL, f"sdk/agents/{agent.id}/run")
return agent


def validate_llm(model_id: Text) -> None:
from aixplain.factories.model_factory import ModelFactory

try:
llm = ModelFactory.get(model_id)
assert llm.function == Function.TEXT_GENERATION, "Large Language Model must be a text generation model."
except Exception:
raise Exception(f"Large Language Model with ID '{model_id}' not found.")
28 changes: 28 additions & 0 deletions aixplain/factories/wallet_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import aixplain.utils.config as config
from aixplain.modules.wallet import Wallet
from aixplain.utils.file_utils import _request_with_retry
import logging
from typing import Text


class WalletFactory:
aixplain_key = config.AIXPLAIN_API_KEY
backend_url = config.BACKEND_URL

@classmethod
def get(cls, api_key: Text = config.TEAM_API_KEY) -> Wallet:
"""Get wallet information"""
try:
resp = None
url = f"{cls.backend_url}/sdk/billing/wallet"
headers = {"Authorization": f"Token {api_key}", "Content-Type": "application/json"}
logging.info(f"Start fetching billing information from - {url} - {headers}")
headers = {"Content-Type": "application/json", "x-api-key": api_key}
r = _request_with_retry("get", url, headers=headers)
resp = r.json()
total_balance = float(resp.get("totalBalance", 0.0))
reserved_balance = float(resp.get("reservedBalance", 0.0))

return Wallet(total_balance=total_balance, reserved_balance=reserved_balance)
except Exception as e:
raise Exception(f"Failed to get the wallet credit information. Error: {str(e)}")
16 changes: 13 additions & 3 deletions aixplain/modules/agent/tool/model_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,23 @@ def __init__(

if model is not None:
if isinstance(model, Text) is True:
from aixplain.factories.model_factory import ModelFactory

model = ModelFactory.get(model)
self.model = model
model = self.validate()
function = model.function
if isinstance(model.supplier, Supplier):
supplier = model.supplier
model = model.id
self.supplier = supplier
self.model = model
self.function = function

def validate(self) -> Model:
from aixplain.factories.model_factory import ModelFactory

try:
model = None
if self.model is not None:
model = ModelFactory.get(self.model)
return model
except Exception:
raise Exception(f"Model Tool Unavailable. Make sure Model '{self.model}' exists or you have access to it.")
8 changes: 8 additions & 0 deletions aixplain/modules/agent/tool/pipeline_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,11 @@ def __init__(
if isinstance(pipeline, Pipeline):
pipeline = pipeline.id
self.pipeline = pipeline

def validate(self):
from aixplain.factories.pipeline_factory import PipelineFactory

try:
PipelineFactory.get(self.pipeline)
except Exception:
raise Exception(f"Pipeline Tool Unavailable. Make sure Pipeline '{self.pipeline}' exists or you have access to it.")
26 changes: 21 additions & 5 deletions aixplain/modules/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,27 @@ def run_async(self, data: Union[Text, Dict], name: Text = "model_process", param

resp = None
try:
resp = r.json()
logging.info(f"Result of request for {name} - {r.status_code} - {resp}")

poll_url = resp["data"]
response = {"status": "IN_PROGRESS", "url": poll_url}
if 200 <= r.status_code < 300:
resp = r.json()
logging.info(f"Result of request for {name} - {r.status_code} - {resp}")
poll_url = resp["data"]
response = {"status": "IN_PROGRESS", "url": poll_url}
else:
if r.status_code == 401:
error = "Unauthorized API key: Please verify the spelling of the API key and its current validity."
elif 460 <= r.status_code < 470:
error = "Subscription-related error: Please ensure that your subscription is active and has not expired."
elif 470 <= r.status_code < 480:
error = "Billing-related error: Please ensure you have enough credits to run this model. "
elif 480 <= r.status_code < 490:
error = "Supplier-related error: Please ensure that the selected supplier provides the model you are trying to access."
elif 490 <= r.status_code < 500:
error = "Validation-related error: Please ensure all required fields are provided and correctly formatted."
else:
status_code = str(r.status_code)
error = f"Status {status_code}: Unspecified error: An unspecified error occurred while processing your request."
response = {"status": "FAILED", "error_message": error}
logging.error(f"Error in request for {name} - {r.status_code}: {error}")
except Exception:
response = {"status": "FAILED"}
msg = f"Error in request for {name} - {traceback.format_exc()}"
Expand Down
26 changes: 21 additions & 5 deletions aixplain/modules/model/llm_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,27 @@ def run_async(

resp = None
try:
resp = r.json()
logging.info(f"Result of request for {name} - {r.status_code} - {resp}")

poll_url = resp["data"]
response = {"status": "IN_PROGRESS", "url": poll_url}
if 200 <= r.status_code < 300:
resp = r.json()
logging.info(f"Result of request for {name} - {r.status_code} - {resp}")
poll_url = resp["data"]
response = {"status": "IN_PROGRESS", "url": poll_url}
else:
if r.status_code == 401:
error = "Unauthorized API key: Please verify the spelling of the API key and its current validity."
elif 460 <= r.status_code < 470:
error = "Subscription-related error: Please ensure that your subscription is active and has not expired."
elif 470 <= r.status_code < 480:
error = "Billing-related error: Please ensure you have enough credits to run this model. "
elif 480 <= r.status_code < 490:
error = "Supplier-related error: Please ensure that the selected supplier provides the model you are trying to access."
elif 490 <= r.status_code < 500:
error = "Validation-related error: Please ensure all required fields are provided and correctly formatted."
else:
status_code = str(r.status_code)
error = f"Status {status_code}: Unspecified error: An unspecified error occurred while processing your request."
response = {"status": "FAILED", "error_message": error}
logging.error(f"Error in request for {name} - {r.status_code}: {error}")
except Exception:
response = {"status": "FAILED"}
msg = f"Error in request for {name} - {traceback.format_exc()}"
Expand Down
26 changes: 21 additions & 5 deletions aixplain/modules/pipeline/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,27 @@ def run_async(

resp = None
try:
resp = r.json()
logging.info(f"Result of request for {name} - {r.status_code} - {resp}")

poll_url = resp["url"]
response = {"status": "IN_PROGRESS", "url": poll_url}
if 200 <= r.status_code < 300:
resp = r.json()
logging.info(f"Result of request for {name} - {r.status_code} - {resp}")
poll_url = resp["url"]
response = {"status": "IN_PROGRESS", "url": poll_url}
else:
if r.status_code == 401:
error = "Unauthorized API key: Please verify the spelling of the API key and its current validity."
elif 460 <= r.status_code < 470:
error = "Subscription-related error: Please ensure that your subscription is active and has not expired."
elif 470 <= r.status_code < 480:
error = "Billing-related error: Please ensure you have enough credits to run this pipeline. "
elif 480 <= r.status_code < 490:
error = "Supplier-related error: Please ensure that the selected supplier provides the pipeline you are trying to access."
elif 490 <= r.status_code < 500:
error = "Validation-related error: Please ensure all required fields are provided and correctly formatted."
else:
status_code = str(r.status_code)
error = f"Status {status_code}: Unspecified error: An unspecified error occurred while processing your request."
response = {"status": "FAILED", "error_message": error}
logging.error(f"Error in request for {name} - {r.status_code}: {error}")
except Exception:
response = {"status": "FAILED"}
if resp is not None:
Expand Down
35 changes: 35 additions & 0 deletions aixplain/modules/wallet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
__author__ = "aixplain"

"""
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.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Author: aiXplain Team
Date: August 20th 2024
Description:
Wallet Class
"""


class Wallet:
def __init__(self, total_balance: float, reserved_balance: float):
"""
Args:
total_balance (float): total credit balance
reserved_balance (float): reserved credit balance
available_balance (float): available balance (total - credit)
"""
self.total_balance = total_balance
self.reserved_balance = reserved_balance
self.available_balance = total_balance-reserved_balance
6 changes: 6 additions & 0 deletions tests/functional/agent/agent_functional_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,9 @@ def test_list_agents():
assert "results" in agents
agents_result = agents["results"]
assert type(agents_result) is list


def test_fail_non_existent_llm():
with pytest.raises(Exception) as exc_info:
AgentFactory.create(name="Test Agent", llm_id="non_existent_llm", tools=[])
assert str(exc_info.value) == "Large Language Model with ID 'non_existent_llm' not found."
71 changes: 71 additions & 0 deletions tests/unit/agent_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import requests_mock
from aixplain.modules import Agent
from aixplain.utils import config
from aixplain.factories import AgentFactory
from aixplain.modules.agent import PipelineTool, ModelTool
from urllib.parse import urljoin


def test_fail_no_data_query():
Expand Down Expand Up @@ -61,3 +64,71 @@ def test_sucess_query_content():
response = agent.run_async(data={"query": "Translate the text: {{input1}}"}, content={"input1": "Hello, how are you?"})
assert response["status"] == ref_response["status"]
assert response["url"] == ref_response["data"]


def test_invalid_pipelinetool():
with pytest.raises(Exception) as exc_info:
AgentFactory.create(
name="Test", tools=[PipelineTool(pipeline="309851793", description="Test")], llm_id="6646261c6eb563165658bbb1"
)
assert str(exc_info.value) == "Pipeline Tool Unavailable. Make sure Pipeline '309851793' exists or you have access to it."


def test_invalid_modeltool():
with pytest.raises(Exception) as exc_info:
AgentFactory.create(name="Test", tools=[ModelTool(model="309851793")], llm_id="6646261c6eb563165658bbb1")
assert str(exc_info.value) == "Model Tool Unavailable. Make sure Model '309851793' exists or you have access to it."


def test_create_agent():
from aixplain.enums import Supplier

with requests_mock.Mocker() as mock:
url = urljoin(config.BACKEND_URL, "sdk/agents")
headers = {"x-api-key": config.TEAM_API_KEY, "Content-Type": "application/json"}

ref_response = {
"id": "123",
"name": "Test Agent",
"description": "Test Agent Description",
"teamId": "123",
"version": "1.0",
"status": "onboarded",
"llmId": "6646261c6eb563165658bbb1",
"pricing": {"currency": "USD", "value": 0.0},
"assets": [
{
"type": "model",
"supplier": "openai",
"version": "1.0",
"assetId": "6646261c6eb563165658bbb1",
"function": "text-generation",
}
],
}
mock.post(url, headers=headers, json=ref_response)

url = urljoin(config.BACKEND_URL, "sdk/models/6646261c6eb563165658bbb1")
model_ref_response = {
"id": "6646261c6eb563165658bbb1",
"name": "Test LLM",
"description": "Test LLM Description",
"function": {"id": "text-generation"},
"supplier": "openai",
"version": {"id": "1.0"},
"status": "onboarded",
"pricing": {"currency": "USD", "value": 0.0},
}
mock.get(url, headers=headers, json=model_ref_response)

agent = AgentFactory.create(
name="Test Agent",
description="Test Agent Description",
llm_id="6646261c6eb563165658bbb1",
tools=[AgentFactory.create_model_tool(supplier=Supplier.OPENAI, function="text-generation")],
)

assert agent.name == ref_response["name"]
assert agent.description == ref_response["description"]
assert agent.llm_id == ref_response["llmId"]
assert agent.tools[0].function.value == ref_response["assets"][0]["function"]
Loading