Пример 1. Суммаризация веб-страницы цепочкой (как в лекции)
Загружаем содержимое веб-страницы загрузчиком и отдаём готовой цепочке, которая «впихивает» документ в промпт и обращается к LLM.
# ai5_1.py
import os
from dotenv import load_dotenv
# Цепочка: объединяет документы и обрабатывает их с помощью LLM
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_community.document_loaders import WebBaseLoader
load_dotenv()
api_key = os.getenv("GEMINI_API_KEY")
# Модель Gemini как LLM для цепочки
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", google_api_key=api_key)
# Загрузчик скачает содержимое веб-страницы
loader = WebBaseLoader("https://habr.com/ru/articles/883604/")
docs = loader.load()
# Шаблон промпта; {context} — место, куда подставится загруженный документ
prompt = ChatPromptTemplate.from_template(
"Напишите краткое изложение следующего текста: {context}")
# Готовая цепочка: документы + промпт -> LLM
chain = create_stuff_documents_chain(llm, prompt)
# invoke обрабатывает вход и возвращает ответ модели
result = chain.invoke({"context": docs})
print(result)
Пример 1b. Та же идея на LCEL (современный синтаксис)
Если документ короткий, цепочку удобно собрать вручную оператором |. Здесь StrOutputParser сразу отдаёт строку.
# ai5_1_lcel.py
import os
from dotenv import load_dotenv
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_community.document_loaders import WebBaseLoader
load_dotenv()
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash",
google_api_key=os.getenv("GEMINI_API_KEY"))
docs = WebBaseLoader("https://habr.com/ru/articles/883604/").load()
text = "\n\n".join(d.page_content for d in docs) # объединяем страницы в один текст
prompt = ChatPromptTemplate.from_template("Краткое изложение текста:\n{context}")
chain = prompt | llm | StrOutputParser() # | — сборка цепочки (pipe)
print(chain.invoke({"context": text}))
Пример 2. Вопрос-ответ по PDF: эмбеддинги + поиск (как в лекции)
Загружаем PDF постранично, строим эмбеддинги страниц в векторном хранилище и ищем по смыслу нужный фрагмент. Здесь Google-эмбеддинги используются через LangChain (в уроке 04 мы делали то же напрямую через FAISS).
# ai5_2.py
import os
import asyncio
from dotenv import load_dotenv
from langchain_community.document_loaders import PyPDFLoader
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_google_genai import GoogleGenerativeAIEmbeddings
# Асинхронно читаем PDF постранично
async def read_pdf():
loader = PyPDFLoader("../files/The-Old-Man-and-The-Sea-by-Ernest-Hemingway.pdf")
pages = []
async for page in loader.alazy_load(): # ленивая асинхронная загрузка страниц
pages.append(page)
return pages
load_dotenv()
api_key = os.getenv("GEMINI_API_KEY")
# Часть библиотек Google ждёт ключ в GOOGLE_API_KEY — продублируем
if "GOOGLE_API_KEY" not in os.environ:
os.environ["GOOGLE_API_KEY"] = api_key
print("Start reading..")
result = asyncio.run(read_pdf())
print("Start embedding..")
# Векторное хранилище: страницы -> эмбеддинги (модель Google)
vector_store = InMemoryVectorStore.from_documents(
result, GoogleGenerativeAIEmbeddings(model="models/embedding-001"))
# Поиск по смыслу: 2 наиболее похожие страницы
docs = vector_store.similarity_search(
"Moment when sharks for the first time attack the fish", k=2)
for doc in docs:
print(f'Page {doc.metadata["page"]}: {doc.page_content}\n')
⚠️ Для длинных документов перед эмбеддингами текст обычно разбивают на чанки сплиттером (
RecursiveCharacterTextSplitter) — так поиск точнее. В примере из лекции страница = фрагмент; для книг/отчётов лучше явное разбиение. Модель models/embedding-001 устарела — см. Справочник.
Пример 3. Полноценный вопрос-ответ (retrieval → промпт → LLM)
Соединим поиск и генерацию: находим релевантные фрагменты и просим LLM ответить только по найденному контексту. Это и есть мини-RAG.
# ai5_qa.py (фрагмент; продолжение примера 2)
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_google_genai import ChatGoogleGenerativeAI
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", google_api_key=api_key)
question = "When do the sharks first attack the fish?"
found = vector_store.similarity_search(question, k=3)
context = "\n\n".join(d.page_content for d in found)
prompt = ChatPromptTemplate.from_template(
"Ответь на вопрос, опираясь ТОЛЬКО на контекст ниже.\n\n"
"Контекст:\n{context}\n\nВопрос: {question}")
chain = prompt | llm | StrOutputParser()
print(chain.invoke({"context": context, "question": question}))