lfx-nightly 0.2.0.dev41__py3-none-any.whl → 0.3.0.dev3__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 (98) hide show
  1. lfx/__main__.py +137 -6
  2. lfx/_assets/component_index.json +1 -1
  3. lfx/base/agents/agent.py +10 -6
  4. lfx/base/agents/altk_base_agent.py +5 -3
  5. lfx/base/agents/altk_tool_wrappers.py +1 -1
  6. lfx/base/agents/events.py +1 -1
  7. lfx/base/agents/utils.py +4 -0
  8. lfx/base/composio/composio_base.py +78 -41
  9. lfx/base/data/cloud_storage_utils.py +156 -0
  10. lfx/base/data/docling_utils.py +130 -55
  11. lfx/base/datastax/astradb_base.py +75 -64
  12. lfx/base/embeddings/embeddings_class.py +113 -0
  13. lfx/base/models/__init__.py +11 -1
  14. lfx/base/models/google_generative_ai_constants.py +33 -9
  15. lfx/base/models/model_metadata.py +6 -0
  16. lfx/base/models/ollama_constants.py +196 -30
  17. lfx/base/models/openai_constants.py +37 -10
  18. lfx/base/models/unified_models.py +1123 -0
  19. lfx/base/models/watsonx_constants.py +43 -4
  20. lfx/base/prompts/api_utils.py +40 -5
  21. lfx/base/tools/component_tool.py +2 -9
  22. lfx/cli/__init__.py +10 -2
  23. lfx/cli/commands.py +3 -0
  24. lfx/cli/run.py +65 -409
  25. lfx/cli/script_loader.py +18 -7
  26. lfx/cli/validation.py +6 -3
  27. lfx/components/__init__.py +0 -3
  28. lfx/components/composio/github_composio.py +1 -1
  29. lfx/components/cuga/cuga_agent.py +39 -27
  30. lfx/components/data_source/api_request.py +4 -2
  31. lfx/components/datastax/astradb_assistant_manager.py +4 -2
  32. lfx/components/docling/__init__.py +45 -11
  33. lfx/components/docling/docling_inline.py +39 -49
  34. lfx/components/docling/docling_remote.py +1 -0
  35. lfx/components/elastic/opensearch_multimodal.py +1733 -0
  36. lfx/components/files_and_knowledge/file.py +384 -36
  37. lfx/components/files_and_knowledge/ingestion.py +8 -0
  38. lfx/components/files_and_knowledge/retrieval.py +10 -0
  39. lfx/components/files_and_knowledge/save_file.py +91 -88
  40. lfx/components/langchain_utilities/ibm_granite_handler.py +211 -0
  41. lfx/components/langchain_utilities/tool_calling.py +37 -6
  42. lfx/components/llm_operations/batch_run.py +64 -18
  43. lfx/components/llm_operations/lambda_filter.py +213 -101
  44. lfx/components/llm_operations/llm_conditional_router.py +39 -7
  45. lfx/components/llm_operations/structured_output.py +38 -12
  46. lfx/components/models/__init__.py +16 -74
  47. lfx/components/models_and_agents/agent.py +51 -203
  48. lfx/components/models_and_agents/embedding_model.py +171 -255
  49. lfx/components/models_and_agents/language_model.py +54 -318
  50. lfx/components/models_and_agents/mcp_component.py +96 -10
  51. lfx/components/models_and_agents/prompt.py +105 -18
  52. lfx/components/ollama/ollama_embeddings.py +111 -29
  53. lfx/components/openai/openai_chat_model.py +1 -1
  54. lfx/components/processing/text_operations.py +580 -0
  55. lfx/components/vllm/__init__.py +37 -0
  56. lfx/components/vllm/vllm.py +141 -0
  57. lfx/components/vllm/vllm_embeddings.py +110 -0
  58. lfx/custom/custom_component/component.py +65 -10
  59. lfx/custom/custom_component/custom_component.py +8 -6
  60. lfx/events/observability/__init__.py +0 -0
  61. lfx/events/observability/lifecycle_events.py +111 -0
  62. lfx/field_typing/__init__.py +57 -58
  63. lfx/graph/graph/base.py +40 -1
  64. lfx/graph/utils.py +109 -30
  65. lfx/graph/vertex/base.py +75 -23
  66. lfx/graph/vertex/vertex_types.py +0 -5
  67. lfx/inputs/__init__.py +2 -0
  68. lfx/inputs/input_mixin.py +55 -0
  69. lfx/inputs/inputs.py +120 -0
  70. lfx/interface/components.py +24 -7
  71. lfx/interface/initialize/loading.py +42 -12
  72. lfx/io/__init__.py +2 -0
  73. lfx/run/__init__.py +5 -0
  74. lfx/run/base.py +464 -0
  75. lfx/schema/__init__.py +50 -0
  76. lfx/schema/data.py +1 -1
  77. lfx/schema/image.py +26 -7
  78. lfx/schema/message.py +104 -11
  79. lfx/schema/workflow.py +171 -0
  80. lfx/services/deps.py +12 -0
  81. lfx/services/interfaces.py +43 -1
  82. lfx/services/mcp_composer/service.py +7 -1
  83. lfx/services/schema.py +1 -0
  84. lfx/services/settings/auth.py +95 -4
  85. lfx/services/settings/base.py +11 -1
  86. lfx/services/settings/constants.py +2 -0
  87. lfx/services/settings/utils.py +82 -0
  88. lfx/services/storage/local.py +13 -8
  89. lfx/services/transaction/__init__.py +5 -0
  90. lfx/services/transaction/service.py +35 -0
  91. lfx/tests/unit/components/__init__.py +0 -0
  92. lfx/utils/constants.py +2 -0
  93. lfx/utils/mustache_security.py +79 -0
  94. lfx/utils/validate_cloud.py +81 -3
  95. {lfx_nightly-0.2.0.dev41.dist-info → lfx_nightly-0.3.0.dev3.dist-info}/METADATA +7 -2
  96. {lfx_nightly-0.2.0.dev41.dist-info → lfx_nightly-0.3.0.dev3.dist-info}/RECORD +98 -80
  97. {lfx_nightly-0.2.0.dev41.dist-info → lfx_nightly-0.3.0.dev3.dist-info}/WHEEL +0 -0
  98. {lfx_nightly-0.2.0.dev41.dist-info → lfx_nightly-0.3.0.dev3.dist-info}/entry_points.txt +0 -0
@@ -1,29 +1,68 @@
1
1
  from .model_metadata import create_model_metadata
2
2
 
3
+ WATSONX_DEFAULT_LLM_MODELS = [
4
+ create_model_metadata(
5
+ provider="IBM WatsonX",
6
+ name="ibm/granite-3-2b-instruct",
7
+ icon="WatsonxAI",
8
+ model_type="llm",
9
+ tool_calling=False,
10
+ default=True,
11
+ ),
12
+ create_model_metadata(
13
+ provider="IBM WatsonX",
14
+ name="ibm/granite-3-8b-instruct",
15
+ icon="WatsonxAI",
16
+ model_type="llm",
17
+ tool_calling=True,
18
+ default=True,
19
+ ),
20
+ create_model_metadata(
21
+ provider="IBM WatsonX",
22
+ name="ibm/granite-13b-instruct-v2",
23
+ icon="WatsonxAI",
24
+ model_type="llm",
25
+ tool_calling=False,
26
+ default=True,
27
+ ),
28
+ ]
29
+
3
30
  WATSONX_DEFAULT_EMBEDDING_MODELS = [
4
31
  create_model_metadata(
5
- provider="IBM Watsonx",
32
+ provider="IBM WatsonX",
6
33
  name="sentence-transformers/all-minilm-l12-v2",
7
34
  icon="WatsonxAI",
35
+ model_type="embeddings",
36
+ default=True,
8
37
  ),
9
38
  create_model_metadata(
10
- provider="IBM Watsonx",
39
+ provider="IBM WatsonX",
11
40
  name="ibm/slate-125m-english-rtrvr-v2",
12
41
  icon="WatsonxAI",
42
+ model_type="embeddings",
43
+ default=True,
13
44
  ),
14
45
  create_model_metadata(
15
- provider="IBM Watsonx",
46
+ provider="IBM WatsonX",
16
47
  name="ibm/slate-30m-english-rtrvr-v2",
17
48
  icon="WatsonxAI",
49
+ model_type="embeddings",
50
+ default=True,
18
51
  ),
19
52
  create_model_metadata(
20
- provider="IBM Watsonx",
53
+ provider="IBM WatsonX",
21
54
  name="intfloat/multilingual-e5-large",
22
55
  icon="WatsonxAI",
56
+ model_type="embeddings",
57
+ default=True,
23
58
  ),
24
59
  ]
25
60
 
26
61
 
62
+ WATSONX_EMBEDDING_MODELS_DETAILED = WATSONX_DEFAULT_EMBEDDING_MODELS
63
+ # Combined list for all watsonx models
64
+ WATSONX_MODELS_DETAILED = WATSONX_DEFAULT_LLM_MODELS + WATSONX_DEFAULT_EMBEDDING_MODELS
65
+
27
66
  WATSONX_EMBEDDING_MODEL_NAMES = [metadata["name"] for metadata in WATSONX_DEFAULT_EMBEDDING_MODELS]
28
67
 
29
68
  IBM_WATSONX_URLS = [
@@ -3,6 +3,7 @@ from typing import Any
3
3
 
4
4
  from fastapi import HTTPException
5
5
  from langchain_core.prompts import PromptTemplate
6
+ from langchain_core.prompts.string import mustache_template_vars
6
7
 
7
8
  from lfx.inputs.inputs import DefaultPromptField
8
9
  from lfx.interface.utils import extract_input_variables_from_prompt
@@ -90,7 +91,7 @@ def _check_variable(var, invalid_chars, wrong_variables, empty_variables):
90
91
  def _check_for_errors(input_variables, fixed_variables, wrong_variables, empty_variables) -> None:
91
92
  if any(var for var in input_variables if var not in fixed_variables):
92
93
  error_message = (
93
- f"Error: Input variables contain invalid characters or formats. \n"
94
+ f"Input variables contain invalid characters or formats. \n"
94
95
  f"Invalid variables: {', '.join(wrong_variables)}.\n"
95
96
  f"Empty variables: {', '.join(empty_variables)}. \n"
96
97
  f"Fixed variables: {', '.join(fixed_variables)}."
@@ -122,8 +123,37 @@ def _check_input_variables(input_variables):
122
123
  return fixed_variables
123
124
 
124
125
 
125
- def validate_prompt(prompt_template: str, *, silent_errors: bool = False) -> list[str]:
126
- input_variables = extract_input_variables_from_prompt(prompt_template)
126
+ def validate_prompt(prompt_template: str, *, silent_errors: bool = False, is_mustache: bool = False) -> list[str]:
127
+ if is_mustache:
128
+ # Extract only mustache variables
129
+ try:
130
+ input_variables = mustache_template_vars(prompt_template)
131
+ except Exception as exc:
132
+ # Mustache parser errors are often cryptic (e.g., "unclosed tag at line 1")
133
+ # Provide a more helpful error message
134
+ error_str = str(exc).lower()
135
+ if "unclosed" in error_str or "tag" in error_str:
136
+ msg = "Invalid template syntax. Check that all {{variables}} have matching opening and closing braces."
137
+ else:
138
+ msg = f"Invalid mustache template: {exc}"
139
+ raise ValueError(msg) from exc
140
+
141
+ # Also get f-string variables to filter them out
142
+ fstring_vars = extract_input_variables_from_prompt(prompt_template)
143
+
144
+ # Only keep variables that are actually in mustache syntax (not in f-string syntax)
145
+ # This handles cases where template has both {var} and {{var}}
146
+ input_variables = [v for v in input_variables if v not in fstring_vars or f"{{{{{v}}}}}" in prompt_template]
147
+ else:
148
+ # Extract f-string variables
149
+ input_variables = extract_input_variables_from_prompt(prompt_template)
150
+
151
+ # Also get mustache variables to filter them out
152
+ mustache_vars = mustache_template_vars(prompt_template)
153
+
154
+ # Only keep variables that are NOT in mustache syntax
155
+ # This handles cases where template has both {var} and {{var}}
156
+ input_variables = [v for v in input_variables if v not in mustache_vars]
127
157
 
128
158
  # Check if there are invalid characters in the input_variables
129
159
  input_variables = _check_input_variables(input_variables)
@@ -199,11 +229,16 @@ def update_input_variables_field(input_variables, template) -> None:
199
229
 
200
230
 
201
231
  def process_prompt_template(
202
- template: str, name: str, custom_fields: dict[str, list[str]] | None, frontend_node_template: dict[str, Any]
232
+ template: str,
233
+ name: str,
234
+ custom_fields: dict[str, list[str]] | None,
235
+ frontend_node_template: dict[str, Any],
236
+ *,
237
+ is_mustache: bool = False,
203
238
  ):
204
239
  """Process and validate prompt template, update template and custom fields."""
205
240
  # Validate the prompt template and extract input variables
206
- input_variables = validate_prompt(template)
241
+ input_variables = validate_prompt(template, is_mustache=is_mustache)
207
242
 
208
243
  # Initialize custom_fields if None
209
244
  if custom_fields is None:
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import asyncio
4
4
  import re
5
- from typing import TYPE_CHECKING, Literal
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  import pandas as pd
8
8
  from langchain_core.tools import BaseTool, ToolException
@@ -22,7 +22,6 @@ if TYPE_CHECKING:
22
22
  from lfx.events.event_manager import EventManager
23
23
  from lfx.inputs.inputs import InputTypes
24
24
  from lfx.io import Output
25
- from lfx.schema.content_block import ContentBlock
26
25
  from lfx.schema.dotdict import dotdict
27
26
 
28
27
  TOOL_TYPES_SET = {"Tool", "BaseTool", "StructuredTool"}
@@ -42,15 +41,9 @@ def build_description(component: Component) -> str:
42
41
 
43
42
  async def send_message_noop(
44
43
  message: Message,
45
- text: str | None = None, # noqa: ARG001
46
- background_color: str | None = None, # noqa: ARG001
47
- text_color: str | None = None, # noqa: ARG001
48
- icon: str | None = None, # noqa: ARG001
49
- content_blocks: list[ContentBlock] | None = None, # noqa: ARG001
50
- format_type: Literal["default", "error", "warning", "info"] = "default", # noqa: ARG001
51
44
  id_: str | None = None, # noqa: ARG001
52
45
  *,
53
- allow_markdown: bool = True, # noqa: ARG001
46
+ skip_db_update: bool = False, # noqa: ARG001
54
47
  ) -> Message:
55
48
  """No-op implementation of send_message."""
56
49
  return message
lfx/cli/__init__.py CHANGED
@@ -1,5 +1,13 @@
1
1
  """LFX CLI module for serving flows."""
2
2
 
3
- from lfx.cli.commands import serve_command
4
-
5
3
  __all__ = ["serve_command"]
4
+
5
+
6
+ def __getattr__(name: str):
7
+ """Lazy import for serve_command."""
8
+ if name == "serve_command":
9
+ from lfx.cli.commands import serve_command
10
+
11
+ return serve_command
12
+ msg = f"module {__name__!r} has no attribute {name!r}"
13
+ raise AttributeError(msg)
lfx/cli/commands.py CHANGED
@@ -303,6 +303,9 @@ async def serve_command(
303
303
  console.print()
304
304
 
305
305
  # Start the server
306
+ # Use uvicorn.Server to properly handle async context
307
+ # uvicorn.run() uses asyncio.run() internally which fails when
308
+ # an event loop is already running (due to syncify decorator)
306
309
  try:
307
310
  config = uvicorn.Config(
308
311
  serve_app,