97 lines
2.9 KiB
Python
97 lines
2.9 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}")
|
|
|
|
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
|