Repository navigation
feat(search-index): 远端向量推理改用 OpenAI 兼容协议,支持 Ollama / WeMM 等服务 - #184
Conversation
本地语义检索原先只有三个 ONNX 编码器模型:权重要下载到本机,推理也只能在本机跑。WeMM-Embedding-2B 是解码器结构的多模态向量模型,官方只提供 GGUF,走不通现有的 ONNX + tokenizer.json 通路。 新增 backend 为 remote 的模型规格:文本仍在本机切分,向量交给局域网内的服务计算。模型目录加入 wemm-2b-remote(2048 维),在下载列表里直接标记为已就绪,不下载任何文件;远端服务需要 tokenizer 才能把文本切成模型认得的形式,首次使用时从服务端拉取 tokenizer.json 并缓存到模型目录,之后直接用缓存。
目录里的地址只是默认值,换机器或换端口就只能改仓库文件。把 remote_endpoint 补进账号设置:留空沿用目录默认地址,非空则覆盖,前端在远端模型的卡片里提供输入框。 地址必须列进 DEFAULTS:_configure 只比较 DEFAULTS 里的键,否则「只改地址」会被当成没有改动而直接返回旧配置。
Windows 上代理客户端会把代理写进注册表,httpx 默认会读取并使用它。向量服务跑在同一台机器或局域网内时,请求会被代理拦下,报错表现为 502 或连接失败:实测把地址指向 127.0.0.1 上已关闭的端口,拿到的是代理的 502,而不是连接被拒绝,完全看不出真正原因。 新增 is_lan_endpoint() 判断是否需要直连:回环、.local、单标签主机名,以及 ai.providers.is_lan_address 认的 RFC 1918 / IPv6 ULA 网段;局域网定义直接复用该函数,与「允许局域网 IP 的模型服务使用 HTTP」保持同一套口径。远端 tokenizer 的拉取同样处理。
c0e8cdb to
f8ea1c4
Compare
|
感谢这个 PR!把向量推理交给独立服务,能让更多用户用上较大的模型,这个方向很有价值。 |
|
@taosiuman 按照上述要求改了就行 |
|
其实想引入WeMM这个向量模型的初衷就是看到了这个模型通吃文本、音频、视频、图片的潜质,对于处理微信的数据库信息来说再合适不过,我继续再跟进这个PR |
- 远端推理固定走 POST {base}/v1/embeddings({model,input,encoding_format}),
按 data[].index 取向量并兼容 base64 编码;Ollama、LM Studio、vLLM 等可直接
接入,WeMM 等退化为目录预设,不再要求服务方实现本工具自有接口。
- 账号配置新增远端模型名、可选 API Key、允许自签名证书;保存时探测向量维度
并在每次响应校验,维度不一致直接报错而不是给出无意义结果。
- 索引身份指纹(协议+地址+模型名+维度)变化时重建 generation,避免换服务后
旧向量与新查询落在不同向量空间却继续复用。
- 远端不提供 tokenizer.json 时按字符上界切块,不再中断整轮建索引;查询串按
字符上限收口。
- 代理绕过扩展到 100.64.0.0/10(Tailscale 等覆盖网络)与链路本地地址,明文
HTTP 的允许范围保持不变。
- 新增 POST /api/ai/local-search/remote/test,供前端「测试连接」列出服务模型
并探测维度;模型名不被服务端校验,因此清单里没有时给出明确提示。
- 远端模型卡片提供服务地址、模型名、可选 API Key、允许自签名证书,以及 WeMM 2B / Ollama / LM Studio 快速预设与「测试连接」(列出服务上的模型并 探测维度,模型名对不上时直接提示)。 - 底部隐私说明按当前模型是否为远端切换措辞:远端检索会把文本发送到该服务, 本机模型仍是「不上传聊天」。 - AI 服务页标签改为「本机或你指定的服务」,不再笼统承诺检索只在本机运行。
|
按 review 意见改完了(
另外三点是实测才发现的,建议一并考虑:
还有一个与 review 无关但影响可用性的点: 验证方式见 PR 描述——这次是接一台真实部署的 vLLM + WeMM-Embedding-2B(HTTPS 自签名)跑通了建索引与检索,不再只是假服务。 |
背景
本地语义检索原先只有三个 ONNX 编码器模型(BGE Small / BGE Base / Multilingual E5 Small):权重必须下载到本机,向量也只能在本机算。想用更大的向量模型(例如 WeMM-Embedding-2B)就走不通:它是解码器结构的多模态模型,官方只提供 GGUF,套不进现有的 ONNX + tokenizer.json 通路。
最初的实现自定义了一套
POST /embed协议。按 review 意见改为通用的 OpenAI 兼容接口:文本仍在本机切分,向量交给远端服务计算,服务方不需要为本工具另写适配层。改动
local_search/catalog.pyremote_spec(id, endpoint, model, api_key, allow_self_signed, dimension):地址/模型名/密钥由账号配置覆盖目录预设;新增remote_identity()索引身份指纹local_search/inference.pyPOST {base}/v1/embeddings,按data[].index取向量、兼容 base64、请求encoding_format: "float";新增remote_api_base()/parse_remote_vectors()/decode_remote_vector();is_lan_endpoint()扩展为覆盖网络直连local_search/service.pyremote_model/remote_api_key/remote_allow_self_signed/remote_dimension;保存时探测维度;generation 由身份指纹决定是否重建;ensure_tokenizer()取不到时返回None而不是中断建索引;新增remote_probe()local_search/index.pymake_chunks(..., max_chars=None):没有 tokenizer 时按字符上界切块local_search/downloads.pyresources/local_search_models.jsonremote-openai(协议 openai、维度由探测决定、max_chars: 512)routers/local_search.pySettings增加远端模型名/密钥/自签名开关;新增POST /remote/test供前端「测试连接」ai/providers.pyPROXY_BYPASS_NETWORKS/is_proxy_bypass_host():100.64.0.0/10(Tailscale 等)与链路本地也要直连frontend/components/LocalSearchSettings.vuefrontend/components/AiSettings.vue远端服务约定
POST {base}/v1/embeddings,请求{"model": "...", "input": ["..."], "encoding_format": "float"},响应{"data": [{"index": 0, "embedding": [...]}]}/v1即可,也接受完整的/v1/embeddings;裸主机地址会自动补/v1GET {base}/v1/models:可选,只用于「测试连接」列出服务上的模型GET {endpoint}/tokenizer.json:可选,没有就按字符上界切块Authorization: Bearer);HTTPS 使用自签名证书时需要显式勾选Ollama、LM Studio、vLLM、TEI 等都自带这个入口,所以「支持 OpenAI 兼容」即「支持 Ollama」,不需要第二套协议。
四个容易被忽略的点
/v1/models交叉核对并提示。100.64.0.0/10不在 RFC 1918 里;实测环境里存在不可达代理时请求会直接失败。该判定与明文 HTTP 的允许范围分开,后者保持原样。验证
在隔离进程里对接一台真实部署的 vLLM(WeMM-Embedding-2B,HTTPS 自签名证书):
tests/test_local_search*.py83 passed限制
usage.prompt_tokens恒为 0,不依赖它做 token 计量。api-key头、dimensions截断参数、rerank、Ollama 原生/api/embed协议。