内部文档系统最容易被低估的一件事,是搜索。
一开始大家以为接个模型就能解决,后来才发现用户搜的东西很具体:错误码、配置项、版本号、工单号、客户名、接口名。语义检索能解决描述性问题,但这些精确词还得靠全文搜索、过滤和排序。
Meilisearch 适合做这个入口。它轻量,Docker 跑起来快,还能从 full-text 逐步走到 hybrid search。但自托管前建议先把下面这张工程清单跑完。
1. 镜像和版本
不要直接把 latest 写进团队文档里。开发环境可以试,团队复现和生产环境最好固定版本。
bash
docker pull docker.1ms.run/getmeili/meilisearch:v1.47.0
这里使用毫秒镜像,只是先处理 Docker Hub 镜像预检。搜索质量、索引、备份和权限都不是镜像入口能解决的。
2. 最小可运行命令
bash
docker run --rm \
-p 7700:7700 \
-e MEILI_MASTER_KEY='replace-with-a-strong-key' \
-v $(pwd)/meili_data:/meili_data \
docker.1ms.run/getmeili/meilisearch:v1.47.0
这条命令里真正关键的是三点:
7700:只对可信网络开放。MEILI_MASTER_KEY:不要进前端。meili_data:不挂载就没有持久化。
3. 搜索服务不是只看 health
健康检查只能说明服务活着:
bash
curl http://127.0.0.1:7700/health
但内部文档搜索还要测:
| 验证项 | 示例 |
|---|---|
| 精确词 | AUTH_REDIRECT_LOOP |
| 模糊输入 | 错别字、缩写、半截功能名 |
| 业务过滤 | 产品线、租户、文档类型 |
| 自然语言 | "登录后一直跳回首页" |
| 权限边界 | 用户能否看到不该看的文档 |
只有 health 通过,不代表搜索可以上线。
4. 导入文档要看 task
Meilisearch 写入文档后会返回 task。很多人踩坑是:接口返回了,但搜索不到,于是以为索引坏了。实际是 task 还没处理完,或者处理失败。
bash
curl http://127.0.0.1:7700/tasks/replace-with-task-uid \
-H 'Authorization: Bearer replace-with-a-server-key'
导入大批文档时,建议记录:
- 批次大小。
- task uid。
- 成功/失败数量。
- 失败原因。
- 本次文档版本。
这些信息后面排查搜索质量很有用。
5. Hybrid search 不是开关
Meilisearch 的 hybrid search 会结合全文和语义。官方文档里一个很关键的点是:语义搜索用的是 embedding models,不是 LLM。
这意味着你要管理:
- 哪些字段进入 embedding。
- embedder 配置是否会触发重建。
- 精确词是否仍由全文搜索兜住。
semanticRatio是否适合你的查询。
内部文档搜索里,我通常不会一上来就纯语义。先把全文搜索和过滤做扎实,再给描述性问题加语义能力。
6. 备份和升级
Meilisearch 的 snapshot 和 dump 用途不同:
| 方式 | 用途 |
|---|---|
| snapshot | 日常恢复,速度快,适合同版本 |
| dump | 版本迁移,升级前使用 |
Runbook 里至少写:
- 每天什么时候 snapshot。
- 升级前 dump 放哪里。
- 恢复命令怎么跑。
- 谁来验证恢复后的搜索结果。
7. 一张工程清单
text
Docker 镜像固定版本
7700 端口限制来源
Master key 不进前端
API keys 按权限拆分
meili_data 挂载持久化
文档写入后检查 task
精确词和自然语言分别验证
周期 snapshot,升级前 dump
结尾
给内部文档加搜索,不是把文档丢给模型就结束。模型回答之前,要先有一个稳定的搜索入口。
Meilisearch 能把这层做得比较轻。毫秒镜像在这里解决的是更前面的一步:别让 Docker 镜像拉取阻塞部署。真正跑稳,还要靠版本固定、密钥拆分、索引任务、备份和搜索质量验证。