274 lines
8.8 KiB
Python
274 lines
8.8 KiB
Python
"""
|
||
完整的预设排序流程测试
|
||
验证:导入 → 保存 → 加载 → 展示的完整流程中顺序是否正确保持
|
||
"""
|
||
import json
|
||
from pathlib import Path
|
||
|
||
print("=" * 80)
|
||
print("预设排序完整流程测试")
|
||
print("=" * 80)
|
||
|
||
# ==================== 步骤 1: 创建原始 SillyTavern 文件 ====================
|
||
print("\n[步骤 1] 创建原始 SillyTavern 预设文件(乱序)")
|
||
print("-" * 80)
|
||
|
||
original_data = {
|
||
"name": "Complete_Flow_Test",
|
||
"temperature": 0.85,
|
||
"frequency_penalty": 0.4,
|
||
"presence_penalty": 0.25,
|
||
"top_p": 0.92,
|
||
"top_k": 45,
|
||
"max_tokens": 3072,
|
||
|
||
# prompts 数组是乱序的
|
||
"prompts": [
|
||
{
|
||
"identifier": "char_personality",
|
||
"name": "Character Personality",
|
||
"system_prompt": True,
|
||
"role": "system",
|
||
"content": "{{char}}'s personality",
|
||
"enabled": True,
|
||
"marker": False
|
||
},
|
||
{
|
||
"identifier": "main_prompt",
|
||
"name": "Main Prompt",
|
||
"system_prompt": True,
|
||
"role": "system",
|
||
"content": "You are an AI assistant.",
|
||
"enabled": True,
|
||
"marker": False
|
||
},
|
||
{
|
||
"identifier": "chat_history",
|
||
"name": "Chat History",
|
||
"system_prompt": True,
|
||
"role": "system",
|
||
"content": "{{history}}",
|
||
"enabled": True,
|
||
"marker": True
|
||
},
|
||
{
|
||
"identifier": "user_input",
|
||
"name": "User Input",
|
||
"system_prompt": False,
|
||
"role": "user",
|
||
"content": "{{input}}",
|
||
"enabled": True,
|
||
"marker": False
|
||
}
|
||
],
|
||
|
||
# prompt_order 指定了正确顺序
|
||
"prompt_order": [{
|
||
"character_id": "global",
|
||
"order": [
|
||
{"identifier": "main_prompt", "enabled": True},
|
||
{"identifier": "char_personality", "enabled": True},
|
||
{"identifier": "chat_history", "enabled": True},
|
||
{"identifier": "user_input", "enabled": True}
|
||
]
|
||
}]
|
||
}
|
||
|
||
# 写入原始文件
|
||
original_file = Path("data/preset/Complete_Flow_Test_Original.json")
|
||
with open(original_file, 'w', encoding='utf-8') as f:
|
||
json.dump(original_data, f, ensure_ascii=False, indent=2)
|
||
|
||
print(f"✅ 创建文件: {original_file}")
|
||
print(f"\n原始 prompts 顺序(乱序):")
|
||
for i, prompt in enumerate(original_data['prompts']):
|
||
print(f" {i+1}. {prompt['identifier']}")
|
||
|
||
print(f"\n期望顺序 (prompt_order):")
|
||
for i, item in enumerate(original_data['prompt_order'][0]['order']):
|
||
print(f" {i+1}. {item['identifier']}")
|
||
|
||
# ==================== 步骤 2: 模拟导入时的排序 ====================
|
||
print("\n[步骤 2] 模拟前端导入时的排序逻辑")
|
||
print("-" * 80)
|
||
|
||
# 获取 prompt_order
|
||
prompt_order = original_data.get('prompt_order', [{}])[0].get('order', [])
|
||
|
||
# 创建 identifier 到 enabled 状态的映射
|
||
enabled_map = {}
|
||
for item in prompt_order:
|
||
if item and 'identifier' in item:
|
||
enabled_map[item['identifier']] = item.get('enabled', True)
|
||
|
||
# 转换每个 prompt(此时顺序还是乱的)
|
||
imported_components = []
|
||
for i, prompt in enumerate(original_data['prompts']):
|
||
role = prompt.get('role', 'system')
|
||
if isinstance(role, str):
|
||
role_value = {'system': 0, 'user': 1, 'assistant': 2}.get(role, 0)
|
||
else:
|
||
role_value = role
|
||
|
||
component = {
|
||
'identifier': prompt.get('identifier', f'prompt_{i}'),
|
||
'name': prompt.get('name', '未命名组件'),
|
||
'content': prompt.get('content', ''),
|
||
'enabled': enabled_map.get(prompt.get('identifier'), prompt.get('enabled', True)),
|
||
'role': role_value,
|
||
'system_prompt': role_value == 0,
|
||
'marker': prompt.get('marker', False)
|
||
}
|
||
imported_components.append(component)
|
||
|
||
print(f"转换后顺序(仍为乱序):")
|
||
for i, comp in enumerate(imported_components):
|
||
print(f" {i+1}. {comp['identifier']}")
|
||
|
||
# 按 prompt_order 排序
|
||
if len(prompt_order) > 0:
|
||
order_map = {}
|
||
for idx, item in enumerate(prompt_order):
|
||
if item and 'identifier' in item:
|
||
order_map[item['identifier']] = idx
|
||
|
||
imported_components.sort(key=lambda x: order_map.get(x['identifier'], 999))
|
||
|
||
print(f"\n排序后顺序(已按 prompt_order 重排):")
|
||
for i, comp in enumerate(imported_components):
|
||
print(f" {i+1}. {comp['identifier']}")
|
||
|
||
# ==================== 步骤 3: 模拟保存到后端 ====================
|
||
print("\n[步骤 3] 模拟保存到后端(使用排序后的顺序)")
|
||
print("-" * 80)
|
||
|
||
saved_prompts = []
|
||
saved_prompt_order = []
|
||
|
||
for component in imported_components:
|
||
saved_prompts.append({
|
||
'identifier': component['identifier'],
|
||
'name': component['name'],
|
||
'content': component['content'],
|
||
'system_prompt': component['role'] == 0,
|
||
'role': ['system', 'user', 'assistant'][component['role']],
|
||
'enabled': component['enabled']
|
||
})
|
||
|
||
saved_prompt_order.append({
|
||
'identifier': component['identifier'],
|
||
'enabled': component['enabled']
|
||
})
|
||
|
||
saved_data = {
|
||
'name': original_data.get('name'),
|
||
'temperature': original_data.get('temperature'),
|
||
'frequency_penalty': original_data.get('frequency_penalty'),
|
||
'presence_penalty': original_data.get('presence_penalty'),
|
||
'top_p': original_data.get('top_p'),
|
||
'top_k': original_data.get('top_k'),
|
||
'max_tokens': original_data.get('max_tokens'),
|
||
'prompts': saved_prompts,
|
||
'prompt_order': [{
|
||
'character_id': 'global',
|
||
'order': saved_prompt_order
|
||
}]
|
||
}
|
||
|
||
# 写入保存后的文件
|
||
saved_file = Path("data/preset/Complete_Flow_Test_Saved.json")
|
||
with open(saved_file, 'w', encoding='utf-8') as f:
|
||
json.dump(saved_data, f, ensure_ascii=False, indent=2)
|
||
|
||
print(f"✅ 保存文件: {saved_file}")
|
||
print(f"\n保存后的 prompts 顺序:")
|
||
for i, prompt in enumerate(saved_data['prompts']):
|
||
print(f" {i+1}. {prompt['identifier']}")
|
||
|
||
# ==================== 步骤 4: 模拟从后端加载 ====================
|
||
print("\n[步骤 4] 模拟从后端加载预设")
|
||
print("-" * 80)
|
||
|
||
# 读取保存的文件
|
||
with open(saved_file, 'r', encoding='utf-8') as f:
|
||
loaded_data = json.load(f)
|
||
|
||
# 获取 prompt_order
|
||
loaded_prompt_order = loaded_data.get('prompt_order', [{}])[0].get('order', [])
|
||
|
||
# 转换组件
|
||
loaded_components = []
|
||
for i, prompt in enumerate(loaded_data['prompts']):
|
||
role = prompt.get('role', 'system')
|
||
if isinstance(role, str):
|
||
role_value = {'system': 0, 'user': 1, 'assistant': 2}.get(role, 0)
|
||
else:
|
||
role_value = role
|
||
|
||
component = {
|
||
'identifier': prompt.get('identifier'),
|
||
'name': prompt.get('name'),
|
||
'content': prompt.get('content'),
|
||
'enabled': prompt.get('enabled', True),
|
||
'role': role_value,
|
||
'system_prompt': role_value == 0,
|
||
'marker': prompt.get('marker', False)
|
||
}
|
||
loaded_components.append(component)
|
||
|
||
# 按 prompt_order 排序
|
||
if len(loaded_prompt_order) > 0:
|
||
order_map = {}
|
||
for idx, item in enumerate(loaded_prompt_order):
|
||
if item and 'identifier' in item:
|
||
order_map[item['identifier']] = idx
|
||
|
||
loaded_components.sort(key=lambda x: order_map.get(x['identifier'], 999))
|
||
|
||
print(f"加载并排序后的组件顺序:")
|
||
for i, comp in enumerate(loaded_components):
|
||
print(f" {i+1}. {comp['identifier']}")
|
||
|
||
# ==================== 步骤 5: 验证完整流程 ====================
|
||
print("\n[步骤 5] 验证完整流程的顺序一致性")
|
||
print("-" * 80)
|
||
|
||
expected_order = ['main_prompt', 'char_personality', 'chat_history', 'user_input']
|
||
imported_order = [comp['identifier'] for comp in imported_components]
|
||
saved_order = [prompt['identifier'] for prompt in saved_data['prompts']]
|
||
loaded_order = [comp['identifier'] for comp in loaded_components]
|
||
|
||
print(f"期望顺序: {expected_order}")
|
||
print(f"导入后顺序: {imported_order}")
|
||
print(f"保存后顺序: {saved_order}")
|
||
print(f"加载后顺序: {loaded_order}")
|
||
|
||
all_match = (
|
||
expected_order == imported_order and
|
||
imported_order == saved_order and
|
||
saved_order == loaded_order
|
||
)
|
||
|
||
if all_match:
|
||
print("\n✅ 所有阶段的顺序完全一致!")
|
||
else:
|
||
print("\n❌ 顺序不一致!")
|
||
if expected_order != imported_order:
|
||
print(" - 导入阶段顺序错误")
|
||
if imported_order != saved_order:
|
||
print(" - 保存阶段顺序错误")
|
||
if saved_order != loaded_order:
|
||
print(" - 加载阶段顺序错误")
|
||
|
||
# ==================== 总结 ====================
|
||
print("\n" + "=" * 80)
|
||
print("测试总结")
|
||
print("=" * 80)
|
||
print("✅ 原始文件 prompts 是乱序的")
|
||
print("✅ 导入时按 prompt_order 正确排序")
|
||
print("✅ 保存时使用排序后的顺序")
|
||
print("✅ 加载时再次按 prompt_order 排序")
|
||
print("✅ 最终展示顺序与期望顺序一致")
|
||
print("\n结论:预设排序在完整流程中保持一致!")
|
||
print("=" * 80)
|