折腾侠
项目实战

从零到一构建 AI 驱动的个人知识管理系统:一个全栈实战项目

本文记录了我如何用 3 周时间,从 0 到 1 构建一个 AI 驱动的个人知识管理系统(PKM)。涵盖需求分析、技术选型、架构设计、核心功能实现、部署上线全流程。代码开源,可直接复用。

折腾侠
2026/03/16 发布
17约 11 分钟1963 字 / 1413 词00

从零到一构建 AI 驱动的个人知识管理系统:一个全栈实战项目

本文记录了我如何用 3 周时间,从 0 到 1 构建一个 AI 驱动的个人知识管理系统(PKM)。涵盖需求分析、技术选型、架构设计、核心功能实现、部署上线全流程。代码开源,可直接复用。


一、为什么需要构建自己的知识管理系统

1.1 知识工作者的痛点

2026 年的今天,我们每天面对的信息量是十年前的数十倍:

  • 碎片化严重:微信文章、Twitter 推文、Slack 讨论、会议记录、代码片段... 信息散落在 10+ 个平台
  • 检索困难:「我记得看过这篇文章,但就是找不到」—— 这种挫败感每周至少发生 3 次
  • 知识孤岛:收藏 = 学会?Notion 里躺着的 500+ 页面,真正被复用的不到 10%
  • 缺乏连接:知识点之间是孤立的,无法形成知识网络,难以产生洞察

1.2 现有方案的局限

我尝试过几乎所有主流方案:

工具优点缺点
Notion功能强大、模板丰富检索弱、AI 功能需额外付费、数据在云端
Obsidian本地存储、双向链接移动端体验差、AI 插件配置复杂
Logseq大纲友好、开源性能问题、生态较小
Heptabase视觉化好付费较高、自定义有限
Mem.aiAI 原生国内访问慢、数据隐私顾虑

核心问题:没有一个方案能同时满足「本地优先 + AI 原生 + 完全可控 + 开源免费」。

1.3 我的需求清单

决定自己动手后,我列出了 Must-Have 功能:

  1. 智能采集:一键保存网页、PDF、微信文章,自动提取正文
  2. AI 自动标签:上传内容后自动分析主题、生成标签、提取关键词
  3. 语义检索:支持自然语言提问,如「找一下关于 React 性能优化的文章」
  4. 知识图谱:可视化展示知识之间的关联
  5. 本地优先:数据存储在本地,支持端到端加密同步
  6. 开放 API:可与其他工具集成(如自动同步 GitHub Issues、Twitter 书签)

二、技术选型:2026 年的全栈方案

2.1 整体架构

┌─────────────────────────────────────────────────────────┐
│                     Frontend                            │
│  Next.js 15 + React 19 + TailwindCSS + shadcn/ui       │
└─────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────┐
│                     Backend                             │
│  Hono (Edge-ready) + TypeScript + Bun Runtime          │
└─────────────────────────────────────────────────────────┘
                            ↓
        ┌───────────────────┴───────────────────┐
        ↓                                       ↓
┌───────────────────┐               ┌───────────────────┐
│   PostgreSQL 17   │               │   Qdrant Vector   │
│   (主数据存储)    │               │   DB (语义检索)   │
└───────────────────┘               └───────────────────┘
        ↓                                       ↓
┌───────────────────┐               ┌───────────────────┐
│   Local Storage   │               │   AI Services     │
│   (加密同步)      │               │   (Ollama/本地)   │
└───────────────────┘               └───────────────────┘

2.2 核心选型决策

前端:Next.js 15 + React 19

为什么不是纯静态?

  • 需要 SSR 支持知识图谱的动态渲染
  • React 19 的 INLINE_CODE_0 和 Server Components 大幅减少客户端 JS
  • Next.js 15 的 Turbopack 开发速度极快(冷启动 <500ms)

UI 组件库:shadcn/ui

  • 完全可控的代码(不是黑盒 npm 包)
  • 基于 Radix UI,无障碍支持完善
  • 与 TailwindCSS 无缝集成

后端:Hono + Bun

为什么不是 Node.js + Express?

指标Node + ExpressBun + Hono
冷启动~800ms~50ms
内存占用~150MB~40MB
TypeScript需要 tsc 编译原生支持
API 兼容性OpenAPI 需额外配置内置 OpenAPI 生成

Hono 的 Edge-ready 特性让未来部署到 Cloudflare Workers 成为可能。

数据库:PostgreSQL 17 + Qdrant

PostgreSQL 17 新特性利用

  • JSONB 索引优化:存储非结构化元数据
  • 增量物化视图:知识图谱预计算
  • pgvector 扩展:基础向量检索(备用方案)

Qdrant 向量数据库

  • 专为语义检索设计,支持 HNSW 索引
  • 内置过滤查询(filter + vector search)
  • Rust 编写,性能卓越(单节点 100 万向量 <10ms)

AI 层:本地优先策略

方案对比

方案成本隐私延迟质量
OpenAI API$0.01/请求数据出境~500ms⭐⭐⭐⭐⭐
Claude API$0.03/请求数据出境~800ms⭐⭐⭐⭐⭐
Ollama (本地)免费完全本地~2s⭐⭐⭐⭐
LM Studio免费完全本地~1.5s⭐⭐⭐⭐

最终选择:Ollama + Qwen2.5-7B-Instruct

  • 7B 模型在 M2 Mac 上推理速度 ~20 tokens/s
  • 中文能力优秀(阿里出品)
  • 支持函数调用(用于自动标签提取)

三、核心功能实现

3.1 智能采集器

目标:一键保存任意网页,自动提取正文和元数据。

TypeScript
// src/services/content-extractor.ts
import { Readability } from '@mozilla/readability';
import { JSDOM } from 'jsdom';

export async function extractContent(url: string) {
  const response = await fetch(url, {
    headers: { 'User-Agent': 'PKM-Bot/1.0' }
  });
  const html = await response.text();
  
  const dom = new JSDOM(html, { url });
  const reader = new Readability(dom.window.document);
  const article = reader.parse();
  
  // AI 自动提取元数据
  const metadata = await extractMetadata(article.content, url);
  
  return {
    title: article.title,
    content: article.content,
    textContent: article.textContent,
    url,
    publishedAt: metadata.publishedAt,
    author: metadata.author,
    siteName: metadata.siteName,
    savedAt: new Date().toISOString()
  };
}

async function extractMetadata(content: string, url: string) {
  // 调用本地 Ollama 模型
  const response = await fetch('http://localhost:11434/api/generate', {
    method: 'POST',
    body: JSON.stringify({
      model: 'qwen2.5:7b',
      prompt: `分析以下内容,提取元数据(JSON 格式):
      URL: ${url}
      内容前 2000 字:${content.slice(0, 2000)}
      
      返回格式:
      {
        "author": string | null,
        "publishedAt": ISO8601 | null,
        "siteName": string
      }`
    })
  });
  
  return await response.json();
}

效果

  • 自动识别文章标题、作者、发布时间
  • 过滤广告、导航、评论区等噪声
  • 支持微信公众号、知乎、Medium 等常见平台

3.2 AI 自动标签系统

核心思路:使用函数调用让 AI 结构化输出标签。

TypeScript
// src/services/auto-tagger.ts
interface TagSuggestion {
  primaryTag: string;      // 主分类,如 "前端开发"
  subTags: string[];       // 子标签,如 ["React", "性能优化"]
  entities: string[];      // 提取的实体,如 ["Next.js", "Vercel"]
  summary: string;         // 一句话摘要
  difficulty: 'beginner' | 'intermediate' | 'advanced';
}

export async function generateTags(content: string): Promise<TagSuggestion> {
  const prompt = `
你是一个专业的知识管理助手。请分析以下内容,提取结构化标签信息。

内容:
${content.slice(0, 4000)}

请严格按照以下 JSON Schema 返回:
{
  "primaryTag": "主分类(从以下选择:前端开发/后端开发/DevOps/AI 技术/产品设计/职业发展)",
  "subTags": ["最多 5 个子标签"],
  "entities": ["文中提到的技术/工具/人名,最多 10 个"],
  "summary": "50 字以内的摘要",
  "difficulty": "文章难度级别"
}
`;

  const response = await fetch('http://localhost:11434/api/generate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      model: 'qwen2.5:7b',
      prompt,
      format: 'json'
    })
  });
  
  return await response.json();
}

实际效果示例

输入:一篇关于 React Server Components 的技术文章

输出:

JSON
{
  "primaryTag": "前端开发",
  "subTags": ["React", "Server Components", "Next.js"],
  "entities": ["React 19", "Next.js 15", "Vercel", "Dan Abramov"],
  "summary": "介绍 React Server Components 的核心概念、使用场景及与 Client Components 的区别",
  "difficulty": "intermediate"
}

3.3 语义检索:用自然语言找知识

技术栈:Qdrant + 本地 Embedding 模型

TypeScript
// src/services/semantic-search.ts
import { QdrantClient } from '@qdrant/js-client-rest';

const qdrant = new QdrantClient({
  url: 'http://localhost:6333',
});

// 使用本地 Embedding 模型(bge-m3)
async function generateEmbedding(text: string): Promise<number[]> {
  const response = await fetch('http://localhost:11434/api/embeddings', {
    method: 'POST',
    body: JSON.stringify({
      model: 'bge-m3',
      prompt: text
    })
  });
  const data = await response.json();
  return data.embedding;
}

export async function semanticSearch(
  query: string,
  filters?: { tags?: string[]; dateRange?: [string, string] }
) {
  const queryVector = await generateEmbedding(query);
  
  const results = await qdrant.search('knowledge', {
    vector: queryVector,
    limit: 10,
    filter: {
      must: [
        ...(filters?.tags?.map(tag => ({
          key: 'tags',
          match: { value: tag }
        })) || []),
        ...(filters?.dateRange ? [{
          key: 'savedAt',
          range: {
            gte: filters.dateRange[0],
            lte: filters.dateRange[1]
          }
        }] : [])
      ]
    }
  });
  
  return results.map(r => ({
    id: r.id,
    score: r.score,
    ...r.payload
  }));
}

使用示例

用户输入:「找一下关于 React 性能优化的文章」

系统执行:
1. 将查询转换为向量
2. 在 Qdrant 中搜索相似内容
3. 返回最相关的 10 篇文章

结果:
1. 《React 性能优化实战:从 3s 到 300ms》(相似度 0.89)
2. 《使用 useMemo 和 useCallback 的正确姿势》(相似度 0.85)
3. 《Next.js 图片优化完整指南》(相似度 0.78)

3.4 知识图谱可视化

技术选型:React Flow + 自定义布局算法

TypeScript
// src/components/KnowledgeGraph.tsx
import ReactFlow, { Node, Edge } from 'reactflow';
import { useForceGraph } from '../hooks/useForceGraph';

interface KnowledgeNode {
  id: string;
  label: string;
  type: 'article' | 'tag' | 'entity';
  metadata: {
    savedAt: string;
    tags: string[];
  };
}

export function KnowledgeGraph({ articles }: { articles: Article[] }) {
  // 构建节点和边
  const { nodes, edges } = useForceGraph(articles);
  
  return (
    <div className="h-[600px] border rounded-lg">
      <ReactFlow
        nodes={nodes}
        edges={edges}
        fitView
        attributionPosition="bottom-left"
        nodeTypes={{
          article: ArticleNode,
          tag: TagNode,
          entity: EntityNode
        }}
      />
    </div>
  );
}

// 力导向布局:相关知识点自动聚集
function useForceGraph(articles: Article[]) {
  // 使用 d3-force 进行布局计算
  // 文章节点根据共同标签/实体产生吸引力
  // 标签节点作为枢纽连接相关文章
  ...
}

可视化效果

  • 文章节点:圆形,大小表示重要性(被引用次数)
  • 标签节点:六边形,颜色表示分类
  • 实体节点:方形,边框颜色表示类型(工具/框架/人物)
  • 连线:表示关联关系,粗细表示关联强度

四、部署与运维

4.1 本地开发环境

Bash
# 1. 克隆项目
git clone https://github.com/your-username/ai-pkm.git
cd ai-pkm

# 2. 安装依赖
bun install

# 3. 启动数据库(Docker Compose)
docker compose up -d postgres qdrant

# 4. 启动 AI 服务
ollama pull qwen2.5:7b
ollama pull bge-m3
ollama serve

# 5. 启动开发服务器
bun run dev

# 访问 http://localhost:3000

4.2 生产部署方案

方案 A:VPS 部署(推荐)

YAML
# docker-compose.prod.yml
version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://...
      - QDRANT_URL=http://qdrant:6333
      - OLLAMA_URL=http://ollama:11434
    depends_on:
      - postgres
      - qdrant
  
  postgres:
    image: postgres:17
    volumes:
      - pgdata:/var/lib/postgresql/data
  
  qdrant:
    image: qdrant/qdrant
    volumes:
      - qdrant_data:/qdrant/storage
  
  ollama:
    image: ollama/ollama
    volumes:
      - ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

volumes:
  pgdata:
  qdrant_data:
  ollama_data:

成本估算(2026 年价格):

资源配置月成本
VPS4 核 8G + 100G SSD¥150
GPU(可选)T4 × 1¥300
域名 + SSL-¥50
合计-¥500/月

方案 B:边缘部署(低成本)

  • 前端:Vercel(免费)
  • 后端 API:Cloudflare Workers($5/月)
  • 数据库:Neon PostgreSQL(免费 tier)
  • 向量库:Qdrant Cloud($20/月)
  • AI:Ollama 本地运行(免费)

合计:$25/月(约 ¥180)

4.3 数据备份策略

Bash
#!/bin/bash
# backup.sh - 每日自动备份

# 1. PostgreSQL 备份
pg_dump $DATABASE_URL | gzip > backups/pg-$(date +%Y%m%d).sql.gz

# 2. Qdrant 快照
curl -X POST http://localhost:6333/collections/knowledge/snapshots \
  -o backups/qdrant-$(date +%Y%m%d).snapshot

# 3. 加密同步到云存储(可选)
rclone sync backups/ encrypted-remote:/pkm-backups \
  --crypt-remote-password=$ENCRYPTION_KEY

# 4. 保留最近 30 天
find backups/ -mtime +30 -delete

五、项目成果与反思

5.1 三周开发时间线

周次完成内容工时
Week 1需求分析、技术选型、基础架构搭建20h
Week 2核心功能开发(采集、标签、检索)25h
Week 3UI 优化、知识图谱、部署上线15h
合计-60h

5.2 使用效果(上线 1 个月后)

  • 采集文章:127 篇
  • 自动标签准确率:~85%(需要手动修正的约 15%)
  • 检索满意度:语义检索命中率 ~90%
  • 知识复用:通过图谱发现 12 组之前未注意到的关联

5.3 踩过的坑

  1. 向量维度不匹配:Qdrant 集合创建后无法修改维度,需提前规划
  2. Ollama 并发限制:默认单请求,需配置 INLINE_CODE_1 参数
  3. 中文分词问题:初期标签提取把「React Hooks」分成两个标签,后改为实体识别
  4. 知识图谱性能:文章超过 500 篇后渲染变慢,改为虚拟滚动 + 按需加载

5.4 未来规划

  • 移动端 App(React Native)
  • 浏览器插件(一键保存 + 高亮批注)
  • 多人协作版本(团队知识库)
  • 自动化工作流(如:每天自动推送「去年今日」的文章)

六、开源与复用

项目已开源:https://github.com/your-username/ai-pkm

你可以

  • Fork 后自行部署
  • 提交 Issue 和 PR
  • 基于此项目构建自己的变体

许可证:MIT(完全免费,可商用)


结语

构建这个系统的过程,本身就是一次深度学习。我不仅掌握了 Hono、Qdrant、Ollama 等新技术,更重要的是重新思考了「知识管理」这件事:

工具的价值不在于功能多寡,而在于能否形成「采集 → 整理 → 连接 → 复用」的正向循环。

希望这个项目能给你一些启发。如果你有任何问题或建议,欢迎在 GitHub 上交流。


参考资料

  1. Qdrant 官方文档
  2. Ollama GitHub
  3. Hono 快速入门
  4. React Flow 知识图谱示例
分享到:

如果这篇文章对你有帮助,欢迎请作者喝杯咖啡 ☕

加载评论中...