构建 Perplexica:使用 TypeScript 和 RAG 管道的开源 AI 搜索引擎
通过 TypeScript 构建开源 AI 搜索引擎,集成 RAG 管道、向量嵌入和本地 LLM,实现隐私保护的语义搜索与实时答案合成。
Perplexica 是一个开源的 AI 驱动搜索引擎,旨在提供类似于 Perplexity AI 的功能,但完全开源且注重隐私保护。它使用 TypeScript 开发,结合 RAG(Retrieval-Augmented Generation)管道、向量嵌入和本地 LLM(Large Language Model)集成,实现高效的语义搜索和答案合成。本文将指导你从零构建类似系统,聚焦于核心技术栈的落地参数、监控要点和可操作清单,确保系统隐私优先且实时性强。
为什么选择 Perplexica 风格的构建?
传统搜索引擎如 Google 依赖中心化索引,而 AI 搜索引擎如 Perplexity 通过 LLM 合成答案,提供更智能的响应。但这些服务往往涉及数据上传,隐私风险高。Perplexica 的开源替代方案使用本地 LLM(如通过 Ollama 运行的 Llama 或 Mistral),结合 SearxNG 元搜索引擎获取实时 web 数据,避免数据外泄。同时,RAG 管道确保检索到的内容直接注入 LLM 提示中,生成准确答案。
构建目标:创建一个 TypeScript-based 的 Web UI,支持语义搜索模式,集成向量数据库进行嵌入匹配。整个系统可在本地 Docker 环境中运行,响应时间控制在 5 秒内。
技术栈选择与安装清单
-
后端框架:Next.js with TypeScript
- 为什么?Next.js 支持 SSR(Server-Side Rendering),适合实时搜索 UI;TypeScript 提供类型安全,减少 RAG 管道中的 bug。
- 安装参数:
- Node.js >= 18.0.0
npx create-next-app@latest perplexica --typescript --tailwind --eslint
- 依赖:
npm install langchain @langchain/community ollama searxng-python-client
(用于 RAG 和 LLM 集成)
- 监控要点:使用 Vercel 或本地 PM2 监控 API 延迟,阈值 < 2s。
-
搜索源:SearxNG
- 作用:作为元搜索引擎,聚合 Google、Bing 等结果,提供 JSON 输出,避免单点故障。
- 部署清单:
- Docker 安装:
docker run -d --name searxng -p 8080:8080 searxng/searxng
- 配置:编辑
/etc/searxng/settings.yml
,启用 JSON 格式,禁用图像搜索以优化速度。 - 集成:在 TypeScript 中使用 fetch API 调用
http://localhost:8080/search?q=query&format=json
,解析 results 字段提取标题、URL 和内容片段。
- Docker 安装:
- 风险控制:SearxNG 默认不追踪用户,结合本地运行确保隐私;如果结果为空,回退到备用引擎如 DuckDuckGo。
-
向量嵌入:使用 Hugging Face 或 Sentence Transformers
- 核心:将查询和搜索结果转换为嵌入向量,进行余弦相似度匹配,实现语义检索。
- 实现参数:
- 库:
npm install @xenova/transformers
(浏览器端轻量嵌入)或后端使用 Ollama 的嵌入模型。 - 模型选择:all-MiniLM-L6-v2(维度 384,低计算开销)。
- 管道步骤:
- 查询嵌入:
const queryEmbedding = await embedder.embedQuery(userQuery);
- 结果嵌入:对 top-10 搜索结果的 snippet 批量嵌入。
- 相似度计算:使用 cosine similarity,阈值 > 0.7 筛选相关片段。
- 查询嵌入:
- 存储:可选集成 LanceDB 或简单内存向量存储(小型应用),索引大小控制在 1GB 内。
- 库:
- 可落地清单:
- 预热嵌入模型:启动时加载,避免首次查询延迟。
- 批量处理:每批 5-10 片段,GPU 加速如果可用(本地 NVIDIA CUDA)。
RAG 管道的核心实现
RAG 是 Perplexica 的灵魂:检索(Retrieval)+ 生成(Generation)。不同于纯 LLM 幻觉,RAG 注入真实 web 数据。
-
检索阶段(Retrieval)
- 输入:用户查询,如“TypeScript RAG 最佳实践”。
- 步骤:
- 调用 SearxNG 获取 top-5 结果。
- 提取 snippet(每条 < 500 字符)。
- 生成嵌入并排序:使用 FAISS 或简单 numpy 实现 top-k 检索(k=3)。
- 参数优化:检索深度 20 条初始结果,rerank 后取 3 条;超时 3s。
-
增强阶段(Augmentation)
- 构建提示模板:
基于以下来源回答查询:\n来源1: [snippet1]\n来源2: [snippet2]\n查询: {query}\n请提供简洁答案并引用来源。
- 注入上下文长度:控制在 2000 tokens,避免 LLM 溢出。
- 构建提示模板:
-
生成阶段(Generation)
- LLM 集成:优先本地 Ollama。
- 安装:
curl -fsSL https://ollama.com/install.sh | sh
,拉取模型ollama pull llama3.1:8b
。 - API 调用:在 TypeScript 中使用
fetch('http://localhost:11434/api/generate', { method: 'POST', body: JSON.stringify({model: 'llama3.1', prompt: augmentedPrompt, stream: false}) })
。 - 参数:temperature=0.1(确定性输出),max_tokens=500。
- 安装:
- 隐私保障:所有处理本地,无云 API key;如果 fallback,使用自托管 OpenAI-compatible 如 llama.cpp server。
- LLM 集成:优先本地 Ollama。
-
合成与 UI 输出
- Next.js 页面:
/search/[query]
路由,异步渲染答案。 - 实时性:使用 React Suspense 流式输出 LLM 响应。
- 引用:答案末尾添加来源链接,如“来源:[URL1]”。
- Next.js 页面:
本地 LLM 集成与隐私优化
本地 LLM 是隐私核心,避免数据发送到 OpenAI 等云服务。
-
Ollama 配置:
- 端口:11434,host: 0.0.0.0(Docker 内部访问)。
- 模型管理:支持 Qwen、DeepSeek 等中文优化模型;量化 Q4_K_M 减少内存(8B 模型需 6GB RAM)。
- 错误处理:连接失败时,回滚到纯搜索模式,仅返回链接列表。
-
向量数据库隐私:
- 使用本地 Pinecone-free 替代如 ChromaDB(
npm install chromadb
),数据永不上传。 - 监控:日志查询频率,阈值 >10/min 触发限流。
- 使用本地 Pinecone-free 替代如 ChromaDB(
-
风险与回滚:
- 风险1:LLM 响应慢(>5s),解决方案:异步队列 + 缓存热门查询(Redis,TTL 1h)。
- 风险2:嵌入不准,导致无关答案,解决方案:用户反馈循环,fine-tune 嵌入阈值。
- 回滚策略:如果 RAG 失败,降级到 SearxNG 原始结果显示。
部署与测试清单
-
Docker 部署(推荐):
- docker-compose.yml:服务包括 Next.js app、SearxNG、Ollama。
- 卷挂载:./data:/app/data(持久化模型)。
- 命令:
docker-compose up -d
,暴露 3000 端口。
-
性能测试:
- 工具:Apache Bench,模拟 100 查询,平均响应 <4s。
- 指标:准确率(人工评估 >80%),隐私(无网络外发,Wireshark 验证)。
-
扩展点:
- Focus Modes:添加 Academic/YouTube 模式,通过查询前缀路由不同 RAG 变体。
- API:暴露 /api/search 端点,支持 JSON 输出集成其他 app。
通过以上步骤,你可以构建一个完整的 Perplexica-like 系统,总代码量约 500 行 TypeScript。重点在于 RAG 的参数调优和本地 LLM 的稳定集成,确保系统既智能又安全。未来,可添加 Copilot 模式,通过多查询扩展检索深度。
(字数:1025)