我用 Python 搭了一套知识管理系统:从零散笔记到结构化知识库,AI 帮我自动整理
适合有大量零散笔记/文档/收藏,想让 AI 帮忙整理成结构化知识库的人。
本文提供完整的 Python 代码,从文件扫描、分类、摘要到知识图谱,全程自动化。
问题:笔记越来越多,找东西越来越难
我有 200+ 篇笔记,分散在不同文件夹、不同格式(Markdown、TXT、PDF、网页收藏)。每次想找某个话题的资料,要在 5 个地方搜索,经常找不到。
根本原因是:笔记没有结构化。文件名不统一、没有标签、没有分类、没有关联。
后来我用 Python + AI 搭了一套知识管理系统,自动完成这些事情:
- 扫描所有笔记文件
- AI 自动提取关键词和摘要
- 自动分类到对应目录
- 自动建立笔记之间的关联
- 生成知识图谱可视化
系统架构
文件扫描 → 内容提取 → AI 分类 → 自动整理 → 知识图谱模块 1:文件扫描与内容提取
扫描指定目录下的所有文件,提取文本内容。
importosfrompathlibimportPathdefscan_files(root_dir,extensions=(".md",".txt",".py",".json")):"""扫描目录下所有指定类型的文件"""files=[]forextinextensions:files.extend(Path(root_dir).rglob(f"*{ext}"))print(f"扫描完成,找到{len(files)}个文件")returnfilesdefextract_content(file_path):"""提取文件内容"""path=Path(file_path)ext=path.suffix.lower()ifextin(".md",".txt",".py",".json",".yaml"):returnpath.read_text(encoding="utf-8",errors="ignore")elifext==".pdf":# 需要 PyPDF2 或 pdfplumbertry:importPyPDF2 reader=PyPDF2.PdfReader(str(path))return"\n".join(page.extract_text()or""forpageinreader.pages)exceptImportError:print(f"需要安装 PyPDF2: pip install PyPDF2")return""else:return""模块 2:AI 自动提取关键词和摘要
fromopenaiimportOpenAI client=OpenAI()defextract_metadata(content,max_content=2000):"""用 AI 提取关键词、摘要、分类"""# 截取前 max_content 字符truncated=content[:max_content]prompt=f"""分析以下文本,返回 JSON 格式的元数据: 文本:{truncated}返回格式: {{ "title": "文章标题(如果没有明确标题就根据内容生成一个)", "summary": "50字以内的摘要", "keywords": ["关键词1", "关键词2", "关键词3"], "category": "分类(技术/方法论/复盘/工具/其他)", "tags": ["标签1", "标签2"] }}"""response=client.chat.completions.create(model="gpt-4",messages=[{"role":"user","content":prompt}],temperature=0.3)importjsontry:returnjson.loads(response.choices[0].message.content)exceptjson.JSONDecodeError:return{"title":"","summary":"","keywords":[],"category":"其他","tags":[]}模块 3:自动分类整理
根据 AI 提取的分类,自动移动文件到对应目录。
importshutildefauto_organize(files,metadata_map,output_dir):"""根据 AI 分类自动整理文件"""category_dirs={"技术":"01_技术","方法论":"02_方法论","复盘":"03_复盘","工具":"04_工具","其他":"05_其他",}forfile_pathinfiles:meta=metadata_map.get(str(file_path),{})category=meta.get("category","其他")target_dir=Path(output_dir)/category_dirs.get(category,"05_其他")target_dir.mkdir(parents=True,exist_ok=True)# 重命名:标题_原文件名title=meta.get("title","")iftitle:new_name=f"{title[:30]}_{Path(file_path).name}"else:new_name=Path(file_path).name target=target_dir/new_name shutil.copy2(str(file_path),str(target))print(f"整理:{Path(file_path).name}→{category}/{new_name}")模块 4:生成知识图谱
分析笔记之间的关键词关联,生成可视化知识图谱。
defbuild_knowledge_graph(metadata_map):"""基于关键词关联构建知识图谱"""# 收集所有关键词keyword_to_docs={}fordoc_path,metainmetadata_map.items():forkwinmeta.get("keywords",[])+meta.get("tags",[]):ifkwnotinkeyword_to_docs:keyword_to_docs[kw]=[]keyword_to_docs[kw].append(doc_path)# 找到共享关键词的文档对edges=[]keywords_list=list(keyword_to_docs.keys())foriinrange(len(keywords_list)):forjinrange(i+1,len(keywords_list)):kw1,kw2=keywords_list[i],keywords_list[j]shared=set(keyword_to_docs[kw1])&set(keyword_to_docs[kw2])iflen(shared)>=2:# 至少共享 2 篇文档edges.append((kw1,kw2,len(shared)))# 按关联强度排序edges.sort(key=lambdax:x[2],reverse=True)returnedges[:50]# 取 top 50 条关联模块 5:生成 Markdown 索引
defgenerate_index(metadata_map,output_path):"""生成知识库的 Markdown 索引文件"""lines=["# 知识库索引\n"]lines.append(f"共{len(metadata_map)}篇文档\n\n")# 按分类分组by_category={}forpath,metainmetadata_map.items():cat=meta.get("category","其他")ifcatnotinby_category:by_category[cat]=[]by_category[cat].append((path,meta))forcategory,docsinsorted(by_category.items()):lines.append(f"##{category}({len(docs)}篇)\n\n")forpath,metaindocs:title=meta.get("title",Path(path).stem)summary=meta.get("summary","")keywords=", ".join(meta.get("keywords",[])[:5])lines.append(f"###{title}\n")lines.append(f"- **摘要**:{summary}\n")lines.append(f"- **关键词**:{keywords}\n")lines.append(f"- **文件**: `{Path(path).name}`\n\n")Path(output_path).write_text("".join(lines),encoding="utf-8")print(f"索引已生成:{output_path}")完整运行
defrun_knowledge_system(root_dir,output_dir):"""完整知识管理流程"""print("📂 Step 1: 扫描文件...")files=scan_files(root_dir)print("\n🤖 Step 2: AI 提取元数据...")metadata_map={}fori,file_pathinenumerate(files):content=extract_content(file_path)ifcontent:meta=extract_metadata(content)metadata_map[str(file_path)]=metaprint(f" [{i+1}/{len(files)}]{file_path.name}→{meta.get('category','?')}")print("\n📁 Step 3: 自动分类整理...")auto_organize(files,metadata_map,output_dir)print("\n📊 Step 4: 生成知识图谱...")graph=build_knowledge_graph(metadata_map)print(f" 找到{len(graph)}条关联")print("\n📝 Step 5: 生成索引...")generate_index(metadata_map,os.path.join(output_dir,"INDEX.md"))print("\n✅ 知识库整理完成!")# 运行run_knowledge_system(r"C:\my_notes",r"C:\knowledge_base")踩坑记录
坑 1:AI 分类不稳定
症状:同一篇笔记,运行两次分类结果不一样(一次是"技术",一次是"方法论")。
原因:temperature 太高,AI 输出不确定。
解决:把 temperature 设为 0.3 以下,保证输出稳定。
坑 2:大文件提取摘要超时
症状:50MB 的文件提取内容时 API 超时。
原因:文件太大,截取后仍然很长。
解决:大文件只取前 2000 字符,或者分段提取后合并。
坑 3:PDF 中文乱码
症状:提取 PDF 内容时中文全是乱码。
原因:PDF 是扫描件(图片),不是文本 PDF。
解决:扫描件 PDF 需要用 OCR(如 pytesseract),纯文本 PDF 用 PyPDF2。
坑 4:知识图谱太密
症状:关键词关联太多,图谱变成一团乱麻。
原因:关联阈值太低,任何两个关键词都有关联。
解决:提高阈值(至少共享 3 篇文档),或者只取 top 30 条关联。
坑 5:API 成本太高
症状:200 篇笔记每篇调一次 GPT-4,费用超过预期。
原因:GPT-4 API 价格高。
解决:用 GPT-3.5-turbo 做初步分类,只对"不确定"的用 GPT-4 二次确认。
总结
3 条核心经验:
先扫描再整理。不要一上来就改文件结构,先扫描一遍看看有多少文件、什么类型、分布在哪,再决定怎么整理。
AI 分类要加约束。不限定分类类别,AI 会给出几十种分类,根本没法用。明确告诉它"只有这 5 个类别"。
索引比分类更重要。文件放哪个目录其实不关键,关键是能快速搜索到。生成 Markdown 索引 + 关键词标签,比按目录分类更实用。
你有多少零散笔记?有没有遇到找资料困难的问题?评论区聊聊。