datarobot-genai 0.1.70__tar.gz → 0.1.72__tar.gz

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.
Files changed (101) hide show
  1. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/PKG-INFO +3 -3
  2. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/pyproject.toml +3 -3
  3. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dr_mcp_server_logo.py +1 -1
  4. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/langgraph/agent.py +32 -15
  5. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/nat/datarobot_llm_clients.py +66 -7
  6. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/nat/datarobot_llm_providers.py +32 -0
  7. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/.gitignore +0 -0
  8. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/AUTHORS +0 -0
  9. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/LICENSE +0 -0
  10. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/README.md +0 -0
  11. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/__init__.py +0 -0
  12. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/__init__.py +0 -0
  13. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/agents/__init__.py +0 -0
  14. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/agents/base.py +0 -0
  15. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/chat/__init__.py +0 -0
  16. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/chat/auth.py +0 -0
  17. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/chat/client.py +0 -0
  18. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/chat/responses.py +0 -0
  19. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/cli/__init__.py +0 -0
  20. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/cli/agent_environment.py +0 -0
  21. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/cli/agent_kernel.py +0 -0
  22. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/custom_model.py +0 -0
  23. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/mcp/__init__.py +0 -0
  24. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/mcp/common.py +0 -0
  25. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/telemetry_agent.py +0 -0
  26. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/utils/__init__.py +0 -0
  27. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/utils/auth.py +0 -0
  28. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/core/utils/urls.py +0 -0
  29. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/crewai/__init__.py +0 -0
  30. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/crewai/agent.py +0 -0
  31. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/crewai/base.py +0 -0
  32. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/crewai/events.py +0 -0
  33. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/crewai/mcp.py +0 -0
  34. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/__init__.py +0 -0
  35. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/__init__.py +0 -0
  36. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/auth.py +0 -0
  37. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/clients.py +0 -0
  38. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/config.py +0 -0
  39. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/config_utils.py +0 -0
  40. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/constants.py +0 -0
  41. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/credentials.py +0 -0
  42. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dr_mcp_server.py +0 -0
  43. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_prompts/__init__.py +0 -0
  44. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_prompts/controllers.py +0 -0
  45. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_prompts/dr_lib.py +0 -0
  46. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_prompts/register.py +0 -0
  47. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_prompts/utils.py +0 -0
  48. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/__init__.py +0 -0
  49. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/__init__.py +0 -0
  50. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/__init__.py +0 -0
  51. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/base.py +0 -0
  52. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/default.py +0 -0
  53. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/drum.py +0 -0
  54. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/config.py +0 -0
  55. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/controllers.py +0 -0
  56. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/metadata.py +0 -0
  57. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/register.py +0 -0
  58. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/schemas/drum_agentic_fallback_schema.json +0 -0
  59. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/schemas/drum_prediction_fallback_schema.json +0 -0
  60. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/register.py +0 -0
  61. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/dynamic_tools/schema.py +0 -0
  62. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/exceptions.py +0 -0
  63. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/logging.py +0 -0
  64. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/mcp_instance.py +0 -0
  65. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/mcp_server_tools.py +0 -0
  66. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/memory_management/__init__.py +0 -0
  67. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/memory_management/manager.py +0 -0
  68. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/memory_management/memory_tools.py +0 -0
  69. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/routes.py +0 -0
  70. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/routes_utils.py +0 -0
  71. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/server_life_cycle.py +0 -0
  72. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/telemetry.py +0 -0
  73. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/tool_filter.py +0 -0
  74. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/core/utils.py +0 -0
  75. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/server.py +0 -0
  76. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/test_utils/__init__.py +0 -0
  77. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/test_utils/integration_mcp_server.py +0 -0
  78. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/test_utils/mcp_utils_ete.py +0 -0
  79. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/test_utils/mcp_utils_integration.py +0 -0
  80. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/test_utils/openai_llm_mcp_client.py +0 -0
  81. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/test_utils/tool_base_ete.py +0 -0
  82. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/test_utils/utils.py +0 -0
  83. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/__init__.py +0 -0
  84. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/__init__.py +0 -0
  85. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/data.py +0 -0
  86. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/deployment.py +0 -0
  87. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/deployment_info.py +0 -0
  88. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/model.py +0 -0
  89. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/predict.py +0 -0
  90. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/predict_realtime.py +0 -0
  91. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/project.py +0 -0
  92. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/drmcp/tools/predictive/training.py +0 -0
  93. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/langgraph/__init__.py +0 -0
  94. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/langgraph/mcp.py +0 -0
  95. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/llama_index/__init__.py +0 -0
  96. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/llama_index/agent.py +0 -0
  97. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/llama_index/base.py +0 -0
  98. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/llama_index/mcp.py +0 -0
  99. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/nat/__init__.py +0 -0
  100. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/nat/agent.py +0 -0
  101. {datarobot_genai-0.1.70 → datarobot_genai-0.1.72}/src/datarobot_genai/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datarobot-genai
3
- Version: 0.1.70
3
+ Version: 0.1.72
4
4
  Summary: Generic helpers for GenAI
5
5
  Project-URL: Homepage, https://github.com/datarobot-oss/datarobot-genai
6
6
  Author: DataRobot, Inc.
@@ -23,7 +23,7 @@ Requires-Dist: ragas<0.4.0,>=0.3.8
23
23
  Requires-Dist: requests<3.0.0,>=2.32.4
24
24
  Provides-Extra: crewai
25
25
  Requires-Dist: crewai-tools[mcp]<0.77.0,>=0.69.0; extra == 'crewai'
26
- Requires-Dist: crewai<1.0.0,>=0.193.2; extra == 'crewai'
26
+ Requires-Dist: crewai>=1.1.0; extra == 'crewai'
27
27
  Requires-Dist: opentelemetry-instrumentation-crewai<1.0.0,>=0.40.5; extra == 'crewai'
28
28
  Requires-Dist: pybase64<2.0.0,>=1.4.2; extra == 'crewai'
29
29
  Provides-Extra: drmcp
@@ -56,8 +56,8 @@ Requires-Dist: llama-index<0.14.0,>=0.13.6; extra == 'llamaindex'
56
56
  Requires-Dist: opentelemetry-instrumentation-llamaindex<1.0.0,>=0.40.5; extra == 'llamaindex'
57
57
  Requires-Dist: pypdf<7.0.0,>=6.0.0; extra == 'llamaindex'
58
58
  Provides-Extra: nat
59
+ Requires-Dist: crewai>=1.1.0; (python_version >= '3.11') and extra == 'nat'
59
60
  Requires-Dist: llama-index-llms-litellm<0.7.0,>=0.4.1; extra == 'nat'
60
- Requires-Dist: nvidia-nat-crewai==1.3.0; (python_version >= '3.11') and extra == 'nat'
61
61
  Requires-Dist: nvidia-nat-langchain==1.3.0; (python_version >= '3.11') and extra == 'nat'
62
62
  Requires-Dist: nvidia-nat-opentelemetry==1.3.0; (python_version >= '3.11') and extra == 'nat'
63
63
  Requires-Dist: nvidia-nat==1.3.0; (python_version >= '3.11') and extra == 'nat'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "datarobot-genai"
7
- version = "0.1.70"
7
+ version = "0.1.72"
8
8
  description = "Generic helpers for GenAI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10, <3.13"
@@ -35,7 +35,7 @@ datarobot_llm_clients = "datarobot_genai.nat.datarobot_llm_clients"
35
35
 
36
36
  [project.optional-dependencies]
37
37
  crewai = [
38
- "crewai>=0.193.2,<1.0.0",
38
+ "crewai>=1.1.0",
39
39
  "crewai-tools[mcp]>=0.69.0,<0.77.0",
40
40
  "opentelemetry-instrumentation-crewai>=0.40.5,<1.0.0",
41
41
  "pybase64>=1.4.2,<2.0.0",
@@ -59,8 +59,8 @@ llamaindex = [
59
59
  nat = [
60
60
  "nvidia-nat==1.3.0; python_version >= '3.11'",
61
61
  "nvidia-nat-opentelemetry==1.3.0; python_version >= '3.11'",
62
- "nvidia-nat-crewai==1.3.0; python_version >= '3.11'",
63
62
  "nvidia-nat-langchain==1.3.0; python_version >= '3.11'",
63
+ "crewai>=1.1.0; python_version >= '3.11'",
64
64
  "llama-index-llms-litellm>=0.4.1,<0.7.0", # Need this to support datarobot-llm plugin
65
65
  "opentelemetry-instrumentation-crewai>=0.40.5,<1.0.0",
66
66
  "opentelemetry-instrumentation-llamaindex>=0.40.5,<1.0.0",
@@ -38,7 +38,7 @@ def _apply_green(text: str) -> str:
38
38
  return "\n".join(colored_lines)
39
39
 
40
40
 
41
- DR_LOGO_ASCII = _apply_green("""\
41
+ DR_LOGO_ASCII = _apply_green(r"""
42
42
  ____ _ ____ _ _
43
43
  | _ \ __ _| |_ __ _| _ \ ___ | |__ ___ | |_
44
44
  | | | |/ _` | __/ _` | |_) / _ \| '_ \ / _ \| __|
@@ -84,21 +84,38 @@ class LangGraphAgent(BaseAgent[BaseTool], abc.ABC):
84
84
  async def wrapped_generator() -> AsyncGenerator[
85
85
  tuple[str, Any | None, UsageMetrics], None
86
86
  ]:
87
- async with mcp_tools_context(
88
- authorization_context=self._authorization_context,
89
- forwarded_headers=self.forwarded_headers,
90
- ) as mcp_tools:
91
- self.set_mcp_tools(mcp_tools)
92
- result = await self._invoke(completion_create_params)
93
-
94
- # Yield all items from the result generator
95
- # The context will be closed when this generator is exhausted
96
- # Cast to async generator since we know stream=True means it's a generator
97
- result_generator = cast(
98
- AsyncGenerator[tuple[str, Any | None, UsageMetrics], None], result
99
- )
100
- async for item in result_generator:
101
- yield item
87
+ try:
88
+ async with mcp_tools_context(
89
+ authorization_context=self._authorization_context,
90
+ forwarded_headers=self.forwarded_headers,
91
+ ) as mcp_tools:
92
+ self.set_mcp_tools(mcp_tools)
93
+ result = await self._invoke(completion_create_params)
94
+
95
+ # Yield all items from the result generator
96
+ # The context will be closed when this generator is exhausted
97
+ # Cast to async generator since we know stream=True means it's a generator
98
+ result_generator = cast(
99
+ AsyncGenerator[tuple[str, Any | None, UsageMetrics], None], result
100
+ )
101
+ async for item in result_generator:
102
+ yield item
103
+ except RuntimeError as e:
104
+ error_message = str(e).lower()
105
+ if "different task" in error_message and "cancel scope" in error_message:
106
+ # Due to anyio task group constraints when consuming async generators
107
+ # across task boundaries, we cannot always clean up properly.
108
+ # The underlying HTTP client/connection pool should handle resource cleanup
109
+ # via timeouts and connection pooling, but this
110
+ # may lead to delayed resource release.
111
+ logger.debug(
112
+ "MCP context cleanup attempted in different task. "
113
+ "This is a limitation when consuming async generators "
114
+ "across task boundaries."
115
+ )
116
+ else:
117
+ # Re-raise if it's a different RuntimeError
118
+ raise
102
119
 
103
120
  return wrapped_generator()
104
121
  else:
@@ -23,6 +23,7 @@ from nat.builder.builder import Builder
23
23
  from nat.builder.framework_enum import LLMFrameworkEnum
24
24
  from nat.cli.register_workflow import register_llm_client
25
25
 
26
+ from ..nat.datarobot_llm_providers import DataRobotLLMComponentModelConfig
26
27
  from ..nat.datarobot_llm_providers import DataRobotLLMDeploymentModelConfig
27
28
  from ..nat.datarobot_llm_providers import DataRobotLLMGatewayModelConfig
28
29
  from ..nat.datarobot_llm_providers import DataRobotNIMModelConfig
@@ -75,6 +76,7 @@ async def datarobot_llm_gateway_langchain(
75
76
  config = llm_config.model_dump(exclude={"type", "thinking"}, by_alias=True, exclude_none=True)
76
77
  config["base_url"] = config["base_url"] + "/genai/llmgw"
77
78
  config["stream_options"] = {"include_usage": True}
79
+ config["model"] = config["model"].removeprefix("datarobot/")
78
80
  yield DataRobotChatOpenAI(**config)
79
81
 
80
82
 
@@ -85,7 +87,8 @@ async def datarobot_llm_gateway_crewai(
85
87
  llm_config: DataRobotLLMGatewayModelConfig, builder: Builder
86
88
  ) -> AsyncGenerator[LLM]:
87
89
  config = llm_config.model_dump(exclude={"type", "thinking"}, by_alias=True, exclude_none=True)
88
- config["model"] = "datarobot/" + config["model"]
90
+ if not config["model"].startswith("datarobot/"):
91
+ config["model"] = "datarobot/" + config["model"]
89
92
  config["base_url"] = config["base_url"].removesuffix("/api/v2")
90
93
  yield LLM(**config)
91
94
 
@@ -97,7 +100,8 @@ async def datarobot_llm_gateway_llamaindex(
97
100
  llm_config: DataRobotLLMGatewayModelConfig, builder: Builder
98
101
  ) -> AsyncGenerator[LLM]:
99
102
  config = llm_config.model_dump(exclude={"type", "thinking"}, by_alias=True, exclude_none=True)
100
- config["model"] = "datarobot/" + config["model"]
103
+ if not config["model"].startswith("datarobot/"):
104
+ config["model"] = "datarobot/" + config["model"]
101
105
  config["api_base"] = config.pop("base_url").removesuffix("/api/v2")
102
106
  yield DataRobotLiteLLM(**config)
103
107
 
@@ -109,11 +113,12 @@ async def datarobot_llm_deployment_langchain(
109
113
  llm_config: DataRobotLLMDeploymentModelConfig, builder: Builder
110
114
  ) -> AsyncGenerator[ChatOpenAI]:
111
115
  config = llm_config.model_dump(
112
- exclude={"type", "thinking", "datarobot_endpoint", "llm_deployment_id"},
116
+ exclude={"type", "thinking"},
113
117
  by_alias=True,
114
118
  exclude_none=True,
115
119
  )
116
120
  config["stream_options"] = {"include_usage": True}
121
+ config["model"] = config["model"].removeprefix("datarobot/")
117
122
  yield DataRobotChatOpenAI(**config)
118
123
 
119
124
 
@@ -128,7 +133,8 @@ async def datarobot_llm_deployment_crewai(
128
133
  by_alias=True,
129
134
  exclude_none=True,
130
135
  )
131
- config["model"] = "datarobot/" + config["model"]
136
+ if not config["model"].startswith("datarobot/"):
137
+ config["model"] = "datarobot/" + config["model"]
132
138
  config["api_base"] = config.pop("base_url") + "/chat/completions"
133
139
  yield LLM(**config)
134
140
 
@@ -144,7 +150,8 @@ async def datarobot_llm_deployment_llamaindex(
144
150
  by_alias=True,
145
151
  exclude_none=True,
146
152
  )
147
- config["model"] = "datarobot/" + config["model"]
153
+ if not config["model"].startswith("datarobot/"):
154
+ config["model"] = "datarobot/" + config["model"]
148
155
  config["api_base"] = config.pop("base_url") + "/chat/completions"
149
156
  yield DataRobotLiteLLM(**config)
150
157
 
@@ -159,6 +166,7 @@ async def datarobot_nim_langchain(
159
166
  exclude_none=True,
160
167
  )
161
168
  config["stream_options"] = {"include_usage": True}
169
+ config["model"] = config["model"].removeprefix("datarobot/")
162
170
  yield DataRobotChatOpenAI(**config)
163
171
 
164
172
 
@@ -171,7 +179,8 @@ async def datarobot_nim_crewai(
171
179
  by_alias=True,
172
180
  exclude_none=True,
173
181
  )
174
- config["model"] = "datarobot/" + config["model"]
182
+ if not config["model"].startswith("datarobot/"):
183
+ config["model"] = "datarobot/" + config["model"]
175
184
  config["api_base"] = config.pop("base_url") + "/chat/completions"
176
185
  yield LLM(**config)
177
186
 
@@ -185,6 +194,56 @@ async def datarobot_nim_llamaindex(
185
194
  by_alias=True,
186
195
  exclude_none=True,
187
196
  )
188
- config["model"] = "datarobot/" + config["model"]
197
+ if not config["model"].startswith("datarobot/"):
198
+ config["model"] = "datarobot/" + config["model"]
189
199
  config["api_base"] = config.pop("base_url") + "/chat/completions"
190
200
  yield DataRobotLiteLLM(**config)
201
+
202
+
203
+ @register_llm_client(
204
+ config_type=DataRobotLLMComponentModelConfig, wrapper_type=LLMFrameworkEnum.LANGCHAIN
205
+ )
206
+ async def datarobot_llm_component_langchain(
207
+ llm_config: DataRobotLLMComponentModelConfig, builder: Builder
208
+ ) -> AsyncGenerator[ChatOpenAI]:
209
+ config = llm_config.model_dump(exclude={"type", "thinking"}, by_alias=True, exclude_none=True)
210
+ if config["use_datarobot_llm_gateway"]:
211
+ config["base_url"] = config["base_url"] + "/genai/llmgw"
212
+ config["stream_options"] = {"include_usage": True}
213
+ config["model"] = config["model"].removeprefix("datarobot/")
214
+ config.pop("use_datarobot_llm_gateway")
215
+ yield DataRobotChatOpenAI(**config)
216
+
217
+
218
+ @register_llm_client(
219
+ config_type=DataRobotLLMComponentModelConfig, wrapper_type=LLMFrameworkEnum.CREWAI
220
+ )
221
+ async def datarobot_llm_component_crewai(
222
+ llm_config: DataRobotLLMComponentModelConfig, builder: Builder
223
+ ) -> AsyncGenerator[LLM]:
224
+ config = llm_config.model_dump(exclude={"type", "thinking"}, by_alias=True, exclude_none=True)
225
+ if not config["model"].startswith("datarobot/"):
226
+ config["model"] = "datarobot/" + config["model"]
227
+ if config["use_datarobot_llm_gateway"]:
228
+ config["base_url"] = config["base_url"].removesuffix("/api/v2")
229
+ else:
230
+ config["api_base"] = config.pop("base_url") + "/chat/completions"
231
+ config.pop("use_datarobot_llm_gateway")
232
+ yield LLM(**config)
233
+
234
+
235
+ @register_llm_client(
236
+ config_type=DataRobotLLMComponentModelConfig, wrapper_type=LLMFrameworkEnum.LLAMA_INDEX
237
+ )
238
+ async def datarobot_llm_component_llamaindex(
239
+ llm_config: DataRobotLLMComponentModelConfig, builder: Builder
240
+ ) -> AsyncGenerator[LLM]:
241
+ config = llm_config.model_dump(exclude={"type", "thinking"}, by_alias=True, exclude_none=True)
242
+ if not config["model"].startswith("datarobot/"):
243
+ config["model"] = "datarobot/" + config["model"]
244
+ if config["use_datarobot_llm_gateway"]:
245
+ config["api_base"] = config.pop("base_url").removesuffix("/api/v2")
246
+ else:
247
+ config["api_base"] = config.pop("base_url") + "/chat/completions"
248
+ config.pop("use_datarobot_llm_gateway")
249
+ yield DataRobotLiteLLM(**config)
@@ -32,11 +32,43 @@ class Config(DataRobotAppFrameworkBaseSettings):
32
32
  datarobot_api_token: str | None = None
33
33
  llm_deployment_id: str | None = None
34
34
  nim_deployment_id: str | None = None
35
+ use_datarobot_llm_gateway: bool = False
36
+ llm_default_model: str | None = None
35
37
 
36
38
 
37
39
  config = Config()
38
40
 
39
41
 
42
+ class DataRobotLLMComponentModelConfig(OpenAIModelConfig, name="datarobot-llm-component"): # type: ignore[call-arg]
43
+ """A DataRobot LLM provider to be used with an LLM client."""
44
+
45
+ api_key: str | None = Field(
46
+ default=config.datarobot_api_token, description="DataRobot API key."
47
+ )
48
+ base_url: str | None = Field(
49
+ default=config.datarobot_endpoint.rstrip("/")
50
+ if config.use_datarobot_llm_gateway
51
+ else config.datarobot_endpoint + f"/deployments/{config.llm_deployment_id}",
52
+ description="DataRobot LLM URL.",
53
+ )
54
+ model_name: str = Field(
55
+ validation_alias=AliasChoices("model_name", "model"),
56
+ serialization_alias="model",
57
+ description="The model name.",
58
+ default=config.llm_default_model or "datarobot-deployed-llm",
59
+ )
60
+ use_datarobot_llm_gateway: bool = config.use_datarobot_llm_gateway
61
+
62
+
63
+ @register_llm_provider(config_type=DataRobotLLMComponentModelConfig)
64
+ async def datarobot_llm_component(
65
+ config: DataRobotLLMComponentModelConfig, _builder: Builder
66
+ ) -> LLMProviderInfo:
67
+ yield LLMProviderInfo(
68
+ config=config, description="DataRobot LLM Component for use with an LLM client."
69
+ )
70
+
71
+
40
72
  class DataRobotLLMGatewayModelConfig(OpenAIModelConfig, name="datarobot-llm-gateway"): # type: ignore[call-arg]
41
73
  """A DataRobot LLM provider to be used with an LLM client."""
42
74