Metadata-Version: 2.4
Name: rag-assistant-ldxs
Version: 2.0.0b1
Summary: rag-assistant — AI Agent
Home-page: https://github.com/Ldxs001/workbuddy-skills
Author: Ldxs (wUwproject)
Author-email: wuwofc@yeah.net
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: chromadb>=0.5
Requires-Dist: hnswlib>=0.8
Requires-Dist: sentence-transformers>=3.0
Requires-Dist: huggingface-hub>=0.20
Requires-Dist: modelscope>=1.15
Requires-Dist: torch>=2.0
Requires-Dist: transformers>=4.30
Requires-Dist: numpy>=1.24
Requires-Dist: easyocr>=1.7
Requires-Dist: requests>=2.28
Requires-Dist: duckduckgo_search>=4.0
Requires-Dist: jieba>=0.42
Requires-Dist: sentencepiece>=0.1
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# RAG Assistant

> 本地知识库问答智能体 — LLM 驱动的组合式语义检索与多库路由。
> 版本：2.0.0b1 | 作者：wUwproject | 许可证：Apache 2.0

## ⚠️ 从 1.x 升级到 2.x 必须重建 HNSW 索引

**2.x 将向量搜索引擎从 ChromaDB 内置 HNSW 替换为独立 hnswlib 索引，以解决 ChromaDB Rust 后端在 Windows 上的 HNSW 持久化 bug。**

升级后首次搜索会自动触发懒重建（每个 KB 约 1-2 分钟），也可手动点击 🔨 HNSW 按钮，或通过 `POST /api/kb/rebuild-hnsw` API 触发。

- **重建不可跳过**：ChromaDB HNSW 和 hnswlib 索引格式不兼容
- **旧索引自动清理**：重建后 ChromaDB 的 HNSW 段文件会自动废弃
- **数据不丢失**：文档文本和 metadata 全部保留，仅重新计算向量索引

基于 local-rag-builder 技能构建的独立 RAG 智能体，支持 LM Studio / Ollama 双后端。

---

## 快速开始

```bash
# 1. 安装依赖
pip install -r requirements.txt

# 2. 启动（需要 LM Studio 或 Ollama 运行中）
python main.py

# 3. 打开浏览器访问 http://localhost:8765

# 同时启动外部 API（可选）
python main.py --api-port 8767
```

---

## 核心特性

| 特性 | 说明 |
|------|------|
| **组合式查询** | LLM 自动做 entities/attrs 分词，穷举组合后独立检索，SM3 去重合并，LLM 综合回答 |
| **多库路由** | 硬编码关键词 + 嵌入模型×KB签名语义回退两级路由 |
| **三层推理流水线** | 检索 → Reranker 精排 → NLI 三向分类（entailment/neutral/contradiction） |
| **自修正决策** | LLM 格式错误时自动反馈重试（最多 5 次），重试耗尽时清上下文重来 |
| **功能运行态切换** | 路由/重排序/NLI/搜索开关无需改配置重启 |
| **联网搜索** | 5 种后端：DuckDuckGo/Tavily/Google/Bing/自定义 |

---

## 文件结构

```
rag-assistant/
├── main.py                           # 入口（CLI/Web/Batch/External API 四模式）
├── setup.bat                         # Windows 一键启动
├── requirements.txt                  # 依赖清单
├── CHANGELOG.md                      # 版本更新日志
│
├── rag_assistant/                    # 智能体核心
│   ├── agent.py                      # LLM 决策循环
│   ├── web_ui.py                     # Web 界面（port 8765）
│   ├── external_api.py               # 外部接入 API（port 8767）← 新增
│   ├── llm_client.py                 # LLM 统一客户端（LM Studio / Ollama）
│   ├── rag_wrapper.py                # 技能封装层
│   ├── search.py                     # 联网搜索（5 种后端）
│   ├── memory.py                     # 三层记忆系统
│   └── _fix_rag.py                   # 破损数据修复工具
│
├── engine/                           # 技能引擎（独立副本）
│   ├── rag_core.py                   # 检索/路由/rerank/NLI 编排
│   ├── router.py                     # 两级路由 + KB 签名生成
│   ├── reranker.py                   # 重排序（model/rule/hybrid）
│   ├── nli_classifier.py             # NLI 三向分类器
│   ├── knowledge_base_manager.py     # KB CRUD + 备份/恢复/移动
│   ├── text_splitter.py              # 5 种切分策略 + 5 种守卫
│   ├── prompt_manager.py             # 提示词管理（模板/插槽/预设）
│   └── ...
│
├── vendor/                           # 内嵌第三方库（bs4/pypdf/markdownify）
└── data/                             # 运行时数据
    ├── config/rag_config.json        # 全量配置
    ├── kb/                           # ChromaDB 知识库
    ├── models/                       # 嵌入/reranker/NLI 模型
    ├── sessions/                     # 会话历史
    ├── memory/                       # 压缩摘要/知识缺口/习惯
    └── prompts/                      # 自定义模板/预设
```

---

## 启动模式

```bash
python main.py                              # Web UI（port 8765）
python main.py --api-port 8767              # Web UI + 外部 API
python main.py --no-web --api-port 8767     # 仅外部 API
python main.py --no-web                     # CLI 交互模式
python main.py --batch --input q.json --output r.json   # 批量处理
cat queries.jsonl | python main.py --jsonl              # 管道模式
python main.py migrate                      # 从 local-rag-builder 迁移
```

---

## 架构概览

```
用户输入
  → [LLM 决策层]
       ├─ 闲聊 → 直接回答
       └─ 知识库查询 → entities/attrs 分词
           → [组合展开器] 穷举 entities × attrs
           → [多切片检索] 每片独立走完整 RAG 流程
              1. 路由（嵌入模型 × KB签名/关键词）
              2. 检索（Chroma 相似度）
              3. (可选) 重排序（reranker）
              4. (可选) NLI 三向分类（entailment/neutral/contradiction）
           → [SM3 去重合并]（保留 NLI 标签）
           → [LLM 综合回答]（带 NLI 标签辅助判断）
```

---

## 文档导航

| 文档 | 用途 |
|------|------|
| `PROTOCOL.md` | Web UI API 契约（port 8765）— 聊天/配置/文件交互 |
| `EXTERNAL_API.md` | 外部接入 API 契约（port 8767）— 功能开关/模型调用/KB管理/提示词/切分 |
| `rag_assistant/engine/rag-assistant-architecture.md` | 内部架构设计文档 |
| `CHANGELOG.md` | 完整版本更新日志 |
| `llms.txt` | AI 可读项目描述（llmstxt.org 规范） |

---

## 三端口架构

| 端口 | 模块 | 定位 | 文档 |
|------|------|------|------|
| 8765 | `web_ui.py` | 人机交互（聊天+配置面板） | `PROTOCOL.md` |
| 8766 | `rag_web_ui.py`（subprocess） | KB/模型配置 GUI | 架构文档 |
| 8767 | `external_api.py` | 系统间集成（组件级调用） | `EXTERNAL_API.md` |

---

## 技术栈

- **LLM 后端**：LM Studio（OpenAI 兼容） / Ollama
- **向量存储**：ChromaDB（langchain-chroma）
- **嵌入模型**：BCE-embedding-base_v1（本地加载）
- **Reranker**：BAAI/bge-reranker-base（本地加载）
- **NLI 分类**：MoritzLaurer/mDeBERTa-v3-base-mnli-xnli（本地加载）
- **文本切分**：5 种策略 + GuardStack 守卫栈
- **哈希去重**：SM3 国密哈希

## 依赖

- LM Studio 或 Ollama（本地 LLM 推理服务）
- Python 3.9+
- 嵌入模型（推荐 maidalun1020/bce-embedding-base_v1）
- ChromaDB（向量存储，自动安装）

## 协议

Apache 2.0


---

## 更新说明

## [2.0.0b1] - 2026-07-22
### 重大变更 — 1.x → 2.x 迁移警告
**HNSW 管理重构：ChromaDB 内置 HNSW → hnswlib 独立索引**
- ChromaDB Rust 后端的 HNSW compactor 在 Windows 上存在持久化 bug，导致索引反复损坏
- 2.x 将向量搜索改为 **hnswlib 独立管理**，ChromaDB 仅用于 metadata 存储
- **从 1.x 升级到 2.x 必须重建 HNSW 索引**（启动时自动懒重建，或手动点击 🔨 HNSW）
- hnswlib 索引文件存储位置：`data/_hnsw/{sm3_hash}/`（ASCII 路径，避免中文路径 bug）

### 新增
- **懒重建机制**：`retrieve_documents()` 检测到 hnswlib 为空但 ChromaDB SQLite 有数据时，自动触发 `rebuild_kb_hnsw()` 重建索引，用户不感知
- **`estimate_rebuild_time.py`**：启动时加载嵌入模型 + 采样 10 条真实文档 chunk 测速，精确预估全库重建耗时。显示模型名称、每文档耗时 ms、预计分钟数
- **`rebuild_all_hnsw.py`**：批量重建全部 KB 的 HNSW 索引，跳过已有有效索引的 KB 和空 KB，供 `setup.bat` 调用
- **`setup.bat` Y/N/K 三选项**：Y 全量重建、N 跳过（后续懒重建或手动）、K 写入 `data/.no_hnsw_prompt` 永久跳过，再次部署 2.x 不再提示
- **`kb_index.json` 启动对齐**：自动删除目录已不存在的残留条目
- **懒重建控制台醒目标记**：重建开始/结束用 `===` 包围 + `⏳`/`✅` 标记，区分于普通输出
- **导入后自动删除源文件**：`data/imports/` 下已入库文件自动 `os.unlink()`

### 修复
- **HNSW 重建 ID 映射错误（关键修复）**：`rebuild_kb_hnsw()` 原来用 SQLite `embedding_metadata.id` 行号作为 ChromaDB ID 存入 hnswlib 的 `_id_map`，但 ChromaDB 的文档 ID 是 SM3 哈希值（64 位十六进制串）。搜索时 hnswlib 返回 SQLite 行号，`chroma_coll.get(ids=[...])` 全部空命中。修复为 `JOIN embeddings` 表读取真实 `embedding_id`，重建后搜索正常返回结果
- **`main.py` KB 扫描 `index` 未定义**：第 311 行 `index.get(entry, {})` 中 `index` 变量不存在导致 `NameError` → `except Exception: pass` 静默吞掉，输出"知识库: 无"。新增 `_load_index()` 导入 + `kb_index` 变量
- **启动扫描触发全量懒重建**：`main.py` 扫描每个 KB 时调用 `retrieve_documents("test")`，内部检测到 hnswlib 为空触发 `rebuild_kb_hnsw()`，19 个 KB 全部重建，启动卡死数小时。改为只创建 Chroma adapter 验证可访问性，不触发重建
- **`setup.bat` 括号内标签 + `else if` 语法**：`:ASK_HNSW` 标签位于 `if (...) { ... }` 块内 + `else if` 非标准 cmd.exe 语法，导致整个版本检测块被跳过，不弹交互、不启动浏览器。重写为纯 `goto` 流，无嵌套块
- **`setup.bat` 杀进程静默失败**：`Get-CimInstance` + `Get-NetTCPConnection` PowerShell 命令用 `>nul 2>&1` 隐藏所有错误，权限不足时旧进程不杀、新进程起不来。改为 `server.pid` PID 文件精确杀 + 端口兜底
- **`setup.bat` `[!]` 被延迟展开吃掉**：`setlocal enabledelayedexpansion` 下 `!` 触发变量展开，`[!]` 输出为 `[]`。改用 `***` 替代
- **`__pycache__` 缓存旧 `_hnsw_storage_dir`**：`chroma_adapter.py` 代码已改但运行的 Python 进程加载旧 `.pyc`，`_hnsw_storage_dir` 仍返回 `data/kb/_hnsw/`，导致懒重建写到旧位置、Chroma adapter 从新位置读不到 → 反复触发懒重建。清除后解决
- **`estimate_rebuild_time.py` 测速不准确**：用 `"测试文本" * 10` 测速（极短文本，12ms/条），实际文档 chunk 长 100-500 字（100ms+/条），预估偏差 8 倍。改为从 SQLite 随机取真实 chunk 测速
- **`rebuild_kb_hnsw` 中 `encode()` 进度条被 `2>&1` 隐藏**：SentenceTransformer 默认 `show_progress_bar=True` 但 tqdm 在非 TTY 输出下自动隐藏。加显式 `show_progress_bar=True` 强制显示
- **`kb_index.json` 残留已删除 KB 条目**：手动删 KB 目录后索引未更新显示旧 KB。启动时自动遍历索引检查目录是否存在，不存在则移除
- **`default` 空 KB 每次启动报 `HNSW 损坏`**：扫描器跳过空 KB，不调用 `retrieve_documents`，无 warning 噪音
- **导入后源文件未删除**：`agent.py` 第 895-901 行已有删除逻辑，但因之前 `UnboundLocalError` 导致导入函数抛异常退出，`success=True` 路径未走到。修复后导入成功自动 `os.unlink(pp)`

### 变更
- **彻底移除 langchain 依赖**：`langchain`, `langchain-community`, `langchain-huggingface`, `langchain-chroma`, `langchain-text-splitters`, `openai` 全部移除
- **5 种切分策略手写替代**：fixed/recursive/headers/sentence/semantic，含 5 种守卫栈
- **ChromaDB 降级为 metadata-only**：列式向量搜索走 hnswlib，ChromaDB 只存文本+键值对
- **`count()` 改为 SQLite 实时查询**：不再依赖 hnswlib 或 ChromaDB API
