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-anthropicZacznijmy 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.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.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.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.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.