LangChain w 7 prostych krokach – kompleksowy przewodnik dla początkujących #EN68

TL;DR

  • LangChain to otwartoźródłowy framework do tworzenia aplikacji LLM, który łączy modele językowe z zewnętrznymi źródłami danych i narzędziami obliczeniowymi
  • Frameworka używa się głównie do budowania chatbotów, aplikacji RAG (Retrieval Augmented Generation) i systemów agentowych
  • Łańcuchy (chains) w LangChain to sekwencje połączonych komponentów przetwarzających zapytania użytkownika z pomocą LLM
  • Protokół Runnable pozwala na łączenie komponentów w łańcuchy przy użyciu operatora pipe (|)
  • Splittery umożliwiają podział dokumentów na fragmenty, które można przechowywać w bazach wektorowych
  • RAG (Retrieval Augmented Generation) to technika wzbogacania wiedzy LLM o zewnętrzne dane poprzez indeksowanie i pobieranie kontekstu
  • Agenty to programy wykorzystujące LLM do podejmowania decyzji o kolejności wykonywania działań i używaniu narzędzi

Czym jest LangChain i dlaczego warto się go nauczyć?

LangChain to otwartoźródłowy framework do tworzenia aplikacji opartych na modelach językowych (LLM), który umożliwia deweloperom łączenie LLM z zewnętrznymi źródłami obliczeń i danych. Framework upraszcza wdrażanie aplikacji LLM, dostarczając narzędzia do inspekcji, monitorowania i ewaluacji.

Główne funkcje LangChain:

  • ✅ Integracja LLM z zewnętrznymi źródłami danych
  • ✅ Zarządzanie kontekstem i pamięcią konwersacji
  • ✅ Budowanie złożonych łańcuchów przetwarzania
  • ✅ Tworzenie agentów wybierających narzędzia na podstawie kontekstu
  • ✅ Monitorowanie i ocena wydajności aplikacji LLM

Istnieją co najmniej dwa ważne powody, dla których warto poznać LangChain:

  1. Przejście do nowej generacji języków programowania – LangChain ułatwia tworzenie pipelinów przetwarzających język naturalny na wartościowe wyniki. Jest to krok w ewolucji programowania, gdzie przechodzimy od języków niskiego poziomu (maszynowy, asembler), przez języki wysokiego poziomu (Python, Java), do języka naturalnego jako najwyższego poziomu abstrakcji. Z obecną generacją najlepszych LLM możemy już pisać działający kod za pomocą instrukcji w języku naturalnym.
  2. Ekosystem narzędzi na LangChain – Szczególnie istotny jest Langgraph (rozszerzenie LangChain), który umożliwia budowanie złożonych interakcji między agentami i ludźmi oraz tworzenie systemów wieloagentowych. Langgraph, choć pojawił się później niż konkurencyjne rozwiązania jak Autogen czy Crewai, pozwala na tworzenie zaawansowanych systemów komunikacji między agentami, umożliwiając podział zadań i asynchroniczne wykonywanie operacji.

Rodzaje aplikacji budowanych z LangChain:

Typ aplikacji Zastosowania Kluczowe komponenty
Chatboty Marketing, obsługa klienta, edukacja Pamięć konwersacji, łańcuchy
Aplikacje RAG (Q&A) Podsumowywanie dokumentów, analiza danych, generowanie kodu Retrievery, bazy wektorowe, splittery
Systemy agentowe Zarządzanie łańcuchem dostaw, optymalizacja przychodów, zarządzanie operacjami Narzędzia, multiagenty, Langgraph

Konfiguracja środowiska deweloperskiego

Checklista konfiguracji LangChain:

  • Uzyskaj klucze API do wybranego dostawcy LLM (OpenAI, Anthropic, itp.)
  • Stwórz plik .env do bezpiecznego przechowywania kluczy API
  • Zainstaluj wymagane biblioteki:
    • langchain – rdzeń frameworka
    • langchain-community – integracje z zewnętrznymi serwisami
    • Biblioteki dostawców LLM (np. openai, anthropic)
    • Dodatkowe zależności do konkretnych zastosowań (np. redis, sentence-transformers)

Przykładowa konfiguracja w notatniku Colab obejmuje:

python
# Instalacja niezbędnych bibliotek
# pip install python-dotenv langchain langchain-community openai anthropic

# Ładowanie zmiennych środowiskowych
# Połączenie z modelami LLM
from langchain.chat_models import ChatOpenAI, ChatAnthropic

llm_gpt4 = ChatOpenAI(model="gpt-4")
llm_claude = ChatAnthropic(model="claude-3-opus-20240229")

Budowanie łańcuchów (Chains)

Czym są łańcuchy w LangChain?

Łańcuch (chain) w LangChain to sekwencja połączonych komponentów, które przetwarzają zapytanie użytkownika wykorzystując jeden lub więcej modeli LLM w celu wygenerowania wartościowego wyniku. Wynikiem może być odpowiedź na pytanie, podsumowanie dokumentu, rekomendacja, kod wykonywalny lub dane JSON dla API.

Komponenty łańcucha:

  • 📝 Prompty – szablony instrukcji z placeholderami na zmienne
  • 🧠 LLM/Chat Models – modele językowe przetwarzające zapytania
  • 🔄 Parsery wyjścia – przetwarzają surowe odpowiedzi LLM na strukturyzowane dane
  • 🛠️ Narzędzia – pozwalają LLM na dostęp do zewnętrznych zasobów i wykonywanie działań
  • 🔧 Funkcje – niestandardowe funkcje Pythona przekształcone w runnables

Łańcuchy można porównać do pipelinów danych: tak jak pipeline danych przetwarza surowe dane na czyste tabele, tak łańcuch LLM przetwarza zapytanie na wartościowy wynik przy użyciu wywołań LLM, funkcji i dodatkowych danych.

Szablony promptów i ładowarki dokumentów

Szablony promptów (prompt templates) to predefiniowane wzorce promptów z placeholderami na zmienne. Przykład:

python
from langchain.prompts import PromptTemplate

template = "Napisz krótkie podsumowanie na temat: {topic}"
prompt = PromptTemplate(input_variables=["topic"], template=template)

# Tworzenie łańcucha
chain = prompt | llm_gpt4

# Wywołanie łańcucha
result = chain.invoke({"topic": "Sztuczna inteligencja"})

Ładowarki dokumentów (document loaders) umożliwiają wczytywanie danych z różnych źródeł. Transkrypt pokazuje praktyczny przykład wykorzystania ładowarki YouTube:

python
from langchain_community.document_loaders import YoutubeLoader

# Załadowanie transkryptu z filmu YouTube
loader = YoutubeLoader.from_youtube_url("https://youtube.com/watch?v=example", add_video_info=True)
documents = loader.load()

# Transkrypt można uzyskać przez:
transcript = documents[0].page_content

# Tworzenie łańcucha do podsumowania transkryptu
summary_prompt = PromptTemplate.from_template(
    "Podsumuj poniższy transkrypt z YouTube:\n\n{video_transcript}"
)
summary_chain = summary_prompt | llm_gpt4

# Wywołanie łańcucha podsumowującego
summary = summary_chain.invoke({"video_transcript": documents})

Ten przykład pokazuje, jak można wykorzystać loader do pobrania transkryptu z YouTube, a następnie użyć go w łańcuchu do generowania podsumowania. Możemy bezpośrednio przekazać dokumenty do łańcucha bez konieczności wyodrębniania surowego tekstu.

Protokół Runnable i język wyrażeń LangChain

Język wyrażeń LangChain upraszcza budowanie złożonych łańcuchów z podstawowych komponentów za pomocą operatora pipe (|), który łączy różne elementy przekazując wyjście jednego do kolejnego.

Runnables (elementy wykonywalne) to jednostki pracy, które można wywołać, przetwarzać wsadowo, streamować i składać.

Kluczowe typy Runnables w LangChain:

Typ Runnable Przeznaczenie Typowe zastosowanie
Runnable Sequence Łączy komponenty sekwencyjnie Tworzenie pipeline’ów przetwarzania
Runnable Lambda Zamienia funkcję Python w element łańcucha Niestandardowe transformacje danych
Runnable PassThrough Przekazuje dane bez zmian lub dodaje klucze Zachowanie danych wejściowych, dodawanie nowych wartości
Runnable Parallel Uruchamia wiele runnables jednocześnie Równoległe przetwarzanie, branching łańcuchów

Metody dostępne dla każdego Runnable:

  • ▶️ invoke() – wywołanie z pojedynczym wejściem
  • 📊 batch() – przetwarzanie wielu wejść jednocześnie
  • 🔄 stream() – strumieniowanie wyników w czasie rzeczywistym
  • 📋 bind() – tworzenie nowego Runnable z przypisanymi argumentami

Przykład tworzenia łańcucha z parserem wyjścia:

python
from langchain.schema.output_parser import StrOutputParser

chain = prompt | llm_gpt4 | StrOutputParser()
result = chain.invoke({"context": "LangChain to framework dla LLM"})

Dodanie funkcji jako runnable lambda:

python
def calculate_length(text):
    return len(text)

# Automatyczne opakowanie funkcji w Runnable Lambda
chain_with_length = prompt | llm_gpt4 | StrOutputParser() | calculate_length

RunnableParallel – równoległe wykonywanie operacji

RunnableParallel pozwala na jednoczesne uruchomienie kilku komponentów z tym samym wejściem, a następnie zwrócenie słownika z wynikami. Jest to szczególnie przydatne, gdy chcemy wykonać kilka niezależnych operacji na tych samych danych:

python
from langchain_core.runnables import RunnableParallel

# Tworzymy dwa różne łańcuchy
summary_chain = prompt | llm_gpt4 | StrOutputParser()

def calculate_length(text):
    return len(text)
length_chain = lambda x: calculate_length(x)

# Łączymy je w RunnableParallel
parallel_chain = RunnableParallel(
    summary=summary_chain,
    length=length_chain
)

# Otrzymamy słownik z wynikami obu łańcuchów
result = parallel_chain.invoke({"context": "LangChain to framework dla LLM"})
# result = {"summary": "...", "length": 123}

RunnableParallel jest również pomocny przy przygotowywaniu danych dla kolejnych komponentów łańcucha, gdy trzeba przetworzyć dane w sposób, który wymaga kilku równoległych operacji.

Splitters i Retrievers

Dzielenie danych na fragmenty

Splittery tekstu to narzędzia do dzielenia dużych dokumentów na mniejsze fragmenty. LangChain oferuje różne typy splitterów:

  • RecursiveCharacterTextSplitter – próbuje zachować powiązane fragmenty tekstu obok siebie
  • Splittery dla HTML, Markdown, kodu, znaków i tokenów

Przykład użycia:

python
from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=100
)
chunks = splitter.split_documents(documents)

Retrievery i bazy wektorowe

Retriever w LangChain to interfejs zwracający dokumenty na podstawie zapytania. Najczęściej opiera się na wektorowej bazie danych, ale sam nie przechowuje dokumentów.

Przewodnik wdrażania retrievera krok po kroku:

  1. Podziel dane na fragmenty
    • Wybierz odpowiedni splitter (np. RecursiveCharacterTextSplitter)
    • Określ rozmiar fragmentów (chunk_size) i nakładanie (chunk_overlap)
    • Wywołaj split_documents() lub split_text()
  2. Generuj embeddingi i ładuj do bazy wektorowej
    • Wybierz model embeddingów (np. OpenAI, HuggingFace)
    • Wybierz bazę wektorową (Redis, Pinecone, Chroma, FAISS)
    • Skonfiguruj połączenie z bazą
    • Użyj metody from_documents() do załadowania danych
  3. Utwórz retriever
    • Wywołaj metodę as_retriever() na bazie wektorowej
    • Skonfiguruj parametry wyszukiwania (typ, ilość wyników)
    • Przetestuj retriever z przykładowymi zapytaniami

Transkrypt przedstawia praktyczny przykład z Redis:

python
from langchain.vectorstores import Redis
from langchain.embeddings import HuggingFaceEmbeddings

# Utworzenie embeddingów (darmowe z HuggingFace)
embeddings = HuggingFaceEmbeddings()

# Konfiguracja połączenia z Redis
redis_url = "redis://username:password@host:port"

# Załadowanie podzielonych dokumentów do Redis
vectorstore = Redis.from_documents(
    chunks,
    embeddings,
    redis_url=redis_url,
    index_name="youtube"
)

# Utworzenie retrievera z parametrami wyszukiwania
retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 10}  # pobierz 10 najlepszych dopasowań
)

# Wyszukiwanie podobnych dokumentów
docs = retriever.invoke("data analysis")

Ten przykład pokazuje pełny proces: od podziału dokumentów, przez generowanie embeddingów, po zapisanie ich w Redis i wykonanie wyszukiwania. LangChain upraszcza ten proces, zapewniając spójny interfejs dla różnych baz wektorowych.

Tworzenie aplikacji RAG

Tworzenie aplikacji RAG

RAG (Retrieval Augmented Generation) to technika wzbogacania wiedzy LLM zewnętrznymi danymi.

Dwa główne etapy RAG:

Etap 1: Indeksowanie danych (wykonywane raz)

  • ↪️ Podział dokumentów na fragmenty (chunking)
  • ↪️ Tworzenie embeddingów wektorowych
  • ↪️ Zapisywanie wektorów w bazie

Etap 2: Wyszukiwanie i generowanie (przy każdym zapytaniu)

  • ↪️ Przekształcenie zapytania użytkownika w embedding
  • ↪️ Wyszukanie podobnych fragmentów w bazie wektorowej
  • ↪️ Skonstruowanie prompta z zapytaniem i kontekstem
  • ↪️ Wygenerowanie odpowiedzi przez LLM

Flow danych w procesie RAG:

Zapytanie użytkownika → Retriever → Kontekst + Zapytanie → LLM → Odpowiedź

Precision i Recall – kluczowe metryki dla retrievalu

Przy budowaniu aplikacji biznesowych opartych na RAG, szczególnie chatbotów, kluczowe są dwie metryki:

Metryka Definicja Znaczenie w RAG
Precision (precyzja) Jaki procent znalezionych dokumentów jest faktycznie istotny Jakość kontekstu dostarczanego do LLM
Recall (pełność) Jaki procent wszystkich istotnych dokumentów został znaleziony Kompletność informacji dostępnych dla LLM

Dlaczego kontrola nad retrievalem jest kluczowa:

Problem z abstrakcją retrievalu:

  • OpenAI Assistants i podobne API abstrahują proces retrievalu
  • Brak kontroli nad procesem wyszukiwania = niemożność optymalizacji
  • CRO (optymalizacja współczynników konwersji) dla chatbotów wymaga kontroli nad retrievalem

Konsekwencje dla biznesu:

  • Tak jak firmy optymalizują strony web pod CRO
  • Tak będą optymalizować retrievery w chatbotach
  • Kontrola nad retrievalem to kontrola nad konwersją

Jak zauważa autor: „Pomyśl, ile firm obecnie zajmuje się CRO (optymalizacją współczynników konwersji) na stronach internetowych. Wraz z wdrażaniem chatbotów, znaczna część pracy nad CRO będzie koncentrować się na optymalizacji retrieveru.”

Przykład łańcucha RAG:

python
from langchain.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template("""
Odpowiedz na pytanie bazując TYLKO na poniższym kontekście:
{context}

Pytanie: {question}
""")

def format_docs(docs):
    return "\n\n".join([d.page_content for d in docs])

rag_chain = {
    "context": lambda input: format_docs(retriever.invoke(input["question"])),
    "question": lambda input: input["question"]
} | prompt | llm_gpt4 | StrOutputParser()

response = rag_chain.invoke({"question": "Co możemy zrobić z llama 3?"})

Narzędzia (Tools) w LangChain

Narzędzia (Tools) w LangChain

Narzędzia (tools) w LangChain to interfejsy, których mogą używać agenty, łańcuchy lub LLM do interakcji ze światem. Podobnie jak ludzie potrzebują narzędzi do wykonywania zadań, LLM potrzebują narzędzi do wykonywania obliczeń lub dostępu do dodatkowych danych.

Wbudowane narzędzia w LangChain:

Kategoria Przykłady narzędzi Zastosowanie
Wyszukiwanie informacji WikipediaTool, DuckDuckGoTool, YouTubeTool Dostęp do zewnętrznych źródeł wiedzy
Wykonywanie kodu PythonREPLTool, BashTool Wykonywanie obliczeń, operacje na systemie
Dostęp do danych SqlDatabaseTool, SpreadsheetTool Operacje na bazach danych i arkuszach
API zewnętrzne RequestsTool, ZapierTool Integracja z zewnętrznymi serwisami
Toolkity AirByte, GitHub, GitLab Zestawy narzędzi do konkretnych platform

Dwa sposoby używania narzędzi:

  1. Bezpośrednie wywołanie – ręczne wywoływanie metody run() narzędzia z konkretnym zapytaniem
    python
    results = youtube_tool.run("langchain tutorial")
  2. Przypisanie do LLM – tworzenie LLM z dostępem do narzędzi, który może je dynamicznie wywoływać
    python
    llm_with_tools = llm_gpt4.bind_tools([youtube_tool])

Kiedy używać którego podejścia:

Bezpośrednie wywołanie – gdy znasz dokładną kolejność operacji i którą operację należy wykonać ✅ Przypisanie do LLM – gdy chcesz pozwolić LLM zdecydować, które narzędzie użyć i kiedy

Przykład z YouTubeTool:

python
from langchain_community.tools import YouTubeSearchTool

youtube_tool = YouTubeSearchTool()
results = youtube_tool.run("langchain tutorial")

# Przypisanie narzędzia do LLM
llm_with_tools = llm_gpt4.bind_tools([youtube_tool])
response = llm_with_tools.invoke("Find videos about LangChain")

# Tworzenie łańcucha z narzędziem
def extract_args(ai_message):
    tool_calls = ai_message.tool_calls
    return tool_calls[0].args

chain = llm_with_tools | extract_args | youtube_tool
results = chain.invoke("find some rabbit metrics videos on LangChain")

Tworzenie własnych narzędzi z dekoratorem @tool

LangChain umożliwia tworzenie własnych narzędzi przy użyciu dekoratora @tool, który zamienia funkcję w narzędzie dostępne dla agentów:

python
from langchain.tools import tool

@tool
def transcribe_video(video_url: str) -> str:
    """Transkrybuje film z YouTube."""
    loader = YoutubeLoader.from_youtube_url(video_url)
    transcript = loader.load()[0].page_content
    return transcript

# Narzędzie można teraz używać samodzielnie
transcript = transcribe_video.run("https://www.youtube.com/watch?v=example")

# Lub dodać do listy narzędzi dostępnych dla agenta
tools = [youtube_tool, transcribe_video]

Dekorator @tool automatycznie dodaje dokumentację i podpowiedzi typów, które pomagają LLM zrozumieć, jak używać narzędzia. Jest to szczególnie istotne przy tworzeniu agentów, które muszą wybierać odpowiednie narzędzia do różnych zadań.

Budowanie agentów

Agenty to programy zdolne do rozumowania i wykonywania zadań przez integrację LLM z narzędziami. Wykorzystują możliwości LLM do generowania strukturyzowanego wyjścia (JSON).

Porównanie Agentów i Łańcuchów:

Cecha Łańcuchy (Chains) Agenty (Agents)
Sekwencja działań Predefiniowana, stała Dynamiczna, ustalana w czasie rzeczywistym
Wybór narzędzi Określony przez programistę Determinowany przez LLM na podstawie kontekstu
Złożoność Niższa, łatwiejsze w debugowaniu Wyższa, trudniejsze w debugowaniu
Elastyczność Ograniczona do zaprogramowanej ścieżki Wysoka, adaptacja do różnych scenariuszy
Przewidywalność Wysoka Niższa (zależna od decyzji LLM)
Zastosowanie Proste, powtarzalne zadania Złożone, wieloetapowe problemy

Agent może wielokrotnie wykorzystywać różne narzędzia, decydując o kolejnych krokach aż do ukończenia zadania. Może też zwracać się po dodatkowe informacje, gdy są potrzebne, lub wybierać alternatywne ścieżki w przypadku niepowodzenia.

Praktyczny przykład agenta YouTube

Transkrypt prezentuje praktyczny przykład agenta, który może wyszukiwać filmy na YouTube, a następnie transkrybować je i analizować:

python
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain import hub

# Pobranie gotowego promptu z LangChain Hub
prompt = hub.pull("langchain-ai/tool-calling-agent")

# Tworzenie własnego narzędzia do transkrypcji wideo
@tool
def transcribe_video(video_url: str) -> str:
    """Transkrybuje film z YouTube."""
    loader = YoutubeLoader.from_youtube_url(video_url)
    transcript = loader.load()[0].page_content
    return transcript

# Lista narzędzi dla agenta
tools = [youtube_tool, transcribe_video]

# Tworzenie agenta
agent = create_tool_calling_agent(llm_gpt4, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)

# Wywołanie agenta z złożonym zadaniem
result = agent_executor.invoke(
    "what topics does the Rabbit Metrics YouTube channel cover?"
)

W powyższym przykładzie agent:

  1. Najpierw używa youtube_tool do wyszukania filmów z kanału Rabbit Metrics
  2. Następnie wybiera odpowiedni film i używa transcribe_video do pobrania transkryptu
  3. Analizuje transkrypt, by zidentyfikować omawiane tematy
  4. Formułuje ostateczną odpowiedź na podstawie zebranych informacji

Agent samodzielnie decyduje o kolejności kroków i wyborze narzędzi, adaptując się do zadania. To pokazuje przewagę agentów nad statycznymi łańcuchami – mogą elastycznie reagować na różne sytuacje i rozwiązywać złożone problemy wymagające sekwencji działań.

Podsumowanie

LangChain to potężny framework do tworzenia aplikacji opartych na LLM, który umożliwia łączenie modeli językowych z zewnętrznymi źródłami danych i narzędziami.

Checklista podstawowych komponentów LangChain:

  • Łańcuchy (Chains) – sekwencje komponentów przetwarzających dane
    • Szablony promptów i parsery wyjścia
    • Operatory łączenia (|, .pipe())
  • Protokół Runnable – interfejs do wywoływania komponentów
    • Sequence, Lambda, PassThrough, Parallel
  • Splittery i Retrievery – zarządzanie danymi
    • Dzielenie dokumentów na fragmenty
    • Tworzenie i używanie baz wektorowych
  • Aplikacje RAG – wzbogacanie LLM o zewnętrzne dane
    • Indeksowanie i retrieval
    • Optymalizacja precision i recall
  • Narzędzia (Tools) – rozszerzenia możliwości LLM
    • Wbudowane narzędzia
    • Tworzenie własnych narzędzi
  • Agenty – autonomiczne systemy decyzyjne
    • Dynamiczny wybór narzędzi
    • Wieloetapowe rozwiązywanie problemów

Co dalej?

Dla osób, które chcą zagłębić się w temat zaawansowanych zastosowań LangChain, warto poznać:

  1. Langgraph – tworzenie systemów wieloagentowych
  2. Langsmith – monitorowanie i ewaluacja łańcuchów
  3. Lang Serve – wdrażanie aplikacji LangChain
  4. Zaawansowane łańcuchy – niestandardowe łańcuchy do specyficznych zastosowań

Ten artykuł jest częścią serii notatek z wartościowych webinarów na temat AI i nowości technologicznych. Bazuje na webinaru „Learn LangChain in 7 Easy Steps – Full Interactive Beginner Tutorial„.


Opublikowano

Komentarze

Dodaj komentarz