You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

265 lines
9.3 KiB

"""
首次运行初始化脚本
- 创建桌面快捷方式指向 main.py,用 Python 运行,图标为 icon.png
- 检查 knowledge 文件夹文件数量
- 如果 <= 3,提示用户建立知识库,并自动运行 process_knowledge_base.py
"""
import os
import sys
import subprocess
import shutil
import json
import platform
import urllib.parse
import urllib.request
from pathlib import Path
# 获取脚本所在目录(项目根目录)
PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
MAIN_SCRIPT = os.path.join(PROJECT_DIR, "main.py")
ICON_ICO = os.path.join(PROJECT_DIR, "icon.ico")
ICON_PNG = os.path.join(PROJECT_DIR, "icon.png")
KNOWLEDGE_DIR = os.path.join(PROJECT_DIR, "knowledge")
PROCESS_SCRIPT = os.path.join(PROJECT_DIR, "process_knowledge_base.py")
CONFIG_PATH = os.path.join(PROJECT_DIR, "config.json")
def load_config():
if not os.path.exists(CONFIG_PATH):
return {}
try:
with open(CONFIG_PATH, "r", encoding="utf-8") as f:
return json.load(f) or {}
except Exception as exc:
print(f"✗ 读取 config.json 失败:{exc}")
return {}
def save_config(cfg):
try:
with open(CONFIG_PATH, "w", encoding="utf-8") as f:
json.dump(cfg, f, ensure_ascii=False, indent=4)
print(f"✓ 配置已写入:{CONFIG_PATH}")
except Exception as exc:
print(f"✗ 写入 config.json 失败:{exc}")
def check_network_reachable(url="https://www.google.com/generate_204", timeout_ms=2000):
"""Check connectivity via ping + lightweight HTTPS GET. Returns True if either succeeds."""
parsed = urllib.parse.urlparse(url)
host = parsed.hostname or "google.com"
is_windows = platform.system().lower().startswith("win")
if is_windows:
cmd = ["ping", "-n", "1", "-w", str(timeout_ms), host]
else:
cmd = ["ping", "-c", "1", "-W", str(int(timeout_ms / 1000)), host]
try:
result = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if result.returncode == 0:
return True
except Exception as exc:
print(f"✗ 无法执行 ping:{exc}")
# Fallback: HTTPS request (respects proxy envs)
try:
with urllib.request.urlopen(url, timeout=timeout_ms / 1000.0) as resp:
return 200 <= getattr(resp, "status", 200) < 400
except Exception as exc:
print(f"✗ HTTPS 连通性检测失败:{exc}")
return False
def prompt_config_if_needed():
cfg = load_config()
defaults = {
"base_url": cfg.get("base_url") or "https://api.moonshot.cn/v1",
"model": cfg.get("model") or "kimi-latest",
}
if not cfg.get("system_prompt"):
cfg["system_prompt"] = (
"You are a WorldQuant BRAIN platform expert and Consultant. "
"Your goal is to assist users with Alpha development, BRAIN API usage, and maximizing consultant income."
)
def ask(field, label, default_value=None, allow_empty=False):
current = str(cfg.get(field, "")).strip()
prompt = f"请输入 {label}" + (f" [默认: {current or default_value}]" if (current or default_value) else "") + ": "
value = input(prompt).strip()
if not value:
value = current if current else (default_value if default_value is not None else "")
if value or allow_empty:
cfg[field] = value
return value
api_key = ask("api_key", "API Key")
base_url = ask("base_url", "Base URL", defaults["base_url"], allow_empty=True)
model = ask("model", "模型名称", defaults["model"], allow_empty=True)
if api_key:
save_config(cfg)
return True
print("✗ 配置文件中的 api_key 为空,请填写后再运行本脚本。")
return False
def is_api_key_configured():
"""Check config; if api_key missing/empty, prompt user to fill and persist."""
cfg = load_config()
api_key = str(cfg.get("api_key", "")).strip()
if api_key:
return True
print("✗ 当前 config.json 中 api_key 为空。")
return prompt_config_if_needed()
def create_desktop_shortcut():
"""创建桌面快捷方式"""
try:
import win32com.client
desktop = os.path.expanduser("~\\Desktop")
shortcut_path = os.path.join(desktop, "BRAIN顾问助手.lnk")
# 获取 Python 可执行文件路径
python_exe = sys.executable
# 创建 shortcut
shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortcut(shortcut_path)
shortcut.TargetPath = python_exe
shortcut.Arguments = f'"{MAIN_SCRIPT}"'
shortcut.WorkingDirectory = PROJECT_DIR
# 设置图标:优先使用 .ico(Windows 标准格式),再试 .png
icon_found = False
if os.path.exists(ICON_ICO):
# .ico 文件:使用 "路径,0" 格式
shortcut.IconLocation = f"{ICON_ICO},0"
icon_found = True
print(f" 使用图标:{ICON_ICO}")
elif os.path.exists(ICON_PNG):
# .png 文件:也需要 "路径,0" 格式
shortcut.IconLocation = f"{ICON_PNG},0"
icon_found = True
print(f" 使用图标:{ICON_PNG}")
else:
# 使用 Python 可执行文件的图标作为默认
shortcut.IconLocation = f"{python_exe},0"
print(f" 使用默认图标(Python 图标)")
shortcut.Description = "BRAIN 顾问助手 - AI 驱动的交互工具"
shortcut.save()
print(f"✓ 桌面快捷方式已创建:{shortcut_path}")
return True
except ImportError:
print("⚠ pywin32 未安装,尝试使用备选方案创建快捷方式...")
try:
# 备选方案:使用 Windows API
create_shortcut_via_batch(desktop, shortcut_path, python_exe)
return True
except Exception as e:
print(f"✗ 创建快捷方式失败:{e}")
print(f" 请手动创建快捷方式,目标为:{python_exe} \"{MAIN_SCRIPT}\"")
return False
except Exception as e:
print(f"✗ 创建快捷方式失败:{e}")
return False
def check_knowledge_base():
"""检查 knowledge 文件夹中的文件数量"""
if not os.path.exists(KNOWLEDGE_DIR):
os.makedirs(KNOWLEDGE_DIR)
print(f"✓ 创建 knowledge 文件夹:{KNOWLEDGE_DIR}")
return 0
# 只计算文件,不计算目录
files = [f for f in os.listdir(KNOWLEDGE_DIR) if os.path.isfile(os.path.join(KNOWLEDGE_DIR, f))]
file_count = len(files)
print(f"知识库文件数量:{file_count}")
if files:
print(f" 已有文件:{', '.join(files)}")
return file_count
def run_process_knowledge_base():
"""运行 process_knowledge_base.py 建立知识库"""
if not os.path.exists(PROCESS_SCRIPT):
print(f"✗ 找不到 {PROCESS_SCRIPT}")
return False
print(f"\n正在运行知识库初始化脚本...")
print(f"命令:{sys.executable} \"{PROCESS_SCRIPT}\"")
try:
subprocess.run([sys.executable, PROCESS_SCRIPT], cwd=PROJECT_DIR)
print("✓ 知识库初始化完成")
return True
except Exception as e:
print(f"✗ 运行 process_knowledge_base.py 失败:{e}")
return False
def main():
print("=" * 60)
print("BRAIN 顾问助手 - 首次运行初始化")
print("=" * 60)
print()
# 0. 检查 api_key 是否已配置,未配置则直接退出
if not is_api_key_configured():
input("按 Enter 键退出...")
return
# 0.1 检查网络(ping + HTTPS),以确认代理已开启
print("[网络检查] 正在测试到 https://www.google.com 的连通性...")
if not check_network_reachable("https://www.google.com/generate_204"):
print("✗ 无法连通 google.com,请确认代理已开启,然后重新运行本脚本。")
input("按 Enter 键退出...")
return
print("✓ 网络检查通过")
# 1. 创建桌面快捷方式
print("[1/2] 创建桌面快捷方式...")
shortcut_ok = create_desktop_shortcut()
print()
# 2. 检查知识库
print("[2/2] 检查本地知识库...")
file_count = check_knowledge_base()
print()
if file_count <= 3:
print("⚠ 知识库文件较少(<= 3 个)")
print("建议建立本地知识库以增强 AI 回答效果")
print()
response = input("是否现在运行知识库初始化脚本?(y/n) [默认: y]: ").strip().lower()
if response != 'n':
run_process_knowledge_base()
else:
print(f"✓ 知识库已初始化(包含 {file_count} 个文件)")
print()
print("=" * 60)
print("初始化完成!")
print("=" * 60)
print()
if shortcut_ok:
print("📌 你现在可以从桌面快捷方式启动应用")
print(f" 或者运行:{sys.executable} \"{MAIN_SCRIPT}\"")
else:
print(f"请运行:{sys.executable} \"{MAIN_SCRIPT}\"")
print()
input("按 Enter 键退出...")
if __name__ == "__main__":
main()