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:
- 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.
- 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:
# 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:
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:
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:
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:
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:
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:
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:
- 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()
lubsplit_text()
- 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
- Utwórz retriever
- Wywołaj metodę
as_retriever()
na bazie wektorowej - Skonfiguruj parametry wyszukiwania (typ, ilość wyników)
- Przetestuj retriever z przykładowymi zapytaniami
- Wywołaj metodę
Transkrypt przedstawia praktyczny przykład z Redis:
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:
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:
- Bezpośrednie wywołanie – ręczne wywoływanie metody
run()
narzędzia z konkretnym zapytaniempythonresults = youtube_tool.run("langchain tutorial")
- 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:
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:
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ć:
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:
- Najpierw używa
youtube_tool
do wyszukania filmów z kanału Rabbit Metrics - Następnie wybiera odpowiedni film i używa
transcribe_video
do pobrania transkryptu - Analizuje transkrypt, by zidentyfikować omawiane tematy
- 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ć:
- Langgraph – tworzenie systemów wieloagentowych
- Langsmith – monitorowanie i ewaluacja łańcuchów
- Lang Serve – wdrażanie aplikacji LangChain
- 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„.
Dodaj komentarz
Musisz się zalogować, aby móc dodać komentarz.