← Claude на русском
Перевод с разбором · для Вани
Адаптировал Claude Opus 4.7 (ИИ) на основе документации Anthropic. Полная версия — в docs/tool-use.html.

Tool use: функции и действия

Адаптация для Вани · 2026-04-23

Зачем тебе это нужно

В статье про галлюцинации мы договорились: арифметику и данные — не LLM, а Kotlin. Tool use — это способ «подружить» эти два мира. Модель видит набор функций (get_price, calculate_cuts, save_order) и, когда считает нужным, возвращает структурированный вызов. Твой код выполняет и отдаёт результат обратно. Модель продолжает разговор уже с этим фактом.

Схема работы

  1. Ты описываешь инструменты: имя, что делают, какие параметры.
  2. Модель получает запрос + список инструментов.
  3. Если решает вызвать — возвращает объект tool_call с параметрами.
  4. Твой Kotlin-код выполняет, результат отдаёт обратно.
  5. Модель пишет финальный ответ пользователю, опираясь на результат.

Пример: инструмент для получения цены

// Описание инструмента (OpenAI-формат)
val tools = listOf(
    mapOf(
        "type" to "function",
        "function" to mapOf(
            "name" to "get_material_price",
            "description" to "Возвращает цену единицы материала из прайса.",
            "parameters" to mapOf(
                "type" to "object",
                "properties" to mapOf(
                    "material_code" to mapOf("type" to "string", "description" to "Код: oak_board_40mm и т.п.")
                ),
                "required" to listOf("material_code")
            )
        )
    )
)

Что здесь происходит: описали один инструмент. Ключевое — description: по нему модель решает, когда его звать. Чем яснее — тем точнее.

Обработка вызова в Kotlin

val response = openAi.chatCompletion {
    model = "gpt-5.4-mini"
    messages { system(SYSTEM_PROMPT); user(userMessage) }
    this.tools = tools
}

val msg = response.choices.first().message
if (msg.toolCalls?.isNotEmpty() == true) {
    val call = msg.toolCalls.first()
    if (call.function.name == "get_material_price") {
        val args = Json.decodeFromString<PriceArgs>(call.function.arguments)
        val price = priceRepo.getUnitPrice(args.materialCode)
            ?: return respondError("price not found")
        // отправляем результат обратно модели
        val followUp = openAi.chatCompletion {
            messages {
                system(SYSTEM_PROMPT); user(userMessage)
                assistant(msg)
                tool(toolCallId = call.id, content = "{\"price\": $price}")
            }
            this.tools = tools
        }
        return followUp.choices.first().message.content
    }
}

Что здесь происходит: проверили, не хочет ли модель позвать функцию → если хочет, распарсили параметры, достали цену из Postgres, отдали обратно. Модель видит результат и формирует финальный ответ.

Какие инструменты имеет смысл делать

Strict mode и защита от ошибок

У OpenAI и Anthropic есть strict: true — гарантия, что параметры вызова будут точно по схеме. Для прода — включай всегда. Дополнительно валидируй на Kotlin-стороне: даже если пришла «правильная» строка, её значение может быть невалидным (material_code = "unobtanium").

Что это значит для твоей системы

Полная версия — в docs/tool-use.html.