LangChain in 5 Minutes: Build Your First AI Demo with Model I/O
This article mainly walks through a basic LangChain Model I/O (Model Input/Output): that is, how you feed data "into the model" (Input) and how you "get results" from the model (Output).
We'll start with the most basic: initialize the model -> user input -> model invocation. Complete the minimal loop. Prompt engineering, structured output, and message types will be covered later.
Below is a diagram of LangChain Model I/O: the "input/output protocol layer" for model invocation
Table of Contents
- Why use LangChain to develop AI applications
- API Key application and development environment setup
- Model initialization:
initChatModelmethod - Model invocation:
invokemethod - Details and summary
Why use LangChain to develop AI applications?
- Unify differences between model providers
Nowadays, AI model providers are emerging one after another. This is good for the industry as a whole, driving rapid AI development. But for developers, it's not that friendly.
In real projects, we often don't use just one model provider's service. For example, we might simultaneously integrate:
- OpenAI
- Alibaba Bailian
- Zhipu AI
- Even some local models
At this point, the problem arises: 👉 Different providers have different API invocation methods, parameter formats, and return structures
If you write a set of adaptation logic for each model:
- The code becomes very messy
- Maintenance costs are extremely high later on
This is where LangChain's value lies:
👉 Unified model invocation method, shielding underlying differences
You can think of it as:
LangChain ≈ JDBC in Java
Just develop against a unified interface, and you can flexibly switch between different model providers.
See the diagram:
LangChain source code reflection:
👉 Enumerate each provider, then implement through dynamic import + a unified ConfigurableModel proxy (details not discussed)
- Provides rich component capabilities
LangChain is not just about "unified model invocation"; it is essentially a complete AI application development framework with many built-in core capabilities, such as:
- Prompt templates (PromptTemplate)
- Output parsing (OutputParser)
- Tool invocation (Tools)
- Memory management (Memory)
- Agent capabilities
But to be honest, for most frontend/application developers:
👉 What is most commonly used in daily work is still:
- Chat capabilities (LLM invocation)
- Simple Prompt organization
- AI tool integration (cursor, Cloud Code)
Large Model ≠ Complete AI Application
Many people have a misconception:
"Having a large model equals having an AI application"
Actually, it doesn't.
You can think of a large model as a "super brain" that possesses:
- Powerful knowledge capabilities
- Reasoning capabilities
But it itself lacks:
- Long-term memory
- Action capabilities
- Task planning capabilities
Therefore, a complete AI application usually looks like this:
AI Agent = LLM (Brain) + Memory + Planning + Tools
👉 LangChain is precisely the tool that helps you "assemble" these capabilities.
Let's start with a demo to get a taste 😄😄😄
Model Application (Alibaba Cloud Bailian: Free Credits Available)
Click the link below, read the documentation, and follow the instructions to apply for an API Key.
- Choose a suitable model from the Model Plaza. Here we use
qwen-coder-turbo.
Development Environment Setup
- Create project
mkdir langchain-project
cd langchain-project
npm init -y
- Create entry file
src/langchain-invoke.mjs
Note:
.mjsis the ESM module format- Supports
import / export - Convenient for quick debugging
👉 After engineering, using .js directly is perfectly fine.
Initialize the Model
- Install dependencies
pnpm install langchain
- Use
initChatModelto initialize the model
import { initChatModel } from 'langchain';
const model = initChatModel(
'qwen-coder-turbo' // model name
{
modelProvider: "openai", // Tell the factory: although it's xxx service, use OpenAI's SDK logic
baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1" // Corresponds to the field in the SDK
apiKey: 'sk-d69fd787d37241fxxxxe8bb914292108' // Corresponds to the field in the SDK
}
)
Model Invocation
We are using ChatModel (conversation model) here, initialized with initChatModel.
👉 Features:
- Input: Single message / list of messages
- Output: An AIMessage
Using invoke
const response = await model.invoke("Why do parrots have colorful feathers?");
console.log(response);
// console.log(response.content);
Return Result Explanation
The return value is an AIMessage object, for example:
{
content: "Because feathers contain pigments and structural colors...",
...
}
👉 If you only care about the text content:
console.log(response.content);
🎉 Summary
At this point, we have completed:
- Model initialization
- Model invocation
- Getting the return result
👉 A most basic LangChain Demo is up and running. Isn't it simple?
Advanced Supplement
❗ Don't Let Your API Key "Naked" – Use .env
Hardcoding the API Key directly in the code:
apiKey: 'sk-xxx'
👉 Only suitable for temporary testing 👉 Very dangerous in production environments (key will leak)
Use dotenv to manage environment variables
- Install:
pnpm install dotenv
- Create
.envfile:
# OpenAI API Configuration
# OpenAI API Key
OPENAI_API_KEY=sk-d69fd787d37241xxxf9e8bb914292108
# OpenAI API Base URL
OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
# Model Name
MODEL_NAME=qwen-coder-turbo
- Use in code
// import dotenv from "dotenv";
// dotenv.config();
import 'dotenv/config';
import { initChatModel } from 'langchain';
const model = await initChatModel(process.env.MODEL_NAME, {
modelProvider: 'openai',
apiKey: process.env.OPENAI_API_KEY,
baseUrl: process.env.OPENAI_BASE_URL,
});
const result = await model.invoke("Why do parrots have colorful feathers?");
console.log(result);
.gitignoreto ignore sensitive information
node_modules
.env
package-lock.json
.DS_Store
Why sometimes can't read .env?
Initially, to save time, I directly cd into the src directory and executed:
node ./langchain-invoke.mjs
It immediately reported an error: 👉 Prompt saying API Key not found
🧠 Root Cause
The problem lies in this point:
dotenvby default looks for the.envfile based on the current working directory (process.cwd)
That is to say:
👉 Node doesn't know where your "project root directory" is
👉 It only knows: which directory you executed the node command from
👉 There is no .env under src, so naturally it can't read it.
Another Way to Initialize the Model: ChatOpenAI
In earlier LangChain usage, we often directly used model classes like ChatOpenAI. However, with the advent of the multi-model era, LangChain provides initChatModel as a unified entry point, allowing developers to switch between different model providers without modifying business code, achieving true model decoupling.
- Install
pnpm install @langchain/openai
- Use
import { ChatOpenAI } from '@langchain/openai';
const model = new ChatOpenAI({
model: process.env.MODEL_NAME,
apiKey: process.env.OPENAI_API_KEY,
configuration: {
baseURL: process.env.OPENAI_BASE_URL,
},
});
const result = await model.invoke("Why do parrots have colorful feathers?");
console.log(result);
Difference between initChatModel and ChatOpenAI
👉 ChatOpenAI = Model SDK for OpenAI (specific implementation)
👉 initChatModel = Unified model entry point (abstraction layer + factory pattern)
Architecture Comparison
# ChatOpenAI (single provider)
Your code → ChatOpenAI → OpenAI API
# initChatModel (multi-model architecture)
Your code → initChatModel → Provider Adapter → Any model
Message Types
Above we already encountered AIMessage, which, as the name suggests, represents the message returned by AI.
In addition, LangChain defines a series of standard message types:
HumanMessage: User inputSystemMessage: System instructions (used to control AI behavior)AIMessage: Model outputToolMessage: Tool execution result
Demo
- Object list (new xxx)
import { SystemMessage, HumanMessage, AIMessage } from "langchain";
const messages = [
new SystemMessage("You are a poetry expert"),
new HumanMessage("Write a haiku about spring"),
new AIMessage("Cherry blossoms bloom..."),
];
const response = await model.invoke(messages);
- Dictionary format (k-v)
const messages = [
{ role: "system", content: "You are a poetry expert" },
{ role: "user", content: "Write a haiku about spring" },
{ role: "assistant", content: "Cherry blossoms bloom..." },
];
const response = await model.invoke(messages);
His demo is relatively simple; refer to the official documentation. https://docs.langchain.com/oss/javascript/langchain/messages
🤔 Why not just return a string?
You might have a question:
👉 "When I ask AI a question, can't it just return a string? Why wrap it in an
AIMessage?"
🤔 Conclusion First
The existence of Message is not to "add an extra layer," but to upgrade AI's output from "text" to "an orchestrateable data structure."
4 Real Problems Solved by Message (Key Points)
Message is the "state carrier" of the AI execution process, which will run through the entire subsequent learning flow, so it is crucial!!!
1️⃣ Allows AI to "Invoke System Capabilities"
AIMessage.tool_calls
👉 Used for:
- Checking weather
- Querying databases
- Calling APIs
- Invoking your written functions
👉 Without Message:
AI can only "suggest you do it"
👉 With Message:
AI can "drive the system to do it for you"
2️⃣ Allows AI to Output "Structured Data"
For example, if you are doing e-commerce (which you are doing now) 👇
User says:
Help me generate a product title
👉 string:
"2024 New Men's Sports Shoes, Breathable and Comfortable"
👉 You still have to parse it yourself 😓
👉 Message + Structured:
{
content: "",
additional_kwargs: {
title: "2024 New Men's Sports Shoes",
keywords: ["Breathable", "Comfortable"],
category: "Sports Shoes"
}
}
💥 Third value:
✅ Natively supports structured output (suitable for business systems)
3️⃣ Supports Multi-turn Dialogue (Context)
[
new SystemMessage("You are an e-commerce operations assistant"),
new HumanMessage("Help me optimize the title"),
new AIMessage("Please provide product information"),
new HumanMessage("Men's running shoes")
]
👉 If it were just a string:
❌ All context is lost
💥 Fourth value:
✅ Message = Dialogue context container
4️⃣ Supports "Intermediate States" (Very Critical)
In complex workflows, AI doesn't just return the final result:
👉 For example:
Think → Call tool → Think again → Output result
👉 Message can carry:
- Intermediate reasoning (partially visible)
- Tool calls
- Token consumption
- Trace information
Other Model Invocation Methods
Above we used invoke to call the model. You can see that it returns the complete result after generation is finished, so it often requires waiting for some time.
If you want to see the model's output in real-time like a "typewriter" (streaming return), you can use the stream method, allowing results to be output as they are generated, improving the interactive experience. Additionally, there is batch for batch processing model requests.
// stream
const stream = await model.stream("Help me generate a product title for BYD");
for await (const chunk of stream) {
// console.log('stream:', chunk);
// console.log(chunk.text)
console.log(chunk.content)
}
🎉 Summary
This article focuses on LangChain's Model I/O, completing the minimal loop from model initialization → input construction → model invocation → output parsing.
The main content includes:
Why use LangChain Unify differences between different model providers through a unified interface, while providing rich component capabilities, allowing us to focus on business development instead of dealing with various compatibility issues.
Model Initialization Taking the most common ChatModel as an example, it introduces how to use
initChatModelto initialize the model, and the configuration of core parameters likeapiKey,baseUrl, and supplements the practice of usingdotenvenvironment variables.Message Types Through the model's return value
AIMessage, it introduces message types likeSystemMessage,HumanMessage, and explains the syntax for object form and dictionary form. It also explains: 👉 Why the model doesn't just return a string, but uses the Message structure – because Message is the "state carrier" of the AI execution process, capable of supporting tool calls, multi-turn dialogue, intermediate states, and structured output.Model Invocation Methods Compares three invocation methods:
invoke,stream,batch:invoke: Returns all at once, suitable for debuggingstream: Streaming output, more suitable for actual interactive scenarios (mainstream method)batch: Batch processing requests
At this point, a most basic AI Demo has been completed. I believe you now have an overall understanding of LangChain's Model I/O.
However, the understanding of Message is still at the "usable" stage. 👉 In the next article, we will delve into LangChain's message mechanism and how it drives Tool and Agent execution.
For the sake of smooth sentences, some AI-assisted writing has been added. I hope you understand 🐶🐶🐶
This is an introductory article. If there are any omissions, please feel free to correct me 🤝🤝🤝