# Horus Source Intelligence
[](https://pypi.org/project/horus-source/)
[](https://pepy.tech/projects/horus-source)
[](https://pepy.tech/projects/horus-source)
[](https://github.com/Mhmdhammoud/horus-source)
[](https://github.com/Mhmdhammoud/horus-source/blob/main/LICENSE)
**为你的代码库构建的知识图谱 —— 可视化探索,或让你的 AI agent 进行查询。**
[Horus](https://horus.sh) 开源事件调查平台的一部分。它将任何代码库索引为结构化的知识图谱 —— 涵盖每一个依赖项、调用链、集群和执行流。你可以通过带有力导向图可视化的**交互式 Web 仪表盘**进行探索,或者通过 **MCP 工具**将其暴露出来,让 AI agent 在每次工具调用中获得完整的结构化理解。
```
$ horus-source analyze .
Walking files... 142 files found
Parsing code... 142/142
Tracing calls... 847 calls resolved
Analyzing types... 234 type relationships
Detecting communities... 8 clusters found
Detecting execution flows... 34 processes found
Finding dead code... 12 unreachable symbols
Analyzing git history... 18 coupled file pairs
Generating embeddings... 623 vectors stored
Done in 4.2s — 623 symbols, 1,847 edges, 8 clusters, 34 flows
```
然后可视化地探索你的代码库:
```
horus-source ui # Opens interactive dashboard at localhost:8420
```
**三种视图,一个命令:**
- **Explorer** —— 交互式力导向图(Sigma.js + WebGL)。点击任何节点即可查看其代码、调用者、被调用者、影响范围和所属社区。社区轮廓叠加可以让你一目了然地看到架构集群。
- **Analysis** —— 健康评分、耦合热力图、死代码报告、继承树、分支差异 —— 在一个仪表盘中全面了解代码库健康状况。
- **Cypher Console** —— 编写并运行针对图谱的 Cypher 查询,支持语法高亮、预设和历史记录。
此外:命令面板(`Cmd+K`)、键盘快捷键、流程追踪动画、图谱小地图,以及在开启 watch 模式时由 SSE 驱动的实时重载。
## 问题所在
你的 AI agent 修改了 `UserService.validate()`。它并不知道有 47 个函数依赖于该返回值类型,有 3 条执行流经过了它,而且在 80% 的情况下 `payment_handler.py` 会与其同时发生更改。
**破坏性的更改就此被发布。**
发生这种情况是因为 AI agent 处理的是平面的文本。它们通过 grep 查找调用者,遗漏了间接调用,并且对代码是如何*连接*的毫无理解。上下文窗口是有限的。LSP 不会暴露调用图。使用 grep 只能得到字符串,而不是结构。
Agent 需要的是一个**知识图谱** —— 而不是更多的文本。
## Horus Source Intelligence 如何解决它
大多数代码智能工具会给 agent 原始文件,并指望它能读取足够多的内容。Horus Source Intelligence 采取了不同的方法:**在索引时预先计算结构**,这样每次工具调用都会返回完整、可操作上下文。
一个包含 12 个阶段的流水线在你的仓库上运行一次。之后:
- `horus_source_impact("validate")` 在单次调用中返回所有 47 个受影响的符号,并按深度分组(将会中断 / 可能中断 / 需要审查),同时附带置信度分数
- `horus_source_query("auth handler")` 返回按执行流分组的混合排名结果,而不是扁平的名称匹配列表
- `horus_source_context("UserService")` 返回调用者、被调用者、类型引用、社区成员身份以及死代码状态 —— 全局视图
**三大优势:**
1. **可靠性** —— 上下文已经包含在工具响应中。不会出现可能遗漏代码的多步探索过程。
2. **Token 效率** —— 一次工具调用取代了 10 次查询的搜索链。Agent 将 token 花费在推理上,而不是导航上。
3. **模型普惠化** —— 即便是较小的模型也能获得完整的架构清晰度,因为繁重的工作由工具完成了。
**零云依赖。** 所有操作均在本地运行 —— 解析、图谱存储、embeddings、搜索。无需 API 密钥,数据也不会离开你的计算机。
## TL;DR
```
pip install horus-source # 1. Install
cd your-project && horus-source analyze . # 2. Index (one command, ~5s for most repos)
horus-source ui # 3. Explore visually at localhost:8420
```
**对于 AI agent** —— 在你的项目根目录下添加到 `.mcp.json`:
```
{
"mcpServers": {
"horus-source": {
"command": "horus-source",
"args": ["serve", "--watch"]
}
}
}
```
**对于开发者** —— 自己探索图谱:
```
horus-source ui # Interactive dashboard (standalone or attaches to running host)
horus-source ui --watch # Live reload on file changes
horus-source host --watch # Shared host: UI + multi-session MCP
```
## 你将获得什么
### 可视化探索你的代码库
**Web UI**
完整的交互式仪表盘 —— 无需终端或扩展。只需一个命令:
```
horus-source ui # Launch at localhost:8420
horus-source ui --watch # Live reload on file changes
horus-source ui --port 9000 # Custom port
horus-source ui --dev # Dev mode (Vite HMR on :5173)
```
| 视图 | 展示内容 |
|------|--------------|
| **Explorer** | 交互式力导向图(Sigma.js + WebGL)、文件树侧边栏、带有代码预览的符号详情面板、调用者/被调用者、影响分析和进程成员资格。社区轮廓叠加可揭示架构集群。 |
| **Analysis** | 健康评分、耦合热力图、死代码报告、继承树可视化、分支差异和汇总统计 —— 一目了然地掌握代码库健康状况。 |
| **Cypher Console** | 带有语法高亮、预设查询库、结果表和查询历史的查询编辑器。 |
**附加功能:** 命令面板(`Cmd+K`)、键盘快捷键、图谱小地图、流程追踪和影响涟漪动画,以及在启用 watch 模式时由 SSE 驱动的实时重载。
该 UI 由一个带有完整 REST API 的 FastAPI 服务器提供支持 —— 请参阅下方的 [API Endpoints](#api-endpoints)。
### 按名称、概念或拼写错误查找任何内容
**混合搜索(BM25 + 向量 + 模糊匹配)**
三种搜索策略通过 [倒数排名融合](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf) 结合在一起:
- **BM25 全文搜索** —— 通过 KuzuDB FTS 进行快速的精确名称和关键字匹配
- **语义向量搜索** —— 通过 384 维 embeddings(BAAI/bge-small-en-v1.5)进行概念查询
- **模糊名称搜索** —— 针对拼写错误和部分匹配的 Levenshtein 回退机制
结果会经过测试文件降权(0.5x)和源文件函数/类加权(1.2x)处理,然后**按执行流分组**,以便 agent 在单次调用中就能看到架构上下文。
### 在修改之前了解会受影响的内容
**带有深度分组的影响分析**
当你准备修改一个符号时,Horus Source Intelligence 会在调用图、类型引用和 git 耦合历史中进行向上游追踪。为了提高可操作性,结果按深度进行分组:
- **深度 1** —— 直接调用者(将会中断)
- **深度 2** —— 间接调用者(可能中断)
- **深度 3+** —— 传递性调用者(需要审查)
每条边都带有置信度分数(1.0 = 精确匹配,0.8 = 接收者方法,0.5 = 模糊匹配),以便你优先审查重点。
### 找出可以删除的内容
**死代码检测**
不仅仅是检查“零调用者” —— 而是一项理解你所使用框架的多遍分析:
1. **初始扫描** —— 标记没有传入调用的符号
2. **豁免机制** —— 入口点、导出、构造函数、测试代码、dunder 方法、`__init__.py` 符号、被装饰的函数、`@property` 方法
3. **覆盖处理** —— 取消标记那些覆盖了非死基类方法的方法
4. **协议遵循** —— 取消标记符合 Protocol 的类上的方法
5. **协议存根** —— 取消标记 Protocol 类(接口契约)上的所有方法
### 理解代码是如何运行的,而不仅仅是它所在的位置
**执行流追踪**
使用框架感知模式检测入口点:
- **Python**: `@app.route`、`@router.get`、`@click.command`、`test_*` 函数、`__main__` 块
- **JavaScript/TypeScript**: Express 处理程序、导出的函数、`handler`/`middleware` 模式
然后通过调用图从每个入口点追踪 BFS 执行流,将流分类为社区内部流或跨社区流。
### 无需阅读文档即可查看你的架构
**社区检测**
使用 [Leiden 算法](https://www.nature.com/articles/s41598-019-41695-z)(igraph + leidenalg)自动发现功能集群。每个社区都会获得一个内聚得分和自动生成的标签。Agent 可以询问“这个符号属于哪个集群?”,并在不阅读任何设计文档的情况下获得答案。
### 发现 git 记录的隐藏依赖
**变更耦合(Git 历史)**
分析 6 个月的 git 历史记录,以查找静态分析遗漏的依赖关系:
```
coupling(A, B) = co_changes(A, B) / max(changes(A), changes(B))
```
耦合强度 >= 0.3 且有 3 次以上共同变更的文件会被建立关联。这些关联会显示在影响分析中 —— 因此当你修改 `user.py` 时,agent 也知道需要检查 `user_test.py` 和 `auth_middleware.py`。
### 始终保持最新
**Watch 模式**
由基于 Rust 的文件监视器(watchfiles)提供支持的实时重新索引:
```
$ horus-source watch
Watching /Users/you/project for changes...
[10:32:15] src/auth/validate.py modified -> re-indexed (0.3s)
[10:33:02] 2 files modified -> re-indexed (0.5s)
```
文件局部阶段(解析、导入、调用、类型)在发生更改时立即运行。全局阶段(社区、进程、死代码)每 30 秒批量运行一次。
### 结构化差异,而非文本差异
**分支比较**
使用 git worktree 在符号级别比较分支(无需 stashing):
```
$ horus-source diff main..feature
Symbols added (4):
+ process_payment (Function) -- src/payments/stripe.py
+ PaymentIntent (Class) -- src/payments/models.py
Symbols modified (2):
~ checkout_handler (Function) -- src/routes/checkout.py
Symbols removed (1):
- old_charge (Function) -- src/payments/legacy.py
```
### 干净的调用图
**噪声过滤**
内置的黑名单(138 个条目)会自动从调用图中过滤掉语言内置函数(`print`、`len`、`isinstance`)、JS/TS 全局对象(`console`、`setTimeout`、`fetch`)、React hooks(`useState`、`useEffect`)以及常见的标准库方法。你的图谱展示的是*你*代码的关系,而不是来自 `list.append()` 的噪声。
## 流水线
Horus Source Intelligence 通过 12 个顺序分析阶段建立深度的结构化理解:
| 阶段 | 作用 |
|-------|-------------|
| **File Walking** | 遍历仓库并遵守 `.gitignore`,按支持的语言进行过滤 |
| **Structure** | 创建带有 CONTAINS 关系的文件/文件夹层次结构 |
| **Parsing** | 提取 tree-sitter AST —— 函数、类、方法、接口、枚举、类型别名 |
| **Import Resolution** | 将 import 语句解析为实际文件(相对路径、绝对路径、裸指定符) |
| **Call Tracing** | 映射带有置信度分数的函数调用。噪声过滤会跳过 138 个语言内置函数 |
| **Heritage** | 追踪类继承(EXTENDS)和接口实现(IMPLEMENTS) |
| **Type Analysis** | 从参数、返回类型和变量注解中提取类型引用 |
| **Community Detection** | Leiden 算法将相关符号聚类为功能社区 |
| **Process Detection** | 框架感知的入口点检测 + BFS 流程追踪 |
| **Dead Code Detection** | 具备覆盖、协议和装饰器感知能力的多遍分析 |
| **Change Coupling** | Git 历史分析 —— 查找总是同时发生更改的文件 |
| **Embeddings** | 为每个符号生成 384 维向量,启用语义搜索。可通过 `--no-embeddings` 跳过 |
## MCP 集成
Horus Source Intelligence 将其全部智能作为 MCP 服务器公开。只需设置一次,你的 AI agent 就能永久获得对你代码库的结构化理解。
### 设置
**Claude Code** —— 添加到项目根目录下的 `.mcp.json` 中(或运行 `claude mcp add horus-source -- horus-source serve --watch`):
```
{
"mcpServers": {
"horus-source": {
"command": "horus-source",
"args": ["serve", "--watch"]
}
}
}
```
**Cursor** —— 添加到你的 MCP 设置中:
```
{
"horus-source": {
"command": "horus-source",
"args": ["serve", "--watch"]
}
}
```
可选的共享主机模式:
```
horus-source host --watch
```
这将为 UI 和多个 MCP 客户端启动一个共享主机。`--watch` 标志可启用实时重新索引 —— 图谱会随着你编辑代码而更新。
### 工具
| 工具 | Agent 获得的信息 |
|------|-------------|
| `horus_source_query` | 混合搜索(BM25 + 向量 + 模糊),结果按执行流分组 |
| `horus_source_context` | 360 度视图 —— 调用者、被调用者、类型引用、置信度标签、死代码状态 |
| `horus_source_impact` | 按深度分组的爆炸半径 —— 直接调用(将会中断)、间接调用(可能中断)、传递调用 |
| `horus_source_dead_code` | 所有无法访问的符号,按文件分组 |
| `horus_source_detect_changes` | 将 `git diff` 映射到受影响的符号和执行流 |
| `horus_source_list_repos` | 所有已索引的仓库及其统计信息 |
| `horus_source_cypher` | 针对知识图谱的只读 Cypher 查询 |
每个工具响应都包含一个**下一步提示**,引导 agent 走完自然的调查工作流:
```
horus_source_query -> "Next: Use horus_source_context() on a specific symbol for the full picture."
horus_source_context -> "Next: Use horus_source_impact() if planning changes to this symbol."
horus_source_impact -> "Tip: Review each affected symbol before making changes."
```
### 资源
| URI | 描述 |
|-----|-------------|
|horus://overview` | 按类型统计的节点和关系数量 |
| `horus://dead-code` | 完整的死代码报告 |
| `horus://schema` | 用于 Cypher 查询的图谱 schema 参考 |
## API 端点
Web UI 由 FastAPI 服务器提供支持。所有端点均位于 `/api` 下:
| 端点 | 描述 |
|----------|-------------|
| `GET /api/graph` | 完整的知识图谱(分页显示) |
| `GET /api/node/{id}` | 包含调用者、被调用者、类型引用的节点详情 |
| `GET /api/overview` | 汇总的节点/边数量 |
| `GET /api/search` | 混合搜索(BM25 + 向量 + 模糊) |
| `GET /api/impact/{id}` | 按深度进行的爆炸半径分析 |
| `GET /api/dead-code` | 死代码报告 |
| `GET /api/communities` | 带有成员的社区列表 |
| `GET /api/coupling` | 变更耦合热力图数据 |
| `GET /api/files/{path}` | 带有语法上下文的源文件内容 |
| `POST /api/cypher` | 执行只读的 Cypher 查询 |
| `GET /api/diff` | 结构化的分支比较 |
| `GET /api/processes` | 执行流列表 |
| `GET /api/events` | 用于实时重载事件的 SSE 流 |
| `POST /api/reindex` | 触发完整的重新索引(仅在 watch 模式下可用) |
Cypher 查询会在服务器端进行验证 —— 在剥离注释后,写入关键字(`CREATE`、`DELETE`、`DROP` 等)将被拒绝。
## 功能对比
| 功能 | grep / ripgrep | LSP | 填充上下文窗口 | Horus Source |
|-----------|---------------|-----|------------------------|------|
| **交互式图形界面** | **否** | **否** | **否** | **是(完整的 Web 仪表盘)** |
| 文本搜索 | 是 | 否 | 是 | 是(混合 BM25 + 向量) |
| 查找所有调用者 | 否 | 部分 | 碰运气 | 是(带有置信度的完整调用图) |
| 类型关系 | 否 | 是 | 否 | 是(参数/返回值/变量角色) |
| 死代码检测 | 否 | 否 | 否 | 是(多遍扫描,框架感知) |
| 执行流追踪 | 否 | 否 | 否 | 是(入口点 -> 流程) |
| 社区检测 | 否 | 否 | 否 | 是(Leiden 算法) |
| 变更耦合 | 否 | 否 | 否 | 是(6 个月的共同变更分析) |
| 影响分析 | 否 | 否 | 否 | 是(按深度分组并附带置信度) |
| AI agent 集成 | 否 | 部分 | 不适用 | 是(完整的 MCP 服务器) |
| 结构化分支差异 | 否 | 否 | 否 | 是(节点/边级别) |
| Watch 模式 | 否 | 是 | 否 | 是(基于 Rust,500ms 防抖) |
| 离线工作 | 是 | 是 | 否 | 是 |
## 支持的语言
| 语言 | 扩展名 | 解析器 |
|----------|-----------|--------|
| Python | `.py` | tree-sitter-python |
| TypeScript | `.ts`, `.tsx` | tree-sitter-typescript |
| JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` | tree-sitter-javascript |
## 安装
```
# 使用 pip
pip install horus-source
# 使用 uv(推荐)
uv add horus-source
```
要求 **Python 3.11+**。已内置 Web UI(前端 + 后端) —— 无需 Node.js 或进行额外安装。
### 从源码安装
```
git clone https://github.com/Mhmdhammoud/horus-source.git
cd horus-source
uv sync --all-extras
uv run horus-source --help
```
## 命令行参考
```
horus-source analyze [PATH] Index a repository (default: current directory)
--full Force full rebuild (skip incremental)
--no-embeddings Skip vector embedding generation (faster indexing)
horus-source status Show index status for current repo
horus-source list List all indexed repositories
horus-source clean Delete index for current repo
--force / -f Skip confirmation prompt
horus-source query QUERY Hybrid search the knowledge graph
--limit / -n N Max results (default: 20)
horus-source context SYMBOL 360-degree view of a symbol
horus-source impact SYMBOL Blast radius analysis
--depth / -d N BFS traversal depth (default: 3)
horus-source dead-code List all detected dead code
horus-source cypher QUERY Execute a raw Cypher query (read-only)
horus-source watch Watch mode — live re-indexing on file changes
horus-source diff BASE..HEAD Structural branch comparison
horus-source host Shared host for UI + HTTP MCP (default: localhost:8420)
--port / -p PORT Port to serve on (default: 8420)
--watch / --no-watch Enable live file watching
--dev Dev mode — proxy to Vite dev server for HMR
--no-open Don't auto-open browser
horus-source ui Launch the web UI (default: localhost:8420)
--port / -p PORT Port to serve on (default: 8420)
--watch / -w Enable live file watching with auto-reindex
--dev Dev mode — proxy to Vite dev server for HMR
--no-open Don't auto-open browser
--direct Force standalone mode even if a shared host exists
horus-source setup Print MCP configuration JSON
--claude For Claude Code
--cursor For Cursor
horus-source mcp Start the MCP server (stdio transport)
horus-source serve Start the MCP server
--watch, -w Enable live file watching with auto-reindex
horus-source --version Print version
```
## 示例工作流
### “我需要重构 User 类 —— 会影响什么?”
```
# 查看与 User 相关联的所有内容
horus-source context User
# 检查 blast radius — 按深度分组
horus-source impact User --depth 3
# 查找始终随 user.py 变化的文件
horus-source cypher "MATCH (a:File)-[r:CodeRelation]->(b:File) WHERE a.name = 'user.py' AND r.rel_type = 'coupled_with' RETURN b.name, r.strength ORDER BY r.strength DESC"
```
### “有我们应该清理的死代码吗?”
```
horus-source dead-code
```
### “主要的执行流是什么?”
```
horus-source cypher "MATCH (p:Process) RETURN p.name, p.properties ORDER BY p.name"
```
### “代码库中哪些部分耦合最紧密?”
```
horus-source cypher "MATCH (a:File)-[r:CodeRelation]->(b:File) WHERE r.rel_type = 'coupled_with' RETURN a.name, b.name, r.strength ORDER BY r.strength DESC LIMIT 20"
```
## 知识图谱模型
### 节点
| 标签 | 描述 |
|-------|-------------|
| `File` | 源文件 |
| `Folder` | 目录 |
| `Function` | 顶级函数 |
| `Class` | 类定义 |
| `Method` | 类中的方法 |
| `Interface` | 接口 / Protocol 定义 |
| `TypeAlias` | 类型别名 |
| `Enum` | 枚举 |
| `Community` | 自动检测到的功能集群 |
| `Process` | 检测到的执行流 |
### 关系
| 类型 | 描述 | 关键属性 |
|------|-------------|----------------|
| `CONTAINS` | 文件夹 -> 文件/符号层次结构 | -- |
| `DEFINES` | 文件 -> 其定义的符号 | -- |
| `CALLS` | 符号 -> 其调用的符号 | `confidence` (0.0-1.0) |
| `IMPORTS` | 文件 -> 其导入的源文件 | `symbols` (名称列表) |
| `EXTENDS` | 类 -> 其扩展的类 | -- |
| `IMPLEMENTS` | 类 -> 其实现的接口 | -- |
| `USES_TYPE` | 符号 -> 其引用的类型 | `role` (参数/返回值/变量) |
| `EXPORTS` | 文件 -> 其导出的符号 | -- |
| `MEMBER_OF` | 符号 -> 其所属的社区 | -- |
| `STEP_IN_PROCESS` | 符号 -> 其参与的进程 | `step_number` |
| `COUPLED_WITH` | 文件 -> 与其共同变更的文件 | `strength`, `co_changes` |
### 节点 ID 格式
```
{label}:{relative_path}:{symbol_name}
Examples:
function:src/auth/validate.py:validate_user
class:src/models/user.py:User
method:src/models/user.py:User.save
```
## 架构
```
Source Code (.py, .ts, .js, .tsx, .jsx)
|
v
+----------------------------------------------+
| Ingestion Pipeline (12 phases) |
| |
| walk -> structure -> parse -> imports |
| -> calls -> heritage -> types |
| -> communities -> processes -> dead_code |
| -> coupling -> embeddings |
+----------------------+-----------------------+
|
v
+-----------------+
| KnowledgeGraph | (in-memory during build)
+--------+--------+
|
+------------+------------+
v v v
+---------+ +---------+ +---------+
| KuzuDB | | FTS | | Vector |
| (graph) | | (BM25) | | (HNSW) |
+----+----+ +----+----+ +----+----+
+------------+------------+
|
StorageBackend Protocol
|
+-----------+-----------+
v v v
+----------+ +----------+ +----------+
| MCP | | Web UI | | CLI |
| Server | | (FastAPI | | (Typer) |
| (stdio) | | + React)| | |
+----+-----+ +----+-----+ +----+-----+
| | |
Claude Code Browser Terminal
/ Cursor (developer) (developer)
```
### 技术栈
| 层级 | 技术 | 用途 |
|-------|-----------|---------|
| 解析 | tree-sitter | 语言无关的 AST 提取 |
| 图存储 | KuzuDB | 内嵌式图数据库,支持 Cypher、FTS 和向量 |
| 图算法 | igraph + leidenalg | Leiden 社区检测 |
| Embeddings | fastembed | 基于 ONNX 的 384 维向量(约 100MB,无需 PyTorch) |
| MCP 协议 | mcp SDK (FastMCP) | 通过 stdio 与 AI agent 通信 |
| Web 后端 | FastAPI + Uvicorn | 为 Web UI 提供 REST API,以及用于实时更新的 SSE |
| Web 前端 | React + TypeScript + Vite | 使用 Tailwind CSS 的交互式仪表盘 |
| 图可视化 | Sigma.js + Graphology | 使用 ForceAtlas2 布局的 WebGL 图渲染 |
| 命令行 | Typer + Rich | 带有进度条的终端界面 |
| 文件监视 | watchfiles | 基于 Rust 的文件系统监视器 |
| Gitignore | pathspec | 完整的 `.gitignore` 模式匹配 |
### 存储
所有内容均保存在本地:
```
your-project/
+-- .horus/
+-- source/
+-- kuzu/ # KuzuDB graph database (graph + FTS + vectors)
+-- meta.json # Index metadata and stats
+-- host.json # Running host metadata (written while host is alive)
```
将 `.horus/` 添加到你的 `.gitignore` 中。
在执行 `horus-source analyze` 时,会自动填充位于 `~/.horus/source/repos/` 的全局注册表,这使得 `horus-source list` 能够发现你计算机上所有已索引的仓库。
存储层被抽象在 `StorageBackend` Protocol 背后 —— KuzuDB 是默认选项。
## 开发
```
git clone https://github.com/Mhmdhammoud/horus-source.git
cd horus-source
uv sync --all-extras
# 运行测试
uv run pytest
# Lint
uv run ruff check src/
# 从源码运行
uv run horus-source --help
# 前端开发 (React + Vite with HMR)
uv run horus-source ui --dev # Backend on :8420, proxies to Vite dev server
```
## License
MIT
属于 [Horus](https://horus.sh) —— 开源事件调查平台。