2025-08-15 17:25:07 +08:00
|
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
'''
|
|
|
|
|
|
双AI角色对话系统主控制程序
|
|
|
|
|
|
完整的工作流程:PDF处理 -> 角色加载 -> RAG对话 -> 历史记录
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
import sys
|
|
|
|
|
|
import shutil
|
|
|
|
|
|
from typing import List, Dict
|
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
|
|
def check_dependencies():
|
|
|
|
|
|
"""检查依赖库"""
|
|
|
|
|
|
missing_deps = []
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
import PyPDF2
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
missing_deps.append("PyPDF2")
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
import pymupdf
|
|
|
|
|
|
print("✓ pymupdf 可用")
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
print("⚠ pymupdf 不可用,将使用 PyPDF2")
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
import sentence_transformers
|
|
|
|
|
|
import faiss
|
|
|
|
|
|
print("✓ 向量化功能可用")
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
print("⚠ 向量化功能不可用,将使用文本匹配")
|
|
|
|
|
|
|
|
|
|
|
|
if missing_deps:
|
|
|
|
|
|
print(f"✗ 缺少依赖库: {', '.join(missing_deps)}")
|
|
|
|
|
|
print("请运行: pip install PyPDF2 sentence-transformers faiss-cpu")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def setup_directories():
|
|
|
|
|
|
"""设置项目目录结构"""
|
|
|
|
|
|
directories = [
|
|
|
|
|
|
"./knowledge_base",
|
|
|
|
|
|
"./characters",
|
|
|
|
|
|
"./worldview",
|
|
|
|
|
|
"./rag_knowledge",
|
|
|
|
|
|
"./conversation_data"
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
for dir_path in directories:
|
|
|
|
|
|
os.makedirs(dir_path, exist_ok=True)
|
|
|
|
|
|
print(f"✓ 目录就绪: {dir_path}")
|
|
|
|
|
|
|
|
|
|
|
|
def copy_demo_files():
|
|
|
|
|
|
"""复制演示文档到知识库目录"""
|
|
|
|
|
|
file_mappings = [
|
|
|
|
|
|
("./worldview/worldview_template_coc.json", "./knowledge_base/worldview_template_coc.json"),
|
|
|
|
|
|
("./characters/character_template_detective.json", "./knowledge_base/character_template_detective.json"),
|
|
|
|
|
|
("./characters/character_template_professor.json", "./knowledge_base/character_template_professor.json")
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
for source, target in file_mappings:
|
|
|
|
|
|
if os.path.exists(source):
|
|
|
|
|
|
shutil.copy2(source, target)
|
|
|
|
|
|
print(f"✓ 复制文档: {os.path.basename(target)}")
|
|
|
|
|
|
|
|
|
|
|
|
def process_pdf_workflow():
|
|
|
|
|
|
"""PDF处理工作流"""
|
|
|
|
|
|
print("\n" + "="*60)
|
|
|
|
|
|
print("PDF世界观文档处理")
|
|
|
|
|
|
print("="*60)
|
|
|
|
|
|
|
|
|
|
|
|
from pdf_to_rag_processor import PDFToRAGProcessor
|
|
|
|
|
|
|
|
|
|
|
|
pdf_path = input("请输入PDF文件路径 (例: ./coc.pdf): ").strip()
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(pdf_path):
|
|
|
|
|
|
print(f"✗ 文件不存在: {pdf_path}")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
processor = PDFToRAGProcessor()
|
|
|
|
|
|
result = processor.process_pdf_to_rag(pdf_path, "./rag_knowledge")
|
|
|
|
|
|
|
|
|
|
|
|
print(f"\n✓ PDF处理完成!")
|
|
|
|
|
|
print(f" - 文档块数: {result['chunks_count']}")
|
|
|
|
|
|
print(f" - 概念数: {result['concepts_count']}")
|
|
|
|
|
|
print(f" - 向量索引: {'启用' if result['vector_enabled'] else '未启用'}")
|
|
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"✗ PDF处理失败: {e}")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def show_character_info():
|
|
|
|
|
|
"""显示角色信息"""
|
|
|
|
|
|
print("\n" + "="*60)
|
|
|
|
|
|
print("角色设定信息")
|
|
|
|
|
|
print("="*60)
|
|
|
|
|
|
|
|
|
|
|
|
knowledge_dir = "./knowledge_base"
|
|
|
|
|
|
character_files = [f for f in os.listdir(knowledge_dir) if f.startswith('character') and f.endswith('.json')]
|
|
|
|
|
|
|
|
|
|
|
|
for char_file in character_files:
|
|
|
|
|
|
try:
|
|
|
|
|
|
with open(os.path.join(knowledge_dir, char_file), 'r', encoding='utf-8') as f:
|
|
|
|
|
|
char_data = json.load(f)
|
|
|
|
|
|
|
|
|
|
|
|
name = char_data.get('character_name', '未知')
|
|
|
|
|
|
occupation = char_data.get('basic_info', {}).get('occupation', '未知')
|
|
|
|
|
|
traits = char_data.get('personality', {}).get('core_traits', [])
|
|
|
|
|
|
|
|
|
|
|
|
print(f"\n角色: {name}")
|
|
|
|
|
|
print(f" 职业: {occupation}")
|
|
|
|
|
|
print(f" 特点: {', '.join(traits[:3])}")
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"✗ 读取角色文件失败: {char_file} - {e}")
|
|
|
|
|
|
|
|
|
|
|
|
def run_dialogue_system():
|
2025-08-15 17:58:11 +08:00
|
|
|
|
"""运行双AI对话系统"""
|
2025-08-15 17:25:07 +08:00
|
|
|
|
print("\n" + "="*60)
|
|
|
|
|
|
print("启动双AI角色对话系统")
|
|
|
|
|
|
print("="*60)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
2025-08-15 17:58:11 +08:00
|
|
|
|
|
|
|
|
|
|
# 直接启动双模型对话
|
|
|
|
|
|
print("\n正在初始化双模型对话系统...")
|
|
|
|
|
|
|
|
|
|
|
|
from dual_ai_dialogue_system import RAGKnowledgeBase, ConversationManager, DualAIDialogueEngine
|
|
|
|
|
|
from npc_dialogue_generator import DualModelDialogueGenerator
|
|
|
|
|
|
|
|
|
|
|
|
# 初始化组件
|
|
|
|
|
|
kb = RAGKnowledgeBase("./knowledge_base")
|
|
|
|
|
|
conv_mgr = ConversationManager("./conversation_data/conversations.db")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查模型路径
|
2025-08-18 18:25:19 +08:00
|
|
|
|
base_model_path = '/mnt/e/AI/Project02/AITrain/Qwen/Qwen3-4B'
|
2025-08-15 17:58:11 +08:00
|
|
|
|
lora_model_path = './output/NPC_Dialogue_LoRA/final_model'
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(base_model_path):
|
|
|
|
|
|
print(f"✗ 基础模型路径不存在: {base_model_path}")
|
|
|
|
|
|
print("请修改 main_controller.py 中的模型路径")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(lora_model_path):
|
|
|
|
|
|
lora_model_path = None
|
|
|
|
|
|
print("⚠ LoRA模型不存在,使用基础模型")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查角色数据
|
|
|
|
|
|
if not hasattr(kb, 'character_data') or len(kb.character_data) < 2:
|
|
|
|
|
|
print("✗ 角色数据不足,无法创建双模型对话系统")
|
|
|
|
|
|
print("请确保knowledge_base目录中有至少两个角色文件")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# 获取前两个角色
|
|
|
|
|
|
character_names = list(kb.character_data.keys())[:2]
|
|
|
|
|
|
char1_name = character_names[0]
|
|
|
|
|
|
char2_name = character_names[1]
|
|
|
|
|
|
|
|
|
|
|
|
print(f"✓ 使用角色: {char1_name} 和 {char2_name}")
|
|
|
|
|
|
|
|
|
|
|
|
# 配置两个角色的模型
|
|
|
|
|
|
character1_config = {
|
|
|
|
|
|
"name": char1_name,
|
|
|
|
|
|
"lora_path": lora_model_path,
|
|
|
|
|
|
"character_data": kb.character_data[char1_name]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
character2_config = {
|
|
|
|
|
|
"name": char2_name,
|
|
|
|
|
|
"lora_path": lora_model_path,
|
|
|
|
|
|
"character_data": kb.character_data[char2_name]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 创建双模型对话生成器
|
|
|
|
|
|
print("正在初始化双模型对话生成器...")
|
|
|
|
|
|
dual_generator = DualModelDialogueGenerator(
|
|
|
|
|
|
base_model_path,
|
|
|
|
|
|
character1_config,
|
|
|
|
|
|
character2_config
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 创建对话引擎
|
|
|
|
|
|
dialogue_engine = DualAIDialogueEngine(kb, conv_mgr, dual_generator)
|
|
|
|
|
|
|
|
|
|
|
|
# 创建对话会话
|
|
|
|
|
|
characters = [char1_name, char2_name]
|
|
|
|
|
|
worldview = kb.worldview_data.get('worldview_name', '未知世界观') if kb.worldview_data else '未知世界观'
|
|
|
|
|
|
|
|
|
|
|
|
session_id = conv_mgr.create_session(characters, worldview)
|
|
|
|
|
|
print(f"✓ 创建对话会话: {session_id}")
|
|
|
|
|
|
|
|
|
|
|
|
# 交互式对话循环
|
|
|
|
|
|
print(f"\n=== 双AI模型对话系统 ===")
|
|
|
|
|
|
print(f"角色: {char1_name} vs {char2_name}")
|
|
|
|
|
|
print(f"世界观: {worldview}")
|
|
|
|
|
|
print("输入 'quit' 退出对话")
|
|
|
|
|
|
print("-" * 50)
|
|
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 获取用户输入
|
|
|
|
|
|
user_input = input("\n请输入对话主题或指令: ").strip()
|
|
|
|
|
|
|
|
|
|
|
|
if user_input.lower() == 'quit':
|
|
|
|
|
|
print("退出双AI对话系统")
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
if not user_input:
|
|
|
|
|
|
print("请输入有效的对话主题")
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
# 询问对话轮数
|
|
|
|
|
|
turns_input = input("请输入对话轮数 (默认4): ").strip()
|
|
|
|
|
|
turns = int(turns_input) if turns_input.isdigit() else 4
|
|
|
|
|
|
|
|
|
|
|
|
# 询问历史上下文设置
|
2025-08-18 18:25:19 +08:00
|
|
|
|
history_input = input("使用历史对话轮数 (默认2): ").strip()
|
|
|
|
|
|
history_count = int(history_input) if history_input.isdigit() else 2
|
2025-08-15 17:58:11 +08:00
|
|
|
|
|
2025-08-18 18:25:19 +08:00
|
|
|
|
context_input = input("使用上下文信息数量 (默认10): ").strip()
|
|
|
|
|
|
context_info_count = int(context_input) if context_input.isdigit() else 10
|
2025-08-15 17:58:11 +08:00
|
|
|
|
|
|
|
|
|
|
print(f"\n开始对话 - 主题: {user_input}")
|
|
|
|
|
|
print(f"轮数: {turns}, 历史: {history_count}, 上下文: {context_info_count}")
|
|
|
|
|
|
print("-" * 50)
|
|
|
|
|
|
|
|
|
|
|
|
# 运行双模型对话
|
|
|
|
|
|
dialogue_engine.run_dual_model_conversation(
|
|
|
|
|
|
session_id, user_input, turns, history_count, context_info_count
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
print("-" * 50)
|
|
|
|
|
|
print("对话完成!")
|
|
|
|
|
|
|
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
|
print("\n\n用户中断对话")
|
|
|
|
|
|
break
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"对话过程中出现错误: {e}")
|
|
|
|
|
|
import traceback
|
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-08-15 17:25:07 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"✗ 对话系统启动失败: {e}")
|
|
|
|
|
|
import traceback
|
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
|
|
def create_demo_scenario():
|
|
|
|
|
|
"""创建演示场景"""
|
|
|
|
|
|
print("\n创建演示对话场景...")
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
from dual_ai_dialogue_system import RAGKnowledgeBase, ConversationManager, DualAIDialogueEngine
|
|
|
|
|
|
from npc_dialogue_generator import NPCDialogueGenerator
|
|
|
|
|
|
|
|
|
|
|
|
# 初始化组件
|
|
|
|
|
|
kb = RAGKnowledgeBase("./knowledge_base")
|
|
|
|
|
|
conv_mgr = ConversationManager("./conversation_data/demo_conversations.db")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查模型路径
|
2025-08-18 18:25:19 +08:00
|
|
|
|
base_model_path = '/mnt/e/AI/Project02/AITrain/Qwen/Qwen3-4B'
|
2025-08-15 17:25:07 +08:00
|
|
|
|
lora_model_path = './output/NPC_Dialogue_LoRA/final_model'
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(base_model_path):
|
|
|
|
|
|
print(f"✗ 基础模型路径不存在: {base_model_path}")
|
|
|
|
|
|
print("请修改 main_controller.py 中的模型路径")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(lora_model_path):
|
|
|
|
|
|
lora_model_path = None
|
|
|
|
|
|
print("⚠ LoRA模型不存在,使用基础模型")
|
|
|
|
|
|
|
|
|
|
|
|
llm_generator = NPCDialogueGenerator(base_model_path, lora_model_path, kb.character_data)
|
|
|
|
|
|
dialogue_engine = DualAIDialogueEngine(kb, conv_mgr, llm_generator)
|
|
|
|
|
|
|
|
|
|
|
|
# 创建演示对话
|
|
|
|
|
|
characters = ["维多利亚·布莱克伍德", "阿奇博尔德·韦恩"]
|
|
|
|
|
|
worldview = "克苏鲁的呼唤"
|
|
|
|
|
|
|
|
|
|
|
|
session_id = conv_mgr.create_session(characters, worldview)
|
|
|
|
|
|
print(f"✓ 创建演示会话: {session_id}")
|
|
|
|
|
|
|
|
|
|
|
|
# 运行几轮对话
|
|
|
|
|
|
topic = "最近发生的神秘事件"
|
|
|
|
|
|
print(f"\n开始演示对话 - 主题: {topic}")
|
|
|
|
|
|
print("-" * 40)
|
|
|
|
|
|
|
|
|
|
|
|
# 演示不同的历史上下文设置
|
|
|
|
|
|
# print("演示1: 使用默认上下文设置(历史3轮,信息2个)")
|
|
|
|
|
|
# dialogue_engine.run_conversation_turn(session_id, characters, 6, topic)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
session_id = conv_mgr.create_session(characters, worldview)
|
|
|
|
|
|
print(f"✓ 创建演示会话: {session_id}")
|
|
|
|
|
|
print("\n演示3: 使用最少历史上下文(历史1轮,信息1个)")
|
|
|
|
|
|
dialogue_engine.run_conversation_turn(session_id, characters, 6, topic, 1, 10)
|
|
|
|
|
|
|
|
|
|
|
|
session_id = conv_mgr.create_session(characters, worldview)
|
|
|
|
|
|
print(f"✓ 创建演示会话: {session_id}")
|
|
|
|
|
|
print("\n演示2: 使用更多历史上下文(历史10轮,信息10个)")
|
|
|
|
|
|
dialogue_engine.run_conversation_turn(session_id, characters, 6, topic, 5, 10)
|
|
|
|
|
|
|
|
|
|
|
|
print(f"\n✓ 演示完成!会话ID: {session_id}")
|
|
|
|
|
|
print("你可以通过主对话系统继续这个对话")
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"✗ 演示场景创建失败: {e}")
|
|
|
|
|
|
import traceback
|
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
|
|
def show_system_status():
|
|
|
|
|
|
"""显示系统状态"""
|
|
|
|
|
|
print("\n" + "="*60)
|
|
|
|
|
|
print("系统状态检查")
|
|
|
|
|
|
print("="*60)
|
|
|
|
|
|
|
|
|
|
|
|
# 检查文件
|
|
|
|
|
|
files_to_check = [
|
|
|
|
|
|
("./knowledge_base/worldview_template_coc.json", "世界观模板"),
|
|
|
|
|
|
("./knowledge_base/character_template_detective.json", "侦探角色"),
|
|
|
|
|
|
("./knowledge_base/character_template_professor.json", "教授角色"),
|
|
|
|
|
|
("./pdf_to_rag_processor.py", "PDF处理器"),
|
|
|
|
|
|
("./dual_ai_dialogue_system.py", "对话系统"),
|
|
|
|
|
|
("./npc_dialogue_generator.py", "NPC生成器")
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
print("\n文件检查:")
|
|
|
|
|
|
for file_path, description in files_to_check:
|
|
|
|
|
|
if os.path.exists(file_path):
|
|
|
|
|
|
print(f"✓ {description}: {file_path}")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"✗ {description}: {file_path} (不存在)")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查目录
|
|
|
|
|
|
print("\n目录检查:")
|
|
|
|
|
|
directories = ["./knowledge_base", "./rag_knowledge", "./conversation_data"]
|
|
|
|
|
|
for dir_path in directories:
|
|
|
|
|
|
if os.path.exists(dir_path):
|
|
|
|
|
|
file_count = len([f for f in os.listdir(dir_path) if os.path.isfile(os.path.join(dir_path, f))])
|
|
|
|
|
|
print(f"✓ {dir_path}: {file_count} 个文件")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"✗ {dir_path}: 不存在")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查对话会话
|
|
|
|
|
|
try:
|
|
|
|
|
|
from dual_ai_dialogue_system import ConversationManager
|
|
|
|
|
|
conv_mgr = ConversationManager("./conversation_data/conversations.db")
|
|
|
|
|
|
sessions = conv_mgr.list_sessions()
|
|
|
|
|
|
print(f"\n✓ 对话会话: {len(sessions)} 个")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"\n✗ 对话会话检查失败: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
|
"""主控制程序"""
|
|
|
|
|
|
print("="*70)
|
|
|
|
|
|
print(" 双AI角色对话系统 - 主控制程序")
|
|
|
|
|
|
print(" 基于RAG的世界观增强对话引擎")
|
|
|
|
|
|
print("="*70)
|
|
|
|
|
|
|
|
|
|
|
|
# 检查依赖
|
|
|
|
|
|
if not check_dependencies():
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# 设置目录
|
|
|
|
|
|
# setup_directories()
|
|
|
|
|
|
# copy_demo_files()
|
|
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
print("\n" + "="*50)
|
|
|
|
|
|
print("主菜单 - 请选择操作:")
|
|
|
|
|
|
print("1. 处理PDF世界观文档 (转换为RAG格式)")
|
|
|
|
|
|
print("2. 查看角色设定信息")
|
2025-08-15 17:58:11 +08:00
|
|
|
|
print("3. 启动双AI对话系统 (支持双模型对话)")
|
2025-08-15 17:25:07 +08:00
|
|
|
|
print("4. 创建演示对话场景")
|
|
|
|
|
|
print("5. 系统状态检查")
|
|
|
|
|
|
print("6. 查看使用说明")
|
|
|
|
|
|
print("0. 退出")
|
|
|
|
|
|
print("="*50)
|
|
|
|
|
|
|
|
|
|
|
|
choice = input("请输入选择 (0-6): ").strip()
|
|
|
|
|
|
|
|
|
|
|
|
if choice == '0':
|
|
|
|
|
|
print("\n感谢使用双AI角色对话系统!")
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
elif choice == '1':
|
|
|
|
|
|
process_pdf_workflow()
|
|
|
|
|
|
|
|
|
|
|
|
elif choice == '2':
|
|
|
|
|
|
show_character_info()
|
|
|
|
|
|
|
|
|
|
|
|
elif choice == '3':
|
|
|
|
|
|
run_dialogue_system()
|
|
|
|
|
|
|
|
|
|
|
|
elif choice == '4':
|
|
|
|
|
|
create_demo_scenario()
|
|
|
|
|
|
|
|
|
|
|
|
elif choice == '5':
|
|
|
|
|
|
show_system_status()
|
|
|
|
|
|
|
|
|
|
|
|
elif choice == '6':
|
|
|
|
|
|
show_usage_guide()
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
print("❌ 无效选择,请重新输入")
|
|
|
|
|
|
|
|
|
|
|
|
def show_usage_guide():
|
|
|
|
|
|
"""显示使用说明"""
|
|
|
|
|
|
print("\n" + "="*60)
|
|
|
|
|
|
print("系统使用说明")
|
|
|
|
|
|
print("="*60)
|
|
|
|
|
|
|
|
|
|
|
|
guide = """
|
|
|
|
|
|
🚀 快速开始:
|
|
|
|
|
|
1. 首次使用建议先运行"创建演示对话场景"
|
|
|
|
|
|
2. 如有PDF世界观文档,选择"处理PDF世界观文档"
|
|
|
|
|
|
3. 通过"启动双AI对话系统"开始角色对话
|
|
|
|
|
|
|
|
|
|
|
|
📁 文档格式说明:
|
|
|
|
|
|
- 世界观文档: worldview_template_coc.json (参考COC设定)
|
|
|
|
|
|
- 角色设定: character_template_*.json (包含详细人设)
|
|
|
|
|
|
|
|
|
|
|
|
🔧 系统功能:
|
|
|
|
|
|
- PDF自动转换为RAG知识库
|
|
|
|
|
|
- 基于向量相似度的上下文检索
|
|
|
|
|
|
- 持久化对话历史存储
|
|
|
|
|
|
- 角色设定一致性保持
|
|
|
|
|
|
|
|
|
|
|
|
📝 自定义角色:
|
|
|
|
|
|
1. 参考 character_template_*.json 格式
|
|
|
|
|
|
2. 保存到 knowledge_base/ 目录
|
|
|
|
|
|
3. 重启对话系统加载新角色
|
|
|
|
|
|
|
|
|
|
|
|
💾 对话数据:
|
|
|
|
|
|
- 历史对话保存在 conversation_data/ 目录
|
|
|
|
|
|
- 支持会话恢复和历史查看
|
|
|
|
|
|
- 自动记录使用的上下文信息
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 注意事项:
|
|
|
|
|
|
- 确保模型路径正确设置
|
|
|
|
|
|
- 首次运行需要下载向量化模型
|
|
|
|
|
|
- PDF处理需要足够内存
|
|
|
|
|
|
"""
|
|
|
|
|
|
print(guide)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
main()
|