本文 AI 產出,尚未審核

LangChain 課程 – LLM 評估(Evaluation)

主題:生成品質評估方法


簡介

在使用大型語言模型(LLM)產生文字、摘要、程式碼或其他內容時,**「生成品質」**往往是決定應用成功與否的關鍵指標。即使模型本身已經非常強大,若缺乏系統化的評估機制,我們仍無法判斷模型輸出是否符合使用者需求、是否具備可接受的正確性與流暢度。

LangChain 作為 LLM 應用開發的框架,內建了多種 評估工具(Evaluator),讓開發者能在開發流程中即時取得量化指標,並結合 LangSmith 進行追蹤與可視化。這篇文章將從概念、實作、常見陷阱與最佳實踐,完整說明「生成品質評估方法」的使用方式,幫助你在實務專案中快速上手、提升模型表現。


核心概念

1. 為什麼需要多元評估指標?

類型 代表指標 優點 限制
字面相似度 BLEU、ROUGE、METEOR 計算詞彙或 n‑gram 重合度,易於實作 無法捕捉語意、會受參考答案長度影響
語意相似度 BERTScore、Sentence‑BLEU、Embedding‑Cosine 考慮上下文語意,對同義改寫較寬容 需要額外的語意模型,計算較昂貴
模型即評審(LLM‑as‑Judge) OpenAI gpt‑4、Claude、Gemini 能直接以自然語言給出「正確性」或「可讀性」評分 成本較高、結果受 Prompt 影響大
人工評分 0‑5 分制、A/B Test 最終驗證真實使用者感受 時間成本高、難以大規模化

結論:單一指標往往不足以完整描述生成品質,結合多種指標 才能得到更可靠的判斷。


2. LangChain 中的 Evaluator 介面

LangChain 把評估抽象為 BaseEvaluator,常見的內建實作有:

Evaluator 主要用途 典型呼叫方式
LLMEvalChain 使用 LLM 作為評審,支援自訂 Prompt LLMEvalChain.from_llm(OpenAI(...))
EmbeddingDistanceEvaluator 計算輸出與參考答案的向量相似度 EmbeddingDistanceEvaluator(model="text-embedding-ada-002")
StringEvaluator 基於 BLEU、ROUGE、METEOR 等字面相似度 StringEvaluator(metric="rouge")
CustomEvaluator 允許開發者自行實作任意評分邏輯 繼承 BaseEvaluator 並實作 evaluate 方法

這些 Evaluator 都可以直接與 LangChain 的 evaluate API 搭配,批次處理結果自動寫入 LangSmith


3. 常見評估流程

  1. 準備測試資料:每筆測試資料包含 inputexpected_output(或多個 reference)以及可選的 metadata
  2. 建立 Chain:例如 LLMChainConversationalRetrievalChain 等。
  3. 選擇 Evaluator:根據需求挑選或自訂多個 Evaluator。
  4. 呼叫 evaluate:LangChain 會自動跑多輪、收集指標、回傳 EvaluationResult
  5. 分析與視覺化:使用 LangSmith Dashboard 或自行匯出 CSV 進行統計。

程式碼範例

以下示範 五個實用範例,涵蓋字面相似度、語意相似度、LLM‑as‑Judge、客製化指標與批次評估。所有範例皆以 Python 撰寫,符合 LangChain 官方使用方式。

3.1 基本字面相似度(ROUGE)評估

from langchain.evaluation import evaluate
from langchain.evaluation.string import StringEvaluator
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate

# 1️⃣ 建立簡單的問答 Chain
prompt = PromptTemplate.from_template("請用中文回答以下問題:{question}")
llm = OpenAI(model="gpt-3.5-turbo", temperature=0.0)
qa_chain = LLMChain(llm=llm, prompt=prompt)

# 2️⃣ 準備測試資料
test_cases = [
    {"question": "台北 101 的高度是多少?", "expected_output": "508 公尺"},
    {"question": "Python 的創始人是誰?", "expected_output": "Guido van Rossum"},
]

# 3️⃣ 使用 ROUGE 評估器
rouge_evaluator = StringEvaluator(metric="rouge")

# 4️⃣ 執行評估
results = evaluate(
    qa_chain,
    test_cases,
    evaluators=[rouge_evaluator],
    # 直接把結果寫入 LangSmith(可選)
    # callbacks=[LangSmithCallbackHandler()]
)

print(results)   # 每筆會回傳 {'rouge': 0.xx, 'output': ..., 'input': ...}

重點StringEvaluator 內建 rouge_l, bleu, meteor 等,只要換 metric 即可。


3.2 語意相似度(BERTScore)評估

from langchain.evaluation import evaluate
from langchain.evaluation.embedding_distance import EmbeddingDistanceEvaluator

# 1️⃣ 仍使用上面的 qa_chain
# 2️⃣ 使用嵌入距離(BERTScore 近似)評估器
embedding_evaluator = EmbeddingDistanceEvaluator(
    model="text-embedding-ada-002",   # OpenAI 的嵌入模型
    similarity_metric="cosine"       # 也支援 "dot"、"l2"
)

# 3️⃣ 執行評估(同樣的測試資料)
results = evaluate(
    qa_chain,
    test_cases,
    evaluators=[embedding_evaluator],
)

for r in results:
    print(f"Cosine 相似度: {r['cosine']:.4f}")

說明:此評估會先把模型產生的文字與參考答案轉成向量,再計算餘弦相似度,能較好捕捉語意相近但字面不同的情況。


3.3 LLM‑as‑Judge:讓 GPT‑4 為答案打分

from langchain.evaluation import evaluate
from langchain.evaluation.llm import LLMEvalChain

# 1️⃣ 建立評審 LLM(使用 gpt-4,溫度設 0 以減少隨機性)
judge_llm = OpenAI(model="gpt-4", temperature=0.0)

# 2️⃣ 自訂評分 Prompt
judge_prompt = """
你是一位嚴謹的評審,請根據以下指標給出 0~5 分(5 分最佳):
1. 正確性(答案是否事實正確)  
2. 完整性(是否包含所有關鍵資訊)  
3. 可讀性(語句是否流暢、易懂)

請直接回傳 JSON,格式為 {"correctness": x, "completeness": y, "readability": z}
"""

llm_judge = LLMEvalChain.from_llm(judge_llm, prompt=judge_prompt)

# 3️⃣ 執行評估
results = evaluate(
    qa_chain,
    test_cases,
    evaluators=[llm_judge],
)

for r in results:
    print(r["evaluation"])   # 會印出 {"correctness": 5, "completeness": 4, "readability": 5}

技巧:Prompt 中明確要求 JSON 回傳,可以避免 LLM 輸出雜訊,後續程式碼直接 json.loads 解析。


3.4 自訂指標:計算「關鍵字覆蓋率」

有時候業務需求只在乎某些關鍵字是否出現在答案中,我們可以自行寫一個 Evaluator。

import json
from typing import List, Dict
from langchain.evaluation import BaseEvaluator

class KeywordCoverageEvaluator(BaseEvaluator):
    """檢查答案是否包含所有指定關鍵字,返回覆蓋率 0~1。"""

    def __init__(self, keywords: List[str]):
        self.keywords = [k.lower() for k in keywords]

    def evaluate(self, *, input: str, prediction: str, **kwargs) -> Dict[str, float]:
        pred = prediction.lower()
        covered = sum(1 for kw in self.keywords if kw in pred)
        coverage = covered / len(self.keywords) if self.keywords else 1.0
        return {"keyword_coverage": round(coverage, 3)}

# 使用範例
keyword_evaluator = KeywordCoverageEvaluator(keywords=["台北", "101", "公尺"])

results = evaluate(
    qa_chain,
    test_cases,
    evaluators=[keyword_evaluator],
)

for r in results:
    print(f"關鍵字覆蓋率: {r['keyword_coverage']*100:.1f}%")

應用:法律文件、醫療報告等必須包含特定術語時,這類自訂指標非常實用。


3.5 批次評估 + LangSmith 追蹤

在實務上,我們往往一次要評估上千筆資料。以下示範如何結合 LangSmith(LangChain 的實驗追蹤平台)與 Pandas,把結果寫入資料庫或 CSV。

import pandas as pd
from langchain.callbacks import LangSmithCallbackHandler
from langchain.evaluation import evaluate

# 1️⃣ 建立 LangSmith 回呼
langsmith_handler = LangSmithCallbackHandler(
    project_name="LLM 生成品質評估",
    experiment_name="qa_rouge_embedding"
)

# 2️⃣ 準備大量測試資料(假設已有 DataFrame)
df = pd.read_csv("qa_test_cases.csv")   # 必須包含 question、expected_output 欄位
test_cases = df.to_dict(orient="records")

# 3️⃣ 同時使用兩個 Evaluator
evaluators = [
    StringEvaluator(metric="rouge"),
    EmbeddingDistanceEvaluator(model="text-embedding-ada-002", similarity_metric="cosine")
]

# 4️⃣ 執行批次評估,結果自動上傳至 LangSmith
results = evaluate(
    qa_chain,
    test_cases,
    evaluators=evaluators,
    callbacks=[langsmith_handler],
    # 設定 batch_size 可降低 API 呼叫次數
    batch_size=20,
)

# 5️⃣ 把結果寫回 DataFrame,方便後續分析
df["rouge"] = [r["rouge"] for r in results]
df["cosine"] = [r["cosine"] for r in results]
df.to_csv("qa_evaluation_report.csv", index=False)
print("評估完成,報告已儲存至 qa_evaluation_report.csv")

提示LangSmithCallbackHandler 會自動把每筆 inputoutputevaluation 記錄在雲端,可在 Dashboard 中檢視趨勢、比較不同模型或 Prompt 版本。


常見陷阱與最佳實踐

陷阱 可能的後果 解決方式 / 最佳實踐
只看單一指標 只關注 BLEU 可能忽略語意正確性 同時使用 字面語意LLM‑as‑Judge 三類指標
測試資料與模型訓練資料重疊 產生過度樂觀的分數 確保測試集 與訓練集 完全分離,最好使用 時間切割領域外 資料
Prompt 變動未同步 評估結果不可比 在批次評估時,固定 Prompt 並將 Prompt 本身記錄於 LangSmith
忽略成本 使用 GPT‑4 評審大量樣本會產生高額費用 先用 字面/語意指標 篩選,僅對疑似失敗樣本使用 LLM‑as‑Judge
評分標準不一致 人工評分與自動指標差距大 在設計 Prompt 時加入 具體評分規則,並在小樣本上先做 A/B 測試
隨機性未控制 同一輸入多次得到不同分數 設定 temperature=0(或 0.1 以下)以減少隨機性;若必須使用較高 temperature,則 多次取平均

最佳實踐總結

  1. 多指標混合:至少結合一個字面指標、語意指標與 LLM‑as‑Judge。
  2. 分層抽樣:先用低成本指標篩選,再用高成本 LLM 評審。
  3. 版本化 Prompt:每次改動 Prompt 都新增一個 experiment,方便回溯比較。
  4. 自動化流水線:把 evaluate 步驟寫入 CI/CD,確保每次模型更新都有回歸測試。
  5. 可視化與警示:使用 LangSmith Dashboard 設定 分數下降警示,即時發現品質退化。

實際應用場景

場景 需要的評估指標 為何重要
客服聊天機器人 正確性(LLM‑as‑Judge)+ 可讀性(BLEU/ROUGE) 錯誤答案會直接影響客戶滿意度與品牌形象
新聞摘要服務 ROUGE‑L、BERTScore、關鍵字覆蓋率 必須保證摘要既完整不失真,且包含所有重要事實
程式碼自動生成 正確性(單元測試通過率)+ 可讀性(PEP8 compliance) 錯誤程式碼直接導致部署失敗,風險極高
醫療報告生成 正確性(專業術語覆蓋)+ 語意相似度 醫療資訊錯誤可能危及病人安全
多語言翻譯 BLEU、chrF、語意相似度 評估不同語言間的翻譯品質,確保語意一致

案例說明:假設你在開發一個「法律文件問答」系統,關鍵字覆蓋率(如「契約」、「違約金」)與 LLM‑as‑Judge 的正確性評分是必備指標。透過 LangChain 的 自訂 Evaluator 結合 LangSmith 追蹤,你可以快速定位哪些條款的回答不夠完整,並在每次模型調整後自動生成報表。


總結

生成品質的評估不再是「事後檢查」的附屬工作,而是 LLM 應用開發流程的核心環節。LangChain 提供了 多樣化的 Evaluator,從傳統的 BLEU/ROUGE 到最前沿的 LLM‑as‑Judge,甚至允許開發者自行實作關鍵字覆蓋率等客製指標。結合 LangSmith 的實驗追蹤與可視化功能,我們可以:

  • 系統化、可重現 地測量模型輸出品質
  • 分層成本控制:先用低成本指標篩選,再用高成本 LLM 評審
  • 快速迭代:在 CI/CD 中嵌入 evaluate,每次模型更新都有回歸報告
  • 洞察問題根源:透過多指標交叉比對,快速定位「正確性」與「可讀性」的瓶頸

掌握這套評估方法,你的 LLM 應用將更具 可靠性可維護性,也更能在實務場景中產生真正的價值。祝你在 LangChain 的旅程中,寫出更好、更加可信的生成式 AI 產品! 🚀