3 LangGraph రీరైట్స్: ప్రొడక్షన్ చెక్‌పాయింటింగ్ నాకు నేర్పిన పాఠాలు

మూడు వారాల పాటు, మా ఆన్‌బోర్డింగ్ ఏజెంట్ సేవ్ చేయాల్సిన ప్రతి పనిని కోల్పోయింది. లాగ్స్‌లో ఏమీ కనిపించలేదు. ఎటువంటి ఎర్రర్స్ లేవు. ఎటువంటి వార్నింగ్స్ లేవు. చెక్‌పాయింటర్ సక్సెస్ అని చూపించింది, కానీ రీజ్యూ చేసినప్పుడు స్టేట్ (state) మాయమైపోయింది.

నిజం అర్థం చేసుకునే ముందు నేను అదే LangGraph పైప్‌లైన్‌ను మూడుసార్లు రీరైట్ చేశాను. ఫ్రేమ్‌వర్క్ నేను చెప్పినట్లే చేసింది. నేను దానికి తప్పుడు సూచనలు ఇస్తున్నాను.

మీరు ప్రొడక్షన్ కోసం స్టేట్‌ఫుల్ ఏజెంట్లను (stateful agents) నిర్మిస్తుంటే, డిఫాల్ట్ సెట్టింగ్స్ మిమ్మల్ని కాపాడతాయని అనుకోవద్దు. ఇక్కడ ఏమి విఫలమైంది మరియు నేను దానిని ఎలా సరిదిద్దానో చూడండి.

మొదటి విఫలం: సైలెంట్ స్టేట్ లాస్

నా ఏజెంట్ ఐదు దశల ఆన్‌బోర్డింగ్ ఫ్లోను హ్యాండిల్ చేసేది. యూజర్లు తర్వాత కొనసాగించగలిగేలా ప్రోగ్రెస్ సేవ్ చేయడానికి నేను Postgres ఉపయోగించాను. కానీ ప్రతిసారీ రీజ్యూ చేసినప్పుడు మొదటి దశ నుండే ప్రారంభమయ్యేది.

దీనికి కారణం నా స్టేట్ స్కీమా (state schema). LangGraphలో, ప్రతి నోడ్ స్టేట్‌లోకి మెర్జ్ అయ్యే ఒక అప్‌డేట్‌ను రిటర్న్ చేస్తుంది. మీరు ఎలా మెర్జ్ చేయాలో పేర్కొనకపోతే, డిఫాల్ట్‌గా అది పాత డేటాను ఓవర్‌రైట్ (overwrite) చేస్తుంది.

నా మెసేజ్ లిస్ట్ అపెండ్ (append) అవుతుందని నేను అనుకున్నాను. కానీ దానికి బదులుగా, ప్రతి కొత్త నోడ్ మొత్తం హిస్టరీని కేవలం ఒకే ఒక మెసేజ్‌తో రీప్లేస్ చేసింది. చెక్‌పాయింటర్ తప్పు డేటాను ఖచ్చితంగా సేవ్ చేసింది.

పరిష్కారం: ఎక్స్‌ప్లిసిట్ రిడ్యూసర్‌లతో (explicit reducers) Annotated ఫీల్డ్స్‌ను ఉపయోగించండి.

• మెసేజ్ లిస్ట్‌ల కోసం add ఆపరేటర్‌ను ఉపయోగించండి. • డిక్షనరీల కోసం కస్టమ్ మెర్జ్ ఫంక్షన్‌ను ఉపయోగించండి. • "step" వంటి సింగిల్ వాల్యూస్ కోసం మాత్రమే డిఫాల్ట్ ఓవర్‌రైట్‌ను ఉపయోగించండి.

రెండవ విఫలం: డీసీరియలైజేషన్ మరియు కన్కరెన్సీ

రెండవ రీరైట్‌లో రెండు కొత్త సమస్యలు ఎదురయ్యాయి:

  1. కరప్ట్ రోస్ (Corrupt rows): నేను స్టేట్‌లో కస్టమ్ ఆబ్జెక్ట్‌లను స్టోర్ చేశాను. సీరియలైజర్ వాటిని హ్యాండిల్ చేయలేకపోయింది. దీనివల్ల రోస్ (rows) ఉన్నప్పటికీ, అవి ఉపయోగపడకుండా పోయాయి.
  2. డూప్లికేట్ కీస్ (Duplicate keys): మీరు వేగంగా స్పందించకపోతే WhatsApp వెబ్‌హుక్స్‌ను (webhooks) మళ్ళీ మళ్ళీ ప్రయత్నిస్తుంది. ఒకేసారి రెండు మెసేజ్‌లు వచ్చినప్పుడు, రెండు గ్రాఫ్ రన్‌లు ఒకే థ్రెడ్‌కు డేటాను రాయడానికి ప్రయత్నించాయి. దీనివల్ల డేటాబేస్ కొలిజన్స్ (collisions) ఏర్పడ్డాయి.

పరిష్కారాలు: • కస్టమ్ ఆబ్జెక్ట్‌లను తొలగించండి. కేవలం ప్లెయిన్ డిక్ట్స్ (plain dicts) మరియు స్టాండర్డ్ LangChain టైప్స్‌ను మాత్రమే ఉపయోగించండి. • వెబ్‌హుక్స్‌ను గ్రాఫ్ వెలుపల హ్యాండిల్ చేయండి. డూప్లికేట్‌లను తొలగించడానికి క్యూ (queue) మరియు ఐడెంపోటెన్సీ కీ (idempotency key) ఉపయోగించండి. • డేటాబేస్ లాక్ (database lock) జోడించండి. ఒక సమయంలో ఒక థ్రెడ్‌కు ఒకే రన్ జరుగుతుందని నిర్ధారించుకోండి.

మూడవ రీరైట్: స్థిరమైన ప్యాటర్న్

చివరి వెర్షన్ మూడు సూత్రాలపై దృష్టి సారించింది:

• చిన్న గ్రాఫ్‌లు: నేను ఒక భారీ గ్రాఫ్‌ను మూడు చిన్న సబ్‌గ్రాఫ్‌లుగా విభజించాను. దీనివల్ల బగ్స్ వల్ల కలిగే ప్రభావ పరిధి (blast radius) తగ్గింది. • స్పష్టమైన చెక్‌పాయింట్లు: ప్రతి నోడ్ తర్వాత చెక్‌పాయింటింగ్ చేయడం నేను ఆపివేశాను. కేవలం అర్థవంతమైన రీజ్యూమ్ పాయింట్ల వద్ద మాత్రమే చెక్‌పాయింట్ చేస్తాను. దీనివల్ల డేటాబేస్ రైట్స్ (database writes) 60% తగ్గాయి. • ఐడెంపోటెంట్ నోడ్స్ (Idempotent nodes): ఇది చాలా కీలకం. ప్రతి నోడ్ రెండుసార్లు రన్ అయినప్పటికీ ఒకే ఫలితాన్ని ఇవ్వాలి. ఒక నోడ్ స్టేట్‌లో ఏదైనా టాస్క్ ఇప్పటికే పూర్తయిందని గుర్తిస్తే, అది వెంటనే రిటర్న్ అవ్వాలి. ఇది ఖరీదైన మోడల్ కాల్స్ కోసం డబుల్ ఛార్జింగ్‌ను నివారిస్తుంది.

మీ కోసం పాఠాలు:

  • కోడ్ రాయడానికి ముందు రిడ్యూసర్ సెమాంటిక్స్ (reducer semantics) చదవండి.
  • స్టేట్‌లో కస్టమ్ ఆబ్జెక్ట్‌లను నిల్వ చేయవద్దు.
  • కన్కరెన్సీ కంట్రోల్‌ను గ్రాఫ్ వెలుపల ఉంచండి.
  • ప్రతి నోడ్‌ను ఐడెంపోటెంట్‌గా (idempotent) చేయండి.

ఫ్రేమ్‌వర్క్ విఫలం కాలేదు. నా ఊహలే విఫలమయ్యాయి.

Source: https://dev.to/elenarevicheva/three-langgraph-rewrites-what-production-checkpointing-actually-taught-me-ok9

Optional learning community: https://t.me/GyaanSetuAi