랭체인 완벽 입문

2024. 4. 20. 14:26·언어모델

https://www.yes24.com/Product/Goods/124922985
책 내용 중 기록하고 싶은 내용을 작성합니다.

1. 챗지피티와 랭체인

기존에는 용도별로 각각의 모델을 준비해야 했지만, GPT는 엄청나게 많은 다양한 종류의 텍스트로 학습해 다양한 작업에 댕응할 수 있는 언어 모델이다.

언어 모델을 크게 두가지로 분류됨

  • Chat : 대화형 상호작용 생성에 특화된 모델
  • Complete : 주어진 텍스트에 이어 텍스트를 생성

모델 별 허용 컨텍스트

  • gpt-3.5-turbo-16k : 16k의 컨텍스트 길이를 처리할 수 있음
  • suffix가 없으면 일반적으로 4k

gpt-3.5-turbo-0613 와 같이 날짜가 suffix로 있는 경우는 특정 버전으로 고정된 것

API 요금은 송신 입력 토큰과 수신 출력 토큰에 모두에 대해 발생함

http://poe.com/ 에서 다양한 언어 모델 사용해보기

RAG(Retrieval-Augmented Generation)

  • 언어 모델이 알지 못하는 정보에 대해 대답하게 함

ReAct(Reasoning and Acting)

  • 추론과 행동을 언어 모델 스스로 판단해 인터넷 검색이나 파일 저장등을 자율적으로 수행

-> 얘네도 랭체은을 통해 쉽게 구현할 수 있음

랭체인에 준비된 6개 모듈

  • Model I/O - 언어 모델을 쉽게 다룰 수 있다.
  • Retrieval - 알 수 없는 데이터를 다룰 수 있다.
  • Memory - 과거의 대화를 장-단기전으로 기억한다.
  • Chains - 여러 프로세스를 통합한다.
  • Agents - 자율적으로 외부와 상호작용해 언어 모델을 한계를 뛰어넘는다.
  • Callbacks - 다양한 이벤트 발생 시 처리한다.

finish_reason

  • Chat 모델의 결과 필드 중 하나
  • 모델이 응답을 종료한 이유를 나타낸다.
  • stop은 자연스러운 끝을 찾은 경우
  • length는 max_tokens에 도달한 경우

2. Model I/O - 언어 모델을 다루기 쉽게 만들기

언어 모델의 활용한 애플리케이션은 좋은 결과를 얻기 위해 시행착오를 거쳐야 함
ex) 아이폰8 출시일을 알려줘라고 했을 때 2017/09/22 로 출력할지, 2017년 9월 22일로 출력할지 알 수 없다. 하지만 yyyy-mm/dd 라는 형식으로 알려주세요 라고 입력하면 원하는 결과를 출력할 수 있다.

Model I/O를 구성하는 3개의 서브 모듈

  • Language Models : 다양한 언어 모델을 동일한 인터페이스에서 호출
  • Prompts : 언어 모델을 호출하기 위한 프롬프트를 구축하는 데 유용한 기능 제공
  • Output parsers : 언어 모델을 통해 받은 결과를 분석해 사용하기 좋게 변환

과거의 응답을 바탕으로 답변하게 하려면 매번 소스코드를 다시 작성해야 하므로 매우 번거로움 -> 상호 작용을 지원하기 위해 Memory 모듈이 준비되어 있음

Language Models에서 크게 두가지 모듈을 지원함

  • Chat Models
  • LLMs (Complete 모델)

Language Models의 편리한 기능

  • 캐싱
    • langchain.llm_cache = InMemoryCache() 와 같이 캐시를 지정하면 동일 입력에 대한 캐싱 로직 동작
      • InMemory는 프로세스에서 동작하므로 휘발됨
      • SQLite도 손쉽게 가능
  • 스트리밍
    • CallBacks 모듈을 통해 동작함 (ChatGPT도 결과를 지속적으로 보여주니 스트리밍을 하고 있다고 볼 수 있을거 같음)

프롬프트 엔지니어링

  • 프롬프트를 최적화하면 단순한 명령어로는 어려웠던 작업을 수행할 수 있게 되거나 더 나은 결과를 얻을 수 있음
  • Templates 모듈이 프롬프트 엔지니어링을 도움

퓨샷 프롬프트

  • 효과가 높다고 알려짐 프롬프트 엔지니어링 기법중 하나
  • Steps
    • 언어 모델을 수행할 작업을 간결하게 지시 (Prompts)
    • 작업의 입력과 출력의 예시를 제시 (Example)
  • langchain.prompts.FewShotPromptTemplate

Output Parser

  • 모델의 출력 형식을 지정
  • 랭체인 제공 Parser도 여러가지가 있지만 사용자 정의 형식도 정의할 수 있음 (Pydantic)

PydanticOutputParser

  • 출력 규칙을 유연하게 정의할 수 있다.
  • 파싱된 데이터의 무결성을 보장할 수 있다.
  • 파싱 결과를 쉽게 처리할 수 있다.

@validator를 통해 검증을 할 수도 있음

-> 검증에 실패하는 경우 에러 발생

-> 이때 OutputFixingParser를 사용해 재시도할 수 있게 지원한다. (링크)

-> max_retries 필드로 몇번 재시도할 지 선택할 수 있음

3. Retrieval - 알지 못하는 데이터를 다루기

Retrieval은 언어 모델이 학습하지 않은 개념이나 정보를 처리할 수 있게 하는 모듈
GPT

    • 학습한 정보 -> 답변 생성
    • 학습하지 않은 정보 -> 답변 생성 X

해결책이 Retrieval

 

답변에 필요한 문장을 찾는 방법이 중요함

    • 검색이 어려운 정보원에 대응하기 위해 텍스트를 벡터화해 검색을 가능하게 함
      텍스트를 벡터화하면 벡터간의 유사도를 구할 수 있음 (cosine 유사도)

어떻게 벡터화하는지가 중요함 -> 여기선 OpenAI의 text-embedding-ada-002 를 사용

from langchain.embeddings import OpenAIEmbeddings
from numpy import dot
from numpy.linalg import norm

embeddings = OpenAIEmbeddings(model="text-embedding-ada-002") # 임베딩 정의

query_vector = embeddings.embed_query("비행 자동차의 최대 속도는?")

document_1_vector = embeddings.embed_query("비행 자동차의 최고 속도는 시속 150km입니다.")
document_2_vector = embeddings.embed_query("내 이름은 철수입니다.")

# query_vector와 서로다른 document vector 간의 유사도 검색
cos_sim_1 = dot(query_vector, document_1_vector) / (norm(query_vector) * norm(document_1_vector))
cos_sim_2 = dot(query_vector, document_2_vector) / (norm(query_vector) * norm(document_2_vector))

print(f"1문장 유사도: {cos_sim_1:.2f}, 2문장 유사도: {cos_sim_2:.2f}")
# 1문장 유사도: 0.92, 2문장 유사도: 0.75

 

RAG를 수행하는 절차

  1. 사전 준비: 여기서 사전은 dictionary를 의미
    문서에서 텍스트를 추출한 뒤 벡터화해서 DB에 저장해야 함
  2. 검색 및 프롬프트 구축
    DB에서 유사학 벡터를 검색해서 가져온 뒤 질문과 조합해서 프롬프트 구성

사전준비
사전준비의 단계

  1. 텍스트 추출 (ex, pdf로 부터 텍스트를 가져옴)
  2. 텍스트 분할 (모델이 처리할 수 있는 텍스트 길이의 한계가 있음)
  3. 텍스트의 벡터화 (아까 했던 것처럼 Embedding 활용)
  4. 텍스트와 벡터를 벡터 DB에 저장 (Chroma DB등 벡터를 저장하기에 특화되어 있는 DB)

검색 및 프롬프트 구축

  1. 사용자의 입력을 벡터화
  2. 해당 벡터를 DB에서 검색해 문장 가져옴
  3. 검색된 문장과 질문을 조합해서 프롬프트 작성
  4. 언어 모델에 입력

임베딩 정의하고 벡터 DB에 넣는 예시

embeddings = OpenAIEmbeddings(model="text-embedding-ada-002") # 임베딩 정의

database = Chroma(persist_directory="data", embedding_function=embeddings) # DB 정의 

database.add_documents(documents) # documents를 임베팅한 뒤 DB에 넣음

그리고 이렇게 준비된 DB에 유사도 검색을 하는 예시

documents = database.similarity_search("비행 자동차의 최고 속도는?")

 

챗봇을 쉽게 만들기 위한 chainlit이라는 라이브러리가 있음

 

RetrievalQA 모듈을 사용하면 RAG를 위해 반복되는 작업을 단순화할 수 있음

4. Memory - 과거의 대화를 장, 단기 기억하기

언어 모델 자체는 Stateless 하다. State를 전달해줘야 한다.
이때 도움이 되는 것이 Memory 모듈이다.

history를 전달하기 위해 다음과 같은 과정이 필요하다

  1. 메모리 내용을 로드
  2. 메모리에서 메시지 가져옴
  3. 메시지에 사용자 메시지 추가
  4. 언어 모델 호출
  5. 결과를 메모리에 저장

랭체인에선 이러한 작동을 쉽게 구현할 수 있는 ConversationChain을 제공한다.

chat = ChatOpenAI(model=<채팅 모델>) # chat을 위한 모델 불러
memory = ConversationBufferMemory()
chain = ConversationChain(memory=memory, llm=chat) # memory와 llm을 chaining

result = chain(message) # 사용자 메시지를 chain에 넣음

위 예시는 버퍼 메모리를 사용해서 프로세스가 죽으면 memory에 있는 대화들은 사라진다.

대화 기록을 저장하기 위한 DB
이 책에선 Redis를 사용한다. Redis를 쉽게 사용하기 위한 방법은 간단히 포스팅해두었다.

Langchain에서 제공하는 RedisChatMessageHistory 모듈을 사용하면 Redis에 대화를 손쉽게 저장 및 관리할 수 있다.
session_id 를 argument로 넣으면 f"message_store:{session}" 와 같이 Redis에 Key가 생성되는 걸 확인했다.

대화가 너무 길어지면 언어 모델을 호출할 수 없음 대응법

  1. ConversationBufferWindowMemory - 오래된 메시지 삭제
  2. ConversationSummaryMemory - 대화 요약함 (llm을 인자로 넣어야 함)

5. Chains - 여러 프로세스를 통합

일련의 처리를 하나의 묶음으로 처리할 수 있는 모듈
(앞서 사용했던 ConversationChain도 Chain 중 하나)

여러개의 체인을 순서대로 실행할 수도 있음

특정 URL에 접속해서 정보를 가져와 그 정보를 바탕으로 답변을 생성할 수 있는 LLMRequestsChain도 있음

언어 모델한테 복수개의 작업을 실행 시키면 그 결과가 안정적이지 못할 수 있다. 이때 SimpleSequentialChain을 사용해 작업을 분할해서 순서대로 실행하도록 할 수 있다.

'언어모델' 카테고리의 다른 글
  • LangChain으로 똑똑한 Slack bot 만들기 (RAG)
  • Langchain으로 쉽게 크롤링하기
  • Langchain의 Memory로 Llama2를 더 독똑하게 만들기
  • 로컬 환경에 Llama 2 실행 및 LangChain으로 애플리케이션 개발
ssuwani
ssuwani
  • ssuwani
    Oops!!
    ssuwani
  • 전체
    오늘
    어제
    • 분류 전체보기 (69)
      • MLOps (19)
      • 데이터 엔지니어링 (4)
      • Kubernetes (5)
      • Kafka (10)
      • 📚책 (3)
      • 라즈베리파이 (1)
      • ETC (8)
      • Python (6)
      • 언어모델 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    태그2
    Kubernetes
    FastAPI
    Python
    producer
    datadrift
    Schema Registry
    Spark
    auto tagging
    Prometheus
    topic
    Kafka
    LLM
    Docker
    asyncronous
    BentoML
    gcp
    태그1
    LangChain
    Confluent Cloud
    Github Actions
    RDD
    evidently ai
    fluentbit
    consumer
    Airflow
    Kubeflow
    redis
    mlflow
    MLOps
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
ssuwani
랭체인 완벽 입문
상단으로

티스토리툴바