[KT AIVLE SCHOOL]

Text - 챗봇

조진목_스터디 2024. 11. 6. 22:43

LangChain: 대규모 언어 모델을 활용하여 체인을 구성, 복잡한 작업을 자동화하고 쉽게 수행할 수 있도록 돕는 라이브러리

def ask_chatgpt1(question):

    # api key 지정
    # client = openai.OpenAI()

    # # API를 사용하여 'gpt-3.5-turbo' 모델로부터 응답을 생성합니다.
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "역할", "content": "내용"},  # 기본 역할 부여
            {"role": "사용자", "content": question},  # 질문
        ]
    )

    return response.choices[0].message.content


# 질문
question = "세계에서 가장 높은 산은 무엇인가요?"
response = ask_chatgpt1(question)
print(response)

# 출력
세계에서 가장 높은 산은 에베레스트 산입니다. 
에베레스트 산은 네팔과 중국의 국경에 위치하고 있으며, 높이는 8,848미터(29,029피트)에 달합니다.

 

 

출력 구조화 - OutputParser

from langchain.output_parsers import CommaSeparatedListOutputParser

# 출력파서 선언
output_parser = CommaSeparatedListOutputParser()

# 사용
result = chat([HumanMessage(content = "트랜스포머 기반 언어모델 3개 알려줘."),
               HumanMessage(content = output_parser.get_format_instructions())])

# 결과 출력1
print(result.content)

# 결과 출력2
output = output_parser.parse(result.content)
print(output)

# 출력
GPT-3, BERT, T5
['GPT-3', 'BERT', 'T5']

 

 

스트리밍: 생성하며 출력

# 스트리밍 방식으로 출력
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

chat2 = ChatOpenAI(model="gpt-3.5-turbo",
                   streaming=True, callbacks=[StreamingStdOutCallbackHandler()])  # 스트리밍 설정

 

 

Modeling - 내 데이터를 가지고 직접 학습 시킨다. 

Fine-tuning - 내 데이터를 가지고 추가 학습 시킨다.

RAG  - 내 데이터를 가지고 답변 시킨다. 

 

사용자 질문 받기 --> 지식DB에서 답변에 필요한 문서 검색 --> 필요한 문서를 포함한 프롬프트 생성 --> LLM 답변 생성

 

 

Vector DB: 대규모 텍스트 데이터 및 임베딩 벡터를 저장, 검색용

사용자 질문 받기

--> 임베딩 : 벡터로 변환(질문 벡터)

--> 준비된 정보 DB에서 답변에 필요한 문서 검색  [질문 벡터]와 DB내 저장된 [문서 벡터]와 유사도 계산 • 가장 유사도가 높은 문서 n개 찾기

--> 필요한 문서를 포함한 프롬프트 생성

--> LLM이 답변 생성하기

 

 

Vector DB 구축 절차(Chroma DB)

- 텍스트 추출 : Document Loader

- 다양한 문서(word, pdf, web page 등)로 부터 텍스트 추출하기

- 텍스트 분할 : Text Splitter

- chunk 단위로 분할

- Document 객체로 만들기

- 텍스트 벡터화 : Text Embedding

- Vector DB로 저장 : Vector Store

# DB 구성
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

database = Chroma(persist_directory = path + "db",  # 경로 지정(구글 드라이브에서 db 폴더 생성)
                    embedding_function = embeddings)  # 임베딩 벡터로 만들 모델 지정

 

 

Insert 방법

1. 단순 텍스트 입력 : 단위 텍스트를 리스트로 입력 - add_texts()

input_list = ['test 데이터 입력1', 'test 데이터 입력2']

# 입력시 인덱스 저장(조회시 사용)
ind = database.add_texts(input_list)

 

2. 텍스트와 메타데이터 입력 : 단위 텍스트와 메타정보 입력 - add_documents()

input_list2 = ['오늘 날씨는 매우 맑음. 낮 기온은 30도 입니다.', '어제 주가는 큰 폭으로 상승했습니다.']
metadata = [{'category':'test'}, {'category':'test'}]

doc2 = [Document(page_content = input_list2[i], metadata = metadata[i]) for i in range(2)]

 

 

데이터 베이스 조회

# 전체 조회
database.get()

# 인덱스 조회
database.get(index)

 

 

유사도 점수: 코사인 유사도 ( 1 − Cosine Similarity (𝒂, 𝒃): 코사인 유사도가 -1이면 반대, 0이면 엇갈림, 1이면 같은 방향)

- 수학적 의미 : 두 단위 벡터의 내적

- 자연어 처리에서의 의미 : 유사한 벡터 --> 유사한 문맥적 의미

# 문서 조회1
query = "질문할 문장"   # 질문할 문장
k = 3                  # 유사도 상위 k 개 문서 가져오기.

result = database.similarity_search(query, k = k) #← 데이터베이스에서 유사도가 높은 문서를 가져옴
print(result)
print('-'*50)
for doc in result:
    print(f"문서 내용: {doc.page_content}") # 문서 내용 표시

 

# 문서 조회2 : 유사도 점수도 함께 조회
query = "질문할 문장?"   # 질문할 문장
k = 3                   # 유사도 상위 k 개 문서 가져오기.

result = database.similarity_search_with_score(query, k = k) #← 데이터베이스에서 유사도가 높은 문서를 가져옴
print(result)
print('-'*50)
for doc in result:
    print(f"유사도 점수 : {round(doc[1], 5)}, 문서 내용: {doc[0].page_content}") # 문서 내용 표시

 

 

데이터 베이스에서 삭제

database.delete(ids = id_list) # id_list: 삭제할 행의 id

 

 

RAG 구성 함수

- llm : 언어 모델

- retriever : RAG로 연결할 VectorDB

- return_source_documents=True : 모델이 답변을 생성할 뿐만 아니라 그 답변에 사용된 출처 문서도 함께 반환

# 함수 구성
chat = ChatOpenAI(model="gpt-3.5-turbo")
retriever = database2.as_retriever()
qa = RetrievalQA.from_llm(llm=chat,  retriever=retriever,  return_source_documents=True )

# 질문
query = "질문"
result = qa(query)

print(result["result"])

 

 

메모리: ConversationBufferMemory

- return_source_documents=True: True로 설정되어 있으면, 답변과 함께 출처 문서도 반환됨 

- Output_key: 모델 출력이 저장될 키 지정

from langchain.memory import ConversationBufferMemory

embeddings = OpenAIEmbeddings(model = "text-embedding-ada-002")
database = Chroma(persist_directory = "./db2", 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 체인 생성
# memory=memory: 대화를 기억
qa = ConversationalRetrievalChain.from_llm(llm=chat, retriever=retriever, memory=memory,
                                           return_source_documents=True,  output_key="answer")

 

 

사용하기: 질문과 답변이 저장됨을 알 수 있다.

# 첫번째 질문
query1 = "생성형 AI 도입시 예상되는 보안 위협은 어떤 것들이 있어?"
result = qa(query1)
result['answer']

# 두번째 질문
query2 = "모델을 재학습시키면 어떤 문제가 발생되는거야?"
result = qa(query2)
result['answer']

# 메모리 확인
memory.load_memory_variables({})

 

 

나만의 챗봇 만들기

# 데이터 불러오기
data = pd.read_csv(path + 'data.csv', encoding='utf-8')

# Vector DB 생성
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
database = Chroma(persist_directory="./db", embedding_function = embeddings )

# 데이터 입력
qa_list = data['컬럼'].tolist()
cat_list = [{'category':text} for text in data['인덱스'].tolist()]

# 각 행의 데이터를 Document 객체로 변환
documents = [Document(page_content=qa_list[i], metadata = cat_list[i]) for i in range(len(qa_list))]

# 데이터프레임에서 문서 추가
database.add_documents(documents)

# 모델 선언
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 체인 생성
qa = ConversationalRetrievalChain.from_llm(llm=chat, retriever=retriever, memory=memory,
                                           return_source_documents=True,  output_key="answer")

 

 

챗봇 사용하기

# 질문
query = "질문할 문장"  

# 답변
result = qa(query)
answer = result["answer"]
print(answer)

'[KT AIVLE SCHOOL]' 카테고리의 다른 글

객체탐지(2)  (0) 2024.11.10
객체탐지(1)  (4) 2024.11.07
NLP  (9) 2024.11.05
CNN  (1) 2024.11.04
딥러닝(3)  (0) 2024.11.01