標籤: Auto-ABTest

  • 讓 LLM 真的會做研究:拆解 ResearchEVO

    📌 本文重點

    • ResearchEVO 讓 LLM 直接在程式碼空間做演化搜尋
    • 論文寫作以 sentence-level RAG 確保可檢索與可驗證
    • 可拆解為可落地的 Auto-Research / Auto-ABTest / Auto-Feature-Engineering 流程

    多數所謂「AI 做研究」還停留在幫你寫 code、寫報告;ResearchEVO 解決的痛點是:讓 LLM 直接在程式碼空間裡做演化搜尋、自己排實驗、自己寫論文。從工程角度看,它提供了一個可實作的 blueprint,讓你能在公司內做 Auto-Research / Auto-ABTest / Auto-Feature-Engineering,而不是只多一個聊天機器人。


    重點說明

    1. 演化階段:LLM 驅動的「程式碼空間搜索」

    ResearchEVO 的核心是 LLM + 演化算法 操作「程式碼本身」:

    1. 程式碼空間表示
    2. 個體 = 一份可執行程式碼(例如一個 train.py 或一個 model 定義 + config)。
    3. 用 LLM 實作 變異 / 交配
      • 變異:改損失函數、網路結構、優化器、訓練 schedule。
      • 交配:將兩個高適應度方案的關鍵設計融合。
    4. 不做 AST 級別操作也可以,實務上多數情況直接用 自然語言 prompt + code diff 就夠用。

    5. fitness 評估與搜索控制

    6. fitness 只看 metrics:例如 val_accuracyAUClatency
    7. Search loop:
      1. LLM 生成/修改程式碼。
      2. 提交到 GPU/雲端排程系統跑實驗。
      3. 收集結果 → 更新種群 → 再交給 LLM 反思與生成。
    8. 約束控制 避免亂飛:
      • 硬約束:只允許改特定檔案 / 函數;強制保持 I/O 介面不變。
      • 軟約束:LLM prompt 中加入「只動這幾個維度」「保留下列設計」。

    💡 關鍵: 把 fitness 完全交給客觀 metrics(如 val_accuracylatency),可以讓 LLM 的創意探索與實際效能緊密對齊。

    1. 對接現有 GPU / 雲端排程
    2. ResearchEVO 本身不是新的 scheduler,而是:
      • 上游:LLM 生成/修改 code & config。
      • 下游:把 job 提交給你已有的 Kubernetes / Slurm / Airflow / SageMaker / Vertex AI
    3. 你只需要做一層 adapter,把 ExperimentSpec → Job 映射好。

    2. 寫作階段:sentence-level RAG + 驗證

    演化出最佳演算法後,ResearchEVO 的寫作階段是在做 「可檢索、可驗證」的自動論文生成

    1. 論文結構模板
    2. 先固定一個論文 schema(Title / Abstract / Intro / Method / Exp / Discussion / Related Work)。
    3. 每個 section 再細分成 段落 level 的子任務,讓 LLM 聚焦生成。

    4. 句子級 RAG(sentence-level RAG)

    5. 檢索單位不是 chunk,而是句子
      • 實驗 log、表格、程式碼註解、對照文獻都 embed 成 sentence vector。
      • 每當 LLM 要生成一個句子,就檢索最相關的 3~5 個 evidence。
    6. 這樣可以:
      • 降低 context 噪音。
      • 讓每句話都有「引用依據」。

    💡 關鍵: 以「句子」為檢索單位,讓每一句論文敘述能精確對應到 3–5 條證據,大幅降低幻覺與錯引。

    1. 事實核查與防幻覺
    2. 對每一句包含數字、claim 的句子,送到 Verifier agent
      • 檢查是否能在實驗結果 / log / paper corpus 中找到支持證據。
      • 找不到就要求 LLM 重寫或改成不那麼強的 claim。
    3. 論文內引用的實驗表格、圖表,ID 必須能對回到真實跑出的 artifacts(例如 MLflow run id / S3 path)。

    3. 如何落地 Auto-Research / Auto-ABTest / Auto-Feature-Engineering

    你不一定要重現完整 ResearchEVO。實務上可以拆成:

    • 一個 orchestrator(Airflow / Prefect / Dagster / LangGraph)
    • 幾個 LLM agent(code 生成 / 反思 / 寫作)
    • 一個實驗調度器(K8s / Slurm / 自家平台)
    • 一個結果分析工具(MLflow / Weights & Biases / 自製 dashboard)

    核心流程:

    1. 目標定義
    2. LLM 生成候選方案
    3. 實驗排程跑
    4. 收集結果 & 自動分析
    5. LLM 反思改進
    6. 收斂後自動產出報告/論文

    💡 關鍵: 把「做研究」拆成可編排的 6 步驟流程後,Auto-Research 就變成一組可插拔模組,而不是神秘黑盒。


    實作範例

    以下用 Python + Airflow/LangGraph 說明一個簡化版 pipeline。

    1. 演化 loop 的 code 表示與變異

    假設我們把「演算法個體」抽象成一個簡單的 spec:

    from pydantic import BaseModel
    from typing import Dict, Any
    
    class AlgoSpec(BaseModel):
        name: str
        base_script: str              # 參考模板路徑
        hyperparams: Dict[str, Any]   # 学习率, layer 数等
        patches: str                  # LLM 產生的程式碼 patch (diff-like)
    

    讓 LLM 做「變異」:

    SYSTEM_PROMPT = """你是資深 ML 研究員,幫我在保持 I/O 介面不變的前提下,
    只修改 loss function、網路架構與訓練策略。輸出 unified diff 格式的 patch。"""
    
    user_msg = f"""
    目前的程式碼:
    {current_code}
    
    本輪實驗結果:
    val_accuracy = {metrics['val_acc']}
    train_loss_curve = {metrics['loss_curve'][:10]}
    
    請根據結果給出改進 patch。"""
    
    resp = llm.chat([
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": user_msg},
    ])
    
    patch = extract_patch(resp)  # 解析成純文本 diff
    new_spec = AlgoSpec(
        name=f"algo_v{gen_id}",
        base_script="templates/train_base.py",
        hyperparams={"lr": 3e-4, "hidden_dim": 512},
        patches=patch,
    )
    

    接著用簡單的 patch engine 把 diff 套進檔案,產生下一版 train.py


    2. 串接實驗排程(以 K8s Job 為例)

    假設有一個內部的 submit_experiment(spec: AlgoSpec) -> str 會幫你:

    1. 打包 code + config 到 image/volume。
    2. 生成 K8s Job yaml。
    3. 提交到 cluster,回傳 job_id

    簡化 pseudo-code:

    import kubernetes as k8s
    
    def submit_experiment(spec: AlgoSpec) -> str:
        job = build_k8s_job(spec)  # 填入 image, args, resource 限制
        api = k8s.client.BatchV1Api()
        resp = api.create_namespaced_job(namespace="research", body=job)
        return resp.metadata.name
    
    # fitness 評估:等 job 完成,讀取 metrics.json
    
    def fetch_fitness(job_id: str) -> float:
        # 假設每個 job 在 /results/metrics.json 寫入 val_acc
        metrics = load_from_object_store(f"results/{job_id}/metrics.json")
        return metrics["val_acc"]
    

    你只要確保:

    • 所有實驗都寫出 統一格式的 metrics.json / config.json
    • job name、run id 能對應回實驗記錄系統(MLflow、W&B)。

    3. Orchestrator:以 LangGraph 為例構建演化 DAG

    LangGraph 可以把 LLM、工具、迭代邏輯包成圖:

    from langgraph.graph import StateGraph, END
    
    class EvoState(BaseModel):
        population: list[AlgoSpec]
        history: list[dict]
        generation: int
    
    
    def propose_candidates(state: EvoState) -> EvoState:
        # 用 LLM 對每個 top-k spec 做變異
        ...
    
    
    def run_experiments(state: EvoState) -> EvoState:
        # 提交所有 candidates,等待完成,回寫 fitness
        ...
    
    
    def select_and_check_stop(state: EvoState) -> str:
        if state.generation >= MAX_GEN:
            return END
        return "propose"
    
    
    graph = StateGraph(EvoState)
    
    graph.add_node("propose", propose_candidates)
    graph.add_node("run", run_experiments)
    
    graph.add_edge("propose", "run")
    
    graph.add_conditional_edges("run", select_and_check_stop, {"propose": "propose", END: END})
    
    evo_app = graph.compile()
    

    後面你可以在另一個 graph 裡接上 writing phase:以最優 AlgoSpec + 實驗結果為輸入,調用 sentence-level RAG agent 生成報告或論文。


    4. sentence-level RAG 實作簡例

    from sentence_transformers import SentenceTransformer
    from qdrant_client import QdrantClient
    
    encoder = SentenceTransformer("all-mpnet-base-v2")
    qdrant = QdrantClient(host="localhost", port=6333)
    
    # 建 index:把實驗 log、表格、文獻拆成句子
    
    def index_sentences(sentences: list[str], meta: list[dict]):
        vecs = encoder.encode(sentences)
        qdrant.upsert(
            collection_name="research_corpus",
            points=[{"id": i, "vector": v, "payload": meta[i]} for i, v in enumerate(vecs)],
        )
    
    
    def retrieve_evidence(query_sentence: str, k: int = 5):
        qvec = encoder.encode([query_sentence])[0]
        hits = qdrant.search("research_corpus", query_vector=qvec, limit=k)
        return hits
    
    # LLM 每寫一句話前,先取 evidence
    
    claim = "在 QEC 任務上,我們的演算法平均錯誤率降低了 12.3%。"
    evidences = retrieve_evidence(claim)
    llm_context = format_evidence(evidences)
    
    resp = llm.chat([
        {"role": "system", "content": "根據下面的實驗證據,生成一個對應的結論句。"},
        {"role": "user", "content": llm_context},
    ])
    

    再加一個 Verifier:重新檢索一次,看 claim 是否可被證據支持,不行就標記為需重寫。


    建議與注意事項

    1. 實驗結果格式不一致

    • :每個實驗 script 隨意 print,LLM/agent 很難 parse,fitness 評估混亂。
    • 建議
    • 強制所有實驗輸出 統一 schema 的 JSON,例如:
      • metrics.json{"val_acc": 0.92, "train_time": 360}
      • config.json(完整 hyperparams)。
    • schema 驗證(Pydantic)檢查 artifact;不合法就標記這個個體為低適應度。

    2. LLM 收斂到壞思路 / mode collapse

    • :LLM 易過度放大小樣本成功設計,反覆微調同一個局部解,失去探索。
    • 建議
    • 搜索策略上引入 探索度控制:族群裡保留一部分「純隨機變異」個體。
    • 每 N 代重啟一次高多樣性的種群(借鑑 evolutionary algo 的 restart 策略)。
    • LLM prompt 中顯式要求「給出三類不同思路」,避免只改超參數。

    3. 成本與資源控制

    • :LLM + GPU 雙重成本,很容易跑成燒錢機器。
    • 建議
    • 在 orchestrator 層面設 hard budget:最大世代數、最大 job 數、最大雲端花費。
    • 用低成本模型做日常迭代,大模型只用在 跨世代總結 / 報告撰寫
    • 優先讓 LLM 做 靜態檢查(例如檢查明顯錯誤設計)再送去跑 GPU。

    4. LLM 對數據科學工具的錯用

    • :LLM 可能亂用 API(例如 pandas groupby 用錯、Sklearn split 漏掉 stratify),結果漂亮但不可信。
    • 建議
    • 對關鍵 API(train/test split、metrics 計算、cross-validation)儘量做成 封裝好的 utility 函數,禁止 LLM 自己寫這些低級邏輯。
    • 在 pipeline 裡加入 sanity check step
      • label 分布是否合理?
      • baseline 是否被超過?
      • 結果是否疑似 data leakage?

    5. 開始時先做「窄版」

    • 不要一開始就做「全自動研究員」。較務實的起點:
    • Auto-ABTest:讓 LLM 只改部分業務策略 / feature 配置,實驗系統沿用現有 AB 平台。
    • Auto-Feature-Engineering:LLM 只負責產生特徵轉換 pipeline(例如 SQL / PySpark),模型訓練沿用既有框架。
    • 寫作階段先只產出 自動實驗報告(非論文),幫團隊省時間。

    從工程的角度看,ResearchEVO 真正帶來的啟發是:

    把「做研究」拆成可編排的演化搜尋 + sentence-level RAG 寫作兩個 pipeline,然後用現成的 LLM、orchestrator、GPU 排程系統拼起來。

    只要你公司已經有基本的實驗平台,做一個自己的「輕量版 ResearchEVO」其實沒有想像中難,但能快速幫你把實驗速度和研究產出拉一個量級。

    🚀 你現在可以做的事

    • 先為現有實驗腳本統一輸出 metrics.json / config.json schema,打好 Auto-Research 地基
    • 選一個任務,用一個 LLM agent + 既有 K8s/Slurm 搭出最小可用的演化搜尋 loop
    • 把歷史實驗 log 拆成句子建一個向量索引,試做 sentence-level RAG 自動實驗報告生成