Community研究與資料分析github.com

2016judea/垂直市場代理

構建一個聊天代理,它比任何通用模型都更了解某個行業和某個都會區,因為它攜帶了預先計算的真實公開記錄摘要,並能在對話中即時拉取最新資訊。

垂直市場代理 是什麼?

此技能旨在引導開發者建立一款專注於單一行業與單一都會區的垂直型 AI 代理。其核心優勢在於,代理並非依賴模型的通用知識回答問題,而是使用一個預先計算好的「基底」(substrate)——一份凍結的 JSON 摘要,其中包含真實的公開記錄(如產權、稅務、評論)。這確保了答案的可追溯性與準確性,並建立了競爭對手難以複製的護城河。 技能詳細涵蓋了從專案定位(步驟 0)、尋找數據護城河(步驟 1)、構建基底(步驟 2),到處理數據陷阱(步驟 4)、實現確定性數學計算(步驟 5)、控制提示詞成本(步驟 6),以及最終部署與監控(步驟 7)的完整實作生命週期。其中特別強調了數據處理中的關鍵陷阱,例如如何避免產生「看似合理但實際錯誤的數字」,以及如何處理空間資料(步驟 9)等進階議題。 本技能支援的技術平台廣泛,可應用於 Claude Code、Coder 或 Codex 等 AI 代理工具。其在實務上的適用場景包括:建立一個比通用模型更了解當地房地產市場的查詢代理、一個專精於特定行業(如餐廳、汽車維修)評論分析的推薦代理,或是一個能根據即時公開記錄提供估值建議的商業顧問代理。總而言之,本技能為開發者提供了一套嚴謹、可驗證的方法論,用於打造以真實數據為基礎的垂直領域 AI 解決方案。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/2016judea/brick-mortar-skills/tree/HEAD/skills/vertical-market-agent

Installed? Explore more 研究與資料分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜歡的 AI 中提問

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

說明文件

建立垂直市場代理

一個聊天代理,在單一行業和單一都會區的表現勝過通用模型,因為它攜帶了預先計算的真實數據摘要,並能在對話中即時拉取最新記錄。完成 = 在一個 URL 上線,能回答帶有可追溯至數據源頭的數字,拒絕編造不存在的資訊,並已透過真實的生產環境探測(而非本地測試)驗證。

第 0 步:業主回答的兩個問題

  1. 哪個都會區,為什麼選它? 選擇你已經在當地進行過實地考察或擁有真實數據的地方。先開採一個都會區的數據,然後 再在該處投放廣告。
  2. 是否會投放廣告,並且是否相關聯? 這會影響四個工程決策(像素追蹤、快取 TTL、自訂網址、歸因)。請參閱第 7 步。

第 1 步:在寫程式碼前找到護城河

兩種形式:一個你開採並擁有的語料庫(例如數萬則評論),或一個聯集(將即時待售清單與縣政府的地塊、估價和稅務記錄結合:兩個沒人費心整合的免費資源)。付費的批量列舉通常會失敗(信用額度用完、缺少業主查詢功能)。

當批量列舉被封鎖時,切入點是限制條件,而非數據本身。 一個能回答任何地址但無法列出清單的縣政府應用程式,只要你能在其他地方列舉地址(第 3 步),就沒有問題。

非揭露州反而是個機會:沒有人擁有銷售比較數據,包括競爭對手在內,因此縣政府自身整理良好的算術資料就成了最佳的參考基準。

第 2 步:建立基底

一個凍結的 JSON 摘要,在每次訊息交換時由伺服器端注入系統提示詞中。

  • 首先檢查評論語料庫代理的樣本規模。「你在同類場所中的排名」需要約 50 家以上、每家擁有 50 則以上評論的商家。低於此門檻,不要發布排名功能。
  • 模型撰寫的行業簡介不是基底。載入模型自己寫的文字,只是在告訴模型它已經知道的事,無法創造護城河。基底是經過測量的。
  • 缺失的資料是待辦事項,不是障礙:如果你擁有開採某個資料集的方法,就去開採它。
  • 開採前先檢查授權條款。有些資料來源的數據不可重新發布,這決定了開採後的資料集是否能提供下載。
  • 每個區塊都帶有 _interpretation:2-4 句解釋其意義以及專業人士如何使用它。這是每字節價值最高的部分;它區分了「背誦」和「推理」。
  • 字節穩定的輸出:使用 sort_keys=True,對整體進行排序並以唯一欄位作為平手時的依據,除 generated_on 外不包含時間戳記。任何一個字節的變化都會導致每次訊息的快取前綴被重新計費。
  • 分層,並允許較新的層取代舊層;針對同一個問題,如果有兩個區塊給出不同數值,模型將在中間進行仲裁。當一個區塊內容混合時,在子鍵層級進行取代。
  • 存檔完整版,發布精簡版(使用 .compact.json 雙胞胎檔案),若精簡版遺失則回退到存檔版。
  • 從合併的研究資料中清除個人電子郵件:在廣告規模下,模型可能會將某個公務員的收件匣變成你的對外溝通渠道。提供部門名稱和電話號碼即可達到相同目的。

第 3 步:列舉記錄無法涵蓋的資料

一個精簡的清單 feed 幾乎什麼都看不到。「在附近搜尋」會以一個小型圓圈的網格進行,然後將每個搜尋結果與縣政府的記錄進行比對(一次執行:307 個社區 -> 208 個匹配地塊 -> 9,736 個單位)。

  • 小型圓圈(約 3.5 公里,網格間距約 3.9 公里):API 對每次呼叫的回傳結果數量設有上限,因此一次都會區範圍的查詢只會無聲地回傳最知名的地點。
  • 讓公開記錄決定某事物的本質,而非你列舉的來源(例如,目錄中的「公寓」在縣政府記錄中可能是護理設施;一輛被標記為多戶住宅的二手車停車場)。
  • 在一個幾乎沒有待售物件的市場中,值得交談的人是那些不在賣東西的人。

第 4 步:數據陷阱(請讀兩遍)

這裡的每個錯誤都產生了一個看似合理但實際錯誤的數字,從來不會產生錯誤訊息。 請針對已知正確的測試基準,預留除錯時間。

  1. 在根據來源的描述進行規劃之前,先重新查詢該來源。文件中的圖層名稱只是一個假設。在相信欄位名稱之前,請先讀取服務的中繼資料(對於 ArcGIS 使用 ?f=json,檢查 editingInfo.dataLastEditDate)和實際的欄位值。
  2. 用你已知的資訊進行驗證。一個已知有 36 個單位的建築物,被解析為 10 個:一個測試基準就抓到了最嚴重的錯誤。更好的是,將你的輸出樣本以不同的座標系送回發布者的 API 進行比較。
  3. 注意反向關係,而不僅僅是離群值:小房產每戶的估值高於大房產,表示解析器有誤,而不是市場有問題。
  4. 讓數據自我檢查。當存在交叉檢查機會時(例如每戶平方英尺),計算一個不明確欄位的兩個讀數,並讓合理的範圍來決定;如果兩者都不合適,則標記並排除。
  5. 在匯總之前先進行去重。一個 feed 將一個房產以其適用的每種資產類型列出:623 行資料實際上是 206 個房產。
  6. 快取原始 (RAW) 資料,而非解析後的資料,否則解析器修正後,就必須重新爬取小型縣政府的伺服器。
  7. 地址格式與記錄索引不同。縮寫方向詞並刪除後綴;使用變體階梯法恢復了約一半的配對失敗。
  8. 為小樣本標註其數量 n;有時資料的稀疏性本身就是一個發現。
  9. 對於評論語料庫,請閱讀實際的 MATCHES,而非比例。對實際的 1-3 星評論文本執行每個分類正則表達式,並閱讀它匹配的內容。該行業的服務動詞通常是傷害動詞:一個針對 cut (me|my) 的「傷害」模式,匹配了 10.7% 的美容院投訴,其中大部分是「付了 40 美元自己剪頭髮」。請檢查 drill(牙科)、pull(拖吊)、strip(汽車美容)、break(玻璃)、shave / clip(理髮、美容)、stick(抽血)。而且,一個沒有人提出的主題仍然會存在。
  10. 發布者的詞彙並非買家的詞彙。縣政府定義的「主幹道」類別可能是高速公路網路,那裡的房產並不臨街,而仲介所說的商業街則是「集散道路」。在進行對應之前,先列出每個分類的內容,並根據其內容來命名欄位。
  11. 共享的綱要共享欄位名稱,但不共享慣例。跨縣市時,一個欄位可能承載四種分類系統,使用 -9999 或 0,以及第三個自住房屋價值。請對每個縣市逐一普查每個欄位;將來自某縣市的零值視為查詢錯誤,直到被證明為止;偏好使用衍生測試(建築物價值 = 0 且土地價值 > 0 表示空置)。
  12. 一個名稱代表多個事物(一條高速公路及其輔助道路共享一個名稱)。回傳所有可能,並讓模型說明它使用了哪一個。
  13. 理論上「應該」相交一次的事物,實際上可能相交多次(兩條道路在六個地點交叉)。對點進行平均的結果可能落在田野中;請進行聚類,保留每個位置,並根據既定規則進行選擇。
  14. 一個衍生的總和會無聲地丟棄你從未計算過的行。在任何帶有部分輸入的總和旁邊附上覆蓋範圍計數,並使其顯示為一個下限值。

第 5 步:確定性的數學計算應放在工具中,絕不放在提示詞中

DSCR、IRR、現金回報率、劑量、稅務:使用工具進行計算,並回傳其假設和警告。模型的算術是看似合理但錯誤的(一個 1.19 的 DSCR 實際上是 1.09,這會傳給貸款方)。這強制了一個真實的代理循環(串流 -> 執行工具 -> 回饋結果 -> 串流),包括處理 pause_turn 和 max_tokens。

第 6 步:提示詞成本,經過測量

  • 使用 API 計算 token 數量。 密集的 JSON 大約是 2.4 位元組/token,而不是 4 位元組。
  • 在測試中強制執行位元組/token 上限:發布存檔版而非精簡版雙胞胎檔案,除了帳單金額增加外,不會有任何明顯症狀。
  • 快取 TTL 應根據流量調整。 少量、手動分享的流量:使用 5 分鐘的預設值(寫入 1 小時的資料是一種沒人會重複使用的附加費用)。持續的付費流量:使用 1 小時,因為訪客會共享前綴。

第 7 步:發布

  • 從單一生成器推導頁面;每個替代方案都斷言其錨點存在,且防護機制會檢查雙向(被移除的內容已消失並且該功能已存活)。
  • 如果它是廣告目標頁:使用暫時重新導向的自訂網址(永久重新導向會被廣告平台快取),並驗證查詢字串是否保留;每個廣告活動使用一個像素事件名稱;快取 TTL 設為 1 小時;以及歸因資訊固定在 sessionStorage 中,在到達頁面時設置,並在每次對話回合中傳遞(不要使用 localStorage,否則下週的自然訪問可能會被歸功於今天的廣告)。
  • 驗證部署狀態,而非建置日誌;無伺服器函數的容量限制或未追蹤的檔案,可能會在綠色日誌的背後悄悄失敗。以靜態方式匯入資料檔案,以便打包工具能將其包含在內。

提示詞的嚴格規則

  1. 絕不編造數字。 只能來自基底、實際執行的工具呼叫,或已標記的估計值。
  2. 絕不將公開記錄值呈現為市場價值。 說明你提供的是哪一種。
  3. 在工具描述和提示詞中都說明覆蓋範圍的邊界(哪些縣市)。只在一處設定的規則會被繞過。
  4. 一次查詢單一筆公開記錄,而非整份清單。 查詢所問物件的業主資訊是可以的;批量取得姓名和地址名冊可能違反州政府對商業用途的公開記錄法律。
  5. 重新檢查提示詞中認為不可能的事。 對於無法得知的事物,一個自信的錯誤陳述比資料缺口更糟糕。

用於上下文層的研究代理

給並行的研究代理一個token預算(以及 2.4 位元組/token 的比例),告訴他們寧可刪減數字也不要刪除警告,並預期他們會修正你之前的工作。

第 8 步:領域外的結尾

有些訪客不是你的目標用戶(例如,一個餐廳代理收到關於二手商店的查詢)。預設的「我不知道」會讓你失去你能得到的最佳訊號:一個真正的業主說出你下一步該建立的領域。

  • 一個 flag_out_of_scope(sector) 工具:客戶端呈現三個可點擊的選項;一個 submit_feature_request 工具記錄此次點擊。
  • 在第一則回覆中包含所有資訊:中位數的對話深度只有一個回合。
  • 不要列出代理已有的功能(某次修改將回覆長度從 1,275 個字符減少到 124 個字符)。
  • 選項由客戶端呈現,絕非以散文編號列表的形式呈現(純粹的「2」可能觸發技能 2)。
  • 告訴模型選項在哪裡呈現;模型看不到客戶端。
  • 將選項對應到通用功能,以便提交的請求能命名某個領域的某個功能。

第 9 步:空間層(「這旁邊是什麼」)

  • 找到縣政府的 ArcGIS Online 組織,而非其被 WAF 封鎖的 GIS 主機;託管服務通常允許匿名訪問。以圖層的原生空間參考請求幾何圖形。
  • 當兩個來源相交時,在第一個來源的座標系中請求第二個來源(使用 outSR),並在產出行之前斷定它們的範圍有重疊:座標系不匹配會導致沒有任何相交,並報告「每個地塊都未分區」。在 DuckDB 中,ST_Transform 需要 always_xy := true,否則會無聲地回傳 POINT(inf inf)。
  • 根據中心點進行分區;分割分區需要一個份額門檻(大於地塊面積的 5%),比較的是區域而非多邊形。簡單的相交呼叫導致 37% 的地塊被標記為分割;設定了門檻後約為 4%。
  • 一個城市的分區代碼只屬於那個城市。 相同的代碼在相鄰城市可能代表不同的分區;在每個代碼旁邊附上城市名稱和官方發布的名稱。
  • 離線預先計算,發布不含幾何資料的索引,不增加 API 路由:縣政府的 GIS -> DuckDB 空間鏡像 -> 一個已提交的 JSON 索引;執行時期僅進行查詢和 Haversine 計算。失敗的空間依賴會降級為一個空的鄰居列表,這是一個自信的錯誤答案。在載入時驗證索引,並拋出錯誤。
  • 空間聯結中的任何不等式條件,都會將空間謂詞降級為後置過濾器(ON a.id < b.id AND ST_Intersects(...) 測試了大約 290 億個配對)。讓謂詞獨立存在,使用 EXPLAIN 檢查 SPATIAL_JOIN,產出鍵值,然後進行去重:原本 7 分鐘無法完成的作業,變成了 19 秒。
  • 將發布的索引範圍限制在買方交易的區域加上緊鄰的區域,並標記承載較少資料的「背景」地塊。

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

2016judea/ascii-charts

Build charts as plain Unicode-block text — bar, range, bullet, gap-bracket, star-histogram, heatmap, line, Venn, pie, donut and scatter — with a dependency-free Python script, for anywhere only monospace text survives (newsletter code blocks, Markdown, terminals, plain-text email, chat). Use when a chart has to embed as literal text instead of an image or a third-party chart service, or when you want a hand-made terminal look with no branding footer.

2016judea/buffett-checklist

Apply Warren Buffett's investment framework as a discipline lens when weighing a buy, hold, or sell decision — circle of competence, economic moat, owner earnings & intrinsic value, margin of safety, management/capital-allocation quality, and market psychology (Mr. Market, fear vs greed, temperament). Use when asked to "run this through Buffett", "what would Buffett say", "does this pass the moat test", "is this cheap enough", or for a second, more skeptical read on a name being evaluated or already held. This is a discipline overlay, not a replacement for a strategy — it applies the Buffett lens to how someone actually invests, rather than issuing generic advice.

2016judea/image-riff

Turn one or more reference images into original art in that reference's own visual language, then cut it to whatever surface it's for. Use when you paste or point at art and say "use this as the base image", "generate art from this", "riff on this", "some creative ideation with these images", "make me a channel banner / avatar / cover / plate", "wilder version of this", or want a spread of options off one piece of reference. This is the TASK skill; the engine is the `make-art` tool skill.

2016judea/leonardo

Draw the way Leonardo da Vinci drew — a study sheet, a notebook folio, a red-chalk or silverpoint study, a machine cutaway, a storm of vortices — in his real materials and page-logic, generated with the make-art engine and anchored on fifteen of his actual (public-domain) sheets. Use when you say "Leonardo", "da Vinci", "like his notebooks", "a codex page of X", "draw this as one of his study sheets", "sanguine", "silverpoint", or wants a design, diagram, or illustration in that hand. Also a reading guide to his notebooks (Richter's 1883 public-domain translation) for "what did Leonardo say about shadow / trees / water". This is a TASK skill; the engine is `make-art`.

2016judea/mcp-stack

Which free MCP server or framework to reach for, and its traps — finance/gov data (SEC EDGAR, Yahoo, SAM.gov, USAspending), web research (Exa, Firecrawl, Crawl4AI, Jina reader), design/art/brand (Canva, Inkscape, Penpot, Figma, Orshot, Hugging Face image gen, vectorizing, charts), data/spatial (DuckDB spatial, live ArcGIS layers, OpenStreetMap/Overpass, Census, MapLibre), and ops (PostHog, iMessage, context7 docs). Use when making a social post, OG card, poster, logo/vector, chart, map, or brand asset; when querying parquet/geojson/duckdb or a city's open-data layer; when an MCP "needs authentication" or fails; or when asked "what tools do we have", "is there an MCP for X", "should we add X".

2016judea/records-request

Get a specific record out of a US government office by public-records request — "request the assessor's model", "file a data practices request", "FOIA this", "open records request", "can we just ask the county for it", "who do I write to at <county>", "chase that request", "did they ever answer". Covers checking the website first, finding the right office and statute, the carve-out paragraph that makes a request answerable instead of refused, web-form traps (hidden character caps, WAFs that reject apostrophes), chasing (there is usually no deadline), whether what comes back may be republished, and parsing multi-year tables without silent errors.

2016judea/sms-native-product

Build a product whose interface is text messages rather than an app or a website — "no app, no website", "they just text a number", "chat with our agent natively in Text Messages", "can we do this over text", "an SMS bot", "a Telegram bot", "make it a group chat", "minimum viable friction". Fires equally when it has already gone wrong — "my campaign got rejected", "our number is blocked", "the texts aren't arriving", "why do I need to register". Covers the gate that decides whether such a product can send at all (US A2P 10DLC registration, SHAFT content rules, permanent rejection codes), group MMS from code, what each channel can't do, an architecture that survives losing the channel, and guarding model-rewritten user content.

相關技能