1 line
23 KiB
JSON
1 line
23 KiB
JSON
{"repo": "baizhixin/ai-rime", "files": {"bzx/bzx_config.json": {"c8b5d0f0a896b2acfa18a3d80caec972f587c70a": {"t": 1785746261.6035113, "n": 700, "h": "57319ad1c4d61c6e", "c": "{\n \"api_url\": \"https://api.deepseek.com/v1/chat/completions\",\n \"api_key\": \"sk-\",\n \"model\": \"deepseek-chat\",\n \"auto_trigger\": true,\n \"context_aware\": true,\n \"debug\": false,\n \"system_prompts\": {\n \"correct\": \"{\\\"role\\\":\\\"逆向拼音纠错专家\\\",\\\"protocol\\\":\\\"仅输出修正后汉字,严禁解释多言,长度严格守恒\\\",\\\"logic\\\":\\\"1.声学还原:兼容平翘舌、前后鼻音、fh模糊音;2.意境采样:文学语境(含山/巅/长风/明月/负/至)史诗感优先,即便原句通顺,若同音字张力更强(如负变扶)则强制替换;上下文原则:用户携带历史输入时,必须按照历史输入的信息推断预测内容,例如人称性别区分\\\",\\\"output\\\":\\\"直接输出修正后的文本\\\"}\",\n \"translate\": \"你是翻译专家。用户会给你一段文本,中文翻译成英文,英文翻译成中文。\\n\\n【输出要求】\\n- 只输出翻译结果\\n- 禁止任何解释或说明\",\n \"chat\": \"你是内容生成助手。根据用户的需求生成内容。\\n\\n【输出要求】\\n- 只输出生成的内容\\n- 禁止任何解释或前缀\\n- 严禁附带markdown语法的符号表示\\n- 所有回答应当尽可能简洁高效\\n- 对于命令的询问应当给出一条命令\"\n }\n}"}, "2be6903a18266992ac9777b0b17d6accf12008b7": {"t": 1785761239.2129946, "n": 700, "h": "57319ad1c4d61c6e", "c": "{\n \"api_url\": \"https://api.deepseek.com/v1/chat/completions\",\n \"api_key\": \"sk-\",\n \"model\": \"deepseek-chat\",\n \"auto_trigger\": true,\n \"context_aware\": true,\n \"debug\": false,\n \"system_prompts\": {\n \"correct\": \"{\\\"role\\\":\\\"逆向拼音纠错专家\\\",\\\"protocol\\\":\\\"仅输出修正后汉字,严禁解释多言,长度严格守恒\\\",\\\"logic\\\":\\\"1.声学还原:兼容平翘舌、前后鼻音、fh模糊音;2.意境采样:文学语境(含山/巅/长风/明月/负/至)史诗感优先,即便原句通顺,若同音字张力更强(如负变扶)则强制替换;上下文原则:用户携带历史输入时,必须按照历史输入的信息推断预测内容,例如人称性别区分\\\",\\\"output\\\":\\\"直接输出修正后的文本\\\"}\",\n \"translate\": \"你是翻译专家。用户会给你一段文本,中文翻译成英文,英文翻译成中文。\\n\\n【输出要求】\\n- 只输出翻译结果\\n- 禁止任何解释或说明\",\n \"chat\": \"你是内容生成助手。根据用户的需求生成内容。\\n\\n【输出要求】\\n- 只输出生成的内容\\n- 禁止任何解释或前缀\\n- 严禁附带markdown语法的符号表示\\n- 所有回答应当尽可能简洁高效\\n- 对于命令的询问应当给出一条命令\"\n }\n}"}}, "bzx/bzx_service.py": {"c8b5d0f0a896b2acfa18a3d80caec972f587c70a": {"t": 1785746388.7245853, "n": 8144, "h": "36f8e2ae258221e1", "c": "#!/usr/bin/env python3\n\"\"\"\nbzx_service.py - Rime AI 多功能后台服务\n\n通过临时文件与 Rime Lua 通信,处理纠错、翻译、对话请求。\n\n使用方法:\n python bzx_service.py [--config PATH]\n\"\"\"\n\nimport os\nimport sys\nimport json\nimport signal\nimport logging\nfrom logging.handlers import RotatingFileHandler\nfrom typing import Dict, Any\nimport argparse\n\n# 获取脚本所在目录\nSCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))\n\n# 导入 IPC 模块\ntry:\n from bzx_ipc import create_ipc_server\nexcept ImportError:\n sys.path.insert(0, SCRIPT_DIR)\n from bzx_ipc import create_ipc_server\n\n# 导入 AI 模块\nfrom bzx_ai import AIClient\n\n# 尝试导入 jieba\ntry:\n import jieba\n jieba.setLogLevel(jieba.logging.WARNING)\n JIEBA_AVAILABLE = True\nexcept ImportError:\n JIEBA_AVAILABLE = False\n\n\n# ============ 日志配置 ============\n\ndef setup_logging(debug: bool = False) -> logging.Logger:\n \"\"\"配置日志(带轮转)\"\"\"\n logger = logging.getLogger(\"bzx_service\")\n logger.setLevel(logging.DEBUG if debug else logging.INFO)\n \n # 日志文件在脚本目录\n log_file = os.path.join(SCRIPT_DIR, \"bzx_service.log\")\n \n # 轮转:最大 1MB,保留 3 个备份\n handler = RotatingFileHandler(\n log_file, \n maxBytes=1024 * 1024, # 1MB\n backupCount=3,\n encoding=\"utf-8\"\n )\n handler.setFormatter(logging.Formatter(\n \"%(asctime)s - %(levelname)s - %(message)s\"\n ))\n logger.addHandler(handler)\n \n # 同时输出到控制台\n console = logging.StreamHandler()\n console.setFormatter(logging.Formatter(\"%(message)s\"))\n logger.addHandler(console)\n \n return logger\n\n\n# ============ 默认配置 ============\n\nDEFAULT_CONFIG = {\n \"api_url\": \"https://api.deepseek.com/v1/chat/completions\",\n \"api_key\": \"sk-\",\n \"model\": \"deepseek-chat\",\n \"context_aware\": False,\n \"debug\": False,\n \"model_params\": {\n \"temperature\": 0.1,\n \"max_tokens\": 512,\n \"top_p\": 1.0,\n \"timeout\": 30\n },\n \"system_prompts\": {\n \"correct\": \"{\\\"role\\\":\\\"逆向拼音纠错专家\\\",\\\"protocol\\\":\\\"仅输出修正后汉字,严禁解释多言,长度严格守恒\\\",\\\"logic\\\":\\\"1.声学还原:兼容平翘舌、前后鼻音、fh模糊音;2.意境采样:文学语境(含山/巅/长风/明月/负/至)史诗感优先,即便原句通顺,若同音字张力更强(如负变扶)则强制替换;如果有上下文内容的话**必须**参考上下文内容的名词进行纠正,例如女性->她,男性->他。\\\",\\\"output\\\":\\\"直接输出修正后的文本\\\"}\",\n \"translate\": \"你是翻译专家。用户会给你一段文本,中文翻译成英文,英文翻译成中文。\\n\\n【输出要求】\\n- 只输出翻译结果\\n- 禁止任何解释或说明\",\n \"chat\": \"你是内容生成助手。根据用户的需求生成内容。\\n\\n【输出要求】\\n- 只输出生成的内容\\n- 禁止任何解释或前缀\\n- 严禁附带markdown语法的符号表示\\n- 所有回答应当尽可能简洁高效\\n- 对于命令的询问应当给出一条命令\"\n }\n}\n\nIPC_NAME = \"bzx_rime\"\n\n\n# ============ 配置加载 ============\n\ndef load_config(config_path: str = None) -> Dict[str, Any]:\n \"\"\"加载配置文件\"\"\"\n # 搜索路径:命令行指定 > 当前目录\n search_paths = []\n if config_path:\n search_paths.append(config_path)\n search_paths.append(os.path.join(SCRIPT_DIR, \"bzx_config.json\"))\n \n for path in search_paths:\n if os.path.exists(path):\n try:\n with open(path, \"r\", encoding=\"utf-8\") as f:\n config = json.load(f)\n print(f\"已加载配置: {path}\")\n merged = DEFAULT_CONFIG.copy()\n merged.update(config)\n if \"system_prompts\" in config:\n merged[\"system_prompts\"] = {**DEFAULT_CONFIG[\"system_prompts\"], **config[\"system_prompts\"]}\n return merged\n except Exception as e:\n print(f\"配置文件读取失败 {path}: {e}\")\n \n print(\"警告: 未找到配置文件,使用默认配置\")\n return DEFAULT_CONFIG.copy()\n\n\n# ============ 请求处理 ============\n\nclass RequestHandler:\n \"\"\"处理来自 Lua 的请求\"\"\"\n \n def __init__(self, config: Dict[str, Any], logger: logging.Logger):\n self.config = config\n self.logger = logger\n self.system_prompts = config.get(\"system_prompts\", {})\n self.context_enabled = config.get(\"context_aware\", False)\n self.ai_client = AIClient.from_config(config)\n \n def handle(self, request_json: str) -> str:\n \"\"\"处理请求并返回 JSON 响应\"\"\"\n try:\n req = json.loads(request_json)\n except json.JSONDecodeError as e:\n self.logger.error(f\"JSON 解析失败: {e}\")\n return json.dumps({\"error\": f\"Invalid JSON: {e}\", \"result\": None})\n \n req_type = req.get(\"type\", \"correct\")\n text = req.get(\"text\", \"\")\n pinyin = req.get(\"pinyin\", \"\")\n context = req.get(\"context\", \"\")\n reqid = req.get(\"reqid\", \"\")\n \n func_name = {\"correct\": \"纠错\", \"translate\": \"翻译\", \"chat\": \"对话\"}.get(req_type, req_type)\n self.logger.info(f\"[{func_name}] 收到请求: {text[:50]}{'...' if len(text) > 50 else ''}\")\n \n # 获取系统提示词\n system_prompt = self.system_prompts.get(req_type, \"\")\n \n # 构建用户消息\n user_text = text\n context_messages = [] # 额外的消息列表\n \n if req_type == \"correct\":\n if pinyin:\n user_text = f\"拼音:{pinyin}\\n待纠正:{text}\"\n self.logger.debug(f\" 拼音: {pinyin}\")\n \n if self.context_enabled and context:\n # 使用 jieba 分词\n if JIEBA_AVAILABLE:\n tokens = list(jieba.cut(context))\n tokens = [t.strip() for t in tokens if t.strip()]\n else:\n tokens = list(context)\n \n context_tokens = \" \".join(tokens)\n self.logger.info(f\" 上下文: {context_tokens}\")\n \n # 通过 assistant 消息传递上下文\n context_messages = [\n {\"role\": \"assistant\", \"content\": f\"用户历史输入:{context_tokens}\"}\n ]\n \n # 调用 AI(传递上下文消息)\n result = self.ai_client.chat(system_prompt, user_text, context_messages if context_messages else None)\n \n if result:\n self.logger.info(f\"[{func_name}] 结果: {result[:50]}{'...' if len(result) > 50 else ''}\")\n else:\n self.logger.warning(f\"[{func_name}] 处理失败,返回原文\")\n result = text\n \n return json.dumps({\n \"reqid\": reqid,\n \"result\": result,\n \"error\": None\n }, ensure_ascii=False)\n\n\n# ============ 主服务 ============\n\nclass BzxService:\n \"\"\"IPC 通信服务\"\"\"\n \n def __init__(self, config: Dict[str, Any], logger: logging.Logger):\n self.config = config\n self.logger = logger\n self.handler = RequestHandler(config, logger)\n self.server = None\n \n def start(self):\n \"\"\"启动服务\"\"\"\n self.logger.info(\"=\" * 50)\n self.logger.info(\"Rime AI 服务已启动\")\n self.logger.info(\"=\" * 50)\n self.logger.info(f\" API: {self.config.get('api_url', 'N/A')}\")\n self.logger.info(f\" 模型: {self.config.get('model', 'N/A')}\")\n self.logger.info(f\" IPC: {IPC_NAME}\")\n self.logger.info(f\" 上下文: {'开启' if self.config.get('context_aware') else '关闭'}\")\n self.logger.info(\"=\" * 50)\n self.logger.info(\"按 Ctrl+C 停止服务...\")\n \n self.server = create_ipc_server(IPC_NAME)\n \n try:\n self.server.run(self.handler.handle)\n except KeyboardInterrupt:\n pass\n finally:\n self.stop()\n \n def stop(self):\n \"\"\"停止服务\"\"\"\n if self.server:\n self.server.stop()\n self.server.cleanup()\n self.logger.info(\"服务已停止\")\n\n\n# ============ 主函数 ============\n\ndef main():\n parser = argparse.ArgumentParser(description=\"Rime AI 服务\")\n parser.add_argument(\"--config\", \"-c\", type=str, help=\"配置文件路径\")\n parser.add_argument(\"--debug\", \"-d\", action=\"store_true\", help=\"开启调试模式\")\n args = parser.parse_args()\n \n config = load_config(args.config)\n \n # 命令行 debug 优先\n if args.debug:\n config[\"debug\"] = True\n \n logger = setup_logging(config.get(\"debug\", False))\n \n if not config.get(\"api_key\"):\n logger.warning(\"=\" * 50)\n logger.warning(\"警告: 现已使用博主bzx的api_key\")\n logger.warning(\"有能力者请编辑配置文件改用自己的api_key!\")\n logger.warning(\"=\" * 50)\n \n service = BzxService(config, logger)\n \n def signal_handler(sig, frame):\n service.stop()\n sys.exit(0)\n \n signal.signal(signal.SIGINT, signal_handler)\n signal.signal(signal.SIGTERM, signal_handler)\n \n service.start()\n\n\nif __name__ == \"__main__\":\n main()\n"}, "2be6903a18266992ac9777b0b17d6accf12008b7": {"t": 1785761238.5677197, "n": 8144, "h": "36f8e2ae258221e1", "c": "#!/usr/bin/env python3\n\"\"\"\nbzx_service.py - Rime AI 多功能后台服务\n\n通过临时文件与 Rime Lua 通信,处理纠错、翻译、对话请求。\n\n使用方法:\n python bzx_service.py [--config PATH]\n\"\"\"\n\nimport os\nimport sys\nimport json\nimport signal\nimport logging\nfrom logging.handlers import RotatingFileHandler\nfrom typing import Dict, Any\nimport argparse\n\n# 获取脚本所在目录\nSCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))\n\n# 导入 IPC 模块\ntry:\n from bzx_ipc import create_ipc_server\nexcept ImportError:\n sys.path.insert(0, SCRIPT_DIR)\n from bzx_ipc import create_ipc_server\n\n# 导入 AI 模块\nfrom bzx_ai import AIClient\n\n# 尝试导入 jieba\ntry:\n import jieba\n jieba.setLogLevel(jieba.logging.WARNING)\n JIEBA_AVAILABLE = True\nexcept ImportError:\n JIEBA_AVAILABLE = False\n\n\n# ============ 日志配置 ============\n\ndef setup_logging(debug: bool = False) -> logging.Logger:\n \"\"\"配置日志(带轮转)\"\"\"\n logger = logging.getLogger(\"bzx_service\")\n logger.setLevel(logging.DEBUG if debug else logging.INFO)\n \n # 日志文件在脚本目录\n log_file = os.path.join(SCRIPT_DIR, \"bzx_service.log\")\n \n # 轮转:最大 1MB,保留 3 个备份\n handler = RotatingFileHandler(\n log_file, \n maxBytes=1024 * 1024, # 1MB\n backupCount=3,\n encoding=\"utf-8\"\n )\n handler.setFormatter(logging.Formatter(\n \"%(asctime)s - %(levelname)s - %(message)s\"\n ))\n logger.addHandler(handler)\n \n # 同时输出到控制台\n console = logging.StreamHandler()\n console.setFormatter(logging.Formatter(\"%(message)s\"))\n logger.addHandler(console)\n \n return logger\n\n\n# ============ 默认配置 ============\n\nDEFAULT_CONFIG = {\n \"api_url\": \"https://api.deepseek.com/v1/chat/completions\",\n \"api_key\": \"sk-\",\n \"model\": \"deepseek-chat\",\n \"context_aware\": False,\n \"debug\": False,\n \"model_params\": {\n \"temperature\": 0.1,\n \"max_tokens\": 512,\n \"top_p\": 1.0,\n \"timeout\": 30\n },\n \"system_prompts\": {\n \"correct\": \"{\\\"role\\\":\\\"逆向拼音纠错专家\\\",\\\"protocol\\\":\\\"仅输出修正后汉字,严禁解释多言,长度严格守恒\\\",\\\"logic\\\":\\\"1.声学还原:兼容平翘舌、前后鼻音、fh模糊音;2.意境采样:文学语境(含山/巅/长风/明月/负/至)史诗感优先,即便原句通顺,若同音字张力更强(如负变扶)则强制替换;如果有上下文内容的话**必须**参考上下文内容的名词进行纠正,例如女性->她,男性->他。\\\",\\\"output\\\":\\\"直接输出修正后的文本\\\"}\",\n \"translate\": \"你是翻译专家。用户会给你一段文本,中文翻译成英文,英文翻译成中文。\\n\\n【输出要求】\\n- 只输出翻译结果\\n- 禁止任何解释或说明\",\n \"chat\": \"你是内容生成助手。根据用户的需求生成内容。\\n\\n【输出要求】\\n- 只输出生成的内容\\n- 禁止任何解释或前缀\\n- 严禁附带markdown语法的符号表示\\n- 所有回答应当尽可能简洁高效\\n- 对于命令的询问应当给出一条命令\"\n }\n}\n\nIPC_NAME = \"bzx_rime\"\n\n\n# ============ 配置加载 ============\n\ndef load_config(config_path: str = None) -> Dict[str, Any]:\n \"\"\"加载配置文件\"\"\"\n # 搜索路径:命令行指定 > 当前目录\n search_paths = []\n if config_path:\n search_paths.append(config_path)\n search_paths.append(os.path.join(SCRIPT_DIR, \"bzx_config.json\"))\n \n for path in search_paths:\n if os.path.exists(path):\n try:\n with open(path, \"r\", encoding=\"utf-8\") as f:\n config = json.load(f)\n print(f\"已加载配置: {path}\")\n merged = DEFAULT_CONFIG.copy()\n merged.update(config)\n if \"system_prompts\" in config:\n merged[\"system_prompts\"] = {**DEFAULT_CONFIG[\"system_prompts\"], **config[\"system_prompts\"]}\n return merged\n except Exception as e:\n print(f\"配置文件读取失败 {path}: {e}\")\n \n print(\"警告: 未找到配置文件,使用默认配置\")\n return DEFAULT_CONFIG.copy()\n\n\n# ============ 请求处理 ============\n\nclass RequestHandler:\n \"\"\"处理来自 Lua 的请求\"\"\"\n \n def __init__(self, config: Dict[str, Any], logger: logging.Logger):\n self.config = config\n self.logger = logger\n self.system_prompts = config.get(\"system_prompts\", {})\n self.context_enabled = config.get(\"context_aware\", False)\n self.ai_client = AIClient.from_config(config)\n \n def handle(self, request_json: str) -> str:\n \"\"\"处理请求并返回 JSON 响应\"\"\"\n try:\n req = json.loads(request_json)\n except json.JSONDecodeError as e:\n self.logger.error(f\"JSON 解析失败: {e}\")\n return json.dumps({\"error\": f\"Invalid JSON: {e}\", \"result\": None})\n \n req_type = req.get(\"type\", \"correct\")\n text = req.get(\"text\", \"\")\n pinyin = req.get(\"pinyin\", \"\")\n context = req.get(\"context\", \"\")\n reqid = req.get(\"reqid\", \"\")\n \n func_name = {\"correct\": \"纠错\", \"translate\": \"翻译\", \"chat\": \"对话\"}.get(req_type, req_type)\n self.logger.info(f\"[{func_name}] 收到请求: {text[:50]}{'...' if len(text) > 50 else ''}\")\n \n # 获取系统提示词\n system_prompt = self.system_prompts.get(req_type, \"\")\n \n # 构建用户消息\n user_text = text\n context_messages = [] # 额外的消息列表\n \n if req_type == \"correct\":\n if pinyin:\n user_text = f\"拼音:{pinyin}\\n待纠正:{text}\"\n self.logger.debug(f\" 拼音: {pinyin}\")\n \n if self.context_enabled and context:\n # 使用 jieba 分词\n if JIEBA_AVAILABLE:\n tokens = list(jieba.cut(context))\n tokens = [t.strip() for t in tokens if t.strip()]\n else:\n tokens = list(context)\n \n context_tokens = \" \".join(tokens)\n self.logger.info(f\" 上下文: {context_tokens}\")\n \n # 通过 assistant 消息传递上下文\n context_messages = [\n {\"role\": \"assistant\", \"content\": f\"用户历史输入:{context_tokens}\"}\n ]\n \n # 调用 AI(传递上下文消息)\n result = self.ai_client.chat(system_prompt, user_text, context_messages if context_messages else None)\n \n if result:\n self.logger.info(f\"[{func_name}] 结果: {result[:50]}{'...' if len(result) > 50 else ''}\")\n else:\n self.logger.warning(f\"[{func_name}] 处理失败,返回原文\")\n result = text\n \n return json.dumps({\n \"reqid\": reqid,\n \"result\": result,\n \"error\": None\n }, ensure_ascii=False)\n\n\n# ============ 主服务 ============\n\nclass BzxService:\n \"\"\"IPC 通信服务\"\"\"\n \n def __init__(self, config: Dict[str, Any], logger: logging.Logger):\n self.config = config\n self.logger = logger\n self.handler = RequestHandler(config, logger)\n self.server = None\n \n def start(self):\n \"\"\"启动服务\"\"\"\n self.logger.info(\"=\" * 50)\n self.logger.info(\"Rime AI 服务已启动\")\n self.logger.info(\"=\" * 50)\n self.logger.info(f\" API: {self.config.get('api_url', 'N/A')}\")\n self.logger.info(f\" 模型: {self.config.get('model', 'N/A')}\")\n self.logger.info(f\" IPC: {IPC_NAME}\")\n self.logger.info(f\" 上下文: {'开启' if self.config.get('context_aware') else '关闭'}\")\n self.logger.info(\"=\" * 50)\n self.logger.info(\"按 Ctrl+C 停止服务...\")\n \n self.server = create_ipc_server(IPC_NAME)\n \n try:\n self.server.run(self.handler.handle)\n except KeyboardInterrupt:\n pass\n finally:\n self.stop()\n \n def stop(self):\n \"\"\"停止服务\"\"\"\n if self.server:\n self.server.stop()\n self.server.cleanup()\n self.logger.info(\"服务已停止\")\n\n\n# ============ 主函数 ============\n\ndef main():\n parser = argparse.ArgumentParser(description=\"Rime AI 服务\")\n parser.add_argument(\"--config\", \"-c\", type=str, help=\"配置文件路径\")\n parser.add_argument(\"--debug\", \"-d\", action=\"store_true\", help=\"开启调试模式\")\n args = parser.parse_args()\n \n config = load_config(args.config)\n \n # 命令行 debug 优先\n if args.debug:\n config[\"debug\"] = True\n \n logger = setup_logging(config.get(\"debug\", False))\n \n if not config.get(\"api_key\"):\n logger.warning(\"=\" * 50)\n logger.warning(\"警告: 现已使用博主bzx的api_key\")\n logger.warning(\"有能力者请编辑配置文件改用自己的api_key!\")\n logger.warning(\"=\" * 50)\n \n service = BzxService(config, logger)\n \n def signal_handler(sig, frame):\n service.stop()\n sys.exit(0)\n \n signal.signal(signal.SIGINT, signal_handler)\n signal.signal(signal.SIGTERM, signal_handler)\n \n service.start()\n\n\nif __name__ == \"__main__\":\n main()\n"}}}} |