Implement the real two-step abstraction behind LangChain's LLMChain: format the prompt, call the model, return the result.
1The Chain Is Deceptively Simple
It's tempting to assume 'Chain' implies something architecturally complex. Structurally, the simplest one does exactly two things: format a prompt, call a model. The value isn't complexity — it's that this exact two-step pattern gets reused identically across every prompt/model pairing in your application, instead of being rewritten (and subtly varied) each time.
2Why a Fake LLM for This Exercise
The llm parameter is deliberately just a function here — fake_llm() — because a Chain's entire design point is that it doesn't care what's on the other end, real API or test double, as long as it's a callable that takes a formatted prompt string and returns text. That's what makes chains easy to test without hitting a real, costly API on every test run.
3Step-by-Step Breakdown
You now have two working pieces: a PromptTemplate that formats text, and an output parser that structures the response. A Chain is what LangChain calls the object that wires a prompt and a model call together into one reusable unit — call .invoke() once, get the final answer.
Structurally, a Chain does exactly two things in sequence: format the prompt with the given inputs, then pass that formatted string to the model. That's the entire abstraction — deceptively simple, and exactly what you're about to build.
Build LLMChain Yourself. fake_llm below stands in for a real model call, so this exercise is fully deterministic. Finish LLMChain.invoke(): format the prompt with the given inputs, then pass the formatted string to self.llm and return its result.
What are the exact two steps an LLMChain performs when you call .invoke()?
- →Format the prompt template with the given inputs, then pass that formatted string to the model and return its response.
- →Fine-tune the model, then run inference.
One chain wires a prompt to a model. Next: wiring the OUTPUT of one chain into the INPUT of another — the sequential composition pattern that lets you build genuinely multi-step reasoning pipelines.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Keep Chain Composition Logic Separate From UI Rendering
A Chain's invoke() result is plain data — keep any UI formatting or rendering logic separate from the chain itself, so the same chain can serve accessible text output regardless of which UI consumes it.
const answer = await chain.invoke(inputs);SEO Implications
- 1
Target 'LangChain LLMChain example' as a distinct, high-intent search
This is one of the first LangChain classes developers search for a working example of, right after PromptTemplate.
Best Practices
Design Chain Components Around a Simple, Swappable Interface
Because a Chain's llm is just 'anything callable with a formatted prompt string', you can swap in a fake/mock LLM for tests, or a completely different real provider, without changing the chain's own logic at all.
Frequent Bugs
Passing an already-formatted string into a chain expecting a raw inputs dict, or vice versa, silently producing a broken prompt.
Keep the boundary clear: `invoke()` takes the raw inputs dict and handles formatting internally — callers should never format the prompt themselves before calling invoke().
Real-World Examples
Swapping Models Without Touching Chain Logic
A summarization chain built against a fake test double during development gets a real OpenAI-backed llm function swapped in for production, with zero changes to the PromptTemplate or LLMChain class themselves.
chain = LLMChain(prompt=prompt, llm=real_openai_call) // was: llm=fake_llm