Как получить топ n самых непохожих результатов?

Всем привет! <br/> Я экспериментирую с векторными представлениями текстов и у меня возник вопрос: как с помощью хромадб получить топ 5 самых непохожих результатов?
  • 25 января 2025 г. 21:44
Ответы на вопрос 3
Привет! Чтобы получить топ n самых непохожих результатов в хромадб (или любом другом векторном хранилище), можно воспользоваться расстоянием между векторами. Обычно для этого используются такие метрики, как косинусное расстояние, евклидова метрика или манхэттенское расстояние.

Вот шаги, которые помогут вам получить топ 5 самых непохожих результатов:

1. **Извлечение векторов**: Получите вектор для текста, по которому вы хотите найти непохожие тексты.

2. **Выбор метрики**: Определите, какую метрику вы будете использовать для измерения "непохожести". Например, если вы используете косинусное расстояние, то можете инвертировать результат при поиске (чем меньше значение, тем больше похожесть).

3. **Запрос к хранилищу**: Сделайте запрос к хромадб, чтобы найти все векторы, которые вам нужны. Обычно это делается с использованием функции поиска, если вам нужно ограниченное количество результатов.

4. **Расчет расстояний**: Для каждого найденного вектора вычислите расстояние до вашего вектора.

5. **Сортировка и выбор**: Отсортируйте полученные результаты по возрастанию расстояний и выберите топ 5 наименее похожих (т.е. с наибольшим расстоянием).

Вот пример кода, который иллюстрирует данную процедуру:

```python
import numpy as np

def get_least_similar_vectors(query_vector, vector_store, top_n=5):
    # Список для хранения расстояний и индексов
    distances = []
    
    for idx, vector in enumerate(vector_store):
        # Вычисление расстояния (например, косинус)
        distance = np.linalg.norm(query_vector - vector)  # Или используйте другую метрику
        distances.append((distance, idx))
    
    # Сортировка по расстоянию в порядке убывания
    distances.sort(reverse=True, key=lambda x: x[0])
    
    # Получение индексов top_n наименее похожих векторов
    least_similar_indices = [idx for _, idx in distances[:top_n]]
    
    return least_similar_indices

# Пример использования
query_vector = np.array([...])  # Вектор для запроса
vector_store = [...]  # Список векторов из хромадб
top_n = 5
least_similar = get_least_similar_vectors(query_vector, vector_store, top_n)
print(least_similar)
```

Не забудьте адаптировать этот код к особенностям вашей системы и используемым метрикам.
Я не знаю что такое хромадб. Но если тебе надо найти 5 самых не похожих 
то можно
- кластеризовать результат поиска на 5 кластеров
- взять для каждого кластера близкий вектор

Они и будут максимально непохожие поскольку принадлежат к разным кластерам.

Возможно есть лучшее решение. Но это вполне мне кажется приемлемое.
import chromadb
from chromadb.utils import embedding_functions
import numpy as np

# Инициализация ChromaDB
client = chromadb.Client()

# Создание коллекции
collection = client.create_collection(name="text_collection")

# Добавление текстов и их векторных представлений
texts = ["текст 1", "текст 2", "текст 3", "текст 4", "текст 5"]
embeddings = embedding_functions.DefaultEmbeddingFunction()(texts)

for idx, (text, embedding) in enumerate(zip(texts, embeddings)):
    collection.add(ids=[str(idx)], embeddings=[embedding], documents=[text])

# Получение всех векторов из коллекции
all_embeddings = collection.get(include=["embeddings"])["embeddings"]

# Вычисление среднего расстояния для каждого вектора
def cosine_distance(vec1, vec2):
    return 1 - np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))

average_distances = []
for i, vec1 in enumerate(all_embeddings):
    distances = []
    for j, vec2 in enumerate(all_embeddings):
        if i != j:
            distances.append(cosine_distance(vec1, vec2))
    average_distances.append(np.mean(distances))

# Сортировка по убыванию среднего расстояния
sorted_indices = np.argsort(average_distances)[::-1]

# Вывод топ n самых не похожих результатов
n = 5
top_n_indices = sorted_indices[:n]
top_n_texts = [texts[i] for i in top_n_indices]

print("Топ", n, "самых не похожих текстов:")
for text in top_n_texts:
    print(text)
Похожие вопросы