aiqtoolkit 1.1.0a20250503__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.
- aiq/agent/__init__.py +0 -0
- aiq/agent/base.py +76 -0
- aiq/agent/dual_node.py +67 -0
- aiq/agent/react_agent/__init__.py +0 -0
- aiq/agent/react_agent/agent.py +322 -0
- aiq/agent/react_agent/output_parser.py +104 -0
- aiq/agent/react_agent/prompt.py +46 -0
- aiq/agent/react_agent/register.py +148 -0
- aiq/agent/reasoning_agent/__init__.py +0 -0
- aiq/agent/reasoning_agent/reasoning_agent.py +224 -0
- aiq/agent/register.py +23 -0
- aiq/agent/rewoo_agent/__init__.py +0 -0
- aiq/agent/rewoo_agent/agent.py +410 -0
- aiq/agent/rewoo_agent/prompt.py +108 -0
- aiq/agent/rewoo_agent/register.py +158 -0
- aiq/agent/tool_calling_agent/__init__.py +0 -0
- aiq/agent/tool_calling_agent/agent.py +123 -0
- aiq/agent/tool_calling_agent/register.py +105 -0
- aiq/builder/__init__.py +0 -0
- aiq/builder/builder.py +223 -0
- aiq/builder/component_utils.py +303 -0
- aiq/builder/context.py +212 -0
- aiq/builder/embedder.py +24 -0
- aiq/builder/eval_builder.py +116 -0
- aiq/builder/evaluator.py +29 -0
- aiq/builder/framework_enum.py +24 -0
- aiq/builder/front_end.py +73 -0
- aiq/builder/function.py +297 -0
- aiq/builder/function_base.py +376 -0
- aiq/builder/function_info.py +627 -0
- aiq/builder/intermediate_step_manager.py +127 -0
- aiq/builder/llm.py +25 -0
- aiq/builder/retriever.py +25 -0
- aiq/builder/user_interaction_manager.py +71 -0
- aiq/builder/workflow.py +143 -0
- aiq/builder/workflow_builder.py +749 -0
- aiq/cli/__init__.py +14 -0
- aiq/cli/cli_utils/__init__.py +0 -0
- aiq/cli/cli_utils/config_override.py +233 -0
- aiq/cli/cli_utils/validation.py +37 -0
- aiq/cli/commands/__init__.py +0 -0
- aiq/cli/commands/configure/__init__.py +0 -0
- aiq/cli/commands/configure/channel/__init__.py +0 -0
- aiq/cli/commands/configure/channel/add.py +28 -0
- aiq/cli/commands/configure/channel/channel.py +36 -0
- aiq/cli/commands/configure/channel/remove.py +30 -0
- aiq/cli/commands/configure/channel/update.py +30 -0
- aiq/cli/commands/configure/configure.py +33 -0
- aiq/cli/commands/evaluate.py +139 -0
- aiq/cli/commands/info/__init__.py +14 -0
- aiq/cli/commands/info/info.py +37 -0
- aiq/cli/commands/info/list_channels.py +32 -0
- aiq/cli/commands/info/list_components.py +129 -0
- aiq/cli/commands/registry/__init__.py +14 -0
- aiq/cli/commands/registry/publish.py +88 -0
- aiq/cli/commands/registry/pull.py +118 -0
- aiq/cli/commands/registry/registry.py +38 -0
- aiq/cli/commands/registry/remove.py +108 -0
- aiq/cli/commands/registry/search.py +155 -0
- aiq/cli/commands/start.py +250 -0
- aiq/cli/commands/uninstall.py +83 -0
- aiq/cli/commands/validate.py +47 -0
- aiq/cli/commands/workflow/__init__.py +14 -0
- aiq/cli/commands/workflow/templates/__init__.py.j2 +0 -0
- aiq/cli/commands/workflow/templates/config.yml.j2 +16 -0
- aiq/cli/commands/workflow/templates/pyproject.toml.j2 +22 -0
- aiq/cli/commands/workflow/templates/register.py.j2 +5 -0
- aiq/cli/commands/workflow/templates/workflow.py.j2 +36 -0
- aiq/cli/commands/workflow/workflow.py +37 -0
- aiq/cli/commands/workflow/workflow_commands.py +313 -0
- aiq/cli/entrypoint.py +133 -0
- aiq/cli/main.py +44 -0
- aiq/cli/register_workflow.py +408 -0
- aiq/cli/type_registry.py +879 -0
- aiq/data_models/__init__.py +14 -0
- aiq/data_models/api_server.py +588 -0
- aiq/data_models/common.py +143 -0
- aiq/data_models/component.py +46 -0
- aiq/data_models/component_ref.py +135 -0
- aiq/data_models/config.py +349 -0
- aiq/data_models/dataset_handler.py +122 -0
- aiq/data_models/discovery_metadata.py +269 -0
- aiq/data_models/embedder.py +26 -0
- aiq/data_models/evaluate.py +104 -0
- aiq/data_models/evaluator.py +26 -0
- aiq/data_models/front_end.py +26 -0
- aiq/data_models/function.py +30 -0
- aiq/data_models/function_dependencies.py +64 -0
- aiq/data_models/interactive.py +237 -0
- aiq/data_models/intermediate_step.py +269 -0
- aiq/data_models/invocation_node.py +38 -0
- aiq/data_models/llm.py +26 -0
- aiq/data_models/logging.py +26 -0
- aiq/data_models/memory.py +26 -0
- aiq/data_models/profiler.py +53 -0
- aiq/data_models/registry_handler.py +26 -0
- aiq/data_models/retriever.py +30 -0
- aiq/data_models/step_adaptor.py +64 -0
- aiq/data_models/streaming.py +33 -0
- aiq/data_models/swe_bench_model.py +54 -0
- aiq/data_models/telemetry_exporter.py +26 -0
- aiq/embedder/__init__.py +0 -0
- aiq/embedder/langchain_client.py +41 -0
- aiq/embedder/nim_embedder.py +58 -0
- aiq/embedder/openai_embedder.py +42 -0
- aiq/embedder/register.py +24 -0
- aiq/eval/__init__.py +14 -0
- aiq/eval/config.py +42 -0
- aiq/eval/dataset_handler/__init__.py +0 -0
- aiq/eval/dataset_handler/dataset_downloader.py +106 -0
- aiq/eval/dataset_handler/dataset_filter.py +52 -0
- aiq/eval/dataset_handler/dataset_handler.py +169 -0
- aiq/eval/evaluate.py +323 -0
- aiq/eval/evaluator/__init__.py +14 -0
- aiq/eval/evaluator/evaluator_model.py +44 -0
- aiq/eval/intermediate_step_adapter.py +93 -0
- aiq/eval/rag_evaluator/__init__.py +0 -0
- aiq/eval/rag_evaluator/evaluate.py +138 -0
- aiq/eval/rag_evaluator/register.py +138 -0
- aiq/eval/register.py +23 -0
- aiq/eval/remote_workflow.py +128 -0
- aiq/eval/runtime_event_subscriber.py +52 -0
- aiq/eval/swe_bench_evaluator/__init__.py +0 -0
- aiq/eval/swe_bench_evaluator/evaluate.py +215 -0
- aiq/eval/swe_bench_evaluator/register.py +36 -0
- aiq/eval/trajectory_evaluator/__init__.py +0 -0
- aiq/eval/trajectory_evaluator/evaluate.py +118 -0
- aiq/eval/trajectory_evaluator/register.py +40 -0
- aiq/eval/tunable_rag_evaluator/__init__.py +0 -0
- aiq/eval/tunable_rag_evaluator/evaluate.py +263 -0
- aiq/eval/tunable_rag_evaluator/register.py +50 -0
- aiq/eval/utils/__init__.py +0 -0
- aiq/eval/utils/output_uploader.py +131 -0
- aiq/eval/utils/tqdm_position_registry.py +40 -0
- aiq/front_ends/__init__.py +14 -0
- aiq/front_ends/console/__init__.py +14 -0
- aiq/front_ends/console/console_front_end_config.py +32 -0
- aiq/front_ends/console/console_front_end_plugin.py +107 -0
- aiq/front_ends/console/register.py +25 -0
- aiq/front_ends/cron/__init__.py +14 -0
- aiq/front_ends/fastapi/__init__.py +14 -0
- aiq/front_ends/fastapi/fastapi_front_end_config.py +150 -0
- aiq/front_ends/fastapi/fastapi_front_end_plugin.py +103 -0
- aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py +607 -0
- aiq/front_ends/fastapi/intermediate_steps_subscriber.py +80 -0
- aiq/front_ends/fastapi/job_store.py +161 -0
- aiq/front_ends/fastapi/main.py +70 -0
- aiq/front_ends/fastapi/message_handler.py +279 -0
- aiq/front_ends/fastapi/message_validator.py +345 -0
- aiq/front_ends/fastapi/register.py +25 -0
- aiq/front_ends/fastapi/response_helpers.py +195 -0
- aiq/front_ends/fastapi/step_adaptor.py +315 -0
- aiq/front_ends/fastapi/websocket.py +148 -0
- aiq/front_ends/mcp/__init__.py +14 -0
- aiq/front_ends/mcp/mcp_front_end_config.py +32 -0
- aiq/front_ends/mcp/mcp_front_end_plugin.py +93 -0
- aiq/front_ends/mcp/register.py +27 -0
- aiq/front_ends/mcp/tool_converter.py +242 -0
- aiq/front_ends/register.py +22 -0
- aiq/front_ends/simple_base/__init__.py +14 -0
- aiq/front_ends/simple_base/simple_front_end_plugin_base.py +52 -0
- aiq/llm/__init__.py +0 -0
- aiq/llm/nim_llm.py +45 -0
- aiq/llm/openai_llm.py +45 -0
- aiq/llm/register.py +22 -0
- aiq/llm/utils/__init__.py +14 -0
- aiq/llm/utils/env_config_value.py +94 -0
- aiq/llm/utils/error.py +17 -0
- aiq/memory/__init__.py +20 -0
- aiq/memory/interfaces.py +183 -0
- aiq/memory/models.py +102 -0
- aiq/meta/module_to_distro.json +3 -0
- aiq/meta/pypi.md +59 -0
- aiq/observability/__init__.py +0 -0
- aiq/observability/async_otel_listener.py +433 -0
- aiq/observability/register.py +99 -0
- aiq/plugins/.namespace +1 -0
- aiq/profiler/__init__.py +0 -0
- aiq/profiler/callbacks/__init__.py +0 -0
- aiq/profiler/callbacks/agno_callback_handler.py +295 -0
- aiq/profiler/callbacks/base_callback_class.py +20 -0
- aiq/profiler/callbacks/langchain_callback_handler.py +278 -0
- aiq/profiler/callbacks/llama_index_callback_handler.py +205 -0
- aiq/profiler/callbacks/semantic_kernel_callback_handler.py +238 -0
- aiq/profiler/callbacks/token_usage_base_model.py +27 -0
- aiq/profiler/data_frame_row.py +51 -0
- aiq/profiler/decorators/__init__.py +0 -0
- aiq/profiler/decorators/framework_wrapper.py +131 -0
- aiq/profiler/decorators/function_tracking.py +254 -0
- aiq/profiler/forecasting/__init__.py +0 -0
- aiq/profiler/forecasting/config.py +18 -0
- aiq/profiler/forecasting/model_trainer.py +75 -0
- aiq/profiler/forecasting/models/__init__.py +22 -0
- aiq/profiler/forecasting/models/forecasting_base_model.py +40 -0
- aiq/profiler/forecasting/models/linear_model.py +196 -0
- aiq/profiler/forecasting/models/random_forest_regressor.py +268 -0
- aiq/profiler/inference_metrics_model.py +25 -0
- aiq/profiler/inference_optimization/__init__.py +0 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +452 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +258 -0
- aiq/profiler/inference_optimization/data_models.py +386 -0
- aiq/profiler/inference_optimization/experimental/__init__.py +0 -0
- aiq/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +468 -0
- aiq/profiler/inference_optimization/experimental/prefix_span_analysis.py +405 -0
- aiq/profiler/inference_optimization/llm_metrics.py +212 -0
- aiq/profiler/inference_optimization/prompt_caching.py +163 -0
- aiq/profiler/inference_optimization/token_uniqueness.py +107 -0
- aiq/profiler/inference_optimization/workflow_runtimes.py +72 -0
- aiq/profiler/intermediate_property_adapter.py +102 -0
- aiq/profiler/profile_runner.py +433 -0
- aiq/profiler/utils.py +184 -0
- aiq/registry_handlers/__init__.py +0 -0
- aiq/registry_handlers/local/__init__.py +0 -0
- aiq/registry_handlers/local/local_handler.py +176 -0
- aiq/registry_handlers/local/register_local.py +37 -0
- aiq/registry_handlers/metadata_factory.py +60 -0
- aiq/registry_handlers/package_utils.py +198 -0
- aiq/registry_handlers/pypi/__init__.py +0 -0
- aiq/registry_handlers/pypi/pypi_handler.py +251 -0
- aiq/registry_handlers/pypi/register_pypi.py +40 -0
- aiq/registry_handlers/register.py +21 -0
- aiq/registry_handlers/registry_handler_base.py +157 -0
- aiq/registry_handlers/rest/__init__.py +0 -0
- aiq/registry_handlers/rest/register_rest.py +56 -0
- aiq/registry_handlers/rest/rest_handler.py +237 -0
- aiq/registry_handlers/schemas/__init__.py +0 -0
- aiq/registry_handlers/schemas/headers.py +42 -0
- aiq/registry_handlers/schemas/package.py +68 -0
- aiq/registry_handlers/schemas/publish.py +63 -0
- aiq/registry_handlers/schemas/pull.py +82 -0
- aiq/registry_handlers/schemas/remove.py +36 -0
- aiq/registry_handlers/schemas/search.py +91 -0
- aiq/registry_handlers/schemas/status.py +47 -0
- aiq/retriever/__init__.py +0 -0
- aiq/retriever/interface.py +37 -0
- aiq/retriever/milvus/__init__.py +14 -0
- aiq/retriever/milvus/register.py +81 -0
- aiq/retriever/milvus/retriever.py +228 -0
- aiq/retriever/models.py +74 -0
- aiq/retriever/nemo_retriever/__init__.py +14 -0
- aiq/retriever/nemo_retriever/register.py +60 -0
- aiq/retriever/nemo_retriever/retriever.py +190 -0
- aiq/retriever/register.py +22 -0
- aiq/runtime/__init__.py +14 -0
- aiq/runtime/loader.py +188 -0
- aiq/runtime/runner.py +176 -0
- aiq/runtime/session.py +136 -0
- aiq/runtime/user_metadata.py +131 -0
- aiq/settings/__init__.py +0 -0
- aiq/settings/global_settings.py +318 -0
- aiq/test/.namespace +1 -0
- aiq/tool/__init__.py +0 -0
- aiq/tool/code_execution/__init__.py +0 -0
- aiq/tool/code_execution/code_sandbox.py +188 -0
- aiq/tool/code_execution/local_sandbox/Dockerfile.sandbox +60 -0
- aiq/tool/code_execution/local_sandbox/__init__.py +13 -0
- aiq/tool/code_execution/local_sandbox/local_sandbox_server.py +79 -0
- aiq/tool/code_execution/local_sandbox/sandbox.requirements.txt +4 -0
- aiq/tool/code_execution/local_sandbox/start_local_sandbox.sh +25 -0
- aiq/tool/code_execution/register.py +70 -0
- aiq/tool/code_execution/utils.py +100 -0
- aiq/tool/datetime_tools.py +42 -0
- aiq/tool/document_search.py +141 -0
- aiq/tool/github_tools/__init__.py +0 -0
- aiq/tool/github_tools/create_github_commit.py +133 -0
- aiq/tool/github_tools/create_github_issue.py +87 -0
- aiq/tool/github_tools/create_github_pr.py +106 -0
- aiq/tool/github_tools/get_github_file.py +106 -0
- aiq/tool/github_tools/get_github_issue.py +166 -0
- aiq/tool/github_tools/get_github_pr.py +256 -0
- aiq/tool/github_tools/update_github_issue.py +100 -0
- aiq/tool/mcp/__init__.py +14 -0
- aiq/tool/mcp/mcp_client.py +220 -0
- aiq/tool/mcp/mcp_tool.py +76 -0
- aiq/tool/memory_tools/__init__.py +0 -0
- aiq/tool/memory_tools/add_memory_tool.py +67 -0
- aiq/tool/memory_tools/delete_memory_tool.py +67 -0
- aiq/tool/memory_tools/get_memory_tool.py +72 -0
- aiq/tool/nvidia_rag.py +95 -0
- aiq/tool/register.py +36 -0
- aiq/tool/retriever.py +89 -0
- aiq/utils/__init__.py +0 -0
- aiq/utils/data_models/__init__.py +0 -0
- aiq/utils/data_models/schema_validator.py +58 -0
- aiq/utils/debugging_utils.py +43 -0
- aiq/utils/exception_handlers/__init__.py +0 -0
- aiq/utils/exception_handlers/schemas.py +114 -0
- aiq/utils/io/__init__.py +0 -0
- aiq/utils/io/yaml_tools.py +119 -0
- aiq/utils/metadata_utils.py +74 -0
- aiq/utils/optional_imports.py +142 -0
- aiq/utils/producer_consumer_queue.py +178 -0
- aiq/utils/reactive/__init__.py +0 -0
- aiq/utils/reactive/base/__init__.py +0 -0
- aiq/utils/reactive/base/observable_base.py +65 -0
- aiq/utils/reactive/base/observer_base.py +55 -0
- aiq/utils/reactive/base/subject_base.py +79 -0
- aiq/utils/reactive/observable.py +59 -0
- aiq/utils/reactive/observer.py +76 -0
- aiq/utils/reactive/subject.py +131 -0
- aiq/utils/reactive/subscription.py +49 -0
- aiq/utils/settings/__init__.py +0 -0
- aiq/utils/settings/global_settings.py +197 -0
- aiq/utils/type_converter.py +232 -0
- aiq/utils/type_utils.py +397 -0
- aiq/utils/url_utils.py +27 -0
- aiqtoolkit-1.1.0a20250503.dist-info/METADATA +330 -0
- aiqtoolkit-1.1.0a20250503.dist-info/RECORD +314 -0
- aiqtoolkit-1.1.0a20250503.dist-info/WHEEL +5 -0
- aiqtoolkit-1.1.0a20250503.dist-info/entry_points.txt +17 -0
- aiqtoolkit-1.1.0a20250503.dist-info/licenses/LICENSE-3rd-party.txt +3686 -0
- aiqtoolkit-1.1.0a20250503.dist-info/licenses/LICENSE.md +201 -0
- aiqtoolkit-1.1.0a20250503.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,127 @@
|
|
|
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 contextvars
|
|
17
|
+
import dataclasses
|
|
18
|
+
import logging
|
|
19
|
+
|
|
20
|
+
from aiq.data_models.intermediate_step import IntermediateStep
|
|
21
|
+
from aiq.data_models.intermediate_step import IntermediateStepPayload
|
|
22
|
+
from aiq.data_models.intermediate_step import IntermediateStepState
|
|
23
|
+
from aiq.data_models.invocation_node import InvocationNode
|
|
24
|
+
from aiq.utils.reactive.observable import OnComplete
|
|
25
|
+
from aiq.utils.reactive.observable import OnError
|
|
26
|
+
from aiq.utils.reactive.observable import OnNext
|
|
27
|
+
from aiq.utils.reactive.subscription import Subscription
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
_current_open_step_id = contextvars.ContextVar[str | None]("_current_open_step_id", default=None)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclasses.dataclass
|
|
35
|
+
class OpenStep:
|
|
36
|
+
step_id: str
|
|
37
|
+
step_name: str
|
|
38
|
+
step_type: str
|
|
39
|
+
step_parent_id: str | None
|
|
40
|
+
context: contextvars.Context
|
|
41
|
+
token: contextvars.Token[str | None]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class IntermediateStepManager:
|
|
45
|
+
"""
|
|
46
|
+
Manages updates to the AIQ Toolkit Event Stream for intermediate steps
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(self, context_state: "AIQContextState"): # noqa: F821
|
|
50
|
+
self._context_state = context_state
|
|
51
|
+
|
|
52
|
+
self._outstanding_start_steps: dict[str, OpenStep] = {}
|
|
53
|
+
|
|
54
|
+
def push_intermediate_step(self, payload: IntermediateStepPayload) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Pushes an intermediate step to the AIQ Toolkit Event Stream
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
if not isinstance(payload, IntermediateStepPayload):
|
|
60
|
+
raise TypeError(f"Payload must be of type IntermediateStepPayload, not {type(payload)}")
|
|
61
|
+
|
|
62
|
+
parent_step_id = _current_open_step_id.get()
|
|
63
|
+
|
|
64
|
+
if (payload.event_state == IntermediateStepState.START):
|
|
65
|
+
|
|
66
|
+
token = _current_open_step_id.set(payload.UUID)
|
|
67
|
+
|
|
68
|
+
self._outstanding_start_steps[payload.UUID] = OpenStep(step_id=payload.UUID,
|
|
69
|
+
step_name=payload.name,
|
|
70
|
+
step_type=payload.event_type,
|
|
71
|
+
step_parent_id=parent_step_id,
|
|
72
|
+
context=contextvars.copy_context(),
|
|
73
|
+
token=token)
|
|
74
|
+
|
|
75
|
+
elif (payload.event_state == IntermediateStepState.END):
|
|
76
|
+
|
|
77
|
+
# Remove the current step from the outstanding steps
|
|
78
|
+
open_step = self._outstanding_start_steps.pop(payload.UUID, None)
|
|
79
|
+
|
|
80
|
+
if (open_step is None):
|
|
81
|
+
logger.warning("Step id %s not found in outstanding start steps", payload.UUID)
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
# Restore the parent step ID directly instead of using a cross‑context token.
|
|
85
|
+
if parent_step_id == payload.UUID:
|
|
86
|
+
_current_open_step_id.set(open_step.step_parent_id)
|
|
87
|
+
else:
|
|
88
|
+
# Different context (e.g. thread‑pool); safely restore the parent ID **without**
|
|
89
|
+
# trying to use a token that belongs to another Context.
|
|
90
|
+
_current_open_step_id.set(open_step.step_parent_id)
|
|
91
|
+
parent_step_id = open_step.step_parent_id
|
|
92
|
+
|
|
93
|
+
elif (payload.event_state == IntermediateStepState.CHUNK):
|
|
94
|
+
|
|
95
|
+
# Get the current step from the outstanding steps
|
|
96
|
+
open_step = self._outstanding_start_steps.get(payload.UUID, None)
|
|
97
|
+
|
|
98
|
+
# Generate a warning if the parent step id is not set to the current step id
|
|
99
|
+
if (open_step is None):
|
|
100
|
+
logger.warning(
|
|
101
|
+
"Created a chunk for step %s, but no matching start step was found. "
|
|
102
|
+
"Chunks must be created with the same ID as the start step.",
|
|
103
|
+
payload.UUID)
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
if (parent_step_id != payload.UUID):
|
|
107
|
+
# Manually set the parent step ID. This happens when running on the thread pool
|
|
108
|
+
parent_step_id = open_step.step_parent_id
|
|
109
|
+
|
|
110
|
+
function_ancestry = InvocationNode(function_name=self._context_state.active_function.get().function_name,
|
|
111
|
+
function_id=self._context_state.active_function.get().function_id,
|
|
112
|
+
parent_id=parent_step_id,
|
|
113
|
+
parent_name=self._context_state.active_function.get().parent_name)
|
|
114
|
+
|
|
115
|
+
intermediate_step = IntermediateStep(function_ancestry=function_ancestry, payload=payload)
|
|
116
|
+
|
|
117
|
+
self._context_state.event_stream.get().on_next(intermediate_step)
|
|
118
|
+
|
|
119
|
+
def subscribe(self,
|
|
120
|
+
on_next: OnNext[IntermediateStep],
|
|
121
|
+
on_error: OnError = None,
|
|
122
|
+
on_complete: OnComplete = None) -> Subscription:
|
|
123
|
+
"""
|
|
124
|
+
Subscribes to the AIQ Toolkit Event Stream for intermediate steps
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
return self._context_state.event_stream.get().subscribe(on_next, on_error, on_complete)
|
aiq/builder/llm.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from aiq.data_models.llm import LLMBaseConfig
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class LLMProviderInfo:
|
|
20
|
+
|
|
21
|
+
def __init__(self, *, config: LLMBaseConfig, description: str):
|
|
22
|
+
|
|
23
|
+
self.config = config
|
|
24
|
+
self.provider_type = type(config).static_type()
|
|
25
|
+
self.description = description
|
aiq/builder/retriever.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
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 aiq.data_models.retriever import RetrieverBaseConfig
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RetrieverProviderInfo:
|
|
20
|
+
|
|
21
|
+
def __init__(self, *, config: RetrieverBaseConfig, description: str):
|
|
22
|
+
|
|
23
|
+
self.config = config
|
|
24
|
+
self.provider_type = type(config).static_type()
|
|
25
|
+
self.description = description
|
|
@@ -0,0 +1,71 @@
|
|
|
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 time
|
|
17
|
+
import uuid
|
|
18
|
+
|
|
19
|
+
from aiq.data_models.interactive import HumanPrompt
|
|
20
|
+
from aiq.data_models.interactive import HumanResponse
|
|
21
|
+
from aiq.data_models.interactive import InteractionPrompt
|
|
22
|
+
from aiq.data_models.interactive import InteractionResponse
|
|
23
|
+
from aiq.data_models.interactive import InteractionStatus
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AIQUserInteractionManager:
|
|
27
|
+
"""
|
|
28
|
+
AIQUserInteractionManager is responsible for requesting user input
|
|
29
|
+
at runtime. It delegates the actual prompting to a callback function
|
|
30
|
+
stored in AIQContextState.user_input_callback.
|
|
31
|
+
|
|
32
|
+
Type is not imported in __init__ to prevent partial import.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, context_state: "AIQContextState") -> None: # noqa: F821
|
|
36
|
+
self._context_state = context_state
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
async def default_callback_handler(prompt: InteractionPrompt) -> HumanResponse:
|
|
40
|
+
"""
|
|
41
|
+
Default callback handler for user input. This is a no-op function
|
|
42
|
+
that simply returns the input text from the Interaction Content
|
|
43
|
+
object.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
prompt (InteractionPrompt): The interaction to process.
|
|
47
|
+
"""
|
|
48
|
+
raise NotImplementedError("No human prompt callback was registered. Unable to handle requested prompt.")
|
|
49
|
+
|
|
50
|
+
async def prompt_user_input(self, content: HumanPrompt) -> InteractionResponse:
|
|
51
|
+
"""
|
|
52
|
+
Ask the user a question and wait for input. This calls out to
|
|
53
|
+
the callback from user_input_callback, which is typically
|
|
54
|
+
set by AIQSessionManager.
|
|
55
|
+
|
|
56
|
+
Returns the user's typed-in answer as a string.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
uuid_req = str(uuid.uuid4())
|
|
60
|
+
status = InteractionStatus.IN_PROGRESS
|
|
61
|
+
timestamp = time.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
62
|
+
sys_human_interaction = InteractionPrompt(id=uuid_req, status=status, timestamp=timestamp, content=content)
|
|
63
|
+
|
|
64
|
+
resp = await self._context_state.user_input_callback.get()(sys_human_interaction)
|
|
65
|
+
|
|
66
|
+
# Rebuild a InteractionResponse object with the response
|
|
67
|
+
timestamp = time.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
68
|
+
status = InteractionStatus.COMPLETED
|
|
69
|
+
sys_human_interaction = InteractionResponse(id=uuid_req, status=status, timestamp=timestamp, content=resp)
|
|
70
|
+
|
|
71
|
+
return sys_human_interaction
|
aiq/builder/workflow.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from contextlib import asynccontextmanager
|
|
17
|
+
from contextvars import ContextVar
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from aiq.builder.context import AIQContextState
|
|
21
|
+
from aiq.builder.embedder import EmbedderProviderInfo
|
|
22
|
+
from aiq.builder.function import Function
|
|
23
|
+
from aiq.builder.function_base import FunctionBase
|
|
24
|
+
from aiq.builder.function_base import InputT
|
|
25
|
+
from aiq.builder.function_base import SingleOutputT
|
|
26
|
+
from aiq.builder.function_base import StreamingOutputT
|
|
27
|
+
from aiq.builder.llm import LLMProviderInfo
|
|
28
|
+
from aiq.builder.retriever import RetrieverProviderInfo
|
|
29
|
+
from aiq.data_models.config import AIQConfig
|
|
30
|
+
from aiq.memory.interfaces import MemoryEditor
|
|
31
|
+
from aiq.runtime.runner import AIQRunner
|
|
32
|
+
from aiq.utils.optional_imports import TelemetryOptionalImportError
|
|
33
|
+
from aiq.utils.optional_imports import try_import_opentelemetry
|
|
34
|
+
|
|
35
|
+
# Try to import OpenTelemetry modules
|
|
36
|
+
# If the dependencies are not installed, use a dummy span exporter here
|
|
37
|
+
try:
|
|
38
|
+
opentelemetry = try_import_opentelemetry()
|
|
39
|
+
from opentelemetry.sdk.trace.export import SpanExporter
|
|
40
|
+
except TelemetryOptionalImportError:
|
|
41
|
+
from aiq.utils.optional_imports import DummySpanExporter # pylint: disable=ungrouped-imports
|
|
42
|
+
SpanExporter = DummySpanExporter
|
|
43
|
+
|
|
44
|
+
callback_handler_var: ContextVar[Any | None] = ContextVar("callback_handler_var", default=None)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Workflow(FunctionBase[InputT, StreamingOutputT, SingleOutputT]):
|
|
48
|
+
|
|
49
|
+
def __init__(self,
|
|
50
|
+
*,
|
|
51
|
+
config: AIQConfig,
|
|
52
|
+
entry_fn: Function[InputT, StreamingOutputT, SingleOutputT],
|
|
53
|
+
functions: dict[str, Function] | None = None,
|
|
54
|
+
llms: dict[str, LLMProviderInfo] | None = None,
|
|
55
|
+
embeddings: dict[str, EmbedderProviderInfo] | None = None,
|
|
56
|
+
memory: dict[str, MemoryEditor] | None = None,
|
|
57
|
+
exporters: dict[str, SpanExporter] | None = None,
|
|
58
|
+
retrievers: dict[str | None, RetrieverProviderInfo] | None = None,
|
|
59
|
+
context_state: AIQContextState):
|
|
60
|
+
|
|
61
|
+
super().__init__(input_schema=entry_fn.input_schema,
|
|
62
|
+
streaming_output_schema=entry_fn.streaming_output_schema,
|
|
63
|
+
single_output_schema=entry_fn.single_output_schema)
|
|
64
|
+
|
|
65
|
+
self.config = config
|
|
66
|
+
self.functions = functions or {}
|
|
67
|
+
self.llms = llms or {}
|
|
68
|
+
self.embeddings = embeddings or {}
|
|
69
|
+
self.memory = memory or {}
|
|
70
|
+
self.retrievers = retrievers or {}
|
|
71
|
+
|
|
72
|
+
self._entry_fn = entry_fn
|
|
73
|
+
|
|
74
|
+
self._context_state = context_state
|
|
75
|
+
|
|
76
|
+
self._exporters = exporters or {}
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def has_streaming_output(self) -> bool:
|
|
80
|
+
|
|
81
|
+
return self._entry_fn.has_streaming_output
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def has_single_output(self) -> bool:
|
|
85
|
+
|
|
86
|
+
return self._entry_fn.has_single_output
|
|
87
|
+
|
|
88
|
+
@asynccontextmanager
|
|
89
|
+
async def run(self, message: InputT):
|
|
90
|
+
"""
|
|
91
|
+
Called each time we start a new workflow run. We'll create
|
|
92
|
+
a new top-level workflow span here.
|
|
93
|
+
"""
|
|
94
|
+
async with AIQRunner(input_message=message, entry_fn=self._entry_fn,
|
|
95
|
+
context_state=self._context_state) as runner:
|
|
96
|
+
|
|
97
|
+
# The caller can `yield runner` so they can do `runner.result()` or `runner.result_stream()`
|
|
98
|
+
yield runner
|
|
99
|
+
|
|
100
|
+
async def result_with_steps(self, message: InputT, to_type: type | None = None):
|
|
101
|
+
|
|
102
|
+
async with self.run(message) as runner:
|
|
103
|
+
|
|
104
|
+
from aiq.eval.runtime_event_subscriber import pull_intermediate
|
|
105
|
+
|
|
106
|
+
# Start the intermediate stream
|
|
107
|
+
pull_done, intermediate_steps = pull_intermediate()
|
|
108
|
+
|
|
109
|
+
# Wait on the result
|
|
110
|
+
result = await runner.result(to_type=to_type)
|
|
111
|
+
|
|
112
|
+
await pull_done.wait()
|
|
113
|
+
|
|
114
|
+
return result, intermediate_steps
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def from_entry_fn(*,
|
|
118
|
+
config: AIQConfig,
|
|
119
|
+
entry_fn: Function[InputT, StreamingOutputT, SingleOutputT],
|
|
120
|
+
functions: dict[str, Function] | None = None,
|
|
121
|
+
llms: dict[str, LLMProviderInfo] | None = None,
|
|
122
|
+
embeddings: dict[str, EmbedderProviderInfo] | None = None,
|
|
123
|
+
memory: dict[str, MemoryEditor] | None = None,
|
|
124
|
+
exporters: dict[str, SpanExporter] | None = None,
|
|
125
|
+
retrievers: dict[str | None, RetrieverProviderInfo] | None = None,
|
|
126
|
+
context_state: AIQContextState) -> 'Workflow[InputT, StreamingOutputT, SingleOutputT]':
|
|
127
|
+
|
|
128
|
+
input_type: type = entry_fn.input_type
|
|
129
|
+
streaming_output_type = entry_fn.streaming_output_type
|
|
130
|
+
single_output_type = entry_fn.single_output_type
|
|
131
|
+
|
|
132
|
+
class WorkflowImpl(Workflow[input_type, streaming_output_type, single_output_type]):
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
return WorkflowImpl(config=config,
|
|
136
|
+
entry_fn=entry_fn,
|
|
137
|
+
functions=functions,
|
|
138
|
+
llms=llms,
|
|
139
|
+
embeddings=embeddings,
|
|
140
|
+
memory=memory,
|
|
141
|
+
exporters=exporters,
|
|
142
|
+
retrievers=retrievers,
|
|
143
|
+
context_state=context_state)
|