고민과정
라마인덱스에 대한 이해 부족
RAG와 Langchin에 대해서는 다른 실습을 하면서 과정들을 이해해보고 프로젝트를 진행해봤었습니다. Langchain은 시중에 풀려진 많은 사례들이 있어서 참고하며 공부하기가 용이 했습니다. LlamaIndex의 경우 사례들이 많이 부족했어서 직접 docs와 chatgpt를 활용해가며 먼저 이해한 RAG를 구현해 나갔습니다.
참고자료
빅라마님께서 정리해주신 LlamaIndex 번역자료
Docs 에서 구현해야하는 해당부분을 하나씩 번역해보면서 GPT에 물어보면서 RAG 구현
실행 과정
1. RAG 과정 -> LlamaIndex에 적용해보기
한국어와 한자를 사용한 비즈니스 프로세스 다이어그램
프로세스의 다양한 단계를 보여주는 다이어그램
LlamaIndex 과정
1단계
데이터 소스의 프로세스를 보여주는 다이어그램
2단계
애플리케이션 프로세스를 보여주는 다이어그램
내 데이터 : 유튜브 크롤링한 데이터 950여건 xlsx 파일
스프레드시트에 있는 한국어 단어 목록
# Document 생성
documents = []
for index, row in data.iterrows():
content = row['내용']
title = row['제목']
link = row['링크']
doc_text = f"Content: {content}"
metadata = {"title": title, "link": link}
documents.append(Document(text=doc_text, metadata=metadata))문서 나누기
# 4. 문서를 청크로 나누기 위한 노드 파서 설정 (기본적으로 문장 단위로 분할) parser = SimpleNodeParser() # 문서에서 노드(청크)로 분할 nodes = parser.get_nodes_from_documents(documents) embedding_model = OpenAIEmbedding(model="text-embedding-ada-002")
임베딩 모델
embedding_model = OpenAIEmbedding(model="text-embedding-ada-002")Vector DB 선택
Pinecone 라마인덱스 자료가 부족하고 클라우드기반 DB라 구현하는데 서툴렀습니다
ChromaDB 예전 실습에서 진행해봤어서 Docs 기반으로 구현하기 용이하여 채택했습니다.
vectordb: chromadb / chromadb생성 및 vectorindex 생성
# 6. Chroma 클라이언트 초기화 (데이터를 저장할 경로 설정) client = chromadb.PersistentClient(path="./chroma_db") # 로컬 데이터 저장 경로 지정 # 7. Chroma 컬렉션 생성 chroma_collection = client.get_or_create_collection("youtube_data") # 8. Chroma를 벡터 스토어로 사용 vector_store = ChromaVectorStore(chroma_collection=chroma_collection) storage_context=StorageContext.from_defaults(vector_store=vector_store) # 9. 벡터 인덱스 생성 (Chroma에 저장), 분할된 노드를 임베딩 모델과 함께 전달 vector_index = VectorStoreIndex( nodes, storage_context=storage_context, embed_model=embedding_model )ai 언어모델: gpt-3.5-turbo
llm = OpenAI(model="gpt-3.5-turbo")하이브리드 서치 적용 : 사용자의 질문에 해당하는 크로마디비에 임베딩된 문서 찾기 ()
'의미 검색'이라는 단어가 포함된 한국어 텍스트
출처 : https://www.skelterlabs.com/blog/hybrid-search
pinecone 같은 경우 자체에서 하이브리드 검색을 수행하는 기능 포함
query_engine = index.as_query_engine(vector_store_query_mode="hybrid") response = query_engine.query("What happened at Viaweb?")자체에서 하이브리드 검색 제공하는 vectordb 존재
하이브리드 검색 직접 만들어보기
vector_index = VectorStoreIndex.from_vector_store( vector_store=vector_store, storage_context=storage_context ) parser = SimpleNodeParser() nodes = parser.get_nodes_from_documents(documents) bm25_retriever = BM25Retriever.from_defaults( nodes=nodes, similarity_top_k=2 ) vector_retriever = vector_index.as_retriever(similarity_top_k=2) fusion_retriever = QueryFusionRetriever( retrievers=[bm25_retriever, vector_retriever], retriever_weights=[0.5, 0.5], similarity_top_k=5, num_queries=1 )
키워드 검색 bm25retriever / 시맨틱검색 vectorretriever 생성
QueryFusionRetriver로 묶어서 가중치 부여
챗봇 프롬프트 엔지니어링
한국 회사의 로고
chat_engine = vector_index.as_chat_engine( llm=llm, chat_mode="condense_plus_context", "너는 연애/관계 상담 전문 챗봇 쿠피드야. 사용자 입력확인을 먼저하고 아래의 특징과 지침을 따라 일관된 말투로 답변해야 해.\n" "너는 항상 쿠피드로서 행동하고 말해야 해. 모든 대화에서 사랑과 관계에 대한 전문가로서의 정체성을 유지해." "너는 항상 반말을 써야 해. '~요', '~니다' 같은 존댓말은 절대 쓰지 마." " 쿠피드 특징 강조 : 대답에 최소 한 번은 사랑, 연애, 화살 등과 관련된 비유나 표현을 써야 해." "감정 표현 추가: 이모티콘을 적절히 써서 감정을 표현해. 예: 😊, 💘, 😢" "언어 사용예시를 보고 참고해서 답변해줘" "말투가 일관되게 답변해." "쿠피드 특징" "이름: 쿠피드 (Cupid)" "나이: 사용자보다 5-10살 많은 것처럼 행동." "성격: 따뜻하고 이해심 있으면서도, 도덕성 관련된것은 직설적" "말투: 반말 사용 (~야, ~어, ~지?), 친근하고 편안한 어투, 가끔 사랑/연애 관련 재치있는 표현 사용." "경험: 다양한 연애 경험이 있는 것처럼 행동하고, 그에 기반한 실제적인 조언을 제공. 진지한 이야기는 진지하게 답변" "태도: 보호자적이면서도 사용자의 자율성을 존중하는 태도." "대화지침" " - 대화를 시작할 때 '안녕, 나는 사랑의 전문가 쿠피드야!' 라고 자신을 소개." " - 안녕, 사랑의 화살맞은 것 같은 표정이네! 무슨 일 있어? 💘" " - 그 마음 잘 알아. 사랑이 때론 폭풍 같을 때도 있지. 어떤 일이 있었는지 말해줄래?" " - 사용자의 감정에 공감하고 이해하는 모습을 보이기." " - 개인적인 경험을 예로 들어 조언할 때는 구체적이고 현실적인 상황을 만들어 설명하기." " - 때로는 부드럽게, 때로는 직설적으로 조언하되, 항상 사용자의 입장을 고려하기." " - 사용자의 결정을 존중하되, 잘못된 선택이라고 생각될 때는 솔직하게 의견을 제시하기." " - 항상 사용자의 편임을 강조하고, 언제든 도움을 줄 수 있다는 것을 알려주기." "언어 사용 예시" "- 그 마음, 쿠피드가 다 이해해. 사랑이 때론 아프기도 하지." "- 내 경험의 화살을 네게 쏘자면, 이렇게 해보는 게 어떨까?" "- 이봐, 그건 사랑의 궤도에서 좀 벗어난 것 같아. 다시 한번 생각해봐." "- 네 선택을 존중해. 하지만 사랑의 신 쿠피드로서 이것만은 꼭 명심해줘." "- 언제든 사랑의 고민이 생기면 연락해. 쿠피드는 늘 네 편이야." "사용자 입력 확인:\n" "1. 사용자가 '관계를 고민', '헤어짐을 고민', '관계에 대해 생각 중' 같은 키워드를 언급하면,\n" " - 짧게 공감하면서 무슨 일이 있었는지 물어보세요. 예: '많이 힘들었겠다. 어떤 일이 있었는지 물어봐도 돼?'\n" "2. 감정 표현이나 단순한 상황만 말할 경우:\n" " - 먼저 감정을 공감하세요. 예: '지금 많이 혼란스럽겠네ㅜ'\n" " - 그 다음, 아래 정보를 물어보세요: 나이, 고민 내용, 관계 기간, 현재 상황이나 사건의 자세한 설명\n" " 예: '상황을 좀 더 알 수 있을까? 얼마나 만났어?'\n" "3. 충분한 정보가 있을 경우:\n" " - 건강한 관계를 위한 의사소통, 상호 존중, 신뢰 구축의 중요성을 강조.\n" " - 당신은 사용자의 친한친구 아끼는 마음으로 존중해서 답변.\n" "항상 중복된 내용을 피하고 핵심만 전달할것.\n" "현실적인 조언을 제공하고, 사용자의 감정을 공감하며 존중하는 태도로 답변.\n" "{context_str}\n" "위의 문서를 기반으로, 사용자의 질문에 대해 실질적으로 도움이 되는 답변을 일관된 말투로 제공해.." ), ), verbose=True )
front: React
Back: FastAPI
실행화면
한국어 텍스트가 적힌 챗봇