mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-27 01:11:40 +00:00
feat: API server model name derived from profile name (#6857)
* feat: API server model name derived from profile name For multi-user setups (e.g. OpenWebUI), each profile's API server now advertises a distinct model name on /v1/models: - Profile 'lucas' -> model ID 'lucas' - Profile 'admin' -> model ID 'admin' - Default profile -> 'hermes-agent' (unchanged) Explicit override via API_SERVER_MODEL_NAME env var or platforms.api_server.model_name config for custom names. Resolves friction where OpenWebUI couldn't distinguish multiple hermes-agent connections all advertising the same model name. * docs: multi-user setup with profiles for API server + Open WebUI - api-server.md: added Multi-User Setup section, API_SERVER_MODEL_NAME to config table, updated /v1/models description - open-webui.md: added Multi-User Setup with Profiles section with step-by-step guide, updated model name references - environment-variables.md: added API_SERVER_MODEL_NAME entry
This commit is contained in:
parent
2d0d05a337
commit
9634e20e15
7 changed files with 152 additions and 9 deletions
|
|
@ -299,6 +299,9 @@ class APIServerAdapter(BasePlatformAdapter):
|
|||
self._cors_origins: tuple[str, ...] = self._parse_cors_origins(
|
||||
extra.get("cors_origins", os.getenv("API_SERVER_CORS_ORIGINS", "")),
|
||||
)
|
||||
self._model_name: str = self._resolve_model_name(
|
||||
extra.get("model_name", os.getenv("API_SERVER_MODEL_NAME", "")),
|
||||
)
|
||||
self._app: Optional["web.Application"] = None
|
||||
self._runner: Optional["web.AppRunner"] = None
|
||||
self._site: Optional["web.TCPSite"] = None
|
||||
|
|
@ -324,6 +327,26 @@ class APIServerAdapter(BasePlatformAdapter):
|
|||
|
||||
return tuple(str(item).strip() for item in items if str(item).strip())
|
||||
|
||||
@staticmethod
|
||||
def _resolve_model_name(explicit: str) -> str:
|
||||
"""Derive the advertised model name for /v1/models.
|
||||
|
||||
Priority:
|
||||
1. Explicit override (config extra or API_SERVER_MODEL_NAME env var)
|
||||
2. Active profile name (so each profile advertises a distinct model)
|
||||
3. Fallback: "hermes-agent"
|
||||
"""
|
||||
if explicit and explicit.strip():
|
||||
return explicit.strip()
|
||||
try:
|
||||
from hermes_cli.profiles import get_active_profile_name
|
||||
profile = get_active_profile_name()
|
||||
if profile and profile not in ("default", "custom"):
|
||||
return profile
|
||||
except Exception:
|
||||
pass
|
||||
return "hermes-agent"
|
||||
|
||||
def _cors_headers_for_origin(self, origin: str) -> Optional[Dict[str, str]]:
|
||||
"""Return CORS headers for an allowed browser origin."""
|
||||
if not origin or not self._cors_origins:
|
||||
|
|
@ -468,12 +491,12 @@ class APIServerAdapter(BasePlatformAdapter):
|
|||
"object": "list",
|
||||
"data": [
|
||||
{
|
||||
"id": "hermes-agent",
|
||||
"id": self._model_name,
|
||||
"object": "model",
|
||||
"created": int(time.time()),
|
||||
"owned_by": "hermes",
|
||||
"permission": [],
|
||||
"root": "hermes-agent",
|
||||
"root": self._model_name,
|
||||
"parent": None,
|
||||
}
|
||||
],
|
||||
|
|
@ -546,7 +569,7 @@ class APIServerAdapter(BasePlatformAdapter):
|
|||
# history already set from request body above
|
||||
|
||||
completion_id = f"chatcmpl-{uuid.uuid4().hex[:29]}"
|
||||
model_name = body.get("model", "hermes-agent")
|
||||
model_name = body.get("model", self._model_name)
|
||||
created = int(time.time())
|
||||
|
||||
if stream:
|
||||
|
|
@ -923,7 +946,7 @@ class APIServerAdapter(BasePlatformAdapter):
|
|||
"object": "response",
|
||||
"status": "completed",
|
||||
"created_at": created_at,
|
||||
"model": body.get("model", "hermes-agent"),
|
||||
"model": body.get("model", self._model_name),
|
||||
"output": output_items,
|
||||
"usage": {
|
||||
"input_tokens": usage.get("input_tokens", 0),
|
||||
|
|
@ -1653,8 +1676,8 @@ class APIServerAdapter(BasePlatformAdapter):
|
|||
|
||||
self._mark_connected()
|
||||
logger.info(
|
||||
"[%s] API server listening on http://%s:%d",
|
||||
self.name, self._host, self._port,
|
||||
"[%s] API server listening on http://%s:%d (model: %s)",
|
||||
self.name, self._host, self._port, self._model_name,
|
||||
)
|
||||
return True
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue