Module 1: Models and Providers
init_chat_model and Providers
Capsule overview
init_chat_model is LangChain's universal function for initializing models from any provider. Instead of importing a different class for each provider (ChatOpenAI, ChatAnthropic, ChatGoogleGenerativeAI), you use a single function that resolves everything internally.
In this capsule you'll learn to use init_chat_model with the main providers (OpenAI, Anthropic, Google, Ollama), understand the string identifiers it uses to resolve models, and configure API keys properly. By the end, you'll be able to connect to any language model in a single line of code.
Everything you learn here is the foundation of the module's mini-project: a multi-provider chat with automatic fallback.
init_chat_model: the universal function
The problem it solves
Without init_chat_model, every provider requires its own class and initialization pattern:
# Without init_chat_model — different imports and classes per provider
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
from langchain_google_genai import ChatGoogleGenerativeAI
openai_model = ChatOpenAI(model="gpt-4.1")
anthropic_model = ChatAnthropic(model="claude-sonnet-4-20250514")
google_model = ChatGoogleGenerativeAI(model="gemini-2.0-flash")
It works, but if you want to switch providers you have to change imports, classes and possibly parameters. With init_chat_model, one function handles it all:
# With init_chat_model — one function, any provider
from langchain.chat_models import init_chat_model
openai_model = init_chat_model("openai:gpt-4.1")
anthropic_model = init_chat_model("anthropic:claude-sonnet-4-20250514")
google_model = init_chat_model("google_genai:gemini-2.0-flash")
Same function, same interface, any provider. Switching providers is switching a string.
Basic example
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
# Initialize an OpenAI model
model = init_chat_model("openai:gpt-4.1-mini")
# Run it with invoke
response = model.invoke("What is LangChain in one sentence?")
print(response.content)
# Expected output: LangChain is an open-source framework for building
# applications with language models.
That's it. One line to initialize, one line to run.
String identifiers
init_chat_model uses a standard format to identify models:
provider:model
Examples:
| String identifier | Provider | Model |
|---|---|---|
"openai:gpt-4.1" | OpenAI | GPT-4.1 |
"openai:gpt-4.1-mini" | OpenAI | GPT-4.1 Mini |
"openai:o3-mini" | OpenAI | o3-mini (reasoning) |
"anthropic:claude-sonnet-4-20250514" | Anthropic | Claude Sonnet 4 |
"anthropic:claude-haiku-4-20250514" | Anthropic | Claude Haiku 4 |
"google_genai:gemini-2.0-flash" | Gemini 2.0 Flash | |
"ollama:llama3.1" | Ollama (local) | Llama 3.1 |
"ollama:mistral" | Ollama (local) | Mistral |
Alternative format: no provider prefix
You can also pass the model and the provider separately:
# These two lines are equivalent
model = init_chat_model("openai:gpt-4.1")
model = init_chat_model("gpt-4.1", model_provider="openai")
The prefixed format ("openai:gpt-4.1") is more concise and recommended. The model_provider format is handy when the model name is dynamic (it comes from a variable or a config).
# Useful when the model comes from configuration
model_name = config.get("model_name") # "gpt-4.1"
provider = config.get("model_provider") # "openai"
model = init_chat_model(model_name, model_provider=provider)
Supported providers
OpenAI
Package: pip install langchain-openai
API key: OPENAI_API_KEY
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
# GPT-4.1 — the flagship model
model = init_chat_model("openai:gpt-4.1")
response = model.invoke("Explain what RAG is in 2 sentences")
print(response.content)
# GPT-4.1 Mini — faster and cheaper
model_mini = init_chat_model("openai:gpt-4.1-mini")
response = model_mini.invoke("Hello")
print(response.content)
# o3-mini — a reasoning model (it thinks before answering)
model_reasoning = init_chat_model("openai:o3-mini")
response = model_reasoning.invoke("Solve: 15 * 23 + 47")
print(response.content)
Recommended models:
gpt-4.1— OpenAI's most capable model for complex tasksgpt-4.1-mini— A balance of cost and capability. Ideal for most caseso3-mini— For tasks that require step-by-step reasoning
Anthropic
Package: pip install langchain-anthropic
API key: ANTHROPIC_API_KEY
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
# Claude Sonnet 4 — a quality/speed balance
model = init_chat_model("anthropic:claude-sonnet-4-20250514")
response = model.invoke("Explain the difference between RAG and fine-tuning")
print(response.content)
# Claude Haiku 4 — Anthropic's fastest
model_fast = init_chat_model("anthropic:claude-haiku-4-20250514")
response = model_fast.invoke("Summarize this text in one sentence: [text]")
print(response.content)
Recommended models:
claude-sonnet-4-20250514— Ideal for most tasksclaude-haiku-4-20250514— Very fast, ideal for classification and simple tasks
Google (Gemini)
Package: pip install langchain-google-genai
API key: GOOGLE_API_KEY
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
# Gemini 2.0 Flash — fast, with good quality
model = init_chat_model("google_genai:gemini-2.0-flash")
response = model.invoke("What are the 3 pillars of observability?")
print(response.content)
Recommended models:
gemini-2.0-flash— Fast and cheap, a good option as a fallback
Ollama (local models)
Package: pip install langchain-ollama
Requirement: Ollama installed and running locally
# Install Ollama: https://ollama.ai
# Pull a model
ollama pull llama3.1
ollama pull mistral
from langchain.chat_models import init_chat_model
# No API key needed — it runs on your machine
model = init_chat_model("ollama:llama3.1")
response = model.invoke("What is a vector database?")
print(response.content)
# Mistral — a lightweight alternative
model_mistral = init_chat_model("ollama:mistral")
response = model_mistral.invoke("Hello")
print(response.content)
Advantages of local models:
- ✅ No cost per use (it runs on your machine)
- ✅ No network latency
- ✅ Data never leaves your machine (privacy)
Downsides:
- ❌ Lower quality than GPT-4.1 or Claude Sonnet
- ❌ Needs a powerful GPU for large models
- ❌ Slower on limited hardware
Azure OpenAI
Package: pip install langchain-openai
API key: AZURE_OPENAI_API_KEY + AZURE_OPENAI_ENDPOINT
from langchain.chat_models import init_chat_model
model = init_chat_model(
"openai:gpt-4.1",
model_provider="azure_openai",
azure_endpoint="https://your-resource.openai.azure.com/",
api_version="2024-12-01-preview"
)
response = model.invoke("Hello from Azure")
print(response.content)
Azure OpenAI is useful in enterprise environments where the organization already has contracts with Microsoft.
Direct initialization vs init_chat_model
Both work. Pick based on your case:
| Criterion | init_chat_model | Direct class (ChatOpenAI) |
|---|---|---|
| Simplicity | ✅ One function for everything | ❌ A different class per provider |
| Switching providers | ✅ Change one string | ❌ Change import + class |
| Configurable models | ✅ Native via configurable_fields | ❌ Requires custom code |
| IDE autocomplete | ⚠️ Returns a generic type | ✅ The IDE knows the methods |
| Provider-specific params | ⚠️ Via kwargs | ✅ Documented on the class |
Recommendation: Use init_chat_model as your default. Only reach for direct classes if you need advanced IDE autocomplete for provider-specific parameters.
# Recommended for most cases
model = init_chat_model("openai:gpt-4.1")
# The alternative, when you need very provider-specific parameters
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="gpt-4.1",
organization="org-abc123",
default_headers={"X-Custom-Header": "value"}
)
Configure API keys properly
Recommended approach: a .env file
# .env (at the root of your project)
OPENAI_API_KEY=sk-proj-your-key-here
ANTHROPIC_API_KEY=sk-ant-your-key-here
GOOGLE_API_KEY=your-key-here
from dotenv import load_dotenv
load_dotenv() # Loads the variables from .env
from langchain.chat_models import init_chat_model
# LangChain's packages look for these variables automatically
model = init_chat_model("openai:gpt-4.1") # Uses OPENAI_API_KEY
Alternative approach: pass it explicitly
model = init_chat_model("openai:gpt-4.1", api_key="sk-proj-...")
Not recommended for code you share or push to git. Useful only for quick testing.
Environment variables per provider
| Provider | Environment variable |
|---|---|
| OpenAI | OPENAI_API_KEY |
| Anthropic | ANTHROPIC_API_KEY |
GOOGLE_API_KEY | |
| Azure OpenAI | AZURE_OPENAI_API_KEY + AZURE_OPENAI_ENDPOINT |
| Ollama | Not required (local) |
Connection to the project
In the Multi-Provider Chat with Fallback (this module's project):
- You'll use
init_chat_modelto initialize 3 different providers - The string identifier will let you switch providers with a simple config change
- The automatic fallback will try provider 1 → provider 2 → provider 3
Everything you learn here applies directly in Capsule 08.
Troubleshooting
Problem 1: ImportError: cannot import name 'init_chat_model'
Cause: Your langchain version is too old.
Fix:
pip install --upgrade langchain langchain-core
Problem 2: ValueError: Could not find chat model provider for ...
Cause: The provider's package isn't installed. Fix:
# For OpenAI
pip install langchain-openai
# For Anthropic
pip install langchain-anthropic
# For Google
pip install langchain-google-genai
Problem 3: AuthenticationError or Invalid API Key
Cause: The API key is missing, wrong, or not loaded. Fix:
# Check that the key exists
import os
from dotenv import load_dotenv
load_dotenv()
print(os.getenv("OPENAI_API_KEY")) # Should print your key
# If it prints None, check your .env file
Problem 4: Ollama doesn't respond
Cause: Ollama isn't running, or the model isn't downloaded. Fix:
# Check that Ollama is running
ollama list
# If the model isn't listed, pull it
ollama pull llama3.1
# Check that the server responds
curl http://localhost:11434/api/tags
Exercises
Exercise 1: Your first model (Easy)
Initialize an OpenAI model with init_chat_model and ask it a simple question. Print the response.
See solution
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
model = init_chat_model("openai:gpt-4.1-mini")
response = model.invoke("What is the capital of France?")
print(response.content)
# Expected output: The capital of France is Paris.
Explanation: init_chat_model detects the provider from the string identifier "openai:...", looks for the API key in OPENAI_API_KEY, and returns a ready-to-use instance.
Exercise 2: Switch providers (Easy)
Change the previous exercise to use Anthropic instead of OpenAI. You should only need to change one line.
See solution
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
# Only the string identifier changes
model = init_chat_model("anthropic:claude-haiku-4-20250514")
response = model.invoke("What is the capital of France?")
print(response.content)
# Expected output: The capital of France is Paris.
Explanation: The interface is identical. Only the string identifier changes. The rest of the code is exactly the same.
Exercise 3: Multiple providers (Medium)
Write a function ask_model(provider, question) that takes a provider name ("openai", "anthropic", "google") and a question, initializes the right model, and returns the response.
See solution
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
MODELS = {
"openai": "openai:gpt-4.1-mini",
"anthropic": "anthropic:claude-haiku-4-20250514",
"google": "google_genai:gemini-2.0-flash",
}
def ask_model(provider: str, question: str) -> str:
"""Initializes the model for the given provider and returns the response."""
if provider not in MODELS:
raise ValueError(f"Unsupported provider: {provider}")
model = init_chat_model(MODELS[provider])
response = model.invoke(question)
return response.content
# Usage
print(ask_model("openai", "Say hello in Japanese"))
print(ask_model("anthropic", "Say hello in Japanese"))
# Expected output: こんにちは (Konnichiwa) — or variants
Explanation: The MODELS dictionary maps simple names to full string identifiers. The function is provider-agnostic because init_chat_model unifies the interface.
Exercise 4: Compare responses (Medium)
Write a script that asks the same question to 2 different providers and compares their responses side by side. Print the provider, its response, and the type of object returned.
See solution
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
providers = {
"OpenAI": "openai:gpt-4.1-mini",
"Anthropic": "anthropic:claude-haiku-4-20250514",
}
question = "What is an embedding, in one sentence?"
for name, model_id in providers.items():
model = init_chat_model(model_id)
response = model.invoke(question)
print(f"--- {name} ---")
print(f"Response: {response.content}")
print(f"Type: {type(response)}")
print(f"Metadata: {response.response_metadata.get('model_name', 'N/A')}")
print()
# Expected output:
# --- OpenAI ---
# Response: An embedding is a numerical representation...
# Type: <class 'langchain_core.messages.ai.AIMessage'>
# Metadata: gpt-4.1-mini
#
# --- Anthropic ---
# Response: An embedding is a numerical vector...
# Type: <class 'langchain_core.messages.ai.AIMessage'>
# Metadata: N/A
Explanation: Both providers return the same type (AIMessage), which confirms the interface is unified. The specific content varies, but the structure is identical.
Exercise 5: Dynamic model from config (Hard)
Build a system where the model is configured from a configuration dictionary (simulating a config file). The function should take the config dict, initialize the model, and return the response along with metadata about the provider used.
See solution
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import init_chat_model
def chat_with_config(config: dict, question: str) -> dict:
"""
Initializes a model based on config and returns the response with metadata.
Expected config:
{
"model": "gpt-4.1-mini",
"provider": "openai",
"temperature": 0.7
}
"""
model = init_chat_model(
config["model"],
model_provider=config["provider"],
temperature=config.get("temperature", 0.7)
)
response = model.invoke(question)
return {
"answer": response.content,
"provider": config["provider"],
"model": config["model"],
"tokens": response.usage_metadata if hasattr(response, "usage_metadata") else None
}
# Production config
prod_config = {
"model": "gpt-4.1-mini",
"provider": "openai",
"temperature": 0.3
}
# Development config (cheaper)
dev_config = {
"model": "gpt-4.1-nano",
"provider": "openai",
"temperature": 0.7
}
result = chat_with_config(prod_config, "What is LangChain?")
print(f"Provider: {result['provider']}")
print(f"Model: {result['model']}")
print(f"Response: {result['answer'][:100]}...")
Explanation: The config-dict pattern is common in real applications where configuration comes from YAML files, environment variables, or databases. init_chat_model with model_provider accepts the values separately, which makes this pattern straightforward.
Summary
In this capsule you learned:
init_chat_modelis the universal function for initializing models from any provider- String identifiers follow the format
provider:model(e.g."openai:gpt-4.1") - You can split model and provider using the
model_providerparameter - The main providers are OpenAI, Anthropic, Google (cloud) and Ollama (local)
- Each provider needs its package (
langchain-openai, etc.) and its API key - The interface is identical across providers — switching providers = switching a string
- Use
.env+python-dotenvto handle API keys safely
Next capsule: Parameters and configuration — you'll learn to tune the model's behavior with temperature, max_tokens, timeout, and models configurable at runtime.
Additional resources
- init_chat_model API Reference - Full documentation for the function
- Chat Models Universal Init - The official how-to guide
- LangChain Integrations: Chat Models - Complete list of supported providers
- OpenAI Models Documentation - Models available from OpenAI
- Anthropic Models Documentation - Models available from Anthropic
- Ollama Library - Models available for local execution
- python-dotenv Documentation - Handling environment variables
Module 1 — LangChain & LangGraph: From Chains to Agents