RAG
강사: 생활코딩 이고잉님
임베딩이란 의미를 숫자로 표현한 것이다.
🟩 RAG(Retrieval-Augmented Generation)
: 질문 - 응답 시스템에서 사용하는 기법으로 정보 검색(Retrieval)과 생성(Generation)단계를 결합하여
높은 정확도의 응답을 제공합니다.
RAG의 장점
- 높은 정확도: 필요한 정보를 검색해서 제공하므로, 단순 생성 모델보다 정밀한 응답이 가능합니다.
- 확장성: 대규모 지식 데이터베이스를 활용하여 정보의 최신성 및 정확성을 유지합니다.
- 추론 능력 향상: 검색된 정보의 근거를 바탕으로 답변을 생성하므로, 복잡한 질의에서도 일관성 있고 신뢰성 높은 답변을 제공합니다.
RAG의 활용 분야
- 고객 지원 챗봇: 실시간 정보와 최신 FAQ를 바탕으로 정확한 답변을 제공합니다.
- 질의 응답 시스템: 논문, 문서, 기술 자료를 참고하여 깊이 있는 답변을 생성할 수 있습니다.
- 검색 기반 텍스트 생성: 최신 뉴스나 사실을 포함해야 하는 경우에도 사용됩니다.
🟦 OpenAI
- Calab에 OpenAI 키 설정(화면 왼쪽 열쇠 모양 선택)
- OpenAI 시작
from google.colab import userdata
from openai import OpenAI
client = OpenAI(api_key=userdata.get('OPENAI_API_KEY'))
text = input("Enter text : ")
text = text.replace("\n", " ") # 줄바꿈 커서 제거
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": f"{text}"}
]
)
answer = response.choices[0].message.content
print("답변: ", answer)
- 입력하는 값의 vector 구하기
import os
from openai import OpenAI
from google.colab import userdata
client = OpenAI(api_key=userdata.get('OPENAI_API_KEY'))
text = input("Enter text to get embedding: ")
text = text.replace("\n", " ")
response = client.embeddings.create(input=[text], model="text-embedding-3-small")
vector = response.data[0].embedding
print(f"size : {len(vector)}") # size: 1536
print(vector)
# 결과
[0.00348..., -0.00555..., ...]
- Vector extension On
CREATE EXTENSION IF NOT EXISTS vector;
- Table 생성
CREATE TABLE
public.memo2 (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
CONTENT TEXT NOT NULL,
embedding vector (1536)
) TABLESPACE pg_default;
- [공통] import 문 + supabase(PostgreSQL 연결 설정)
import os
from openai import OpenAI
from google.colab import userdata
import psycopg2 as ps
import json
client = OpenAI(api_key=userdata.get('OPENAI_API_KEY'))
user = userdata.get('POSTGRES_USER')
password = userdata.get('POSTGRES_PASSWORD')
# Supabase PostgreSQL 연결 설정
conn = ps.connect(
host="aws-0-ap-northeast-2.pooler.supabase.com",
port="6543",
database="postgres",
user=user,
password=password
)
- supabase 연동(DB에 Text와 Vector 전송)
...
[공통] import 문 + supabase(PostgreSQL 연결 설정)
...
cur = conn.cursor()
# 사용자의 데이터를 입력 받는다
text = input("Enter text to get embedding: ")
text = text.replace("\n", " ")
# 임베딩 벡터를 구한다.
response = client.embeddings.create(input=[text], model="text-embedding-3-small")
vector = response.data[0].embedding
embedding_json = json.dumps(vector) # JSON 파일로 변환
print('embedding_json: ', embedding_json) # (개발자) 1500개의 용어로 이루어진 벡터를 받았다.
# 행을 추가한다.
insert_query = """
INSERT INTO memo2 (content, embedding)
VALUES (%s, %s)
"""
cur.execute(insert_query, (text, embedding_json))
conn.commit()
cur.close()
conn.close()
- DB에서 입력한 값과 유사한 데이터를 가져오기(유사도 검사)
...
[공통] import 문 + supabase(PostgreSQL 연결 설정)
...
cur = conn.cursor()
# 1단계: 사용자로부터 텍스트 입력
text = input("Enter text to find similar records: ")
# 2단계: 입력한 텍스트를 임베딩으로 변환
response = client.embeddings.create(input=[text], model="text-embedding-3-small")
query_embedding = response.data[0].embedding # 생성된 임베딩 벡터
print('query_embedding', query_embedding)
cur.execute("""
SELECT id, content, (embedding <=> %s::vector) AS similarity
FROM public.memo2
ORDER BY embedding <=> %s::vector
""", (query_embedding, query_embedding))
# 결과 출력
matches = cur.fetchall()
if matches:
print("Most similar record(s):")
for match in matches:
print(f"ID: {match[0]}, Content: {match[1]}, Similarity: {match[2]}")
else:
print("No similar records found.")
cur.close()
conn.close()
# 결과
Enter text to find similar records: 주말이다.
query_embedding [0.00947636179625988, 0.011235509067773819, ...]
Most similar record(s):
ID: 14, Content: 내일은 즐거운 주말입니다., Similarity: 0.519824177026749
ID: 1, Content: 오늘 친구와 오랜만에 카페에서 시간을 보냈다. ... , Similarity: 0.775715914283284
- 질문 임베딩과 유사한 상위 3개의 컨텍스트(문서) 조회
...
[공통] import 문 + supabase(PostgreSQL 연결 설정)
...
cur = conn.cursor()
# 1단계: 사용자로부터 질문 입력
question = input("Enter your question: ")
# 2단계: 질문의 임베딩 생성
response = client.embeddings.create(input=[question], model="text-embedding-3-small")
question_embedding = response.data[0].embedding # 생성된 임베딩 벡터
# 3단계: 질문 임베딩과 유사한 컨텍스트(문서) 조회
cur.execute("""
SELECT id, content, (embedding <=> %s::vector) AS similarity
FROM public.memo2
ORDER BY embedding <=> %s::vector
LIMIT 3; -- 상위 3개의 유사한 문서만 조회
""", (question_embedding, question_embedding))
# 가장 유사한 컨텍스트 출력
contexts = cur.fetchall()
if contexts:
print("Retrieved contexts:")
for context in contexts:
print(f"ID: {context[0]}, Content: {context[1]}, Similarity: {context[2]}")
combined_context = "\n".join([context[1] for context in contexts])
print('combined_context : ', combined_context)
# LLM에 질문과 결합된 컨텍스트를 전달하여 답변 생성
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are an assistant that provides answers based on context."},
{"role": "user", "content": f"Context:\n{combined_context}\n\nQuestion: {question}"}
]
)
# 생성된 답변 출력
answer = response.choices[0].message.content
print("\nAnswer from LLM:")
print(answer)
# 연결 종료
cur.close()
conn.close()
- gradio 연동
...
[공통] import 문 + supabase(PostgreSQL 연결 설정)
...
cur = conn.cursor()
# RAG 검색 및 응답 생성 함수
def retrieve_and_generate_answer(question):
# 1단계: 질문의 임베딩 생성
response = client.embeddings.create(input=[question], model="text-embedding-3-small")
question_embedding = response.data[0].embedding # 생성된 임베딩 벡터
# 2단계: 유사도가 가장 높은 2개의 글을 데이터베이스에서 조회
cur.execute("""
SELECT id, content, (embedding <=> %s::vector) AS similarity
FROM public.memo2
ORDER BY embedding <=> %s::vector # 가까운 순서대로 정렬
LIMIT 2;
""", (question_embedding, question_embedding))
contexts = cur.fetchall()
if not contexts:
return "No similar records found."
# 조회된 글을 출력용 문자열로 구성
context_text = ""
for context in contexts:
context_text += f"ID: {context[0]}, Content: {context[1]}, Similarity: {context[2]:.3f}\n\n"
# 조회된 글을 하나의 텍스트로 결합
combined_context = "\n".join([context[1] for context in contexts])
# 3단계: LLM에 질문과 결합된 컨텍스트를 전달하여 답변 생성
llm_response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are an assistant that provides answers based on context."},
{"role": "user", "content": f"Context:\n{combined_context}\n\nQuestion: {question}"}
]
)
# LLM에서 생성된 답변
answer = llm_response.choices[0].message.content
# 결과 출력
return f"Retrieved contexts:\n{context_text}\nAnswer from LLM:\n{answer}"
# Gradio 인터페이스 설정
with gr.Blocks() as demo:
gr.Markdown("## RAG 기반 질문 응답 시스템")
# 질문 입력 필드
question = gr.Textbox(label="Enter your question")
# 실행 버튼과 결과 표시 영역
answer = gr.Textbox(label="Response", interactive=False)
# 버튼과 이벤트 연결
question.submit(retrieve_and_generate_answer, question, answer)
# Gradio 인터페이스 실행
demo.launch()
출처: AI Hub 교육과정 - WEB+AI (위 내용이 문제가 된다면 댓글에 남겨주세요. 바로 삭제조치하도록 하겠습니다.)
'Programming 개발은 구글로 > 기타 정보' 카테고리의 다른 글
[WEB+AI] 17일차 티처블 머신 활용 + 머신러닝 (5) | 2024.11.05 |
---|---|
[WEB+AI] 16일차 Gradio 복습 (6) | 2024.11.04 |
[WEB+AI] 14일차 Embedding(임베딩) + Python (0) | 2024.10.31 |
[WEB+AI] 13일차 Chatbot + Python (3) | 2024.10.30 |
[WEB+AI] 12일차 Chat AI + GPT (3) | 2024.10.29 |
댓글