AWS 기술 블로그

Amazon ECS와 AWS Fargate를 사용하여 AWS CDK Python으로 Langfuse 호스팅하기

인공지능, 특히 대형 언어 모델(LLM)의 개발 및 배포 분야에서 Langfuse는 혁신적인 플랫폼으로 부상하고 있습니다. Langfuse는 개발팀이 공동으로 LLM 애플리케이션을 디버깅하고, 분석하며, 반복 개선을 할 수 있도록 도와주는 오픈 소스 LLM 엔지니어링 플랫폼입니다. 이 블로그 포스팅에서는 AWS Cloud Development Kit (CDK)를 활용하여 Amazon Elastic Container Registry (ECR)Amazon Elastic Container Service (ECS)AWS Fargate를 사용하여 Langfuse를 배포하는 방법을 소개하고자 합니다.

Langfuse의 주요 기능 및 해결 문제

Langfuse를 사용해서 LLM 애플리케이션 개발 및 운영상의 여러 중요한 문제를 해결할 수 있습니다.

  • 관찰 가능성 및 디버깅: LLM 애플리케이션 내의 모든 관련 데이터 포인트와 상호 작용을 캡처하는 포괄적인 추적 도구를 제공하여 복잡하고 반복적이며 연쇄적(chain)이거나 에이전트(Agent) 기반 호출에서 문제의 근본 원인을 파악할 수 있습니다. Python 및 JavaScript/TypeScript용 비동기 SDK와 OpenAI SDK, Langchain, LlamaIndex와 같은 인기 있는 프레임워크(Framework)에 대한 통합을 제공합니다.
  • 프롬프트 관리: 프롬프트를 원활하게 관리, 버전 관리 및 배포할 수 있습니다. 성능을 개선하기 위해 프롬프트를 테스트하고 반복할 수 있는 LLM 플레이그라운드(Playground)를 제공합니다.
  • 분석 및 비용 최적화: LLM 비용, 지연 시간 및 품질과 같은 주요 메트릭(Metric)을 추적합니다. 직관적인 대시보드와 데이터 내보내기를 통해 심층 분석을 제공하여 LLM 애플리케이션의 리소스가 많이 사용되는 부분을 식별하고 비용 절감 노력을 목표로 합니다.
  • 품질 모니터링 및 평가: 품질을 더 면밀히 측정할 수 있도록 프로덕션 추적에 점수를 부여할 수 있으며, 모델 기반 평가, 사용자 피드백 수집 및 수동 주석을 지원합니다.
  • 실험 및 테스트: 새로운 버전을 배포하기 전에 애플리케이션 동작을 추적하고 테스트할 수 있습니다. 예상 입력-출력 쌍을 테스트하고 성능을 벤치마킹하기 위한 데이터 세트를 지원합니다.
  • 사용자 행동 분석: 입력을 분류하고 사용자 행동을 심층 분석하여 LLM 애플리케이션의 다양한 입력과 사용자 의도를 이해하는 데 도움이 됩니다.

Langfuse을 Amazon ECS에 배포 하기

AWS CDK는 인프라를 코드화하여 관리할 수 있는 Infrastructure as Code (IaC) 도구로, 클라우드 리소스를 프로그래밍 방식으로 정의하고 프로비저닝할 수 있습니다. Amazon ECS는 컨테이너 애플리케이션을 쉽게 배포, 관리 및 확대할 수 있도록 도와주는 완전 관리형 컨테이너 오케스트레이션 서비스(managed container orchestration service)입니다.

AWS CDK를 이용해서 Langfuse를 Amazon ECS에 아래와 같은 아키텍처를 구성하는 방법을 설명하겠습니다.

[그림 1.] Langfuse를 AWS ECS Fargate에 배포한 아키텍처

CDK 프로젝트 배포 순서는 다음과 같습니다.

  1. CDK 프로젝트 환경 설정
  2. CDK 컨텍스트 (cdk.contex.json) 구성
  3. 배포

1. CDK 프로젝트 환경 설정

Langfuse CDK 프로젝트 리포지토리는 표준 Python 프로젝트로 구조화되어 있습니다. CDK 프로젝트에는 CDK 명령어로 앱(App)을 실행하는 방법을 지시하는 설정 파일, cdk.json이 포함되어 있습니다.

CDK Python 앱을 실행하기 위해서 Python 가상 환경(.venv 디렉토리)을 설정합니다.

가상 환경 생성 및 활성화:

MacOS 및 Linux의 경우:

$ python3 -m venv .venv
$ source .venv/bin/activate

Windows의 경우:

% .venv\Scripts\activate.bat

Python 패키지 설치:

(.venv) $ pip install -r requirements.txt

2. CDK 컨텍스트(Context) 구성

cdk.context.json 파일은 CDK 애플리케이션에서 사용되는 문맥 정보 (Context)를 키-값(Key-Value) 형식으로 저장하고 파일 입니다. Langfuse 배포에 필요한 설정들을 아래 예제와 같이 cdk.context.json 파일에 저장합니다.

{
  "db_cluster_name": "langfuse-db",
  "ecs_cluster_name": "langfuse-cluster",
  "ecs_service_name": "langfuse-alb-service",
  "image_version": "latest",
  "langfuse_env": {
    "NODE_ENV": "production",
    "NEXTAUTH_SECRET": "mysecret",
    "SALT": "mysalt",
    "TELEMETRY_ENABLED": "true",
    "NEXT_PUBLIC_SIGN_UP_DISABLED": "false",
    "LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES": "true"
  }
}

cdk.context.json 파일에 포함된 주요 속성들에 대해 설명 드리자면:

  1. db_cluster_name: Langfuse 애플리케이션에서 사용할 PostgreSQL 데이터베이스 클러스터의 이름을 지정합니다.
  2. ecs_cluster_name: Amazon ECS 클러스터의 이름을 정의합니다. 이 클러스터는 Langfuse 애플리케이션을 호스팅하는 데 사용됩니다.
  3. ecs_service_name: Amazon ECS Service의 이름을 지정합니다. 이 서비스는 Application Load Balancer(ALB)와 함께 사용되어 Langfuse 애플리케이션을 실행합니다.
  4. image_version: 배포할 Langfuse 도커 이미지(Docker Image)의 버전을 지정합니다. “latest”는 최신 버전을 사용한다는 의미입니다.
  5. langfuse_env: 이 객체는 Langfuse 애플리케이션의 환경 변수를 설정합니다.
    • NODE_ENV: 애플리케이션이 프로덕션 모드로 실행됨을 나타냅니다. ( developement, production 중 하나의 값을 가질 수 있습니다.)
    • NEXTAUTH_SECRET: NextAuth.js 인증에 사용되는 비밀 키입니다.
    • SALT: 데이터 암호화나 해싱에 사용되는 랜덤 데이터 값 입니다. (솔트(Salt))
    • TELEMETRY_ENABLED: 텔레메트리(Telemetry) 데이터 수집을 활성화합니다.
    • NEXT_PUBLIC_SIGN_UP_DISABLED: 사용자 가입(Sign-up) 기능을 활성화합니다.
    • LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: Langfuse의 실험적 기능을 활성화합니다.

이러한 설정들은 Langfuse 애플리케이션의 배포 및 실행 환경을 구성하는 데 중요한 역할을 합니다. 특히 langfuse_env 객체 내의 환경 변수들은 애플리케이션의 동작을 제어하고 보안 설정을 관리하는 데 사용됩니다.

보안상 중요한 NEXTAUTH_SECRETSALT 값은 실제 배포 시 안전한 방식으로 생성되고 관리되어야 합니다. 이 값들을 생성하기 위해 openssl rand -base64 32 명령어를 사용할 것을 권장합니다.

ℹ️ Langfuse 환경 변수 설정에 대한 자세한 내용은Langfuse Configuring Environment Variables 문서를 참고하세요.

3. 배포

Step 1) CloudFormation 템플릿 생성:

export CDK_DEFAULT_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
export CDK_DEFAULT_REGION=$(curl -s 169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region)
cdk synth --all

Step 2) CDK 스택(Stack) 배포:

cdk deploy --require-approval never --all

Step 3) (선택 사항) CDK 스택 목록 확인:

cdk list

ℹ️ CDK 명령어에 대한 자세한 설명은 AWS CDK CLI Reference에서 확인할 수 있습니다.
ℹ️ AWS CDK는 스택(Stack)이라는 단위로 AWS 리소스와 속성을 정의합니다. 배포 시에는 스택(Stack) 단위로 프로비저닝 됩니다.

Langfuse에서 LLM 애플리케이션을 Tracing하기

Langfuse 배포가 완료되면, Langfuse의 트레이스(Trace) 기능을 이용해서 LLM 애플리케이션의 실행을 추적하고, 분석할 수 있습니다. Langfuse의 트레이스(Trace)는 일반적으로 단일 요청이나 작업을 나타내며, 함수의 전체 입력과 출력 뿐만 아니라 요청에 대한 메타 데이터를 포함합니다.

지금 부터 Langfuse를 통해 LLM 애플리케이션의 첫 트레이스를 생성하고, 분석하는 방법을 간략하게 설명하겠습니다.

Langfuse 접속 URL

Langfuse 웹 애플리케이션에 접근하기 위해서 다음과 같은 AWS CLI 명령어를 이용해서 Langfuse의 URL을 찾습니다:

aws cloudformation describe-stacks --stack-name LangFuseECSAlbFargateServiceStack | \
jq -r '.Stacks[0].Outputs | map(select(.OutputKey == "LoadBalancerDNS")) | .[0].OutputValue'

이 명령어는 CloudFormation 스택의 출력을 조회하여 Langfuse 웹 애플리케이션에 접근할 수 있는 로드 밸런서의 DNS 이름을 반환합니다.

Langfuse에서 새 프로젝트 생성

Langfuse는 LLM 애플리케이션의 개발, 디버깅, 분석, 및 최적화 작업을 프로젝트라는 단위로 구성합니다.
Langfuse에 처음 접속하면 다음과 같은 절차를 통해 새 프로젝트를 생성할 수 있습니다:

  1. Langfuse 계정 생성: Langfuse 웹사이트에서 계정을 생성하거나 로그인합니다.

  2. 새 프로젝트 생성: 로그인 후, 홈 화면에서 “New” 버튼을 클릭하여 새 프로젝트를 생성합니다.
  3. API 자격 증명 생성: 프로젝트 설정에서 “Create API Keys”를 클릭하여 새로운 API 자격 증명을 생성합니다. 이 자격 증명은 LLM 애플리케이션과 Langfuse를 통합하는 데 필요합니다.

Langfuse에 Amazon Bedrock LLM 애플리케이션 호출 로깅(Logging)

Langfuse CDK 프로젝트 리포지토리examples 폴더에 Langfuse와 Amazon Bedrock의 Claude 3 Sonnet을 통합하여 LLM 호출을 로깅하는 예제 Jupyter 노트북(tracing_for_langchain_bedrock.ipynb)이 있습니다.

이 예제를 통해서 Langfuse로 LLM 애플리케이션의 호출을 로깅하는 방법에 대해서 간략하게 설명하겠습니다.

  1. 필요한 패키지 설치:
    pip install langfuse langchain langchain-community langchain-aws
  2. 환경 변수 설정:
    다음과 같이 Langfuse 프로젝트를 위한 환경 변수를 설정합니다:

    import os
    from langfuse.callback import CallbackHandler
    
    os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..."
    os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..."
    os.environ["LANGFUSE_HOST"] = "http://langfu-***-****.{region}.elb.amazonaws.com"

    ℹ️ LANGFUSE_SECRET_KEY, LANGFUSE_PUBLIC_KEY는 Langfuse 프로젝트를 생성할 때 만든 API Keys입니다.

  3. Langfuse Callback Handler 초기화:
    from langfuse.callback import CallbackHandler
    
    # Initialize Langfuse Callback Handler
    langfuse_handler = CallbackHandler()
  4. Amazon Bedrock LLM 모델 초기화:

    import boto3
    from langchain_aws import ChatBedrock as BedrockChat
    
    region = boto3.Session().region_name
    model_kwargs = {
        "max_tokens": 512,
        "temperature": 0,
        "top_p": 0.9
    }
    
    model_id = "anthropic.claude-3-sonnet-20240229-v1:0"
    llm = BedrockChat(
        model_id=model_id,
        region_name=region,
        model_kwargs=model_kwargs
    )
  5. 예제 LLM 애플리케이션 코드
    from langchain.prompts import ChatPromptTemplate
    from langchain.schema import StrOutputParser
    from operator import itemgetter
    
    prompt1 = ChatPromptTemplate.from_template("What is the city {person} is from?")
    prompt2 = ChatPromptTemplate.from_template(
        "What country is the city {city} in? Respond in {language}"
    )
    
    chain1 = prompt1 | llm | StrOutputParser()
    chain2 = (
        {"city": chain1, "language": itemgetter("language")}
        | prompt2
        | llm
        | StrOutputParser()
    )

    이제 LLM 애플리케이션 코드를 실행하면 Langfuse 웹 콘솔에서 생성된 트레이스를 확인할 수 있습니다.

    # Invoke chain with Langfuse callback handler
    result = chain2.invoke(
        {"person": "Obama", "language": "Spanish"},
        config={"callbacks": [langfuse_handler]}
    )
    
    print(result)

트레이스(Trace) 분석

Langfuse에서 생성된 트레이스를 분석하여 LLM 애플리케이션의 성능과 동작을 이해할 수 있습니다.
Langfuse 웹 콘솔에서 Traces 메뉴를 클릭하면, 트레이스 전체 목록을 확인할 수 있습니다.
트레이스 목록에서 분석하고자 하는 LLM 애플리케이션의 트레이스를 클릭하면, 트레이스에 저장된 애플리케이션의 실행 정보를 확인할 수 있습니다.

트레이스는 다음과 같은 정보를 포함합니다:

  • 입력(Input) 및 출력(Output): 함수의 전체 입력과 출력 데이터.
  • 메타데이터(Metadata): 사용자, 세션, 태그 등의 추가 정보.
  • 관찰(Observations): 실행 과정의 개별 단계들을 기록. 이벤트(Event), 스팬(Span), AI 모델의 생성(Generation) 로그 등이 포함됩니다.

지금까지 Langfuse를 Amazon ECS Fargate에 배포하고, Langfuse를 이용해서 LLM 애플리케이션의 동작을 분석하는 방법에 대해서 간략히 살펴봤습니다.

리소스 정리

Langfuse가 더 이상 필요하지 않은 경우, 다음 CDK 명령어를 이용해서 모든 CloudFormation 스택을 삭제할 수 있습니다:

cdk destroy --force --all

결론

이 블로그 포스팅을 통해서 AWS CDK, Amazon ECR, ECS 및 AWS Fargate를 사용하여 Langfuse를 효율적으로 배포할 수 있는 방법을 소개해 드렸습니다. 이제 여러분들도 Langfuse의 강력한 기능을 활용하여 LLM 애플리케이션을 디버깅, 분석 및 최적화할 수 있습니다.

특히, Amazon ECS Fargate에서 Langfuse를 배포하면 LLM 애플리케이션의 전체 효율성, 보안 및 확장성을 향상할 수 있는 여러 가지 이점을 제공받을 수 있습니다:

  • 간소화된 인프라 관리: AWS Fargate는 기본 인프라를 추상화하여 서버 프로비저닝, 스케일링 또는 운영 체제 관리를 걱정하지 않고 애플리케이션 구축 및 배포에 집중할 수 있습니다.
  • 향상된 보안: AWS Fargate는 컨테이너 간의 격리, 안전한 통신 및 세분화된 액세스 제어를 위한 AWS IAM 통합과 같은 내장 보안 기능을 제공합니다.
  • 확장성: AWS Fargate는 수요에 따라 활성 컨테이너 수를 동적으로 조정하여 수동 개입 없이 다양한 부하를 처리할 수 있도록 자동 스케일링을 지원합니다.
  • 비용 효율성: AWS Fargate는 사용한 vCPU 및 메모리 리소스에 대해서만 비용을 청구하는 종량제 가격 모델을 따르며, 과도한 프로비저닝과 관련된 비용을 피할 수 있습니다.
  • 유연성: AWS Fargate는 각 컨테이너에 대해 CPU 및 메모리 리소스를 지정할 수 있으며, Linux 및 Windows 컨테이너를 모두 지원하고 Docker와 같은 다양한 컨테이너화 기술과 원활하게 통합됩니다.
  • 다른 AWS 서비스와의 쉬운 통합: AWS Fargate는 Amazon Elastic Container Registry (ECR), CloudWatch 및 AWS IAM과 같은 다른 AWS 서비스와 원활하게 통합되어 컨테이너 관리를 위한 포괄적인 솔루션을 제공합니다.
  • 로깅 및 가시성: AWS Fargate의 Amazon CloudWatch와의 통합은 강력한 로깅 및 가시성 기능을 제공하여 실시간 모니터링 및 문제의 신속한 식별 및 해결을 가능하게 합니다.

참고 자료

Sungmin Kim

Sungmin Kim

김성민님은 AWS의 솔루션즈 아키텍트 입니다. Startup 고객들과 협력하여 비즈니스 성과를 실현하는데 도움을 드리고 있습니다.