ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LlamaIndex Callbacks 事件追踪与调试机制深度解析:从回调管理器到 Token 计数

LlamaIndex Callbacks 事件追踪与调试机制深度解析:从回调管理器到 Token 计数 LlamaIndex Callbacks 事件追踪与调试机制深度解析从回调管理器到 Token 计数【免费下载链接】llama_indexLlamaIndex is the document processing platform for AI项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index导读LlamaIndex 作为文档处理平台其内部执行链文档解析 → 切分 → 嵌入 → 检索 → 合成 → 响应复杂且异步交错。本文聚焦于 LlamaIndex 的Callbacks回调与 CallbackManager回调管理器机制——它是官方提供的一套用于调试、追踪、观测库内部运行过程的统一事件系统。读完本文你将掌握LlamaIndex 内部可追踪的全部事件类型与载荷结构、回调管理器基于contextvars的追踪栈实现原理、内置LlamaDebugHandler与TokenCountingHandler的完整用法以及如何编写自定义回调接入观测平台。一、核心概念为什么需要 CallbacksLlamaIndex 通过 Callbacks 帮助开发者调试、追踪和观测库内部的运行过程。借助CallbackManager你可以在不侵入业务代码的前提下挂载任意数量的回调处理器Callback Handler每个处理器只关心自己感兴趣的事件。除了记录与事件相关的日志数据外回调系统还具备两个进阶能力时长统计追踪每个事件的持续时长duration与发生次数occurrence事件追踪图谱Trace Map记录事件的嵌套父子关系回调可以按自己的方式消费这些数据。例如内置的LlamaDebugHandler默认会在大多数操作结束后打印完整的事件追踪图谱。这一设计让观测与业务逻辑彻底解耦无论是本地打印调试、Token 用量统计还是对接 WB Prompts、Arize Phoenix 等第三方观测平台都只需挂载对应 Handler 即可。二、可追踪的事件类型CBEventType事件类型由枚举CBEventType定义位于 llama-index-core/llama_index/core/callbacks/schema.py。官方文档列出的核心事件如下事件类型触发时机与含义CHUNKING文本切分text splitting前后的日志NODE_PARSING文档Documents及其解析产出的节点Nodes日志EMBEDDING被嵌入embed的文本数量日志LLMLLM 调用的模板与响应日志QUERY每次查询的起始与结束追踪RETRIEVE查询所检索到的节点日志SYNTHESIZEsynthesize 调用结果的日志TREE摘要及其层级level日志SUB_QUESTION生成的子问题sub question及其答案日志需要说明的是并非每个回调都会用到每一种事件类型这些事件只是可供追踪的候选全集由各 Handler 自行决定消费哪些。从源码看当前版本的事件枚举还扩展了文档未列出的类型见 schema.pyTEMPLATING提示词模板构建、FUNCTION_CALLLLM 函数调用、RERANKING重排序、EXCEPTION异常捕获与AGENT_STEPAgent 单步执行。其中LEAF_EVENTS (CBEventType.CHUNKING, CBEventType.LLM, CBEventType.EMBEDDING)schema.py被标记为永远不会再有子事件的叶子事件它们不会进入追踪栈的压栈/出栈流程详见下文追踪原理。三、事件载荷EventPayload事件携带的数据与事件类型配套的是载荷枚举EventPayloadschema.py它定义了每个事件可携带的具体数据字段是编写自定义 Handler 时读取数据的关键索引DOCUMENTS/CHUNKS/NODES解析前的文档列表、文本块列表、节点列表PROMPTformatted_prompt发送给 LLM 的格式化提示词MESSAGES发送给 LLM 的消息列表COMPLETION/RESPONSELLM 的补全结果与消息响应QUERY_STR查询引擎使用的查询字符串SUB_QUESTION子问题及其答案与来源EMBEDDINGS嵌入向量列表TOP_K检索返回的 Top-K 节点数SERIALIZED事件调用方的序列化对象FUNCTION_CALL/FUNCTION_OUTPUTLLM 函数调用及输出TOOLLLM 调用中使用的工具MODEL_NAME事件使用的模型名TEMPLATE/TEMPLATE_VARS/SYSTEM_PROMPT/QUERY_WRAPPER_PROMPTLLM 调用相关模板数据EXCEPTION事件中抛出的异常。事件对象本身由数据类CBEvent承载schema.py包含event_type、payload、格式为%m/%d/%Y, %H:%M:%S.%f的time时间戳以及自动生成的id_统计类结果由EventStatsschema.py承载包含total_secs总耗时、average_secs平均耗时与total_count总次数。四、CallbackManager事件调度的中枢CallbackManagerllama-index-core/llama_index/core/callbacks/base.py是所有回调处理器的调度中枢。它的职责有两层一是把事件的 start/end 广播给所有注册的 Handler二是维护当前事件的追踪栈trace stack与追踪图谱trace map。4.1 三个核心状态trace_stack当前尚未结束的事件栈。事件开始时入栈、结束时出栈。由于它由contextvars.ContextVar承载base.py因此对每个线程/协程是隔离的天然支持并发场景下的独立追踪trace_map事件 ID 到其子事件 ID 列表的映射。事件开始时追踪栈栈底元素被视为当前父事件形成父子嵌套关系trace_id当前追踪的名称通常表示入口点query、index_construction、insert 等。4.2 事件生命周期EventContextHandler 无需直接调用on_event_start/on_event_end更推荐使用CallbackManager.event()上下文管理器base.pywith callback_manager.event(CBEventType.QUERY, payload{key: val}) as event: ... event.on_end(payload{key: val}) # 可选提前结束EventContext会保证on_start只触发一次若事件体内抛出异常它会自动把异常写入EventPayload.EXCEPTION载荷并结束事件随后重新抛出避免回调系统掩盖业务异常。4.3 Trace 的启动与结束as_trace(trace_id)上下文管理器base.py用于包裹一次完整的追踪如一次查询或一次索引构建在其 finally 分支中确保追踪一定被结束并回调各 Handler 的end_trace。若事件启动时发现当前没有活跃追踪管理器会自动启动一个名为llama-index的默认追踪。在业务代码中最常用的接入方式是trace_method装饰器llama-index-core/llama_index/core/callbacks/utils.pytrace_method(my_trace_id) def my_method(self): ...它假定self上存在callback_manager属性可用callback_manager_attr参数覆盖并用as_trace包裹被装饰方法同时自动适配同步与异步async def函数是向自定义类方法快速接入追踪的标准姿势。4.4 全局默认回调CallbackManager.__init__会自动并入llama_index.core.global_handler通过set_global_handler设置且不允许同一类型的 Handler 重复注册base.py若未显式传入任何 Handler则会回退使用全局Settings._callback_manager上的处理器。add_handler/remove_handler/set_handlers提供了运行期动态管理处理器的能力。五、内置回调处理器详解5.1 LlamaDebugHandler基础追踪与调试LlamaDebugHandlerllama-index-core/llama_index/core/callbacks/llama_debug.py是开箱即用的调试处理器。其构造函数支持event_starts_to_ignore/event_ends_to_ignore忽略指定事件类型的 start/endprint_trace_on_end追踪结束时是否自动打印追踪图谱默认Truelogger传入自定义logging.Logger若传入则通过 logger 输出而非print。典型用法完整示例见 docs/examples/observability/LlamaDebugHandler.ipynbfrom llama_index.core.callbacks import ( CallbackManager, LlamaDebugHandler, CBEventType, ) from llama_index.llms.openai import OpenAI from llama_index.core import VectorStoreIndex, SimpleDirectoryReader llm OpenAI(modelgpt-3.5-turbo, temperature0) llama_debug LlamaDebugHandler(print_trace_on_endTrue) callback_manager CallbackManager([llama_debug]) docs SimpleDirectoryReader(./data/paul_graham/).load_data() index VectorStoreIndex.from_documents(docs, callback_managercallback_manager) query_engine index.as_query_engine() response query_engine.query(What did the author do growing up?)执行完查询后处理器提供以下调试 API# 1. 统计某类事件的耗时与次数返回 EventStatstotal_secs / average_secs / total_count print(llama_debug.get_event_time_info(CBEventType.LLM)) # 2. 精确获取每次 LLM 调用的输入/输出按事件 ID 配对 start/end event_pairs llama_debug.get_llm_inputs_outputs() print(event_pairs[0][0]) # LLM start 事件 print(event_pairs[0][1].payload.keys()) print(event_pairs[0][1].payload[response]) # 读取载荷中的响应 # 3. 获取任意事件类型的成对事件如 CHUNKING event_pairs llama_debug.get_event_pairs(CBEventType.CHUNKING) print(event_pairs[0][0].payload.keys()) print(event_pairs[0][1].payload.keys()) # 4. 清空内存中缓存的全部事件 llama_debug.flush_event_logs()get_event_pairs在内部按事件 ID 将 start/end 事件配对并按起始时间排序llama_debug.pyget_event_time_info则基于配对结果计算EventStatsllama_debug.py。追踪结束时print_trace_map会以树状缩进递归打印最近一次追踪的父子事件层级与各事件耗时llama_debug.py。5.2 TokenCountingHandler灵活的 Token 计数TokenCountingHandlerllama-index-core/llama_index/core/callbacks/token_counting.py专用于统计提示词prompt、补全completion与嵌入embedding的 Token 用量。其核心参数tokenizer接受一段文本、返回 Token 列表的函数不传时默认使用全局 tokenizer即llama_index.core.utils中的get_tokenizerverbose为True时将用量打印到控制台token_budget可选的最大总 LLM Token 预算超限时抛出ValueError当前仅作用于 LLM Token 计数event_starts_to_ignore/event_ends_to_ignore/logger同 LlamaDebugHandler。从旧实现迁移Token Counting Migration旧的 Token 计数实现已被弃用它直接挂在llm_predictor与embed_model对象上使用固定的 gpt-2 分词器且last_token_usage/total_token_usage属性并非总能被正确维护。新方案把 Token 计数下沉为回调从而获得三方面的灵活性计数方式可选、计数生命周期可控、可为不同索引创建相互独立的计数器。官方迁移指南详见 docs/src/content/docs/framework/module_guides/observability/callbacks/token_counting_migration.md。最小化使用示例配 OpenAI 模型import tiktoken from llama_index.core import VectorStoreIndex, SimpleDirectoryReader from llama_index.core.callbacks import CallbackManager, TokenCountingHandler from llama_index.core import Settings # tokenizer 可以是任意「输入文本、输出 Token 列表」的函数也可省略以使用全局默认 token_counter TokenCountingHandler( tokenizertiktoken.encoding_for_model(gpt-3.5-turbo).encode, verboseFalse, # 设为 True 可将用量打印到控制台 ) Settings.callback_manager CallbackManager([token_counter]) documents SimpleDirectoryReader(./data).load_data() # verbose 开启时控制台会打印嵌入 Token 用量 index VectorStoreIndex.from_documents(documents) # 否则直接读取计数 print(token_counter.total_embedding_token_count) # 在需要时重置计数 token_counter.reset_counts() # 同时追踪 prompt / completion / 总 LLM Token以及嵌入 Token response index.as_query_engine().query(What did the author do growing up?) print( Embedding Tokens: , token_counter.total_embedding_token_count, \n, LLM Prompt Tokens: , token_counter.prompt_llm_token_count, \n, LLM Completion Tokens: , token_counter.completion_llm_token_count, \n, Total LLM Token Count: , token_counter.total_llm_token_count, )从实现上看计数逻辑存在两条路径token_counting.pyLLM 事件优先从响应原始对象response.raw或usage_metadata读取prompt_tokens/completion_tokens等官方用量字段兼容input_tokens、candidates_token_count等多种命名读取不到时才回退到 tokenizer 估算其中消息场景使用estimate_tokens_in_messagesEmbedding 事件遍历载荷中的CHUNKS对每个文本块调用 tokenizer 计数并累加。该处理器提供四个只读统计属性total_llm_token_count、prompt_llm_token_count、completion_llm_token_count、total_embedding_token_count以及reset_counts()重置方法token_counting.py。完整示例见 docs/examples/observability/TokenCountingHandler.ipynb。5.3 其他官方回调除上述两个核心 Handler 外官方文档还列出了以下回调对应示例 notebook 均位于 docs/examples/observabilityWandbCallbackHandler使用 WB Prompts 前端追踪事件与轨迹示例见 WandbCallbackHandler.ipynbAimCallback追踪 LLM 输入与输出示例见 AimCallback.ipynbOpenInferenceCallbackHandler追踪 AI 模型推理inference过程示例见 OpenInferenceCallback.ipynbOpenAIFineTuningHandler记录全部 LLM 输入输出并提供save_finetuning_events()方法将其保存为适合 OpenAI 微调的格式。此外通过set_global_handler(eval_mode, **eval_params)llama-index-core/llama_index/core/callbacks/global_handlers.py可以一次性设置全局回调支持的eval_mode包括wandb、openinference、arize_phoenix、honeyhive、promptlayer、deepeval、simple、argilla、langfuse、agentops、literalai、opik等global_handlers.py。第三方回调作为独立包维护如llama-index-callbacks-langfuse、llama-index-callbacks-wandb等见 llama-index-integrations/callbacks 目录安装对应包后即可按上述模式接入。六、实现自定义回调所有内置 Handler 都继承自抽象基类BaseCallbackHandlerllama-index-core/llama_index/core/callbacks/base_handler.py。实现自定义回调只需完成四件事调用super().__init__(event_starts_to_ignore, event_ends_to_ignore)声明需要忽略的事件实现on_event_start(event_type, payload, event_id, parent_id, **kwargs)事件开始时被调用返回事件 ID实现on_event_end(event_type, payload, event_id, **kwargs)事件结束时被调用实现start_trace(trace_id)与end_trace(trace_id, trace_map)追踪整体启动/结束时被调用trace_map参数携带完整的事件父子关系图谱。若希望日志输出走标准logging体系而非print可继承PythonicallyPrintingBaseHandlerllama-index-core/llama_index/core/callbacks/pythonically_printing_base_handler.py传入logger后其_print方法会转调logger.debug——这是内置LlamaDebugHandler与TokenCountingHandler共同的基类。之后把实例传入CallbackManager([your_handler])再赋值给Settings.callback_manager或具体 Index / QueryEngine 的callback_manager参数即可全程捕获事件。七、总结LlamaIndex 的 Callbacks 体系以CBEventType定义事件全集、以EventPayload定义载荷结构、以CallbackManager负责调度与追踪栈维护最终通过可插拔的 Handler 实现一次埋点、多种消费。调试用LlamaDebugHandler成本控制用TokenCountingHandler生产观测对接第三方平台自定义需求则继承BaseCallbackHandler自行扩展。这套机制把观测能力从核心库中彻底解耦是理解 LlamaIndex 全链路行为、定位性能瓶颈与控制 Token 成本的首选入口。【免费下载链接】llama_indexLlamaIndex is the document processing platform for AI项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表