1. langchain中的tool使用 (How to create tools)

本教程将介绍如何使用 LangChain 库中的工具(Tool)功能。通过一系列示例代码,我们将展示如何定义、使用和扩展工具。

1. 定义简单的工具

首先,我们从定义一个简单的乘法工具开始。

from langchain_core.tools import tool

@tool
def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

# 查看工具的属性
print(multiply.name)
print(multiply.description)
print(multiply.args)

输出:

multiply
Multiply two numbers.
{'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}

解释

  • @tool 装饰器用于将函数定义为一个工具。
  • multiply 函数接受两个整数参数 ab,返回它们的乘积。
  • 通过打印工具的属性,我们可以看到工具的名称、描述和参数信息。

2. 定义异步工具

接下来,我们定义一个异步的乘法工具。

from langchain_core.tools import tool

@tool
async def amultiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

解释

  • 使用 async 关键字定义异步函数 amultiply
  • 其他部分与同步工具定义相同。

3. 使用注解定义工具参数

我们可以使用注解来更详细地描述工具的参数。

from typing import Annotated, List

@tool
def multiply_by_max(
    a: Annotated[str, "scale factor"],
    b: Annotated[List[int], "list of ints over which to take maximum"],
) -> int:
    """Multiply a by the maximum of b."""
    return a * max(b)

print(multiply_by_max.args_schema.schema())

输出:

{'description': 'Multiply a by the maximum of b.',
 'properties': {'a': {'description': 'scale factor',
   'title': 'A',
   'type': 'string'},
  'b': {'description': 'list of ints over which to take maximum',
   'items': {'type': 'integer'},
   'title': 'B',
   'type': 'array'}},
 'required': ['a', 'b'],
 'title': 'multiply_by_max',
 'type': 'object'}

解释

  • 使用 Annotated 类型注解来添加参数的描述。
  • multiply_by_max 函数接受一个字符串 a 和一个整数列表 b,返回 ab 中最大值的乘积。
  • 通过打印参数模式(schema),我们可以看到详细的参数描述。

4. 使用 Pydantic 定义工具参数

我们可以使用 Pydantic 库来更严格地定义工具的参数。

from pydantic import BaseModel, Field

class CalculatorInput(BaseModel):
    a: int = Field(description="first number")
    b: int = Field(description="second number")

@tool("multiplication-tool", args_schema=CalculatorInput, return_direct=True)
def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

# 查看工具的属性
print(multiply.name)
print(multiply.description)
print(multiply.args)
print(multiply.return_direct)

输出:

multiplication-tool
Multiply two numbers.
{'a': {'description': 'first number', 'title': 'A', 'type': 'integer'}, 'b': {'description': 'second number', 'title': 'B', 'type': 'integer'}}
True

解释

  • 使用 Pydantic 的 BaseModelField 来定义参数模型 CalculatorInput
  • multiply 工具使用 CalculatorInput 作为参数模式,并设置 return_direct=True 表示直接返回结果。
  • 通过打印工具的属性,我们可以看到详细的工具信息。

5. 自动解析文档字符串

我们可以让 LangChain 自动解析函数的文档字符串来生成参数模式。

@tool(parse_docstring=True)
def foo(bar: str, baz: int) -> str:
    """The foo.

    Args:
        bar: The bar.
        baz: The baz.
    """
    return bar

print(foo.args_schema.schema())

输出:

{'description': 'The foo.',
 'properties': {'bar': {'description': 'The bar.',
   'title': 'Bar',
   'type': 'string'},
  'baz': {'description': 'The baz.', 'title': 'Baz', 'type': 'integer'}},
 'required': ['bar', 'baz'],
 'title': 'foo',
 'type': 'object'}

解释

  • 使用 parse_docstring=True 参数,LangChain 会自动解析函数的文档字符串来生成参数模式。
  • foo 函数接受一个字符串 bar 和一个整数 baz,返回 bar

6. 使用 StructuredTool

我们可以使用 StructuredTool 来创建工具实例。

from langchain_core.tools import StructuredTool

def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

async def amultiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

calculator = StructuredTool.from_function(func=multiply, coroutine=amultiply)

print(calculator.invoke({"a": 2, "b": 3}))
print(await calculator.ainvoke({"a": 2, "b": 5}))

输出:

6
10

解释

  • StructuredTool.from_function 方法用于从同步和异步函数创建工具实例。
  • invoke 方法用于同步调用工具,ainvoke 方法用于异步调用工具。

7. 自定义工具

我们可以自定义工具类。

class CalculatorInput(BaseModel):
    a: int = Field(description="first number")
    b: int = Field(description="second number")

def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

calculator = StructuredTool.from_function(
    func=multiply,
    name="Calculator",
    description="multiply numbers",
    args_schema=CalculatorInput,
    return_direct=True,
)

print(calculator.invoke({"a": 2, "b": 3}))
print(calculator.name)
print(calculator.description)
print(calculator.args)

输出:

6
Calculator
multiply numbers
{'a': {'description': 'first number', 'title': 'A', 'type': 'integer'}, 'b': {'description': 'second number', 'title': 'B', 'type': 'integer'}}

解释

  • 使用 StructuredTool.from_function 方法创建自定义工具实例。
  • 可以指定工具的名称、描述、参数模式和是否直接返回结果。

8. 将链式调用转换为工具

我们可以将链式调用转换为工具。

from langchain_core.language_models import GenericFakeChatModel
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages(
    [("human", "Hello. Please respond in the style of {answer_style}.")]
)

# 占位符 LLM
llm = GenericFakeChatModel(messages=iter(["hello matey"]))

chain = prompt | llm | StrOutputParser()

as_tool = chain.as_tool(
    name="Style responder", description="Description of when to use tool."
)

print(as_tool.args)

输出:

{'answer_style': {'title': 'Answer Style', 'type': 'string'}}

解释

  • 使用 ChatPromptTemplate 创建提示模板。
  • 使用 GenericFakeChatModel 作为占位符语言模型。
  • 将提示模板、语言模型和输出解析器链式调用,并转换为工具。

9. 处理工具错误

我们可以定义工具错误处理。

def get_weather(city: str) -> int:
    """Get weather for the given city."""
    raise ToolException(f"Error: There is no city by the name of {city}.")

get_weather_tool = StructuredTool.from_function(
    func=get_weather,
    handle_tool_error=True,
)

print(get_weather_tool.invoke({"city": "foobar"}))

输出:

Error: There is no city by the name of foobar.

解释

  • get_weather 函数抛出 ToolException
  • 使用 handle_tool_error=True 参数,工具会自动处理错误并返回错误信息。

10. 自定义错误信息

我们可以自定义工具错误信息。

get_weather_tool = StructuredTool.from_function(
    func=get_weather,
    handle_tool_error="There is no such city, but it's probably above 0K there!",
)

print(get_weather_tool.invoke({"city": "foobar"}))

输出:

"There is no such city, but it's probably above 0K there!"

解释

  • 使用 handle_tool_error 参数自定义错误信息。

11. 生成随机数工具

我们可以定义生成随机数的工具。

import random
from typing import List, Tuple

@tool(response_format="content_and_artifact")
def generate_random_ints(min: int, max: int, size: int) -> Tuple[str, List[int]]:
    """Generate size random ints in the range [min, max]."""
    array = [random.randint(min, max) for _ in range(size)]
    content = f"Successfully generated array of {size} random ints in [{min}, {max}]."
    return content, array

print(generate_random_ints.invoke({"min": 0, "max": 9, "size": 10}))

输出:

'Successfully generated array of 10 random ints in [0, 9].'

解释

  • generate_random_ints 函数生成指定范围内的随机整数列表。
  • 使用 response_format="content_and_artifact" 参数,工具返回内容和结果列表。

12. 带有工具调用的生成随机数

我们可以使用工具调用格式生成随机数。

print(generate_random_ints.invoke(
    {
        "name": "generate_random_ints",
        "args": {"min": 0, "max": 9, "size": 10},
        "id": "123",  # required
        "type": "tool_call",  # required
    }
))

输出:

ToolMessage(content='Successfully generated array of 10 random ints in [0, 9].', name='generate_random_ints', tool_call_id='123', artifact=[0, 4, 2, 7, 4, 3, 1, 7, 5, 1])

解释

  • 使用工具调用格式,工具返回 ToolMessage 对象,包含内容和结果列表。

13. 生成随机浮点数工具

我们可以定义生成随机浮点数的工具。

from langchain_core.tools import BaseTool

class GenerateRandomFloats(BaseTool):
    name: str = "generate_random_floats"
    description: str = "Generate size random floats in the range [min, max]."
    response_format: str = "content_and_artifact"

    ndigits: int = 2

    def _run(self, min: float, max: float, size: int) -> Tuple[str, List[float]]:
        range_ = max - min
        array = [
            round(min + (range_ * random.random()), ndigits=self.ndigits)
            for _ in range(size)
        ]
        content = f"Generated {size} floats in [{min}, {max}], rounded to {self.ndigits} decimals."
        return content, array

rand_gen = GenerateRandomFloats(ndigits=4)

print(rand_gen.invoke(
    {
        "name": "generate_random_floats",
        "args": {"min": 0.1, "max": 3.3333, "size": 3},
        "id": "123",
        "type": "tool_call",
    }
))

输出:

ToolMessage(content='Generated 3 floats in [0.1, 3.3333], rounded to 4 decimals.', name='generate_random_floats', tool_call_id='123', artifact=[2.033, 2.6058, 2.5919])

解释

  • GenerateRandomFloats 类定义了一个生成随机浮点数的工具。
  • 使用 _run 方法实现工具的逻辑。
  • 通过工具调用格式,返回 ToolMessage 对象,包含内容和结果列表。

通过以上示例,我们展示了如何使用 LangChain 库中的工具功能,包括定义工具、使用注解和 Pydantic、处理错误、生成随机数等。希望这些示例能帮助你更好地理解和应用 LangChain 工具。

参考链接:https://python.langchain.com/docs/how_to/custom_tools/

Hydra is a popular tool used for performing brute force attacks against various network services. However, it should be noted that using Hydra to perform attacks against an Oracle database without proper authorization is illegal and can result in severe legal consequences. Assuming you have proper authorization to perform security testing on an Oracle database, here are the steps to use Hydra against it: 1. Install Hydra: Hydra is available for most Linux distributions and can be installed using the package manager. For example, on Ubuntu, you can install Hydra using the following command: `sudo apt-get install hydra`. 2. Identify the Oracle database service: You need to identify the Oracle database service that you want to attack. The default port for Oracle databases is 1521, and the service name is usually "ORCL". 3. Create a password list: Hydra works by trying a list of passwords against a target service. You need to create a list of passwords that you want to try. You can use tools like Crunch or Cewl to generate custom wordlists. 4. Run Hydra: Once you have the target service and password list, you can run Hydra using the following command: `hydra -L <username_list> -P <password_list> <ip_address> -s <port> oracle`. For example, if the target IP address is 192.168.1.100, the port is 1521, and the username list and password list are "usernames.txt" and "passwords.txt", respectively, the command would be: `hydra -L usernames.txt -P passwords.txt 192.168.1.100 -s 1521 oracle`. It's important to note that using Hydra to perform unauthorized attacks against any system or service is illegal and can result in serious legal consequences. Always make sure you have proper authorization before performing any security testing.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值