100 lines
3.0 KiB
Python
100 lines
3.0 KiB
Python
"""
|
||
场景配置加载与运行时准备
|
||
"""
|
||
|
||
import copy
|
||
import json
|
||
import time
|
||
import uuid
|
||
from pathlib import Path
|
||
from typing import Any
|
||
|
||
from fastapi import Request
|
||
|
||
from config.custom_scene import (
|
||
CUSTOM_SCENE_ID,
|
||
build_custom_scene_from_env,
|
||
build_llm_settings_from_env,
|
||
)
|
||
from security.rtc_token import AccessToken, privileges
|
||
from utils.validation import assert_scene_value, assert_token_generation_ready
|
||
|
||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||
SCENES_DIR = BASE_DIR / "scenes"
|
||
|
||
|
||
def load_scenes() -> dict:
|
||
scenes = {
|
||
CUSTOM_SCENE_ID: build_custom_scene_from_env(),
|
||
}
|
||
for p in sorted(SCENES_DIR.glob("*.json")):
|
||
if p.stem == CUSTOM_SCENE_ID:
|
||
continue
|
||
with open(p, encoding="utf-8") as f:
|
||
scenes[p.stem] = json.load(f)
|
||
return scenes
|
||
|
||
|
||
def prepare_scene_runtime(scene_name: str, data: dict[str, Any]):
|
||
data = copy.deepcopy(data)
|
||
scene_config = data.get("SceneConfig", {})
|
||
rtc_config = data.get("RTCConfig", {})
|
||
voice_chat = data.get("VoiceChat", {})
|
||
|
||
app_id = rtc_config.get("AppId", "")
|
||
assert_scene_value(scene_name, "RTCConfig.AppId", app_id)
|
||
|
||
token = rtc_config.get("Token", "")
|
||
user_id = rtc_config.get("UserId", "")
|
||
room_id = rtc_config.get("RoomId", "")
|
||
app_key = rtc_config.get("AppKey", "")
|
||
|
||
if app_id and (not token or not user_id or not room_id):
|
||
rtc_config["RoomId"] = voice_chat["RoomId"] = room_id or str(uuid.uuid4())
|
||
rtc_config["UserId"] = user_id = user_id or str(uuid.uuid4())
|
||
|
||
agent_config = voice_chat.get("AgentConfig", {})
|
||
target_user_ids = agent_config.get("TargetUserId")
|
||
if target_user_ids:
|
||
target_user_ids[0] = rtc_config["UserId"]
|
||
|
||
assert_token_generation_ready(scene_name, app_key)
|
||
key = AccessToken(app_id, app_key, rtc_config["RoomId"], rtc_config["UserId"])
|
||
key.add_privilege(privileges["PrivSubscribeStream"], 0)
|
||
key.add_privilege(privileges["PrivPublishStream"], 0)
|
||
key.expire_time(int(time.time()) + 24 * 3600)
|
||
rtc_config["Token"] = key.serialize()
|
||
|
||
return scene_config, rtc_config, voice_chat
|
||
|
||
|
||
def get_custom_llm_callback_settings() -> dict[str, Any]:
|
||
missing: list[str] = []
|
||
settings = build_llm_settings_from_env(missing)
|
||
if missing:
|
||
missing_str = ", ".join(dict.fromkeys(missing))
|
||
raise ValueError(f"Custom 场景缺少以下环境变量: {missing_str}")
|
||
|
||
if settings["mode"] != "CustomLLM":
|
||
raise ValueError("当前 CUSTOM_LLM_MODE 不是 CustomLLM,无法使用本地回调接口")
|
||
|
||
return settings
|
||
|
||
|
||
def ensure_custom_llm_authorized(request: Request, api_key: str):
|
||
if not api_key:
|
||
return
|
||
|
||
authorization = request.headers.get("authorization", "")
|
||
expected_value = f"Bearer {api_key}"
|
||
if authorization == expected_value:
|
||
return
|
||
|
||
raise PermissionError("自定义 LLM 回调鉴权失败,请检查 CUSTOM_LLM_API_KEY")
|
||
|
||
|
||
try:
|
||
Scenes = load_scenes()
|
||
except ValueError as exc:
|
||
raise RuntimeError(f"Custom 场景配置错误:{exc}") from exc
|