0xRyanlee/salva

GitHub: 0xRyanlee/salva

一个自托管的结构化发现智能运行时,面向 Agent/MCP/CLI/API 提供多轮检索、记忆复利与 n-ary 超图实体关系构建能力。

Stars: 1 | Forks: 0

# Salva Runtime Salva 是一个自托管的 **Discovery Intelligence Runtime** — 面向 Agent、CLI 和 API 调用的结构化检索服务。 ## 核心定位 - **Event-triggered**:由调用触发,非定时轮询 - **API-first**:REST API + MCP + CLI 三端整合 - **Agent-native**:MCP 是主要 agent 接口(Claude Code / Claude Desktop 直接接入) - **Review-gated compounding**:content terms 可沉淀到隔离记忆,但默认不跨 run 读取;只有同 campaign 已提升的记忆会再次注入 ## Pipeline 运作机制 ``` trigger (agent / CLI / API call) → Intent 解析 + domain 路由 → KeywordGraph 擴展(依 ExecutionContext 決定是否注入 memory seeds) → Multi-round multi-provider 檢索 → 提取 → BM25 去重 → 評分 → content_terms 提取 → 沉澱進 memory → 輸出 entities + relations + telemetry ``` ### 记忆与复利(B1+B2) ``` Round N 結果片段 → _extract_content_terms() [B1: controller.py] → telemetry.metadata["content_terms"] → content_nodes_json 持久化 [B2: persistence/runs.py] ↓ 後續 run(僅 campaign_promoted / campaign_all / global_legacy) → seed_from_memory() 讀取允許範圍內的 content_nodes → 注入圖中,擴展查詢範圍 ``` 默认值是 `read_scope=none`、`write_mode=quarantine`。单次调用内的多轮 KeywordGraph 仍在内存中运作,不需要在项目根目录建立 cache。 ### 执行与数据隔离 ``` { "execution": { "campaign_id": "naturehike-dach-2026", "continuation_id": "channel-map-r1", "persistence": "audit", "memory": { "read_scope": "campaign_promoted", "write_mode": "quarantine" } } } ``` - Agent 负责声明 objective、campaign、continuation 与是否需要旧记忆。 - Salva 负责强制 campaign filter、quarantine/promote 与 no-write 模式。 - 部署平台负责 auth、tenant 权限、filesystem roots、secrets。 完整契约:[docs/spec/execution-context.md](docs/spec/execution-context.md) ## 调用方式 ### 1. MCP(推荐 — Agent 首选) 配置 `apps/mcp/server.py` 为 Claude Code MCP extension: ``` { "mcpServers": { "salva": { "command": "python3", "args": ["-m", "apps.mcp"] } } } ``` 可用工具: | 工具 | 用途 | |------|------| | `salva_discover` | 同步 discovery(小任务) | | `salva_job_create` | 异步 job(大任务) | | `salva_job_status` | 轮询 job 状态 | | `salva_run_result` | 取完整 run 结果 | | `salva_audit` | 质量审计 | | `salva_pilot` | 下一步建议 | | `salva_hold_walk` | 遍历 n-ary 超图 | | `salva_routing_table` | 查看学习到的 source 权威排名 | | `salva_memory_summary` | 顶层 query families + content seeds | ### 2. REST API(同步) ``` curl -X POST http://localhost:8000/v1/discover \ -H "Content-Type: application/json" \ -d '{ "objective": "find_companies", "intent": {"market": "US", "industry": "AI hardware"}, "max_results": 10 }' ``` ### 3. REST API(异步) ``` # 創建 job curl -X POST http://localhost:8000/v1/jobs \ -d '{"discovery": {...}, "wait_for_completion": false}' # 查狀態 curl http://localhost:8000/v1/jobs/{job_id} ``` ### 4. CLI ``` salva find --market US --industry "AI hardware" salva job status salva audit ``` ## API 端点 | 端点 | 说明 | |------|------| | `POST /v1/discover` | 同步 discovery | | `POST /v1/jobs` | 创建异步 job | | `GET /v1/jobs/{job_id}` | Job 状态 | | `GET /v1/jobs/{job_id}/stream` | SSE 事件流 | | `GET /v1/runs/{run_id}` | Run 结果 | | `GET /v1/query-families` | 依 campaign / continuation / status 查询记忆 | | `POST /v1/query-families/{memory_id}/promote` | 提升已审核的 query-family memory | | `GET /v1/routes` | 路由目录 | | `GET /v1/providers` | 供应商列表 | | `POST /v1/pilot` | 下一步建议 | | `POST /v1/audits/{run_id}` | 质量审计 | | `GET /v1/hold/walk` | 超图遍历 | | `GET /v1/usage` | 用量统计 | ## 项目结构 ``` salva/ ├── apps/ │ ├── api/ # REST API (FastAPI) │ ├── cli/ # CLI (typer) │ └── mcp/ # MCP Server(9 tools,agent 主要入口) ├── core/ │ ├── controller.py # 協調器 + B1 content term 提取 │ ├── keyword_graph.py # 查詢圖 + B2 memory seed 注入 │ └── domain_vocab.py # 領域詞彙 registry ├── retrieval/ # 供應商適配器(SearXNG / Whoogle / DDG) ├── processing/ │ ├── dedup.py # BM25-hybrid 去重 │ └── scorer.py # 評分(injectable ScorerConfig) ├── enrichment/ # LLM/OSINT 富化(omlx bounded prompts) ├── hold/ # 超圖容器入口 ├── experiments/ # 理論驗證實驗(E1–E9) └── salva_core/ ├── persistence/ # SQLite — 分模組 │ ├── db.py # Schema + migration │ ├── runs.py # Run 記錄(含 content_nodes_json) │ ├── memory.py # Query family memory + seed 查詢 │ ├── hold.py # n-ary 超邊、canonical entities、routing memory │ ├── jobs.py # Job 記錄 │ ├── evidence.py # 證據鏈 │ ├── telemetry.py # 遙測 │ └── usage.py # 用量統計 ├── relation_ontology.py # FtM 對齊關係類型(7 canonical + multilingual surface forms) ├── vector_backends.py # JinaOmlxVectorBackend(1024d)+ HybridHash fallback ├── schemas.py # Canonical types ├── execution.py # ExecutionContext 標準化與 metadata └── service.py # 核心服務 ``` ## 快速启动 ``` # 1. 安裝 pip install -e ".[dev]" # 2. 設置環境變數 cp .env.example .env # 或直接編輯 .env # 必填: # OMLX_BASE_URL=http://localhost:8140 (本地 omlx,Jina embedding + LLM) # SALVA_SQLITE_PATH=./data/salva.db # SEARXNG_ENABLED=false (若無本地 SearXNG) # 3. 啟動 API python3 -m uvicorn apps.api.main:app --port 8000 # 4. 健康檢查 curl http://localhost:8000/health # 5. 測試 pytest ``` ## Embedding Backend | Backend | 启用方式 | 用途 | |---------|---------|------| | `jina_omlx` | `SALVA_SEMANTIC_VECTOR_BACKEND=jina_omlx` | 内容语义搜索(1024d Jina v5) | | `hybrid_hash` | 默认 | 轻量 hash 备用(无 omlx 时自动降级) | **注意:** Jina v5 小模型不适合跨字形实体名称解析(台积电↔TSMC cosine≈0.04)。 跨语言实体合并依赖 `canonical_entities` + `entity_aliases` gazetteer(Hold C2)。 ## n-ary 超图(Hold) Salva 使用 n-ary 超边表示多方关系(如 §13(d)(3) 集体持股、多方控股协议): ``` # 一條 acting_in_concert 超邊包含多個參與者 hyperedge: acting_in_concert ├── BlueMountain Capital [group_lead, 5.2%] ├── BM Fund A [group_member, 2.1%] ├── BM Fund B [group_member, 1.8%] └── Chatham Lodging Trust [target] evidence: SEC EDGAR SC 13D/A 2013-05-15 ``` 支持: - HIF(Hypergraph Interchange Format)lossless round-trip export/import - Bipartite projection(entity ↔ hyperedge) - Star projection(entity ↔ entity via shared hyperedge) ## 实验验证结果(E1–E9) | VP | 主张 | 结论 | |----|------|------| | VP1 | n-ary 超图忠实度 | ✅ E1 PASS | | VP2 | 公开源可得性 | ✅ E2 PASS | | VP3 | 真实 filing → n-ary 事实 | ✅ E3 PASS | | VP4 | 路由表自我优化 | ✅ E4 PASS | | VP5 | 跨语言实体解析 | ✅ gazetteer / ⚠️ Jina FAIL(跨字形 F1=0.31) | | VP6 | 跨语义关系合并 | ✅ E6 PASS(7→3 canonical 超边) | | VP7 | 语义+二跳 > 关键词 | ⚠️ E7 INCONCLUSIVE(2-hop recall=1.00;precision 下降) | | VP8 | HIF round-trip + 投影 | ✅ E8 PASS(零 diff) | | VP9 | 持久化复利可量测 | ✅ E9 PASS(seeds 0→46,nodes 34→61) | 详细结果:`experiments/hg_penetration/E*_FINDINGS.md` ### Agent-only vs Salva Dogfood(E10) Naturehike DACH 渠道检索的 live dogfood 显示: | Condition | Round 1 | Round 2 | Round 3 | Best pooled recall | |---|---:|---:|---:|---:| | Agent-only | 5 verified | 11 cumulative | 15 cumulative | 88.2% | | Salva | 2 verified | 0 snapshot | 0 snapshot | 11.8% | ![Naturehike DACH comparison](https://static.pigsec.cn/wp-content/uploads/repos/cas/0e/0e4f0300b626e5672e76d5d3b5918bf16e669994eec0d8e155f6a4d0715307e6.svg) Pooled recall 的分母是两条路径事后验证候选的联集,不是预先冻结的外部 ground truth。这也不是等预算 benchmark:Agent raw SERP 未完整保存、耗时不可比、Salva 使用 DDG live provider 且 R2/R3 发生零结果。它是可重现的 dogfood 与失败模式记录, 不能被解读为一般性模型排名。 详见:[experiments/agent_vs_salva/README.md](experiments/agent_vs_salva/README.md) ## 文档导航 | 文件 | 用途 | |------|------| | [CLAUDE.md](CLAUDE.md) | 开发者必读:设计原则与架构边界 | | [DEVELOPMENT_PROGRESS.md](DEVELOPMENT_PROGRESS.md) | 本次开发进度报告 | | [TODO.md](TODO.md) | 开发任务清单 | | [docs/spec/](docs/spec/) | 行为契约(正式规范) | | [docs/reports/execution-isolation-update-2026-06-08.md](docs/reports/execution-isolation-update-2026-06-08.md) | 隔离架构、风险与对抗审计 | | [docs/dogfood/naturehike-dach-2026-06-08.md](docs/dogfood/naturehike-dach-2026-06-08.md) | Naturehike DACH 渠道与 dogfood 结果 | | [experiments/EXPERIMENT_PLAN.md](experiments/EXPERIMENT_PLAN.md) | 实验计划与验证状态 | ## 错误处理 - `400` — 验证失败或输入错误 - `403` — Tenant 权限不足 - `404` — 找不到资源 - `429` — Quota 超限 - `500` — 内部错误 ## 许可证 采用 [Apache License 2.0](LICENSE)。允许商用、修改与私有部署,并附带专利授权;再散布时请保留版权与授权声明。 Copyright © 2026 Ryan Lee.
标签:MCP, REST API, 数据提取, 检索引擎, 自托管, 逆向工具