पाठ 19 / 29
LLM Calls का Tracing और Logging
अनुरोध का हर चरण दर्ज करें ताकि धीमे या ग़लत उत्तरों का निदान हो सके।
जो दिखे नहीं उसे debug नहीं कर सकते
LLM अनुरोध एक pipeline है, इसलिए trace spans का वृक्ष है: अनुरोध सँभालना, retrieve, rerank, मॉडल call, validate, हर एक की शुरुआती समय, अवधि और attributes (मॉडल, token गिनती, chunks की संख्या, validation परिणाम, release ID) सहित। Traces से आप उत्तर दे सकते हैं "यह धीमा क्यों था?" (1.6 में से 1.2 सेकंड मॉडल call ने लिए), "यह ग़लत क्यों था?" (retrieval ने ग़लत chunk लौटाया), और "इसकी क्या लागत थी?"। समस्या दोहराने के लिए पर्याप्त log करें: release ID, अंतिम prompt (या उसका संदर्भ), retrieved दस्तावेज़ IDs, tool calls व परिणाम, कच्चा आउटपुट और parsed आउटपुट, साथ में user प्रतिक्रिया। इसे privacy से संतुलित करें: व्यक्तिगत डेटा redact करें, पहुँच सीमित करें, और retention सीमाएँ रखें। मानक tools (OpenTelemetry-संगत tracing और LLM-विशिष्ट observability प्लेटफ़ॉर्म) spans, dashboards और खोज देते हैं; अवधारणा उदाहरण जैसी ही है।
देखें, बाँधें, उबरें
Traces दिखाते हैं क्या हुआ, drift पहचान दिखाती है क्या बदला, और परतदार विफलता-सँभाल users को सेवा देती रहती है।
वृक्ष के रूप में अनुरोध trace, चलाकर
मैंने यह सादे Python 3 (सिर्फ़ standard library) से चलाया। Trace 1.62 s का अनुरोध दिखाता है जिसके child चरण retrieve (0.18 s), rerank (0.11 s), मॉडल call (1.20 s, token गिनती सहित) और आउटपुट validation (0.01 s) हैं। सबसे धीमा child चरण मॉडल call है। समय संरचना दिखाने को गढ़े हैं।
class Tracer:
def __init__(self): self.t = 0.0; self.events = []; self.depth = 0
def span(self, name, duration, attrs=None):
start = self.t
self.events.append((self.depth, name, start, duration, attrs or {}))
return self
def advance(self, d): self.t += d
tr = Tracer()
tr.span("handle_request", 1.62); tr.depth = 1
tr.span("retrieve", 0.18, {"chunks": 5}); tr.advance(0.18)
tr.span("rerank", 0.11, {"kept": 3}); tr.advance(0.11)
tr.span("llm_call", 1.20, {"in_tokens": 1450, "out_tokens": 210, "model": "model-a"}); tr.advance(1.20)
tr.span("validate_output", 0.01, {"valid": True}); tr.advance(0.01)
for depth, name, start, dur, attrs in tr.events:
print(" " * depth + f"{name:16} start {start:5.2f}s took {dur:4.2f}s {attrs if attrs else ''}")
slowest = max((e for e in tr.events if e[0] == 1), key=lambda e: e[3])
print("slowest step:", slowest[1])
Output:
handle_request start 0.00s took 1.62s
retrieve start 0.00s took 0.18s {'chunks': 5}
rerank start 0.18s took 0.11s {'kept': 3}
llm_call start 0.29s took 1.20s {'in_tokens': 1450, 'out_tokens': 210, 'model': 'model-a'}
validate_output start 1.49s took 0.01s {'valid': True}
slowest step: llm_callRelease ID log करें
हर trace बताए कि कौन-से prompt और मॉडल बंडल ने उसे बनाया।
त्वरित जाँच: Trace आपको क्या करने देता है जो समग्र metric नहीं?
- विफलताएँ छिपाना
- मॉडल को होशियार बनाना
- Tests की ज़रूरत हटाना
- एक विशिष्ट अनुरोध के भीतर देखना कि समय और त्रुटियाँ कहाँ हुईं
Answer
एक विशिष्ट अनुरोध के भीतर देखना कि समय और त्रुटियाँ कहाँ हुईं — समग्र बताते हैं कि कुछ धीमा है; traces बताते हैं कहाँ।