Перейти к содержанию

Ответы 2.4

Теория

  1. Назначение эмбеддингов: Преобразование текста в числовые векторы, которые сохраняют смысловое значение, позволяя компьютерам «понимать» текст.
  2. Семантическая близость: Отражается в схожести векторов слов/предложений с похожим значением в многомерном пространстве.
  3. Обучение эмбеддингов: Происходит на корпусах текстов, где векторы слов зависят от контекста их употребления (дистрибутивная семантика).
  4. Эмбеддинги в семантическом поиске: Позволяют находить релевантные документы по смыслу, даже без точных совпадений ключевых слов.
  5. Сопоставление документов и запросов: Эмбеддинги документа описывают его общий смысл, а эмбеддинг запроса — намерение пользователя; их сравнение выявляет релевантные соответствия.
  6. Векторное хранилище: База данных для эмбеддингов, оптимизированная для быстрого поиска ближайших соседей.
  7. Выбор хранилища: Зависит от объема данных, требований к персистентности и назначения (исследование, прототип, продакшен).
  8. Chroma для прототипирования: Удобна для прототипов и небольших наборов данных (работает в памяти, быстро), но имеет ограничения по персистентности и масштабированию.
  9. Типовой конвейер: Разделение текста → генерация эмбеддингов → индексация в векторном хранилище → обработка запроса → генерация ответа.
  10. Разделение текста: Улучшает гранулярность; сопоставление происходит на уровне смысловых фрагментов (чанков), а не целых документов.
  11. Генерация эмбеддингов: Преобразует текст в векторы, пригодные для вычислительного сравнения.
  12. Индексация в хранилище: Обеспечивает быстрый поиск наиболее схожих по смыслу фрагментов.
  13. Обработка запроса: Создание эмбеддинга запроса и поиск похожих фрагментов с использованием метрик (косинусное сходство, евклидово расстояние и др.).
  14. Генерация ответа: Использует найденные фрагменты и исходный запрос для формирования связного ответа.
  15. Настройка окружения: Установка необходимых библиотек, ключей API и конфигурация для работы с эмбеддингами и векторным хранилищем.
  16. Загрузка и разделение документов: Критически важны для эффективного управления текстом и повышения качества поиска.
  17. Иллюстрация схожести: Может быть показана с помощью скалярного произведения или косинусного сходства.
  18. Особенности Chroma: Важно учитывать директорию персистентности, очистку старых данных и правильную инициализацию коллекции.
  19. Поиск по схожести: Находит наиболее релевантные фрагменты по отношению к запросу.
  20. Типичные сбои и их устранение: Дубликаты и нерелевантные результаты могут быть исправлены путем фильтрации и тонкой настройки конвейера.

Практические задания

  1. def generate_embeddings(sentences):
        """
        Генерирует простой заглушечный эмбеддинг для каждого предложения на основе его длины.
    
        Параметры:
        - sentences (list of str): Список предложений для генерации эмбеддингов.
    
        Возвращает:
        - list of int: Список эмбеддингов, где каждый эмбеддинг - это длина соответствующего предложения.
        """
        return [len(sentence) for sentence in sentences]
    
    def cosine_similarity(vector_a, vector_b):
        """
        Вычисляет косинусное сходство между двумя векторами.
    
        Параметры:
        - vector_a (list of float): Первый вектор.
        - vector_b (list of float): Второй вектор.
    
        Возвращает:
        - float: Косинусное сходство между `vector_a` и `vector_b`.
        """
        dot_product = sum(a*b for a, b in zip(vector_a, vector_b))
        magnitude_a = sum(a**2 for a in vector_a) ** 0.5
        magnitude_b = sum(b**2 for b in vector_b) ** 0.5
        return dot_product / (magnitude_a * magnitude_b)
    
    # Пример использования:
    sentences = ["Hello, world!", "This is a longer sentence.", "Short"]
    embeddings = generate_embeddings(sentences)
    print("Эмбеддинги:", embeddings)
    
    vector_a = [1, 2, 3]
    vector_b = [2, 3, 4]
    similarity = cosine_similarity(vector_a, vector_b)
    print("Косинусная близость:", similarity)
    
  2. def cosine_similarity(vector_a, vector_b):
        """Вычисляет косинусное сходство между двумя векторами."""
        dot_product = sum(a*b for a, b in zip(vector_a, vector_b))
        magnitude_a = sum(a**2 for a in vector_a) ** 0.5
        magnitude_b = sum(b**2 for b in vector_b) ** 0.5
        if magnitude_a == 0 or magnitude_b == 0:
            return 0  # Избегаем деления на ноль для предотвращения ошибок
        return dot_product / (magnitude_a * magnitude_b)
    
  3. class SimpleVectorStore:
        def __init__(self):
            self.vectors = []  # Инициализируем пустой список для хранения векторов
    
        def add_vector(self, vector):
            """Добавляет вектор в хранилище."""
            self.vectors.append(vector)
    
        def find_most_similar(self, query_vector):
            """Находит и возвращает вектор, наиболее похожий на `query_vector`."""
            if not self.vectors:
                return None  # Возвращаем None, если хранилище пусто
            similarities = [cosine_similarity(query_vector, vector) for vector in self.vectors]
            max_index = similarities.index(max(similarities))
            return self.vectors[max_index]
    
  4. import sys
    
    def split_text_into_chunks(text, chunk_size):
        """Разбивает заданный текст на чанки указанного размера."""
        return [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]
    
    def load_and_print_chunks(file_path, chunk_size):
        """Загружает текст из файла, разбивает его на чанки и выводит каждый чанк."""
        try:
            with open(file_path, 'r') as file:
                text = file.read()
                chunks = split_text_into_chunks(text, chunk_size)
                for i, chunk in enumerate(chunks, 1):
                    print(f"Чанк {i}:\n{chunk}\n{'-'*50}")
        except FileNotFoundError:
            print(f"Ошибка: Файл '{file_path}' не найден.")
        except Exception as e:
            print(f"Произошла непредвиденная ошибка: {e}")
    
    if __name__ == "__main__":
        if len(sys.argv) != 3:
            print("Использование: python script.py <путь_к_файлу> <размер_чанка>")
            sys.exit(1)
        file_path = sys.argv[1]
        chunk_size = int(sys.argv[2])
        load_and_print_chunks(file_path, chunk_size)
    
  5. # Предполагаем, что SimpleVectorStore и функция cosine_similarity определены ранее.
    
    def generate_query_embedding(query):
        """
        Генерирует простой заглушечный эмбеддинг для запроса на основе его длины.
        В реальном сценарии для генерации эмбеддингов использовалась бы модель.
        """
        return [len(query)]
    
    def query_processing(store, query):
        """
        Обрабатывает запрос: генерирует эмбеддинг, ищет наиболее похожий фрагмент в векторном хранилище
        и выводит его.
        """
        query_embedding = generate_query_embedding(query)
        most_similar = store.find_most_similar(query_embedding)
        if most_similar is not None:
            print("Наиболее похожий фрагмент документа:", most_similar)
        else:
            print("Фрагменты документов не найдены.")
    
  6. def remove_duplicates(document_chunks):
        """Удаляет дублирующиеся фрагменты документов на основе точного совпадения их содержимого."""
        unique_chunks = []
        for chunk in document_chunks:
            if chunk not in unique_chunks:
                unique_chunks.append(chunk)
        return unique_chunks
    
  7. # Инициализация SimpleVectorStore для демонстрации
    store = SimpleVectorStore()
    
    # Заглушка для фрагментов документов и их эмбеддингов для примера
    document_chunks = ["Document chunk 1", "Document chunk 2", "Document chunk 3"]
    # Симулируем эмбеддинги для этих фрагментов, например, на основе их длины
    document_embeddings = [[len(chunk)] for chunk in document_chunks]
    
    # Добавляем сгенерированные эмбеддинги документов в хранилище
    for embedding in document_embeddings:
        store.add_vector(embedding)
    
    # Проводим поиск по сходству с использованием примера запроса
    query = "Document"
    query_embedding = generate_query_embedding(query)
    
    # Находим наиболее похожие фрагменты документов на основе косинусного сходства
    similarities = [(cosine_similarity(query_embedding, doc_embedding), idx) for idx, doc_embedding in enumerate(document_embeddings)]
    similarities.sort(reverse=True)  # Сортируем по сходству в порядке убывания
    top_n_indices = [idx for _, idx in similarities[:3]]  # Получаем индексы топ-3 наиболее похожих фрагментов
    
    # Выводим ID или содержимое топ-3 наиболее похожих фрагментов документов
    print("Топ-3 наиболее похожих фрагмента документов:")
    for idx in top_n_indices:
        print(f"{idx + 1}: {document_chunks[idx]}")
    
  8. def embed_and_store_documents(document_chunks):
        """
        Генерирует эмбеддинги для каждого фрагмента документа и сохраняет их в `SimpleVectorStore`.
    
        Параметры:
        - document_chunks (list of str): Список фрагментов документов в виде строк.
    
        Возвращает:
        - SimpleVectorStore: Векторное хранилище, инициализированное эмбеддингами документов.
        """
        store = SimpleVectorStore()
        for chunk in document_chunks:
            # Заглушка для генерации эмбеддинга на основе длины фрагмента
            embedding = [len(chunk)]
            store.add_vector(embedding)
        return store
    
  9. import json
    
    def save_vector_store(store, filepath):
        """
        Сохраняет состояние объекта `SimpleVectorStore` в указанный файл.
    
        Параметры:
        - store (SimpleVectorStore): Векторное хранилище для сохранения.
        - filepath (str): Путь к файлу, где будет сохранено хранилище.
        """
        with open(filepath, 'w') as file:
            json.dump(store.vectors, file)
    
    def load_vector_store(filepath):
        """
        Загружает состояние объекта `SimpleVectorStore` из указанного файла.
    
        Параметры:
        - filepath (str): Путь к файлу, из которого нужно загрузить хранилище.
    
        Возвращает:
        - SimpleVectorStore: Загруженное векторное хранилище.
        """
        store = SimpleVectorStore()
        with open(filepath, 'r') as file:
            store.vectors = json.load(file)
        return store
    
    def vector_store_persistence():
        """Демонстрирует сохранение и загрузку состояния `SimpleVectorStore`."""
        store = SimpleVectorStore()  # Предполагаем, что хранилище уже заполнено данными
        filepath = 'vector_store.json'
    
        # Пример сохранения и загрузки данных
        save_vector_store(store, filepath)
        loaded_store = load_vector_store(filepath)
        print("Векторное хранилище загружено с векторами:", loaded_store.vectors)
    
  10. def evaluate_search_accuracy(queries, expected_chunks):
        """
        Оценивает точность поиска по сходству для списка запросов и их ожидаемых результатов.
    
        Параметры:
        - queries (list of str): Список запросов в виде строк.
        - expected_chunks (list of str): Список ожидаемых наиболее похожих фрагментов документов,
          соответствующих каждому запросу.
    
        Возвращает:
        - float: Точность результатов поиска (доля правильно найденных фрагментов).
        """
        correct = 0
        # Эмбеддинг и сохранение документов плюс некоторые дополнительные для обеспечения уникальности
        store = embed_and_store_documents(expected_chunks + list(set(expected_chunks) - set(queries)))
    
        for query, expected in zip(queries, expected_chunks):
            query_embedding = generate_query_embedding(query)
            most_similar = store.find_most_similar(query_embedding)
            # Предполагаем, что expected_chunks — это эмбеддинги документов, сохраненные в том же порядке.
            if most_similar and most_similar == [len(expected)]:
                correct += 1
    
        accuracy = correct / len(queries)
        return accuracy
    
    # Предполагаем, что embed_and_store_documents, generate_query_embedding и SimpleVectorStore
    # реализованы, как описано выше.