뉴스 기사 수집해서 llama2 에 질의하기 (feat. Silicon 맥북 with GPU)
M1/M2 같은 Silicon Mac 계열에서 GPU 를 사용하여 llama2 를 파인튜닝 해보고, 뉴스기사를 Embedding 하여 langchain 으로 얼마나 만족스러운 답변을 하는지를 테스트 해봤다.
M1/M2 같은 Silicon Mac 계열에서 GPU 를 사용하여 llama2 를 연동해보고, 뉴스기사를 Embedding 하여 얼마나 만족스러운 답변을 하는지를 테스트 해봤다.
1. LlamaCpp 설치하기
1) GGUF 버전의 Llama2 다운로드
지난글을 참조하여 llama2 모델을 설치하도록 한다.
2) LlamaCpp 사용하기
llama.cpp의 주요 목표 중 하나는 MacBook에서 4비트 정수 양자화(feat. GGML)를 사용하여 LLaMA 모델을 실행하는 것이라고 한다.
게다가 silicon 맥북에서 "하드웨어 가속 그래픽 API 인 Metal" 을 통해 GPU 가속이 가능하도록 해준다.
아래와 같이 llama-cpp-python 을 CMAKE_ARGS 를 주어 설치 해주어야 GPU 가속이 가능하다.
CMAKE_ARGS="-DLLAMA_METAL=on" FORCE_CMAKE=1 pip install llama-cpp-python
2. 뉴스기사 Embedding 하기
1) 뉴스 크롤링 데이터 구조 소개
langchain, DocStore 의 Document 포멧으로 다음과 같이 뉴스 포털의 페이지를 사회/경제/정치 섹션을 10 페이지씩 수집하여 1172건 정도의 뉴스를 모았다.
구성한 langchain, DocStore 의 Document 의 구조는 다음과 같다.
[
Document(
page_content='[https://n.news.naver.com....] 정치 대전현충원·블랙야크 보훈 둘레길 걷기 인증 행사 호응 대전현충원·블랙야크 보훈 둘레길 걷기 인증 행사 호응 재판매 및 DB 금지 대전 연합뉴스 이주형 기자 정전 70주년을 맞아 진행 중인 대전현충원 보훈 둘레길 걷기 인증이 참가자들의 호응을 얻고 있다. 오는 10월 24일까지 진행되는 이번 행사는 참가자들이 대전현충원 보훈 둘레길을 걸으며 지정장소마다 인증사진을 찍고 블랙야크 알파인 클럽 BAC 앱에 사진 등록을 하면 된다. 황원채 국립대전현충원장은 전국 곳곳에서 참가자들의 발길이 이어지고 있다 며 보훈 둘레길을 걸으며 국가유공자의 숭고한 희생정신을 기리는 계기가 되길 바란다 고 밝혔다.',
metadata={
'section': '정치',
'title': '대전현충원·블랙야크 보훈 둘레길 걷기 인증 행사 호응',
'date': '2023.08.21. 오후 5:18',
'url': 'https://n.news.naver.com...'
}
)
(...생략...)
]
2) HuggingFace, Embeding 모델 (feat. jhgan/ko-sroberta-multitask)
기사가 한글이라 한글 문장 임베딩을 위한 모델을 적용했다.
3) Embeding 하고 Chroma VectorDB 에 저장/로드 하기
# 데이터를 불러와서 텍스트를 일정한 수로 나누고 구분자로 연결하는 작업
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
chunk_size=800,
chunk_overlap=200,
separator="\n"
)
texts = text_splitter.split_documents(new_documents)
# 임베딩 모델 로드
from langchain.embeddings import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="jhgan/ko-sroberta-multitask", encode_kwargs={'normalize_embeddings': True}
)
# Chroma DB에 기사 벡터화하여 저장하기
from langchain.vectorstores import Chroma
docsearch = Chroma.from_documents(texts, embeddings, persist_directory="./news_chroma_db")
4) Chroma VectorDB 에 질의하기
llama2 chat 모델에 질문하기 전에, chroma db 에서 유사도 검색을 통해 원하는 내용의 기사가 들어가 있는지 확인했다.
3. Langchain, RetrievalQA 로 질의하기
from langchain.llms import LlamaCpp
from langchain import PromptTemplate, LLMChain
from langchain.retrievers.document_compressors import EmbeddingsFilter
from langchain.retrievers import ContextualCompressionRetriever
from langchain.chains import RetrievalQA
llm = LlamaCpp(
# model_path: 로컬머신에 다운로드 받은 모델의 위치
model_path="./llama-2-7b-chat.Q4_K_M.gguf",
temperature=0.75,
top_p=0.95,
max_tokens=8192,
verbose=True,
# n_ctx: 모델이 한 번에 처리할 수 있는 최대 컨텍스트 길이
n_ctx=8192,
# n_gpu_layers: 실리콘 맥에서는 1이면 충분하다고 한다
n_gpu_layers=1,
n_batch=512,
f16_kv=True,
n_threads=16,
)
# 유사도에 맞추어 대상이 되는 텍스트를 임베딩함
embeddings_filter = EmbeddingsFilter(
embeddings=embeddings,
similarity_threshold=0.5
)
# 압축 검색기 생성
compression_retriever = ContextualCompressionRetriever(
# embeddings_filter 설정
base_compressor=embeddings_filter,
# retriever 를 호출하여 검색쿼리와 유사한 텍스트를 찾음
base_retriever=docsearch.as_retriever()
)
# context 를 참조하여 순서에 맞게 명료하게 응답하게 구성
from langchain.prompts import PromptTemplate
prompt_template = """
Give an answer by referring to the context, and include the address within the context in the answer, and clearly number the answer.
{context}
Question: {question}
Answer in English:"""
# RetrievalQA 클래스의 from_chain_type이라는 클래스 메서드를 호출하여 질의응답 객체를 생성
qa = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=compression_retriever,
return_source_documents=True,
verbose=True,
chain_type_kwargs={"prompt": PromptTemplate(
input_variables=["context","question"],
template=prompt_template,
)},
)
1) 벡터화 한 DB를 참조 하여 답변하는지 확인
res = qa({"query":"북한 러시아가 군사협력을 하게 되면 무슨 일이 벌어질까? 5가지로 요약해주고 소스 컨텍스트의 URL 도 반드시 알려줘"})
print(res)
> Entering new RetrievalQA chain...
Based on the provided context, here are five possible outcomes if North Korea and Russia were to cooperate on military matters:
1. Increased pace of military development: The two countries may accelerate their military modernization programs and develop new technologies and capabilities together. (Source: [https://n.news.naver.com/mnews/article/052/0001924038?sid=100])
2. Enhanced nuclear deterrence: North Korea may receive advanced nuclear weapons and missile technology from Russia, which could enhance its nuclear deterrent capabilities. (Source: [https://n.news.naver.com/mnews/article/052/0001924038?sid=100])
3. Greater military cooperation: The two countries may deepen their military ties and jointly develop new military strategies, including the possibility of conducting joint military exercises or operations. (Source: [https://n.news.naver.com/mnews/article/052/0001924038?sid=100])
4. Increased threat perception: The increased military cooperation between North Korea and Russia may be perceived as a threat by other countries, particularly the United States and South Korea. (Source: [https://n.news.naver.com/mnews/article/052/0001924038?sid=100])
5. International condemnation: The cooperation between North Korea and Russia may lead to international condemnation, particularly from the United States and its allies, who may view it as a violation of international sanctions and a threat to regional security. (Source: [https://n.news.naver.com/mnews/article/052/0001924038?sid=100])
하나의 기사에서 5가지 주제로 나누어 응답을 한 것으로 보이며, source_documents 를 보면 Chroma DB 에 넣은 기사를 잘 참조하고 있는 것으로 확인했다.
2) 벡터화한 DB에 없는 질문을 하는 경우
res = qa({"query":"북한 러시아가 군사협력을 하게 되면 남한이 겪게 되는 경제적 영향은 어떨까? 소스 컨텍스트의 URL 도 반드시 알려줘"})
print(res)
> Entering new RetrievalQA chain...
Llama.generate: prefix-match hit
1. According to the source (<https://www.korea-institute.or.kr/ English/publication/view?pid=Sky&uber=sky0413268>), the economic impact of a military alliance between North Korea and Russia would have significant consequences for South Korea.
Context: The source is an article from the Korea Institute for International Economic Policy, titled "The Impact of a Military Alliance between North Korea and Russia on South Korea's Economy."
2. Firstly, the article states that the formation of such an alliance would lead to a significant increase in military spending by both countries, which would divert resources away from other sectors of their economies, including infrastructure development, education, and healthcare. (Paragraph 1)
Address: The address of the source is <https://www.korea-institute.or.kr/ English/publication/view?pid=Sky&uber=sky0413268>.
3. Secondly, the article argues that a military alliance between North Korea and Russia would heighten South Korea's security concerns, leading to increased defense spending and a decreased ability to invest in other areas of the economy. (Paragraph 2)
Address: <https://www.korea-institute.or.kr/ English/publication/view?pid=Sky&uber=sky0413268>.
4. Furthermore, the article suggests that a North Korean-Russian military alliance could potentially disrupt South Korea's supply chains and trade networks, as well as its investment environment. (Paragraph 3)
Address: <https://www.korea-institute.or.kr/ English/publication/view?pid=Sky&uber=sky0413268>.
5. In conclusion, the article concludes that a military alliance between North Korea and Russia would have significant negative economic consequences for South Korea, including increased defense spending, reduced investment in other sectors, disrupted supply chains and trade networks, and a decreased ability to participate in global trade. (Paragraph 4)
Address: <https://www.korea-institute.or.kr/ English/publication/view?pid=Sky&uber=sky0413268>.
> Finished chain.
모델이 가지고 있는 데이터를 기반으로 비교적 납득할만한 응답을 줬다. (다만 URL 은 존재 하지 않는 것으로 보인다)
이후로 다양한 질문을 해봤는데, 이를테면 "사회면에 있는 기사를 5가지로 요약해줘" 와 같은 질문에 대해서는 응답을 제대로 하지 못했고 "2023년 8월 국내 사회면 기사에 살인 예고 글을 참고로 위험할 수 있는 지역을 나열해줘." 와 같은 명확한 질문에는 만족스러운 답변을 해줬다.
res = qa({"query":"2023년 8월 국내 사회면 기사에 살인 예고 글을 참고로 위험할 수 있는 지역을 나열해줘. 소스 컨텍스트의 URL 도 반드시 알려줘. URL이 중복 되서는 안돼"})
print(res)
> Entering new RetrievalQA chain...
Llama.generate: prefix-match hit
Based on the article you provided, there are several regions in Korea where the police are conducting an investigation related to the murder threat made through a social media post. These regions include:
1. Gangnam Station area (Seoul) - The police have set up a special task force to investigate the case and are currently tracking down the user who made the threatening post.
2. Bundang Police Station area (Seongnam) - The police have received a report about a threat made through a social media post and are conducting an investigation.
3. Cheongnyangi Police Station area (Daejeon) - The police have received a report about a threatening post on a social media platform and are conducting an investigation.
The URLs of the articles you provided are as follows:
1. <https://n.news.naver.com/mnews/article/052/0001925550?sid=102>
2. <https://n.news.naver.com/mnews/article/214/0001294451?sid=102>
Please note that these are the URLs of the articles you provided, and they may not be the same as the URLs of the original articles.
> Finished chain.