[DL] LangChain 기초 사용법

Minjeong Kim·2026년 1월 7일

인공지능

목록 보기
41/50

📢 LangChain 기초 실습 및 여러 기능들에 대한 페이지입니다.

Prompt Template 만들기

프롬프트 작성 원칙

  • 프롬프트: LLM 모델에게 입력하는 명령어
  • 모델이 최대한 정확하고 유용한 정보를 제공할 수 있도록 효과적인 프롬프트 작성하는 것이 매우 중요
  1. 명확성, 구체성
    • 질문은 명확하고 구체적이어야 함
  2. 배경 정보 포함
    • 모델이 문맥을 이해할 수 있도록 필요한 배경 정보를 제공 → 환각 줄일 수 있음
  3. 간결성
    • 핵심 정보에 초점을 맞추고, 불필요한 정보는 배제
  4. 페르소나 설정
    • llm 에 역할 부여
    • 예) 너는 ‘인공지능 전문가야’ 등
  5. 문체, 언어
    • 대화의 맥락에 맞는 언어와 문체 선택
  6. 예시 작성
    • 명확한 출력 결과를 위하여 예시 제공

프롬프트 템플릿 만들기

LCEL (LangChain Expression Language)

  • 체인을 구성하고 기본적으로 사용하는 방법
  • LangChain 프레임워크에서 LLM 체인을 쉽고 직관적으로 구성하기 위한 문법
  • 파이프라인(|)으로 체인 연결
    • | 기호를 사용하여 체인 연결
    • prompt | LLM 모델 | 출력 parser

PromptTemplate

  • template 지정하겠삼 ~
  • prompt(llm 에 전달되는 명령어)를 미리 구조화하여 간편하게 재사용할 수 있게 도와주는 방법
  • 입력받는 값과 고정된 텍스트를 묶어 유연하게 prompt 를 생성할 수 있도록 도와주는 역할

(예시) 수도 물어보기

  • 순서
    • prompt template 정의 (기본적인 틀 생성)
    • 모델 정의
    • 체인 연결
    • 체인 구동
  • code
    # 수도를 물어보는 템플릿 생성
    from langchain_core.prompts import PromptTemplate
    prompt = PromptTemplate.from_template('{country}의 수도는 어디야?')
    
    # 모델 생성
    from langchain_openai import ChatOpenAI
    llm = ChatOpenAI()
    
    # 체인 연결
    chain = prompt | llm
    
    # 체인 구동
    chain.invoke({'country':'대한민국'})
    

(예시) 문장 감정 분석

# '{sentence}' 문장의 감정을 분석해줘
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

question = "'{sentence}' 문장의 감정을 분석해줘"
prompt = PromptTemplate.from_template(question)
llm = ChatOpenAI(model='gpt-4o-mini', temperature=1, max_tokens=200)
chain = prompt | llm
chain.invoke({'sentence':'나 어제 늦게 자서 졸리고 힘들어.'})

ChatPromptTemplate

  • 대화형 메시지를 입력으로 사용하고 대화형 메시지를 출력
  • 대화의 맥락을 포함한 메시지를 처리할 때 사용하는 템플릿
  • 대화의 연속성을 고려하여 응답메시지를 생성
  • 역할(role), 내용(content)으로 구성
    • 메시지의 역할과 내용을 기반으로 프롬프트를 구성
      • system_message: 시스템의 기능을 설명 (role 부여)
      • human_message: 사용자의 질문 (content 해당)
chat_prompt = ChatPromptTemplate.from_messages([
    ('system','이 시스템은 여행 전문가입니다.'),
    ('human', '{text} 지역의 맛집에 대해서 작성해줘')
])

(예시) 지역 이름 → 여행 관련 지식, 추천

# template 설정
from langchain_core.prompts import ChatPromptTemplate
chat_prompt = ChatPromptTemplate.from_messages([
    ('system','이 시스템은 여행 전문가입니다.'),
    ('human', '{text}')
])

# model 생성
llm_model = ChatOpenAI(model = 'gpt-4o-mini', temperature=0, max_tokens=1000)

# 체인 생성
travel_chain = chat_prompt | llm_model

# 체인 구동
travel_chain.invoke({'text':'광주 대표 여행지 추천해줘'}).content

다양한 모델들을 활용하여 성능 비교

ChatOpenAI()

# making template
prompt_template = PromptTemplate.from_template('{country}의 수도는 어디야?')

# definition model
llm3_5 = ChatOpenAI(model = 'gpt-3.5-turbo', temperature=0, max_tokens=500)
llm4 = ChatOpenAI(model = 'gpt-4o-mini', temperature=0, max_tokens=500)

# making chain
chain3_5 = prompt_template | llm3_5
chain4 = prompt_template | llm4

# execution chain
print(chain3_5.invoke({'country':'중국'}).content)
print(chain4.invoke({'country':'중국'}).content)

print(chain3_5.invoke({'country':'안드로메다'}).content)
print(chain4.invoke({'country':'안드로메다'}).content)
  • 결과 해석
    • 중국
      • std
        중국의 수도는 베이징(北京)입니다.
        중국의 수도는 베이징(北京)입니다.
      • 모델 3.5 나 4 차이 없음 → 이런 간단한 질문할 때는 3.5 사용하기 (4는 비싸니까)
    • 안드로메다
      • std
        안드로메다 은하의 수도는 안드로메다 1번이라고도 알려진 안드로메다 은하의 중심에 위치한 안드로메다 센터입니다.
        안드로메다 은하에는 실제로 알려진 수도나 도시가 없습니다. 안드로메다는 우리 은하와 가까운 은하 중 하나로, 과학적으로 연구되고 있지만, 그 안에는 생명체나 문명이 존재하는지에 대한 증거는 없습니다. 만약 SF 작품이나 특정 이야기에서 안드로메다의 수도에 대한 설정이 있다면, 그에 대한 정보를 제공해 주시면 더 구체적으로 답변해 드릴 수 있습니다.
      • 모델 3.5 에서는 halluciation (환각) 일어남
      • 모델 4는 비교적 괜찮은 대답을 함!

HuggingFace 모델 연동하여 사용

  • gpt 모델들을 openai api 키를 활용하여 불러 사용 가능
  • ‘LangChain’ 은 OpenAI 전용이 아님!
    • 다양한 LLM 모델들과 함께 사용 가능
  • HuggingFace 에 있는 문장 생성 모델을 활용하여 챗봇 구성
# huggingface 모델을 불러와 연동을 도와주는 라이브러리 설치
!pip install -qU huggingface_hub langchain_huggingface
from langchain_huggingface import HuggingFacePipeline

# model 객체 생성
hf_model = HuggingFacePipeline.from_model_id('gpt2', task='text-generation')
# 한글 모델
hf_model_ko = HuggingFacePipeline.from_model_id('skt/kogpt2-base-v2', task='text-generation')

Streaming 활용 출력

  • 스트리밍: 응답이 생성되는 토큰 단위로 출력 (연속적으로 출력되는 형태)
  • 위 chain 사용
for token in travel_chain.stream({'text':'무등산 등산 코스에 대해 알려줘'}):
  print(token.content, end='')

번역기 생성

  • 한국어를 영어로 번역하는 번역기 생성
# prompt template 생성
from langchain_core.prompts import ChatPromptTemplate
prompt_translation = ChatPromptTemplate.from_messages([
    ('system','너는 번약 전문가야.'),
    ('human','"{text}" 한국어로 된 이 문장을 영어로 번역해줘.')
])

# model 생성
llm_model = ChatOpenAI(model='gpt-4o-mini', temperature=0, max_tokens=1000)

# chain 생성
chain_translation = prompt_translation | llm_model

# chain 구동
human_input = input('번역할 한국어 문장을 입력하세요.')
# chain_translation.invoke({'text':human_input}).content
for token in chain_translation.stream({'text':human_input}):
  print(token.content, end='')
  • std
    번역할 한국어 문장을 입력하세요. 
    저는 한국인입니다.
    "I am Korean."

AI 메시지 사용하기

  • 목적: AI 역할이 포함된 대화흐름을 구성하고 이를 응답에 활용하기 위함
    • c.f.) 앞선 대화 내용을 주입하는 형식이지, LLM 이 새로운 대화를 메모리에 저장하는 것과는 다름!
  • LLM 이 과거의 내용을 기억하여(대화 내용을 문자열로 입력하는 것 O / 메모리 X) 추론에 사용할 수 있도록 문맥을 구성하는 학습 방식
  • 이 방법은 자주 사용하지는 않고, 보통 메모리를 많이 사용함!
ai_role = ChatPromptTemplate.from_messages([
    ('system','너는 다양한 분야에 능통한 AI야.'),
    ('human', '안녕? 오랜만이야.'),
    ('ai', '네 안녕하세요.'),
    ('human', '2+2는 몇이야?'),
    ('ai', '2+2는 4입니다.'),
    ('human', '거기에 1을 더하면?')
])

# 체인 생성
ai_role_chain = ai_role | llm_model

# 체인 구동
print(ai_role_chain.invoke({}).content)
# std: 4에 1을 더하면 5가 됩니다.

메시지 출력 형식 지정하기

  • 질문에 대한 답을 원하는 출력 형식으로 받을 수 있도록 지정하기
# 출력형식 지정하기
prompt_template = ChatPromptTemplate.from_messages([
    ('system', "너는 여행전문가이고 여행지의 맛있는 음식에 대해 전문적으로 대답할 수 있어"),
    ('human', '{question}'),
    ('ai',""" 아래의 형식처럼 답변을 작성해주세요
    ======================
    타이틀
    ======================
    - 응답 1
      - 설명
    - 응답 2
      - 설명
    - 응답 3
      - 설명
    """)
])

# 체인 생성
chain = prompt_template | llm_model

# 체인 구동
print(chain.invoke({'question':'홍대 맛집 추천해줘'}).content)
  • std
    ======================
    홍대 맛집 추천
    ======================
    - 응답 1: **홍대 돈부리**
      - 일본식 덮밥 전문점으로, 다양한 종류의 돈부리를 제공합니다. 신선한 재료와 정성 가득한 조리법으로 맛있는 한 끼를 즐길 수 있습니다. 특히, 매운 소스를 곁들인 매운 돈부리가 인기입니다.
    
    - 응답 2: **마포갈매기**
      - 갈매기살 전문점으로, 고기의 질이 뛰어나고 불판에서 구워 먹는 맛이 일품입니다. 다양한 소스와 함께 제공되는 신선한 채소와 함께 즐기면 더욱 맛있습니다. 분위기도 좋고, 친구들과 함께 가기 좋은 장소입니다.
    
    - 응답 3: **카페 드 파리**
      - 프랑스식 디저트 카페로, 특히 망고 생크림 케이크가 유명합니다. 부드러운 크림과 신선한 과일이 조화를 이루며, 인테리어도 아기자기해 사진 찍기 좋은 장소입니다. 커피와 함께 달콤한 디저트를 즐기기에 안성맞춤입니다

2개 이상의 변수를 템플릿 안에 정의

  • 여행지의 지식을 출력하는 여행 전문자
  • {area} 에서 유명한 {topic} {num}가지 추천해줘.
# 출력형식 지정하기
prompt_template = ChatPromptTemplate.from_messages([
    ('system', "여행지의 지식을 출력하는 여행 전문자"),
    ('human', '{area} 에서 유명한 {topic} {num}가지 추천해줘.'),
    ('ai',""" 아래의 형식처럼 답변을 작성해주세요
    ======================
    타이틀
    ======================
    - 응답 1
      - 설명
    - 응답 2
      - 설명
    - 응답 3
      - 설명
    """)
])

# 체인 생성
chain = prompt_template | llm_model

# 체인 구동
print(chain.invoke({'area':'홍대', 'topic':'디저트', 'num':'5'}).content)

1개 변수에 여러 입력 넣기 (여러 답변 한 번에 받고 싶은 경우)

  • 한 개의 변수에 2개 이상의 값을 넣고 싶을 때
  • batch() : invoke 대신 사용하여 1개의 변수에 여러개의 값을 전달
prompt = PromptTemplate.from_template('{country}의 {topic}은 뭐야?')
chain = prompt | llm_model

input_list = [{'country':'한국', 'topic':'수도'}, {'country':'스웨덴', 'topic':'시간'}, {'country':'폴란드', 'topic':'대통령'}]
result = chain.batch(input_list)

for i in result:
  print(i.content)
  • std
    한국의 수도는 서울입니다.
    스웨덴은 중앙유럽 표준시(Central European Time, CET)를 사용하며, UTC+1 시간대에 속합니다. 그러나 여름철에는 중앙유럽 일광절약시간(Central European Summer Time, CEST)으로 전환되어 UTC+2가 됩니다. 일반적으로 3월 마지막 주 일요일부터 10월 마지막 주 일요일까지 일광절약시간이 적용됩니다. 현재 시각을 확인하려면, 현재 UTC 시간을 기준으로 계산하시면 됩니다.
    2023년 기준으로 폴란드의 대통령은 안제이 두다(Andrzej Duda)입니다. 그는 2015년에 처음으로 대통령에 취임하였고, 2020년에 재선에 성공했습니다. 두다는 폴란드의 보수 정당인 법과 정의당(PiS) 소속입니다. 다만, 정치 상황은 변할 수 있으므로 최신 정보를 확인하는 것이 좋습니다.

문서 요약 시스템 만들기

  • 뉴스 기사 50자 이내로 요약하여 출력
prompt = ChatPromptTemplate([
    ('system', '넌 요약 전문가야.'),
    ('human', '뉴스 기사 내용 50자로 요약해줘. {document}'),
    ('ai', """ 아래 형식처럼 대답해줘.
    =================
    뉴스 기사 제목
    =================
    요약 내용 (50자 이내)
    """)
])

chain = prompt | llm_model
for token in chain.stream({'document':input()}):
  print(token.content, end="")
  • std
    =================
    메모리 반도체 투자 전략
    =================
    메모리 반도체는 2026~2027년까지 유망, 조정 시 매수 권장.

데이터 효과적으로 입출력하기

Runnable

  1. RunnablePassthrough

    • 입력받은 값을 그대로 통과시키는 역할
    • 기본적으로 단일 입력 → 단일 출력의 경우 사용하지 않아도 됨
    • 가장 기본적인 형태 (그대로 통과) ← 써도 안써도 그만 ..
    from langchain_core.runnables import RunnablePassthrough
    prompt = ChatPromptTemplate.from_template('{obj}의 주요 기능에 대해서 설명해줘.')
    chain = {'obj' : RunnablePassthrough()} | prompt | llm_model
    result = chain.invoke('사과') # 실제 데이터 형식으로 넣어주면 됨
    result.content
    • std
      사과는 여러 가지 주요 기능과 이점을 가지고 있는 과일입니다. 다음은 사과의 주요 기능에 대한 설명입니다.
      
      1. **영양소 공급**: 사과는 비타민 C, 식이섬유, 항산화 물질(: 플라보노이드) 등이 풍부하여 면역력 강화와 건강 유지에 도움을 줍니다.
      
      2. **소화 개선**: 사과에 포함된 식이섬유는 장 건강에 도움을 주며, 변비 예방과 소화 개선에 기여합니다.
      
      3. **체중 관리**: 사과는 칼로리가 낮고 수분 함량이 높아 포만감을 주기 때문에 체중 관리에 유리합니다.
      
      4. **심혈관 건강**: 사과에 포함된 항산화 물질과 식이섬유는 심혈관 질환의 위험을 줄이는 데 도움을 줄 수 있습니다. 특히, LDL 콜레스테롤 수치를 낮추는 데 기여합니다.
      
      5. **혈당 조절**: 사과는 혈당 지수가 낮아 당뇨병 환자에게도 적합한 과일입니다. 식이섬유가 혈당 상승을 완화하는 데 도움을 줍니다.
      
      6. **항산화 작용**: 사과에 포함된 다양한 항산화 물질은 세포 손상을 방지하고 노화 방지에 기여합니다.
      
      7. **치아 건강**: 사과를 씹는 과정에서 침 분비가 촉진되어 구강 건강에 도움을 줄 수 있습니다. 또한, 사과의 산성 성분이 세균 성장 억제에 기여할 수 있습니다.
      
      이 외에도 사과는 다양한 요리에 활용될 수 있으며, 간편하게 섭취할 수 있는 건강한 간식으로 인기가 높습니다.
  2. RunnableParallel()

    • 여러 개의 chain 을 동시에 실행하여 결과를 dictionary 로 묶어줌
    • 딕셔너리 형태로 입력할 때 딕셔너리 형태로 그대로 넘겨주기 위해 사용 (RAG) → chain 연결용 입력층
    • 같은 입력으로 서로 다른 질문을 받아 결과를 낼 때 사용
    • 예시
      • 입력 키워드: 대한민국
      • 출력: 수도, 면적
    from langchain_core.runnables import RunnableParallel
    
    prompt1 = ChatPromptTemplate.from_template('{capital}의 수도가 어디야?')
    prompt2 = ChatPromptTemplate.from_template('{area}의 면적이 얼마야?')
    chain1 = {'capital': RunnablePassthrough()} | prompt1 | llm_model
    chain2 = {'area': RunnablePassthrough()} | prompt2 | llm_model
    
    combine_chain = RunnableParallel({'capital':chain1, 'area':chain2})
    result = combine_chain.invoke('대한민국')
    result

OutputParser

  • 출력파서
  • 기능: 출력 포맷 설정
  • 종류
    • StrOutputParser(): 결과를 문자열로 반환 ← default
    • JsonOutputParser() : 결과를 json 형태로 반환 (json 약간 dic 형태랑 비슷)
    • CommaSeperatedListOutputParser : csv 로 반환
  1. StrOutputParser()

    from langchain_core.output_parsers import StrOutputParser
    
    prompt_template = ChatPromptTemplate.from_messages([
        ('system', "여행지의 지식을 출력하는 여행 전문자"),
        ('human', '{area} 에서 유명한 {topic} {num}가지 추천해줘.'),
        ('ai',""" 아래의 형식처럼 답변을 작성해주세요
        ======================
        타이틀
        ======================
        - 응답 1
          - 설명
        - 응답 2
          - 설명
        - 응답 3
          - 설명
        """)
    ])
    
    chain = prompt_template | llm_model | StrOutputParser()
    result = chain.invoke({'area':'일본','topic':'디저트','num':'5'})
    print(result)
    • std
      ======================
      일본에서 유명한 디저트 5가지
      ======================
      - 모찌 (Mochi)
        - 찹쌀로 만든 쫄깃한 식감의 디저트로, 다양한 맛과 속재료로 즐길 수 있습니다. 특히, 팥소나 아이스크림을 넣은 모찌가 인기가 많습니다.
      
      - 다이후쿠 (Daifuku)
        - 모찌의 일종으로, 안에 팥소, 과일, 아이스크림 등을 넣어 만든 디저트입니다. 다양한 맛과 색깔로 제공되어 시각적으로도 즐거움을 줍니다.
      
      - 카스테라 (Castella)
        - 포르투갈에서 유래된 일본식 스폰지 케이크로, 부드럽고 촉촉한 식감이 특징입니다. 주로 달콤한 맛으로, 차와 함께 즐기기 좋습니다.
      
      - 파르페 (Parfait)
        - 일본식 아이스크림 디저트로, 아이스크림, 과일, 시리얼, 휘핑크림 등을 층층이 쌓아 만든 화려한 디저트입니다. 다양한 재료로 구성되어 있어 시각적으로도 매력적입니다.
      
      - 센베이 (Senbei)
        - 일본의 전통적인 쌀 과자로, 다양한 맛과 형태로 제공됩니다. 달콤한 맛부터 짭짤한 맛까지 다양하게 즐길 수 있어 간식으로 인기가 많습니다.
      • content 에 대하여 str 형태로 변경하여 출력
      • parser 를 안쓰면 AIMessage 객체로 메타데이터도 다 포함되어서 출력됨 → 그래서 결과.content 를 써야했음
        • but, parser 를 쓰면 문자열 형태로 바로 출력 가능

0개의 댓글