생성형 AI 입문자를 위한 LangChain 기초

2024, Aug 16    

강의 정보

강의 URL : https://inf.run/f5aQg
강사: 오승환님
총 수강시간: 1시간 3분
실습파일 : https://github.com/tsdata/langchain-study
실습환경: 코랩
비용 : 강의는 무료이지만, 테스트가 되려면, gpt에 billing을 추가해야 해당 모델을 사용할 수 있다.

학습 목표

  • 랭체인 기본 개념과 사용법 실습
  • rag 기법 이해

선수학습

  • 파이썬
  • 약간의 머신러닝

강의 내용 기반으로 정리했습니다. 궁금한 것들 추가적으로 찾아봐서 정리했습니다.

Q. 기존에도 gpt api에 프롬프트 요청해서 응답을 얻는 것은 가능했던것인데 굳이 랭체인을 사용하는 이유는 무엇인가? 어떤 장점이 있는가?

  • 내 개인 생각으론 멀티 체인과 결과 파싱인 것 같다. 아무래도 결과에서 데이터 뽑아오는 구조가 일반적?이지 못한 부분인데 result.content로 텍스트만 얻을 수 있어서 이런 부분이 좋다.

1. 복잡한 워크플로우 관리

  • 단순히 GPT API에 프롬프트를 보내는 것과 달리, LangChain은 다양한 작업을 순차적으로 또는 병렬로 처리할 수 있는 기능이 있다.
    • 체인(Chains): 예를 들어, 데이터 수집, 전처리, 모델 학습 및 예측과 같은 복잡한 작업을 하나의 체인으로 구성해서 여러 단계의 처리를 하나로 관리할 수 있게 한다.
    • 에이전트(Agents): LangChain은 다양한 에이전트를 제공하여 작업의 흐름을 동적으로 제어할 수 있다.

2. 유연한 프롬프트 관리

  • 프로프트 템플릿(Prompt Templates): 다양한 상황에 맞게 프롬프트를 동적으로 생성할 수 있다.
  • 프롬프트 체인(Prompt Chaining): 여러 프롬프트를 조합하여 복잡한 질문이나 작업을 처리할 수 있다.

3. 다양한 데이터 소스 및 도구와의 통합

  • 데이터 커넥터(Data Connectors): 다양한 데이터베이스, API, 파일 시스템 등과 통합하여 실시간 데이터를 가져오고 활용할 수 있다.
  • 툴(도구) 사용: 예를 들어, 수학적 계산, 정보 검색, 데이터베이스 쿼리 등 다양한 툴을 사용하여 모델의 기능을 확장할 수 있다.

4. 상태 관리 및 메모리 기능

  • 메모리(Memory): 대화 상태와 문맥을 관리할 수 있는 이전 대화 내용을 기억하고 재사용할 수 있는 메모리 기능이 있다.
  • 상태 관리(State Management): 작업의 진행 상황과 결과를 추적하고 관리할 수 있다.

5. 사용자 정의 및 확장성

  • 사용자 정의 체인 및 에이전트: 사용자가 자신의 필요에 따라 체인과 에이전트를 정의하고 사용할 수 있다.
  • 확장 가능한 아키텍처: LangChain은 다양한 기능을 추가하고 확장할 수 있는 유연한 아키텍처를 제공한다.

강의1. 체인에 대한 이해

  • 기본 체인 = Prompt + LLM
    • 3단계 구조 : Prompt Format → LLM or Chat Model Predict → Parse
  • 프롬프트를 받아 llm을 통해 응답을 생성하는 구조
  • 셋팅 구성
    • langchain

        pip install -q langchain langchain-openai tiktoken
      
  • 프롬프트 템플릿 구성 및 기본체인

      from langchain_openai import ChatOpenAI
      from langchain_core.prompts import ChatPromptTemplate
      from langchain_core.output_parsers import StrOutputParser
        
      # prompt + model + ouput parser
      prompt = ChatPromptTemplate.from_template("You car an export in astronomy. Answer the question. <Question>: {input}")
      llm = ChatOpenAI(model = "gpt-3.5-turbo-0125")
      output_parser = StrOutputParser()
        
      # LCEL chaining
      chain = prompt | llm | output_parser
        
      # chain 호춯
      chain.invoke({"input": "지구의 자전 주기는?"})
    
  • 멀티 체인
    • 2개 이상의 체인을 순차적으로 연결 수행
      prompt1 = ChatPromptTemplate.from_template("translates {korean_word} to English.")
      prompt2 = ChatPromptTemplate.from_template("explain {english_word} using oxford dictionary to me in Korean.")
        
      llm = ChatOpenAI(model = "gpt-3.5-turbo-0125")
      chain1 = prompt1 | llm | StrOutputParser()
        
      chain1.invoke({"korean_word": "미래"})
        
      chain2 = (
          {"english_word": chain1}
          | prompt2
          | llm
          | StrOutputParser()
      )
        
      chain2.invoke({"korean_word": "미래"})
    

강의 2. 프롬프트 만들기(PromptTemplate)

  • 핵심은 재사용 가능한 프롬프트 구성
  • 환경 구성

      !pip install -q langchain langchain-openai tiktoken
    

1. PromptTemplate

  • 단일 문자 입력하면 단일문장 출력하는 체인을 사용할때
  • langchaing의 prompttemplate은 문자열 기반이기때문에 문자열 템플릿끼리 결합해서 사용할 수 있다.

      from langchain_core.prompts import PromptTemplate
        
      # name과 age라는 두개의 변수를 사용하는 프롬프트 템플릿을 정의
      template_text = "안녕하세요. 제이름은 {name}이고, 나이는 {age}살입니다."
        
      # PromptTemplate 인스턴스를 생성
      prompt_template = PromptTemplate.from_template(template_text)
        
      # 템플릿에 값을 채워서 프롬프트를 완성
      filled_prompt = prompt_template.format(name="홍길동", age=30)
      filled_prompt
        
      combined_prompt = (
          prompt_template
          + PromptTemplate.from_template("아버지를 아버지라 부를 수 없습니다.")
          + " {language}로 번역해주세요."
      )
        
      combined_prompt
    

2. 챗 프롬프트 템플릿(ChatPromptTemplate)

  • 대화형 상황에서 여러 메시지 입력을 기반으로 단일 메시지로 된 응답을 생성할 때 사용
  • 대화형 모델이나 챗봇 개발에 주로 사용
  • 구성 : 각 채팅 메시지는 역할과 내용이 짝을 이루는 형태
  • ChatPromptTemplates + ChatModels
  • 메시지 구성방법
    • 1안) 튜플 활용

        from langchain_core.prompts import ChatPromptTemplate
              
        chat_prompt = ChatPromptTemplate.from_m
        	essages(
            [
                ("system", "이 시스템은 천문학 질문에 답변할 수 있습니다."),
                ("user", "{user_input}"),
            ]
        )
              
        messages = chat_prompt.format_messages(user_input="태양계에서 가장 큰 행성은 무엇인가요?")
        messages
              
        chain = chat_prompt | llm | StrOutputParser()
              
        chain.invoke({"user_input": "태양계에서 가장 큰 행성은 무엇인가요?"})
      
    • 2안) MessagePromptTemplate 활용

      • 역할에 따른 SystemMessagePromptTempate, HumanMessagePromptTemplate, AiMessagePromptTemplate 등등이 있다.
        from langchain_core.prompts import SystemMessagePromptTemplate, HumanMessagePromptTemplate
              
        chat_prompt = ChatPromptTemplate.from_messages(
            [
                SystemMessagePromptTemplate.from_template("이 시스템은 천문학 질문에 답변할 수 있습니다."),
                HumanMessagePromptTemplate.from_template("{user_input}")
            ]
        )
              
        messages = chat_prompt.format_messages(user_input="태양계에서 가장 큰 행성은 무엇인가요?")
        messages
      

강의3. llm 모델 구조

  • 랭체인 모델 유형
    • llm, chat model 클래스 두개의 모델이 있다.

1. llm

  • llm은 단일 질문에 대한 복잡한 출력을 생성
  • 광범위한 언어 이해 및 텍스트 생성 작업에 사용
from langchain_openai import OpenAI

llm = O

penAI()

llm.invoke("한국의 대표적인 관광지 3군데를 추천해주세요.")

2. chat model

  • 연속적으로 대화하는 형태의 상호작용
  • 여러개의 메시지를 입력으로 받아서 하나의 메시지를 반환하는 대화형 상황에 최적화

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

chat = ChatOpenAI()

chat_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "이 시스템은 여행 전문가입니다."),
        ("user", "{user_input}"),
    ]
)

chain = chat_prompt | chat
chain.invoke({"user_input" : "안녕하세요? 한국의 대표적인 관광지 3군데 추천해주세요."})

강의4. llm 모델 튜닝

  • 모델 파라미터 설정
    • temperature : 값이 크면 다양하고 예측이 어려운 출력이 생성.
  • 설정 시점
    • 방법1) 모델 인스턴스 생성할때 설정값을 인자로 전달하는 방법
    • 방법2) 모델에 직접 파라미터를 전달(모델 호출 시점)

        model.invoke(input=question, **params)
      
    • 방법3) 모델에 추가적인 파라미터 전달
      • bind메서드를 통해서 새로운 파라미터 전달

          chain = prompt | model.bind(max_tokens=10)
        

강의5. RAG 기법 이해

  • rag란?
    • llm을 확장해서, 더욱 정확하고 풍부한 정보를 제공하는 기법으로 모델에 포함되지 않은 외부데이터를 실시간으로 검색하고 리를 기반으로 답변 생성하는 과정으로, 환각을 방지할 수 있다.
    • 실시간 정보가 반영되는 장점이 있다.
    • rag에선 환각 방지 위해 temperatur를 낮춘다.
  • 기본 구조
    • 검색단계 → 생성단계
    • 파이프라인
      • load data → text split → indexing → retrieval → generation
!pip instal

l -q la

ngchain langchain-openai tiktoken chromadb

## 
import langchain

langchain.__version__

## 1. Data load
from langchain_community.document_loaders import WebBaseLoader

# 위키피디아 정책과 지침
url = 'http://...'
loader = WebBaseLoader(url)

# 웹페이지 텍스트 -> Documents
docs = loader.load()

## Text split

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)

## Indexing (texts -> embedding -> store)

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings

vectorstore = Chroma.from_document(documents = splits, embedding=OpenAIEmbeddings())

docs = vectorstore.similarity_search("격하 과정에 대해서 설명해주세요)")

## Retrieval - Generation
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

# Prompt
template = ''' Answr the question based only on the following context:
[context]

Question: {question}
'''

prompt = ChatPromptTemplate.from_template(template)

# LLM
model = ChatOpenAI(model='gpt-3.5-turbo-0125', temperature=0)

# Retriever
retriever = vectorstore.as_retriever()

# Combine Documents
def format_docs(docs):
  return '\n\n'.join(doc.page_content for doc in docs)

# Rag Chain 연결
rag_chain = (
    {'context': retriever | format_docs, 'question': RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)

# Chain 실행
rag_chain.invoke("격하 과정에 대해서 설명해주세요.")