Lcel
Recap: On Day 8, LangBot gained a long-term memory — a vector store (Pinecone) filled with document embeddings. You can ask /search home office stipend and get relevant chunks back. But that is half the picture. You still have to type /search, read raw chunks, and synthesize the answer yourself. Today we close the loop: the retriever feeds into the chatbot automatically, so you ask “How much is the home office stipend?” and LangBot answers from your documents — no slash command, no manual lookup.
Recap: On Day 6, LangBot gained output parsers and now responds in two modes — chat mode returns typed LangBotResponse objects with mood and confidence, and list mode returns clean list[str] via CommaSeparatedListOutputParser. Both modes use .invoke(), which means the entire response arrives at once after the model finishes generating. Today we fix that — LangBot learns to type its replies one token at a time.
The problem: waiting for the whole answer
Every interaction so far has the same rhythm:
Recap: On Day 5, LangBot started returning typed objects — every response is now a LangBotResponse with .message, .mood, and .confidence. That is great when you need structured metadata. But structured output is not always the right tool. Sometimes you just want a clean string. Sometimes you want a parsed list. Today we add output parsers — lightweight LCEL components that transform raw AIMessage output into exactly the shape you need.
Recap: On Day 1 we built a basic CLI chatbot. Day 2 gave it memory so it remembers the conversation. Day 3 added a prompt template so LangBot has a personality. But every turn still requires two separate steps — format the template, then call the model. Today we stitch them together into one fluid pipeline.
The problem: two steps where one should do
Here is how LangBot works on Day 3. Every single turn: