aiqtoolkit 1.1.0rc1__py3-none-any.whl → 1.1.0rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aiqtoolkit might be problematic. Click here for more details.

@@ -27,6 +27,7 @@ from aiq.data_models.config import AIQConfig
27
27
  from aiq.data_models.config import GeneralConfig
28
28
  from aiq.data_models.evaluate import EvalGeneralConfig
29
29
  from aiq.data_models.evaluator import EvaluatorBaseConfig
30
+ from aiq.data_models.function import EmptyFunctionConfig
30
31
  from aiq.utils.type_utils import override
31
32
 
32
33
  logger = logging.getLogger(__name__)
@@ -102,7 +103,10 @@ class WorkflowEvalBuilder(WorkflowBuilder, EvalBuilder):
102
103
  return tools
103
104
 
104
105
  async def populate_builder(self, config: AIQConfig):
105
- await super().populate_builder(config)
106
+ # Skip setting workflow if workflow config is EmptyFunctionConfig
107
+ skip_workflow = isinstance(config.workflow, EmptyFunctionConfig)
108
+
109
+ await super().populate_builder(config, skip_workflow)
106
110
  # Instantiate the evaluators
107
111
  for name, evaluator_config in config.eval.evaluators.items():
108
112
  await self.add_evaluator(name, evaluator_config)
@@ -586,8 +586,15 @@ class WorkflowBuilder(Builder, AbstractAsyncContextManager):
586
586
  def get_user_manager(self):
587
587
  return UserManagerHolder(context=AIQContext(self._context_state))
588
588
 
589
- async def populate_builder(self, config: AIQConfig):
589
+ async def populate_builder(self, config: AIQConfig, skip_workflow: bool = False):
590
+ """
591
+ Populate the builder with components and optionally set up the workflow.
592
+
593
+ Args:
594
+ config (AIQConfig): The configuration object containing component definitions.
595
+ skip_workflow (bool): If True, skips the workflow instantiation step. Defaults to False.
590
596
 
597
+ """
591
598
  # Generate the build sequence
592
599
  build_sequence = build_dependency_sequence(config)
593
600
 
@@ -614,7 +621,8 @@ class WorkflowBuilder(Builder, AbstractAsyncContextManager):
614
621
  raise ValueError(f"Unknown component group {component_instance.component_group}")
615
622
 
616
623
  # Instantiate the workflow
617
- await self.set_workflow(config.workflow)
624
+ if not skip_workflow:
625
+ await self.set_workflow(config.workflow)
618
626
 
619
627
  @classmethod
620
628
  @asynccontextmanager
@@ -19,6 +19,7 @@ import click
19
19
 
20
20
  from aiq.cli.commands.info.list_channels import list_channels
21
21
  from aiq.cli.commands.info.list_components import list_components
22
+ from aiq.cli.commands.info.list_mcp import list_mcp
22
23
 
23
24
  logger = logging.getLogger(__name__)
24
25
 
@@ -35,3 +36,4 @@ def info_command(**kwargs):
35
36
 
36
37
  info_command.add_command(list_components, name="components")
37
38
  info_command.add_command(list_channels, "channels")
39
+ info_command.add_command(list_mcp, "mcp")
@@ -0,0 +1,126 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import json
17
+ import logging
18
+
19
+ import anyio
20
+ import click
21
+
22
+ from aiq.tool.mcp.mcp_client import MCPBuilder
23
+
24
+ # Suppress verbose logs from mcp.client.sse and httpx
25
+ logging.getLogger("mcp.client.sse").setLevel(logging.WARNING)
26
+ logging.getLogger("httpx").setLevel(logging.WARNING)
27
+
28
+
29
+ def format_tool(tool):
30
+ name = getattr(tool, 'name', None)
31
+ description = getattr(tool, 'description', '')
32
+ input_schema = getattr(tool, 'input_schema', None) or getattr(tool, 'inputSchema', None)
33
+
34
+ schema_str = None
35
+ if input_schema:
36
+ if hasattr(input_schema, "schema_json"):
37
+ schema_str = input_schema.schema_json(indent=2)
38
+ else:
39
+ schema_str = str(input_schema)
40
+
41
+ return {
42
+ "name": name,
43
+ "description": description,
44
+ "input_schema": schema_str,
45
+ }
46
+
47
+
48
+ def print_tool(tool_dict, detail=False):
49
+ click.echo(f"Tool: {tool_dict['name']}")
50
+ if detail or tool_dict.get('input_schema') or tool_dict.get('description'):
51
+ click.echo(f"Description: {tool_dict['description']}")
52
+ if tool_dict["input_schema"]:
53
+ click.echo("Input Schema:")
54
+ click.echo(tool_dict["input_schema"])
55
+ else:
56
+ click.echo("Input Schema: None")
57
+ click.echo("-" * 60)
58
+
59
+
60
+ async def list_tools_and_schemas(url, tool_name=None):
61
+ builder = MCPBuilder(url=url)
62
+ try:
63
+ if tool_name:
64
+ tool = await builder.get_tool(tool_name)
65
+ return [format_tool(tool)]
66
+ else:
67
+ tools = await builder.get_tools()
68
+ return [format_tool(tool) for tool in tools.values()]
69
+ except Exception as e:
70
+ click.echo(f"[ERROR] Failed to fetch tools via MCPBuilder: {e}", err=True)
71
+ return []
72
+
73
+
74
+ async def list_tools_direct(url, tool_name=None):
75
+ from mcp import ClientSession
76
+ from mcp.client.sse import sse_client
77
+
78
+ try:
79
+ async with sse_client(url=url) as (read, write):
80
+ async with ClientSession(read, write) as session:
81
+ await session.initialize()
82
+ response = await session.list_tools()
83
+
84
+ tools = []
85
+ for tool in response.tools:
86
+ if tool_name:
87
+ if tool.name == tool_name:
88
+ return [format_tool(tool)]
89
+ else:
90
+ tools.append(format_tool(tool))
91
+ if tool_name and not tools:
92
+ click.echo(f"[INFO] Tool '{tool_name}' not found.")
93
+ return tools
94
+ except Exception as e:
95
+ click.echo(f"[ERROR] Failed to fetch tools via direct protocol: {e}", err=True)
96
+ return []
97
+
98
+
99
+ @click.group(invoke_without_command=True, help="List tool names (default), or show details with --detail or --tool.")
100
+ @click.option('--direct', is_flag=True, help='Bypass MCPBuilder and use direct MCP protocol')
101
+ @click.option('--url', default='http://localhost:9901/sse', show_default=True, help='MCP server URL')
102
+ @click.option('--tool', default=None, help='Get details for a specific tool by name')
103
+ @click.option('--detail', is_flag=True, help='Show full details for all tools')
104
+ @click.option('--json-output', is_flag=True, help='Output tool metadata in JSON format')
105
+ @click.pass_context
106
+ def list_mcp(ctx, direct, url, tool, detail, json_output):
107
+ """
108
+ List tool names (default). Use --detail for full output. If --tool is provided,
109
+ always show full output for that tool.
110
+ """
111
+ if ctx.invoked_subcommand is not None:
112
+ return
113
+ fetcher = list_tools_direct if direct else list_tools_and_schemas
114
+ tools = anyio.run(fetcher, url, tool)
115
+
116
+ if json_output:
117
+ click.echo(json.dumps(tools, indent=2))
118
+ elif tool:
119
+ for tool_dict in tools:
120
+ print_tool(tool_dict, detail=True)
121
+ elif detail:
122
+ for tool_dict in tools:
123
+ print_tool(tool_dict, detail=True)
124
+ else:
125
+ for tool_dict in tools:
126
+ click.echo(tool_dict['name'])
@@ -150,7 +150,11 @@ class DiscoveryMetadata(BaseModel):
150
150
  logger.error("Encountered issue getting distro_name for module %s", module.__name__)
151
151
  return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
152
152
 
153
- version = importlib.metadata.version(distro_name) if distro_name != "" else ""
153
+ try:
154
+ version = importlib.metadata.version(distro_name) if distro_name != "" else ""
155
+ except importlib.metadata.PackageNotFoundError:
156
+ logger.warning("Package metadata not found for %s", distro_name)
157
+ version = ""
154
158
  except Exception as e:
155
159
  logger.exception("Encountered issue extracting module metadata for %s: %s", config_type, e, exc_info=True)
156
160
  return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
@@ -185,7 +189,11 @@ class DiscoveryMetadata(BaseModel):
185
189
  module = inspect.getmodule(fn)
186
190
  root_package: str = module.__package__.split(".")[0]
187
191
  root_package = DiscoveryMetadata.get_distribution_name(root_package)
188
- version = importlib.metadata.version(root_package) if root_package != "" else ""
192
+ try:
193
+ version = importlib.metadata.version(root_package) if root_package != "" else ""
194
+ except importlib.metadata.PackageNotFoundError:
195
+ logger.warning("Package metadata not found for %s", root_package)
196
+ version = ""
189
197
  except Exception as e:
190
198
  logger.exception("Encountered issue extracting module metadata for %s: %s", fn, e, exc_info=True)
191
199
  return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
@@ -213,10 +221,15 @@ class DiscoveryMetadata(BaseModel):
213
221
 
214
222
  try:
215
223
  package_name = DiscoveryMetadata.get_distribution_name(package_name)
216
- metadata = importlib.metadata.metadata(package_name)
217
- description = metadata.get("Summary", "")
218
- if (package_version is None):
219
- package_version = importlib.metadata.version(package_name)
224
+ try:
225
+ metadata = importlib.metadata.metadata(package_name)
226
+ description = metadata.get("Summary", "")
227
+ if (package_version is None):
228
+ package_version = importlib.metadata.version(package_name)
229
+ except importlib.metadata.PackageNotFoundError:
230
+ logger.warning("Package metadata not found for %s", package_name)
231
+ description = ""
232
+ package_version = package_version or ""
220
233
  except Exception as e:
221
234
  logger.exception("Encountered issue extracting module metadata for %s: %s", package_name, e, exc_info=True)
222
235
  return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
@@ -252,7 +265,11 @@ class DiscoveryMetadata(BaseModel):
252
265
  module = inspect.getmodule(config_type)
253
266
  root_package: str = module.__package__.split(".")[0]
254
267
  root_package = DiscoveryMetadata.get_distribution_name(root_package)
255
- version = importlib.metadata.version(root_package) if root_package != "" else ""
268
+ try:
269
+ version = importlib.metadata.version(root_package) if root_package != "" else ""
270
+ except importlib.metadata.PackageNotFoundError:
271
+ logger.warning("Package metadata not found for %s", root_package)
272
+ version = ""
256
273
  except Exception as e:
257
274
  logger.exception("Encountered issue extracting module metadata for %s: %s", config_type, e, exc_info=True)
258
275
  return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
aiq/eval/evaluate.py CHANGED
@@ -177,8 +177,10 @@ class EvaluationRun: # pylint: disable=too-many-public-methods
177
177
  workflow_output_file.parent.mkdir(parents=True, exist_ok=True)
178
178
 
179
179
  # Write the workflow output to a file (this can be used for re-running the evaluation)
180
- workflow_output = dataset_handler.publish_eval_input(
181
- self.eval_input, self.eval_config.general.output.workflow_output_step_filter)
180
+
181
+ step_filter = self.eval_config.general.output.workflow_output_step_filter \
182
+ if self.eval_config.general.output else None
183
+ workflow_output = dataset_handler.publish_eval_input(self.eval_input, step_filter)
182
184
  with open(workflow_output_file, "w", encoding="utf-8") as f:
183
185
  # set indent to 2 for pretty printing
184
186
  f.write(workflow_output)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiqtoolkit
3
- Version: 1.1.0rc1
3
+ Version: 1.1.0rc2
4
4
  Summary: Agent Intelligence Toolkit (AIQ Toolkit)
5
5
  Author: NVIDIA Corporation
6
6
  Maintainer: NVIDIA Corporation
@@ -21,7 +21,7 @@ aiq/builder/builder.py,sha256=JE3uCw6qTmWX2akUfS-Ga5WSiJVTzBjDQPniiONMjy4,7448
21
21
  aiq/builder/component_utils.py,sha256=2jIXWSLIlKxDKAO7kdXz_4BHqQNWw4t9GmcQfw0ER4g,12923
22
22
  aiq/builder/context.py,sha256=Sk2Vcduz7zbGkJe28VxCDt8GC5GKDhwvl1zLuRBTmss,8574
23
23
  aiq/builder/embedder.py,sha256=M-n2oXSlwE7u-nmpzRbPq6UVWtFtMvrEdKqqsbKQZLk,965
24
- aiq/builder/eval_builder.py,sha256=nNsSc33rjdYjJdgqK77W5YWvn5RjCJ03bBrOQ0HYBRg,4437
24
+ aiq/builder/eval_builder.py,sha256=UnNgtQiDAUfT3yuwjZQVerenI09-4q0Cse9uwLjk3Fg,4657
25
25
  aiq/builder/evaluator.py,sha256=O6Gu0cUwQkrPxPX29Vf_-RopgijxPnhy7mhg_j-9A84,1162
26
26
  aiq/builder/framework_enum.py,sha256=eYwHQifZ86dx-OTubVA3qhCLRqhB4ElMBYBGA0gYtic,885
27
27
  aiq/builder/front_end.py,sha256=Xhvfi4VcDh5EoCtLr6AlLQfbRm8_TyugUc_IRfirN6Y,2225
@@ -33,7 +33,7 @@ aiq/builder/llm.py,sha256=DcoYCyschsRjkW_yGsa_Ci7ELSpk5KRbi9778Dm_B9c,951
33
33
  aiq/builder/retriever.py,sha256=GM7L1T4NdNZKerFZiCfLcQOwsGoX0NRlF8my7SMq3l4,970
34
34
  aiq/builder/user_interaction_manager.py,sha256=OXr-RxWf1sEZjzQH_jt0nmqrLBtYLHGEZEcfDYYFV88,2913
35
35
  aiq/builder/workflow.py,sha256=UOjrXmu1sxWTxTjygszqYgK0gK65r_beLKUwOpxtXuc,5894
36
- aiq/builder/workflow_builder.py,sha256=bl893QITWZbfEwGOQkVUIukLiggz7JvGvQ4lTAATja8,29319
36
+ aiq/builder/workflow_builder.py,sha256=LBlNc3HiKzMxI5XNiV4hj9PVLH1N6p9ErHWgWaRZsZM,29694
37
37
  aiq/cli/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
38
38
  aiq/cli/entrypoint.py,sha256=BJsCZgC2nVyAWj7tBXwW67OIteg833xAI54R-e9O8oc,4757
39
39
  aiq/cli/main.py,sha256=yVTX5-5-21OOfG8qAdcK3M1fCQUxdr3G37Mb5OldPQc,1772
@@ -55,9 +55,10 @@ aiq/cli/commands/configure/channel/channel.py,sha256=3y4lCk1PqqKPLlPtBo-B7jkUZ-K
55
55
  aiq/cli/commands/configure/channel/remove.py,sha256=zvLw1gRwF58erC1EWbPiWbPMRYXfNNcf2SKusBqsm24,1104
56
56
  aiq/cli/commands/configure/channel/update.py,sha256=vsQzt4vFAg5PsmbRimrKoChtkGUSsVywusOrUxgLWd0,1100
57
57
  aiq/cli/commands/info/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
58
- aiq/cli/commands/info/info.py,sha256=tkpAssNarrxAX9Bd3xE46q_sDyaCKS7AT7IaAnhwua8,1265
58
+ aiq/cli/commands/info/info.py,sha256=ePgsfHfmfAkjg-MoS9AIfY0Zqm0GSEG3Blid821-woc,1359
59
59
  aiq/cli/commands/info/list_channels.py,sha256=OVmb_BtCQiH5j2KVd0srwMUW90JUHyNIU7tqo2GdiGc,1292
60
60
  aiq/cli/commands/info/list_components.py,sha256=1qkJazV_dsoCVd4T8Vjv3F7Kg7P7xmzMjLs2o0fkpws,4483
61
+ aiq/cli/commands/info/list_mcp.py,sha256=OOTtmCUFoeWX3SslMACsDvhlu_BAf-4grIT0gf04cbs,4632
61
62
  aiq/cli/commands/registry/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
62
63
  aiq/cli/commands/registry/publish.py,sha256=uPKJ_pvHkDohvIYlGtkGSoo6KCftBtC-vRDUfmUyceE,3234
63
64
  aiq/cli/commands/registry/pull.py,sha256=jMR9NP7rV4g1WuUxGXUXjMgv0tV3UAJTKrTZvstx-Tc,4119
@@ -79,7 +80,7 @@ aiq/data_models/component.py,sha256=x6jm1Fhn1k1hGu-5AjM0ywuyvs6ztaZfapD8bLUXSqc,
79
80
  aiq/data_models/component_ref.py,sha256=GyyIf4k80aUIn6LV9r84m5imbiVhpdaY7uKMMpYpbzU,3872
80
81
  aiq/data_models/config.py,sha256=ERLjZY0iqexZ-gSXsCSN1UqgNeiwkEjWdYJEdKqeYTY,14116
81
82
  aiq/data_models/dataset_handler.py,sha256=SifWhFHtxTMEjrXaXOYQgBOSKfWOzkc6OtOoPJ39pD4,3978
82
- aiq/data_models/discovery_metadata.py,sha256=nF3SfGO_XER2bIPaSlTfXOCBbrZvWPuf0GVRUcbUXZk,11946
83
+ aiq/data_models/discovery_metadata.py,sha256=OcITQc5VeML4bTHurrsMNiK_oB3z7wudMxcyN7LI8pY,12785
83
84
  aiq/data_models/embedder.py,sha256=0v917IiohVA_7zdF7hoO_zQcmNe4hQEFhh4fxRiYBbk,940
84
85
  aiq/data_models/evaluate.py,sha256=Llu9_H840nbV_nAimcFQaTeK6oLRmGac9UKsoaLlL58,3786
85
86
  aiq/data_models/evaluator.py,sha256=bd2njsyQB2t6ClJ66gJiCjYHsQpWZwPD7rsU0J109TI,939
@@ -106,7 +107,7 @@ aiq/embedder/openai_embedder.py,sha256=5FO3xsyNvEmbLBsZb3xsCpbN1Soxio4yf4b5gTPVx
106
107
  aiq/embedder/register.py,sha256=3MTZrfNQKp6AZTbfaA-PpTnyXiMyu-8HH9JnDCC0v9o,978
107
108
  aiq/eval/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
108
109
  aiq/eval/config.py,sha256=IlOr2o618kbkXP0G1F-AklZfsKYVos9UB4Dvlxf66xk,1431
109
- aiq/eval/evaluate.py,sha256=MI7ufASKJGrdsiIVUd4jmcRxwgyZ_8dOY39uyVZKy6Y,14543
110
+ aiq/eval/evaluate.py,sha256=WPGLBeJ46mwIlnprbtia1cm2MwMqZ-GskXoTn6R4oV0,14624
110
111
  aiq/eval/intermediate_step_adapter.py,sha256=D645cfnncBEYc-LhYNwr0NwweCr1kTLENt1pLNvmVvU,4211
111
112
  aiq/eval/register.py,sha256=QOHJqA2CQixeWMC9InyKbzXo1jByvrntD_m9-2Mvg9k,1076
112
113
  aiq/eval/remote_workflow.py,sha256=Fb7Z6gdP2L_gqyWB--AEWfcXe9xPpQ_hPsf9lmqGXjI,5524
@@ -305,10 +306,10 @@ aiq/utils/reactive/base/observer_base.py,sha256=UAlyAY_ky4q2t0P81RVFo2Bs_R7z5Nde
305
306
  aiq/utils/reactive/base/subject_base.py,sha256=Ed-AC6P7cT3qkW1EXjzbd5M9WpVoeN_9KCe3OM3FLU4,2521
306
307
  aiq/utils/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
307
308
  aiq/utils/settings/global_settings.py,sha256=U9TCLdoZsKq5qOVGjREipGVv9e-FlStzqy5zv82_VYk,7454
308
- aiqtoolkit-1.1.0rc1.dist-info/licenses/LICENSE-3rd-party.txt,sha256=8o7aySJa9CBvFshPcsRdJbczzdNyDGJ8b0J67WRUQ2k,183936
309
- aiqtoolkit-1.1.0rc1.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
310
- aiqtoolkit-1.1.0rc1.dist-info/METADATA,sha256=L6nqvLQoUMRV0jjfk_p4E5SExTm_ESY6RF_LqcCGKwg,20132
311
- aiqtoolkit-1.1.0rc1.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
312
- aiqtoolkit-1.1.0rc1.dist-info/entry_points.txt,sha256=gRlPfR5g21t328WNEQ4CcEz80S1sJNS8A7rMDYnzl4A,452
313
- aiqtoolkit-1.1.0rc1.dist-info/top_level.txt,sha256=fo7AzYcNhZ_tRWrhGumtxwnxMew4xrT1iwouDy_f0Kc,4
314
- aiqtoolkit-1.1.0rc1.dist-info/RECORD,,
309
+ aiqtoolkit-1.1.0rc2.dist-info/licenses/LICENSE-3rd-party.txt,sha256=8o7aySJa9CBvFshPcsRdJbczzdNyDGJ8b0J67WRUQ2k,183936
310
+ aiqtoolkit-1.1.0rc2.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
311
+ aiqtoolkit-1.1.0rc2.dist-info/METADATA,sha256=K7cu558y6_mxK5lUhD7PdHte-yDX3Y1qDjbuRgCqwrQ,20132
312
+ aiqtoolkit-1.1.0rc2.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
313
+ aiqtoolkit-1.1.0rc2.dist-info/entry_points.txt,sha256=gRlPfR5g21t328WNEQ4CcEz80S1sJNS8A7rMDYnzl4A,452
314
+ aiqtoolkit-1.1.0rc2.dist-info/top_level.txt,sha256=fo7AzYcNhZ_tRWrhGumtxwnxMew4xrT1iwouDy_f0Kc,4
315
+ aiqtoolkit-1.1.0rc2.dist-info/RECORD,,