Перейти к содержанию

Tools

Многие AI-приложения взаимодействуют с пользователями через естественный язык. Однако в некоторых случаях требуется, чтобы модели напрямую взаимодействовали с внешними системами — например, с API, базами данных или файловыми системами — используя структурированный ввод. В таких сценариях инструменты (tools) предоставляют модели возможность совершать действия: они инкапсулируют вызываемую функцию (callable) и её схему ввода.

Эти инструменты можно передавать совместимым чат-моделям, что позволяет модели решать, вызывать ли инструмент и с какими аргументами. В сценариях, где используется tool calling, модель генерирует запросы, соответствующие заданной схеме ввода.

Некоторые чат-модели (например, OpenAI, Anthropic и Gemini) имеют встроенные инструменты, которые выполняются на стороне сервера — например, веб-поиск или интерпретаторы кода. Для информации о том, как получить доступ к таким инструментам у вашей модели — смотрите раздел provider overview.


Create tools

Basic tool definition

Самый простой способ создать инструмент — использовать декоратор @tool. По умолчанию строка документации функции (docstring) становится описанием инструмента, которое помогает модели понять, когда этот инструмент следует использовать:

from langchain.tools import tool

@tool
def search_database(query: str, limit: int = 10) -> str:
    """Search the customer database for records matching the query.

    Args:
        query: Search terms to look for
        limit: Maximum number of results to return
    """
    return f"Found {limit} results for '{query}'"

Важно: при объявлении такого инструмента необходимы type hints — они определяют схему ввода (input schema) инструмента. Докстринг должен быть информативным и кратким, чтобы модель могла правильно понять назначение инструмента.

Customize tool properties

Custom tool name

По умолчанию имя инструмента совпадает с именем функции. При необходимости можно переопределить его, чтобы дать более описательное имя:

@tool("web_search")  # Custom name
def search(query: str) -> str:
    """Search the web for information."""
    return f"Results for: {query}"

print(search.name)  # web_search

Custom tool description

Также можно переопределить автоматически сгенерированное описание инструмента, если требуется более ясное пояснение для модели:

@tool("calculator", description="Performs arithmetic calculations. Use this for any math problems.")
def calc(expression: str) -> str:
    """Evaluate mathematical expressions."""
    return str(eval(expression))

Advanced schema definition

Если ваш инструмент требует более сложных и структурированных входных данных — например, несколько полей, перечислений, вложенные структуры — можно определить схему ввода через модели Pydantic или JSON Schema.

from pydantic import BaseModel, Field
from typing import Literal

class WeatherInput(BaseModel):
    """Input for weather queries."""
    location: str = Field(description="City name or coordinates")
    units: Literal["celsius", "fahrenheit"] = Field(
        default="celsius",
        description="Temperature unit preference"
    )
    include_forecast: bool = Field(
        default=False,
        description="Include 5-day forecast"
    )

@tool(args_schema=WeatherInput)
def get_weather(location: str, units: str = "celsius", include_forecast: bool = False) -> str:
    """Get current weather and optional forecast."""
    temp = 22 if units == "celsius" else 72
    result = f"Current weather in {location}: {temp} degrees {units[0].upper()}"
    if include_forecast:
        result += "\nNext 5 days: Sunny"
    return result

Reserved argument names

Есть имена параметров, которые зарезервированы и не могут быть использованы в сигнатуре вашего инструмента — иначе возникнут ошибки во время выполнения:

Имя параметра Назначение
config Зарезервировано для передачи внутреннего RunnableConfig для инструментов
runtime Зарезервировано для параметра ToolRuntime (доступ к состоянию, контексту, store и т.п.)

Если вам нужно получить доступ к runtime-информации — используйте ToolRuntime, а не свой собственный аргумент runtime.

Accessing Context

ToolRuntime

Инструменты могут получать доступ к состоянию агента, контексту, долговременной памяти и другим runtime-данным через параметр ToolRuntime. Для этого просто добавьте runtime: ToolRuntime в сигнатуру вашей функции — этот параметр будет автоматически передан, и при этом не будет виден модели, то есть не станет частью схемы ввода.

ToolRuntime предоставляет:

  • state — изменяемое состояние, которое передаётся между шагами (например, сообщения, счётчики, кастомные поля)
  • context — неизменяемые конфигурации, такие как идентификаторы пользователей, данные сессии, настройки приложения и т.п.
  • store — персистентная долговременная память, общую между разговорами/сессиями.
  • stream_writer — возможность стримить пользовательские обновления из инструмента во время выполнения.
  • config — внутренний конфиг для запуска инструмента (RunnableConfig)
  • tool_call_id — ID текущего вызова инструмента.

Пример использования ToolRuntime

from langchain.tools import tool, ToolRuntime

@tool
def summarize_conversation(runtime: ToolRuntime) -> str:
    """Summarize the conversation so far."""
    messages = runtime.state["messages"]
    human_msgs = sum(1 for m in messages if m.__class__.__name__ == "HumanMessage")
    ai_msgs = sum(1 for m in messages if m.__class__.__name__ == "AIMessage")
    tool_msgs = sum(1 for m in messages if m.__class__.__name__ == "ToolMessage")
    return f"Conversation has {human_msgs} user messages, {ai_msgs} AI responses, and {tool_msgs} tool results"

В этом примере модель увидит только аргументы, необходимые для задачи (в данном случае — никаких), а runtime не попадает в схему, и её не видит модель.

Memory (Store)

Инструменты могут использовать долговременную память — store — через ToolRuntime для хранения и получения данных между сессиями. Это удобно для сохранения пользовательских данных, кеширования, ведения истории и т.п.

from typing import Any
from langgraph.store.memory import InMemoryStore
from langchain.agents import create_agent
from langchain.tools import tool, ToolRuntime

@tool
def get_user_info(user_id: str, runtime: ToolRuntime) -> str:
    """Look up user info."""
    store = runtime.store
    user_info = store.get(("users",), user_id)
    return str(user_info.value) if user_info else "Unknown user"

@tool
def save_user_info(user_id: str, user_info: dict[str, Any], runtime: ToolRuntime) -> str:
    """Save user info."""
    store = runtime.store
    store.put(("users",), user_id, user_info)
    return "Successfully saved user info."

В примере выше: первый запуск может сохранять данные пользователя, а последующие — извлекать их из памяти.

Stream Writer

Если ваш инструмент выполняет операцию, которая может занимать заметное время — вы можете использовать runtime.stream_writer внутри инструмента, чтобы отправлять промежуточные обновления клиенту в режиме потоковой передачи. Это может быть полезно, чтобы показывать прогресс выполнения задачи, логировать ход, уведомлять пользователя и т.п.

from langchain.tools import tool, ToolRuntime

@tool
def get_weather(city: str, runtime: ToolRuntime) -> str:
    """Get weather for a given city."""
    writer = runtime.stream_writer
    writer(f"Looking up data for city: {city}")
    writer(f"Acquired data for city: {city}")
    return f"It's always sunny in {city}!"

Если вы используете runtime.stream_writer — убедитесь, что инструмент вызывается в контексте выполнения LangGraph, так как стриминг поддерживается только там.

Source: https://docs.langchain.com/oss/python/langchain/tools