neuro-simulator 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,143 @@
1
+ # --- API密钥配置(无法通过外部控制面板修改) ---
2
+ api_keys:
3
+ # Letta API Token - 用于与 Letta 服务进行身份验证
4
+ # 如果你自建 Letta Server 且没有设置 token,可以留空
5
+ letta_token: "YOUR_LETTA_TOKEN_HERE"
6
+
7
+ # Letta Server 基础 URL - 如果你自建 Letta Server 请填写完整地址,否则留空以使用Letta Cloud
8
+ letta_base_url: ""
9
+
10
+ # Neuro Agent ID - 在 Letta 中创建的 Agent 的唯一标识符
11
+ neuro_agent_id: "YOUR_AGENT_ID_HERE"
12
+
13
+ # Gemini API Key - 用于调用 Google Gemini API 生成观众聊天内容
14
+ gemini_api_key: "YOUR_GEMINI_KEY_HERE"
15
+
16
+ # OpenAI API Key - 用于调用兼容 OpenAI 的 API 生成观众聊天内容
17
+ openai_api_key: "YOUR_OPENAI_KEY_HERE"
18
+
19
+ # OpenAI API 基础 URL - 如果使用第三方兼容 OpenAI API 服务(如 SiliconFlow)请填写对应地址
20
+ openai_api_base_url: "YOUR_OPENAI_BASE_URL_HERE"
21
+
22
+ # Azure 语音服务密钥 - 用于调用微软 Azure TTS 服务合成语音
23
+ azure_speech_key: "YOUR_AZURE_KEY_HERE"
24
+
25
+ # Azure 语音服务区域 - Azure 服务所在的区域,如 "eastus" 或 "westus"
26
+ azure_speech_region: "YOUR_AZURE_REGION_HERE"
27
+
28
+ # --- 直播元数据配置 ---
29
+ stream_metadata:
30
+ # 主播昵称 - 显示在直播中的主播名称(此设置无法通过外部控制面板修改)
31
+ streamer_nickname: "vedal987"
32
+
33
+ # 直播标题 - 显示在直播页面的标题
34
+ stream_title: "neuro-sama is here for u all"
35
+
36
+ # 直播分类 - 直播内容的分类标签
37
+ stream_category: "谈天说地"
38
+
39
+ # 直播标签 - 用于描述直播内容的标签列表
40
+ stream_tags: ["Vtuber", "AI", "Cute", "English", "Gremlin", "catgirl"]
41
+
42
+ # --- Neuro 行为与节奏控制 ---
43
+ neuro_behavior:
44
+ # 输入聊天采样数量 - 每次生成 Neuro 回复时从观众聊天中采样的消息数量,不建议太长
45
+ input_chat_sample_size: 10
46
+
47
+ # 说话后冷却时间(秒) - Neuro 每次说完话后的等待时间
48
+ post_speech_cooldown_sec: 1.0
49
+
50
+ # 初始问候语 - 直播开始时给 Neuro 的系统提示语
51
+ initial_greeting: "The stream has just started. Greet your audience and say hello!"
52
+
53
+ # --- Chatbot 配置 ---
54
+ audience_simulation:
55
+ # LLM 提供商 - 选择用于生成观众聊天的 AI 服务,只能是 'gemini' 或 'openai'
56
+ llm_provider: "gemini"
57
+
58
+ # Gemini 模型 - 使用 Gemini 服务时的具体模型名称
59
+ # 推荐使用gemma-3-27b-it,每天可免费调用14000次(15:00 GMT+8 刷新次数)
60
+ gemini_model: "gemma-3-27b-it"
61
+
62
+ # OpenAI 模型 - 使用 OpenAI 服务时的具体模型名称
63
+ # 使用 SiliconFlow 等第三方服务时可以尝试 THUDM/GLM-4-9B-0414 等模型
64
+ openai_model: "THUDM/GLM-4-9B-0414"
65
+
66
+ # LLM 温度 - 控制 AI 生成内容的随机性,值越高越随机(0-2之间)
67
+ llm_temperature: 0.7
68
+
69
+ # 聊天生成间隔(秒) - 调用 Chatbot 生成新观众聊天的时间间隔
70
+ chat_generation_interval_sec: 2
71
+
72
+ # 每批聊天生成数量 - 每次调用 Chatbot 时生成的聊天消息数量
73
+ chats_per_batch: 3
74
+
75
+ # 最大输出 Token 数 - 单次调用 Chatbot 时允许生成的最大 token 数量
76
+ max_output_tokens: 300
77
+
78
+ # Chatbot 提示模板 - 用于指导 AI 生成观众聊天内容的提示词
79
+ # 其中 {neuro_speech} 和 {num_chats_to_generate} 会被动态替换
80
+ prompt_template: |
81
+ You are a Twitch live stream viewer. Your goal is to generate short, realistic, and relevant chat messages.
82
+ The streamer, Neuro-Sama, just said the following:
83
+ ---
84
+ {neuro_speech}
85
+ ---
86
+ Based on what Neuro-Sama said, generate a variety of chat messages. Your messages should be:
87
+ - Directly reacting to her words.
88
+ - Asking follow-up questions.
89
+ - Using relevant Twitch emotes (like LUL, Pog, Kappa, etc.).
90
+ - General banter related to the topic.
91
+ - Short and punchy, like real chat messages.
92
+ Do NOT act as the streamer. Do NOT generate full conversations.
93
+ Generate exactly {num_chats_to_generate} distinct chat messages. Each message must be prefixed with a DIFFERENT fictional username, like 'ChatterBoy: message text', 'EmoteFan: message text'.
94
+
95
+ # 用户名黑名单 - 当检测到这些用户名时会自动替换为 username_pool 中的用户名
96
+ username_blocklist: ["ChatterBoy", "EmoteFan", "Username", "User"]
97
+
98
+ # 用户名池 - 用于替换黑名单用户名或生成新用户名(有时候Chatbot LLM可能未给出用户名)的候选列表
99
+ username_pool:
100
+ - "ChatterBox"
101
+ - "EmoteLord"
102
+ - "QuestionMark"
103
+ - "StreamFan"
104
+ - "PixelPundit"
105
+ - "CodeSage"
106
+ - "DataDiver"
107
+ - "ByteBard"
108
+
109
+ # --- 音频合成 (TTS) 配置 ---
110
+ tts:
111
+ # 语音名称 - 不要调整这个设置
112
+ voice_name: "en-US-AshleyNeural"
113
+
114
+ # 语音音调 - 除非你不想听Neuro的声音
115
+ voice_pitch: 1.25
116
+
117
+ # --- 数据流与性能配置 ---
118
+ performance:
119
+ # 输入队列最大大小 - 可能被提供给 Neuro 作为输入的聊天消息最大数量
120
+ # 具体逻辑是在 neuro_input_queue_max_size 中抽取 input_chat_sample_size 条消息发送
121
+ neuro_input_queue_max_size: 200
122
+
123
+ # 观众聊天缓冲区最大大小 - 后端存储的聊天记录总量
124
+ audience_chat_buffer_max_size: 1000
125
+
126
+ # 客户端初始聊天数 - 向新客户端发送的历史聊天消息数量,主要用来应对中途加入的客户端
127
+ initial_chat_backlog_limit: 50
128
+
129
+ # --- 服务器配置 ---
130
+ server:
131
+ # 服务器主机地址 - 服务器监听的主机地址(使用 uvicorn 命令启动时此设置无效)
132
+ host: "127.0.0.1"
133
+
134
+ # 服务器端口 - 服务器监听的端口号(使用 uvicorn 命令启动时此设置无效)
135
+ port: 8000
136
+
137
+ # 面板密码 - 设置 API token 用于外部控制面板的身份验证,在公网持续部署时强烈建议开启
138
+ panel_password: "your-secret-api-token-here"
139
+
140
+ # 客户端来源 - 允许跨域访问的客户端地址列表,非本机访问时记得添加一下
141
+ client_origins:
142
+ - "http://localhost:5173"
143
+ - "http://127.0.0.1:5173"
@@ -0,0 +1,11 @@
1
+ # backend/shared_state.py
2
+ import asyncio
3
+
4
+ # 用来同步直播进入 LIVE 阶段的信号
5
+ live_phase_started_event = asyncio.Event()
6
+
7
+ # --- 用于在任务间共享 Neuro 的最新发言 ---
8
+ # 使用一个锁来确保在读写时不会发生冲突
9
+ neuro_last_speech_lock = asyncio.Lock()
10
+ # 存储 Neuro 最新一次完整发言的文本,并提供一个初始值
11
+ neuro_last_speech: str = "Neuro-Sama has just started the stream and hasn't said anything yet."
@@ -0,0 +1,29 @@
1
+ # backend/stream_chat.py
2
+ from collections import deque
3
+ from .config import config_manager
4
+
5
+ # 使用 settings 对象来初始化 deque 的 maxlen
6
+ audience_chat_buffer: deque[dict] = deque(maxlen=config_manager.settings.performance.audience_chat_buffer_max_size)
7
+ neuro_input_queue: deque[dict] = deque(maxlen=config_manager.settings.performance.neuro_input_queue_max_size)
8
+
9
+ def clear_all_queues():
10
+ audience_chat_buffer.clear()
11
+ neuro_input_queue.clear()
12
+ print("所有聊天队列已清空。")
13
+
14
+ def add_to_audience_buffer(chat_item: dict):
15
+ audience_chat_buffer.append(chat_item)
16
+
17
+ def add_to_neuro_input_queue(chat_item: dict):
18
+ neuro_input_queue.append(chat_item)
19
+
20
+ def get_recent_audience_chats(limit: int) -> list[dict]:
21
+ return list(audience_chat_buffer)[-limit:]
22
+
23
+ def get_all_neuro_input_chats() -> list[dict]:
24
+ chats = list(neuro_input_queue)
25
+ neuro_input_queue.clear()
26
+ return chats
27
+
28
+ def is_neuro_input_queue_empty() -> bool:
29
+ return not bool(neuro_input_queue)
@@ -0,0 +1,143 @@
1
+ # backend/stream_manager.py
2
+ import asyncio
3
+ import time
4
+ import os
5
+ from .config import config_manager
6
+ import neuro_simulator.shared_state as shared_state
7
+ from mutagen.mp4 import MP4, MP4StreamInfoError
8
+
9
+ class LiveStreamManager:
10
+ class NeuroAvatarStage:
11
+ HIDDEN = "hidden"
12
+ STEP1 = "step1"
13
+ STEP2 = "step2"
14
+
15
+ class StreamPhase:
16
+ OFFLINE = "offline"
17
+ INITIALIZING = "initializing"
18
+ AVATAR_INTRO = "avatar_intro"
19
+ LIVE = "live"
20
+
21
+ event_queue: asyncio.Queue = asyncio.Queue()
22
+
23
+ # Get the working directory where media files are located
24
+ _working_dir = os.getcwd() # This will be set by cli.py to the --dir path
25
+ _WELCOME_VIDEO_PATH_BACKEND = os.path.join(_working_dir, "media", "neuro_start.mp4")
26
+ _WELCOME_VIDEO_DURATION_SEC_DEFAULT = 10.0
27
+
28
+ # --- NEW: 使用 mutagen 获取时长的静态方法 ---
29
+ @staticmethod
30
+ def _get_video_duration_mutagen_static(video_path: str) -> float:
31
+ """使用 mutagen 库可靠地获取 MP4 视频时长。"""
32
+ if not os.path.exists(video_path):
33
+ print(f"警告: 视频文件 '{video_path}' 不存在。将使用默认值。")
34
+ return LiveStreamManager._WELCOME_VIDEO_DURATION_SEC_DEFAULT
35
+ try:
36
+ video = MP4(video_path)
37
+ duration = video.info.length
38
+ print(f"已通过 mutagen 成功读取视频 '{video_path}' 时长: {duration:.2f} 秒。")
39
+ return duration
40
+ except MP4StreamInfoError:
41
+ print(f"警告: mutagen 无法解析 '{video_path}' 的流信息。它可能不是一个标准的MP4文件。将使用默认值。")
42
+ return LiveStreamManager._WELCOME_VIDEO_DURATION_SEC_DEFAULT
43
+ except Exception as e:
44
+ print(f"使用 mutagen 获取视频时长时出错: {e}. 将使用默认视频时长。")
45
+ return LiveStreamManager._WELCOME_VIDEO_DURATION_SEC_DEFAULT
46
+
47
+ # --- 核心修改点: 调用新的 mutagen 方法 ---
48
+ _WELCOME_VIDEO_DURATION_SEC = _get_video_duration_mutagen_static(_WELCOME_VIDEO_PATH_BACKEND)
49
+ AVATAR_INTRO_TOTAL_DURATION_SEC = 3.0
50
+
51
+ def __init__(self):
52
+ self._current_phase: str = self.StreamPhase.OFFLINE
53
+ self._stream_start_global_time: float = 0.0
54
+ self._is_neuro_speaking: bool = False
55
+ # Note: We don't call reset_stream_state here to avoid asyncio issues during initialization
56
+ print("LiveStreamManager 初始化完成。")
57
+
58
+ async def broadcast_stream_metadata(self):
59
+ """将直播元数据放入事件队列进行广播。"""
60
+ metadata_event = {
61
+ "type": "update_stream_metadata",
62
+ **config_manager.settings.stream_metadata.model_dump()
63
+ }
64
+ await self.event_queue.put(metadata_event)
65
+ print("直播元数据已放入广播队列。")
66
+
67
+ def reset_stream_state(self):
68
+ """重置直播状态到初始离线状态。"""
69
+ self._current_phase = self.StreamPhase.OFFLINE
70
+ self._stream_start_global_time = 0.0
71
+ self._is_neuro_speaking = False
72
+ while not self.event_queue.empty():
73
+ self.event_queue.get_nowait()
74
+ shared_state.live_phase_started_event.clear()
75
+ print("直播状态已重置为 OFFLINE。")
76
+ # Don't create task during initialization, will be called properly in main.py startup
77
+
78
+ async def start_new_stream_cycle(self):
79
+ """开始一个全新的直播周期,从欢迎视频开始。"""
80
+ if self._current_phase != self.StreamPhase.OFFLINE:
81
+ print("警告: 直播已在进行中,无法开始新周期。")
82
+ return
83
+
84
+ print("正在启动新的直播周期...")
85
+ self._stream_start_global_time = time.time()
86
+
87
+ self._current_phase = self.StreamPhase.INITIALIZING
88
+ print(f"进入阶段: {self.StreamPhase.INITIALIZING}. 广播 'play_welcome_video' 事件。")
89
+ await self.event_queue.put({
90
+ "type": "play_welcome_video",
91
+ "progress": 0,
92
+ "elapsed_time_sec": self.get_elapsed_time()
93
+ })
94
+
95
+ print(f"等待视频时长: {self._WELCOME_VIDEO_DURATION_SEC:.2f} 秒")
96
+ await asyncio.sleep(self._WELCOME_VIDEO_DURATION_SEC)
97
+
98
+ self._current_phase = self.StreamPhase.AVATAR_INTRO
99
+ print(f"进入阶段: {self.StreamPhase.AVATAR_INTRO}. 广播 'start_avatar_intro' 事件。")
100
+ await self.event_queue.put({"type": "start_avatar_intro", "elapsed_time_sec": self.get_elapsed_time()})
101
+
102
+ print(f"等待立绘入场动画: {self.AVATAR_INTRO_TOTAL_DURATION_SEC} 秒")
103
+ await asyncio.sleep(self.AVATAR_INTRO_TOTAL_DURATION_SEC)
104
+
105
+ self._current_phase = self.StreamPhase.LIVE
106
+ print(f"进入阶段: {self.StreamPhase.LIVE}. 广播 'enter_live_phase' 事件。")
107
+ await self.event_queue.put({"type": "enter_live_phase", "elapsed_time_sec": self.get_elapsed_time()})
108
+
109
+ shared_state.live_phase_started_event.set()
110
+ print("Live phase started event has been set.")
111
+
112
+ def set_neuro_speaking_status(self, speaking: bool):
113
+ """设置并广播Neuro是否正在说话。"""
114
+ if self._is_neuro_speaking != speaking:
115
+ self._is_neuro_speaking = speaking
116
+ # Only create task if we're in an event loop
117
+ try:
118
+ asyncio.get_running_loop()
119
+ asyncio.create_task(self.event_queue.put({"type": "neuro_is_speaking", "speaking": speaking}))
120
+ except RuntimeError:
121
+ # No running loop, just put directly (this might block)
122
+ self.event_queue.put_nowait({"type": "neuro_is_speaking", "speaking": speaking})
123
+
124
+ def get_elapsed_time(self) -> float:
125
+ """获取从直播开始到现在的总时长(秒)。"""
126
+ if self._stream_start_global_time > 0:
127
+ return time.time() - self._stream_start_global_time
128
+ return 0.0
129
+
130
+ def get_initial_state_for_client(self) -> dict:
131
+ """为新连接的客户端生成当前的初始状态事件。"""
132
+ elapsed_time = self.get_elapsed_time()
133
+ base_state = {"elapsed_time_sec": elapsed_time}
134
+ if self._current_phase == self.StreamPhase.INITIALIZING:
135
+ return {"type": "play_welcome_video", "progress": elapsed_time, **base_state}
136
+ elif self._current_phase == self.StreamPhase.AVATAR_INTRO:
137
+ return {"type": "start_avatar_intro", **base_state}
138
+ elif self._current_phase == self.StreamPhase.LIVE:
139
+ return {"type": "enter_live_phase", "is_speaking": self._is_neuro_speaking, **base_state}
140
+ return {"type": "offline", **base_state}
141
+
142
+ # 全局单例
143
+ live_stream_manager = LiveStreamManager()
@@ -0,0 +1,51 @@
1
+ # backend/websocket_manager.py
2
+ from fastapi import WebSocket
3
+ from collections import deque
4
+ import asyncio
5
+ import json
6
+ from starlette.websockets import WebSocketState # 确保导入 WebSocketState
7
+
8
+ class WebSocketManager:
9
+ """管理所有活动的 WebSocket 连接,并提供消息广播功能。"""
10
+ def __init__(self):
11
+ self.active_connections: deque[WebSocket] = deque()
12
+ print("WebSocketManager 初始化完成。")
13
+
14
+ async def connect(self, websocket: WebSocket):
15
+ await websocket.accept()
16
+ self.active_connections.append(websocket)
17
+ print(f"WebSocket 客户端已连接。当前连接数: {len(self.active_connections)}")
18
+
19
+ def disconnect(self, websocket: WebSocket):
20
+ try:
21
+ if websocket in self.active_connections:
22
+ self.active_connections.remove(websocket)
23
+ print(f"WebSocket 客户端已断开连接。当前连接数: {len(self.active_connections)}")
24
+ except Exception as e:
25
+ print(f"断开 WebSocket 连接时出错: {e}")
26
+
27
+ async def send_personal_message(self, message: dict, websocket: WebSocket):
28
+ if websocket.client_state == WebSocketState.CONNECTED:
29
+ try:
30
+ await websocket.send_json(message)
31
+ except Exception as e:
32
+ print(f"发送个人消息时出错,客户端可能已断开: {e}")
33
+ self.disconnect(websocket)
34
+
35
+ async def broadcast(self, message: dict):
36
+ disconnected_sockets = []
37
+ for connection in list(self.active_connections):
38
+ if connection.client_state == WebSocketState.CONNECTED:
39
+ try:
40
+ await connection.send_json(message)
41
+ except Exception as e:
42
+ print(f"广播消息时出错,客户端 {connection} 可能已断开: {e}")
43
+ disconnected_sockets.append(connection)
44
+ else:
45
+ disconnected_sockets.append(connection)
46
+
47
+ for disconnected_socket in disconnected_sockets:
48
+ self.disconnect(disconnected_socket)
49
+
50
+ # --- 核心修改点:只创建一个实例 ---
51
+ connection_manager = WebSocketManager()
@@ -0,0 +1,181 @@
1
+ Metadata-Version: 2.4
2
+ Name: neuro-simulator
3
+ Version: 0.0.1
4
+ Summary: Neuro Simulator Server
5
+ Home-page: https://github.com/Moha-Master/neuro-simulator
6
+ Author: Moha-Master
7
+ Author-email: hongkongreporter@outlook.com
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: description
24
+ Dynamic: description-content-type
25
+ Dynamic: home-page
26
+ Dynamic: requires-python
27
+ Dynamic: summary
28
+
29
+ # Neuro-Simulator 服务端
30
+
31
+ *关注Vedal喵,关注Vedal谢谢喵*
32
+
33
+ *本临时README由AI自动生成*
34
+
35
+ 这是 Neuro Simulator 的后端服务,基于 Python 和 FastAPI 构建,负责处理直播逻辑、AI 交互、TTS 合成等核心功能。
36
+
37
+ ## 功能特性
38
+
39
+ - **多 LLM 支持**:支持 Gemini 和 OpenAI API,用于生成观众聊天内容
40
+ - **配置管理**:支持通过 API 动态修改和热重载配置
41
+ - **外部控制**:完全使用外部API端点操控服务端运行
42
+
43
+ ## 目录结构
44
+
45
+ ```
46
+ neuro_simulator/
47
+ ├── main.py # 应用入口和核心逻辑
48
+ ├── config.py # 配置管理模块
49
+ ├── letta.py # Letta Agent 集成
50
+ ├── chatbot.py # 观众聊天生成器
51
+ ├── audio_synthesis.py # 音频合成模块
52
+ ├── stream_chat.py # 聊天消息处理
53
+ ├── stream_manager.py # 直播管理器
54
+ ├── websocket_manager.py # WebSocket 连接管理
55
+ ├── process_manager.py # 进程管理器
56
+ ├── shared_state.py # 全局状态管理
57
+ ├── log_handler.py # 日志处理模块
58
+ ├── requirements.txt # Python 依赖列表
59
+ ├── setup.py # Python 包安装配置
60
+ ├── cli.py # 命令行启动脚本
61
+ ├── settings.yaml.example # 自带的备用配置模板
62
+ └── media/ # 自带的备用媒体文件
63
+    └── neuro_start.mp4 # 用来计算Start Soon长度,仅读取时长
64
+ ```
65
+
66
+ ```
67
+ working_dir_example/ # 工作目录结构
68
+ ├── media/ # 媒体文件夹,如缺失会使用自带资源覆盖
69
+ │   └── neuro_start.mp4 # 用来计算Start Soon长度,仅读取时长
70
+ ├── settings.yaml # 由用户手工创建的配置文件
71
+ └── settings.yaml.example # 自动生成的配置文件模板,必须手动重命名和填写
72
+ ```
73
+
74
+ ## 安装与配置
75
+
76
+ 0. **配置设置**
77
+ 复制一份 `working_dir_example` 到你想要的位置,作为配置文件目录
78
+ 然后进入配置文件目录,复制 `settings.yaml.example` 到 `settings.yaml`
79
+ 编辑 `settings.yaml` 文件,填入必要的 API 密钥和配置项:
80
+ - Letta Token 和 Agent ID
81
+ - Gemini/OpenAI API Key
82
+ - Azure TTS Key 和 Region
83
+ 可以执行替换media/neuro_start.mp4为其它视频文件,但记得手动替换client中的同名文件
84
+
85
+ ### 方法一:使用 pip 安装
86
+
87
+ 1. **从云端安装PyPi包,适合直接使用**
88
+ ```bash
89
+ python3 -m venv venv
90
+ # Windows
91
+ venv/Scripts/pip install neuro-simulator
92
+ # macOS/Linux
93
+ venv/bin/pip install neuro-simulator
94
+ ```
95
+
96
+ **从本地安装PyPi包,适合二次开发**
97
+ ```bash
98
+ python3 -m venv venv
99
+ #Windows
100
+ venv/Scripts/pip install -e .
101
+ # macOS/Linux
102
+ venv/bin/pip install -e .
103
+ ```
104
+
105
+ 2. **运行服务**
106
+ ```bash
107
+ # 使用默认配置 (~/.config/neuro-simulator/)
108
+ neuro
109
+
110
+ # 指定工作目录
111
+ neuro -D /path/to/your/config
112
+
113
+ # 指定主机和端口
114
+ neuro -H 0.0.0.0 -P 8080
115
+
116
+ # 组合使用
117
+ neuro -D /path/to/your/config -H 0.0.0.0 -P 8080
118
+ ```
119
+
120
+ ### 方法二:传统方式运行
121
+
122
+ 1. **创建并激活虚拟环境**
123
+ ```bash
124
+ python -m venv venv
125
+ # Windows
126
+ venv\Scripts\activate
127
+ # macOS/Linux
128
+ source venv/bin/activate
129
+ ```
130
+
131
+ 2. **安装依赖**
132
+ ```bash
133
+ pip install -r requirements.txt
134
+ ```
135
+
136
+ 3. **启动服务**
137
+ ```bash
138
+ uvicorn main:app --host 127.0.0.1 --port 8000
139
+ ```
140
+
141
+ 服务默认运行在 `http://127.0.0.1:8000`。
142
+
143
+ ## API 接口
144
+
145
+ 后端提供丰富的 API 接口用于控制和管理:
146
+
147
+ - `/api/stream/*` - 直播控制接口(启动/停止/重启/状态)
148
+ - `/api/configs/*` - 配置管理接口(获取/更新/重载配置)
149
+ - `api_keys` `server` 等敏感配置项无法从接口获取和修改。
150
+ - `/api/logs` - 日志获取接口
151
+ - `/api/tts/synthesize` - TTS 合成接口
152
+ - `/api/system/health` - 健康检查接口
153
+ - `/ws/stream` - 直播内容 WebSocket 接口
154
+ - `/ws/logs` - 日志流 WebSocket 接口
155
+
156
+ 详细接口说明可通过 `http://127.0.0.1:8000/docs` 访问 API 文档查看。
157
+
158
+ ## 配置说明
159
+
160
+ 配置文件 `settings.yaml` 包含以下主要配置项:
161
+
162
+ - `api_keys` - 各种服务的 API 密钥
163
+ - `stream_metadata` - 直播元数据(标题、分类、标签等)
164
+ - `neuro_behavior` - Neuro 行为设置
165
+ - `audience_simulation` - 观众模拟设置
166
+ - `tts` - TTS 语音合成设置
167
+ - `performance` - 性能相关设置
168
+ - `server` - 服务器设置(主机、端口、CORS 等)
169
+
170
+ ## 安全说明
171
+
172
+ 1. 通过 `panel_password` 配置项可以设置控制面板访问密码
173
+ 2. 敏感配置项(如 API 密钥)不会通过 API 接口暴露
174
+ 3. 支持 CORS,但仅允许预配置的来源访问
175
+
176
+ ## 故障排除
177
+
178
+ - 确保所有必需的 API 密钥都已正确配置
179
+ - 检查网络连接是否正常
180
+ - 查看日志文件获取错误信息
181
+ - 确保端口未被其他程序占用
@@ -0,0 +1,20 @@
1
+ neuro_simulator/__init__.py,sha256=JJWUFh_lBowSfGMhmC9zixE70cB7GG1pTbjGY4Kg3mU,29
2
+ neuro_simulator/audio_synthesis.py,sha256=fwS0car42-aheCFVQDgRpUTnqLv4DU9Re66PCa6zTBM,2938
3
+ neuro_simulator/chatbot.py,sha256=qQamPO5QTPwV1avNXrzjZpiJlWN3X_6vxSZPSA17jb0,5152
4
+ neuro_simulator/cli.py,sha256=uMN9N6n69ceBRwACQ67-reDTB4mEY7RTgBD2choO_BU,6002
5
+ neuro_simulator/config.py,sha256=rnosgBCJ2waKB7F63paT0aRnWsda_bvmyHdzOTvIW_0,9625
6
+ neuro_simulator/letta.py,sha256=F0PbnL9vmcznxwkTQKiK9PoGsp42FbCpSbiDuFdjUWo,6475
7
+ neuro_simulator/log_handler.py,sha256=JlCtJ7wJ0pruVGVO5u-kz-F5uaYhlBl4H5xoGUFhT18,1079
8
+ neuro_simulator/main.py,sha256=NlYM9OSv9sxmDIP7KEPOFyDRsU8VlQ2ngqNoNMo9CAE,22043
9
+ neuro_simulator/process_manager.py,sha256=KqW11PRJR5e4RSBytaZdkgbd3wxRtWqlz6D0TA4oR1s,2492
10
+ neuro_simulator/settings.yaml.example,sha256=uywVEnoFZGZ4g6qdp616Qoi78F2AF21rSG99gtFiY-s,6003
11
+ neuro_simulator/shared_state.py,sha256=cvYg8vGrkuDmb0e-4J1xvIjXVwspRisuxQaIR9YgsyQ,459
12
+ neuro_simulator/stream_chat.py,sha256=X655rrOW8oQ77qAFK-dQDhHT3bYiE9w44a9Na_ikM2w,997
13
+ neuro_simulator/stream_manager.py,sha256=vA88HQGgYguFb3_GUDSY-FpTG0rsjt8J-JFtMoCWWCo,6720
14
+ neuro_simulator/websocket_manager.py,sha256=a9mMAN7xmgK2w9tVDOOzy4DuWSwdAPatSp6bW9fhE3I,2183
15
+ neuro_simulator/media/neuro_start.mp4,sha256=xCLnNzv4THnzRYwkdV6EiqXc-XtFd867R2ZVLDvNp0Y,8226418
16
+ neuro_simulator-0.0.1.dist-info/METADATA,sha256=jwCS_r3EoIzO7LXc9crNmM_ftPFjbss_h16VjbGNEIg,5836
17
+ neuro_simulator-0.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ neuro_simulator-0.0.1.dist-info/entry_points.txt,sha256=qVd5ypnRRgU8Cw7rWfZ7o0OXyS9P9hgY-cRoN_mgz9g,51
19
+ neuro_simulator-0.0.1.dist-info/top_level.txt,sha256=V8awSKpcrFnjJDiJxSfy7jtOrnuE2BgAR9hLmfMDWK8,16
20
+ neuro_simulator-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ neuro = neuro_simulator.cli:main
@@ -0,0 +1 @@
1
+ neuro_simulator