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)