Ответы 2.2
Теория
-
Document loaders (загрузчики документов) — это компоненты LangChain, которые извлекают данные из различных источников и форматов, преобразуя их в унифицированный объект документа (содержащий контент и метаданные). Это служит основой для интеграции таких данных, как PDF, HTML, JSON и других, в приложения на базе LLM.
-
Неструктурированные загрузчики работают с источниками данных, такими как YouTube, Twitter, Figma, Notion и другими. Структурированные загрузчики предназначены для табличных источников (Airbyte, Stripe, Airtable), что позволяет выполнять семантический поиск и Q&A по таблицам.
-
Подготовка окружения включает установку необходимых пакетов, настройку API-ключей (например, OpenAI) и загрузку переменных окружения из файла
.env
. -
PyPDFLoader
загружает PDF-документы по указанному пути, позволяя извлекать текст, очищать и токенизировать его для последующего анализа (подсчёт частоты слов, фильтрация пустых страниц и т. п.). -
Очистка и токенизация: удаление лишних символов, перевод текста к нижнему регистру и разбиение на слова являются базовыми шагами нормализации для точного подсчёта и дальнейшей обработки.
-
Для работы с YouTube используется
GenericLoader
в сочетании сYouTubeAudioLoader
иWhisperParser
, который загружает аудиодорожку и транскрибирует её в текст с помощью модели Whisper. -
Токенизация по предложениям позволяет детально анализировать текст. Сентимент-анализ (например, с помощью
TextBlob
) предоставляет информацию о тональности и субъективности текста. -
Для веб-контента используется
WebBaseLoader(url)
в сочетании с парсингом черезBeautifulSoup
для очистки разметки, извлечения ссылок/заголовков и другой структурированной информации. -
После очистки можно извлекать ключевую информацию (ссылки, заголовки) и создавать сжатое резюме на основе частоты слов и фильтрации стоп-слов.
-
NotionDirectoryLoader
читает экспортированные данные Notion (в формате Markdown), конвертирует их в HTML для парсинга, извлекает структуру (заголовки, ссылки) и сохраняет вDataFrame
для дальнейшей фильтрации и суммаризации. -
Практические рекомендации включают оптимизацию вызовов API (чтобы избежать лишних затрат), предобработку данных сразу после загрузки и активное участие в развитии LangChain путём написания загрузчиков для новых источников.
-
Вклад в разработку новых загрузчиков расширяет экосистему, увеличивая количество поддерживаемых форматов и источников, приносит пользу сообществу и способствует росту экспертизы контрибьютора.
Практика
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)