import os import glob import time import threading from concurrent.futures import ThreadPoolExecutor, as_completed from openai import OpenAI api_key = input("Enter SiliconFlow API Key (sk-xxxx): ").strip() client = OpenAI( api_key=api_key, base_url="https://api.siliconflow.cn/v1" ) MODEL_NAME = "Qwen/Qwen2.5-72B-Instruct" book_dir = "./docs" output_dir = "./life-skill" os.makedirs(os.path.join(output_dir, "chapters"), exist_ok=True) md_files = sorted(glob.glob(os.path.join(book_dir, "**", "*.md"), recursive=True)) if not md_files: md_files = sorted(glob.glob("./*.md")) total = len(md_files) print(f"Detected {total} files to process...") lock = threading.Lock() finished = 0 def is_rate_limited(e): status = getattr(e, "status_code", None) if status is None: status = getattr(e, "status", None) if status is None and getattr(e, "response", None) is not None: status = getattr(e.response, "status_code", None) code = getattr(e, "code", None) if code is None: code = getattr(e, "error", None) code = getattr(code, "code", None) if code is not None else None msg = str(getattr(e, "message", "") or getattr(e, "error", "") or e) lowered = msg.lower() if status not in (None, 200): if int(status) == 429: return True if code is not None and "rate_limit" in str(code).lower(): return True if "429" in msg: return True if "rate limit" in lowered or "ratelimit" in lowered: return True return False def create_completion_with_retry(prompt, max_retries=5): delay = 3 for attempt in range(max_retries + 1): try: resp = client.chat.completions.create( model=MODEL_NAME, messages=[{"role": "user", "content": prompt}], temperature=0.3 ) return resp.choices[0].message.content except Exception as e: if attempt >= max_retries or not is_rate_limited(e): raise with lock: print( f"Rate limited, retrying in {delay}s " f"(attempt {attempt + 1}/{max_retries}) ..." ) time.sleep(delay) delay = delay * 2 raise RuntimeError("unreachable") def process_chapter(file_path): global finished file_name = os.path.basename(file_path) if file_name in ["README.md", "SUMMARY.md"]: return None out_file = os.path.join(output_dir, "chapters", file_name) if os.path.exists(out_file) and os.path.getsize(out_file) > 0: with lock: finished += 1 print(f"[{finished}/{total}] Skipped (already exists): {file_name}") return out_file try: with open(file_path, "r", encoding="utf-8") as f: content = f.read() except Exception: return None prompt = ( "你是一个顶级的知识架构工程师。请将以下《高性价比人生指南》章节内容精炼为适合 AI Agent 调用的技能参考模块。\n" "要求:\n" "1. 提取出核心原则、硬核决策卡尺、避免踩坑清单、核心执行步骤。\n" "2. 保留具体的量化标准(如成本、具体法条或医保操作)。\n" "3. 语言精炼,按 Markdown 输出,去掉冗余闲聊。\n\n" f"章节原始内容:\n{content[:15000]}" ) try: result_text = create_completion_with_retry(prompt) with open(out_file, "w", encoding="utf-8") as f: f.write(result_text) time.sleep(0.5) with lock: finished += 1 print(f"[{finished}/{total}] Finished: {file_name}") return out_file except Exception as e: with lock: print(f"Error processing {file_name}: {e}") return None completed_files = [] with ThreadPoolExecutor(max_workers=2) as executor: futures = {executor.submit(process_chapter, fp): fp for fp in md_files} for future in as_completed(futures): result = future.result() if result: completed_files.append(os.path.basename(result)) print("Generating master index SKILL.md ...") summaries = [] if os.path.isdir(os.path.join(output_dir, "chapters")): for file_name in sorted(os.listdir(os.path.join(output_dir, "chapters"))): chap_path = os.path.join(output_dir, "chapters", file_name) if os.path.isfile(chap_path) and os.path.getsize(chap_path) > 0: summaries.append(f"- [{file_name}](chapters/{file_name})") skill_content = ( "---\n" "name: high-cost-performance-life-guide\n" "description: Evidence-based high-ROI life decision rules covering health, law, finance, career, and housing\n" "---\n\n" "# 高性价比人生指南技能包\n\n" "模块工序索引:\n\n" + "\n".join(summaries) ) with open(os.path.join(output_dir, "SKILL.md"), "w", encoding="utf-8") as f: f.write(skill_content) print("All tasks finished successfully! Output saved in ./life-skill")