openoperator / plugins /_model_config /api /model_config_set.py
Leon4gr45's picture
Upload folder using huggingface_hub (part 5)
57d4e72 verified
Raw History Blame Contribute Delete
3.38 kB
from copy import deepcopy
from helpers.api import ApiHandler, Request, Response
from helpers import defer, dotenv
from helpers.extension import call_extensions_async
from plugins._model_config.helpers import model_config
API_KEY_PLACEHOLDER = "************"
class ModelConfigSet(ApiHandler):
async def process(self, input: dict, request: Request) -> dict | Response:
project_name = input.get("project_name", "")
agent_profile = input.get("agent_profile", "")
config = input.get("config")
if not config or not isinstance(config, dict):
return Response(status=400, response="Missing or invalid config")
config_to_save = deepcopy(config)
for section_name in ("chat_model", "utility_model", "embedding_model"):
section = config_to_save.get(section_name, {})
if not isinstance(section, dict):
continue
provider = str(section.get("provider", "")).strip()
api_key = section.get("api_key", "")
if (
provider
and isinstance(api_key, str)
and api_key.strip()
and api_key != API_KEY_PLACEHOLDER
):
dotenv.save_dotenv_value(f"API_KEY_{provider.upper()}", api_key)
section.pop("api_key", None)
preset_name = str(
input.get("preset_name")
or config_to_save.get(model_config.MODEL_PRESET_CONFIG_KEY)
or model_config.get_configured_preset_name(
project_name=project_name or None,
agent_profile=agent_profile or None,
)
).strip()
preset = model_config.resolve_preset(preset_name)
if not preset:
return Response(status=404, response=f"Preset '{preset_name}' not found")
preset_name = str(preset.get("name") or model_config.DEFAULT_PRESET_NAME)
# Read the preset before saving so embedding changes can still trigger
# the established re-index notification.
prev_config = model_config.resolve_config_settings(
{model_config.MODEL_PRESET_CONFIG_KEY: preset_name}
)
try:
model_config.update_preset_from_config(preset_name, config_to_save)
except ValueError as exc:
return Response(status=400, response=str(exc))
# Keep the requested scope pointed at the preset being edited. This is
# selection-only persistence; model dictionaries live in presets.yaml.
from helpers import plugins
plugins.save_plugin_config(
"_model_config",
project_name=project_name or None,
agent_profile=agent_profile or None,
settings={model_config.MODEL_PRESET_CONFIG_KEY: preset_name},
)
# Check if embedding model changed and notify
prev_embed = prev_config.get("embedding_model", {})
new_embed = config_to_save.get("embedding_model", {})
if (
prev_embed.get("provider") != new_embed.get("provider")
or prev_embed.get("name") != new_embed.get("name")
or prev_embed.get("kwargs") != new_embed.get("kwargs")
):
defer.DeferredTask().start_task(
call_extensions_async, "embedding_model_changed"
)
return {"ok": True, "preset_name": preset_name}