{"id":10493,"date":"2025-06-16T12:05:35","date_gmt":"2025-06-16T03:05:35","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=10493"},"modified":"2025-07-16T14:12:00","modified_gmt":"2025-07-16T05:12:00","slug":"rag-%ec%b1%97%eb%b4%87-%ea%b5%ac%ec%b6%95-%ea%b0%80%ec%9d%b4%eb%93%9c","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=10493","title":{"rendered":"RAG \ucc57\ubd07 \uad6c\ucd95 \uac00\uc774\ub4dc"},"content":{"rendered":"<h1>RAG \ucc57\ubd07 \uad6c\ucd95 \uac00\uc774\ub4dc<\/h1>\n<h2>\uac1c\uc694<\/h2>\n<p>RAG(Retrieval-Augmented Generation) \ucc57\ubd07\uc740 \uc678\ubd80 \uc9c0\uc2dd\ubca0\uc774\uc2a4\ub97c \ud65c\uc6a9\ud574 \ub354 \uc815\ud655\ud558\uace0 \ucd5c\uc2e0 \uc815\ubcf4\ub97c \uc81c\uacf5\ud558\ub294 AI \ucc57\ubd07\uc785\ub2c8\ub2e4. \uc774 \uac00\uc774\ub4dc\ub294 RAG \ucc57\ubd07\uc744 \uad6c\ucd95\ud558\ub294 \uacfc\uc815\uc744 \ub2e8\uacc4\ubcc4\ub85c \uc124\uba85\ud569\ub2c8\ub2e4.<\/p>\n<h2>RAG\ub780 \ubb34\uc5c7\uc778\uac00?<\/h2>\n<p>RAG\ub294 <strong>\uac80\uc0c9(Retrieval)<\/strong>\uacfc <strong>\uc0dd\uc131(Generation)<\/strong>\uc744 \uacb0\ud569\ud55c \uc811\uadfc \ubc29\uc2dd\uc785\ub2c8\ub2e4. \uc0ac\uc6a9\uc790 \uc9c8\ubb38\uc5d0 \ub300\ud574 \uad00\ub828 \ubb38\uc11c\ub97c \uba3c\uc800 \uac80\uc0c9\ud558\uace0, \uadf8 \uc815\ubcf4\ub97c \ubc14\ud0d5\uc73c\ub85c \ub2f5\ubcc0\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4.<\/p>\n<h3>RAG\uc758 \uc7a5\uc810<\/h3>\n<ul>\n<li><strong>\uc815\ud655\uc131<\/strong>: \uc2e4\uc81c \ubb38\uc11c\uc5d0 \uae30\ubc18\ud55c \ub2f5\ubcc0 \uc81c\uacf5<\/li>\n<li><strong>\ucd5c\uc2e0\uc131<\/strong>: \uc9c0\uc2dd\ubca0\uc774\uc2a4 \uc5c5\ub370\uc774\ud2b8\ub85c \ucd5c\uc2e0 \uc815\ubcf4 \ubc18\uc601<\/li>\n<li><strong>\ud22c\uba85\uc131<\/strong>: \ub2f5\ubcc0\uc758 \ucd9c\ucc98\ub97c \uba85\ud655\ud788 \uc81c\uc2dc<\/li>\n<li><strong>\ube44\uc6a9 \ud6a8\uc728\uc131<\/strong>: \ubaa8\ub378 \uc7ac\ud559\uc2b5 \uc5c6\uc774 \uc9c0\uc2dd \ud655\uc7a5 \uac00\ub2a5<\/li>\n<\/ul>\n<h2>\uc2dc\uc2a4\ud15c \uc544\ud0a4\ud14d\ucc98<\/h2>\n<pre><code>\uc0ac\uc6a9\uc790 \uc9c8\ubb38 \u2192 \uc784\ubca0\ub529 \u2192 \ubca1\ud130 \uac80\uc0c9 \u2192 \ubb38\uc11c \uac80\uc0c9 \u2192 \ucee8\ud14d\uc2a4\ud2b8 + \uc9c8\ubb38 \u2192 LLM \u2192 \ub2f5\ubcc0<\/code><\/pre>\n<h3>\uc8fc\uc694 \uad6c\uc131 \uc694\uc18c<\/h3>\n<ol>\n<li><strong>\ubb38\uc11c \ucc98\ub9ac \ud30c\uc774\ud504\ub77c\uc778<\/strong>: \uc6d0\ubcf8 \ubb38\uc11c\ub97c \uccad\ud06c \ub2e8\uc704\ub85c \ubd84\ud560\ud558\uace0 \ubca1\ud130\ud654<\/li>\n<li><strong>\ubca1\ud130 \ub370\uc774\ud130\ubca0\uc774\uc2a4<\/strong>: \ubb38\uc11c \uc784\ubca0\ub529\uc744 \uc800\uc7a5\ud558\uace0 \uc720\uc0ac\ub3c4 \uac80\uc0c9 \uc218\ud589<\/li>\n<li><strong>\uac80\uc0c9 \uc5d4\uc9c4<\/strong>: \uc0ac\uc6a9\uc790 \uc9c8\ubb38\uacfc \uad00\ub828\ub41c \ubb38\uc11c \uccad\ud06c\ub97c \ucc3e\uc544 \ubc18\ud658<\/li>\n<li><strong>\uc0dd\uc131 \ubaa8\ub378<\/strong>: \uac80\uc0c9\ub41c \ucee8\ud14d\uc2a4\ud2b8\ub97c \ud65c\uc6a9\ud574 \ucd5c\uc885 \ub2f5\ubcc0 \uc0dd\uc131<\/li>\n<\/ol>\n<h2>\ub2e8\uacc4\ubcc4 \uad6c\ucd95 \uac00\uc774\ub4dc<\/h2>\n<h3>1\ub2e8\uacc4: \ud658\uacbd \uc124\uc815<\/h3>\n<pre><code class=\"language-bash\"># \ud544\uc694\ud55c \ub77c\uc774\ube0c\ub7ec\ub9ac \uc124\uce58\npip install langchain chromadb openai sentence-transformers pypdf\n\npip install -U langchain-community\npip install -U langchain-openai<\/code><\/pre>\n<h3>2\ub2e8\uacc4: \ubb38\uc11c \uc804\ucc98\ub9ac<\/h3>\n<pre><code class=\"language-python\">from langchain_community.document_loaders import PyPDFLoader\nfrom langchain_community.document_loaders import TextLoader\nfrom langchain.text_splitter import RecursiveCharacterTextSplitter\n\ndef load_documents(file_path):\n    &quot;&quot;&quot;\ubb38\uc11c \ub85c\ub4dc&quot;&quot;&quot;\n    if file_path.endswith(&#039;.pdf&#039;):\n        loader = PyPDFLoader(file_path)\n    else:\n        loader = TextLoader(file_path)\n    return loader.load()\n\ndef split_documents(documents):\n    &quot;&quot;&quot;\ubb38\uc11c\ub97c \uccad\ud06c\ub85c \ubd84\ud560&quot;&quot;&quot;\n    text_splitter = RecursiveCharacterTextSplitter(\n        chunk_size=1000,\n        chunk_overlap=200,\n        length_function=len\n    )\n    return text_splitter.split_documents(documents)<\/code><\/pre>\n<h3>3\ub2e8\uacc4: \ubca1\ud130 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uad6c\ucd95<\/h3>\n<pre><code class=\"language-python\">from langchain_community.vectorstores import Chroma\nfrom langchain_community.embeddings import OpenAIEmbeddings\n# from langchain_openai import OpenAIEmbeddings\n\ndef create_vectorstore(documents):\n    &quot;&quot;&quot;\ubca1\ud130 \uc800\uc7a5\uc18c \uc0dd\uc131&quot;&quot;&quot;\n    embeddings = OpenAIEmbeddings()\n    vectorstore = Chroma.from_documents(\n        documents=documents,\n        embedding=embeddings,\n        persist_directory=&quot;.\/chroma_db&quot;\n    )\n    return vectorstore<\/code><\/pre>\n<h3>4\ub2e8\uacc4: \uac80\uc0c9 \uc2dc\uc2a4\ud15c \uad6c\ud604<\/h3>\n<pre><code class=\"language-python\">def create_retriever(vectorstore, search_type=&quot;similarity&quot;, k=5):\n    &quot;&quot;&quot;\uac80\uc0c9\uae30 \uc0dd\uc131&quot;&quot;&quot;\n    retriever = vectorstore.as_retriever(\n        search_type=search_type,\n        search_kwargs={&quot;k&quot;: k}\n    )\n    return retriever<\/code><\/pre>\n<h3>5\ub2e8\uacc4: RAG \uccb4\uc778 \uad6c\uc131<\/h3>\n<pre><code class=\"language-python\">from langchain.chains import RetrievalQA\nfrom langchain_community.llms import OpenAI\n\ndef create_rag_chain(retriever):\n    &quot;&quot;&quot;RAG \uccb4\uc778 \uc0dd\uc131&quot;&quot;&quot;\n    llm = OpenAI(temperature=0)\n    qa_chain = RetrievalQA.from_chain_type(\n        llm=llm,\n        chain_type=&quot;stuff&quot;,\n        retriever=retriever,\n        return_source_documents=True\n    )\n    return qa_chain<\/code><\/pre>\n<h3>6\ub2e8\uacc4: \ucc57\ubd07 \uc778\ud130\ud398\uc774\uc2a4 \uad6c\ud604<\/h3>\n<p><a href=\"https:\/\/velog.io\/@ji1kang\/OpenAI%EC%9D%98-API-Key-%EB%B0%9C%EA%B8%89-%EB%B0%9B%EA%B3%A0-%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%95%98%EA%B8%B0\">OPENAI_API_KEY \ubc1c\uae09\ubc1b\uae30<\/a><\/p>\n<pre><code class=\"language-python\">import os\nfrom langchain_community.document_loaders import PyPDFLoader\nfrom langchain_community.document_loaders import TextLoader\nfrom langchain.text_splitter import RecursiveCharacterTextSplitter\nfrom langchain_community.vectorstores import Chroma\nfrom langchain_openai import OpenAIEmbeddings\nfrom langchain.chains import RetrievalQA\nfrom langchain_openai import OpenAI\nfrom langchain_openai import ChatOpenAI\n\nos.environ[&quot;OPENAI_API_KEY&quot;] = &quot;your-openai-api-key-here&quot;\n\ndef load_documents(file_path):\n    &quot;&quot;&quot;\ubb38\uc11c \ub85c\ub4dc&quot;&quot;&quot;\n    if file_path.endswith(&#039;.pdf&#039;):\n        loader = PyPDFLoader(file_path)\n    else:\n        loader = TextLoader(file_path)\n    return loader.load()\n\ndef split_documents(documents):\n    &quot;&quot;&quot;\ubb38\uc11c\ub97c \uccad\ud06c\ub85c \ubd84\ud560&quot;&quot;&quot;\n    text_splitter = RecursiveCharacterTextSplitter(\n        chunk_size=1000,\n        chunk_overlap=200,\n        length_function=len\n    )\n    return text_splitter.split_documents(documents)\n\ndef create_vectorstore(documents):\n    &quot;&quot;&quot;\ubca1\ud130 \uc800\uc7a5\uc18c \uc0dd\uc131&quot;&quot;&quot;\n    embeddings = OpenAIEmbeddings()\n    vectorstore = Chroma.from_documents(\n        documents=documents,\n        embedding=embeddings,\n        persist_directory=&quot;.\/chroma_db&quot;\n    )\n    return vectorstore\n\ndef create_retriever(vectorstore, search_type=&quot;similarity&quot;, k=5):\n    &quot;&quot;&quot;\uac80\uc0c9\uae30 \uc0dd\uc131&quot;&quot;&quot;\n    retriever = vectorstore.as_retriever(\n        search_type=search_type,\n        search_kwargs={&quot;k&quot;: k}\n    )\n    return retriever\n\ndef create_rag_chain(retriever):\n    &quot;&quot;&quot;RAG \uccb4\uc778 \uc0dd\uc131&quot;&quot;&quot;\n    # llm = OpenAI(temperature=0)\n    llm = ChatOpenAI(\n        model=&quot;gpt-4o-mini&quot;,\n        temperature=0,\n        max_tokens=200  # \uc751\ub2f5 \uae38\uc774 \uc81c\ud55c\n    )\n    qa_chain = RetrievalQA.from_chain_type(\n        llm=llm,\n        chain_type=&quot;stuff&quot;,\n        retriever=retriever,\n        return_source_documents=True\n    )\n    return qa_chain\n\nclass RAGChatbot:\n    def __init__(self, documents_path):\n        # \ubb38\uc11c \ub85c\ub4dc \ubc0f \uc804\ucc98\ub9ac\n        documents = load_documents(documents_path)\n        splits = split_documents(documents)\n\n        # \ubca1\ud130 \uc800\uc7a5\uc18c \uc0dd\uc131\n        self.vectorstore = create_vectorstore(splits)\n\n        # \uac80\uc0c9\uae30 \ubc0f \uccb4\uc778 \uc0dd\uc131\n        retriever = create_retriever(self.vectorstore)\n        self.qa_chain = create_rag_chain(retriever)\n\n    def chat(self, question):\n        &quot;&quot;&quot;\uc0ac\uc6a9\uc790 \uc9c8\ubb38\uc5d0 \ub300\ud55c \ub2f5\ubcc0 \uc0dd\uc131&quot;&quot;&quot;\n        result = self.qa_chain.invoke({&quot;query&quot;: question})\n        return {\n            &quot;answer&quot;: result[&quot;result&quot;],\n            &quot;sources&quot;: result[&quot;source_documents&quot;]\n        }\n\n# \uc0ac\uc6a9 \uc608\uc2dc\nchatbot = RAGChatbot(&quot;.\/law.pdf&quot;)\nresponse = chatbot.chat(&quot;\uc131\ub144\uc758 \uae30\uc900\uc774 \ub418\ub294 \ub098\uc774\uac00 \uc5b4\ub5bb\uac8c \ub418\uc9c0?&quot;)\nprint(response[&quot;answer&quot;])<\/code><\/pre>\n<h2>\uc131\ub2a5 \ucd5c\uc801\ud654<\/h2>\n<p><font color=red><b>\uc5ec\uae30\uc11c\ubd80\ud130 \uc544\ub798\uc758 \ubb38\uc11c\ub294 \uc778\uacf5\uc9c0\ub2a5\uc5d0 \uc758\ud574 \uc791\uc131\ub418\uc5c8\uc73c\uba70, \ud14c\uc2a4\ud2b8 \ub418\uc9c0 \uc54a\uc740 \ucf54\ub4dc\uc785\ub2c8\ub2e4.<\/b><\/font><\/p>\n<h3>\uccad\ud06c \ud06c\uae30 \uc870\uc815<\/h3>\n<pre><code class=\"language-python\"># \ub2e4\uc591\ud55c \uccad\ud06c \ud06c\uae30 \uc2e4\ud5d8\nchunk_sizes = [500, 1000, 1500, 2000]\nfor size in chunk_sizes:\n    text_splitter = RecursiveCharacterTextSplitter(\n        chunk_size=size,\n        chunk_overlap=size\/\/5\n    )\n    # \uc131\ub2a5 \ud3c9\uac00<\/code><\/pre>\n<h3>\ud558\uc774\ube0c\ub9ac\ub4dc \uac80\uc0c9<\/h3>\n<pre><code class=\"language-python\">from langchain.retrievers import EnsembleRetriever\nfrom langchain.retrievers import BM25Retriever\n\ndef create_hybrid_retriever(documents, vectorstore):\n    &quot;&quot;&quot;\ud558\uc774\ube0c\ub9ac\ub4dc \uac80\uc0c9\uae30 \uc0dd\uc131&quot;&quot;&quot;\n    # \ud0a4\uc6cc\ub4dc \uae30\ubc18 \uac80\uc0c9\n    bm25_retriever = BM25Retriever.from_documents(documents)\n\n    # \uc758\ubbf8 \uae30\ubc18 \uac80\uc0c9\n    vector_retriever = vectorstore.as_retriever()\n\n    # \uc559\uc0c1\ube14 \uac80\uc0c9\uae30\n    ensemble_retriever = EnsembleRetriever(\n        retrievers=[bm25_retriever, vector_retriever],\n        weights=[0.5, 0.5]\n    )\n    return ensemble_retriever<\/code><\/pre>\n<h3>\uc7ac\ub7ad\ud0b9 \uc2dc\uc2a4\ud15c<\/h3>\n<pre><code class=\"language-python\">from langchain.document_transformers import LongContextReorder\n\ndef rerank_documents(documents, query):\n    &quot;&quot;&quot;\ubb38\uc11c \uc7ac\ub7ad\ud0b9&quot;&quot;&quot;\n    reordering = LongContextReorder()\n    reordered_docs = reordering.transform_documents(documents)\n    return reordered_docs<\/code><\/pre>\n<h2>\uace0\uae09 \uae30\ub2a5<\/h2>\n<h3>\ub300\ud654 \uba54\ubaa8\ub9ac \ucd94\uac00<\/h3>\n<pre><code class=\"language-python\">from langchain.memory import ConversationBufferMemory\nfrom langchain.chains import ConversationalRetrievalChain\n\ndef create_conversational_chain(retriever):\n    &quot;&quot;&quot;\ub300\ud654\ud615 RAG \uccb4\uc778 \uc0dd\uc131&quot;&quot;&quot;\n    memory = ConversationBufferMemory(\n        memory_key=&quot;chat_history&quot;,\n        return_messages=True\n    )\n\n    qa_chain = ConversationalRetrievalChain.from_llm(\n        llm=OpenAI(temperature=0),\n        retriever=retriever,\n        memory=memory\n    )\n    return qa_chain<\/code><\/pre>\n<h3>\uc2e4\uc2dc\uac04 \ubb38\uc11c \uc5c5\ub370\uc774\ud2b8<\/h3>\n<pre><code class=\"language-python\">def update_vectorstore(vectorstore, new_documents):\n    &quot;&quot;&quot;\ubca1\ud130 \uc800\uc7a5\uc18c \uc5c5\ub370\uc774\ud2b8&quot;&quot;&quot;\n    splits = split_documents(new_documents)\n    vectorstore.add_documents(splits)\n    vectorstore.persist()<\/code><\/pre>\n<h3>\ub2f5\ubcc0 \ud488\uc9c8 \ud3c9\uac00<\/h3>\n<pre><code class=\"language-python\">from langchain.evaluation.qa import QAEvalChain\n\ndef evaluate_rag_system(qa_chain, test_questions):\n    &quot;&quot;&quot;RAG \uc2dc\uc2a4\ud15c \ud3c9\uac00&quot;&quot;&quot;\n    eval_chain = QAEvalChain.from_llm(OpenAI(temperature=0))\n\n    results = []\n    for question in test_questions:\n        result = qa_chain({&quot;query&quot;: question})\n        evaluation = eval_chain.evaluate(\n            question,\n            result[&quot;result&quot;],\n            result[&quot;source_documents&quot;]\n        )\n        results.append(evaluation)\n\n    return results<\/code><\/pre>\n<h2>\ubc30\ud3ec \ubc0f \ubaa8\ub2c8\ud130\ub9c1<\/h2>\n<h3>FastAPI\ub97c \uc774\uc6a9\ud55c API \uc11c\ubc84<\/h3>\n<pre><code class=\"language-python\">from fastapi import FastAPI\nfrom pydantic import BaseModel\n\napp = FastAPI()\nchatbot = RAGChatbot(&quot;.\/documents\/&quot;)\n\nclass ChatRequest(BaseModel):\n    question: str\n\n@app.post(&quot;\/chat&quot;)\nasync def chat_endpoint(request: ChatRequest):\n    response = chatbot.chat(request.question)\n    return response<\/code><\/pre>\n<h3>\ub85c\uae45 \ubc0f \ubaa8\ub2c8\ud130\ub9c1<\/h3>\n<pre><code class=\"language-python\">import logging\nfrom datetime import datetime\n\ndef setup_logging():\n    logging.basicConfig(\n        level=logging.INFO,\n        format=&#039;%(asctime)s - %(levelname)s - %(message)s&#039;,\n        handlers=[\n            logging.FileHandler(&#039;rag_chatbot.log&#039;),\n            logging.StreamHandler()\n        ]\n    )\n\ndef log_interaction(question, answer, sources):\n    &quot;&quot;&quot;\uc0ac\uc6a9\uc790 \uc0c1\ud638\uc791\uc6a9 \ub85c\uadf8&quot;&quot;&quot;\n    logging.info(f&quot;Question: {question}&quot;)\n    logging.info(f&quot;Answer: {answer}&quot;)\n    logging.info(f&quot;Sources: {len(sources)} documents&quot;)<\/code><\/pre>\n<h2>\uc8fc\uc758\uc0ac\ud56d \ubc0f \ubaa8\ubc94 \uc0ac\ub840<\/h2>\n<h3>\ubcf4\uc548 \uace0\ub824\uc0ac\ud56d<\/h3>\n<ul>\n<li>API \ud0a4 \ubc0f \ubbfc\uac10\ud55c \uc815\ubcf4\ub294 \ud658\uacbd \ubcc0\uc218\ub85c \uad00\ub9ac<\/li>\n<li>\uc0ac\uc6a9\uc790 \uc785\ub825 \uac80\uc99d \ubc0f sanitization \ud544\uc218<\/li>\n<li>\uc811\uadfc \uad8c\ud55c \ubc0f \uc778\uc99d \uc2dc\uc2a4\ud15c \uad6c\ud604<\/li>\n<\/ul>\n<h3>\uc131\ub2a5 \ucd5c\uc801\ud654<\/h3>\n<ul>\n<li>\uce90\uc2f1 \uc2dc\uc2a4\ud15c \ub3c4\uc785\uc73c\ub85c \uc751\ub2f5 \uc2dc\uac04 \ub2e8\ucd95<\/li>\n<li>\ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud1b5\ud55c \ub3d9\uc2dc \uc694\uccad \ucc98\ub9ac<\/li>\n<li>\ubca1\ud130 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc778\ub371\uc2f1 \ucd5c\uc801\ud654<\/li>\n<\/ul>\n<h3>\ub370\uc774\ud130 \ud488\uc9c8 \uad00\ub9ac<\/h3>\n<ul>\n<li>\uc815\uae30\uc801\uc778 \ubb38\uc11c \uc5c5\ub370\uc774\ud2b8 \ubc0f \ud488\uc9c8 \uac80\ud1a0<\/li>\n<li>\uc911\ubcf5 \ubb38\uc11c \uc81c\uac70 \ubc0f \uc77c\uad00\uc131 \uc720\uc9c0<\/li>\n<li>\uc0ac\uc6a9\uc790 \ud53c\ub4dc\ubc31\uc744 \ud1b5\ud55c \uc9c0\uc18d\uc801\uc778 \uac1c\uc120<\/li>\n<\/ul>\n<h2>\uacb0\ub860<\/h2>\n<p>RAG \ucc57\ubd07\uc740 \uae30\uc874 LLM\uc758 \ud55c\uacc4\ub97c \uadf9\ubcf5\ud558\uace0 \ub3c4\uba54\uc778 \ud2b9\ud654\ub41c \uace0\ud488\uc9c8 \ub2f5\ubcc0\uc744 \uc81c\uacf5\ud558\ub294 \uac15\ub825\ud55c \uc194\ub8e8\uc158\uc785\ub2c8\ub2e4. \uc774 \uac00\uc774\ub4dc\ub97c \ud1b5\ud574 \uae30\ubcf8\uc801\uc778 RAG \uc2dc\uc2a4\ud15c\ubd80\ud130 \uace0\uae09 \uae30\ub2a5\uae4c\uc9c0 \ub2e8\uacc4\ubcc4\ub85c \uad6c\ucd95\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc131\uacf5\uc801\uc778 RAG \ucc57\ubd07 \uad6c\ucd95\uc744 \uc704\ud574\uc11c\ub294 \uc9c0\uc18d\uc801\uc778 \ubaa8\ub2c8\ud130\ub9c1\uacfc \uac1c\uc120\uc774 \ud544\uc694\ud558\uba70, \uc0ac\uc6a9\uc790 \ud53c\ub4dc\ubc31\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ubc18\uc601\ud574 \uc2dc\uc2a4\ud15c\uc758 \ud488\uc9c8\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<h2>\ucc38\uace0 \uc790\ub8cc<\/h2>\n<ul>\n<li><a href=\"https:\/\/python.langchain.com\/\">LangChain \uacf5\uc2dd \ubb38\uc11c<\/a><\/li>\n<li><a href=\"https:\/\/platform.openai.com\/docs\">OpenAI API \ubb38\uc11c<\/a><\/li>\n<li><a href=\"https:\/\/www.trychroma.com\/\">Chroma \ubca1\ud130 \ub370\uc774\ud130\ubca0\uc774\uc2a4<\/a><\/li>\n<li><a href=\"https:\/\/www.sbert.net\/\">Sentence Transformers<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>RAG \ucc57\ubd07 \uad6c\ucd95 \uac00\uc774\ub4dc \uac1c\uc694 RAG(Retrieval-Augmented Generation) \ucc57\ubd07\uc740 \uc678\ubd80 \uc9c0\uc2dd\ubca0\uc774\uc2a4\ub97c \ud65c\uc6a9\ud574 \ub354 \uc815\ud655\ud558\uace0 \ucd5c\uc2e0 \uc815\ubcf4\ub97c \uc81c\uacf5\ud558\ub294 AI \ucc57\ubd07\uc785\ub2c8\ub2e4. \uc774 \uac00\uc774\ub4dc\ub294 RAG \ucc57\ubd07\uc744 \uad6c\ucd95\ud558\ub294 \uacfc\uc815\uc744 \ub2e8\uacc4\ubcc4\ub85c \uc124\uba85\ud569\ub2c8\ub2e4. RAG\ub780 \ubb34\uc5c7\uc778\uac00? RAG\ub294 \uac80\uc0c9(Retrieval)\uacfc \uc0dd\uc131(Generation)\uc744 \uacb0\ud569\ud55c \uc811\uadfc \ubc29\uc2dd\uc785\ub2c8\ub2e4. \uc0ac\uc6a9\uc790 \uc9c8\ubb38\uc5d0 \ub300\ud574 \uad00\ub828 \ubb38\uc11c\ub97c \uba3c\uc800 \uac80\uc0c9\ud558\uace0, \uadf8 \uc815\ubcf4\ub97c \ubc14\ud0d5\uc73c\ub85c \ub2f5\ubcc0\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4. RAG\uc758 \uc7a5\uc810 \uc815\ud655\uc131: \uc2e4\uc81c \ubb38\uc11c\uc5d0 \uae30\ubc18\ud55c \ub2f5\ubcc0 \uc81c\uacf5 \ucd5c\uc2e0\uc131:\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=10493\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":["post-10493","post","type-post","status-publish","format-standard","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/10493","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10493"}],"version-history":[{"count":14,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/10493\/revisions"}],"predecessor-version":[{"id":10508,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/10493\/revisions\/10508"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10493"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10493"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10493"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}