import sys, os, json sys.path.insert(0, "/home/ubuntu/inspiration-collector") from tools.config import load_secrets, get_output_dir from tools.llm import DeepSeekClient from tools.memos_client import MemosClient from datetime import datetime, timezone, timedelta import subprocess secrets = load_secrets() mc = MemosClient(secrets.get("memos_url", "http://localhost:5230"), secrets["memos_token"]) llm = DeepSeekClient(secrets["deepseek_api_key"], secrets.get("deepseek_model", "deepseek-chat"), temperature=0.7, max_retries=5) TZ_BJ = timezone(timedelta(hours=8)) VAULT = "/home/ubuntu/obsidian-vault" def read_vault_sample(): parts = [] dirs_to_read = [ "01 写作/随笔", "03 日志/日省录", "03 日志/交易日志", "00 Inbox", "05 投资交易", "02 阅读学习/微信读书阅读摘录" ] for rel in dirs_to_read: d = os.path.join(VAULT, rel) if not os.path.isdir(d): continue files = sorted([f for f in os.listdir(d) if f.endswith(".md")]) for fname in files[:5]: fpath = os.path.join(d, fname) try: with open(fpath, "r", encoding="utf-8", errors="ignore") as f: c = f.read() if c.startswith("---"): idx = c.find("---", 3) if idx != -1: c = c[idx+3:].strip() if len(c) > 1500: c = c[:1500] + "\n...[截断]" parts.append("### " + fname + "\n\n" + c) except: pass return "\n\n".join(parts) # Also read key philosophical/life reflection pieces def read_key_writings(): key_files = [ "01 写作/随笔/朝闻道,夕死可矣之我见.md", "01 写作/随笔/君子不立危墙之下.md", "01 写作/随笔/我曾在魔窟走过一遭.md", "01 写作/随笔/很多人的一生,就是狗生.md", "01 写作/随笔/长时间的深入思考,才有可能灵光一闪.md", "01 写作/个人修养十八字.md", "01 写作/我的个人规则.md", "01 写作/道之既出,淡乎其无味.md", ] parts = [] for rel in key_files: fp = os.path.join(VAULT, rel) if not os.path.isfile(fp): continue try: with open(fp, "r", encoding="utf-8", errors="ignore") as f: c = f.read() if c.startswith("---"): idx = c.find("---", 3) if idx != -1: c = c[idx+3:].strip() if len(c) > 2000: c = c[:2000] + "\n...[截断]" parts.append("### " + rel + "\n\n" + c) except: pass return "\n\n".join(parts) memos_raw = mc.list_memos(days=30) memo_texts = [] for m in memos_raw: ct = m["created_at"] try: dt = datetime.fromisoformat(ct.replace("Z", "+00:00")) + timedelta(hours=8) ts = dt.strftime("%m/%d %H:%M") except: ts = ct[:16] memo_texts.append("- [" + ts + "] " + m["content"].strip()) memo_block = "\n".join(memo_texts[-50:]) print("Reading vault...") vault_sample = read_vault_sample() key_writings = read_key_writings() prompt = "以下是一个人的全部思想素材——他的私人写作、哲学思考、阅读笔记、日常灵感。请基于这些素材进行深度人格分析。\n\n" prompt += "## 一、代表性随笔与哲学思考\n\n" + key_writings + "\n\n" prompt += "## 二、文库代表性笔记\n\n" + vault_sample[:8000] + "\n\n" prompt += "## 三、近期灵感碎片\n\n" + memo_block + "\n\n" prompt += "请从三个维度回答:\n\n" prompt += "### 1. 人格素描\n" prompt += "用500字左右描述这个人的核心人格特征——他的动力来源、思维模式、情感模式、与世界互动的方式。不要套用MBTI标签,用他自己的语言和事例说话。\n\n" prompt += "### 2. 最适合的哲学流派与作者\n" prompt += "分析他天然亲近哪个哲学流派(存在主义?斯多葛?道家?儒家?尼采?),以及哪位作者的思想与他最为共振。要给出具体理由,引用他原文中的证据。\n\n" prompt += "### 3. 生命之书类比\n" prompt += "如果有人把他的思想、经历、感悟编撰成一本书,这本书会和市面上哪本现成的书最为相似?可以是小说、哲学著作、传记、随笔集。分析相似之处和差异。\n\n" prompt += "请输出纯Markdown,字数不限,但务必有实质、有证据、有引用。" sp = "你是一个深度的文本分析者和人格解读者。你将从一个人的全部写作素材中,提炼出他的人格内核、哲学倾向和思想谱系。用他的原文作为证据,不要泛泛而谈。输出纯Markdown。" print("Calling DeepSeek API...") result = llm.ask(system_prompt=sp, user_prompt=prompt) date = datetime.now(timezone.utc) now_bj = datetime.now(TZ_BJ) content = "---\ndate: " + date.strftime("%Y-%m-%d") + "\ntype: personality-deep\ntags: [人格分析, 哲学, 深度解读]\n---\n\n" content += result daily_dir = os.path.join(get_output_dir("daily"), date.strftime("%Y-%m-%d")) os.makedirs(daily_dir, exist_ok=True) now_str = now_bj.strftime("%H%M%S") fname = date.strftime("%Y-%m-%d") + "_personality_deep_" + now_str + ".md" fpath = os.path.join(daily_dir, fname) with open(fpath, "w", encoding="utf-8") as f: f.write(content) print("Done: " + fpath + " (" + str(len(result)) + " chars)") proj = "/home/ubuntu/inspiration-collector" subprocess.run(["git", "add", fpath], cwd=proj, capture_output=True, timeout=15) subprocess.run(["git", "commit", "-m", "deep personality analysis " + now_str], cwd=proj, capture_output=True, timeout=15) subprocess.run(["git", "push", "origin", "main"], cwd=proj, capture_output=True, timeout=30) print("Pushed")