{"slug": "learning-langchain", "title": "Learning LangChain", "summary": "A developer rebuilt their hand-rolled note-answering app, Synapse, using LangChain and documented how the framework maps onto each step they had previously written manually. The account covers message classes, prompt templates, output parsers, pipe-based chain composition with RunnableLambda and RunnableParallel, document loading and splitting, OpenAI embeddings, Chroma vector storage, and similarity versus MMR retrieval, noting that batching two requests took 2.67 seconds versus about 7.5 seconds for separate calls.", "body_md": "A while back I built Synapse, a small app that answers questions using my own notes. I did every part of it by hand: load the files, turn them into vectors, find the closest ones to the question, and hand those to an LLM. It worked, and I understood it, because I'd written every line myself.\n\nSo when I started LangChain, a framework that promised to do all of that for me felt a little suspicious. My honest question was: what is this doing that I haven't already done?\n\nIt turns out the answer is less \"new ideas\" and more \"a standard shape for the ones you already have.\" Let me walk through it the way I learned it.\n\nA chat model doesn't take one big string. It takes a list of messages: a system message that sets the role, then human messages from you, then AI messages from the model. LangChain gives each of those its own class. Nothing magic, it's the same thing the raw API wants.\n\nPrompt templates were the next small step. Instead of building a string every time, you write the prompt once with a gap in it:\n\n``` python\nfrom langchain_core.prompts import ChatPromptTemplate\n\ntemplate = ChatPromptTemplate.from_template(\n    \"I've recently adopted a {pet}. Suggest three {pet} names.\"\n)\n```\n\nThen an output parser takes the model's text reply and turns it into something you can actually use, like a Python list. The thing that stuck with me here is that the parser is only as good as your instructions. Vague instructions about the format gave me a messy list. Strict ones gave me a clean one.\n\nThis is the bit where it clicked for me. LangChain lets you join those pieces with a `|`, like a Unix pipe:\n\n```\nchain = chat_template | chat | list_output_parser\nchain.invoke({\"pet\": \"dog\"})\n# ['Max', 'Bella', 'Luna']\n```\n\nA prompt goes in one end, the model sits in the middle, and a clean list comes out the other end. Each step's output is the next step's input. That's the whole idea.\n\nIt even works for ordinary Python functions. Wrap them in `RunnableLambda` and they snap in like any other piece:\n\n``` python\nfrom langchain_core.runnables import RunnableLambda\n\nadd_up = RunnableLambda(lambda x: sum(x))\nsquare = RunnableLambda(lambda x: x**2)\n\n(add_up | square).invoke([1, 2, 5])   # 8, then 64\n```\n\nYou can also draw a chain. `chain.get_graph().print_ascii()` prints the boxes and arrows, which is surprisingly handy when a chain gets long.\n\nTwo more things I liked. `RunnableParallel` runs two chains side by side and gives both results to the next step. And `batch` is quicker than looping: two requests through `batch` took 2.67 seconds in my notebook, while the same two as separate calls took about 7.5.\n\nRemember my five hand-built steps? LangChain has a piece for each.\n\nFor loading, there are loaders for different file types. I used one for PDFs and one for Word documents. Splitting was the new part, since Synapse never did any. I split a six-page document twice. First by its headings, so every chunk remembers which lecture it came from, then by size, about 500 characters with a little overlap. That left me with 20 chunks, each labelled with where it came from.\n\nEach chunk then became 1,536 numbers using OpenAI's embedding model. I wanted to see if it really worked, so I compared three pairs of chunks. They scored 0.88, 0.80 and 0.79, so related text does end up close together. The vectors all have a length of about 1, which is why a plain dot product works as a similarity score.\n\nThose vectors went into Chroma, which saves them to a folder on disk so I don't have to re-embed every time I open the notebook.\n\nRetrieval comes in two flavours. A plain similarity search gives you the closest chunks. MMR gives you close chunks that are also different from each other, so you don't get five copies of the same paragraph.\n\nAnd the last step is where the pipe comes back. The whole thing is one chain:\n\n```\nchain = (\n    {\"context\": retriever, \"question\": RunnablePassthrough()}\n    | prompt_template\n    | chat\n    | StrOutputParser()\n)\n\nchain.invoke(\"What software do data scientists use?\")\n```\n\nThe retriever fills in the context, the question passes straight through, the prompt tells the model to answer only from that context and name the lecture it used, and the parser hands back plain text. The answer ended with:\n\nResources: Programming Languages & Software Employed in Data Science - All the Tools You Need\n\nThat's the same \"only use these notes\" guard I wrote by hand in Synapse, plus the sources I'd been putting off adding.\n\nLangChain didn't teach me a new idea. Everything in that pipeline is something I'd already done by hand: load, embed, find the closest, ask. What it gave me was a standard shape for each step, and the pipe to join them. Having built it the long way first is what made the short way make sense.\n\nNext up is LangGraph.", "url": "https://wpnews.pro/news/learning-langchain", "canonical_source": "https://dev.to/sabimantock/learning-langchain-4jlp", "published_at": "2026-10-12 17:44:01+00:00", "updated_at": "2026-10-12 17:50:07.862734+00:00", "lang": "en", "topics": ["large-language-models", "ai-tools", "developer-tools", "natural-language-processing"], "entities": ["LangChain", "Synapse", "OpenAI", "Chroma", "RunnableLambda", "RunnableParallel", "ChatPromptTemplate", "StrOutputParser"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/learning-langchain", "markdown": "https://wpnews.pro/news/learning-langchain.md", "text": "https://wpnews.pro/news/learning-langchain.txt", "jsonld": "https://wpnews.pro/news/learning-langchain.jsonld"}}