𝟯 LangGraph ری رائٹس: پروڈکشن چیک پوائنٹنگ نے مجھے کیا سکھایا
تین ہفتوں تک، ہمارا آن بورڈنگ ایجنٹ ہر اس کام کو کھو دیتا تھا جسے اسے محفوظ کرنا تھا۔ لاگز میں کچھ نظر نہیں آیا۔ نہ کوئی ایرر، نہ کوئی وارننگ۔ چیک پوائنٹر نے کامیابی کی اطلاع دی، لیکن دوبارہ شروع کرنے (resume) پر اسٹیٹ غائب ہو جاتی تھی۔
حقیقت سمجھنے سے پہلے میں نے ایک ہی LangGraph پائپ لائن کو تین بار دوبارہ لکھا۔ فریم ورک نے بالکل وہی کیا جو میں نے اسے کرنے کو کہا تھا۔ میں اسے غلط ہدایات دے رہا تھا۔
اگر آپ پروڈکشن کے لیے اسٹیٹ فل (stateful) ایجنٹس بنا رہے ہیں، تو یہ فرض نہ کریں کہ ڈیفالٹس آپ کو بچا لیں گے۔ یہاں وہ چیزیں ہیں جو خراب ہوئیں اور میں نے انہیں کیسے ٹھیک کیا۔
𝗧𝗵𝗲 𝗙𝗶𝗿𝘀𝘁 𝗕𝗿𝗲𝗮𝗸: 𝗦𝗶𝗹𝗲𝗻𝘁 𝗦𝘁𝗮𝘁𝗲 𝗟𝗼𝘀𝘀
میرا ایجنٹ پانچ مرحلوں والے آن بورڈنگ فلو کو ہینڈل کرتا تھا۔ میں نے پروگریس کو محفوظ کرنے کے لیے Postgres کا استعمال کیا تاکہ صارفین بعد میں وہیں سے شروع کر سکیں۔ لیکن ہر بار دوبارہ شروع کرنے پر یہ پہلے مرحلے سے شروع ہوتا تھا۔
اس کی وجہ میرا اسٹیٹ اسکیمہ (state schema) تھا۔ LangGraph میں، ہر نوڈ ایک اپ ڈیٹ واپس کرتا ہے جو اسٹیٹ میں ضم (merge) ہو جاتی ہے۔ اگر آپ یہ متعین نہیں کرتے کہ اسے کیسے ضم کرنا ہے، تو ڈیفالٹ طور پر یہ پرانی ویلیو کو اوور رائٹ (overwrite) کر دیتا ہے۔
میں نے سوچا تھا کہ میری میسج لسٹ میں نئے پیغامات شامل (append) ہوتے رہیں گے۔ اس کے بجائے، ہر نئے نوڈ نے پوری ہسٹری کو صرف ایک پیغام سے بدل دیا۔ چیک پوائنٹر نے غلط ڈیٹا کو بالکل صحیح طریقے سے محفوظ کر لیا تھا۔
حل: واضح ریڈیوسرز (reducers) کے ساتھ Annotated فیلڈز کا استعمال کریں۔
• میسج لسٹوں کے لیے add آپریٹر کا استعمال کریں۔
• ڈکشنریز کے لیے ایک کسٹم مرج فنکشن استعمال کریں۔
• ڈیفالٹ اوور رائٹ کا استعمال صرف ان سنگل ویلیوز کے لیے کریں جیسے کہ "step"۔
𝗧𝗵𝗲 𝗦𝗲𝗰𝗼𝗻𝗱 𝗕𝗿𝗲𝗮𝗸: 𝗗𝗲𝘀𝗲𝗿𝗶𝗮𝗹𝗶𝘇𝗮𝘁𝗶𝗼𝗻 𝗮𝗻𝗱 𝗖𝗼𝗻𝗰𝘂𝗿𝗿𝗲𝗻𝗰𝘆
دوسرے ری رائٹ میں دو نئے مسائل پیش آئے:
- خراب روز (Corrupt rows): میں نے اسٹیٹ میں کسٹم آبجیکٹس اسٹور کیے تھے۔ سیریلائزر انہیں ہینڈل نہیں کر سکا۔ اس سے ایسی روز (rows) بن گئیں جو موجود تو تھیں لیکن ناقابل استعمال تھیں۔
- ڈپلیکیٹ کیز (Duplicate keys): اگر آپ تیزی سے جواب نہیں دیتے تو WhatsApp ویب ہکس (webhooks) کو دوبارہ کوشش کرتا ہے۔ اگر دو پیغامات ایک ساتھ پہنچتے، تو گراف کے دو رنز ایک ہی تھریڈ میں لکھنے کی کوشش کرتے۔ اس سے ڈیٹا بیس میں ٹکراؤ (collisions) پیدا ہوا۔
حل:
• کسٹم آبجیکٹس کو ہٹا دیں۔ صرف سادہ dict اور معیاری LangChain ٹائپس کا استعمال کریں۔
• ویب ہکس کو گراف سے باہر ہینڈل کریں۔ ڈپلیکیٹس کو ختم کرنے کے لیے ایک کیو (queue) اور idempotency key کا استعمال کریں۔
• ڈیٹا بیس لاک شامل کریں۔ اس بات کو یقینی بنائیں کہ ایک وقت میں ایک تھریڈ پر صرف ایک ہی رن ہو۔
𝗧𝗵𝗲 𝗧𝗵𝗶𝗿𝗱 𝗥𝗲𝘄𝗿𝗶𝘁𝗲: 𝗧𝗵𝗲 𝗦𝘁𝗮𝗯𝗹𝗲 𝗣𝗮𝘁𝘁𝗲𝗿𝗻
حتمی ورژن تین اصولوں پر مرکوز تھا:
• Small graphs: I broke one massive graph into three smaller subgraphs. This reduced the blast radius of bugs. • Explicit checkpoints: I stopped checkpointing after every single node. I only checkpoint at meaningful resume points. This cut database writes by 60%. • Idempotent nodes: This is vital. Every node must produce the same result if it runs twice. If a node sees that a task is already done in the state, it should return immediately. This prevents double-charging for expensive model calls.
𝗟𝗲𝘀𝘀𝗼𝗻𝘀 𝗳𝗼𝗿 𝘆𝗼𝘂:
- Read reducer semantics before you write code.
- Do not store custom objects in state.
- Move concurrency control outside the graph.
- Make every node idempotent.
The framework did not fail. My assumptions did.
Optional learning community: https://t.me/GyaanSetuAi