-
Notifications
You must be signed in to change notification settings - Fork 1
【DO NOT MERGE!!!】init commit on deployment related configs(coding structure) #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ef09387
9c53c84
bdf035f
5d7cc16
63784b7
0428291
defb8d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,24 @@ | ||
| from .config_loader import Config, load_config | ||
| from .runtime_policy import ( | ||
| PreflightIssue, | ||
| RuntimePolicy, | ||
| VALID_NETWORK_MODES, | ||
| VALID_RESOURCE_TIERS, | ||
| apply_runtime_environment, | ||
| build_runtime_policy, | ||
| handle_preflight_issues, | ||
| run_global_preflight, | ||
| ) | ||
|
|
||
| __all__ = ["Config", "load_config"] | ||
| __all__ = [ | ||
| "Config", | ||
| "PreflightIssue", | ||
| "RuntimePolicy", | ||
| "VALID_NETWORK_MODES", | ||
| "VALID_RESOURCE_TIERS", | ||
| "apply_runtime_environment", | ||
| "build_runtime_policy", | ||
| "handle_preflight_issues", | ||
| "load_config", | ||
| "run_global_preflight", | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import ipaddress | ||
| import os | ||
| from dataclasses import dataclass | ||
| from typing import Any | ||
| from urllib.parse import urlparse | ||
|
|
||
|
|
||
| VALID_NETWORK_MODES = {"online", "offline"} | ||
| VALID_RESOURCE_TIERS = {"light", "standard", "full"} | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 定义合法值枚举类,校验的时候会用到。 如果资源配置需要改,这里也要改掉。 |
||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class RuntimePolicy: | ||
| network_mode: str = "online" | ||
| resource_tier: str = "light" | ||
|
|
||
| @property | ||
| def online(self) -> bool: | ||
| return self.network_mode == "online" | ||
|
|
||
| @property | ||
| def offline(self) -> bool: | ||
| return self.network_mode == "offline" | ||
|
|
||
| @property | ||
| def light_resource_tier(self) -> bool: | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 根据resource_tier自动判断资源档位。可以直接读这些 property,或者读policy.resource_tier。 |
||
| return self.resource_tier == "light" | ||
|
|
||
| @property | ||
| def standard_resource_tier(self) -> bool: | ||
| return self.resource_tier == "standard" | ||
|
|
||
| @property | ||
| def full_resource_tier(self) -> bool: | ||
| return self.resource_tier == "full" | ||
|
|
||
| @property | ||
| def model_policy(self) -> str: | ||
| return "local_only" if self.offline else "allow_download" | ||
|
|
||
| @property | ||
| def strict_preflight(self) -> bool: | ||
| return self.offline | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class PreflightIssue: | ||
| level: str | ||
| code: str | ||
| message: str | ||
| checker_name: str | None = None | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 用来统一表示preflight问题。 后面做network_mode / resource_tier相关的校验时安札个结构返回。 |
||
|
|
||
| def format(self) -> str: | ||
| prefix = f"[{self.code}]" | ||
| if self.checker_name: | ||
| prefix += f" {self.checker_name}:" | ||
| return f"{prefix} {self.message}" | ||
|
|
||
|
|
||
| def build_runtime_policy(config: Any) -> RuntimePolicy: | ||
| deployment = _get_section(config, "deployment") | ||
| network_mode = str(_get_value(deployment, "network_mode", "online") or "online").strip().lower() | ||
| resource_tier = str(_get_value(deployment, "resource_tier", "light") or "light").strip().lower() | ||
| return RuntimePolicy(network_mode=network_mode, resource_tier=resource_tier) | ||
|
|
||
|
|
||
| def apply_runtime_environment(policy: RuntimePolicy) -> None: | ||
| if not policy.offline: | ||
| return | ||
| os.environ.setdefault("HF_HUB_OFFLINE", "1") | ||
| os.environ.setdefault("TRANSFORMERS_OFFLINE", "1") | ||
| os.environ.setdefault("HF_DATASETS_OFFLINE", "1") | ||
| os.environ.setdefault("DATAELF_OFFLINE_MODE", "1") | ||
|
|
||
|
|
||
| def run_global_preflight(config: Any, policy: RuntimePolicy) -> list[PreflightIssue]: | ||
| issues: list[PreflightIssue] = [] | ||
|
|
||
| if policy.network_mode not in VALID_NETWORK_MODES: | ||
| issues.append(PreflightIssue( | ||
| level="error", | ||
| code="invalid_network_mode", | ||
| message=( | ||
| f"deployment.network_mode must be one of {sorted(VALID_NETWORK_MODES)}, " | ||
| f"got {policy.network_mode!r}." | ||
| ), | ||
| )) | ||
|
|
||
| if policy.resource_tier not in VALID_RESOURCE_TIERS: | ||
| issues.append(PreflightIssue( | ||
| level="error", | ||
| code="invalid_resource_tier", | ||
| message=( | ||
| f"deployment.resource_tier must be one of {sorted(VALID_RESOURCE_TIERS)}, " | ||
| f"got {policy.resource_tier!r}." | ||
| ), | ||
| )) | ||
|
|
||
| if not policy.offline: | ||
| # TODO: (network_mode) Add best-effort online dependency checks here as tools | ||
| # expose cheap, non-network preflight hooks. | ||
| return issues | ||
|
|
||
|
|
||
| # TODO: (network_mode) Re-enable strict offline endpoint checks after local | ||
| # LLM deployment is ready. Development still uses an external relay LLM. | ||
| # issues.extend(_validate_offline_llm_endpoint(config, "agent", required=_agent_requires_llm(config))) | ||
| # issues.extend(_validate_offline_llm_endpoint(config, "tool_llm", required=_tool_llm_configured(config))) | ||
| return issues | ||
|
|
||
|
|
||
| def handle_preflight_issues( | ||
| issues: list[PreflightIssue], | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 统一处理preflight结果 |
||
| *, | ||
| strict: bool, | ||
| logger: Any | None = None, | ||
| ) -> None: | ||
| if not issues: | ||
| return | ||
|
|
||
| errors = [issue for issue in issues if issue.level == "error"] | ||
| warnings = [issue for issue in issues if issue.level != "error"] | ||
|
|
||
| for issue in warnings: | ||
| if logger is not None and hasattr(logger, "warning"): | ||
| logger.warning(f"Preflight warning: {issue.format()}") | ||
|
|
||
| blocking = errors + (warnings if strict else []) | ||
| if blocking: | ||
| message = "Preflight failed:\n" + "\n".join(f" - {issue.format()}" for issue in blocking) | ||
| raise RuntimeError(message) | ||
|
|
||
|
|
||
| def _validate_offline_llm_endpoint( | ||
| config: Any, | ||
| section_name: str, | ||
| *, | ||
| required: bool, | ||
| ) -> list[PreflightIssue]: | ||
| section = _get_section(config, section_name) | ||
| base_url = _get_value(section, "base_url", None) | ||
| if not base_url: | ||
| if not required: | ||
| return [] | ||
| return [PreflightIssue( | ||
| level="error", | ||
| code="offline_missing_llm_endpoint", | ||
| message=( | ||
| f"deployment.network_mode=offline requires {section_name}.base_url " | ||
| "to point to a local or intranet OpenAI-compatible service." | ||
| ), | ||
| )] | ||
|
|
||
| if _is_public_ip_endpoint(str(base_url)): | ||
| return [PreflightIssue( | ||
| level="error", | ||
| code="offline_public_llm_endpoint", | ||
| message=( | ||
| f"deployment.network_mode=offline cannot use public endpoint " | ||
| f"{section_name}.base_url={base_url!r}." | ||
| ), | ||
| )] | ||
| # TODO: (network_mode) Add optional endpoint allowlisting once the first | ||
| # deployment config needs approved intranet hostnames beyond private IPs. | ||
| return [] | ||
|
|
||
|
|
||
| def _agent_requires_llm(config: Any) -> bool: | ||
| agent = _get_section(config, "agent") | ||
| return _get_value(agent, "type", "opencode") == "opencode" | ||
|
|
||
|
|
||
| def _tool_llm_configured(config: Any) -> bool: | ||
| tool_llm = _get_section(config, "tool_llm") | ||
| return bool(_get_value(tool_llm, "model", None) or _get_value(tool_llm, "base_url", None)) | ||
|
|
||
|
|
||
| def _is_public_ip_endpoint(url: str) -> bool: | ||
| parsed = urlparse(url) | ||
| host = parsed.hostname | ||
| if not host: | ||
| return False | ||
| if host in {"localhost", "127.0.0.1", "::1"}: | ||
| return False | ||
| try: | ||
| ip = ipaddress.ip_address(host) | ||
| except ValueError: | ||
| # Hostnames may be intranet DNS names; keep the first version flexible. | ||
| return False | ||
| return not (ip.is_private or ip.is_loopback or ip.is_link_local) | ||
|
|
||
|
|
||
| def _get_section(config: Any, name: str) -> Any: | ||
| if isinstance(config, dict): | ||
| return config.get(name, {}) | ||
| return getattr(config, name, {}) | ||
|
|
||
|
|
||
| def _get_value(section: Any, name: str, default: Any = None) -> Any: | ||
| if isinstance(section, dict): | ||
| return section.get(name, default) | ||
| return getattr(section, name, default) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
让全局config对象能带上新加的部署策略