AI-система Search-as-a-Service (поисковый AI-сервис для клиентов)

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
AI-система Search-as-a-Service (поисковый AI-сервис для клиентов)
Сложная
от 1 недели до 3 месяцев
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

AI Search as a Service: поиск как платформа

Строить поиск с нуля для каждого продукта — дорого и долго. Search as a Service — это готовая поисковая платформа с AI-слоем, которую команды подключают через API или SDK, не разбираясь в векторных базах данных и re-ranking моделях.

Типичный сценарий: у компании 5 продуктов, в каждом нужен поиск по каталогу / документам / контенту. Без платформы — 5 независимых реализаций, 5 раз настраивать индексы, 5 раз платить за GPU для embedding-модели. С платформой — один shared сервис, разные индексы (tenants), единый API.

Архитектура multi-tenant поисковой платформы

from fastapi import FastAPI, Header, HTTPException, Depends
from pydantic import BaseModel
from typing import Optional
import uuid

app = FastAPI(title="Search as a Service")

class IndexConfig(BaseModel):
    name: str
    embedding_model: str = "intfloat/multilingual-e5-large"
    chunk_size: int = 512
    chunk_overlap: int = 64
    language: str = "ru"
    reranker_enabled: bool = True

class SearchRequest(BaseModel):
    query: str
    index_name: str
    filters: Optional[dict] = None
    top_k: int = 10
    mode: str = "hybrid"  # "vector" | "keyword" | "hybrid"
    generate_answer: bool = False

class SearchService:
    def __init__(self):
        self.tenant_indexes = {}  # tenant_id → {index_name → index}
        self.embedding_models = {}  # model_name → loaded_model
        self.reranker = self._load_reranker()

    async def create_index(self, tenant_id: str, config: IndexConfig):
        """Создаёт изолированный индекс для тенанта"""
        collection_name = f"{tenant_id}_{config.name}"
        # Каждый тенант — отдельная коллекция в Qdrant
        # с собственными payload-фильтрами
        self.qdrant.create_collection(
            collection_name=collection_name,
            vectors_config=VectorParams(
                size=self._get_vector_size(config.embedding_model),
                distance=Distance.COSINE
            )
        )
        return {"index_id": collection_name, "status": "created"}

    async def search(
        self,
        tenant_id: str,
        request: SearchRequest
    ) -> dict:
        collection = f"{tenant_id}_{request.index_name}"

        if request.mode == "hybrid":
            results = await self._hybrid_search(
                collection, request.query,
                request.filters, request.top_k
            )
        elif request.mode == "vector":
            results = await self._vector_search(
                collection, request.query, request.top_k
            )
        else:
            results = await self._keyword_search(
                collection, request.query, request.top_k
            )

        if request.generate_answer and results:
            answer = await self._generate_answer(request.query, results)
            return {"results": results, "answer": answer}

        return {"results": results}

SDK для команд-потребителей

# pip install search-platform-sdk
from search_platform import SearchClient

client = SearchClient(
    api_key="sk-...",
    base_url="https://search.internal.company.com"
)

# Индексация документов
client.index.upload(
    index_name="product-catalog",
    documents=[
        {"id": "p001", "title": "Ноутбук Dell XPS", "description": "...",
         "price": 89999, "category": "laptops"},
        # ...
    ]
)

# Поиск
results = client.search(
    index_name="product-catalog",
    query="тонкий ноутбук для работы с видео",
    filters={"price": {"lte": 100000}, "category": "laptops"},
    top_k=5,
    generate_answer=True
)

print(results.answer)   # "На основе вашего запроса рекомендую..."
print(results.items)    # список документов с релевантностью

Rate limiting и мониторинг

from fastapi_limiter import FastAPILimiter
from fastapi_limiter.depends import RateLimiter
import redis.asyncio as redis

# Лимиты по тенантам
TENANT_LIMITS = {
    "free": "100/minute",
    "pro": "1000/minute",
    "enterprise": "unlimited"
}

@app.post("/search")
@limiter.limit(get_tenant_limit)  # динамический лимит по плану
async def search_endpoint(
    request: SearchRequest,
    x_api_key: str = Header(...),
    tenant = Depends(authenticate_tenant)
):
    return await search_service.search(tenant.id, request)

Billing и usage tracking

Каждый поиск и каждый embedding-запрос логируются в TimescaleDB:

CREATE TABLE search_usage (
    id          BIGSERIAL PRIMARY KEY,
    tenant_id   TEXT NOT NULL,
    index_name  TEXT NOT NULL,
    query_hash  TEXT,           -- хэш для анонимизации
    mode        TEXT,
    latency_ms  INTEGER,
    result_count INTEGER,
    answer_generated BOOLEAN,
    tokens_used  INTEGER,       -- для LLM-ответа
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

-- Гипертаблица TimescaleDB для эффективного time-range запросов
SELECT create_hypertable('search_usage', 'created_at');

Кейс: SaaS-компания с 12 продуктами мигрировала со своих разрозненных Elasticsearch-инстансов на единую платформу. 3 команды подключились через SDK за 1 день (без понимания векторных баз и embedding-моделей). Стоимость инфраструктуры снизилась на 35% за счёт shared GPU для embedding. Среднее время ответа поиска: 280 мс P50, 650 мс P99 на корпусе 2M документов.

SLA и параметры платформы

Параметр Значение
Latency P50 < 300 мс
Latency P99 < 1 сек
Доступность 99.9%
Максимальный размер документа 5 MB
Поддерживаемые форматы PDF, DOCX, TXT, HTML, JSON
Языки RU, EN, DE, FR, ES (multilingual-E5)
Максимум тенантов Не ограничено (горизонтальное масштабирование)

Сроки: базовая платформа (API + индексация + гибридный поиск): 6–8 недель; с генерацией ответов, SDK и биллингом: 3–4 месяца.