מדוע חיפוש-כשירות (Search-as-a-Service) מהיר יותר מפתרונות פנימיים
לעתים קרובות אנו רואים חברות שמבזבזות חודשים על בניית חיפוש AI מאפס עבור כל מוצר: כתיבת וקטוריזציה משלהן, הגדרת reranking, תצורת תשתית. חיפוש כשירות הוא פלטפורמת חיפוש סמנטי מוכנה עם שכבת AI שאנו מחברים דרך API חיפוש מאוחד ו-SDK חיפוש. המהנדסים שלנו עם ניסיון של 10+ שנים ב-MLOps מטפלים בכל התשתית: מבחירת מודל embedding ועד להגדרת חיפוש וקטורי, חיפוש היברידי ו-reranking.
עם יותר מ-20 פריסות מוצלחות ו-5+ שנים בתחום החיפוש, חידדנו את הגישה שלנו. תרחיש טיפוסי: לחברה יש 5 מוצרים, כל אחד צריך חיפוש בקטלוגים, מסמכים ותוכן. ללא פלטפורמה, זה אומר 5 הטמעות עצמאיות, 5 פעמים הגדרת אינדקסים, 5 פעמים תשלום עבור GPU עבור מודל ה-embedding. עם הפלטפורמה שלנו, זה שירות משותף אחד, אינדקסים שונים (דיירים), API יחיד. עלויות התשתית יורדות ב-30–50% הודות ל-GPU משותף, וזמן פריסת החיפוש מתקצר מחודשים לשבועות.
עבור פריסה טיפוסית של 5 מוצרים, הלקוחות שלנו מדווחים על חיסכון בעלויות תשתית של $20K–$50K בשנה.
כיצד פועלת ריבוי-דיירות בפלטפורמת החיפוש
אנו מספקים חיפוש רב-דייר עם סביבות מבודדות. כל לקוח מקבל סביבה מבודדת: אוסף משלו ב-Qdrant (או מסד וקטורי אחר), צינור אינדוקס משלו, ומגבלות גמישות. אנו מבטיחים שנתונים מלקוחות שונים לעולם לא מתערבבים, והעומס מתחלק באופן שווה באמצעות קנה מידה אופקי.
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 לצוותי צרכנים
אנו מספקים SDK בפייתון עם תלות מינימלית. צוותים מתחברים לפלטפורמה תוך 10 דקות—אין צורך להיכנס לפרטים של מסד וקטורי או LLM.
# 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) # список документов с релевантностью
מדוע לבחור בחיפוש-כשירות במקום פתרון ביתי?
השוו: בנייה עצמית דורשת גיוס צוות של מהנדסי ML, בחירה והדרכה של מודל embedding, הגדרת חיפוש וקטורי, reranker, מאזן עומסים, ניטור—6–12 חודשים של עבודה. הפלטפורמה שלנו מספקת את אותה פונקציונליות תוך 6–8 שבועות, מהירה פי 4, עם SLA של 99.9% מובטח ו-זמן תגובה P99 מתחת לשנייה. כבר ערכנו בדיקות עומס על הארכיטקטורה עם 2 מיליון מסמכים ו-12 מוצרים—תוצאה: 35% חיסכון בתשתית, 4 ימים להטמעת צוות דרך SDK.
| תכונה | פיתוח פנימי | חיפוש-כשירות |
|---|---|---|
| זמן פריסה | 6–12 חודשים | 6–8 שבועות |
| עלות תשתית | גבוהה (GPUs נפרדים, צוותים מרובים) | עד 35% חיסכון באמצעות GPU משותף |
| SLA | נמוך יותר (ללא ניטור, ללא גיבויים) | 99.9% |
| תמיכה במקורות נתונים חדשים | דורש עבודה מותאמת אישית | תוספים ו-SDK |
מחקר מקרה: חברת SaaS עברה ממקרי Elasticsearch מפוזרים לפלטפורמה מאוחדת. שלושה צוותים התחברו דרך SDK ביום אחד (ללא הבנה של מסדי נתונים וקטוריים או מודלי embedding). עלויות התשתית ירדו ב-35%—חיסכון משמעותי. זמן תגובה ממוצע לחיפוש: 280 אלפיות השנייה P50, 650 אלפיות השנייה P99 על מאגר של 2 מיליון מסמכים.
הגבלת קצב וניטור
אנו שולטים בעומס עם מגבלות דינמיות לפי תוכנית ורושמים כל בקשה ל-TimescaleDB.
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) חיוב ומעקב שימוש
כל חיפוש וכל בקשת 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');
פרטים טכניים של ארכיטקטורת האינדוקס
מסמכים עוברים חלוקה ל-chunks (פיצול ל-chunks של 512 טוקנים עם חפיפה של 64 טוקנים), וקטוריזציה דרך מודל embedding, ולאחר מכן נשמרים ב-Qdrant עם payload מלא. כל דייר מקבל אוסף נפרד. במהלך חיפוש היברידי, התוצאות משולבות באמצעות סכום משוקלל עם reranking מ-cross-encoder.מה כלול
- ביקורת על תשתית החיפוש הקיימת (אם קיימת): ניתוח אינדקסים, מדידות זמן אחזור, זיהוי צווארי בקבוק.
- עיצוב ארכיטקטורת ריבוי-דיירים: בחירת מסד וקטורי (Qdrant, Pinecone, Weaviate), הגדרת בידוד, תכנון קיבולת.
- פיתוח API ו-SDK: RESTful API (FastAPI) ו-SDK בפייתון עם תמיכה בחיפוש היברידי, reranking, וחיפוש RAG עם יצירת תשובות מבוססות RAG עם בקרת הזיות באמצעות few-shot prompting.
- אינטגרציה עם מערכות קיימות: מחברים מותאמים אישית ל-CMS, ERP, DMS.
- ניטור וחיוב: לוחות מחוונים של Grafana, יומני TimescaleDB, מערכת הגבלת קצב לפי תוכנית.
- תיעוד והדרכה: סכימת API מתועדת במלואה, דוגמאות קוד, הדרכה מקוונת של שעתיים לצוותים.
- תמיכה ו-SLA: ערבות זמינות של 99.9%, תגובה לאירועים תוך שעה.
תהליך
- ניתוח — דיון בדרישות, פרופיל עומס, נפח נתונים ומדדים רצויים (זמן אחזור P50/P99).
- עיצוב — יצירת ארכיטקטורה, בחירת מחסנית (מודל embedding, מסד וקטורי, reranker), עיצוב סכמת דיירים.
- הטמעה — פיתוח API, SDK, צינור אינדוקס, בדיקות אינטגרציה.
- בדיקות עומס — על הנתונים שלך (או סינתטיים) מדידת זמן אחזור, תפוקה, זיהוי נקודות כשל.
- פריסה — פריסה על התשתית שלך (AWS/GCP/on-prem) או בענן שלנו. הגדרת ניטור.
- קבלה והדרכה — הדגמה, העברת תיעוד, הדרכת הצוות שלך.
פרמטרי SLA ופלטפורמה
| פרמטר | ערך |
|---|---|
| זמן אחזור P50 | < 300 אלפיות השנייה |
| זמן אחזור P99 | < שנייה אחת |
| זמינות | 99.9% |
| גודל מסמך מקסימלי | 5 MB |
| פורמטים נתמכים | PDF, DOCX, TXT, HTML, JSON |
| שפות | RU, EN, DE, FR, ES (רב-לשוני E5) |
| מקסימום דיירים | ללא הגבלה (קנה מידה אופקי) |
לוחות זמנים: פלטפורמה בסיסית (API + אינדוקס + חיפוש היברידי) — 6–8 שבועות; עם יצירת תשובות, SDK וחיוב — 3–4 חודשים. צרו קשר להערכה מדויקת של הפרויקט שלכם — נחשב עלות ולוח זמנים למשימה שלכם. קבלו ייעוץ מהמהנדסי AI שלנו.







