feat: 人设模板系统、节点调度标签、pydantic-settings收敛、错误处理增强
新增persona_template表和CRUD API,BaseIndividualModel增加node_affinity和template_origin_id字段, WorkerCluster支持多集群Ray资源调度,环境变量收敛到pydantic-settings统一校验, 数据库异常转换为结构化BusinessError/RetryableError,系统节点支持custom_system_prompt。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -42,12 +42,8 @@ class TokenData(BaseModel):
|
||||
|
||||
|
||||
def _get_secret_key() -> str:
|
||||
"""读取并校验 SECRET_KEY 环境变量。
|
||||
|
||||
校验在首次实际使用 JWT 时进行,避免在模块导入阶段抛错,
|
||||
从而把"环境约束"和"模块加载"解耦。
|
||||
"""
|
||||
key = os.getenv("SECRET_KEY")
|
||||
from kilostar.utils.settings import get_settings
|
||||
key = get_settings().security.secret_key
|
||||
if not key or key in _INSECURE_SECRETS:
|
||||
raise RuntimeError(
|
||||
"未提供有效的 SECRET_KEY 或使用了不安全的默认值,请设置一个高熵的随机字符串"
|
||||
|
||||
+15
-11
@@ -25,10 +25,11 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Dict
|
||||
|
||||
_DEFAULT_LOCALE: str = os.getenv("KILOSTAR_LANG", "zh")
|
||||
from kilostar.utils.settings import get_settings
|
||||
|
||||
_DEFAULT_LOCALE: str = get_settings().kilostar_lang
|
||||
|
||||
# ─── Agent System Prompts ──────────────────────────────────────────────────
|
||||
|
||||
@@ -163,16 +164,16 @@ def t(key: str, locale: str | None = None, accept_language: str | None = None, *
|
||||
return text.format(**kwargs) if kwargs else text
|
||||
|
||||
|
||||
def agent_prompt(agent_name: str, locale: str | None = None, accept_language: str | None = None) -> str:
|
||||
def agent_prompt(
|
||||
agent_name: str,
|
||||
locale: str | None = None,
|
||||
accept_language: str | None = None,
|
||||
custom_system_prompt: str | None = None,
|
||||
) -> str:
|
||||
"""获取指定 Agent 的 system prompt,并追加语言指令。
|
||||
|
||||
Args:
|
||||
agent_name: ``regulatory_node`` / ``consciousness_node`` / ``control_node``
|
||||
locale: 显式指定语言代码。
|
||||
accept_language: ``Accept-Language`` 头内容。
|
||||
|
||||
Returns:
|
||||
完整 system prompt(含 "请使用 XX 语言回复" 的追加指令)。
|
||||
若 ``custom_system_prompt`` 不为空,追加在默认 prompt 和语言指令之后,
|
||||
使管理员自定义内容能够覆盖/补充默认行为,同时保留角色定义。
|
||||
"""
|
||||
loc = _resolve_locale(locale, accept_language)
|
||||
prompt = _PROMPTS.get(agent_name, {}).get(loc) or _PROMPTS.get(agent_name, {}).get(_DEFAULT_LOCALE, "")
|
||||
@@ -180,4 +181,7 @@ def agent_prompt(agent_name: str, locale: str | None = None, accept_language: st
|
||||
"zh": "\n\n【重要】请始终使用简体中文进行思考和回复。",
|
||||
"en": "\n\n[Important] Please always think and reply in English.",
|
||||
}.get(loc, "")
|
||||
return prompt + lang_instruction
|
||||
result = prompt + lang_instruction
|
||||
if custom_system_prompt and custom_system_prompt.strip():
|
||||
result += f"\n\n{custom_system_prompt.strip()}"
|
||||
return result
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from loguru import logger
|
||||
@@ -23,15 +22,11 @@ from kilostar.utils.request_context import get_request_id, get_trace_id
|
||||
|
||||
|
||||
def _is_json_mode() -> bool:
|
||||
"""根据环境变量决定是否启用 JSON 结构化日志。
|
||||
|
||||
支持开关:``KILOSTAR_LOG_FORMAT=json`` 或 ``KILOSTAR_LOG_JSON=1/true``。
|
||||
"""
|
||||
fmt = os.environ.get("KILOSTAR_LOG_FORMAT", "").lower()
|
||||
if fmt == "json":
|
||||
from kilostar.utils.settings import get_settings
|
||||
s = get_settings().log
|
||||
if s.kilostar_log_format.lower() == "json":
|
||||
return True
|
||||
flag = os.environ.get("KILOSTAR_LOG_JSON", "").lower()
|
||||
return flag in {"1", "true", "yes", "on"}
|
||||
return s.kilostar_log_json.lower() in {"1", "true", "yes", "on"}
|
||||
|
||||
|
||||
def _ctx_patcher(record):
|
||||
@@ -58,7 +53,8 @@ def setup_logger() -> Logger:
|
||||
"""
|
||||
logger.remove()
|
||||
|
||||
log_level = os.environ.get("KILOSTAR_LOG_LEVEL", "DEBUG").upper()
|
||||
from kilostar.utils.settings import get_settings
|
||||
log_level = get_settings().log.kilostar_log_level.upper()
|
||||
|
||||
if _is_json_mode():
|
||||
logger.configure(
|
||||
|
||||
@@ -125,3 +125,18 @@ def ray_actor_hook(*actor_names: str, timeout: float = 0.0, interval: float = 0.
|
||||
handle = _get_cached_actor_handle(actor_name)
|
||||
setattr(actor_list, actor_name, handle)
|
||||
return actor_list
|
||||
|
||||
|
||||
def get_worker_cluster(affinity: str = "cpu"):
|
||||
"""按 node_affinity 标签取对应的 WorkerCluster actor 句柄。
|
||||
|
||||
单机模式统一返回唯一的 worker_cluster 实例。
|
||||
分布式模式按 affinity 路由到 worker_cluster_cpu / _core / _gpu。
|
||||
未知标签降级到 cpu。
|
||||
"""
|
||||
if _STANDALONE:
|
||||
return _standalone_registry.get("worker_cluster")
|
||||
|
||||
_valid = {"cpu", "core", "gpu"}
|
||||
node_type = affinity if affinity in _valid else "cpu"
|
||||
return _get_cached_actor_handle(f"worker_cluster_{node_type}")
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
"""KiloStar 集中式环境变量管理。
|
||||
|
||||
所有散落在各模块的 os.getenv/os.environ 收敛到此处,
|
||||
通过 pydantic-settings 统一校验、类型转换、默认值管理。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import lru_cache
|
||||
|
||||
from pydantic import Field
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
|
||||
class DatabaseSettings(BaseSettings):
|
||||
postgres_user: str = "postgres"
|
||||
postgres_password: str = ""
|
||||
postgres_host: str = "db"
|
||||
postgres_port: int = 5432
|
||||
postgres_db: str = "postgres"
|
||||
|
||||
|
||||
class SecuritySettings(BaseSettings):
|
||||
secret_key: str = ""
|
||||
kilostar_secret_key: str = ""
|
||||
kilostar_env: str = "production"
|
||||
|
||||
|
||||
class LogSettings(BaseSettings):
|
||||
kilostar_log_level: str = "DEBUG"
|
||||
kilostar_log_format: str = ""
|
||||
kilostar_log_json: str = ""
|
||||
|
||||
|
||||
class OnebotSettings(BaseSettings):
|
||||
onebot_access_token: str = ""
|
||||
onebot_http_url: str = "http://127.0.0.1:5700"
|
||||
|
||||
|
||||
class AppSettings(BaseSettings):
|
||||
kilostar_mode: str = "distributed"
|
||||
kilostar_lang: str = "zh"
|
||||
kilostar_cors_origins: str = ""
|
||||
|
||||
db: DatabaseSettings = Field(default_factory=DatabaseSettings)
|
||||
security: SecuritySettings = Field(default_factory=SecuritySettings)
|
||||
log: LogSettings = Field(default_factory=LogSettings)
|
||||
onebot: OnebotSettings = Field(default_factory=OnebotSettings)
|
||||
|
||||
model_config = {"env_nested_delimiter": "__"}
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def get_settings() -> AppSettings:
|
||||
return AppSettings()
|
||||
Reference in New Issue
Block a user