fix(llm): configurable per-call litellm params instead of mutating the global

llm_completion / llm_acompletion (pageindex/utils.py and
pageindex/index/utils.py) set `litellm.drop_params = True` on the litellm
module. litellm is a process-wide singleton, so this leaked into every other
library sharing it (e.g. a host app like OpenKB that exposes its own litellm
config) and could not be turned off.

Replace the hardcoded `temperature=0` + global `drop_params` with a single
PageIndex-owned per-call kwargs mechanism (config._LLM_PARAMS):

- defaults preserve behavior: {"temperature": 0, "drop_params": True};
- passed per call via **get_llm_params(), never writing litellm's globals, so
  nothing leaks into other litellm users in the same process;
- externally configurable: pageindex.set_llm_params(drop_params=False,
  temperature=1, num_retries=5, ...) or the PAGEINDEX_DROP_PARAMS env shortcut;
- model/messages are reserved (PageIndex supplies them) and rejected.
This commit is contained in:
mountain 2026-06-25 16:47:27 +08:00
parent f354eb17bf
commit 2cab6b5be9
4 changed files with 56 additions and 8 deletions

View file

@ -7,6 +7,8 @@ import re
import asyncio
import PyPDF2
from ..config import get_llm_params
logger = logging.getLogger(__name__)
@ -23,11 +25,12 @@ def llm_completion(model, prompt, chat_history=None, return_finish_reason=False)
messages = list(chat_history) + [{"role": "user", "content": prompt}] if chat_history else [{"role": "user", "content": prompt}]
for i in range(max_retries):
try:
litellm.drop_params = True
response = litellm.completion(
model=model,
messages=messages,
temperature=0,
# Per-call litellm kwargs (default temperature=0, drop_params=True);
# configure via config.set_llm_params(...) — never the litellm global.
**get_llm_params(),
)
content = response.choices[0].message.content
if return_finish_reason:
@ -52,11 +55,10 @@ async def llm_acompletion(model, prompt):
messages = [{"role": "user", "content": prompt}]
for i in range(max_retries):
try:
litellm.drop_params = True
response = await litellm.acompletion(
model=model,
messages=messages,
temperature=0,
**get_llm_params(), # per-call kwargs; never the litellm global
)
return response.choices[0].message.content
except Exception as e: