Files
AI/참고/guardrails-main/guardrails/hub/install.py
2026-05-12 19:40:31 +09:00

222 lines
7.3 KiB
Python

from contextlib import contextmanager
import contextlib
from string import Template
from typing import Callable, cast, List
import importlib.metadata
from guardrails.hub.validator_package_service import (
ValidatorPackageService,
ValidatorModuleType,
)
from guardrails.classes.rc import RC
from guardrails.cli.hub.console import console
from guardrails.cli.logger import LEVELS, logger as cli_logger
class LocalModelFlagNotSet(Exception):
pass
@contextmanager
def do_nothing_context(*args, **kwargs):
try:
yield
finally:
pass
def default_local_models_confirm():
raise LocalModelFlagNotSet(
"The 'install_local_models' keyword argument"
" must be explicitly set to True or False to continue."
)
def install(
package_uri: str,
install_local_models=None,
quiet: bool = True,
upgrade: bool = False,
install_local_models_confirm: Callable = default_local_models_confirm,
) -> ValidatorModuleType:
"""Install a validator package from a hub URI.
Args:
package_uri (str): The URI of the package to install.
install_local_models (bool): Whether to install local models or not.
quiet (bool): Whether to suppress output or not.
install_local_models_confirm (Callable): A function to confirm the
installation of local models.
Returns:
ModuleType: The installed validator module.
Examples:
>>> RegexMatch = install("hub://guardrails/regex_match").RegexMatch
>>> RegexMatch = install("hub://guardrails/regex_match~=1.4").RegexMatch
>>> install("hub://guardrails/regex_match>=1.4,==1.*.")
>>> from guardrails.hub.regex_match import RegexMatch
"""
verbose_printer = console.print
quiet_printer = console.print if not quiet else lambda x: None
# 1. Validation
rc_file_exists = RC.exists()
validator_id, validator_version = ValidatorPackageService.get_validator_id(
package_uri
)
installing_msg = f"Installing {package_uri}..."
cli_logger.log(
level=LEVELS.get("SPAM"), # type: ignore
msg=installing_msg,
)
verbose_printer(installing_msg)
# Define Loader for UX purposes
loader = console.status if not quiet else do_nothing_context
# 2. Prep Installation
fetch_manifest_msg = "Fetching manifest"
with loader(fetch_manifest_msg, spinner="bouncingBar"):
(module_manifest, site_packages) = (
ValidatorPackageService.get_manifest_and_site_packages(validator_id)
)
# 3. Install - Pip Installation of git module
dl_deps_msg = "Downloading dependencies"
with loader(dl_deps_msg, spinner="bouncingBar"):
ValidatorPackageService.install_hub_module(
validator_id,
validator_version=validator_version,
quiet=quiet,
upgrade=upgrade,
logger=cli_logger,
)
use_remote_endpoint = False
module_has_endpoint = (
module_manifest.tags and module_manifest.tags.has_guardrails_endpoint
)
try:
if rc_file_exists:
# if we do want to remote then we don't want to install local models
use_remote_endpoint = (
RC.load(cli_logger).use_remote_inferencing and module_has_endpoint
)
elif install_local_models is None and module_has_endpoint:
install_local_models = install_local_models_confirm()
except AttributeError:
pass
# 4. Post Installation
install_local_models = (
install_local_models if install_local_models is not None else True
)
if not use_remote_endpoint and install_local_models is True:
cli_logger.log(
level=LEVELS.get("SPAM"), # type: ignore
msg="Installing models locally!",
)
post_msg = "Running post-install setup"
with loader(post_msg, spinner="bouncingBar"):
ValidatorPackageService.run_post_install(
module_manifest, site_packages, logger=cli_logger
)
else:
cli_logger.log(
level=LEVELS.get("SPAM"), # type: ignore
msg="Skipping post install, models will not be "
"downloaded for local inference.",
)
ValidatorPackageService.register_validator(module_manifest)
# 5. Get Validator Class for the installed module
installed_module = ValidatorPackageService.get_validator_from_manifest(
module_manifest
)
installed_module = cast(ValidatorModuleType, installed_module)
# Print success messages
cli_logger.info("Installation complete")
installed_version_message = ""
with contextlib.suppress(Exception):
package_name = ValidatorPackageService.get_normalized_package_name(validator_id)
installed_version = importlib.metadata.version(package_name)
if installed_version:
installed_version_message = f" version {installed_version}"
verbose_printer(
f"✅Successfully installed {validator_id}{installed_version_message}!\n\n"
)
success_message_cli = Template(
"[bold]Import validator:[/bold]\n"
"from guardrails.hub import ${export}\n\n"
"[bold]Get more info:[/bold]\n"
"https://guardrailsai.com/hub/validator/${id}\n"
).safe_substitute(
module_name=package_uri,
id=module_manifest.id,
export=module_manifest.exports[0],
)
success_message_logger = Template(
"✅Successfully installed ${module_name}!\n\n"
"Import validator:\n"
"from guardrails.hub import ${export}\n\n"
"Get more info:\n"
"https://guardrailsai.com/hub/validator/${id}\n"
).safe_substitute(
module_name=package_uri,
id=module_manifest.id,
export=module_manifest.exports[0],
)
quiet_printer(success_message_cli) # type: ignore
cli_logger.log(level=LEVELS.get("SPAM"), msg=success_message_logger) # type: ignore
# Not a fan of this but allows the installation to be used in create command as is
installed_module.__validator_exports__ = module_manifest.exports
return installed_module
def install_multiple(
package_uris: List[str],
install_local_models=None,
quiet: bool = True,
upgrade: bool = False, # Add the upgrade parameter here
install_local_models_confirm: Callable = default_local_models_confirm,
) -> List[ValidatorModuleType]:
"""Install multiple validator packages from hub URIs.
Args:
package_uris (List[str]): List of URIs of the packages to install.
install_local_models (bool): Whether to install local models or not.
quiet (bool): Whether to suppress output or not.
upgrade (bool): Whether to upgrade to the latest package version.
install_local_models_confirm (Callable): A function to confirm the
installation of local models.
Returns:
List[ValidatorModuleType]: List of installed validator modules.
"""
installed_modules = []
for package_uri in package_uris:
installed_module = install(
package_uri,
install_local_models=install_local_models,
quiet=quiet,
upgrade=upgrade, # Pass upgrade here
install_local_models_confirm=install_local_models_confirm,
)
installed_modules.append(installed_module)
return installed_modules