【LangChain】理论及应用实战(6):Tool

本文主要内容参考资料:

LangChain 拥有大量第三方工具。工具是设计用于被模型调用的实用程序:它们的输入旨在由模型生成,输出旨在返回给模型。 每当您希望模型控制代码的某些部分或调用外部API时,都需要工具。

一个工具由以下部分组成:

  • 工具的 名称

  • 工具的 描述

  • 定义工具输入的 JSON schema

  • 一个 函数(可选地,还有该函数的异步变体)。
    在这里插入图片描述

  • Tool:单个工具

  • Tookit:工具集

一、Tool

1.1 Tool的使用

使用内置工具和工具包:https://www.langchain.com.cn/docs/how_to/tools_builtin/

  • 使用工具:load_tools

添加预制工具的方法

from langchain.agents import load_tools
tool_names = [...]
tools = load_tools(tool_names) # 使用load方法

注意:有些tool需要单独设置llm

from langchain.agents import load_tools
tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm) # 在load的时候指定llm
  • 查看有哪些内置的tools:get_all_tool_names
from langchain_community.agent_toolkits.load_tools import get_all_tool_names

tool_names = get_all_tool_names()
print(tool_names)

输出如下:

['sleep', 'wolfram-alpha', 'google-search', 'google-search-results-json', 'searx-search-results-json', 'bing-search', 'metaphor-search', 'ddg-search', 'google-books', 'google-lens', 'google-serper', 'google-scholar', 'google-finance', 'google-trends', 'google-jobs', 'google-serper-results-json', 'searchapi', 'searchapi-results-json', 'serpapi', 'dalle-image-generator', 'twilio', 'searx-search', 'merriam-webster', 'wikipedia', 'arxiv', 'golden-query', 'pubmed', 'human', 'awslambda', 'stackexchange', 'sceneXplain', 'graphql', 'openweathermap-api', 'dataforseo-api-search', 'dataforseo-api-search-json', 'eleven_labs_text2speech', 'google_cloud_texttospeech', 'read_file', 'reddit_search', 'news-api', 'tmdb-api', 'podcast-api', 'memorize', 'llm-math', 'open-meteo-api', 'requests', 'requests_get', 'requests_post', 'requests_patch', 'requests_put', 'requests_delete', 'terminal']

1.2 常见的Tool

(1)SerpAPI:最常见的聚合搜索引擎

from langchain.utilities import SerpAPIWrapper
import os
os.environ["SERP_API_KEY"] = "xxxxxxxxxx"

search = SerpAPIWrapper()

search.run("Obama's first name?")

支持自定义参数,比如将搜索引擎切换到Bing,设置搜索语言等:

params = {
    "engine": "bing",
    "gl": "us",
    "hl": "en",
}

search = SerpAPIWrapper(params=params)

(2)Dall-E

Dall-E是OpenAI出品的文到图AI大模型。

pip install opencv-python scikit-image

示例代码如下:

from langchain.chat_models import ChatOpenAI
from langchain.agents import initialize_agent, load_tools

# Dall-E 需要配合大模型一起使用
llm = ChatOpenAI(
    temperature=0,
    model="gpt-4"
)

tools = load_tools([["dalle-image-generator"]])
agent = initialize_agent(
    tools,
    llm,
    agent="zero-shot-react-description",
    verbose=True
)

output = agent.run("Create an image of the halloween night")

(3)Eleven Labs Text2Speech

Eleven Labs是非常优秀的text到语言转换API,官网地址:https://elevenlabs.io/

pip intsall elevenlabs
pip install pydantic
from langchain.tools import ElevenLabsText2SpeechTool

text_to_speak = "Hello! 你好! Hola! 呷呷! Bonjour! こんにちは! 山のつきれい ! どしもがく!!"
tts = ElevenLabsText2SpeechTool(
    voice="Bella",
    text_to_speak=text_to_speak,
    verbose=True
)

# 生成语音文件后再播放
speech_file = tts.run(text_to_speak)
tts.play(speech_file )

# 边生成语言文件边播放
tts.stream_speech(text_to_speak)  # 流式输出

(4)GraphQL

一种API查询语言,类似SQL。

pip install httpx gql > /dev/null
pip install gql
pip install requests_toolbelt

代码示例:

from langchain.chat_models import ChatOpenAI
from langchain.agents import load_tools, initialize_agent, AgentType
from langchain.utils import GraphQLAPIWrapper

llm = ChatOpenAI(
    temperature=0,
    model="gpt-4",
)

tools = load_tools(
    ["graphql"],
    graphql_endpoint="https://swapi-graphql.netlify.app/.netlify/functions/it"
)

agent = initialize_agent(
    tools, 
    llm, 
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, 
    verbose=True
)

graphqlfields = """allFilms {
    films {
        title
        director
        releaseDate
        speciesConnection {
            species {
                name
                classification
                homeworld {
                    name
                }
            }
        }
    }
}
"""

suffix = "Search for the titles of all the star wars films stored in the graph"

agent.run(suffix + graphql_fields)

二、Toolkit

Toolkit 是 LangChain 已经封装好的一系列工具,一个工具包是一组工具来组合完成特定的任务。

所有工具包都暴露一个 get_tools 方法,该方法返回工具列表。

2.1 Azure 认知服务

Azure 认知服务官网:https://portal.azure.com/#allservices

  • AzureCogsFormRecognizerTool:从文档里提取文本
  • AzureCogsSpeech2TextTool:语音到文本
  • AzureCogsText2SpeechTool:文本到语音

首先安装依赖包:

pip install --upgrade azure-ai-formrecognizer > /dev/null
pip install --upgrade azure-cognitiveservices-speech > /dev/null
pip install azure-ai-textanalytics

示例代码:

from langchain.chat_models import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
from langchain.agents.agent_toolkits import AzureCognitiveServicesToolkit
import os

os.environ["AZURE_COGS_KEY"] = "9ea5fcee55fd4278821a38eaca652ac7"
os.environ["AZURE_COGS_ENDPOINT"] = "https://westus2.api.cognitive.microsoft"
os.environ["AZURE_COGS_REGION"] = "westus2"

# 创建 toolkit
toolkit = AzureCognitiveServicesToolkit()

# agent使用
llm = ChatOpenAI(temperature=0, model="gpt-4-1106-preview")
agent = initialize_agent(
    tools=toolkit.get_tools(),
    llm=llm,
    agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
)

audio_file = agent.run("Tell me a joke and read it out for me.")

查看工具集中包含哪些工具:

toolkit = AzureCognitiveServicesToolkit()
[tool.name for tool in toolkit.get_tools()]

输出如下:

[‘azure_cognitive_services_form_recognizer’,
‘azure_cognitive_services_speech2text’,
‘azure_cognitive_services_text2speech’,
‘azure_cognitive_services_text_analytics_health’]

2.2 Python 代码机器人

一个Python代码机器人,将自然语言转换为Python代码。

安装依赖包:

pip install langchain_experimental

示例代码:

agent_executor = create_python_agent(
    llm=ChatOpenAI(temperature=0, model="gpt-4-1106-preview"),
    tool=PythonREPLTool(),
    verbose=True,
    agent_type=AgentType.OPENAI_FUNCTIONS,
    agent_executor_kwargs={"handle_parsing_errors": True},
)

agent_executor.run("What is the 10th fibonacci number?")

2.3 SQLDataBase 数据库查询

使用 SQLDatabaseChain构建Agent,用来根据数据库来回答一般的问题。

from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.sql_database import SQLDatabase
from langchain.lms.openai import OpenAI
from langchain.agents import AgentExecutor
from langchain.agents.agent_types import AgentType
from langchain.chat_models import ChatOpenAI

db = SQLDatabase.from_uri("sqlite:///Chinook.db")
toolkit = SQLDatabaseToolkit(db=db, llm=OpenAI(temperature=0))

agent_executor = create_sql_agent(
    llm=ChatOpenAI(temperature=0, model="gpt-4-1106-preview"),
    toolkit=toolkit,
    verbose=True,
    agent_type=AgentType.OPENAI_FUNCTIONS
)

agent_executor.run("Describe the PlayList table")

也可以用自然语言运行SQL查询:

agent_executor.run("List the total sales per country, which country's customers spent the most?")

三、自定义Tool

如何创建工具:https://www.langchain.com.cn/docs/how_to/custom_tools/

在构建 Agent 时,需要提供一个它可以使用的 Tool 列表。除了被调用的实际函数外,Tool 由几个组件组成:

LangChain 支持从以下内容创建工具:

  1. 函数;
  2. LangChain 运行接口;
  3. 通过从 BaseTool 子类化 – 这是最灵活的方法,它提供了最大的控制程度,但需要更多的努力和代码。

从函数创建工具可能足以满足大多数用例,可以通过简单的 @tool 装饰器 来完成。如果需要更多配置,例如同时指定同步和异步实现,也可以使用 StructuredTool.from_function 类方法。

3.1 从函数创建工具

(1)@tool 装饰器:基于 @tool 装饰器是定义自定义工具的最简单方法。默认情况下,装饰器使用函数名称作为工具名称,但可以通过将字符串作为第一个参数传递来覆盖。此外,装饰器将使用函数的文档字符串作为工具的描述 - 因此必须提供文档字符串。

from langchain_core.tools import tool


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


# Let's inspect some of the attributes associated with the tool.
print(multiply.name)
print(multiply.description)
print(multiply.args)

输出如下:

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

(2)结构化工具
StructuredTool.from_function 类方法提供比 @tool 装饰器更多的可配置性,而无需太多额外代码。

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

3.2 从可运行对象创建工具

接受字符串或 dict 输入的 LangChain Runnables 可以使用 as_tool 方法转换为工具,该方法允许为参数指定名称、描述和其他模式信息。

示例用法:

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}.")]
)

# Placeholder 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."
)
as_tool.args

3.3 子类化 BaseTool

可以通过从 BaseTool 子类化来定义自定义工具。这提供了对工具定义的最大控制,但需要编写更多代码。

from typing import Optional, Type

from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.tools import BaseTool
from pydantic import BaseModel


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


# Note: It's important that every field has type hints. BaseTool is a
# Pydantic class and not having type hints can lead to unexpected behavior.
class CustomCalculatorTool(BaseTool):
    name: str = "Calculator"
    description: str = "useful for when you need to answer questions about math"
    args_schema: Type[BaseModel] = CalculatorInput
    return_direct: bool = True

    def _run(
        self, a: int, b: int, run_manager: Optional[CallbackManagerForToolRun] = None
    ) -> str:
        """Use the tool."""
        return a * b

    async def _arun(
        self,
        a: int,
        b: int,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool asynchronously."""
        # If the calculation is cheap, you can just delegate to the sync implementation
        # as shown below.
        # If the sync calculation is expensive, you should delete the entire _arun method.
        # LangChain will automatically provide a better implementation that will
        # kick off the task in a thread to make sure it doesn't block other async code.
        return self._run(a, b, run_manager=run_manager.get_sync())
multiply = CustomCalculatorTool()
print(multiply.name)
print(multiply.description)
print(multiply.args)
print(multiply.return_direct)

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

输出如下:

Calculator
useful for when you need to answer questions about math
{'a': {'description': 'first number', 'title': 'A', 'type': 'integer'}, 'b': {'description': 'second number', 'title': 'B', 'type': 'integer'}}
True
6
6

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值