lfx-nightly 0.2.0.dev0__py3-none-any.whl → 0.2.0.dev41__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.
Files changed (196) hide show
  1. lfx/_assets/component_index.json +1 -1
  2. lfx/base/agents/agent.py +21 -4
  3. lfx/base/agents/altk_base_agent.py +393 -0
  4. lfx/base/agents/altk_tool_wrappers.py +565 -0
  5. lfx/base/agents/events.py +2 -1
  6. lfx/base/composio/composio_base.py +159 -224
  7. lfx/base/data/base_file.py +97 -20
  8. lfx/base/data/docling_utils.py +61 -10
  9. lfx/base/data/storage_utils.py +301 -0
  10. lfx/base/data/utils.py +178 -14
  11. lfx/base/mcp/util.py +2 -2
  12. lfx/base/models/anthropic_constants.py +21 -12
  13. lfx/base/models/groq_constants.py +74 -58
  14. lfx/base/models/groq_model_discovery.py +265 -0
  15. lfx/base/models/model.py +1 -1
  16. lfx/base/models/model_utils.py +100 -0
  17. lfx/base/models/openai_constants.py +7 -0
  18. lfx/base/models/watsonx_constants.py +32 -8
  19. lfx/base/tools/run_flow.py +601 -129
  20. lfx/cli/commands.py +9 -4
  21. lfx/cli/common.py +2 -2
  22. lfx/cli/run.py +1 -1
  23. lfx/cli/script_loader.py +53 -11
  24. lfx/components/Notion/create_page.py +1 -1
  25. lfx/components/Notion/list_database_properties.py +1 -1
  26. lfx/components/Notion/list_pages.py +1 -1
  27. lfx/components/Notion/list_users.py +1 -1
  28. lfx/components/Notion/page_content_viewer.py +1 -1
  29. lfx/components/Notion/search.py +1 -1
  30. lfx/components/Notion/update_page_property.py +1 -1
  31. lfx/components/__init__.py +19 -5
  32. lfx/components/{agents → altk}/__init__.py +5 -9
  33. lfx/components/altk/altk_agent.py +193 -0
  34. lfx/components/apify/apify_actor.py +1 -1
  35. lfx/components/composio/__init__.py +70 -18
  36. lfx/components/composio/apollo_composio.py +11 -0
  37. lfx/components/composio/bitbucket_composio.py +11 -0
  38. lfx/components/composio/canva_composio.py +11 -0
  39. lfx/components/composio/coda_composio.py +11 -0
  40. lfx/components/composio/composio_api.py +10 -0
  41. lfx/components/composio/discord_composio.py +1 -1
  42. lfx/components/composio/elevenlabs_composio.py +11 -0
  43. lfx/components/composio/exa_composio.py +11 -0
  44. lfx/components/composio/firecrawl_composio.py +11 -0
  45. lfx/components/composio/fireflies_composio.py +11 -0
  46. lfx/components/composio/gmail_composio.py +1 -1
  47. lfx/components/composio/googlebigquery_composio.py +11 -0
  48. lfx/components/composio/googlecalendar_composio.py +1 -1
  49. lfx/components/composio/googledocs_composio.py +1 -1
  50. lfx/components/composio/googlemeet_composio.py +1 -1
  51. lfx/components/composio/googlesheets_composio.py +1 -1
  52. lfx/components/composio/googletasks_composio.py +1 -1
  53. lfx/components/composio/heygen_composio.py +11 -0
  54. lfx/components/composio/mem0_composio.py +11 -0
  55. lfx/components/composio/peopledatalabs_composio.py +11 -0
  56. lfx/components/composio/perplexityai_composio.py +11 -0
  57. lfx/components/composio/serpapi_composio.py +11 -0
  58. lfx/components/composio/slack_composio.py +3 -574
  59. lfx/components/composio/slackbot_composio.py +1 -1
  60. lfx/components/composio/snowflake_composio.py +11 -0
  61. lfx/components/composio/tavily_composio.py +11 -0
  62. lfx/components/composio/youtube_composio.py +2 -2
  63. lfx/components/cuga/__init__.py +34 -0
  64. lfx/components/cuga/cuga_agent.py +730 -0
  65. lfx/components/data/__init__.py +78 -28
  66. lfx/components/data_source/__init__.py +58 -0
  67. lfx/components/{data → data_source}/api_request.py +26 -3
  68. lfx/components/{data → data_source}/csv_to_data.py +15 -10
  69. lfx/components/{data → data_source}/json_to_data.py +15 -8
  70. lfx/components/{data → data_source}/news_search.py +1 -1
  71. lfx/components/{data → data_source}/rss.py +1 -1
  72. lfx/components/{data → data_source}/sql_executor.py +1 -1
  73. lfx/components/{data → data_source}/url.py +1 -1
  74. lfx/components/{data → data_source}/web_search.py +1 -1
  75. lfx/components/datastax/astradb_cql.py +1 -1
  76. lfx/components/datastax/astradb_graph.py +1 -1
  77. lfx/components/datastax/astradb_tool.py +1 -1
  78. lfx/components/datastax/astradb_vectorstore.py +1 -1
  79. lfx/components/datastax/hcd.py +1 -1
  80. lfx/components/deactivated/json_document_builder.py +1 -1
  81. lfx/components/docling/__init__.py +0 -3
  82. lfx/components/docling/chunk_docling_document.py +3 -1
  83. lfx/components/docling/export_docling_document.py +3 -1
  84. lfx/components/elastic/elasticsearch.py +1 -1
  85. lfx/components/files_and_knowledge/__init__.py +47 -0
  86. lfx/components/{data → files_and_knowledge}/directory.py +1 -1
  87. lfx/components/{data → files_and_knowledge}/file.py +304 -24
  88. lfx/components/{knowledge_bases → files_and_knowledge}/retrieval.py +2 -2
  89. lfx/components/{data → files_and_knowledge}/save_file.py +218 -31
  90. lfx/components/flow_controls/__init__.py +58 -0
  91. lfx/components/{logic → flow_controls}/conditional_router.py +1 -1
  92. lfx/components/{logic → flow_controls}/loop.py +43 -9
  93. lfx/components/flow_controls/run_flow.py +108 -0
  94. lfx/components/glean/glean_search_api.py +1 -1
  95. lfx/components/groq/groq.py +35 -28
  96. lfx/components/helpers/__init__.py +102 -0
  97. lfx/components/ibm/watsonx.py +7 -1
  98. lfx/components/input_output/__init__.py +3 -1
  99. lfx/components/input_output/chat.py +4 -3
  100. lfx/components/input_output/chat_output.py +10 -4
  101. lfx/components/input_output/text.py +1 -1
  102. lfx/components/input_output/text_output.py +1 -1
  103. lfx/components/{data → input_output}/webhook.py +1 -1
  104. lfx/components/knowledge_bases/__init__.py +59 -4
  105. lfx/components/langchain_utilities/character.py +1 -1
  106. lfx/components/langchain_utilities/csv_agent.py +84 -16
  107. lfx/components/langchain_utilities/json_agent.py +67 -12
  108. lfx/components/langchain_utilities/language_recursive.py +1 -1
  109. lfx/components/llm_operations/__init__.py +46 -0
  110. lfx/components/{processing → llm_operations}/batch_run.py +17 -8
  111. lfx/components/{processing → llm_operations}/lambda_filter.py +1 -1
  112. lfx/components/{logic → llm_operations}/llm_conditional_router.py +1 -1
  113. lfx/components/{processing/llm_router.py → llm_operations/llm_selector.py} +3 -3
  114. lfx/components/{processing → llm_operations}/structured_output.py +1 -1
  115. lfx/components/logic/__init__.py +126 -0
  116. lfx/components/mem0/mem0_chat_memory.py +11 -0
  117. lfx/components/models/__init__.py +64 -9
  118. lfx/components/models_and_agents/__init__.py +49 -0
  119. lfx/components/{agents → models_and_agents}/agent.py +6 -4
  120. lfx/components/models_and_agents/embedding_model.py +353 -0
  121. lfx/components/models_and_agents/language_model.py +398 -0
  122. lfx/components/{agents → models_and_agents}/mcp_component.py +53 -44
  123. lfx/components/{helpers → models_and_agents}/memory.py +1 -1
  124. lfx/components/nvidia/system_assist.py +1 -1
  125. lfx/components/olivya/olivya.py +1 -1
  126. lfx/components/ollama/ollama.py +24 -5
  127. lfx/components/processing/__init__.py +9 -60
  128. lfx/components/processing/converter.py +1 -1
  129. lfx/components/processing/dataframe_operations.py +1 -1
  130. lfx/components/processing/parse_json_data.py +2 -2
  131. lfx/components/processing/parser.py +1 -1
  132. lfx/components/processing/split_text.py +1 -1
  133. lfx/components/qdrant/qdrant.py +1 -1
  134. lfx/components/redis/redis.py +1 -1
  135. lfx/components/twelvelabs/split_video.py +10 -0
  136. lfx/components/twelvelabs/video_file.py +12 -0
  137. lfx/components/utilities/__init__.py +43 -0
  138. lfx/components/{helpers → utilities}/calculator_core.py +1 -1
  139. lfx/components/{helpers → utilities}/current_date.py +1 -1
  140. lfx/components/{processing → utilities}/python_repl_core.py +1 -1
  141. lfx/components/vectorstores/local_db.py +9 -0
  142. lfx/components/youtube/youtube_transcripts.py +118 -30
  143. lfx/custom/custom_component/component.py +57 -1
  144. lfx/custom/custom_component/custom_component.py +68 -6
  145. lfx/custom/directory_reader/directory_reader.py +5 -2
  146. lfx/graph/edge/base.py +43 -20
  147. lfx/graph/state/model.py +15 -2
  148. lfx/graph/utils.py +6 -0
  149. lfx/graph/vertex/param_handler.py +10 -7
  150. lfx/helpers/__init__.py +12 -0
  151. lfx/helpers/flow.py +117 -0
  152. lfx/inputs/input_mixin.py +24 -1
  153. lfx/inputs/inputs.py +13 -1
  154. lfx/interface/components.py +161 -83
  155. lfx/log/logger.py +5 -3
  156. lfx/schema/image.py +2 -12
  157. lfx/services/database/__init__.py +5 -0
  158. lfx/services/database/service.py +25 -0
  159. lfx/services/deps.py +87 -22
  160. lfx/services/interfaces.py +5 -0
  161. lfx/services/manager.py +24 -10
  162. lfx/services/mcp_composer/service.py +1029 -162
  163. lfx/services/session.py +5 -0
  164. lfx/services/settings/auth.py +18 -11
  165. lfx/services/settings/base.py +56 -30
  166. lfx/services/settings/constants.py +8 -0
  167. lfx/services/storage/local.py +108 -46
  168. lfx/services/storage/service.py +171 -29
  169. lfx/template/field/base.py +3 -0
  170. lfx/utils/image.py +29 -11
  171. lfx/utils/ssrf_protection.py +384 -0
  172. lfx/utils/validate_cloud.py +26 -0
  173. {lfx_nightly-0.2.0.dev0.dist-info → lfx_nightly-0.2.0.dev41.dist-info}/METADATA +38 -22
  174. {lfx_nightly-0.2.0.dev0.dist-info → lfx_nightly-0.2.0.dev41.dist-info}/RECORD +189 -160
  175. {lfx_nightly-0.2.0.dev0.dist-info → lfx_nightly-0.2.0.dev41.dist-info}/WHEEL +1 -1
  176. lfx/components/agents/altk_agent.py +0 -366
  177. lfx/components/agents/cuga_agent.py +0 -1013
  178. lfx/components/docling/docling_remote_vlm.py +0 -284
  179. lfx/components/logic/run_flow.py +0 -71
  180. lfx/components/models/embedding_model.py +0 -195
  181. lfx/components/models/language_model.py +0 -144
  182. lfx/components/processing/dataframe_to_toolset.py +0 -259
  183. /lfx/components/{data → data_source}/mock_data.py +0 -0
  184. /lfx/components/{knowledge_bases → files_and_knowledge}/ingestion.py +0 -0
  185. /lfx/components/{logic → flow_controls}/data_conditional_router.py +0 -0
  186. /lfx/components/{logic → flow_controls}/flow_tool.py +0 -0
  187. /lfx/components/{logic → flow_controls}/listen.py +0 -0
  188. /lfx/components/{logic → flow_controls}/notify.py +0 -0
  189. /lfx/components/{logic → flow_controls}/pass_message.py +0 -0
  190. /lfx/components/{logic → flow_controls}/sub_flow.py +0 -0
  191. /lfx/components/{processing → models_and_agents}/prompt.py +0 -0
  192. /lfx/components/{helpers → processing}/create_list.py +0 -0
  193. /lfx/components/{helpers → processing}/output_parser.py +0 -0
  194. /lfx/components/{helpers → processing}/store_message.py +0 -0
  195. /lfx/components/{helpers → utilities}/id_generator.py +0 -0
  196. {lfx_nightly-0.2.0.dev0.dist-info → lfx_nightly-0.2.0.dev41.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,49 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ from lfx.components._importing import import_mod
6
+
7
+ if TYPE_CHECKING:
8
+ from lfx.components.models_and_agents.agent import AgentComponent
9
+ from lfx.components.models_and_agents.embedding_model import EmbeddingModelComponent
10
+ from lfx.components.models_and_agents.language_model import LanguageModelComponent
11
+ from lfx.components.models_and_agents.mcp_component import MCPToolsComponent
12
+ from lfx.components.models_and_agents.memory import MemoryComponent
13
+ from lfx.components.models_and_agents.prompt import PromptComponent
14
+
15
+ _dynamic_imports = {
16
+ "AgentComponent": "agent",
17
+ "EmbeddingModelComponent": "embedding_model",
18
+ "LanguageModelComponent": "language_model",
19
+ "MCPToolsComponent": "mcp_component",
20
+ "MemoryComponent": "memory",
21
+ "PromptComponent": "prompt",
22
+ }
23
+
24
+ __all__ = [
25
+ "AgentComponent",
26
+ "EmbeddingModelComponent",
27
+ "LanguageModelComponent",
28
+ "MCPToolsComponent",
29
+ "MemoryComponent",
30
+ "PromptComponent",
31
+ ]
32
+
33
+
34
+ def __getattr__(attr_name: str) -> Any:
35
+ """Lazily import model and agent components on attribute access."""
36
+ if attr_name not in _dynamic_imports:
37
+ msg = f"module '{__name__}' has no attribute '{attr_name}'"
38
+ raise AttributeError(msg)
39
+ try:
40
+ result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
41
+ except (ModuleNotFoundError, ImportError, AttributeError) as e:
42
+ msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
43
+ raise AttributeError(msg) from e
44
+ globals()[attr_name] = result
45
+ return result
46
+
47
+
48
+ def __dir__() -> list[str]:
49
+ return list(__all__)
@@ -14,9 +14,9 @@ from lfx.base.models.model_input_constants import (
14
14
  MODELS_METADATA,
15
15
  )
16
16
  from lfx.base.models.model_utils import get_model_name
17
- from lfx.components.helpers.current_date import CurrentDateComponent
18
- from lfx.components.helpers.memory import MemoryComponent
17
+ from lfx.components.helpers import CurrentDateComponent
19
18
  from lfx.components.langchain_utilities.tool_calling import ToolCallingAgentComponent
19
+ from lfx.components.models_and_agents.memory import MemoryComponent
20
20
  from lfx.custom.custom_component.component import get_component_toolkit
21
21
  from lfx.custom.utils import update_component_build_config
22
22
  from lfx.helpers.base_model import build_model_from_schema
@@ -619,9 +619,11 @@ class AgentComponent(ToolCallingAgentComponent):
619
619
  # Call each component class's update_build_config method
620
620
  # remove the prefix from the field_name
621
621
  if isinstance(field_name, str) and isinstance(prefix, str):
622
- field_name = field_name.replace(prefix, "")
622
+ field_name_without_prefix = field_name.replace(prefix, "")
623
+ else:
624
+ field_name_without_prefix = field_name
623
625
  build_config = await update_component_build_config(
624
- component_class, build_config, field_value, "model_name"
626
+ component_class, build_config, field_value, field_name_without_prefix
625
627
  )
626
628
  return dotdict({k: v.to_dict() if hasattr(v, "to_dict") else v for k, v in build_config.items()})
627
629
 
@@ -0,0 +1,353 @@
1
+ from typing import Any
2
+
3
+ import requests
4
+ from ibm_watsonx_ai.metanames import EmbedTextParamsMetaNames
5
+ from langchain_openai import OpenAIEmbeddings
6
+
7
+ from lfx.base.embeddings.model import LCEmbeddingsModel
8
+ from lfx.base.models.model_utils import get_ollama_models, is_valid_ollama_url
9
+ from lfx.base.models.openai_constants import OPENAI_EMBEDDING_MODEL_NAMES
10
+ from lfx.base.models.watsonx_constants import (
11
+ IBM_WATSONX_URLS,
12
+ WATSONX_EMBEDDING_MODEL_NAMES,
13
+ )
14
+ from lfx.field_typing import Embeddings
15
+ from lfx.io import (
16
+ BoolInput,
17
+ DictInput,
18
+ DropdownInput,
19
+ FloatInput,
20
+ IntInput,
21
+ MessageTextInput,
22
+ SecretStrInput,
23
+ )
24
+ from lfx.log.logger import logger
25
+ from lfx.schema.dotdict import dotdict
26
+ from lfx.utils.util import transform_localhost_url
27
+
28
+ # Ollama API constants
29
+ HTTP_STATUS_OK = 200
30
+ JSON_MODELS_KEY = "models"
31
+ JSON_NAME_KEY = "name"
32
+ JSON_CAPABILITIES_KEY = "capabilities"
33
+ DESIRED_CAPABILITY = "embedding"
34
+ DEFAULT_OLLAMA_URL = "http://localhost:11434"
35
+
36
+
37
+ class EmbeddingModelComponent(LCEmbeddingsModel):
38
+ display_name = "Embedding Model"
39
+ description = "Generate embeddings using a specified provider."
40
+ documentation: str = "https://docs.langflow.org/components-embedding-models"
41
+ icon = "binary"
42
+ name = "EmbeddingModel"
43
+ category = "models"
44
+
45
+ inputs = [
46
+ DropdownInput(
47
+ name="provider",
48
+ display_name="Model Provider",
49
+ options=["OpenAI", "Ollama", "IBM watsonx.ai"],
50
+ value="OpenAI",
51
+ info="Select the embedding model provider",
52
+ real_time_refresh=True,
53
+ options_metadata=[{"icon": "OpenAI"}, {"icon": "Ollama"}, {"icon": "WatsonxAI"}],
54
+ ),
55
+ MessageTextInput(
56
+ name="api_base",
57
+ display_name="API Base URL",
58
+ info="Base URL for the API. Leave empty for default.",
59
+ advanced=True,
60
+ ),
61
+ MessageTextInput(
62
+ name="ollama_base_url",
63
+ display_name="Ollama API URL",
64
+ info=f"Endpoint of the Ollama API (Ollama only). Defaults to {DEFAULT_OLLAMA_URL}",
65
+ value=DEFAULT_OLLAMA_URL,
66
+ show=False,
67
+ real_time_refresh=True,
68
+ load_from_db=True,
69
+ ),
70
+ DropdownInput(
71
+ name="base_url_ibm_watsonx",
72
+ display_name="watsonx API Endpoint",
73
+ info="The base URL of the API (IBM watsonx.ai only)",
74
+ options=IBM_WATSONX_URLS,
75
+ value=IBM_WATSONX_URLS[0],
76
+ show=False,
77
+ real_time_refresh=True,
78
+ ),
79
+ DropdownInput(
80
+ name="model",
81
+ display_name="Model Name",
82
+ options=OPENAI_EMBEDDING_MODEL_NAMES,
83
+ value=OPENAI_EMBEDDING_MODEL_NAMES[0],
84
+ info="Select the embedding model to use",
85
+ real_time_refresh=True,
86
+ refresh_button=True,
87
+ ),
88
+ SecretStrInput(
89
+ name="api_key",
90
+ display_name="OpenAI API Key",
91
+ info="Model Provider API key",
92
+ required=True,
93
+ show=True,
94
+ real_time_refresh=True,
95
+ ),
96
+ # Watson-specific inputs
97
+ MessageTextInput(
98
+ name="project_id",
99
+ display_name="Project ID",
100
+ info="IBM watsonx.ai Project ID (required for IBM watsonx.ai)",
101
+ show=False,
102
+ ),
103
+ IntInput(
104
+ name="dimensions",
105
+ display_name="Dimensions",
106
+ info="The number of dimensions the resulting output embeddings should have. "
107
+ "Only supported by certain models.",
108
+ advanced=True,
109
+ ),
110
+ IntInput(name="chunk_size", display_name="Chunk Size", advanced=True, value=1000),
111
+ FloatInput(name="request_timeout", display_name="Request Timeout", advanced=True),
112
+ IntInput(name="max_retries", display_name="Max Retries", advanced=True, value=3),
113
+ BoolInput(name="show_progress_bar", display_name="Show Progress Bar", advanced=True),
114
+ DictInput(
115
+ name="model_kwargs",
116
+ display_name="Model Kwargs",
117
+ advanced=True,
118
+ info="Additional keyword arguments to pass to the model.",
119
+ ),
120
+ IntInput(
121
+ name="truncate_input_tokens",
122
+ display_name="Truncate Input Tokens",
123
+ advanced=True,
124
+ value=200,
125
+ show=False,
126
+ ),
127
+ BoolInput(
128
+ name="input_text",
129
+ display_name="Include the original text in the output",
130
+ value=True,
131
+ advanced=True,
132
+ show=False,
133
+ ),
134
+ ]
135
+
136
+ @staticmethod
137
+ def fetch_ibm_models(base_url: str) -> list[str]:
138
+ """Fetch available models from the watsonx.ai API."""
139
+ try:
140
+ endpoint = f"{base_url}/ml/v1/foundation_model_specs"
141
+ params = {
142
+ "version": "2024-09-16",
143
+ "filters": "function_embedding,!lifecycle_withdrawn:and",
144
+ }
145
+ response = requests.get(endpoint, params=params, timeout=10)
146
+ response.raise_for_status()
147
+ data = response.json()
148
+ models = [model["model_id"] for model in data.get("resources", [])]
149
+ return sorted(models)
150
+ except Exception: # noqa: BLE001
151
+ logger.exception("Error fetching models")
152
+ return WATSONX_EMBEDDING_MODEL_NAMES
153
+
154
+ def build_embeddings(self) -> Embeddings:
155
+ provider = self.provider
156
+ model = self.model
157
+ api_key = self.api_key
158
+ api_base = self.api_base
159
+ base_url_ibm_watsonx = self.base_url_ibm_watsonx
160
+ ollama_base_url = self.ollama_base_url
161
+ dimensions = self.dimensions
162
+ chunk_size = self.chunk_size
163
+ request_timeout = self.request_timeout
164
+ max_retries = self.max_retries
165
+ show_progress_bar = self.show_progress_bar
166
+ model_kwargs = self.model_kwargs or {}
167
+
168
+ if provider == "OpenAI":
169
+ if not api_key:
170
+ msg = "OpenAI API key is required when using OpenAI provider"
171
+ raise ValueError(msg)
172
+ return OpenAIEmbeddings(
173
+ model=model,
174
+ dimensions=dimensions or None,
175
+ base_url=api_base or None,
176
+ api_key=api_key,
177
+ chunk_size=chunk_size,
178
+ max_retries=max_retries,
179
+ timeout=request_timeout or None,
180
+ show_progress_bar=show_progress_bar,
181
+ model_kwargs=model_kwargs,
182
+ )
183
+
184
+ if provider == "Ollama":
185
+ try:
186
+ from langchain_ollama import OllamaEmbeddings
187
+ except ImportError:
188
+ try:
189
+ from langchain_community.embeddings import OllamaEmbeddings
190
+ except ImportError:
191
+ msg = "Please install langchain-ollama: pip install langchain-ollama"
192
+ raise ImportError(msg) from None
193
+
194
+ transformed_base_url = transform_localhost_url(ollama_base_url)
195
+
196
+ # Check if URL contains /v1 suffix (OpenAI-compatible mode)
197
+ if transformed_base_url and transformed_base_url.rstrip("/").endswith("/v1"):
198
+ # Strip /v1 suffix and log warning
199
+ transformed_base_url = transformed_base_url.rstrip("/").removesuffix("/v1")
200
+ logger.warning(
201
+ "Detected '/v1' suffix in base URL. The Ollama component uses the native Ollama API, "
202
+ "not the OpenAI-compatible API. The '/v1' suffix has been automatically removed. "
203
+ "If you want to use the OpenAI-compatible API, please use the OpenAI component instead. "
204
+ "Learn more at https://docs.ollama.com/openai#openai-compatibility"
205
+ )
206
+
207
+ return OllamaEmbeddings(
208
+ model=model,
209
+ base_url=transformed_base_url or "http://localhost:11434",
210
+ **model_kwargs,
211
+ )
212
+
213
+ if provider == "IBM watsonx.ai":
214
+ try:
215
+ from langchain_ibm import WatsonxEmbeddings
216
+ except ImportError:
217
+ msg = "Please install langchain-ibm: pip install langchain-ibm"
218
+ raise ImportError(msg) from None
219
+
220
+ if not api_key:
221
+ msg = "IBM watsonx.ai API key is required when using IBM watsonx.ai provider"
222
+ raise ValueError(msg)
223
+
224
+ project_id = self.project_id
225
+
226
+ if not project_id:
227
+ msg = "Project ID is required for IBM watsonx.ai provider"
228
+ raise ValueError(msg)
229
+
230
+ from ibm_watsonx_ai import APIClient, Credentials
231
+
232
+ credentials = Credentials(
233
+ api_key=self.api_key,
234
+ url=base_url_ibm_watsonx or "https://us-south.ml.cloud.ibm.com",
235
+ )
236
+
237
+ api_client = APIClient(credentials)
238
+
239
+ params = {
240
+ EmbedTextParamsMetaNames.TRUNCATE_INPUT_TOKENS: self.truncate_input_tokens,
241
+ EmbedTextParamsMetaNames.RETURN_OPTIONS: {"input_text": self.input_text},
242
+ }
243
+
244
+ return WatsonxEmbeddings(
245
+ model_id=model,
246
+ params=params,
247
+ watsonx_client=api_client,
248
+ project_id=project_id,
249
+ )
250
+
251
+ msg = f"Unknown provider: {provider}"
252
+ raise ValueError(msg)
253
+
254
+ async def update_build_config(
255
+ self, build_config: dotdict, field_value: Any, field_name: str | None = None
256
+ ) -> dotdict:
257
+ if field_name == "provider":
258
+ if field_value == "OpenAI":
259
+ build_config["model"]["options"] = OPENAI_EMBEDDING_MODEL_NAMES
260
+ build_config["model"]["value"] = OPENAI_EMBEDDING_MODEL_NAMES[0]
261
+ build_config["api_key"]["display_name"] = "OpenAI API Key"
262
+ build_config["api_key"]["required"] = True
263
+ build_config["api_key"]["show"] = True
264
+ build_config["api_base"]["display_name"] = "OpenAI API Base URL"
265
+ build_config["api_base"]["advanced"] = True
266
+ build_config["api_base"]["show"] = True
267
+ build_config["ollama_base_url"]["show"] = False
268
+ build_config["project_id"]["show"] = False
269
+ build_config["base_url_ibm_watsonx"]["show"] = False
270
+ build_config["truncate_input_tokens"]["show"] = False
271
+ build_config["input_text"]["show"] = False
272
+ elif field_value == "Ollama":
273
+ build_config["ollama_base_url"]["show"] = True
274
+
275
+ if await is_valid_ollama_url(url=self.ollama_base_url):
276
+ try:
277
+ models = await get_ollama_models(
278
+ base_url_value=self.ollama_base_url,
279
+ desired_capability=DESIRED_CAPABILITY,
280
+ json_models_key=JSON_MODELS_KEY,
281
+ json_name_key=JSON_NAME_KEY,
282
+ json_capabilities_key=JSON_CAPABILITIES_KEY,
283
+ )
284
+ build_config["model"]["options"] = models
285
+ build_config["model"]["value"] = models[0] if models else ""
286
+ except ValueError:
287
+ build_config["model"]["options"] = []
288
+ build_config["model"]["value"] = ""
289
+ else:
290
+ build_config["model"]["options"] = []
291
+ build_config["model"]["value"] = ""
292
+ build_config["truncate_input_tokens"]["show"] = False
293
+ build_config["input_text"]["show"] = False
294
+ build_config["api_key"]["display_name"] = "API Key (Optional)"
295
+ build_config["api_key"]["required"] = False
296
+ build_config["api_key"]["show"] = False
297
+ build_config["api_base"]["show"] = False
298
+ build_config["project_id"]["show"] = False
299
+ build_config["base_url_ibm_watsonx"]["show"] = False
300
+
301
+ elif field_value == "IBM watsonx.ai":
302
+ build_config["model"]["options"] = self.fetch_ibm_models(base_url=self.base_url_ibm_watsonx)
303
+ build_config["model"]["value"] = self.fetch_ibm_models(base_url=self.base_url_ibm_watsonx)[0]
304
+ build_config["api_key"]["display_name"] = "IBM watsonx.ai API Key"
305
+ build_config["api_key"]["required"] = True
306
+ build_config["api_key"]["show"] = True
307
+ build_config["api_base"]["show"] = False
308
+ build_config["ollama_base_url"]["show"] = False
309
+ build_config["base_url_ibm_watsonx"]["show"] = True
310
+ build_config["project_id"]["show"] = True
311
+ build_config["truncate_input_tokens"]["show"] = True
312
+ build_config["input_text"]["show"] = True
313
+ elif field_name == "base_url_ibm_watsonx":
314
+ build_config["model"]["options"] = self.fetch_ibm_models(base_url=field_value)
315
+ build_config["model"]["value"] = self.fetch_ibm_models(base_url=field_value)[0]
316
+ elif field_name == "ollama_base_url":
317
+ # # Refresh Ollama models when base URL changes
318
+ # if hasattr(self, "provider") and self.provider == "Ollama":
319
+ # Use field_value if provided, otherwise fall back to instance attribute
320
+ ollama_url = self.ollama_base_url
321
+ if await is_valid_ollama_url(url=ollama_url):
322
+ try:
323
+ models = await get_ollama_models(
324
+ base_url_value=ollama_url,
325
+ desired_capability=DESIRED_CAPABILITY,
326
+ json_models_key=JSON_MODELS_KEY,
327
+ json_name_key=JSON_NAME_KEY,
328
+ json_capabilities_key=JSON_CAPABILITIES_KEY,
329
+ )
330
+ build_config["model"]["options"] = models
331
+ build_config["model"]["value"] = models[0] if models else ""
332
+ except ValueError:
333
+ await logger.awarning("Failed to fetch Ollama embedding models.")
334
+ build_config["model"]["options"] = []
335
+ build_config["model"]["value"] = ""
336
+
337
+ elif field_name == "model" and self.provider == "Ollama":
338
+ ollama_url = self.ollama_base_url
339
+ if await is_valid_ollama_url(url=ollama_url):
340
+ try:
341
+ models = await get_ollama_models(
342
+ base_url_value=ollama_url,
343
+ desired_capability=DESIRED_CAPABILITY,
344
+ json_models_key=JSON_MODELS_KEY,
345
+ json_name_key=JSON_NAME_KEY,
346
+ json_capabilities_key=JSON_CAPABILITIES_KEY,
347
+ )
348
+ build_config["model"]["options"] = models
349
+ except ValueError:
350
+ await logger.awarning("Failed to refresh Ollama embedding models.")
351
+ build_config["model"]["options"] = []
352
+
353
+ return build_config