📌 本文重點
- 用 LLM 在編譯階段產生狹義程式碼,執行期不再依賴 LLM
- 業務邏輯可測試、可審計,安全面積與成本大幅下降
- 特別適合高要求、高流量且規則穩定的企業級工作流
在多數專案裡,我們會每個請求都叫一次模型,把非結構化的 prompt 丟給 LLM,期待它「大致照規則」行事。問題是:結果不穩、難回溯、成本高,還容易被 prompt injection 玩壞。Compiled AI 要解的是這個痛點:
把原本寫在 prompt 里的業務邏輯,在編譯階段用 LLM 產生狹義程式碼,透過型別檢查、靜態分析與測試驗收,一旦通過就當成普通程式部署,執行期不再依賴 LLM。
對開發者的直接好處:
- 結果可預測且可審計:輸出由 deterministic code 決定,不是每次抽樣
- 安全面縮小:執行期不再接受任意自然語言指令
- 成本與延遲大幅下降:大量交易共用同一份已編譯邏輯,token 成本被攤薄
💡 關鍵: Compiled AI 把「每次都叫 LLM」改成「先編譯一次,再重複執行」,大幅提升穩定性並攤平成本。
重點說明
1. 架構:LLM 只在「編譯階段」出現
典型 Compiled AI 架構可以拆成三層:
- 模板/SDK 層(受控框架)
- 你先定義好已驗證的 workflow 模板與 SDK,例如:HTTP 呼叫、DB 查詢、RAG 檢索、權限檢查等
-
LLM 只能在模板內部空洞生成狹義業務邏輯函式,例如
select_customer_segment()、build_rag_query() -
編譯管線(有 LLM)
- Step 1 – Prompt 設計:描述任務、提供 API 規格 & 範例,要求輸出符合特定語言/框架(如 TypeScript + 自家 SDK)
- Step 2 – 產生 code artifact:LLM 產生一份或多份候選程式碼
- Step 3 – 謝與測試:型別檢查、靜態分析、單元測試/合約測試,不過關就自動 loop 回 LLM 要求修正
-
Step 4 – 人工審核 + 簽章(視風險):例如醫療或金流流程
-
執行期(無 LLM)
- 線上請求只執行已編譯出的 code artifact,全程 deterministic,可以完整 log & replay
核心概念:限制 LLM 的自由度,換取可測試、可版本控管的業務邏輯程式碼。
2. 工作流設計:把一個傳統 RAG / Agent 重構成 Compiled AI
以一個典型 RAG QA 流程為例:
使用者問問題 → LLM 根據 prompt 決定如何搜尋 → 呼叫向量庫 → LLM 基於檢索結果生成答案
在傳統設計中,LLM 負責檢索策略 + 答案生成,兩段都高度隨機。重構成 Compiled AI,可以這樣拆:
- 編譯階段
- 用 LLM 生成一個狹義函式:
build_search_plan(question: string) => SearchPlan,被嵌在已驗證的 RAG 模板中 SearchPlan僅包含:要查哪個 index、使用哪些 filter、topK、是否需要 fallback 等-
再用 LLM 生成:
synthesize_answer(question, contexts) => string,但這個函式需遵守強約束(例如:不可編造、必須引用 context id) -
執行階段
- 每次 QA 時:
- 用 deterministic code 呼叫
build_search_plan()→ 打 DB / 向量庫 - 把檢索到的 contexts 丟給
synthesize_answer()(也是普通函式)
- 用 deterministic code 呼叫
-
整個過程再也不直接丟自然語言給 LLM,所有 decision path 都是可測試、可覆盤的程式碼
-
版本控管與灰度發布
- 每次重新編譯:產出新版本如
rag_workflow_v3.ts - 用 Git tag & CI pipeline 把版本與測試報告綁在一起
- 線上:用 routing 或 feature flag 灰度流量,對比 v2 / v3 的成功率、平均延遲、查詢成本
3. 工程實務:與「每請求叫一次模型」的差異
基於現有研究與業界實測,Compiled AI 在幾個維度的典型差異:
- 可靠性(確定性 vs 隨機)
- 傳統:每次請求都用 sampling(
temperature > 0),同一輸入結果可能不同 -
Compiled AI:執行期只跑 deterministic code + DB/RAG,相同輸入必然同樣輸出
-
安全
- 傳統:使用者輸入直接進 prompt,prompt injection 面積很大
-
Compiled AI:執行期輸入只餵進已定義的函式參數(string / enum / id 等),無法直接改變控制流
-
成本與延遲
- 編譯階段比較貴,但只做一次,之後可在大量請求上攤平
- 實務上常見:十幾次交易後就開始比傳統架構便宜,長期 token 使用量可降數十倍
💡 關鍵: 只要請求次數夠多,執行期省下的 token 成本與延遲,會很快抵消一次性的編譯開銷。
實作範例
以下用 TypeScript + 假想 SDK 示範一個簡化版 pipeline。
1. 已驗證模板/SDK
// sdk.ts - 由你維護的安全 SDK
export type SearchPlan = {
index: 'faq' | 'policy' | 'logs';
topK: number;
filters?: Record<string, string>;
};
export async function runRagWorkflow(
question: string,
buildSearchPlan: (q: string) => SearchPlan,
synthesizeAnswer: (q: string, ctxs: string[]) => string
): Promise<string> {
const plan = buildSearchPlan(question);
const contexts = await vectorSearch(plan.index, question, plan.topK, plan.filters);
return synthesizeAnswer(question, contexts);
}
async function vectorSearch(
index: string,
query: string,
topK: number,
filters?: Record<string, string>
): Promise<string[]> {
// 已驗證的檢索實作
/* ... */
return [];
}
2. LLM 產生的狹義業務邏輯(編譯產物)
在編譯階段,你用一個 prompt 要求模型只實作兩個函式:
// generated_v3.ts - 由 LLM 產生,但要通過型別檢查與測試
import { SearchPlan } from './sdk';
export function buildSearchPlan(question: string): SearchPlan {
const q = question.toLowerCase();
if (q.includes('退款') || q.includes('billing') || q.includes('invoice')) {
return { index: 'policy', topK: 5, filters: { category: 'refund' } };
}
if (q.includes('錯誤') || q.includes('error code')) {
return { index: 'logs', topK: 10 };
}
return { index: 'faq', topK: 8 };
}
export function synthesizeAnswer(question: string, contexts: string[]): string {
// 嚴格規定:
// 1. 不得回答與 contexts 無關內容
// 2. 必須在文末列出引用的 context 索引
const summary = summarizeWithRules(question, contexts); // 你事先實作好的工具
const citations = contexts
.map((_, i) => `[#${i + 1}]`)
.join(' ');
return `${summary}\n\n引用來源:${citations}`;
}
3. 編譯 pipeline(CI 裡跑)
// compile.ts - 只在 CI / 開發環境執行
import { z } from 'zod';
import { callLLM } from './llm_client';
import { execSync } from 'child_process';
const schema = z.object({
code: z.string(),
});
async function generateCode() {
const prompt = `
你是一個 TypeScript AI,請只輸出一個檔案內容,實作:
- export function buildSearchPlan(question: string): SearchPlan
- export function synthesizeAnswer(question: string, contexts: string[]): string
必須符合已存在的型別定義:
- SearchPlan { index: 'faq' | 'policy' | 'logs'; topK: number; filters?: Record<string, string> }
禁止:
- 呼叫任何未在註解中允許的函式
- 使用 eval / new Function
- 動態匯入
`;
const raw = await callLLM({
model: '**gpt-4.1**',
temperature: 0,
response_format: { type: 'json_schema', schema },
messages: [{ role: 'user', content: prompt }],
});
const { code } = schema.parse(JSON.parse(raw));
return code;
}
async function main() {
const code = await generateCode();
require('fs').writeFileSync('generated_v3.ts', code, 'utf8');
// 1) 型別檢查
execSync('npx tsc --noEmit', { stdio: 'inherit' });
// 2) 靜態分析
execSync('npx eslint generated_v3.ts', { stdio: 'inherit' });
// 3) 測試
execSync('npm test -- generated_v3.test.ts', { stdio: 'inherit' });
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
搭配 CI/CD:
- CI:觸發
compile.ts→ 產出generated_v3.ts→ 跑測試 → 產出報表 - CD:若通過,打 tag
rag_workflow_v3,並更新配置讓 5% 流量導到 v3;監控成功率、latency、成本指標再逐步擴大
💡 關鍵: 把 LLM 產物納入 CI/CD(型別檢查、靜態分析、測試與灰度發佈),就能像管理普通程式碼一樣管理 AI 邏輯。
建議與注意事項
1. 業務規則變更頻率
Compiled AI 適合:
- 規則相對穩定、但正確性要求高的流程(客服 QA、金融函數呼叫、醫療文件處理)
不適合:
- 每天都在改規則、或依賴即時實驗的場景,因為每次改都要走「重新編譯 + 測試」流程
- 高度探索型、open-ended 任務(創作、策略 brainstorm、UX 研究等)
實務建議:
- 把流程拆成兩層:核心決策邏輯用 Compiled AI,外層的探索與創意仍然用即時 LLM
2. 測試覆蓋不足 = 把錯誤「編進系統」
Compiled AI 的風險是:一旦編譯出的邏輯有 bug,它會一直穩定地錯。
必做:
- 為生成函式設計合約測試:同一輸入 → 必須產出指定的
SearchPlan/ 函式呼叫序列 - 對關鍵場景建立 golden QA 測試集,每次編譯都跑完整 regression
- 對模型產物加上防呆檢查(如:topK 不可大於 50,index 只能是白名單)
3. 安全與最小權限
- 模板 / SDK 層要實施 最小權限:
- 不給生成函式直接打 DB 連線,只能呼叫封裝好的
queryCustomerById(id)等高階 API - 不允許檔案寫入、外網 request 等敏感操作
- 透過靜態分析檢查:是否有
eval、動態 import、直接執行 shell 等 pattern
4. 成本模型與「何時值得編譯」
可以用簡單估算:
- 編譯一次成本:
C_compile(幾萬 token) - 傳統架構每次請求成本:
C_online - Compiled AI 每次請求成本:
C_compiled(通常 ≪C_online)
只要請求數 N 滿足:
C_compile + N * C_compiled < N * C_online
就值得改成 Compiled AI。研究與實務常見:十幾到幾十次請求後就開始回本,高流量業務會很划算。
5. 與現有專案整合的落地步驟
- 先挑一個穩定且高流量的子流程(例如:FAQ RAG 檢索策略、金融 function calling 的參數整理)
- 為它抽象出一個窄介面函式(例如
buildSearchPlan、prepareFunctionCallParams) - 建立 minimal 的編譯 pipeline(LLM → 生成 code → tsc + 測試)
- 先 offline 對比:新老流程在測試集上的正確率 / 成本
- 小流量灰度上線,配合 metrics 監控,逐步拓展到更多流程
結論:Compiled AI 的核心不是「用 LLM 寫程式」,而是把 prompt 中模糊的規則,轉成可測試、可簽章、可審計的程式碼工件。對需要穩定性、安全與成本控制的企業工作流,特別是 RAG、function calling、金融與醫療場景,是非常值得實驗的架構升級方向。
🚀 你現在可以做的事
- 在現有系統中挑一段高流量、規則穩定的 RAG 或 function calling 流程,先抽象出一個窄介面函式如
buildSearchPlan- 建一個最小可行的編譯 pipeline:用 LLM 產生 TypeScript 函式 → 跑
tsc+ 單元/合約測試 → 輸出generated_v1.ts- 用 feature flag 灰度導入新流程,監控正確率、延遲與 token 成本,評估轉為 Compiled AI 的回本點

發佈留言