aiqtoolkit 1.2.0rc3__py3-none-any.whl → 1.2.0rc5__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 (440) hide show
  1. aiqtoolkit-1.2.0rc5.dist-info/METADATA +29 -0
  2. aiqtoolkit-1.2.0rc5.dist-info/RECORD +4 -0
  3. aiqtoolkit-1.2.0rc5.dist-info/top_level.txt +1 -0
  4. aiq/agent/__init__.py +0 -0
  5. aiq/agent/base.py +0 -239
  6. aiq/agent/dual_node.py +0 -67
  7. aiq/agent/react_agent/__init__.py +0 -0
  8. aiq/agent/react_agent/agent.py +0 -355
  9. aiq/agent/react_agent/output_parser.py +0 -104
  10. aiq/agent/react_agent/prompt.py +0 -41
  11. aiq/agent/react_agent/register.py +0 -149
  12. aiq/agent/reasoning_agent/__init__.py +0 -0
  13. aiq/agent/reasoning_agent/reasoning_agent.py +0 -225
  14. aiq/agent/register.py +0 -23
  15. aiq/agent/rewoo_agent/__init__.py +0 -0
  16. aiq/agent/rewoo_agent/agent.py +0 -411
  17. aiq/agent/rewoo_agent/prompt.py +0 -108
  18. aiq/agent/rewoo_agent/register.py +0 -158
  19. aiq/agent/tool_calling_agent/__init__.py +0 -0
  20. aiq/agent/tool_calling_agent/agent.py +0 -119
  21. aiq/agent/tool_calling_agent/register.py +0 -106
  22. aiq/authentication/__init__.py +0 -14
  23. aiq/authentication/api_key/__init__.py +0 -14
  24. aiq/authentication/api_key/api_key_auth_provider.py +0 -92
  25. aiq/authentication/api_key/api_key_auth_provider_config.py +0 -124
  26. aiq/authentication/api_key/register.py +0 -26
  27. aiq/authentication/exceptions/__init__.py +0 -14
  28. aiq/authentication/exceptions/api_key_exceptions.py +0 -38
  29. aiq/authentication/exceptions/auth_code_grant_exceptions.py +0 -86
  30. aiq/authentication/exceptions/call_back_exceptions.py +0 -38
  31. aiq/authentication/exceptions/request_exceptions.py +0 -54
  32. aiq/authentication/http_basic_auth/__init__.py +0 -0
  33. aiq/authentication/http_basic_auth/http_basic_auth_provider.py +0 -81
  34. aiq/authentication/http_basic_auth/register.py +0 -30
  35. aiq/authentication/interfaces.py +0 -93
  36. aiq/authentication/oauth2/__init__.py +0 -14
  37. aiq/authentication/oauth2/oauth2_auth_code_flow_provider.py +0 -107
  38. aiq/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +0 -39
  39. aiq/authentication/oauth2/register.py +0 -25
  40. aiq/authentication/register.py +0 -21
  41. aiq/builder/__init__.py +0 -0
  42. aiq/builder/builder.py +0 -285
  43. aiq/builder/component_utils.py +0 -316
  44. aiq/builder/context.py +0 -264
  45. aiq/builder/embedder.py +0 -24
  46. aiq/builder/eval_builder.py +0 -161
  47. aiq/builder/evaluator.py +0 -29
  48. aiq/builder/framework_enum.py +0 -24
  49. aiq/builder/front_end.py +0 -73
  50. aiq/builder/function.py +0 -344
  51. aiq/builder/function_base.py +0 -380
  52. aiq/builder/function_info.py +0 -627
  53. aiq/builder/intermediate_step_manager.py +0 -174
  54. aiq/builder/llm.py +0 -25
  55. aiq/builder/retriever.py +0 -25
  56. aiq/builder/user_interaction_manager.py +0 -74
  57. aiq/builder/workflow.py +0 -148
  58. aiq/builder/workflow_builder.py +0 -1117
  59. aiq/cli/__init__.py +0 -14
  60. aiq/cli/cli_utils/__init__.py +0 -0
  61. aiq/cli/cli_utils/config_override.py +0 -231
  62. aiq/cli/cli_utils/validation.py +0 -37
  63. aiq/cli/commands/__init__.py +0 -0
  64. aiq/cli/commands/configure/__init__.py +0 -0
  65. aiq/cli/commands/configure/channel/__init__.py +0 -0
  66. aiq/cli/commands/configure/channel/add.py +0 -28
  67. aiq/cli/commands/configure/channel/channel.py +0 -36
  68. aiq/cli/commands/configure/channel/remove.py +0 -30
  69. aiq/cli/commands/configure/channel/update.py +0 -30
  70. aiq/cli/commands/configure/configure.py +0 -33
  71. aiq/cli/commands/evaluate.py +0 -139
  72. aiq/cli/commands/info/__init__.py +0 -14
  73. aiq/cli/commands/info/info.py +0 -39
  74. aiq/cli/commands/info/list_channels.py +0 -32
  75. aiq/cli/commands/info/list_components.py +0 -129
  76. aiq/cli/commands/info/list_mcp.py +0 -213
  77. aiq/cli/commands/registry/__init__.py +0 -14
  78. aiq/cli/commands/registry/publish.py +0 -88
  79. aiq/cli/commands/registry/pull.py +0 -118
  80. aiq/cli/commands/registry/registry.py +0 -38
  81. aiq/cli/commands/registry/remove.py +0 -108
  82. aiq/cli/commands/registry/search.py +0 -155
  83. aiq/cli/commands/sizing/__init__.py +0 -14
  84. aiq/cli/commands/sizing/calc.py +0 -297
  85. aiq/cli/commands/sizing/sizing.py +0 -27
  86. aiq/cli/commands/start.py +0 -246
  87. aiq/cli/commands/uninstall.py +0 -81
  88. aiq/cli/commands/validate.py +0 -47
  89. aiq/cli/commands/workflow/__init__.py +0 -14
  90. aiq/cli/commands/workflow/templates/__init__.py.j2 +0 -0
  91. aiq/cli/commands/workflow/templates/config.yml.j2 +0 -16
  92. aiq/cli/commands/workflow/templates/pyproject.toml.j2 +0 -22
  93. aiq/cli/commands/workflow/templates/register.py.j2 +0 -5
  94. aiq/cli/commands/workflow/templates/workflow.py.j2 +0 -36
  95. aiq/cli/commands/workflow/workflow.py +0 -37
  96. aiq/cli/commands/workflow/workflow_commands.py +0 -313
  97. aiq/cli/entrypoint.py +0 -135
  98. aiq/cli/main.py +0 -44
  99. aiq/cli/register_workflow.py +0 -488
  100. aiq/cli/type_registry.py +0 -1000
  101. aiq/data_models/__init__.py +0 -14
  102. aiq/data_models/api_server.py +0 -694
  103. aiq/data_models/authentication.py +0 -231
  104. aiq/data_models/common.py +0 -171
  105. aiq/data_models/component.py +0 -54
  106. aiq/data_models/component_ref.py +0 -168
  107. aiq/data_models/config.py +0 -406
  108. aiq/data_models/dataset_handler.py +0 -123
  109. aiq/data_models/discovery_metadata.py +0 -286
  110. aiq/data_models/embedder.py +0 -27
  111. aiq/data_models/evaluate.py +0 -127
  112. aiq/data_models/evaluator.py +0 -26
  113. aiq/data_models/front_end.py +0 -26
  114. aiq/data_models/function.py +0 -30
  115. aiq/data_models/function_dependencies.py +0 -72
  116. aiq/data_models/interactive.py +0 -246
  117. aiq/data_models/intermediate_step.py +0 -302
  118. aiq/data_models/invocation_node.py +0 -38
  119. aiq/data_models/its_strategy.py +0 -30
  120. aiq/data_models/llm.py +0 -27
  121. aiq/data_models/logging.py +0 -26
  122. aiq/data_models/memory.py +0 -27
  123. aiq/data_models/object_store.py +0 -44
  124. aiq/data_models/profiler.py +0 -54
  125. aiq/data_models/registry_handler.py +0 -26
  126. aiq/data_models/retriever.py +0 -30
  127. aiq/data_models/retry_mixin.py +0 -35
  128. aiq/data_models/span.py +0 -187
  129. aiq/data_models/step_adaptor.py +0 -64
  130. aiq/data_models/streaming.py +0 -33
  131. aiq/data_models/swe_bench_model.py +0 -54
  132. aiq/data_models/telemetry_exporter.py +0 -26
  133. aiq/embedder/__init__.py +0 -0
  134. aiq/embedder/langchain_client.py +0 -41
  135. aiq/embedder/nim_embedder.py +0 -59
  136. aiq/embedder/openai_embedder.py +0 -43
  137. aiq/embedder/register.py +0 -24
  138. aiq/eval/__init__.py +0 -14
  139. aiq/eval/config.py +0 -60
  140. aiq/eval/dataset_handler/__init__.py +0 -0
  141. aiq/eval/dataset_handler/dataset_downloader.py +0 -106
  142. aiq/eval/dataset_handler/dataset_filter.py +0 -52
  143. aiq/eval/dataset_handler/dataset_handler.py +0 -254
  144. aiq/eval/evaluate.py +0 -506
  145. aiq/eval/evaluator/__init__.py +0 -14
  146. aiq/eval/evaluator/base_evaluator.py +0 -73
  147. aiq/eval/evaluator/evaluator_model.py +0 -45
  148. aiq/eval/intermediate_step_adapter.py +0 -99
  149. aiq/eval/rag_evaluator/__init__.py +0 -0
  150. aiq/eval/rag_evaluator/evaluate.py +0 -178
  151. aiq/eval/rag_evaluator/register.py +0 -143
  152. aiq/eval/register.py +0 -23
  153. aiq/eval/remote_workflow.py +0 -133
  154. aiq/eval/runners/__init__.py +0 -14
  155. aiq/eval/runners/config.py +0 -39
  156. aiq/eval/runners/multi_eval_runner.py +0 -54
  157. aiq/eval/runtime_event_subscriber.py +0 -52
  158. aiq/eval/swe_bench_evaluator/__init__.py +0 -0
  159. aiq/eval/swe_bench_evaluator/evaluate.py +0 -215
  160. aiq/eval/swe_bench_evaluator/register.py +0 -36
  161. aiq/eval/trajectory_evaluator/__init__.py +0 -0
  162. aiq/eval/trajectory_evaluator/evaluate.py +0 -75
  163. aiq/eval/trajectory_evaluator/register.py +0 -40
  164. aiq/eval/tunable_rag_evaluator/__init__.py +0 -0
  165. aiq/eval/tunable_rag_evaluator/evaluate.py +0 -245
  166. aiq/eval/tunable_rag_evaluator/register.py +0 -52
  167. aiq/eval/usage_stats.py +0 -41
  168. aiq/eval/utils/__init__.py +0 -0
  169. aiq/eval/utils/output_uploader.py +0 -140
  170. aiq/eval/utils/tqdm_position_registry.py +0 -40
  171. aiq/eval/utils/weave_eval.py +0 -184
  172. aiq/experimental/__init__.py +0 -0
  173. aiq/experimental/decorators/__init__.py +0 -0
  174. aiq/experimental/decorators/experimental_warning_decorator.py +0 -130
  175. aiq/experimental/inference_time_scaling/__init__.py +0 -0
  176. aiq/experimental/inference_time_scaling/editing/__init__.py +0 -0
  177. aiq/experimental/inference_time_scaling/editing/iterative_plan_refinement_editor.py +0 -147
  178. aiq/experimental/inference_time_scaling/editing/llm_as_a_judge_editor.py +0 -204
  179. aiq/experimental/inference_time_scaling/editing/motivation_aware_summarization.py +0 -107
  180. aiq/experimental/inference_time_scaling/functions/__init__.py +0 -0
  181. aiq/experimental/inference_time_scaling/functions/execute_score_select_function.py +0 -105
  182. aiq/experimental/inference_time_scaling/functions/its_tool_orchestration_function.py +0 -205
  183. aiq/experimental/inference_time_scaling/functions/its_tool_wrapper_function.py +0 -146
  184. aiq/experimental/inference_time_scaling/functions/plan_select_execute_function.py +0 -224
  185. aiq/experimental/inference_time_scaling/models/__init__.py +0 -0
  186. aiq/experimental/inference_time_scaling/models/editor_config.py +0 -132
  187. aiq/experimental/inference_time_scaling/models/its_item.py +0 -48
  188. aiq/experimental/inference_time_scaling/models/scoring_config.py +0 -112
  189. aiq/experimental/inference_time_scaling/models/search_config.py +0 -120
  190. aiq/experimental/inference_time_scaling/models/selection_config.py +0 -154
  191. aiq/experimental/inference_time_scaling/models/stage_enums.py +0 -43
  192. aiq/experimental/inference_time_scaling/models/strategy_base.py +0 -66
  193. aiq/experimental/inference_time_scaling/models/tool_use_config.py +0 -41
  194. aiq/experimental/inference_time_scaling/register.py +0 -36
  195. aiq/experimental/inference_time_scaling/scoring/__init__.py +0 -0
  196. aiq/experimental/inference_time_scaling/scoring/llm_based_agent_scorer.py +0 -168
  197. aiq/experimental/inference_time_scaling/scoring/llm_based_plan_scorer.py +0 -168
  198. aiq/experimental/inference_time_scaling/scoring/motivation_aware_scorer.py +0 -111
  199. aiq/experimental/inference_time_scaling/search/__init__.py +0 -0
  200. aiq/experimental/inference_time_scaling/search/multi_llm_planner.py +0 -128
  201. aiq/experimental/inference_time_scaling/search/multi_query_retrieval_search.py +0 -122
  202. aiq/experimental/inference_time_scaling/search/single_shot_multi_plan_planner.py +0 -128
  203. aiq/experimental/inference_time_scaling/selection/__init__.py +0 -0
  204. aiq/experimental/inference_time_scaling/selection/best_of_n_selector.py +0 -63
  205. aiq/experimental/inference_time_scaling/selection/llm_based_agent_output_selector.py +0 -131
  206. aiq/experimental/inference_time_scaling/selection/llm_based_output_merging_selector.py +0 -159
  207. aiq/experimental/inference_time_scaling/selection/llm_based_plan_selector.py +0 -128
  208. aiq/experimental/inference_time_scaling/selection/threshold_selector.py +0 -58
  209. aiq/front_ends/__init__.py +0 -14
  210. aiq/front_ends/console/__init__.py +0 -14
  211. aiq/front_ends/console/authentication_flow_handler.py +0 -233
  212. aiq/front_ends/console/console_front_end_config.py +0 -32
  213. aiq/front_ends/console/console_front_end_plugin.py +0 -96
  214. aiq/front_ends/console/register.py +0 -25
  215. aiq/front_ends/cron/__init__.py +0 -14
  216. aiq/front_ends/fastapi/__init__.py +0 -14
  217. aiq/front_ends/fastapi/auth_flow_handlers/__init__.py +0 -0
  218. aiq/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +0 -27
  219. aiq/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +0 -107
  220. aiq/front_ends/fastapi/fastapi_front_end_config.py +0 -234
  221. aiq/front_ends/fastapi/fastapi_front_end_controller.py +0 -68
  222. aiq/front_ends/fastapi/fastapi_front_end_plugin.py +0 -116
  223. aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py +0 -1092
  224. aiq/front_ends/fastapi/html_snippets/__init__.py +0 -14
  225. aiq/front_ends/fastapi/html_snippets/auth_code_grant_success.py +0 -35
  226. aiq/front_ends/fastapi/intermediate_steps_subscriber.py +0 -80
  227. aiq/front_ends/fastapi/job_store.py +0 -183
  228. aiq/front_ends/fastapi/main.py +0 -72
  229. aiq/front_ends/fastapi/message_handler.py +0 -298
  230. aiq/front_ends/fastapi/message_validator.py +0 -345
  231. aiq/front_ends/fastapi/register.py +0 -25
  232. aiq/front_ends/fastapi/response_helpers.py +0 -195
  233. aiq/front_ends/fastapi/step_adaptor.py +0 -321
  234. aiq/front_ends/mcp/__init__.py +0 -14
  235. aiq/front_ends/mcp/mcp_front_end_config.py +0 -32
  236. aiq/front_ends/mcp/mcp_front_end_plugin.py +0 -93
  237. aiq/front_ends/mcp/register.py +0 -27
  238. aiq/front_ends/mcp/tool_converter.py +0 -242
  239. aiq/front_ends/register.py +0 -22
  240. aiq/front_ends/simple_base/__init__.py +0 -14
  241. aiq/front_ends/simple_base/simple_front_end_plugin_base.py +0 -54
  242. aiq/llm/__init__.py +0 -0
  243. aiq/llm/aws_bedrock_llm.py +0 -57
  244. aiq/llm/nim_llm.py +0 -46
  245. aiq/llm/openai_llm.py +0 -46
  246. aiq/llm/register.py +0 -23
  247. aiq/llm/utils/__init__.py +0 -14
  248. aiq/llm/utils/env_config_value.py +0 -94
  249. aiq/llm/utils/error.py +0 -17
  250. aiq/memory/__init__.py +0 -20
  251. aiq/memory/interfaces.py +0 -183
  252. aiq/memory/models.py +0 -112
  253. aiq/meta/module_to_distro.json +0 -3
  254. aiq/meta/pypi.md +0 -58
  255. aiq/object_store/__init__.py +0 -20
  256. aiq/object_store/in_memory_object_store.py +0 -74
  257. aiq/object_store/interfaces.py +0 -84
  258. aiq/object_store/models.py +0 -36
  259. aiq/object_store/register.py +0 -20
  260. aiq/observability/__init__.py +0 -14
  261. aiq/observability/exporter/__init__.py +0 -14
  262. aiq/observability/exporter/base_exporter.py +0 -449
  263. aiq/observability/exporter/exporter.py +0 -78
  264. aiq/observability/exporter/file_exporter.py +0 -33
  265. aiq/observability/exporter/processing_exporter.py +0 -322
  266. aiq/observability/exporter/raw_exporter.py +0 -52
  267. aiq/observability/exporter/span_exporter.py +0 -265
  268. aiq/observability/exporter_manager.py +0 -335
  269. aiq/observability/mixin/__init__.py +0 -14
  270. aiq/observability/mixin/batch_config_mixin.py +0 -26
  271. aiq/observability/mixin/collector_config_mixin.py +0 -23
  272. aiq/observability/mixin/file_mixin.py +0 -288
  273. aiq/observability/mixin/file_mode.py +0 -23
  274. aiq/observability/mixin/resource_conflict_mixin.py +0 -134
  275. aiq/observability/mixin/serialize_mixin.py +0 -61
  276. aiq/observability/mixin/type_introspection_mixin.py +0 -183
  277. aiq/observability/processor/__init__.py +0 -14
  278. aiq/observability/processor/batching_processor.py +0 -309
  279. aiq/observability/processor/callback_processor.py +0 -42
  280. aiq/observability/processor/intermediate_step_serializer.py +0 -28
  281. aiq/observability/processor/processor.py +0 -71
  282. aiq/observability/register.py +0 -96
  283. aiq/observability/utils/__init__.py +0 -14
  284. aiq/observability/utils/dict_utils.py +0 -236
  285. aiq/observability/utils/time_utils.py +0 -31
  286. aiq/plugins/.namespace +0 -1
  287. aiq/profiler/__init__.py +0 -0
  288. aiq/profiler/calc/__init__.py +0 -14
  289. aiq/profiler/calc/calc_runner.py +0 -627
  290. aiq/profiler/calc/calculations.py +0 -288
  291. aiq/profiler/calc/data_models.py +0 -188
  292. aiq/profiler/calc/plot.py +0 -345
  293. aiq/profiler/callbacks/__init__.py +0 -0
  294. aiq/profiler/callbacks/agno_callback_handler.py +0 -295
  295. aiq/profiler/callbacks/base_callback_class.py +0 -20
  296. aiq/profiler/callbacks/langchain_callback_handler.py +0 -290
  297. aiq/profiler/callbacks/llama_index_callback_handler.py +0 -205
  298. aiq/profiler/callbacks/semantic_kernel_callback_handler.py +0 -238
  299. aiq/profiler/callbacks/token_usage_base_model.py +0 -27
  300. aiq/profiler/data_frame_row.py +0 -51
  301. aiq/profiler/data_models.py +0 -24
  302. aiq/profiler/decorators/__init__.py +0 -0
  303. aiq/profiler/decorators/framework_wrapper.py +0 -131
  304. aiq/profiler/decorators/function_tracking.py +0 -254
  305. aiq/profiler/forecasting/__init__.py +0 -0
  306. aiq/profiler/forecasting/config.py +0 -18
  307. aiq/profiler/forecasting/model_trainer.py +0 -75
  308. aiq/profiler/forecasting/models/__init__.py +0 -22
  309. aiq/profiler/forecasting/models/forecasting_base_model.py +0 -40
  310. aiq/profiler/forecasting/models/linear_model.py +0 -196
  311. aiq/profiler/forecasting/models/random_forest_regressor.py +0 -268
  312. aiq/profiler/inference_metrics_model.py +0 -28
  313. aiq/profiler/inference_optimization/__init__.py +0 -0
  314. aiq/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
  315. aiq/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +0 -460
  316. aiq/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +0 -258
  317. aiq/profiler/inference_optimization/data_models.py +0 -386
  318. aiq/profiler/inference_optimization/experimental/__init__.py +0 -0
  319. aiq/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +0 -468
  320. aiq/profiler/inference_optimization/experimental/prefix_span_analysis.py +0 -405
  321. aiq/profiler/inference_optimization/llm_metrics.py +0 -212
  322. aiq/profiler/inference_optimization/prompt_caching.py +0 -163
  323. aiq/profiler/inference_optimization/token_uniqueness.py +0 -107
  324. aiq/profiler/inference_optimization/workflow_runtimes.py +0 -72
  325. aiq/profiler/intermediate_property_adapter.py +0 -102
  326. aiq/profiler/profile_runner.py +0 -473
  327. aiq/profiler/utils.py +0 -184
  328. aiq/registry_handlers/__init__.py +0 -0
  329. aiq/registry_handlers/local/__init__.py +0 -0
  330. aiq/registry_handlers/local/local_handler.py +0 -176
  331. aiq/registry_handlers/local/register_local.py +0 -37
  332. aiq/registry_handlers/metadata_factory.py +0 -60
  333. aiq/registry_handlers/package_utils.py +0 -198
  334. aiq/registry_handlers/pypi/__init__.py +0 -0
  335. aiq/registry_handlers/pypi/pypi_handler.py +0 -251
  336. aiq/registry_handlers/pypi/register_pypi.py +0 -40
  337. aiq/registry_handlers/register.py +0 -21
  338. aiq/registry_handlers/registry_handler_base.py +0 -157
  339. aiq/registry_handlers/rest/__init__.py +0 -0
  340. aiq/registry_handlers/rest/register_rest.py +0 -56
  341. aiq/registry_handlers/rest/rest_handler.py +0 -237
  342. aiq/registry_handlers/schemas/__init__.py +0 -0
  343. aiq/registry_handlers/schemas/headers.py +0 -42
  344. aiq/registry_handlers/schemas/package.py +0 -68
  345. aiq/registry_handlers/schemas/publish.py +0 -63
  346. aiq/registry_handlers/schemas/pull.py +0 -82
  347. aiq/registry_handlers/schemas/remove.py +0 -36
  348. aiq/registry_handlers/schemas/search.py +0 -91
  349. aiq/registry_handlers/schemas/status.py +0 -47
  350. aiq/retriever/__init__.py +0 -0
  351. aiq/retriever/interface.py +0 -37
  352. aiq/retriever/milvus/__init__.py +0 -14
  353. aiq/retriever/milvus/register.py +0 -81
  354. aiq/retriever/milvus/retriever.py +0 -228
  355. aiq/retriever/models.py +0 -74
  356. aiq/retriever/nemo_retriever/__init__.py +0 -14
  357. aiq/retriever/nemo_retriever/register.py +0 -60
  358. aiq/retriever/nemo_retriever/retriever.py +0 -190
  359. aiq/retriever/register.py +0 -22
  360. aiq/runtime/__init__.py +0 -14
  361. aiq/runtime/loader.py +0 -194
  362. aiq/runtime/runner.py +0 -190
  363. aiq/runtime/session.py +0 -158
  364. aiq/runtime/user_metadata.py +0 -130
  365. aiq/settings/__init__.py +0 -0
  366. aiq/settings/global_settings.py +0 -318
  367. aiq/test/.namespace +0 -1
  368. aiq/tool/__init__.py +0 -0
  369. aiq/tool/chat_completion.py +0 -74
  370. aiq/tool/code_execution/README.md +0 -152
  371. aiq/tool/code_execution/__init__.py +0 -0
  372. aiq/tool/code_execution/code_sandbox.py +0 -267
  373. aiq/tool/code_execution/local_sandbox/.gitignore +0 -1
  374. aiq/tool/code_execution/local_sandbox/Dockerfile.sandbox +0 -60
  375. aiq/tool/code_execution/local_sandbox/__init__.py +0 -13
  376. aiq/tool/code_execution/local_sandbox/local_sandbox_server.py +0 -198
  377. aiq/tool/code_execution/local_sandbox/sandbox.requirements.txt +0 -6
  378. aiq/tool/code_execution/local_sandbox/start_local_sandbox.sh +0 -50
  379. aiq/tool/code_execution/register.py +0 -74
  380. aiq/tool/code_execution/test_code_execution_sandbox.py +0 -414
  381. aiq/tool/code_execution/utils.py +0 -100
  382. aiq/tool/datetime_tools.py +0 -42
  383. aiq/tool/document_search.py +0 -141
  384. aiq/tool/github_tools/__init__.py +0 -0
  385. aiq/tool/github_tools/create_github_commit.py +0 -133
  386. aiq/tool/github_tools/create_github_issue.py +0 -87
  387. aiq/tool/github_tools/create_github_pr.py +0 -106
  388. aiq/tool/github_tools/get_github_file.py +0 -106
  389. aiq/tool/github_tools/get_github_issue.py +0 -166
  390. aiq/tool/github_tools/get_github_pr.py +0 -256
  391. aiq/tool/github_tools/update_github_issue.py +0 -100
  392. aiq/tool/mcp/__init__.py +0 -14
  393. aiq/tool/mcp/exceptions.py +0 -142
  394. aiq/tool/mcp/mcp_client.py +0 -255
  395. aiq/tool/mcp/mcp_tool.py +0 -96
  396. aiq/tool/memory_tools/__init__.py +0 -0
  397. aiq/tool/memory_tools/add_memory_tool.py +0 -79
  398. aiq/tool/memory_tools/delete_memory_tool.py +0 -67
  399. aiq/tool/memory_tools/get_memory_tool.py +0 -72
  400. aiq/tool/nvidia_rag.py +0 -95
  401. aiq/tool/register.py +0 -38
  402. aiq/tool/retriever.py +0 -89
  403. aiq/tool/server_tools.py +0 -66
  404. aiq/utils/__init__.py +0 -0
  405. aiq/utils/data_models/__init__.py +0 -0
  406. aiq/utils/data_models/schema_validator.py +0 -58
  407. aiq/utils/debugging_utils.py +0 -43
  408. aiq/utils/exception_handlers/__init__.py +0 -0
  409. aiq/utils/exception_handlers/automatic_retries.py +0 -289
  410. aiq/utils/exception_handlers/mcp.py +0 -211
  411. aiq/utils/exception_handlers/schemas.py +0 -114
  412. aiq/utils/io/__init__.py +0 -0
  413. aiq/utils/io/model_processing.py +0 -28
  414. aiq/utils/io/yaml_tools.py +0 -119
  415. aiq/utils/log_utils.py +0 -37
  416. aiq/utils/metadata_utils.py +0 -74
  417. aiq/utils/optional_imports.py +0 -142
  418. aiq/utils/producer_consumer_queue.py +0 -178
  419. aiq/utils/reactive/__init__.py +0 -0
  420. aiq/utils/reactive/base/__init__.py +0 -0
  421. aiq/utils/reactive/base/observable_base.py +0 -65
  422. aiq/utils/reactive/base/observer_base.py +0 -55
  423. aiq/utils/reactive/base/subject_base.py +0 -79
  424. aiq/utils/reactive/observable.py +0 -59
  425. aiq/utils/reactive/observer.py +0 -76
  426. aiq/utils/reactive/subject.py +0 -131
  427. aiq/utils/reactive/subscription.py +0 -49
  428. aiq/utils/settings/__init__.py +0 -0
  429. aiq/utils/settings/global_settings.py +0 -197
  430. aiq/utils/string_utils.py +0 -38
  431. aiq/utils/type_converter.py +0 -290
  432. aiq/utils/type_utils.py +0 -484
  433. aiq/utils/url_utils.py +0 -27
  434. aiqtoolkit-1.2.0rc3.dist-info/METADATA +0 -363
  435. aiqtoolkit-1.2.0rc3.dist-info/RECORD +0 -437
  436. aiqtoolkit-1.2.0rc3.dist-info/entry_points.txt +0 -20
  437. aiqtoolkit-1.2.0rc3.dist-info/licenses/LICENSE-3rd-party.txt +0 -3686
  438. aiqtoolkit-1.2.0rc3.dist-info/licenses/LICENSE.md +0 -201
  439. aiqtoolkit-1.2.0rc3.dist-info/top_level.txt +0 -1
  440. {aiqtoolkit-1.2.0rc3.dist-info → aiqtoolkit-1.2.0rc5.dist-info}/WHEEL +0 -0
@@ -1,405 +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
- An advanced script that:
17
-
18
- 1. Builds chronological call sequences (LLM or TOOL) from a DataFrame of events.
19
- 2. Incorporates llm_text_input for LLM calls into the token used by PrefixSpan.
20
- 3. Runs PrefixSpan to discover frequent sub-sequences (patterns) across examples.
21
- 4. Computes coverage (fraction of examples containing each pattern) and average sub-sequence duration.
22
- 5. Returns a Pydantic model with the top patterns plus a textual report.
23
-
24
- Main use case:
25
-
26
- - Identify recurring sequences of calls + repeated LLM text inputs, which can help with caching or further optimization
27
- (deduplicate repeated calls or pre-load certain tokens).
28
- """
29
-
30
- import logging
31
-
32
- import numpy as np
33
- import pandas as pd
34
-
35
- from aiq.data_models.intermediate_step import IntermediateStep
36
- from aiq.profiler.inference_optimization.data_models import FrequentPattern
37
- from aiq.profiler.inference_optimization.data_models import PrefixCallNode
38
- from aiq.profiler.inference_optimization.data_models import PrefixSpanSubworkflowResult
39
- from aiq.profiler.utils import create_standardized_dataframe
40
-
41
- logger = logging.getLogger(__name__)
42
-
43
- # --------------------------------------------------------------------------------
44
- # 1) Building Sequences (Including llm_text_input)
45
- # --------------------------------------------------------------------------------
46
-
47
-
48
- def parse_op_type(evt: str) -> str | None:
49
- """Map event_type => 'LLM' or 'TOOL' if it starts with those prefixes."""
50
- et = evt.upper()
51
- if et.startswith("LLM_"):
52
- return "LLM"
53
- if et.startswith("TOOL_"):
54
- return "TOOL"
55
- return None
56
-
57
-
58
- def get_op_name(row: pd.Series, op_type: str) -> str:
59
- """Pick the operation_name from either llm_name or tool_name based on op_type."""
60
- if op_type == "LLM":
61
- return row.get("llm_name") or "unknown_llm"
62
- if op_type == "TOOL":
63
- return row.get("tool_name") or "unknown_tool"
64
- return "unknown_op"
65
-
66
-
67
- def build_call_sequence_for_example(example_df: pd.DataFrame) -> list[PrefixCallNode]:
68
- """
69
- For a single example's events, pair START/END calls and build a chronological list of PrefixCallNodes,
70
- storing llm_text_input if op_type=LLM and it's available at START or END.
71
-
72
- """
73
- example_df = example_df.sort_values("event_timestamp")
74
- example_num = int(example_df["example_number"].iloc[0])
75
-
76
- partial_map: dict[str, dict] = {}
77
- calls_list: list[PrefixCallNode] = []
78
-
79
- for _, row in example_df.iterrows():
80
- evt_type = row["event_type"].value.upper()
81
- uuid = str(row["UUID"])
82
- ts = float(row["event_timestamp"])
83
-
84
- op_type = parse_op_type(evt_type)
85
- if not op_type:
86
- # ignore events that are not LLM_/TOOL_
87
- continue
88
-
89
- if evt_type.endswith("_START"):
90
- op_name = get_op_name(row, op_type)
91
- call_info = {
92
- "uuid": uuid,
93
- "example_number": example_num,
94
- "operation_type": op_type,
95
- "operation_name": op_name,
96
- "start_time": ts,
97
- "llm_text_input": None
98
- }
99
- # If llm_text_input is present in START
100
- if op_type == "LLM" and "llm_text_input" in row and pd.notna(row["llm_text_input"]):
101
- call_info["llm_text_input"] = str(row["llm_text_input"])
102
- partial_map[uuid] = call_info
103
-
104
- elif evt_type.endswith("_END"):
105
- if uuid in partial_map:
106
- # finalize
107
- start_info = partial_map[uuid]
108
- end_time = ts
109
- duration = max(0.0, end_time - start_info["start_time"])
110
- # If we only have llm_text_input at END, override if not present
111
- if op_type == "LLM" and "llm_text_input" in row and pd.notna(row["llm_text_input"]):
112
- start_info["llm_text_input"] = str(row["llm_text_input"])
113
-
114
- node = PrefixCallNode(uuid=uuid,
115
- example_number=example_num,
116
- operation_type=start_info["operation_type"],
117
- operation_name=start_info["operation_name"],
118
- start_time=start_info["start_time"],
119
- end_time=end_time,
120
- duration=duration,
121
- llm_text_input=start_info["llm_text_input"])
122
- calls_list.append(node)
123
- del partial_map[uuid]
124
-
125
- # Sort final calls by start_time
126
- calls_list.sort(key=lambda c: c.start_time)
127
- return calls_list
128
-
129
-
130
- def build_sequences(df: pd.DataFrame) -> dict[int, list[PrefixCallNode]]:
131
- """
132
- Group events by example_number, build a chronological list of PrefixCallNode for each example,
133
- including the LLM text input if present.
134
- """
135
- dfc = df.copy()
136
- dfc.sort_values(["example_number", "event_timestamp"], inplace=True)
137
-
138
- sequences_map = {}
139
- for ex_num, group_df in dfc.groupby("example_number"):
140
- seq_calls = build_call_sequence_for_example(group_df)
141
- sequences_map[ex_num] = seq_calls
142
- return sequences_map
143
-
144
-
145
- # --------------------------------------------------------------------------------
146
- # 2) Token Construction & PrefixSpan
147
- # --------------------------------------------------------------------------------
148
-
149
-
150
- def build_token(call: PrefixCallNode, max_text_len: int = 20, prefix_list: list[str] = None) -> str:
151
- """
152
- Construct a token for prefixspan from a PrefixCallNode.
153
- - We do "LLM:{operation_name}|{text}" if it's an LLM call and text is available
154
- - We optionally truncate or hash the text for length. Here we just do naive truncation
155
- - For a tool call, we do "TOOL:{operation_name}"
156
- """
157
- if call.operation_type == "LLM":
158
- text_part = ""
159
- if call.llm_text_input:
160
- # naive truncation
161
- truncated = call.llm_text_input
162
-
163
- # Check truncated text for an exact match of any string in prefix_list
164
- # Does not have to be in just the prefix, but anywhere
165
- # Replaces the matched string with <common_prefix>
166
- if prefix_list:
167
- for prefix in prefix_list:
168
- for i in range(len(prefix), 0, -1):
169
- if truncated.startswith(prefix[:i]):
170
- truncated = truncated.replace(prefix[:i], "<common_prefix>")
171
- break
172
-
173
- truncated = truncated[:max_text_len].replace("\n", " ")
174
- text_part = f"|{truncated}"
175
- return f"LLM:{call.operation_name}{text_part}"
176
-
177
- return f"TOOL:{call.operation_name}"
178
-
179
-
180
- def convert_sequences_for_prefixspan(sequences_map: dict[int, list[PrefixCallNode]],
181
- max_text_len: int = 20,
182
- prefix_list: list[str] = None) -> list[list[str]]:
183
- """
184
- Convert each example's list of PrefixCallNode into a list of tokens. Return a list-of-lists
185
- suitable for prefixspan. E.g.::
186
-
187
- [
188
- ["LLM:llama-3|Hello", "TOOL:internet-search", "LLM:llama-3|How are you?"],
189
- ["LLM:davinci|some prompt", "TOOL:vector-db"]
190
- ...
191
- ]
192
-
193
- """
194
- result = []
195
- for _, call_list in sequences_map.items():
196
- token_list = [build_token(c, max_text_len, prefix_list) for c in call_list]
197
- result.append(token_list)
198
- return result
199
-
200
-
201
- def run_prefixspan(sequences_map: dict[int, list[PrefixCallNode]],
202
- min_support: int | float,
203
- max_text_len: int = 20,
204
- prefix_list: list[str] = None) -> list[tuple[list[str], int]]:
205
- """
206
- 1) Convert all example sequences => tokens
207
- 2) Run prefixspan with min_support
208
- 3) Return (pattern, freq) list
209
- """
210
-
211
- try:
212
- from prefixspan import PrefixSpan
213
- except ImportError:
214
- logger.error("prefixspan is not installed. Please install prefixspan to run the prefix analysis in the "
215
- "profiler or install `aiq[profiler]` to install all necessary profiling packages.")
216
-
217
- raise
218
-
219
- token_seqs = convert_sequences_for_prefixspan(sequences_map, max_text_len, prefix_list)
220
-
221
- ps = PrefixSpan(token_seqs)
222
-
223
- # Convert min_support if float => absolute freq
224
- # prefixspan interprets min_support as an absolute occurrence count
225
- if isinstance(min_support, float):
226
- total_seq_count = len(token_seqs)
227
- abs_min_support = max(1, int(round(min_support * total_seq_count)))
228
- else:
229
- abs_min_support = min_support
230
-
231
- freq_patterns = ps.frequent(abs_min_support) # pylint: disable=not-callable
232
- # freq_patterns => [(count, [item1, item2, ...])]
233
-
234
- results = []
235
- for (count, pat) in freq_patterns:
236
- results.append((pat, count))
237
- return results
238
-
239
-
240
- # --------------------------------------------------------------------------------
241
- # 3) Coverage & Duration Computation
242
- # --------------------------------------------------------------------------------
243
-
244
-
245
- def find_contiguous_matches(pattern: list[str], seq: list[str]) -> list[tuple[int, int]]:
246
- """
247
- Look for contiguous matches of 'pattern' in 'seq' by naive scanning.
248
- e.g. pattern=["LLM:llama-3|Hello", "TOOL:internet-search"], seq=...
249
- Return list of (start_idx, end_idx).
250
- """
251
- matches = []
252
- plen = len(pattern)
253
- slen = len(seq)
254
- for start in range(slen - plen + 1):
255
- if seq[start:start + plen] == pattern:
256
- matches.append((start, start + plen - 1))
257
- return matches
258
-
259
-
260
- def compute_coverage_and_duration(sequences_map: dict[int, list[PrefixCallNode]],
261
- prefixspan_patterns: list[tuple[list[str], int]],
262
- top_k: int,
263
- min_coverage: float = 0.0,
264
- max_text_len: int = 20) -> list[FrequentPattern]:
265
- """
266
- For each pattern from prefixspan, compute:
267
-
268
- - coverage: fraction of examples that contain it
269
- - average_duration: sum of durations of calls in sub-sequence / total occurrences
270
-
271
- Then filter by min_coverage and pick top_k, sorted by frequency, coverage, avg_duration desc.
272
- """
273
- # We'll also rebuild token sequences for matching
274
- token_sequences = {}
275
- call_sequences = {}
276
- for ex_num, call_list in sequences_map.items():
277
- token_seq = [build_token(c, max_text_len) for c in call_list]
278
- token_sequences[ex_num] = token_seq
279
- call_sequences[ex_num] = call_list
280
-
281
- total_examples = len(token_sequences)
282
- results: list[FrequentPattern] = []
283
-
284
- for (pat, freq) in prefixspan_patterns:
285
- # coverage => how many distinct example_num have at least one contiguous match
286
- examples_with_pattern = []
287
- total_occ = 0
288
- total_dur = 0.0
289
-
290
- for ex_num, token_seq in token_sequences.items():
291
- matches = find_contiguous_matches(pat, token_seq)
292
- if matches:
293
- examples_with_pattern.append(ex_num)
294
- # sum durations for each occurrence
295
- calls = call_sequences[ex_num]
296
- for (start_idx, end_idx) in matches:
297
- dur_sum = float(np.sum([calls[i].duration for i in range(start_idx, end_idx + 1)]))
298
- total_dur += dur_sum
299
- total_occ += 1
300
-
301
- coverage_val = len(examples_with_pattern) / total_examples if total_examples > 0 else 0.0
302
- if coverage_val < min_coverage:
303
- continue
304
-
305
- avg_dur = total_dur / total_occ if total_occ > 0 else 0.0
306
-
307
- fp = FrequentPattern(pattern=pat,
308
- frequency=freq,
309
- coverage=coverage_val,
310
- average_duration=avg_dur,
311
- examples_containing=sorted(examples_with_pattern))
312
- results.append(fp)
313
-
314
- # sort & top_k
315
- results.sort(key=lambda p: (p.frequency, p.coverage, p.average_duration), reverse=True)
316
- return results[:top_k]
317
-
318
-
319
- # --------------------------------------------------------------------------------
320
- # 4) Main Entry Function
321
- # --------------------------------------------------------------------------------
322
-
323
-
324
- def prefixspan_subworkflow_with_text( # pylint: disable=too-many-positional-arguments
325
- all_steps: list[list[IntermediateStep]],
326
- min_support: int | float = 2,
327
- top_k: int = 10,
328
- min_coverage: float = 0.0,
329
- max_text_len: int = 700,
330
- prefix_list: list[str] = None) -> PrefixSpanSubworkflowResult:
331
- """
332
- 1) Build sequences of calls for each example (with llm_text_input).
333
- 2) Convert to token lists, run PrefixSpan with min_support.
334
- 3) Compute coverage & average duration for each pattern, filter by min_coverage, pick top_k.
335
- 4) Return Pydantic model with final patterns & textual report.
336
-
337
- :param all_steps: Intermediate steps
338
- :param min_support: minimal # of times (int) or fraction (float) for prefixspan
339
- :param top_k: how many patterns to keep
340
- :param min_coverage: discard patterns that appear in fewer than this fraction of examples
341
- :param max_text_len: how many chars of llm_text_input to incorporate in the token
342
- :param prefix_list: list of prefixes to filter on and exclude from pattern matching
343
- """
344
- df = create_standardized_dataframe(all_steps)
345
- # Validate columns
346
- required_cols = {
347
- "framework",
348
- "tool_name",
349
- "llm_name",
350
- "llm_text_input",
351
- "llm_text_output",
352
- "event_timestamp",
353
- "event_type",
354
- "UUID",
355
- "example_number",
356
- "prompt_tokens",
357
- "completion_tokens",
358
- "total_tokens"
359
- }
360
- missing = required_cols - set(df.columns)
361
- if missing:
362
- raise ValueError(f"DataFrame missing required columns: {missing}")
363
-
364
- # 1) Build sequences
365
- sequences_map = build_sequences(df)
366
- total_examples = len(sequences_map)
367
-
368
- # 2) prefixspan
369
- prefixspan_patterns = run_prefixspan(sequences_map,
370
- min_support=min_support,
371
- max_text_len=max_text_len,
372
- prefix_list=prefix_list)
373
- if not prefixspan_patterns:
374
- return PrefixSpanSubworkflowResult(
375
- patterns=[], textual_report="No frequent patterns found by PrefixSpan with the given min_support.")
376
-
377
- # 3) coverage & duration
378
- final_patterns = compute_coverage_and_duration(sequences_map,
379
- prefixspan_patterns,
380
- top_k=top_k,
381
- min_coverage=min_coverage,
382
- max_text_len=max_text_len)
383
- if not final_patterns:
384
- return PrefixSpanSubworkflowResult(patterns=[],
385
- textual_report="No patterns passed coverage/duration thresholds.")
386
-
387
- # 4) Build textual report
388
- lines = []
389
- lines.append("=== PrefixSpan Sub-Workflow Mining w/ LLM Text ===")
390
- lines.append(f"Total examples: {total_examples}")
391
- lines.append(f"min_support={min_support}, top_k={top_k}, min_coverage={min_coverage}, max_text_len={max_text_len}")
392
- lines.append(f"Patterns discovered: {len(final_patterns)}")
393
-
394
- for i, pat in enumerate(final_patterns, start=1):
395
- chain_str = " -> ".join(pat.pattern)
396
- lines.append(f"\n{i}) Pattern: {chain_str}")
397
- lines.append(f" Frequency: {pat.frequency}")
398
- lines.append(f" Coverage: {pat.coverage:.2f} (appears in {len(pat.examples_containing)} examples)")
399
- lines.append(f" Avg Duration: {pat.average_duration:.2f} seconds")
400
- lines.append(f" Examples containing: {pat.examples_containing}")
401
-
402
- report_text = "\n".join(lines)
403
-
404
- # 5) Return final model
405
- return PrefixSpanSubworkflowResult(patterns=final_patterns, textual_report=report_text)
@@ -1,212 +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 numpy as np
17
- import pandas as pd
18
-
19
- from aiq.data_models.intermediate_step import IntermediateStep
20
- from aiq.profiler.utils import create_standardized_dataframe
21
-
22
-
23
- class LLMMetrics:
24
- """
25
- A utility class for computing derived metrics on standardized LLM call logs.
26
- """
27
-
28
- @staticmethod
29
- def compute_profiling_metrics(all_steps: list[list[IntermediateStep]]) -> pd.DataFrame:
30
- """
31
- Compute and append the following columns to the provided DataFrame:
32
-
33
- 1. NOVA-Event-ID (str):
34
-
35
- - The name of the calling function (`function_name`).
36
-
37
- 2. NOVA-Requests-Remaining-In-Event (int):
38
-
39
- - For each row, how many future LLM_START events will occur (strictly after
40
- this row's event_timestamp) in the same (example_number, function_name).
41
-
42
- 3. NOVA-Time-To-Next-Event (float):
43
-
44
- - For each row, the number of milliseconds until the next LLM_START event in
45
- the same (example_number, function_name). If no future event, set to -1.
46
-
47
- 4. NOVA-Time-To-Event-End (float):
48
-
49
- - For each row, the number of milliseconds until the last future LLM_START
50
- event in the same (example_number, function_name). If no future event, set to -1.
51
-
52
- 5. NOVA-Predicted-OSL (float or int):
53
-
54
- - For rows where event_type == 'LLM_START', this column will hold the
55
- `completion_tokens` of the corresponding LLM_END (matched by UUID). If no match,
56
- set to NaN (or another sentinel).
57
-
58
- 6. NOVA-Time-To-Session-End (float):
59
-
60
- - For each row, the total milliseconds remaining in the workflow invocation,
61
- i.e. until the max event_timestamp within that example_number.
62
-
63
- Assumptions:
64
-
65
- - event_timestamp is an epoch timestamp in *seconds*.
66
- - Columns required in the input df (at minimum)::
67
-
68
- ['example_number', 'event_timestamp', 'event_type', 'function_name', 'UUID', 'completion_tokens']
69
-
70
- - 'LLM_START' / 'LLM_END' events share the same UUID.
71
- - The DataFrame may have additional columns such as 'llm_text_input', 'llm_text_output',
72
- 'function_id', 'parent_function_name', 'parent_function_id', etc.
73
-
74
- :param all_steps: All intermediate steps for each example.
75
- :return: The same DataFrame with the six NOVA- columns appended.
76
- """
77
-
78
- df = create_standardized_dataframe(all_steps)
79
-
80
- if df.empty:
81
- return df
82
-
83
- # ---------------------------------------------------------------------
84
- # 1. NOVA-Event-ID
85
- # This is simply the function_name.
86
- # ---------------------------------------------------------------------
87
- df['NOVA-Event-ID'] = df['function_name']
88
-
89
- # ---------------------------------------------------------------------
90
- # 2. NOVA-Requests-Remaining-In-Event,
91
- # 3. NOVA-Time-To-Next-Event,
92
- # 4. NOVA-Time-To-Event-End
93
- #
94
- # We'll compute these by grouping on (example_number, function_name),
95
- # sorting by event_timestamp, and for each row calculating:
96
- #
97
- # - how many LLM_START events lie strictly in the future,
98
- # - the time to the next LLM_START event in the future,
99
- # - the time to the last LLM_START event in the future.
100
- #
101
- # For times, we convert to milliseconds by multiplying by 1000,
102
- # assuming event_timestamp is in seconds.
103
- # ---------------------------------------------------------------------
104
-
105
- # Initialize columns with default values.
106
- df['NOVA-Requests-Remaining-In-Event'] = -1
107
- df['NOVA-Time-To-Next-Event'] = -1.0
108
- df['NOVA-Time-To-Event-End'] = -1.0
109
-
110
- def _compute_group_metrics(subdf: pd.DataFrame) -> pd.DataFrame:
111
- """
112
- For a sub-DataFrame with a unique (example_number, function_name),
113
- compute the requested columns for each row.
114
- """
115
- # Sort by time to ensure chronological order.
116
- subdf = subdf.sort_values('event_timestamp').copy()
117
-
118
- # Collect all LLM_START timestamps in this group as a sorted array.
119
- llm_start_mask = (subdf['event_type'] == 'LLM_START')
120
- llm_start_ts = subdf.loc[llm_start_mask, 'event_timestamp'].values
121
-
122
- # If no LLM_START events present, we can return immediately.
123
- if len(llm_start_ts) == 0:
124
- # No future LLM_START events to compute; everything stays default -1.
125
- return subdf
126
-
127
- def _rowwise_calc(row):
128
- """
129
- For each row, compute:
130
- - how many LLM_START events lie strictly in the future,
131
- - time to the next LLM_START event,
132
- - time to the last LLM_START event (in the future).
133
- """
134
- row_ts = row['event_timestamp']
135
-
136
- # Use searchsorted to find how many LLM_START events lie after this row's timestamp.
137
- # side='right' means we treat any LLM_START at exactly row_ts as not 'in the future'.
138
- insertion_idx = np.searchsorted(llm_start_ts, row_ts, side='right')
139
-
140
- # (A) Requests remaining = how many LLM_START events are strictly after row_ts
141
- requests_remaining = len(llm_start_ts) - insertion_idx
142
-
143
- # (B) Time to next LLM_START (if any)
144
- if insertion_idx < len(llm_start_ts):
145
- next_event_time = llm_start_ts[insertion_idx]
146
- time_to_next_event = (next_event_time - row_ts) * 1000.0
147
- else:
148
- time_to_next_event = -1.0
149
-
150
- # (C) Time to the last LLM_START in the future (if any).
151
- # The last LLM_START in the future is simply the last entry of llm_start_ts
152
- # if there's at least one future LLM_START. We'll check that it is strictly > row_ts.
153
- if requests_remaining > 0:
154
- last_future_llm_start = llm_start_ts[-1]
155
- # double-check that it's truly in the future
156
- if last_future_llm_start > row_ts:
157
- time_to_event_end = (last_future_llm_start - row_ts) * 1000.0
158
- else:
159
- time_to_event_end = -1.0
160
- else:
161
- time_to_event_end = -1.0
162
-
163
- return pd.Series({
164
- 'NOVA-Requests-Remaining-In-Event': requests_remaining,
165
- 'NOVA-Time-To-Next-Event': time_to_next_event,
166
- 'NOVA-Time-To-Event-End': time_to_event_end
167
- })
168
-
169
- # Apply row-wise calculations
170
- metrics_df = subdf.apply(_rowwise_calc, axis=1)
171
-
172
- # Merge back into subdf
173
- subdf[['NOVA-Requests-Remaining-In-Event', 'NOVA-Time-To-Next-Event',
174
- 'NOVA-Time-To-Event-End']] = metrics_df
175
-
176
- return subdf
177
-
178
- # Apply the group metrics
179
- df_group = df.groupby(['example_number', 'function_name'], group_keys=False)
180
- df = df_group[df.columns].apply(_compute_group_metrics).sort_index()
181
-
182
- # ---------------------------------------------------------------------
183
- # 5. NOVA-Predicted-OSL
184
- #
185
- # For each LLM_START event, we want the completion_tokens from its
186
- # corresponding LLM_END event. Both share the same UUID.
187
- # We'll do a map from UUID -> completion_tokens for LLM_END rows.
188
- # ---------------------------------------------------------------------
189
- df['NOVA-Predicted-OSL'] = np.nan
190
-
191
- # Build a map of UUID -> completion_tokens from LLM_END
192
- llm_end_map = (df.loc[df['event_type'] == 'LLM_END', ['UUID', 'completion_tokens']].dropna(
193
- subset=['UUID']).set_index('UUID')['completion_tokens'].to_dict())
194
-
195
- # Only assign to rows which are LLM_START
196
- llm_start_mask = (df['event_type'] == 'LLM_START')
197
- df.loc[llm_start_mask, 'NOVA-Predicted-OSL'] = (df.loc[llm_start_mask, 'UUID'].map(llm_end_map))
198
-
199
- # ---------------------------------------------------------------------
200
- # 6. NOVA-Time-To-Session-End
201
- #
202
- # For each example_number, we want the difference (in ms) between
203
- # the row's event_timestamp and the final (max) event_timestamp
204
- # in that example_number.
205
- # ---------------------------------------------------------------------
206
- max_ts_per_example = (df.groupby('example_number')['event_timestamp'].transform('max'))
207
-
208
- # We'll subtract row's timestamp from the max, and convert to ms
209
- df['NOVA-Time-To-Session-End'] = (max_ts_per_example - df['event_timestamp']) * 1000.0
210
-
211
- # Return the updated DataFrame
212
- return df