--- name: pipeline-persistence description: "Pipeline persistence — save, load, and reuse structured search plans. Triggers: pipeline, 管道, search plan, 搜尋計畫, 重複搜尋, saved search, 排程, schedule, workflow, DAG" --- # Pipeline 持久化 — 結構化搜尋計畫管理 ## 描述 將複雜的搜尋流程保存為可重複使用的 Pipeline YAML 配置。支援: - 從模板快速建立(pico、comprehensive、exploration、gene_drug、snowball) - 自訂 DAG(有向無環圖)多步驟管道 - 雙層儲存(workspace + global) - Schema-exact 驗證 + 有限度的安全 normalization ## 觸發條件 - 「把這個搜尋存起來」、「建立搜尋計畫」 - 「每週跑一次這個搜尋」、「保存這個 pipeline」 - 「列出我的管道」、「上次的搜尋可以再跑嗎」 - 「把剛才的搜尋轉成 search plan」 --- ## 🌟 快速開始 ### 方法 1: 用模板(最簡單) ```python # 保存一個 PICO 模板 pipeline save_pipeline( name="icu_remimazolam_vs_propofol", config=""" template: pico template_params: P: ICU patients requiring sedation I: remimazolam C: propofol O: delirium incidence, sedation quality """, tags=["anesthesia", "sedation", "ICU"], description="Weekly monitoring: remimazolam vs propofol ICU sedation" ) # 執行已保存的 pipeline unified_search(pipeline="saved:icu_remimazolam_vs_propofol") ``` ### 方法 2: 自訂 DAG(完整控制) ```python save_pipeline( name="brca1_comprehensive", config=""" steps: - id: expand action: expand params: topic: BRCA1 breast cancer - id: pubmed action: search params: query: BRCA1 breast cancer sources: [pubmed] limit: 50 - id: expanded action: search inputs: [expand] params: strategy: mesh sources: [pubmed, openalex] limit: 50 - id: merged action: merge inputs: [pubmed, expanded] params: method: rrf - id: enriched action: metrics inputs: [merged] output: format: markdown limit: 30 ranking: quality """, tags=["genetics", "oncology"], description="BRCA1 breast cancer comprehensive search with MeSH expansion" ) ``` --- ## 7 個 MCP 工具 ### save_pipeline — 保存管道 ```python save_pipeline( name="weekly_remimazolam", # 唯一名稱 (英數 + _ -, max 64) config="", # Pipeline 配置 tags=["tag1", "tag2"], # 最多 20 個 canonical 字串標籤 description="...", # 人類可讀描述 scope="auto" # "workspace" | "global" | "auto" ) ``` **Fail-closed contract:** - action/template 只接受下列 canonical 值;alias 與拼字錯誤直接拒絕 - template 參數只使用頂層 `template_params`;已退役的頂層 `params` 直接拒絕 - step ID 必須明確且唯一;dependency ID 必須精確引用前面的 step - 未知 `on_error`、output format 或 ranking 不會被猜測或改寫 ### list_pipelines — 列出管道 ```python list_pipelines() # 列出所有 list_pipelines(tag="ICU") # 按標籤過濾 list_pipelines(scope="workspace") # 只看工作區 ``` ### load_pipeline — 載入管道 ```python load_pipeline(source="weekly_remimazolam") # 從已保存 load_pipeline(source="file:path/to/pipeline.yaml") # 從檔案 ``` ### delete_pipeline — 刪除管道 ```python delete_pipeline(name="old_search") # 刪除配置 + 歷史 ``` ### get_pipeline_history — 查看執行歷史 ```python get_pipeline_history(name="weekly_remimazolam", limit=5) # 顯示:日期、文章數、新增/移除文章、狀態 ``` ### schedule_pipeline — 建立或更新排程 ```python schedule_pipeline(name="weekly_remimazolam", cron="0 9 * * 1") ``` `diff_mode=True` 會在排程報告附上與前次成功執行的差異:新增文章與移除 PMID 各最多 20 筆,首次執行標示 baseline。Partial/error 不據以推論移除。 `notify=True` 保存最後 run ID 與新增/移除數量;`list_pipelines` 顯示新增文章數並引導至 `get_pipeline_history`,不是外部推播。停用通知會清除舊摘要。 ### unschedule_pipeline — 移除排程 ```python unschedule_pipeline(name="weekly_remimazolam") ``` --- ## 5 個內建模板 ### pico — PICO 臨床問題 ```yaml template: pico template_params: P: ICU patients requiring sedation I: remimazolam C: propofol O: delirium incidence sources: [pubmed] # 可選,預設 pubmed limit: 20 # 可選 ``` **自動產生的 DAG:** ``` pico → search_p ──┐ → search_i ──┤ → search_c ──┼→ merged → enriched ``` ### comprehensive — 多資料庫 + MeSH 擴展 ```yaml template: comprehensive template_params: query: CRISPR gene therapy safety sources: [pubmed, openalex, europe_pmc] # 可選 limit: 30 # 可選 min_year: 2020 # 可選 ``` **自動產生的 DAG:** ``` expand → search_expanded ──┐ search_original ──┼→ merged → enriched ``` ### exploration — 種子論文探索 ```yaml template: exploration template_params: pmid: "33475315" limit: 20 # 每個方向的限制 ``` **自動產生的 DAG:** ``` related ──┐ citing ──┼→ merged → enriched refs ──┘ ``` ### gene_drug — 基因/藥物搜尋 ```yaml template: gene_drug template_params: term: BRCA1 sources: [pubmed, openalex] # 可選 limit: 20 # 可選 min_year: 2020 # 可選 ``` --- ### snowball — 多種子引用擴展 ```yaml template: snowball template_params: query: remimazolam ICU sedation seed_limit: 5 # 可選,1–10,預設 5 limit: 20 # 可選,預設 20 ``` 流程:search → citing + references → union merge(含原始搜尋結果)。 `related`/`citing`/`references` 也可透過 `inputs` 搭配 `seed_limit`,但不可同時給 `pmid`。 依輸入順序取前幾個不重複 PMID,每個 seed 消耗一次外部呼叫預算;合併去重後排除 seeds,並以 `limit` 截斷該 action 的結果。 ## 10 個可用 Action | Action | 說明 | 主要參數 | |--------|------|----------| | `search` | 文獻搜尋 | `query`, `sources`, `limit`, `min_year`, `max_year` | | `pico` | Agent-provided PICO handoff search | `P`, `I`, optional `C`, recommended `O` | | `expand` | MeSH/同義詞擴展 | `topic` | | `details` | 取得文章詳情 | `pmids` | | `related` | 相關文章 | `pmid` 或 `inputs` + `seed_limit`,`limit` | | `citing` | 引用文章 | `pmid` 或 `inputs` + `seed_limit`,`limit` | | `references` | 參考文獻 | `pmid` 或 `inputs` + `seed_limit`,`limit` | | `metrics` | iCite 引用指標 | (從 inputs 取得) | | `merge` | 合併結果 | `method`: `union` / `intersection` / `rrf` | | `filter` | 過濾結果 | `min_year`, `max_year`, `article_types`, `min_citations`, `has_abstract` | --- ## 雙層儲存模型 ``` Workspace scope (.pubmed-search/pipelines/) ├── 每個專案獨立 ├── 可納入 git 追蹤 └── 團隊共享 Global scope (~/.pubmed-search-mcp/pipelines/) ├── 跨專案共用 ├── 個人偏好 └── 通用模板 ``` **解析順序:** workspace 優先 → global fallback --- ## 生產級範例 ### 範例 1: 週報搜尋 — 麻醉藥物監控 ```yaml name: weekly_anesthesia_monitoring steps: - id: search_remimazolam action: search params: query: remimazolam sources: [pubmed, europe_pmc] limit: 50 min_year: 2024 - id: search_dex action: search params: query: dexmedetomidine ICU sedation sources: [pubmed] limit: 50 min_year: 2024 - id: merged action: merge inputs: [search_remimazolam, search_dex] params: method: union - id: filtered action: filter inputs: [merged] params: has_abstract: true article_types: [journal-article, clinical-trial, randomized-controlled-trial] - id: enriched action: metrics inputs: [filtered] output: format: markdown limit: 30 ranking: recency ``` ### 範例 2: 種子論文深度探索 ```yaml name: explore_landmark_paper steps: - id: seed_details action: details params: pmids: ["33475315"] - id: related action: related params: pmid: "33475315" limit: 30 - id: citing action: citing params: pmid: "33475315" limit: 30 - id: refs action: references params: pmid: "33475315" limit: 30 - id: merged action: merge inputs: [related, citing, refs] params: method: rrf - id: enriched action: metrics inputs: [merged] output: format: markdown limit: 25 ranking: impact ``` ### 範例 3: 系統性文獻回顧 — SGLT2 + 心衰竭 ```yaml name: sglt2_heart_failure_review steps: - id: pico action: pico params: P: Type 2 diabetes with heart failure I: SGLT2 inhibitors C: standard care O: hospitalization, mortality - id: mesh_expand action: expand params: topic: SGLT2 inhibitors heart failure outcomes - id: search_pico_p action: search inputs: [pico] params: element: P sources: [pubmed, europe_pmc] limit: 100 - id: search_pico_i action: search inputs: [pico] params: element: I sources: [pubmed, europe_pmc] limit: 100 - id: search_expanded action: search inputs: [mesh_expand] params: strategy: mesh sources: [pubmed, openalex] limit: 100 - id: merged action: merge inputs: [search_pico_p, search_pico_i, search_expanded] params: method: rrf - id: filtered action: filter inputs: [merged] params: min_year: 2018 has_abstract: true - id: enriched action: metrics inputs: [filtered] output: format: markdown limit: 50 ranking: quality ``` --- ## Agent 產生 Pipeline 的最佳實踐 ### 從中斷的搜尋回復 先讀 server-side durable state,不要依賴對話記憶或 `.github/hooks/_state`: ```python read_session(request={"action":"search_runs"}) read_session(request={"action":"search_run","run_id":""}) read_session(request={"action":"replay_search","run_id":""}) ``` `replay_search` 只回傳 credential-free `unified_search` arguments,不會自動執行或消耗 provider quota。Agent 檢查 source status、artifact audit 與使用者意圖後,再明確呼叫 `unified_search`。如果原 run 已有 artifact,優先讀 artifact,只有需要最新結果時才 replay。 ### 將對話搜尋轉為 Pipeline Agent 在完成一次成功搜尋後,可以: ```python # 1. 回顧剛才的搜尋策略 # 2. 轉化為 Pipeline YAML save_pipeline( name="auto_from_session", config=""" steps: - id: main_search action: search params: query: "<剛才的查詢>" sources: [pubmed, openalex] limit: 50 - id: enriched action: metrics inputs: [main_search] output: limit: 20 ranking: balanced """, description="Auto-generated from search session" ) # 3. 下次直接重複 # unified_search(pipeline="saved:auto_from_session") ``` ### 常見模式 | 場景 | 推薦模板 | 說明 | |------|----------|------| | 臨床問題 A vs B | `pico` | Agent 提供 P/I/C/O;後端執行含 O 的 precision/recall 搜尋 | | 主題綜合搜尋 | `comprehensive` | 多源 + MeSH 擴展 | | 已知重要論文 | `exploration` | 三方向探索(related/citing/refs) | | 基因/藥物研究 | `gene_drug` | 詞彙擴展 + 多源 | | 複雜工作流 | 自訂 DAG | 完全控制每個步驟 |