JashanLabs/LogsRAG
GitHub: JashanLabs/LogsRAG
LogsRAG 是一套面向事件响应场景的实时 RAG 系统,通过 Kafka 流式摄入 GitHub、Jira 及日志事件并写入 pgvector,支持值班工程师基于混合检索进行上下文感知的故障排查。
Stars: 0 | Forks: 0
# LogsRAG
一个用于事件响应(incident response)的实时 RAG pipeline。通过 Kafka 将操作事件(GitHub commits、Jira tickets、系统日志)流式传输到 pgvector 知识库,然后使用混合检索(hybrid retrieval)和 LLM 生成来回答值班(on-call)查询。
标准的 RAG pipeline 会按计划批处理文档。这意味着在正在发生的服务中断期间,导致该事件的 commits 尚未被索引。OpsStream-RAG 消除了这一差距 —— 事件在发生后的几秒钟内即被向量化并可供查询。
## 架构
六个服务,全部容器化。只需一条 `docker compose up --build -d` 命令即可运行整个技术栈。
```
GitHub / Jira Webhooks On-Call Engineer
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ API Gateway │ │ API Gateway │
│ POST /webhooks │ │ POST /ask │
│ (Pydantic) │ │ (RAG generate) │
└───────┬────────┘ └───────┬────────┘
│ │
▼ │
┌────────────────┐ │
│ Apache Kafka │ │
│ (3 partitions)│ │
└───────┬────────┘ │
│ │
┌──────┼──────┐ │
▼ ▼ ▼ │
Consumer Consumer Consumer │
(batch → embed → upsert) │
│ │ │ │
└──────┼──────┘ │
▼ │
┌────────────────┐ │
│ Embedding API │ │
│ Jina v2 local │ │
│ (768-dim) │ │
└───────┬────────┘ │
▼ │
┌────────────────┐ ┌────────┴───────┐
│ PostgreSQL 16 │◄─────────────────────┤ Retrieval API │
│ pgvector HNSW │ │ hybrid search │
│ + GIN FTS │ │ + time decay │
└────────────────┘ └────────────────┘
```
| 服务 | 容器 | 端口 | 功能描述 |
|---|---|---|---|
| API Gateway | `opsstream_rag_api` | 8897 | 接收 webhooks,生产消息到 Kafka。负责协调 RAG 答案的生成。 |
| Kafka | `opsstream_broker` | 9092 | KRaft 模式 broker。包含 3 个分区的 topic,用于并行消费。 |
| Consumer | ×3 个副本 | — | 轮询 Kafka,批量处理事件,调用 embedding API,并 upsert 到 Postgres。 |
| Embedding API | `opsstream_embedder` | 8000 | 通过 PyTorch 在本地运行 `jina-embeddings-v2-base-code`。模型已内置到 Docker 镜像中。 |
| Retrieval API | `opsstream_retrieval` | 8085 | 混合 vector + 关键词搜索,并带有时间衰减重排序(temporal decay reranking)。 |
| PostgreSQL | `opsstream_db` | 5432 | 配备用于向量的 HNSW 索引 + 用于全文搜索的 GIN 索引的 pgvector。 |
## 数据摄入(Ingestion)工作原理
1. Webhook 发送至 `POST /webhooks/github` 或 `POST /webhooks/jira`
2. Pydantic 验证 payload —— 格式错误的请求会被拒绝并返回 HTTP 422,绝不会触及 Kafka
3. 根据事件 ID 生成确定性的 UUID v5(相同的输入 → 每次都会生成相同的 UUID)
4. 事件被生产到 Kafka topic `system-events` 中,并采用基于 key 的分区(partitioning)
5. API 立即返回 —— webhook 响应耗时 <5ms
在 consumer 端:
6. 3 个 consumer 副本以 `enable.auto.commit: False` 模式轮询 Kafka
7. 事件会被缓冲,直到累积达到 10 条或超过 2 秒
8. 批次被发送到本地 embedding API(Jina v2,768 维向量)
9. 向量通过 `ON CONFLICT (id) DO NOTHING` 被 upsert 到 PostgreSQL
10. **仅在**数据库事务成功之后,Kafka 的 offset 才会被提交
如果 consumer 在第 8 步到第 10 步之间崩溃,offset 将保持未提交状态,Kafka 会在重启时重放该批次。确定性的 UUID + 冲突保护机制可确保不会有重复数据进入数据库。
## 检索(Retrieval)工作原理
检索 API 针对 PostgreSQL 运行两个并行的、由索引支持的查询,然后合并结果:
**语义搜索(Semantic search)** —— 针对 `embedding` 列的 HNSW 索引,按余弦距离(cosine distance)排序。捕获语义层面的相似性(比如 _"database crashed"_ 会匹配 _"PostgreSQL connection refused"_)。
**关键词搜索(Keyword search)** —— 针对 `to_tsvector('english', content)` 的 GIN 索引,按 `ts_rank_cd` 排序。捕获向量搜索容易遗漏的精确匹配:如 `Refs #33173` 这样的 ticket ID、`test_ForeignKey_using_to_field` 这样的测试名称,以及版本号。
这两个结果集会被合并并评分:
```
hybrid_score = 0.7 × semantic_score + 0.3 × keyword_score
```
接着会应用时间衰减因子来降低旧事件的权重:
```
final_score = hybrid_score × exp(−0.05 × age_in_days)
```
这会带来大约 14 天的半衰期(half-life)—— 近期事件会自然浮现,而无需使用那些可能会丢弃潜在有用的旧上下文的硬性日期截断。衰减系数存在于应用层,因此调整它不需要修改 schema 或重建索引。
在执行搜索之前,查询本身会经过一次 LLM 调用来进行优化,该调用会从自然语言输入中提取错误代码、服务名称和关键术语。这是一个尽力而为(best-effort)的步骤 —— 如果失败(如受到速率限制、超时),则会退回到原始查询作为后备方案。
## 故障处理
| 故障情况 | 后果 |
|---|---|
| PostgreSQL 宕机 | Consumers 以指数退避方式重试(5秒 → 10秒 → 20秒)。Kafka offsets 保持未提交状态,因此事件会保留在磁盘上,并在数据库恢复后重放。 |
| Embedding API 崩溃 | Consumer 会记录错误并故意崩溃。Docker 的 `restart: unless-stopped` 策略会重新启动它。未提交的 offsets 会触发重放。 |
| 消息结构错误 | 如果 embedding API 返回 400/422(根本上属于坏数据),consumer 会将该批次路由到死信队列(Dead Letter Queue)topic,并提交 offset 以避免阻塞队列。 |
| Consumer 副本死亡 | Kafka 会检测到心跳丢失,触发分区重平衡(rebalance),并将孤立的分区重新分配给存活的副本。 |
| 查询时触及 LLM 速率限制 | API 会以指数退避方式重试(最多 5 次)。检索 API 的查询优化步骤会平滑降级为使用原始查询。 |
## 快速开始
**前提要求:** Docker Desktop (Compose V2+)、Python 3.11+、一个 [OpenRouter](https://openrouter.ai/) API key(免费额度即可)。
```
git clone https://github.com/YOUR_USERNAME/OpsStream-RAG.git
cd OpsStream-RAG
```
创建 `.env`:
```
OPENROUTER_API_KEY=sk-or-v1-...
LLM_MODEL=google/gemma-4-31b-it:free
GITHUB_TOKEN=ghp_... # optional, raises GitHub API rate limit
```
启动技术栈:
```
docker compose up --build -d
```
首次构建需要几分钟(下载 PyTorch,并将 Jina 模型内置到镜像中)。在此之后,启动将是瞬间完成的。
### 加载数据
从 [Django](https://github.com/django/django) 仓库摄入 1,000 条 commits:
```
python -m venv venv
venv\Scripts\activate
pip install requests python-dotenv
python scripts/ingest_historical_github.py
```
验证:
```
docker exec opsstream_db psql -U admin -d incident_logs -c "SELECT count(*) FROM incident_logs;"
```
### 查询
```
curl -X POST http://localhost:8897/ask \
-H "Content-Type: application/json" \
-d '{"question": "Who resolved the parallel test database destruction issue on Windows?"}'
```
### Streamlit dashboard
```
pip install streamlit psycopg[binary] pandas
streamlit run scripts/app.py
```
三个标签页:
- **Copilot Chat** —— 提出问题,获取基于检索到的日志所生成的答案
- **Vector Search Explorer** —— 检查原始检索得分(语义、关键词、时间衰减、最终得分)
- **Timeline Analytics** —— 随时间变化的摄入率
### 连接实时 webhooks
| 平台 | URL | Content Type |
|---|---|---|
| GitHub | `http://YOUR_HOST:8897/webhooks/github` | `application/json` |
| Jira | `http://YOUR_HOST:8897/webhooks/jira` | `application/json` |
## 评估
内置评估工具,采用 LLM-as-a-judge 针对黄金数据集(`data/eval_set.json`)进行评估:
```
python scripts/evaluate.py
```
衡量每个问题的四个指标:
| 指标 | 定义 |
|---|---|
| Context Precision | 检索到的日志中真正相关的比例 |
| Context Recall | 检索到的日志是否包含回答所需的所有信息 |
| Faithfulness | 生成的答案是否来源于上下文(而非幻觉) |
| Answer Relevance | 答案是否直接切中该问题 |
## 项目结构
```
OpsStream-RAG/
├── api/ # Webhook ingestion + RAG orchestration
│ ├── main.py # Pydantic models, Kafka producer, /ask endpoint
│ └── Dockerfile
├── consumer/ # Kafka consumer workers (3 replicas)
│ ├── main.py # Batching, embedding, upsert, DLQ routing
│ └── Dockerfile
├── embedding_api/ # Local vector inference
│ ├── main.py # Jina v2 via sentence-transformers
│ └── Dockerfile # Model downloaded at build time
├── retrieval_api/ # Hybrid search engine
│ ├── main.py # HNSW + GIN queries, time decay, query refinement
│ └── Dockerfile
├── scripts/
│ ├── app.py # Streamlit dashboard
│ ├── evaluate.py # RAG evaluation harness
│ └── ingest_historical_github.py
├── data/
│ └── eval_set.json # Golden evaluation dataset
├── docker-compose.yaml # 6 services, 8 containers
└── .env # API keys (gitignored)
```
## 许可证
MIT
标签:AIOps, Kubernetes, PMD, RAG系统, 凭据扫描, 实时流处理, 测试用例, 请求拦截, 软件成分分析, 运维自动化, 逆向工具