Communitygithub.com

exmergo/dex

Dex 是專為代理(Agent)設計的分析工程工具組。只需指向您的資料倉儲與 dbt 專案,它便能學習資料結構、自動撰寫轉換邏輯,並在綱要偏移時明確告訴您該修正什麼。專為想從程式碼代理中獲得更多價值的分析工程師與資料工程師打造。

dex 是什麼?

Dex 是一個代理原生(agent-native)的分析工程工具組,讓 AI 代理(如 Claude Code、Cursor)能像資深分析工程師一樣與資料倉儲互動。它透過唯讀的命令列封裝器操作,輸出結構化的 JSON 信封(envelope),代理需據此決定下一步行動。支援 DuckDB 以及 BigQuery、Snowflake 等雲端資料庫。核心功能包含探索(explore),可對物件進行排名與剖析,並推斷關聯性與候選鍵。其進階的查詢防火牆會阻擋可能揭露個人識別資訊(PII)的語句,且有嚴格的成本控管(包含確認步驟與預算限制),確保安全可控的資料存取。它也支援 dbt 語意層查詢、叢集分析,並可將探索結果繪製成 Mermaid ER 圖。所有運算都在唯讀模式下進行,絕不修改原始資料。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add exmergo/dex

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

探索(Explore)

以分析工程師的方式理解一個資料倉儲或本機 DuckDB 資料庫:對重要項目進行排名、選擇性深入探查,並將草稿地圖持續儲存。這是旗艦級、完全唯讀的技能。它將資料剖析與關聯性推斷吸收為內建能力,而非獨立技能。

如何使用

透過封裝器(wrapper)執行引擎。它只會輸出一個清理過的 JSON 信封,沒有其他內容;請讀取該信封並決定下一步。

uv run "${CLAUDE_SKILL_DIR}/scripts/run.py" <子命令> [旗標]

子命令,按一般順序:

  1. connect test --path <file.duckdb> 確認唯讀連線並回報能力。
  2. explore inventory --rank 回傳排名後的物件摘要(計數與大小,不含資料列)。
  3. explore profile <objects>(以空格或逗號分隔)回傳資料行輪廓(column profiles),PII 旗標記錄為(資料行, 類別, 信心度)且絕不回傳範例值,以及候選鍵、可能的粒度(grain),與資料品質警告(例如:會導致連表爆炸的非唯一 id)。*_name 這類通用旗標的信心度會根據同一掃描中取得的數值形狀證據進行雙向調整:符合人名形狀的數值會強化它,封閉的參考詞彙或過長的標籤則會將其降級至防火牆的封鎖門檻以下,而缺乏證據則不會改變任何事(旗標本身絕不會被移除)。不重複計數(Distinct counts)為近似值以利擴展,但任何在近似誤差範圍內看起來唯一的資料行,都會被升級為精確的 COUNT(DISTINCT)(distinct_count_exact: true),因此唯一性與粒度判斷是建立在實證基礎上;警告中的 ~ 前綴表示該計數仍是近似值。如果請求物件的快取輪廓仍然新鮮(相同的連接器、綱要未變更、在 profile_freshness_hours 內,預設為 24 小時),則會從快取中提供(cache_hit_count)而非重新掃描,因此對 map 剛寫入的表格進行剖析幾乎不需成本;如果來源以自由中繼資料檢查無法察覺的方式發生了變更,請傳遞 --refresh 以強制重新掃描。
  4. explore relationships 回傳推斷出的與宣告的關聯(joins)及其信心度,以及說明推斷依據的備註(因此空列表是有意義的)。加上 --verify 會透過聚合重疊探針(孤立資料比例,並調整信心度)來測量每個推斷出的關聯。
  5. explore map 寫入或更新 .dex/ 快取並輸出摘要(此處 --verify 同樣適用)。超過 50 個物件時,它只會根據排名剖析前 25 個,並在 notes 中說明(包含 skipped_count);傳遞 --full 以剖析所有物件。在重新製圖時,本次執行跳過的物件會保留其先前的輪廓(carried_forward_count),每個物件都標有各自的 profiled_at 時間戳,因此過時情況是透明的,而非欄位細節默默消失。如果所選物件的快取輪廓仍然新鮮(相同的連接器、綱要未變更、在 profile_freshness_hours 內,預設為 24 小時),則會重複使用而不重新掃描(cache_hit_count),因此重新執行幾乎不需成本;如果來源以自由中繼資料檢查無法察覺的方式發生了變更(例如資料列變更但綱要未變),請傳遞 --refresh 以強制完整重新剖析。explore relationships 和獨立的 explore profile 也以相同方式重複使用新鮮的輪廓。
  6. explore diagram [--full] 將快取的地圖渲染為 data.mermaid 中的 Mermaid ER 圖。此操作免費且無需連線(僅讀取快取,從不連線資料倉儲),因此在調整圖形時可以安全地重新執行。請將字串原封不動地放在一個被圍起來的```mermaid 區塊中,讓人類可以查看,並在使用者想要將圖儲存到磁碟時,將其寫入 .mmd 或 Markdown 檔案:引擎刻意不寫入任何檔案。 切勿手動重新繪製或「整理」圖表。這些圖形是引擎根據證據推斷出的主張,而您提供的看似合理的基數,正是此命令旨在防止的過度主張:已宣告的關聯為實線,推斷出的為虛線,而未經驗證的推斷絕不會說「恰好一個」。在呈現圖表前請先閱讀 notes,因為它會說明哪些物件或欄位被遺漏了;--full 會將範圍從預設值(已剖析的、有關聯的物件及其粒度、鍵、關聯和 PII 欄位)擴展到所有符合條件的項目。
  7. explore query "<SELECT ...>" ["<SELECT ...>" ...] 回答固定命令無法涵蓋的臨時性問題:您編寫 SQL,引擎的查詢防火牆會拒絕或限制它。每個引數傳遞一個陳述句,或使用 --sql-file <path> 傳遞更長的列表,並在一次呼叫中提出一整個問題鏈,而非每次一個;每個陳述句都會被獨立判斷和回答,因此其中一個被拒絕並不會影響其他陳述句,而 data.results 為每個陳述句提供一個對應條目。您尚未剖析的表格(包括剛建立的模型)會自動為您剖析,然後陳述句才會執行,因此探索新物件只需一次呼叫而非三次;信封會說明它剖析了什麼,而在計量連接器上,該剖析的成本與陳述句的成本會計入同一次確認中。結果以列為主的方式回傳並有上限;拒絕時會指出違規的欄位和修復方式,因此只需重寫一次。在編寫探查查詢前,請閱讀 ${CLAUDE_SKILL_DIR}/references/probe-playbook.md:它將常見問題映射到有效的探查形狀。
  8. explore cluster <object> [--features a,b,c] [-k N] 對物件數值欄位的有限樣本執行 k-means 聚類,並回傳分段結構:每個叢集的大小與比例、質心(每個座標是該叢集該特徵的平均值,是一個聚合值)、輪廓係數(silhouette score),以及當省略 -k 時,它選擇的 k 值及其選擇依據的輪廓係數掃描過程。需要 .dex/ 快取(先執行 map/profile),以便從已剖析的數值、非 PII、非鍵欄位中自動選擇特徵;傳遞 --features 讓您自己選擇(指定 PII 欄位或鍵會刻意將其加入,並且只會報告其平均值)。鍵永遠不會作為特徵:其平均值無意義,且事實表主要由鍵加上少數度量組成,因此對它們進行聚類只是在分割代理範圍。鍵是唯一欄位、進行關聯的欄位(來自 map 推斷的關聯),以及名稱類似於鍵的欄位;在此處,map 優於單獨的 profile,因為沒有推斷出的關聯,外部鍵只有在名稱洩露其身份時才會被捕捉到。備註會說明每個被排除的欄位,因此在相信結果之前請先檢查它們。輪廓係數本身無法告訴您的兩件事,備註都會說明。樣本中佔比低於 1% 的叢集是一個離群值口袋,不是一個分段,它會因為距離遙遠而推高分數:請將其報告為離群值偵測,或使用 -k 重新執行以分割主要部分。而在無法為樣本設定種子的連接器上,每次執行的抽取結果都會不同,因此兩次執行得出的 k 值可能不一致;信封中的 sample_repeatable 會說明您屬於哪種情況,比較不同抽取的執行結果是沒有意義的。只有聚合值會跨越邊界:樣本資料列在進程內進行聚類,絕不會進入上下文。在計量連接器上,它與下面的掃描命令採取相同的成本確認流程(僅掃描特徵欄位,且方言感知的取樣子句會讀取一部分),因此請先呈現估計值並取得預算。需要 [cluster] 套件(scikit-learn);封裝器會為此子命令自動安裝。
  9. explore semantic list 和 explore semantic query 可存取 dbt 語意層(指標、維度、實體)。list 是探索:有哪些指標存在,以及每個指標可以按哪些維度分組。query 在明確模式之後使用一個位置引數傳遞指標(--metric 保留以向後相容),以及 --group-by <entity__dim>(可選的 --where、--grain 和 --limit),並以有上限的、欄位為主的結果回傳指標值。名稱旗標接受逗號分隔的列表或重複的旗標(--group-by a,b 等同於 --group-by a --group-by b);--where 永不分割。兩個後端可回答這些問題,由 .dex/config.yml 中的 semantic.backend 選擇,並可透過 --local / --api 覆蓋。--local 使用 MetricFlow 渲染 SQL,並透過 dex 自己的連接器和成本確認流程執行,因此在花費之前會呈現成本(需要 dbt 專案,並且對於 query 需要 [semantic] 套件;list 是一個清單檢視,兩者都不需要)。--api 將查詢傳送到託管的 dbt Cloud 部署(僅需要主機、環境 ID 和 DBT_SL_TOKEN,加上 [semantic-api] 套件,不需要本地專案)。託管後端是成本防護無法適用的唯一地方:dbt Cloud 在伺服器端執行,因此結果會帶有明確的警告,說明花費由 dbt Cloud 管理,而非 dex,且不會要求 --confirm。無論哪種方式,形似 PII 的分組或過濾維度(例如 user__email)都會在查詢執行前被拒絕。這是查詢語意層;編寫它則是 transform 的工作。

query 的參與規則:當固定命令能回答問題時,優先使用它們;一個探查查詢回答一個問題;將相關的度量批次處理到單一查詢中,而不是發出多個查詢;PII 標記欄位上的聚合必須是測量型(COUNT、APPROX_COUNT_DISTINCT、AVG(LENGTH(...))),絕不能是數值攜帶型(MIN、ANY_VALUE、STRING_AGG)。FROM 子句可以使用連接器原生的慣用語法來展開 JSON 和陣列欄位,這是探索無綱要資料的正確方式(例如「哪個鍵在此 JSON 欄位的每一列中出現」):BigQuery 使用 t, UNNEST(JSON_KEYS(doc)) AS k,Snowflake 使用 t, LATERAL FLATTEN(input => doc) f,Databricks 使用 t LATERAL VIEW EXPLODE(json_object_keys(doc)) x AS k,Postgres 使用 t, jsonb_object_keys(doc) AS k,Redshift 使用 t, UNPIVOT t.doc AS v AT k,DuckDB 使用 t, UNNEST(json_keys(doc)) AS u(k)。展開的值必須來自查詢中某個表格的欄位(直接使用,或透過 JSON/陣列函數);展開子查詢、另一個表格、字面值或生成器都會被拒絕,且展開的輸出會繼承來源欄位的 PII 旗標。某個欄位的旗標若被降級至 0.5 的封鎖門檻以下,則會正常投影,但信封中會有警告說明其名稱;請將此警告視為給使用者的資訊,而非需要修復的錯誤。如果使用者說某個被拒絕的欄位不是個人資料,建議在 .dex/config.yml 中加入 pii_overrides 條目(完全限定欄位名稱、可選原因):它可以立即解除查詢封鎖、在重新剖析後仍保留,並且可在 git 中審查。切勿手動編輯 .dex/cache.json 來清除旗標。切勿使用原始 Python 或資料庫 CLI 來執行 SQL;防火牆路徑是唯一被認可的方式。

雲端與資料庫目標(BigQuery、Snowflake、Databricks、Postgres、Redshift)

遠端資料倉儲或資料庫以連接器設定取代 --path。從 connect test --connector <name> 開始(或在 .dex/config.yml 中設定 connector: 以及對應的區塊:bigquery: 加上 project 和 datasets 允許清單,snowflake: 加上固定的 warehouse 和 databases 允許清單,databricks: 加上固定的 SQL warehouse 和 catalogs 允許清單,postgres: 加上 schemas 允許清單,redshift: 加上 Serverless workgroup 和 schemas 允許清單)。憑證是自動發現的,無需詢問:如果信封回報缺少或過期的憑證,請轉達它所說明的修復方式(對於 BigQuery 是 gcloud auth application-default login;對於 Snowflake 是 connections.toml 條目或 SNOWFLAKE_* 環境變數;對於 Databricks 是 databricks auth login 或 DATABRICKS_* 環境變數;對於 Postgres 是 DATABASE_URL、PG* 環境變數或 pg_service.conf 條目;對於 Redshift 是 AWS 憑證鏈(aws configure、AWS_* 環境變數)或 REDSHIFT_* 環境變數),且切勿要求使用者貼上金鑰、令牌或密碼。

在計量連接器上,掃描命令(profile、map、relationships、query)會執行兩步驟確認。第一次呼叫會回傳 needs_confirmation,其中包含 cost.estimate 中的估計值(以及相關的按表細項):在 BigQuery 上是精確的乾執行位元組數,在 Snowflake 上是以倉儲秒為單位的啟發式估計(標記為 estimate_quality: "heuristic",同時附上點數),在 Databricks 上是以倉儲秒為單位的下限估計(標記為 estimate_quality: "low",同時附上 DBU;它會在已確認的預算內自行修正),在 Redshift 上是以計算秒為單位的啟發式估計(同時附上 RPU-小時;Serverless 估計一次包含 60 秒的啟動最小值),在 Postgres 上則是以資料庫秒為單位(無金額;受防護的數量是營運資料庫的負載)。以人類可讀的單位向使用者呈現估計值,向他們取得明確的預算,然後使用 --confirm 和 --budget <數量>(以該標準的單位)重新發出相同的命令。切勿編造使用者未同意的預算,且未經詢問,切勿在被拒絕後以更高的預算重試。中繼資料是免費的(connect test、inventory 會立即執行),而 OK 信封會報告 data.spend 下的實際花費。

在 BigQuery 上,剖析估計值會為每個剖析在聚合掃描後可能仍會發出的升級查詢,保留每個表格 10 MB 的下限,因此在包含許多小型表格的倉儲中,大部分數字可能都是為從未發生的作業所做的保留。確認流程和被拒絕的報告都會說明這個拆分情況(reserved_bytes 和 reserved_queries,以及說明文字)。當您呈現估計值時,請傳達此資訊:一個數字是掃描還是保留,會影響提高預算是購買工作量還是儲備空間。

當估計值大於實際應有的工作量時,請縮小範圍而非提高預算。--scope(可重複)將命令限制在所設定來源允許清單的一部分,使用連接器自身的詞彙:在 BigQuery 上是資料集,在 Snowflake 上是 schema 或 database.schema,在 Databricks 上是 catalog.schema,在 Postgres 或 Redshift 上是綱要。它可以免費解析,並且只會縮小範圍。

相關技能