hanzalah5/sentinel
GitHub: hanzalah5/sentinel
一款基于 LangGraph 与 Gemini 的智能体事件响应系统,自动接收生产告警并生成经过验证的根因分析假设。
Stars: 0 | Forks: 0
# Sentinel
[](https://github.com/hanzalah5/sentinel/actions/workflows/ci.yml)
[](LICENSE)
**一个智能体事件响应与根因分析副驾驶。** Sentinel 接收生产
警报,像资深 SRE 那样进行调查——关联信号,形成
排序且有证据支持的根因假设——并(在后续迭代中)在人工审批关卡之后提出
修复方案。
本项目的工程重点**不是**“一个谈论事件的 LLM”。
而是一个生产级的 agent *系统*:在所有边界处进行类型检查,端到端追踪,
在 CI 中评估,并有意识地划定范围。
## 架构(迭代 1)
```
┌─────────────────────────────────────────────┐
POST /investigate │ FastAPI app │
(Alert JSON) ────────► │ CorrelationIdMiddleware → typed endpoint │
│ │ │
│ ▼ │
│ InvestigationService │
│ │ (correlation id + Langfuse cb) │
│ ▼ │
│ LangGraph: [triage_and_hypothesize] │
│ │ │
│ ▼ │
│ Gemini .with_structured_output(...) │
└────────────┼─────────────────────────────────┘
▼
RootCauseHypothesis (validated) ──► Langfuse trace
```
**此处重要的设计选择**
- **结构化输出,而非 JSON 解析。** 模型被强制返回
`RootCauseHypothesis` ——验证发生在模型边界,因此格式错误的
响应是一个被捕获的错误,而不是下游的意外。
- **可观测性先于功能。** 追踪和 correlation ID 在最初的
迭代中就被接入;每个请求及其 trace 共享一个 `correlation_id`。
- **存活 ≠ 就绪。** 只要进程启动,`/healthz` 就保持绿色(通过);
`/readyz` 只有在 agent 实际连接好(存在 Gemini 密钥)时才会通过。
- **提供者接缝(Provider seam)。** Agent 依赖于来自 `get_chat_model()`
工厂的 `BaseChatModel` ——后续迭代可以在不触及 graph 的情况下切换为具备成本/延迟感知的路由。
## 技术栈
| 关注点 | 选择 |
|---|---|
| 编排 | LangGraph(目前为单节点,有扩展空间) |
| LLM | 通过 `langchain-google-genai` 使用 Google Gemini |
| 类型安全的 I/O | Pydantic v2 + 结构化输出 |
| API | FastAPI |
| 摄入 | Redis Streams ——消费者组,至少一次交付,死信队列 |
| 可观测性 | Langfuse (v3) + 结构化 `structlog` 日志,共享 correlation ID |
| 工具 | `uv`, `ruff`, `mypy --strict`, `pytest` |
| 打包 / 部署 | Docker + Docker Compose |
| CI | GitHub Actions:lint → format-check → type-check → test |
## 快速开始
需要 Python 3.12 和 [`uv`](https://docs.astral.sh/uv/)。
```
# 1. 安装依赖(创建 .venv,解析 lockfile)
uv sync
# 2. 配置(测试可选;实际调用必需)
cp .env.example .env # then set GOOGLE_API_KEY
# 3. 质量门禁 — 全部离线运行,无需 API key
uv run ruff check .
uv run mypy src tests
uv run pytest
# 4. 本地运行 API
uv run uvicorn sentinel.api.app:create_app --factory --reload --port 8000
```
(如果您安装了 `make`:`make check` 运行 lint + typecheck + test;`make run` 启动 API。)
### 试一试
```
curl -s http://localhost:8000/healthz
curl -s -X POST http://localhost:8000/investigate \
-H 'Content-Type: application/json' \
-d '{
"alert_id": "alert-1024",
"title": "High p99 latency on checkout-api",
"description": "p99 latency rose to 2.4s; DB connection pool saturation warnings.",
"severity": "critical",
"service": "checkout-api",
"source": "prometheus",
"fired_at": "2026-07-12T09:31:00Z",
"labels": {"region": "us-east-1"}
}'
```
交互式 API 文档位于 `http://localhost:8000/docs`。
### 摄入流水线(事件驱动路径)
无需直接调用 `/investigate`,警报可以通过 Redis Streams 流转:
```
# Terminal 1 — 启动 Redis + 应用 + consumer worker
docker compose up --build
# Terminal 2 — 向 stream 重放合成事件
uv run python -m sentinel.ingestion.generator --count 20 --rate 2 --seed 42
# (或:make seed)
```
Worker 消费每条警报,运行调查,且仅在成功时 ACK。
失败的警报会被重试;反复失败(或无法解析)的警报会进入
死信流 `sentinel:alerts:dlq`。要在 Docker 外部运行 worker(需要一个
可达的 `REDIS_URL` 和 `GOOGLE_API_KEY`):`make worker`。
### Docker
```
docker compose up --build # redis + app (:8000) + ingestion worker
```
## 配置
所有设置均从环境变量或本地 `.env` 文件加载(参见 `.env.example`)。
| 变量 | 默认值 | 用途 |
|---|---|---|
| `GOOGLE_API_KEY` | — | Gemini 密钥。如果没有它,`/investigate` 将返回 `503`。 |
| `GEMINI_MODEL` | `gemini-2.5-flash` | 模型 ID。 |
| `LLM_TEMPERATURE` | `0.1` | 采样温度。 |
| `LANGFUSE_PUBLIC_KEY` / `LANGFUSE_SECRET_KEY` | — | 当两者都设置时启用追踪。 |
| `LANGFUSE_HOST` | `https://cloud.langfuse.com` | Langfuse 端点。 |
| `LOG_LEVEL` / `JSON_LOGS` | `INFO` / `true` | 日志记录。 |
## 刻意裁剪与路线图
范围本身就是一种功能。迭代 1 提供了一个完整且经过插桩的切片;下面的一切
都被有意推迟到首次*需要*它的那个迭代(包括基础设施)。
- [x] **迭代 2 —— 摄入:** Redis Streams 警报队列 + 可重放的合成
事件生成器,以至少一次交付方式消费,带有有界重试,以及
死信流。
- [ ] **迭代 3 —— Runbook RAG:** Postgres + pgvector 检索,以将假设建立在实际的 runbook 基础之上。
- [ ] **迭代 4 —— 持久化 HITL:** LangGraph checkpointer + `interrupt()`;修复
暂停以等待人工审批,并在做出决定后恢复。
- [ ] **迭代 5 —— 评估即 CI:** 一个带标签的事件集,用于对根因准确性进行评分,
在出现回归时阻止合并。
- [ ] **迭代 6 —— 成本路由与加固:** 廉价模型分诊 + 前沿模型
推理,语义缓存,速率限制,仪表板,部署。
## 项目布局
```
src/sentinel/
config.py # pydantic-settings
logging.py # structlog + correlation-id contextvar
contracts.py # Alert, RootCauseHypothesis, InvestigationResult, ...
llm.py # get_chat_model() provider seam (Gemini)
observability.py # Langfuse v3 client + LangChain callback handler
service.py # InvestigationService: run graph, package result
agent/
state.py # typed graph state
graph.py # the LangGraph investigation graph
ingestion/
streams.py # AlertStream: Redis Streams + consumer-group wrapper
worker.py # IngestionWorker: at-least-once consume, retry, dead-letter
generator.py # synthetic-incident generator CLI
api/
middleware.py # CorrelationIdMiddleware
app.py # FastAPI factory, lifespan, endpoints
tests/ # offline suite (fake model + fakeredis), keyless
```
标签:AIOps, LangGraph, 事故响应, 搜索引擎查询, 根因分析, 请求拦截, 运维工具, 逆向工具