XERJ语义搜索完全指南:semantic_text字段与neural嵌入模式怎么配才对?
【免费下载链接】xerjXERJ is the new way for AI to search data. Its autoindex capability activates agents to know your data without the token waste of grep and sed. One command indexes code, docs, logs and PDFs for search, RAG, security audits and agent memory, using 40x fewer tokens than grep. Elasticsearch compatible, so existing clients just work.项目地址: https://gitcode.com/GitHub_Trending/xe/xerj
XERJ 是一个为 AI 时代设计的搜索引擎,其内置的semantic_text 语义字段和neural 嵌入模式,让你无需搭建独立的向量数据库、也无需调用外部嵌入 API,就能对文档、日志、代码和 PDF 做"按意思找内容"的语义搜索。本文将手把手讲清楚:semantic_text 字段如何声明、三种嵌入后端(lexical / neural / proxy)如何选型与配置,以及让语义搜索效果达到预期的 5 个实用技巧。
semantic_text 字段是什么?一句话:写文字,自动变向量
传统做法要搭一套完整的 RAG 检索栈:向量数据库 + 嵌入服务 + 同步胶水代码。而 XERJ 把这套东西压缩成一个字段类型:
PUT /kb { "mappings": { "properties": { "title": { "type": "text" }, "body": { "type": "semantic_text" } } } }声明之后,XERJ 会在写入时自动把body字段的文本向量化,生成一个伴生的 HNSW 向量字段(body_vector,默认 384 维、余弦相似度)。你不需要声明dense_vector、不用记录维度、不用管第二个存储系统 —— 写入和查询时发送的始终是普通字符串。完整的端到端示例见 docs/recipes/semantic-search-rag.md 和可运行的 docs/examples/semantic-search-rag/rag_demo.py。
不想手写 mapping?用 autoindex 自动映射
如果你的数据是一个文件夹(Markdown 事故复盘、FAQ、NDJSON 工单、CSV),一条命令就能搞定:
xerj autoindex ./demo/data/support-folderautoindex 会嗅探每个文件的格式、推断 schema,并把散文正文自动映射成带semantic_text 正文的索引(ax-txtprose),而结构化文件保留精确可过滤的类型化字段。配方文档在 docs/recipes/autoindex-semantic-search.md,可直接运行的脚本是 recipes/autoindex_semantic.sh。
三种嵌入后端:lexical、neural、proxy 怎么选?
semantic_text的"聪明程度"取决于嵌入后端。后端只需在服务器启动时选定一次,之后所有写入与查询都走同一个模型。通过三种方式任选其一配置:--embed-mode启动参数、配置文件embedding.mode(可参考 demo/playbooks/neural-embedder-verification/neural.toml),或环境变量XERJ_EMBED_MODE:
| 嵌入模式 | 后端 | 质量 | 部署成本 |
|---|---|---|---|
lexical(默认) | 内置特征哈希 | 仅词汇重叠,离线确定性 | 零成本,无模型文件 |
neural | 内置 BERT(all-MiniLM-L6-v2) | 真正的神经语义 | 零额外服务,模型首次使用自动下载一次(约 90 MB) |
proxy | 任意 OpenAI 兼容/v1/embeddings | 取决于你指向的模型 | 需配置embedding.default_endpoint |
默认 lexical 模式:够用,但要知道它的边界
默认的后置是词法嵌入 —— 它把重叠和相关词汇映射到向量空间。当问题和答案共享部分词汇时(同义词、换一种说法),它能工作得很好,覆盖了大量真实的支持/FAQ 流量。但它不是神经句向量模型,拿不到词汇桥梁的深层语义会失手。官方配方里记录了一个典型翻车现场:
Q: 'how do I rotate my API key' semantic top -> kb-5 Rate limits (expected kb-1) # lexical 模式文档标题虽然叫 "Rotating an API key",但正文里从没用过 "rotate" 这个词 —— 词法模式下这个改述就查不到了。官方回归测试 engine/tests/es-compat-yaml/yaml/vectors/50_semantic_text_builtin.yml 也明确锁定了这个"词汇重叠"的保证边界。
如何开启 neural 嵌入模式:一条参数,真正理解语义
启动命令
xerj --insecure --data-dir ./data --embed-mode neuralneural 后端内置在标准二进制里,不需要特殊编译。首次使用时自动下载sentence-transformers/all-MiniLM-L6-v2(6 层 BERT、384 维)到本地缓存,之后在进程内用 CPU 推理 —— 纯 Rust 实现,无 Python、无外部服务。
切换后端后,上面那个 "rotate" 改述就能命中kb-1了 —— BERT 编码器能理解rotate ≈ regenerate ≈ replace,即使没有任何共享词汇。在官方句子相似度基准上,内置 neural 嵌入对改述句的余弦相似度是0.72,对无关句是−0.04,能清晰区分开(词法嵌入做不到)。
在 8 条已判定的查询上,官方实测词法默认模式 precision@3 为 0.4167,而 neural 嵌入模式 precision@3 达到 0.6667 且 recall 为 1.0 —— 这是"要不要开 neural"最直观的一组数字。
离线 / 气隙环境的 neural 配置
模型默认从 HuggingFace Hub 下载一次后走本地缓存。如果节点没有外网,用embedding.local_model_dir指向你预先放置好的模型目录即可。相关设置与批处理参数(batch_size、timeout_ms、neural_window_concurrency等)都在配置文件[embedding]段里,完整注释见 engine/xerj.default.toml。
验证当前节点加载了哪个嵌入器
别靠猜,直接问服务器:
curl -s -XGET http://127.0.0.1:9200/v1/embedding/identity{"data":{"backend":"neural","resumable":false, "non_resumable_reason":"the neural model is is not content-addressed; use a fresh autoindex state after changing it", "semantic_contract":"semantic_text-derived-vector.v1","version":1}}注意resumable: false的含义:已有的 semantic_text 索引不能在 lexical 与 neural 之间切换后端(避免两种向量空间混在一个字段里)。需要切换时,用新的索引前缀和新的--state-dir重建即可。
写 semantic 查询:field、query、k 三个参数
检索时用顶层semantic查询,与 Elasticsearch 8.x 同一套线路协议,现有 ES 客户端无需改动:
GET /kb/_search { "size": 2, "query": { "semantic": { "field": "body", "query": "how do I regenerate my API token", "k": 2 } } }三个参数的含义:
| 参数 | 含义 | 建议 |
|---|---|---|
field | 指向semantic_text字段 | 固定为你映射的语义字段 |
query | 自然语言问题 | 直接写用户原话 |
k | 从向量索引取多少个最近邻 | 先 5–10,再配合size控制返回条数 |
在官方 5 篇文档的知识库上跑 5 个改述问题(没有一个与原文共享完整措辞),semantic查询 5/5 全部命中正确文档且排名第一;同一批问题走关键词match查询则零命中。
混合检索:关键词 + 向量一条请求搞定
如果你的场景既要精确术语匹配又要语义理解,用hybrid查询在同一个索引里融合 BM25 与 kNN(RRF 倒数排名融合),一次请求返回已融合的排序 —— 不需要第二套存储,也不需要在应用层做拼接重排。完整示例见 docs/recipes/hybrid-search.md 和 docs/examples/hybrid-search/hybrid_search.py。
5 个让配置"才对"的实战技巧
1️⃣ 嵌入真正承载含义的文本如果标题对用户很重要,就把标题也放进semantic_text字段(或者建第二个semantic_text字段配合hybrid融合)。只嵌入正文、却指望标题里的词能被搜到,是 lexical 模式下最常见的翻车点。
2️⃣ 长文档放心写:XERJ 按段落分块嵌入写入时,长semantic_text值会被切成重叠段落、逐段嵌入;查询时按文档内最佳匹配段落计分(max-sim),而不是被整篇平均稀释。官方回归测试 engine/tests/es-compat-yaml/yaml/vectors/52_semantic_text_chunked.yml 专门锁定了这个行为:一篇夹着生物段落的海量金融长文,能被生物类问题排到纯金融短文前面。
3️⃣ 用_rank_eval量化你的语义质量拿到相关度判定后,用与 Elasticsearch 相同的线路 API 给排序打分:precision、recall、dcg(加"normalize": true得 nDCG)、mean_reciprocal_rank都是真实计算,未知指标名会直接返回 400 而不是给个误导性的数字。调嵌入、调k、调 hybrid 权重时,用这组指标说话。
4️⃣ 需要特定模型时走 proxy,而不是魔改二进制--embed-mode proxy加embedding.default_endpoint就能接入任意 OpenAI 兼容/v1/embeddings服务(OpenAI、Cohere、本地 vLLM 等),写入和查询都自动走该模型。另有实验性的 ONNX 后端(需onnx-experimental特性编译),细节见 docs/EXPERIMENTAL_ONNX.md。
5️⃣ 换嵌入后端 = 换新索引再次强调:已写入语义索引的后端不能热切换。规划好再用新前缀 + 新--state-dir重建,等新索引验证通过再下线旧索引。官方验证 playbook 在 demo/playbooks/neural-embedder-verification/,其中的 sanity.py 可以帮你做切换前后的 sanity check。
总结:一张表记住正确姿势
| 你的情况 | 推荐配置 |
|---|---|
| 快速原型 / 离线确定性 | semantic_text+ 默认 lexical,零配置 |
| 生产级语义质量、不想加组件 | --embed-mode neural,模型本地缓存 |
| 已有自己的嵌入模型 | --embed-mode proxy+embedding.default_endpoint |
| 已有向量、只要存储和检索 | 用原始dense_vector+knn,别用semantic_text |
| 关键词与语义都要 | semantic_text+hybrid查询(RRF 融合) |
记住这条决策线:有现成嵌入 → 原始knn;有文本、想让引擎代劳 →semantic_text;要语义质量 → neural 或 proxy。更多可复现配方见 docs/recipes/ 目录,向量检索底层(HNSW 图、精确重打分、recall 实测)的设计说明见 docs/recipes/vector-search-knn.md。
【免费下载链接】xerjXERJ is the new way for AI to search data. Its autoindex capability activates agents to know your data without the token waste of grep and sed. One command indexes code, docs, logs and PDFs for search, RAG, security audits and agent memory, using 40x fewer tokens than grep. Elasticsearch compatible, so existing clients just work.项目地址: https://gitcode.com/GitHub_Trending/xe/xerj
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考