在 Python 通过 watsonx.ai 调用 Granite-3.0-8B-Instruct 模型,实现 LangChain 工具调用

作者

Anna Gutowska

AI Engineer, Developer Advocate

IBM

在本教程中,我们将为 ReAct 智能体使用预构建的 LangChain 工具,以展示其为每个工具区分适当用例的能力。我们将主要使用开源 LangChain Python 包。

什么是工具调用?

工具调用,也称为函数调用,是允许人工智能 (AI) 智能体执行需要最新信息的特定任务的接口,否则经过训练的大型语言模型 (LLM) 无法使用。LLM 如 IBM Granite 模型或 OpenAI 的 GPT(生成式预训练转换器)模型仅能访问用于训练的数据。通过 LangChain 可以访问许多默认工具,包括用于处理 SQL 数据库查询、访问维基百科信息等的工具。我们鼓励您阅读 LangChain 文档 ,获取预构建工具的完整列表。

自定义工具可以通过各种方法定义,包括使用 @tool 装饰器或 LangChain Runnables,我们将在本教程中介绍这些方法。可以使用 StructuredTool 或 BaseTool 类创建异步工具。有关每种方法之间的区别,我们鼓励您参考官方 LangChain 文档。有关自定义工具的示例,请参阅 IBM 函数调用教程 。

我们建议您查看 AI 智能体阅读解释器 ,以获取关于各种 AI 智能体类型及其与传统 LLM 聊天机器人差异的详细信息。

先决条件

您需要一个  IBM Cloud 帐户

步骤

第 1 步:设置环境

虽然您可以选择多种工具,本教程将引导您如何设置 IBM 帐户以使用 Jupyter Notebook。

  1. 使用您的 IBM Cloud 帐户登录 watsonx.ai 。

  2. 创建  watsonx.ai 项目

    您可以从项目内部获取项目 ID。点击 管理 选项卡。然后,从 常规 页面的 详细信息 部分复制项目 ID。您需要此 ID 来完成本教程。

  3. 创建一个 Jupyter Notebook

    此步骤将打开 Jupyter Notebook 环境,您可以在其中复制本教程中的代码。或者,您可以将此笔记本下载到本地系统并将其作为资产上传到您的 watsonx.ai 项目。要查看更多 Granite 教程,请访问  IBM Granite 社区 。本教程也可在 Github 上找到。

第 2 步:设置 watsonx.ai 运行时实例和 API 密钥

  1. 创建一个 watsonx.ai 运行时 服务实例(选择适当的区域并选择精简计划,这是一个免费实例)。

  2. 生成  API 密钥

  3. 将 watsonx.ai 运行时服务实例与您在 watsonx.ai 中创建的项目关联。

第 3 步:安装并导入相关库,并设置您的凭据

本教程需要一些库和模块。请确保导入以下内容;如果尚未安装,可以通过快速的 pip 安装来解决。LangChain 和 LangGraph 将是使用的框架和开发人员工具包。

注意 :本教程使用 Python 3.11.9 构建,也与使用 Python 3.10.12 的 Google Colab 兼容。要检查您的 Python 版本,您可以在代码单元中运行 !python --version  命令。

#installations
!pip install -q langchain \
    "langchain_community<0.3.0" \
    langgraph \
    youtube_search \
    pyowm \
    ionic-langchain \
    python-dotenv

!pip install -qU langchain-ibm
#imports
import os

from langchain_ibm import ChatWatsonx
from langgraph.prebuilt import create_react_agent
from langchain_core.tools import Tool
from langchain_core.messages import HumanMessage
from langchain_community.tools import YouTubeSearchTool
from langchain_community.utilities import OpenWeatherMapAPIWrapper
from ionic_langchain.tool import IonicTool
from dotenv import load_dotenv

load_dotenv(os.getcwd()+"/.env", override=True)

为了设置凭据,我们需要您在第 1 步中生成的 WATSONX_APIKEY 和 WATSONX_PROJECT_ID 。您可以将它们存储在目录中的 .env 文件中,也可以替换占位符文本。我们还将设置作为 API 端点的 URL。

WATSONX_APIKEY = os.getenv('WATSONX_APIKEY', "<WATSONX_APIKEY_HERE>")
WATSONX_PROJECT_ID = os.getenv('WATSONX_PROJECT_ID', "<WATSONX_PROJECT_ID_HERE>")
URL = "https://us-south.ml.cloud.ibm.com"

本教程中使用的天气工具需要 OpenWeather API 密钥。要生成密钥,请 创建一个 OpenWeather 帐户。创建帐户后,选择“API 密钥”选项卡,即可显示您的免费密钥。

OPENWEATHERMAP_API_KEY = os.getenv('OPENWEATHERMAP_API_KEY', "<OPEN_WEATHERMAP_API_KEY_HERE>")

第 4 步:初始化 LLM

在本教程中,我们将使用 ChatWatsonx 包装器来设置聊天模型。该包装器简化了工具调用和链接的整合。我们将使用 granite-3-8b-instruct 模型。我们鼓励您使用 ChatWatsonx 文档 中的 API 参考来获取更多信息。

为了初始化 LLM,我们需要设置模型参数。为了限制智能体幻觉,在此处配置模型的 温度 参数非常重要。

llm = ChatWatsonx(
    model_id="ibm/granite-3-8b-instruct",
    url = URL,
    apikey = WATSONX_APIKEY,
    project_id = WATSONX_PROJECT_ID,
    params = {
        "decoding_method": "greedy",
        "temperature": 0,
        "min_new_tokens": 5,
        "max_new_tokens": 2000
    }
)

第 5 步:建立内置工具

我们可以使用 Tool 类来调用我们的工具。清晰简洁的工具描述同样至关重要。此外, return_direct 布尔属性决定是否应将工具响应直接返回给用户。最后, pydantic.BaseModel 类型的可选 args_schema 属性用于向模型提供附加信息或验证。

假设您正在计划下一次去希腊度假,迫切希望了解更多有关希腊的信息,为旅行做好准备。首先,让我们设置内置的 LangChain 天气工具。该工具使用 OpenWeatherMapAPIWrapper, 它使用我们之前生成的 OPENWEATHERMAP_API_KEY 。

weather = OpenWeatherMapAPIWrapper(openweathermap_api_key=OPENWEATHERMAP_API_KEY)

weather_search = Tool(
    name="weather_search",
    description="Get weather for a city and country code, e.g. Athens, GR",
    func=weather.run,
)

接下来,我们要使用 LangChain 提供的 YouTube Search 软件包来设置预构建的 YouTube 工具。此步骤将有助于找到有关您的旅行目的地的视频。

youtube = YouTubeSearchTool()

youtube_search = Tool(
    name="youtube_search",
    description="Search YouTube for video links.",
    func=youtube.run,
)

最后,让我们使用 Ionic 设置 一个在线购物工具。此工具返回与通过电子商务市场销售的用户查询相关的商品。

ionic_search = IonicTool().tool()

让我们列出为 LLM 提供的多种工具。我们还可以打印列表,查看加载情况。有关可用 LangChain 工具的扩展列表,请参阅 LangChain 文档

tools = [weather_search, youtube_search, ionic_search]
tools

Output:

[Tool(name='weather_search', description='Get weather for a city and country code, e.g. Athens, GR', func=<bound method OpenWeatherMapAPIWrapper.run of OpenWeatherMapAPIWrapper(owm=<pyowm.owm.OWM - API key=************************611450cc, subscription type=free, PyOWM version=(3, 3, 0)>, openweathermap_api_key='******************')>),

Tool(name='youtube_search', description='Search YouTube for video links.', func=<bound method BaseTool.run of YouTubeSearchTool()>),

Tool(name='ionic_commerce_shopping_tool', description='\nIonic is an e-commerce shopping tool...[abbreviated]', verbose=True, func=<bound method Ionic.query of <ionic_langchain.tool.Ionic object at 0x17f6e5510>>)] 

第 6 步:工具调用

工具调用通常是指 LLM 返回要调用的工具名称及其参数。我们可以将提取的信息用于其他目的,或者使用这些参数调用该工具。有关更多示例,请参阅 函数调用 教程。

实际上,运行该工具并获取其输出并不总是默认的。在本教程中,我们将深入了解这两种 approaches。

返回相关的工具和参数

要完成传统的工具调用,我们只需提供一个用户查询,并使用预构建的 bind_tools 方法在每次迭代时将工具列表传递给 LLM。

llm_with_tools = llm.bind_tools(tools)
response = llm_with_tools.invoke([("human", "What are some youtube videos about greece")])
response

Output

AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'chatcmpl-tool-7a15abba7d3c4419970d807ac0c8d353', 'type': 'function', 'function': {'name': 'youtube_search', 'arguments': '{"query": "greece"}'}}]}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 578, 'total_tokens': 599}, 'model_name': 'ibm/granite-3-8b-instruct', 'system_fingerprint': '', 'finish_reason': 'tool_calls'}, id='chat-5fe7a26b8f954c179c4995e873bff91e', tool_calls=[{'name': 'youtube_search', 'args': {'query': 'greece'}, 'id': 'chatcmpl-tool-7a15abba7d3c4419970d807ac0c8d353', 'type': 'tool_call'}], usage_metadata={'input_tokens': 578, 'output_tokens': 21, 'total_tokens': 599})

response.additional_kwargs

Output

{'tool_calls': [{'id': 'chatcmpl-tool-7a15abba7d3c4419970d807ac0c8d353',
'type': 'function',
'function': {'name': 'youtube_search',
'arguments': '{"query": "greece"}'}}]}

从 tool_calls 输出中可以看出,LLM 正确识别了适当的工具调用和参数。LLM 本身不运行该工具。我们将在后续步骤中执行此操作。

运行工具调用并检索其输出

要运行工具调用,我们首先需要使用预构建的 LangGraph create_react_gent 辅助方法创建一个 ReAct 智能体。该函数创建了一个图表,作为聊天模型和可用工具之间的桥梁,从而实现智能体工具调用。该图表如下图所示。

ReAct 智能体图
agent_executor = create_react_agent(llm, tools)

现在,我们可以向智能体询问需要调用工具的问题。首先,我们可以要求模型返回有关希腊的 YouTube 视频的 URL。我们可以使用 HumanMessage 类将用户查询传递给 LLM。

user_query = "What are some YouTube videos about Greece"
response = agent_executor.invoke({"messages": user_query})
response["messages"]

Output

[HumanMessage(content='What are some YouTube videos about Greece', additional_kwargs={}, response_metadata={}, id='1adba6c0-32e6-4bbd-92a6-7d21b0177439'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'chatcmpl-tool-b4b5bf452404424ba4d6d9c26e53c6ce', 'type': 'function', 'function': {'name': 'youtube_search', 'arguments': '{"query": "Greece"}'}}]}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 578, 'total_tokens': 600}, 'model_name': 'ibm/granite-3-8b-instruct', 'system_fingerprint': '', 'finish_reason': 'tool_calls'}, id='chat-5f41aee6736842749285aa7fbff50f65', tool_calls=[{'name': 'youtube_search', 'args': {'query': 'Greece'}, 'id': 'chatcmpl-tool-b4b5bf452404424ba4d6d9c26e53c6ce', 'type': 'tool_call'}], usage_metadata={'input_tokens': 578, 'output_tokens': 22, 'total_tokens': 600}),
ToolMessage(content="['https://www.youtube.com/watch?v=waQY2Ucpbd0&pp=ygUGR3JlZWNl', 'https://www.youtube.com/watch?v=NMlBB2pK5qo&pp=ygUGR3JlZWNl']", name='youtube_search', id='1ccf3137-2c10-495e-86ad-a548a3434243', tool_call_id='chatcmpl-tool-b4b5bf452404424ba4d6d9c26e53c6ce'),
AIMessage(content='Here are some YouTube videos about Greece:\n\n1. [Greece Travel Guide | Top 10 Tourist Attractions](https://www.youtube.com/watch?v=waQY2Ucpbd0&pp=ygUGR3JlZWNl)\n2. [Greece Travel Guide | Top 10 Tourist Attractions](https://www.youtube.com/watch?v=NMlBB2pK5qo&pp=ygUGR3JlZWNl)', additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 117, 'prompt_tokens': 677, 'total_tokens': 794}, 'model_name': 'ibm/granite-3-8b-instruct', 'system_fingerprint': '', 'finish_reason': 'stop'}, id='chat-801e3b596a174ac88246b507c93e5869', usage_metadata={'input_tokens': 677, 'output_tokens': 117, 'total_tokens': 794})]

太棒了!从 AIMessage 中可以看出,模型正确识别了适当的工具调用。在 ToolMessage 中,我们看到模型使用内置的 LangChain YouTube 工具成功返回了预期的输出。最后, AIMessage 显示了 LLM 合成的工具响应。

接下来,让我们向模型询问希腊的天气,以确定它是否按预期调用 weather_search 工具。

user_query = "What is the weather in Athens, GR"
response = agent_executor.invoke({"messages": user_query})
response["messages"]

Output

[HumanMessage(content='What is the weather in Athens, GR', additional_kwargs={}, response_metadata={}, id='a0c4b69c-988a-4f7d-9b8a-4780305f8e2a'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'chatcmpl-tool-9a0c07a3b35f4c69a351c5540ab663f8', 'type': 'function', 'function': {'name': 'weather_search', 'arguments': '{"__arg1": "Athens, GR"}'}}]}, response_metadata={'token_usage': {'completion_tokens': 26, 'prompt_tokens': 579, 'total_tokens': 605}, 'model_name': 'ibm/granite-3-8b-instruct', 'system_fingerprint': '', 'finish_reason': 'tool_calls'}, id='chat-eeed087050e049f0ad715f3615c7fdda', tool_calls=[{'name': 'weather_search', 'args': {'__arg1': 'Athens, GR'}, 'id': 'chatcmpl-tool-9a0c07a3b35f4c69a351c5540ab663f8', 'type': 'tool_call'}], usage_metadata={'input_tokens': 579, 'output_tokens': 26, 'total_tokens': 605}),
ToolMessage(content='In Athens, GR, the current weather is as follows:\nDetailed status: few clouds\nWind speed: 4.47 m/s, direction: 23°\nHumidity: 58%\nTemperature: \n - Current: 15.15°C\n - High: 15.74°C\n - Low: 14.1°C\n - Feels like: 14.24°C\nRain: {}\nHeat index: None\nCloud cover: 20%', name='weather_search', id='587b0230-b667-41de-97b9-3779554d2559', tool_call_id='chatcmpl-tool-9a0c07a3b35f4c69a351c5540ab663f8'),
AIMessage(content='The current weather in Athens, GR is:\n- Detailed status: few clouds\n- Wind speed: 4.47 m/s, direction: 23°\n- Humidity: 58%\n- Temperature:\n - Current: 15.15°C\n - High: 15.74°C\n - Low: 14.1°C\n - Feels like: 14.24°C\n- Rain: None\n- Heat index: None\n- Cloud cover: 20%', additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 125, 'prompt_tokens': 733, 'total_tokens': 858}, 'model_name': 'ibm/granite-3-8b-instruct', 'system_fingerprint': '', 'finish_reason': 'stop'}, id='chat-6719a5ca266a439bb10ed410db25c5ef', usage_metadata={'input_tokens': 733, 'output_tokens': 125, 'total_tokens': 858})]

该模型能够识别要调用的适当工具,使用提取的参数运行工具,以及合成工具输出。现在,让我们向 LLM 询问一些 100 美元以下的旅行箱,以备即将到来的旅行之用。请注意,该工具专为按美分单位搜索价格而设计。在这种情况下,我们要求行李箱价格低于 10,000 美分,即 100 美元。

user_query = "Find some suitcases for less than 10000"
response = agent_executor.invoke({"messages": user_query})
response["messages"]

Output

[HumanMessage(content='Find some suitcases for less than 10000', additional_kwargs={}, response_metadata={}, id='8b207035-150a-4390-aff3-8b09ef85a592'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'chatcmpl-tool-b011e718b18e41dcbcae2f7786af263d', 'type': 'function', 'function': {'name': 'ionic_commerce_shopping_tool', 'arguments': '{"__arg1": "suitcases, 10, 0, 10000"}'}}]}, response_metadata={'token_usage': {'completion_tokens': 41, 'prompt_tokens': 582, 'total_tokens': 623}, 'model_name': 'ibm/granite-3-8b-instruct', 'system_fingerprint': '', 'finish_reason': 'tool_calls'}, id='chat-e38c8568d1754636a6a92082561180bd', tool_calls=[{'name': 'ionic_commerce_shopping_tool', 'args': {'__arg1': 'suitcases, 10, 0, 10000'}, 'id': 'chatcmpl-tool-b011e718b18e41dcbcae2f7786af263d', 'type': 'tool_call'}], usage_metadata={'input_tokens': 582, 'output_tokens': 41, 'total_tokens': 623}),
ToolMessage(content='[{"products": [{"links": [{"text": "Details", "type": "pdp", "url": "https://go.ionic.click/Ch4CKd"}], "merchant_name": "Walmart", "merchant_product_id": "811277349", "name": "Zimtown Hardside Lightweight Spinner Orange 3 Piece Luggage Set with TSA Lock", "price": "$69.99", "status": "available", "thumbnail": "https://i5.walmartimages.com/asr/b809a274-ccc7-4ca4-b4f1-e848b4412fe6.314144bcd13e5467a33cb99e8dd5237c.jpeg?odnHeight=100&odnWidth=100&odnBg=ffffff", "brand_name": "Zimtown", "upc": "273109526768"}, {"links": [{"text": "Details", "type": "pdp", "url": "https://www.amazon.com/dp/B071HHX6VF?tag=ioniccommer00-20&linkCode=osi&th=1&psc=1"}], "merchant_name": "Amazon", "merchant_product_id": "B071HHX6VF", "name": "Amazon Basics Expandable Hardside Luggage, Suitcase with Wheels, 30-Inch Spinner with Four Spinner Wheels and Scratch-Resistant Surface, Black", "price": "$74.49", "status": "available", "thumbnail": "https://m.media-amazon.com/images/I/41jJcuMYSdL._SL160_.jpg", "brand_name": "Amazon Basics", "upc": "841710177190"}, .....[abbreviated],
AIMessage(content='Here are some suitcases that are less than 10000:\n\n1. [Zimtown Hardside Lightweight Spinner Orange 3 Piece Luggage Set with TSA Lock](https://go.ionic.click/Ch4CKd) - $69.99\n2. [Amazon Basics Expandable Hardside Luggage, Suitcase with Wheels, 30-Inch Spinner](https://www.amazon.com/dp/B071HHX6VF) - $74.49\n3. [SwissGear Sion Softside Expandable Luggage, Blue, Carry-On 21-Inch](https://www.amazon.com/dp/B01MFBVKDF) - $80.73\n4. [Travelers Club Midtown Hardside Luggage Travel, Rose Gold, 4-Piece Set](https://www.amazon.com/dp/B07RS4PK3J) - $95.19\n5. [American Tourister Stratum 2.0 Expandable Hardside Luggage with Spinner Wheels, 28" SPINNER, Slate Blue](https://www.amazon.com/dp/B0B2X1BDFH) - $89.97\n6. [Wrangler Smart Luggage Set with Cup Holder and USB Port, Navy Blue, 20-Inch Carry-On](https://www.amazon.com/dp/B07SLG6WZ2) - $39.99\n7. [Wrangler Hardside Carry-On Spinner Luggage, Lilac, 20-Inch](https://www.amazon.com/dp/B0C7YWMBGP) - $40.00\n8. [Protege 20 inch Hard Side Carry-On Spinner Luggage, Black Matte Finish (Walmart.com Exclusive)](https://go.ionic.click/qJqBRA) - $29.87\n9. [Wrangler Wesley Rolling Duffel Bag, Tannin, Large 30-Inch](https://www.amazon.com/dp/B07XKWMLJ5) - $44.00\n10. [U.S. Traveler Boren Polycarbonate Hardside Rugged Travel Suitcase Luggage with 8 Spinner Wheels, Aluminum Handle, Lavender, Checked-Large 30-Inch](https://www.amazon.com/dp/B085B4D852) - $79.99', additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 612, 'prompt_tokens': 2794, 'total_tokens': 3406}, 'model_name': 'ibm/granite-3-8b-instruct', 'system_fingerprint': '', 'finish_reason': 'stop'}, id='chat-d08201ff6ef84c428e7ae44372396926', usage_metadata={'input_tokens': 2794, 'output_tokens': 612, 'total_tokens': 3406})]

从响应可以看出,该模型正确地使用了购物工具,返回了几个低于 100 美元的网购旅行箱。

摘要

在本教程中,您使用了预构建的 LangChain 工具,使用 granite-3-8b-instruct  模型,用 watsonx 在 Python 中创建一个 ReAct 智能体。您使用了 youtube_search 、 weather_search  以及 ionic_search  工具。本教程展示了如何实现传统的工具调用以及运行工具的智能体方法。示例输出很重要,因为它展示了智能体使用可用功能创建自己的工作流所采取的步骤。授予智能体的工具对于回答用户的询问至关重要。

相关解决方案
商用 AI 智能体

构建、部署和管理强大的 AI 助手和智能体,运用生成式 AI 实现工作流和流程自动化。

    探索 watsonx Orchestrate
    IBM AI 智能体解决方案

    借助值得信赖的 AI 解决方案,您可以勾勒未来业务发展蓝图。

    深入了解 AI 智能体解决方案
    IBM Consulting AI 服务

    IBM Consulting AI 服务有助于重塑企业利用 AI 实现转型的方式。

    探索人工智能服务
    采取下一步行动

    无论您是选择定制预构建的应用程序和技能,还是使用 AI 开发平台构建和部署定制代理服务,IBM watsonx 平台都能满足您的需求。

    探索 watsonx Orchestrate 深入了解 watsonx.ai