"""Step 6: 更新知识库(Obsidian + 知识图谱)""" import json, os, sys from datetime import datetime from collections import defaultdict sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from paths import LINKS_DIR, DATA_DIR, DOCS_DIR, OBSIDIAN_DIR, KG_DIR def safe_name(n): for c in '<>:"/\\|?*': n=n.replace(c,'_') return n[:80] def w(path, content): os.makedirs(os.path.dirname(path), exist_ok=True) with open(path,"w",encoding="utf-8") as f: f.write(content) def load_json(p): if not os.path.isfile(p): return None with open(p,"r",encoding="utf-8") as f: return json.load(f) def main(): content = load_json(os.path.join(LINKS_DIR,"all_feishu_content.json")) or {} messages = load_json(os.path.join(DATA_DIR,"raw-messages","all_messages_combined.json")) or {} docs = content.get("documents",[]) print(f"文档: {len(docs)}, 消息: {sum(len(v) for v in messages.values())}") # Obsidian by_group = defaultdict(list) for d in docs: by_group[d.get("group","未分组")].append(d) by_sender = defaultdict(list) for d in docs: by_sender[d.get("sender","?")].append(d) moc = ["---","tags: [MOC, 飞书文档]",f"created: {datetime.now().strftime('%Y-%m-%d')}","---","","# 飞书文档知识库","",f"> 更新: {datetime.now().strftime('%Y-%m-%d %H:%M')}",""] for grp, gd in sorted(by_group.items()): moc.append(f"## {grp}") for d in sorted(gd,key=lambda x:x.get("time",""),reverse=True): t = d.get("title","") or d.get("doc_id","") moc.append(f"- [[{safe_name(t)}]] ({d.get('sender','?')}, {d.get('time','')})") moc.append("") w(os.path.join(OBSIDIAN_DIR,"00-MOC","飞书文档索引.md"),"\n".join(moc)) for sender, sd in sorted(by_sender.items()): lines = ["---",f"tags: [人物, {sender}]","---",f"# {sender}",f"\n贡献: {len(sd)} 篇\n"] for d in sorted(sd,key=lambda x:x.get("time",""),reverse=True): t = d.get("title","") or d.get("doc_id","") lines.append(f"- [[{safe_name(t)}]] ({d.get('time','')})") w(os.path.join(OBSIDIAN_DIR,"04-人物",f"{safe_name(sender)}.md"),"\n".join(lines)) for d in docs: did = d.get("doc_id","") fpath = os.path.join(DOCS_DIR,f"{did}.md") if not os.path.isfile(fpath): continue with open(fpath,"r",encoding="utf-8") as f: c = f.read() t = d.get("title","") or did fm = ["---",f"tags: [飞书文档, {d.get('group','')}]",f"sender: {d.get('sender','')}",f"date: {d.get('time','')}",f"source: {d.get('url','')}","---",""] w(os.path.join(OBSIDIAN_DIR,"01-产品研究",f"{safe_name(t)}.md"),"\n".join(fm)+c) print(f" Obsidian: {len(docs)} 文档, {len(by_sender)} 人物") # 知识图谱 nodes, edges, nids = [], [], set() for s in {d.get("sender","") for d in docs} | {m.get("sender","") for msgs in messages.values() for m in msgs}: if s: nid=f"person:{s}"; nodes.append({"id":nid,"type":"person","label":s}); nids.add(nid) for d in docs: did,t = d.get("doc_id",""), d.get("title","") or d.get("doc_id","") nid = f"doc:{did}" if nid not in nids: nodes.append({"id":nid,"type":"document","label":t[:50]}); nids.add(nid) s = d.get("sender","") if s: edges.append({"source":f"person:{s}","target":nid,"type":"authored"}) g = d.get("group","") if g: gid=f"group:{g}" if gid not in nids: nodes.append({"id":gid,"type":"group","label":g}); nids.add(gid) edges.append({"source":gid,"target":nid,"type":"contains"}) os.makedirs(KG_DIR, exist_ok=True) with open(os.path.join(KG_DIR,"knowledge_graph.json"),"w",encoding="utf-8") as f: json.dump({"date":datetime.now().strftime("%Y-%m-%d"),"nodes":nodes,"edges":edges},f,ensure_ascii=False,indent=2) print(f" 图谱: {len(nodes)} 节点, {len(edges)} 关系") if __name__ == "__main__": main()