Семантический поиск (Semantic Search) -- это поиск по смыслу, а не по ключевым словам. Вместо точного совпадения строк семантический поиск понимает, что «как снизить расходы на AI» и «оптимизация стоимости языковых моделей» -- это про одно и то же. Основа семантического поиска -- AI Embeddings: числовые векторы, отражающие смысл текста.
Как работают AI Embeddings
Embedding -- это вектор (массив чисел), в который модель преобразует текст. Тексты с похожим смыслом получают близкие векторы в многомерном пространстве. Для оценки близости используется косинусное расстояние (cosine similarity).
from openai import OpenAI
import numpy as np
client = OpenAI(
base_url="https://api.modelswitch.ru/v1",
api_key="msk_ваш_ключ"
)
def get_embedding(text: str, model: str = "text-embedding-3-small") -> list[float]:
"""Получить embedding для текста через ModelSwitch."""
response = client.embeddings.create(
model=model,
input=text
)
return response.data[0].embedding
def cosine_similarity(a: list[float], b: list[float]) -> float:
"""Вычислить косинусное сходство двух векторов."""
a, b = np.array(a), np.array(b)
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# Пример: сравниваем смысловую близость
emb1 = get_embedding("Как подключить GPT-4o через API")
emb2 = get_embedding("Настройка доступа к языковой модели OpenAI")
emb3 = get_embedding("Рецепт борща с мясом")
print(f"Похожие: {cosine_similarity(emb1, emb2):.4f}") # ~0.87
print(f"Разные: {cosine_similarity(emb1, emb3):.4f}") # ~0.12
Популярные модели для embeddings: text-embedding-3-small (OpenAI, 1536 размерность, $0.02/1M токенов), text-embedding-3-large (3072 размерность, выше качество), cohere-embed-v3 (1024 размерность, мультиязычный). Все доступны через ModelSwitch.
Строим семантический поиск: пошаговый туториал
Создадим полноценный семантический поиск по базе знаний за 4 шага:
Шаг 1: Подготовка данных -- разбиваем документы на чанки (500-1000 токенов каждый) с перекрытием.
def chunk_text(text: str, chunk_size: int = 500, overlap: int = 50) -> list[str]:
"""Разбить текст на чанки с перекрытием."""
words = text.split()
chunks = []
for i in range(0, len(words), chunk_size - overlap):
chunk = " ".join(words[i:i + chunk_size])
if chunk:
chunks.append(chunk)
return chunks
Шаг 2: Генерация embeddings -- преобразуем каждый чанк в вектор через API.
documents = [
"ModelSwitch -- это прокси-биллинг для AI API...",
"Для подключения измените base_url и api_key...",
"Оплата доступна в рублях для юридических лиц..."
]
# Batch-генерация embeddings (эффективнее поодиночке)
response = client.embeddings.create(
model="text-embedding-3-small",
input=documents
)
embeddings = [item.embedding for item in response.data]
Шаг 3: Сохранение в векторную БД -- для production используйте специализированную БД (Qdrant, Pinecone, Weaviate, pgvector). Для прототипа достаточно NumPy.
Шаг 4: Поиск -- преобразуем запрос пользователя в вектор и находим ближайшие документы.
def semantic_search(query: str, documents: list[str],
embeddings: list[list[float]], top_k: int = 3) -> list[dict]:
"""Поиск наиболее релевантных документов."""
query_emb = get_embedding(query)
scores = [cosine_similarity(query_emb, emb) for emb in embeddings]
ranked = sorted(zip(scores, documents), reverse=True)
return [{"score": s, "text": t} for s, t in ranked[:top_k]]
results = semantic_search("Как оплатить API для компании?", documents, embeddings)
for r in results:
print(f"[{r['score']:.3f}] {r['text'][:100]}...")
От поиска к RAG: генерация ответов на основе контекста
Семантический поиск -- это фундамент RAG (Retrieval-Augmented Generation). Добавляем один шаг: найденные документы передаём LLM как контекст для генерации ответа.
def rag_answer(query: str, documents: list[str],
embeddings: list[list[float]]) -> str:
"""RAG: поиск контекста + генерация ответа."""
# 1. Поиск релевантного контекста
results = semantic_search(query, documents, embeddings, top_k=3)
context = "
".join([r["text"] for r in results])
# 2. Генерация ответа с контекстом
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": f"Отвечай на вопросы на основе контекста.
Контекст:
{context}"},
{"role": "user", "content": query}
]
)
return response.choices[0].message.content
Оптимизация: советы для production
- Размер чанков -- экспериментируйте с 256-1024 токенами. Слишком маленькие чанки теряют контекст, слишком большие -- снижают точность поиска
- Метаданные -- сохраняйте вместе с embedding метаданные: источник, дату, категорию. Это позволяет фильтровать результаты
- Hybrid search -- комбинируйте семантический поиск с keyword search (BM25) для лучших результатов
- Re-ranking -- после первичного поиска по embeddings используйте Cross-Encoder модель для более точного ранжирования top-20 результатов
- Кэширование -- embeddings для документов генерируются один раз. Кэшируйте embedding запроса, если пользователи часто задают похожие вопросы
Семантический поиск с AI Embeddings -- это технология, которая кардинально улучшает пользовательский опыт в любом приложении с поиском. Через ModelSwitch вы получаете доступ к лучшим embedding-моделям через один API и можете легко переключаться между ними для оптимизации качества и стоимости.