많은 LLM 애플리케이션은 사용자와 LLM 애플리케이션이 다중 턴 대화를 나누는 챗봇과 같은 인터페이스를 가지고 있습니다. 이러한 대화를 추적하기 위해 LangSmith의 Threads 기능을 사용할 수 있습니다.

Trace를 thread로 그룹화하기

Thread는 단일 대화를 나타내는 trace의 시퀀스입니다. 각 응답은 자체 trace로 표현되지만, 이러한 trace들은 동일한 thread의 일부로서 함께 연결됩니다. Trace를 함께 연결하려면 해당 thread의 고유 식별자를 값으로 하는 특별한 metadata 키를 전달해야 합니다. 키 이름은 다음 중 하나여야 합니다:
  • session_id
  • thread_id
  • conversation_id.
값은 원하는 문자열이 될 수 있지만, f47ac10b-58cc-4372-a567-0e02b2c3d479와 같은 UUID를 사용하는 것을 권장합니다. Trace에 metadata를 추가하는 방법은 이 가이드를 확인하세요.

예제

이 예제는 장기 실행 채팅을 유지하기 위해 구조화된 메시지 형식을 사용하여 대화 기록을 로깅하고 검색하는 방법을 보여줍니다.
import os
from typing import List, Dict, Any, Optional

import openai
from langsmith import traceable, Client
import langsmith as ls
from langsmith.wrappers import wrap_openai

# Initialize clients
client = wrap_openai(openai.Client())
langsmith_client = Client()

# Configuration
LANGSMITH_PROJECT = "project-with-threads"
THREAD_ID = "thread-id-1"
langsmith_extra={"project_name": LANGSMITH_PROJECT, "metadata":{"session_id": THREAD_ID}}

# gets a history of all LLM calls in the thread to construct conversation history
def get_thread_history(thread_id: str, project_name: str):
    # Filter runs by the specific thread and project
    filter_string = f'and(in(metadata_key, ["session_id","conversation_id","thread_id"]), eq(metadata_value, "{thread_id}"))'
    # Only grab the LLM runs
    runs = [r for r in langsmith_client.list_runs(project_name=project_name, filter=filter_string, run_type="llm")]

    # Sort by start time to get the most recent interaction
    runs = sorted(runs, key=lambda run: run.start_time, reverse=True)

    # Reconstruct the conversation state
    latest_run = runs[0]
    return latest_run.inputs['messages'] + [latest_run.outputs['choices'][0]['message']]


@traceable(name="Chat Bot")
def chat_pipeline(messages: list, get_chat_history: bool = False):
    # Whether to continue an existing thread or start a new one
    if get_chat_history:
        run_tree = ls.get_current_run_tree()
        # Get existing conversation history and append new messages
        history_messages = get_thread_history(run_tree.extra["metadata"]["session_id"], run_tree.session_name)
        all_messages = history_messages + messages
        # Include the complete conversation in the input for tracing
        input_messages = all_messages
    else:
        all_messages = messages
        input_messages = messages

    # Invoke the model
    chat_completion = client.chat.completions.create(
        model="gpt-4o-mini", messages=all_messages
    )

    # Return the complete conversation including input and response
    response_message = chat_completion.choices[0].message
    return {
        "messages": input_messages + [response_message]
    }

# Format message
messages = [
    {
        "content": "Hi, my name is Sally",
        "role": "user"
    }
]
get_chat_history = False

# Call the chat pipeline
result = chat_pipeline(messages, get_chat_history, langsmith_extra=langsmith_extra)
몇 초 기다린 후, 다음 호출을 통해 대화를 계속할 수 있습니다. get_chat_history=True,/getChatHistory: true를 전달하면 중단된 지점부터 대화를 계속할 수 있습니다. 이는 LLM이 최신 메시지에만 응답하는 대신 전체 메시지 기록을 받아 응답한다는 것을 의미합니다.
# Continue the conversation.
messages = [
    {
        "content": "What is my name?",
        "role": "user"
    }
]
get_chat_history = True

chat_pipeline(messages, get_chat_history, langsmith_extra=langsmith_extra)
대화를 계속 진행하세요. 과거 메시지가 포함되어 있으므로 LLM은 대화를 기억할 것입니다.
# Continue the conversation.
messages = [
    {
        "content": "What was the first message I sent you?",
        "role": "user"
    }
]
get_chat_history = True

chat_pipeline(messages, get_chat_history, langsmith_extra=langsmith_extra)

Thread 보기

프로젝트 세부 정보 페이지의 Threads 탭을 클릭하여 thread를 볼 수 있습니다. 그러면 가장 최근 활동순으로 정렬된 모든 thread 목록이 표시됩니다.
Thread 테이블을 보여주는 LangSmith UI.

Thread 보기

특정 thread를 클릭할 수 있습니다. 그러면 해당 thread의 기록이 열립니다.
Thread 테이블을 보여주는 LangSmith UI.
Thread는 두 가지 방식으로 볼 수 있습니다: 페이지 상단의 버튼을 사용하여 두 뷰 간에 전환하거나 키보드 단축키 T를 사용하여 두 뷰 간에 토글할 수 있습니다.

Thread overview

Thread overview 페이지는 대화의 각 턴에 대한 입력과 출력을 볼 수 있는 챗봇과 같은 UI를 보여줍니다. Configure 버튼을 클릭하여 overview에 표시되는 입력 및 출력의 필드를 구성하거나 여러 필드를 표시할 수 있습니다. 입력 및 출력에 대한 JSON path는 음수 인덱싱을 지원하므로 -1을 사용하여 배열의 마지막 요소에 액세스할 수 있습니다. 예를 들어, inputs.messages[-1].contentmessages 배열의 마지막 메시지에 액세스합니다.

Trace view

여기의 trace view는 단일 run을 볼 때의 trace view와 유사하지만, thread의 각 턴에 대한 모든 run에 쉽게 액세스할 수 있습니다.

Feedback 보기

Thread를 볼 때 페이지 상단에 Feedback이라는 섹션이 표시됩니다. 여기에서 thread를 구성하는 각 run에 대한 feedback을 볼 수 있습니다. 이 feedback은 집계되므로, 동일한 기준으로 thread의 각 run을 평가하면 모든 run에 걸친 평균 점수가 표시됩니다. 여기에 남겨진 thread 레벨 feedback도 볼 수 있습니다.

Thread 레벨 필터 저장하기

프로젝트 레벨에서 필터를 저장하는 것과 유사하게, thread 레벨에서도 자주 사용하는 필터를 저장할 수 있습니다. Thread 테이블에서 필터를 저장하려면 필터 버튼을 사용하여 필터를 설정한 다음 Save filter 버튼을 클릭하세요. AnnotateOpen trace를 각각 클릭하여 사이드 패널에서 trace를 열거나 주석을 달 수 있습니다.
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I