lfx-nightly 0.2.0.dev26__py3-none-any.whl → 0.2.1.dev7__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.
- lfx/_assets/component_index.json +1 -1
- lfx/base/agents/agent.py +9 -4
- lfx/base/agents/altk_base_agent.py +16 -3
- lfx/base/agents/altk_tool_wrappers.py +1 -1
- lfx/base/agents/utils.py +4 -0
- lfx/base/composio/composio_base.py +78 -41
- lfx/base/data/base_file.py +14 -4
- lfx/base/data/cloud_storage_utils.py +156 -0
- lfx/base/data/docling_utils.py +191 -65
- lfx/base/data/storage_utils.py +109 -0
- lfx/base/datastax/astradb_base.py +75 -64
- lfx/base/mcp/util.py +2 -2
- lfx/base/models/__init__.py +11 -1
- lfx/base/models/anthropic_constants.py +21 -12
- lfx/base/models/google_generative_ai_constants.py +33 -9
- lfx/base/models/model_metadata.py +6 -0
- lfx/base/models/ollama_constants.py +196 -30
- lfx/base/models/openai_constants.py +37 -10
- lfx/base/models/unified_models.py +1123 -0
- lfx/base/models/watsonx_constants.py +36 -0
- lfx/base/tools/component_tool.py +2 -9
- lfx/cli/commands.py +6 -1
- lfx/cli/run.py +65 -409
- lfx/cli/script_loader.py +13 -3
- lfx/components/__init__.py +0 -3
- lfx/components/composio/github_composio.py +1 -1
- lfx/components/cuga/cuga_agent.py +39 -27
- lfx/components/data_source/api_request.py +4 -2
- lfx/components/docling/__init__.py +45 -11
- lfx/components/docling/chunk_docling_document.py +3 -1
- lfx/components/docling/docling_inline.py +39 -49
- lfx/components/docling/export_docling_document.py +3 -1
- lfx/components/elastic/opensearch_multimodal.py +215 -57
- lfx/components/files_and_knowledge/file.py +439 -39
- lfx/components/files_and_knowledge/ingestion.py +8 -0
- lfx/components/files_and_knowledge/retrieval.py +10 -0
- lfx/components/files_and_knowledge/save_file.py +123 -53
- lfx/components/ibm/watsonx.py +7 -1
- lfx/components/input_output/chat_output.py +7 -1
- lfx/components/langchain_utilities/tool_calling.py +14 -6
- lfx/components/llm_operations/batch_run.py +80 -25
- lfx/components/llm_operations/lambda_filter.py +33 -6
- lfx/components/llm_operations/llm_conditional_router.py +39 -7
- lfx/components/llm_operations/structured_output.py +38 -12
- lfx/components/models/__init__.py +16 -74
- lfx/components/models_and_agents/agent.py +51 -201
- lfx/components/models_and_agents/embedding_model.py +185 -339
- lfx/components/models_and_agents/language_model.py +54 -318
- lfx/components/models_and_agents/mcp_component.py +58 -9
- lfx/components/ollama/ollama.py +9 -4
- lfx/components/ollama/ollama_embeddings.py +2 -1
- lfx/components/openai/openai_chat_model.py +1 -1
- lfx/components/processing/__init__.py +0 -3
- lfx/components/vllm/__init__.py +37 -0
- lfx/components/vllm/vllm.py +141 -0
- lfx/components/vllm/vllm_embeddings.py +110 -0
- lfx/custom/custom_component/custom_component.py +8 -6
- lfx/custom/directory_reader/directory_reader.py +5 -2
- lfx/graph/utils.py +64 -18
- lfx/inputs/__init__.py +2 -0
- lfx/inputs/input_mixin.py +54 -0
- lfx/inputs/inputs.py +115 -0
- lfx/interface/initialize/loading.py +42 -12
- lfx/io/__init__.py +2 -0
- lfx/run/__init__.py +5 -0
- lfx/run/base.py +494 -0
- lfx/schema/data.py +1 -1
- lfx/schema/image.py +28 -19
- lfx/schema/message.py +19 -3
- lfx/services/interfaces.py +5 -0
- lfx/services/manager.py +5 -4
- lfx/services/mcp_composer/service.py +45 -13
- lfx/services/settings/auth.py +18 -11
- lfx/services/settings/base.py +12 -24
- lfx/services/settings/constants.py +2 -0
- lfx/services/storage/local.py +37 -0
- lfx/services/storage/service.py +19 -0
- lfx/utils/constants.py +1 -0
- lfx/utils/image.py +29 -11
- lfx/utils/validate_cloud.py +14 -3
- {lfx_nightly-0.2.0.dev26.dist-info → lfx_nightly-0.2.1.dev7.dist-info}/METADATA +5 -2
- {lfx_nightly-0.2.0.dev26.dist-info → lfx_nightly-0.2.1.dev7.dist-info}/RECORD +84 -78
- lfx/components/processing/dataframe_to_toolset.py +0 -259
- {lfx_nightly-0.2.0.dev26.dist-info → lfx_nightly-0.2.1.dev7.dist-info}/WHEEL +0 -0
- {lfx_nightly-0.2.0.dev26.dist-info → lfx_nightly-0.2.1.dev7.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
|
+
from lfx.base.models.unified_models import (
|
|
4
|
+
get_language_model_options,
|
|
5
|
+
get_llm,
|
|
6
|
+
update_model_options_in_build_config,
|
|
7
|
+
)
|
|
3
8
|
from lfx.custom import Component
|
|
4
|
-
from lfx.io import
|
|
9
|
+
from lfx.io import (
|
|
10
|
+
BoolInput,
|
|
11
|
+
MessageInput,
|
|
12
|
+
MessageTextInput,
|
|
13
|
+
ModelInput,
|
|
14
|
+
MultilineInput,
|
|
15
|
+
Output,
|
|
16
|
+
SecretStrInput,
|
|
17
|
+
TableInput,
|
|
18
|
+
)
|
|
5
19
|
from lfx.schema.message import Message
|
|
6
20
|
from lfx.schema.table import EditMode
|
|
7
21
|
|
|
@@ -17,13 +31,20 @@ class SmartRouterComponent(Component):
|
|
|
17
31
|
self._matched_category = None
|
|
18
32
|
|
|
19
33
|
inputs = [
|
|
20
|
-
|
|
21
|
-
name="
|
|
34
|
+
ModelInput(
|
|
35
|
+
name="model",
|
|
22
36
|
display_name="Language Model",
|
|
23
|
-
info="
|
|
24
|
-
|
|
37
|
+
info="Select your model provider",
|
|
38
|
+
real_time_refresh=True,
|
|
25
39
|
required=True,
|
|
26
40
|
),
|
|
41
|
+
SecretStrInput(
|
|
42
|
+
name="api_key",
|
|
43
|
+
display_name="API Key",
|
|
44
|
+
info="Model Provider API key",
|
|
45
|
+
real_time_refresh=True,
|
|
46
|
+
advanced=True,
|
|
47
|
+
),
|
|
27
48
|
MessageTextInput(
|
|
28
49
|
name="input_text",
|
|
29
50
|
display_name="Input",
|
|
@@ -111,6 +132,17 @@ class SmartRouterComponent(Component):
|
|
|
111
132
|
|
|
112
133
|
outputs: list[Output] = []
|
|
113
134
|
|
|
135
|
+
def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None):
|
|
136
|
+
"""Dynamically update build config with user-filtered model options."""
|
|
137
|
+
return update_model_options_in_build_config(
|
|
138
|
+
component=self,
|
|
139
|
+
build_config=build_config,
|
|
140
|
+
cache_key_prefix="language_model_options",
|
|
141
|
+
get_options_func=get_language_model_options,
|
|
142
|
+
field_name=field_name,
|
|
143
|
+
field_value=field_value,
|
|
144
|
+
)
|
|
145
|
+
|
|
114
146
|
def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict:
|
|
115
147
|
"""Create a dynamic output for each category in the categories table."""
|
|
116
148
|
if field_name in {"routes", "enable_else_output"}:
|
|
@@ -153,7 +185,7 @@ class SmartRouterComponent(Component):
|
|
|
153
185
|
|
|
154
186
|
# Find the matching category using LLM-based categorization
|
|
155
187
|
matched_category = None
|
|
156
|
-
llm =
|
|
188
|
+
llm = get_llm(model=self.model, user_id=self.user_id, api_key=self.api_key)
|
|
157
189
|
|
|
158
190
|
if llm and categories:
|
|
159
191
|
# Create prompt for categorization
|
|
@@ -315,7 +347,7 @@ class SmartRouterComponent(Component):
|
|
|
315
347
|
|
|
316
348
|
# Check if any category matches using LLM categorization
|
|
317
349
|
has_match = False
|
|
318
|
-
llm =
|
|
350
|
+
llm = get_llm(model=self.model, user_id=self.user_id, api_key=self.api_key)
|
|
319
351
|
|
|
320
352
|
if llm and categories:
|
|
321
353
|
try:
|
|
@@ -2,13 +2,19 @@ from pydantic import BaseModel, Field, create_model
|
|
|
2
2
|
from trustcall import create_extractor
|
|
3
3
|
|
|
4
4
|
from lfx.base.models.chat_result import get_chat_result
|
|
5
|
+
from lfx.base.models.unified_models import (
|
|
6
|
+
get_language_model_options,
|
|
7
|
+
get_llm,
|
|
8
|
+
update_model_options_in_build_config,
|
|
9
|
+
)
|
|
5
10
|
from lfx.custom.custom_component.component import Component
|
|
6
11
|
from lfx.helpers.base_model import build_model_from_schema
|
|
7
12
|
from lfx.io import (
|
|
8
|
-
HandleInput,
|
|
9
13
|
MessageTextInput,
|
|
14
|
+
ModelInput,
|
|
10
15
|
MultilineInput,
|
|
11
16
|
Output,
|
|
17
|
+
SecretStrInput,
|
|
12
18
|
TableInput,
|
|
13
19
|
)
|
|
14
20
|
from lfx.log.logger import logger
|
|
@@ -25,13 +31,20 @@ class StructuredOutputComponent(Component):
|
|
|
25
31
|
icon = "braces"
|
|
26
32
|
|
|
27
33
|
inputs = [
|
|
28
|
-
|
|
29
|
-
name="
|
|
34
|
+
ModelInput(
|
|
35
|
+
name="model",
|
|
30
36
|
display_name="Language Model",
|
|
31
|
-
info="
|
|
32
|
-
|
|
37
|
+
info="Select your model provider",
|
|
38
|
+
real_time_refresh=True,
|
|
33
39
|
required=True,
|
|
34
40
|
),
|
|
41
|
+
SecretStrInput(
|
|
42
|
+
name="api_key",
|
|
43
|
+
display_name="API Key",
|
|
44
|
+
info="Model Provider API key",
|
|
45
|
+
real_time_refresh=True,
|
|
46
|
+
advanced=True,
|
|
47
|
+
),
|
|
35
48
|
MultilineInput(
|
|
36
49
|
name="input_value",
|
|
37
50
|
display_name="Input Message",
|
|
@@ -126,10 +139,23 @@ class StructuredOutputComponent(Component):
|
|
|
126
139
|
),
|
|
127
140
|
]
|
|
128
141
|
|
|
142
|
+
def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None):
|
|
143
|
+
"""Dynamically update build config with user-filtered model options."""
|
|
144
|
+
return update_model_options_in_build_config(
|
|
145
|
+
component=self,
|
|
146
|
+
build_config=build_config,
|
|
147
|
+
cache_key_prefix="language_model_options",
|
|
148
|
+
get_options_func=get_language_model_options,
|
|
149
|
+
field_name=field_name,
|
|
150
|
+
field_value=field_value,
|
|
151
|
+
)
|
|
152
|
+
|
|
129
153
|
def build_structured_output_base(self):
|
|
130
154
|
schema_name = self.schema_name or "OutputModel"
|
|
131
155
|
|
|
132
|
-
|
|
156
|
+
llm = get_llm(model=self.model, user_id=self.user_id, api_key=self.api_key)
|
|
157
|
+
|
|
158
|
+
if not hasattr(llm, "with_structured_output"):
|
|
133
159
|
msg = "Language model does not support structured output."
|
|
134
160
|
raise TypeError(msg)
|
|
135
161
|
if not self.output_schema:
|
|
@@ -155,9 +181,9 @@ class StructuredOutputComponent(Component):
|
|
|
155
181
|
"callbacks": self.get_langchain_callbacks(),
|
|
156
182
|
}
|
|
157
183
|
# Generate structured output using Trustcall first, then fallback to Langchain if it fails
|
|
158
|
-
result = self._extract_output_with_trustcall(output_model, config_dict)
|
|
184
|
+
result = self._extract_output_with_trustcall(llm, output_model, config_dict)
|
|
159
185
|
if result is None:
|
|
160
|
-
result = self._extract_output_with_langchain(output_model, config_dict)
|
|
186
|
+
result = self._extract_output_with_langchain(llm, output_model, config_dict)
|
|
161
187
|
|
|
162
188
|
# OPTIMIZATION NOTE: Simplified processing based on trustcall response structure
|
|
163
189
|
# Handle non-dict responses (shouldn't happen with trustcall, but defensive)
|
|
@@ -204,9 +230,9 @@ class StructuredOutputComponent(Component):
|
|
|
204
230
|
return DataFrame(output)
|
|
205
231
|
return DataFrame()
|
|
206
232
|
|
|
207
|
-
def _extract_output_with_trustcall(self, schema: BaseModel, config_dict: dict) -> list[BaseModel] | None:
|
|
233
|
+
def _extract_output_with_trustcall(self, llm, schema: BaseModel, config_dict: dict) -> list[BaseModel] | None:
|
|
208
234
|
try:
|
|
209
|
-
llm_with_structured_output = create_extractor(
|
|
235
|
+
llm_with_structured_output = create_extractor(llm, tools=[schema], tool_choice=schema.__name__)
|
|
210
236
|
result = get_chat_result(
|
|
211
237
|
runnable=llm_with_structured_output,
|
|
212
238
|
system_message=self.system_prompt,
|
|
@@ -222,9 +248,9 @@ class StructuredOutputComponent(Component):
|
|
|
222
248
|
return None
|
|
223
249
|
return result or None # langchain fallback is used if error occurs or the result is empty
|
|
224
250
|
|
|
225
|
-
def _extract_output_with_langchain(self, schema: BaseModel, config_dict: dict) -> list[BaseModel] | None:
|
|
251
|
+
def _extract_output_with_langchain(self, llm, schema: BaseModel, config_dict: dict) -> list[BaseModel] | None:
|
|
226
252
|
try:
|
|
227
|
-
llm_with_structured_output =
|
|
253
|
+
llm_with_structured_output = llm.with_structured_output(schema)
|
|
228
254
|
result = get_chat_result(
|
|
229
255
|
runnable=llm_with_structured_output,
|
|
230
256
|
system_message=self.system_prompt,
|
|
@@ -1,89 +1,31 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Compatibility layer for lfx.components.models.
|
|
2
2
|
|
|
3
|
-
This module
|
|
4
|
-
to models_and_agents where the actual model components are located.
|
|
3
|
+
This module redirects imports to lfx.components.models_and_agents for backward compatibility.
|
|
5
4
|
"""
|
|
6
5
|
|
|
7
6
|
from __future__ import annotations
|
|
8
7
|
|
|
9
|
-
import sys
|
|
10
8
|
from typing import Any
|
|
11
9
|
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
_dynamic_imports = {
|
|
16
|
-
"LanguageModelComponent": "language_model",
|
|
17
|
-
"EmbeddingModelComponent": "embedding_model",
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
__all__ = [
|
|
21
|
-
"EmbeddingModelComponent",
|
|
22
|
-
"LanguageModelComponent",
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
# Register redirected submodules in sys.modules for direct importlib.import_module() calls
|
|
26
|
-
# This allows imports like: import lfx.components.models.embedding_model
|
|
27
|
-
_redirected_submodules = {
|
|
28
|
-
"lfx.components.models.embedding_model": "lfx.components.models_and_agents.embedding_model",
|
|
29
|
-
"lfx.components.models.language_model": "lfx.components.models_and_agents.language_model",
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
for old_path, new_path in _redirected_submodules.items():
|
|
33
|
-
if old_path not in sys.modules:
|
|
34
|
-
# Use a lazy loader that imports the actual module when accessed
|
|
35
|
-
class _RedirectedModule:
|
|
36
|
-
def __init__(self, target_path: str, original_path: str):
|
|
37
|
-
self._target_path = target_path
|
|
38
|
-
self._original_path = original_path
|
|
39
|
-
self._module = None
|
|
40
|
-
|
|
41
|
-
def __getattr__(self, name: str) -> Any:
|
|
42
|
-
if self._module is None:
|
|
43
|
-
from importlib import import_module
|
|
44
|
-
|
|
45
|
-
self._module = import_module(self._target_path)
|
|
46
|
-
# Also register under the original path for future imports
|
|
47
|
-
sys.modules[self._original_path] = self._module
|
|
48
|
-
return getattr(self._module, name)
|
|
49
|
-
|
|
50
|
-
def __repr__(self) -> str:
|
|
51
|
-
return f"<redirected module '{self._original_path}' -> '{self._target_path}'>"
|
|
52
|
-
|
|
53
|
-
sys.modules[old_path] = _RedirectedModule(new_path, old_path)
|
|
10
|
+
# Import everything from models_and_agents to maintain backward compatibility
|
|
11
|
+
from lfx.components.models_and_agents import * # noqa: F403
|
|
12
|
+
from lfx.components.models_and_agents import __all__ # noqa: F401
|
|
54
13
|
|
|
55
14
|
|
|
15
|
+
# Set up module-level __getattr__ to handle dynamic imports
|
|
56
16
|
def __getattr__(attr_name: str) -> Any:
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
if attr_name == "embedding_model":
|
|
60
|
-
from importlib import import_module
|
|
61
|
-
|
|
62
|
-
result = import_module("lfx.components.models_and_agents.embedding_model")
|
|
63
|
-
globals()[attr_name] = result
|
|
64
|
-
return result
|
|
65
|
-
if attr_name == "language_model":
|
|
66
|
-
from importlib import import_module
|
|
17
|
+
"""Redirect all attribute access to models_and_agents module."""
|
|
18
|
+
from lfx.components import models_and_agents
|
|
67
19
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return result
|
|
20
|
+
if hasattr(models_and_agents, attr_name):
|
|
21
|
+
return getattr(models_and_agents, attr_name)
|
|
71
22
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
raise AttributeError(msg)
|
|
75
|
-
|
|
76
|
-
# Import from models_and_agents using the correct package path
|
|
77
|
-
package = "lfx.components.models_and_agents"
|
|
78
|
-
try:
|
|
79
|
-
result = import_mod(attr_name, _dynamic_imports[attr_name], package)
|
|
80
|
-
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
|
81
|
-
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
|
82
|
-
raise AttributeError(msg) from e
|
|
83
|
-
globals()[attr_name] = result
|
|
84
|
-
return result
|
|
23
|
+
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
|
24
|
+
raise AttributeError(msg)
|
|
85
25
|
|
|
86
26
|
|
|
87
27
|
def __dir__() -> list[str]:
|
|
88
|
-
"""Return directory of available
|
|
89
|
-
|
|
28
|
+
"""Return the directory of available attributes."""
|
|
29
|
+
from lfx.components import models_and_agents
|
|
30
|
+
|
|
31
|
+
return dir(models_and_agents)
|
|
@@ -1,27 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import json
|
|
2
4
|
import re
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
3
6
|
|
|
4
|
-
from langchain_core.tools import StructuredTool, Tool
|
|
5
7
|
from pydantic import ValidationError
|
|
6
8
|
|
|
9
|
+
from lfx.components.models_and_agents.memory import MemoryComponent
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from langchain_core.tools import Tool
|
|
13
|
+
|
|
7
14
|
from lfx.base.agents.agent import LCToolsAgentComponent
|
|
8
15
|
from lfx.base.agents.events import ExceptionWithMessageError
|
|
9
|
-
from lfx.base.models.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
MODEL_PROVIDERS_LIST,
|
|
14
|
-
MODELS_METADATA,
|
|
16
|
+
from lfx.base.models.unified_models import (
|
|
17
|
+
get_language_model_options,
|
|
18
|
+
get_llm,
|
|
19
|
+
update_model_options_in_build_config,
|
|
15
20
|
)
|
|
16
|
-
from lfx.base.models.model_utils import get_model_name
|
|
17
21
|
from lfx.components.helpers import CurrentDateComponent
|
|
18
22
|
from lfx.components.langchain_utilities.tool_calling import ToolCallingAgentComponent
|
|
19
|
-
from lfx.components.models_and_agents.memory import MemoryComponent
|
|
20
23
|
from lfx.custom.custom_component.component import get_component_toolkit
|
|
21
|
-
from lfx.custom.utils import update_component_build_config
|
|
22
24
|
from lfx.helpers.base_model import build_model_from_schema
|
|
23
|
-
from lfx.inputs.inputs import BoolInput,
|
|
24
|
-
from lfx.io import
|
|
25
|
+
from lfx.inputs.inputs import BoolInput, ModelInput
|
|
26
|
+
from lfx.io import IntInput, MessageTextInput, MultilineInput, Output, SecretStrInput, TableInput
|
|
25
27
|
from lfx.log.logger import logger
|
|
26
28
|
from lfx.schema.data import Data
|
|
27
29
|
from lfx.schema.dotdict import dotdict
|
|
@@ -44,66 +46,21 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
44
46
|
|
|
45
47
|
memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]
|
|
46
48
|
|
|
47
|
-
# Filter out json_mode from OpenAI inputs since we handle structured output differently
|
|
48
|
-
if "OpenAI" in MODEL_PROVIDERS_DICT:
|
|
49
|
-
openai_inputs_filtered = [
|
|
50
|
-
input_field
|
|
51
|
-
for input_field in MODEL_PROVIDERS_DICT["OpenAI"]["inputs"]
|
|
52
|
-
if not (hasattr(input_field, "name") and input_field.name == "json_mode")
|
|
53
|
-
]
|
|
54
|
-
else:
|
|
55
|
-
openai_inputs_filtered = []
|
|
56
|
-
|
|
57
49
|
inputs = [
|
|
58
|
-
|
|
59
|
-
name="
|
|
60
|
-
display_name="Model
|
|
61
|
-
info="
|
|
62
|
-
options=[*MODEL_PROVIDERS_LIST],
|
|
63
|
-
value="OpenAI",
|
|
50
|
+
ModelInput(
|
|
51
|
+
name="model",
|
|
52
|
+
display_name="Language Model",
|
|
53
|
+
info="Select your model provider",
|
|
64
54
|
real_time_refresh=True,
|
|
65
|
-
|
|
66
|
-
input_types=[],
|
|
67
|
-
options_metadata=[MODELS_METADATA[key] for key in MODEL_PROVIDERS_LIST if key in MODELS_METADATA],
|
|
68
|
-
external_options={
|
|
69
|
-
"fields": {
|
|
70
|
-
"data": {
|
|
71
|
-
"node": {
|
|
72
|
-
"name": "connect_other_models",
|
|
73
|
-
"display_name": "Connect other models",
|
|
74
|
-
"icon": "CornerDownLeft",
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
},
|
|
55
|
+
required=True,
|
|
79
56
|
),
|
|
80
57
|
SecretStrInput(
|
|
81
58
|
name="api_key",
|
|
82
59
|
display_name="API Key",
|
|
83
|
-
info="
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
StrInput(
|
|
87
|
-
name="base_url",
|
|
88
|
-
display_name="Base URL",
|
|
89
|
-
info="The base URL of the API.",
|
|
90
|
-
required=True,
|
|
91
|
-
show=False,
|
|
92
|
-
),
|
|
93
|
-
StrInput(
|
|
94
|
-
name="project_id",
|
|
95
|
-
display_name="Project ID",
|
|
96
|
-
info="The project ID of the model.",
|
|
97
|
-
required=True,
|
|
98
|
-
show=False,
|
|
99
|
-
),
|
|
100
|
-
IntInput(
|
|
101
|
-
name="max_output_tokens",
|
|
102
|
-
display_name="Max Output Tokens",
|
|
103
|
-
info="The maximum number of tokens to generate.",
|
|
104
|
-
show=False,
|
|
60
|
+
info="Model Provider API key",
|
|
61
|
+
real_time_refresh=True,
|
|
62
|
+
advanced=True,
|
|
105
63
|
),
|
|
106
|
-
*openai_inputs_filtered,
|
|
107
64
|
MultilineInput(
|
|
108
65
|
name="system_prompt",
|
|
109
66
|
display_name="Agent Instructions",
|
|
@@ -204,11 +161,16 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
204
161
|
|
|
205
162
|
async def get_agent_requirements(self):
|
|
206
163
|
"""Get the agent requirements for the agent."""
|
|
207
|
-
|
|
164
|
+
from langchain_core.tools import StructuredTool
|
|
165
|
+
|
|
166
|
+
llm_model = get_llm(
|
|
167
|
+
model=self.model,
|
|
168
|
+
user_id=self.user_id,
|
|
169
|
+
api_key=self.api_key,
|
|
170
|
+
)
|
|
208
171
|
if llm_model is None:
|
|
209
172
|
msg = "No language model selected. Please choose a model to proceed."
|
|
210
173
|
raise ValueError(msg)
|
|
211
|
-
self.model_name = get_model_name(llm_model, display_name=display_name)
|
|
212
174
|
|
|
213
175
|
# Get memory data
|
|
214
176
|
self.chat_history = await self.get_memory_data()
|
|
@@ -456,55 +418,6 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
456
418
|
message for message in messages if getattr(message, "id", None) != getattr(self.input_value, "id", None)
|
|
457
419
|
]
|
|
458
420
|
|
|
459
|
-
async def get_llm(self):
|
|
460
|
-
if not isinstance(self.agent_llm, str):
|
|
461
|
-
return self.agent_llm, None
|
|
462
|
-
|
|
463
|
-
try:
|
|
464
|
-
provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)
|
|
465
|
-
if not provider_info:
|
|
466
|
-
msg = f"Invalid model provider: {self.agent_llm}"
|
|
467
|
-
raise ValueError(msg)
|
|
468
|
-
|
|
469
|
-
component_class = provider_info.get("component_class")
|
|
470
|
-
display_name = component_class.display_name
|
|
471
|
-
inputs = provider_info.get("inputs")
|
|
472
|
-
prefix = provider_info.get("prefix", "")
|
|
473
|
-
|
|
474
|
-
return self._build_llm_model(component_class, inputs, prefix), display_name
|
|
475
|
-
|
|
476
|
-
except (AttributeError, ValueError, TypeError, RuntimeError) as e:
|
|
477
|
-
await logger.aerror(f"Error building {self.agent_llm} language model: {e!s}")
|
|
478
|
-
msg = f"Failed to initialize language model: {e!s}"
|
|
479
|
-
raise ValueError(msg) from e
|
|
480
|
-
|
|
481
|
-
def _build_llm_model(self, component, inputs, prefix=""):
|
|
482
|
-
model_kwargs = {}
|
|
483
|
-
for input_ in inputs:
|
|
484
|
-
if hasattr(self, f"{prefix}{input_.name}"):
|
|
485
|
-
model_kwargs[input_.name] = getattr(self, f"{prefix}{input_.name}")
|
|
486
|
-
return component.set(**model_kwargs).build_model()
|
|
487
|
-
|
|
488
|
-
def set_component_params(self, component):
|
|
489
|
-
provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)
|
|
490
|
-
if provider_info:
|
|
491
|
-
inputs = provider_info.get("inputs")
|
|
492
|
-
prefix = provider_info.get("prefix")
|
|
493
|
-
# Filter out json_mode and only use attributes that exist on this component
|
|
494
|
-
model_kwargs = {}
|
|
495
|
-
for input_ in inputs:
|
|
496
|
-
if hasattr(self, f"{prefix}{input_.name}"):
|
|
497
|
-
model_kwargs[input_.name] = getattr(self, f"{prefix}{input_.name}")
|
|
498
|
-
|
|
499
|
-
return component.set(**model_kwargs)
|
|
500
|
-
return component
|
|
501
|
-
|
|
502
|
-
def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:
|
|
503
|
-
"""Delete specified fields from build_config."""
|
|
504
|
-
for field in fields:
|
|
505
|
-
if build_config is not None and field in build_config:
|
|
506
|
-
build_config.pop(field, None)
|
|
507
|
-
|
|
508
421
|
def update_input_types(self, build_config: dotdict) -> dotdict:
|
|
509
422
|
"""Update input types for all fields in build_config."""
|
|
510
423
|
for key, value in build_config.items():
|
|
@@ -516,74 +429,29 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
516
429
|
return build_config
|
|
517
430
|
|
|
518
431
|
async def update_build_config(
|
|
519
|
-
self,
|
|
432
|
+
self,
|
|
433
|
+
build_config: dotdict,
|
|
434
|
+
field_value: list[dict],
|
|
435
|
+
field_name: str | None = None,
|
|
520
436
|
) -> dotdict:
|
|
521
|
-
#
|
|
522
|
-
#
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
437
|
+
# Update model options with caching (for all field changes)
|
|
438
|
+
# Agents require tool calling, so filter for only tool-calling capable models
|
|
439
|
+
def get_tool_calling_model_options(user_id=None):
|
|
440
|
+
return get_language_model_options(user_id=user_id, tool_calling=True)
|
|
441
|
+
|
|
442
|
+
build_config = update_model_options_in_build_config(
|
|
443
|
+
component=self,
|
|
444
|
+
build_config=dict(build_config),
|
|
445
|
+
cache_key_prefix="language_model_options_tool_calling",
|
|
446
|
+
get_options_func=get_tool_calling_model_options,
|
|
447
|
+
field_name=field_name,
|
|
448
|
+
field_value=field_value,
|
|
449
|
+
)
|
|
450
|
+
build_config = dotdict(build_config)
|
|
533
451
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
[
|
|
538
|
-
MODEL_PROVIDERS_DICT[other_provider]["fields"]
|
|
539
|
-
for other_provider in MODEL_PROVIDERS_DICT
|
|
540
|
-
if other_provider != provider
|
|
541
|
-
],
|
|
542
|
-
)
|
|
543
|
-
for provider in MODEL_PROVIDERS_DICT
|
|
544
|
-
}
|
|
545
|
-
if field_value in provider_configs:
|
|
546
|
-
fields_to_add, fields_to_delete = provider_configs[field_value]
|
|
547
|
-
|
|
548
|
-
# Delete fields from other providers
|
|
549
|
-
for fields in fields_to_delete:
|
|
550
|
-
self.delete_fields(build_config, fields)
|
|
551
|
-
|
|
552
|
-
# Add provider-specific fields
|
|
553
|
-
if field_value == "OpenAI" and not any(field in build_config for field in fields_to_add):
|
|
554
|
-
build_config.update(fields_to_add)
|
|
555
|
-
else:
|
|
556
|
-
build_config.update(fields_to_add)
|
|
557
|
-
# Reset input types for agent_llm
|
|
558
|
-
build_config["agent_llm"]["input_types"] = []
|
|
559
|
-
build_config["agent_llm"]["display_name"] = "Model Provider"
|
|
560
|
-
elif field_value == "connect_other_models":
|
|
561
|
-
# Delete all provider fields
|
|
562
|
-
self.delete_fields(build_config, ALL_PROVIDER_FIELDS)
|
|
563
|
-
# # Update with custom component
|
|
564
|
-
custom_component = DropdownInput(
|
|
565
|
-
name="agent_llm",
|
|
566
|
-
display_name="Language Model",
|
|
567
|
-
info="The provider of the language model that the agent will use to generate responses.",
|
|
568
|
-
options=[*MODEL_PROVIDERS_LIST],
|
|
569
|
-
real_time_refresh=True,
|
|
570
|
-
refresh_button=False,
|
|
571
|
-
input_types=["LanguageModel"],
|
|
572
|
-
placeholder="Awaiting model input.",
|
|
573
|
-
options_metadata=[MODELS_METADATA[key] for key in MODEL_PROVIDERS_LIST if key in MODELS_METADATA],
|
|
574
|
-
external_options={
|
|
575
|
-
"fields": {
|
|
576
|
-
"data": {
|
|
577
|
-
"node": {
|
|
578
|
-
"name": "connect_other_models",
|
|
579
|
-
"display_name": "Connect other models",
|
|
580
|
-
"icon": "CornerDownLeft",
|
|
581
|
-
},
|
|
582
|
-
}
|
|
583
|
-
},
|
|
584
|
-
},
|
|
585
|
-
)
|
|
586
|
-
build_config.update({"agent_llm": custom_component.to_dict()})
|
|
452
|
+
# Iterate over all providers in the MODEL_PROVIDERS_DICT
|
|
453
|
+
if field_name == "model":
|
|
454
|
+
self.log(str(field_value))
|
|
587
455
|
# Update input types for all fields
|
|
588
456
|
build_config = self.update_input_types(build_config)
|
|
589
457
|
|
|
@@ -591,7 +459,7 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
591
459
|
default_keys = [
|
|
592
460
|
"code",
|
|
593
461
|
"_type",
|
|
594
|
-
"
|
|
462
|
+
"model",
|
|
595
463
|
"tools",
|
|
596
464
|
"input_value",
|
|
597
465
|
"add_current_date_tool",
|
|
@@ -605,24 +473,6 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
605
473
|
if missing_keys:
|
|
606
474
|
msg = f"Missing required keys in build_config: {missing_keys}"
|
|
607
475
|
raise ValueError(msg)
|
|
608
|
-
if (
|
|
609
|
-
isinstance(self.agent_llm, str)
|
|
610
|
-
and self.agent_llm in MODEL_PROVIDERS_DICT
|
|
611
|
-
and field_name in MODEL_DYNAMIC_UPDATE_FIELDS
|
|
612
|
-
):
|
|
613
|
-
provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)
|
|
614
|
-
if provider_info:
|
|
615
|
-
component_class = provider_info.get("component_class")
|
|
616
|
-
component_class = self.set_component_params(component_class)
|
|
617
|
-
prefix = provider_info.get("prefix")
|
|
618
|
-
if component_class and hasattr(component_class, "update_build_config"):
|
|
619
|
-
# Call each component class's update_build_config method
|
|
620
|
-
# remove the prefix from the field_name
|
|
621
|
-
if isinstance(field_name, str) and isinstance(prefix, str):
|
|
622
|
-
field_name = field_name.replace(prefix, "")
|
|
623
|
-
build_config = await update_component_build_config(
|
|
624
|
-
component_class, build_config, field_value, "model_name"
|
|
625
|
-
)
|
|
626
476
|
return dotdict({k: v.to_dict() if hasattr(v, "to_dict") else v for k, v in build_config.items()})
|
|
627
477
|
|
|
628
478
|
async def _get_tools(self) -> list[Tool]:
|