The Runnable interface is the foundation of LangChain.js. It provides a standard protocol for components that can be invoked, streamed, and batched. Nearly every component in LangChain - from chat models to prompts to chains - implements the Runnable interface.
The Runnable interface is defined in @langchain/core/runnables/base.ts
import { ChatPromptTemplate } from "@langchain/core/prompts";import { ChatOpenAI } from "@langchain/openai";const model = new ChatOpenAI({ model: "gpt-4o" });const result = await model.invoke([ { role: "user", content: "Hello!" }]);console.log(result.content);// "Hello! How can I assist you today?"
import { ChatPromptTemplate } from "@langchain/core/prompts";import { ChatOpenAI } from "@langchain/openai";import { StringOutputParser } from "@langchain/core/output_parsers";const prompt = ChatPromptTemplate.fromTemplate( "Tell me a short joke about {topic}");const model = new ChatOpenAI({ model: "gpt-4o" });const outputParser = new StringOutputParser();const chain = prompt.pipe(model).pipe(outputParser);const result = await chain.invoke({ topic: "programming" });console.log(result);// "Why do programmers prefer dark mode? Because light attracts bugs!"
import { RunnableLambda } from "@langchain/core/runnables";const upperCase = new RunnableLambda({ func: (input: string) => input.toUpperCase(),});const chain = prompt .pipe(model) .pipe(outputParser) .pipe(upperCase);const result = await chain.invoke({ topic: "cats" });// Result will be in uppercase
Pass inputs through unchanged, optionally adding fields:
import { RunnablePassthrough } from "@langchain/core/runnables";import { RunnableParallel } from "@langchain/core/runnables";const chain = RunnableParallel.from({ // Pass the original input through original: new RunnablePassthrough(), // Also get a processed version processed: prompt.pipe(model),});const result = await chain.invoke({ question: "What is AI?" });// {// original: { question: "What is AI?" },// processed: AIMessage(...)// }
Add fields:
const chain = RunnablePassthrough.assign({ // Add a new field while keeping existing ones answer: (input) => model.invoke(input.question),});const result = await chain.invoke({ question: "What is AI?" });// {// question: "What is AI?",// answer: AIMessage(...)// }