aiqtoolkit 1.1.0rc5__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.0rc5.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 -135
  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.0rc5.dist-info/METADATA +0 -331
  315. aiqtoolkit-1.1.0rc5.dist-info/RECORD +0 -316
  316. aiqtoolkit-1.1.0rc5.dist-info/entry_points.txt +0 -17
  317. aiqtoolkit-1.1.0rc5.dist-info/licenses/LICENSE-3rd-party.txt +0 -3686
  318. aiqtoolkit-1.1.0rc5.dist-info/licenses/LICENSE.md +0 -201
  319. aiqtoolkit-1.1.0rc5.dist-info/top_level.txt +0 -1
@@ -1,205 +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
- from __future__ import annotations
17
-
18
- import copy
19
- import logging
20
- import threading
21
- import time
22
- from typing import Any
23
-
24
- from llama_index.core.callbacks import CBEventType
25
- from llama_index.core.callbacks import EventPayload
26
- from llama_index.core.callbacks.base_handler import BaseCallbackHandler
27
- from llama_index.core.llms import ChatResponse
28
-
29
- from aiq.builder.context import AIQContext
30
- from aiq.builder.framework_enum import LLMFrameworkEnum
31
- from aiq.data_models.intermediate_step import IntermediateStepPayload
32
- from aiq.data_models.intermediate_step import IntermediateStepType
33
- from aiq.data_models.intermediate_step import StreamEventData
34
- from aiq.data_models.intermediate_step import TraceMetadata
35
- from aiq.data_models.intermediate_step import UsageInfo
36
- from aiq.profiler.callbacks.base_callback_class import BaseProfilerCallback
37
- from aiq.profiler.callbacks.token_usage_base_model import TokenUsageBaseModel
38
-
39
- logger = logging.getLogger(__name__)
40
-
41
-
42
- class LlamaIndexProfilerHandler(BaseCallbackHandler, BaseProfilerCallback):
43
- """
44
- A callback handler for LlamaIndex that tracks usage stats similarly to NIMCallbackHandler.
45
- Collects:
46
-
47
- - Prompts
48
- - Token usage
49
- - Response data
50
- - Time intervals between calls
51
-
52
- and appends them to AIQContextState.usage_stats.
53
- """
54
-
55
- def __init__(self) -> None:
56
- BaseCallbackHandler.__init__(self, event_starts_to_ignore=[], event_ends_to_ignore=[])
57
- BaseProfilerCallback.__init__(self)
58
- self._lock = threading.Lock()
59
- self.last_call_ts = time.time()
60
- self._last_tool_map: dict[str, str] = {}
61
- self.step_manager = AIQContext.get().intermediate_step_manager
62
-
63
- self._run_id_to_llm_input = {}
64
- self._run_id_to_tool_input = {}
65
- self._run_id_to_timestamp = {}
66
-
67
- def on_event_start(
68
- self,
69
- event_type: CBEventType,
70
- payload: dict[str, Any] | None = None,
71
- event_id: str = "",
72
- parent_id: str = "",
73
- **kwargs: Any,
74
- ) -> str:
75
- """
76
- Called at the *start* of a LlamaIndex "event" (LLM call, Embedding, etc.).
77
- We capture the prompts or query strings here, if any.
78
- """
79
-
80
- prompts_or_messages = None
81
- now = time.time()
82
- seconds_between_calls = int(now - self.last_call_ts)
83
-
84
- # For LLM or chat calls, look in `payload` for messages/prompts
85
- if event_type == CBEventType.LLM and payload:
86
- # For example, "PROMPT" or "MESSAGES" might be in the payload.
87
- # If found, store them in usage stats (just like your NIMCallbackHandler).
88
- if EventPayload.PROMPT in payload:
89
- prompts_or_messages = [payload[EventPayload.PROMPT]]
90
- elif EventPayload.MESSAGES in payload:
91
- prompts_or_messages = [str(msg) for msg in payload[EventPayload.MESSAGES]]
92
-
93
- model_name = ""
94
- try:
95
- model_name = payload.get(EventPayload.SERIALIZED)['model']
96
- except Exception as e:
97
- logger.exception("Error getting model name: %s", e, exc_info=True)
98
-
99
- llm_text_input = " ".join(prompts_or_messages) if prompts_or_messages else ""
100
-
101
- if prompts_or_messages:
102
- stats = IntermediateStepPayload(event_type=IntermediateStepType.LLM_START,
103
- framework=LLMFrameworkEnum.LLAMA_INDEX,
104
- name=model_name,
105
- UUID=event_id,
106
- data=StreamEventData(input=llm_text_input),
107
- metadata=TraceMetadata(chat_inputs=copy.deepcopy(prompts_or_messages)),
108
- usage_info=UsageInfo(token_usage=TokenUsageBaseModel(),
109
- num_llm_calls=1,
110
- seconds_between_calls=seconds_between_calls))
111
-
112
- self.step_manager.push_intermediate_step(stats)
113
- self._run_id_to_llm_input[event_id] = llm_text_input
114
- self.last_call_ts = now
115
- self._run_id_to_timestamp[event_id] = time.time()
116
-
117
- elif event_type == CBEventType.FUNCTION_CALL and payload:
118
- tool_metadata = payload.get(EventPayload.TOOL)
119
- tool_metadata = {
120
- "description": tool_metadata.description if hasattr(tool_metadata, "description") else "",
121
- "fn_schema_str": tool_metadata.fn_schema_str if hasattr(tool_metadata, "fn_schema_str") else "",
122
- "name": tool_metadata.name if hasattr(tool_metadata, "name") else "",
123
- }
124
- stats = IntermediateStepPayload(
125
- event_type=IntermediateStepType.TOOL_START,
126
- framework=LLMFrameworkEnum.LLAMA_INDEX,
127
- name=payload.get(EventPayload.TOOL).name,
128
- UUID=event_id,
129
- data=StreamEventData(input=copy.deepcopy(payload.get(EventPayload.FUNCTION_CALL))),
130
- metadata=TraceMetadata(tool_inputs=copy.deepcopy(payload.get(EventPayload.FUNCTION_CALL)),
131
- tool_info=tool_metadata),
132
- usage_info=UsageInfo(token_usage=TokenUsageBaseModel()))
133
-
134
- self._run_id_to_tool_input[event_id] = copy.deepcopy(payload.get(EventPayload.FUNCTION_CALL))
135
- self._last_tool_map[event_id] = payload.get(EventPayload.TOOL).name
136
- self.step_manager.push_intermediate_step(stats)
137
- self._run_id_to_timestamp[event_id] = time.time()
138
- return event_id # must return the event_id
139
-
140
- def on_event_end(
141
- self,
142
- event_type: CBEventType,
143
- payload: dict[str, Any] | None = None,
144
- event_id: str = "",
145
- **kwargs: Any,
146
- ) -> None:
147
- """
148
- Called at the *end* of a LlamaIndex "event".
149
- We collect token usage (if available) and the returned response text.
150
- """
151
-
152
- if payload and event_type == CBEventType.LLM:
153
- # Often, token usage is embedded in e.g. payload["RESPONSE"].raw["usage"] for OpenAI-based calls
154
- response = payload.get(EventPayload.RESPONSE)
155
- if isinstance(response, ChatResponse):
156
- llm_text_output = ""
157
-
158
- try:
159
- for block in response.message.blocks:
160
- llm_text_output += block.text
161
- except Exception as e:
162
- logger.exception("Error getting LLM text output: %s", e, exc_info=True)
163
-
164
- model_name = ""
165
- try:
166
- model_name = response.raw.model
167
- except Exception as e:
168
- logger.exception("Error getting model name: %s", e, exc_info=True)
169
-
170
- # Append usage data to AIQ Toolkit usage stats
171
- with self._lock:
172
- stats = IntermediateStepPayload(
173
- event_type=IntermediateStepType.LLM_END,
174
- span_event_timestamp=self._run_id_to_timestamp.get(event_id),
175
- framework=LLMFrameworkEnum.LLAMA_INDEX,
176
- name=model_name,
177
- UUID=event_id,
178
- data=StreamEventData(input=self._run_id_to_llm_input.get(event_id), output=llm_text_output),
179
- metadata=TraceMetadata(chat_responses=response.message if response.message else None),
180
- usage_info=UsageInfo(token_usage=TokenUsageBaseModel(**response.additional_kwargs)))
181
- self.step_manager.push_intermediate_step(stats)
182
-
183
- elif event_type == CBEventType.FUNCTION_CALL and payload:
184
- stats = IntermediateStepPayload(
185
- event_type=IntermediateStepType.TOOL_END,
186
- span_event_timestamp=self._run_id_to_timestamp.get(event_id),
187
- framework=LLMFrameworkEnum.LLAMA_INDEX,
188
- name=self._last_tool_map.get(event_id),
189
- UUID=event_id,
190
- data=StreamEventData(output=copy.deepcopy(payload.get(EventPayload.FUNCTION_OUTPUT))),
191
- usage_info=UsageInfo(token_usage=TokenUsageBaseModel()))
192
-
193
- self.step_manager.push_intermediate_step(stats)
194
-
195
- def start_trace(self, trace_id: str | None = None) -> None:
196
- """Run when an overall trace is launched."""
197
- pass
198
-
199
- def end_trace(
200
- self,
201
- trace_id: str | None = None,
202
- trace_map: dict[str, list[str]] | None = None,
203
- ) -> None:
204
- """Run when an overall trace is exited."""
205
- pass
@@ -1,238 +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 copy
17
- import logging
18
- import threading
19
- import time
20
- from collections.abc import Callable
21
- from typing import Any
22
- from uuid import uuid4
23
-
24
- import semantic_kernel
25
- from pydantic import BaseModel
26
- from pydantic import Field
27
- from semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion_base import OpenAIChatCompletionBase
28
-
29
- from aiq.builder.context import AIQContext
30
- from aiq.builder.framework_enum import LLMFrameworkEnum
31
- from aiq.data_models.intermediate_step import IntermediateStepPayload
32
- from aiq.data_models.intermediate_step import IntermediateStepType
33
- from aiq.data_models.intermediate_step import StreamEventData
34
- from aiq.data_models.intermediate_step import TraceMetadata
35
- from aiq.data_models.intermediate_step import UsageInfo
36
- from aiq.profiler.callbacks.base_callback_class import BaseProfilerCallback
37
- from aiq.profiler.callbacks.token_usage_base_model import TokenUsageBaseModel
38
-
39
- logger = logging.getLogger(__name__)
40
-
41
-
42
- class SemanticKernelPatchMethod(BaseModel):
43
- """
44
- Stores the module and function to patch in Semantic Kernel.
45
- """
46
- module: Any = Field(..., description="The module to patch")
47
- function: str = Field(..., description="The function to patch")
48
-
49
-
50
- class SemanticKernelProfilerHandler(BaseProfilerCallback):
51
- """
52
- A callback manager/handler for Msft Semantic Kernel that intercepts calls to:
53
-
54
- - Chat Completions Endpoints
55
- - Tool calls
56
-
57
- to collect usage statistics (tokens, inputs, outputs, time intervals, etc.)
58
- and store them in AIQ Toolkit's usage_stats queue for subsequent analysis.
59
- """
60
-
61
- def __init__(self, workflow_llms: dict) -> None:
62
- super().__init__()
63
- self._lock = threading.Lock()
64
- self.last_call_ts = time.time()
65
- self.step_manager = AIQContext.get().intermediate_step_manager
66
- self._builder_llms = workflow_llms
67
-
68
- # Original references to SK methods
69
- self._original_tool_call = None
70
-
71
- # Store a mapping of current SK methods we support patching for
72
- self._patch_methods = {
73
- "openai_streaming":
74
- SemanticKernelPatchMethod(module=OpenAIChatCompletionBase,
75
- function="_inner_get_streaming_chat_message_contents"),
76
- "openai_non_streaming":
77
- SemanticKernelPatchMethod(module=OpenAIChatCompletionBase, function="_inner_get_chat_message_contents")
78
- }
79
-
80
- def instrument(self) -> None:
81
- """
82
- Monkey-patch the relevant Semantic Kernel methods with usage-stat collection logic.
83
- """
84
-
85
- functions_to_patch = []
86
-
87
- # Gather the appropriate modules/functions based on your builder config
88
- for llm in self._builder_llms:
89
- if self._builder_llms[llm].provider_type == 'openai': # pylint: disable=consider-using-in
90
- functions_to_patch.extend(["openai_non_streaming", "openai_streaming"])
91
-
92
- # Grab original reference for the tool call
93
- self._original_tool_call = getattr(semantic_kernel.Kernel, "invoke_function_call", None)
94
-
95
- # Now do direct monkey-patching: replace each function with a closure
96
- for method in functions_to_patch:
97
- patch_method = self._patch_methods[method]
98
- setattr(patch_method.module,
99
- patch_method.function,
100
- self._build_llm_call_patch(getattr(patch_method.module, patch_method.function)))
101
-
102
- if self._original_tool_call:
103
- patched_tool_call = self._build_tool_call_patch(self._original_tool_call)
104
- setattr(semantic_kernel.Kernel, "invoke_function_call", patched_tool_call)
105
-
106
- logger.debug("SemanticKernelProfilerHandler instrumentation applied successfully.")
107
-
108
- def _build_llm_call_patch(self, original_func: Callable[..., Any]) -> Callable[..., Any]:
109
- """
110
- Returns an async monkey-patch that wraps the original chat-completion method.
111
- Replicates the usage collection from _llm_call_wrapper.
112
- """
113
-
114
- async def patched_llm_call(sk_self, *args, **kwargs) -> Any:
115
- now = time.time()
116
- seconds_between_calls = int(now - self.last_call_ts)
117
- uuid = str(uuid4())
118
-
119
- # Build the input stats
120
- if args:
121
- chat_input = [copy.deepcopy(args[0].model_dump())]
122
- else:
123
- # if no args, fallback on kwargs["chat_history"]
124
- chat_input = [kwargs["chat_history"].model_dump()]
125
-
126
- model_name = sk_self.ai_model_id
127
-
128
- model_input = ""
129
- try:
130
- for message in chat_input[0]["messages"]:
131
- for item in message["items"]:
132
- if "text" in item:
133
- model_input += item["text"]
134
- except Exception as e:
135
- logger.exception("Error in getting model input: %s", e, exc_info=True)
136
-
137
- input_stats = IntermediateStepPayload(event_type=IntermediateStepType.LLM_START,
138
- framework=LLMFrameworkEnum.SEMANTIC_KERNEL,
139
- name=model_name,
140
- UUID=uuid,
141
- data=StreamEventData(input=model_input),
142
- metadata=TraceMetadata(chat_inputs=copy.deepcopy(chat_input)),
143
- usage_info=UsageInfo(token_usage=TokenUsageBaseModel(),
144
- num_llm_calls=1,
145
- seconds_between_calls=seconds_between_calls))
146
-
147
- self.step_manager.push_intermediate_step(input_stats)
148
-
149
- # Call the original method
150
- output = await original_func(sk_self, *args, **kwargs)
151
-
152
- model_output = output[0].content
153
- now = time.time()
154
- # Build the output stats
155
- output_stats = IntermediateStepPayload(
156
- event_type=IntermediateStepType.LLM_END,
157
- span_event_timestamp=now,
158
- framework=LLMFrameworkEnum.SEMANTIC_KERNEL,
159
- name=model_name,
160
- UUID=uuid,
161
- data=StreamEventData(input=model_input, output=model_output),
162
- metadata=TraceMetadata(chat_responses=output[0].model_dump()),
163
- usage_info=UsageInfo(token_usage=TokenUsageBaseModel(**output[0].metadata["usage"].model_dump())))
164
-
165
- self.step_manager.push_intermediate_step(output_stats)
166
-
167
- # Update last_call_ts
168
- self.last_call_ts = time.time()
169
-
170
- return output
171
-
172
- return patched_llm_call
173
-
174
- def _build_tool_call_patch(self, original_func: Callable[..., Any]) -> Callable[..., Any]:
175
- """
176
- Returns an async monkey-patch that wraps the original tool call (invoke_function_call).
177
- Replicates usage collection from _tool_use_wrapper.
178
- """
179
-
180
- async def patched_tool_call(kernel_self, *args, **kwargs) -> Any:
181
-
182
- uuid = str(uuid4())
183
- now = time.time()
184
- # Extract the tool input
185
- if kwargs:
186
- tool_input = kwargs["function_call"].model_dump(exclude="content_type")
187
- else:
188
- tool_input = args[0].model_dump(exclude="content_type")
189
-
190
- try:
191
- # Pre-call usage event
192
- input_stat = IntermediateStepPayload(event_type=IntermediateStepType.TOOL_START,
193
- framework=LLMFrameworkEnum.SEMANTIC_KERNEL,
194
- name=tool_input["name"],
195
- UUID=uuid,
196
- data=StreamEventData(input=tool_input),
197
- metadata=TraceMetadata(tool_inputs=copy.deepcopy(tool_input),
198
- tool_info=copy.deepcopy(tool_input)),
199
- usage_info=UsageInfo(token_usage=TokenUsageBaseModel()))
200
-
201
- self.step_manager.push_intermediate_step(input_stat)
202
- now = time.time()
203
- # Call the original invoke_function_call
204
- result = await original_func(kernel_self, *args, **kwargs)
205
-
206
- # Try to get the chat history from kwargs or args
207
- if kwargs:
208
- chat_history = copy.deepcopy(kwargs["chat_history"])
209
- else:
210
- chat_history = copy.deepcopy(args[1])
211
-
212
- # Post-call usage event
213
- output_stat = IntermediateStepPayload(event_type=IntermediateStepType.TOOL_END,
214
- span_event_timestamp=now,
215
- framework=LLMFrameworkEnum.SEMANTIC_KERNEL,
216
- name=tool_input["name"],
217
- UUID=uuid,
218
- data=StreamEventData(input=tool_input,
219
- output=[
220
- item.model_dump(exclude="content_type")
221
- for item in chat_history[-1].items
222
- ]),
223
- metadata=TraceMetadata(tool_outputs=[
224
- item.model_dump(exclude="content_type")
225
- for item in chat_history[-1].items
226
- ],
227
- tool_info=copy.deepcopy(tool_input)),
228
- usage_info=UsageInfo(token_usage=TokenUsageBaseModel()))
229
-
230
- self.step_manager.push_intermediate_step(output_stat)
231
-
232
- return result
233
-
234
- except Exception as e:
235
- logger.exception("ToolUsage._use error: %s", e)
236
- raise
237
-
238
- return patched_tool_call
@@ -1,27 +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
- from pydantic import BaseModel
17
- from pydantic import Field
18
-
19
-
20
- class TokenUsageBaseModel(BaseModel):
21
- """
22
- Base model for token usage callbacks.
23
- """
24
-
25
- prompt_tokens: int = Field(default=0, description="Number of tokens in the prompt.")
26
- completion_tokens: int = Field(default=0, description="Number of tokens in the completion.")
27
- total_tokens: int = Field(default=0, description="Number of tokens total.")
@@ -1,51 +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
- from typing import Any
17
-
18
- from pydantic import BaseModel
19
- from pydantic import ConfigDict
20
- from pydantic import field_validator
21
-
22
-
23
- class DataFrameRow(BaseModel):
24
- model_config = ConfigDict(extra="allow", validate_assignment=True)
25
-
26
- event_type: Any
27
- event_timestamp: float | None
28
- example_number: int | None
29
- prompt_tokens: int | None
30
- completion_tokens: int | None
31
- total_tokens: int | None
32
- llm_text_input: str | None
33
- llm_text_output: str | None
34
- llm_new_token: str | None
35
- llm_name: str | None
36
- tool_name: str | None
37
- function_name: str | None
38
- function_id: str | None
39
- parent_function_name: str | None
40
- parent_function_id: str | None
41
- UUID: str | None
42
- framework: str | None
43
-
44
- @field_validator('llm_text_input', 'llm_text_output', 'llm_new_token', mode='before')
45
- def cast_to_str(cls, v): # pylint: disable=no-self-argument
46
- if v is None:
47
- return v
48
- try:
49
- return str(v)
50
- except Exception as e:
51
- raise ValueError(f"Value {v} cannot be cast to str: {e}") from e
File without changes
@@ -1,131 +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
- # pylint disable=ungrouped-imports
17
-
18
- from __future__ import annotations
19
-
20
- import functools
21
- import logging
22
- from collections.abc import Callable
23
- from contextlib import AbstractAsyncContextManager as AsyncContextManager
24
- from contextlib import asynccontextmanager
25
- from contextvars import ContextVar
26
- from typing import Any
27
-
28
- from aiq.builder.framework_enum import LLMFrameworkEnum
29
-
30
- logger = logging.getLogger(__name__)
31
-
32
- _library_instrumented = {
33
- "langchain": False,
34
- "crewai": False,
35
- "semantic_kernel": False,
36
- "agno": False,
37
- }
38
-
39
- callback_handler_var: ContextVar[Any | None] = ContextVar("callback_handler_var", default=None)
40
-
41
-
42
- def set_framework_profiler_handler(
43
- workflow_llms: dict = None,
44
- frameworks: list[LLMFrameworkEnum] = None,
45
- ) -> Callable[[Callable[..., AsyncContextManager[Any]]], Callable[..., AsyncContextManager[Any]]]:
46
- """
47
- Decorator that wraps an async context manager function to set up framework-specific profiling.
48
- """
49
-
50
- def decorator(func: Callable[..., AsyncContextManager[Any]]) -> Callable[..., AsyncContextManager[Any]]:
51
-
52
- @functools.wraps(func)
53
- @asynccontextmanager
54
- async def wrapper(workflow_config, builder):
55
-
56
- if LLMFrameworkEnum.LANGCHAIN in frameworks and not _library_instrumented["langchain"]:
57
- from langchain_core.tracers.context import register_configure_hook
58
-
59
- from aiq.profiler.callbacks.langchain_callback_handler import LangchainProfilerHandler
60
-
61
- handler = LangchainProfilerHandler()
62
- callback_handler_var.set(handler)
63
- register_configure_hook(callback_handler_var, inheritable=True)
64
- _library_instrumented["langchain"] = True
65
- logger.debug("Langchain callback handler registered")
66
-
67
- if LLMFrameworkEnum.LLAMA_INDEX in frameworks:
68
- from llama_index.core import Settings
69
- from llama_index.core.callbacks import CallbackManager
70
-
71
- from aiq.profiler.callbacks.llama_index_callback_handler import LlamaIndexProfilerHandler
72
-
73
- handler = LlamaIndexProfilerHandler()
74
- Settings.callback_manager = CallbackManager([handler])
75
- logger.debug("LlamaIndex callback handler registered")
76
-
77
- if LLMFrameworkEnum.CREWAI in frameworks and not _library_instrumented["crewai"]:
78
- from aiq.plugins.crewai.crewai_callback_handler import \
79
- CrewAIProfilerHandler # pylint: disable=ungrouped-imports,line-too-long # noqa E501
80
-
81
- handler = CrewAIProfilerHandler()
82
- handler.instrument()
83
- _library_instrumented["crewai"] = True
84
- logger.debug("CrewAI callback handler registered")
85
-
86
- if LLMFrameworkEnum.SEMANTIC_KERNEL in frameworks and not _library_instrumented["semantic_kernel"]:
87
- from aiq.profiler.callbacks.semantic_kernel_callback_handler import SemanticKernelProfilerHandler
88
-
89
- handler = SemanticKernelProfilerHandler(workflow_llms=workflow_llms)
90
- handler.instrument()
91
- _library_instrumented["semantic_kernel"] = True
92
- logger.debug("SemanticKernel callback handler registered")
93
-
94
- if LLMFrameworkEnum.AGNO in frameworks and not _library_instrumented["agno"]:
95
- from aiq.profiler.callbacks.agno_callback_handler import AgnoProfilerHandler
96
-
97
- handler = AgnoProfilerHandler()
98
- handler.instrument()
99
- _library_instrumented["agno"] = True
100
- logger.info("Agno callback handler registered")
101
-
102
- # IMPORTANT: actually call the wrapped function as an async context manager
103
- async with func(workflow_config, builder) as result:
104
- yield result
105
-
106
- return wrapper
107
-
108
- return decorator
109
-
110
-
111
- def chain_wrapped_build_fn(
112
- original_build_fn: Callable[..., AsyncContextManager],
113
- workflow_llms: dict,
114
- function_frameworks: list[LLMFrameworkEnum],
115
- ) -> Callable[..., AsyncContextManager]:
116
- """
117
- Convert an original build function into an async context manager that
118
- wraps it with a single call to set_framework_profiler_handler, passing
119
- all frameworks at once.
120
- """
121
-
122
- # Define a base async context manager that simply calls the original build function.
123
- @asynccontextmanager
124
- async def base_fn(*args, **kwargs):
125
- async with original_build_fn(*args, **kwargs) as w:
126
- yield w
127
-
128
- # Instead of wrapping iteratively, we now call the decorator once,
129
- # passing the entire list of frameworks along with the workflow_llms.
130
- wrapped_fn = set_framework_profiler_handler(workflow_llms, function_frameworks)(base_fn)
131
- return wrapped_fn