docs: add offline embedding server & model downloader

This commit is contained in:
Haitao Pan 2025-08-10 16:22:53 +08:00
parent 98c3f12a62
commit 1c8876b69f
6 changed files with 224 additions and 13 deletions

View File

@ -0,0 +1,69 @@
#!/usr/bin/env python3
"""
离线模型下载器Hugging Face Hub + SOCKS5 自动支持
默认参数
- MODEL_ID="BAAI/bge-m3"
- MODEL_DIR="./models/bge-m3"
- PROXY="socks5://127.0.0.1:1080"
可用环境变量覆盖
- export MODEL_ID="你的模型ID"
- export MODEL_DIR="/保存路径"
- export PROXY="socks5h://ip:port" # 为空表示直连
"""
import os
import sys
from pathlib import Path
# ==== 自动安装 SOCKS 依赖 ====
try:
import socks # PySocks
except ImportError:
print("📦 Installing SOCKS proxy support (requests[socks])...")
os.system(f"{sys.executable} -m pip install -U 'requests[socks]'")
import socks
# ==== 自动安装 huggingface_hub ====
try:
from huggingface_hub import snapshot_download
except ImportError:
print("📦 Installing huggingface_hub...")
os.system(f"{sys.executable} -m pip install -U huggingface_hub")
from huggingface_hub import snapshot_download
# ==== 默认配置 ====
DEFAULT_MODEL_ID = "BAAI/bge-m3"
DEFAULT_MODEL_DIR = "models/bge-m3"
DEFAULT_PROXY = "socks5://127.0.0.1:1080"
# ==== 从环境变量读取 ====
MODEL_ID = os.environ.get("MODEL_ID", DEFAULT_MODEL_ID)
MODEL_DIR = Path(os.environ.get("MODEL_DIR", DEFAULT_MODEL_DIR))
PROXY = os.environ.get("PROXY", DEFAULT_PROXY)
# ==== 设置代理 ====
if PROXY:
os.environ["HTTP_PROXY"] = PROXY
os.environ["HTTPS_PROXY"] = PROXY
print(f"🌐 Using proxy: {PROXY}")
else:
print("🚫 No proxy configured, direct connection.")
# ==== 创建保存目录 ====
MODEL_DIR.parent.mkdir(parents=True, exist_ok=True)
# ==== 下载模型 ====
print(f"⬇️ Downloading model from Hugging Face...")
print(f" Model ID: {MODEL_ID}")
print(f" Save dir: {MODEL_DIR}")
snapshot_download(
repo_id=MODEL_ID,
local_dir=str(MODEL_DIR),
local_dir_use_symlinks=False
)
print(f"✅ Model cached to {MODEL_DIR}")

View File

@ -0,0 +1,45 @@
#!/usr/bin/env python3
import os, sys, numpy as np
from pathlib import Path
# 自动装依赖
try:
from flask import Flask, request, jsonify
from fastembed import TextEmbedding
from huggingface_hub import snapshot_download
except ImportError:
os.system(f"{sys.executable} -m pip install -U flask fastembed numpy huggingface_hub")
from flask import Flask, request, jsonify
from fastembed import TextEmbedding
from huggingface_hub import snapshot_download
# 模型路径
MODEL_DIR = Path(os.getenv("BGE_M3_DIR", "models/bge-m3"))
# 如果本地无模型,先下载
if not MODEL_DIR.exists():
print(f"⬇️ Downloading BGE-M3 to {MODEL_DIR} ...")
snapshot_download("BAAI/bge-m3", local_dir=str(MODEL_DIR), local_dir_use_symlinks=False)
# 离线模式
os.environ["HF_HOME"] = str(Path.cwd() / "hf_cache")
os.environ["HF_HUB_OFFLINE"] = "1"
# 启动服务
app = Flask(__name__)
model = TextEmbedding(str(MODEL_DIR))
@app.post("/v1/embeddings")
def embeddings():
data = request.get_json(force=True) or {}
texts = [data["input"]] if isinstance(data.get("input"), str) else data.get("input", [])
vecs = [np.asarray(v, np.float32) / (np.linalg.norm(v) + 1e-12) for v in model.embed(texts)]
return jsonify({"object": "list", "data": [
{"object": "embedding", "index": i, "embedding": v.tolist()} for i, v in enumerate(vecs)
], "model": data.get("model", "BAAI/bge-m3")})
@app.get("/healthz")
def healthz(): return "ok", 200
if __name__ == "__main__":
app.run(host=os.getenv("EMBED_HOST", "0.0.0.0"), port=int(os.getenv("EMBED_PORT", 9000)))

View File

@ -136,3 +136,36 @@ make init-db
使用 Markdown 编写(支持标题、列表、代码块等)。
可使用 plantuml 或 mermaid 绘制架构图并嵌入 Markdown。
## DEV
1. 运行(首次会自动下载模型)
python offline_embed_server.py
2. 测试接口
编辑
curl -s http://127.0.0.1:9000/v1/embeddings \
-H "Content-Type: application/json" \
-d '{"model":"BAAI/bge-m3","input":["你好","PGVector 怎么建 HNSW"]}' | jq .
3. 环境变量(可选)
export BGE_M3_DIR="/path/to/bge-m3"
export EMBED_HOST="127.0.0.1"
export EMBED_PORT=9100
python offline_embed_server.py
## Ollama API test
用流式接收(推荐):
curl http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-oss:20b",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Tell me three tips for optimizing HNSW in PostgreSQL."}
],
"max_tokens": 512,
"stream": true
}'
这样会实时输出分块数据

53
docs/setup_macos_m4.sh Normal file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env bash
set -euo pipefail
echo "==> 1. Xcode Command Line Tools"
xcode-select -p >/dev/null 2>&1 || xcode-select --install || true
echo "==> 2. Homebrew"
if ! command -v brew >/dev/null 2>&1; then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
echo "==> 3. 基础工具"
brew update
brew install git gh wget curl jq cmake pkg-config tree htop tmux
echo "==> 4. Go / Node / Yarn"
brew install go
# Node 推荐用 corepack 管理pnpm/yarn
brew install node
corepack enable || true
corepack prepare yarn@stable --activate || true
echo "==> 5. PostgreSQL + pgvector"
brew install postgresql@16
brew services start postgresql@16
# pgvector 扩展Homebrew 版已包含或单独提供)
brew install pgvector || true
echo "==> 6. Redis"
brew install redis
brew services start redis
echo "==> 7. Python 与虚拟环境"
brew install python@3.12
python3 -m venv ~/.venvs/xcontrol && source ~/.venvs/xcontrol/bin/activate
pip install -U pip wheel
echo "==> 8. RAG: fastembed + Flask做本地 /v1/embeddings"
pip install -U fastembed flask numpy huggingface_hub
echo "==> 9. 可选PyTorch + MPSApple GPU 加速,用于 Transformers 生成)"
# 官方 pip 已支持 MPS一般直接安装即可若失败可按官网指引重装
pip install -U torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cpu
echo "==> 10. 可选Ollama本地生成模型"
if ! command -v ollama >/dev/null 2>&1; then
curl -fsSL https://ollama.com/install.sh | sh
fi
echo "==> 完成 ✅ 请重新打开终端或执行:"
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"'

View File

@ -19,22 +19,33 @@ sync:
repo:
proxy: socks5://127.0.0.1:1080 # 仅在同步仓库时使用代理
provider:
- name: allama
base_url: http://localhost:11434
token: ""
# For DEV
models:
embedder:
provider: "huggingface_hub"
models: "bge-m3"
endpoint: "http://127.0.0.1:9000/v1/embeddings"
generator:
provider: "ollama"
models:
- 'gpt-oss:20b'
- name: chutes
base_url: https://llm.chutes.ai
token: "cpk_xxxxxxxxxxxxxxxxxxxx"
models:
- 'moonshotai/Kimi-K2-Instruct'
endpoint: "http://127.0.0.1:11434/v1/chat/completions"
token: ""
# For PROD
#models:
# embedder:
#provider: "chutes"
#models: "bge-m3"
#endpoint: "https://chutes-baai-bge-m3.chutes.ai/embed/v1/embeddings"
#token: "cpk_xxxxxxxxxxxxxxxxxxxx"
# generator:
#provider: "chutes"
#endpoint: "https://llm.chutes.ai/v1/chat/completions"
#token: "cpk_xxxxxxxxxxxxxxxxxxxx"
#models:
# - 'moonshotai/Kimi-K2-Instruct'
embedding:
base_url: http://localhost:11434
token: ""
models: bge-m3
max_batch: 64
dimension: 1024 #维度
max_chars: 8000

2
ui/dist/index.html vendored

File diff suppressed because one or more lines are too long