問題現場
天線工程師手上的場型量測檔來自好幾種來源與年代:新版 Excel 長表、舊版正規化 workbook,以及 .dat、.aten、.ffs 等格式。要把它們畫成 2D/3D 圖、算出關鍵指標、再跟廠商規格比對。
我最早以為難點在「格式多」,後來發現真正會出事的是定義對不上:不同來源對「方向角度」的認定不一致——有些量測站把 theta / phi 的語意對調。一旦對調又沒被抓到,畫出來的場型圖漂漂亮亮、看起來完全合理,工程判讀卻是錯的,而且很難一眼看出來。錯的還不只是這張圖,是後面所有判讀和給廠商的回饋。
最小技術背景
- 天線場型(antenna pattern):天線往各方向收發訊號的強弱分布。
- theta / phi:描述方向的兩個角度。本工具的約定是
theta= 仰角0–180°、phi= 方位角0–360°。 - matrix shape:場型資料是一個矩陣,這裡固定為
(len(theta), len(phi))——列對應 theta、行對應 phi。 - realized gain:天線實際輻射效率納入後的增益;
.ffs提供的是 E-field,需要換算。 - grounding:讓 AI 的判斷「踩在已確認的事實上」,而不是自己猜。
系統架構與資料流
核心原則:KPI 由確定性程式算,LLM 只做覆核與解釋,永遠不讓模型憑空產出工程數字。形狀驗證是整條鏈的閘門:
flowchart TD
F["多格式檔案|dat / aten / ffs / excel"] --> P["依副檔名分流 parser"]
P --> N["正規化成統一 PatternData|釘死 theta/phi 與 shape"]
N --> V{"matrix shape 驗證"}
V -->|不符| BLK["擋下,不進視覺化"]
V -->|符合| K["計算 KPI|peak gain / efficiency / coverage"]
K --> VIS["2D polar + 3D surface 視覺化"]
K --> LLM["LLM grounded audit|只覆核,不算數字"]
關鍵設計決策(含取捨)
| 決策 | 選了什麼 | 否決的替代 | 為什麼 |
|---|---|---|---|
| 資料模型 | 所有格式先收斂成統一 PatternData | 每種格式各自一套處理 + 各自畫圖 | 否決:同樣的邏輯散在好幾處,改一個忘一個,遲早不一致 |
| 座標語意 | 在 parser 層把 theta/phi 與 row/col 對應釘死 | 當成 UI 細節、畫圖時再調 | 否決:座標語意是「產品對不對」的問題,不是「畫面好不好看」的細節 |
| 形狀檢查 | 依檔案實際內容動態驗 shape | hard-code 取樣點數量 | 否決:格式一變就靜默失真,圖照畫,只是畫錯的 |
| AI 角色 | KPI 先 deterministic 算,LLM 只覆核 | 讓 LLM 直接讀原始檔給結論 | 否決:模型很會給那種「看起來很對、其實是錯」的數字 |
代表性技術證據
統一資料模型與形狀驗證(pseudo-code,示意)
def to_pattern_data(theta, phi, gain):
# 不寫死數量;拿檔案真正的維度來驗,對不上就擋下、不放行
assert gain.shape == (len(theta), len(phi)), \
f"shape {gain.shape} != ({len(theta)}, {len(phi)})"
return PatternData(theta=theta, phi=phi, gain=gain) # row=theta, col=phi
舉個具體的:某檔讀進 theta=[0,90,180](3 點)、phi=[0,90,180,270](4 點),那 gain 就必須是 3 × 4。要是拿到 4 × 3,代表來源把 theta/phi 對調了——這時候我寧可直接擋下,也不要默默畫一張看起來沒事的錯圖。
LLM grounded audit(pseudo-code,示意)
kpi = compute_kpi(pattern) # 數字先用確定性程式算好,這步不關 AI 的事
audit = llm.audit(kpi, vendor_spec) # LLM 只負責解釋、挑可疑,絕不讓它算數字
assert_schema(audit, REQUIRED_KEYS) # 鎖死回傳格式,免得它今天這樣回、明天那樣回
踩過的坑
| 欄位 | 內容 |
|---|---|
| 症狀 | 某舊格式匯入後,3D 主瓣方向看起來合理,卻與量測站報告對不上 |
| 初判(猜錯) | 第一個念頭是繪圖的角度/視角設錯了 |
| 驗證 | 印出 matrix shape 與軸對應,發現列、行其實對到了相反的角度 |
| 根因 | 該格式的 theta/phi 語意與內部約定相反,且當時沒驗 shape |
| 修法 | 在 parser 層強制依檔案內容對齊(列=theta、行=phi)並驗 shape,不 hard-code |
| 預防 | 新增「theta 與 phi 維度不相等」的 synthetic case,對調時必定失敗 |
驗證方式
- 形狀 / 語意:拿刻意讓 theta、phi 點數不同的 synthetic 場型,看對調時會不會乖乖被擋。
- 報表一致性:
tests/test_app_gui_frequency_report.py驗證 axis label、KPI 欄位、矩陣方向一致。 - AI 回傳:
tests/test_llm_prompt_schema.py鎖 prompt / 回傳 schema,防止格式漂移。 - 驗收標準:同一份資料,圖、KPI 與報表三者方向一致,且 LLM 不得改動數值、只能標註。
可複製 SOP:把外部資料安全接進分析工具
適用情境:要把多來源、語意可能不一致的資料,接進同一個分析或 AI 工具。
不適用情境:單一固定格式、語意已保證一致時,可省略動態驗證。
前置條件
- 先寫下這個領域「不可妥協的定義」(這裡是 theta/phi 語意與 matrix shape)。
- 準備至少一組刻意「會出錯」的合成資料(如 theta、phi 點數不同),用來證明驗證真的會擋。
步驟
- 收斂模型:不管來源幾種格式,先全部收成同一套內部資料模型。
- 入口驗證:在入口就按檔案實際內容驗 shape / 語意,別寫死數量。
- 確定性計算:關鍵指標(KPI)一律自己用程式算,不外包給 AI。
- AI 只覆核:定義釘死、數字算好了,才輪到 AI 解釋與挑可疑。
- 鎖回傳格式:AI 輸出限定固定欄位,再用 schema 測試把漂移擋掉。
停損點
- shape / 語意驗證不過 → 擋下,不進視覺化(寧可不畫,也不畫錯)。
- 合成「會出錯」案例沒被擋下 → 驗證本身失效,先修驗證再說。
驗收標準
- 對調、缺欄、格式變動都會被擋。
- 同一份資料,圖、KPI、報表三者方向一致。
- AI 不能竄改任何數值,只能標註。
回滾:parser 對應出錯時,回到最後一次「合成案例全綠」的設定。
可複製到:任何「先確立 domain 事實、再讓 AI 覆核」的資料工具。
決策回放(三個月後回讀用)
- 背景:把零散、語意不一致的天線量測檔,做成可信、可比對的分析工具。
- 限制:不可外流內部 LLM 服務憑證、
.env、廠商規格與真實客戶量測資料。 - 考慮過但放棄:讓 LLM 直接讀原始檔給 KPI——被「會給看起來對、其實錯的數字」否決。
- 證據:
PatternDatashape 驗證、KPI 確定性計算、prompt schema 測試。 - 未解:要主打哪個格式(
.dat/.aten/.ffs);是否加 theta/phi 教學小節。
作者備註: 這案子最容易被低估的一點:座標方向搞反,圖還是很漂亮。所以「定義」一定要放在會擋人的程式檢查裡,不能靠看圖的人自己小心。