<НА ГЛАВНУЮ

Создание полностью трассируемого локального QA-пайплайна LLM с Opik для воспроизводимых и прозрачных оценок

'Практическое руководство по созданию, трассировке и оценке локального QA-пайплайна LLM с Opik и лёгкой моделью Hugging Face для измеримых и воспроизводимых результатов.'

Настройка и инициализация

Установите необходимые библиотеки и инициализируйте Opik. Ниже показан код для загрузки модулей, определения устройства и конфигурации проекта, чтобы все трейсы попадали в нужное рабочее пространство.

!pip install -q opik transformers accelerate torch
 
import torch
from transformers import pipeline
import textwrap
 
 
import opik
from opik import Opik, Prompt, track
from opik.evaluation import evaluate
from opik.evaluation.metrics import Equals, LevenshteinRatio
 
 
device = 0 if torch.cuda.is_available() else -1
print("Using device:", "cuda" if device == 0 else "cpu")
 
 
opik.configure()
PROJECT_NAME = "opik-hf-tutorial"
 

Это закладывает основу для воспроизводимого рабочего пространства трассировки.

Локальная модель и генератор

Загрузите лёгкую модель Hugging Face и создайте вспомогательную функцию для генерации текста локально без обращения к внешним API. Это даёт согласованный уровень генерации для пайплайна.

llm = pipeline(
   "text-generation",
   model="distilgpt2",
   device=device,
)
 
 
def hf_generate(prompt: str, max_new_tokens: int = 80) -> str:
   result = llm(
       prompt,
       max_new_tokens=max_new_tokens,
       do_sample=True,
       temperature=0.3,
       pad_token_id=llm.tokenizer.eos_token_id,
   )[0]["generated_text"]
   return result[len(prompt):].strip()
 

Структурированные подсказки

Определите шаблоны подсказок для этапов планирования и ответа. Чёткие шаблоны помогают поддерживать единообразие и упрощают анализ поведения модели.

plan_prompt = Prompt(
   name="hf_plan_prompt",
   prompt=textwrap.dedent("""
       You are an assistant that creates a plan to answer a question
       using ONLY the given context.
 
 
       Context:
       {{context}}
 
 
       Question:
       {{question}}
 
 
       Return exactly 3 bullet points as a plan.
   """).strip(),
)
 
 
answer_prompt = Prompt(
   name="hf_answer_prompt",
   prompt=textwrap.dedent("""
       You answer based only on the given context.
 
 
       Context:
       {{context}}
 
 
       Question:
       {{question}}
 
 
       Plan:
       {{plan}}
 
 
       Answer the question in 2–4 concise sentences.
   """).strip(),
)
 

Минимальное хранилище документов и функция поиска

Соберите небольшой набор документов и реализуйте функцию извлечения контекста, которую Opik будет отслеживать как инструмент. Это имитирует RAG-подход без внешней векторной базы.

DOCS = {
   "overview": """
       Opik is an open-source platform for debugging, evaluating,
       and monitoring LLM and RAG applications. It provides tracing,
       datasets, experiments, and evaluation metrics.
   """,
   "tracing": """
       Tracing in Opik logs nested spans, LLM calls, token usage,
       feedback scores, and metadata to inspect complex LLM pipelines.
   """,
   "evaluation": """
       Opik evaluations are defined by datasets, evaluation tasks,
       scoring metrics, and experiments that aggregate scores,
       helping detect regressions or issues.
   """,
}
 
 
@track(project_name=PROJECT_NAME, type="tool", name="retrieve_context")
def retrieve_context(question: str) -> str:
   q = question.lower()
   if "trace" in q or "span" in q:
       return DOCS["tracing"]
   if "metric" in q or "dataset" in q or "evaluate" in q:
       return DOCS["evaluation"]
   return DOCS["overview"]
 

Трассируемые функции пайплайна

Обёрните ключевые компоненты пайплайна декораторами Opik, чтобы каждая функция, спаны и вызовы LLM фиксировались и отображались в дашборде Opik.

@track(project_name=PROJECT_NAME, type="llm", name="plan_answer")
def plan_answer(context: str, question: str) -> str:
   rendered = plan_prompt.format(context=context, question=question)
   return hf_generate(rendered, max_new_tokens=80)
 
 
@track(project_name=PROJECT_NAME, type="llm", name="answer_from_plan")
def answer_from_plan(context: str, question: str, plan: str) -> str:
   rendered = answer_prompt.format(
       context=context,
       question=question,
       plan=plan,
   )
   return hf_generate(rendered, max_new_tokens=120)
 
 
@track(project_name=PROJECT_NAME, type="general", name="qa_pipeline")
def qa_pipeline(question: str) -> str:
   context = retrieve_context(question)
   plan = plan_answer(context, question)
   answer = answer_from_plan(context, question, plan)
   return answer
 
 
print("Sample answer:\n", qa_pipeline("What does Opik help developers do?"))
 

Так вы объединяете извлечение, планирование и ответ в полностью трассируемый QA-пайплайн.

Создание датасета в Opik

Создайте датасет и заполните его вопросами и эталонными ответами, которые будут использоваться в оценке.

client = Opik()
 
 
dataset = client.get_or_create_dataset(
   name="HF_Opik_QA_Dataset",
   description="Small QA dataset for HF + Opik tutorial",
)
 
 
dataset.insert([
   {
       "question": "What kind of platform is Opik?",
       "context": DOCS["overview"],
       "reference": "Opik is an open-source platform for debugging, evaluating and monitoring LLM and RAG applications.",
   },
   {
       "question": "What does tracing in Opik log?",
       "context": DOCS["tracing"],
       "reference": "Tracing logs nested spans, LLM calls, token usage, feedback scores, and metadata.",
   },
   {
       "question": "What are the components of an Opik evaluation?",
       "context": DOCS["evaluation"],
       "reference": "An Opik evaluation uses datasets, evaluation tasks, scoring metrics and experiments that aggregate scores.",
   },
])
 

Задача оценки и метрики

Выберите метрики и определите задачу оценки, которая прогоняет пайплайн по элементам датасета и возвращает результат для подсчёта очков.

equals_metric = Equals()
lev_metric = LevenshteinRatio()
 
 
def evaluation_task(item: dict) -> dict:
   output = qa_pipeline(item["question")]
   return {
       "output": output,
       "reference": item["reference"],
   }
 

Запуск эксперимента и агрегация результатов

Запустите evaluate для выполнения полного эксперимента. Для стабильности в интерактивной среде выполняйте последовательно.

evaluation_result = evaluate(
   dataset=dataset,
   task=evaluation_task,
   scoring_metrics=[equals_metric, lev_metric],
   experiment_name="HF_Opik_QA_Experiment",
   project_name=PROJECT_NAME,
   task_threads=1,
)
 
 
print("\nExperiment URL:", evaluation_result.experiment_url)
 

После завершения получите ссылку на эксперимент и агрегируйте метрики для анализа производительности.

agg = evaluation_result.aggregate_evaluation_scores()
 
 
print("\nAggregated scores:")
for metric_name, stats in agg.aggregated_scores.items():
   print(metric_name, "=>", stats)
 

Наблюдения

Этот пример показывает компактную, но полноценную экосистему оценки LLM, полностью запущенную локально и инструментированную с помощью Opik. Трассировка, структурированные подсказки, управляемый датасет и явные метрики дают прозрачное, измеримое и воспроизводимое представление о поведении пайплайна и качестве ответов.

🇬🇧

Switch Language

Read this article in English

Switch to English