티스토리 뷰

반응형

필자는 Openai API를 그다지 좋아하지 않는 편이다.

 

편하지 않다고 하기보다는, 돈이 정말 많이 깨진다. 임베딩도 그렇고, API 호출값도 그렇고.

심지어는 레벨이 높지 않으면 토큰 제한까지 존재한다.

 

그래서 필자는 RAG를 만들 때도 당연히 Ollama와 같은 로컬로 써야 한다고 생각한다. 그러나 애석하게도 AutoRAG 프레임워크는 초보자들을 위해서 기본 Openai API를 쓰게 되어 있다. 그러나 Ollama를 쓰려고 튜토리얼도 없고, 굉장히 험난한 길을 걷게 된다.

 

이 글은 좀 심화용으로, 어느정도 코딩을 알고, AutuRAG를 활용하면서도 돈을 아끼고 싶은 분들에게 추천하는 글 되시겠다.

 

데이터셋 만들 때 Ollama 활용하기

사실 데이터셋 정도는 ChatgptAPI를 활용해도 되지만..그것마저도 아까운 사람들이 있다.

Ollama의 기능은 로컬에서 쓸 수 있다는 장점이 있다. 무엇보다 양자화된 모델을 활용하면서, Huggingface의 모델들도 가져다 쓸 수 있다는 장점이 있기에 자신이 파인튜닝한 모델도 활용해볼 수 있다.

 

ollama에 허깅페이스 모델 추가하기

 

허깅페이스 모델 Ollama에 추가하기 프엔블로그

허깅페이스(HuggingFace) 플랫폼에서 모델을 GGUF 파일 형식으로 다운로드하는 방법을 알아보자. 이렇게 다운로드한 모델을 Ollama에 추가하는 방법에 대해서도 살펴보자. Llama-3-Open-Ko-8B-Instruct-preview

www.propengi.com

 

이 블로그가 그 점에 대해서는 아주 잘 설명해놨다.

 

자, 이제 모델이 준비되었다고 가정하고, Ollama를 한번 써보자.

 

아, 만약 윈도우에서 vscode를 이용한다면 서버를 반드시 켜주는 걸 잊지 말자.

ollama server

 

한국어 데이터셋 예제 : https://github.com/Marker-Inc-Korea/AutoRAG-tutorial-ko

 

GitHub - Marker-Inc-Korea/AutoRAG-tutorial-ko: AutoRAG 한국어 튜토리얼을 위한 레포입니다.

AutoRAG 한국어 튜토리얼을 위한 레포입니다. Contribute to Marker-Inc-Korea/AutoRAG-tutorial-ko development by creating an account on GitHub.

github.com

 

 

기본적으로 데이터셋 예제는 이미 있다.

하지만 ChatgptAPI로 되어 있다.

그럼 Ollama는? LangChain에서 불러와야 하나?

필자가 디버깅 해본 바로는 애초에 불러오는 함수들이 전부 비동기 함수로 되어 있기에 Langchain 거는 못 쓴다.

 

그래서 그냥 Llamaindex에서 Ollama를 불러와야 한다.

코드는 다음과 같다.

import os

import click
import pandas as pd
from dotenv import load_dotenv

from llama_index.llms.ollama import Ollama #ollama를 llama index에서 불러옴
from llama_index.core import Settings
# from llama_index.llms.openai import OpenAI
from autorag.data.qacreation import generate_qa_llama_index, make_single_content_qa

root_path = os.path.dirname(os.path.realpath(__file__))
prompt = """다음은 재정정보와 관련된 PDF 파일의 텍스트입니다. 
텍스트를 보고 할 만한 질문과 답변을 생성할 질문 개수만큼 만들어 주세요.
답변은 주어진 질문에만 답변하세요.
답변은 문장으로 답변해주세요.
답변할 때 질문의 주어를 써주세요.

텍스트:
{{text}}

생성할 질문 개수: {{num_questions}}

예시:
[Q]: 2024년 중앙정부 재정체계는 어떻게 구성되어 있나요?
[A]: 2024년 중앙정부 재정체계는 예산(일반·특별회계)과 기금으로 구분되며, 2024년 기준으로 일반회계 1개, 특별회계 21개, 기금 68개로 구성되어 있습니다.

결과:
"""


@click.command()
@click.option('--corpus_path', type=click.Path(exists=True),
              default=os.path.join('data', 'corpus_new.parquet'))
@click.option('--save_path', type=click.Path(exists=False, dir_okay=False, file_okay=True),
              default=os.path.join('data', 'qa_new2.parquet'))
@click.option('--qa_size', type=int, default=100)
def main(corpus_path, save_path, qa_size):
    load_dotenv()
    
    corpus_df = pd.read_parquet(corpus_path, engine='pyarrow')
    llm = Ollama(model="gemma-rtiz:latest", temprature=0.2,request_timeout=60000.0) #llama를 고쳐준다.
    # llm = OpenAI(model='gpt-4o-mini', temperature=0.5)
    qa_df = make_single_content_qa(corpus_df, content_size=qa_size, qa_creation_func=generate_qa_llama_index,
                                   llm=llm, prompt=prompt, question_num_per_content=1)
                                   
    # delete if the output question is '재정정보와 관련 없습니다'
    qa_df = qa_df.loc[~qa_df['query'].str.contains('재정정보와 관련 없습니다')]
    qa_df.reset_index(drop=True, inplace=True)
    qa_df.to_parquet(save_path)


if __name__ == '__main__':
    main()

 

타임아웃을 저렇게 준 이유는 필자의 컴이 AI를 돌리기에는 안좋은 컴퓨터이기에, 기본으로 되어 있는 timeout 30초로는 바로 연결이 끊겨버리기 때문이다.

 

이는 AutoRAG evaluate 돌릴 때도 마찬가지이다. 그래서 어떻게 설정하느냐?

결론부터 말하자면 ollama 자체의 설정에서 바꿔주면 된다.

 conda 가상환경을 설정했다면 대략적으로 경로는 이렇다.

C:\Users\Administer\anaconda3\envs\autorag\Lib\site-packages\llama_index\llms\ollama\base.py

여기서

DEFAULT_REQUEST_TIMEOUT = 30

을 바꿔주면 된다. 단위는 초 단위이다.

 

그리고 설정해야 할게 하나 더 있다.

 

Yaml 파일 수정

이것도 거슬러 올라가서 Yaml 파일을 먼저 설정해야 한다.

generator 부분 기본이 openai로 되어 있어서, 이거 디버깅하는데 한참 걸렸다..

AutoRAG 관계자 분들이 본다면 이거 좀 수정할 수 있게 해주길. docs에도 안나와 있고 코드를 모르는 사람들이 Yaml 파일 설정하다가 까무러질 거 같다.

 

C:\Users\Administer\anaconda3\envs\autorag\Lib\site-packages\autorag\nodes\promptmaker\run.py

def make_generator_callable_params(strategy_dict: Dict):
    node_dict = deepcopy(strategy_dict)
    generator_module_list: Optional[List[Dict]] = node_dict.pop('generator_modules', None)
    if generator_module_list is None:
        generator_module_list = [{
            'module_type': 'llama_index_llm',
            'llm': 'openai',
            'model': 'gpt-3.5-turbo',
        }]
    node_params = node_dict
    modules = list(map(lambda module_dict: get_support_modules(module_dict.pop('module_type')),
                       generator_module_list))
    param_combinations = list(map(lambda module_dict: make_combinations({**module_dict, **node_params}),
                                  generator_module_list))
    return explode(modules, param_combinations)

 

이 부분인데, openai를 사용하지 않는다면 llm에는 ollama를,  모델에는 자신의 ollama 모델 이름을 적어주면 된다.

 

아니면 yaml에서 generator_modules를 설정해줘도 된다.

node_lines:
  - node_line_name: retrieve_node_line
    nodes:
      - node_type: retrieval
        strategy:
          metrics: [ retrieval_f1, retrieval_recall, retrieval_precision ]
        top_k: 3
        modules:
          - module_type: vectordb
            embedding_model: multilingual-e5-base
          - module_type: bm25
            bm25_tokenizer: [ko_kiwi, ko_kkma, ko_okt]
       - node_type: generator_modules
         modules:
            - module_type: llama_index_llm
              llm: ollama
              model: [gemma2-9b-it]
          # - module_type: hybrid_rrf
          #   weight_range: (4,80)
          # - module_type: hybrid_cc
          #   normalize_method: [ mm, tmm, z, dbsf ]
      # - node_type: passage_reranker
      #   modules:
      #     - module_type: koreranker
      #     - module_type: pass_reranker
          # - module_type: cohere_reranker
        # strategy:
        #     metrics: [ retrieval_recall, retrieval_precision, retrieval_map ]
        # top_k: 10
  - node_line_name: post_retrieve_node_line
    nodes:
      - node_type: prompt_maker
        strategy:
          metrics: [rouge]
        modules:
          - module_type: fstring
            prompt: ["주어진 passage만을 이용하여 question에 따라 답하시오 passage: {retrieved_contents} \n\n Question: {query} \n\n Answer:", "다음 정보를 바탕으로 질문에 답하세요: {retrieved_contents} \n\n 질문: {query} \n\n 주어진 질문에만 답변하세요. 문장으로 답변해주세요. 답변할 때 질문의 주어를 써주세요. \n 답변:"]
      - node_type: prompt_maker
        strategy:
          metrics: [rouge]
        modules:
          - module_type: llama_index_llm
            llm: ollama
            model: gemma-rtiz:latest
            temperature: [ 0.2, 0.5, 1.0 ]
            batch: 1

 

임베딩, LLM 모델 추가하기

 

마지막으로 한 가지 더 말하자면, Docs에 나와있는 임베딩 모델 추가, LLM 추가는 전혀 작동하지 않는다.

따라서 직접 써넣어야 한다.

C:\Users\Administer\anaconda3\envs\autorag\Lib\site-packages\autorag\__init__.py

에 있다.

embedding_models = {
    # 'openai': LazyInit(OpenAIEmbedding),  # default model is OpenAIEmbeddingModelType.TEXT_EMBED_ADA_002
    # 'openai_embed_3_large': LazyInit(OpenAIEmbedding, model_name=OpenAIEmbeddingModelType.TEXT_EMBED_3_LARGE),
    # 'openai_embed_3_small': LazyInit(OpenAIEmbedding, model_name=OpenAIEmbeddingModelType.TEXT_EMBED_3_SMALL),
    # you can use your own model in this way.
    'huggingface_baai_bge_small': LazyInit(HuggingFaceEmbedding, model_name="BAAI/bge-small-en-v1.5"),
    'huggingface_cointegrated_rubert_tiny2': LazyInit(HuggingFaceEmbedding, model_name="cointegrated/rubert-tiny2"),
    'huggingface_all_mpnet_base_v2': LazyInit(HuggingFaceEmbedding,
                                              model_name="sentence-transformers/all-mpnet-base-v2",
                                              max_length=512, ),
    'multilingual-e5-base': LazyInit(HuggingFaceEmbedding, model_name="intfloat/multilingual-e5-base"),
    'multilingual-e5-large': LazyInit(HuggingFaceEmbedding, model_name="intfloat/multilingual-e5-large"),
    'kosimcse': LazyInit(HuggingFaceEmbedding, model_name="BM-K/KoSimCSE-roberta-multitask"),                                   
}

generator_models = {
    # 'openai': OpenAI,
    'huggingfacellm': HuggingFaceLLM,
    'openailike': OpenAILike,
    'ollama': Ollama,
    'mock': MockLLM,

이 부분을 양식대로 추가해주면 된다.

 

마치며

이상으로 AutoRAG에서 Ollama를 사용하여 돌리는 방법을 알아보았다.

 누군가에게는 이 글이 도움이 되었으면 좋겠다.

반응형