本节摘要:LlamaIndex 的生态由 core(核心抽象)加数百个按
llama-index-类别-产品命名的集成包构成,社区通过统一的接口契约向 core 贡献扩展。本节画出六个官方扩展点(自定义 Reader、NodeParser、VectorStore、Retriever、LLM、Tool),演示两个最常用的自定义实现骨架,并说明贡献与版本跟进的实操注意事项。
core 定义接口,集成包填实现。你自己的业务代码站在同样的位置——自定义扩展与官方集成包遵循完全相同的契约,这是"框架可以被你延长"的制度保证。六个最常动的扩展点:BaseReader(读数据,2.4 节写过)、BaseNodeParser(切分)、BaseVectorStore(存取向量)、BaseRetriever(自定义召回逻辑)、BaseLLM(接私有模型服务)、BaseTool(给智能体的能力单元,5.1 节)。
# 扩展点一:自定义检索器 —— 比如给召回结果加业务重试逻辑 from llama_index.core.retrievers import BaseRetriever from llama_index.core.schema import NodeWithScore class BoostedRetriever(BaseRetriever): """先走基础召回,再按业务规则加权:近期文档优先""" def __init__(self, base: BaseRetriever, recency_field="updated_at"): self._base, self._field = base, recency_field super().__init__() def _retrieve(self, query_bundle): nodes = self._base.retrieve(query_bundle) boosted = [] for n in nodes: if n.node.metadata.get(self._field, "") >= "2025-01": n.score = (n.score or 0.5) + 0.1 # 新版本制度加权 boosted.append(n) boosted.sort(key=lambda x: x.score or 0, reverse=True) return boosted engine = index.as_query_engine( retriever=BoostedRetriever(index.as_retriever(similarity_top_k=8)))
# 扩展点二:自定义 LLM —— 把公司私有模型服务接进来 from llama_index.core.llms import CustomLLM, CompletionResponse, LLMMetadata class InternalLLM(CustomLLM): """对接内部自研模型服务的最小实现""" @property def metadata(self) -> LLMMetadata: return LLMMetadata(context_window=32768, num_output=2048) def complete(self, prompt: str, **kwargs) -> CompletionResponse: raw = internal_model_gateway.generate(prompt=prompt, **kwargs) return CompletionResponse(text=raw["text"]) def stream_complete(self, prompt: str, **kwargs): for chunk in internal_model_gateway.stream(prompt=prompt): yield CompletionResponse(text=chunk, delta=chunk) Settings.llm = InternalLLM() # 之后全链路(含智能体)都走内部模型
这两个骨架展示同一件事:继承基类、实现少数方法,你的实现就获得了与官方集成包同等的公民权——能被 Settings 装配、能进查询引擎、能被智能体调用。
版本节奏快是现实:核心与集成包独立发版,升级前看变更说明里的废弃项。经验法则是"锁版本上线,按季度评估升级",不要追最新版。集成包质量分层:官方维护的核心包(主流模型与向量库)响应快;社区包质量参差,采纳前看三样——最近提交时间、issue 响应情况、测试覆盖。这个判断与 2.1 节"连接器三路线"一脉相承。贡献路径:发现社区包的 bug,修复后按仓库贡献指南提合并请求,是最快的"让生态为你工作"的方式;新数据源的连接器也是新手友好的贡献切入点——实现一个 load_data 加测试即可。
把自定义扩展写成符合契约的形式(而不是散落在业务代码里的函数),短期看是多写几行样板,长期看是复利:换向量库不动业务代码(VectorStore 契约)、换模型不动检索逻辑(LLM 契约)、升级框架时自定义件沿用接口稳定层。本册反复拆装的"插槽"心智模型,最终就落实为这组契约。
自定义扩展升级框架时会碎吗? 落在公开契约(BaseRetriever 这类稳定接口)上的实现基本无恙;碎的往往是依赖内部私有行为的代码(比如直接摸某个类的私有属性)。原则:只用文档化的接口与属性,升级前跑评估集回归,碎不碎十分钟内就知道。
想贡献社区,从哪开始? 阶梯:先用(真实使用暴露问题)→ 提带复现步骤的 issue → 修文档错漏(最友好的切入点)→ 修小 bug → 最后才是新集成包。跳过前两步直接写代码,大概率因为不符合仓库规范被退回。社区贡献的隐形回报:你的痛点被官方维护后,长期维护成本归零。
集成包太多选择困难怎么办? 每个类别认准官方维护的一两个即可:向量库选你团队已运维的,模型选你已采购的,连接器选你数据源对应的。技术选型的最大浪费是"为了用最新组件而引入新组件"——每个新依赖都是一份长期账单。