🌐 EN | πŸ‡―πŸ‡΅ JP

Chapter 2: Core Components

Chat Models, Prompts, and LCEL

πŸ“– Reading Time: 20-25 minutes πŸ“Š Difficulty: Beginner πŸ’» Code Examples: 5 πŸ“ Exercises: 2

Learning Objectives

2.1 Chat Models

Chat Models are the foundation of LangChain applications. They provide a unified interface for interacting with LLMs from any provider.

graph LR subgraph Providers["LLM Providers"] P1[OpenAI] P2[Anthropic] P3[Google] P4[Others...] end subgraph Interface["LangChain Interface"] CM[ChatModel] end subgraph Methods["Common Methods"] M1[.invoke] M2[.stream] M3[.batch] end Providers --> CM CM --> Methods style CM fill:#667eea,color:#fff

Key Concepts

Chat Model

A wrapper around an LLM that provides a consistent interface for sending messages and receiving responses. All chat models support the same core methods: invoke(), stream(), and batch().

Code Example 1: Working with Chat Models
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage

# Initialize a chat model
llm = ChatOpenAI(
    model="gpt-4",
    temperature=0.7,    # Creativity level (0-1)
    max_tokens=500      # Maximum response length
)

# Messages are the input format for chat models
messages = [
    SystemMessage(content="You are a helpful coding assistant."),
    HumanMessage(content="Write a Python function to calculate factorial."),
]

# invoke() - Get a single response
response = llm.invoke(messages)
print(response.content)

# stream() - Get response as it's generated
for chunk in llm.stream(messages):
    print(chunk.content, end="", flush=True)

# batch() - Process multiple inputs efficiently
batch_messages = [
    [HumanMessage(content="What is 2+2?")],
    [HumanMessage(content="What is 3+3?")],
]
responses = llm.batch(batch_messages)
for r in responses:
    print(r.content)

Message Types

Message Type Purpose Example
SystemMessage Set behavior/persona "You are a helpful assistant"
HumanMessage User input "Explain quantum computing"
AIMessage Model's previous response Used for conversation history

2.2 Prompt Templates

Prompt Templates allow you to create reusable, parameterized prompts:

Code Example 2: Prompt Templates
from langchain_core.prompts import ChatPromptTemplate

# Create a template with variables
template = ChatPromptTemplate.from_messages([
    ("system", "You are an expert in {topic}. Explain concepts clearly."),
    ("human", "{question}")
])

# Format with specific values
messages = template.invoke({
    "topic": "machine learning",
    "question": "What is gradient descent?"
})

print(messages)
# Output: [SystemMessage(content="You are an expert in machine learning..."),
#          HumanMessage(content="What is gradient descent?")]

# Use with a model
from langchain_openai import ChatOpenAI
llm = ChatOpenAI()
response = llm.invoke(messages)
print(response.content)

Advanced Template Features

Code Example 3: Few-Shot Prompting
from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate

# Define examples
examples = [
    {"input": "happy", "output": "sad"},
    {"input": "tall", "output": "short"},
    {"input": "fast", "output": "slow"},
]

# Create example prompt
example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"),
    ("ai", "{output}"),
])

# Create few-shot prompt
few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples,
)

# Final template
final_prompt = ChatPromptTemplate.from_messages([
    ("system", "You give the opposite of words."),
    few_shot_prompt,
    ("human", "{input}"),
])

# Use it
messages = final_prompt.invoke({"input": "big"})
response = llm.invoke(messages)
print(response.content)  # Expected: "small"

2.3 Output Parsers

Output Parsers convert LLM text responses into structured data:

graph LR A[LLM Response
Raw Text] --> B[Output Parser] B --> C[Structured Data
dict, list, Pydantic] style B fill:#667eea,color:#fff
Code Example 4: Structured Output with Pydantic
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field

# Define the output structure
class MovieReview(BaseModel):
    title: str = Field(description="The movie title")
    rating: int = Field(description="Rating from 1-10")
    summary: str = Field(description="Brief summary of the review")

# Create model with structured output
llm = ChatOpenAI(model="gpt-4")
structured_llm = llm.with_structured_output(MovieReview)

# Create prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a movie critic. Analyze the given movie."),
    ("human", "Review the movie: {movie}")
])

# Chain and invoke
chain = prompt | structured_llm
result = chain.invoke({"movie": "Inception"})

# Result is a Pydantic object!
print(f"Title: {result.title}")
print(f"Rating: {result.rating}/10")
print(f"Summary: {result.summary}")

2.4 LangChain Expression Language (LCEL)

LCEL is a declarative way to compose chains using the pipe (|) operator:

LCEL (LangChain Expression Language)

A syntax for composing LangChain components into chains. Components connected with | pass their output as input to the next component. All LCEL chains support invoke, stream, and batch automatically.

graph LR A[Prompt
Template] -->|pipe| B[Chat
Model] -->|pipe| C[Output
Parser] style A fill:#667eea,color:#fff style B fill:#11998e,color:#fff style C fill:#f093fb,color:#fff
Code Example 5: Building Chains with LCEL
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# Define components
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant."),
    ("human", "Translate '{text}' to {language}.")
])

model = ChatOpenAI(model="gpt-4")

parser = StrOutputParser()  # Extracts string from AIMessage

# Compose with LCEL (pipe operator)
chain = prompt | model | parser

# Use the chain
result = chain.invoke({
    "text": "Hello, world!",
    "language": "Japanese"
})
print(result)  # Output: "γ“γ‚“γ«γ‘γ―γ€δΈ–η•ŒοΌ"

# Streaming works automatically!
for chunk in chain.stream({"text": "Good morning", "language": "French"}):
    print(chunk, end="", flush=True)
# Output: "Bonjour" (streamed character by character)

LCEL Benefits

When to Use LCEL vs LangGraph

Use LCEL for simple, linear chains (prompt β†’ model β†’ parser). For complex workflows with branching, cycles, or state management, use LangGraph instead. You can always use LCEL within LangGraph nodes.

Exercises

Exercise 1: Custom Prompt Template

Create a prompt template for a code review assistant. It should accept language (programming language) and code as parameters, and ask the model to review the code for bugs and improvements.

Exercise 2: Structured Output

Create a chain that extracts structured information from a job posting. Define a Pydantic model with fields: job_title, company, salary_range (optional), and required_skills (list of strings).

Summary

Disclaimer

This content is provided for educational purposes. LangChain is developed and maintained by LangChain Inc.