이 가이드 튜토리얼에서 다음을 알아보게 됩니다:
- RAG 개요 및 작동 메커니즘
- RAG를 통해 GPT-4o에 SERP 데이터를 통합하는 장점
- OpenAI GPT 모델과 SERP 데이터를 활용한 Python RAG 챗봇 구현 방법
시작해 보겠습니다!
RAG란 무엇인가요?
RAG( Retrieval-Augmented Generation)는 정보 검색과 텍스트 생성을 결합한 AI 접근법입니다. RAG 워크플로우에서 애플리케이션은 먼저 문서, 웹 페이지, 데이터베이스 등 외부 소스에서 관련 데이터를 검색합니다. 그런 다음 AI 모델에 데이터를 전달하여 더 맥락에 맞는 응답을 생성할 수 있도록 합니다.
RAG는 GPT와 같은 대규모 언어 모델(LLM)이 원래 훈련 데이터 범위를 넘어 최신 정보에 접근하고 참조할 수 있도록 하여 성능을 향상시킵니다. 이 접근법은 정확하고 맥락에 특화된 정보가 필요한 시나리오에서 핵심적이며, AI 생성 응답의 품질과 정확도를 모두 개선합니다.
AI 모델에 SERP 데이터를 공급해야 하는 이유
GPT-4o의 지식 컷오프 날짜는 2023년 10월로, 해당 시점 이후 발생한 사건이나 정보에 접근할 수 없습니다. 그러나 GPT-4o 모델은 빙 검색 통합을 통해 인터넷에서 실시간으로 데이터를 가져올 수 있습니다. 이를 통해 보다 최신 정보를 제공할 수 있습니다.
하지만 AI 모델이 특정 데이터 소스를 활용하거나 더 신뢰할 수 있는 검색 엔진을 선호하도록 하고 싶다면 어떻게 해야 할까요? 바로 여기서 RAG(Retrieval-Augmented Generation)가 등장합니다!
특히 RAG를 통해 AI 모델에 SERP(검색 엔진 결과 페이지) 데이터를 공급하는 것은 더 나은 응답을 얻는 훌륭한 방법입니다. 이 접근 방식은 최신 정보나 전문적인 통찰력이 필요한 작업에 특히 유용합니다.
요약하자면, 상위 검색 결과를 GPT-4o 또는 GPT-4o 미니에 전달하면 상세하고 정확하며 맥락이 풍부한 답변을 얻을 수 있습니다.
Python을 사용한 GPT 모델과 SERP 데이터를 활용한 RAG: 단계별 튜토리얼
이 튜토리얼에서는 OpenAI의 GPT 모델을 사용해 RAG 챗봇을 구축하는 방법을 배웁니다. 핵심은 특정 검색어에 대해 구글 상위 노출 페이지의 텍스트를 수집하여 GPT 요청의 컨텍스트로 활용하는 것입니다.
가장 큰 과제는 SERP 데이터 스크래핑입니다. 대부분의 검색 엔진은 자동화된 페이지 접근을 차단하기 위해 고급 봇 방지 솔루션을 적용하고 있기 때문입니다. 자세한 안내는 파이썬으로 Google 스크래핑하는 방법 가이드를 참조하세요.
스크래핑 과정을 간소화하기 위해 Bright Data의 SERP API를 사용할 것입니다:

이 프리미엄 SERP 스크레이퍼를 사용하면 간단한 HTTP 요청으로 Google, DuckDuckGo, Bing, Yandex, Baidu 등 다양한 검색 엔진의 SERP를 쉽게 가져올 수 있습니다.
그런 다음 헤드리스 브라우저를 사용하여 반환된 URL에서 텍스트 데이터를 추출합니다. 이후 이 정보를 RAG 워크플로우에서 GPT 모델의 컨텍스트로 활용할 것입니다. AI를 사용하여 온라인 데이터를 직접 수집하고 싶다면 ChatGPT를 활용한 웹 스크래핑 관련 글을 참고하세요.
코드를 살펴보고 싶거나 아래 단계를 따라가며 코드를 참고하고 싶다면, 본 글을 지원하는 GitHub 저장소를 복제하세요:
git clone https://github.com/Tonel/rag_gpt_serp_scraping
README.md 파일의 지침에 따라 프로젝트의 종속성을 설치하고 프로젝트를 실행하세요.
본 블로그 포스트에서 소개하는 접근 방식은 다른 검색 엔진이나 대규모 언어 모델(LLM)에도 쉽게 적용할 수 있습니다.
참고: 본 가이드는 Unix 및 macOS 환경을 기준으로 합니다. Windows 사용자의 경우 Windows 서브시스템 for Linux(WSL)를 사용하여 튜토리얼을 따라갈 수 있습니다.
1단계: Python 프로젝트 초기화
컴퓨터에 Python 3이 설치되어 있는지 확인하십시오. 설치되어 있지 않다면 다운로드하여 설치하십시오.
프로젝트용 폴더를 생성하고 터미널에서 해당 폴더로 이동하세요:
mkdir rag_gpt_serp_scraping
cd rag_gpt_serp_scraping
rag_gpt_serp_scraping 폴더가 Python RAG 프로젝트를 담게 됩니다.
그런 다음 선호하는 Python IDE에서 프로젝트 디렉터리를 로드하세요. PyCharm Community Edition이나 Python 확장 프로그램이 설치된 Visual Studio Code를 사용하면 됩니다.
rag_gpt_serp_scraping 내부에 빈 app.py 파일을 추가하세요. 여기에는 스크래핑 및 RAG 로직이 포함될 것입니다.
다음으로 프로젝트 디렉터리에서 Python 가상 환경을 초기화합니다:
python3 -m venv env
아래 명령어로 가상 환경을 활성화하세요:
source ./env/bin/activate
완료! 이제 모든 설정이 완료되었습니다.
2단계: 필요한 라이브러리 설치
GPT 모델 기반 이 Python RAG 프로젝트에서 사용하는 종속성은 다음과 같습니다:
python-dotenv: .env 파일에서 환경 변수를 로드합니다. Bright Data 자격 증명 및 OpenAI API 키와 같은 민감한 자격 증명을 안전하게 관리하는 데 사용됩니다.requests: Bright Data의 SERP API에 HTTP 요청을 수행하기 위해 사용됩니다. 자세한 내용은 Requests와 함께 프록시를 사용하는 방법에 대한 가이드를 참조하세요.langchain-community: 상호 운용 가능한 구성 요소를 연결하여 LLM을 구축하는 도구 세트인 LangChain 프레임워크의 일부입니다. Google SERP 페이지에서 텍스트를 검색하고 이를 정리하여 RAG에 적합한 콘텐츠를 생성하는 데 사용됩니다.openai: OpenAI API의 공식 Python 클라이언트 라이브러리입니다. GPT 모델과 연동하여 주어진 입력값과 RAG 컨텍스트를 기반으로 자연어 응답을 생성하는 데 사용됩니다.streamlit: Python으로 대화형 웹 애플리케이션을 구축하기 위한 프레임워크입니다. 사용자가 Google 검색 쿼리와 AI 프롬프트를 입력하고 결과를 동적으로 확인할 수 있는 UI를 만드는 데 유용하게 사용될 것입니다.
활성화된 가상 환경에서 아래 명령어를 실행하여 모든 종속성을 설치하세요:
pip install python-dotenv requests langchain-community openai streamlit
구체적으로 langchain-community의 AsyncChromiumLoader를 사용할 예정이며, 이를 위해 다음 종속성이 필요합니다:
pip install --upgrade --quiet playwright beautifulsoup4 html2text
Playwright가 정상 작동하려면 브라우저도 설치해야 합니다:
playwright install
모든 라이브러리 설치에는 시간이 다소 소요되니 기다려 주세요.
훌륭합니다! 이제 Python 로직을 작성할 준비가 되었습니다.
3단계: 프로젝트 준비
app.py에 다음 임포트를 추가하세요:
from dotenv import load_dotenv
import os
import requests
from langchain_community.document_loaders import AsyncChromiumLoader
from langchain_community.document_transformers import BeautifulSoupTransformer
from openai import OpenAI
import streamlit as st
그런 다음 프로젝트 폴더에 모든 인증 정보를 저장할 .env 파일을 생성하세요. 이제 프로젝트 구조는 아래와 같을 것입니다:

app.py 에서 아래 함수를 사용하여 python-dotenv가 .env 파일에서 환경 변수를 로드하도록 지시하세요:
load_dotenv()
이제 .env 또는 시스템에서 환경 변수를 다음과 같이 가져올 수 있습니다:
os.environ.get("<ENV_NAME>")
이것이 바로 Python 표준 라이브러리인 os를 임포트한 이유이기도 합니다.
4단계: SERP API 구성
소개에서 언급했듯이, 검색 엔진 결과 페이지의 콘텐츠를 가져와 Python RAG 워크플로에 활용하기 위해 Bright Data의 SERP API를 사용할 것입니다. 구체적으로 SERP API가 반환하는 웹 페이지 URL에서 텍스트를 추출할 것입니다.
SERP API 설정 방법은 공식 문서를 참조하십시오. 또는 아래 지침을 따르세요.
아직 계정이 없다면 Bright Data에 가입하세요. 로그인 후 계정 대시보드로 이동합니다:

해당 페이지에서 “프록시 제품 받기(Get proxy products)” 버튼을 클릭하세요.
그러면 아래 페이지로 이동하며, “SERP API” 행을 클릭해야 합니다:

SERP API 제품 페이지에서 “Activate zone”을 토글하여 제품을 활성화하세요:

이제 “액세스 매개변수” 섹션의 SERP API 호스트, 포트, 사용자 이름, 비밀번호를 복사하여 .env 파일에 추가하세요:
BRIGHT_DATA_SERP_API_HOST="<YOUR_HOST>"
BRIGHT_DATA_SERP_API_PORT=<YOUR_PORT>
BRIGHT_DATA_SERP_API_USERNAME="<YOUR_USERNAME>"
BRIGHT_DATA_SERP_API_PASSWORD="<YOUR_PASSWORD>"
<YOUR_XXXX> 자리 표시자를 Bright Data의 SERP API 페이지에서 제공된 값으로 대체하세요.
“접근 매개변수”의 호스트 형식은 다음과 같습니다:
brd.superproxy.io:33335
아래와 같이 분할해야 합니다:
BRIGHT_DATA_SERP_API_HOST="brd.superproxy.io"
BRIGHT_DATA_SERP_API_PORT=33335
훌륭합니다! 이제 Python에서 SERP API를 사용할 수 있습니다.
단계 #5: SERP 스크래핑 로직 구현
app.py에 Google SERP 페이지에서 첫 번째 number_of_urls 개의 URL을 가져오는 다음 함수를 추가하세요:
def get_google_serp_urls(query, number_of_urls=5):
# Bright Data의 SERP API 요청 수행
# JSON 자동 파싱 포함
host = os.environ.get("BRIGHT_DATA_SERP_API_HOST")
port = os.environ.get("BRIGHT_DATA_SERP_API_PORT")
username = os.environ.get("BRIGHT_DATA_SERP_API_USERNAME")
password = os.environ.get("BRIGHT_DATA_SERP_API_PASSWORD")
proxy_url = f"http://{username}:{password}@{host}:{port}"
proxies = {"http": proxy_url, "https": proxy_url}
url = f"https://www.google.com/search?q={query}&brd_json=1"
response = requests.get(url, proxies=proxies, verify=False)
# 파싱된 JSON 응답 가져오기
response_data = response.json()
# 응답에서 "number_of_urls" 개수의
# Google SERP URL 추출
google_serp_urls = []
if "organic" in response_data:
for item in response_data["organic"]:
if "link" in item:
google_serp_urls.append(item["link"])
return google_serp_urls[:number_of_urls]
이 코드는 쿼리 인자에 지정된 검색어로 SERP API에 HTTP GET 요청을 수행합니다. brd_json=1 쿼리 매개변수는 SERP API가 결과를 아래 형식의 JSON으로 파싱하도록 보장합니다:
{
"general": {
"search_engine": "google",
"results_cnt": 1980000000,
"search_time": 0.57,
"language": "en",
"mobile": false,
"basic_view": false,
"search_type": "text",
"page_title": "pizza - Google Search",
"code_version": "1.90",
"timestamp": "2023-06-30T08:58:41.786Z"
},
"input": {
"original_url": "https://www.google.com/search?q=pizza&brd_json=1",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/608.2.11 (KHTML, like Gecko) Version/13.0.3 Safari/608.2.11",
"request_id": "hl_1a1be908_i00lwqqxt1"
},
"organic": [
{
"link": "https://www.pizzahut.com/",
"display_link": "https://www.pizzahut.com",
"title": "피자헛 | 배달 & 테이크아웃 - 피자 헛을 따라올 수 있는 곳은 없습니다!",
"image": "간결함을 위해 생략...",
"image_alt": "www.pizzahut.com의 피자",
"image_base64": "생략...",
"rank": 1,
"global_rank": 1
},
{
"link": "https://www.dominos.com/en/",
"display_link": "https://www.dominos.com › ...",
"title": "도미노: 피자 배달 & 테이크아웃, 파스타, 치킨 등",
"description": "도미노에서 피자, 파스타, 샌드위치 등을 온라인으로 주문하여 테이크아웃 또는 배달 받으세요. 메뉴 확인, 매장 찾기, 주문 추적이 가능합니다. 도미노 이메일 가입하기 ...",
"image": "생략...",
"image_alt": "www.dominos.com의 피자",
"image_base64": "생략...",
"rank": 2,
"global_rank": 3
},
// 생략...
],
// 생략...
}
함수의 마지막 몇 줄은 결과 JSON 데이터에서 각 SERP URL을 가져오고, 첫 번째 number_of_urls 개 URL만 선택하여 목록으로 반환합니다.
이제 이 URL들에서 텍스트를 추출할 차례입니다!
6단계: SERP URL에서 텍스트 추출
각 SERP URL에서 텍스트를 추출하는 함수를 정의합니다:
def extract_text_from_urls(urls, number_of_words=600):
# 제공된 URL들을 방문하도록 헤드리스 크롬 인스턴스에 지시
# 지정된 사용자 에이전트 사용
loader = AsyncChromiumLoader(
urls,
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",)
html_documents = loader.load()
# 추출된 HTML 문서 처리하여 텍스트 추출
bs_transformer = BeautifulSoupTransformer()
docs_transformed = bs_transformer.transform_documents(
html_documents,
tags_to_extract=["p", "em", "li", "strong", "h1", "h2"],
unwanted_tags=["a"],
remove_comments=True,
)
# 각 HTML 텍스트 문서가 숫자만 포함하도록 보장
# number_of_words 단어
extracted_text_list = []
for doc_transformed in docs_transformed:
# 텍스트를 단어로 분할하고 첫 number_of_words 개를 연결
words = doc_transformed.page_content.split()[:number_of_words]
extracted_text = " ".join(words)
# 빈 텍스트 문서는 무시
if len(extracted_text) != 0:
extracted_text_list.append(extracted_text)
return extracted_text_list
이 함수는:
- 인수로 전달된 URL에서 헤드리스 크롬 브라우저 인스턴스를 사용하여 웹 페이지를 로드합니다.
- BeautifulSoupTransformer를 활용하여 각 페이지의 HTML을 처리하고 특정 태그(<p>, <h1>, <strong> 등)에서 텍스트를 추출하며, 원하지 않는 태그(<a> 등)와 주석은 생략합니다.
- 각 웹페이지에서 추출된 텍스트를
number_of_words인자로 지정된 단어 수로 제한합니다. - 각 URL에서 추출된 텍스트 목록을 반환합니다.
[“p”, “em”, “li”, “strong”, “h1”, “h2”] 태그만으로도 대부분의 웹 페이지에서 텍스트를 추출하는 데 충분합니다. 그러나 특정 상황에서는 이 HTML 태그 목록을 사용자 정의해야 할 수 있습니다. 또한 각 텍스트 항목의 목표 단어 수를 늘리거나 줄여야 할 수도 있습니다.
예를 들어, 아래 웹 페이지를 고려해 보십시오:

해당 페이지에 이 함수를 적용하면 다음과 같은 텍스트 배열이 생성됩니다:
["리사 존슨 맨델의 트랜스포머 원 리뷰는 지금까지 상상조차 할 수 없었던 사실을 드러냅니다: 이 영화는 올해 최고의 애니메이션 영화 중 하나입니다! 트랜스포머 영화에 대해 이런 글을 쓰게 될 줄은 꿈에도 몰랐지만, 트랜스포머 원은 실제로 탁월한 영화입니다! ..."]
놀랍습니다! 완벽하지는 않지만 AI 모델 기준으로는 여전히 높은 품질입니다.
extract_text_from_urls() 가 반환한 텍스트 항목 목록은 OpenAI 모델에 공급할 RAG 컨텍스트를 나타냅니다.
7단계: RAG 프롬프트 생성
AI 프롬프트 요청과 텍스트 컨텍스트를 최종 RAG 프롬프트로 변환하는 함수를 정의합니다:
def get_openai_prompt(request, text_context=[]):
# 기본 프롬프트
prompt = request
# 컨텍스트가 존재할 경우 프롬프트에 추가
if len(text_context) != 0:
context_string = "nn--------nn".join(text_context)
prompt = f"아래 컨텍스트만을 사용하여 요청에 답변하십시오.nn컨텍스트:n{context_string}nn요청: {request}"
return prompt
RAG 컨텍스트가 지정되었을 때 이전 함수가 반환하는 프롬프트는 다음과 같은 형식을 가집니다:
아래 컨텍스트만 사용하여 요청에 답변하십시오.
컨텍스트:
블라 블라 블라...
--------
블라 블라 블라...
--------
블라 블라 블라...
요청: <YOUR_REQUEST>
8단계: GPT 요청 수행
먼저, app.py 파일 상단에서 OpenAI 클라이언트를 초기화합니다:
openai_client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
이는 OPENAI_API_KEY 환경 변수에 의존하며, 시스템 환경 변수나 .env 파일에 직접 정의할 수 있습니다:
OPENAI_API_KEY="<YOUR_API_KEY>"
<YOUR_API_KEY> 를 자신의 OpenAI API 키 값으로 대체하세요. API 키를 얻는 방법을 모르는 경우 공식 가이드를 따르세요.
다음으로 OpenAI 공식 클라이언트를 사용하여 GPT-4o 미니 AI 모델에 요청을 수행하는 함수를 작성합니다:
def interrogate_openai(prompt, max_tokens=800):
# 주어진 프롬프트로 OpenAI 모델에 질의
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,)
return response.choices[0].message.content
OpenAI API에서 지원하는 다른 GPT 모델도 구성할 수 있습니다.
get_openai_prompt() 에서 반환된 프롬프트에 지정된 텍스트 컨텍스트가 포함된 경우 interrogate_openai()는 의도한 대로 검색 강화 생성(retrieval-augmented generation)을 성공적으로 수행합니다.
9단계: 애플리케이션 UI 생성
Streamlit을 사용하여 사용자가 다음을 지정할 수 있는 간단한 양식 UI 를 정의합니다:
- SERP API에 전달할 Google 검색 쿼리
- GPT-4o mini에 전송할 AI 프롬프트
다음 코드 줄로 구현하세요:
with st.form("prompt_form"):
# 출력 결과 초기화
result = ""
final_prompt = ""
# 사용자가 Google 검색 쿼리를 입력할 텍스트 영역
google_search_query = st.text_area("Google Search:", None)
# 사용자가 AI 프롬프트를 입력할 텍스트 영역
request = st.text_area("AI 프롬프트:", None)
# 양식 제출 버튼
submitted = st.form_submit_button("보내기")
# 양식이 제출된 경우
if submitted:
# 주어진 검색 쿼리로 Google SERP URL 가져오기
google_serp_urls = get_google_serp_urls(google_search_query)
# 각 HTML 페이지에서 텍스트 추출
extracted_text_list = extract_text_from_urls(google_serp_urls)
# 추출된 텍스트를 컨텍스트로 AI 프롬프트 생성
final_prompt = get_openai_prompt(request, extracted_text_list)
# 생성된 프롬프트로 OpenAI 모델 질의
result = interrogate_openai(final_prompt)
# 생성된 프롬프트를 포함하는 드롭다운
final_prompt_expander = st.expander("AI 최종 프롬프트:")
final_prompt_expander.write(final_prompt)
# OpenAI 모델 결과 기록
st.write(result)
자, 이제 Python RAG 스크립트가 준비되었습니다.
10단계: 모든 것을 통합하기
app.py 파일에는 다음 코드가 포함되어야 합니다:
from dotenv import load_dotenv
import os
import requests
from langchain_community.document_loaders import AsyncChromiumLoader
from langchain_community.document_transformers import BeautifulSoupTransformer
from openai import OpenAI
import streamlit as st
# .env 파일에서 환경 변수 불러오기
load_dotenv()
# API 키로 OpenAI API 클라이언트 초기화
openai_client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
def get_google_serp_urls(query, number_of_urls=5):
# Bright Data의 SERP API 요청 수행
# JSON 자동 파싱 포함
host = os.environ.get("BRIGHT_DATA_SERP_API_HOST")
port = os.environ.get("BRIGHT_DATA_SERP_API_PORT")
username = os.environ.get("BRIGHT_DATA_SERP_API_USERNAME")
password = os.environ.get("BRIGHT_DATA_SERP_API_PASSWORD")
proxy_url = f"http://{username}:{password}@{host}:{port}"
proxies = {"http": proxy_url, "https": proxy_url}
url = f"https://www.google.com/search?q={query}&brd_json=1"
response = requests.get(url, proxies=proxies, verify=False)
# 파싱된 JSON 응답 가져오기
response_data = response.json()
# "number_of_urls" 개수의
# Google SERP URL 추출
google_serp_urls = []
if "organic" in response_data:
for item in response_data["organic"]:
if "link" in item:
google_serp_urls.append(item["link"])
return google_serp_urls[:number_of_urls]
def extract_text_from_urls(urls, number_of_words=600):
# 제공된 URL들을 방문하도록 헤드리스 크롬 인스턴스에 지시
# 지정된 사용자 에이전트 사용
loader = AsyncChromiumLoader(
urls,
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",)
html_documents = loader.load()
# 추출된 HTML 문서 처리하여 텍스트 추출
bs_transformer = BeautifulSoupTransformer()
docs_transformed = bs_transformer.transform_documents(
html_documents,
tags_to_extract=["p", "em", "li", "strong", "h1", "h2"],
unwanted_tags=["a"],
remove_comments=True,
)
# 각 HTML 텍스트 문서가 숫자만 포함하도록 보장
# number_of_words 단어
extracted_text_list = []
for doc_transformed in docs_transformed:
# 텍스트를 단어로 분할하고 첫 number_of_words 개를 연결
words = doc_transformed.page_content.split()[:number_of_words]
extracted_text = " ".join(words)
# 빈 텍스트 문서는 무시
if len(extracted_text) != 0:
extracted_text_list.append(extracted_text)
return extracted_text_list
def get_openai_prompt(request, text_context=[]):
# 기본 프롬프트
prompt = request
# 텍스트 컨텍스트가 존재할 경우 프롬프트에 추가
if len(text_context) != 0:
context_string = "nn--------nn".join(text_context)
prompt = f"아래 컨텍스트만을 사용하여 요청에 답변하십시오.nn컨텍스트:n{context_string}nn요청: {request}"
return prompt
def interrogate_openai(prompt, max_tokens=800):
# 주어진 프롬프트로 OpenAI 모델에 질의
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,)
return response.choices[0].message.content
# Streamlit 앱에 사용자 입력용 폼 생성
with st.form("prompt_form"):
# 출력 결과 초기화
result = ""
final_prompt = ""
# 사용자가 구글 검색어를 입력할 텍스트 영역
google_search_query = st.text_area("Google Search:", None)
# 사용자가 AI 프롬프트를 입력할 텍스트 영역
request = st.text_area("AI Prompt:", None)
# 양식 제출 버튼
submitted = st.form_submit_button("Send")
# 양식이 제출된 경우
if submitted:
# 주어진 검색어로 Google SERP URL 가져오기
google_serp_urls = get_google_serp_urls(google_search_query)
# 각 HTML 페이지에서 텍스트 추출
extracted_text_list = extract_text_from_urls(google_serp_urls)
# 추출된 텍스트를 컨텍스트로 AI 프롬프트 생성
final_prompt = get_openai_prompt(request, extracted_text_list)
# 생성된 프롬프트로 OpenAI 모델 질의
result = interrogate_openai(final_prompt)
# 생성된 프롬프트를 포함하는 드롭다운
final_prompt_expander = st.expander("AI 최종 프롬프트")
final_prompt_expander.write(final_prompt)
# OpenAI 모델 결과 기록
st.write(result)
믿을 수 있나요? 150줄도 안 되는 코드로 파이썬으로 RAG를 구현할 수 있습니다!
11단계: 애플리케이션 테스트
다음 명령어로 Python RAG 애플리케이션을 실행하세요:
streamlit run app.py
터미널에 다음과 같은 출력이 표시됩니다:
이제 브라우저에서 Streamlit 앱을 확인할 수 있습니다.
로컬 URL: http://localhost:8501
네트워크 URL: http://172.27.134.248:8501
지시사항을 따라 브라우저에서 http://localhost:8501 로 접속하세요. 아래와 같은 화면이 표시됩니다:

보시다시피, 양식에는 코드에서 정의한 “Google Search:” 및 “AI Prompt:” 텍스트 입력란과 “Send” 버튼, “AI Final Prompt” 드롭다운이 포함되어 있습니다.
아래와 같이 Google 검색 쿼리를 사용하여 애플리케이션을 테스트해 보세요:
Transformers One 리뷰
다음과 같은 AI 프롬프트를 입력하세요:
영화 트랜스포머 원에 대한 리뷰를 작성하세요
“Send”를 클릭하고 애플리케이션이 요청을 처리하는 동안 잠시 기다리세요. 몇 초 후 다음과 같은 결과를 확인할 수 있습니다:

와! 나쁘지 않은 리뷰네요…
“AI 최종 프롬프트” 드롭다운을 확장하면 애플리케이션이 RAG에 사용한 전체 프롬프트를 확인할 수 있습니다.
자, 이제 SERP 데이터를 활용한 GPT-4o mini 기반 Python RAG 챗봇 구현을 완료했습니다.
결론
이 튜토리얼에서는 RAG가 무엇인지, 그리고 SERP 데이터를 AI 모델에 공급하여 이를 구현하는 방법을 살펴보았습니다. 구체적으로, SERP 데이터를 스크래핑하고 GPT 모델에서 이를 활용하여 결과 정확도를 향상시키는 Python RAG 챗봇을 구축하는 방법을 배웠습니다.
이 접근법의 주요 어려움은 Google과 같은 검색 엔진에서 데이터를 스크래핑하는 데 있습니다. 그 이유는 다음과 같습니다:
- 검색 엔진은 SERP 페이지 구조를 자주 변경합니다.
- 가장 정교한 봇 방지 조치로 보호받고 있습니다.
- 대량의 SERP 데이터를 동시에 검색하는 것은 복잡하고 많은 비용이 들 수 있습니다.
여기서 보듯이, Bright Data의 SERP API는 모든 주요 검색 엔진에서 실시간 SERP 데이터를 손쉽게 수집할 수 있도록 지원합니다. 이는 RAG 및 다양한 애플리케이션에 활용 가능합니다. 지금 무료 체험을 시작하세요!
지금 가입하여 Bright Data의 프록시 서비스 또는 스크래핑 제품 중 귀하의 요구에 가장 적합한 솔루션을 확인하세요. 무료 체험으로 시작하세요!