aiqtoolkit 1.1.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 (316) hide show
  1. aiq/agent/__init__.py +0 -0
  2. aiq/agent/base.py +76 -0
  3. aiq/agent/dual_node.py +67 -0
  4. aiq/agent/react_agent/__init__.py +0 -0
  5. aiq/agent/react_agent/agent.py +322 -0
  6. aiq/agent/react_agent/output_parser.py +104 -0
  7. aiq/agent/react_agent/prompt.py +46 -0
  8. aiq/agent/react_agent/register.py +148 -0
  9. aiq/agent/reasoning_agent/__init__.py +0 -0
  10. aiq/agent/reasoning_agent/reasoning_agent.py +224 -0
  11. aiq/agent/register.py +23 -0
  12. aiq/agent/rewoo_agent/__init__.py +0 -0
  13. aiq/agent/rewoo_agent/agent.py +410 -0
  14. aiq/agent/rewoo_agent/prompt.py +108 -0
  15. aiq/agent/rewoo_agent/register.py +158 -0
  16. aiq/agent/tool_calling_agent/__init__.py +0 -0
  17. aiq/agent/tool_calling_agent/agent.py +123 -0
  18. aiq/agent/tool_calling_agent/register.py +105 -0
  19. aiq/builder/__init__.py +0 -0
  20. aiq/builder/builder.py +223 -0
  21. aiq/builder/component_utils.py +303 -0
  22. aiq/builder/context.py +227 -0
  23. aiq/builder/embedder.py +24 -0
  24. aiq/builder/eval_builder.py +120 -0
  25. aiq/builder/evaluator.py +29 -0
  26. aiq/builder/framework_enum.py +24 -0
  27. aiq/builder/front_end.py +73 -0
  28. aiq/builder/function.py +297 -0
  29. aiq/builder/function_base.py +376 -0
  30. aiq/builder/function_info.py +627 -0
  31. aiq/builder/intermediate_step_manager.py +176 -0
  32. aiq/builder/llm.py +25 -0
  33. aiq/builder/retriever.py +25 -0
  34. aiq/builder/user_interaction_manager.py +71 -0
  35. aiq/builder/workflow.py +143 -0
  36. aiq/builder/workflow_builder.py +757 -0
  37. aiq/cli/__init__.py +14 -0
  38. aiq/cli/cli_utils/__init__.py +0 -0
  39. aiq/cli/cli_utils/config_override.py +231 -0
  40. aiq/cli/cli_utils/validation.py +37 -0
  41. aiq/cli/commands/__init__.py +0 -0
  42. aiq/cli/commands/configure/__init__.py +0 -0
  43. aiq/cli/commands/configure/channel/__init__.py +0 -0
  44. aiq/cli/commands/configure/channel/add.py +28 -0
  45. aiq/cli/commands/configure/channel/channel.py +36 -0
  46. aiq/cli/commands/configure/channel/remove.py +30 -0
  47. aiq/cli/commands/configure/channel/update.py +30 -0
  48. aiq/cli/commands/configure/configure.py +33 -0
  49. aiq/cli/commands/evaluate.py +139 -0
  50. aiq/cli/commands/info/__init__.py +14 -0
  51. aiq/cli/commands/info/info.py +39 -0
  52. aiq/cli/commands/info/list_channels.py +32 -0
  53. aiq/cli/commands/info/list_components.py +129 -0
  54. aiq/cli/commands/info/list_mcp.py +126 -0
  55. aiq/cli/commands/registry/__init__.py +14 -0
  56. aiq/cli/commands/registry/publish.py +88 -0
  57. aiq/cli/commands/registry/pull.py +118 -0
  58. aiq/cli/commands/registry/registry.py +38 -0
  59. aiq/cli/commands/registry/remove.py +108 -0
  60. aiq/cli/commands/registry/search.py +155 -0
  61. aiq/cli/commands/start.py +250 -0
  62. aiq/cli/commands/uninstall.py +83 -0
  63. aiq/cli/commands/validate.py +47 -0
  64. aiq/cli/commands/workflow/__init__.py +14 -0
  65. aiq/cli/commands/workflow/templates/__init__.py.j2 +0 -0
  66. aiq/cli/commands/workflow/templates/config.yml.j2 +16 -0
  67. aiq/cli/commands/workflow/templates/pyproject.toml.j2 +22 -0
  68. aiq/cli/commands/workflow/templates/register.py.j2 +5 -0
  69. aiq/cli/commands/workflow/templates/workflow.py.j2 +36 -0
  70. aiq/cli/commands/workflow/workflow.py +37 -0
  71. aiq/cli/commands/workflow/workflow_commands.py +313 -0
  72. aiq/cli/entrypoint.py +133 -0
  73. aiq/cli/main.py +44 -0
  74. aiq/cli/register_workflow.py +408 -0
  75. aiq/cli/type_registry.py +879 -0
  76. aiq/data_models/__init__.py +14 -0
  77. aiq/data_models/api_server.py +588 -0
  78. aiq/data_models/common.py +143 -0
  79. aiq/data_models/component.py +46 -0
  80. aiq/data_models/component_ref.py +135 -0
  81. aiq/data_models/config.py +349 -0
  82. aiq/data_models/dataset_handler.py +122 -0
  83. aiq/data_models/discovery_metadata.py +286 -0
  84. aiq/data_models/embedder.py +26 -0
  85. aiq/data_models/evaluate.py +104 -0
  86. aiq/data_models/evaluator.py +26 -0
  87. aiq/data_models/front_end.py +26 -0
  88. aiq/data_models/function.py +30 -0
  89. aiq/data_models/function_dependencies.py +64 -0
  90. aiq/data_models/interactive.py +237 -0
  91. aiq/data_models/intermediate_step.py +269 -0
  92. aiq/data_models/invocation_node.py +38 -0
  93. aiq/data_models/llm.py +26 -0
  94. aiq/data_models/logging.py +26 -0
  95. aiq/data_models/memory.py +26 -0
  96. aiq/data_models/profiler.py +53 -0
  97. aiq/data_models/registry_handler.py +26 -0
  98. aiq/data_models/retriever.py +30 -0
  99. aiq/data_models/step_adaptor.py +64 -0
  100. aiq/data_models/streaming.py +33 -0
  101. aiq/data_models/swe_bench_model.py +54 -0
  102. aiq/data_models/telemetry_exporter.py +26 -0
  103. aiq/embedder/__init__.py +0 -0
  104. aiq/embedder/langchain_client.py +41 -0
  105. aiq/embedder/nim_embedder.py +58 -0
  106. aiq/embedder/openai_embedder.py +42 -0
  107. aiq/embedder/register.py +24 -0
  108. aiq/eval/__init__.py +14 -0
  109. aiq/eval/config.py +42 -0
  110. aiq/eval/dataset_handler/__init__.py +0 -0
  111. aiq/eval/dataset_handler/dataset_downloader.py +106 -0
  112. aiq/eval/dataset_handler/dataset_filter.py +52 -0
  113. aiq/eval/dataset_handler/dataset_handler.py +169 -0
  114. aiq/eval/evaluate.py +325 -0
  115. aiq/eval/evaluator/__init__.py +14 -0
  116. aiq/eval/evaluator/evaluator_model.py +44 -0
  117. aiq/eval/intermediate_step_adapter.py +93 -0
  118. aiq/eval/rag_evaluator/__init__.py +0 -0
  119. aiq/eval/rag_evaluator/evaluate.py +138 -0
  120. aiq/eval/rag_evaluator/register.py +138 -0
  121. aiq/eval/register.py +23 -0
  122. aiq/eval/remote_workflow.py +128 -0
  123. aiq/eval/runtime_event_subscriber.py +52 -0
  124. aiq/eval/swe_bench_evaluator/__init__.py +0 -0
  125. aiq/eval/swe_bench_evaluator/evaluate.py +215 -0
  126. aiq/eval/swe_bench_evaluator/register.py +36 -0
  127. aiq/eval/trajectory_evaluator/__init__.py +0 -0
  128. aiq/eval/trajectory_evaluator/evaluate.py +118 -0
  129. aiq/eval/trajectory_evaluator/register.py +40 -0
  130. aiq/eval/tunable_rag_evaluator/__init__.py +0 -0
  131. aiq/eval/tunable_rag_evaluator/evaluate.py +263 -0
  132. aiq/eval/tunable_rag_evaluator/register.py +50 -0
  133. aiq/eval/utils/__init__.py +0 -0
  134. aiq/eval/utils/output_uploader.py +131 -0
  135. aiq/eval/utils/tqdm_position_registry.py +40 -0
  136. aiq/front_ends/__init__.py +14 -0
  137. aiq/front_ends/console/__init__.py +14 -0
  138. aiq/front_ends/console/console_front_end_config.py +32 -0
  139. aiq/front_ends/console/console_front_end_plugin.py +107 -0
  140. aiq/front_ends/console/register.py +25 -0
  141. aiq/front_ends/cron/__init__.py +14 -0
  142. aiq/front_ends/fastapi/__init__.py +14 -0
  143. aiq/front_ends/fastapi/fastapi_front_end_config.py +150 -0
  144. aiq/front_ends/fastapi/fastapi_front_end_plugin.py +103 -0
  145. aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py +607 -0
  146. aiq/front_ends/fastapi/intermediate_steps_subscriber.py +80 -0
  147. aiq/front_ends/fastapi/job_store.py +161 -0
  148. aiq/front_ends/fastapi/main.py +70 -0
  149. aiq/front_ends/fastapi/message_handler.py +279 -0
  150. aiq/front_ends/fastapi/message_validator.py +345 -0
  151. aiq/front_ends/fastapi/register.py +25 -0
  152. aiq/front_ends/fastapi/response_helpers.py +195 -0
  153. aiq/front_ends/fastapi/step_adaptor.py +320 -0
  154. aiq/front_ends/fastapi/websocket.py +148 -0
  155. aiq/front_ends/mcp/__init__.py +14 -0
  156. aiq/front_ends/mcp/mcp_front_end_config.py +32 -0
  157. aiq/front_ends/mcp/mcp_front_end_plugin.py +93 -0
  158. aiq/front_ends/mcp/register.py +27 -0
  159. aiq/front_ends/mcp/tool_converter.py +242 -0
  160. aiq/front_ends/register.py +22 -0
  161. aiq/front_ends/simple_base/__init__.py +14 -0
  162. aiq/front_ends/simple_base/simple_front_end_plugin_base.py +52 -0
  163. aiq/llm/__init__.py +0 -0
  164. aiq/llm/nim_llm.py +45 -0
  165. aiq/llm/openai_llm.py +45 -0
  166. aiq/llm/register.py +22 -0
  167. aiq/llm/utils/__init__.py +14 -0
  168. aiq/llm/utils/env_config_value.py +94 -0
  169. aiq/llm/utils/error.py +17 -0
  170. aiq/memory/__init__.py +20 -0
  171. aiq/memory/interfaces.py +183 -0
  172. aiq/memory/models.py +112 -0
  173. aiq/meta/module_to_distro.json +3 -0
  174. aiq/meta/pypi.md +58 -0
  175. aiq/observability/__init__.py +0 -0
  176. aiq/observability/async_otel_listener.py +429 -0
  177. aiq/observability/register.py +99 -0
  178. aiq/plugins/.namespace +1 -0
  179. aiq/profiler/__init__.py +0 -0
  180. aiq/profiler/callbacks/__init__.py +0 -0
  181. aiq/profiler/callbacks/agno_callback_handler.py +295 -0
  182. aiq/profiler/callbacks/base_callback_class.py +20 -0
  183. aiq/profiler/callbacks/langchain_callback_handler.py +278 -0
  184. aiq/profiler/callbacks/llama_index_callback_handler.py +205 -0
  185. aiq/profiler/callbacks/semantic_kernel_callback_handler.py +238 -0
  186. aiq/profiler/callbacks/token_usage_base_model.py +27 -0
  187. aiq/profiler/data_frame_row.py +51 -0
  188. aiq/profiler/decorators/__init__.py +0 -0
  189. aiq/profiler/decorators/framework_wrapper.py +131 -0
  190. aiq/profiler/decorators/function_tracking.py +254 -0
  191. aiq/profiler/forecasting/__init__.py +0 -0
  192. aiq/profiler/forecasting/config.py +18 -0
  193. aiq/profiler/forecasting/model_trainer.py +75 -0
  194. aiq/profiler/forecasting/models/__init__.py +22 -0
  195. aiq/profiler/forecasting/models/forecasting_base_model.py +40 -0
  196. aiq/profiler/forecasting/models/linear_model.py +196 -0
  197. aiq/profiler/forecasting/models/random_forest_regressor.py +268 -0
  198. aiq/profiler/inference_metrics_model.py +25 -0
  199. aiq/profiler/inference_optimization/__init__.py +0 -0
  200. aiq/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
  201. aiq/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +452 -0
  202. aiq/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +258 -0
  203. aiq/profiler/inference_optimization/data_models.py +386 -0
  204. aiq/profiler/inference_optimization/experimental/__init__.py +0 -0
  205. aiq/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +468 -0
  206. aiq/profiler/inference_optimization/experimental/prefix_span_analysis.py +405 -0
  207. aiq/profiler/inference_optimization/llm_metrics.py +212 -0
  208. aiq/profiler/inference_optimization/prompt_caching.py +163 -0
  209. aiq/profiler/inference_optimization/token_uniqueness.py +107 -0
  210. aiq/profiler/inference_optimization/workflow_runtimes.py +72 -0
  211. aiq/profiler/intermediate_property_adapter.py +102 -0
  212. aiq/profiler/profile_runner.py +433 -0
  213. aiq/profiler/utils.py +184 -0
  214. aiq/registry_handlers/__init__.py +0 -0
  215. aiq/registry_handlers/local/__init__.py +0 -0
  216. aiq/registry_handlers/local/local_handler.py +176 -0
  217. aiq/registry_handlers/local/register_local.py +37 -0
  218. aiq/registry_handlers/metadata_factory.py +60 -0
  219. aiq/registry_handlers/package_utils.py +198 -0
  220. aiq/registry_handlers/pypi/__init__.py +0 -0
  221. aiq/registry_handlers/pypi/pypi_handler.py +251 -0
  222. aiq/registry_handlers/pypi/register_pypi.py +40 -0
  223. aiq/registry_handlers/register.py +21 -0
  224. aiq/registry_handlers/registry_handler_base.py +157 -0
  225. aiq/registry_handlers/rest/__init__.py +0 -0
  226. aiq/registry_handlers/rest/register_rest.py +56 -0
  227. aiq/registry_handlers/rest/rest_handler.py +237 -0
  228. aiq/registry_handlers/schemas/__init__.py +0 -0
  229. aiq/registry_handlers/schemas/headers.py +42 -0
  230. aiq/registry_handlers/schemas/package.py +68 -0
  231. aiq/registry_handlers/schemas/publish.py +63 -0
  232. aiq/registry_handlers/schemas/pull.py +82 -0
  233. aiq/registry_handlers/schemas/remove.py +36 -0
  234. aiq/registry_handlers/schemas/search.py +91 -0
  235. aiq/registry_handlers/schemas/status.py +47 -0
  236. aiq/retriever/__init__.py +0 -0
  237. aiq/retriever/interface.py +37 -0
  238. aiq/retriever/milvus/__init__.py +14 -0
  239. aiq/retriever/milvus/register.py +81 -0
  240. aiq/retriever/milvus/retriever.py +228 -0
  241. aiq/retriever/models.py +74 -0
  242. aiq/retriever/nemo_retriever/__init__.py +14 -0
  243. aiq/retriever/nemo_retriever/register.py +60 -0
  244. aiq/retriever/nemo_retriever/retriever.py +190 -0
  245. aiq/retriever/register.py +22 -0
  246. aiq/runtime/__init__.py +14 -0
  247. aiq/runtime/loader.py +188 -0
  248. aiq/runtime/runner.py +176 -0
  249. aiq/runtime/session.py +140 -0
  250. aiq/runtime/user_metadata.py +131 -0
  251. aiq/settings/__init__.py +0 -0
  252. aiq/settings/global_settings.py +318 -0
  253. aiq/test/.namespace +1 -0
  254. aiq/tool/__init__.py +0 -0
  255. aiq/tool/code_execution/__init__.py +0 -0
  256. aiq/tool/code_execution/code_sandbox.py +188 -0
  257. aiq/tool/code_execution/local_sandbox/Dockerfile.sandbox +60 -0
  258. aiq/tool/code_execution/local_sandbox/__init__.py +13 -0
  259. aiq/tool/code_execution/local_sandbox/local_sandbox_server.py +83 -0
  260. aiq/tool/code_execution/local_sandbox/sandbox.requirements.txt +4 -0
  261. aiq/tool/code_execution/local_sandbox/start_local_sandbox.sh +25 -0
  262. aiq/tool/code_execution/register.py +70 -0
  263. aiq/tool/code_execution/utils.py +100 -0
  264. aiq/tool/datetime_tools.py +42 -0
  265. aiq/tool/document_search.py +141 -0
  266. aiq/tool/github_tools/__init__.py +0 -0
  267. aiq/tool/github_tools/create_github_commit.py +133 -0
  268. aiq/tool/github_tools/create_github_issue.py +87 -0
  269. aiq/tool/github_tools/create_github_pr.py +106 -0
  270. aiq/tool/github_tools/get_github_file.py +106 -0
  271. aiq/tool/github_tools/get_github_issue.py +166 -0
  272. aiq/tool/github_tools/get_github_pr.py +256 -0
  273. aiq/tool/github_tools/update_github_issue.py +100 -0
  274. aiq/tool/mcp/__init__.py +14 -0
  275. aiq/tool/mcp/mcp_client.py +220 -0
  276. aiq/tool/mcp/mcp_tool.py +95 -0
  277. aiq/tool/memory_tools/__init__.py +0 -0
  278. aiq/tool/memory_tools/add_memory_tool.py +79 -0
  279. aiq/tool/memory_tools/delete_memory_tool.py +67 -0
  280. aiq/tool/memory_tools/get_memory_tool.py +72 -0
  281. aiq/tool/nvidia_rag.py +95 -0
  282. aiq/tool/register.py +37 -0
  283. aiq/tool/retriever.py +89 -0
  284. aiq/tool/server_tools.py +63 -0
  285. aiq/utils/__init__.py +0 -0
  286. aiq/utils/data_models/__init__.py +0 -0
  287. aiq/utils/data_models/schema_validator.py +58 -0
  288. aiq/utils/debugging_utils.py +43 -0
  289. aiq/utils/exception_handlers/__init__.py +0 -0
  290. aiq/utils/exception_handlers/schemas.py +114 -0
  291. aiq/utils/io/__init__.py +0 -0
  292. aiq/utils/io/yaml_tools.py +119 -0
  293. aiq/utils/metadata_utils.py +74 -0
  294. aiq/utils/optional_imports.py +142 -0
  295. aiq/utils/producer_consumer_queue.py +178 -0
  296. aiq/utils/reactive/__init__.py +0 -0
  297. aiq/utils/reactive/base/__init__.py +0 -0
  298. aiq/utils/reactive/base/observable_base.py +65 -0
  299. aiq/utils/reactive/base/observer_base.py +55 -0
  300. aiq/utils/reactive/base/subject_base.py +79 -0
  301. aiq/utils/reactive/observable.py +59 -0
  302. aiq/utils/reactive/observer.py +76 -0
  303. aiq/utils/reactive/subject.py +131 -0
  304. aiq/utils/reactive/subscription.py +49 -0
  305. aiq/utils/settings/__init__.py +0 -0
  306. aiq/utils/settings/global_settings.py +197 -0
  307. aiq/utils/type_converter.py +232 -0
  308. aiq/utils/type_utils.py +397 -0
  309. aiq/utils/url_utils.py +27 -0
  310. aiqtoolkit-1.1.0.dist-info/METADATA +331 -0
  311. aiqtoolkit-1.1.0.dist-info/RECORD +316 -0
  312. aiqtoolkit-1.1.0.dist-info/WHEEL +5 -0
  313. aiqtoolkit-1.1.0.dist-info/entry_points.txt +17 -0
  314. aiqtoolkit-1.1.0.dist-info/licenses/LICENSE-3rd-party.txt +3686 -0
  315. aiqtoolkit-1.1.0.dist-info/licenses/LICENSE.md +201 -0
  316. aiqtoolkit-1.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,122 @@
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 typing
18
+ from collections.abc import Callable
19
+ from pathlib import Path
20
+
21
+ import pandas as pd
22
+ from pydantic import BaseModel
23
+ from pydantic import Discriminator
24
+ from pydantic import FilePath
25
+ from pydantic import Tag
26
+
27
+ from aiq.data_models.common import BaseModelRegistryTag
28
+ from aiq.data_models.common import TypedBaseModel
29
+
30
+
31
+ class EvalS3Config(BaseModel):
32
+
33
+ endpoint_url: str
34
+ bucket: str
35
+ access_key: str
36
+ secret_key: str
37
+
38
+
39
+ class EvalFilterEntryConfig(BaseModel):
40
+ # values are lists of allowed/blocked values
41
+ field: dict[str, list[str | int | float]] = {}
42
+
43
+
44
+ class EvalFilterConfig(BaseModel):
45
+ allowlist: EvalFilterEntryConfig | None = None
46
+ denylist: EvalFilterEntryConfig | None = None
47
+
48
+
49
+ class EvalDatasetStructureConfig(BaseModel):
50
+ disable: bool = False
51
+ question_key: str = "question"
52
+ answer_key: str = "answer"
53
+ generated_answer_key: str = "generated_answer"
54
+ trajectory_key: str = "intermediate_steps"
55
+ expected_trajectory_key: str = "expected_intermediate_steps"
56
+
57
+
58
+ # Base model
59
+ class EvalDatasetBaseConfig(TypedBaseModel, BaseModelRegistryTag):
60
+
61
+ id_key: str = "id"
62
+ structure: EvalDatasetStructureConfig = EvalDatasetStructureConfig()
63
+
64
+ # Filters
65
+ filter: EvalFilterConfig | None = EvalFilterConfig()
66
+
67
+ s3: EvalS3Config | None = None
68
+
69
+ remote_file_path: str | None = None # only for s3
70
+ file_path: Path | str = Path(".tmp/aiq/examples/default/default.json")
71
+
72
+
73
+ class EvalDatasetJsonConfig(EvalDatasetBaseConfig, name="json"):
74
+
75
+ @staticmethod
76
+ def parser() -> tuple[Callable, dict]:
77
+ return pd.read_json, {}
78
+
79
+
80
+ def read_jsonl(file_path: FilePath, **kwargs):
81
+ with open(file_path, 'r', encoding='utf-8') as f:
82
+ data = [json.loads(line) for line in f]
83
+ return pd.DataFrame(data)
84
+
85
+
86
+ class EvalDatasetJsonlConfig(EvalDatasetBaseConfig, name="jsonl"):
87
+
88
+ @staticmethod
89
+ def parser() -> tuple[Callable, dict]:
90
+ return read_jsonl, {}
91
+
92
+
93
+ class EvalDatasetCsvConfig(EvalDatasetBaseConfig, name="csv"):
94
+
95
+ @staticmethod
96
+ def parser() -> tuple[Callable, dict]:
97
+ return pd.read_csv, {}
98
+
99
+
100
+ class EvalDatasetParquetConfig(EvalDatasetBaseConfig, name="parquet"):
101
+
102
+ @staticmethod
103
+ def parser() -> tuple[Callable, dict]:
104
+ return pd.read_parquet, {}
105
+
106
+
107
+ class EvalDatasetXlsConfig(EvalDatasetBaseConfig, name="xls"):
108
+
109
+ @staticmethod
110
+ def parser() -> tuple[Callable, dict]:
111
+ return pd.read_excel, {"engine": "openpyxl"}
112
+
113
+
114
+ # Union model with discriminator
115
+ EvalDatasetConfig = typing.Annotated[typing.Annotated[EvalDatasetJsonConfig, Tag(EvalDatasetJsonConfig.static_type())]
116
+ | typing.Annotated[EvalDatasetCsvConfig, Tag(EvalDatasetCsvConfig.static_type())]
117
+ | typing.Annotated[EvalDatasetXlsConfig, Tag(EvalDatasetXlsConfig.static_type())]
118
+ | typing.Annotated[EvalDatasetParquetConfig,
119
+ Tag(EvalDatasetParquetConfig.static_type())]
120
+ | typing.Annotated[EvalDatasetJsonlConfig,
121
+ Tag(EvalDatasetJsonlConfig.static_type())],
122
+ Discriminator(TypedBaseModel.discriminator)]
@@ -0,0 +1,286 @@
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 importlib.metadata
17
+ import inspect
18
+ import json
19
+ import logging
20
+ import typing
21
+ from enum import Enum
22
+ from functools import lru_cache
23
+ from pathlib import Path
24
+ from typing import TYPE_CHECKING
25
+
26
+ from pydantic import BaseModel
27
+ from pydantic import field_validator
28
+
29
+ from aiq.builder.framework_enum import LLMFrameworkEnum
30
+ from aiq.data_models.component import AIQComponentEnum
31
+ from aiq.utils.metadata_utils import generate_config_type_docs
32
+
33
+ if TYPE_CHECKING:
34
+ from aiq.cli.type_registry import ToolWrapperBuildCallableT
35
+ from aiq.data_models.common import TypedBaseModelT
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ class DiscoveryStatusEnum(str, Enum):
41
+ SUCCESS = "success"
42
+ FAILURE = "failure"
43
+
44
+
45
+ class DiscoveryContractFieldsEnum(str, Enum):
46
+ PACKAGE = "package"
47
+ VERSION = "version"
48
+ COMPONENT_TYPE = "component_type"
49
+ COMPONENT_NAME = "component_name"
50
+ DESCRIPTION = "description"
51
+ DEVELOPER_NOTES = "developer_notes"
52
+
53
+
54
+ class DiscoveryMetadata(BaseModel):
55
+ """A data model representing metadata about each registered component to faciliate its discovery.
56
+
57
+ Args:
58
+ package (str): The name of the package containing the AIQ Toolkit component.
59
+ version (str): The version number of the package containing the AIQ Toolkit component.
60
+ component_type (AIQComponentEnum): The type of AIQ Toolkit component this metadata represents.
61
+ component_name (str): The registered name of the AIQ Toolkit component.
62
+ description (str): Description of the AIQ Toolkit component pulled from its config objects docstrings.
63
+ developer_notes (str): Other notes to a developers to aid in the use of the component.
64
+ status (DiscoveryStatusEnum): Provides the status of the metadata discovery process.
65
+ """
66
+
67
+ package: str = ""
68
+ version: str = ""
69
+ component_type: AIQComponentEnum = AIQComponentEnum.UNDEFINED
70
+ component_name: str = ""
71
+ description: str = ""
72
+ developer_notes: str = ""
73
+ status: DiscoveryStatusEnum = DiscoveryStatusEnum.SUCCESS
74
+
75
+ @field_validator("description", mode="before")
76
+ @classmethod
77
+ def ensure_description_string(cls, v: typing.Any):
78
+ if not isinstance(v, str):
79
+ return ""
80
+ return v
81
+
82
+ @staticmethod
83
+ def get_preferred_item(items: list, preferred: str) -> str:
84
+ return preferred if preferred in items else items[0]
85
+
86
+ @staticmethod
87
+ @lru_cache
88
+ def get_distribution_name_from_metadata(root_package_name: str) -> str | None:
89
+ """
90
+ This is not performant and is only present to be used (not used
91
+ currently) as a fallback when the distro name doesn't match the
92
+ module name and private_data is not available to map it.
93
+ """
94
+ mapping = importlib.metadata.packages_distributions()
95
+ try:
96
+ distro_names = mapping.get(root_package_name, [None])
97
+ distro_name = DiscoveryMetadata.get_preferred_item(distro_names, "aiqtoolkit")
98
+ except KeyError:
99
+ return root_package_name
100
+
101
+ return distro_name if distro_name else root_package_name
102
+
103
+ @staticmethod
104
+ @lru_cache
105
+ def get_distribution_name_from_private_data(root_package: str) -> str | None:
106
+ # Locate distibution mapping stored in the packages private data
107
+ module = __import__(root_package)
108
+ for path in module.__path__:
109
+ package_dir = Path(path).resolve()
110
+ distinfo_path = package_dir / "meta" / "module_to_distro.json"
111
+
112
+ if distinfo_path.exists():
113
+ with distinfo_path.open("r") as f:
114
+ data = json.load(f)
115
+ return data.get(root_package, None)
116
+ return None
117
+
118
+ @staticmethod
119
+ @lru_cache
120
+ def get_distribution_name(root_package: str) -> str:
121
+ """
122
+ The aiq library packages use a distro name 'aiqtoolkit[]' and
123
+ root package name 'aiq'. They provide mapping in a metadata file
124
+ for optimized installation.
125
+ """
126
+ distro_name = DiscoveryMetadata.get_distribution_name_from_private_data(root_package)
127
+ return distro_name if distro_name else root_package
128
+
129
+ @staticmethod
130
+ def from_config_type(config_type: type["TypedBaseModelT"],
131
+ component_type: AIQComponentEnum = AIQComponentEnum.UNDEFINED) -> "DiscoveryMetadata":
132
+ """Generates discovery metadata from an AIQ Toolkit config object.
133
+
134
+ Args:
135
+ config_type (type[TypedBaseModelT]): A registered component's configuration object.
136
+ component_type (AIQComponentEnum, optional): The type of the registered component. Defaults to
137
+ AIQComponentEnum.UNDEFINED.
138
+
139
+ Returns:
140
+ DiscoveryMetadata: A an object containing component metadata to facilitate discovery and reuse.
141
+ """
142
+
143
+ try:
144
+ module = inspect.getmodule(config_type)
145
+ root_package: str = module.__package__.split(".")[0]
146
+ distro_name = DiscoveryMetadata.get_distribution_name(root_package)
147
+
148
+ if not distro_name:
149
+ # raise an exception
150
+ logger.error("Encountered issue getting distro_name for module %s", module.__name__)
151
+ return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
152
+
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 = ""
158
+ except Exception as e:
159
+ logger.exception("Encountered issue extracting module metadata for %s: %s", config_type, e, exc_info=True)
160
+ return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
161
+
162
+ description = generate_config_type_docs(config_type=config_type)
163
+
164
+ return DiscoveryMetadata(package=distro_name,
165
+ version=version,
166
+ component_type=component_type,
167
+ component_name=config_type.static_type(),
168
+ description=description)
169
+
170
+ @staticmethod
171
+ def from_fn_wrapper(fn: "ToolWrapperBuildCallableT",
172
+ wrapper_type: LLMFrameworkEnum | str,
173
+ component_type: AIQComponentEnum = AIQComponentEnum.TOOL_WRAPPER) -> "DiscoveryMetadata":
174
+ """Generates discovery metadata from function with specified wrapper type.
175
+
176
+ Args:
177
+ fn (ToolWrapperBuildCallableT): A tool wrapper callable to source component metadata.
178
+ wrapper_type (LLMFrameworkEnum): The wrapper to apply to the callable to faciliate inter-framwork
179
+ interoperability.
180
+
181
+ component_type (AIQComponentEnum, optional): The type of the registered component. Defaults to
182
+ AIQComponentEnum.TOOL_WRAPPER.
183
+
184
+ Returns:
185
+ DiscoveryMetadata: A an object containing component metadata to facilitate discovery and reuse.
186
+ """
187
+
188
+ try:
189
+ module = inspect.getmodule(fn)
190
+ root_package: str = module.__package__.split(".")[0]
191
+ root_package = DiscoveryMetadata.get_distribution_name(root_package)
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 = ""
197
+ except Exception as e:
198
+ logger.exception("Encountered issue extracting module metadata for %s: %s", fn, e, exc_info=True)
199
+ return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
200
+
201
+ if isinstance(wrapper_type, LLMFrameworkEnum):
202
+ wrapper_type = wrapper_type.value
203
+
204
+ return DiscoveryMetadata(package=root_package,
205
+ version=version,
206
+ component_type=component_type,
207
+ component_name=wrapper_type,
208
+ description=fn.__doc__ or "")
209
+
210
+ @staticmethod
211
+ def from_package_name(package_name: str, package_version: str | None) -> "DiscoveryMetadata":
212
+ """Generates discovery metadata from an installed package name.
213
+
214
+ Args:
215
+ package_name (str): The name of the AIQ Toolkit plugin package containing registered components.
216
+ package_version (str, optional): The version of the package, Defaults to None.
217
+
218
+ Returns:
219
+ DiscoveryMetadata: A an object containing component metadata to facilitate discovery and reuse.
220
+ """
221
+
222
+ try:
223
+ package_name = DiscoveryMetadata.get_distribution_name(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 ""
233
+ except Exception as e:
234
+ logger.exception("Encountered issue extracting module metadata for %s: %s", package_name, e, exc_info=True)
235
+ return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
236
+
237
+ return DiscoveryMetadata(package=package_name,
238
+ version=package_version,
239
+ component_type=AIQComponentEnum.PACKAGE,
240
+ component_name=package_name,
241
+ description=description)
242
+
243
+ @staticmethod
244
+ def from_provider_framework_map(
245
+ config_type: type["TypedBaseModelT"],
246
+ wrapper_type: LLMFrameworkEnum | str | None,
247
+ provider_type: AIQComponentEnum,
248
+ component_type: AIQComponentEnum = AIQComponentEnum.UNDEFINED) -> "DiscoveryMetadata":
249
+ """Generates discovery metadata from provider and framework mapping information.
250
+
251
+ Args:
252
+ config_type (type[TypedBaseModelT]): A registered component's configuration object.
253
+ wrapper_type (LLMFrameworkEnum | str): The wrapper to apply to the callable to faciliate inter-framwork
254
+ interoperability.
255
+
256
+ provider_type (AIQComponentEnum): The type of provider the registered component supports.
257
+ component_type (AIQComponentEnum, optional): The type of the registered component. Defaults to
258
+ AIQComponentEnum.UNDEFINED.
259
+
260
+ Returns:
261
+ DiscoveryMetadata: A an object containing component metadata to facilitate discovery and reuse.
262
+ """
263
+
264
+ try:
265
+ module = inspect.getmodule(config_type)
266
+ root_package: str = module.__package__.split(".")[0]
267
+ root_package = DiscoveryMetadata.get_distribution_name(root_package)
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 = ""
273
+ except Exception as e:
274
+ logger.exception("Encountered issue extracting module metadata for %s: %s", config_type, e, exc_info=True)
275
+ return DiscoveryMetadata(status=DiscoveryStatusEnum.FAILURE)
276
+
277
+ wrapper_type = wrapper_type.value if isinstance(wrapper_type, LLMFrameworkEnum) else wrapper_type
278
+ component_name = f"{config_type.static_type()} ({provider_type.value}) - {wrapper_type}"
279
+
280
+ description = generate_config_type_docs(config_type=config_type)
281
+
282
+ return DiscoveryMetadata(package=root_package,
283
+ version=version,
284
+ component_type=component_type,
285
+ component_name=component_name,
286
+ description=description)
@@ -0,0 +1,26 @@
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 typing
17
+
18
+ from .common import BaseModelRegistryTag
19
+ from .common import TypedBaseModel
20
+
21
+
22
+ class EmbedderBaseConfig(TypedBaseModel, BaseModelRegistryTag):
23
+ pass
24
+
25
+
26
+ EmbedderBaseConfigT = typing.TypeVar("EmbedderBaseConfigT", bound=EmbedderBaseConfig)
@@ -0,0 +1,104 @@
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 typing
17
+ from pathlib import Path
18
+
19
+ from pydantic import BaseModel
20
+ from pydantic import Discriminator
21
+ from pydantic import model_validator
22
+
23
+ from aiq.data_models.common import TypedBaseModel
24
+ from aiq.data_models.dataset_handler import EvalDatasetConfig
25
+ from aiq.data_models.dataset_handler import EvalS3Config
26
+ from aiq.data_models.evaluator import EvaluatorBaseConfig
27
+ from aiq.data_models.intermediate_step import IntermediateStepType
28
+ from aiq.data_models.profiler import ProfilerConfig
29
+
30
+
31
+ class EvalCustomScriptConfig(BaseModel):
32
+ # Path to the script to run
33
+ script: Path
34
+ # Keyword arguments to pass to the script
35
+ kwargs: dict[str, str] = {}
36
+
37
+
38
+ class EvalOutputConfig(BaseModel):
39
+ # Output directory for the workflow and evaluation results
40
+ dir: Path = Path("/tmp/aiq/examples/default/")
41
+ # S3 prefix for the workflow and evaluation results
42
+ remote_dir: str | None = None
43
+ # Custom scripts to run after the workflow and evaluation results are saved
44
+ custom_scripts: dict[str, EvalCustomScriptConfig] = {}
45
+ # S3 config for uploading the contents of the output directory
46
+ s3: EvalS3Config | None = None
47
+ # Whether to cleanup the output directory before running the workflow
48
+ cleanup: bool = True
49
+ # Filter for the workflow output steps
50
+ workflow_output_step_filter: list[IntermediateStepType] | None = None
51
+
52
+
53
+ class EvalGeneralConfig(BaseModel):
54
+ max_concurrency: int = 8
55
+
56
+ # Output directory for the workflow and evaluation results
57
+ output_dir: Path = Path("/tmp/aiq/examples/default/")
58
+
59
+ # If present overrides output_dir
60
+ output: EvalOutputConfig | None = None
61
+
62
+ # Dataset for running the workflow and evaluating
63
+ dataset: EvalDatasetConfig | None = None
64
+
65
+ # Inference profiler
66
+ profiler: ProfilerConfig | None = None
67
+
68
+ # overwrite the output_dir with the output config if present
69
+ @model_validator(mode="before")
70
+ @classmethod
71
+ def override_output_dir(cls, values):
72
+ if values.get("output") and values["output"].get("dir"):
73
+ values["output_dir"] = values["output"]["dir"]
74
+ return values
75
+
76
+
77
+ class EvalConfig(BaseModel):
78
+
79
+ # General Evaluation Options
80
+ general: EvalGeneralConfig = EvalGeneralConfig()
81
+
82
+ # Evaluators
83
+ evaluators: dict[str, EvaluatorBaseConfig] = {}
84
+
85
+ @classmethod
86
+ def rebuild_annotations(cls):
87
+
88
+ from aiq.cli.type_registry import GlobalTypeRegistry # pylint: disable=cyclic-import
89
+
90
+ type_registry = GlobalTypeRegistry.get()
91
+
92
+ EvaluatorsAnnotation = dict[str,
93
+ typing.Annotated[type_registry.compute_annotation(EvaluatorBaseConfig),
94
+ Discriminator(TypedBaseModel.discriminator)]]
95
+
96
+ should_rebuild = False
97
+
98
+ evaluators_field = cls.model_fields.get("evaluators")
99
+ if evaluators_field is not None and evaluators_field.annotation != EvaluatorsAnnotation:
100
+ evaluators_field.annotation = EvaluatorsAnnotation
101
+ should_rebuild = True
102
+
103
+ if (should_rebuild):
104
+ cls.model_rebuild(force=True)
@@ -0,0 +1,26 @@
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 typing
17
+
18
+ from .common import BaseModelRegistryTag
19
+ from .common import TypedBaseModel
20
+
21
+
22
+ class EvaluatorBaseConfig(TypedBaseModel, BaseModelRegistryTag):
23
+ pass
24
+
25
+
26
+ EvaluatorBaseConfigT = typing.TypeVar("EvaluatorBaseConfigT", bound=EvaluatorBaseConfig)
@@ -0,0 +1,26 @@
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 typing
17
+
18
+ from .common import BaseModelRegistryTag
19
+ from .common import TypedBaseModel
20
+
21
+
22
+ class FrontEndBaseConfig(TypedBaseModel, BaseModelRegistryTag):
23
+ pass
24
+
25
+
26
+ FrontEndConfigT = typing.TypeVar("FrontEndConfigT", bound=FrontEndBaseConfig)
@@ -0,0 +1,30 @@
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 typing
17
+
18
+ from .common import BaseModelRegistryTag
19
+ from .common import TypedBaseModel
20
+
21
+
22
+ class FunctionBaseConfig(TypedBaseModel, BaseModelRegistryTag):
23
+ pass
24
+
25
+
26
+ class EmptyFunctionConfig(FunctionBaseConfig, name="EmptyFunctionConfig"):
27
+ pass
28
+
29
+
30
+ FunctionConfigT = typing.TypeVar("FunctionConfigT", bound=FunctionBaseConfig)
@@ -0,0 +1,64 @@
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
+ from pydantic import BaseModel
17
+ from pydantic import Field
18
+ from pydantic import field_serializer
19
+
20
+
21
+ class FunctionDependencies(BaseModel):
22
+ """
23
+ A class to represent the dependencies of a function.
24
+ """
25
+ functions: set[str] = Field(default_factory=set)
26
+ llms: set[str] = Field(default_factory=set)
27
+ embedders: set[str] = Field(default_factory=set)
28
+ memory_clients: set[str] = Field(default_factory=set)
29
+ retrievers: set[str] = Field(default_factory=set)
30
+
31
+ @field_serializer("functions", when_used="json")
32
+ def serialize_functions(self, v: set[str]) -> list[str]:
33
+ return list(v)
34
+
35
+ @field_serializer("llms", when_used="json")
36
+ def serialize_llms(self, v: set[str]) -> list[str]:
37
+ return list(v)
38
+
39
+ @field_serializer("embedders", when_used="json")
40
+ def serialize_embedders(self, v: set[str]) -> list[str]:
41
+ return list(v)
42
+
43
+ @field_serializer("memory_clients", when_used="json")
44
+ def serialize_memory_clients(self, v: set[str]) -> list[str]:
45
+ return list(v)
46
+
47
+ @field_serializer("retrievers", when_used="json")
48
+ def serialize_retrievers(self, v: set[str]) -> list[str]:
49
+ return list(v)
50
+
51
+ def add_function(self, function: str):
52
+ self.functions.add(function) # pylint: disable=no-member
53
+
54
+ def add_llm(self, llm: str):
55
+ self.llms.add(llm) # pylint: disable=no-member
56
+
57
+ def add_embedder(self, embedder: str):
58
+ self.embedders.add(embedder) # pylint: disable=no-member
59
+
60
+ def add_memory_client(self, memory_client: str):
61
+ self.memory_clients.add(memory_client) # pylint: disable=no-member
62
+
63
+ def add_retriever(self, retriever: str):
64
+ self.retrievers.add(retriever) # pylint: disable=no-member