-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
PRD:按角色分离 LLM 模型
一、背景与目标
1.1 背景
LightRAG 在文档处理与检索问答流程中,存在多类 LLM 调用,但当前统一使用同一个 llm_model_func。这会导致:
- 抽取、关键词、最终回答使用同一模型,成本和时延无法按任务特性优化。
- 角色间并发队列与超时策略共用,无法针对热点链路单独扩容或限流。
- 无法在运行时按角色热切换模型(前端管理配置场景受限)。
1.2 目标
- 保持向后兼容:不新增任何配置时,行为与当前版本一致。
- 角色化模型路由:支持
extract / keyword / query三角色独立 LLM。 - 可继承且可覆盖:同 Provider 时按字段继承,按需最小覆盖。
- 强隔离:每个角色始终创建独立 LLM 函数和独立并发队列,不复用 base 函数。
- 运行时可变:支持运行中更新角色的
provider/model/host/api_key/options/timeout/max_async。
二、术语与角色定义
- base LLM:
llm_model_func对应的默认模型配置。 - extract 角色:实体关系抽取 + 描述摘要。
- keyword 角色:查询关键词提取。
- query 角色:最终回答生成(包含 KG/naive/bypass 以及 emulation 直调问答)。
三、设计原则(新增约束)
3.1 独立函数与连接创建规则
三个角色函数(extract/keyword/query)一律独立创建,且一律使用各自独立并发队列,不允许角色函数复用 base 包装函数。
说明:
- base 的作用是提供默认参数来源(继承源),不是角色函数复用目标。
- 即使角色最终参数与 base 完全一致,也仍要构造独立角色函数与独立队列。
- 角色
host/api_key/model/provider options/max_async/timeout变化都只影响该角色函数。
3.2 命名统一规则
并发环境变量统一为:
MAX_ASYNC(base)MAX_ASYNC_EXTRACT_LLMMAX_ASYNC_KEYWORD_LLMMAX_ASYNC_QUERY_LLM
超时环境变量统一为:
LLM_TIMEOUT(base)LLM_TIMEOUT_EXTRACT_LLMLLM_TIMEOUT_KEYWORD_LLMLLM_TIMEOUT_QUERY_LLM
3.3 跨 Provider 继承规则
当 role_binding != base_binding 时:
- 不得继承 base
host/api_key/provider_options。 host必须显式提供(校验失败即启动失败)。api_key和model必须显式提供(校验失败即启动失败)。- provider options 从新 provider 类型默认值起步,再叠加角色覆盖项。
四、方案总览
4.1 LightRAG 新增字段
# per-role llm function
extract_llm_model_func: Callable[..., object] | None = field(default=None)
keyword_llm_model_func: Callable[..., object] | None = field(default=None)
query_llm_model_func: Callable[..., object] | None = field(default=None)
# per-role queue limit
extract_llm_model_max_async: int | None = field(default=None)
keyword_llm_model_max_async: int | None = field(default=None)
query_llm_model_max_async: int | None = field(default=None)
# per-role timeout
extract_llm_timeout: int | None = field(default=None)
keyword_llm_timeout: int | None = field(default=None)
query_llm_timeout: int | None = field(default=None)4.2 __post_init__ 行为
- 先保存 base 原始函数
_raw_llm_func。 - 解析每个角色的有效
max_async/timeout(None -> fallback base)。 - 包装 base
self.llm_model_func。 - 对每个角色都执行独立构造:基于角色最终生效参数创建独立函数并单独包装队列。
关键点:
- 角色函数不能指向
self.llm_model_func,必须基于角色参数独立构造,避免双队列嵌套和队列串扰。 asdict(self)每次查询/插入都会重建快照,因此实例属性更新可在下一次调用生效。
4.3 调用路由变更
operate.py:
extract_entities()->extract_llm_model_func_summarize_descriptions()->extract_llm_model_funcextract_keywords_only()->keyword_llm_model_funckg_query()->query_llm_model_funcnaive_query()->query_llm_model_funcaquery_llm()bypass ->query_llm_model_func
api/routers/ollama_api.py:
/api/generate与/api/chat中所有直接 LLM 调用改为使用 query 角色 LLM。
五、API 配置与构造改造
5.1 config.py 新增角色参数
每角色新增参数:
*_LLM_BINDING*_LLM_MODEL*_LLM_BINDING_HOST*_LLM_BINDING_API_KEYMAX_ASYNC_*_LLMLLM_TIMEOUT_*_LLM
其中 * 为 EXTRACT/KEYWORD/QUERY。
5.2 binding_options.py 扩展
新增:
@classmethod
def options_dict_for_role(cls, args: Namespace, role_prefix: str) -> dict[str, Any]:
...用途:
- 同 Provider:从 base options 继承,再叠加角色项。
- 跨 Provider:从该 Provider 默认 options 起步,再叠加角色项。
角色 provider 参数命名:
{ROLE}_{PROVIDER_PREFIX}_{FIELD}- 例如:
EXTRACT_OPENAI_LLM_TEMPERATURE
5.3 lightrag_server.py 构造流程
A. 新增 create_llm_func_with_params(...)
输入完整的 binding/model/host/api_key/provider_options/timeout,返回预配置 LLM callable。
B. 新增 create_role_llm_config(role, args, config_cache)
负责解析并校验角色最终配置:
- 应用继承规则;
- 判断是否跨 Provider;
- 执行必填校验(跨 Provider 强制 model/api_key/host);
- 返回结构化配置对象(不做与 base 的复用判定)。
C. 跨 Provider Host 必填校验
取消跨 Provider 的 host 自动默认逻辑。若角色切换了 provider 且未设置 *_LLM_BINDING_HOST,应该使用新Provider默认的端点URL。
LightRAG对象初始化完成后,应该把各个角色的LLM函数配置输出到控制台日志;/health端点应该各个角色的LLM函数配资。
六、运行时动态更新接口(增强版)
将 update_llm_role_func() 升级为配置级接口,支持完整热更新:
def update_llm_role_config(
self,
role: Literal["extract", "keyword", "query"],
*,
binding: str | None = None,
model: str | None = None,
host: str | None = None,
api_key: str | None = None,
provider_options: dict[str, Any] | None = None,
max_async: int | None = None,
timeout: int | None = None,
model_func: Callable[..., object] | None = None,
) -> None:
"""
Update role config at runtime.
- If model_func is provided, treat as fully configured callable.
- Otherwise rebuild callable from binding/model/host/api_key/options.
- max_async/timeout changes always trigger rewrap.
"""行为要求:
- 原子替换角色函数与角色配置字段。
- 更新后下一次
aquery()/ainsert()生效。 - 失败时不污染当前可用配置(回滚/不提交)。
七、环境变量示例(统一命名)
7.1 仅改模型名(同 Provider)
LLM_BINDING=gemini
LLM_MODEL=gemini-2.5-flash
LLM_BINDING_API_KEY=xxx
KEYWORD_LLM_MODEL=gemini-2.0-flash-lite
QUERY_LLM_MODEL=gemini-2.5-pro7.2 独立并发与超时
MAX_ASYNC=4
MAX_ASYNC_EXTRACT_LLM=8
MAX_ASYNC_QUERY_LLM=12
LLM_TIMEOUT=180
LLM_TIMEOUT_EXTRACT_LLM=240
LLM_TIMEOUT_QUERY_LLM=3007.3 跨 Provider(必须显式 model/api_key/host)
# base
LLM_BINDING=ollama
LLM_MODEL=qwen2.5:7b
LLM_BINDING_HOST=http://localhost:11434
# extract -> openai
EXTRACT_LLM_BINDING=openai
EXTRACT_LLM_MODEL=gpt-4o
EXTRACT_LLM_BINDING_API_KEY=sk-xxx
EXTRACT_LLM_BINDING_HOST=https://api.openai.com/v1
EXTRACT_OPENAI_LLM_TEMPERATURE=0.17.4 角色函数修改配置示例(同 Provider,独立函数独立队列)
# base (openai)
LLM_BINDING=openai
LLM_MODEL=gpt-4o-mini
LLM_BINDING_HOST=https://api.openai.com/v1
LLM_BINDING_API_KEY=sk-base
MAX_ASYNC=4
LLM_TIMEOUT=180
# extract 角色:改模型 + 改 key + 改并发 + 改超时 + 改 provider 参数
EXTRACT_LLM_MODEL=gpt-4o
EXTRACT_LLM_BINDING_API_KEY=sk-extract
MAX_ASYNC_EXTRACT_LLM=10
LLM_TIMEOUT_EXTRACT_LLM=300
EXTRACT_OPENAI_LLM_TEMPERATURE=0.1
EXTRACT_OPENAI_LLM_MAX_COMPLETION_TOKENS=6000
# keyword 角色:轻量模型与小并发
KEYWORD_LLM_MODEL=gpt-4o-mini
MAX_ASYNC_KEYWORD_LLM=3
LLM_TIMEOUT_KEYWORD_LLM=60
KEYWORD_OPENAI_LLM_TEMPERATURE=0.0
# query 角色:强模型与大并发
QUERY_LLM_MODEL=o3
QUERY_LLM_BINDING_API_KEY=sk-query
MAX_ASYNC_QUERY_LLM=16
LLM_TIMEOUT_QUERY_LLM=360
QUERY_OPENAI_LLM_REASONING_EFFORT=high八、实施清单
lightrag/lightrag.pylightrag/operate.pylightrag/api/config.pylightrag/api/lightrag_server.pylightrag/llm/binding_options.pylightrag/api/routers/ollama_api.pyenv.example- 测试与文档同步
九、测试与验收标准
9.1 回归与兼容
- 不设置任何新变量,行为与旧版一致。
- 三角色函数均独立创建,且各自拥有独立并发队列。
9.2 路由正确性
- 只设
KEYWORD_LLM_MODEL,仅关键词提取链路模型变化。 - bypass 和 emulation 直调均走 query 角色函数。
9.3 隔离性
- 即便角色参数与 base 一致,角色函数对象也应与 base 不同。
- 三角色队列互不干扰(压测下无串队)。
9.4 跨 Provider 校验
- 跨 Provider 且缺失
model-> 启动失败并给出明确错误。 - 跨 Provider 且缺失
api_key(对于需 key 的 provider)-> 启动失败。 - 跨 Provider 且缺失
host-> 启动失败并给出明确错误。
9.5 动态更新
update_llm_role_config修改max_async/timeout/provider后下一次调用生效。- 非法更新不影响已有可用配置。
十、风险与缓解
-
配置组合增多导致复杂度上升
处理:引入统一配置解析与校验模块,避免散落判断。 -
环境变量命名不一致导致迁移混乱
处理:统一采用新命名并在发布说明中明确“无旧命名兼容”。 -
跨 Provider 配置漏填导致启动失败
处理:在错误信息中明确缺失字段与角色名(如EXTRACT_LLM_BINDING_HOST)。
十一、非目标
- 本期不调整 Embedding 的角色化路由。
- 本期不引入更多角色(如 rerank 专用 LLM)。
十二、后续工作
在把Ray-Anything整合到LightRAG过程中需要引入VLM角色。