AI Engineering Academy · Урок

Трассировка с LangSmith

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

Урок 2 из 413 шагов

«Трассировка с LangSmith» — бесплатный урок AI Engineering Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Engineering Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Engineering Academy содержит 4 уроков всего.

Что такое LangSmith

LangSmith — это платформа наблюдаемости, специально созданная для приложений на основе LLM. Она автоматически сохраняет трассировки каждого запуска LangChain — каждого этапа цепочки, вызова LLM, выполнения инструмента, поиска и анализатора результата — и отображает их в иерархическом обозревателе трассировок с поиском. Вы можете фильтровать трассировки по задержке, стоимости, статусу ошибки или пользовательским метаданным, а также повторно запускать любую трассировку для отладки сбоев.

# Install: pip install langsmith
import os

# Set environment variables to enable automatic tracing
os.environ['LANGCHAIN_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_API_KEY'] = 'lsv2_...your_key_here...'
os.environ['LANGCHAIN_PROJECT'] = 'my-rag-app'  # project name in LangSmith UI

# That's all - LangChain now sends traces to LangSmith automatically
# No code changes needed to your chain or agent

Автоматическая трассировка без изменений в коде

Самая привлекательная возможность LangSmith заключается в том, что после задания трёх переменных окружения каждая операция LangChain автоматически трассируется без дополнительного кода. Сохраняются каждая цепочка LCEL, каждый вызов ChatOpenAI, каждый вызов средства поиска и каждое выполнение инструмента — вместе с вводом, выводом, временем выполнения и количеством токенов. Трассировку LangSmith можно развернуть в рабочей среде, изменив всего одну переменную окружения.

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# This chain is automatically traced - no extra code needed
llm = ChatOpenAI(model='gpt-4o')
prompt = ChatPromptTemplate.from_template('Answer this question: {question}')
chain = prompt | llm | StrOutputParser()

# This call creates a trace in LangSmith showing:
# - The formatted prompt (with question substituted)
# - The LLM call with model, temperature, token counts
# - The parsed output
# - End-to-end latency and cost
result = chain.invoke({'question': 'What is RAG?'})
print(result)

Трассировка конвейеров RAG

Для приложений RAG трассировки LangSmith особенно полезны, поскольку они охватывают весь конвейер поиска и последующей генерации. Вы можете увидеть, какие документы были найдены, каковы их оценки сходства, как контекст был оформлен в запросе и что сгенерировала LLM. Благодаря этому сразу становится понятно, был ли неправильный ответ вызван плохим поиском или некачественной генерацией.

from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores import Chroma
from langchain_core.runnables import RunnablePassthrough

embeddings = OpenAIEmbeddings()
vectorstore = Chroma(embedding_function=embeddings)
retriever = vectorstore.as_retriever(search_kwargs={'k': 5})

rag_chain = (
    {'context': retriever, 'question': RunnablePassthrough()}
    | ChatPromptTemplate.from_template('Context: {context}\n\nQuestion: {question}\n\nAnswer:')
    | ChatOpenAI(model='gpt-4o')
    | StrOutputParser()
)

# LangSmith traces EVERY step:
# 1. Retriever: query embedding + vector search + returned documents (with scores)
# 2. Prompt: formatted template with context injected
# 3. LLM: full prompt, response, tokens, latency, cost
# 4. Parser: final string output
answer = rag_chain.invoke('What is the capital of France?')

Добавление метаданных в трассировки

По умолчанию трассировки LangSmith содержат ввод и вывод каждого этапа. Вы можете дополнить трассировки пользовательскими тегами метаданных: идентификатором пользователя, идентификатором сеанса, значениями флагов функций, вариантом A/B-теста или любым другим контекстом, который помогает фильтровать и анализировать трассировки в интерфейсе. Используйте RunnableConfig, чтобы передать метаданные, которые появятся во всех трассировках этого запроса.

from langchain_core.runnables import RunnableConfig

def handle_user_request(user_id: str, query: str, ab_variant: str):
    config = RunnableConfig(
        tags=['production', ab_variant],
        metadata={
            'user_id': user_id,
            'ab_variant': ab_variant,
            'feature': 'rag_qa'
        }
    )
    
    result = rag_chain.invoke(query, config=config)
    return result

# In LangSmith UI you can now:
# - Filter traces by user_id to debug a specific user's issue
# - Compare latency between ab_variant='A' and ab_variant='B'
# - See all traces tagged 'production' vs 'staging'

Создание интервалов вручную

Для кода, который не проходит через LangChain (пользовательские вызовы API, запросы к базам данных, этапы предварительной обработки), можно создавать интервалы вручную, используя клиент LangSmith напрямую. Это гарантирует, что этапы, не относящиеся к LangChain, будут записаны в ту же трассировку, что и этапы LangChain, и даст полное представление о пути выполнения каждого запроса.

from langsmith import Client, traceable

client = Client()

# Decorate functions to auto-trace them
@traceable(name='preprocess_query')
def preprocess_query(raw_query: str) -> str:
    # This step is now traced even though it doesn't use LangChain
    cleaned = raw_query.strip().lower()
    cleaned = ' '.join(cleaned.split())  # normalize whitespace
    return cleaned

@traceable(name='fetch_user_history')
def fetch_user_history(user_id: str) -> list[str]:
    # Database call - also traced
    return db.query('SELECT message FROM chat_history WHERE user_id = ? ORDER BY timestamp DESC LIMIT 5', user_id)

# All three steps appear in the same trace
def handle_request(user_id: str, raw_query: str):
    query = preprocess_query(raw_query)         # traced
    history = fetch_user_history(user_id)       # traced
    result = rag_chain.invoke({'query': query, 'history': history})  # traced by LangChain
    return result

Оценка трассировок в LangSmith

LangSmith включает инфраструктуру оценки, позволяющую запускать средства оценки для набора данных трассировок. Вы можете выбрать набор записанных примеров, запустить автоматизированные средства оценки (в том числе оценщики с LLM в роли судьи для проверки корректности и релевантности) и сравнить результаты разных версий конвейера. Так рабочие трассировки превращаются в цикл обратной связи для улучшения приложения.

from langsmith.evaluation import evaluate, LangChainStringEvaluator

# Create an evaluator that uses an LLM to judge correctness
correctness_evaluator = LangChainStringEvaluator(
    'qa',
    config={'llm': ChatOpenAI(model='gpt-4o')}
)

# Run evaluation against a dataset of traced examples
results = evaluate(
    rag_chain,
    data='my-rag-test-set',      # name of dataset in LangSmith
    evaluators=[correctness_evaluator],
    experiment_prefix='rag-v2-chunking-test'
)

print('Evaluation results:')
print(f'Correctness: {results.results["correctness"].mean():.2f}')
print(f'Average latency: {results.results["latency"].mean():.2f}s')

Создание наборов тестов из трассировок

Одна из самых мощных возможностей LangSmith — способность создавать наборы тестов непосредственно из рабочих трассировок. Заметив интересную трассировку (сбой, крайний случай или отличный пример), Вы можете добавить её в набор данных одним нажатием. Со временем Вы создадите полноценный набор регрессионных тестов на основе реальных пользовательских запросов, а не искусственных примеров.

from langsmith import Client

client = Client()

# Create a dataset from existing traces
dataset = client.create_dataset('rag-regression-tests')

# Add examples from production traces (by trace ID)
for trace_id in failed_trace_ids:
    run = client.read_run(trace_id)
    client.create_example(
        inputs=run.inputs,
        outputs={'answer': run.outputs.get('output', '')},
        dataset_id=dataset.id,
        metadata={'source': 'production_failure', 'date': run.start_time.isoformat()}
    )

print(f'Added {len(failed_trace_ids)} examples to regression test dataset')

Фильтрация и поиск трассировок

В рабочей среде у Вас будут тысячи трассировок. Интерфейс и API LangSmith поддерживают расширенные возможности фильтрации и поиска: можно найти трассировки с задержкой выше порога, определённым типом ошибки, от конкретного пользователя, содержащие определённое ключевое слово в результате или имеющие количество токенов результата выше заданного ограничения. Это упрощает исследование определённых категорий сбоев и мониторинг поведения конкретных пользователей.

from langsmith import Client

client = Client()

# Find slow traces (useful for performance investigation)
slow_runs = client.list_runs(
    project_name='my-rag-app',
    filter='gt(latency, 5)',  # latency > 5 seconds
    limit=20
)

# Find error traces
error_runs = client.list_runs(
    project_name='my-rag-app',
    filter='eq(error, true)',
    limit=50
)

# Find traces from a specific user
user_runs = client.list_runs(
    project_name='my-rag-app',
    filter='has(metadata, user_id="user_abc123")',
    limit=100
)

for run in slow_runs:
    print(f'Slow run: {run.id}, latency: {run.end_time - run.start_time}')

Сравнение экспериментов в LangSmith

LangSmith поддерживает сравнение экспериментов: пропустите один и тот же набор тестов через две версии конвейера (например, с размером фрагмента 500 и 1000), а затем сравните их показатели задержки, стоимости и качества. Это позволяет легко убедиться, что изменение конвейера улучшает систему, а не приводит к регрессии, прежде чем развернуть его в рабочей среде.

from langsmith.evaluation import evaluate

test_dataset = 'my-rag-eval-set'

# Run experiment A: chunk size 500
results_a = evaluate(
    rag_pipeline_v1,
    data=test_dataset,
    evaluators=[correctness_evaluator, relevance_evaluator],
    experiment_prefix='chunk-500'
)

# Run experiment B: chunk size 1000
results_b = evaluate(
    rag_pipeline_v2,
    data=test_dataset,
    evaluators=[correctness_evaluator, relevance_evaluator],
    experiment_prefix='chunk-1000'
)

# Compare in LangSmith UI: Experiments tab shows A vs B side by side
# Or compare programmatically:
print(f'Correctness - v1: {results_a.results["correctness"].mean():.2f}, v2: {results_b.results["correctness"].mean():.2f}')

LangSmith в рабочей среде

LangSmith доступен как размещаемый SaaS-сервис на smith.langchain.com, а также в варианте для самостоятельного размещения. В рабочей среде трассировку можно выполнять асинхронно (без блокировки), чтобы не добавлять задержку в критический путь. Можно также отбирать трассировки (например, трассировать только 10% запросов при высокой нагрузке), контролируя затраты и сохраняя видимость. На панели мониторинга отображаются графики в реальном времени: объём запросов, задержка, стоимость и доля ошибок.

import os

# Production configuration
os.environ['LANGCHAIN_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_ENDPOINT'] = 'https://api.smith.langchain.com'
os.environ['LANGCHAIN_PROJECT'] = 'production'

# Enable async tracing (non-blocking - does not add latency to requests)
os.environ['LANGCHAIN_CALLBACKS_BACKGROUND'] = 'true'

# Optional: sample 10% of traces to reduce cost in high-traffic scenarios
import random

def should_trace() -> bool:
    return random.random() < 0.10  # 10% sampling rate

def handle_request(query):
    config = RunnableConfig()
    if not should_trace():
        config = RunnableConfig(callbacks=[])  # disable tracing for this request
    return rag_chain.invoke(query, config=config)

LangSmith и пользовательское ведение журнала

Вы можете создать собственную систему журналирования трассировок, и для некоторых задач это будет правильным выбором. Преимущества LangSmith по сравнению с пользовательским журналированием: интеграция с LangChain без написания кода, специализированный интерфейс для изучения трассировок LLM (а не универсальные панели Kibana/Grafana), встроенная поддержка оценки и сравнения экспериментов, а также автоматический подсчёт токенов и отслеживание затрат. Компромисс заключается в зависимости от поставщика и затратах при масштабировании.

Быстрая проверка

Проверьте своё понимание трассировки с помощью LangSmith по материалам этого урока.

Итоги урока

В этом уроке Вы узнали, что LangSmith обеспечивает автоматическую сквозную трассировку приложений LangChain: для этого достаточно задать три переменные окружения, не изменяя код; декоратор @traceable расширяет трассировку на этапы, не относящиеся к LangChain, например обращения к базе данных и предварительную обработку; а сравнение экспериментов позволяет проверять улучшения конвейера на тестовом наборе данных до развёртывания. Далее мы рассмотрим Langfuse как альтернативу наблюдаемости, не зависящую от модели.

Можно начать бесплатно

Изучай Python с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
30
Уроки
120

Часто задаваемые вопросы

Урок «Трассировка с LangSmith» бесплатный?

Да — полный текст урока «Трассировка с LangSmith» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Engineering Academy, подпишись на CoddyKit PRO. Курс AI Engineering Academy содержит 4 уроков всего.

Чему я научусь в уроке «Трассировка с LangSmith»?

Оснастите приложение LangChain трассировкой LangSmith, чтобы записывать каждый шаг цепочки, вызов LLM, количество токенов и задержку в доступном для поиска обозревателе трассировок. Ты практикуешь AI Engineering Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать AI Engineering Academy?

Предыдущий опыт не требуется. AI Engineering Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Трассировка с LangSmith»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке AI Engineering Academy?

Да. Каждый урок AI Engineering Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Почему приложения на LLM сложно отлаживать
  2. Трассировка с LangSmith
  3. Langfuse для наблюдаемости, независимой от модели
  4. Оповещения о задержке, расходах и ухудшении качества
← Назад к AI Engineering Academy