diff --git a/libs/ibm/langchain_ibm/chat_models.py b/libs/ibm/langchain_ibm/chat_models.py index 8271554..450763d 100644 --- a/libs/ibm/langchain_ibm/chat_models.py +++ b/libs/ibm/langchain_ibm/chat_models.py @@ -1,5 +1,6 @@ """IBM watsonx.ai chat wrapper.""" +import ast import hashlib import json import logging @@ -90,6 +91,35 @@ logger = logging.getLogger(__name__) +def normalize_tool_arguments(args_str: str) -> str: + """Ensure arguments is always a proper JSON string. + + Handles: + - JSON string + - Python dict string + - Extra wrapping quotes like '"{...}"' + Args: + args_str: tool call args_str. + + Returns: + The LangChain tool call arguments args_str. + """ + # Try to parse as JSON + try: + parsed = json.loads(args_str) + except json.JSONDecodeError: + pass + else: + if isinstance(parsed, str): + json.loads(parsed) + return parsed + return args_str + + # Try Python literal (e.g., "{'a': 1}") + obj: Any = ast.literal_eval(args_str) + return json.dumps(obj, ensure_ascii=False) + + def _convert_dict_to_message(_dict: Mapping[str, Any], call_id: str) -> BaseMessage: """Convert a dictionary to a LangChain message. @@ -117,6 +147,13 @@ def _convert_dict_to_message(_dict: Mapping[str, Any], call_id: str) -> BaseMess if raw_tool_calls := _dict.get("tool_calls"): additional_kwargs["tool_calls"] = raw_tool_calls for raw_tool_call in raw_tool_calls: + ## Code change to support langgraph with A2A and graph.astream. + if "function" in raw_tool_call: + func = raw_tool_call.get("function", {}) + if "arguments" in func: + raw_args = raw_tool_call["function"]["arguments"] + json_args_str = normalize_tool_arguments(raw_args) + raw_tool_call["function"]["arguments"] = json_args_str try: tool_calls.append(parse_tool_call(raw_tool_call, return_id=True)) except Exception as e: diff --git a/libs/ibm/pyproject.toml b/libs/ibm/pyproject.toml index 32dff52..a83bd60 100644 --- a/libs/ibm/pyproject.toml +++ b/libs/ibm/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "pdm.backend" [project] name = "langchain-ibm" -version = "0.3.19.dev1" +version = "0.3.20" description = "An integration package connecting IBM watsonx.ai and LangChain" authors = [{ name = "IBM" }] license = { text = "MIT" } diff --git a/libs/ibm/tests/integration_tests/test_embeddings.py b/libs/ibm/tests/integration_tests/test_embeddings.py index 31fa4e6..53d2d00 100644 --- a/libs/ibm/tests/integration_tests/test_embeddings.py +++ b/libs/ibm/tests/integration_tests/test_embeddings.py @@ -15,7 +15,7 @@ WX_PROJECT_ID = os.environ.get("WATSONX_PROJECT_ID", "") URL = "https://us-south.ml.cloud.ibm.com" -MODEL_ID = "ibm/slate-125m-english-rtrvr" +MODEL_ID = "ibm/slate-125m-english-rtrvr-v2" DOCUMENTS = ["What is a generative ai?", "What is a loan and how does it works?"] diff --git a/libs/ibm/tests/integration_tests/test_embeddings_standard.py b/libs/ibm/tests/integration_tests/test_embeddings_standard.py index 5f199a1..f6fabe9 100644 --- a/libs/ibm/tests/integration_tests/test_embeddings_standard.py +++ b/libs/ibm/tests/integration_tests/test_embeddings_standard.py @@ -9,7 +9,7 @@ URL = "https://us-south.ml.cloud.ibm.com" -MODEL_ID = "ibm/granite-embedding-107m-multilingual" +MODEL_ID = "ibm/granite-embedding-278m-multilingual" class TestWatsonxEmbeddingsStandard(EmbeddingsIntegrationTests): diff --git a/libs/ibm/tests/integration_tests/test_rerank.py b/libs/ibm/tests/integration_tests/test_rerank.py index 0c5dbb2..3843bad 100644 --- a/libs/ibm/tests/integration_tests/test_rerank.py +++ b/libs/ibm/tests/integration_tests/test_rerank.py @@ -14,7 +14,7 @@ URL = "https://us-south.ml.cloud.ibm.com" -MODEL_ID = "ibm/slate-125m-english-rtrvr" +MODEL_ID = "ibm/slate-125m-english-rtrvr-v2" def test_01_rerank_init() -> None: @@ -47,7 +47,7 @@ def test_02_rerank_documents() -> None: def test_02_rerank_documents_with_params() -> None: - params = RerankParameters(truncate_input_tokens=1) + params = RerankParameters(truncate_input_tokens=2) test_documents = [ Document(page_content="This is a test document."), ] diff --git a/libs/ibm/uv.lock b/libs/ibm/uv.lock index 482f231..695bd07 100644 --- a/libs/ibm/uv.lock +++ b/libs/ibm/uv.lock @@ -428,7 +428,7 @@ wheels = [ [[package]] name = "langchain-ibm" -version = "0.3.19.dev1" +version = "0.3.20" source = { editable = "." } dependencies = [ { name = "ibm-watsonx-ai", version = "1.3.42", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },