Search Agent 是一个面向混合文件库的中文检索与问答 Agent。它的目标不是做一个简单 RAG,而是把源文件归一化成可读、可索引、可追溯的镜像库,再通过类似 Codex 的多轮工具调用完成检索、读证据、精排、验证和回答。
当前项目包含两部分:
- 后端:Python CLI、归一化、SQLite 索引、检索问答、FastAPI 标准接口。
- 前端:静态 Web 控制台,只通过 HTTP API 调用后端能力,不直接耦合 Python 内部模块。
更多工程细节见 docs/architecture.md。
- 混合文件归一化:支持代码、Markdown、文本、配置、HTML、JSONL、PDF、Word、PPT、Excel、CSV/TSV、图片、视频、字幕、压缩包、Jupyter Notebook 等。
- 语义镜像库:为每个文件生成 Markdown 镜像、manifest、attributes、chunks、tags、symbols、OCR、媒体时间段等结构化数据。
- SQLite 检索索引:使用
index.sqlite保存 files、chunks、symbols、tags、citations、FTS 全文索引。 - 单聊天入口:
POST /api/chat自动分流普通对话、文件问答、记忆保存、敏感信息保存、文件发送和纯搜索。 - 多轮工具调用:问答时会进行问题分析、查询规划、查询扩展、项目地图、候选文件读取、文件镜像读取、证据评分、覆盖度判断、只读验证和最终回答。
- 本地记忆:Agent 可以主动保存记忆、知识规则、用户文件和敏感信息。
- Web 控制台:聊天、文件树、镜像编辑、动态根目录、任务中心、设置、概览、OpenAPI 文档。
- 动态根目录:可以在 Web 中切换当前源文件根目录;每个根目录会派生独立镜像工作区,避免不同资料库混在一起。
- 本地持久化配置:Web 修改模型、主题、面板宽度、快捷根目录等配置后会写入
config.toml。
cd D:\Desktop\code\search_agent
python -m pip install -r requirements.txt
python -m pip install -e ..\start-web.ps1启动后访问:
- Web 控制台:http://127.0.0.1:8787/
- OpenAPI JSON:http://127.0.0.1:8787/openapi.json
- Swagger 文档:http://127.0.0.1:8787/docs
如果需要在当前终端直接看日志:
.\start-web.ps1 -Foreground默认监听 127.0.0.1:8787。不要把未加防护的本地服务暴露到公网。
项目会使用 config.toml 保存 Web 和模型配置。这个文件包含本地路径和 API Key,默认被 .gitignore 忽略,不应该提交到仓库。
常见结构如下:
[server]
host = "127.0.0.1"
port = 8787
api_token = "local-dev-token"
[workspace]
data_root = "D:\\Desktop\\code\\search_agent\\data"
current_root = "D:\\Desktop\\资料库"
roots = ["D:\\Desktop\\资料库"]
env_file = "D:\\Desktop\\code\\search_agent\\.env"
[models.deepseek]
api_key = "..."
base_url = "..."
planner_model = "..."
answer_model = "..."
[models.vision]
api_key = "..."
base_url = "..."
model = "..."
[web_search]
enabled = false
provider = "duckduckgo"
[ui]
theme = "gradient-white"
files_panel_width = 420目录策略是单根数据目录加动态工作区:
data/files/:默认源文件根目录。data/normalized/:默认镜像库根目录。data/normalized/workspaces/<workspace_id>/:外部动态根目录对应的镜像库。data/normalized/_agent_workspace/:默认根目录下的 Agent 记忆、文件、知识、密钥、日志。
如果当前根目录不是 data/files/,后端会基于源路径自动派生一个独立的 workspace_id 和镜像目录。
agent-kb sync SOURCE NORMALIZED --llm-normalize --env-file .env常用参数:
--llm-normalize:对图片和视频等媒体启用 LLM 视觉归一化。--llm-limit N:限制本次 LLM 归一化文件数量。--video-sample-interval-seconds 5:视频抽帧间隔,默认 5 秒。--video-max-frames 60:视频最多抽帧 60 张。--video-max-duration-seconds 600:视频最多处理前 10 分钟。--workers N:并发归一化 worker 数。
agent-kb index NORMALIZEDagent-kb ask NORMALIZED "我一共有几周的周报?" --source-root SOURCE --env-file .env --jsonagent-kb chat NORMALIZED "帮我总结所有周报主要做了什么" --source-root SOURCE --env-file .env --use-llm --jsonagent-kb inspect NORMALIZED --path some/file.mdagent-kb benchmark --json所有 /api/* 接口在设置 token 后都需要:
Authorization: Bearer local-dev-token| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/health |
健康检查 |
| GET | /api/workspace |
当前根目录、镜像目录、快捷根目录、配置文件路径 |
| PUT | /api/workspace/root |
切换动态根目录 |
| GET | /api/stats |
文件数、manifest、attributes、chunks、symbols、tags、token 统计 |
| GET | /api/capabilities |
当前支持的文件类型、接口和 benchmark 覆盖范围 |
| GET | /api/config/model |
读取模型和 WebSearch 配置 |
| PUT | /api/config/model |
更新模型和 WebSearch 配置,落盘到 config.toml |
| GET | /api/config/ui |
读取 UI 配置 |
| PUT | /api/config/ui |
更新主题、文件栏宽度、进程中心位置 |
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/chat |
主聊天入口,支持文字、上下文、附件、LLM、WebSearch |
| POST | /api/ask |
直接问答接口 |
| POST | /api/search |
直接检索接口 |
| GET | /api/sessions |
查询本地会话列表 |
| POST | /api/sessions |
创建新会话 |
| GET | /api/context |
查询最近上下文,最多 8 条 |
| GET | /api/logs/traces |
查询最近聊天工具调用日志 |
POST /api/chat 是推荐接入接口。请求示例:
{
"message": "帮我总结所有周报主要做了什么",
"session_id": "default",
"use_llm": true,
"use_web_search": false,
"context": [
{"role": "user", "content": "上一次问题"},
{"role": "assistant", "content": "上一次回答"}
],
"attachments": []
}上下文是只读参考,Agent 应该遵循最后一条用户指令。Web 会先通过 /api/context 查询本地上下文,再拼进 /api/chat;其他聊天软件也可以自己构造上下文列表。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/files/tree |
文件树,合并源文件和镜像状态 |
| GET | /api/files/merged-node |
读取节点详情、源文件、manifest、attributes、镜像内容 |
| GET | /api/files/node |
读取 source 或 normalized 节点 |
| PUT | /api/files/node |
保存 normalized .md、.json、.txt |
| DELETE | /api/files/node |
删除源文件并清理镜像侧车文件 |
| POST | /api/files/resync |
单文件重新归一化 |
| POST | /api/uploads |
上传文件并归一化 |
| GET | /api/memory |
查询记忆 |
| POST | /api/memory |
保存普通记忆 |
| POST | /api/agent-files |
保存 Agent 主动整理的文件 |
| GET | /api/secrets |
高权限查询敏感信息,返回明文 |
| GET | /api/public/secrets |
低权限查询敏感信息,只返回脱敏值 |
| POST | /api/secrets |
保存敏感信息 |
| GET | /api/inspect |
查看某个文件的 manifest 和 attributes |
源文件通过 API 始终只读;Web 只允许编辑 normalized 镜像中的 .md、.json、.txt 文件。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/jobs |
提交 sync、index、benchmark 后台任务 |
| GET | /api/jobs |
查看任务列表 |
| GET | /api/jobs/{job_id} |
查看任务详情 |
| POST | /api/jobs/{job_id}/cancel |
取消未开始任务;运行中任务标记为 cancel requested |
任务中心会显示回答、归一化、索引、benchmark 等进程。写入型任务同一时间只跑一个,避免同时修改镜像和索引。
归一化后,一个源文件通常会产生:
*.md:人类可读 Markdown 镜像。*.manifest.json:文件级清单,记录 source path、normalized path、file type、status、summary、tags、attributes path、chunk ids。attributes/*.attributes.json:结构化属性,记录 OCR、objects、symbols、imports、config keys、segments、chunks、model、error 等。index.sqlite:SQLite 索引。
媒体归一化策略:
- 图片:基础镜像始终可用;启用 LLM 后生成中文视觉描述、OCR、对象、界面/安装/接线线索和 tags。
- 视频:默认每 5 秒抽帧,最多 60 帧或 10 分钟;生成时间线 segments、场景摘要、OCR 和 tags。
- LLM 不可用时不会阻断基础同步,媒体增强会标记为 pending 或 failed,后续可重试。
聊天入口的第一步是 select_entry,负责把用户消息分流到:
native_chat:普通聊天,不检索文件。file_qa:文件问答,多轮检索和证据读取。storage:保存记忆、知识、文件或密钥。send_file:根据用户要求发送文件位置。search_only:只返回检索结果。
文件问答会执行多轮工具链:
- 分析问题意图、覆盖模式和证据需求。
- 建立项目地图,查看文件、路径、symbols、tags。
- 规划多组查询词,结合 LLM、知识区规则、关键词、n-gram 和可选 WebSearch。
- 多路召回 FTS、metadata、路径、symbols、tags、候选文件。
- 读取证据 chunk、明确提到的文件、文件镜像、源文件片段。
- 给每条证据打 collector score。
- 判断覆盖度是否足够;不够则继续补充跨文件证据。
- 按运行时代码、测试、配置、官方/结构化文档、媒体、泛化说明排序。
- 可选执行只读验证命令。
- 使用 LLM 组织最终回答,并附 citations、hits、tool_calls 和 evidence_chain。
回答必须基于证据;证据不足或冲突时应该明确说明。
默认忽略以下本地数据:
.envconfig.toml.temp/data/*.sqlite*.db*.log
敏感信息不要放进普通记忆或镜像文件。save_secret 会写入:
<normalized_root>/_agent_workspace/secrets/secrets.json
高权限接口 /api/secrets 会返回明文;低权限接口 /api/public/secrets 只返回 masked value。
运行测试:
pytest -q检查前端 JavaScript 语法:
node --check src/search_agent/web/static/assets/app.js当前测试覆盖包括:
- 基础归一化和索引重建。
- chunk id 冲突时索引不崩溃。
- 文本、代码、PDF、Office、Excel、图片、视频、字幕、压缩包等文件检索。
- 多轮工具调用、上下文、记忆、密钥、上传、动态根目录、任务系统。
- Web API 的读写权限、路径逃逸保护、source 只读、normalized 可编辑。
- 第一版是单工作区服务,但动态根目录已经按可拆分方式设计,后续可以扩展为多用户或多工作区。
- Web 前端不是核心能力,只是控制台;其他系统应该接 REST API。
- 源文件不自动修改;只有用户明确触发删除或上传时才改变源文件树。
- 归一化镜像和 Agent 记忆可以写入,但都在当前 normalized workspace 内。
- 项目偏置知识不写进代码,只能放进知识区,例如
_agent_workspace/knowledge/query_expansions.json。