You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_langchain_tools.py 4.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import logging
  2. from typing import Optional, Type, cast
  3. import pytest
  4. from autogen_core import CancellationToken
  5. from autogen_core.tools import Tool
  6. from autogen_ext.tools.langchain import LangChainToolAdapter # type: ignore
  7. from langchain_core.callbacks.manager import AsyncCallbackManagerForToolRun, CallbackManagerForToolRun
  8. from langchain_core.tools import BaseTool as LangChainTool
  9. from langchain_core.tools import tool # pyright: ignore
  10. from pydantic import BaseModel, Field
  11. @tool # type: ignore
  12. def add(a: int, b: int) -> int:
  13. """Add two numbers"""
  14. return a + b
  15. class CalculatorInput(BaseModel):
  16. a: int = Field(description="first number")
  17. b: int = Field(description="second number")
  18. class CustomCalculatorTool(LangChainTool):
  19. name: str = "Calculator"
  20. description: str = "useful for when you need to answer questions about math"
  21. args_schema: Type[BaseModel] = CalculatorInput
  22. return_direct: bool = True
  23. def _run(self, a: int, b: int, run_manager: Optional[CallbackManagerForToolRun] = None) -> int:
  24. """Use the tool."""
  25. return a * b
  26. async def _arun(
  27. self,
  28. a: int,
  29. b: int,
  30. run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
  31. ) -> int:
  32. """Use the tool asynchronously."""
  33. return self._run(a, b, run_manager=run_manager.get_sync() if run_manager else None)
  34. @pytest.mark.asyncio
  35. async def test_langchain_tool_adapter(caplog: pytest.LogCaptureFixture) -> None:
  36. # Create a LangChain tool
  37. langchain_tool = add # type: ignore
  38. # Create an adapter
  39. adapter = cast(Tool, LangChainToolAdapter(langchain_tool)) # type: ignore
  40. # Test schema generation
  41. schema = adapter.schema
  42. assert schema["name"] == "add"
  43. assert "description" in schema
  44. assert schema["description"] == "Add two numbers"
  45. assert "parameters" in schema
  46. assert schema["parameters"]["type"] == "object"
  47. assert "properties" in schema["parameters"]
  48. assert "a" in schema["parameters"]["properties"]
  49. assert "b" in schema["parameters"]["properties"]
  50. assert schema["parameters"]["properties"]["a"]["type"] == "integer"
  51. assert schema["parameters"]["properties"]["b"]["type"] == "integer"
  52. assert "required" in schema["parameters"]
  53. assert set(schema["parameters"]["required"]) == {"a", "b"}
  54. assert len(schema["parameters"]["properties"]) == 2
  55. # Check log.
  56. with caplog.at_level(logging.INFO):
  57. # Test run method
  58. result = await adapter.run_json({"a": 2, "b": 3}, CancellationToken())
  59. assert result == 5
  60. assert str(result) in caplog.text
  61. # Test that the adapter's run method can be called multiple times
  62. result = await adapter.run_json({"a": 5, "b": 7}, CancellationToken())
  63. assert result == 12
  64. # Test CustomCalculatorTool
  65. custom_langchain_tool = CustomCalculatorTool()
  66. custom_adapter = LangChainToolAdapter(custom_langchain_tool) # type: ignore
  67. # Test schema generation for CustomCalculatorTool
  68. custom_schema = custom_adapter.schema
  69. assert custom_schema["name"] == "Calculator"
  70. assert custom_schema["description"] == "useful for when you need to answer questions about math" # type: ignore
  71. assert "parameters" in custom_schema
  72. assert custom_schema["parameters"]["type"] == "object"
  73. assert "properties" in custom_schema["parameters"]
  74. assert "a" in custom_schema["parameters"]["properties"]
  75. assert "b" in custom_schema["parameters"]["properties"]
  76. assert custom_schema["parameters"]["properties"]["a"]["type"] == "integer"
  77. assert custom_schema["parameters"]["properties"]["b"]["type"] == "integer"
  78. assert "required" in custom_schema["parameters"]
  79. assert set(custom_schema["parameters"]["required"]) == {"a", "b"}
  80. # Test run method for CustomCalculatorTool
  81. custom_result = await custom_adapter.run_json({"a": 3, "b": 4}, CancellationToken())
  82. assert custom_result == 12