Lessons available in both languages
Gen AI · Interview Prep

Memory Management interview questions & answers

159+ real Memory Management interview questions with model answers, plus free lessons to learn the concepts. Prepare in English & Hinglish, then practise with an AI mock interview.

13 topics · 159+ questions

Hirenix kaise padhata hai

Ek chapter. 90 minute.
Interview ke liye taiyaar.

Har concept ek real-world problem se — jaisa production code mein aata hai, waisa. Ratna nahi padta, samajh aa jaata hai. Har question ka model answer diya hai: interviewer ko exactly kya bolna hai, aur kyun. Phir usi chapter ka AI mock interview.

  • 📖Concept, 5 min meinJargon nahi — seedhi baat
  • 🛠️Real-world problemJaisa production code mein aata hai
  • 💬Model answerInterview mein kya bolna hai
  • 🧠FlashcardsRevision 10 min mein
  • 🤖AI mock interviewFollow-up bhi poochta hai
  • 📊Weak topicsKahan phans rahe ho, pata chale
Ye chapter shuru karo — free🌐 English🇮🇳 Hinglish
A student learning an interview concept on Hirenix at home
Video playlistsyllabus ke hisaab se18h+
Hirenix chapterinterview ke hisaab se90 min

Farq content ka nahi, filter ka hai — sirf wahi jo production mein actually use hota hai aur interview mein actually poocha jaata hai. Kitaabi topics jo industry mein kahin nahi chalte, wo yahan nahi milenge.

Lessons available in both languages

What you’ll learn

  • Memory kya hai?
  • Buffer memory
  • Summary memoryFree account
  • Vector store memoryFree account
  • Checkpointers: short-term memoryFree account
  • Persistent memoryFree account
  • Long-term memory: the StoreFree account
  • User-specific memoryFree account
  • Short-term vs long-term memoryFree account
  • RecapFree account
  • Project: Chatbot jo tumhe yaad rakhe
  • Project: Personalised assistantFree account
  • Project: Support bot with memory budgetFree account

Memory kya hai?

Ek call-center agent with amnesia socho: jab bhi tu call karta hai, unhe teri last call ki koi memory nahi hoti -- na ticket history, kuch nahi. Agar call phir bhi smoothly chal jaati hai, toh iski wajah ye hai ki ek alag banda (supervisor) chupke se teri poori purani conversation ka transcript agent ke desk pe slide kar deta hai, phone uthaane se theek pehle -- har baar jab tu call karta hai. Agent kuch yaad nahi rakh raha -- koi use har call pe poori history re-feed kar raha hai.

LLMs me, model wahi amnesiac agent hai. Model ka API call stateless hota hai -- usse kabhi bhi kisi bhi pichli call ki zero memory hoti hai. Jab ek chatbot "yaad rakhta hai" ki tune teen messages pehle kya kaha tha, model ne kuch retain nahi kiya -- teri application ne un teen messages ko wapas is call ke prompt me bundle karke bhej diya. "Memory" model ka feature nahi hai -- ye application-side state hai jo tu turns ke across carry karta hai aur wapas feed karta hai.

Isse ek hard trade-off create hota hai: har purana message jo tu resend karta hai, wo real input tokens consume karta hai, har single turn pe, aur context window finite hota hai. Bahut kam carry karo toh model useful context "bhool" jaata hai; bahut zyada carry karo toh tokens (aur paise) burn hote hain aisi cheez re-send karke jo barely matter karti hai. Ye poora chapter isi trade-off ko achhe se manage karne ki techniques hai -- trimming, summarising, sirf relevant cheez retrieve karna, aur state ko persist karna taaki restart se wo wipe na ho.

LangGraph memory ko do clean buckets me split karta hai. Short-term memory = ek conversation ka state, jo ek checkpointer hold karta hai aur thread_id se key hota hai. Same thread → conversation continue hoti hai; naya thread_id → bilkul blank slate, chahe graph exact wahi ho. Long-term memory = user ke baare me facts jo har conversation ke across survive karne chahiye ("user ka naam Fraz hai") -- ye ek alag object hai jise Store kehte hain, checkpointer nahi. Is chapter ke baad ke topics dono pe deep jaate hain; abhi bas map clear kar lo.

Ek aur cheez shuru me hi jaan lo: purane LangChain tutorials (0.x) ek poora langchain.memory module sikhate the -- ConversationBufferMemory, ConversationSummaryMemory, aur unke jaise. Wo poora module current 1.x line me delete ho chuka hai; use import karte hi tera program chalne se pehle hi ModuleNotFoundError aata hai. Uska modern replacement LangGraph ka checkpointer + Store system hai, jo ye chapter sikhata hai.

🌍 Real-world example: ek customer-support chatbot "maine abhi kya poocha tha?" ka sahi jawab isliye deta hai kyunki model ko yaad hai -- balki isliye ki tere backend ne is conversation ke last kuch messages ko database/checkpointer se nikala aur model ko dobara call karne se pehle prompt me paste kar diya.

💡 Stateless = model ko har API call independent hoti hai; usme kisi bhi pichli call ki koi memory nahi hoti.

💡 Short-term memory = ek conversation ka state, thread_id tak scoped, ek checkpointer manage karta hai.

💡 Long-term memory = user/world ke baare me facts jo kisi bhi ek conversation se zyada tak survive karte hain, ek Store manage karta hai.

💡 Token budget = har call me available finite space (tokens me measure hota hai); har resend kiya message isme se khaata hai.

Standard definition (interview me bolo): An LLM is stateless — it retains nothing between API calls — so "memory" is application-side state (prior messages, summaries, or stored facts) that your code resends or retrieves and feeds back into each new call; LangGraph implements this with a thread-scoped checkpointer for short-term memory and a separate Store for long-term memory, replacing the deleted 0.x langchain.memory module.

from typing import TypedDict
from langgraph.graph import StateGraph, START, END, MessagesState
from langgraph.checkpoint.memory import InMemorySaver
from langchain_core.messages import HumanMessage, AIMessage


def fake_model_node(state: MessagesState):
    # Stand-in for a real LLM call -- NO API key needed.
    # It just reports how many messages it can see, which is enough
    # to prove whether prior turns are present or not.
    msgs = state["messages"]
    reply = f"I can see {len(msgs)} message(s) in this conversation so far."
    return {"messages": [AIMessage(content=reply)]}


# 1) a BARE graph, no checkpointer -- every invoke starts from zero
bare_builder = StateGraph(MessagesState)
bare_builder.add_node("model", fake_model_node)
bare_builder.add_edge(START, "model")
bare_builder.add_edge("model", END)
bare = bare_builder.compile()  # NO checkpointer

r1 = bare.invoke({"messages": [HumanMessage(content="Hi, I am Fraz")]})
print("Bare call 1:", r1["messages"][-1].content)

r2 = bare.invoke({"messages": [HumanMessage(content="What is my name?")]})
print("Bare call 2:", r2["messages"][-1].content)

# 2) SAME kind of graph, but compiled with a checkpointer + a thread_id
mem_builder = StateGraph(MessagesState)
mem_builder.add_node("model", fake_model_node)
mem_builder.add_edge(START, "model")
mem_builder.add_edge("model", END)
remembering = mem_builder.compile(checkpointer=InMemorySaver())

config = {"configurable": {"thread_id": "user_123"}}
t1 = remembering.invoke({"messages": [HumanMessage(content="Hi, I am Fraz")]}, config)
print("Thread user_123, turn 1:", t1["messages"][-1].content)

t2 = remembering.invoke({"messages": [HumanMessage(content="What is my name?")]}, config)
print("Thread user_123, turn 2:", t2["messages"][-1].content)

# a DIFFERENT thread_id = a fresh conversation, no memory of user_123
new_config = {"configurable": {"thread_id": "user_999"}}
t3 = remembering.invoke({"messages": [HumanMessage(content="Hello")]}, new_config)
print("Thread user_999 (new thread), turn 1:", t3["messages"][-1].content)

# confirm the old memory module really is gone
try:
    from langchain.memory import ConversationBufferMemory
except ModuleNotFoundError as e:
    print("langchain.memory is gone:", e)

Buffer memory

Apna WhatsApp chat socho kisi dost ke saath jiske saath 3 saal ki history hai. Jab tu chat kholta hai, WhatsApp saare 20,000 messages load nahi karta — wo tujhe last 10-ish dikhata hai, aur abhi kya chal raha hai samajhne ke liye itna hi kaafi hota hai. Agar koi 2 saal purani baat cheden, tujhe manually scroll back karna padega; app khud se wo aage nahi carry karta.

Buffer memory yehi exact idea hai, LLM conversation pe apply kiya hua: sirf last N messages rakho, aur baaki sab drop kar do. Ye sabse simple possible memory strategy hai — koi summarising nahi, koi searching nahi, bas "recent tail rakho, baaki bhool jao".

Manual pattern ek plain Python list hai jiski ek size-cap hai: naya message append karo, aur agar list max_messages se badi ho jaaye, use slice karke wapas chhota kar do (usually system prompt ko index 0 pe pin karke, phir sabse recent messages). Ye exactly wahi hai jo koi chatbot under the hood karta hai model ko call karne se pehle — ye decide karta hai ki is turn me actually kaunse messages bheje jaayenge.

LangChain (1.x) me ek real tool hai jo ye window-trimming tere liye karta hai: langchain_core.messages se trim_messages. Ye ek messages ki list, ek token budget (max_tokens), ek strategy ("last" = sabse recent rakho), aur ek token_counter (production me ek real tokenizer; demo ke liye len jaisa placeholder) leta hai, aur trimmed list return karta hai. Purane LangChain tutorials iske liye ek class sikhate the — ConversationBufferWindowMemory — wo class current 1.x line me DELETE ho chuki hai; from langchain.memory import ConversationBufferWindowMemory import karte hi ModuleNotFoundError aata hai, program shuru hone se pehle hi. trim_messages iska modern, working replacement hai, aur typically ise ek checkpointer (thread-scoped memory mechanism) ke saath combine kiya jaata hai taaki trimmed list hi actually har turn model ko resend ho.

🌍 Real-world example: ek customer-support bot jise sirf customer ki last 2-3 baatein pata honi chahiye ("mera order number X hai", "abhi tak nahi aaya") — use har turn poori chat history resend karne ki zaroorat nahi, last N messages ka buffer hi answer dene ke liye kaafi context hai, aur har API call sasti rehti hai.

💡 Buffer memory = conversation ke sirf last N messages rakhna, baaki discard karna — sabse simple memory strategy.

💡 trim_messages = 1.x ka langchain_core.messages function jo message list ko ek chosen strategy use karke token/message budget tak trim karta hai.

💡 token_counter = wo function jo trim_messages use karta hai har message ka size "count" karne ke liye; production me ye ek real tokenizer hota hai, len jaisa stand-in nahi.

Standard definition (interview me bolo): Buffer memory keeps only the most recent N messages of a conversation and drops older ones to stay within the token budget; in current LangChain (1.x) the working tool for this is trim_messages(messages, max_tokens=N, strategy="last", token_counter=...) — the older ConversationBufferWindowMemory class is deleted.

# --- 1. The manual last-N pattern (plain Python, no library needed) ---
class BufferMemory:
    def __init__(self, max_messages=4):
        self.messages = []
        self.max_messages = max_messages

    def add(self, role, content):
        self.messages.append({"role": role, "content": content})
        if len(self.messages) > self.max_messages:
            # keep the system prompt (index 0) + the most recent (max_messages - 1)
            self.messages = [self.messages[0]] + self.messages[-(self.max_messages - 1):]

    def get_messages(self):
        return self.messages

memory = BufferMemory(max_messages=4)
memory.add("system", "You are a helpful assistant.")
memory.add("user", "Hi, I am Fraz")
memory.add("assistant", "Hello Fraz!")
memory.add("user", "What is 2+2?")
memory.add("assistant", "4")
memory.add("user", "What is my name?")
for m in memory.get_messages():
    print(m)

# --- 2. The real 1.x tool: trim_messages ---
from langchain_core.messages import trim_messages, HumanMessage

msgs = [HumanMessage(content=f"m{i}") for i in range(1, 6)]
trimmed = trim_messages(msgs, max_tokens=3, strategy="last", token_counter=len)
print([m.content for m in trimmed])

# --- 3. Proof the old 0.x class is gone ---
try:
    from langchain.memory import ConversationBufferWindowMemory
except ModuleNotFoundError as e:
    print("dead:", e)

Project: Chatbot jo tumhe yaad rakhe

Kya bana rahe hain: ek chatbot jo tumhe yaad rakhe — ek LangGraph graph jismein DO alag memories ek saath wired hain: ek InMemorySaver checkpointer jo IS session ke messages carry karta hai (short-term, thread_id se keyed), aur ek InMemoryStore fact jo tumhe naam se greet karta hai ek BILKUL NAYI session mein bhi (long-term, user_id se keyed). Yehi is poore chapter ka mental model hai — checkpointer vs Store — ek runnable project mein fuse kiya gaya jo resume pe daal sakte ho.


Step 0 — Mental model (pehle padho)

Turn aata hai (thread_id, user_id) ke saath
        |
        v
[chatbot node] -- state["messages"] padhta hai (checkpointer: sirf IS thread ka)
        |
        +-- store.get(("users", user_id), "profile") padhta hai (Store: SAARE threads ke across)
        |
        +-- agar message kehta hai "I am <Name>" -> store.put(...) fact HAMESHA ke liye save karta hai
        |
        v
   reply: "Hi <Name>!" agar Store mein naam hai, warna "Hi stranger!"

Do ALAG storage systems, do ALAG lifetimes: checkpointer ki messages list thread_id badalte hi empty ho jaati hai. Store ka profile fact thread_id badalne pe reset NAHI hota — sirf tab hota hai jab user_id badalta hai. Yehi contrast poora chapter hai, concrete roop mein.

💡 Checkpointer = short-term memory, ek conversation ki message history, thread_id se keyed. 💡 Store = long-term memory, user ke baare mein facts jo kisi bhi ek conversation se aage tak zinda rehte hain, user_id se keyed (namespaced).


Step 1 — State define karo

from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages

class ChatState(TypedDict):
    messages: Annotated[list, add_messages]
    user_id: str

Ho ye raha hai: messages add_messages reducer se tagged hai, to har node ka returned message list history mein APPEND hota hai, kabhi overwrite nahi hota — bilkul wahi rule jo checkpointers se hai. user_id har turn ke saath state mein saath chalta hai taaki node ko pata rahe KIS user ke long-term facts Store mein dekhne hain; ye checkpointer se bilkul touch nahi hota, ye bas ek plain field hai.


Step 2 — Store banao (long-term memory)

from langgraph.store.memory import InMemoryStore

store = InMemoryStore()

Ho ye raha hai: InMemoryStore checkpointer se ek alag object hai, ek baar banaya jaata hai aur neeche ke node function mein close over hota hai. Ye namespaced key-value storage hai: store.put(namespace_tuple, key, value_dict) likhta hai, store.get(namespace_tuple, key) wapas ek object deta hai jiska .value wo dict hai. Hum ("users", user_id) se namespace karenge taaki har user ke facts har doosre user se isolated rahein, bilkul long-term-memory-store wala pattern.


Step 3 — Chatbot node (DONO memories padhta hai)

def chatbot(state: ChatState):
    last_human = state["messages"][-1].content
    user_id = state["user_id"]
    namespace = ("users", user_id)
    remembered = store.get(namespace, "profile")

    # pehli baar "I am <Name>" dekhte hi naam extract karo (pure Python, ise chalane ke liye LLM nahi chahiye)
    if "i am" in last_human.lower():
        name = last_human.lower().split("i am")[-1].strip().split()[0].capitalize()
        store.put(namespace, "profile", {"name": name})
        remembered = store.get(namespace, "profile")

    if remembered:
        name = remembered.value["name"]
        reply = f"Hi {name}! (this session has {len(state['messages'])} messages so far)"
    else:
        reply = f"Hi stranger! (this session has {len(state['messages'])} messages so far)"

    from langchain_core.messages import AIMessage
    return {"messages": [AIMessage(content=reply)]}

Ho ye raha hai: state["messages"] CHECKPOINTER ka kaam hai — LangGraph ne pehle hi is thread ke pichhle turns ko state mein restore kar diya hai node call karne se pehle, to len(state["messages"]) genuinely EK thread_id ke andar turn-over-turn badhta hai. store.get(...) / store.put(...) STORE ka kaam hai — ye ek fact user_id se keyed read/write karte hain, chaahe koi bhi thread ho us se bilkul independent. Ek real build "i am" in last_human.lower() extraction ki jagah ek LLM call use karti jo free text se structured facts nikaale (usse illustrative maano); neeche ki store/namespace WIRING dono tarah se same rehti hai — yehi exact pure-Python version hai jo hum neeche run aur verify karte hain.


Step 4 — Graph ko checkpointer ke saath wire karo

from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver

graph = StateGraph(ChatState)
graph.add_node("chatbot", chatbot)
graph.add_edge(START, "chatbot")
graph.add_edge("chatbot", END)

checkpointer = InMemorySaver()
app = graph.compile(checkpointer=checkpointer)

Ho ye raha hai: .compile() ko checkpointer=InMemorySaver() pass karna wahi EK line hai jo ek plain graph ko memory-carrying graph mein badalti hai — app ke har .invoke() call mein, agar config mein thread_id ho, to node chalane se pehle us thread ke pichhle messages load honge aur update hone ke baad save honge. config mein thread_id na ho to koi persistence nahi hoti. C:/lcv pe verified: ye exact graph zero API keys aur zero network calls ke saath compile hota hai — is project mein construct ya invoke karne ke liye kahin bhi key nahi chahiye, yehi ek pure-Python node ka poora point hai.


Step 5 — Turn 1 aur Turn 2, SAME thread (checkpointer prove karta hai)

from langchain_core.messages import HumanMessage

config1 = {"configurable": {"thread_id": "abc123"}}
r1 = app.invoke({"messages": [HumanMessage(content="Hi, I am Fraz")], "user_id": "user_1"}, config1)
r2 = app.invoke({"messages": [HumanMessage(content="What's the weather like?")], "user_id": "user_1"}, config1)

Ye C:/lcv pe ACTUALLY chala — zero API keys — aur ye real state diya, turn by turn:

--- Turn 1 (thread abc123) ---
HumanMessage | Hi, I am Fraz
AIMessage    | Hi Fraz! (this session has 1 messages so far)
msg count: 2

--- Turn 2 (SAME thread abc123) ---
HumanMessage | Hi, I am Fraz
AIMessage    | Hi Fraz! (this session has 1 messages so far)
HumanMessage | What's the weather like?
AIMessage    | Hi Fraz! (this session has 3 messages so far)
msg count: 4

Beat by beat trace karo: Turn 1 sirf apna khud ka HumanMessage dekhta hai (checkpointer ke paas abc123 ke liye kuch nahi tha abhi), "Fraz" extract karta hai, fact Store mein likhta hai, aur reply karta hai. Turn 2 .invoke() ko ek NAYE HumanMessage aur SAME config1 ke saath call karta hai — checkpointer PEHLE turn 1 ke do messages restore karta hai, add_messages naye turn ke do messages upar append karta hai, to node dekhta hai len(state["messages"]) == 3 (apna reply append hone se theek pehle ka fresh count) aur final list mein 4 hain. Ye short-term memory hai, genuinely carried, real numbers ke saath.


Step 6 — Ek bilkul nayi session, SAME user (Store prove karta hai)

config2 = {"configurable": {"thread_id": "xyz789"}}
r3 = app.invoke({"messages": [HumanMessage(content="Hello again")], "user_id": "user_1"}, config2)

Ye bhi real mein chala:

--- New thread xyz789 (new session, same user_1) ---
HumanMessage | Hello again
AIMessage    | Hi Fraz! (this session has 1 messages so far)
msg count: 2

Ye poora chapter ek line ke output mein hai. thread_id "abc123" se "xyz789" ho gaya, to CHECKPOINTER ke paas kuch nahi hai — state["messages"] bilkul fresh 1 message se start hota hai, bilkul ek nayi conversation ki tarah, upar wale turn 1 aur turn 2 ki koi memory nahi. Par user_id abhi bhi "user_1" hai, to STORE lookup ("users", "user_1") pe wahi {"name": "Fraz"} fact dhoondh leta hai jo Step 5 mein likha gaya tha, aur bot Fraz ko naam se greet kar deta hai. Short-term memory zero pe reset ho gayi; long-term memory nahi hui.


Step 7 — Ek alag user (isolation prove karta hai)

config3 = {"configurable": {"thread_id": "thread_new_user"}}
r4 = app.invoke({"messages": [HumanMessage(content="Hey")], "user_id": "user_999"}, config3)
--- New thread + new user_999 ---
HumanMessage | Hey
AIMessage    | Hi stranger! (this session has 1 messages so far)

Ye kya prove karta hai: ("users", "user_999") mein kabhi kuch likha hi nahi gaya, to store.get(...) None return karta hai aur node "Hi stranger!" pe fallback karta hai. Store namespace genuinely ek user ke facts ko doosre se isolate karta hai — ye koi global variable nahi hai, per-user storage hai.


Step 8 — Real LLM kahan fit hota (illustrative)

Is project mein do jagah plain Python se stub kiya gaya hai taaki WIRING zero API keys se chale; ek production build inhe real model calls se swap kar sakti hai, graph ko touch kiye bina:

  1. Fact extraction"i am" in last_human.lower() ek toy string match hai. Ek real build message ko ek LLM ko ek chhota extraction prompt ke saath bhejti hai ("agar user ka naam mila to nikaalo") aur jo bhi structured fact wapas aaye use store karti hai. Ise illustrative maano — isko key chahiye.
  2. Khud replyf"Hi {name}! ..." ek f-string hai. Ek real build state["messages"] (plus recalled fact ek system message mein inject kiya hua) ek chat model ko bhejti hai aur uska AIMessage return karti hai, haath se banaya string nahi.

In dono swaps se Step 4 ki graph wiring, Step 5 ka checkpointer behaviour, ya Step 6/7 ka Store behaviour ki ek bhi line nahi badalti — wo SAB upar bina key ke genuinely verified hain. Sirf model jo WORDING produce karta, wo illustrative hai:

AI (illustrative, real LLM node mein): "Welcome back, Fraz! Last time you asked about
the weather -- anything else I can help with today?"

✅ Jo tumne abhi banaya — aur resume framing

Tumne ek chatbot banaya jismein do INDEPENDENT, sahi se scoped memories hain: ek checkpointer (InMemorySaver, thread_id se keyed) jo genuinely ek conversation ke messages turn to turn carry karta hai, aur ek Store (InMemoryStore, ("users", user_id) se namespaced) jo genuinely ek bilkul nayi thread_id ke baad bhi survive karta hai aur user ke baare mein ek fact yaad rakhta hai. Tumne DONO ko real .invoke() calls aur real message counts se prove kiya, koi mocked example nahi — same thread 2 se 4 messages tak badha; ek naya thread 1 message pe reset hua par phir bhi user ko naam se greet kiya; ek naye user ko stranger fallback mila. Yehi exact short-term/long-term split hai jo har LangGraph memory question actually poochta hai.

Resume/interview ke liye: "Built a memory-aware chatbot in LangGraph — an InMemorySaver checkpointer scoped to thread_id for per-conversation short-term memory, plus an InMemoryStore namespaced by user_id for long-term facts that persist across sessions, with add_messages correctly appending state instead of overwriting it." Ye sentence dikhata hai ki tum checkpointer-vs-Store distinction samajhte ho, sirf .invoke() call kiya nahi.

Ise extend karne ke liye bonus features (project claim karne ke liye teenon banana zaroori NAHI hai):

  1. Real fact extraction"i am" string match ki jagah ek LLM call se multiple facts (naam, role, preferences) free text se Store mein extract karo.
  2. Durable persistenceInMemorySaver/InMemoryStore ko ek SqliteSaver-backed setup se swap karo (separate package, langgraph-checkpoint-sqlite) taaki dono memories process restart ke baad bhi survive karein, sirf RAM mein nahi.
  3. Checkpointer ki history trim karo — ek thread lambi ho jaaye to state["messages"] pe trim_messages chalao real model ko bhejne se pehle, taaki checkpointer sab kuch rakhe par model ko sirf ek bounded window dikhe (dekho buffer-memory).

Standard definition (interview me bolo): a memory-aware LangGraph chatbot combines two distinct persistence layers — a checkpointer (short-term, keyed by thread_id, carries one conversation's message history and resets on a new thread) and a Store (long-term, keyed/namespaced by user_id, holds facts that survive across every thread) — so the same application can both remember the last few turns of THIS conversation and recognise a returning user in a conversation it has never seen before.

from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.store.memory import InMemoryStore
from langchain_core.messages import HumanMessage, AIMessage

class ChatState(TypedDict):
    messages: Annotated[list, add_messages]  # reducer: APPENDS, never overwrites
    user_id: str

store = InMemoryStore()  # long-term memory: facts survive across every thread_id

def chatbot(state: ChatState):
    last_human = state["messages"][-1].content
    user_id = state["user_id"]
    namespace = ("users", user_id)
    remembered = store.get(namespace, "profile")

    if "i am" in last_human.lower():
        name = last_human.lower().split("i am")[-1].strip().split()[0].capitalize()
        store.put(namespace, "profile", {"name": name})
        remembered = store.get(namespace, "profile")

    if remembered:
        name = remembered.value["name"]
        reply = f"Hi {name}! (this session has {len(state['messages'])} messages so far)"
    else:
        reply = f"Hi stranger! (this session has {len(state['messages'])} messages so far)"

    return {"messages": [AIMessage(content=reply)]}

graph = StateGraph(ChatState)
graph.add_node("chatbot", chatbot)
graph.add_edge(START, "chatbot")
graph.add_edge("chatbot", END)

checkpointer = InMemorySaver()  # short-term memory: carries THIS thread_id's messages
app = graph.compile(checkpointer=checkpointer)

config1 = {"configurable": {"thread_id": "abc123"}}
r1 = app.invoke({"messages": [HumanMessage(content="Hi, I am Fraz")], "user_id": "user_1"}, config1)
r2 = app.invoke({"messages": [HumanMessage(content="What's the weather like?")], "user_id": "user_1"}, config1)

config2 = {"configurable": {"thread_id": "xyz789"}}  # NEW thread, SAME user
r3 = app.invoke({"messages": [HumanMessage(content="Hello again")], "user_id": "user_1"}, config2)

config3 = {"configurable": {"thread_id": "thread_new_user"}}  # NEW thread, NEW user
r4 = app.invoke({"messages": [HumanMessage(content="Hey")], "user_id": "user_999"}, config3)

for label, result in [("Turn 1", r1), ("Turn 2 (same thread)", r2), ("New thread, same user", r3), ("New thread, new user", r4)]:
    print(f"--- {label} ---")
    for m in result["messages"]:
        print(type(m).__name__, "|", m.content)

Memory Managementinterview questions & answers

10 sample questions below — 159+ in the full bank inside.

`trim_messages` kya karta hai?

`trim_messages(messages, max_tokens=N, strategy="last", token_counter=...)` ek message list leta hai aur sirf utni recent messages return karta hai jitni `max_tokens` me fit ho jaayen, baaki purani drop kar deta hai. Ye message list bound karne ka real 1.x tool hai — verified: 5 messages ko `max_tokens=3, token_counter=len` ke saath trim karne pe last 3 milti hain.

In simple terms: Ye ek chhoti suitcase pack karne jaisa hai — tum sabse recent, sabse zaroori kapde rakhte ho aur purane chhod dete ho kyunki jagah limited hai. Example: `trim_messages([m1,m2,m3,m4,m5], max_tokens=3, strategy="last", token_counter=len)` `[m3, m4, m5]` return karta hai.

Buffer memory ka manual pattern kya hai, aur `trim_messages` khud likhne se kaise alag hai?

Manual pattern plain Python hai: ek list rakho, naye messages append karo, aur jab wo `max_messages` se zyada ho jaaye to use last N tak slice kar do (aksar index 0, system message, ko alag rakhte hue). `trim_messages` wahi kaam karta hai lekin library-provided, tested version hai jo LangGraph node me plug hota hai aur sirf list length count karne ke bajaye real token counter leta hai.

In simple terms: Ye ingredients haath se measure karne aur kitchen scale use karne jaisa hai — dono se portion mil jata hai, lekin tool calibrated aur kam error-prone hota hai. Example: `messages = [messages[0]] + messages[-max_messages:]` manual slice hai; `trim_messages(messages, max_tokens=N, strategy="last", token_counter=count_tokens)` uska 1.x equivalent hai.

Agar LLM khud kuch yaad nahi rakhta, to 'memory' ka actually matlab kya hota hai jab log AI chatbot ke baare me baat karte hain?

Memory application-side state management hai, model ka feature nahi. App kahin pe purane messages (ya facts) track karta hai — kisi variable me, database me, checkpointer me — aur relevant part har nayi call pe prompt me wapas daal deta hai. 'Memory add karna' ka matlab hai 'ek system banana jo sahi context resend kare'.

In simple terms: Ek doctor ko socho jiske 200 patients hain — doctor har visit yaad nahi rakhta, lekin file room rakhta hai, aur doctor har appointment se pehle tumhari file padh leta hai. Example: LangGraph ka checkpointer wahi file room hai — ye purane messages ko `thread_id` se store karta hai aur agle `.invoke()` se pehle graph ko wapas de deta hai.

Modern LangChain/LangGraph me `ConversationBufferMemory` (aur `ConversationBufferWindowMemory`) ki jagah kya aaya?

Dono deleted 0.x classes hain — `from langchain.memory import ConversationBufferMemory` current 1.x line pe `ModuleNotFoundError` deta hai. Short-term memory ab ek LangGraph checkpointer hai (`InMemorySaver`, a.k.a. `MemorySaver`) jo `thread_id` se key hota hai, aur message list ko window/trim karne ke liye `langchain_core.messages` ka `trim_messages` use hota hai.

In simple terms: Ye ek discontinued car part jaisa hai — part number shop pe resolve hi nahi hota, isliye current replacement part use karte ho. Example: `ConversationBufferWindowMemory(k=5)` ki jagah, tum graph ko `checkpointer=InMemorySaver()` ke saath compile karte ho aur node ke andar `trim_messages(state["messages"], max_tokens=N, strategy="last", token_counter=...)` call karte ho.

Buffer memory kya hai, ek line me?

Buffer memory ka matlab hai conversation ke sirf last N messages rakhna aur usse purana sab bhool jana, instead of har turn pe poori history resend karne ke. Ye har call pe resend hone wale tokens ko bound karne ka sabse simple tarika hai.

In simple terms: Ye aisa hai jaise chat catch-up karne ke liye sirf apne last 10 WhatsApp messages padhna, message 1 tak scroll na karna — recent context usually kaafi hota hai. Example: N=4 ke saath, 6 messages ke baad tum sirf messages 3-6 rakhte ho aur 1-2 bhool jaate ho.

Buffer memory ke pros aur cons kya hain?

Pros: implement karna simple hai, fast hai, aur token-efficient hai kyunki tum hamesha ek bounded window hi resend karte ho. Con: window se purana koi bhi context poori tarah gayab ho jata hai — model ko pata hi nahi chalta wo kabhi hua bhi tha, uska summary tak nahi bachta.

In simple terms: Ye ek limited-space wale whiteboard jaisa hai — newest notes likhna fast aur sasta hai, lekin jagah banane ke liye jab purani notes mitaate ho, wo hamesha ke liye gayab ho jaati hain, kahin file nahi hoti. Example: agar koi message 1 me apna naam batata hai aur window sirf last 4 messages rakhti hai, to message 10 tak bot ko naam sach me yaad nahi rehta.

Vector-store memory ka quick pros/cons summary do.

Pros: sirf relevant context retrieve karti hai chahe wo kitna bhi purana ho, aur hazaron past messages tak scale hoti hai bina prompt ko unboundedly bade kiye. Cons: har store aur har retrieval pe ek embedding call ka cost lagta hai, aur similarity search nuance miss kar sakti hai ya technically-similar-but-wrong match return kar sakti hai.

In simple terms: Ye phone book (fast lekin sirf exact-name lookup) aur smart search engine (flexible meaning-based lookup, lekin har search pe compute cost) ke beech ka trade-off hai. Example: hazaron stored facts wale ek personalised assistant ko vector memory ke scale se bahut fayda hota hai, lekin ek chhoti 5-message chat me isse kuch nahi milta aur buffer memory simpler aur sasti hogi.

Agar tum ek LLM ko do alag, unrelated Python function calls me back-to-back call karo, to kya doosri call ko pata hoga ki pehli me kya poocha tha?

Nahi. Jab tak tumhara code explicitly pehli call ke messages capture karke doosri call ke input me include na kare, model ko pehli call ke baare me zero awareness hoti hai — ye ek bilkul fresh request hoti hai. Ye concrete proof hai ki statelessness model/API layer pe hoti hai, tumhare program me nahi.

In simple terms: Ye do alag letters do alag strangers ko bhejne jaisa hai aur ye expect karna ki doosra stranger jaan jayega pehle letter me kya likha tha — usne wo dekha hi nahi. Example: `model.invoke("My name is Fraz")` ke baad ek bilkul nayi `model.invoke("What's my name?")` call (koi shared state pass kiye bina) kuch aisa return karti hai jaise 'I don't have that information' — 'Fraz' nahi.

LLMs stateful hote hain ya stateless?

LLMs stateless hote hain. Har API call independent hoti hai — model ko pichli call ka kuch yaad nahi rehta jab tak application current prompt ke saath purani conversation resend na kare. Chatbot jo 'yaad rakhta' lagta hai, wo actually app hai jo har turn pe history wapas bhej raha hota hai.

In simple terms: Ye aisa hai jaise kisi total amnesia wale insaan se baat karna jo har sentence bolne se pehle ek notebook padhta hai jo tum usko dete ho — wo yaad nahi rakh raha, tum use har baar yaad dila rahe ho. Example: agar tum model ko do baar sirf `"What's my name?"` bolo aur pehle kabhi naam bataya hi na ho usi call me, to usko pata hi nahi chal sakta — server side pe koi hidden session nahi hota.

Modern LangChain/LangGraph me `ConversationBufferMemory` ki jagah kya aaya?

Pura `langchain.memory` module — `ConversationBufferMemory` samet — current (1.x) line me delete ho chuka hai; ise import karne pe `ModuleNotFoundError` aata hai. Modern replacement hai LangGraph checkpointer: `graph.compile(checkpointer=InMemorySaver())`, jisme conversation ko `thread_id` se identify kiya jata hai jo `config` me pass hota hai.

In simple terms: Ye aisa hai jaise ek dukaan band ho gayi aur saamne ek naya store khul gaya jisme tumhara tab rakhne ka tareeka bilkul alag hai — purani ledger book (`ConversationBufferMemory`) gayi, aur ab cashier tumhe customer ID (`thread_id`) se dhundta hai. Example: `from langgraph.checkpoint.memory import InMemorySaver` phir `graph.compile(checkpointer=InMemorySaver())` — koi `langchain.memory` import ki zaroorat hi nahi.

149+ more Memory Management questions inside

Create a free account to read the full question bank, learn every topic, and practise with an AI mock interview.

Unlock all questions — free

Ready to practise Memory Management?

Unlock every topic free, then face an AI interviewer that asks follow-ups and grades your answers.