自托管 AI 知识库与联网搜索全套方案:SearXNG + Infinity + R2R + pgvector
2026/8/27 9:06:50 网站建设 项目流程

自托管 AI 知识库与联网搜索全套方案:SearXNG + mcp-searxng + Infinity + R2R + pgvector

目标:用 4 个开源组件 + 1 个 MCP 桥接服务,在本地搭一套完全自托管的「向量知识库(RAG)+ 隐私联网搜索」基础设施,供 Claude、OpenCode、Cursor 等 AI 客户端调用。

一、方案总览

1.1 组件与镜像

组件镜像作用
SearXNGsearxng/searxng:latest自托管元搜索引擎,聚合 Google/Bing/DuckDuckGo 等结果,不追踪用户
mcp-searxngisokoliuk/mcp-searxng:latest(或 npx 本地运行)MCP 协议桥,把 SearXNG 的搜索能力暴露给 AI 客户端(Claude Desktop/Code、Cursor、OpenCode 等)
Infinitymichaelf34/infinity:0.0.77-cpu高吞吐 Embedding/Rerank 推理服务,提供 OpenAI 兼容的/embeddings接口,CPU 版无需显卡
R2R (RAG to Riches)sciphiai/r2r:3.6.6-amd64生产级 RAG 服务:文档解析、切片、向量化入库、混合检索、RAG API
pgvectorpgvector/pgvector:pg16内置 pgvector 扩展的 PostgreSQL 16,作为向量数据库持久层

1.2 架构图

┌──────────────────────────────┐ │ AI 客户端(Claude/OpenCode)│ └──────┬───────────────┬───────┘ MCP 协议 │ │ HTTP API ▼ ▼ ┌─────────────────┐ ┌──────────────────┐ │ mcp-searxng │ │ R2R :7272 │◄── 你自己的应用 │ (搜索工具桥) │ │ RAG 服务 │ (/v1/retrieval 等) └────────┬────────┘ └───────┬──────────┘ │ HTTP JSON │ 调用 embedding ▼ ▼ ┌─────────────────┐ ┌──────────────────┐ │ SearXNG :8080 │ │ Infinity :7997 │ │ 元搜索 │ │ bge-m3 向量模型 │ └────────┬────────┘ └──────────────────┘ │ 抓取各搜索引擎 │ 向量读写 ▼ ▼ Google/Bing/... ┌──────────────────┐ │ pgvector (PG16) │ │ 5432 向量存储 │ └──────────────────┘

两条能力线相互独立又互补:

  • 联网搜索线:客户端 → mcp-searxng → SearXNG → 各大搜索引擎。解决「模型不知道最新信息」的问题。
  • 私有知识线:文档 → R2R → Infinity 向量化 → pgvector 存储 → 检索问答。解决「模型不知道你的私有资料」的问题。

1.3 为什么选这套组合

  1. 全部可自托管:搜索记录不出内网;Embedding 在本地 CPU 跑,不依赖 OpenAI。
  2. 版本都经过社区验证:Infinity 0.0.77 与 R2R 3.6.x 是各自项目稳定期版本,镜像多架构齐全。
  3. 标准协议对接:MCP 是 AI 工具生态事实标准;Infinity 和 R2R 都讲 OpenAI 兼容 HTTP,替换任何一个组件都不影响整体。

二、环境准备

要求说明
Docker ≥ 24 + Compose v2所有服务容器化部署
内存 ≥ 8GBInfinity 加载 bge-m3 约占 2~3GB;R2R 约占 1GB
磁盘 ≥ 20GB含模型权重(bge-m3 约 2GB)、Postgres 数据
可访问 HuggingFace首次启动拉取模型;国内建议配HF_ENDPOINT=https://hf-mirror.com

目录结构约定:

/opt/ai-stack/ ├── docker-compose.yml ├── .env # 密码、密钥等敏感配置 ├── searxng/ │ ├── settings.yml # SearXNG 主配置 │ └── limiter.toml ├── r2r/ │ └── r2r.toml # R2R 配置(指向 infinity + pgvector) └── pgdata/ # PG 数据卷

三、逐个部署

3.1 pgvector:PostgreSQL 16 + 向量扩展

pgvector/pgvector:pg16就是官方 PostgreSQL 16 镜像加了 pgvector 扩展,用法与普通 PG 完全一致:

postgres: image: pgvector/pgvector:pg16 restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-r2r} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set in .env} POSTGRES_DB: ${POSTGRES_DB:-r2r} volumes: - ./pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-r2r}"] interval: 10s timeout: 5s retries: 5

验证扩展可用(R2R 会自动建表,但可以手动确认扩展存在):

docker compose exec postgres psql -U r2r -c "CREATE EXTENSION IF NOT EXISTS vector;" docker compose exec postgres psql -U r2r -c "SELECT extname, extversion FROM pg_extension WHERE extname='vector';"

注意:pgvector 的索引(HNSW/IVFFlat)和查询参数由 R2R 自动管理,一般不需要手工建表。向量维度必须与 Embedding 模型输出一致——本文用 bge-m3(1024 维),中途换模型必须重建集合并重新入库。

3.2 Infinity:CPU 版 Embedding 服务

BAAI/bge-m3:多语言(中英效果好)、1024 维、支持长文本(8192 tokens),是中文知识库的主力选择。

compose 片段:

infinity: image: michaelf34/infinity:0.0.77-cpu restart: unless-stopped environment: HF_ENDPOINT: ${HF_ENDPOINT:-} # 国内镜像加速,如 https://hf-mirror.com command: > v2 --model-id BAAI/bge-m3 --served-model-name bge-m3 --port 7997 --batch-size 16 volumes: - ./infinity-cache:/app/.cache # 缓存模型权重,重启不用重新下载 ports: - "127.0.0.1:7997:7997" # 只暴露给本机/容器网络

验证(OpenAI 兼容接口):

curl http://127.0.0.1:7997/embeddings \ -H "Content-Type: application/json" \ -d '{"model":"bge-m3","input":["你好,世界"]}' # 返回 JSON 中 data[0].embedding 应为长度 1024 的数组

要点说明:

  • 0.0.77版本起命令行入口为v2子命令,所有参数也可用INFINITY_前缀环境变量代替(如INFINITY_MODEL_ID=BAAI/bge-m3;)。
  • -cpu镜像内置 ONNX/CPU 优化,无 NVIDIA 显卡时的最佳选择;有卡请换默认镜像并加--gpus all
  • 还可以再挂一个 rerank 模型(如--model-id BAAI/bge-reranker-base)供 R2R 重排用,按需增加。
  • 首次启动要下载约 2GB 权重,耐心等待日志出现Uvicorn running再测接口。

3.3 R2R:RAG 编排服务

R2R 负责最重的活:文档摄取(PDF/DOCX/HTML/MD)、语义切块、调 Infinity 向量化、写入 pgvector、提供检索与 RAG 问答 API。

r2r/r2r.toml关键配置(把 embedding 指到本地 Infinity,把存储指到本地 pgvector):

[completion] # 生成模型仍需要一个 LLM 提供方;provider 用 litellm 时模型名要带 openai/ 前缀 provider = "litellm" concurrent_request_limit = 16 [completion.generation_config] model = "openai/gpt-4o-mini" # 也可以指向任意 OpenAI 兼容的本地大模型 temperature = 0.1 max_tokens_to_sample = 1024 stream = true [embedding] provider = "openai" # 走 OpenAI 兼容协议 → 即本地 Infinity base_model = "bge-m3" # 对应 --served-model-name [database] provider = "pgvector"

配套环境变量(写入.env或 compose 的environment):

# 让 R2R 的 openai/litellm 客户端打到本地 Infinity OPENAI_API_BASE=http://infinity:7997/v1 OPENAI_API_KEY=empty # Infinity 不校验,占位即可 # pgvector 连接 POSTGRES_HOST=postgres POSTGRES_PORT=5432 POSTGRES_USER=r2r POSTGRES_PASSWORD=your-strong-password POSTGRES_DB=r2r

提示:不同小版本的 toml 字段名偶有调整,以上结构以 R2R GitHub 仓库 v3.6.x 的示例配置为准,冲突时以官方模板为准。

compose 片段:

r2r: image: sciphiai/r2r:3.6.6-amd64 restart: unless-stopped depends_on: postgres: condition: service_healthy infinity: condition: service_started environment: OPENAI_API_BASE: http://infinity:7997/v1 OPENAI_API_KEY: empty POSTGRES_HOST: postgres POSTGRES_PORT: "5432" POSTGRES_USER: ${POSTGRES_USER:-r2r} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-r2r} volumes: - ./r2r/r2r.toml:/app/config/r2r.toml - ./r2r/data:/app/data ports: - "7272:7272" # R2R API

常用操作:

# 上传文档建立知识库(会自动切片→Infinity向量化→入pgvector) curl -X POST http://127.0.0.1:7272/v1/documents \ -F "file=@./manual.pdf" # RAG 问答:检索 + LLM 生成 curl -X POST http://127.0.0.1:7272/v1/retrieval/rag \ -H "Content-Type: application/json" \ -d '{"query":"设备保修政策是什么?"}'

排错速查:

现象原因与处理
R2R 启动即退出pgvector 未就绪或密码不对,看docker logs r2r
入库报维度不匹配换过 Embedding 模型;删掉对应 collection 重新入库
入库很慢Infinity 首次下载模型中;CPU 下 bge-m3 吞吐有限属正常,可调大--batch-size

3.4 SearXNG:隐私元搜索

SearXNG 必须开启 JSON 输出格式,否则 mcp-searxng 拿不到数据(最常见的坑)。

searxng/settings.yml最小可用配置:

use_default_settings: true server: secret_key: "change-me-to-random-string" # openssl rand -hex 32 生成 limiter: false # 仅本机/内网使用时可关 image_proxy: true search: safe_search: 0 formats: # ← 关键!默认没有 json - html - json engines: - name: google disabled: false - name: bing disabled: false - name: duckduckgo disabled: false

compose 片段(SearXNG 官方推荐 Redis 做缓存):

redis: image: valkey/valkey:8-alpine restart: unless-stopped command: valkey-server --save 30 1 --loglevel warning searxng: image: searxng/searxng:latest restart: unless-stopped depends_on: - redis environment: SEARXNG_BASE_URL: http://127.0.0.1:8080/ volumes: - ./searxng/settings.yml:/etc/searxng/settings.yml:ro ports: - "8080:8080"

验证 JSON API:

curl "http://127.0.0.1:8080/search?q=docker+searxng&format=json" # 返回 results 数组即成功;返回 403 说明 formats 里没开 json

3.5 mcp-searxng:给 AI 客户端装上搜索

mcp-searxng 不是 SearXNG 插件,而是独立的 MCP Server(Node.js 进程),唯一必填变量是SEARXNG_URL。它通常跑在客户端一侧(STDIO 模式),不必进 compose。

Claude Code 注册(用户级):

claude mcp add --scope user --env SEARXNG_URL=http://127.0.0.1:8080 --transport stdio searxng -- npx -y mcp-searxng

Claude Desktop / Cursor / OpenCode 等(JSON 配置):

{ "mcpServers": { "searxng": { "command": "npx", "args": ["-y", "mcp-searxng"], "env": { "SEARXNG_URL": "http://127.0.0.1:8080", "SEARXNG_MAX_RESULTS": "10", "SEARXNG_DEFAULT_LANGUAGE": "zh-CN" } } } }

常用可选变量:

变量默认说明
SEARXNG_URL必填SearXNG 地址,支持分号分隔多实例做故障转移
SEARXNG_FANOUTfalsetrue 时并行查询所有实例并合并去重
SEARXNG_DEFAULT_LANGUAGEall默认搜索语言,如 zh-CN
SEARXNG_MAX_RESULTS10返回结果条数上限
SEARXNG_TIMEOUT_MS10000单次搜索超时

配置完成后在客户端里说一句"搜一下 xxx",能看到工具调用 SearXNG 即接入成功。


四、完整 docker-compose.yml(汇总)

services: postgres: image: pgvector/pgvector:pg16 restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-r2r} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set in .env} POSTGRES_DB: ${POSTGRES_DB:-r2r} volumes: - ./pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-r2r}"] interval: 10s timeout: 5s retries: 5 infinity: image: michaelf34/infinity:0.0.77-cpu restart: unless-stopped environment: HF_ENDPOINT: ${HF_ENDPOINT:-} command: > v2 --model-id BAAI/bge-m3 --served-model-name bge-m3 --port 7997 --batch-size 16 volumes: - ./infinity-cache:/app/.cache ports: - "127.0.0.1:7997:7997" r2r: image: sciphiai/r2r:3.6.6-amd64 restart: unless-stopped depends_on: postgres: condition: service_healthy environment: OPENAI_API_BASE: http://infinity:7997/v1 OPENAI_API_KEY: empty POSTGRES_HOST: postgres POSTGRES_PORT: "5432" POSTGRES_USER: ${POSTGRES_USER:-r2r} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-r2r} volumes: - ./r2r/r2r.toml:/app/config/r2r.toml - ./r2r/data:/app/data ports: - "7272:7272" redis: image: valkey/valkey:8-alpine restart: unless-stopped command: valkey-server --save 30 1 --loglevel warning searxng: image: searxng/searxng:latest restart: unless-stopped depends_on: - redis environment: SEARXNG_BASE_URL: http://127.0.0.1:8080/ volumes: - ./searxng/settings.yml:/etc/searxng/settings.yml:ro ports: - "8080:8080"

.env示例:

POSTGRES_USER=r2r POSTGRES_PASSWORD=please-change-me POSTGRES_DB=r2r HF_ENDPOINT=https://hf-mirror.com

一键启停:

docker compose up -d docker compose ps # 全部 healthy/running 即就绪 docker compose logs -f infinity # 观察模型加载

五、验收清单

#验证项命令预期
1pgvector 扩展psql -U r2r -c "CREATE EXTENSION IF NOT EXISTS vector;"无报错
2Embedding 服务curl 127.0.0.1:7997/embeddings ...返回 1024 维向量
3RAG 入库+问答POST/v1/documents后 POST/v1/retrieval/rag能引用上传文档作答
4搜索 JSON APIcurl ".../search?q=test&format=json"返回 results 数组
5MCP 搜索AI 客户端内发起一次搜索工具调用成功返回网页摘要

六、安全与运维建议

  1. 不要把端口裸奔公网:SearXNG/R2R/Infinity/PG 只绑127.0.0.1或走反向代理加认证;mcp-searxng 若以 HTTP 模式对外,务必设置MCP_HTTP_AUTH_TOKEN并启用 hardened 模式。
  2. 密钥管理settings.ymlsecret_key.env里的数据库密码都要换掉示例值;csdcn.env类凭据文件不要进 git。
  3. 备份:定期备份pgdata/目录(或用pg_dump),向量库重建成本高。
  4. 升级策略:Infinity 与 R2R 升级可能改变向量维度或表结构,升级前备份,升级后先跑第五节验收清单。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询