Розробка AI-агента з доступом до бази даних

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

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

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

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

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

Розвиток AI-агента з доступом до бази даних

AI-агент з доступом до БД може самостійно запитувати дані, формувати SQL-запити на основі запитань природною мовою й виконувати операції запису з необхідними перевірками. Text-to-SQL — ключова технологія, яка дозволяє нетехнічним користувачам взаємодіяти з даними через діалог.

Text-to-SQL: Перетворення запитань на SQL

from langchain_openai import ChatOpenAI
from langchain_community.utilities import SQLDatabase
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain.agents import create_sql_agent

# Підключення до PostgreSQL
db = SQLDatabase.from_uri(
    "postgresql://user:password@localhost:5432/company_db",
    include_tables=["orders", "customers", "products", "inventory"],
    sample_rows_in_table_info=3,  # Включаємо приклади даних у схему
)

llm = ChatOpenAI(model="gpt-4o", temperature=0)
toolkit = SQLDatabaseToolkit(db=db, llm=llm)

# SQL агент з автоматичним виправленням помилок
agent = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    verbose=True,
    handle_parsing_errors=True,
    max_iterations=10,
)

# Приклади запитів
result = agent.invoke({"input": "Які топ-5 клієнтів за дохідом за останні 3 місяці?"})
result = agent.invoke({"input": "Покажи товари зі залишком на складі менше 10 одиниць"})

Безпека: тільки READ-доступ

from langchain_community.utilities import SQLDatabase
from sqlalchemy import create_engine, text

# Read-only користувач PostgreSQL
READ_ONLY_USER_URI = "postgresql://readonly_user:pass@localhost:5432/db"

# Додаткова валідація: заборона DML-операцій
def validate_sql_query(query: str) -> bool:
    """Перевіряє, що запит є тільки SELECT"""
    forbidden_keywords = ["INSERT", "UPDATE", "DELETE", "DROP", "CREATE", "ALTER", "TRUNCATE"]
    query_upper = query.upper()
    for keyword in forbidden_keywords:
        if keyword in query_upper:
            return False
    return True

class SafeSQLTool:
    def __init__(self, db_uri: str):
        self.engine = create_engine(db_uri)

    def execute_query(self, query: str) -> str:
        if not validate_sql_query(query):
            return "ERROR: Only SELECT queries are allowed"

        # Обмеження кількості рядків
        if "LIMIT" not in query.upper():
            query = f"{query.rstrip(';')} LIMIT 100"

        with self.engine.connect() as conn:
            result = conn.execute(text(query))
            rows = result.fetchall()
            columns = result.keys()
            return str([dict(zip(columns, row)) for row in rows])

Схема бази з контекстом для LLM

Якість Text-to-SQL критично залежить від якості описання схеми:

SCHEMA_CONTEXT = """
Таблиці бази даних:

1. orders (замовлення)
   - id: PK, INTEGER
   - customer_id: FK → customers.id
   - status: VARCHAR (pending, confirmed, shipped, delivered, cancelled)
   - total_amount: DECIMAL(12,2) — сума замовлення
   - created_at: TIMESTAMP
   - shipped_at: TIMESTAMP (NULL якщо не відправлено)

2. customers (клієнти)
   - id: PK
   - name: VARCHAR — назва компанії або ПІБ
   - inn: VARCHAR(12) — реєстраційний номер
   - segment: VARCHAR (enterprise, mid, small) — сегмент клієнта
   - manager_id: FK → employees.id — менеджер рахунку

3. products (товари)
   - sku: VARCHAR — артикул
   - name: VARCHAR
   - category: VARCHAR
   - price_rub: DECIMAL
   - cost_rub: DECIMAL — собівартість

ВАЖЛИВО: Статуси замовлення: 'delivered' = успішно виконано. 'cancelled' = скасовано.
         Дохід = сума total_amount замовлень зі статусом 'delivered'.
"""

system_prompt = f"""Ти — аналітик даних. Переводи запитання на SQL-запити.
Використовуй наступну схему бази даних:

{SCHEMA_CONTEXT}

Правила:
- Тільки SELECT запити
- Завжди додавай LIMIT (не більше 1000)
- Використовуй прозорі alias для колон
- Додавай ORDER BY при агрегуванні"""

Практичний кейс: BI-агент для e-commerce

Завдання: аналітичний помічник для комерційного директора — аналіз продажів, ABC-аналіз асортименту, воронка замовлень, cohort retention.

БД: PostgreSQL, 15 таблиць, 3M замовлень.

Приклади діалогів:

Користувач: «Яка конверсія з pending у delivered за останні 30 днів по сегментах клієнтів?»

Агент генерує:

SELECT
    c.segment AS сегмент,
    COUNT(*) FILTER (WHERE o.status = 'pending') AS очікуючих,
    COUNT(*) FILTER (WHERE o.status = 'delivered') AS доставлено,
    ROUND(
        COUNT(*) FILTER (WHERE o.status = 'delivered')::decimal /
        NULLIF(COUNT(*), 0) * 100, 1
    ) AS конверсія_pct
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.created_at >= NOW() - INTERVAL '30 days'
GROUP BY c.segment
ORDER BY конверсія_pct DESC
LIMIT 100;

Результати:

  • Час отримання аналітики: 2 дні → 3 хвилини
  • Точність SQL (запитання → коректний SQL): 87%
  • Типові помилки: неправильні JOIN при складних запитах (вирішується через few-shot приклади у промпті)

Few-shot приклади для підвищення точності

FEW_SHOT_EXAMPLES = """
Приклади коректних запитів:

Запитання: Топ-10 товарів за маржею за останній квартал
SQL:
SELECT p.name, p.sku,
       SUM(oi.quantity * (p.price_rub - p.cost_rub)) AS маржа_руб
FROM order_items oi
JOIN products p ON oi.sku = p.sku
JOIN orders o ON oi.order_id = o.id
WHERE o.status = 'delivered'
  AND o.created_at >= DATE_TRUNC('quarter', CURRENT_DATE) - INTERVAL '3 months'
GROUP BY p.name, p.sku
ORDER BY маржа_руб DESC
LIMIT 10;

Запитання: Середній чек по місяцях за 2025 рік
SQL:
SELECT DATE_TRUNC('month', created_at) AS місяць,
       ROUND(AVG(total_amount), 0) AS середній_чек,
       COUNT(*) AS кіл_замовлень
FROM orders
WHERE status = 'delivered'
  AND created_at BETWEEN '2025-01-01' AND '2025-12-31'
GROUP BY 1
ORDER BY 1;
"""

Графік

  • Розвиток Text-to-SQL агента: 2–3 тижні
  • Налаштування схеми та few-shot прикладів: 1 тиждень
  • Тестування на реальних запитах: 1–2 тижні
  • Всього: 4–6 тижнів