From 29da6659cf2eeff61c515642efabfbffd8052969 Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Thu, 2 Jan 2025 19:40:56 +0530 Subject: [PATCH 01/12] added the skeleton for the AIMind tool --- .../tools/ai_minds_tool/README.md | 0 .../tools/ai_minds_tool/__init__.py | 0 .../tools/ai_minds_tool/ai_minds_tool.py | 40 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 src/crewai_tools/tools/ai_minds_tool/README.md create mode 100644 src/crewai_tools/tools/ai_minds_tool/__init__.py create mode 100644 src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py diff --git a/src/crewai_tools/tools/ai_minds_tool/README.md b/src/crewai_tools/tools/ai_minds_tool/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/crewai_tools/tools/ai_minds_tool/__init__.py b/src/crewai_tools/tools/ai_minds_tool/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py new file mode 100644 index 000000000..99d8e3f8f --- /dev/null +++ b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py @@ -0,0 +1,40 @@ +from typing import Dict, Optional, Type, TYPE_CHECKING + +from crewai.tools import BaseTool +from openai import OpenAI +from pydantic import BaseModel + +if TYPE_CHECKING: + from minds_sdk import Client + + +class AIMindInputSchema(BaseModel): + """Input for AIMind Tool.""" + + query: str = "Question in natural language to ask the AI-Mind" + + +class AIMindTool(BaseTool): + name: str = "AIMind Tool" + description: str = ( + "A wrapper around [AI-Minds](https://mindsdb.com/minds). " + "Useful for when you need answers to questions from your data, stored in " + "data sources including PostgreSQL, MySQL, MariaDB, ClickHouse, Snowflake " + "and Google BigQuery. " + "Input should be a question in natural language." + ) + args_schema: Type[BaseModel] = AIMindInputSchema + api_key: Optional[str] = None + datasources: Optional[Dict] = None + minds_client: Optional["Client"] = None + + def __init__(self, api_key: Optional[str] = None, **kwargs): + super().__init__(**kwargs) + try: + from minds_sdk import Client # type: ignore + except ImportError: + raise ImportError( + "`minds_sdk` package not found, please run `pip install minds-sdk`" + ) + + self.minds_client = Client(api_key=api_key) \ No newline at end of file From 55f669989bca634ba61919f1295ee8f47b4a208c Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 00:28:30 +0530 Subject: [PATCH 02/12] completed the initialization logic for the tool --- .../tools/ai_minds_tool/ai_minds_tool.py | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py index 99d8e3f8f..411daf209 100644 --- a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py +++ b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py @@ -1,12 +1,10 @@ -from typing import Dict, Optional, Type, TYPE_CHECKING +import secrets +from typing import Dict, Optional, Text, Type from crewai.tools import BaseTool from openai import OpenAI from pydantic import BaseModel -if TYPE_CHECKING: - from minds_sdk import Client - class AIMindInputSchema(BaseModel): """Input for AIMind Tool.""" @@ -26,15 +24,38 @@ class AIMindTool(BaseTool): args_schema: Type[BaseModel] = AIMindInputSchema api_key: Optional[str] = None datasources: Optional[Dict] = None - minds_client: Optional["Client"] = None + mind_name: Optional[Text] = None def __init__(self, api_key: Optional[str] = None, **kwargs): super().__init__(**kwargs) try: from minds_sdk import Client # type: ignore + from minds.datasources import DatabaseConfig # type: ignore except ImportError: raise ImportError( "`minds_sdk` package not found, please run `pip install minds-sdk`" ) - self.minds_client = Client(api_key=api_key) \ No newline at end of file + minds_client = Client(api_key=api_key) + + # Convert the datasources to DatabaseConfig objects. + datasources = [] + for datasource in self.datasources: + if datasource["type"] == "database": + config = DatabaseConfig( + name=datasource["name"], + engine=datasource["engine"], + description=datasource["description"], + connection_data=datasource["connection_data"], + tables=datasource["tables"], + ) + datasources.append(config) + + # Generate a random name for the Mind. + name = f"cai_mind_{secrets.token_hex(5)}" + + mind = minds_client.minds.create( + name=name, datasources=datasources, replace=True + ) + + self.mind_name = mind.name \ No newline at end of file From 0b5f0841bf235eb029e4d24c19efd00c90bbeccd Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 00:32:24 +0530 Subject: [PATCH 03/12] implemented the run function for the tool --- .../tools/ai_minds_tool/ai_minds_tool.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py index 411daf209..915ed1ca0 100644 --- a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py +++ b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py @@ -58,4 +58,20 @@ class AIMindTool(BaseTool): name=name, datasources=datasources, replace=True ) - self.mind_name = mind.name \ No newline at end of file + self.mind_name = mind.name + + def _run( + self, + query: Text + ): + # Run the query on the AI-Mind. + # The Minds API is OpenAI compatible and therefore, the OpenAI client can be used. + openai_client = OpenAI(base_url="https://mdb.ai/", api_key=self.api_key) + + completion = openai_client.create( + model=self.mind_name, + messages=[{"role": "user", "content": query}], + stream=False, + ) + + return completion.choices[0].message.content \ No newline at end of file From 555638a654f61c2c07afc68320e272421be94f7b Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 00:37:12 +0530 Subject: [PATCH 04/12] added the main import statements --- src/crewai_tools/__init__.py | 1 + src/crewai_tools/tools/__init__.py | 1 + src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/crewai_tools/__init__.py b/src/crewai_tools/__init__.py index 87aca8531..a0e384683 100644 --- a/src/crewai_tools/__init__.py +++ b/src/crewai_tools/__init__.py @@ -1,4 +1,5 @@ from .tools import ( + AIMindTool, BraveSearchTool, BrowserbaseLoadTool, CodeDocsSearchTool, diff --git a/src/crewai_tools/tools/__init__.py b/src/crewai_tools/tools/__init__.py index f6c31f45f..c125082f3 100644 --- a/src/crewai_tools/tools/__init__.py +++ b/src/crewai_tools/tools/__init__.py @@ -1,3 +1,4 @@ +from .ai_minds_tool.ai_minds_tool import AIMindTool from .brave_search_tool.brave_search_tool import BraveSearchTool from .browserbase_load_tool.browserbase_load_tool import BrowserbaseLoadTool from .code_docs_search_tool.code_docs_search_tool import CodeDocsSearchTool diff --git a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py index 915ed1ca0..8d7750771 100644 --- a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py +++ b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py @@ -26,7 +26,7 @@ class AIMindTool(BaseTool): datasources: Optional[Dict] = None mind_name: Optional[Text] = None - def __init__(self, api_key: Optional[str] = None, **kwargs): + def __init__(self, api_key: Optional[Text] = None, **kwargs): super().__init__(**kwargs) try: from minds_sdk import Client # type: ignore From faff58ba1cc18f2aef203164a75388a2d4f04d3f Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 01:17:11 +0530 Subject: [PATCH 05/12] fixed a few bugs, type hints and imports --- .../tools/ai_minds_tool/ai_minds_tool.py | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py index 8d7750771..222271d7f 100644 --- a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py +++ b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py @@ -1,5 +1,5 @@ import secrets -from typing import Dict, Optional, Text, Type +from typing import Any, Dict, List, Optional, Text, Type from crewai.tools import BaseTool from openai import OpenAI @@ -23,13 +23,13 @@ class AIMindTool(BaseTool): ) args_schema: Type[BaseModel] = AIMindInputSchema api_key: Optional[str] = None - datasources: Optional[Dict] = None + datasources: Optional[List[Dict[str, Any]]] = None mind_name: Optional[Text] = None def __init__(self, api_key: Optional[Text] = None, **kwargs): - super().__init__(**kwargs) + super().__init__(api_key=api_key, **kwargs) try: - from minds_sdk import Client # type: ignore + from minds.client import Client # type: ignore from minds.datasources import DatabaseConfig # type: ignore except ImportError: raise ImportError( @@ -41,15 +41,14 @@ class AIMindTool(BaseTool): # Convert the datasources to DatabaseConfig objects. datasources = [] for datasource in self.datasources: - if datasource["type"] == "database": - config = DatabaseConfig( - name=datasource["name"], - engine=datasource["engine"], - description=datasource["description"], - connection_data=datasource["connection_data"], - tables=datasource["tables"], - ) - datasources.append(config) + config = DatabaseConfig( + name=f"cai_ds_{secrets.token_hex(5)}", + engine=datasource["engine"], + description=datasource["description"], + connection_data=datasource["connection_data"], + tables=datasource["tables"], + ) + datasources.append(config) # Generate a random name for the Mind. name = f"cai_mind_{secrets.token_hex(5)}" @@ -68,7 +67,7 @@ class AIMindTool(BaseTool): # The Minds API is OpenAI compatible and therefore, the OpenAI client can be used. openai_client = OpenAI(base_url="https://mdb.ai/", api_key=self.api_key) - completion = openai_client.create( + completion = openai_client.chat.completions.create( model=self.mind_name, messages=[{"role": "user", "content": query}], stream=False, From 64d54bd42352e54615a89211571b9c22557bee8a Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 01:55:51 +0530 Subject: [PATCH 06/12] updated the content in the README --- .../tools/ai_minds_tool/README.md | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/crewai_tools/tools/ai_minds_tool/README.md b/src/crewai_tools/tools/ai_minds_tool/README.md index e69de29bb..7bb47cde5 100644 --- a/src/crewai_tools/tools/ai_minds_tool/README.md +++ b/src/crewai_tools/tools/ai_minds_tool/README.md @@ -0,0 +1,75 @@ +# AIMind Tool + +## Description + +[Minds](https://mindsdb.com/minds) are AI systems provided by [MindsDB](https://mindsdb.com/) that work similarly to large language models (LLMs) but go beyond by answering any question from any data. + +This is accomplished by selecting the most relevant data for an answer using parametric search, understanding the meaning and providing responses within the correct context through semantic search, and finally, delivering precise answers by analyzing data and using machine learning (ML) models. + +## Installation + +1. Install the `crewai[tools]` package: + +```shell +pip install 'crewai[tools]' +``` + +2. Install the Minds SDK: + +```shell +pip install minds-sdk +``` + +3. Sign for a Minds account [here](https://mdb.ai/register), and obtain an API key. + +4. Set the Minds API key in an environment variable named `MINDS_API_KEY`. + +## Usage + +```python +from crewai_tools import AIMindTool + + +# Initialize the AIMindTool. +aimind_tool = AIMindTool( + datasources=[ + { + "description": "house sales data", + "engine": "postgres", + "connection_data": { + "user": "demo_user", + "password": "demo_password", + "host": "samples.mindsdb.com", + "port": 5432, + "database": "demo", + "schema": "demo_data" + }, + "tables": ["house_sales"] + } + ] +) +``` + +The `datasources` parameter is a list of dictionaries, each containing the following keys: + +- `description`: A description of the data contained in the datasource. +- `engine`: The engine (or type) of the datasource. +- `connection_data`: A dictionary containing the connection parameters for the datasource. +- `tables`: A list of tables that the data source will use. + +A list of supported data sources and their connection parameters can be found [here](https://docs.mdb.ai/docs/data_sources). + +```python +from crewai import Agent +from crewai.project import agent + + +# Define an agent with the AIMindTool. +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config["researcher"], + allow_delegation=False, + tools=[aimind_tool] + ) +``` From 3c29a6cc11cf0a221e2bb84eefcf84797ce6d450 Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 02:25:14 +0530 Subject: [PATCH 07/12] added an example of running the tool to the README --- src/crewai_tools/tools/ai_minds_tool/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/crewai_tools/tools/ai_minds_tool/README.md b/src/crewai_tools/tools/ai_minds_tool/README.md index 7bb47cde5..5b3755515 100644 --- a/src/crewai_tools/tools/ai_minds_tool/README.md +++ b/src/crewai_tools/tools/ai_minds_tool/README.md @@ -48,6 +48,8 @@ aimind_tool = AIMindTool( } ] ) + +aimind_tool.run("How many 3 bedroom houses were sold in 2008?") ``` The `datasources` parameter is a list of dictionaries, each containing the following keys: From 94cce06044af904a8f794511449abf250dc64c2f Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 11:08:38 +0530 Subject: [PATCH 08/12] updated the initialization logic to allow the API key to be passed as env var --- src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py index 222271d7f..1059d0053 100644 --- a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py +++ b/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py @@ -1,3 +1,4 @@ +import os import secrets from typing import Any, Dict, List, Optional, Text, Type @@ -36,7 +37,13 @@ class AIMindTool(BaseTool): "`minds_sdk` package not found, please run `pip install minds-sdk`" ) - minds_client = Client(api_key=api_key) + if os.getenv("MINDS_API_KEY"): + self.api_key = os.getenv("MINDS_API_KEY") + + if self.api_key is None: + raise ValueError("A Minds API key is required to use the AIMind Tool.") + + minds_client = Client(api_key=self.api_key) # Convert the datasources to DatabaseConfig objects. datasources = [] From 29a7961ca8c3164f8d20f46011af4d35019895e0 Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 11:26:16 +0530 Subject: [PATCH 09/12] refined the content in the README --- src/crewai_tools/tools/ai_minds_tool/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/crewai_tools/tools/ai_minds_tool/README.md b/src/crewai_tools/tools/ai_minds_tool/README.md index 5b3755515..95d2deb42 100644 --- a/src/crewai_tools/tools/ai_minds_tool/README.md +++ b/src/crewai_tools/tools/ai_minds_tool/README.md @@ -6,6 +6,8 @@ This is accomplished by selecting the most relevant data for an answer using parametric search, understanding the meaning and providing responses within the correct context through semantic search, and finally, delivering precise answers by analyzing data and using machine learning (ML) models. +The `AIMindTool` can be used to query data sources in natural language by simply configuring their connection parameters. + ## Installation 1. Install the `crewai[tools]` package: @@ -55,9 +57,9 @@ aimind_tool.run("How many 3 bedroom houses were sold in 2008?") The `datasources` parameter is a list of dictionaries, each containing the following keys: - `description`: A description of the data contained in the datasource. -- `engine`: The engine (or type) of the datasource. -- `connection_data`: A dictionary containing the connection parameters for the datasource. -- `tables`: A list of tables that the data source will use. +- `engine`: The engine (or type) of the datasource. Find a list of supported engines in the link below. +- `connection_data`: A dictionary containing the connection parameters for the datasource. Find a list of connection parameters for each engine in the link below. +- `tables`: A list of tables that the data source will use. This is optional and can be omitted if all tables in the data source are to be used. A list of supported data sources and their connection parameters can be found [here](https://docs.mdb.ai/docs/data_sources). From d360906f578c830ea6c80e7bc2e012bfc4195acc Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 11:41:59 +0530 Subject: [PATCH 10/12] renamed the pkg and module --- src/crewai_tools/tools/__init__.py | 2 +- .../tools/{ai_minds_tool => ai_mind_tool}/README.md | 0 .../tools/{ai_minds_tool => ai_mind_tool}/__init__.py | 0 .../ai_minds_tool.py => ai_mind_tool/ai_mind_tool.py} | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename src/crewai_tools/tools/{ai_minds_tool => ai_mind_tool}/README.md (100%) rename src/crewai_tools/tools/{ai_minds_tool => ai_mind_tool}/__init__.py (100%) rename src/crewai_tools/tools/{ai_minds_tool/ai_minds_tool.py => ai_mind_tool/ai_mind_tool.py} (100%) diff --git a/src/crewai_tools/tools/__init__.py b/src/crewai_tools/tools/__init__.py index c125082f3..33d68fb26 100644 --- a/src/crewai_tools/tools/__init__.py +++ b/src/crewai_tools/tools/__init__.py @@ -1,4 +1,4 @@ -from .ai_minds_tool.ai_minds_tool import AIMindTool +from .ai_mind_tool.ai_mind_tool import AIMindTool from .brave_search_tool.brave_search_tool import BraveSearchTool from .browserbase_load_tool.browserbase_load_tool import BrowserbaseLoadTool from .code_docs_search_tool.code_docs_search_tool import CodeDocsSearchTool diff --git a/src/crewai_tools/tools/ai_minds_tool/README.md b/src/crewai_tools/tools/ai_mind_tool/README.md similarity index 100% rename from src/crewai_tools/tools/ai_minds_tool/README.md rename to src/crewai_tools/tools/ai_mind_tool/README.md diff --git a/src/crewai_tools/tools/ai_minds_tool/__init__.py b/src/crewai_tools/tools/ai_mind_tool/__init__.py similarity index 100% rename from src/crewai_tools/tools/ai_minds_tool/__init__.py rename to src/crewai_tools/tools/ai_mind_tool/__init__.py diff --git a/src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py b/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py similarity index 100% rename from src/crewai_tools/tools/ai_minds_tool/ai_minds_tool.py rename to src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py From d1be5a937f6b19569b76a4aab2cccc7e6355a6dd Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 11:48:11 +0530 Subject: [PATCH 11/12] moved constants like the base URL to a class --- .../tools/ai_mind_tool/ai_mind_tool.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py b/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py index 1059d0053..c36400d0b 100644 --- a/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py +++ b/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py @@ -7,7 +7,13 @@ from openai import OpenAI from pydantic import BaseModel -class AIMindInputSchema(BaseModel): +class AIMindToolConstants: + MINDS_API_BASE_URL = "https://mdb.ai/" + MIND_NAME_PREFIX = "crwai_mind_" + DATASOURCE_NAME_PREFIX = "crwai_ds_" + + +class AIMindToolInputSchema(BaseModel): """Input for AIMind Tool.""" query: str = "Question in natural language to ask the AI-Mind" @@ -22,7 +28,7 @@ class AIMindTool(BaseTool): "and Google BigQuery. " "Input should be a question in natural language." ) - args_schema: Type[BaseModel] = AIMindInputSchema + args_schema: Type[BaseModel] = AIMindToolInputSchema api_key: Optional[str] = None datasources: Optional[List[Dict[str, Any]]] = None mind_name: Optional[Text] = None @@ -49,7 +55,7 @@ class AIMindTool(BaseTool): datasources = [] for datasource in self.datasources: config = DatabaseConfig( - name=f"cai_ds_{secrets.token_hex(5)}", + name=f"{AIMindToolConstants.DATASOURCE_NAME_PREFIX}_{secrets.token_hex(5)}", engine=datasource["engine"], description=datasource["description"], connection_data=datasource["connection_data"], @@ -58,7 +64,7 @@ class AIMindTool(BaseTool): datasources.append(config) # Generate a random name for the Mind. - name = f"cai_mind_{secrets.token_hex(5)}" + name = f"{AIMindToolConstants.MIND_NAME_PREFIX}_{secrets.token_hex(5)}" mind = minds_client.minds.create( name=name, datasources=datasources, replace=True @@ -72,7 +78,7 @@ class AIMindTool(BaseTool): ): # Run the query on the AI-Mind. # The Minds API is OpenAI compatible and therefore, the OpenAI client can be used. - openai_client = OpenAI(base_url="https://mdb.ai/", api_key=self.api_key) + openai_client = OpenAI(base_url=AIMindToolConstants.MINDS_API_BASE_URL, api_key=self.api_key) completion = openai_client.chat.completions.create( model=self.mind_name, From ea85f02e035ba106ead271ee7b83d628feae2215 Mon Sep 17 00:00:00 2001 From: Minura Punchihewa Date: Fri, 3 Jan 2025 11:49:58 +0530 Subject: [PATCH 12/12] refactored the logic for accessing the API key --- src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py b/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py index c36400d0b..b38426e09 100644 --- a/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py +++ b/src/crewai_tools/tools/ai_mind_tool/ai_mind_tool.py @@ -34,7 +34,11 @@ class AIMindTool(BaseTool): mind_name: Optional[Text] = None def __init__(self, api_key: Optional[Text] = None, **kwargs): - super().__init__(api_key=api_key, **kwargs) + super().__init__(**kwargs) + self.api_key = api_key or os.getenv("MINDS_API_KEY") + if not self.api_key: + raise ValueError("API key must be provided either through constructor or MINDS_API_KEY environment variable") + try: from minds.client import Client # type: ignore from minds.datasources import DatabaseConfig # type: ignore @@ -43,12 +47,6 @@ class AIMindTool(BaseTool): "`minds_sdk` package not found, please run `pip install minds-sdk`" ) - if os.getenv("MINDS_API_KEY"): - self.api_key = os.getenv("MINDS_API_KEY") - - if self.api_key is None: - raise ValueError("A Minds API key is required to use the AIMind Tool.") - minds_client = Client(api_key=self.api_key) # Convert the datasources to DatabaseConfig objects.