Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ docs/让*
tests/run_*.sh
tests/launch_*.py
*.launch.log
.codegraph/
81 changes: 81 additions & 0 deletions skillopt/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from skillopt.model import azure_openai as _openai
from skillopt.model import claude_backend as _claude
from skillopt.model import hermes_backend as _hermes
from skillopt.model import minimax_backend as _minimax
from skillopt.model import qwen_backend as _qwen
from skillopt.model.backend_config import ( # noqa: F401
Expand Down Expand Up @@ -55,6 +56,10 @@ def set_backend(name: str | None) -> str:
set_optimizer_backend("openai_chat")
set_target_backend("minimax_chat")
return "minimax_chat"
if normalized in {"hermes", "hermes_chat"}:
set_optimizer_backend("hermes_chat")
set_target_backend("hermes_chat")
return "hermes_chat"
raise ValueError(f"Unsupported legacy backend: {name!r}")


Expand All @@ -74,6 +79,8 @@ def get_backend_name() -> str:
return "qwen_chat"
if optimizer == "openai_chat" and target == "minimax_chat":
return "minimax_chat"
if optimizer == "hermes_chat" and target == "hermes_chat":
return "hermes_chat"
return f"{optimizer}+{target}"


Expand Down Expand Up @@ -105,6 +112,15 @@ def chat_optimizer(
reasoning_effort=reasoning_effort,
timeout=timeout,
)
if get_optimizer_backend() == "hermes_chat":
return _hermes.chat_optimizer(
system=system,
user=user,
max_completion_tokens=max_completion_tokens,
retries=retries,
stage=stage,
timeout=timeout,
)
return _openai.chat_optimizer(
system=system,
user=user,
Expand Down Expand Up @@ -153,6 +169,15 @@ def chat_target(
stage=stage,
reasoning_effort=reasoning_effort,
)
if get_target_backend() == "hermes_chat":
return _hermes.chat_target(
system=system,
user=user,
max_completion_tokens=max_completion_tokens,
retries=retries,
stage=stage,
timeout=timeout,
)
if not is_target_chat_backend():
raise NotImplementedError(
"chat_target is only supported with target_backend=openai_chat, claude_chat, qwen_chat, or minimax_chat. "
Expand Down Expand Up @@ -204,6 +229,17 @@ def chat_optimizer_messages(
return_message=return_message,
timeout=timeout,
)
if get_optimizer_backend() == "hermes_chat":
return _hermes.chat_optimizer_messages(
messages=messages,
max_completion_tokens=max_completion_tokens,
retries=retries,
stage=stage,
tools=tools,
tool_choice=tool_choice,
return_message=return_message,
timeout=timeout,
)
return _openai.chat_optimizer_messages(
messages=messages,
max_completion_tokens=max_completion_tokens,
Expand Down Expand Up @@ -263,6 +299,17 @@ def chat_target_messages(
tool_choice=tool_choice,
return_message=return_message,
)
if get_target_backend() == "hermes_chat":
return _hermes.chat_target_messages(
messages=messages,
max_completion_tokens=max_completion_tokens,
retries=retries,
stage=stage,
tools=tools,
tool_choice=tool_choice,
return_message=return_message,
timeout=timeout,
)
if not is_target_chat_backend():
raise NotImplementedError(
"chat_target_messages is only supported with target_backend=openai_chat, claude_chat, qwen_chat, or minimax_chat. "
Expand Down Expand Up @@ -294,6 +341,18 @@ def chat_messages_with_deployment(
return_message: bool = False,
timeout: int | None = None,
) -> tuple[Any, dict]:
if get_optimizer_backend() == "hermes_chat" or get_target_backend() == "hermes_chat":
return _hermes.chat_messages_with_deployment(
deployment=deployment,
messages=messages,
max_completion_tokens=max_completion_tokens,
retries=retries,
stage=stage,
tools=tools,
tool_choice=tool_choice,
return_message=return_message,
timeout=timeout,
)
return _openai.chat_messages_with_deployment(
deployment=deployment,
messages=messages,
Expand All @@ -318,6 +377,16 @@ def chat_with_deployment(
reasoning_effort: str | None = None,
timeout: int | None = None,
) -> tuple[str, dict]:
if get_optimizer_backend() == "hermes_chat" or get_target_backend() == "hermes_chat":
return _hermes.chat_with_deployment(
deployment=deployment,
system=system,
user=user,
max_completion_tokens=max_completion_tokens,
retries=retries,
stage=stage,
timeout=timeout,
)
return _openai.chat_with_deployment(
deployment=deployment,
system=system,
Expand Down Expand Up @@ -365,6 +434,17 @@ def get_token_summary() -> dict:
summary[stage]["prompt_tokens"] += values["prompt_tokens"]
summary[stage]["completion_tokens"] += values["completion_tokens"]
summary[stage]["total_tokens"] += values["total_tokens"]
hermes_summary = _hermes.get_token_summary()
for stage, values in hermes_summary.items():
if stage == "_total":
continue
if stage not in summary:
summary[stage] = values
continue
summary[stage]["calls"] += values["calls"]
summary[stage]["prompt_tokens"] += values["prompt_tokens"]
summary[stage]["completion_tokens"] += values["completion_tokens"]
summary[stage]["total_tokens"] += values["total_tokens"]
total = {
"calls": 0,
"prompt_tokens": 0,
Expand All @@ -387,6 +467,7 @@ def reset_token_tracker() -> None:
_claude.reset_token_tracker()
_qwen.reset_token_tracker()
_minimax.reset_token_tracker()
_hermes.reset_token_tracker()


def configure_azure_openai(
Expand Down
12 changes: 6 additions & 6 deletions skillopt/model/backend_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ def _parse_int(value: str | None, default: int) -> int:
def set_optimizer_backend(backend: str) -> None:
global OPTIMIZER_BACKEND
OPTIMIZER_BACKEND = normalize_backend_name(backend or "openai_chat")
if OPTIMIZER_BACKEND not in {"openai_chat", "claude_chat", "qwen_chat", "minimax_chat"}:
if OPTIMIZER_BACKEND not in {"openai_chat", "claude_chat", "qwen_chat", "minimax_chat", "hermes_chat"}:
raise ValueError(
f"Unsupported optimizer backend: {OPTIMIZER_BACKEND!r}. "
"Supported values are 'openai_chat', 'claude_chat', 'qwen_chat', and 'minimax_chat'."
"Supported values are 'openai_chat', 'claude_chat', 'qwen_chat', 'minimax_chat', and 'hermes_chat'."
)
os.environ["OPTIMIZER_BACKEND"] = OPTIMIZER_BACKEND

Expand All @@ -64,10 +64,10 @@ def get_optimizer_backend() -> str:
def set_target_backend(backend: str) -> None:
global TARGET_BACKEND
TARGET_BACKEND = normalize_backend_name(backend or "openai_chat")
if TARGET_BACKEND not in {"openai_chat", "claude_chat", "qwen_chat", "minimax_chat", "codex_exec", "claude_code_exec"}:
if TARGET_BACKEND not in {"openai_chat", "claude_chat", "qwen_chat", "minimax_chat", "codex_exec", "claude_code_exec", "hermes_chat"}:
raise ValueError(
f"Unsupported target backend: {TARGET_BACKEND!r}. "
"Supported values are 'openai_chat', 'claude_chat', 'qwen_chat', 'minimax_chat', 'codex_exec', and 'claude_code_exec'."
"Supported values are 'openai_chat', 'claude_chat', 'qwen_chat', 'minimax_chat', 'codex_exec', 'claude_code_exec', and 'hermes_chat'."
)
os.environ["TARGET_BACKEND"] = TARGET_BACKEND

Expand All @@ -81,11 +81,11 @@ def is_target_exec_backend() -> bool:


def is_optimizer_chat_backend() -> bool:
return OPTIMIZER_BACKEND in {"openai_chat", "claude_chat", "qwen_chat", "minimax_chat"}
return OPTIMIZER_BACKEND in {"openai_chat", "claude_chat", "qwen_chat", "minimax_chat", "hermes_chat"}


def is_target_chat_backend() -> bool:
return TARGET_BACKEND in {"openai_chat", "claude_chat", "qwen_chat", "minimax_chat"}
return TARGET_BACKEND in {"openai_chat", "claude_chat", "qwen_chat", "minimax_chat", "hermes_chat"}


def configure_codex_exec(
Expand Down
3 changes: 3 additions & 0 deletions skillopt/model/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"claude_code_exec": "claude-sonnet-4-6",
"qwen_chat": "Qwen/Qwen3.5-4B",
"minimax_chat": "MiniMax-M2.7",
"hermes_chat": "hermes",
}

_BACKEND_ALIASES = {
Expand All @@ -44,6 +45,8 @@
"qwen_chat": "qwen_chat",
"minimax": "minimax_chat",
"minimax_chat": "minimax_chat",
"hermes": "hermes_chat",
"hermes_chat": "hermes_chat",
}


Expand Down
Loading