Metadata-Version: 2.4
Name: deepdive-search
Version: 0.1.1
Summary: 基于 MECE 原则的布尔搜索逻辑生成器，借助大模型自动生成精确检索式
Author-email: Chandler <275737875@qq.com>
License-Expression: MIT
Keywords: boolean,llm,mece,research,retrieval,search
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: fastapi>=0.100.0
Requires-Dist: jinja2>=3.1.0
Requires-Dist: llmdog>=0.1.0
Requires-Dist: typer>=0.12.0
Requires-Dist: uvicorn>=0.20.0
Provides-Extra: dev
Requires-Dist: httpx>=0.24.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

# deepdive-search

**基于 MECE 原则的布尔搜索逻辑生成器**

借助大模型自动生成精确检索式，让搜索既不遗漏也不重复

[![Python](https://img.shields.io/badge/Python-3.9%2B-blue.svg)](https://python.org)
[![License](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![PyPI](https://img.shields.io/badge/PyPI-deepdive--search-orange.svg)](https://pypi.org/project/deepdive-search/)

</div>

---

## 目录

- [项目简介](#项目简介)
- [功能特性](#功能特性)
- [编程语言与技术栈](#编程语言与技术栈)
- [应用场景](#应用场景)
- [环境依赖](#环境依赖)
- [安装与部署](#安装与部署)
- [快速开始](#快速开始)
- [使用示例](#使用示例)
  - [CLI 命令行](#cli-命令行)
  - [Python API](#python-api)
  - [内部函数调用](#内部函数调用)
  - [Web 可视化界面](#web-可视化界面)
- [配置说明](#配置说明)
  - [LLM 配置](#llm-配置)
  - [数据存储配置](#数据存储配置)
  - [Web 服务配置](#web-服务配置)
- [搜索平台](#搜索平台)
- [数据管理](#数据管理)
- [项目结构](#项目结构)
- [常见问题 FAQ](#常见问题-faq)
- [开源协议](#开源协议)

---

## 项目简介

在技术调研、文献检索、竞品分析等场景中，构造精确的布尔搜索表达式（如 `(A OR B) AND (C NOT D)`）是常见需求，但手动构造存在三大痛点：

| 痛点 | 说明 |
|------|------|
| **遗漏关键词** | 难以穷尽某一技术领域的所有相关术语 |
| **逻辑混乱** | AND / OR / NOT 组合容易产生语义重叠或逻辑矛盾 |
| **缺乏结构** | 搜索词之间缺少层级与分类，难以复用和审查 |

**deepdive-search** 的核心能力是：根据用户输入的技术领域或关键词集合，借助大模型生成符合 **MECE 原则**（Mutually Exclusive, Collectively Exhaustive，相互独立、完全穷尽）的布尔搜索逻辑，使检索结果既不遗漏也不重复。

### 设计原则

- **简单优先** — 聚焦核心功能，避免过度抽象与过度设计
- **开箱即用** — CLI 安装后即可使用，零配置启动
- **可扩展** — 架构留有扩展点，但不预先实现
- **可靠性** — 异常处理完善，数据不丢失
- **本地优先** — 数据存储于本地 JSON，无需外部数据库依赖

---

## 功能特性

| 特性 | 说明 |
|------|------|
| MECE 自动分解 | 将技术领域自动分解为互斥且穷尽的分类体系 |
| 布尔逻辑生成 | 同类内 OR 连接，不同类间 AND 连接，自动生成完整表达式 |
| 多平台输出 | 支持通用布尔、Google、LinkedIn、脉脉、猎聘、GitHub 六种搜索语法 |
| MECE 校验与自修正 | 内置互斥性/穷尽性校验，未通过时自动构造修正 Prompt 重试（最多 2 次） |
| 三种调用方式 | CLI 命令行 / Python API / 内部函数调用，灵活适配不同场景 |
| 长文本关键词提取 | 输入大段描述文本，自动提取关键词并生成搜索逻辑 |
| 本地持久化 | 搜索记录自动保存至 `~/.deepdive_search/records.json` |
| 全文检索与过滤 | 基于内存倒排索引的轻量检索，支持按领域/标签过滤 |
| 数据可迁移 | JSON 格式导入导出，支持跳过/覆盖/重命名三种合并策略 |
| 可视化展示 | FastAPI + Tailwind CSS Web 界面，含树状思维导图视图与列表分页视图 |
| 开箱即用 | 安装后零配置即可使用，Web 首页直接可用 |

---

## 编程语言与技术栈

| 分类 | 技术 | 用途 |
|------|------|------|
| **编程语言** | Python 3.9+ | 运行时 |
| **LLM 调用** | [llmdog](https://pypi.org/project/llmdog/) >= 0.1.0 | 统一 LLM 调用层，兼容 OpenAI Chat Completions 格式 |
| **CLI 框架** | [typer](https://typer.tiangolo.com/) >= 0.12.0 | 命令行界面构建 |
| **Web 后端** | [FastAPI](https://fastapi.tiangolo.com/) >= 0.100.0 | REST API 与页面渲染 |
| **ASGI 服务器** | [uvicorn](https://www.uvicorn.org/) >= 0.20.0 | Web 服务运行 |
| **模板引擎** | [Jinja2](https://jinja.palletsprojects.com/) >= 3.1.0 | HTML 模板渲染 |
| **前端样式** | [Tailwind CSS](https://tailwindcss.com/) (CDN) | 现代白底主题 UI |
| **构建打包** | [hatchling](https://hatch.pypa.io/) | PEP 517 构建后端 |

---

## 应用场景

| 场景 | 说明 |
|------|------|
| 技术调研 | 系统性检索某一技术领域的文献与资料，确保不遗漏关键方向 |
| 竞品分析 | 按 MECE 分类穷尽搜索竞品信息，避免重复覆盖 |
| 文献综述 | 学术论文的系统性检索，生成结构化搜索策略 |
| 专利检索 | 按技术分支穷尽搜索相关专利，分类清晰可审查 |
| 知识体系梳理 | 将模糊的技术领域结构化为清晰分类树 |
| 团队协作 | 导出搜索方案 JSON 供团队成员复用与审查 |
| 搜索策略教学 | 辅助理解布尔搜索逻辑与 MECE 分类方法论 |

---

## 环境依赖

### 运行时依赖

| 依赖 | 最低版本 | 用途 |
|------|----------|------|
| Python | 3.9 | 运行时语言 |
| `llmdog` | 0.1.0 | LLM 统一调用（兼容 OpenAI 格式的任意端点） |
| `typer` | 0.12.0 | CLI 框架 |
| `fastapi` | 0.100.0 | Web 后端框架 |
| `uvicorn` | 0.20.0 | ASGI 服务器 |
| `jinja2` | 3.1.0 | 模板引擎 |

### 开发依赖（可选）

| 依赖 | 用途 |
|------|------|
| `pytest` >= 7.0.0 | 单元测试 |
| `pytest-cov` >= 4.0.0 | 测试覆盖率 |
| `httpx` >= 0.24.0 | FastAPI 测试客户端 |
| `ruff` >= 0.1.0 | 代码规范检查 |

### 外部依赖

- **LLM API 服务**：需一个兼容 OpenAI Chat Completions 格式的 API 端点（如 OpenAI、DeepSeek、阿里云百炼等），并配置有效的 API Key

---

## 安装与部署

### 方式一：从 PyPI 安装（推荐）

```bash
pip install deepdive-search
```

### 方式二：从源码安装

```bash
git clone https://github.com/your-org/deepdive-search.git
cd deepdive-search
pip install .
```

### 方式三：开发模式安装

```bash
git clone https://github.com/your-org/deepdive-search.git
cd deepdive-search
pip install -e ".[dev]"
```

### 验证安装

```bash
deepdive --version
# 输出: deepdive-search 0.1.0
```

### 首次部署步骤

1. **安装模块**：`pip install deepdive-search`
2. **配置 LLM API Key**：`export LLM_API_KEY="sk-xxxxxxxx"`
3. **（可选）配置 API 端点**：`export LLM_API_URL="https://api.deepseek.com/v1/chat/completions"`
4. **（可选）配置模型**：`export LLM_MODEL="deepseek-chat"`
5. **运行首次搜索**：`deepdive search --domain "machine-learning"`
6. **（可选）启动 Web 界面**：`deepdive serve`

---

## 快速开始

### 30 秒上手

```bash
# 1. 安装
pip install deepdive-search

# 2. 配置 API Key
export LLM_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"

# 3. 生成搜索逻辑（关键词模式）
deepdive search --domain "distributed-systems" --keywords "consensus,raft,paxos"

# 或使用长文本模式
deepdive search --text "我正在研究分布式系统中的共识算法，包括Raft、Paxos等"

# 4. 启动 Web 界面
deepdive serve
# 浏览器访问 http://localhost:5555
```

---

## 使用示例

### CLI 命令行

#### 生成搜索逻辑

```bash
# 基本用法（关键词模式）
deepdive search --domain "distributed-systems" --keywords "consensus,raft,paxos"

# 长文本模式（自动提取关键词）
deepdive search --text "我正在研究分布式系统中的共识算法，包括Raft、Paxos、Byzantine Fault Tolerance等"

# 指定搜索平台
deepdive search --domain "machine-learning" --keywords "transformer,attention" --platform google

# 不保存到本地
deepdive search --domain "kubernetes" --no-save

# 指定 LLM 模型
deepdive search --domain "database" --model deepseek-chat

# 使用自定义 llmdog 配置文件
deepdive search --domain "security" --config-file ~/.llmdog-deepseek.yaml
```

#### 查看历史记录

```bash
# 查看全部记录
deepdive list

# 按领域过滤
deepdive list --domain "distributed-systems"

# 按标签过滤
deepdive list --tag "consensus"

# 分页查看
deepdive list --page 2 --page-size 20
```

#### 查看记录详情

```bash
deepdive show <record_id>
```

#### 导出与导入

```bash
# 导出全部记录
deepdive export --output ./backup.json

# 导入记录（跳过已存在的）
deepdive import ./backup.json --merge-strategy skip

# 导入记录（覆盖已存在的）
deepdive import ./backup.json --merge-strategy overwrite

# 导入记录（重命名后导入）
deepdive import ./backup.json --merge-strategy rename
```

#### 列出领域分类

```bash
deepdive domains
```

#### 启动 Web 服务

```bash
# 默认端口 5555
deepdive serve

# 自定义地址和端口
deepdive serve --host 127.0.0.1 --port 8080
```

### Python API

```python
from deepdive_search import generate_search, list_records, get_record, delete_record
from deepdive_search import export_records, import_records
from deepdive_search.models import SearchPlatform, MergeStrategy

# ---- 生成搜索逻辑（关键词模式）----
record = generate_search(
    domain="kubernetes",
    keywords=["pod", "service", "ingress"],
    platform=SearchPlatform.GENERIC,
    save=True,
)

print(f"领域: {record.domain}")
print(f"置信度: {record.bool_result.confidence_score:.2f}")
print(f"布尔表达式: {record.bool_result.expression.raw_expression}")
print(f"解释: {record.bool_result.expression.explanation}")
print(f"记录 ID: {record.record_id}")

# ---- 生成搜索逻辑（长文本模式）----
record = generate_search(
    domain="auto",
    text="我正在研究分布式系统中的共识算法，包括Raft、Paxos、Byzantine Fault Tolerance等",
    platform=SearchPlatform.GOOGLE,
    save=True,
)
print(f"提取关键词: {record.extracted_keywords}")
print(f"通用表达式: {record.bool_result.expression.raw_expression}")
for platform, expr in record.bool_result.expression.platform_expressions.items():
    print(f"  [{platform}] {expr[:80]}")

# ---- 查看历史记录 ----
results = list_records(domain="kubernetes", page=1, page_size=20)
for r in results.items:
    print(f"[{r.record_id[:8]}] {r.domain} | 置信度 {r.bool_result.confidence_score:.2f}")

# ---- 获取单条记录 ----
record = get_record("your-record-uuid")
if record:
    print(record.bool_result.expression.raw_expression)

# ---- 删除记录 ----
success = delete_record("your-record-uuid")

# ---- 导出记录 ----
file_path = export_records("./my_export.json")

# ---- 导入记录 ----
result = import_records("./my_export.json", merge_strategy=MergeStrategy.SKIP)
print(f"新增: {result.imported_count}, 跳过: {result.skipped_count}")
```

### 内部函数调用

适用于需要精细控制生成流程的高级场景：

```python
from deepdive_search.core import MeceDecomposer, BoolCombiner, PromptBuilder
from deepdive_search.core.llm_client import LlmClient
from deepdive_search.core.text_extractor import TextExtractor
from deepdive_search.models import SearchPlatform

# 步骤 1: 构造 Prompt（支持长文本）
builder = PromptBuilder()
messages = builder.build_mece_prompt("database", keywords=["SQL", "NoSQL", "NewSQL"])
# 或使用长文本输入
messages = builder.build_mece_prompt("auto", text="研究数据库技术，包括SQL、NoSQL、NewSQL等")

# 步骤 2: 调用 LLM
client = LlmClient()
raw_response = client.call_json(messages)

# 步骤 3: 解析为 MECE 树
decomposer = MeceDecomposer(llm_client=client)
tree = decomposer.parse_response(raw_response, "database")

# 步骤 4: 校验 MECE 原则
validation = decomposer.validate_mece(tree)
print(f"是否通过: {validation.is_valid}, 评分: {validation.score}")
if not validation.is_valid:
    print(f"问题: {validation.issues}")

# 步骤 5: 生成布尔表达式
combiner = BoolCombiner()
result = combiner.combine(tree)

# 步骤 6: 转换为特定平台格式
query = combiner.to_query_string(result, SearchPlatform.GOOGLE, tree)
print(f"Google 查询: {query}")
```

### Web 可视化界面

```bash
deepdive serve
# 浏览器访问 http://localhost:5555
```

Web 界面提供三个页面：

| 页面 | 路径 | 说明 |
|------|------|------|
| 首页 | `/` | 搜索输入区域 + 最近记录快速预览 |
| 树状视图 | `/tree` | 思维导图式层级展示，点击节点查看详情 |
| 列表视图 | `/list` | 表格分页展示（50 条/页），支持搜索与过滤 |

REST API 端点：

| 方法 | 路径 | 说明 |
|------|------|------|
| `POST` | `/api/search` | 生成 MECE 搜索逻辑 |
| `GET` | `/api/records` | 获取记录列表（分页） |
| `GET` | `/api/records/{id}` | 获取单条记录详情 |
| `DELETE` | `/api/records/{id}` | 删除记录 |
| `GET` | `/api/records/tree` | 获取树状结构数据 |
| `GET` | `/api/domains` | 获取所有领域分类 |
| `GET` | `/api/tags` | 获取所有标签 |

---

## 配置说明

### LLM 配置

deepdive-search 底层通过 [llmdog](https://pypi.org/project/llmdog/) 调用大模型，支持多级配置来源：

```
运行时参数 → 环境变量 → 配置文件 → 内置默认值
（高优先级覆盖低优先级）
```

#### 环境变量

| 环境变量 | 说明 | 默认值 |
|----------|------|--------|
| `LLM_API_KEY` | API Key（**必填**） | 无 |
| `LLM_API_URL` | API 端点地址 | `http://api.openai.com/v1/chat/completions` |
| `LLM_MODEL` | 默认模型名称 | `qwen2.5-coder-32b-instruct` |
| `LLM_TIMEOUT` | 请求超时秒数 | `120` |
| `LLM_MAX_RETRIES` | 最大重试次数 | `3` |
| `LLM_VERIFY_SSL` | 是否验证 SSL | `false` |

#### 配置文件

llmdog 支持 YAML / JSON 配置文件，搜索顺序：

1. `./.llmdog.yaml`
2. `./.llmdog.yml`
3. `./.llmdog.json`
4. `~/.llmdog.yaml`
5. `~/.llmdog.yml`
6. `~/.llmdog.json`

**YAML 配置示例（`~/.llmdog.yaml`）：**

```yaml
api_key: sk-xxxxxxxxxxxxxxxxxxxxxxxx
api_url: https://api.deepseek.com/v1/chat/completions
model: deepseek-chat
timeout: 60
max_retries: 3
verify_ssl: true
```

#### 常见服务商配置

**DeepSeek：**

```bash
export LLM_API_KEY="sk-xxxxxxxx"
export LLM_API_URL="https://api.deepseek.com/v1/chat/completions"
export LLM_MODEL="deepseek-chat"
```

**阿里云百炼（Qwen）：**

```bash
export LLM_API_KEY="sk-xxxxxxxx"
export LLM_API_URL="https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
export LLM_MODEL="qwen-max"
```

**OpenAI：**

```bash
export LLM_API_KEY="sk-xxxxxxxx"
export LLM_API_URL="https://api.openai.com/v1/chat/completions"
export LLM_MODEL="gpt-4o"
```

### 数据存储配置

| 配置项 | 默认值 | 说明 |
|--------|--------|--------|
| 存储路径 | `~/.deepdive_search/records.json` | JSON 数据文件路径 |
| 存储格式 | JSON | 固定，不支持更改 |
| 写入方式 | 原子写入 | 先写临时文件再替换，防止数据损坏 |

### Web 服务配置

| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| 监听地址 | `0.0.0.0` | 可通过 `--host` 参数修改 |
| 监听端口 | `5555` | 可通过 `--port` 参数修改 |
| 前端样式 | Tailwind CSS (CDN) | 需联网加载 |

---

## 搜索平台

| 平台 | 枚举值 | 格式示例 |
|------|--------|----------|
| 通用布尔 | `generic` | `("raft" OR "paxos") AND ("byzantine" OR "bft")` |
| Google | `google` | `("raft" OR "paxos") AND ("byzantine" OR "bft")` |
| LinkedIn | `linkedin` | `raft paxos byzantine bft` |
| 脉脉 | `maimai` | `raft paxos byzantine bft` |
| 猎聘 | `liepin` | `(raft|paxos) (byzantine|bft)` |
| GitHub | `github` | `(raft OR paxos) (byzantine OR bft)` |

> **向后兼容**：`SearchDialect` 作为 `SearchPlatform` 的别名继续可用。

---

## 数据管理

### 搜索记录结构

每条搜索记录包含以下字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `record_id` | UUID | 唯一标识符 |
| `domain` | str | 技术领域 |
| `input_text` | str | 用户输入的原始长文本 |
| `extracted_keywords` | list[str] | 从 input_text 中提取的关键词 |
| `input_keywords` | list[str] | 向后兼容属性，同 extracted_keywords |
| `mece_tree` | MeceTree | MECE 分类树 |
| `bool_result` | BoolSearchResult | 布尔搜索结果 |
| `tags` | list[str] | 分类标签 |
| `created_at` | str | 创建时间（ISO 8601） |
| `updated_at` | str | 更新时间（ISO 8601） |
| `llm_model` | str | 使用的 LLM 模型 |
| `llm_backend` | str | 使用的 LLM 后端 |

### 导入导出

```bash
# 导出全部记录
deepdive export --output ./backup.json

# 导入记录
deepdive import ./backup.json --merge-strategy skip
```

三种合并策略：

| 策略 | 说明 |
|------|------|
| `skip` | 跳过已存在的记录（默认） |
| `overwrite` | 覆盖已存在的记录 |
| `rename` | 生成新 UUID 后导入 |

---

## 项目结构

```
deepdive-search/
├── pyproject.toml                          # 构建配置与依赖声明
├── README.md                               # 本文档
├── design_spec.md                          # 技术设计规格书
├── examples/
│   └── basic_usage.py                      # 使用示例
└── src/deepdive_search/
    ├── __init__.py                         # 包入口，导出公开 API
    ├── __version__.py                      # 版本号 (0.1.0)
    ├── models.py                           # 数据模型层
    ├── api.py                              # 外部 Python API 入口
    ├── cli.py                              # Typer CLI 入口 (7 个子命令)
    ├── core/                               # 核心引擎层
    │   ├── prompt_builder.py               # Prompt 构造器
    │   ├── llm_client.py                   # llmdog 封装层
    │   ├── mece_decomposer.py              # MECE 分解器 + 校验 + 自修正
    │   ├── bool_combiner.py               # 布尔组合器 (9 种平台)
    │   └── text_extractor.py              # 长文本关键词提取器
    ├── prompts/                            # Prompt 模板
    │   └── mece_search.py                  # 内置 MECE 分解指令模板
    ├── store/                              # 数据存储层
    │   ├── json_store.py                   # JSON 存储 (原子写入/分页/CRUD)
    │   ├── search_index.py                 # 倒排索引检索
    │   └── migration.py                    # 导入导出与迁移
    └── web/                                # Web 可视化层
        ├── app.py                          # FastAPI 应用实例
        ├── routers/                        # 路由模块
        │   ├── search.py                   # 首页 + 生成 API
        │   ├── records.py                  # 列表视图 + 记录 CRUD
        │   └── tree.py                     # 树状视图
        ├── static/css/app.css              # Tailwind 补充样式
        └── templates/                      # Jinja2 模板
            ├── base.html                   # 基础模板 (白底现代风格)
            ├── index.html                  # 首页
            ├── tree_view.html              # 树状/思维导图视图
            └── list_view.html              # 列表分页视图
```

---

## 常见问题 FAQ

### Q1: 安装后运行 `deepdive` 提示命令未找到？

**A:** 请确认 Python 的 Scripts/bin 目录已在系统 PATH 中。可以尝试：

```bash
python -m deepdive_search.cli --help
```

或重新安装：

```bash
pip install --force-reinstall deepdive-search
```

### Q2: 提示 `llmdog 未安装`？

**A:** llmdog 是 deepdive-search 的核心依赖，正常安装时会自动安装。若缺失，请手动安装：

```bash
pip install llmdog>=0.1.0
```

### Q3: LLM 调用失败，提示 API Key 无效？

**A:** 请检查：

1. 环境变量 `LLM_API_KEY` 是否已设置：`echo $LLM_API_KEY`
2. API Key 是否有效且未过期
3. API 端点地址是否正确（不同服务商地址不同，参见[配置说明](#llm-配置)）

### Q4: 生成的搜索逻辑质量不高，关键词重叠或遗漏？

**A:** 可能原因与建议：

- **模型能力不足**：尝试使用更强的模型（如 `gpt-4o`、`qwen-max`）
- **领域过于宽泛**：提供更多具体关键词作为输入
- **MECE 校验未通过**：查看输出中的置信度评分，低于 0.7 建议重新生成

### Q5: 如何切换不同的 LLM 服务商？

**A:** 三种方式（优先级从高到低）：

```bash
# 方式 1: 环境变量
export LLM_API_URL="https://api.deepseek.com/v1/chat/completions"
export LLM_MODEL="deepseek-chat"

# 方式 2: CLI 参数
deepdive search --domain "test" --config-file ~/.llmdog-deepseek.yaml

# 方式 3: Python API
from deepdive_search.api import generate_search
record = generate_search("test", config_file="~/.llmdog-deepseek.yaml")
```

### Q6: 数据存储文件在哪里？可以修改路径吗？

**A:** 默认路径为 `~/.deepdive_search/records.json`。Python API 中可通过 `JsonStore` 的 `data_file` 参数修改：

```python
from deepdive_search.store.json_store import JsonStore
store = JsonStore(data_file="/custom/path/records.json")
```

### Q7: 如何在不同机器间迁移搜索记录？

**A:** 使用导出/导入功能：

```bash
# 源机器导出
deepdive export --output ./my_records.json

# 将文件拷贝至目标机器后导入
deepdive import ./my_records.json --merge-strategy skip
```

### Q8: Web 界面无法加载样式（Tailwind CSS）？

**A:** Web 界面使用 Tailwind CSS CDN，需联网加载。离线环境下样式将降级为浏览器默认样式。

### Q9: JSON 数据文件损坏怎么办？

**A:** deepdive-search 在读取时检测到 JSON 解析错误会自动备份损坏文件（后缀 `.corrupted_时间戳.json`）并创建新的空数据文件。你可以手动从备份中恢复数据。

### Q10: 支持哪些 Python 版本？

**A:** 支持 Python 3.9、3.10、3.11、3.12。Python 3.13 未经过完整测试但可能可用。

---

## 开源协议

本项目基于 [MIT License](https://opensource.org/licenses/MIT) 开源。

```
MIT License

Copyright (c) 2026 deepdive-search contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
