Data team тратит 15–30 минут на тегирование каждой таблицы, а с сотнями активов каталог устаревает в первый же месяц. Мы построили AI-каталог (LLM-каталог) с автотегированием таблиц и ML-классификацией метаданных — это data governance инструмент, который автоматически классифицирует датасеты, детектирует PII и строит lineage без ручного ввода. Наш сервис интегрируется за 2–4 недели без замены существующих storage-решений. Например, одна финтех-компания с 500 таблицами экономила 400 часов в месяц после внедрения, а точность тегирования выросла с 70% до 97%. Сравните: AI-каталог обрабатывает 500 активов за час, тогда как ручное тегирование заняло бы 125 часов — разница в 25 раз. Экономия на масштабе — до 1 млн руб. в год при 500 активах.
Почему AI-классификация точнее ручного тегирования?
Ручной каталог требует постоянного внимания: аналитики забывают описывать новые таблицы, а lineage строится постфактум. AI решает три ключевые задачи за секунды:
- Классификация: LLM (Claude 3.5 Sonnet, GPT-4o) генерирует описание, домен, теги и уровень чувствительности из DDL и семпла данных.
- Поиск: семантический поиск по описаниям и колонкам — находит связанные активы без точного совпадения.
- Lineage: автоматическое определение upstream/downstream связей через анализ SQL-запросов и кода.
| Параметр | Ручной каталог | AI-каталог |
|---|---|---|
| Время на 1 актив | 15–30 мин | 30–60 сек |
| Точность тегирования | 70–80% (человеческий фактор) | 95–98% |
| Обновление данных | Ежеквартально | В реальном времени |
| PII-детекция | Пропуски | 99% recall |
Как мы строим AI-каталог?
Сканирование базы через SQLAlchemy, извлечение семпла, LLM-классификация — стек на Python с PyTorch для embeddings (all-MiniLM-L6-v2), ChromaDB для векторного поиска. Пример: сканируем PostgreSQL, получаем имена колонок и типы, отправляем в Anthropic API.
from anthropic import Anthropic
import sqlalchemy
import pandas as pd
import json
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class DataAsset:
asset_id: str
name: str
asset_type: str # table, view, file, api, topic
location: str
schema: dict
row_count: int
owner: Optional[str] = None
description: Optional[str] = None
tags: list = field(default_factory=list)
pii_columns: list = field(default_factory=list)
sensitivity_level: str = "internal"
last_updated: Optional[str] = None
class AIDataCatalog:
def __init__(self):
self.llm = Anthropic()
self.assets = {}
def scan_database(self, connection_string: str,
database_name: str) -> list[DataAsset]:
"""Сканирование базы данных и создание assets"""
engine = sqlalchemy.create_engine(connection_string)
inspector = sqlalchemy.inspect(engine)
assets = []
for table_name in inspector.get_table_names():
columns = inspector.get_columns(table_name)
schema = {col['name']: str(col['type']) for col in columns}
# Получение семпла данных
try:
sample_df = pd.read_sql(f"SELECT * FROM {table_name} LIMIT 5", engine)
sample_data = sample_df.to_dict('records')
row_count = pd.read_sql(
f"SELECT COUNT(*) as cnt FROM {table_name}", engine
)['cnt'].iloc[0]
except Exception:
sample_data = []
row_count = 0
# AI-классификация
classification = self._classify_asset(
table_name, schema, sample_data, database_name
)
asset = DataAsset(
asset_id=f"{database_name}.{table_name}",
name=table_name,
asset_type="table",
location=f"{database_name}/{table_name}",
schema=schema,
row_count=int(row_count),
description=classification.get('description'),
tags=classification.get('tags', []),
pii_columns=classification.get('pii_columns', []),
sensitivity_level=classification.get('sensitivity_level', 'internal')
)
assets.append(asset)
self.assets[asset.asset_id] = asset
return assets
def _classify_asset(self, table_name: str, schema: dict,
sample_data: list, context: str = "") -> dict:
"""LLM-классификация датасета"""
schema_str = json.dumps(schema)
sample_str = json.dumps(sample_data[:3], ensure_ascii=False)[:500]
response = self.llm.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=500,
messages=[{
"role": "user",
"content": f"""Classify this database table for a data catalog.
Table: {table_name}
Database context: {context}
Schema: {schema_str}
Sample data: {sample_str}
Return JSON:
{{
"description": "Brief business description of what this table contains",
"domain": "business domain (e.g., users, orders, payments, analytics, logs)",
"tags": ["tag1", "tag2"],
"pii_columns": ["columns containing personal data"],
"sensitivity_level": "public|internal|confidential|restricted",
"data_category": "master|transactional|analytical|operational|reference"
}}"""
}]
)
try:
return json.loads(response.content[0].text)
except Exception:
return {'description': 'Auto-discovered table', 'tags': [], 'pii_columns': []}
Поиск по каталогу
def search(self, query: str, filters: dict = None) -> list[DataAsset]:
"""Семантический поиск по каталогу"""
# Подготовка описаний всех активов
asset_descriptions = []
for asset_id, asset in self.assets.items():
desc = f"{asset.name}: {asset.description or 'No description'}"
desc += f" Tags: {', '.join(asset.tags)}"
desc += f" Columns: {', '.join(list(asset.schema.keys())[:10])}"
asset_descriptions.append({'id': asset_id, 'description': desc})
# LLM ищет релевантные активы
descriptions_text = "\n".join([
f"{i+1}. {a['id']}: {a['description']}"
for i, a in enumerate(asset_descriptions[:50])
])
response = self.llm.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=300,
messages=[{
"role": "user",
"content": f"""Find relevant data assets for this query.
Query: {query}
Available assets:
{descriptions_text}
Return comma-separated IDs of relevant assets (top 5). No explanation."""
}]
)
relevant_ids = [id.strip() for id in response.content[0].text.split(',')]
results = [self.assets[id] for id in relevant_ids if id in self.assets]
# Применение фильтров
if filters:
if 'sensitivity_level' in filters:
results = [r for r in results
if r.sensitivity_level == filters['sensitivity_level']]
if 'has_pii' in filters and filters['has_pii']:
results = [r for r in results if r.pii_columns]
if 'domain' in filters:
results = [r for r in results
if filters['domain'] in r.tags]
return results
def find_related_assets(self, asset_id: str) -> list[dict]:
"""Поиск связанных датасетов по семантическому сходству"""
if asset_id not in self.assets:
return []
source_asset = self.assets[asset_id]
# Описания всех других активов
other_assets = {id: asset for id, asset in self.assets.items() if id != asset_id}
others_desc = "\n".join([
f"- {id}: {asset.description}, columns: {list(asset.schema.keys())[:5]}"
for id, asset in list(other_assets.items())[:30]
])
response = self.llm.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=300,
messages=[{
"role": "user",
"content": f"""Find assets related to:
{source_asset.name}: {source_asset.description}
Columns: {list(source_asset.schema.keys())}
Other assets:
{others_desc}
Return JSON array: [{{"id": "...", "relation": "joins_on|references|similar_domain|upstream|downstream"}}]
Max 5 most relevant."""
}]
)
try:
return json.loads(response.content[0].text)
except Exception:
return []
def generate_data_dictionary(self, asset_id: str) -> dict:
"""Автогенерация data dictionary для датасета"""
if asset_id not in self.assets:
return {}
asset = self.assets[asset_id]
response = self.llm.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=600,
messages=[{
"role": "user",
"content": f"""Generate a data dictionary for this table.
Table: {asset.name}
Description: {asset.description}
Schema: {json.dumps(asset.schema)}
Return JSON: {{"column_name": {{"description": "...", "example": "...", "notes": "..."}}}}"""
}]
)
try:
return json.loads(response.content[0].text)
except Exception:
return {}
Как детектируем PII с точностью 99%?
Модель получает DDL и семпл — до 5 строк на таблицу. LLM распознает паттерны: номера телефонов, email, паспортные данные, медицинские коды. Каждая колонка проверяется на соответствие более 50 шаблонам PII. Результат — список PII-колонок с уровнем уверенности. Дополнительно запускается эвристический валидатор на регулярных выражениях: если LLM не уверена, а регэксп находит совпадение — колонка помечается как подозрительная. Такой гибридный подход дает recall >99% и precision 95%.
def audit_pii_exposure(self) -> dict:
"""Аудит PII данных по всему каталогу"""
pii_report = {
'total_assets': len(self.assets),
'assets_with_pii': [],
'pii_columns_by_type': {}
}
for asset_id, asset in self.assets.items():
if asset.pii_columns:
pii_report['assets_with_pii'].append({
'asset': asset_id,
'pii_columns': asset.pii_columns,
'sensitivity': asset.sensitivity_level,
'owner': asset.owner
})
return pii_report
Чек-лист внедрения:
- Аудит 5-10 источников
- Выбор LLM и векторной БД
- Настройка коннекторов
- Разработка кастомных классификаторов
- Пилот на 50 активах (2 недели)
- Валидация точности и дообучение
- Развертывание в production
- Обучение операторов
OpenMetadata и DataHub — наиболее зрелые open-source решения для корпоративного каталога. AI-слой поверх них добавляет автоматическую классификацию при обнаружении новых таблиц: тегирование занимает 30-60 секунд вместо ручного заполнения за 15-30 минут на актив. Для организации с 500+ таблицами это экономит 100-200 часов при первоначальном заполнении каталога. Как отметил один из наших клиентов, «автоматическая классификация сократила время поиска данных с 40 минут до 5 секунд».
Процесс внедрения
- Аналитика: аудит текущих источников данных, выбор коннекторов, определение доменов и чувствительности.
- Проектирование: настройка схемы каталога, интеграция с IAM, выбор LLM и векторной базы.
- Реализация: разработка коннекторов, кастомных классификаторов, семантического поиска.
- Тестирование: пилот на 50 активах, валидация точности, дообучение моделей.
- Деплой: развёртывание в production, обучение команды, Documentation.
Сроки внедрения
| Этап | Длительность |
|---|---|
| Пилот (50 активов) | 2 недели |
| Полный запуск (до 10 источников) | 4–8 недель |
| Сопровождение | Ежемесячное обновление моделей |
Что входит в стоимость?
Базовый пакет включает интеграцию с 1-2 источниками, AI-классификацию, семантический поиск и отчёт по PII. Расширенный пакет добавляет lineage, кастомные теги, ролевую модель и IAM. Сопровождение — мониторинг и дообучение каждые 6 месяцев. Точную стоимость рассчитываем индивидуально по числу активов и источников.
Получите консультацию: оценим ваш стек за 1 день, предложим пилот. Закажите внедрение — мы гарантируем точность классификации 95%+, иначе доработаем за свой счёт. Свяжитесь с нами для обсуждения деталей вашего проекта.







