Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

LangChain - łańcuch, który spina wszystko

Umiesz już wywołać model i napisać dobry prompt. Ale prawdziwa aplikacja to coś więcej: pobierz szablon, wyślij do modelu, sparsuj odpowiedź, zapamiętaj rozmowę. LangChain spina te kroki w jedno - a robi to jednym, zaskakująco prostym pomysłem, który poznasz na początku.

1pip install langchain langchain-openai langchain-anthropic

Klocek: model

Zacznijmy od najmniejszego klocka - samego modelu. W LangChain każdy dostawca (OpenAI, Anthropic) ma tę samą metodę

invoke
, więc zmiana modelu to zmiana jednej linii.

1from langchain_openai import ChatOpenAI
2from langchain_core.messages import HumanMessage, SystemMessage
3
4llm = ChatOpenAI(model="gpt-5", temperature=0.7)
5
6messages = [
7    SystemMessage(content="Jesteś ekspertem od Safari."),
8    HumanMessage(content="Opowiedz o słoniach.")
9]
10print(llm.invoke(messages).content)

Zwróć uwagę na

invoke
- to wspólne "uruchom" dla wszystkich klocków LangChaina. Za chwilę zobaczysz, że tak samo uruchamia się pojedynczy model, jak i cały złożony łańcuch. Ta jednolitość to fundament biblioteki.

Klocek: szablon promptu

Drugi klocek to szablon z lukami - Twój prompt z poprzedniej lekcji, ale wielokrotnego użytku. Zamiast sklejać napisy, wpisujesz

{zmienne}
.

1from langchain_core.prompts import ChatPromptTemplate
2
3prompt = ChatPromptTemplate.from_messages([
4    ("system", "Jesteś ekspertem od {dziedzina}."),
5    ("human", "Opowiedz o {temat}.")
6])

Luki

{dziedzina}
i
{temat}
wypełnisz dopiero przy uruchomieniu. Dzięki temu jeden szablon obsłuży setki pytań - a jako klocek LangChaina też ma
invoke
i da się połączyć z modelem. I tu wchodzi główny pomysł całej biblioteki.

Wielki pomysł: operator | (pipe)

Oto serce LangChaina. Klocki łączysz operatorem

|
, dokładnie jak rurę: wynik jednego wpływa do następnego.
prompt | llm | parser
czyta się "wypełnij prompt, wyślij do modelu, przerób odpowiedź".

1from langchain_core.output_parsers import StrOutputParser
2
3chain = prompt | llm | StrOutputParser()
4
5result = chain.invoke({"dziedzina": "Safari", "temat": "lwy"})
6print(result)

To ten sam

invoke
, co przy pojedynczym modelu - ale teraz uruchamia cały łańcuch naraz. Dane wpływają jako słownik z lukami, przechodzą przez szablon, model i parser, a wypływają jako gotowy tekst.
StrOutputParser
na końcu wyciąga sam tekst z odpowiedzi, żebyś nie pisał
.content
. Zapamiętaj ten wzór
prompt | llm | parser
- to on wraca w każdym kolejnym przykładzie.

Ten sam łańcuch, mocniejszy parser: wynik jako obiekt

Skoro parser to ostatni klocek rury, wystarczy go wymienić, by dostać nie tekst, lecz gotowy obiekt. Opisujesz oczekiwaną strukturę klasą, a LangChain dopilnuje formatu.

1from langchain_core.pydantic_v1 import BaseModel, Field
2from langchain_core.output_parsers import JsonOutputParser
3
4class AnimalInfo(BaseModel):
5    name: str = Field(description="Nazwa zwierzęcia")
6    habitat: str = Field(description="Siedlisko")
7    population: int = Field(description="Populacja")
8
9parser = JsonOutputParser(pydantic_object=AnimalInfo)
10
11prompt = ChatPromptTemplate.from_messages([
12    ("human", "{format_instructions}\n\nZwierzę: {animal}")
13])
14chain = prompt | llm | parser
15
16result = chain.invoke({
17    "animal": "Słoń afrykański",
18    "format_instructions": parser.get_format_instructions()
19})
20print(result)  # {'name': 'Słoń afrykański', 'habitat': ..., 'population': ...}

Wciąż ten sam łańcuch

prompt | llm | parser
- zmienił się tylko ostatni klocek. Klasa
AnimalInfo
opisuje pola, jakich oczekujesz, a
get_format_instructions
wstrzykuje do promptu automatyczną instrukcję "zwróć JSON w tym kształcie". Wynik to od razu słownik Pythona, gotowy do użycia w kodzie - żadnego parsowania ręcznie.

Dokładanie pamięci do łańcucha

Domyślnie model nie pamięta poprzednich wiadomości - każde

invoke
startuje od zera. Żeby prowadził rozmowę, owijasz łańcuch klockiem zapisującym historię.

1from langchain_community.chat_message_histories import ChatMessageHistory
2from langchain_core.runnables.history import RunnableWithMessageHistory
3
4history = ChatMessageHistory()
5
6chain_with_history = RunnableWithMessageHistory(
7    chain,
8    lambda session_id: history,
9    input_messages_key="input",
10    history_messages_key="history"
11)
12
13chain_with_history.invoke(
14    {"input": "Jestem na Safari w Kenii"},
15    config={"configurable": {"session_id": "abc123"}}
16)
17response2 = chain_with_history.invoke(
18    {"input": "Jakie zwierzęta mogę tu zobaczyć?"},
19    config={"configurable": {"session_id": "abc123"}}
20)

RunnableWithMessageHistory
owija istniejący łańcuch i przy każdej turze dokłada wcześniejsze wiadomości. Dzięki temu w drugim pytaniu model wie, że "tu" znaczy Kenia - choć nie powtórzyłeś tego.
session_id
rozdziela rozmowy różnych użytkowników, żeby ich historie się nie mieszały.

Pamiętaj z tej lekcji jeden znak:

|
. LangChain to klocki - prompt, model, parser, pamięć - sklejane w rurę tym samym operatorem i uruchamiane tym samym
invoke
. Gdy to widzisz, każdy nowy element jest tylko kolejnym klockiem do dorzucenia.

Przejdź do CodeWorlds