多源热点采集与分析平台:用插件化渠道把新闻/自定义消息写入 SeekDB,再通过 FastAPI 做语义 / 全文 / 混合检索,并用 OpenAI 兼容 LLM 计算行业活力指数。前端是 Vite + React 控制台。
仓库:https://github.com/wayyoungboy/InfoMerge
- 渠道采集:内置 Tavily 新闻搜索、HTTP Webhook;可用 cron 定时拉取
- 检索:SeekDB 向量语义检索、关键词全文、RRF 混合检索
- 行业活力指数:按行业关键词取消息,经 LLM 打情感/话题分,再合成活跃度 / 情感 / 多样性 / 趋势
- Web 控制台:搜索、活力指数、渠道管理(默认
http://localhost:5173)
- Python 3.11+(
pyseekdb要求;pyproject.toml虽写>=3.10,3.10 装不上 SeekDB SDK) - Linux x86_64 或 macOS arm64(
pylibseekdb有对应 wheel) - 前端(可选):Node.js 18+
- 可选密钥:Tavily API Key、OpenAI 兼容 LLM(
LLM_API_BASE+LLM_API_KEY)
首次向 SeekDB 写入/检索时会下载内置 embedding 模型(约 86MB),需要能访问外网。
git clone https://github.com/wayyoungboy/InfoMerge.git
cd InfoMerge
python3.12 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -U pip
pip install -e ".[dev]"cp .env.example .env.env 字段(src/config.py 用 pydantic-settings 读取):
| 变量 | 默认 | 作用 |
|---|---|---|
SEEKDB_DB_PATH |
./data/seekdb.db |
嵌入式 SeekDB 文件路径(data/ 已 gitignore) |
LLM_API_BASE |
空 | OpenAI 兼容接口根路径,例如 https://api.openai.com/v1 |
LLM_API_KEY |
空 | LLM 密钥;未配置时活力分析 / 行业发现会返回 400 |
LLM_MODEL |
gpt-4o-mini |
模型名 |
TAVILY_API_KEY |
空 | 会被 Settings 读取,但 Tavily 采集实际用的是渠道注册时的 settings.api_key |
活力结果另存在 ./data/vitality.db(SQLite,路径在 src/main.py 写死)。
在仓库根目录:
uvicorn src.main:app --reload --host 0.0.0.0 --port 8000- 健康检查:
GET http://localhost:8000/api/health→{"status":"ok"} - OpenAPI:http://localhost:8000/docs
启动时会初始化 SeekDB 库 infomerge、自动发现 src/channels/plugins/ 下的插件,并启动 APScheduler。
cd web
npm install
npm run dev浏览器打开 http://localhost:5173 。Vite 会把 /api 代理到 http://localhost:8000(见 web/vite.config.ts)。后端 CORS 目前只允许 http://localhost:5173。
渠道配置存在进程内存(src.main.config_store),重启 API 后需要重新注册。
curl -s http://localhost:8000/api/channels \
-H 'Content-Type: application/json' \
-d '{"name":"tavily","settings":{"api_key":"YOUR_TAVILY_KEY","query":"AI news","max_results":10,"topic":"news"}}'cron 可选:注册渠道时带 cron 字段即可定时采集。
立即采集:
curl -s -X POST http://localhost:8000/api/channels/tavily/fetch成功响应类似 {"success":true,"channel":"tavily","fetched":N,"saved":N}。
Tavily 配置 schema:GET /api/channels/tavily/schema(必填 api_key;query 默认 tech news;max_results 1-20;topic 为 news 或 general)。
curl -s http://localhost:8000/api/channels/webhook/receive \
-H 'Content-Type: application/json' \
-d '{"title":"example title","content":"example body","author":"alice","url":"https://example.com"}'# semantic
curl -s http://localhost:8000/api/search/semantic \
-H 'Content-Type: application/json' \
-d '{"query":"AI medicine","top_k":10}'
# fulltext
curl -s http://localhost:8000/api/search/fulltext \
-H 'Content-Type: application/json' \
-d '{"query":"Python","top_k":10}'
# hybrid (vector + keyword RRF)
curl -s http://localhost:8000/api/search/hybrid \
-H 'Content-Type: application/json' \
-d '{"query":"AI progress","keywords":"AI","top_k":10}'消息条数:GET /api/search/messages/count。也可按 channel 过滤。
先保证 .env 里 LLM_API_BASE 与 LLM_API_KEY 非空,并已有相关消息入库。
curl -s http://localhost:8000/api/vitality/analyze \
-H 'Content-Type: application/json' \
-d '{"industry":"artificial intelligence","period_days":7,"max_messages":100}'合成权重(src/analysis/engine.py):活跃度 0.30 + 情感 0.25 + 多样性 0.20 + 趋势 0.25。
列表 / 历史:GET /api/vitality/list、GET /api/vitality/history/{industry}。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/health |
健康检查 |
| GET | /api/channels |
已发现插件 + 内存中的注册状态 |
| GET | /api/channels/{name}/schema |
渠道 JSON Schema |
| POST | /api/channels |
注册渠道(name / settings / 可选 cron) |
| POST | /api/channels/{name}/fetch |
立即采集 |
| POST | /api/channels/webhook/receive |
接收外部消息 |
| POST | /api/search/semantic |
向量检索 |
| POST | /api/search/fulltext |
全文检索 |
| POST | /api/search/hybrid |
混合检索 |
| GET | /api/search/messages/count |
消息数量 |
| GET | /api/search/messages/{doc_id} |
按 channel:source_id 取单条 |
| GET | /api/vitality/list |
已分析行业 |
| GET | /api/vitality/history/{industry} |
历史分数 |
| POST | /api/vitality/analyze |
触发分析 |
| POST | /api/vitality/discover |
LLM 行业发现 |
| GET | /api/vitality/papers/{industry} |
相关论文(当前固定返回空列表) |
source .venv/bin/activate
pytesttests/test_analysis、tests/test_channels:纯单元测试(SQLite / mock)tests/test_e2e.py、tests/test_vitality_api.py:FastAPI TestClient,SeekDB 被 mocktests/test_search.py:真实嵌入式 SeekDB(会下载 embedding 模型)
CI(.github/workflows/ci.yml)在 Python 3.12 上安装依赖后跑上述套件。
src/main.py FastAPI 入口、CORS、路由挂载
src/config.py .env to Settings
src/database.py pyseekdb 嵌入式客户端(库名 infomerge,集合 messages)
src/services.py 采集编排 + APScheduler
src/api/ channels / search / vitality
src/channels/plugins/ tavily、webhook(启动时 auto_discover)
src/analysis/ 活力计算、LLM、SQLite 存储
web/ Vite + React 控制台
tests/ pytest
自写渠道:实现 src.channels.base.ChannelPlugin(fetch + get_config_schema),放到 src/channels/plugins/<name>/ 并 registry.register(...)。
- 渠道
settings/ cron / 上次采集状态只在内存,进程退出即丢失 - Webhook schema 里的
webhook_secret尚未在接收接口校验 /api/vitality/papers/{industry}仍是空实现- 趋势分在分析接口里
previous_count固定为 0,首次分析趋势约为中性 50 - 后端 CORS 只放行
http://localhost:5173
MIT。见 LICENSE。