aiqtoolkit 1.1.0rc6__py3-none-any.whl → 1.2.0__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.

Files changed (319) hide show
  1. aiqtoolkit-1.2.0.dist-info/METADATA +29 -0
  2. aiqtoolkit-1.2.0.dist-info/RECORD +4 -0
  3. {aiqtoolkit-1.1.0rc6.dist-info → aiqtoolkit-1.2.0.dist-info}/WHEEL +1 -1
  4. aiqtoolkit-1.2.0.dist-info/top_level.txt +1 -0
  5. aiq/agent/__init__.py +0 -0
  6. aiq/agent/base.py +0 -76
  7. aiq/agent/dual_node.py +0 -67
  8. aiq/agent/react_agent/__init__.py +0 -0
  9. aiq/agent/react_agent/agent.py +0 -322
  10. aiq/agent/react_agent/output_parser.py +0 -104
  11. aiq/agent/react_agent/prompt.py +0 -46
  12. aiq/agent/react_agent/register.py +0 -148
  13. aiq/agent/reasoning_agent/__init__.py +0 -0
  14. aiq/agent/reasoning_agent/reasoning_agent.py +0 -224
  15. aiq/agent/register.py +0 -23
  16. aiq/agent/rewoo_agent/__init__.py +0 -0
  17. aiq/agent/rewoo_agent/agent.py +0 -410
  18. aiq/agent/rewoo_agent/prompt.py +0 -108
  19. aiq/agent/rewoo_agent/register.py +0 -158
  20. aiq/agent/tool_calling_agent/__init__.py +0 -0
  21. aiq/agent/tool_calling_agent/agent.py +0 -123
  22. aiq/agent/tool_calling_agent/register.py +0 -105
  23. aiq/builder/__init__.py +0 -0
  24. aiq/builder/builder.py +0 -223
  25. aiq/builder/component_utils.py +0 -303
  26. aiq/builder/context.py +0 -227
  27. aiq/builder/embedder.py +0 -24
  28. aiq/builder/eval_builder.py +0 -120
  29. aiq/builder/evaluator.py +0 -29
  30. aiq/builder/framework_enum.py +0 -24
  31. aiq/builder/front_end.py +0 -73
  32. aiq/builder/function.py +0 -297
  33. aiq/builder/function_base.py +0 -376
  34. aiq/builder/function_info.py +0 -627
  35. aiq/builder/intermediate_step_manager.py +0 -176
  36. aiq/builder/llm.py +0 -25
  37. aiq/builder/retriever.py +0 -25
  38. aiq/builder/user_interaction_manager.py +0 -71
  39. aiq/builder/workflow.py +0 -143
  40. aiq/builder/workflow_builder.py +0 -757
  41. aiq/cli/__init__.py +0 -14
  42. aiq/cli/cli_utils/__init__.py +0 -0
  43. aiq/cli/cli_utils/config_override.py +0 -231
  44. aiq/cli/cli_utils/validation.py +0 -37
  45. aiq/cli/commands/__init__.py +0 -0
  46. aiq/cli/commands/configure/__init__.py +0 -0
  47. aiq/cli/commands/configure/channel/__init__.py +0 -0
  48. aiq/cli/commands/configure/channel/add.py +0 -28
  49. aiq/cli/commands/configure/channel/channel.py +0 -36
  50. aiq/cli/commands/configure/channel/remove.py +0 -30
  51. aiq/cli/commands/configure/channel/update.py +0 -30
  52. aiq/cli/commands/configure/configure.py +0 -33
  53. aiq/cli/commands/evaluate.py +0 -139
  54. aiq/cli/commands/info/__init__.py +0 -14
  55. aiq/cli/commands/info/info.py +0 -39
  56. aiq/cli/commands/info/list_channels.py +0 -32
  57. aiq/cli/commands/info/list_components.py +0 -129
  58. aiq/cli/commands/info/list_mcp.py +0 -126
  59. aiq/cli/commands/registry/__init__.py +0 -14
  60. aiq/cli/commands/registry/publish.py +0 -88
  61. aiq/cli/commands/registry/pull.py +0 -118
  62. aiq/cli/commands/registry/registry.py +0 -38
  63. aiq/cli/commands/registry/remove.py +0 -108
  64. aiq/cli/commands/registry/search.py +0 -155
  65. aiq/cli/commands/start.py +0 -250
  66. aiq/cli/commands/uninstall.py +0 -83
  67. aiq/cli/commands/validate.py +0 -47
  68. aiq/cli/commands/workflow/__init__.py +0 -14
  69. aiq/cli/commands/workflow/templates/__init__.py.j2 +0 -0
  70. aiq/cli/commands/workflow/templates/config.yml.j2 +0 -16
  71. aiq/cli/commands/workflow/templates/pyproject.toml.j2 +0 -22
  72. aiq/cli/commands/workflow/templates/register.py.j2 +0 -5
  73. aiq/cli/commands/workflow/templates/workflow.py.j2 +0 -36
  74. aiq/cli/commands/workflow/workflow.py +0 -37
  75. aiq/cli/commands/workflow/workflow_commands.py +0 -313
  76. aiq/cli/entrypoint.py +0 -133
  77. aiq/cli/main.py +0 -44
  78. aiq/cli/register_workflow.py +0 -408
  79. aiq/cli/type_registry.py +0 -879
  80. aiq/data_models/__init__.py +0 -14
  81. aiq/data_models/api_server.py +0 -588
  82. aiq/data_models/common.py +0 -143
  83. aiq/data_models/component.py +0 -46
  84. aiq/data_models/component_ref.py +0 -135
  85. aiq/data_models/config.py +0 -349
  86. aiq/data_models/dataset_handler.py +0 -122
  87. aiq/data_models/discovery_metadata.py +0 -286
  88. aiq/data_models/embedder.py +0 -26
  89. aiq/data_models/evaluate.py +0 -104
  90. aiq/data_models/evaluator.py +0 -26
  91. aiq/data_models/front_end.py +0 -26
  92. aiq/data_models/function.py +0 -30
  93. aiq/data_models/function_dependencies.py +0 -64
  94. aiq/data_models/interactive.py +0 -237
  95. aiq/data_models/intermediate_step.py +0 -269
  96. aiq/data_models/invocation_node.py +0 -38
  97. aiq/data_models/llm.py +0 -26
  98. aiq/data_models/logging.py +0 -26
  99. aiq/data_models/memory.py +0 -26
  100. aiq/data_models/profiler.py +0 -53
  101. aiq/data_models/registry_handler.py +0 -26
  102. aiq/data_models/retriever.py +0 -30
  103. aiq/data_models/step_adaptor.py +0 -64
  104. aiq/data_models/streaming.py +0 -33
  105. aiq/data_models/swe_bench_model.py +0 -54
  106. aiq/data_models/telemetry_exporter.py +0 -26
  107. aiq/embedder/__init__.py +0 -0
  108. aiq/embedder/langchain_client.py +0 -41
  109. aiq/embedder/nim_embedder.py +0 -58
  110. aiq/embedder/openai_embedder.py +0 -42
  111. aiq/embedder/register.py +0 -24
  112. aiq/eval/__init__.py +0 -14
  113. aiq/eval/config.py +0 -42
  114. aiq/eval/dataset_handler/__init__.py +0 -0
  115. aiq/eval/dataset_handler/dataset_downloader.py +0 -106
  116. aiq/eval/dataset_handler/dataset_filter.py +0 -52
  117. aiq/eval/dataset_handler/dataset_handler.py +0 -169
  118. aiq/eval/evaluate.py +0 -325
  119. aiq/eval/evaluator/__init__.py +0 -14
  120. aiq/eval/evaluator/evaluator_model.py +0 -44
  121. aiq/eval/intermediate_step_adapter.py +0 -93
  122. aiq/eval/rag_evaluator/__init__.py +0 -0
  123. aiq/eval/rag_evaluator/evaluate.py +0 -138
  124. aiq/eval/rag_evaluator/register.py +0 -138
  125. aiq/eval/register.py +0 -23
  126. aiq/eval/remote_workflow.py +0 -128
  127. aiq/eval/runtime_event_subscriber.py +0 -52
  128. aiq/eval/swe_bench_evaluator/__init__.py +0 -0
  129. aiq/eval/swe_bench_evaluator/evaluate.py +0 -215
  130. aiq/eval/swe_bench_evaluator/register.py +0 -36
  131. aiq/eval/trajectory_evaluator/__init__.py +0 -0
  132. aiq/eval/trajectory_evaluator/evaluate.py +0 -118
  133. aiq/eval/trajectory_evaluator/register.py +0 -40
  134. aiq/eval/tunable_rag_evaluator/__init__.py +0 -0
  135. aiq/eval/tunable_rag_evaluator/evaluate.py +0 -263
  136. aiq/eval/tunable_rag_evaluator/register.py +0 -50
  137. aiq/eval/utils/__init__.py +0 -0
  138. aiq/eval/utils/output_uploader.py +0 -131
  139. aiq/eval/utils/tqdm_position_registry.py +0 -40
  140. aiq/front_ends/__init__.py +0 -14
  141. aiq/front_ends/console/__init__.py +0 -14
  142. aiq/front_ends/console/console_front_end_config.py +0 -32
  143. aiq/front_ends/console/console_front_end_plugin.py +0 -107
  144. aiq/front_ends/console/register.py +0 -25
  145. aiq/front_ends/cron/__init__.py +0 -14
  146. aiq/front_ends/fastapi/__init__.py +0 -14
  147. aiq/front_ends/fastapi/fastapi_front_end_config.py +0 -150
  148. aiq/front_ends/fastapi/fastapi_front_end_plugin.py +0 -103
  149. aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py +0 -607
  150. aiq/front_ends/fastapi/intermediate_steps_subscriber.py +0 -80
  151. aiq/front_ends/fastapi/job_store.py +0 -161
  152. aiq/front_ends/fastapi/main.py +0 -70
  153. aiq/front_ends/fastapi/message_handler.py +0 -279
  154. aiq/front_ends/fastapi/message_validator.py +0 -345
  155. aiq/front_ends/fastapi/register.py +0 -25
  156. aiq/front_ends/fastapi/response_helpers.py +0 -195
  157. aiq/front_ends/fastapi/step_adaptor.py +0 -320
  158. aiq/front_ends/fastapi/websocket.py +0 -148
  159. aiq/front_ends/mcp/__init__.py +0 -14
  160. aiq/front_ends/mcp/mcp_front_end_config.py +0 -32
  161. aiq/front_ends/mcp/mcp_front_end_plugin.py +0 -93
  162. aiq/front_ends/mcp/register.py +0 -27
  163. aiq/front_ends/mcp/tool_converter.py +0 -242
  164. aiq/front_ends/register.py +0 -22
  165. aiq/front_ends/simple_base/__init__.py +0 -14
  166. aiq/front_ends/simple_base/simple_front_end_plugin_base.py +0 -52
  167. aiq/llm/__init__.py +0 -0
  168. aiq/llm/nim_llm.py +0 -45
  169. aiq/llm/openai_llm.py +0 -45
  170. aiq/llm/register.py +0 -22
  171. aiq/llm/utils/__init__.py +0 -14
  172. aiq/llm/utils/env_config_value.py +0 -94
  173. aiq/llm/utils/error.py +0 -17
  174. aiq/memory/__init__.py +0 -20
  175. aiq/memory/interfaces.py +0 -183
  176. aiq/memory/models.py +0 -112
  177. aiq/meta/module_to_distro.json +0 -3
  178. aiq/meta/pypi.md +0 -58
  179. aiq/observability/__init__.py +0 -0
  180. aiq/observability/async_otel_listener.py +0 -429
  181. aiq/observability/register.py +0 -99
  182. aiq/plugins/.namespace +0 -1
  183. aiq/profiler/__init__.py +0 -0
  184. aiq/profiler/callbacks/__init__.py +0 -0
  185. aiq/profiler/callbacks/agno_callback_handler.py +0 -295
  186. aiq/profiler/callbacks/base_callback_class.py +0 -20
  187. aiq/profiler/callbacks/langchain_callback_handler.py +0 -278
  188. aiq/profiler/callbacks/llama_index_callback_handler.py +0 -205
  189. aiq/profiler/callbacks/semantic_kernel_callback_handler.py +0 -238
  190. aiq/profiler/callbacks/token_usage_base_model.py +0 -27
  191. aiq/profiler/data_frame_row.py +0 -51
  192. aiq/profiler/decorators/__init__.py +0 -0
  193. aiq/profiler/decorators/framework_wrapper.py +0 -131
  194. aiq/profiler/decorators/function_tracking.py +0 -254
  195. aiq/profiler/forecasting/__init__.py +0 -0
  196. aiq/profiler/forecasting/config.py +0 -18
  197. aiq/profiler/forecasting/model_trainer.py +0 -75
  198. aiq/profiler/forecasting/models/__init__.py +0 -22
  199. aiq/profiler/forecasting/models/forecasting_base_model.py +0 -40
  200. aiq/profiler/forecasting/models/linear_model.py +0 -196
  201. aiq/profiler/forecasting/models/random_forest_regressor.py +0 -268
  202. aiq/profiler/inference_metrics_model.py +0 -25
  203. aiq/profiler/inference_optimization/__init__.py +0 -0
  204. aiq/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
  205. aiq/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +0 -452
  206. aiq/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +0 -258
  207. aiq/profiler/inference_optimization/data_models.py +0 -386
  208. aiq/profiler/inference_optimization/experimental/__init__.py +0 -0
  209. aiq/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +0 -468
  210. aiq/profiler/inference_optimization/experimental/prefix_span_analysis.py +0 -405
  211. aiq/profiler/inference_optimization/llm_metrics.py +0 -212
  212. aiq/profiler/inference_optimization/prompt_caching.py +0 -163
  213. aiq/profiler/inference_optimization/token_uniqueness.py +0 -107
  214. aiq/profiler/inference_optimization/workflow_runtimes.py +0 -72
  215. aiq/profiler/intermediate_property_adapter.py +0 -102
  216. aiq/profiler/profile_runner.py +0 -433
  217. aiq/profiler/utils.py +0 -184
  218. aiq/registry_handlers/__init__.py +0 -0
  219. aiq/registry_handlers/local/__init__.py +0 -0
  220. aiq/registry_handlers/local/local_handler.py +0 -176
  221. aiq/registry_handlers/local/register_local.py +0 -37
  222. aiq/registry_handlers/metadata_factory.py +0 -60
  223. aiq/registry_handlers/package_utils.py +0 -198
  224. aiq/registry_handlers/pypi/__init__.py +0 -0
  225. aiq/registry_handlers/pypi/pypi_handler.py +0 -251
  226. aiq/registry_handlers/pypi/register_pypi.py +0 -40
  227. aiq/registry_handlers/register.py +0 -21
  228. aiq/registry_handlers/registry_handler_base.py +0 -157
  229. aiq/registry_handlers/rest/__init__.py +0 -0
  230. aiq/registry_handlers/rest/register_rest.py +0 -56
  231. aiq/registry_handlers/rest/rest_handler.py +0 -237
  232. aiq/registry_handlers/schemas/__init__.py +0 -0
  233. aiq/registry_handlers/schemas/headers.py +0 -42
  234. aiq/registry_handlers/schemas/package.py +0 -68
  235. aiq/registry_handlers/schemas/publish.py +0 -63
  236. aiq/registry_handlers/schemas/pull.py +0 -82
  237. aiq/registry_handlers/schemas/remove.py +0 -36
  238. aiq/registry_handlers/schemas/search.py +0 -91
  239. aiq/registry_handlers/schemas/status.py +0 -47
  240. aiq/retriever/__init__.py +0 -0
  241. aiq/retriever/interface.py +0 -37
  242. aiq/retriever/milvus/__init__.py +0 -14
  243. aiq/retriever/milvus/register.py +0 -81
  244. aiq/retriever/milvus/retriever.py +0 -228
  245. aiq/retriever/models.py +0 -74
  246. aiq/retriever/nemo_retriever/__init__.py +0 -14
  247. aiq/retriever/nemo_retriever/register.py +0 -60
  248. aiq/retriever/nemo_retriever/retriever.py +0 -190
  249. aiq/retriever/register.py +0 -22
  250. aiq/runtime/__init__.py +0 -14
  251. aiq/runtime/loader.py +0 -188
  252. aiq/runtime/runner.py +0 -176
  253. aiq/runtime/session.py +0 -140
  254. aiq/runtime/user_metadata.py +0 -131
  255. aiq/settings/__init__.py +0 -0
  256. aiq/settings/global_settings.py +0 -318
  257. aiq/test/.namespace +0 -1
  258. aiq/tool/__init__.py +0 -0
  259. aiq/tool/code_execution/__init__.py +0 -0
  260. aiq/tool/code_execution/code_sandbox.py +0 -188
  261. aiq/tool/code_execution/local_sandbox/Dockerfile.sandbox +0 -60
  262. aiq/tool/code_execution/local_sandbox/__init__.py +0 -13
  263. aiq/tool/code_execution/local_sandbox/local_sandbox_server.py +0 -83
  264. aiq/tool/code_execution/local_sandbox/sandbox.requirements.txt +0 -4
  265. aiq/tool/code_execution/local_sandbox/start_local_sandbox.sh +0 -25
  266. aiq/tool/code_execution/register.py +0 -70
  267. aiq/tool/code_execution/utils.py +0 -100
  268. aiq/tool/datetime_tools.py +0 -42
  269. aiq/tool/document_search.py +0 -141
  270. aiq/tool/github_tools/__init__.py +0 -0
  271. aiq/tool/github_tools/create_github_commit.py +0 -133
  272. aiq/tool/github_tools/create_github_issue.py +0 -87
  273. aiq/tool/github_tools/create_github_pr.py +0 -106
  274. aiq/tool/github_tools/get_github_file.py +0 -106
  275. aiq/tool/github_tools/get_github_issue.py +0 -166
  276. aiq/tool/github_tools/get_github_pr.py +0 -256
  277. aiq/tool/github_tools/update_github_issue.py +0 -100
  278. aiq/tool/mcp/__init__.py +0 -14
  279. aiq/tool/mcp/mcp_client.py +0 -220
  280. aiq/tool/mcp/mcp_tool.py +0 -95
  281. aiq/tool/memory_tools/__init__.py +0 -0
  282. aiq/tool/memory_tools/add_memory_tool.py +0 -79
  283. aiq/tool/memory_tools/delete_memory_tool.py +0 -67
  284. aiq/tool/memory_tools/get_memory_tool.py +0 -72
  285. aiq/tool/nvidia_rag.py +0 -95
  286. aiq/tool/register.py +0 -37
  287. aiq/tool/retriever.py +0 -89
  288. aiq/tool/server_tools.py +0 -63
  289. aiq/utils/__init__.py +0 -0
  290. aiq/utils/data_models/__init__.py +0 -0
  291. aiq/utils/data_models/schema_validator.py +0 -58
  292. aiq/utils/debugging_utils.py +0 -43
  293. aiq/utils/exception_handlers/__init__.py +0 -0
  294. aiq/utils/exception_handlers/schemas.py +0 -114
  295. aiq/utils/io/__init__.py +0 -0
  296. aiq/utils/io/yaml_tools.py +0 -119
  297. aiq/utils/metadata_utils.py +0 -74
  298. aiq/utils/optional_imports.py +0 -142
  299. aiq/utils/producer_consumer_queue.py +0 -178
  300. aiq/utils/reactive/__init__.py +0 -0
  301. aiq/utils/reactive/base/__init__.py +0 -0
  302. aiq/utils/reactive/base/observable_base.py +0 -65
  303. aiq/utils/reactive/base/observer_base.py +0 -55
  304. aiq/utils/reactive/base/subject_base.py +0 -79
  305. aiq/utils/reactive/observable.py +0 -59
  306. aiq/utils/reactive/observer.py +0 -76
  307. aiq/utils/reactive/subject.py +0 -131
  308. aiq/utils/reactive/subscription.py +0 -49
  309. aiq/utils/settings/__init__.py +0 -0
  310. aiq/utils/settings/global_settings.py +0 -197
  311. aiq/utils/type_converter.py +0 -232
  312. aiq/utils/type_utils.py +0 -397
  313. aiq/utils/url_utils.py +0 -27
  314. aiqtoolkit-1.1.0rc6.dist-info/METADATA +0 -331
  315. aiqtoolkit-1.1.0rc6.dist-info/RECORD +0 -316
  316. aiqtoolkit-1.1.0rc6.dist-info/entry_points.txt +0 -17
  317. aiqtoolkit-1.1.0rc6.dist-info/licenses/LICENSE-3rd-party.txt +0 -3686
  318. aiqtoolkit-1.1.0rc6.dist-info/licenses/LICENSE.md +0 -201
  319. aiqtoolkit-1.1.0rc6.dist-info/top_level.txt +0 -1
@@ -1,190 +0,0 @@
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
- import os
19
- import typing
20
- from functools import partial
21
- from urllib.parse import urljoin
22
-
23
- import httpx
24
- from langchain_core.retrievers import BaseRetriever
25
- from pydantic import BaseModel
26
- from pydantic import Field
27
- from pydantic import HttpUrl
28
-
29
- from aiq.retriever.interface import AIQRetriever
30
- from aiq.retriever.models import AIQDocument
31
- from aiq.retriever.models import RetrieverError
32
- from aiq.retriever.models import RetrieverOutput
33
-
34
- logger = logging.getLogger(__name__)
35
-
36
-
37
- class Collection(BaseModel):
38
- id: str
39
- name: str
40
- meta: typing.Any
41
- pipeline: str
42
- created_at: str
43
-
44
-
45
- class RetrieverPayload(BaseModel):
46
- query: str
47
- top_k: int = Field(le=50, gt=0)
48
-
49
-
50
- class CollectionUnavailableError(RetrieverError):
51
- pass
52
-
53
-
54
- class NemoRetriever(AIQRetriever):
55
- """
56
- Client for retrieving document chunks from a Nemo Retriever service.
57
- """
58
-
59
- def __init__(self, uri: str | HttpUrl, timeout: int = 60, nvidia_api_key: str = None, **kwargs):
60
-
61
- self.base_url = str(uri)
62
- self.timeout = timeout
63
- self._search_func = self._search
64
- self.api_key = nvidia_api_key if nvidia_api_key else os.getenv('NVIDIA_API_KEY')
65
- self._bound_params = []
66
- if not self.api_key:
67
- logger.warning("No API key was specified as part of configuration or as an environment variable.")
68
-
69
- def bind(self, **kwargs) -> None:
70
- """
71
- Bind default values to the search method. Cannot bind the 'query' parameter.
72
-
73
- Args:
74
- kwargs (dict): Key value pairs corresponding to the default values of search parameters.
75
- """
76
- if "query" in kwargs:
77
- kwargs = {k: v for k, v in kwargs.items() if k != "query"}
78
- self._search_func = partial(self._search_func, **kwargs)
79
- self._bound_params = list(kwargs.keys())
80
- logger.debug("Binding paramaters for search function: %s", kwargs)
81
-
82
- def get_unbound_params(self) -> list[str]:
83
- """
84
- Returns a list of unbound parameters which will need to be passed to the search function.
85
- """
86
- return [param for param in ["query", "collection_name", "top_k"] if param not in self._bound_params]
87
-
88
- async def get_collections(self, client) -> list[Collection]:
89
- """
90
- Get a list of all available collections as pydantic `Collection` objects
91
- """
92
- collection_response = await client.get(urljoin(self.base_url, "/v1/collections"))
93
- collection_response.raise_for_status()
94
- if not collection_response or len(collection_response.json().get('collections', [])) == 0:
95
- raise CollectionUnavailableError(f"No collections available at {self.base_url}")
96
-
97
- collections = [
98
- Collection.model_validate(collection) for collection in collection_response.json()["collections"]
99
- ]
100
-
101
- return collections
102
-
103
- async def get_collection_by_name(self, collection_name, client) -> Collection:
104
- """
105
- Retrieve a collection using it's name. Will return the first collection found if the name is ambiguous.
106
- """
107
- collections = await self.get_collections(client)
108
- if (collection := next((c for c in collections if c.name == collection_name), None)) is None:
109
- raise CollectionUnavailableError(f"Collection {collection_name} not found")
110
- return collection
111
-
112
- async def search(self, query: str, **kwargs):
113
- return await self._search_func(query=query, **kwargs)
114
-
115
- async def _search(
116
- self,
117
- query: str,
118
- collection_name: str,
119
- top_k: str,
120
- output_fields: list[str] = None,
121
- ):
122
- """
123
- Retrieve document chunks from the configured Nemo Retriever Service.
124
- """
125
- output = []
126
- try:
127
- async with httpx.AsyncClient(headers={"Authorization": f"Bearer {self.api_key}"},
128
- timeout=self.timeout) as client:
129
- collection = await self.get_collection_by_name(collection_name, client)
130
- url = urljoin(self.base_url, f"/v1/collections/{collection.id}/search")
131
-
132
- payload = RetrieverPayload(query=query, top_k=top_k)
133
- response = await client.post(url, content=json.dumps(payload.model_dump(mode="python")))
134
-
135
- logger.debug("response.status_code=%s", response.status_code)
136
-
137
- response.raise_for_status()
138
- output = response.json().get("chunks")
139
-
140
- # Handle output fields
141
- output = [_flatten(chunk, output_fields) for chunk in output]
142
-
143
- return _wrap_nemo_results(output=output, content_field="content")
144
-
145
- except Exception as e:
146
- logger.exception("Encountered an error when retrieving results from Nemo Retriever: %s", e)
147
- raise CollectionUnavailableError(
148
- f"Error when retrieving documents from {collection_name} for query '{query}'") from e
149
-
150
-
151
- def _wrap_nemo_results(output: list[dict], content_field: str):
152
- return RetrieverOutput(results=[_wrap_nemo_single_results(o, content_field=content_field) for o in output])
153
-
154
-
155
- def _wrap_nemo_single_results(output: dict, content_field: str):
156
- return AIQDocument(page_content=output[content_field],
157
- metadata={
158
- k: v
159
- for k, v in output.items() if k != content_field
160
- })
161
-
162
-
163
- def _flatten(obj: dict, output_fields: list[str]) -> list[str]:
164
- base_fields = [
165
- "format",
166
- "id",
167
- ]
168
- if not output_fields:
169
- output_fields = [
170
- "format",
171
- "id",
172
- ]
173
- output_fields.extend(list(obj["metadata"].keys()))
174
- data = {"content": obj.get("content")}
175
- for field in base_fields:
176
- if field in output_fields:
177
- data.update({field: obj[field]})
178
-
179
- data.update({k: v for k, v in obj['metadata'].items() if k in output_fields})
180
- return data
181
-
182
-
183
- class NemoLangchainRetriever(BaseRetriever, BaseModel):
184
- client: NemoRetriever
185
-
186
- def _get_relevant_documents(self, query, *, run_manager, **kwargs):
187
- raise NotImplementedError
188
-
189
- async def _aget_relevant_documents(self, query, *, run_manager, **kwargs):
190
- return await self.client.search(query, **kwargs)
aiq/retriever/register.py DELETED
@@ -1,22 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-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
- # pylint: disable=unused-import
17
- # flake8: noqa
18
- # isort:skip_file
19
-
20
- # Import any providers which need to be automatically registered here
21
- import aiq.retriever.milvus.register
22
- import aiq.retriever.nemo_retriever.register
aiq/runtime/__init__.py DELETED
@@ -1,14 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-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.
aiq/runtime/loader.py DELETED
@@ -1,188 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-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
- from __future__ import annotations
17
-
18
- import importlib.metadata
19
- import logging
20
- import time
21
- from contextlib import asynccontextmanager
22
- from enum import IntFlag
23
- from enum import auto
24
- from functools import reduce
25
-
26
- from aiq.builder.workflow_builder import WorkflowBuilder
27
- from aiq.cli.type_registry import GlobalTypeRegistry
28
- from aiq.data_models.config import AIQConfig
29
- from aiq.runtime.session import AIQSessionManager
30
- from aiq.utils.data_models.schema_validator import validate_schema
31
- from aiq.utils.debugging_utils import is_debugger_attached
32
- from aiq.utils.io.yaml_tools import yaml_load
33
- from aiq.utils.type_utils import StrPath
34
-
35
- logger = logging.getLogger(__name__)
36
-
37
-
38
- class PluginTypes(IntFlag):
39
- COMPONENT = auto()
40
- """
41
- A plugin that is a component of the workflow. This includes tools, LLMs, retrievers, etc.
42
- """
43
- FRONT_END = auto()
44
- """
45
- A plugin that is a front end for the workflow. This includes FastAPI, Gradio, etc.
46
- """
47
- EVALUATOR = auto()
48
- """
49
- A plugin that is an evaluator for the workflow. This includes evaluators like RAGAS, SWE-bench, etc.
50
- """
51
- REGISTRY_HANDLER = auto()
52
-
53
- # Convenience flag for groups of plugin types
54
- CONFIG_OBJECT = COMPONENT | FRONT_END | EVALUATOR
55
- """
56
- Any plugin that can be specified in the AIQ Toolkit configuration file.
57
- """
58
- ALL = COMPONENT | FRONT_END | EVALUATOR | REGISTRY_HANDLER
59
- """
60
- All plugin types
61
- """
62
-
63
-
64
- def load_config(config_file: StrPath) -> AIQConfig:
65
- """
66
- This is the primary entry point for loading an AIQ Toolkit configuration file. It ensures that all plugins are
67
- loaded and then validates the configuration file against the AIQConfig schema.
68
-
69
- Parameters
70
- ----------
71
- config_file : StrPath
72
- The path to the configuration file
73
-
74
- Returns
75
- -------
76
- AIQConfig
77
- The validated AIQConfig object
78
- """
79
-
80
- # Ensure all of the plugins are loaded
81
- discover_and_register_plugins(PluginTypes.CONFIG_OBJECT)
82
-
83
- config_yaml = yaml_load(config_file)
84
-
85
- # Validate configuration adheres to AIQ Toolkit schemas
86
- validated_aiq_config = validate_schema(config_yaml, AIQConfig)
87
-
88
- return validated_aiq_config
89
-
90
-
91
- @asynccontextmanager
92
- async def load_workflow(config_file: StrPath, max_concurrency: int = -1):
93
- """
94
- Load the AIQ Toolkit configuration file and create an AIQRunner object. This is the primary entry point for running
95
- AIQ Toolkit workflows.
96
-
97
- Parameters
98
- ----------
99
- config_file : StrPath
100
- The path to the configuration file
101
- max_concurrency : int, optional
102
- The maximum number of parallel workflow invocations to support. Specifying 0 or -1 will allow an unlimited
103
- count, by default -1
104
- """
105
-
106
- # Load the config object
107
- config = load_config(config_file)
108
-
109
- # Must yield the workflow function otherwise it cleans up
110
- async with WorkflowBuilder.from_config(config=config) as workflow:
111
-
112
- yield AIQSessionManager(workflow.build(), max_concurrency=max_concurrency)
113
-
114
-
115
- def discover_entrypoints(plugin_type: PluginTypes):
116
- """
117
- Discover all the requested plugin types which were registered via an entry point group and return them.
118
- """
119
-
120
- entry_points = importlib.metadata.entry_points()
121
-
122
- plugin_groups = []
123
-
124
- # Add the specified plugin type to the list of groups to load
125
- if (plugin_type & PluginTypes.COMPONENT):
126
- plugin_groups.extend(["aiq.plugins", "aiq.components"])
127
- if (plugin_type & PluginTypes.FRONT_END):
128
- plugin_groups.append("aiq.front_ends")
129
- if (plugin_type & PluginTypes.REGISTRY_HANDLER):
130
- plugin_groups.append("aiq.registry_handlers")
131
- if (plugin_type & PluginTypes.EVALUATOR):
132
- plugin_groups.append("aiq.evaluators")
133
-
134
- # Get the entry points for the specified groups
135
- aiq_plugins = reduce(lambda x, y: x + y, [entry_points.select(group=y) for y in plugin_groups])
136
-
137
- return aiq_plugins
138
-
139
-
140
- def discover_and_register_plugins(plugin_type: PluginTypes):
141
- """
142
- Discover all the requested plugin types which were registered via an entry point group and register them into the
143
- GlobalTypeRegistry.
144
- """
145
-
146
- # Get the entry points for the specified groups
147
- aiq_plugins = discover_entrypoints(plugin_type)
148
-
149
- count = 0
150
-
151
- # Pause registration hooks for performance. This is useful when loading a large number of plugins.
152
- with GlobalTypeRegistry.get().pause_registration_changed_hooks():
153
-
154
- for entry_point in aiq_plugins:
155
- try:
156
- logger.debug("Loading module '%s' from entry point '%s'...", entry_point.module, entry_point.name)
157
-
158
- start_time = time.time()
159
-
160
- entry_point.load()
161
-
162
- elapsed_time = (time.time() - start_time) * 1000
163
-
164
- logger.debug("Loading module '%s' from entry point '%s'...Complete (%f ms)",
165
- entry_point.module,
166
- entry_point.name,
167
- elapsed_time)
168
-
169
- # Log a warning if the plugin took a long time to load. This can be useful for debugging slow imports.
170
- # The threshold is 300 ms if no plugins have been loaded yet, and 100 ms otherwise. Triple the threshold
171
- # if a debugger is attached.
172
- if (elapsed_time > (300.0 if count == 0 else 100.0) * (3 if is_debugger_attached() else 1)):
173
- logger.warning(
174
- "Loading module '%s' from entry point '%s' took a long time (%f ms). "
175
- "Ensure all imports are inside your registered functions.",
176
- entry_point.module,
177
- entry_point.name,
178
- elapsed_time)
179
-
180
- except ImportError:
181
- logger.warning("Failed to import plugin '%s'", entry_point.name, exc_info=True)
182
- # Optionally, you can mark the plugin as unavailable or take other actions
183
-
184
- except Exception:
185
- logger.exception("An error occurred while loading plugin '%s': {e}", entry_point.name, exc_info=True)
186
-
187
- finally:
188
- count += 1
aiq/runtime/runner.py DELETED
@@ -1,176 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-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 logging
17
- import typing
18
- from enum import Enum
19
-
20
- from aiq.builder.context import AIQContext
21
- from aiq.builder.context import AIQContextState
22
- from aiq.builder.function import Function
23
- from aiq.data_models.invocation_node import InvocationNode
24
- from aiq.observability.async_otel_listener import AsyncOtelSpanListener
25
- from aiq.utils.reactive.subject import Subject
26
-
27
- logger = logging.getLogger(__name__)
28
-
29
-
30
- class UserManagerBase:
31
- pass
32
-
33
-
34
- class AIQRunnerState(Enum):
35
- UNINITIALIZED = 0
36
- INITIALIZED = 1
37
- RUNNING = 2
38
- COMPLETED = 3
39
- FAILED = 4
40
-
41
-
42
- _T = typing.TypeVar("_T")
43
-
44
-
45
- class AIQRunner:
46
-
47
- def __init__(self, input_message: typing.Any, entry_fn: Function, context_state: AIQContextState):
48
- """
49
- The AIQRunner class is used to run a workflow. It handles converting input and output data types and running the
50
- workflow with the specified concurrency.
51
-
52
- Parameters
53
- ----------
54
- input_message : typing.Any
55
- The input message to the workflow
56
- entry_fn : Function
57
- The entry function to the workflow
58
- context_state : AIQContextState
59
- The context state to use
60
- """
61
-
62
- if (entry_fn is None):
63
- raise ValueError("entry_fn cannot be None")
64
-
65
- self._entry_fn = entry_fn
66
- self._context_state = context_state
67
- self._context = AIQContext(self._context_state)
68
-
69
- self._state = AIQRunnerState.UNINITIALIZED
70
-
71
- self._input_message_token = None
72
-
73
- # Before we start, we need to convert the input message to the workflow input type
74
- self._input_message = input_message
75
-
76
- self._span_manager = AsyncOtelSpanListener(context_state=context_state)
77
-
78
- @property
79
- def context(self) -> AIQContext:
80
- return self._context
81
-
82
- def convert(self, value: typing.Any, to_type: type[_T]) -> _T:
83
- return self._entry_fn.convert(value, to_type)
84
-
85
- async def __aenter__(self):
86
-
87
- # Set the input message on the context
88
- self._input_message_token = self._context_state.input_message.set(self._input_message)
89
-
90
- # Create reactive event stream
91
- self._context_state.event_stream.set(Subject())
92
- self._context_state.active_function.set(InvocationNode(
93
- function_name="root",
94
- function_id="root",
95
- ))
96
-
97
- if (self._state == AIQRunnerState.UNINITIALIZED):
98
- self._state = AIQRunnerState.INITIALIZED
99
- else:
100
- raise ValueError("Cannot enter the context more than once")
101
-
102
- return self
103
-
104
- async def __aexit__(self, exc_type, exc_value, traceback):
105
-
106
- if (self._input_message_token is None):
107
- raise ValueError("Cannot exit the context without entering it")
108
-
109
- self._context_state.input_message.reset(self._input_message_token)
110
-
111
- if (self._state not in (AIQRunnerState.COMPLETED, AIQRunnerState.FAILED)):
112
- raise ValueError("Cannot exit the context without completing the workflow")
113
-
114
- @typing.overload
115
- async def result(self) -> typing.Any:
116
- ...
117
-
118
- @typing.overload
119
- async def result(self, to_type: type[_T]) -> _T:
120
- ...
121
-
122
- async def result(self, to_type: type | None = None):
123
-
124
- if (self._state != AIQRunnerState.INITIALIZED):
125
- raise ValueError("Cannot run the workflow without entering the context")
126
-
127
- try:
128
- self._state = AIQRunnerState.RUNNING
129
-
130
- if (not self._entry_fn.has_single_output):
131
- raise ValueError("Workflow does not support single output")
132
-
133
- async with self._span_manager.start():
134
- # Run the workflow
135
- result = await self._entry_fn.ainvoke(self._input_message, to_type=to_type)
136
-
137
- # Close the intermediate stream
138
- self._context_state.event_stream.get().on_complete()
139
-
140
- self._state = AIQRunnerState.COMPLETED
141
-
142
- return result
143
- except Exception as e:
144
- logger.exception("Error running workflow: %s", e)
145
- self._context_state.event_stream.get().on_complete()
146
- self._state = AIQRunnerState.FAILED
147
-
148
- raise
149
-
150
- async def result_stream(self, to_type: type | None = None):
151
-
152
- if (self._state != AIQRunnerState.INITIALIZED):
153
- raise ValueError("Cannot run the workflow without entering the context")
154
-
155
- try:
156
- self._state = AIQRunnerState.RUNNING
157
-
158
- if (not self._entry_fn.has_streaming_output):
159
- raise ValueError("Workflow does not support streaming output")
160
-
161
- # Run the workflow
162
- async with self._span_manager.start():
163
- async for m in self._entry_fn.astream(self._input_message, to_type=to_type):
164
- yield m
165
-
166
- self._state = AIQRunnerState.COMPLETED
167
-
168
- # Close the intermediate stream
169
- self._context_state.event_stream.get().on_complete()
170
-
171
- except Exception as e:
172
- logger.exception("Error running workflow: %s", e)
173
- self._context_state.event_stream.get().on_complete()
174
- self._state = AIQRunnerState.FAILED
175
-
176
- raise