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

Ответы 2.2

Теория

  1. Document loaders (загрузчики документов) — это компоненты LangChain, которые извлекают данные из различных источников и форматов, преобразуя их в унифицированный объект документа (содержащий контент и метаданные). Это служит основой для интеграции таких данных, как PDF, HTML, JSON и других, в приложения на базе LLM.

  2. Неструктурированные загрузчики работают с источниками данных, такими как YouTube, Twitter, Figma, Notion и другими. Структурированные загрузчики предназначены для табличных источников (Airbyte, Stripe, Airtable), что позволяет выполнять семантический поиск и Q&A по таблицам.

  3. Подготовка окружения включает установку необходимых пакетов, настройку API-ключей (например, OpenAI) и загрузку переменных окружения из файла .env.

  4. PyPDFLoader загружает PDF-документы по указанному пути, позволяя извлекать текст, очищать и токенизировать его для последующего анализа (подсчёт частоты слов, фильтрация пустых страниц и т. п.).

  5. Очистка и токенизация: удаление лишних символов, перевод текста к нижнему регистру и разбиение на слова являются базовыми шагами нормализации для точного подсчёта и дальнейшей обработки.

  6. Для работы с YouTube используется GenericLoader в сочетании с YouTubeAudioLoader и WhisperParser, который загружает аудиодорожку и транскрибирует её в текст с помощью модели Whisper.

  7. Токенизация по предложениям позволяет детально анализировать текст. Сентимент-анализ (например, с помощью TextBlob) предоставляет информацию о тональности и субъективности текста.

  8. Для веб-контента используется WebBaseLoader(url) в сочетании с парсингом через BeautifulSoup для очистки разметки, извлечения ссылок/заголовков и другой структурированной информации.

  9. После очистки можно извлекать ключевую информацию (ссылки, заголовки) и создавать сжатое резюме на основе частоты слов и фильтрации стоп-слов.

  10. NotionDirectoryLoader читает экспортированные данные Notion (в формате Markdown), конвертирует их в HTML для парсинга, извлекает структуру (заголовки, ссылки) и сохраняет в DataFrame для дальнейшей фильтрации и суммаризации.

  11. Практические рекомендации включают оптимизацию вызовов API (чтобы избежать лишних затрат), предобработку данных сразу после загрузки и активное участие в развитии LangChain путём написания загрузчиков для новых источников.

  12. Вклад в разработку новых загрузчиков расширяет экосистему, увеличивая количество поддерживаемых форматов и источников, приносит пользу сообществу и способствует росту экспертизы контрибьютора.

Практика

1.

from langchain.document_loaders import PyPDFLoader
import re
from collections import Counter
import nltk

# Загружаем список стоп-слов из NLTK
nltk.download('stopwords')
from nltk.corpus import stopwords

# Инициализируем список английских стоп-слов
stop_words = set(stopwords.words('english'))

# Инициализируем PDF Loader с путём к PDF документу
pdf_loader = PyPDFLoader("path/to/your/document.pdf")

# Загружаем страницы документа
document_pages = pdf_loader.load()

# Функция для очистки, токенизации и удаления стоп-слов из текста
def clean_tokenize_and_remove_stopwords(text):
    words = re.findall(r'\b[a-z]+\b', text.lower())  # Токенизируем и переводим в нижний регистр
    filtered_words = [word for word in words if word not in stop_words]  # Удаляем стоп-слова
    return filtered_words

# Инициализируем объект Counter для подсчёта частоты слов
word_frequencies = Counter()

# Перебираем каждую страницу в документе
for page in document_pages:
    if page.page_content.strip():  # Проверяем, что страница не пустая
        words = clean_tokenize_and_remove_stopwords(page.page_content)
        word_frequencies.update(words)

# Выводим топ-5 наиболее частых слов, исключая стоп-слова
print("Топ-5 наиболее частых слов, исключая стоп-слова:")
for word, freq in word_frequencies.most_common(5):
    print(f"{word}: {freq}")

2.

from langchain.document_loaders.generic import GenericLoader
from langchain.document_loaders.parsers import OpenAIWhisperParser
from langchain.document_loaders.blob_loaders.youtube_audio import YoutubeAudioLoader
import nltk

# Убеждаемся, что ресурсы NLTK загружены (например, punkt для токенизации предложений)
nltk.download('punkt')
from nltk.tokenize import word_tokenize

def transcribe_youtube_video(video_url):
    # Директория, где аудиофайлы будут временно сохранены
    audio_save_directory = "temp_audio/"

    try:
        # Инициализируем загрузчик с YouTube Audio Loader и Whisper Parser
        youtube_loader = GenericLoader(
            YoutubeAudioLoader([video_url], audio_save_directory),
            OpenAIWhisperParser()
        )

        # Загружаем документ (транскрипцию)
        youtube_documents = youtube_loader.load()

        # Получаем доступ к транскрибированному содержимому
        transcribed_text = youtube_documents[0].page_content

        # Токенизируем транскрибированный текст и возвращаем первые 100 слов
        first_100_words = ' '.join(word_tokenize(transcribed_text)[:100])
        return first_100_words
    except Exception as e:
        print(f"Произошла ошибка: {e}")
        return None

# Пример использования
video_url = "https://www.youtube.com/watch?v=example_video_id"
print(transcribe_youtube_video(video_url))

3.

import requests
from bs4 import BeautifulSoup

def load_and_clean_web_content(url):
    try:
        # Получаем содержимое по URL
        response = requests.get(url)
        response.raise_for_status()  # Вызывает HTTPError, если статус 4xx, 5xx

        # Используем BeautifulSoup для парсинга HTML-содержимого
        soup = BeautifulSoup(response.text, 'html.parser')

        # Получаем чистый текст, удаляя все HTML-теги
        clean_text = soup.get_text(separator=' ', strip=True)

        # Выводим очищенный текст
        print(clean_text)
    except requests.exceptions.RequestException as e:
        print(f"Запрос не удался: {e}")
    except Exception as e:
        print(f"Произошла ошибка во время парсинга: {e}")

# Пример использования
url = "https://example.com"
load_and_clean_web_content(url)

4.

import markdown
from bs4 import BeautifulSoup
import os

def convert_md_to_html_and_extract_links(directory_path):
    # Перечисляем все Markdown-файлы в директории
    for filename in os.listdir(directory_path):
        if filename.endswith(".md"):
            # Строим полный путь к файлу
            file_path = os.path.join(directory_path, filename)

            # Читаем Markdown-файл
            with open(file_path, 'r', encoding='utf-8') as md_file:
                md_content = md_file.read()

            # Конвертируем Markdown в HTML
            html_content = markdown.markdown(md_content)

            # Используем BeautifulSoup для парсинга HTML-содержимого
            soup = BeautifulSoup(html_content, 'html.parser')

            # Извлекаем и выводим все ссылки
            links = soup.find_all('a', href=True)
            print(f"Ссылки в {filename}:")
            for link in links:
                print(f"Текст: {link.text}, Href: {link['href']}")
            print("------" * 10)  # Разделитель для ясности

# Пример использования
directory_path = "path/to/your/notion/data"
convert_md_to_html_and_extract_links(directory_path)

5.

from textblob import TextBlob
from langchain.document_loaders.generic import GenericLoader
from langchain.document_loaders.parsers import OpenAIWhisperParser
from langchain.document_loaders.blob_loaders.youtube_audio import YoutubeAudioLoader

def transcribe_and_analyze_sentiment(video_url):
    # Директория, где аудиофайлы будут временно сохранены
    audio_save_directory = "temp_audio/"

    try:
        # Инициализируем загрузчик с YouTube Audio Loader и Whisper Parser
        youtube_loader = GenericLoader(
            YoutubeAudioLoader([video_url], audio_save_directory),
            OpenAIWhisperParser()
        )

        # Загружаем документ (транскрипцию)
        youtube_documents = youtube_loader.load()

        # Получаем доступ к транскрибированному содержимому
        transcribed_text = youtube_documents[0].page_content

        # Анализируем тональность с помощью TextBlob
        blob = TextBlob(transcribed_text)
        polarity = blob.sentiment.polarity

        # Определяем оценку тональности
        if polarity > 0.1:
            sentiment_evaluation = "позитивная"
        elif polarity < -0.1:
            sentiment_evaluation = "негативная"
        else:
            sentiment_evaluation = "нейтральная"

        print(f"Polarity: {polarity:.3f}")
        print(f"Оценка тональности: {sentiment_evaluation}")

        return transcribed_text, polarity, sentiment_evaluation

    except Exception as e:
        print(f"Произошла ошибка: {e}")
        return None, None, None

# Пример использования
video_url = "https://www.youtube.com/watch?v=example_video_id"
text, polarity, sentiment = transcribe_and_analyze_sentiment(video_url)

6.

import pandas as pd
import os
import markdown
from bs4 import BeautifulSoup

def create_notion_dataframe_with_word_count(directory_path):
    # Список для хранения данных о документах
    documents_data = []

    # Перебираем все Markdown-файлы в директории
    for filename in os.listdir(directory_path):
        if filename.endswith(".md"):
            # Строим полный путь к файлу
            file_path = os.path.join(directory_path, filename)

            # Читаем Markdown-файл
            with open(file_path, 'r', encoding='utf-8') as md_file:
                md_content = md_file.read()

            # Конвертируем Markdown в HTML
            html_content = markdown.markdown(md_content)

            # Используем BeautifulSoup для извлечения чистого текста
            soup = BeautifulSoup(html_content, 'html.parser')
            clean_text = soup.get_text()

            # Подсчитываем количество слов
            word_count = len(clean_text.split())

            # Извлекаем заголовок (первая строка или имя файла)
            title = filename.replace('.md', '')
            lines = md_content.split('\n')
            for line in lines:
                if line.strip().startswith('#'):
                    title = line.strip('#').strip()
                    break

            # Добавляем данные в список
            documents_data.append({
                'filename': filename,
                'title': title,
                'word_count': word_count,
                'content': clean_text[:100] + '...'  # Первые 100 символов для предварительного просмотра
            })

    # Создаем DataFrame
    df = pd.DataFrame(documents_data)

    # Сортируем по количеству слов в убывающем порядке
    df_sorted = df.sort_values('word_count', ascending=False)

    # Выводим заголовки 3 самых длинных документов
    print("Заголовки 3 самых длинных документов:")
    for i, row in df_sorted.head(3).iterrows():
        print(f"{i+1}. {row['title']} ({row['word_count']} слов)")

    return df_sorted

# Пример использования
directory_path = "path/to/your/notion/data"
df = create_notion_dataframe_with_word_count(directory_path)
print(df.head())

7.

import requests
from bs4 import BeautifulSoup
import re

def load_and_summarize_web_content(url):
    try:
        # Получаем содержимое по URL
        response = requests.get(url)
        response.raise_for_status()  # Вызывает HTTPError, если статус 4xx, 5xx

        # Используем BeautifulSoup для парсинга HTML-содержимого
        soup = BeautifulSoup(response.text, 'html.parser')

        # Удаляем скрипты и стили для лучшей очистки
        for script in soup(["script", "style"]):
            script.decompose()

        # Получаем чистый текст, удаляя все HTML-теги
        clean_text = soup.get_text(separator=' ', strip=True)

        # Очищаем лишние пробелы и переносы строк
        clean_text = re.sub(r'\s+', ' ', clean_text).strip()

        # Разбиваем текст на предложения
        sentences = re.split(r'[.!?]+', clean_text)
        sentences = [s.strip() for s in sentences if s.strip()]

        if len(sentences) >= 2:
            # Создаем простое резюме из первого и последнего предложений
            summary = f"Первое предложение: {sentences[0]}.\nПоследнее предложение: {sentences[-1]}."
        elif len(sentences) == 1:
            summary = f"Единственное предложение: {sentences[0]}."
        else:
            summary = "Не удалось извлечь предложения из текста."

        print("Простое резюме страницы:")
        print(summary)

        return summary

    except requests.exceptions.RequestException as e:
        print(f"Запрос не удался: {e}")
        return None
    except Exception as e:
        print(f"Произошла ошибка во время парсинга: {e}")
        return None

# Пример использования
url = "https://example.com"
summary = load_and_summarize_web_content(url)