I'd used ChatGPT and Claude as a regular user for a while, but I had no idea what it actually takes to build something like that yourself — what tools developers reach for to make an AI app. LangChain kept coming up as "the" framework for this, so I decided to find out what it actually does.
So I built the same small AI app twice — first with raw API calls, then with LangChain — and wrote down everything I noticed along the way. This is the honest report.
If you've been intimidated by LangChain or wondering whether to learn it as a beginner, this is for you.
What I built
The app is a "document Q&A" — load a text file, ask the AI questions about its contents, and have a conversation with memory (so the AI remembers what you asked before).
This is the foundation of every "chat with your documents" tool out there. ChatPDF. Notion AI. AskYourPDF. They all do this same thing, just with polish on top.
My setup:
- Python in Google Colab (free, runs in the browser)
- Groq's free API for the LLM (no credit card needed)
- Llama 3.3 70B as the model
- LangChain in version 2
I went in completely fresh. I'd never built an AI app before.
Version 1: Raw Groq API
The simplest possible AI call looks like this:
from groq import Groq
client = Groq(api_key=api_key)
response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[
{"role": "system", "content": "You answer questions about a document."},
{"role": "user", "content": "What is this text about?"}
]
)
print(response.choices[0].message.content)
Three things to notice: you set up a client, you send a list of messages with roles (system, user), and you dig into the response to find the actual text (response.choices[0].message.content).
To turn this into a real Q&A app, I wrapped it in a while True loop so I could ask multiple questions.
That's when I hit my first surprise.
The AI has no memory
I asked three questions:
- "How many players per team?" → AI answered correctly.
- "What is the pitch length?" → AI answered correctly.
- "What did I just ask you?" → AI said: "You asked me what you just asked me, but prior to that, you provided a document..."
A complete dodge. The AI had no idea what I'd asked 10 seconds earlier.
This is when I realized: the AI is goldfish-brained by default. Every API call is fresh. The model has no memory of the past. Each question is an isolated event.
To fix this, you have to do the memory yourself. You maintain a list of every message — yours AND the AI's replies — and send the whole thing back every time. The list grows with each round.
conversation = [
{"role": "system", "content": "..."}
]
while True:
question = input("Your question: ")
conversation.append({"role": "user", "content": question})
response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=conversation
)
answer = response.choices[0].message.content
conversation.append({"role": "assistant", "content": answer})
print(answer)
python
That was Day 2 done. App worked. Onto LangChain.
Version 2: The same app with LangChain
Here's the LangChain version of the exact same conversation loop:
from langchain_groq import ChatGroq
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
llm = ChatGroq(api_key=api_key, model="llama-3.3-70b-versatile")
conversation = [
SystemMessage(content="You answer questions about a document.")
]
while True:
question = input("Your question: ")
conversation.append(HumanMessage(content=question))
response = llm.invoke(conversation)
conversation.append(AIMessage(content=response.content))
print(response.content)
Look at it next to Day 2. The structure is identical. What changed:
-
{"role": "user", ...}becameHumanMessage(content=...) -
{"role": "assistant", ...}becameAIMessage(content=...) -
client.chat.completions.create()becamellm.invoke() -
response.choices[0].message.contentbecameresponse.content
That's it. Memory is still my job. The loop is still mine. LangChain didn't make the AI smarter or give it real memory — it renamed the parts and gave me cleaner ways to access them.
So why use it? The pitch is: LangChain is a translator. It speaks Groq's language, OpenAI's, Anthropic's, all of them — but you only have to learn LangChain. Want to swap Groq for OpenAI tomorrow? Change one line — ChatGroq to ChatOpenAI — and the rest of the code works. With raw APIs, you'd have to rewrite the whole thing in each provider's specific format.
That's a real benefit if you ever need it. For my one-file app? Honestly, no benefit yet.
The friction nobody warns you about
Here's what tripped me up in 3 days:
1. LangChain's imports keep moving. I copied an import from a tutorial — from langchain.schema import HumanMessage — and got ModuleNotFoundError. Turns out LangChain moved its core pieces to langchain_core.messages. Half the tutorials online still use the old path. If you're a beginner, you'll burn 20 minutes on this exact error at least once.
2. The LangChain version looked too similar — I almost didn't trust it actually worked. When I rewrote Day 2's code in LangChain, the structure was nearly identical — same loop, same append pattern, just renamed pieces. Part of me expected LangChain to feel different, more "magic." When I ran it and got the same correct memory-based answers, it didn't feel like a breakthrough — it felt like I'd basically retyped the same program with different words. That's when it actually clicked: LangChain isn't doing something fundamentally different here, it's giving the same thing a standard name.
So, is LangChain worth it?
After 3 days, my honest take:
Where LangChain helped:
- Cleaner response access (
response.contentinstead ofresponse.choices[0].message.content) - Type-safe message classes (typo in
SystemMessageand Python yells immediately — typo in"system"and the API silently breaks) - Provider-agnostic — easy to swap LLMs
Where it didn't:
- Memory is still my responsibility
- Imports keep churning
The honest verdict: for a single-file chat app, LangChain is a slight cosmetic upgrade. The real value probably shows up later — vector databases, swapping providers, agents that use tools, chaining multiple AI calls. I haven't built any of that yet. But after these 3 days, at least I understand what LangChain is — not magic, just a wrapper with a standard vocabulary.
What's next
I'm going to keep going — next step is adding a vector database so the app can handle large documents (this is where LangChain is supposed to actually pay off). I'll write that up next.
If you're a beginner: build it raw first. Don't start with LangChain. You'll understand the framework so much better once you know what it's hiding from you.
And if you've used LangChain in real production code — I'd love to hear where it actually saved you time. The framework's value is theoretical to me right now. Tell me where it stopped being theoretical for you.
Top comments (0)