A lightweight local document ingestion and retrieval package.
Project description
searchbox
searchbox 是一个面向本地知识库 / 文档检索场景的 Python 包,提供:
- 内置 FastAPI 服务端
- 基于 Milvus Lite 的本地向量存储
- 文档抽取、分块、向量化、检索、重排的一体化流程
- 面向多用户、多 collection 的数据隔离能力
- 可切换的 embedding / reranking provider(mock、local、DashScope、vLLM)
- 面向论文摘要库与自定义 collection 的扩展接口
项目定位不是“通用 RAG 全家桶”,而是一个轻量、可本地启动、接口明确的“知识检索底座”。安装后可直接通过 python -m searchbox start 启动,不依赖 Docker。
目录
- 项目概览
- 核心能力
- 项目结构
- 工作流程
- 安装
- 快速开始
- 配置文件说明
- Python API 使用说明
- 服务端 REST API
- Provider 说明
- 文件解析与分块策略
- 多用户、多 collection 与论文库
- 自定义 collection
- 测试与示例脚本
- 开发备注与已知事项
- 许可证
项目概览
searchbox 当前实现由两部分组成:
- 客户端封装:提供
MilvusCorpusSearch、MilvusDocumentSearch、MilvusClient等 Python 接口。 - 内置服务端:位于
searchbox/server/,负责文本入库、向量检索、重排、Milvus 管理与 REST API 暴露。
默认运行模式如下:
- 服务端启动后,使用本地 Milvus Lite
.db文件作为向量数据库。 - 客户端通过 HTTP 调用内置服务端。
- 文档入库时先抽取文本,再按字符数切块,再调用 embedding provider 生成向量。
- 查询时先向量召回 chunk,再通过 reranker 做重排,最后按文件级聚合返回结果。
默认数据库文件名是 ./milvus_local.db,服务端还会维护一个 .searchbox_server_state.json 用于记录临时 collection 的 TTL 和论文卷册状态。
核心能力
1. 文档知识库检索
针对普通文档(txt / md / json / html / pdf 等):
- 支持文件或目录递归入库
- 支持按
user_id做数据隔离 - 支持文件级检索:返回最相关文档
- 支持单文档 chunk 级检索:返回文档内最相关片段
- 支持按
file_path过滤检索范围 - 同一路径重复入库时会先删除旧内容,再写入新版本,避免重复数据
2. 多 provider 推理适配
服务端可切换以下 embedding / reranking provider:
mock:测试用,使用哈希向量与伪重排local:本地 HuggingFace 模型dashscope:阿里云 DashScope APIvllm:外部 vLLM HTTP 服务
3. 多 collection 管理
服务端支持:
- 默认 collection
- 手动创建临时 / 永久 collection
- TTL 自动过期清理
- 按 collection 统计用户与文件
4. 论文摘要库
单独的 paper volume 机制,适合维护“论文摘要向量库”:
- 按 volume 建立 collection
- 按摘要向量检索论文
- 支持删除论文、删除整个 volume
5. 自定义 collection
支持通过 REST API 创建带指定 schema 的 Milvus collection,包括:
- 标量字段
- dense vector 字段
- BM25 sparse 字段
当前仓库对自定义 collection 暴露的是“schema 创建 / 描述 / 删除”接口,不包含通用插入与搜索封装。
项目结构
searchbox/
├── pyproject.toml # 包配置与 optional dependencies
├── README.md # 项目说明
├── smoke_test.py # 端到端 smoke test
├── all_methods_demo.py # 历史示例,和当前接口不完全一致
├── tests/
│ ├── test_milvus_document_search.py
│ └── test_server_fixes.py
│
├── searchbox/
│ ├── __init__.py # 对外导出 API
│ ├── __main__.py # CLI 入口:init / start / check
│ ├── config.py # 客户端配置加载与模板生成
│ ├── milvus.py # HTTP client + 高层检索封装
│ ├── extractors.py # 文件文本抽取
│ ├── factory.py # SearchFactory
│ ├── base.py # 通用搜索基类
│ ├── search_types.py # SearchCandidate 数据结构
│ ├── sources.py # 候选源抽象
│ ├── strategies.py # 搜索策略抽象
│ ├── milvus_config.yaml # 内置默认配置模板
│ └── server/
│ ├── __init__.py # start_server / start_server_from_yaml
│ ├── app.py # FastAPI 路由与服务拼装
│ ├── service.py # KnowledgeService / PaperService
│ ├── chunking.py # 文本切块逻辑
│ ├── store.py # MilvusStore / PaperStore / CustomStore
│ └── providers/
│ ├── base.py
│ ├── mock.py
│ ├── local_qwen.py
│ ├── dashscope_qwen.py
│ └── vllm_qwen.py
工作流程
文档入库流程
add_path / add_paths / add_text
↓
FileTextExtractor 抽取文本
↓
split_text 按段落边界分块
↓
Embedder 生成向量
↓
MilvusStore 写入 collection
文件级检索流程
query
↓
Embedder(query)
↓
Milvus 向量召回 top-p chunks
↓
Reranker 对 chunks 重排
↓
按 file_path 做 max-pooling 聚合
↓
返回 top-k 文件
单文档片段检索流程
query + file_path
↓
限定该文件内的 chunks 做向量召回
↓
Reranker 重排
↓
返回 top-k chunk 命中
安装
1. 基础安装
pip install .
这会安装包本体,但如果你要启动服务端,通常还需要额外依赖。
2. 服务端依赖
pip install "searchbox[server]"
包含:
fastapiuvicorn[standard]pydanticpymilvusmilvuspyyamlhttpx
3. 本地模型依赖
pip install "searchbox[server,local]"
额外包含:
torchtransformers
4. DashScope 依赖
pip install "searchbox[server,dashscope]"
5. 全量安装
pip install "searchbox[all]"
快速开始
方式一:直接用默认 mock 配置体验流程
这是当前最推荐的首次使用方式:
- 无需额外模型服务
- 无需 GPU
- 最适合先验证安装、配置、入库、检索链路是否正常
注意:mock 只适合功能验证,不代表真实语义检索质量。
生成配置文件:
python -m searchbox init
建议先把数据库路径改到一个明确可写的子目录,例如:
milvus_db:
uri: "./data/milvus_local.db"
然后创建目录:
mkdir -p data
启动服务:
python -m searchbox start
健康检查:
python -m searchbox check
# 或
curl http://localhost:18765/health
在 Python 中使用:
from searchbox import MilvusCorpusSearch
search = MilvusCorpusSearch.from_config("milvus_config.yaml", user_id="alice")
search.add_text(
text="检索增强生成系统通常需要文档切块、召回与重排。",
file_path="docs/intro.txt",
title="Intro",
)
results = search.search_pretty("什么是重排", top_k=3)
for item in results:
print(item["score"], item["path"], item["snippet"])
方式二:使用 vLLM 模型服务
如果你希望得到更真实的语义检索效果,推荐使用 vllm provider。当前项目的 vllm 方案要求:
- 一个 embedding 服务
- 一个 reranking 服务
searchbox服务再去调用它们
方案 A:联网直接加载 Hugging Face 模型
强烈建议把 vllm 放到单独的 Python / Conda 环境里启动,而不是和 searchbox 主环境混用。原因是 vllm 依赖较重,常见问题包括:
libstdc++/CXXABI版本冲突- CUDA / PyTorch / Triton 版本不匹配
- 与当前业务环境中的
sqlite3、icu、transformers等依赖互相干扰
一个更稳的做法是新建独立环境,例如:
conda create -n vllm_env python=3.12 -y
conda activate vllm_env
conda install -c conda-forge libstdcxx-ng libgcc-ng -y
pip install vllm
如果需要联网从 Hugging Face 拉模型,再按需执行:
huggingface-cli login
先分别启动两个 vLLM 服务:
# embedding 服务
vllm serve Qwen/Qwen3-Embedding-0.6B --port 8806
# rerank 服务
vllm serve Qwen/Qwen3-Reranker-0.6B \
--port 8807 \
--hf_overrides '{"architectures": ["Qwen3ForSequenceClassification"],"classifier_from_token": ["no", "yes"],"is_original_qwen3_reranker": true}'
然后把 milvus_config.yaml 改成:
embedding:
provider: "vllm"
dim: 1024
metric_type: "IP"
model: "Qwen/Qwen3-Embedding-0.6B"
reranking:
provider: "vllm"
model: "Qwen/Qwen3-Reranker-0.6B"
vllm:
embed_base_url: "http://127.0.0.1:8806"
rerank_base_url: "http://127.0.0.1:8807"
embed_api_key: "EMPTY"
rerank_api_key: "EMPTY"
timeout: 60.0
最后启动 searchbox:
python -m searchbox start
方案 B:本地模型目录方式
如果你不想让 vllm serve 直接联网拉模型,可以先把模型下载到本地目录,再用目录路径启动:
huggingface-cli download Qwen/Qwen3-Embedding-0.6B --local-dir /path/to/models/Qwen3-Embedding-0.6B
huggingface-cli download Qwen/Qwen3-Reranker-0.6B --local-dir /path/to/models/Qwen3-Reranker-0.6B
然后启动:
vllm serve /path/to/models/Qwen3-Embedding-0.6B --port 8806
vllm serve /path/to/models/Qwen3-Reranker-0.6B \
--port 8807 \
--hf_overrides '{"architectures": ["Qwen3ForSequenceClassification"],"classifier_from_token": ["no", "yes"],"is_original_qwen3_reranker": true}'
这里要特别注意:
Qwen/Qwen3-Embedding-0.6B这样的字符串默认是 Hugging Face 模型名,不是要求你手动在当前目录创建同名目录- 如果你传的是本地路径,那就用真实存在的模型目录路径
- 当前
searchbox的vllmprovider 期望的是服务根地址,不要把embed_base_url/rerank_base_url写成带/v1的地址
完整 vLLM 配置示例
如果你希望直接把 milvus_config.yaml 改成可运行的 vllm 版本,可以参考下面的完整配置片段:
server:
host: "127.0.0.1"
port: 18765
milvus_db:
uri: "./data/milvus_local.db"
token: ""
db_name: "default"
collection: "knowledge"
embedding:
provider: "vllm"
dim: 1024
metric_type: "IP"
model: "Qwen/Qwen3-Embedding-0.6B" # 或本地目录路径
reranking:
provider: "vllm"
model: "Qwen/Qwen3-Reranker-0.6B" # 或本地目录路径
vllm:
embed_base_url: "http://127.0.0.1:8806"
rerank_base_url: "http://127.0.0.1:8807"
embed_api_key: "EMPTY"
rerank_api_key: "EMPTY"
timeout: 60.0
milvus_service:
base_url: "http://localhost:18765"
timeout: 60.0
search:
recall_top_p: 20
default_top_k: 5
score_threshold: null
collection: null
ingest:
chunk_max_chars: 2000
chunk_overlap: 200
推荐启动顺序:
# 1) 启动 embedding vLLM
vllm serve Qwen/Qwen3-Embedding-0.6B --port 8806
# 2) 启动 rerank vLLM
vllm serve Qwen/Qwen3-Reranker-0.6B \
--port 8807 \
--hf_overrides '{"architectures": ["Qwen3ForSequenceClassification"],"classifier_from_token": ["no", "yes"],"is_original_qwen3_reranker": true}'
# 3) 启动 searchbox
mkdir -p data
python -m searchbox start
如果你使用本地模型目录,把上面两个 vllm serve 后面的模型名替换成真实路径即可。
如何选择
- 只想先验证功能是否可用:优先
mock - 想要更真实的检索效果,并且有可用 GPU / 推理服务:用
vllm - 本地模型太重、又没有现成 vLLM 服务:再考虑
local或其他 provider
方式三:在代码里后台启动服务
from searchbox import start_server, MilvusCorpusSearch
thread = start_server(
config={
"milvus_uri": "./data/milvus_local.db",
"embed_provider": "mock",
"rerank_provider": "mock",
"embed_dim": 1024,
},
host="127.0.0.1",
port=18765,
background=True,
)
search = MilvusCorpusSearch(user_id="alice", base_url="http://127.0.0.1:18765")
search.add_text("hello retrieval", file_path="demo.txt", title="Demo")
print(search.search("retrieval"))
方式四:通过 YAML 启动
from searchbox import start_server_from_yaml
start_server_from_yaml("milvus_config.yaml")
配置文件说明
默认模板文件位于 searchbox/milvus_config.yaml,执行 python -m searchbox init 会复制到当前目录。
配置结构
server:
host: "127.0.0.1"
port: 18765
milvus_db:
uri: "./milvus_local.db"
token: ""
db_name: "default"
collection: "knowledge"
embedding:
provider: "mock"
dim: 1024
metric_type: "IP"
model: "Qwen/Qwen3-Embedding-0.6B"
batch_size: 32
max_length: 8192
reranking:
provider: "mock"
model: "Qwen/Qwen3-Reranker-4B"
vllm:
embed_base_url: "http://127.0.0.1:8806"
rerank_base_url: "http://127.0.0.1:8807"
embed_api_key: ""
rerank_api_key: ""
timeout: 60.0
dashscope:
api_key: ""
milvus_service:
base_url: "http://localhost:18765"
timeout: 60.0
search:
recall_top_p: 20
default_top_k: 5
score_threshold: null
collection: null
ingest:
chunk_max_chars: 2000
chunk_overlap: 200
配置项分工
server
服务端监听地址与端口,只在启动服务端时使用。
milvus_db
Milvus 连接与默认 collection:
uri:本地 Milvus Lite 数据库路径,建议使用明确可写的子目录,例如./data/milvus_local.dbtoken:远程 Milvus 鉴权时使用db_name:逻辑数据库名collection:默认知识库 collection 名称
注意:
- Milvus Lite 除了数据库文件,还会在同目录创建 lock 文件
- 因此
milvus_db.uri所在目录必须可写 - 如果把数据库直接放到只读目录,通常会在首次入库或检索时报错
embedding
控制 embedding provider:
provider:mock/local/dashscope/vllmdim:向量维度,必须与模型输出一致metric_type:Milvus 向量检索度量方式,默认IPmodel:provider 对应模型名或路径batch_size/max_length:仅local模式使用
reranking
控制 reranker provider 和模型名。
vllm
仅 provider=vllm 时生效:
- embedding 与 reranking 走不同 base URL
- 支持独立 API key
- 支持请求超时设置
dashscope
仅 provider=dashscope 时需要填写 api_key。
milvus_service
客户端访问服务端时使用:
base_urltimeout
search
客户端默认检索参数:
recall_top_p:向量召回 chunk 数default_top_k:最终返回结果数score_threshold:结果过滤阈值collection:默认请求的 collection
ingest
客户端默认入库分块参数:
chunk_max_charschunk_overlap
Python API 使用说明
1. MilvusCorpusSearch
多文件语料检索入口。
创建实例
from searchbox import MilvusCorpusSearch
# 推荐:从 YAML 读取客户端配置
search = MilvusCorpusSearch.from_config("milvus_config.yaml", user_id="alice")
# 使用默认配置(base_url=http://localhost:18765)
search = MilvusCorpusSearch.from_config(None, user_id="alice")
# 直接传参
search = MilvusCorpusSearch(
user_id="alice",
base_url="http://localhost:18765",
collection=None,
recall_top_p=20,
default_top_k=5,
score_threshold=0.3,
chunk_max_chars=2000,
chunk_overlap=200,
timeout=60.0,
)
入库文件 / 目录
# 单文件
search.add_path("/data/report.pdf")
# 目录递归入库
search.add_path("/data/docs/")
# 禁止递归
search.add_path("/data/docs/", recursive=False)
# 包含隐藏文件
search.add_path("/data/docs/", include_hidden=True)
# 批量路径
search.add_paths(["/data/docs/", "/data/notes/a.md"])
直接入库文本
result = search.add_text(
text="这是一段不会落地到本地文件的文本。",
file_path="virtual/doc-001",
title="虚拟文档",
)
文件级检索
results = search.search("量子计算", top_k=5)
返回格式:
[
{
"id": "/data/paper1.pdf",
"title": "paper1.pdf",
"content": "最相关的 chunk 文本...",
"score": 0.91,
"metadata": {
"file_path": "/data/paper1.pdf",
"milvus_score": 0.91,
},
}
]
便于展示的结果
pretty = search.search_pretty("量子计算", top_k=5, snippet_length=280)
返回格式:
[
{
"path": "/data/paper1.pdf",
"file_name": "paper1.pdf",
"score": 0.91,
"snippet": "截断后的摘要文本...",
"metadata": {...},
}
]
文件管理
files = search.list_files()
deleted = search.delete_file("/data/paper1.pdf")
health = search.health()
支持的扩展名
exts = search.supported_extensions()
当前支持:
.txt.md.rst.py.toml.yaml.yml.csv.tsv.html.htm.json.pdf
2. MilvusDocumentSearch
单文档 chunk 级检索入口,适合回答“某一篇文档里,哪一段最相关”。
创建实例
from searchbox import MilvusDocumentSearch
doc = MilvusDocumentSearch.from_config(
config="milvus_config.yaml",
user_id="alice",
file_path="/data/book.pdf",
)
检索片段
results = doc.search("实验设置在哪一节", top_k=3)
返回格式:
[
{
"id": "/data/book.pdf#3",
"title": "book.pdf",
"content": "最相关 chunk 文本...",
"score": 0.84,
"metadata": {
"file_path": "/data/book.pdf",
"chunk_id": 3,
"start_offset": 1200,
"end_offset": 1680,
"milvus_score": 0.84,
},
}
]
展示友好结果
pretty = doc.search_pretty("实验设置在哪一节", top_k=3)
字段包含:
pathfile_namechunk_idstart_offsetend_offsetscoresnippet
3. MilvusClient
底层 HTTP 客户端,适合你自己封装 SDK 或服务调用。
from searchbox import MilvusClient
client = MilvusClient(base_url="http://localhost:18765", timeout=60.0)
client.ingest(
user_id="alice",
files=[{"file_path": "a.txt", "text": "hello world"}],
)
print(client.search(user_id="alice", query="hello"))
print(client.search_chunks(user_id="alice", file_path="a.txt", query="hello"))
print(client.list_files(user_id="alice"))
print(client.health())
4. start_server / start_server_from_yaml
from searchbox import start_server, start_server_from_yaml
start_server(config=..., background=True):编程式启动start_server_from_yaml("milvus_config.yaml"):从 YAML 启动
5. MilvusConfig 与配置工具
from searchbox import (
MilvusConfig,
load_milvus_config,
generate_config_template,
check_service,
)
可用于:
- 读取 YAML
- 生成配置模板
- 检查服务是否存活
服务端 REST API
以下接口来自 searchbox/server/app.py。
1. 健康检查
GET /health
示例返回:
{
"ok": true,
"version": "1.0.0",
"default_collection": "knowledge",
"embed_provider": "mock",
"rerank_provider": "mock",
"active_collections": 1,
"active_volumes": 0
}
2. 文档入库与检索
POST /ingestPOST /searchPOST /search/chunksGET /filesDELETE /filesGET /chunks
POST /ingest
请求体:
{
"user_id": "alice",
"collection": "knowledge",
"chunk": {"max_chars": 2000, "overlap": 200},
"files": [
{
"file_path": "docs/a.txt",
"text": "hello world",
"metadata": {"title": "A"}
}
]
}
POST /search
请求体:
{
"user_id": "alice",
"query": "hello",
"recall_top_p": 20,
"top_k": 5,
"include_content": true,
"score_threshold": 0.3,
"file_paths": ["docs/a.txt"],
"collection": "knowledge"
}
POST /search/chunks
请求体:
{
"user_id": "alice",
"file_path": "docs/a.txt",
"query": "hello",
"recall_top_p": 20,
"top_k": 5,
"score_threshold": 0.3,
"collection": "knowledge"
}
3. collection 管理
POST /collectionsGET /collectionsGET /collections/{name}PATCH /collections/{name}DELETE /collections/{name}DELETE /collection(兼容旧接口)GET /collections/{name}/usersDELETE /collections/{name}/users/{user_id}
特性
- 创建时可指定
temporary=true - 临时 collection 支持
ttl_hours - 过期 collection 会在请求触发时被清理
创建请求示例:
{
"name": "tmp_demo",
"temporary": true,
"ttl_hours": 24
}
4. 论文摘要库 API
POST /papers/collectionsGET /papers/collectionsGET /papers/collections/{volume}DELETE /papers/collections/{volume}POST /papers/ingestDELETE /papers/filesPOST /papers/search
论文入库示例
{
"volume": "acl_2025",
"papers": [
{
"file_path": "papers/001.pdf",
"title": "A Retrieval Paper",
"abstract": "This paper studies...",
"metadata": {"authors": ["A", "B"]}
}
]
}
5. 管理接口
GET /admin/collectionsGET /admin/collection/statsGET /admin/filesGET /admin/papers
适合做管理后台或调试脚本。
6. 自定义 collection 接口
POST /custom-collectionsGET /custom-collections/{name}DELETE /custom-collections/{name}
可定义字段类型:
int8/int16/int32/int64float/doubleboolvarcharjson
额外支持索引类型:
DENSEBM25
Provider 说明
1. mock
特点:
- 无需模型与外网
- 最适合测试流程与 API
- 是当前推荐的默认起步方式
- 检索精度非常有限
实现方式:
- embedding:基于文本 md5 派生伪向量
- reranking:再次用 mock 向量做相似度排序
2. local
特点:
- 本地加载 HuggingFace 模型
- 不依赖远程 API
- 更适合有 GPU 的机器
当前默认模型名:
- embedding:
Qwen/Qwen3-Embedding-0.6B - reranking:
Qwen/Qwen3-Reranker-4B
注意:
- embedding 维度必须与配置中的
embedding.dim一致 LocalQwenReranker使用生成式 yes/no 概率近似相关性得分- CPU 也能运行,但速度可能较慢
3. dashscope
特点:
- 调用阿里云 DashScope API
- 无需本地 GPU
- 需要配置
dashscope.api_key
默认模型名:
- embedding:
text-embedding-v3 - reranking:
gte-rerank
4. vllm
特点:
- 适合已有独立推理服务的场景
- embedding 与 reranking 分别连接不同 HTTP 服务
- 比
mock更接近真实语义检索效果
推荐使用方式:
- embedding:
Qwen/Qwen3-Embedding-0.6B - reranking:
Qwen/Qwen3-Reranker-0.6B - 初次使用可以直接让
vllm serve联网拉模型 - 如果要更稳定可控,可以提前下载到本地,再用本地目录启动
- 最好在独立环境中运行
vllm
约定接口:
- embedding:
POST /pooling - reranking:
POST /v1/rerank
配置示例:
embedding:
provider: "vllm"
dim: 1024
metric_type: "IP"
model: "Qwen/Qwen3-Embedding-0.6B"
reranking:
provider: "vllm"
model: "Qwen/Qwen3-Reranker-0.6B"
vllm:
embed_base_url: "http://127.0.0.1:8806"
rerank_base_url: "http://127.0.0.1:8807"
embed_api_key: "EMPTY"
rerank_api_key: "EMPTY"
timeout: 60.0
注意:
- 当前项目的
vllmprovider 不是直接用 OpenAI Python SDK - 它内部调用的是:
- embedding:
/pooling - reranking:
/v1/rerank
- embedding:
- 因此
base_url应填写服务根地址,例如http://127.0.0.1:8806,不要额外带/v1
运行建议
1. 本地 Lite 模式的索引类型
当前项目默认面向 Milvus Lite 本地模式,dense vector 索引使用 FLAT。
原因是:
Milvus Litelocal mode 不支持HNSW- 本地模式常见支持的是
FLAT、IVF_FLAT、AUTOINDEX
影响是:
FLAT在小规模本地知识库里更稳、更兼容- 大规模数据下搜索速度可能不如
HNSW - 但检索结果本身不会因为
FLAT而“更差”,它是精确搜索
对于当前项目的典型场景(少量 PDF、本地实验、功能验证),FLAT 是更合适的默认值。
2. 开发安装方式
本地开发建议使用 editable install:
pip install -e ".[server]"
这样修改 searchbox/ 下源码后,无需重复打包安装,重启脚本或服务即可生效。
3. 用户目录使用方式
项目支持在“非仓库目录”直接使用,典型流程如下:
cd /path/to/your/workdir
python -m searchbox init
python -m searchbox start
然后在同目录编写脚本:
from searchbox import MilvusCorpusSearch
search = MilvusCorpusSearch.from_config("milvus_config.yaml", user_id="alice")
这也是推荐的终端用户使用方式。
文件解析与分块策略
1. 文件解析
FileTextExtractor 当前支持:
- 纯文本类:
.txt、.md、.rst、.py、.toml、.yaml、.yml、.csv、.tsv - HTML:
.html、.htm - JSON:
.json - PDF:
.pdf
处理方式:
- 文本文件:按 UTF-8 读取,忽略非法字符
- HTML:正则去标签后压缩空白
- JSON:递归展开字典 / 列表为文本
- PDF:优先调用
pdftotext -layout,失败时回退到简单字节级文本提取
注意:PDF fallback 仅为兜底方案,复杂版式文档可能效果一般。若系统安装了 pdftotext,效果通常更可靠。
2. 分块逻辑
分块函数位于 searchbox/server/chunking.py。
规则:
- 基于字符数切块,不是基于 token
max_chars下限 200overlap会限制在max_chars // 2以内- 优先尝试在段落边界
\n\n处分割 - 其次尝试在换行
\n处分割 - 保存
chunk_id、start_offset、end_offset
这使得 chunk 检索结果可以直接回定位到原文偏移区间。
多用户、多 collection 与论文库
1. 多用户隔离
普通知识库数据在 MilvusStore 中带有 user_id 字段。
搜索表达式会自动附加:
user_id == "your_user_id"
因此:
- 同一 collection 内不同用户数据相互隔离
list_files、search、delete_file等接口都基于user_id
2. 多 collection
服务端默认 collection 名称由配置中的 milvus_db.collection 指定,默认是 knowledge。
你也可以在请求中传 collection:
- 让不同业务线使用不同知识库
- 用临时 collection 做实验
- 用永久 collection 做正式环境
3. 临时 collection TTL
POST /collections 可创建临时 collection,服务端会记录过期时间。后续任意请求触发 _evict_expired() 时,过期 collection 会被删除。
适合:
- 临时会话知识库
- 实验性数据集
- 每任务独立索引
4. 论文库 volume
论文库使用独立的 PaperStore,与普通 chunk 库不同:
- 入库对象是论文摘要,不是 chunk
- 不区分
user_id - 每个 volume 对应一个 collection,命名规则为
paper_<规范化后的volume>
自定义 collection
CustomStore 支持创建带 schema 的 Milvus collection。
约束与特性:
- 必须且只能有一个主键字段
- 最多允许
4个索引字段 BM25索引仅适用于varcharDENSE会额外创建对应的 float vector 字段- schema 开启
enable_dynamic_field=True
示例请求:
{
"name": "hybrid_docs",
"fields": [
{"name": "doc_id", "field_type": "varchar", "is_primary": true, "max_length": 128},
{"name": "title", "field_type": "varchar", "max_length": 512},
{"name": "body", "field_type": "varchar", "max_length": 65535, "index_type": "BM25"},
{"name": "embedding", "field_type": "varchar", "max_length": 128, "index_type": "DENSE", "dim": 1024}
]
}
说明:当前项目只提供 schema 生命周期接口;如果你要在这个 collection 上做完整数据读写,需要自行补充插入 / 查询逻辑。
测试与示例脚本
1. smoke_test.py
这是当前仓库里最贴近现实现状的端到端示例,覆盖:
- 后台启动服务
- 文本入库
- 文件级检索
- chunk 级检索
- 同路径重复入库替换旧数据
运行:
python smoke_test.py
2. tests/test_server_fixes.py
关注点:
- 重复入库同一
file_path时会先删旧数据,再插入新数据
3. tests/test_milvus_document_search.py
意图是验证单文档搜索封装;但从当前源码看,测试与 MilvusDocumentSearch 的最新构造参数不完全同步,若后续维护测试,建议按当前实现更新。
4. all_methods_demo.py
该文件引用了当前仓库中已不存在的旧接口(如 docsearch、SqliteDocumentRepository 等),属于历史遗留示例,不能直接作为当前版本使用文档。
开发备注与已知事项
1. 当前主线接口是 Milvus 版
从源码看,当前对外稳定接口主要是:
MilvusCorpusSearchMilvusDocumentSearchMilvusClientstart_server/start_server_from_yaml
base.py、sources.py、strategies.py 等保留了通用搜索抽象,但当前项目主流程已经围绕 Milvus 服务端展开。
2. 文件级检索的聚合策略
服务端会:
- 先召回 chunk
- rerank 每个 chunk
- 对同一文件只保留最高分 chunk 作为该文件得分
所以最终结果是“文件级 max-pooling 聚合”,不是多 chunk 得分求和。
3. 重复入库行为
对同一个 user_id + file_path 再次入库时,旧 chunk 会被删掉再重建。这是源码里的明确设计,不会累计重复版本。
4. PDF 解析依赖系统工具
如果环境中没有 pdftotext,会退回到一个非常轻量的 PDF 文本提取逻辑;对于扫描版 PDF 或复杂布局 PDF,建议自行接入更强抽取方案。
5. 搜索分数含义
最终返回的 score 来自 reranker 分数,不一定等于 Milvus 原始向量分数。客户端结果中的 metadata.milvus_score 当前也复用了最终返回值,而不是单独暴露向量召回原始得分。
6. 关闭客户端连接
MilvusCorpusSearch、MilvusDocumentSearch、MilvusClient 都提供 close() 与上下文管理能力,长生命周期服务中建议显式关闭。
7. setuptools / pymilvus 兼容性
当前项目的服务端依赖对以下组合较敏感:
pymilvusmilvus-litesetuptools
原因是部分 pymilvus 版本在导入时仍依赖 pkg_resources,而较新的 setuptools 已经移除了它。
因此项目当前在 pyproject.toml 中显式限制了:
setuptools>=65.0.0,<82.0.0pymilvus[milvus-lite]>=2.5.0,<2.6.0
如果你手动升级了这些包,启动服务时报 pkg_resources、Function / FunctionType、或 Milvus Lite 相关错误,优先检查是否偏离了这组版本约束。
8. Milvus Lite 可写目录要求
健康检查成功并不代表底层 Milvus Lite 一定已经正确打开数据库。
常见现象是:
GET /health正常- 但第一次
/ingest或/search才报错
这通常是因为:
milvus_db.uri指向的目录不可写- 或其旁边的 lock 文件无法创建
推荐始终使用类似下面的配置:
milvus_db:
uri: "./data/milvus_local.db"
并确保:
mkdir -p data
许可证
本项目使用 MIT License,见 LICENSE。
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file searchbox-0.3.1.tar.gz.
File metadata
- Download URL: searchbox-0.3.1.tar.gz
- Upload date:
- Size: 64.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29be07c29cac869deffb24b04a53bec734201fba30ac2e96f383d73052f1074b
|
|
| MD5 |
ed890b7afb9f640938697ed5f0402aaf
|
|
| BLAKE2b-256 |
00bde4657422a9ad3c882069e78754197ec89134f37abf0f6e0955c869acf8bf
|
File details
Details for the file searchbox-0.3.1-py3-none-any.whl.
File metadata
- Download URL: searchbox-0.3.1-py3-none-any.whl
- Upload date:
- Size: 51.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b98e58b40b52e77115ad45fa84b96d3929c6675cf6cf1e284b905679b8ab875
|
|
| MD5 |
6c00f47022a1b7963187b4ded3b20b5d
|
|
| BLAKE2b-256 |
3dd73f5ef9d247b5e112af9a954167a28d369237308eddff6c61afc6cff58756
|