Настройка высокопроизводительной среды оценки
В этом руководстве мы создаём высокопроизводительную среду оценки, ориентированную на интеграцию фреймворка DeepEval для повышения точности модульного тестирования наших приложений LLM.
Мы устраняем разрыв между исходным поиском и окончательным генерированием, внедряя систему, которая рассматривает выходные данные модели как тестируемый код и использует метрики LLM-как-судья для количественной оценки производительности.
Импорт необходимых библиотек
«`python
import sys, os, textwrap, json, math, re
from getpass import getpass
print(«Hardening environment (prevents common Colab/py3.12 numpy corruption)…»)
!pip -q uninstall -y numpy || true
!pip -q install —no-cache-dir —force-reinstall «numpy==1.26.4»
!pip -q install -U deepeval openai scikit-learn pandas tqdm
print(«Packages installed.»)
import numpy as np
import pandas as pd
from tqdm.auto import tqdm
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from deepeval import evaluate
from deepeval.test_case import LLMTestCase, LLMTestCaseParams
from deepeval.metrics import (
AnswerRelevancyMetric,
FaithfulnessMetric,
ContextualRelevancyMetric,
ContextualPrecisionMetric,
ContextualRecallMetric,
GEval,
)
print(«Imports loaded successfully.»)
«`
Настройка окружения
«`python
OPENAIAPIKEY = getpass(«Enter OPENAIAPIKEY (leave empty to run without OpenAI): «).strip()
openaienabled = bool(OPENAIAPI_KEY)
if openai_enabled:
os.environ[«OPENAIAPIKEY»] = OPENAIAPIKEY
print(f»OpenAI enabled: {openai_enabled}»)
«`
Создание тестовых случаев
«`python
DOCS = [
{
«id»: «doc_01»,
«title»: «DeepEval Overview»,
«text»: (
«DeepEval is an open-source LLM evaluation framework for unit testing LLM apps. «
«It supports LLM-as-a-judge metrics, custom metrics like G-Eval, and RAG metrics «
«such as contextual precision and faithfulness.»
),
},
# … дополнительные документы
]
EVAL_QUERIES = [
{
«query»: «What is DeepEval used for?»,
«expected»: «DeepEval is used to evaluate and unit test LLM applications using metrics like LLM-as-a-judge, G-Eval, and RAG metrics.»,
},
# … дополнительные запросы
]
«`
Реализация пользовательского TF-IDF поисковика
«`python
class TfidfRetriever:
def init(self, docs):
self.docs = docs
self.texts = [f»{d[‘title’]}\n{d[‘text’]}» for d in docs]
self.vectorizer = TfidfVectorizer(stopwords=»english», ngramrange=(1, 2))
self.matrix = self.vectorizer.fit_transform(self.texts)
def retrieve(self, query, k=4):
qv = self.vectorizer.transform([query])
sims = cosine_similarity(qv, self.matrix).flatten()
top_idx = np.argsort(-sims)[:k]
results = []
for i in top_idx:
results.append(
{
«id»: self.docs[i][«id»],
«score»: float(sims[i]),
«text»: self.texts[i],
}
)
return results
retriever = TfidfRetriever(DOCS)
«`
Реализация гибридного механизма ответов
«`python
def extractivebaselineanswer(query, retrieved_contexts):
«»»
Offline fallback: we create a short answer by extracting the most relevant sentences.
This keeps the notebook runnable even without OpenAI.
«»»
joined = «\n».join(retrieved_contexts)
sents = re.split(r»(?<=[.!?])\s+", joined)
keywords = [w.lower() for w in re.findall(r»[a-zA-Z]{4,}», query)]
scored = []
for s in sents:
s_l = s.lower()
score = sum(1 for k in keywords if k in s_l)
if len(s.strip()) > 20:
scored.append((score, s.strip()))
scored.sort(key=lambda x: (-x[0], -len(x[1])))
best = [s for sc, s in scored[:3] if sc > 0]
if not best:
best = [s.strip() for s in sents[:2] if len(s.strip()) > 20]
ans = » «.join(best).strip()
if not ans:
ans = «I could not find enough context to answer confidently.»
return ans
def openaianswer(query, retrievedcontexts, model=»gpt-4.1-mini»):
«»»
Simple RAG prompt for demonstration. DeepEval metrics can still evaluate even if
your generation prompt differs; the key is we store retrieval_context separately.
«»»
from openai import OpenAI
client = OpenAI()
contextblock = «\n\n».join([f»[CTX {i+1}]\n{c}» for i, c in enumerate(retrievedcontexts)])
prompt = f»»»You are a concise technical assistant.
Use ONLY the provided context to answer the query. If the answer is not in context, say you don’t know.
Query:
{query}
Context:
{context_block}
Answer:»»»
resp = client.chat.completions.create(
model=model,
messages=[{«role»: «user», «content»: prompt}],
temperature=0.2,
)
return resp.choices[0].message.content.strip()
def raganswer(query, retrievedcontexts):
if openai_enabled:
try:
return openaianswer(query, retrievedcontexts)
except Exception as e:
print(f»OpenAI generation failed, falling back to extractive baseline. Error: {e}»)
return extractivebaselineanswer(query, retrieved_contexts)
else:
return extractivebaselineanswer(query, retrieved_contexts)
«`
Выполнение RAG для создания тестовых случаев
«`python
print(«\n Running RAG to create test cases…»)
test_cases = []
K = 4
for item in tqdm(EVAL_QUERIES):
q = item[«query»]
expected = item[«expected»]
retrieved = retriever.retrieve(q, k=K)
retrieval_context = [r[«text»] for r in retrieved]
actual = raganswer(q, retrievalcontext)
tc = LLMTestCase(
input=q,
actual_output=actual,
expected_output=expected,
retrievalcontext=retrievalcontext,
)
test_cases.append(tc)
print(f» Built {len(test_cases)} LLMTestCase objects.»)
«`
Настройка метрик
«`python
metrics = [
AnswerRelevancyMetric(threshold=0.5, model=»gpt-4.1″, includereason=True, asyncmode=True),
FaithfulnessMetric(threshold=0.5, model=»gpt-4.1″, includereason=True, asyncmode=True),
ContextualRelevancyMetric(threshold=0.5, model=»gpt-4.1″, includereason=True, asyncmode=True),
ContextualPrecisionMetric(threshold=0.5, model=»gpt-4.1″, includereason=True, asyncmode=True),
ContextualRecallMetric(threshold=0.5, model=»gpt-4.1″, includereason=True, asyncmode=True),
GEval(
name=»RAG Correctness Rubric (GEval)»,
criteria=(
«Score the answer for correctness and usefulness. «
«The answer must directly address the query, must not invent facts not supported by context, «
«and should be concise but complete.»
),
evaluation_params=[
LLMTestCaseParams.INPUT,
LLMTestCaseParams.ACTUAL_OUTPUT,
LLMTestCaseParams.EXPECTED_OUTPUT,
LLMTestCaseParams.RETRIEVAL_CONTEXT,
],
model=»gpt-4.1″,
threshold=0.5,
async_mode=True,
),
]
«`
Выполнение оценки
«`python
print(«\n Running DeepEval evaluate(…) …»)
results = evaluate(testcases=testcases, metrics=metrics)
summary_rows = []
for idx, tc in enumerate(test_cases):
row = {
«case_id»: idx,
«query»: tc.input,
«actualoutput»: tc.actualoutput[:200] + («…» if len(tc.actual_output) > 200 else «»),
}
for m in metrics:
row[m.class.name if hasattr(m, «class«) else str(m)] = None
summary_rows.append(row)
«`
Анализ результатов
«`python
print(«\n Compact score table:»)
display(compact)
print(«\n Full details (includes reasons):»)
display(df)
print(«\n Done. Tip: if contextual precision/recall are low, improve retriever ranking/coverage; if faithfulness is low, tighten generation to only use context.»)
«`
Мы выполняем функцию `evaluate`, которая запускает процесс LLM-как-судья для оценки каждого тестового случая по определённым метрикам. Затем мы агрегируем эти оценки и соответствующие качественные обоснования в централизованный DataFrame, предоставляя детализированный обзор того, где конвейер RAG демонстрирует выдающиеся результаты или требует дальнейшей оптимизации в области поиска и генерации.
1. Какие инструменты и библиотеки используются для автоматизации обеспечения качества LLM в статье?
В статье используются следующие инструменты и библиотеки: DeepEval для оценки приложений LLM, OpenAI для взаимодействия с моделями генерации текста, NumPy, Pandas, Scikit-learn, TfidfVectorizer для векторизации текстовых данных и поиска по документам, а также другие библиотеки для работы с данными и оценки производительности моделей.
2. Какие метрики используются для оценки производительности LLM в статье?
Для оценки производительности LLM в статье используются следующие метрики: AnswerRelevancyMetric, FaithfulnessMetric, ContextualRelevancyMetric, ContextualPrecisionMetric, ContextualRecallMetric и GEval. Эти метрики позволяют количественно оценить релевантность, точность и полноту ответов модели.
3. Как в статье реализуется гибридный механизм ответов?
В статье гибридный механизм ответов реализуется путём комбинации экстрактивного подхода (извлечение наиболее релевантных предложений из контекста) и генеративного подхода с использованием модели OpenAI. Это позволяет модели отвечать на запросы, используя контекст, даже если прямого ответа в контексте нет.
4. Какие шаги предпринимаются для создания тестовых случаев в статье?
Для создания тестовых случаев в статье выполняются следующие шаги: определение документов и запросов, реализация пользовательского TF-IDF поисковика для поиска релевантных документов, реализация гибридного механизма ответов для генерации ответов на запросы, выполнение RAG для создания тестовых случаев и настройка метрик для оценки производительности модели.
5. Какие рекомендации даются в статье для улучшения производительности RAG?
В статье даются следующие рекомендации для улучшения производительности RAG: если контекстуальная точность или полнота низкие, улучшить ранжирование или охват поисковика; если низкая достоверность (faithfulness), настроить генерацию так, чтобы модель использовала только контекст.