data science/AI Agents

RAG (Retrieval-Augmented Generation) 시스템구축

꼰대코더 2025. 10. 11. 02:03

LLM 에 단순히 질문하는 것 보다는 정보를 같이 제공함으로써 얻는 결과는 보다 구체적이고 사실적인 결과를 얻을 수 있다.

이때 정보는 문장이 벡터화된 DB로부터 유의도가 높은 순서대로 검색되게 된다. 이를 RAG 이라 한다.

 

정보 데이터(PDF) 등록

   gemini 또는 OpenAI embedding 모델사용

   Embedding 데이터베이스는 Qdrant 클라우드 FREE TIER 이용

정보검색

   질문을 그대로 검색하기 보단 agno Agent를 통해 질문의 의도를 파악하여 구체적인 질문으로 변환

   변환된 질문을 Embedding 데이터베이스로 부터 유이도가 높은 검색 결과를 이용하여 agno Agent 를 통해 정리

 

Qdrant 
https://qdrant.tech/ 에서 구글계정으로 Sign Up하면 FREE TIER 를 제공받는다.

 

LangChain

pip install qdrant-client
pip install langchain-qdrant
pip install langchain-community

 

agno

pip install agno

 

import

import os
import tempfile
from datetime import datetime
from typing import List

import google.generativeai as genai
from agno.agent import Agent
from agno.models.google import Gemini
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_qdrant import QdrantVectorStore
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams
from langchain_core.embeddings import Embeddings

 

QdrantClient 생성

qdrant_client = QdrantClient(
    url="Qdrant에서 생성한 Cluster의 Endpoint",
    api_key="Qdrant에서 생성한 Cluster의 API key",
    timeout=60
    )

 

아래 생성할 QdrantVectorStore 의  embedding 파라미터에 지정할 Embeddings의 클래스를 정의

※ langchain_core.embeddings.Embeddings 클래스를 계승하고 override 메서드는 아래와 같다.
    embed_documents(texts)    :  Embed search docs.
    embed_query(text)               : Embed query text.

 

※ 본인의 테스트 결과로는 dimension이 두배인 openai 의 embedding 결과가 좋게 나왔다.

class GeminiEmbedder(Embeddings):
    def __init__(self, model_name="models/text-embedding-004"):
        genai.configure(api_key=st.session_state.google_api_key)
        self.model = model_name

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        return [self.embed_query(text) for text in texts]

    def embed_query(self, text: str) -> List[float]:
        response = genai.embed_content(
            model=self.model,
            content=text,
            task_type="retrieval_document"
        )
        return response['embedding']

 

class OpenAIEmbedder(Embeddings):
    def __init__(self, model_name="text-embedding-3-small"):
        self.openai_client = openai.Client(api_key="openai_api_key")
        self.model = model_name

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        return [self.embed_query(text) for text in texts]

    def embed_query(self, text: str) -> List[float]:
        response = self.openai_client.embeddings.create(
            model=self.model,
            input=text,
        ).data[0].embedding

        return response

 

맨 처음엔 Qdrant 에 Collection을 생성 

qdran_client .create_collection(
    collection_name= "저장될이름 보통 db의 테이명이라 보면 된다." ,
    vectors_config=VectorParams(
        size=768,  # 중요: gemini는 768, openai는 1536 이다.
        distance=Distance.COSINE
    )

 

QdrantVectorStore 생성
  ⇒ PDF로 분할된 텍스트의 벡터화와 Qdrant에 저장

  ⇒ 검색

vector_store = QdrantVectorStore(
    client=qdran_client,
    collection_name="저장될이름 보통 db의 테이명이라 보면 된다.",
    embedding=GeminiEmbedder() 또는 OpenAIEmbedder()
)

 

Agno Agents

1. agent_rewriter

agent_rewriter = Agent(
    name="Query Rewriter",
    model=Gemini(id="gemini-exp-1206"),
    instructions="""당신은 질문을 더 명확하고 구체적으로 재구성하는 전문가입니다.
            당신의 임무는 다음과 같습니다:
            사용자의 질문을 분석한다.
            질문을 더 구체적이고 검색 친화적으로 다시 작성한다.
            약어나 기술 용어가 있다면 풀어서 쓴다.
            추가적인 설명이나 텍스트 없이, 다시 작성된 질문만 반환한다.

            예시 1:
            사용자: "ML에 대해 뭐라고 되어 있어?"
            출력: "Machine Learning(ML)의 주요 개념, 기술, 그리고 응용 분야에 대해 문맥에서 논의된 내용을 설명하라."

            예시 2:
            사용자: "transformers에 대해 말해줘"
            출력: "자연어 처리와 딥러닝에서 Transformer 신경망의 구조, 작동 원리, 그리고 응용 분야를 설명하라."
    """,
    show_tool_calls=False,
    markdown=True,
)

 

2. agent_rag

agent_rag = Agent(
    name="Gemini RAG Agent",
    model=Gemini(id="gemini-2.0-flash-thinking-exp-01-21"),
    instructions="""당신은 정확한 답변을 제공하는 지능형 에이전트(Intelligent Agent) 입니다.
        다음 지침을 따르십시오:
       
        문서로부터 문맥이 주어졌을 때:
        - 제공된 문서의 정보에 집중한다.
        - 구체적이고 정확한 세부 사항을 인용하여 답변한다.
       
        웹 검색 결과가 주어졌을 때:
        - 해당 정보가 웹 검색을 통해 얻은 것임을 명확히 표시한다.
        - 검색 결과를 명료하게 종합하여 제시한다.
   
    항상 높은 정확성(accuracy) 과 명확성(clarity) 을 유지하여 응답해야 한다
    """,
    show_tool_calls=True,
    markdown=True,
)

 

PDF 화일의 텍스트화와 분할

def process_pdf(file) -> List:
    """Process PDF file and add source metadata."""
    try:
        with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file:
            tmp_file.write(file.getvalue())
            loader = PyPDFLoader(tmp_file.name)
            documents = loader.load()
           
            # Add source metadata
            for doc in documents:
                doc.metadata.update({
                    "source_type": "pdf",
                    "file_name": file.name,
                    "timestamp": datetime.now().isoformat()
                })
               
            text_splitter = RecursiveCharacterTextSplitter(
                chunk_size=1000,
                chunk_overlap=200
            )
            return text_splitter.split_documents(documents)

 

벡터화 저장

texts = process_pdf(uploaded_file)
vector_store.add_documents(texts)

 

질문의 재정의와 벡터화 후 검색 (상위 5개, 유의도는 0.7 이상)

context = ""
 
rewritten_query = agent_rewriter.run(prompt).content
 
retriever = vector_store.as_retriever(
    search_type="similarity_score_threshold",
    search_kwargs={
        "k": 5,
        "score_threshold": 0.7
    }
)
docs = retriever.invoke(rewritten_query)
if docs:
    context = "\n\n".join([d.page_content for d in docs])

 

최종 결과

full_prompt = f"""Context: {context}

                Original Question: {prompt}
                Rewritten Question: {rewritten_query}

                Please provide a comprehensive answer based on the available information.
            """

response = agent_ rag.run(full_prompt)
print(response.content)

'data science > AI Agents' 카테고리의 다른 글

Coordinate(Orchestrate) Agents - agno  (0) 2025.10.12
Multi-Agents : 채용 에이전트  (0) 2025.10.12
memory - mem0 ("mem-zero")  (0) 2025.10.11
google spread sheet 액세스를 위한 작업  (0) 2025.08.23
AI Agents Stack  (0) 2025.08.17