새소식

KT AIVLE SCHOOL

RAG - 모델이 질문과 모델의 답변을 기억하기 및 이어지는 질문과 답변하기

  • -

layout: single
title: "jupyter notebook 변환하기!"
categories: coding
tag: [python, blog, jekyll]
toc: true
author_profile: false


Memory & Chain

1.환경준비

(1) 라이브러리 Import

import pandas as pd
import numpy as np
import os
import openai

from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage, Document
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA, ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)

(2) OpenAI API Key 확인

https://platform.openai.com/api-keys

위 링크에서 자신의 API Key 생성 - gpt-3.5-turbo로 준비하기

API.key 파일을 만들고 거기에 API key 저장하기

image

with open("API.key") as f:
    openai.api_key = f.readlines()[0]

print(openai.api_key[:10])
sk-proj-Gt

또는 직접 입력

# os.environ['OPENAI_API_KEY'] = '여러분의 OpenAI API키'
# openai.api_key = os.getenv('OPENAI_API_KEY')

2.Memory

(1) 대화 기록 저장하기

# 메모리 선언하기(초기화)
memory = ConversationBufferMemory(return_messages=True)

# 메모리에 저장
memory.save_context({"input": "안녕하세요!"},                           # Human Message 
                    {"output": "안녕하세요! 어떻게 도와드릴까요?"})       # System Message   

memory.save_context({"input": "메일을 써야하는데 도와줘"},
                    {"output": "누구에게 보내는 어떤 메일인가요?"})

# 현재 담겨 있는 메모리 내용 전체 확인
memory.load_memory_variables({})    # {} 필요 
{'history': [HumanMessage(content='안녕하세요!'),
  AIMessage(content='안녕하세요! 어떻게 도와드릴까요?'),
  HumanMessage(content='메일을 써야하는데 도와줘'),
  AIMessage(content='누구에게 보내는 어떤 메일인가요?')]}

(2) GPT와 대화 기록 저장하기

1) 대화 준비

k = 3

# Chroma 데이터베이스 인스턴스
embeddings = OpenAIEmbeddings(model = "text-embedding-ada-002")
database = Chroma(persist_directory = "./data3", embedding_function = embeddings)

# retriever 선언
retriever = database.as_retriever(search_kwargs={"k": k})

# ChatOpenAI 선언
chat = ChatOpenAI(model="gpt-3.5-turbo")

# RetrievalQA 선언 retriever와 chat모델 연결시키기 
qa = RetrievalQA.from_llm(
                            llm=chat,                       #← Chat models를 지정
                            retriever=retriever,            #← Retriever를 지정
                            return_source_documents=True    #← 응답에 원본 문서를 포함할지를 지정
                            )

2) 대화 시도 및 기록

# 질문 답변1
query = "생성형 AI 도입시 예상되는 보안 위협은 어떤 것들이 있어?"
result = qa(query)
result['result']
'생성형 AI 도입시 예상되는 보안 위협은 다양합니다. 예를 들어, 해커가 프로젝트의 개발팀에 침투하여 소프트웨어에 악성 코드를 추가하거나, 훈련 데이터나 모델을 오염시키는 등의 위협이 있을 수 있습니다. 또한, 모델을 재훈련하여 사용자 인프라에 침입하거나 가짜 뉴스와 잘못된 정보로 모델을 훈련시키는 위협도 있을 수 있습니다. 이러한 보안 위협을 고려하여 적절한 보안 조치를 강구해야 합니다.'
memory = ConversationBufferMemory(return_messages=True)

memory.save_context({"input": query},
                    {"output": result['result']})

memory.load_memory_variables({})
{'history': [HumanMessage(content='생성형 AI 도입시 예상되는 보안 위협은 어떤 것들이 있어?'),
  AIMessage(content='생성형 AI 도입시 예상되는 보안 위협은 다양합니다. 예를 들어, 해커가 프로젝트의 개발팀에 침투하여 소프트웨어에 악성 코드를 추가하거나, 훈련 데이터나 모델을 오염시키는 등의 위협이 있을 수 있습니다. 또한, 모델을 재훈련하여 사용자 인프라에 침입하거나 가짜 뉴스와 잘못된 정보로 모델을 훈련시키는 위협도 있을 수 있습니다. 이러한 보안 위협을 고려하여 적절한 보안 조치를 강구해야 합니다.')]}

3) 이어지는 질문과 답변

# 질문 답변2
query = "훈련 데이터나 가중치를 오염시키는게 무슨 의미야?"
result = qa(query)
result['result']

memory.save_context({"input": query},
                    {"output": result['result']})

memory.load_memory_variables({})
{'history': [HumanMessage(content='생성형 AI 도입시 예상되는 보안 위협은 어떤 것들이 있어?'),
  AIMessage(content='생성형 AI 도입시 예상되는 보안 위협은 다양합니다. 예를 들어, 해커가 프로젝트의 개발팀에 침투하여 소프트웨어에 악성 코드를 추가하거나, 훈련 데이터나 모델을 오염시키는 등의 위협이 있을 수 있습니다. 또한, 모델을 재훈련하여 사용자 인프라에 침입하거나 가짜 뉴스와 잘못된 정보로 모델을 훈련시키는 위협도 있을 수 있습니다. 이러한 보안 위협을 고려하여 적절한 보안 조치를 강구해야 합니다.'),
  HumanMessage(content='훈련 데이터나 가중치를 오염시키는게 무슨 의미야?'),
  AIMessage(content='훈련 데이터나 가중치를 오염시킨다는 것은 악의적인 공격자가 해당 데이터나 모델을 조작하여 원래의 목적과 다른 결과를 유도하거나 시스템을 손상시키는 것을 의미합니다. 이는 AI 모델의 신뢰성을 훼손시키거나 사용자의 데이터를 유출시키는 등의 악영향을 미칠 수 있습니다.')]}
# 질문 답변3
query = "이를 방지하기 위해 어떻게 해야 해?"
result = qa(query)
result['result']

memory.save_context({"input": query},
                    {"output": result['result']})

memory.load_memory_variables({})
{'history': [HumanMessage(content='생성형 AI 도입시 예상되는 보안 위협은 어떤 것들이 있어?'),
  AIMessage(content='생성형 AI 도입시 예상되는 보안 위협은 다양합니다. 예를 들어, 해커가 프로젝트의 개발팀에 침투하여 소프트웨어에 악성 코드를 추가하거나, 훈련 데이터나 모델을 오염시키는 등의 위협이 있을 수 있습니다. 또한, 모델을 재훈련하여 사용자 인프라에 침입하거나 가짜 뉴스와 잘못된 정보로 모델을 훈련시키는 위협도 있을 수 있습니다. 이러한 보안 위협을 고려하여 적절한 보안 조치를 강구해야 합니다.'),
  HumanMessage(content='훈련 데이터나 가중치를 오염시키는게 무슨 의미야?'),
  AIMessage(content='훈련 데이터나 가중치를 오염시킨다는 것은 악의적인 공격자가 해당 데이터나 모델을 조작하여 원래의 목적과 다른 결과를 유도하거나 시스템을 손상시키는 것을 의미합니다. 이는 AI 모델의 신뢰성을 훼손시키거나 사용자의 데이터를 유출시키는 등의 악영향을 미칠 수 있습니다.'),
  HumanMessage(content='이를 방지하기 위해 어떻게 해야 해?'),
  AIMessage(content='위의 문맥에서 언급된 악의적인 공격을 방지하기 위해서는 다음과 같은 조치를 취할 수 있습니다:\n1. 오픈소스 모델 사용 시, 신뢰할 수 있는 소스에서 다운로드하고 정기적인 보안 업데이트를 수행하여 취약점을 최소화합니다.\n2. AI 모델에 워터마크를 추가하여 무단 복제를 방지하고, 코드를 분석하는 공격을 어렵게 만듭니다.\n3. 모델을 테스트하고 평가하여 취약점을 식별하고, 적절한 보안 장치를 마련하여 시스템을 보호합니다.\n4. 과부하를 일으키는 요청을 필터링하고, 시스템을 과부하시키는 공격을 방지하기 위한 방어 메커니즘을 구축합니다.\n\n그러나 전문적인 보안 담당자나 컨설턴트의 도움을 받아 추가적으로 보안 전략을 강화하는 것이 좋습니다.')]}
  • 훈련 데이터 오염을 방지하기 위한 대책을 물었으나, 일반적인 보안 위협 방지 대책을 이야기 함.

memory와 모델이 연결되어 있지 않음을 알 수 있다.

  • 맥락을 유지하기 위해서 메시지의 내용을 프롬프트에 포함시켜야 함.

    • 이를 손쉽게 엮어주는 방법 Chain

3.Chain

  • 절차 다시 정리

    • 질문을 받아

    • 유사도 높은 문서를 DB에서 검색(RAG)

    • 이전 대화 내용을 메모리에서 읽어오기

    • [질문 + 유사도높은 문서 + 이전 대화내용]으로 프롬프트 구성

    • GPT에 질문하고 답변 받기

  • Chain

    • 이러한 절차를 코드로 하나하나 엮고, 프롬프트를 구성하는 코드는 상당히 복잡합니다.

    • 랭체인에서 제공하는 Chain 함수를 이용하면 쉽게 구현 가능!

(1) Chain 함수로 연결하기

  • ConversationalRetrievalChain
embeddings = OpenAIEmbeddings(model = "text-embedding-ada-002")
database = Chroma(persist_directory = "./data3", embedding_function = embeddings)
chat = ChatOpenAI(model="gpt-3.5-turbo")

k=3
retriever = database.as_retriever(search_kwargs={"k": k})

# 대화 메모리 생성
memory = ConversationBufferMemory(memory_key="chat_history", input_key="question", output_key="answer",
                                  return_messages=True)

# ConversationalRetrievalQA 체인 생성 -> chat모델, 검색기, 메모리 연결
qa = ConversationalRetrievalChain.from_llm(llm=chat, retriever=retriever, memory=memory,
                                           return_source_documents=True,  output_key="answer")

(2) 사용하기

1) 첫번째 질문

# 첫번째 질문
query1 = "생성형 AI 도입시 예상되는 보안 위협은 어떤 것들이 있어?"
result = qa(query1)
result['answer']
'생성형 AI 프로젝트는 보안 위협에 노출될 수 있는 다양한 영역이 있습니다. 예를 들어, 해커가 프로젝트의 개발팀에 침투하여 악성 코드를 추가하거나 훈련 데이터, 미세 조정, 가중치 등을 오염시키는 위협이 있을 수 있습니다. 또한 모델을 재학습시켜 사용자 인프라에 침입하거나 가짜 뉴스 및 잘못된 정보로 모델을 훈련시키는 위협도 있을 수 있습니다. 이러한 위협에 대비하여 보안에 신경을 써야 합니다.'
# 메모리 확인
memory.load_memory_variables({})        
# 알아서 메모리에 들어감을 확인할 수 있음 
{'chat_history': [HumanMessage(content='생성형 AI 도입시 예상되는 보안 위협은 어떤 것들이 있어?'),
  AIMessage(content='생성형 AI 프로젝트는 보안 위협에 노출될 수 있는 다양한 영역이 있습니다. 예를 들어, 해커가 프로젝트의 개발팀에 침투하여 악성 코드를 추가하거나 훈련 데이터, 미세 조정, 가중치 등을 오염시키는 위협이 있을 수 있습니다. 또한 모델을 재학습시켜 사용자 인프라에 침입하거나 가짜 뉴스 및 잘못된 정보로 모델을 훈련시키는 위협도 있을 수 있습니다. 이러한 위협에 대비하여 보안에 신경을 써야 합니다.')]}

2) 두번째 질문

# 두번째 질문
query2 = "모델을 재학습시면 어떤 문제가 발생되는거야?"
result = qa(query2)
result['answer']
'모델을 재학습시키면 악의적인 공격자가 모델을 손상시키거나 오염시킬 수 있습니다. 이는 악의적인 공격자가 모델을 해킹하거나 소프트웨어에 악성 코드를 추가하여 사용자 인프라에 침입할 수 있게 만들거나, 가짜 뉴스 및 잘못된 정보로 모델을 훈련시켜 잘못된 결정을 내리도록 만들 수 있습니다. 따라서 모델을 재학습할 때는 보안에 신경을 써야 합니다.'
# 메모리 확인
memory.load_memory_variables({})
# 두번째 질문과 답변이 저장됨을 확인할 수 있다.
{'chat_history': [HumanMessage(content='생성형 AI 도입시 예상되는 보안 위협은 어떤 것들이 있어?'),
  AIMessage(content='생성형 AI 프로젝트는 보안 위협에 노출될 수 있는 다양한 영역이 있습니다. 예를 들어, 해커가 프로젝트의 개발팀에 침투하여 악성 코드를 추가하거나 훈련 데이터, 미세 조정, 가중치 등을 오염시키는 위협이 있을 수 있습니다. 또한 모델을 재학습시켜 사용자 인프라에 침입하거나 가짜 뉴스 및 잘못된 정보로 모델을 훈련시키는 위협도 있을 수 있습니다. 이러한 위협에 대비하여 보안에 신경을 써야 합니다.'),
  HumanMessage(content='모델을 재학습시면 어떤 문제가 발생되는거야?'),
  AIMessage(content='모델을 재학습시키면 악의적인 공격자가 모델을 손상시키거나 오염시킬 수 있습니다. 이는 악의적인 공격자가 모델을 해킹하거나 소프트웨어에 악성 코드를 추가하여 사용자 인프라에 침입할 수 있게 만들거나, 가짜 뉴스 및 잘못된 정보로 모델을 훈련시켜 잘못된 결정을 내리도록 만들 수 있습니다. 따라서 모델을 재학습할 때는 보안에 신경을 써야 합니다.')]}

(3) 반복문 안에서 질문답변 이어가기

while True:
    query = input('질문 > ')
    query = query.strip()
    print(f'질문 : {query}')
    print('-' * 20)
    if len(query) == 0:
        print('Enter 입력 -> 대화 종료')
        break
    result = qa({"question": query})
    print(f'답변 : {result["answer"]}')
    print('=' * 50)
질문 : 안녕
--------------------
답변 : 저는 기술과 관련된 질문에 도움을 줄 수 있습니다. 궁금한 것이 있으면 언제든지 물어보세요!
==================================================
질문 : 어떤 보안 위협이 있어?
--------------------
답변 : 생성형 AI 프로젝트에서의 보안 위협에는 악의적인 공격자가 프로젝트 팀에 침투하여 소프트웨어에 악성 코드를 추가하거나 훈련 데이터, 미세 조정, 가중치를 오염시키는 것, 모델을 재학습시켜 사용자 인프라에 침입하는 것, 가짜 뉴스나 잘못된 정보로 모델을 훈련시키는 것 등이 포함될 수 있습니다. 또한 악의적인 공격자가 오픈소스 모델을 다운로드하여 해킹을 시도하거나 모델이 사용하는 시스템 프롬프트와 안전 기능을 악용하여 공격하는 경우도 있습니다. 추가적으로 공격자가 워터마크를 제거하거나 모델의 취약한 영역을 찾아내는 등의 방법으로 공격할 수 있습니다. 또한 모델이 특정 시스템에서 사용되는 경우, 공격자는 특정 요청을 계속 보내 인프라를 과부하시켜 모델을 작동하지 않도록 만들 수도 있습니다.
==================================================
질문 : 
--------------------
Enter 입력 -> 대화 종료
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.