基于 BAAI/bge-m3 的本地 Embedding 服务,兼容 OpenAI Embedding API 格式,支持向量检索、记忆管理和反馈训练。
适用环境: macOS (Intel/Apple Silicon), 16GB+ 内存
模型大小: ~2.2GB
向量维度: 1024
cd ~/bge-m3-service
source venv/bin/activate
nohup python3 server.py > server.log 2>&1 &验证:
curl http://127.0.0.1:19238/healthmacOS: 12.0+ (Monterey 或更新)
内存: 16GB (运行后剩余 8GB+ 可用)
磁盘: 5GB 空闲 (模型 2GB + 环境 1GB + 数据 2GB)
Python: 3.9 - 3.12 (推荐 3.11)
检查环境:
sysctl hw.memsize | awk '{print $2 / 1024 / 1024 / 1024 " GB"}'
python3.11 --versionmkdir -p ~/bge-m3-service
cd ~/bge-m3-service
python3.11 -m venv venv
source venv/bin/activate
pip install --upgrade pip setuptools wheelpip install sentence-transformers fastapi uvicorn faiss-cpu numpy pydantic prometheus-clientApple Silicon 注意: 如果
faiss-cpu安装失败,先执行brew install libomp再试。
python3 -c "
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('BAAI/bge-m3')
print('模型加载完成:', model.device)
"首次运行会自动从 HuggingFace 下载模型 (~2.2GB),耗时 3-10 分钟。
如果网络不通,可设置镜像:
export HF_ENDPOINT=https://hf-mirror.com确保 server.py 位于 ~/bge-m3-service/server.py(已随本 README 提供)。
cd ~/bge-m3-service
source venv/bin/activate
nohup python3 server.py > server.log 2>&1 &服务默认监听 0.0.0.0:19238,支持本机和局域网访问。
kill $(pgrep -f "python3 server.py")kill $(pgrep -f "python3 server.py")
sleep 1
rm -f memory.index memory.meta.json feedback.log
nohup python3 server.py > server.log 2>&1 &# 健康检查
curl http://127.0.0.1:19238/health
# 索引统计
curl http://127.0.0.1:19238/v1/statscurl http://127.0.0.1:19238/v1/embeddings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer dummy-key" \
-d '{"input": "测试文本", "model": "bge-m3"}'批量请求:
curl http://127.0.0.1:19238/v1/embeddings \
-H "Content-Type: application/json" \
-d '{"input": ["文本1", "文本2", "文本3"]}'curl http://127.0.0.1:19238/v1/add \
-H "Content-Type: application/json" \
-d '{
"texts": ["bge-m3 是多语言模型", "Docker 容器化部署"],
"ids": ["doc-001", "doc-002"]
}'curl http://127.0.0.1:19238/v1/search \
-H "Content-Type: application/json" \
-d '{"query": "embedding 模型", "top_k": 5, "min_trust": 0.0}'# 标记 helpful(提升 trust)
curl http://127.0.0.1:19238/v1/feedback \
-H "Content-Type: application/json" \
-d '{"doc_id": "doc-001", "helpful": true}'
# 标记 unhelpful(降低 trust)
curl http://127.0.0.1:19238/v1/feedback \
-H "Content-Type: application/json" \
-d '{"doc_id": "doc-001", "helpful": false}'curl http://127.0.0.1:19238/metrics编辑另一台机器上的 ~/.openclaw/openclaw.json:
{
"agents": {
"defaults": {
"memorySearch": {
"enabled": true,
"provider": "openai",
"remote": {
"baseUrl": "http://10.121.144.68:19238",
"apiKey": "dummy-key-local-only",
"headers": {}
},
"model": "bge-m3"
}
}
}
}将
10.121.144.68替换为实际运行服务机器的局域网 IP。
from openai import OpenAI
client = OpenAI(
base_url="http://10.121.144.68:19238",
api_key="dummy-key"
)
response = client.embeddings.create(
model="bge-m3",
input="测试文本"
)
print(len(response.data[0].embedding)) # 1024cd ~/bge-m3-service
source venv/bin/activate
python3 test_service.pypython3 perf_test.py输出示例(Apple Silicon MPS):
【单条延迟测试】
短文本 ( 4字) p50= 22.9ms p95= 26.7ms
中短文本 ( 18字) p50= 22.2ms p95= 24.2ms
中等文本 ( 40字) p50= 22.2ms p95= 28.5ms
长文本 ( 76字) p50= 25.0ms p95= 25.9ms
【批量吞吐测试】
batch=32 avg=206.4ms per_item=6.4ms throughput=155.1 items/s
【并发 QPS 测试】
workers=20 200req/4.4s QPS=46.0 p50=463.4ms p95=503.3ms
【检索延迟测试】
检索延迟 (1000 docs): avg=29.8ms p50=28.3ms p95=40.6ms
【端到端链路测试】
add 5 docs: 76.2ms
embed 1 text: 30.0ms
search top-3: 33.2ms
| 指标 | 结果 |
|---|---|
| 单条嵌入 p50 (18字) | 22.2ms |
| 批量嵌入 (batch=32) | 6.4ms/条 |
| 批量吞吐 | 155.1 items/s |
| 并发 QPS (20 workers) | 46.0 QPS |
| 检索延迟 p50 (1000 docs) | 28.3ms |
详细报告保存为 perf_report.json。
python3 benchmark.py输出示例:
【1. 插入测试】
单条插入: 177.8ms
批量插入: 100条 547.0ms (5.5ms/条)
大数据批量: 500条 2356.0ms (4.7ms/条)
【4. 性能测试】
单次 embedding 延迟: p50=21.9ms p95=23.3ms
批量 embedding batch=32: 172.9ms (5.4ms/条)
检索延迟 (100次): p50=23.9ms
并发 QPS (20线程): 48.1 QPS
python3 monitor.py每 3 秒刷新,显示:
- 服务健康状态
- 累计请求数(按接口)
- 请求延迟 p50/p95/p99
- Embedding 推理延迟
- 索引文档数 / 活跃请求数
远程监控:
python3 monitor.py --host http://10.121.144.68:19238服务原生暴露 Prometheus 格式指标:
| 指标 | 说明 |
|---|---|
bge_m3_requests_total |
请求总数(method/path/status) |
bge_m3_request_duration_seconds |
请求延迟直方图 |
bge_m3_embedding_duration_seconds |
Embedding 推理延迟(按 batch_size) |
bge_m3_active_requests |
当前活跃请求数 |
bge_m3_index_docs_total |
索引文档总数 |
bge_m3_model_loaded |
模型加载状态 |
接入 Prometheus:
scrape_configs:
- job_name: 'bge-m3'
static_configs:
- targets: ['10.121.144.68:19238']~/bge-m3-service/
├── venv/ # Python 虚拟环境
├── server.py # 主服务文件
├── test_service.py # 基础功能测试
├── benchmark.py # 综合性能/精度测试
├── monitor.py # 终端监控面板
├── perf_test.py # 性能专项测试脚本
├── perf_report.json # 性能测试报告(运行时生成)
├── README.md # 本文档
├── server.log # 服务运行日志
├── memory.index # FAISS 向量索引 (运行时生成)
├── memory.meta.json # 文档元数据 (运行时生成)
└── feedback.log # 反馈日志 (运行时生成)
RuntimeError: Failed to load model
解决:
- 检查网络,HuggingFace 被墙时换镜像:
export HF_ENDPOINT=https://hf-mirror.com - 手动下载后指定本地路径:
model = SentenceTransformer("/path/to/local/bge-m3")
Killed (进程被系统终止)
解决:
- 关闭其他应用释放内存
- 使用截断维度(降维到 512):
model = SentenceTransformer("BAAI/bge-m3", truncate_dim=512)
brew install libomp
pip install faiss-cpu --no-cache-dir- 检查 Mac 防火墙是否放行 19238 端口
- 在另一台机器测试:
curl http://10.121.144.68:19238/health
- 确认两台机器在同一局域网
- 使用
min_trust过滤低分记忆:curl /v1/search -d '{"query": "xxx", "min_trust": 0.3}' - 给错误记忆反馈
unhelpful - 手动添加高质量记忆到索引
文档版本: 2026-04-28
测试环境: macOS 16GB, Python 3.11, bge-m3 (BAAI)