Розробка AI-агента з Function Calling (Tool Use)

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Розробка AI-агента з Function Calling (Tool Use)
Середній
від 1 тижня до 3 місяців
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

Розвиток AI-агента з Function Calling (Tool Use)

Function Calling (Tool Use) — механізм, при якому LLM генерує структурований вклик функції замість текстової відповіді. Модель аналізує запит, визначає потрібний інструмент та його параметри, а хост-додаток виконує виклик і повертає результат. Це робить агента здатним взаємодіяти з будь-якими зовнішніми системами.

OpenAI Function Calling

from openai import OpenAI
import json

client = OpenAI()

# Схема інструментів
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_customer_info",
            "description": "Отримати інформацію про клієнта за ID або email",
            "parameters": {
                "type": "object",
                "properties": {
                    "customer_id": {"type": "string"},
                    "email": {"type": "string"},
                    "fields": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "Потрібні поля: name, orders, balance, status"
                    }
                },
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "create_support_ticket",
            "description": "Створити тикет у службу підтримки",
            "parameters": {
                "type": "object",
                "properties": {
                    "customer_id": {"type": "string"},
                    "category": {"type": "string", "enum": ["billing", "technical", "account", "shipping"]},
                    "priority": {"type": "string", "enum": ["low", "medium", "high", "critical"]},
                    "description": {"type": "string"},
                },
                "required": ["customer_id", "category", "description"]
            }
        }
    },
]

# Реєстр функцій
def get_customer_info(customer_id=None, email=None, fields=None) -> dict:
    # Реальна реалізація: запит до CRM/БД
    return {"id": customer_id, "name": "Іванов І.І.", "balance": 15000, "status": "active"}

def create_support_ticket(customer_id: str, category: str, description: str, priority: str = "medium") -> dict:
    # Реальна реалізація: Jira/Zendesk API
    return {"ticket_id": "TKT-12345", "status": "created"}

FUNCTION_MAP = {
    "get_customer_info": get_customer_info,
    "create_support_ticket": create_support_ticket,
}

# Цикл агента з Function Calling
def run_support_agent(user_message: str) -> str:
    messages = [
        {"role": "system", "content": "Ти — агент служби підтримки. Використовуй інструменти для допомоги клієнтам."},
        {"role": "user", "content": user_message},
    ]

    while True:
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=tools,
            tool_choice="auto",
            parallel_tool_calls=True,  # Паралельні виклики
        )

        message = response.choices[0].message
        messages.append(message)

        if not message.tool_calls:
            return message.content

        # Виконуємо всі виклики (паралельно якщо кілька)
        for tool_call in message.tool_calls:
            func_name = tool_call.function.name
            func_args = json.loads(tool_call.function.arguments)

            func = FUNCTION_MAP.get(func_name)
            if func:
                result = func(**func_args)
            else:
                result = {"error": f"Function {func_name} not found"}

            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": json.dumps(result, ensure_ascii=False),
            })

Паралельні виклики інструментів

GPT-4o та Claude 3+ підтримують паралельний виклик кількох інструментів:

# Приклад: агент може запитати дані з кількох джерел одночасно
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Покажи замовлення та баланс клієнта #12345"}],
    tools=tools,
    tool_choice="auto",
    parallel_tool_calls=True,
)

# Модель генерує два паралельних виклики:
# get_orders(customer_id="12345") AND get_balance(customer_id="12345")

Anthropic Tool Use

import anthropic

client = anthropic.Anthropic()

tools = [
    {
        "name": "search_knowledge_base",
        "description": "Пошук у корпоративній базі знань",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {"type": "string"},
                "category": {"type": "string"},
            },
            "required": ["query"],
        }
    }
]

def run_claude_agent(user_message: str) -> str:
    messages = [{"role": "user", "content": user_message}]

    while True:
        response = client.messages.create(
            model="claude-opus-4-5",
            max_tokens=4096,
            tools=tools,
            messages=messages,
        )

        if response.stop_reason == "end_turn":
            # Фінальна текстова відповідь
            return next(b.text for b in response.content if hasattr(b, "text"))

        # Обробка tool_use блоків
        messages.append({"role": "assistant", "content": response.content})

        tool_results = []
        for block in response.content:
            if block.type == "tool_use":
                result = execute_tool(block.name, block.input)
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": json.dumps(result),
                })

        messages.append({"role": "user", "content": tool_results})

Практичний кейс: агент для HR-запитів

Інструменти:

  • get_employee_info(employee_id) — дані співробітника
  • check_vacation_balance(employee_id) — залишок відпустки
  • submit_vacation_request(employee_id, start_date, end_date) — заявка на відпустку
  • get_company_policy(policy_name) — пошук у базі HR-політик

Запит: «Хочу взяти відпустку з 15 квітня по 25 квітня. У мене достатньо днів?»

Траєкторія агента:

  1. get_employee_info(employee_id="emp_789") — отримуємо ID з контексту сесії
  2. check_vacation_balance(employee_id="emp_789") — залишок: 14 днів
  3. get_company_policy("vacation_approval") — читаємо правила узгодження
  4. Фінальна відповідь: «У вас 14 днів відпустки. Період 15–25 квітня — 11 робочих днів (з урахуванням святих днів). Баланс достатній. Для оформлення — submit_vacation_request. Заявку має затвердити ваш керівник протягом 3 робочих днів за політикою.»

Метрики за перший місяць:

  • Автономно обробленні запити (без оператора): 84%
  • Точність інформації про баланс/політики: 97%
  • Середній час відповіді: 4.2с

Валідація викликів інструментів

from pydantic import BaseModel, validator
from datetime import date

class VacationRequest(BaseModel):
    employee_id: str
    start_date: date
    end_date: date

    @validator("end_date")
    def end_after_start(cls, v, values):
        if "start_date" in values and v <= values["start_date"]:
            raise ValueError("end_date must be after start_date")
        return v

# Валідація перед виконанням
def safe_tool_execution(func_name: str, func_args: dict) -> dict:
    try:
        if func_name == "submit_vacation_request":
            VacationRequest(**func_args)  # Валідація
        return FUNCTION_MAP[func_name](**func_args)
    except Exception as e:
        return {"error": str(e), "status": "validation_failed"}

Графік

  • Розвиток агента з 3–7 інструментами: 2–4 тижні
  • Інтеграція з корпоративними системами: 2–4 тижні
  • Тестування та моніторинг: 1–2 тижні
  • Всього: 5–10 тижнів