feat: add watsonx component (#7080)

* feat: add watsonx icon

* feat: added watsonx icon export

* feat: add icon to styleUtils

* feat: add watsonx.ai model component

* feat: added watsonx.ai component to init

* fix: icon not correct

* feat: implemented streaming

* feat: added dynamc list for models

* fix: removed model on change url

* chore: removed refresh, not needed anymore

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* chore: ruff formatting

* [autofix.ci] apply automated fixes

* fix: use ChatWatsonx instead of WatsonxLLM

* Add ibm dependencies to pyproject

* feat: added new parameters for chat

* langflow-specific tweaks

* lint

* [autofix.ci] apply automated fixes

* lint starter project

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>
Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com>
This commit is contained in:
galatro 2025-03-24 16:41:01 +01:00 committed by GitHub
commit 0eeb142ecd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 518 additions and 62 deletions

View file

@ -20,6 +20,7 @@ from .openrouter import OpenRouterComponent
from .perplexity import PerplexityComponent
from .sambanova import SambaNovaComponent
from .vertexai import ChatVertexAIComponent
from .watsonx import WatsonxAIComponent
from .xai import XAIModelComponent
__all__ = [
@ -45,5 +46,6 @@ __all__ = [
"PerplexityComponent",
"QianfanChatEndpointComponent",
"SambaNovaComponent",
"WatsonxAIComponent",
"XAIModelComponent",
]

View file

@ -0,0 +1,204 @@
import json
import logging
from typing import Any
import requests
from langchain_ibm import ChatWatsonx
from pydantic.v1 import SecretStr
from langflow.base.models.model import LCModelComponent
from langflow.field_typing import LanguageModel
from langflow.field_typing.range_spec import RangeSpec
from langflow.inputs import BoolInput, DropdownInput, IntInput, SecretStrInput, SliderInput, StrInput
from langflow.schema.dotdict import dotdict
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class WatsonxAIComponent(LCModelComponent):
display_name = "IBM watsonx.ai"
description = "Generate text using IBM watsonx.ai foundation models."
icon = "WatsonxAI"
name = "IBMwatsonxModel"
beta = False
_default_models = ["ibm/granite-3-2b-instruct", "ibm/granite-3-8b-instruct", "ibm/granite-13b-instruct-v2"]
inputs = [
*LCModelComponent._base_inputs,
DropdownInput(
name="url",
display_name="watsonx API Endpoint",
info="The base URL of the API.",
value=None,
options=[
"https://us-south.ml.cloud.ibm.com",
"https://eu-de.ml.cloud.ibm.com",
"https://eu-gb.ml.cloud.ibm.com",
"https://au-syd.ml.cloud.ibm.com",
"https://jp-tok.ml.cloud.ibm.com",
"https://ca-tor.ml.cloud.ibm.com",
],
real_time_refresh=True,
),
StrInput(
name="project_id",
display_name="watsonx Project ID",
),
SecretStrInput(
name="api_key",
display_name="API Key",
info="The API Key to use for the model.",
required=True,
),
DropdownInput(
name="model_name",
display_name="Model Name",
options=[],
value=None,
dynamic=True,
required=True,
),
IntInput(
name="max_tokens",
display_name="Max Tokens",
advanced=True,
info="The maximum number of tokens to generate.",
range_spec=RangeSpec(min=1, max=4096),
value=1000,
),
StrInput(
name="stop_sequence",
display_name="Stop Sequence",
advanced=True,
info="Sequence where generation should stop.",
field_type="str",
),
SliderInput(
name="temperature",
display_name="Temperature",
info="Controls randomness, higher values increase diversity.",
value=0.1,
range_spec=RangeSpec(min=0, max=2, step=0.01),
advanced=True,
),
SliderInput(
name="top_p",
display_name="Top P",
info="The cumulative probability cutoff for token selection. "
"Lower values mean sampling from a smaller, more top-weighted nucleus.",
value=0.9,
range_spec=RangeSpec(min=0, max=1, step=0.01),
advanced=True,
),
SliderInput(
name="frequency_penalty",
display_name="Frequency Penalty",
info="Penalty for frequency of token usage.",
value=0.5,
range_spec=RangeSpec(min=-2.0, max=2.0, step=0.01),
advanced=True,
),
SliderInput(
name="presence_penalty",
display_name="Presence Penalty",
info="Penalty for token presence in prior text.",
value=0.3,
range_spec=RangeSpec(min=-2.0, max=2.0, step=0.01),
advanced=True,
),
IntInput(
name="seed",
display_name="Random Seed",
advanced=True,
info="The random seed for the model.",
value=8,
),
BoolInput(
name="logprobs",
display_name="Log Probabilities",
advanced=True,
info="Whether to return log probabilities of the output tokens.",
value=True,
),
IntInput(
name="top_logprobs",
display_name="Top Log Probabilities",
advanced=True,
info="Number of most likely tokens to return at each position.",
value=3,
range_spec=RangeSpec(min=1, max=20),
),
StrInput(
name="logit_bias",
display_name="Logit Bias",
advanced=True,
info='JSON string of token IDs to bias or suppress (e.g., {"1003": -100, "1004": 100}).',
field_type="str",
),
]
@staticmethod
def fetch_models(base_url: str) -> list[str]:
"""Fetch available models from the watsonx.ai API."""
try:
endpoint = f"{base_url}/ml/v1/foundation_model_specs"
params = {"version": "2024-09-16", "filters": "function_text_chat,!lifecycle_withdrawn"}
response = requests.get(endpoint, params=params, timeout=10)
response.raise_for_status()
data = response.json()
models = [model["model_id"] for model in data.get("resources", [])]
return sorted(models)
except Exception:
logger.exception("Error fetching models. Using default models.")
return WatsonxAIComponent._default_models
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
"""Update model options when URL or API key changes."""
logger.info("Updating build config. Field name: %s, Field value: %s", field_name, field_value)
if field_name == "url" and field_value:
try:
models = self.fetch_models(base_url=build_config.url.value)
build_config.model_name.options = models
if build_config.model_name.value:
build_config.model_name.value = models[0]
info_message = f"Updated model options: {len(models)} models found in {build_config.url.value}"
logger.info(info_message)
except Exception:
logger.exception("Error updating model options.")
def build_model(self) -> LanguageModel:
# Parse logit_bias from JSON string if provided
logit_bias = None
if hasattr(self, "logit_bias") and self.logit_bias:
try:
logit_bias = json.loads(self.logit_bias)
except json.JSONDecodeError:
logger.warning("Invalid logit_bias JSON format. Using default instead.")
logit_bias = {"1003": -100, "1004": -100}
chat_params = {
"max_tokens": getattr(self, "max_tokens", None),
"temperature": getattr(self, "temperature", None),
"top_p": getattr(self, "top_p", None),
"frequency_penalty": getattr(self, "frequency_penalty", None),
"presence_penalty": getattr(self, "presence_penalty", None),
"seed": getattr(self, "seed", None),
"stop": [self.stop_sequence] if self.stop_sequence else [],
"n": 1,
"logprobs": getattr(self, "logprobs", True),
"top_logprobs": getattr(self, "top_logprobs", None),
"time_limit": 600000,
"logit_bias": logit_bias,
}
return ChatWatsonx(
apikey=SecretStr(self.api_key).get_secret_value(),
url=self.url,
project_id=self.project_id,
model_id=self.model_name,
params=chat_params,
streaming=self.stream,
)

View file

@ -9,21 +9,25 @@
"dataType": "ChatInput",
"id": "ChatInput-4lamw",
"name": "message",
"output_types": ["Message"]
"output_types": [
"Message"
]
},
"targetHandle": {
"fieldName": "input_value",
"id": "Agent-I23ZV",
"inputTypes": ["Message"],
"inputTypes": [
"Message"
],
"type": "str"
}
},
"id": "reactflow__edge-ChatInput-4lamw{œdataTypeœ:œChatInputœ,œidœ:œChatInput-4lamwœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-I23ZV{œfieldNameœ:œinput_valueœ,œidœ:œAgent-I23ZVœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
"selected": false,
"source": "ChatInput-4lamw",
"sourceHandle": "{œdataTypeœ:œChatInputœ,œidœ:œChatInput-4lamwœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}",
"sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-4lamwœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}",
"target": "Agent-I23ZV",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-I23ZVœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}"
"targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-I23ZVœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
},
{
"animated": false,
@ -33,21 +37,27 @@
"dataType": "Agent",
"id": "Agent-I23ZV",
"name": "response",
"output_types": ["Message"]
"output_types": [
"Message"
]
},
"targetHandle": {
"fieldName": "input_value",
"id": "ChatOutput-MBTWS",
"inputTypes": ["Data", "DataFrame", "Message"],
"inputTypes": [
"Data",
"DataFrame",
"Message"
],
"type": "str"
}
},
"id": "reactflow__edge-Agent-I23ZV{œdataTypeœ:œAgentœ,œidœ:œAgent-I23ZVœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-MBTWS{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-MBTWSœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}",
"selected": false,
"source": "Agent-I23ZV",
"sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-I23ZVœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}",
"sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-I23ZVœ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}",
"target": "ChatOutput-MBTWS",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-MBTWSœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}"
"targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-MBTWSœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}"
},
{
"data": {
@ -55,20 +65,24 @@
"dataType": "APIRequest",
"id": "APIRequest-zDdGN",
"name": "component_as_tool",
"output_types": ["Tool"]
"output_types": [
"Tool"
]
},
"targetHandle": {
"fieldName": "tools",
"id": "Agent-I23ZV",
"inputTypes": ["Tool"],
"inputTypes": [
"Tool"
],
"type": "other"
}
},
"id": "xy-edge__APIRequest-zDdGN{œdataTypeœ:œAPIRequestœ,œidœ:œAPIRequest-zDdGNœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-I23ZV{œfieldNameœ:œtoolsœ,œidœ:œAgent-I23ZVœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}",
"source": "APIRequest-zDdGN",
"sourceHandle": "{œdataTypeœ:œAPIRequestœ,œidœ:œAPIRequest-zDdGNœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}",
"sourceHandle": "{œdataTypeœ: œAPIRequestœ, œidœ: œAPIRequest-zDdGNœ, œnameœ: œcomponent_as_toolœ, œoutput_typesœ: [œToolœ]}",
"target": "Agent-I23ZV",
"targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgent-I23ZVœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}"
"targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-I23ZVœ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}"
}
],
"nodes": [
@ -76,7 +90,9 @@
"data": {
"id": "ChatInput-4lamw",
"node": {
"base_classes": ["Message"],
"base_classes": [
"Message"
],
"beta": false,
"category": "inputs",
"conditional_paths": [],
@ -113,7 +129,9 @@
"name": "message",
"selected": "Message",
"tool_mode": true,
"types": ["Message"],
"types": [
"Message"
],
"value": "__UNDEFINED__"
}
],
@ -127,7 +145,9 @@
"display_name": "Background Color",
"dynamic": false,
"info": "The background color of the icon.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -148,7 +168,9 @@
"display_name": "Icon",
"dynamic": false,
"info": "The icon of the message.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -256,7 +278,10 @@
"dynamic": false,
"info": "Type of sender.",
"name": "sender",
"options": ["Machine", "User"],
"options": [
"Machine",
"User"
],
"options_metadata": [],
"placeholder": "",
"required": false,
@ -273,7 +298,9 @@
"display_name": "Sender Name",
"dynamic": false,
"info": "Name of the sender.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -294,7 +321,9 @@
"display_name": "Session ID",
"dynamic": false,
"info": "The session ID of the chat. If empty, the current session ID parameter will be used.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -333,7 +362,9 @@
"display_name": "Text Color",
"dynamic": false,
"info": "The text color of the name",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -371,7 +402,9 @@
"data": {
"id": "ChatOutput-MBTWS",
"node": {
"base_classes": ["Message"],
"base_classes": [
"Message"
],
"beta": false,
"category": "outputs",
"conditional_paths": [],
@ -408,7 +441,9 @@
"name": "message",
"selected": "Message",
"tool_mode": true,
"types": ["Message"],
"types": [
"Message"
],
"value": "__UNDEFINED__"
}
],
@ -422,7 +457,9 @@
"display_name": "Background Color",
"dynamic": false,
"info": "The background color of the icon.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -443,7 +480,9 @@
"display_name": "Icon",
"dynamic": false,
"info": "The icon of the message.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -500,7 +539,9 @@
"display_name": "Data Template",
"dynamic": false,
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -521,7 +562,11 @@
"display_name": "Text",
"dynamic": false,
"info": "Message to be passed as output.",
"input_types": ["Data", "DataFrame", "Message"],
"input_types": [
"Data",
"DataFrame",
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -545,7 +590,10 @@
"dynamic": false,
"info": "Type of sender.",
"name": "sender",
"options": ["Machine", "User"],
"options": [
"Machine",
"User"
],
"options_metadata": [],
"placeholder": "",
"required": false,
@ -562,7 +610,9 @@
"display_name": "Sender Name",
"dynamic": false,
"info": "Name of the sender.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -583,7 +633,9 @@
"display_name": "Session ID",
"dynamic": false,
"info": "The session ID of the chat. If empty, the current session ID parameter will be used.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -622,7 +674,9 @@
"display_name": "Text Color",
"dynamic": false,
"info": "The text color of the name",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -744,7 +798,9 @@
"data": {
"id": "Agent-I23ZV",
"node": {
"base_classes": ["Message"],
"base_classes": [
"Message"
],
"beta": false,
"category": "agents",
"conditional_paths": [],
@ -797,7 +853,9 @@
"name": "response",
"selected": "Message",
"tool_mode": true,
"types": ["Message"],
"types": [
"Message"
],
"value": "__UNDEFINED__"
}
],
@ -830,7 +888,9 @@
"display_name": "Agent Description [Deprecated]",
"dynamic": false,
"info": "The description of the agent. This is only used when in Tool Mode. Defaults to 'A helpful assistant with access to the following tools:' and tools are added dynamically. This feature is deprecated and will be removed in future versions.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -912,7 +972,9 @@
"display_name": "OpenAI API Key",
"dynamic": false,
"info": "The OpenAI API Key to use for the OpenAI model.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"load_from_db": true,
"name": "api_key",
"password": true,
@ -965,7 +1027,9 @@
"display_name": "Input",
"dynamic": false,
"info": "The input provided by the user for the agent to process.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -1064,7 +1128,9 @@
"display_name": "External Memory",
"dynamic": false,
"info": "Retrieve messages from an external memory. If empty, it will use the Langflow tables.",
"input_types": ["Memory"],
"input_types": [
"Memory"
],
"list": false,
"list_add_label": "Add More",
"name": "memory",
@ -1169,7 +1235,10 @@
"dynamic": false,
"info": "Order of the messages.",
"name": "order",
"options": ["Ascending", "Descending"],
"options": [
"Ascending",
"Descending"
],
"options_metadata": [],
"placeholder": "",
"required": false,
@ -1207,7 +1276,11 @@
"dynamic": false,
"info": "Filter by sender type.",
"name": "sender",
"options": ["Machine", "User", "Machine and User"],
"options": [
"Machine",
"User",
"Machine and User"
],
"options_metadata": [],
"placeholder": "",
"required": false,
@ -1224,7 +1297,9 @@
"display_name": "Sender Name",
"dynamic": false,
"info": "Filter by sender name.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -1245,7 +1320,9 @@
"display_name": "Session ID",
"dynamic": false,
"info": "The session ID of the chat. If empty, the current session ID parameter will be used.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -1267,7 +1344,9 @@
"display_name": "Agent Instructions",
"dynamic": false,
"info": "System Prompt: Initial instructions and context provided to guide the agent's behavior.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -1318,7 +1397,9 @@
"display_name": "Template",
"dynamic": false,
"info": "The template to use for formatting the data. It can contain the keys {text}, {sender} or any other key in the message data.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -1358,7 +1439,9 @@
"display_name": "Tools",
"dynamic": false,
"info": "These are the tools that the agent can use to help with tasks.",
"input_types": ["Tool"],
"input_types": [
"Tool"
],
"list": true,
"list_add_label": "Add More",
"name": "tools",
@ -1410,7 +1493,10 @@
"data": {
"id": "APIRequest-zDdGN",
"node": {
"base_classes": ["Data", "DataFrame"],
"base_classes": [
"Data",
"DataFrame"
],
"beta": false,
"category": "data",
"conditional_paths": [],
@ -1451,7 +1537,9 @@
"required_inputs": null,
"selected": "Tool",
"tool_mode": true,
"types": ["Tool"],
"types": [
"Tool"
],
"value": "__UNDEFINED__"
}
],
@ -1465,7 +1553,9 @@
"display_name": "Body",
"dynamic": false,
"info": "The body to send with the request as a dictionary (for POST, PATCH, PUT).",
"input_types": ["Data"],
"input_types": [
"Data"
],
"is_list": true,
"list_add_label": "Add More",
"name": "body",
@ -1534,7 +1624,9 @@
"display_name": "cURL",
"dynamic": false,
"info": "Paste a curl command to populate the fields. This will fill in the dictionary fields for headers and body.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": false,
"list_add_label": "Add More",
"load_from_db": false,
@ -1575,7 +1667,9 @@
"display_name": "Headers",
"dynamic": false,
"info": "The headers to send with the request as a dictionary.",
"input_types": ["Data"],
"input_types": [
"Data"
],
"is_list": true,
"list_add_label": "Add More",
"name": "headers",
@ -1648,7 +1742,13 @@
"dynamic": false,
"info": "The HTTP method to use.",
"name": "method",
"options": ["GET", "POST", "PATCH", "PUT", "DELETE"],
"options": [
"GET",
"POST",
"PATCH",
"PUT",
"DELETE"
],
"options_metadata": [],
"placeholder": "",
"real_time_refresh": true,
@ -1666,7 +1766,9 @@
"display_name": "Query Parameters",
"dynamic": false,
"info": "The query parameters to append to the URL.",
"input_types": ["Data"],
"input_types": [
"Data"
],
"list": false,
"list_add_label": "Add More",
"name": "query_params",
@ -1741,7 +1843,10 @@
"description": "Modify tool names and descriptions to help agents understand when to use each tool.",
"field_parsers": {
"commands": "commands",
"name": ["snake_case", "no_blank"]
"name": [
"snake_case",
"no_blank"
]
},
"hide_options": true
},
@ -1812,13 +1917,17 @@
"description": "make_requests() - Make HTTP requests using URLs or cURL commands.",
"name": "APIRequest-make_requests",
"status": true,
"tags": ["APIRequest-make_requests"]
"tags": [
"APIRequest-make_requests"
]
},
{
"description": "as_dataframe() - Make HTTP requests using URLs or cURL commands.",
"name": "APIRequest-as_dataframe",
"status": true,
"tags": ["APIRequest-as_dataframe"]
"tags": [
"APIRequest-as_dataframe"
]
}
]
},
@ -1828,7 +1937,9 @@
"display_name": "URLs",
"dynamic": false,
"info": "Enter one or more URLs, separated by commas.",
"input_types": ["Message"],
"input_types": [
"Message"
],
"list": true,
"list_add_label": "Add More",
"load_from_db": false,
@ -1894,5 +2005,7 @@
"is_component": false,
"last_tested_version": "1.2.0",
"name": "Pokédex Agent",
"tags": ["agents"]
}
"tags": [
"agents"
]
}

View file

@ -86,6 +86,8 @@ dependencies = [
"elevenlabs>=1.54.0",
"webrtcvad>=2.0.10",
"scipy>=1.15.2",
"ibm-watsonx-ai>=1.3.1",
"langchain-ibm>=0.3.8",
]
[dependency-groups]

View file

@ -0,0 +1,21 @@
const SvgWatsonxAI = (props) => (
<svg viewBox="0 0 32 32" width="1em" height="1em" {...props}>
<path d="m26,24c-1.1046,0-2,.8954-2,2,0,.0764.0142.1488.0225.2229-2.2808,1.7963-5.0792,2.7771-8.0225,2.7771-4.2617,0-8-3.9722-8-8.5,0-4.687,3.813-8.5,8.5-8.5h.5v-2h-.5c-5.7896,0-10.5,4.7104-10.5,10.5,0,1.8839.5304,3.6896,1.4371,5.2565-2.7133-2.3843-4.4371-5.869-4.4371-9.7565,0-2.1152.4917-4.1328,1.4619-5.9956l-1.7744-.9238c-1.104,2.1211-1.6875,4.5137-1.6875,6.9194,0,8.271,6.729,15,15,15,3.3744,0,6.5818-1.1193,9.2048-3.1662.244.106.5123.1662.7952.1662,1.1046,0,2-.8954,2-2s-.8954-2-2-2Z" />
<rect
x="11"
y="20"
width="2"
height="2"
transform="translate(33 9) rotate(90)"
/>
<rect
x="19"
y="10"
width="2"
height="2"
transform="translate(31 -9) rotate(90)"
/>
<path d="m16,1c-3.3744,0-6.5818,1.1193-9.2048,3.1662-.244-.106-.5123-.1662-.7952-.1662-1.1046,0-2,.8954-2,2s.8954,2,2,2,2-.8954,2-2c0-.0764-.0142-.1488-.0225-.2229,2.2808-1.7963,5.0792-2.7771,8.0225-2.7771,4.2617,0,8,3.9722,8,8.5,0,4.687-3.813,8.5-8.5,8.5h-.5v2h.5c5.7896,0,10.5-4.7104,10.5-10.5,0-1.8853-.5322-3.6917-1.4401-5.2593,2.715,2.3843,4.4401,5.8704,4.4401,9.7593,0,2.1152-.4917,4.1328-1.4619,5.9956l1.7744.9238c1.104-2.1211,1.6875-4.5137,1.6875-6.9194C31,7.729,24.271,1,16,1Z" />
</svg>
);
export default SvgWatsonxAI;

View file

@ -0,0 +1,9 @@
import React, { forwardRef } from "react";
import SvgWatsonxAI from "./WatsonxAI";
export const WatsonxAiIcon = forwardRef<
SVGSVGElement,
React.PropsWithChildren<{}>
>((props, ref) => {
return <SvgWatsonxAI ref={ref} {...props} />;
});

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="icon" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<defs>
<style>
.cls-1 {
fill: none;
}
</style>
</defs>
<path d="m26,24c-1.1046,0-2,.8954-2,2,0,.0764.0142.1488.0225.2229-2.2808,1.7963-5.0792,2.7771-8.0225,2.7771-4.2617,0-8-3.9722-8-8.5,0-4.687,3.813-8.5,8.5-8.5h.5v-2h-.5c-5.7896,0-10.5,4.7104-10.5,10.5,0,1.8839.5304,3.6896,1.4371,5.2565-2.7133-2.3843-4.4371-5.869-4.4371-9.7565,0-2.1152.4917-4.1328,1.4619-5.9956l-1.7744-.9238c-1.104,2.1211-1.6875,4.5137-1.6875,6.9194,0,8.271,6.729,15,15,15,3.3744,0,6.5818-1.1193,9.2048-3.1662.244.106.5123.1662.7952.1662,1.1046,0,2-.8954,2-2s-.8954-2-2-2Z"/>
<rect x="11" y="20" width="2" height="2" transform="translate(33 9) rotate(90)"/>
<rect x="19" y="10" width="2" height="2" transform="translate(31 -9) rotate(90)"/>
<path d="m16,1c-3.3744,0-6.5818,1.1193-9.2048,3.1662-.244-.106-.5123-.1662-.7952-.1662-1.1046,0-2,.8954-2,2s.8954,2,2,2,2-.8954,2-2c0-.0764-.0142-.1488-.0225-.2229,2.2808-1.7963,5.0792-2.7771,8.0225-2.7771,4.2617,0,8,3.9722,8,8.5,0,4.687-3.813,8.5-8.5,8.5h-.5v2h.5c5.7896,0,10.5-4.7104,10.5-10.5,0-1.8853-.5322-3.6917-1.4401-5.2593,2.715,2.3843,4.4401,5.8704,4.4401,9.7593,0,2.1152-.4917,4.1328-1.4619,5.9956l1.7744.9238c1.104-2.1211,1.6875-4.5137,1.6875-6.9194C31,7.729,24.271,1,16,1Z"/>
<rect id="_Transparent_Rectangle_" data-name="&amp;lt;Transparent Rectangle&amp;gt;" class="cls-1" width="32" height="32"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -296,6 +296,7 @@ import {
import { GroqIcon } from "../icons/Groq";
import { HCDIcon } from "../icons/HCD";
import { HuggingFaceIcon } from "../icons/HuggingFace";
import { WatsonxAiIcon } from "../icons/IBMWatsonx";
import { IFixIcon } from "../icons/IFixIt";
import { IcosaIcon } from "../icons/Icosa";
import { LMStudioIcon } from "../icons/LMStudio";
@ -757,6 +758,7 @@ export const nodeIconsLucide: iconsType = {
VertexAI: VertexAIIcon,
ChatVertexAI: VertexAIIcon,
VertexAIEmbeddings: VertexAIIcon,
WatsonxAI: WatsonxAiIcon,
Share3: ShareIcon,
Share4: Share2Icon,
WikipediaAPIWrapper: SvgWikipedia,