AI Engineering/LLM API-র ভিত্তি/Lesson 02
Conversation আর memory
API stateless। প্রতিবার পুরো কথোপকথন আবার পাঠাতে হয়। Message history রাখা, user/assistant পালাক্রম, আর context window ভরে গেলে পুরনো message ছাঁটাই।
- সময়
- 22 মিনিট
- Exercise
- 1
- Challenge
- 1
- Quiz
- 3 প্রশ্ন
সহজ ভাষায়
তুমি chatbot-কে বললে "আমার নাম রিয়া", তারপর জিজ্ঞেস করলে "আমার নাম কী?" Chatbot ঠিক উত্তর দেয়। তাহলে কি model মনে রেখেছে? না।
LLM API stateless, অর্থাৎ প্রতিটা request সম্পূর্ণ আলাদা। "মনে রাখা" আসলে তোমার code-এর কাজ: পুরো কথোপকথন একটা list-এ রাখো আর প্রতিবার পুরোটা পাঠাও।
request 1: [user: আমার নাম রিয়া]
request 2: [user: আমার নাম রিয়া, assistant: হ্যালো রিয়া!, user: আমার নাম কী?]
↑ পুরো history আবার পাঠানো হলো
কেন দরকার?
- Chatbot বানানোর মূল কৌশল এটাই
- খরচ: প্রতিটা নতুন message-এ পুরো history আবার input token হিসেবে গোনা হয়
- সীমা: Context window শেষ হলে আর পাঠানো যায় না, তখন ছাঁটাই করতে হয়
Messages-এর নিয়ম
messages = [
{"role": "user", "content": "আমার নাম রিয়া"},
{"role": "assistant", "content": "হ্যালো রিয়া! কীভাবে সাহায্য করতে পারি?"},
{"role": "user", "content": "আমার নাম কী?"},
]
response = client.messages.create(model="claude-opus-5-5", max_tokens=200, messages=messages)
roleহয়userনয়তোassistant- প্রথম message সাধারণত
user - System prompt
messages-এ যায় না, আলাদাsystemparameter-এ যায়
History কতটা বাড়ে
(ধরে নিচ্ছি প্রতিটা প্রশ্ন ~১৫০ token আর প্রতিটা উত্তর ~২৫০ token।) ২০টা প্রশ্নে মোট input token প্রায় দ্বিঘাত হারে (quadratically) বাড়ে। দীর্ঘ কথোপকথনে খরচ বাড়ে এভাবেই।
Context window ভরে গেলে
তিনটা সাধারণ কৌশল:
| কৌশল | কীভাবে | অসুবিধা |
|---|---|---|
| Sliding window | সবচেয়ে পুরনো message বাদ | পুরনো তথ্য হারায় |
| Summarization | পুরনো অংশ LLM দিয়ে সংক্ষেপ করে একটা message বানাও | একটা অতিরিক্ত call, কিছু বিস্তারিত হারায় |
| আলাদা memory | গুরুত্বপূর্ণ তথ্য (নাম, পছন্দ) আলাদা রাখো, system prompt-এ দাও | বেশি জটিল |
Challenge-এ sliding window বানাবে। একটা সূক্ষ্ম নিয়ম আছে: ছাঁটাইয়ের পর প্রথম message যেন assistant না হয়।
Exercise
Exercise
Message history
একটা ছোট Chat class সম্পূর্ণ করো:
self.messages— শুরুতে খালি listsend(self, text, model)—text-কে user message হিসেবে যোগ করবে। তারপরmodel(self.messages)call করবে, যেটা উত্তরের string দেয়। উত্তরকে assistant message হিসেবে যোগ করে return করবে।
প্রতিটা message হবে {"role": ..., "content": ...}। দেওয়া fake_model শুধু গুনে বলে কয়টা message পেয়েছে।
Quiz
Challenge
Challenge
Context window-এ আঁটানো
trim_history(messages, max_tokens, count_tokens) লেখো। এটা সবচেয়ে নতুন message-গুলো রাখবে যাতে মোট token (count_tokens(content) দিয়ে মাপা) max_tokens-এর মধ্যে থাকে।
নিয়ম:
1. পেছন থেকে (নতুন থেকে পুরনো) message নিতে থাকো, যতক্ষণ মোট সীমার মধ্যে থাকে। যেটা আঁটে না, সেখানেই থামো।
2. ফলাফলের প্রথম message অবশ্যই user হবে। শুরুতে assistant থাকলে সেগুলো বাদ দাও।
3. ক্রম অপরিবর্তিত থাকবে, আর মূল list বদলানো যাবে না।
(সরলতার জন্য count_tokens = শব্দ সংখ্যা।)
বাস্তবে কোথায় ব্যবহার হয়?
একটা পূর্ণ terminal chatbot, ২০ লাইনে:
import anthropic
client = anthropic.Anthropic()
messages = []
while True:
text = input("তুমি: ")
if text in {"exit", "quit"}:
break
messages.append({"role": "user", "content": text})
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
system="তুমি একজন বন্ধুসুলভ সহকারী। বাংলায় উত্তর দাও।",
messages=messages,
)
reply = response.content[0].text
messages.append({"role": "assistant", "content": reply})
print("AI:", reply)
বাস্তব app-এ messages database-এ রাখা হয় (প্রতি user-এর আলাদা), যাতে server restart হলেও কথোপকথন থাকে।
Interview প্রশ্ন
- Beginner: LLM chatbot কীভাবে আগের কথা "মনে রাখে"?
- Intermediate: লম্বা কথোপকথনে খরচ কেন বাড়ে? কীভাবে নিয়ন্ত্রণ করবে?
- Advanced: লাখো user-এর একটা chatbot-এ memory-র architecture কেমন হবে? Summarization আর retrieval-based memory তুলনা করো।
এরপর কী?
এ পর্যন্ত output ছিল মুক্ত লেখা। কিন্তু code-এর দরকার structured data, যেমন JSON, যেটা program পড়তে পারে। আর LLM সবসময় ঠিক format দেয় না। পরের lesson: Output validation।