File size: 4,907 Bytes
09a3648
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import os
import sys
from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS

# 引入本地化 Skill 路径 (已从 Global_Shensist_Skills 迁移)
sys.path.append(os.path.abspath("Global_Shensist_Skills"))

try:
    import shensist_voice
    import shensist_brain
except ImportError:
    print("⚠️ 警告: 未找到 Global_Shensist_Skills,正在尝试从上级目录加载...")
    sys.path.append(os.path.abspath("../Global_Shensist_Skills"))
    import shensist_voice
    import shensist_brain

app = Flask(__name__, static_folder=".")
CORS(app)

# 配置文件
VOICE_ASSETS = "./assets/voices"
os.makedirs(VOICE_ASSETS, exist_ok=True)

# 初始化脑库 (Shensist Brain)
brain = None
if 'shensist_brain' in globals():
    try:
        # 允许加载 user 提供的 assets 中的 .txt 文件
        brain = shensist_brain.XiaoqingBrain(assets_dir="./assets")
        print(f"🧠 [Shensist-Brain] 成功加载记忆块: {len(brain.memory)}")
    except Exception as e:
        print(f"❌ [Shensist-Brain] 记忆加载失败: {e}")

@app.route("/chat", methods=["POST"])
def chat():
    try:
        data = request.json
        message = data.get("message", "")
        character_id = data.get("character_id", "default")
        print(f"📡 [Chat Request] Char: {character_id} | Msg: {message}")
        reply = None
        
        # 1. 引导到灵境档案
        archive_keywords = ["小说", "歌词", "剧场", "视频", "档案", "库"]
        if any(k in message for k in archive_keywords):
            reply = "正在为您开启‘灵境档案’。三千年的沉淀已化作文字,请在右侧面板尽情阅读。"
        
        # 2. 身份/姓名识别优先级 (如果是问“你是谁”,优先进入人格模板而不是知识库)
        is_identity_query = any(k in message for k in ["你是谁", "你是哪位", "名字", "叫什么", "是谁", "身份", "你是小智", "你是小青", "你是恶霸"])
        
        # 3. 尝试从脑库匹配知识
        if not reply and not is_identity_query and brain:
            knowledge = brain.query(message, top_k=1)
            if knowledge:
                reply = knowledge[0]
        
        # 3. 动态加载人格宪法 (根据角色 ID)
        if not reply:
            if 'shensist_brain' in globals() and hasattr(shensist_brain, 'generate_response'):
                # 宪法路径映射矩阵
                constituion_map = {
                    "ironviper": "../IronViper_Soul_Agent/IronViper_Constitution.md",
                    "xiaoqing": "../Xiaoqing_Soul_Agent/Xiaoqing_Constitution.md",
                    "male_hero": "../IronViper_Soul_Agent/IronViper_Constitution.md", # 暂时回退
                    "default": "../IronViper_Soul_Agent/IronViper_Constitution.md"
                }
                
                const_path = constituion_map.get(character_id, constituion_map["default"])
                print(f"📖 [Personality] Loading {const_path} for {character_id}")
                
                try:
                    reply = shensist_brain.generate_response(message, const_path, character_id)
                except Exception as brain_err:
                    print(f"🧠 [Brain Error] {brain_err}")
                    reply = f"信号扰动中... 虽然我暂时无法调用 [{character_id}] 的深层逻辑,但我听到了:{message}"
            else:
                reply = f"已收到你的请求:{message}。目前处于 2026 全息互动测试阶段。"

        return jsonify({"message": reply, "character_id": character_id})
    except Exception as e:
        print(f"❌ [Chat Global Error] {e}")
        return jsonify({"message": "音频系统检测到数据流异常,正在重置...", "error": str(e)}), 500

@app.route("/tts", methods=["POST"])
def tts():
    data = request.json
    text = data.get("text", "")
    character_id = data.get("character_id", "default")
    voice = data.get("voice", None)
    
    output_filename = f"voice_{character_id}.mp3"
    output_path = os.path.join(VOICE_ASSETS, output_filename)
    
    if 'shensist_voice' in globals():
        success = shensist_voice.speak(text, character_id, output_path, voice)
        if success:
            return jsonify({"audio_url": f"/assets/voices/{output_filename}"})
    
    return jsonify({"error": "TTS 引擎未激活"}), 500

@app.route("/")
def index():
    return send_from_directory(".", "index.html")

@app.route("/assets/<path:path>")
def send_assets(path):
    return send_from_directory("assets", path)

@app.route("/<path:filename>")
def serve_static(filename):
    return send_from_directory(".", filename)

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 7860))
    print(f"🚀 神思庭 · 全息世界多模态智能体后端已启动: http://localhost:{port}")
    app.run(host='0.0.0.0', port=port)