LangChain Basics: Calling a Chat Model with init_chat_model

A
Author
26 Oct, 2026 3 min read 0 views

LangChain gives every chat model the same interface, so your code calls invoke() or stream() no matter which provider sits behind it. The helper init_chat_model creates a model from a short identifier string, which makes switching providers a one-line change. This post covers installation, the message types, calling a model, streaming, and the settings you will use most.

Install the packages

LangChain splits integrations into separate packages. You install the core library plus one package for each provider you use.

pip install langchain langchain-anthropic
# for OpenAI models instead: pip install langchain-openai

Create a model

from dotenv import load_dotenv
from langchain.chat_models import init_chat_model

load_dotenv()

model = init_chat_model("anthropic:claude-sonnet-5-5", temperature=0)
response = model.invoke("Explain what an API is in one sentence.")
print(response.content)

The string has the form provider:model. The returned object is a chat model that follows the shared interface. invoke returns an AIMessage; its content holds the text. Extra keyword arguments such as temperature and max_tokens are passed on to the provider.

Messages

Chat models work with messages. LangChain has classes for each role: SystemMessage, HumanMessage, AIMessage and ToolMessage. You can pass a list of them, or use dictionaries with role and content keys.

from langchain_core.messages import SystemMessage, HumanMessage

messages = [
    SystemMessage("You answer in exactly one short sentence."),
    HumanMessage("Why is the sky blue?"),
]
reply = model.invoke(messages)
print(reply.content)
print(reply.usage_metadata)

The usage_metadata attribute reports input and output token counts when the provider returns them. Log it from day one; token use is how you will estimate cost later.

Streaming

For a responsive interface, stream the answer as it is generated:

for chunk in model.stream("List three uses of Python."):
    print(chunk.content, end="", flush=True)
print()

Each chunk is a partial message. Async code uses astream and ainvoke with the same arguments.

Swap providers

Because the interface is shared, switching providers needs only a different string and the matching integration package:

import os
from langchain.chat_models import init_chat_model

model_id = os.environ.get("CHAT_MODEL", "anthropic:claude-sonnet-5-5")
model = init_chat_model(model_id)

Reading the identifier from an environment variable lets you change models per environment without touching code. For non-Claude providers, set the variable to a model name you know your account can use.

What a chat model does not do

A chat model is only the model. It has no memory between calls: each invoke sees only the messages you pass. It does not call tools by itself either. Those features come from the layers built on top, which the next posts cover: prompt templates, tools and agents.

Checklist

  • Install langchain plus the provider package.
  • Keep keys in environment variables.
  • Use temperature=0 for repeatable behavior while you develop.
  • Log usage_metadata to watch token use.
  • Remember that history is your job: append messages yourself or use a checkpointer in LangGraph.

Reading the response object

The reply from invoke is more than text. An AIMessage carries content, usage_metadata, response_metadata and, when tools are bound, tool_calls. The response metadata holds provider details such as the stop reason, which tells you whether the model finished normally or was cut off by the token limit. Checking it is a cheap way to catch truncated answers. When you build agents later you will read tool_calls constantly, so get used to inspecting the whole object with print(response) while you learn.

Content can also be a list of blocks rather than a string. Some providers return text blocks, thinking blocks and tool-use blocks in one message. If you are unsure, print response.content and see which shape your model returns before writing code that assumes a string.

Why use LangChain's interface at all?

You could call the provider SDK directly, and for a single model that is perfectly fine. The benefit of the shared interface appears when the rest of your code, such as chains, agents and graphs, is written against it. Those layers then work with any model that follows the interface, so you can test with a cheaper model, move to another provider or run a local model without rewriting the application logic. The cost is one more dependency and a layer of indirection, so adopt it when you expect to use the layers above it.

Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.