Metadata-Version: 2.4
Name: searchbox
Version: 0.3.3
Summary: A compact local vector search service with an agent interface.
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: pymilvus[milvus-lite]<2.6.0,>=2.5.0
Requires-Dist: fastapi>=0.100.0
Requires-Dist: uvicorn[standard]>=0.22.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: langchain>=0.2.0
Requires-Dist: langchain-openai>=0.1.0
Requires-Dist: langgraph>=0.2.0
Requires-Dist: prompt-toolkit>=3.0.0
Requires-Dist: rich>=13.0.0

# searchbox

`searchbox` 是一个轻量的本地知识库检索项目，内置：

- Milvus Lite 本地向量数据库
- FastAPI 检索服务
- 文档入库、文档检索、chunk 检索、文件删除
- Agent 工具调用能力
- 可配置的 embedding / rerank provider

它的目标不是做复杂 RAG 平台，而是提供一个容易安装、容易启动、容易二次开发的本地向量检索底座。

## 适合什么场景

- 把本地文档放进向量数据库
- 根据问题检索相关文档
- 在指定文档内部定位相关片段
- 让 Agent 自动调用本地知识库和 Web 搜索工具
- 作为一个可发布到 pip 的精简 Python package

## 项目结构

```text
searchbox/
├── pyproject.toml
├── config.example.yaml
├── README.md
└── searchbox/
    ├── __main__.py              # CLI: init / start / check / run
    ├── __init__.py              # 对外导出
    ├── config.py                # Agent 配置
    ├── clients.py               # HTTP 客户端、文件读取
    ├── agent.py                 # Agent 工具编排
    ├── default_config.yaml      # 默认配置模板
    └── server/
        ├── app.py               # FastAPI + 检索业务逻辑
        ├── store.py             # Milvus Lite 读写
        └── chunking.py          # 文本切块
```

服务端被刻意压平，核心逻辑集中在 `server/app.py`、`server/store.py`、`server/chunking.py`，方便阅读和维护。

## 安装

在项目根目录执行：

```bash
cd /home1/lsn/重构版searchbox
pip install -e .
```

安装后会得到一个命令：

```bash
searchbox --help
```

## 5 分钟跑通

### 1. 生成配置文件

```bash
searchbox init --output config.yaml
```

### 2. 创建数据目录

```bash
mkdir -p data
```

默认向量数据库文件是：

```text
./data/milvus_local.db
```

这个文件由 Milvus Lite 在运行时创建，不需要手动准备。

### 3. 启动本地知识库服务

```bash
searchbox start --config config.yaml
```

默认监听：

```text
http://127.0.0.1:18765
```

### 4. 检查服务

另开一个终端：

```bash
searchbox check --config config.yaml
```

正常会输出：

```json
{"ok": true}
```

## 入库和检索

当前包提供两种使用方式：

- HTTP API
- Python 客户端

### 方式一：HTTP API

#### 文本入库

```bash
curl -X POST http://127.0.0.1:18765/ingest \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "alice",
    "files": [
      {
        "file_path": "notes/example.txt",
        "text": "searchbox 是一个本地向量检索项目，使用 Milvus Lite 存储文档 chunk。"
      }
    ]
  }'
```

#### 文档级检索

```bash
curl -X POST http://127.0.0.1:18765/search \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "alice",
    "query": "searchbox 用什么存储向量？",
    "top_k": 3,
    "include_content": true
  }'
```

#### 单文档 chunk 检索

```bash
curl -X POST http://127.0.0.1:18765/search/chunks \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "alice",
    "file_path": "notes/example.txt",
    "query": "Milvus Lite 的作用是什么？",
    "top_k": 3
  }'
```

#### 查看文件列表

```bash
curl "http://127.0.0.1:18765/files?user_id=alice"
```

#### 删除文件

```bash
curl -X DELETE http://127.0.0.1:18765/files \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "alice",
    "file_path": "notes/example.txt"
  }'
```

### 方式二：Python 客户端

```python
from searchbox import KnowledgeClient

client = KnowledgeClient("http://127.0.0.1:18765")

client.ingest(
    user_id="alice",
    files=[
        {
            "file_path": "notes/example.txt",
            "text": "searchbox 使用 Milvus Lite 做本地向量数据库。",
        }
    ],
)

results = client.search(
    user_id="alice",
    query="searchbox 用什么做向量数据库？",
    top_k=3,
)

print(results)
```

如果你要把本地文件或目录入库：

```python
from searchbox import KnowledgeClient

client = KnowledgeClient("http://127.0.0.1:18765")
inserted_files = client.add_path(user_id="alice", path="./docs")

print(inserted_files)
```

支持的文件类型包括：

- `.txt`
- `.md`
- `.rst`
- `.py`
- `.toml`
- `.yaml`
- `.yml`
- `.csv`
- `.tsv`
- `.html`
- `.htm`
- `.json`
- `.pdf`

PDF 读取依赖系统命令 `pdftotext`。如果环境没有这个命令，PDF 内容会读不到。

## Agent 使用

Agent 会把本地知识库检索、单文档 chunk 检索、文件管理、Web 搜索包装成工具，让模型按需调用。

### 命令行运行 Agent

先启动服务：

```bash
searchbox start --config config.yaml
```

另开终端：

```bash
searchbox run --config config.yaml "帮我查一下本地文档里关于 Milvus Lite 的内容"
```

如果想像终端助手一样连续交互：

```bash
searchbox chat --config config.yaml
```

进入后直接输入问题：

```text
你> 多模态检索
你> 继续说说它的数据集
你> q
```

`chat` 模式会保留本轮会话上下文。输入 `exit`、`quit` 或 `q` 退出。

会话会自动保存到：

```text
~/.searchbox/sessions/
```

恢复最近一次会话：

```bash
searchbox chat --config config.yaml --resume
```

恢复指定会话：

```bash
searchbox chat --config config.yaml --resume 20260716-120000-a1b2c3
```

列出历史会话：

```bash
searchbox chat --list-sessions
```

交互模式支持：

- Markdown 渲染
- 输出流式显示
- 检索 / 思考阶段 spinner
- 历史记录上下键检索
- 自动保存 / 恢复历史会话
- `/sessions` 列出历史会话
- `/resume <session_id>` 切回历史会话
- `/history` 查看当前会话历史
- `/new` 创建新会话
- `/model <model_name>` 动态切换主模型
- `/multi` 开启/关闭多行输入
- `/status` 查看当前连接、用户、模型
- `/clear` 清空上下文
- `/cls` 清屏

多行输入开启后，使用 `Esc+Enter` 提交。

### Python 中运行 Agent

```python
from langchain_core.messages import HumanMessage
from searchbox import AgentConfig, build_agent

cfg = AgentConfig.from_yaml("config.yaml")
agent = build_agent(cfg)

result = agent.invoke({
    "messages": [
        HumanMessage(content="本地知识库里有没有关于 Milvus Lite 的说明？")
    ]
})

print(result["messages"][-1].content)
```

## 配置说明

生成的 `config.yaml` 同时包含服务端配置和 Agent 配置。

### 服务端配置

```yaml
server:
  milvus_uri: "./data/milvus_local.db"
  milvus_db_name: "default"
  milvus_collection: "knowledge"
  embed_provider: "mock"
  rerank_provider: "mock"
  embed_dim: 1024
  metric_type: "IP"
  default_chunk_max_chars: 2000
  default_chunk_overlap: 200
```

关键字段：

- `milvus_uri`：Milvus Lite 数据库文件路径
- `milvus_collection`：默认 collection 名称
- `embed_provider`：embedding provider，当前支持 `mock` 和 `vllm`
- `rerank_provider`：rerank provider，当前支持 `mock` 和 `vllm`
- `embed_dim`：向量维度，必须和实际 embedding 模型输出一致
- `metric_type`：向量相似度指标，默认 `IP`
- `default_chunk_max_chars`：默认 chunk 最大字符数
- `default_chunk_overlap`：相邻 chunk 重叠字符数

### vLLM 配置

如果你有外部 vLLM embedding / rerank 服务，可以改成：

```yaml
server:
  embed_provider: "vllm"
  rerank_provider: "vllm"
  embed_dim: 1024
  vllm_embed_base_url: "http://127.0.0.1:8806"
  vllm_embed_model: "Qwen/Qwen3-Embedding-0.6B"
  vllm_embed_api_key: "EMPTY"
  vllm_rerank_base_url: "http://127.0.0.1:8807"
  vllm_rerank_model: "Qwen/Qwen3-Reranker-4B"
  vllm_rerank_api_key: "EMPTY"
```

如果只是本地测试，不需要配置 vLLM，默认 `mock` provider 就能跑通完整流程。

注意：`mock` provider 只是确定性的假向量和假重排，适合 smoke test，不适合真实语义检索效果评估。

### Agent 配置

```yaml
llm:
  base_url: "http://127.0.0.1:7815/v1"
  api_key: "replace_me"
  model: "gpt-4o-mini"
  temperature: 0

knowledge:
  base_url: "http://127.0.0.1:18765"
  user_id: "default"
  collection: null
  timeout: 60

web:
  server_url: "http://127.0.0.1:16536/search"
  api_key: ""
  engine: "google"
  timeout: 30

runtime:
  final_top_k: 5
  recall_top_p: 20
```

关键字段：

- `llm.base_url`：OpenAI-compatible chat API 地址
- `llm.api_key`：模型服务 API key
- `llm.model`：模型名称
- `knowledge.base_url`：本地 searchbox 服务地址
- `knowledge.user_id`：当前用户 ID，用于数据隔离
- `web.server_url`：Web 搜索服务地址
- `runtime.recall_top_p`：embedding 粗排召回 chunk 数
- `runtime.final_top_k`：rerank 后最终返回结果数

旧配置字段 `runtime.default_top_k` 仍兼容，但新配置建议使用 `runtime.final_top_k`。

## Milvus 数据库逻辑

searchbox 使用 Milvus Lite 存储 chunk 向量。

一篇文档入库后，会变成多条 chunk 记录：

```text
document
  ↓
chunk 0
chunk 1
chunk 2
  ↓
Milvus records
```

每条记录包含：

```text
user_id
file_path
title
chunk_id
start_offset
end_offset
content
embedding
```

查询时：

```text
query
  ↓
embedding(query)
  ↓
Milvus 召回 top chunks
  ↓
rerank
  ↓
按 file_path 聚合成文档级结果
```

单文档 chunk 检索则会增加 `file_path` 限制，只在指定文档内部搜索。

## 用户隔离

所有入库、查询、删除接口都需要 `user_id`。

不同用户的数据放在同一个 collection 中，但查询表达式会自动加上：

```text
user_id == "xxx"
```

因此同一个服务可以服务多个用户，但当前精简版不提供复杂的用户管理后台。

## CLI 命令

```bash
searchbox init --output config.yaml
```

生成默认配置。

```bash
searchbox start --config config.yaml --host 127.0.0.1 --port 18765
```

启动本地知识库服务。

```bash
searchbox check --config config.yaml
```

检查服务健康状态。

```bash
searchbox run --config config.yaml "你的问题"
```

运行一次 Agent。

```bash
searchbox chat --config config.yaml
```

进入连续交互模式。

## 发布到 pip 的注意事项

数据库文件不应该打包进 wheel。

应该发布：

- Python 源码
- `default_config.yaml`
- `pyproject.toml`
- README

不应该发布：

- `data/milvus_local.db`
- `__pycache__/`
- `.pytest_cache/`
- 本地测试文档
- API key

## 常见问题

### 1. 为什么启动后没有看到数据库文件？

Milvus Lite 通常在第一次创建 collection 或写入数据时生成数据库文件。先调用一次 `/ingest`。

### 2. 为什么 mock 检索效果不好？

`mock` provider 只用于跑通流程。真实语义检索需要配置真实 embedding 模型，例如 vLLM embedding 服务。

### 3. 为什么 PDF 入库为空？

PDF 读取依赖 `pdftotext`。确认系统里有：

```bash
pdftotext -v
```

### 4. 重新入库同一个文件会重复吗？

不会。同一个 `user_id + file_path` 重新入库前，会先删除旧 chunk，再写入新 chunk。

### 5. 当前支持多个 collection 吗？

当前精简版只支持默认 collection。配置项中保留了 `milvus_collection`，但没有恢复多 collection 管理 API。

## 开发建议

优先从这三个文件开始看：

- `searchbox/server/app.py`
- `searchbox/server/store.py`
- `searchbox/agent.py`

如果要扩展真实 provider，建议直接在 `server/app.py` 里增加 `_build_embed()` 或 `_build_rerank()` 分支，保持项目结构简单。
