📌 本文重點
- 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 + 演化算法 操作「程式碼本身」:
- 程式碼空間表示
- 個體 = 一份可執行程式碼(例如一個
train.py或一個 model 定義 + config)。 - 用 LLM 實作 變異 / 交配:
- 變異:改損失函數、網路結構、優化器、訓練 schedule。
- 交配:將兩個高適應度方案的關鍵設計融合。
-
不做 AST 級別操作也可以,實務上多數情況直接用 自然語言 prompt + code diff 就夠用。
-
fitness 評估與搜索控制
- fitness 只看 metrics:例如
val_accuracy、AUC、latency。 - Search loop:
- LLM 生成/修改程式碼。
- 提交到 GPU/雲端排程系統跑實驗。
- 收集結果 → 更新種群 → 再交給 LLM 反思與生成。
- 用 約束控制 避免亂飛:
- 硬約束:只允許改特定檔案 / 函數;強制保持 I/O 介面不變。
- 軟約束:LLM prompt 中加入「只動這幾個維度」「保留下列設計」。
💡 關鍵: 把 fitness 完全交給客觀 metrics(如
val_accuracy、latency),可以讓 LLM 的創意探索與實際效能緊密對齊。
- 對接現有 GPU / 雲端排程
- ResearchEVO 本身不是新的 scheduler,而是:
- 上游:LLM 生成/修改 code & config。
- 下游:把 job 提交給你已有的 Kubernetes / Slurm / Airflow / SageMaker / Vertex AI。
- 你只需要做一層 adapter,把
ExperimentSpec → Job映射好。
2. 寫作階段:sentence-level RAG + 驗證
演化出最佳演算法後,ResearchEVO 的寫作階段是在做 「可檢索、可驗證」的自動論文生成:
- 論文結構模板
- 先固定一個論文 schema(Title / Abstract / Intro / Method / Exp / Discussion / Related Work)。
-
每個 section 再細分成 段落 level 的子任務,讓 LLM 聚焦生成。
-
句子級 RAG(sentence-level RAG)
- 檢索單位不是 chunk,而是句子:
- 實驗 log、表格、程式碼註解、對照文獻都 embed 成 sentence vector。
- 每當 LLM 要生成一個句子,就檢索最相關的 3~5 個 evidence。
- 這樣可以:
- 降低 context 噪音。
- 讓每句話都有「引用依據」。
💡 關鍵: 以「句子」為檢索單位,讓每一句論文敘述能精確對應到 3–5 條證據,大幅降低幻覺與錯引。
- 事實核查與防幻覺
- 對每一句包含數字、claim 的句子,送到 Verifier agent:
- 檢查是否能在實驗結果 / log / paper corpus 中找到支持證據。
- 找不到就要求 LLM 重寫或改成不那麼強的 claim。
- 論文內引用的實驗表格、圖表,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)
核心流程:
- 目標定義
- LLM 生成候選方案
- 實驗排程跑
- 收集結果 & 自動分析
- LLM 反思改進
- 收斂後自動產出報告/論文
💡 關鍵: 把「做研究」拆成可編排的 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 會幫你:
- 打包 code + config 到 image/volume。
- 生成 K8s Job yaml。
- 提交到 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。 jobname、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.jsonschema,打好 Auto-Research 地基- 選一個任務,用一個 LLM agent + 既有 K8s/Slurm 搭出最小可用的演化搜尋 loop
- 把歷史實驗 log 拆成句子建一個向量索引,試做 sentence-level RAG 自動實驗報告生成
