Notex:一个开源 NotebookLM 替代方案的实现

Google 的 NotebookLM 上线后,不少人体验了它的文档问答和内容生成功能。它很好用,但有个问题:数据需要上传到 Google 的服务器。对于一些敏感的内部文档,这不太合适。

于是就想做一个开源版本:数据存在本地,想用什么模型就自己配置。一个元旦假期,基本功能就跑起来了。

项目叫 Notex,代码在 GitHub 上,今天聊聊它的实现。

本项目受open-notebook项目的启发。但是open-notebook缺少信息图、思维导图、幻灯片等高级功能。本项目弥补了这些功能
信息图采用最新的nano banana pro实现
幻灯片采用 宝玉的 《预订本年度最有价值提示词 —— 生成既有质感,又能随意修改文字的完美 PPT》 的方式,生成真正意义上的PPT

功能概览

这块是核心,负责和 LLM 打交道。

使用 LangChainGo 作为抽象层,支持 OpenAI 和 Ollama:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func createLLM(cfg Config) (llms.Model, error) {
if cfg.IsOllama() {
return ollamallm.New(
ollamallm.WithModel(cfg.OllamaModel),
ollamallm.WithServerURL(cfg.OllamaBaseURL),
)
}

opts := []openai.Option{
openai.WithToken(cfg.OpenAIAPIKey),
openai.WithModel(cfg.OpenAIModel),
}
if cfg.OpenAIBaseURL != "" {
opts = append(opts, openai.WithBaseURL(cfg.OpenAIBaseURL))
}

return openai.New(opts...)
}

Prompt Engineering 是关键。不同的转换类型需要不同的 prompt 模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
case "mindmap":
return `你是一位资深的信息架构师和知识管理专家。
请将【文本内容】提炼并转换为 Mermaid.js 的 mindmap 格式。

# 样式规范:
1. 中心主题:root((内容))
2. 主要分支:(内容)
3. 细节节点:[内容]

# 严格规范:
- 严禁使用 graph, LR, --> 等字符
- 节点内容 10 字以内
- 只输出代码块,不解释

来源:{sources}
`

注意这里的 prompt 设计:明确的输出格式要求,加上反面示例("严禁"),能有效减少 LLM 输出格式不稳定的问题。

3. PPT 生成

这是比较复杂的 feature。需要两个步骤:

第一步:生成大纲

用 Gemini Flash 生成 PPT 大纲,每页包含:

  • 叙事目标(这张幻灯片要讲什么)
  • 关键内容(标题、要点)
  • 视觉元素(需要什么图)
  • 布局(怎么排版)

第二步:解析和生成图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func (a *Agent) ParsePPTSlides(content string) []Slide {
// 1. 提取风格指南
styleStart := strings.Index(content, "<STYLE_INSTRUCTIONS>")
styleEnd := strings.Index(content, "</STYLE_INSTRUCTIONS>")

// 2. 按幻灯片分割(支持多种标记)
re := regexp.MustCompile(`(?m)^(?:\s*#{1,6}\s*)?(?:Slide|幻灯片)\s*\d+`)
indices := re.FindAllStringIndex(content, -1)

// 3. 验证每张幻灯片是否包含必需字段
if strings.Contains(lower, "叙事目标") || strings.Contains(lower, "关键内容") {
slides = append(slides, Slide{Style: style, Content: slideContent})
}
}

然后为每张幻灯片调用 Gemini Pro Image 生成图片:

1
2
3
4
5
for i, slide := range slides {
prompt := fmt.Sprintf("Style: %s\n\nSlide Content: %s", slides[0].Style, slide.Content)
imagePath, err := s.agent.GenerateImage(ctx, "gemini-3-pro-image-preview", prompt)
slideURLs = append(slideURLs, "/uploads/"+filepath.Base(imagePath))
}

4. 信息图生成

信息图的核心是让 LLM 把文本内容"翻译"成视觉描述,然后把描述作为 prompt 喂给图像模型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
case "infograph":
return `# Role
你是一位世界顶级的数据可视化设计师和信息图专家。

# Task
阅读所附文本,设计一张信息图。不要进行总结,
而是描述这张图应该长什么样。你的输出将被直接用作图像生成的 prompt。

# Design Guidelines
1. 核心信息提炼:找出最重要的 3-5 个数据点
2. 视觉隐喻:用形象的比喻(如网络安全用"盾牌和锁")
3. 布局结构:明确定义图的结构
4. 文本限制:极简,只保留标题和关键数据
5. 风格:插画或手绘感

# Output Format
Start with "Infographic illustration created in a soft, hand-drawn digital art style..."
[描述整体布局和背景风格]
[详细描述主要视觉元素]
...
`

这个 prompt 设计的要点是:明确告诉 LLM 它的输出会被用作另一个 prompt,这样 LLM 就会更注意输出的结构化和可用性。

5. 思维导图

思维导图的实现最简单,核心是生成 Mermaid.js 的语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
case "mindmap":
return `将文本转换为 Mermaid.js mindmap 格式。

# 样式规范:
root((中心主题)) # 圆圈
(主要分支) # 圆角矩形
[细节节点] # 矩形

# 严格规范:
- 仅限 mindmap 语法
- 节点内容 10 字以内
- 严禁包含引号
`

前端用 Mermaid.js 自动渲染:

1
2
import mermaid from 'https://s4.zstatic.net/ajax/libs/mermaid/11.4.0/mermaid.min.js';
mermaid.initialize({ startOnLoad: true });

数据流

本地运行

1
2
3
4
5
6
7
8
9
10
11
12
git clone https://github.com/smallnest/notex.git
cd notex
go mod tidy

# 使用 OpenAI
export OPENAI_API_KEY=your_key
go run . -server

# 或使用 Ollama(本地模型)
export OLLAMA_BASE_URL=http://localhost:11434
export OLLAMA_MODEL=qwen2.5:7b
go run . -server

Docker 部署

1
docker-compose up

环境变量

变量 说明 默认值
OPENAI_API_KEY OpenAI API 密钥 -
OPENAI_BASE_URL 自定义 API 地址 -
OPENAI_MODEL 模型名称 gpt-4o-mini
OLLAMA_BASE_URL Ollama 地址 -
OLLAMA_MODEL Ollama 模型 -
GOOGLE_API_KEY Gemini API(PPT/信息图) -
SERVER_PORT 服务端口 8080

扩展性

代码结构支持几种扩展方式:

1. 添加新的转换类型

agent.gogetTransformationPrompt 添加新 case:

1
2
case "new_type":
return `你的 prompt 模板...`

2. 支持新的 LLM

LangChainGo 支持多种模型,只需在 createLLM 添加新的分支。

3. 接入向量数据库

VectorStore 目前是内存实现,可以替换成 Qdrant、Milvus 等。

4. 添加新的文档格式

vector.goneedsMarkitdown 添加新的文件扩展名。

代码量和学习价值

项目核心代码大约 2000 行左右,适合学习:

  1. RAG 的完整实现:从文档处理到检索到生成
  2. Prompt Engineering:如何设计稳定的 prompt
  3. Go Web 开发:Gin 框架、SQLite、并发处理
  4. 前后端分离:单页应用 + REST API
  5. LLM 应用架构:如何组织一个 AI 应用的代码

如果你想学习如何构建 AI 应用,或者想找一个 NotebookLM 的替代方案,这个项目可以作为一个起点。

总结

Notex 不是什么高大上的项目,代码也写得朴素。但它解决了实际问题:让你在本地使用 AI 处理文档,数据不外泄。

核心功能就几个:

  • 文档问答(RAG)
  • 多种内容转换(摘要、FAQ、大纲等)
  • 视觉内容生成(PPT、信息图、思维导图)

技术选型务实地选择了 Go 和原生 JS,没有过多的依赖。部署简单,维护成本低。

如果你感兴趣,可以看看代码,提提 PR,或者直接 fork 改成你自己的工具。


项目地址: https://github.com/smallnest/notex

欢迎 Star、Issue、PR。