Skip to content

Commit ba7ecff

Browse files
committed
Fixed minor issues with l2d saving. Prepare for v0.3.2 release.
1 parent 8c3a7ab commit ba7ecff

6 files changed

Lines changed: 82 additions & 85 deletions

File tree

config/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ def get_character_data():
107107
AUDIO_API_KEY = OPENROUTER_API_KEY = ASSIST_API_KEY_OPENAI
108108
elif core_cfg['assistApi'] == 'glm':
109109
OPENROUTER_URL = "https://open.bigmodel.cn/api/paas/v4"
110-
SUMMARY_MODEL = "glm-4-air-250414" # glm-4-flash-250414 <-永久免费模型
110+
SUMMARY_MODEL = "glm-4.5-flash" # <-永久免费模型
111111
CORRECTION_MODEL = "glm-z1-air" # glm-z1-flash <-永久免费模型
112-
EMOTION_MODEL = "glm-4-flash-250414"
112+
EMOTION_MODEL = "glm-4.5-flash"
113113
AUDIO_API_KEY = OPENROUTER_API_KEY = ASSIST_API_KEY_GLM
114114
else:
115115
logger.error("💥 Unknown assistApi: " + core_cfg['assistApi'])

main_server.py

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,50 +1005,74 @@ async def live2d_emotion_manager(request: Request):
10051005
logger.error(f"加载Live2D情感映射管理器页面失败: {e}")
10061006
return JSONResponse(status_code=500, content={"error": str(e)})
10071007

1008-
@app.get('/api/live2d/emotion_mapping')
1009-
async def get_emotion_mapping():
1008+
@app.get('/api/live2d/emotion_mapping/{model_name}')
1009+
async def get_emotion_mapping(model_name: str):
10101010
"""获取情绪映射配置"""
10111011
try:
1012-
mapping_file_path = os.path.join('config', 'live2d_emotion_mapping.json')
1012+
# 在模型目录中查找.model3.json文件
1013+
model_dir = os.path.join('static', model_name)
1014+
if not os.path.exists(model_dir):
1015+
return JSONResponse(status_code=404, content={"success": False, "error": "模型目录不存在"})
10131016

1014-
if not os.path.exists(mapping_file_path):
1015-
# 如果文件不存在,返回空配置
1016-
return {"success": True, "config": {}}
1017+
# 查找.model3.json文件
1018+
model_json_path = None
1019+
for file in os.listdir(model_dir):
1020+
if file.endswith('.model3.json'):
1021+
model_json_path = os.path.join(model_dir, file)
1022+
break
10171023

1018-
with open(mapping_file_path, 'r', encoding='utf-8') as f:
1024+
if not model_json_path or not os.path.exists(model_json_path):
1025+
return JSONResponse(status_code=404, content={"success": False, "error": "模型配置文件不存在"})
1026+
1027+
with open(model_json_path, 'r', encoding='utf-8') as f:
10191028
config_data = json.load(f)
1029+
1030+
emotion_mapping = config_data.get('EmotionMapping', {})
10201031

1021-
return {"success": True, "config": config_data}
1032+
return {"success": True, "config": emotion_mapping}
10221033
except Exception as e:
10231034
logger.error(f"获取情绪映射配置失败: {e}")
10241035
return JSONResponse(status_code=500, content={"success": False, "error": str(e)})
10251036

1026-
@app.post('/api/live2d/emotion_mapping')
1027-
async def update_emotion_mapping(request: Request):
1037+
@app.post('/api/live2d/emotion_mapping/{model_name}')
1038+
async def update_emotion_mapping(model_name: str, request: Request):
10281039
"""更新情绪映射配置"""
10291040
try:
10301041
data = await request.json()
10311042

10321043
if not data:
10331044
return JSONResponse(status_code=400, content={"success": False, "error": "无效的数据"})
1045+
1046+
# 在模型目录中查找.model3.json文件
1047+
model_dir = os.path.join('static', model_name)
1048+
if not os.path.exists(model_dir):
1049+
return JSONResponse(status_code=404, content={"success": False, "error": "模型目录不存在"})
10341050

1035-
mapping_file_path = os.path.join('config', 'live2d_emotion_mapping.json')
1051+
# 查找.model3.json文件
1052+
model_json_path = None
1053+
for file in os.listdir(model_dir):
1054+
if file.endswith('.model3.json'):
1055+
model_json_path = os.path.join(model_dir, file)
1056+
break
10361057

1037-
# 确保config目录存在
1038-
os.makedirs(os.path.dirname(mapping_file_path), exist_ok=True)
1058+
if not model_json_path or not os.path.exists(model_json_path):
1059+
return JSONResponse(status_code=404, content={"success": False, "error": "模型配置文件不存在"})
1060+
1061+
with open(model_json_path, 'r', encoding='utf-8') as f:
1062+
config_data = json.load(f)
1063+
1064+
# 添加或更新 EmotionMapping
1065+
config_data['EmotionMapping'] = data
10391066

10401067
# 保存配置到文件
1041-
with open(mapping_file_path, 'w', encoding='utf-8') as f:
1042-
json.dump(data, f, ensure_ascii=False, indent=2)
1068+
with open(model_json_path, 'w', encoding='utf-8') as f:
1069+
json.dump(config_data, f, ensure_ascii=False, indent=2)
10431070

1044-
logger.info("情绪映射配置已更新")
1071+
logger.info(f"模型 {model_name} 的情绪映射配置已更新")
10451072
return {"success": True, "message": "情绪映射配置已保存"}
10461073
except Exception as e:
10471074
logger.error(f"更新情绪映射配置失败: {e}")
10481075
return JSONResponse(status_code=500, content={"success": False, "error": str(e)})
1049-
except Exception as e:
1050-
logger.error(f"加载Live2D情感映射管理器页面失败: {e}")
1051-
return HTMLResponse(content=f"<h1>页面加载失败: {str(e)}</h1>", status_code=500)
10521076

10531077
@app.post('/api/memory/recent_file/save')
10541078
async def save_recent_file(request: Request):

memory/semantic.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from langchain_chroma import Chroma
1+
# from langchain_chroma import Chroma
2+
# ↑ 这个库引入了Chroma和onnx依赖,显著增大了一键包体积,暂时注释掉
23
from typing import List
34
from langchain_core.documents import Document
45
from datetime import datetime
@@ -75,11 +76,12 @@ def rerank_results(self, query, results: List[Document], k=5) -> List[Document]:
7576
class SemanticMemoryOriginal:
7677
def __init__(self, persist_directory, lanlan_name, name_mapping):
7778
self.embeddings = OpenAIEmbeddings(base_url=OPENROUTER_URL, model=SEMANTIC_MODEL, api_key=OPENROUTER_API_KEY)
78-
self.vectorstore = Chroma(
79-
collection_name="Origin",
80-
persist_directory=persist_directory[lanlan_name],
81-
embedding_function=self.embeddings
82-
)
79+
# self.vectorstore = Chroma(
80+
# collection_name="Origin",
81+
# persist_directory=persist_directory[lanlan_name],
82+
# embedding_function=self.embeddings
83+
# )
84+
self.vectorstore = None
8385
self.lanlan_name = lanlan_name
8486
self.name_mapping = name_mapping
8587

@@ -117,11 +119,12 @@ def __init__(self, persist_directory, lanlan_name, recent_history_manager: Compr
117119
self.lanlan_name = lanlan_name
118120
self.name_mapping = name_mapping
119121
self.embeddings = OpenAIEmbeddings(base_url=OPENROUTER_URL, model=SEMANTIC_MODEL, api_key=OPENROUTER_API_KEY)
120-
self.vectorstore = Chroma(
121-
collection_name="Compressed",
122-
persist_directory=persist_directory[lanlan_name],
123-
embedding_function=self.embeddings
124-
)
122+
self.vectorstore = None
123+
# self.vectorstore = Chroma(
124+
# collection_name="Compressed",
125+
# persist_directory=persist_directory[lanlan_name],
126+
# embedding_function=self.embeddings
127+
# )
125128
self.recent_history_manager = recent_history_manager
126129

127130
def store_compressed_summary(self, event_id, messages):

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ pyaudio~=0.2.14
77
websocket-client~=1.8.0
88
langchain
99
langchain-openai
10-
langchain_chroma
1110
langchain_community
1211
jinja2
1312
dashscope

static/live2d.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,12 @@ class Live2DManager {
277277

278278
const motions = this.emotionMapping.Motions[emotion];
279279
if (!motions || motions.length === 0) {
280-
console.warn(`未找到情感 ${emotion} 对应的动作`);
280+
console.warn(`未找到情感 ${emotion} 对应的动作,但将保持表情`);
281+
// 如果没有找到对应的motion,设置一个短定时器以确保expression能够显示
282+
// 并且不设置回调来清除效果,让表情一直持续
283+
this.motionTimer = setTimeout(() => {
284+
this.motionTimer = null;
285+
}, 500); // 500ms应该足够让expression稳定显示
281286
return;
282287
}
283288

templates/live2d_emotion_manager.html

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,6 @@ <h4>模型信息</h4>
462462
// 页面加载时初始化
463463
document.addEventListener('DOMContentLoaded', function() {
464464
loadAvailableModels();
465-
loadEmotionMappingConfig();
466465
});
467466

468467
// 全局错误处理
@@ -473,25 +472,6 @@ <h4>模型信息</h4>
473472

474473

475474

476-
// 加载情绪映射配置
477-
async function loadEmotionMappingConfig() {
478-
try {
479-
const response = await fetch('/api/live2d/emotion_mapping');
480-
const data = await response.json();
481-
482-
if (data.success) {
483-
emotionMappingConfig = data.config || {};
484-
showStatus('情绪映射配置加载成功', 'success');
485-
} else {
486-
emotionMappingConfig = {};
487-
showStatus('加载情绪映射配置失败: ' + data.error, 'error');
488-
}
489-
} catch (error) {
490-
emotionMappingConfig = {};
491-
showStatus('加载情绪映射配置时出错: ' + error.message, 'error');
492-
}
493-
}
494-
495475
// 加载可用的模型列表
496476
async function loadAvailableModels() {
497477
try {
@@ -525,8 +505,7 @@ <h4>模型信息</h4>
525505
});
526506
}
527507

528-
// 加载模型映射配置
529-
async function loadModelMapping() {
508+
async function loadModelMapping() {
530509
const modelSelect = document.getElementById('model-select');
531510
const selectedModel = modelSelect.value;
532511

@@ -544,13 +523,15 @@ <h4>模型信息</h4>
544523
statusText.textContent = '正在加载配置和模型文件...';
545524
statusDot.className = 'status-dot info';
546525

547-
const [configResponse, filesResponse] = await Promise.all([
526+
const [configResponse, filesResponse, emotionMappingResponse] = await Promise.all([
548527
fetch(`/api/live2d/model_config/${selectedModel}`),
549-
fetch(`/api/live2d/model_files/${selectedModel}`)
528+
fetch(`/api/live2d/model_files/${selectedModel}`),
529+
fetch(`/api/live2d/emotion_mapping/${selectedModel}`)
550530
]);
551531

552532
const configData = await configResponse.json();
553533
const filesData = await filesResponse.json();
534+
const emotionMappingData = await emotionMappingResponse.json();
554535

555536
if (configData.success) {
556537
currentModelConfig = configData.config;
@@ -578,6 +559,13 @@ <h4>模型信息</h4>
578559
statusIndicator.classList.add('hidden');
579560
}, 3000);
580561
}
562+
563+
if (emotionMappingData.success) {
564+
emotionMappingConfig[currentModel] = emotionMappingData.config || { motions: {}, expressions: {} };
565+
} else {
566+
emotionMappingConfig[currentModel] = { motions: {}, expressions: {} };
567+
showStatus('加载情绪映射配置失败: ' + emotionMappingData.error, 'error');
568+
}
581569

582570
// 自动为没有映射的模型添加映射
583571
autoAddModelMapping(selectedModel);
@@ -781,35 +769,21 @@ <h4>表情文件 (${expressions.length})</h4>
781769
try {
782770
showStatus('正在保存配置...', 'info');
783771

784-
// 保存模型配置
785-
const configResponse = await fetch(`/api/live2d/model_config/${currentModel}`, {
786-
method: 'POST',
787-
headers: {
788-
'Content-Type': 'application/json',
789-
},
790-
body: JSON.stringify(currentModelConfig)
791-
});
792-
793-
const configData = await configResponse.json();
794-
795772
// 保存情绪映射配置
796-
const emotionResponse = await fetch('/api/live2d/emotion_mapping', {
773+
const emotionResponse = await fetch(`/api/live2d/emotion_mapping/${currentModel}`, {
797774
method: 'POST',
798775
headers: {
799776
'Content-Type': 'application/json',
800777
},
801-
body: JSON.stringify(emotionMappingConfig)
778+
body: JSON.stringify(emotionMappingConfig[currentModel])
802779
});
803780

804781
const emotionData = await emotionResponse.json();
805782

806-
if (configData.success && emotionData.success) {
783+
if (emotionData.success) {
807784
showStatus('配置保存成功', 'success');
808785
} else {
809-
const errors = [];
810-
if (!configData.success) errors.push('模型配置: ' + configData.error);
811-
if (!emotionData.success) errors.push('情绪映射: ' + emotionData.error);
812-
showStatus('保存配置失败: ' + errors.join(', '), 'error');
786+
showStatus('保存配置失败: ' + emotionData.error, 'error');
813787
}
814788
} catch (error) {
815789
showStatus('保存配置时出错: ' + error.message, 'error');
@@ -843,15 +817,7 @@ <h4>表情文件 (${expressions.length})</h4>
843817
const totalExpressionFiles = currentModelFiles.expression_files.length;
844818
status.textContent = `动作文件: ${totalMotionFiles} | 表情文件: ${totalExpressionFiles}`;
845819
}
846-
847-
848-
849-
850-
851-
852-
853-
854-
820+
855821
// 显示toast通知
856822
function showStatus(message, type) {
857823
const toastContainer = document.getElementById('toast-container');

0 commit comments

Comments
 (0)