728x90
반응형

오늘은 이전에 진행했던 PDF 기반 ChatBot 프로젝트를 한 단계 발전시켜, 로컬 모델 실행 환경인 Ollama를 활용한 RAG 프로젝트를 만들어 보았습니다.

이번 프로젝트의 핵심은 크게 두 가지입니다.

  • 로컬 모델 연동: OpenAI API뿐만 아니라 Ollama를 통해 로컬 모델을 선택적으로 실행
  • 멀티모달 확장: PDF뿐 아니라 이미지까지 인식할 수 있는 챗봇 구현

1. Ollama란?

https://ollama.com/

 

Ollama는 로컬 환경에서 다양한 오픈소스 LLM(Large Language Model)을 실행할 수 있도록 돕는 런타임입니다.

Ollama의 특징

  • 💻 로컬 실행: 인터넷 연결 없이 모델 동작 가능 → 데이터 프라이버시 강화
  • 간단한 모델 관리: ollama pull <model>로 다운로드, ollama run <model>로 즉시 실행
  • 🔌 HTTP API 제공: 서버 모드(ollama serve)로 실행하면 LangChain 등 외부 도구와 손쉽게 연동
  • 💰 비용 절감: 클라우드 API 과금 없이 내 하드웨어 리소스를 활용
  • 🔄 모델 다양성: Llama3, Mistral, Phi, Qwen 등 원하는 모델을 선택 가능

👉 이번 프로젝트에서는 EEVE-KOREAN-10.8B 모델을 사용하여 한국어 중심의 PDF QA를 시도했습니다.


2. 프로젝트 구조

이번 프로젝트는 Streamlit 기반 웹앱으로 구성되어 있습니다.

  • pages/02_Local_RAG.py: PDF 기반 RAG + Ollama 연동
  • pages/03_Multi_Modal.py: 이미지 인식 기반 멀티모달 챗봇

앱을 실행하면 사이드바에서 PDF 업로드모델 선택이 가능하며, 선택한 모델(OpenAI GPT 시리즈 또는 Ollama 로컬 모델)에 따라 응답 품질/속도를 비교할 수 있습니다.


3. Local RAG 구현 (./pages/02_Local_RAG.py)

주요 흐름

  1. PDF 업로드 → 캐시에 저장
  2. Retriever 생성 → 문서 임베딩 후 검색 기능 제공
  3. 체인 구성 → 프롬프트 + LLM(OpenAI or Ollama) 연결
  4. 스트리밍 응답 → 토큰 단위 출력으로 실시간 반응

코드 핵심

def create_chain(retriever, model_name='gpt-4o'):
    if model_name == 'ollama':
        prompt = load_prompt("./prompts/pdf-rag-ollama.yaml")
        llm = ChatOllama(model='EEVE-KOREAN-10.8B:latest', temperature=0)
    else:
        prompt = load_prompt("./prompts/pdf-rag.yaml")
        llm = ChatOpenAI(model=model_name, temperature=0)

    chain = (
        {"context": retriever | format_doc, "question": RunnablePassthrough()}
        | prompt
        | llm
        | StrOutputParser()
    )
    return chain

  • ChatOllama를 사용하여 로컬 모델을 선택적으로 실행
  • 모델에 따라 프롬프트 YAML을 분리(pdf-rag.yaml, pdf-rag-ollama.yaml)
  • chain.stream(user_input)을 통해 실시간 스트리밍 응답 출력

4. 멀티모달 확장 (./pages/03_Multi_Modal.py)

이번에는 이미지 인식 기반 챗봇을 추가했습니다.

  • 이미지 업로드 → 캐시에 저장
  • 선택한 LLM(OpenAI)과 연결
  • MultiModal 객체를 통해 시스템 프롬프트 + 사용자 입력 + 이미지 파일을 조합

코드 예시

def generate_answer(img_file_path, system_prompt, user_prompt, model_name='gpt-4o'):
    llm = ChatOpenAI(temperature=0, model=model_name)
    multimodal_llm_with_prompt = MultiModal(
        llm, system_prompt=system_prompt, user_prompt=user_prompt
    )
    return multimodal_llm_with_prompt.stream(img_file_path)

👉 기본 시스템 프롬프트는 재무제표 분석용 금융 AI 어시스턴트로 설정되어 있습니다. 사용자는 원하는 역할을 직접 커스터마이징할 수도 있습니다.


5. 실행 방법

streamlit run main.py

 

 

 

 


6. 결과 및 느낀 점

  • 동일한 PDF를 기반으로 OpenAI API vs Ollama 로컬 모델을 비교하면서,
    • OpenAI: 응답 품질이 안정적이고 빠름
    • Ollama: 속도는 하드웨어 의존적이지만, 비용이 없고 프라이버시 보장
  • 이미지 인식 기반 확장은 RAG 범위를 넓혀주었고, 추후 로컬 멀티모달 모델(LLaVA, Qwen-VL 등)을 Ollama로 붙이는 방향도 흥미로울 것 같았습니다.

7. 프롬프트 비교: OpenAI vs Ollama

이번 프로젝트에서 저는 OpenAI API와 Ollama 로컬 모델에 서로 다른 프롬프트를 사용했습니다.

이유는 두 모델의 출력 스타일과 강점이 다르기 때문입니다.

 

📌 Ollama용 프롬프트 (pdf-rag-ollama.yaml)

_type: "prompt"
template: |
  You are an assistant for question-answering tasks.
  Use the following pieces of retrieved 'information' to answer the question.
  If you don't know the answer, just say that you don't know.
  Answer in Korean.

  <information>
  {context}
  </information>

  #Question:
  {question}

  #Answer:
input_variables: ["question", "context"]

  • 핵심 포인트
    • 단순하고 직관적
    • 모델이 과한 포맷팅 없이 질문에 집중할 수 있도록 설계
    • Answer in Korean. → 한글 답변 강제

👉 로컬 모델은 출력 안정성이 아직 부족하기 때문에, 불필요한 제약을 최소화해 “질문에 답하는 것”에만 집중하도록 했습니다.


📌 OpenAI용 프롬프트 (pdf-rag.yaml)

_type: "prompt"
template: |
  You are an assistant for question-answering tasks.
  Use the following pieces of retrieved context to answer the question.
  If you don't know the answer, just say that you don't know.
  Please write your answer in a markdown table format with the main points.
  Be sure to include your source and page numbers in your answer.
  Answer in Korean.

  #Example Format:
  (brief summary of the answer)
  (table)
  (answer to the question)

  **출처**
  - page source and page number

  #Context:
  {context}

  #Question:
  {question}
input_variables: ["question", "context"]

  • 핵심 포인트
    • Markdown 표 형식 강제 → 가독성 있는 답변 생성
    • 출처 및 페이지 번호 포함 → 근거 중심 답변
    • 더 다양한 지시사항을 줘도 OpenAI 모델은 잘 따라오기 때문에, 리포트 형태로 답변을 구성하도록 유도

차이 정리

항목 Ollama 프롬프트 OpenAI 프롬프트
출력 형식 자유로운 답변 Markdown 표 형식, 요약 + 출처 포함
지시 강도 최소화 상세 지시 (출처, 포맷, 요약)
목적 안정적 Q&A 수행 구조화된 리포트 생성
언어 한국어 한국어

👉 요약하자면, Ollama는 “단순하고 확실한 답변”에 집중시키고, OpenAI는 “구조화된 리포트”를 생성하도록 프롬프트를 달리 설계했습니다.


마무리

이번 프로젝트는 클라우드 API와 로컬 LLM을 동시에 지원하는 RAG 파이프라인을 구축해본 경험이었습니다.

  • 📄 PDF → RAG → LLM 답변
  • 🖼️ 이미지 인식 → 멀티모달 확장
  • 🌐 OpenAI ↔ Ollama 로컬 모델 토글

앞으로는 로컬 멀티모달 모델 연동프롬프트 최적화를 통해, 완전히 독립적인 AI 에이전트 환경으로 발전시켜 볼 수 있을 것 같습니다 🚀

 

전체 코드는 다음 링크에서 확인하실 수 있습니다.

728x90
반응형

+ Recent posts