Setting Configurations
Overview
The Settings module lets you manage application-wide configurations. Most examples use settings to configure the active LM.
Using the Settings module
import lotus
from lotus.models import LM
lm = LM(model="gpt-4o-mini")
lotus.settings.configure(lm=lm)
Configurable Parameters
enable_cacheEnables or disables caching mechanisms. Default:
False. Cache parameters includecache_type,max_size, andcache_dir. It is recommended to enable caching.
import pandas as pd
import lotus
from lotus.models import LM
from lotus.cache import CacheFactory, CacheConfig, CacheType
cache_config = CacheConfig(cache_type=CacheType.SQLITE, max_size=1000)
cache = CacheFactory.create_cache(cache_config)
lm = LM(model='gpt-4o-mini', cache=cache)
lotus.settings.configure(lm=lm, enable_cache=True)
rmConfigures the retrieval model. Default:
None.
rm = SentenceTransformersRM(model="intfloat/e5-base-v2")
lotus.settings.configure(rm=rm)
helper_lmConfigures a secondary helper LM, often used with cascades. Default:
None.
gpt_4o_mini = LM("gpt-4o-mini")
gpt_4o = LM("gpt-4o")
lotus.settings.configure(lm=gpt_4o, helper_lm=gpt_4o_mini)
Scoped Settings with context()
lotus.settings.context(**kwargs) is a context manager that temporarily overrides
settings for the duration of a with block. The previous values are always restored
on exit — even if an exception is raised.
This is useful for:
Switching to a cheaper model for one step in a pipeline without affecting the rest
Running an evaluation judge with a fresh model and
enable_cache=FalseIsolating settings in tests so one test cannot pollute another
Running concurrent threads or asyncio tasks with independent settings
Basic usage
import lotus
from lotus.models import LM
lm = LM(model="gpt-4o")
cheap_lm = LM(model="gpt-4o-mini")
lotus.settings.configure(lm=lm)
# Use the cheap model only for this step; gpt-4o is restored afterward
with lotus.settings.context(lm=cheap_lm, enable_cache=False):
df = df.sem_filter("Is {Review} positive?")
# Back to gpt-4o here
df = df.sem_map("Summarise {Review} in one sentence.")
Nested contexts
Contexts can be nested. Each level saves and restores independently.
with lotus.settings.context(lm=cheap_lm):
# inner context adds another override on top
with lotus.settings.context(enable_cache=True):
df = df.sem_map(...) # cheap_lm + enable_cache=True
df = df.sem_filter(...) # cheap_lm only, enable_cache restored
Concurrent threads
Because context() uses contextvars.ContextVar internally, each thread sees
only its own overrides. Threads cannot overwrite each other’s settings even though
they share the same lotus.settings object.
import threading
import lotus
from lotus.models import LM
lotus.settings.configure(lm=LM(model="gpt-4o-mini"))
def analyse(df, model, results, key):
with lotus.settings.context(lm=model):
results[key] = df.sem_map("Summarise {Text}.")
results = {}
t1 = threading.Thread(target=analyse, args=(df1, LM("gpt-4o-mini"), results, "fast"))
t2 = threading.Thread(target=analyse, args=(df2, LM("gpt-4o"), results, "quality"))
t1.start(); t2.start()
t1.join(); t2.join()
Concurrent asyncio tasks
asyncio tasks created with asyncio.create_task() or asyncio.gather() each
receive a copy of the caller’s context, so ContextVar mutations inside one task
are invisible to others.
import asyncio
import lotus
from lotus.models import LM
lotus.settings.configure(lm=LM(model="gpt-4o-mini"))
async def run(df, model):
with lotus.settings.context(lm=model):
await asyncio.sleep(0) # yield; other tasks see their own model
return df.sem_map("Classify {Text}.")
async def main():
results = await asyncio.gather(
run(df1, LM("gpt-4o-mini")),
run(df2, LM("gpt-4o")),
)
asyncio.run(main())
Note
configure() mutates the global settings object and is not thread-safe.
Use context() whenever settings need to differ across concurrent execution paths.