rtc-voice-chat/backend/services/scene_service.py

100 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
场景配置加载与运行时准备
"""
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