LangChain и LlamaIndex
🎯 Цель
После прочтения этой главы:
- Знаете разницу между фреймворками LangChain и LlamaIndex
- Можете построить Document loading, splitting, embedding pipeline
- Можете работать с chains и agent (LangChain)
- Быстро создаёте RAG через indexes (LlamaIndex)
- Также знакомитесь с современными alternatives (Pydantic AI, Instructor, raw API)
**Внимание:**В 2024-2026 industry sentiment отворачиваетсяот LangChain (слишком сложный, лишний abstraction). Современный подход: raw API + Instructor + minimal framework. Но LangChain всё ещё используется во многих проектах — знать нужно.
Что нужно изучить
- LangChain: chains, agents, memory, callbacks
- LangChain LCEL(LangChain Expression Language)
- LlamaIndex: indexes, retrievers, query engines
- Document loaders — PDF, HTML, Notion, GitHub
- Text splitters — RecursiveCharacter, Markdown, Code
- Modern alternatives — Pydantic AI, Instructor, raw API
- LangGraph — multi-agent workflows
- LangSmith — observability
Библиотеки
pip install langchain langchain-openai langchain-anthropic langchain-community
pip install llama-index llama-index-llms-openai
pip install pydantic-ai instructor
pip install unstructured pypdf # document loading
Framework comparison
| LangChain | LlamaIndex | Raw API + Instructor | |
|---|---|---|---|
| Learning curve | Крутая | Средняя | Низкая |
| RAG support | Хорошая | Excellent | Manual |
| Agents | Сложно | Хорошая | Нужен LangGraph |
| Production | Mixed reviews | Хорошая | Лучшее |
| Performance | Slow | OK | Самый быстрый |
| Industry trend | ⬇️ | ⬆️ | ⬆️⬆️ |
| Code clarity | Abstract | Better | Самый чёткий |
Рекомендация:
- Новый проект → raw API + Instructor + LlamaIndex(для RAG)
- Существующий LangChain — оставьте, но новые feature мигрируйте
- Complex agent workflows → LangGraph
Примеры кода
LangChain — basic chain
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# LCEL syntax (новый, рекомендуется)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
prompt = ChatPromptTemplate.from_messages([
("system", "Ты вспомогательный assistant. Язык: {language}"),
("user", "{question}"),
])
chain = prompt | llm | StrOutputParser()
# Run
result = chain.invoke({"language": "узбекский", "question": "Что такое Python?"})
print(result)
LangChain — RAG (simple)
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# 1. Load
loader = PyPDFLoader("document.pdf")
docs = loader.load()
# 2. Split
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
chunks = splitter.split_documents(docs)
# 3. Embed + store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(chunks, embeddings)
# 4. Retrieve + answer
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
from langchain.chains import RetrievalQA
qa_chain = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model="gpt-4o-mini"),
retriever=retriever,
return_source_documents=True,
)
result = qa_chain.invoke({"query": "Что говорится о документе?"})
print(result["result"])
LlamaIndex — quickest RAG
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import Settings
# Settings (global)
Settings.llm = OpenAI(model="gpt-4o-mini")
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
# 1. Load (PDF, txt, markdown — разное)
documents = SimpleDirectoryReader("data/").load_data()
# 2. Index (автоматический embedding + chunk)
index = VectorStoreIndex.from_documents(documents)
# 3. Query
query_engine = index.as_query_engine(similarity_top_k=5)
response = query_engine.query("Об этом документе")
print(response)
print(response.source_nodes) # из каких chunks взято
LlamaIndex — Chat engine (multi-turn)
from llama_index.core.memory import ChatMemoryBuffer
memory = ChatMemoryBuffer.from_defaults(token_limit=4000)
chat_engine = index.as_chat_engine(
chat_mode="context",
memory=memory,
system_prompt="Ты опытный assistant. Отвечай только на основе данного контекста.",
)
response = chat_engine.chat("Объясните про этот проект")
print(response.response)
# Follow-up
response = chat_engine.chat("Каковы основные сложности?")
Pydantic AI — современная alternative
from pydantic_ai import Agent
from pydantic import BaseModel
class WeatherInfo(BaseModel):
temperature: float
condition: str
humidity: int
weather_agent = Agent(
model="openai:gpt-4o-mini",
result_type=WeatherInfo,
system_prompt="Ты погодный агент. Сделай прогноз для указанного города.",
)
result = weather_agent.run_sync("Погода в Ташкенте")
print(result.data) # Type-safe WeatherInfo object
Instructor — fully type-safe
import instructor
from openai import OpenAI
from pydantic import BaseModel
client = instructor.from_openai(OpenAI())
class Person(BaseModel):
name: str
age: int
occupation: str
# Guaranteed structured output (retries on failure)
person = client.chat.completions.create(
model="gpt-4o-mini",
response_model=Person,
messages=[{"role": "user", "content": "Меня зовут Али, 30 лет, я developer"}],
)
print(person) # Person(name="Али", age=30, occupation="developer")
LangGraph — multi-agent
from langgraph.graph import StateGraph, END
from typing import TypedDict
class AgentState(TypedDict):
question: str
research: str
answer: str
# Node functions
def researcher(state):
# Search/research
return {"research": "Найденная информация..."}
def writer(state):
# Generate answer
return {"answer": f"Ответ: {state['research']}"}
def reviewer(state):
# Review
if len(state["answer"]) < 50:
return {"answer": state["answer"], "needs_revision": True}
return {"answer": state["answer"], "needs_revision": False}
# Build graph
workflow = StateGraph(AgentState)
workflow.add_node("researcher", researcher)
workflow.add_node("writer", writer)
workflow.add_node("reviewer", reviewer)
workflow.set_entry_point("researcher")
workflow.add_edge("researcher", "writer")
workflow.add_edge("writer", "reviewer")
workflow.add_conditional_edges(
"reviewer",
lambda x: "writer" if x.get("needs_revision") else END,
)
app = workflow.compile()
result = app.invoke({"question": "Что такое Python?"})
Document loaders — variety
# PDF
from langchain_community.document_loaders import PyPDFLoader
docs = PyPDFLoader("file.pdf").load()
# HTML / Website
from langchain_community.document_loaders import WebBaseLoader
docs = WebBaseLoader("https://example.com").load()
# YouTube transcript
from langchain_community.document_loaders import YoutubeLoader
docs = YoutubeLoader.from_youtube_url("https://...", add_video_info=True).load()
# Notion
from langchain_community.document_loaders import NotionDirectoryLoader
docs = NotionDirectoryLoader("notion_export/").load()
# GitHub
from langchain_community.document_loaders import GitHubIssuesLoader
docs = GitHubIssuesLoader("owner/repo", access_token="...").load()
# CSV/Excel
from langchain_community.document_loaders import CSVLoader
docs = CSVLoader("data.csv").load()
Text splitters
from langchain.text_splitter import (
RecursiveCharacterTextSplitter,
MarkdownHeaderTextSplitter,
CharacterTextSplitter,
)
# Recursive — самый распространённый (с разными separator)
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n\n", "\n", ". ", " ", ""],
)
# Markdown — по header
md_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=[
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
])
# Code — semantic splitting
from langchain.text_splitter import Language, RecursiveCharacterTextSplitter
py_splitter = RecursiveCharacterTextSplitter.from_language(
language=Language.PYTHON, chunk_size=1000, chunk_overlap=100
)
Интеграция с backend
FastAPI + LlamaIndex RAG service
from fastapi import FastAPI
from llama_index.core import VectorStoreIndex, StorageContext, load_index_from_storage
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app):
# Load persisted index
storage_context = StorageContext.from_defaults(persist_dir="./index_storage")
app.state.index = load_index_from_storage(storage_context)
app.state.query_engine = app.state.index.as_query_engine(similarity_top_k=5)
yield
app = FastAPI(lifespan=lifespan)
class QueryRequest(BaseModel):
question: str
@app.post("/query")
async def query(req: QueryRequest):
response = await app.state.query_engine.aquery(req.question)
return {
"answer": str(response),
"sources": [
{"text": node.text[:200], "score": node.score}
for node in response.source_nodes
],
}
Production architecture
User → FastAPI → LlamaIndex (in-memory) → Qdrant (vectors) → LLM API
↓
Redis (cache)
↓
Postgres (history, logs)
↓
Langfuse (observability)
Ресурсы
LangChain
- docs: python.langchain.com
- LangChain Academy — бесплатный курс
- LangGraph docs — multi-agent
LlamaIndex
- docs: docs.llamaindex.ai
- LlamaIndex bootcamp — бесплатный
Modern alternatives
- Pydantic AI — ai.pydantic.dev — type-safe agents
- Instructor — python.useinstructor.com — guaranteed JSON
- Haystack — haystack.deepset.ai — production RAG framework
Observability
- Langfuse — langfuse.com (open source)
- LangSmith — от LangChain
- Phoenix (Arize) — open source
🏋️ Упражнения
🟢 Easy
- Простой chain через LangChain LCEL (prompt | llm | parser).
- Сделайте RAG над PDF в 5 строк через LlamaIndex.
- Resume → structured Pydantic через Instructor.
🟡 Medium
- Multi-source RAG: объединённый index из PDF + website + YouTube transcript.
- Conversational RAG: multi-turn с chat history.
- LangGraph workflow: pipeline из 3 agent (researcher → writer → reviewer).
🔴 Hard
- Production RAG service: LlamaIndex + Qdrant + FastAPI + Langfuse. 100+ документов, async query, source citations, monitoring.
- Framework comparison: напишите один и тот же RAG в LangChain, LlamaIndex и raw API, сравните время и точность.
- Migration: перенесите существующий LangChain код на Pydantic AI или raw API.
Capstone
notebooks/month-05/04_langchain_llamaindex.md:
- 50+ документов на узбекском (PDF, websites)
- RAG index через LlamaIndex
- Multi-turn chat engine
- Source citations
- FastAPI + Streamlit UI
✅ Чек-лист
- LangChain LCEL syntax
- LlamaIndex basic RAG
- Pydantic AI / Instructor (современный)
- Document loaders и text splitters
- Multi-source RAG
- Chat engine memory
- LangGraph multi-agent
- Production observability (Langfuse)
Переходим к Vector Databases.