nvidia-nat-crewai 1.1.0a20251020__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.
- nat/meta/pypi.md +23 -0
- nat/plugins/crewai/__init__.py +0 -0
- nat/plugins/crewai/crewai_callback_handler.py +206 -0
- nat/plugins/crewai/llm.py +148 -0
- nat/plugins/crewai/register.py +22 -0
- nat/plugins/crewai/tool_wrapper.py +40 -0
- nvidia_nat_crewai-1.1.0a20251020.dist-info/METADATA +45 -0
- nvidia_nat_crewai-1.1.0a20251020.dist-info/RECORD +13 -0
- nvidia_nat_crewai-1.1.0a20251020.dist-info/WHEEL +5 -0
- nvidia_nat_crewai-1.1.0a20251020.dist-info/entry_points.txt +2 -0
- nvidia_nat_crewai-1.1.0a20251020.dist-info/licenses/LICENSE-3rd-party.txt +5478 -0
- nvidia_nat_crewai-1.1.0a20251020.dist-info/licenses/LICENSE.md +201 -0
- nvidia_nat_crewai-1.1.0a20251020.dist-info/top_level.txt +1 -0
nat/meta/pypi.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
-->
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
# NVIDIA NeMo Agent Toolkit Subpackage
|
|
21
|
+
This is a subpackage for CrewAI integration in NeMo Agent toolkit.
|
|
22
|
+
|
|
23
|
+
For more information about the NVIDIA NeMo Agent toolkit, please visit the [NeMo Agent toolkit GitHub Repo](https://github.com/NVIDIA/NeMo-Agent-Toolkit).
|
|
File without changes
|
|
@@ -0,0 +1,206 @@
|
|
|
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
|
+
|
|
23
|
+
import litellm
|
|
24
|
+
from crewai.tools import tool_usage
|
|
25
|
+
|
|
26
|
+
from nat.builder.context import Context
|
|
27
|
+
from nat.builder.framework_enum import LLMFrameworkEnum
|
|
28
|
+
from nat.data_models.intermediate_step import IntermediateStepPayload
|
|
29
|
+
from nat.data_models.intermediate_step import IntermediateStepType
|
|
30
|
+
from nat.data_models.intermediate_step import StreamEventData
|
|
31
|
+
from nat.data_models.intermediate_step import TraceMetadata
|
|
32
|
+
from nat.data_models.intermediate_step import UsageInfo
|
|
33
|
+
from nat.profiler.callbacks.base_callback_class import BaseProfilerCallback
|
|
34
|
+
from nat.profiler.callbacks.token_usage_base_model import TokenUsageBaseModel
|
|
35
|
+
|
|
36
|
+
logger = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class CrewAIProfilerHandler(BaseProfilerCallback):
|
|
40
|
+
"""
|
|
41
|
+
A callback manager/handler for CrewAI that intercepts calls to:
|
|
42
|
+
- ToolUsage._use
|
|
43
|
+
- LLM Calls
|
|
44
|
+
|
|
45
|
+
to collect usage statistics (tokens, inputs, outputs, time intervals, etc.)
|
|
46
|
+
and store them in NAT's usage_stats queue for subsequent analysis.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(self) -> None:
|
|
50
|
+
super().__init__()
|
|
51
|
+
self._lock = threading.Lock()
|
|
52
|
+
self.last_call_ts = time.time()
|
|
53
|
+
self.step_manager = Context.get().intermediate_step_manager
|
|
54
|
+
|
|
55
|
+
# Original references to CrewAI methods (for uninstrumenting if needed)
|
|
56
|
+
self._original_tool_use = None
|
|
57
|
+
self._original_llm_call = None
|
|
58
|
+
|
|
59
|
+
def instrument(self) -> None:
|
|
60
|
+
"""
|
|
61
|
+
Monkey-patch the relevant CrewAI methods with usage-stat collection logic.
|
|
62
|
+
Assumes the 'crewai' library is installed.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
# Save the originals
|
|
66
|
+
self._original_tool_use = getattr(tool_usage.ToolUsage, "_use", None)
|
|
67
|
+
self._original_llm_call = getattr(litellm, "completion", None)
|
|
68
|
+
|
|
69
|
+
# Patch if available
|
|
70
|
+
if self._original_tool_use:
|
|
71
|
+
tool_usage.ToolUsage._use = self._tool_use_monkey_patch()
|
|
72
|
+
|
|
73
|
+
if self._original_llm_call:
|
|
74
|
+
litellm.completion = self._llm_call_monkey_patch()
|
|
75
|
+
|
|
76
|
+
logger.debug("CrewAIProfilerHandler instrumentation applied successfully.")
|
|
77
|
+
|
|
78
|
+
def _tool_use_monkey_patch(self) -> Callable[..., Any]:
|
|
79
|
+
"""
|
|
80
|
+
Returns a function that wraps calls to ToolUsage._use(...) with usage-logging.
|
|
81
|
+
"""
|
|
82
|
+
original_func = self._original_tool_use
|
|
83
|
+
|
|
84
|
+
def wrapped_tool_use(tool_usage_instance, *args, **kwargs) -> Any:
|
|
85
|
+
"""
|
|
86
|
+
Replicates _tool_use_wrapper logic without wrapt: collects usage stats,
|
|
87
|
+
calls the original, and captures output stats.
|
|
88
|
+
"""
|
|
89
|
+
now = time.time()
|
|
90
|
+
tool_name = ""
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
tool_info = kwargs.get("tool", "")
|
|
94
|
+
|
|
95
|
+
if tool_info:
|
|
96
|
+
tool_name = tool_info.name
|
|
97
|
+
except Exception as e:
|
|
98
|
+
logger.exception("Error getting tool name: %s", e)
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
# Pre-call usage event
|
|
102
|
+
stats = IntermediateStepPayload(event_type=IntermediateStepType.TOOL_START,
|
|
103
|
+
framework=LLMFrameworkEnum.CREWAI,
|
|
104
|
+
name=tool_name,
|
|
105
|
+
data=StreamEventData(),
|
|
106
|
+
metadata=TraceMetadata(tool_inputs={
|
|
107
|
+
"args": args, "kwargs": dict(kwargs)
|
|
108
|
+
}),
|
|
109
|
+
usage_info=UsageInfo(token_usage=TokenUsageBaseModel()))
|
|
110
|
+
|
|
111
|
+
self.step_manager.push_intermediate_step(stats)
|
|
112
|
+
|
|
113
|
+
self.last_call_ts = now
|
|
114
|
+
|
|
115
|
+
# Call the original _use(...)
|
|
116
|
+
result = original_func(tool_usage_instance, *args, **kwargs)
|
|
117
|
+
now = time.time()
|
|
118
|
+
# Post-call usage stats
|
|
119
|
+
usage_stat = IntermediateStepPayload(
|
|
120
|
+
event_type=IntermediateStepType.TOOL_END,
|
|
121
|
+
span_event_timestamp=now,
|
|
122
|
+
framework=LLMFrameworkEnum.CREWAI,
|
|
123
|
+
name=tool_name,
|
|
124
|
+
data=StreamEventData(input={
|
|
125
|
+
"args": args, "kwargs": dict(kwargs)
|
|
126
|
+
}, output=str(result)),
|
|
127
|
+
metadata=TraceMetadata(tool_outputs={"result": str(result)}),
|
|
128
|
+
usage_info=UsageInfo(token_usage=TokenUsageBaseModel()),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
self.step_manager.push_intermediate_step(usage_stat)
|
|
132
|
+
|
|
133
|
+
return result
|
|
134
|
+
|
|
135
|
+
except Exception as e:
|
|
136
|
+
logger.error("ToolUsage._use error: %s", e)
|
|
137
|
+
raise
|
|
138
|
+
|
|
139
|
+
return wrapped_tool_use
|
|
140
|
+
|
|
141
|
+
def _llm_call_monkey_patch(self) -> Callable[..., Any]:
|
|
142
|
+
"""
|
|
143
|
+
Returns a function that wraps calls to litellm.completion(...) with usage-logging.
|
|
144
|
+
"""
|
|
145
|
+
original_func = self._original_llm_call
|
|
146
|
+
|
|
147
|
+
def wrapped_llm_call(*args, **kwargs) -> Any:
|
|
148
|
+
"""
|
|
149
|
+
Replicates _llm_call_wrapper logic without wrapt: collects usage stats,
|
|
150
|
+
calls the original, and captures output stats.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
now = time.time()
|
|
154
|
+
seconds_between_calls = int(now - self.last_call_ts)
|
|
155
|
+
model_name = kwargs.get('model', "")
|
|
156
|
+
|
|
157
|
+
model_input = ""
|
|
158
|
+
try:
|
|
159
|
+
for message in kwargs.get('messages', []):
|
|
160
|
+
model_input += message.get('content', "")
|
|
161
|
+
except Exception as e:
|
|
162
|
+
logger.exception("Error getting model input: %s", e)
|
|
163
|
+
|
|
164
|
+
# Record the start event
|
|
165
|
+
input_stats = IntermediateStepPayload(
|
|
166
|
+
event_type=IntermediateStepType.LLM_START,
|
|
167
|
+
framework=LLMFrameworkEnum.CREWAI,
|
|
168
|
+
name=model_name,
|
|
169
|
+
data=StreamEventData(input=model_input),
|
|
170
|
+
metadata=TraceMetadata(chat_inputs=copy.deepcopy(kwargs.get('messages', []))),
|
|
171
|
+
usage_info=UsageInfo(token_usage=TokenUsageBaseModel(),
|
|
172
|
+
num_llm_calls=1,
|
|
173
|
+
seconds_between_calls=seconds_between_calls))
|
|
174
|
+
|
|
175
|
+
self.step_manager.push_intermediate_step(input_stats)
|
|
176
|
+
|
|
177
|
+
# Call the original litellm.completion(...)
|
|
178
|
+
output = original_func(*args, **kwargs)
|
|
179
|
+
|
|
180
|
+
model_output = ""
|
|
181
|
+
try:
|
|
182
|
+
for choice in output.choices:
|
|
183
|
+
msg = choice.model_extra["message"]
|
|
184
|
+
model_output += msg.get('content', "")
|
|
185
|
+
except Exception as e:
|
|
186
|
+
logger.exception("Error getting model output: %s", e)
|
|
187
|
+
|
|
188
|
+
now = time.time()
|
|
189
|
+
# Record the end event
|
|
190
|
+
output_stats = IntermediateStepPayload(
|
|
191
|
+
event_type=IntermediateStepType.LLM_END,
|
|
192
|
+
span_event_timestamp=now,
|
|
193
|
+
framework=LLMFrameworkEnum.CREWAI,
|
|
194
|
+
name=model_name,
|
|
195
|
+
data=StreamEventData(input=model_input, output=model_output),
|
|
196
|
+
metadata=TraceMetadata(chat_responses=output.choices[0].model_dump()),
|
|
197
|
+
usage_info=UsageInfo(token_usage=TokenUsageBaseModel(**output.model_extra['usage'].model_dump()),
|
|
198
|
+
num_llm_calls=1,
|
|
199
|
+
seconds_between_calls=seconds_between_calls))
|
|
200
|
+
|
|
201
|
+
self.step_manager.push_intermediate_step(output_stats)
|
|
202
|
+
|
|
203
|
+
# (Note: the original code did NOT update self.last_call_ts here)
|
|
204
|
+
return output
|
|
205
|
+
|
|
206
|
+
return wrapped_llm_call
|
|
@@ -0,0 +1,148 @@
|
|
|
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 os
|
|
17
|
+
from typing import TypeVar
|
|
18
|
+
|
|
19
|
+
from nat.builder.builder import Builder
|
|
20
|
+
from nat.builder.framework_enum import LLMFrameworkEnum
|
|
21
|
+
from nat.cli.register_workflow import register_llm_client
|
|
22
|
+
from nat.data_models.llm import LLMBaseConfig
|
|
23
|
+
from nat.data_models.retry_mixin import RetryMixin
|
|
24
|
+
from nat.data_models.thinking_mixin import ThinkingMixin
|
|
25
|
+
from nat.llm.azure_openai_llm import AzureOpenAIModelConfig
|
|
26
|
+
from nat.llm.litellm_llm import LiteLlmModelConfig
|
|
27
|
+
from nat.llm.nim_llm import NIMModelConfig
|
|
28
|
+
from nat.llm.openai_llm import OpenAIModelConfig
|
|
29
|
+
from nat.llm.utils.thinking import BaseThinkingInjector
|
|
30
|
+
from nat.llm.utils.thinking import FunctionArgumentWrapper
|
|
31
|
+
from nat.llm.utils.thinking import patch_with_thinking
|
|
32
|
+
from nat.utils.exception_handlers.automatic_retries import patch_with_retry
|
|
33
|
+
from nat.utils.type_utils import override
|
|
34
|
+
|
|
35
|
+
ModelType = TypeVar("ModelType")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _patch_llm_based_on_config(client: ModelType, llm_config: LLMBaseConfig) -> ModelType:
|
|
39
|
+
|
|
40
|
+
class CrewAIThinkingInjector(BaseThinkingInjector):
|
|
41
|
+
|
|
42
|
+
@override
|
|
43
|
+
def inject(self, messages: list[dict[str, str]], *args, **kwargs) -> FunctionArgumentWrapper:
|
|
44
|
+
# Attempt to inject the system prompt into the first system message
|
|
45
|
+
for i, message in enumerate(messages):
|
|
46
|
+
if message["role"] == "system":
|
|
47
|
+
if self.system_prompt not in message["content"]:
|
|
48
|
+
messages = list(messages)
|
|
49
|
+
messages[i] = {"role": "system", "content": f"{message['content']}\n{self.system_prompt}"}
|
|
50
|
+
break
|
|
51
|
+
else:
|
|
52
|
+
messages = list(messages)
|
|
53
|
+
messages.insert(0, {"role": "system", "content": self.system_prompt})
|
|
54
|
+
return FunctionArgumentWrapper(messages, *args, **kwargs)
|
|
55
|
+
|
|
56
|
+
if isinstance(llm_config, RetryMixin):
|
|
57
|
+
client = patch_with_retry(client,
|
|
58
|
+
retries=llm_config.num_retries,
|
|
59
|
+
retry_codes=llm_config.retry_on_status_codes,
|
|
60
|
+
retry_on_messages=llm_config.retry_on_errors)
|
|
61
|
+
|
|
62
|
+
if isinstance(llm_config, ThinkingMixin) and llm_config.thinking_system_prompt is not None:
|
|
63
|
+
client = patch_with_thinking(
|
|
64
|
+
client, CrewAIThinkingInjector(
|
|
65
|
+
system_prompt=llm_config.thinking_system_prompt,
|
|
66
|
+
function_names=["call"],
|
|
67
|
+
))
|
|
68
|
+
|
|
69
|
+
return client
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@register_llm_client(config_type=AzureOpenAIModelConfig, wrapper_type=LLMFrameworkEnum.CREWAI)
|
|
73
|
+
async def azure_openai_crewai(llm_config: AzureOpenAIModelConfig, _builder: Builder):
|
|
74
|
+
|
|
75
|
+
from crewai import LLM
|
|
76
|
+
|
|
77
|
+
# https://docs.crewai.com/en/concepts/llms#azure
|
|
78
|
+
|
|
79
|
+
api_key = llm_config.api_key or os.environ.get("AZURE_OPENAI_API_KEY") or os.environ.get("AZURE_API_KEY")
|
|
80
|
+
if api_key is None:
|
|
81
|
+
raise ValueError("Azure API key is not set")
|
|
82
|
+
os.environ["AZURE_API_KEY"] = api_key
|
|
83
|
+
api_base = (llm_config.azure_endpoint or os.environ.get("AZURE_OPENAI_ENDPOINT")
|
|
84
|
+
or os.environ.get("AZURE_API_BASE"))
|
|
85
|
+
if api_base is None:
|
|
86
|
+
raise ValueError("Azure endpoint is not set")
|
|
87
|
+
os.environ["AZURE_API_BASE"] = api_base
|
|
88
|
+
|
|
89
|
+
os.environ["AZURE_API_VERSION"] = llm_config.api_version
|
|
90
|
+
model = llm_config.azure_deployment or os.environ.get("AZURE_MODEL_DEPLOYMENT")
|
|
91
|
+
if model is None:
|
|
92
|
+
raise ValueError("Azure model deployment is not set")
|
|
93
|
+
|
|
94
|
+
client = LLM(
|
|
95
|
+
**llm_config.model_dump(
|
|
96
|
+
exclude={
|
|
97
|
+
"type",
|
|
98
|
+
"api_key",
|
|
99
|
+
"azure_endpoint",
|
|
100
|
+
"azure_deployment",
|
|
101
|
+
"thinking",
|
|
102
|
+
},
|
|
103
|
+
by_alias=True,
|
|
104
|
+
exclude_none=True,
|
|
105
|
+
),
|
|
106
|
+
model=model,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
yield _patch_llm_based_on_config(client, llm_config)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@register_llm_client(config_type=NIMModelConfig, wrapper_type=LLMFrameworkEnum.CREWAI)
|
|
113
|
+
async def nim_crewai(llm_config: NIMModelConfig, _builder: Builder):
|
|
114
|
+
|
|
115
|
+
from crewai import LLM
|
|
116
|
+
|
|
117
|
+
# Because CrewAI uses a different environment variable for the API key, we need to set it here manually
|
|
118
|
+
if llm_config.api_key is None and "NVIDIA_NIM_API_KEY" not in os.environ:
|
|
119
|
+
nvidia_api_key = os.getenv("NVIDIA_API_KEY")
|
|
120
|
+
if nvidia_api_key is not None:
|
|
121
|
+
os.environ["NVIDIA_NIM_API_KEY"] = nvidia_api_key
|
|
122
|
+
|
|
123
|
+
client = LLM(
|
|
124
|
+
**llm_config.model_dump(exclude={"type", "model_name", "thinking"}, by_alias=True, exclude_none=True),
|
|
125
|
+
model=f"nvidia_nim/{llm_config.model_name}",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
yield _patch_llm_based_on_config(client, llm_config)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@register_llm_client(config_type=OpenAIModelConfig, wrapper_type=LLMFrameworkEnum.CREWAI)
|
|
132
|
+
async def openai_crewai(llm_config: OpenAIModelConfig, _builder: Builder):
|
|
133
|
+
|
|
134
|
+
from crewai import LLM
|
|
135
|
+
|
|
136
|
+
client = LLM(**llm_config.model_dump(exclude={"type", "thinking"}, by_alias=True, exclude_none=True))
|
|
137
|
+
|
|
138
|
+
yield _patch_llm_based_on_config(client, llm_config)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@register_llm_client(config_type=LiteLlmModelConfig, wrapper_type=LLMFrameworkEnum.CREWAI)
|
|
142
|
+
async def litellm_crewai(llm_config: LiteLlmModelConfig, _builder: Builder):
|
|
143
|
+
|
|
144
|
+
from crewai import LLM
|
|
145
|
+
|
|
146
|
+
client = LLM(**llm_config.model_dump(exclude={"type", "thinking"}, by_alias=True, exclude_none=True))
|
|
147
|
+
|
|
148
|
+
yield _patch_llm_based_on_config(client, llm_config)
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
# flake8: noqa
|
|
17
|
+
# isort:skip_file
|
|
18
|
+
|
|
19
|
+
# Import any providers which need to be automatically registered here
|
|
20
|
+
|
|
21
|
+
from . import llm
|
|
22
|
+
from . import tool_wrapper
|
|
@@ -0,0 +1,40 @@
|
|
|
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 asyncio
|
|
17
|
+
|
|
18
|
+
from nat.builder.builder import Builder
|
|
19
|
+
from nat.builder.framework_enum import LLMFrameworkEnum
|
|
20
|
+
from nat.builder.function import Function
|
|
21
|
+
from nat.cli.register_workflow import register_tool_wrapper
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@register_tool_wrapper(wrapper_type=LLMFrameworkEnum.CREWAI)
|
|
25
|
+
def crewai_tool_wrapper(name: str, fn: Function, builder: Builder):
|
|
26
|
+
|
|
27
|
+
from crewai.tools.base_tool import Tool
|
|
28
|
+
|
|
29
|
+
# Capture the loop at the time this is called
|
|
30
|
+
loop = asyncio.get_event_loop()
|
|
31
|
+
|
|
32
|
+
# Capture the coroutine at the time this is called
|
|
33
|
+
runnable = fn.acall_invoke
|
|
34
|
+
|
|
35
|
+
# Because CrewAI tools are not async, we need to wrap the coroutine in a normal function
|
|
36
|
+
def wrapper(*args, **kwargs):
|
|
37
|
+
|
|
38
|
+
return asyncio.run_coroutine_threadsafe(runnable(*args, **kwargs), loop).result()
|
|
39
|
+
|
|
40
|
+
return Tool(name=name, description=fn.description or "", args_schema=fn.input_schema, func=wrapper)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nvidia-nat-crewai
|
|
3
|
+
Version: 1.1.0a20251020
|
|
4
|
+
Summary: Subpackage for CrewAI integration in NeMo Agent toolkit
|
|
5
|
+
Author: NVIDIA Corporation
|
|
6
|
+
Maintainer: NVIDIA Corporation
|
|
7
|
+
License: Apache-2.0
|
|
8
|
+
Project-URL: documentation, https://docs.nvidia.com/nemo/agent-toolkit/latest/
|
|
9
|
+
Project-URL: source, https://github.com/NVIDIA/NeMo-Agent-Toolkit
|
|
10
|
+
Keywords: ai,rag,agents
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Requires-Python: <3.14,>=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE-3rd-party.txt
|
|
18
|
+
License-File: LICENSE.md
|
|
19
|
+
Requires-Dist: nvidia-nat[litellm]==v1.1.0a20251020
|
|
20
|
+
Requires-Dist: crewai~=0.193.2
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
<!--
|
|
24
|
+
SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
25
|
+
SPDX-License-Identifier: Apache-2.0
|
|
26
|
+
|
|
27
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
28
|
+
you may not use this file except in compliance with the License.
|
|
29
|
+
You may obtain a copy of the License at
|
|
30
|
+
|
|
31
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
32
|
+
|
|
33
|
+
Unless required by applicable law or agreed to in writing, software
|
|
34
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
35
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
36
|
+
See the License for the specific language governing permissions and
|
|
37
|
+
limitations under the License.
|
|
38
|
+
-->
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
# NVIDIA NeMo Agent Toolkit Subpackage
|
|
43
|
+
This is a subpackage for CrewAI integration in NeMo Agent toolkit.
|
|
44
|
+
|
|
45
|
+
For more information about the NVIDIA NeMo Agent toolkit, please visit the [NeMo Agent toolkit GitHub Repo](https://github.com/NVIDIA/NeMo-Agent-Toolkit).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
nat/meta/pypi.md,sha256=T68FnThRzDGFf1LR8u-okM-r11-skSnKqSyI6HOktQY,1107
|
|
2
|
+
nat/plugins/crewai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
nat/plugins/crewai/crewai_callback_handler.py,sha256=m5u0RqUd94F0iIuUvknhVHn1SxYltg3lxAhN_3AogPQ,8334
|
|
4
|
+
nat/plugins/crewai/llm.py,sha256=sfQsdSK6WGWHscald4tG4dyXEcn6zqdhkFjE-1zAtJE,5984
|
|
5
|
+
nat/plugins/crewai/register.py,sha256=_R3bhGmz___696_NwyIcpw3koMBiWqIFoWEFJ0VAgXs,831
|
|
6
|
+
nat/plugins/crewai/tool_wrapper.py,sha256=BNKEPQQCLKtXNzGDAKBLCdmGJXe9lBOVI1hObha8hoI,1569
|
|
7
|
+
nvidia_nat_crewai-1.1.0a20251020.dist-info/licenses/LICENSE-3rd-party.txt,sha256=fOk5jMmCX9YoKWyYzTtfgl-SUy477audFC5hNY4oP7Q,284609
|
|
8
|
+
nvidia_nat_crewai-1.1.0a20251020.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
9
|
+
nvidia_nat_crewai-1.1.0a20251020.dist-info/METADATA,sha256=dQCSEp77WYWT7tjyziMppNpyvU59LnjLDFojc4zAaD4,1922
|
|
10
|
+
nvidia_nat_crewai-1.1.0a20251020.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
+
nvidia_nat_crewai-1.1.0a20251020.dist-info/entry_points.txt,sha256=YF5PUdQGr_OUDXB4TykElHJTsKT8yKkuE0bMX5n_RXs,58
|
|
12
|
+
nvidia_nat_crewai-1.1.0a20251020.dist-info/top_level.txt,sha256=8-CJ2cP6-f0ZReXe5Hzqp-5pvzzHz-5Ds5H2bGqh1-U,4
|
|
13
|
+
nvidia_nat_crewai-1.1.0a20251020.dist-info/RECORD,,
|