Chat models

LangChain · Essentials · 12 min

Every LangChain app starts with a model; the uniform interface lets you swap providers in one line.

A chat model takes a list of messages and returns an AIMessage. Create one with the provider-agnostic helper:

model = init_chat_model("openai:gpt-5-mini", temperature=0)

The string is provider:model; the matching provider package must be installed. Equivalent explicit classes exist, such as ChatOpenAI(model=...) or ChatAnthropic(model=...). Common parameters: temperature, max_tokens, timeout, max_retries.

All chat models share the Runnable interface:

  • model.invoke("Hello") or model.invoke([messages]) returns an AIMessage.
  • model.batch([...]) runs several inputs in parallel.
  • model.stream(...) yields AIMessageChunks as tokens arrive.
  • ainvoke, abatch, astream are the async versions.

The returned AIMessage has:

  • .content: a string or a list of provider-specific content parts,
  • .text: the plain text,
  • .content_blocks: a standardized, provider-independent list of blocks (text, reasoning, tool calls, images),
  • .tool_calls when the model wants to call tools,
  • .usage_metadata with input and output token counts,
  • .response_metadata with the raw provider details.

Because the interface is uniform, comparing providers or adding a fallback is a configuration change, not a rewrite.

Example

from langchain.chat_models import init_chat_model

model = init_chat_model("openai:gpt-5-mini", temperature=0)   # needs OPENAI_API_KEY
# model = init_chat_model("anthropic:claude-sonnet-4-5")       # same interface

reply = model.invoke("In one sentence, what is a vector database?")
print(type(reply).__name__)       # AIMessage
print(reply.text)                 # A vector database stores embeddings ...
print(reply.usage_metadata)       # {'input_tokens': 17, 'output_tokens': 25, ...}

answers = model.batch(["Capital of Japan?", "Capital of Kenya?"])
print([a.text for a in answers])  # ['Tokyo.', 'Nairobi.'] (wording varies)

for chunk in model.stream("Count to five."):
    print(chunk.text, end="", flush=True)   # 1, 2, 3, 4, 5

Remember

  • init_chat_model("provider:model") creates any supported chat model
  • invoke, batch and stream (plus async variants) work the same everywhere
  • Read .text, .content_blocks, .tool_calls and .usage_metadata from the AIMessage

Watch out for

  • Hard-coding a provider class everywhere, which makes switching or adding fallbacks a large refactor.

Check yourself

  1. What does model.invoke('Hi') return for a chat model?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.langchain.com/oss/python/langchain/models