2025.01.29 - [AI, 머신러닝] - RAG 시스템 강화하기 (1) Multi-Query, Self-Query, Reranker - 이론편
이전 포스팅에서 이론적으로 설명한 내용을 RangChain을 통해 구현해보겠다.
from bs4 import SoupStrainer
import getpass
import os
from dataclasses import dataclass
import logging
from typing import List
import faiss
from langchain.schema import Document
from langchain_community.vectorstores import FAISS
from langchain_community.docstore.in_memory import InMemoryDocstore
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
from langchain_community.document_loaders import WebBaseLoader
# -- MultiQueryRetriever (LangChain)
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain.prompts.prompt import PromptTemplate
# For the custom multi-query generation approach
from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
# For Reranking
from sentence_transformers import CrossEncoder
from langchain.retrievers import ContextualCompressionRetriever
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
#%%
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")
#%%
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
os.environ["LANGCHAIN_PROJECT"] = "RAG-MultiQuery-Reranker"
Document Index 생성
2025.01.30 - [AI, 머신러닝] - 네이버 증권뉴스 크롤링으로 RAG 데이터셋 만들기 (python, BeautifulSoup4)
네이버 증권뉴스 크롤링으로 RAG 데이터셋 만들기 (python, BeautifulSoup4)
Qualtative Analysis가 필요한 이유주식이나 금융 시장에서 투자를 결정하는데 있어 흔히 사용하는 방식 중 하나가 재무제표, 차트, 지표 등 정량적 분석(Quantative Analysis)이다. 하지만 이런 수치적인
kangth97.tistory.com
Document는 네이버 증권뉴스를 크롤링하여 사용한다. (이전 포스팅 참고)
먼저 임베딩 모델을 load하고 document vector를 저장하기 위해 FAISS를 선언한다.
embedding_fn = HuggingFaceEmbeddings(model_name="intfloat/multilingual-e5-large-instruct")
dimension_size = len(embedding_fn.embed_query("hello world"))
vector_db = FAISS(
embedding_function=embedding_fn,
index=faiss.IndexFlatL2(dimension_size),
docstore=InMemoryDocstore(),
index_to_docstore_id={},
)
이후 네이버 증권 뉴스를 크롤링 해온다. 가볍게 2025년 1월 1일부터 오늘자 까지의 증권뉴스를 가져온다.
extract_news_links로 (날짜, 페이지) 별 뉴스 링크를 가져오고 LangChain의 WebBaseLoader를 이용해 뉴스데이터를 곧바로 Document로 변환하여 FAISS에 적재한다.
적재시에 RecursiveCharacterTextSplitter로 뉴스 기사를 split한 chunk 단위로 적재한다.
from datetime import datetime, timedelta
from naver_news_crawling import extract_num_pagination, extract_news_links, HEADERS
def add_news_into_db():
daily_news_link_prefix = "https://finance.naver.com/news/mainnews.naver?date="
# 오늘 날짜
start_date = datetime(2025, 1, 1)
end_date = datetime.today()
cur_date = start_date
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
while cur_date <= end_date:
date_string = cur_date.strftime("%Y-%m-%d")
daily_news_link = daily_news_link_prefix + date_string
last_page = extract_num_pagination(daily_news_link)
for i in range(int(last_page)):
page_news_link = daily_news_link + f"&page={i + 1}"
news_link_list = extract_news_links(page_news_link)
loader = WebBaseLoader(
web_paths=news_link_list,
bs_kwargs=dict(
parse_only=SoupStrainer(
"div",
attrs={"class": ["newsct_article _article_body", "media_end_head_title"]},
)
),
header_template=HEADERS
)
docs = loader.load()
for doc in docs:
doc.metadata['date'] = date_string
split_docs = text_splitter.split_documents(docs)
vector_db.add_documents(split_docs)
print(f"URL: {page_news_link} / num of docs: {len(docs)} / num of chunks: {len(split_docs)}")
cur_date += timedelta(days=1)
add_news_into_db()
URL: https://finance.naver.com/news/mainnews.naver?date=2025-01-01&page=1 / num of docs: 20 / num of chunks: 45
URL: https://finance.naver.com/news/mainnews.naver?date=2025-01-01&page=2 / num of docs: 20 / num of chunks: 49
URL: https://finance.naver.com/news/mainnews.naver?date=2025-01-01&page=3 / num of docs: 20 / num of chunks: 52
URL: https://finance.naver.com/news/mainnews.naver?date=2025-01-01&page=4 / num of docs: 20 / num of chunks: 56
URL: https://finance.naver.com/news/mainnews.naver?date=2025-01-01&page=5 / num of docs: 20 / num of chunks: 80
URL: https://finance.naver.com/news/mainnews.naver?date=2025-01-01&page=6 / num of docs: 4 / num of chunks: 17
split한 이후에는 뉴스 개수 대비 약 2~4배의 chunk가 생성되어 저장된다.
현재 FAISS 객체는 in-memory에 document를 들고있기 때문에 만약 process가 종료되면 다시 불러와야 한다.
따라서 로컬에 저장해놓고 다시 불러오고 싶다면 save_local 함수로 저장해준다.
# save local
vector_db.save_local("./vectorstore/naver_news_faiss", index_name="2025_january")
# load local
vector_db = FAISS.load_local("./vectorstore/naver_news_faiss",
index_name="index",
embeddings=embedding_fn,
allow_dangerous_deserialization=True)
Multi-Query Retriever
def get_multiquery_retriever(vectorstore) -> MultiQueryRetriever:
"""
Uses LangChain's MultiQueryRetriever to create multiple queries from a single user query.
"""
# We define a prompt that clarifies how to generate sub-queries
mq_prompt = PromptTemplate(
input_variables=["query"],
template=RAGConfig.multiquery_prompt_template
)
# LLM for generating multi-queries
llm = ChatOpenAI(
model_name=RAGConfig.openai_model_name,
temperature=0.7
)
multiquery_retriever = MultiQueryRetriever.from_llm(
retriever=vectorstore.as_retriever(search_kwargs={"k": RAGConfig.top_k}),
llm=llm,
prompt=mq_prompt
)
return multiquery_retriever
mq_retriever = get_multiquery_retriever(vector_db)
multi-query retriever는 세가지 파라미터가 필요하다.
- multi query를 생성해줄 생성 모델
- 생성된 multi query에 대해 유사한 문서를 찾는 retriever
- multi query 생성 지침을 담은 prompt
여기서 생성 모델은 ChatOpenAI를 사용해 GPT-4o-mini가 multi query를 생성하도록 했다.
Retriever는 위에서 생성한 증권 뉴스를 담은 FAISS로 설정한다.
프롬프트는 다음과 같이 증권 분석가의 role을 맡기고 finance context을 추가하여 query를 생성하도록 했다.
multiquery_prompt_template: str = (
"You are an AI assisting a financial analyst. The user query is:\n"
"{question}\n"
"Rewrite this single query into multiple distinct queries that focus on different aspects "
"of the stock/financial domain. At least 3 variants, ensuring coverage of:\n"
"- Different time frames\n"
"- Different possible financial terms or synonyms\n"
"- Additional detail or context about the company or market trends\n"
"- You must create query by korean language"
)
mq_retriever에 대해 샘플 query를 넣으면 다음과 같이 생성된 쿼리를 확인할 수 있다.
mq_retriever.invoke("삼성전자의 최근 주가가 하락세인 이유에 대해 알려줘")
### output
2025-01-30 12:35:31,324 [INFO] httpx - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
2025-01-30 12:35:31,336 [INFO] langchain.retrievers.multi_query - Generated queries:
['1. 삼성전자의 최근 주가 하락 원인에 대한 분석과 시장 반응은 어떤가요?',
'2. 삼성전자의 주가가 지난 6개월 동안 하락한 이유와 그에 따른 재무적 영향은 무엇인가요?',
'3. 삼성전자 주가 하락과 관련된 글로벌 경제 동향이나 산업 내 경쟁 상황은 어떻게 변화하고 있나요?']
mq_retriever를 통해 여러개의 multi query를 취합해 관련된 증권 뉴스를 30개 가져왔다.
이제 해당 30개 뉴스에 대해 reranker를 통해 순위 재정렬을 하여 관련도가 높은 문서 3개를 뽑아보자.
Reranker
Reranker는 langchain의 CrossEncoderReranker로 compressor, 즉 순위 재정렬을 하고 30개->3개 문서로 압축해주는 모듈을 생성해준다.
그 후 ContextualCompressionRetriever에 이전에 선언한 mq_retriever와 compressor를 설정해주면
mq_retriever에서 multi-query를 생성하고 찾은 문서 30개에 대해 compressor가 reranking을 수행해 3개 문서로 줄여준다.
from langchain.retrievers.document_compressors import CrossEncoderReranker
rerank_model = HuggingFaceCrossEncoder(model_name="Dongjin-kr/ko-reranker")
compressor = CrossEncoderReranker(model=rerank_model, top_n=3)
comp_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=mq_retriever
)
comp_retriever.invoke("삼성전자가 최근에 주가가 떨어지는 이유는 뭐야?")
2025-01-30 12:44:01,374 [INFO] httpx - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
2025-01-30 12:44:01,380 [INFO] langchain.retrievers.multi_query - Generated queries: ['1. 삼성전자의 최근 분기 실적 발표가 주가 하락에 미친 영향은 무엇인가요?', '2. 최근 1년 동안 삼성전자의 주가 변동과 관련된 외부 요인은 어떤 것들이 있나요?', '3. 삼성전자의 경쟁 업체와 비교했을 때, 최근 주가 하락의 원인은 무엇인지 분석해 주세요.']
Batches: 0%| | 0/3 [00:00<?, ?it/s]
[Document(id='0cb7f736-2938-4e24-94b3-c0915056a00e', metadata={'source': 'https://n.news.naver.com/mnews/article/119/0002910180', 'date': '2025-01-03'}, page_content='삼성전자 서초사옥 전경. ⓒ데일리안 DB[데일리안 = 황인욱 기자] 지난해 글로벌 증시 대비 국내 증시의 부진이 두드러졌던 한 요인으로 삼성전자의 하락세가 지목된다. 새해 코스피지수가 상승 국면에 들기 위한 조건으로 삼성전자의 반등세가 절실하나 반도체 업황 우려가 여전해 투심 회복에 시간이 걸릴 것이라는 관측이 나온다.3일 한국거래소에 따르면 작년 말 기준 코스피 시가총액은 1963조3288억원으로 연초(2024년 1월 2일 기준) 2147조2239억원 대비 8.56%(183조8951억원) 감소했다. 이 기간 삼성전자 시총은 475조1957억원에서 319조3834억원으로 32.79%(155조8123억원) 줄었다.작년 코스피 전체 시총 감소분에서 삼성전자가 차지하는 비중은 84.73%에 달했다. 시총 1위 삼성전자의 주가가 32.23%(7만8500→5만3200원)로 하락하며 지수도 9.63%(2655.28→2399.49) 내렸다.삼성전자의 주가 하락은 외국인 수급 이탈 영향이 컸다. 외국인은 작년 한 해(2024.1.2~2024.12.30) 동안 코스피 주식을 2조7464억원 순매수하면서도 삼성전자는 10조5197억원이나 순매도했다.특히 외국인은 작년 9월부터 연말까지 순매도 기조를 보이며 지수 하방 압력을 높였는데 이 기간 외국인의 삼성전자 순매도 규모는 19조1979억원으로 코스피 순매도 19조1416억원을 상회했다. 사실상 삼성전자에만 매도 주문을 쏟아낸 셈이다.박소연 신영증권 연구원은 “작년 외국인 순매매 동향을 집계해보면 특이한 현상이 하나 관찰되는데 삼성전자 한 종목을 제외하면 외국인은 한국시장에서 12조원 가까이를 순매수했다는 점”이라며 “12월 탄핵 정국 이후 은행 등 여타 업종으로 매도세가 번지고 있긴 하나 주류라고 보긴 어렵고 여전히 외국인 매도의 70%는 삼성전자에 집중돼 있다”고 설명했다.삼성전자에 대한 투심 악화 배경으로는 범용(레거시) 메모리의 수요 약화와 재고조정 진행으로 업황 회복 시기가 예상보다 늦어질 것이란 우려가 지목된다.'),
Document(id='bcf1cb20-b269-4178-a4ab-5286eb4f201c', metadata={'source': 'https://n.news.naver.com/mnews/article/001/0015149187', 'date': '2025-01-08'}, page_content='풀이된다. 이경민 대신증권 연구원은 "낮아질 대로 낮아진 기대치로 인해 실적이 예상보다 부진했음에도 불구하고 강한 안도 심리를 자극한 것으로 볼 수 있다"며 "삼성전자 주가 수준이 고점 대비 40% 이상 하락하는 등 역사적 저점권에 위치함에 따라 이런 역발상적 주가 흐름이 가능했다고 판단된다"고 말했다. josh@yna.co.kr'),
Document(id='28427d87-bc46-4f31-a5ce-fa51b88cf206', metadata={'source': 'https://n.news.naver.com/mnews/article/417/0001050311', 'date': '2025-01-07'}, page_content='7일 삼성전자 주가가 실적 발표를 하루 앞두고 하락했다. 지난해 11월14일 오후 서울 여의도 한국거래소 홍보관에서 직원이 삼성전자 주가가 표시된 화면을 보고 있다. /사진=조성봉 삼성전자 주가가 지난해 4분기 실적 발표를 하루 앞둔 7일 다시 하락했다. 이달 2일부터 3거래일 연속으로 오른 삼성전자 주가는 지난해 4분기 삼성전자 실적이 부진했을 것이란 증권가 추정이 이어지며 다시 떨어진 것이다. 이날(7일) 삼성전자는 전 거래일 보다 500원(0.89%) 하락한 5만5400원에 거래를 마쳤다. 삼성전자 주가는 지난해 10월16일부터 56거래일 동안 5만원대에 머물고 있다. 마지막으로 6만원대를 기록한 것은 지난해 10월15일(6만1000원)이다. 삼성전자 주가는 이달 2일 5만3400원으로 전 거래일보다 200원 상승한 이후 3일엔 5만4400원, 6일 5만5900원으로 오르며 상승세를 보였다. 하지만 지난해 4분기 삼성전자 실적이 부진할 것으로 추정하며 삼성전자 주가는 올해 국내 증시가 첫 개장한지 4거래일 만에 하락세로 전환했다. 증권가에 따르면 삼성전자의 영업이익 전망치는 지난해 8월 15조원에 가까웠지만 5개월 만에 영업이익 전망치가 반토막이 났다. SK증권은 삼성전자 4분기 연결 영업이익을 7조3000억원을 기록할 것으로 전망했다. 이는 전 분기 대비 20% 감소한 수준이다. 목표주가는 기존 8만6000원에서 7만7000원으로 내려잡았다. 한동희 SK증권 연구원은 "세트 수요 부진과 계절 비수기 영향, 경쟁 강도 심화 등으로 스마트폰과 디스플레이, 비메모리, 메모리 등 주요 사업부 전반적으로 감익이 불가피해 보인다"고 판단했다. 이어 " 메모리에서의 다소 더딘 경쟁력 회복 속 Legacy 시장 내 경쟁 강도 증가로 단기간 내 업종 내 실적 차별화 가시성이 제한적일 것으로 보인다"고 전망했다. 정민규 상상인증권 연구원도 이달 삼성전자 목표주가를 기존 8만5000원에서 7만7000원으로 낮췄다. 정 연구원은 "올 1분기 DDR4와 DDR5 가격')]
(LangChain을 사용하지 않는 방법도 구현해봤는데 아래 접힌글 참고.)
LangChain을 사용하지 않고 구현하는 방법
# ----------------------------------------------------------
# 4. Reranker (CrossEncoder)
# ----------------------------------------------------------
class CustomCrossEncoderReranker:
"""
Simple Cross-Encoder-based reranker that re-scores
(query, doc) pairs and sorts by highest relevance.
"""
def __init__(self, model_name: str):
logger.info(f"Initializing CrossEncoder reranker with: {model_name}")
self.rerank_model = CrossEncoder(model_name)
def rerank(self, query: str, docs: List[Document], top_k: int = RAGConfig.rerank_top_k) -> List[Document]:
"""
Re-ranks the docs by CrossEncoder score. Returns top_n documents.
"""
# Prepare pairs
pair_inputs = [(query, d.page_content) for d in docs]
scores = self.rerank_model.predict(pair_inputs)
# Sort by descending score
idx_scores = list(enumerate(scores))
idx_scores.sort(key=lambda x: x[1], reverse=True)
top_docs = [docs[i] for (i, s) in idx_scores[:top_k]]
logger.info("Reranker top doc scores:")
for i, (idx, s) in enumerate(idx_scores[:top_k]):
logger.info(f"{i + 1}) Score={s:.4f}, doc source={docs[idx].metadata.get('source', '')}")
return top_docs
reranker = CustomCrossEncoderReranker("cross-encoder/ms-marco-MiniLM-L-12-v2")
user_query = "미국의 AI 데이터센터 뉴스와 관련되어 주목할만한 테마가 있어?"
mq_docs = mq_retriever.invoke(user_query)
rerank_docs = reranker.rerank(user_query, mq_docs)
2025-01-30 12:43:05,146 [INFO] RAG-MultiQuery-Reranker - Initializing CrossEncoder reranker with: cross-encoder/ms-marco-MiniLM-L-12-v2
2025-01-30 12:43:05,624 [INFO] sentence_transformers.cross_encoder.CrossEncoder - Use pytorch device: cuda
2025-01-30 12:43:07,699 [INFO] httpx - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
2025-01-30 12:43:07,702 [INFO] langchain.retrievers.multi_query - Generated queries: ['1. 최근 3개월간 미국 AI 데이터센터와 관련된 주요 기업의 주가 변동은 어땠나요? ', '2. 2024년도 미국 AI 데이터센터 투자 전망에 대한 분석과 관련된 주요 경제 지표는 무엇인가요? ', '3. 미국의 AI 데이터센터 시장 성장률과 이로 인한 관련 기업들의 수익성 변화에 대한 장기적인 트렌드는 어떤가요?']
Batches: 0%| | 0/2 [00:00<?, ?it/s]
2025-01-30 12:43:08,164 [INFO] RAG-MultiQuery-Reranker - Reranker top doc scores:
2025-01-30 12:43:08,164 [INFO] RAG-MultiQuery-Reranker - 1) Score=8.2034, doc source=https://n.news.naver.com/mnews/article/009/0005435367
2025-01-30 12:43:08,165 [INFO] RAG-MultiQuery-Reranker - 2) Score=8.1473, doc source=https://n.news.naver.com/mnews/article/016/0002411373
2025-01-30 12:43:08,165 [INFO] RAG-MultiQuery-Reranker - 3) Score=7.9541, doc source=https://n.news.naver.com/mnews/article/009/0005431897
2025-01-30 12:43:08,165 [INFO] RAG-MultiQuery-Reranker - 4) Score=7.9413, doc source=https://n.news.naver.com/mnews/article/011/0004444337
2025-01-30 12:43:08,165 [INFO] RAG-MultiQuery-Reranker - 5) Score=7.9374, doc source=https://n.news.naver.com/mnews/article/018/0005930350
RAG chain 설정
fin_analysis_template = """
[시스템 역할 / 설정]
당신은 “투자 전문가”이다. 주식·투자 전반에 대한 폭넓은 지식과 인사이트를 갖추고 있으며,
증권 뉴스나 관련 문헌(Context)을 빠르게 분석할 수 있다.
[지시사항]
1. 질문 유형 구분
- "분석" 질문: 미래 투자 포인트, 주가 동향, 향후 전망과 그 이유를 설명
- "검색" 질문: 주어진 context 범위 안에서 정확한 사실(fact)을 기술
2. 답변 방식
- 만약 질문이 "분석" 유형이라면:
- (a) LLM이 이미 알고 있는 금융 지식(in-memory)과
- (b) 위 Context(증권 뉴스)를 종합해,
- **미래전망**이나 **투자 기회**, **재무적 분석**, **시장 트렌드** 등을 제시한다.
- 중요한 근거(뉴스 속 정보, 과거 데이터 등)를 요약적으로 포함하고,
- 예측에 대한 논리와 이유를 구체적으로 설명한다.
- 만약 질문이 "검색" 유형이라면:
- (a) 위 Context 내 명시된 정보에 집중하며,
- (b) 확인된 사실만 전달한다 (추측·예측은 삼가기).
- 특정 주가 변동, 공시 정보, 뉴스에 언급된 사실 등에 대해서만 언급하고,
- 맥락 밖 추론은 피한다.
3. 답변 작성 시 유의사항
- “투자 전문가”의 관점에서 **신뢰성** 있고 **명확한 근거**를 제시한다.
- 필요 시 문장 말미에 “예측일 뿐이며, 실제 투자 판단은 본인의 책임”이라는 식의 간단한 주의 문구를 포함해도 좋다.
- 답변을 최대한 간결하고 핵심만 요약하되, 질문이 분석을 요구한다면 **전문적인 어휘**와 **근거**를 충분히 제시한다.
[최종 출력 (Answer)]
위 지시사항과, "투자 전문가"라는 역할, 그리고 두 가지 질문 유형에 따른 답변 방식을 적용하여 사용자 질문에 대한 답변을 완성하세요.
[사용자 질문 (User Query)]
{question}
[주어진 Context (증권 뉴스)]
{context}
"""
prompt = PromptTemplate.from_template(fin_analysis_template)
투자 전문가의 role을 맡기고 증권 뉴스에서 분석, 검색을 하도록 prompt를 설정한다.
이후 rag_chain을 생성할 때 context에 comp_retriever을 넣으면 multi-query, reranker가 적용된다.
generator = ChatOpenAI(model_name=RAGConfig.openai_model_name, temperature=0)
rag_chain = (
{"context": comp_retriever, "question": RunnablePassthrough()}
| prompt
| generator
| StrOutputParser()
)
실행 결과는 아래와 같다.
rag_chain.invoke("삼성전자 지금 사도 되나요?")
삼성전자의 현재 주가에 대한 투자 결정을 고려할 때, 여러 요소를 분석해볼 필요가 있습니다.
1. **주가 현황**: 삼성전자는 최근 5만4300원에 거래되고 있으며, 이는 지난해 1월 22일 종가인 7만5100원과 비교해 28% 하락한 수치입니다. 또한, 반년 전 52주 최고가인 8만8800원 대비 39% 낮은 가격입니다.
2. **외국인 투자자 매도**: 외국인 투자자들이 올해 들어 삼성전자를 대규모로 매도하고 있으며, 이는 주가 하락의 주요 원인 중 하나입니다. 1월 2일부터 21일 사이에만 7603억원어치를 순매도했습니다.
3. **실적 및 전망**: 삼성전자는 지난해 4분기 연결 매출액 75조원, 영업이익 6조5000억원을 기록했으나, 전 분기 대비 각각 5.18%, 29.19% 감소했습니다. 이는 시장 기대치를 밑돌며 부진한 실적을 나타냅니다. 그러나 전문가들은 현재 주가가 '딥밸류' 구간에 있으며, 저가 매수 전략이 유효하다고 평가하고 있습니다.
4. **미래 전망**: 증권가에서는 올해 하반기부터 실적 개선이 예상되며, '갤럭시 S25' 발매와 메모리 반도체 수급 개선이 주요 상승 동력으로 작용할 것으로 보입니다. 또한, 현재 주가는 대부분의 악재를 반영한 상태로, 작은 호재에도 민감하게 반응할 가능성이 있습니다.
결론적으로, 삼성전자는 현재 저가 매수 기회로 평가받고 있으며, 향후 실적 개선이 기대되는 상황입니다. 그러나 외국인 투자자의 매도세와 부진한 실적이 여전히 주가에 부담을 주고 있으므로, 신중한 접근이 필요합니다.
**예측일 뿐이며, 실제 투자 판단은 본인의 책임입니다.**
Langsmith Trace
구현한 RAG 시스템에 대해 langsmith trace를 살펴보면 다음과 같다.
multi query retriever에서 입력된 query를 기반으로 3개의 추가 쿼리를 생성한 후 각 query에 대하여 VectorStoreRetriever를 수행해 문서들을 가져온다. 총 76개의 문서를 가져왔다.
이후 reranker 역할을 하는 ContextualCompressionRetriever가 76개의 문서를 3개 문서로 압축하였다.
마지막 generator의 prompt를 보면 context에 3개의 뉴스가 들어간 것을 확인할 수 있고,
해당 뉴스 기반으로 답변을 생성하게 된다.
'AI, 머신러닝' 카테고리의 다른 글
LLM의 효율적인 fine-tuning을 위한 PEFT 기법 - LoRA 알아보기 (0) | 2025.02.07 |
---|---|
[Spark] 빅데이터 분산처리를 위한 PySpark 설치와 PostgreSQL 연결하고 세션 생성하기. (1) | 2025.02.02 |
네이버 증권뉴스 크롤링으로 RAG 데이터셋 만들기 (python, BeautifulSoup4) (0) | 2025.01.30 |
RAG 시스템 강화하기 - Multi-Query, Self-Query, Reranker 알아보기 (0) | 2025.01.29 |
OpenAI API와 LangChain으로 만드는 고성능 RAG 시스템 구현하기 (0) | 2025.01.28 |