본문 바로가기
프로그램 개발해서 돈벌기/AI

초보자가 오픈 소스 LLM을 이용해서 나만의 챗봇 만들기

by ubmuhan 2024. 1. 2.
반응형

LLM은 Large Language Models의 약자입니다.

보통 Chat GPT를 많이 알고 있습니다. Chat GPT와 오픈 소스 LLM 차이점은 뭘까요?

오픈 소스 LLM은 모델을 다운로드하여 내가 학습을 시키고 내가 원하는 용도로 만들어 쓸 수 있는 자유도가 높습니다.

물론 Chat GPT도 API 형식으로 프로그래밍을 지원합니다. 그러나 질문과 답변 정보가 Open AI 회사에 있게 되겠죠?

그걸 싫어하는 사람들은 자신의 PC나 회사 서버에 설치해서 사용하고 싶어 할 겁니다.

 

그림 1.

 

우선 용어 초보자가 알아야 할 용어들이 있습니다.

 

  1. 생성 AI
    인공지능과 생성 인공지능의 차이점은 무엇일까? 최근까지 인공지능은 대량의 데이터를 분석하고 통찰력 있는 예측을 내리는 데 일반적으로 적용되었습니다. 좀 더 구체적으로 말하면 이를 예측 인공지능(Predictive Artificial Intelligence)이라고 합니다. 생성 인공 지능은 텍스트, 이미지, 오디오 등과 같은 새로운 콘텐츠를 생성하는 데 중점을 둡니다. 텍스트 생성의 경우 ChatGPT 가 일반적인 예이고 이미지 생성의 경우 DALL·E 널리 사용되는 도구입니다. 이 이 블로그에서는 대규모 언어 모델(일명 “LLM”)을 기반으로 하는 텍스트 생성에 중점을 두고 있습니다.

  2. LLM
    LLM(Large Language Models)은 딥 러닝 기계 학습 알고리즘을 사용하여 방대한 양의 텍스트 데이터 세트로 훈련되는 AI 모델입니다. 본질적으로 LLM은 의미 패턴, 사용법 및 유사점을 분석하여 어린이가 말하기를 배우는 방법과 유사하게 인간이 말하고 쓰는 방식을 모방하도록 훈련되었습니다.

    기초적인 대규모 언어 모델은 인터넷의 대규모 텍스트 모음으로 사전 학습되었습니다. LLM이 처음에 훈련받지 않은 정보에 대한 질문에 대답할 수 있도록 하는 두 가지 주요 방법은 미세 조정과 콘텍스트 주입입니다.

    다음은 몇 가지 인기 있는 LLM입니다.
  3. Fine-Tuning and Context Injection
    Fine-tunning은 사전 훈련된 LLM이 새로운 데이터로 재훈련되는 접근 방식입니다. 이 프로세스는 감정 분석 및 향상된 예측 기술과 같은 특정 작업에 대해 LLM을 최적화하는 데 도움이 될 수 있습니다. 모델을 재훈련할 때 신경망의 가중치와 편향은 새 데이터를 사용한 훈련을 기반으로 조정됩니다. 미세 조정의 단점은 비용이 많이 들고 시간이 많이 소요될 수 있으며 모델을 재교육하는 데 상당한 양의 컴퓨팅 성능이 필요하다는 것입니다.

    Context injection은 (in-context learning)은 LLM에 제공되는 프롬프트를 활용하는 데 초점을 맞춘 접근 방식입니다. LLM을 수정하는 대신 관련 컨텍스트가 프롬프트에 주입됩니다. 이를 통해 LLM은 프롬프트에 제공된 콘텍스트를 활용하여 질문에 답할 수 있습니다.

    각 방법에는 고유한 응용 프로그램과 장점이 있지만 초보자에게는 콘텍스트 주입 접근 방식이 선호되는 방법입니다. 
    이 블로그에서는 컨텍스트 주입과 관련된 프로젝트에 중점을 둘 것입니다.

  4. Context Injection 동작 순서 (그림 1.)
    1. LLM이 질문에 답변하길 원하는 구조화된 데이터나 구조화되지 않은 데이터를 수집하세요.
    2. 데이터를 로드(텍스트 로더)하고 토큰화(텍스트 분할기)하여 이 데이터를 처리합니다. 토큰은 기본적으로 길이가 4자인 짧은 문자열입니다. 예를 들어, "generative"라는 단어는 "ge", "n", "erat" 및 "ive"와 같은 토큰으로 분할될 수 있습니다. LLM은 데이터를 토큰으로 처리합니다.
    3. 토큰은 토큰을 임베딩으로 변환하는 임베딩 모델에 공급됩니다. 임베딩은 단어와 문장이 벡터 공간에 표현되는 방식입니다. (자세한 설명은 다음 섹션에서)
    4. 임베딩 모델에서 생성된 벡터는 벡터 데이터베이스에 저장됩니다. 우리의 경우 ChromaDB를 사용하겠습니다.
    5. 이제 흥미로운 부분입니다. 사용자가 질문을 하면 쿼리를 벡터로 변환하고 데이터베이스에서 가장 가까운 벡터를 검색합니다. 기본적으로 이 프로세스는 사용자의 쿼리와 가장 관련성이 높은 텍스트 덩어리를 찾아서 다시 텍스트로 변환합니다.
    6. 사용자의 질문과 관련 텍스트 덩어리(콘텍스트)는 LLM에 제공되는 프롬프트 템플릿에 포함됩니다. 원본 LLM을 수정하지 않고도 모델은 주입된 콘텍스트를 사용하여 쿼리에 대한 인상적인 답변을 제공할 수 있습니다.

  5. 모델과 벡터 데이터베이스 주입
    임베딩 모델은 단어와 문장, 그리고 그 관계를 벡터로 표현할 수 있는 신경망입니다.
    고차원 벡터는 다음과 같습니다: [1, 0.2, 0.6, 2.0, …]

    벡터 저장소(벡터 데이터베이스라고도 함)는 대량의 벡터 데이터를 저장할 수 있습니다. 이러한 데이터베이스는 벡터 검색 및 검색에 최적입니다.
    선택된 임베딩 모델 유형은 컨텍스트 주입 LLM 결과의 품질에 큰 영향을 미칠 수 있습니다. 저 차원 임베딩 모델은 자연어를 벡터로 표현하는 데 정확도가 낮을 ​​수 있기 때문입니다. 이는 사용자의 쿼리와 데이터베이스의 벡터 간의 유사성 검색에 영향을 미칠 수 있습니다. 원하는 결과를 제공하는 것이 무엇인지 확인하기 위해 다양한 임베딩 모델을 시험해 보는 것이 좋습니다.
    Word2Vec과 같은 다양한 임베딩 모델을 사용할 수 있습니다. 이 블로그에서는 1536개의 출력 차원을 갖는 OpenAI의 임베딩 모델 , 즉 "text-embedding-ada-002"를 활용합니다. OpenAI의 임베딩 모델에는 결제*가 필요하다는 점을 명심하세요. 그러나 좋은 소식은 Ada 모델이 제공하는 가장 저렴한 모델이며 우리의 목적에 매우 적합하다는 것입니다.

    *사용량은 임베딩 모델에서 처리되는 토큰 수에 따라 결정됩니다.


    참고: 이 맥락에서 임베딩(embedding)과 벡터(vector)라는 용어는 동일합니다.


  6. LangChain Framework (그림 2.)
    LangChain은 언어 모델을 기반으로 하는 앱을 개발하기 위한 강력한 프레임워크입니다. 여기에는 문서 로더, 벡터 데이터베이스, 대규모 언어 모델 등 LLM 앱의 다양한 측면을 연결하는 데 도움이 되는 많은 도구가 포함되어 있습니다. LangChain은 다양한 LLM과 비정형 또는 정형 데이터 유형을 지원합니다. 또한 LangChain을 활용하여 LLM 챗봇에 필요한 프롬프트 템플릿을 디자인할 것입니다.

그림 2.

 

 

 

 

오픈 소스 LLM을 이용해서 나만의 챗봇 만들기

Google Colab Notebook을 사용하여 챗봇을 구축할 수 있습니다. 예에서는 온라인 향수 회사를 위한 고객 서비스 챗봇을 만들겠습니다. 사용자 정의 데이터를 자유롭게 추가하세요!

이 튜토리얼에서는 HuggingFace 플랫폼에서 "meta-llama/Llama-2–7b-chat-hf" 모델을 사용합니다. Meta의 이 70억 매개변수 모델은 LLaMa-2에 사용할 수 있는 가장 작은 모델입니다. 아직 HuggingFace 계정이 없다면 계정을 만들어야 합니다.

그런 다음 설정 > 액세스 토큰으로 이동합니다. 새 토큰을 만듭니다.

 

Google Colab에서 새 노트북을 만들어 보겠습니다. GPU T4에 대한 런타임을 구성합니다.

 

colab 상단에 그림 3.처럼 "연결 T4"을 클릭합니다. 그러면 그림 4. 와 같이 연결된 화면이 보입니다.

 

그림 3.

 

그림 4.

 

종속 항목을 설치

!pip install -q transformers einops accelerate langchain bitsandbytes
!pip install -qqq openai
!pip install -Uqqq chromadb

 

필수 패키지 로딩

import os
import textwrap

import langchain
import chromadb
import transformers
import openai
import torch

from transformers import AutoTokenizer
from langchain import HuggingFacePipeline
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders.csv_loader import CSVLoader
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate

 

HuggingFace CLI를 통해 로그인

!huggingface-cli login

 

OpenAI API 키를 생성해야 합니다. OpenAI로 계정을 만들어야 합니다. 프로필을 클릭하고 'API 키 보기'로 이동하세요. 여기에서 비밀 API 키를 생성할 수 있습니다. 이 키는 한 번만 볼 수 있으니 바로 복사해 두세요!

OpenAI의 임베딩 모델에 액세스 할 수 있도록 이 OpenAI API 키를 사용하여 환경 변수를 구성

os.environ["OPENAI_API_KEY"] = "INSERT_YOUR_API_KEY"

 

LLaMa-2 7B 모델을 설정하려면 LangChain의 HuggingFace Pipeline을 사용하고 LLM을 초기화해야 합니다. 파이프라인을 구성하려면 모델과 토크나이저를 정의해야 합니다.

#Set up HuggingFace Pipeline with Llama-2-7b-chat-hf model
model = "meta-llama/Llama-2-7b-chat-hf"
tokenizer = AutoTokenizer.from_pretrained(model)
pipeline = transformers.pipeline(
      "text-generation", #task
      model=model,
      tokenizer=tokenizer,
      torch_dtype=torch.bfloat16,
      trust_remote_code=True,
      device_map="auto",
      max_length=1000,
      do_sample=True,
      top_k=10,
      num_return_sequences=1,
      eos_token_id=tokenizer.eos_token_id
)

#LLM intialized in HuggingFace Pipeline wrapper
llm = HuggingFacePipeline(pipeline = pipeline, model_kwargs = {'temperature':0})

 

위 작업은 어느 정도 시간이 걸리므로 기다려야 합니다.

 

이제 데이터를 로드할 수 있습니다. 우리는 맞춤형 지식 베이스에 대한 데이터가 포함된 CSV 파일을 로드하기 위해 LangChain의 CSVLoader를 사용할 것입니다. LangChain은 ExcelLoader용 문서 로더를 지원하지만 단순성을 위해 스프레드시트에 질문과 답변의 짧은 목록을 만들고 이를 CSV 파일(그림 5.)로 변환합니다.

 

그림 5.

 

 

Google Colab Notebook에서 왼쪽에 있는 파일 아이콘을 클릭하고 CSV 파일을 업로드하세요. 업로드한 파일을 마우스 오른쪽 버튼으로 클릭하고 파일 경로를 복사하세요. 이제 LangChain의 CSVLoader를 사용하여 로컬 파일 경로를 제공함으로써 CSV 파일을 로드할 수 있습니다. 로드된 CSV 파일의 첫 번째 행 출력을 인쇄하여 데이터가 어떻게 보이는지 확인할 수도 있습니다.

# Load documents locally as CSV
loader = CSVLoader('YOUR_CSV_FILE_PATH')
docs = loader.load()
docs[0]

#Output: 
#Document(page_content='\ufeffQuestion: What types of fragrances do you offer in perfumes?\nAnswer: We sell exotic Indian fragrances, Earthy, Herbal & Spicy Fragrances, Fresh And Floral Fragrances, Specialty Fragrances, Musk & Amber Fragrances, and Warm & Woody Fragrances.', metadata={'source': '/content/sample_data/Fragrances-Dataset.csv', 'row': 0})

 

임베딩 모델이 데이터의 벡터 표현을 생성하려면 이를 토큰화해야 합니다. 기본적으로 텍스트를 텍스트 덩어리로 분할합니다.

# Split document into text chunks
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(docs)

 

우리가 사용할 임베딩 모델은 "text-embedding-ada-002"라는 OpenAI의 Ada 모델입니다.

# Initialize the open-source embedding function, default: text-embedding-ada-002
embedding_function = OpenAIEmbeddings()

 

임베딩 모델은 토큰을 벡터 데이터베이스, 즉 오픈 소스 벡터 DB 중에서 널리 사용되는 옵션인 ChromaDB에 저장될 벡터로 변환하는 데 도움이 됩니다. 여기서는 LangChain의 ChromaDB 모듈을 사용하여 임베딩 기능을 사용하여 토큰화된 문서를 처리합니다. 결과 벡터는 ChromaDB에 저장됩니다.

# Load it into ChromaDB
db = Chroma.from_documents(docs, embedding_function)

 

콘텍스트 주입에 중요한 부분은 프롬프트 템플릿입니다. 프롬프트 템플릿을 디자인하는 것은 매우 간단합니다. 이는 LLM에게 특정 인물인 척하라고 말하는 것과 같습니다. 이 경우 LLM에 고객 서비스 담당자 역할을 해야 한다고 알립니다.

다음은 우리가 사용할 프롬프트 템플릿입니다. 사용 사례에 맞게 수정하는 것이 좋습니다.

#Design Prompt Template
template = """You are a customer service chatbot for an online perfume company called Fragrances International.

{context}

Answer the customer's questions only using the source data provided. If you are unsure, say "I don't know, please call our customer support". Use engaging, courteous, and professional language similar to a customer representative.
Keep your answers concise.

Question:

Answer: """

 

LangChain의 PromptTemplate 모듈을 사용하여 템플릿과 콘텍스트를 제공하여 프롬프트를 초기화합니다.

#Intiliaze prompt using prompt template via LangChain
prompt = PromptTemplate(template=template, input_variables=["context"])
print(
    prompt.format(
        context = "A customer is on the perfume company website and wants to chat with the website chatbot."
    )
)

 

이제 모든 구성 요소를 하나로 모았습니다. 문서 Q&A에 최적화된 LangChain의 RetrievalQA 모듈을 사용하겠습니다. 이 모듈은 체인을 사용하고 Q&A를 위해 LLM, 벡터 데이터베이스 및 프롬프트 템플릿과 같은 주요 구성 요소를 함께 제공합니다. 기본적으로 RetrievalQA를 사용하면 유사성 검색을 통해 벡터 DB에서 사용자 쿼리에 가장 가까운 벡터를 검색하고 이를 프롬프트와 함께 LLM에 제공할 수 있습니다.

#Chain to have all components together and query the LLM
chain_type_kwargs = {"prompt": prompt}

chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=db.as_retriever(search_kwargs={"k": 1}),
    chain_type_kwargs=chain_type_kwargs,
)

 

이제 남은 일은 LLM에 쿼리 하는 것뿐입니다! 사용자 정의 기술 자료와 관련된 질문을 해보세요.

# Formatted printing
def print_response(response: str):
    print("\n".join(textwrap.wrap(response, width=80)))

#Running chain through LLM with query
query = "What types of perfumes do you sell?"
response = chain.run(query)
print_response(response)

 

 

원문 블로그

https://medium.com/@alisha3/build-your-first-llm-chatbot-77456438f57b

 

Build Your First LLM Chatbot

A beginner’s guide to Large Language Models, LangChain, Vector DB’s, and more

medium.com

 

구글 Colab 샘플

https://colab.research.google.com/drive/1MRJRPjlhuGOxltMSdJ_VORNZJJsd7Wp3?usp=sharing

 

Medium_Article_LLM_Tutorial.ipynb

Colaboratory notebook

colab.research.google.com

 

결론

블로그에는 LLM을 자체 구축할 때 어떤 모델을 선택하면 할지 그리고 내가 추가로 학습시키는 방법과 도구를 잘 설명되어 있습니다.

colab을 잘 따라가면 더 이해를 잘할 수 있습니다.

반응형

댓글