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. 常見評估流程
- 準備測試資料:每筆測試資料包含
input、expected_output(或多個 reference)以及可選的metadata。 - 建立 Chain:例如
LLMChain、ConversationalRetrievalChain等。 - 選擇 Evaluator:根據需求挑選或自訂多個 Evaluator。
- 呼叫
evaluate:LangChain 會自動跑多輪、收集指標、回傳EvaluationResult。 - 分析與視覺化:使用 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會自動把每筆input、output、evaluation記錄在雲端,可在 Dashboard 中檢視趨勢、比較不同模型或 Prompt 版本。
常見陷阱與最佳實踐
| 陷阱 | 可能的後果 | 解決方式 / 最佳實踐 |
|---|---|---|
| 只看單一指標 | 只關注 BLEU 可能忽略語意正確性 | 同時使用 字面、語意、LLM‑as‑Judge 三類指標 |
| 測試資料與模型訓練資料重疊 | 產生過度樂觀的分數 | 確保測試集 與訓練集 完全分離,最好使用 時間切割 或 領域外 資料 |
| Prompt 變動未同步 | 評估結果不可比 | 在批次評估時,固定 Prompt 並將 Prompt 本身記錄於 LangSmith |
| 忽略成本 | 使用 GPT‑4 評審大量樣本會產生高額費用 | 先用 字面/語意指標 篩選,僅對疑似失敗樣本使用 LLM‑as‑Judge |
| 評分標準不一致 | 人工評分與自動指標差距大 | 在設計 Prompt 時加入 具體評分規則,並在小樣本上先做 A/B 測試 |
| 隨機性未控制 | 同一輸入多次得到不同分數 | 設定 temperature=0(或 0.1 以下)以減少隨機性;若必須使用較高 temperature,則 多次取平均 |
最佳實踐總結:
- 多指標混合:至少結合一個字面指標、語意指標與 LLM‑as‑Judge。
- 分層抽樣:先用低成本指標篩選,再用高成本 LLM 評審。
- 版本化 Prompt:每次改動 Prompt 都新增一個
experiment,方便回溯比較。 - 自動化流水線:把
evaluate步驟寫入 CI/CD,確保每次模型更新都有回歸測試。 - 可視化與警示:使用 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 產品! 🚀