오늘 완성한 코드
korea_food = 'C:\\Users\\kevinkim\\Desktop\\recipes\\한식.json'
western_food = 'C:\\Users\\kevinkim\\Desktop\\recipes\\양식.json'
japanses_food = 'C:\\Users\\kevinkim\\Desktop\\recipes\\일식.json'
chinses_food = 'C:\\Users\\kevinkim\\Desktop\\recipes\\중식.json'
embeddings = OpenAIEmbeddings()
country_food = input('정하세요: ').replace(" ", "_").replace("&", "_")
#----------------------------------------------------------------------
# 한식
if country_food == '한식':
with open (korea_food, 'r', encoding= 'utf-8') as k:
korean_food_list = json.load(k)
document= [Document(page_content = food_list) for food_list in korean_food_list]
vector_store = Chroma.from_documents(documents=document, embedding=embeddings, persist_directory=f"chroma_{country_food}")
vector_store.persist()
#----------------------------------------------------------------------
# 양식
elif country_food == '양식':
with open (western_food, 'r', encoding= 'utf-8') as w:
western_food_list = json.load(w)
document= [Document(page_content = food_list) for food_list in western_food_list]
vector_store = Chroma.from_documents(documents=document, embedding_function=embeddings, persist_directory=f"chroma_{country_food}")
vector_store.persist()
#----------------------------------------------------------------------
# 일식
elif country_food == '일식':
with open (japanses_food, 'r', encoding= 'utf-8') as j:
japanses_food_list = json.load(j)
document= [Document(page_content = food_list) for food_list in japanses_food_list]
vector_store = Chroma.from_documents(documents=document, embedding_function=embeddings, persist_directory=f"chroma_{country_food}")
vector_store.persist()
#----------------------------------------------------------------------
# 중식
elif country_food == '중식':
with open (chinses_food, 'r', encoding= 'utf-8') as c:
chinses_food_list = json.load(c)
document= [Document(page_content = food_list) for food_list in chinses_food_list]
vector_store = Chroma.from_documents(documents=document, embedding_function=embeddings, persist_directory=f"chroma_{country_food}")
vector_store.persist()
#----------------------------------------------------------------------
else:
vector_store = Chroma(persist_directory=f"chroma_{country_food}", embedding_function=embeddings)
llm = ChatOpenAI(model = 'gpt-3.5-turbo', temperature = 0, streaming=True)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vector_store.as_retriever()
)
query = "김치 볶음밥 레시피와 칼로리에 대해 설명해주세요."
response = qa_chain.run(query, return_streaming_output=True)
print(response, end='', flush=True)
데이터는 그냥 .json 파일로 처리를 완료했고, 그것을 LLM과 RAG 구축인데.....아직 잘 작동하지는 않습니다
먼저,
파일 경로 설정: 각 나라별 음식을 저장한 JSON 파일의 경로를 변수로 설정.
Embeddings 설정: OpenAIEmbeddings()는 OpenAI에서 제공하는 임베딩 모델을 사용하여 텍스트 데이터를 벡터로 변환하는 객체입니다. 이를 embeddings 변수에 저장합니다.
2. 사용자 입력 처리
input() 함수로 사용자가 음식 종류(한식, 양식, 일식, 중식)를 입력받습니다. .replace(" ", "_")와 .replace("&", "_")는 공백이나 앰퍼샌드(&)를 _로 변경하는 코드입니다. 입력이 한식이라면 '한식'으로, 공백이나 특수문자를 대체하는 방식입니다.(사실 이건 에러가 나서 고칠려고 한 부분입니다)country_food = input('정하세요: ').replace(" ", "_").replace("&", "_")
if country_food == '한식': with open(korea_food, 'r', encoding='utf-8') as k: korean_food_list = json.load(k) document = [Document(page_content=food_list) for food_list in korean_food_list] vector_store = Chroma.from_documents(documents=document, embedding=embeddings, persist_directory=f"chroma_{country_food}") vector_store.persist()
잠깐 여기서 persist란?
persist는 데이터를 저장(persist) 하거나 유지하는 동작을 말합니다. 코드를 통해 실행 시, 데이터가 메모리에서만 유지되지 않고, 디스크에 영구적으로 저장되어 나중에 다시 사용할 수 있도록 하는 기능을 제공합니다.
프로그램 실행 중 생성된 데이터는 보통 RAM(메모리)에 저장되며, 프로그램이 종료되면 삭제됩니다.
반면, 데이터를 디스크, 데이터베이스, 파일 시스템 등에 저장하면 프로그램이 종료되어도 데이터를 보존(persist)할 수 있습니다.
Persisting 데이터는 디스크, 네트워크, 클라우드 등 영구적인 스토리지로 데이터를 저장하는 작업입니다.
참고로 persist는 Chroma라는 오픈소스 벡터 데이터베이스 프레임워크에서 제공되는 메서드입니다.
그런데 보통 그냥 json으로 저장해도 문제는 없습니다. persist도 하나의 저장 방법이기 때문에(영어뜻)
파일 기반 persist: JSON, CSV 등 파일로 데이터 저장.
데이터베이스 persist: SQLite, MySQL 등 데이터베이스 사용.
캐싱 persist: Redis 같은 메모리 기반 저장소.
객체 persist: Pickle 등으로 파이썬 객체 저장.
벡터 데이터 persist: Chroma 같은 벡터 데이터베이스.
json으로 저장할 때
import json # 데이터 data = { "name": "김치 볶음밥", "calories": 500, "ingredients": ["밥", "김치", "계란"] } # 데이터 persist: JSON 파일로 저장 with open("korean_food.json", "w", encoding="utf-8") as file: json.dump(data, file, ensure_ascii=False) print("데이터가 'korean_food.json'에 저장되었습니다.") # 데이터 로드 with open("korean_food.json", "r", encoding="utf-8") as file: loaded_data = json.load(file) print("로드된 데이터:", loaded_data)
persist()함수 사용
from langchain.vectorstores import Chroma from langchain.embeddings.openai import OpenAIEmbeddings from langchain.schema import Document # 예시 데이터 documents = [ Document(page_content="김치볶음밥 레시피: 밥, 김치, 계란"), Document(page_content="비빔밥 레시피: 밥, 고추장, 나물") ] # 임베딩 모델 embeddings = OpenAIEmbeddings() # Chroma Vector Store 생성 (데이터는 현재 메모리에만 있음) vector_store = Chroma.from_documents( documents=documents, embedding=embeddings, persist_directory="chroma_persist" ) # 데이터 디스크에 저장 vector_store.persist() print("데이터가 디스크에 저장되었습니다.")
persist() 메서드가 호출되는 경우는 특정 라이브러리나 프레임워크가 데이터를 저장(persist)하기 위해 제공하는 함수를 사용하는 것입니다. 이 메서드는 데이터나 객체를 특정한 방식으로 영구 저장하는 역할을 합니다.
여기서 persist()의 역할
persist() 메서드는 데이터의 저장 방식과 위치를 라이브러리나 도구에서 정의된 대로 처리합니다. 예를 들어:
Chroma: 벡터 데이터를 디스크에 저장.
다른 라이브러리: 캐시나 파일 저장소, 데이터베이스 등 다양한 방식으로 데이터를 저장.
vector_store.persist()의 구체적인 역할 (Chroma의 경우)
라이브러리: LangChain의 Chroma
persist()는 메모리 상의 데이터를 디스크로 저장합니다.
저장된 데이터는 프로그램이 종료되더라도 다시 로드할 수 있습니다.
Chroma에서의 저장 과정:
Chroma는 벡터 데이터(문서 임베딩 등)를 디스크의 특정 디렉터리에 저장합니다.
이 데이터는 SQLite 데이터베이스와 파일 형식으로 관리됩니다.
persist()가 호출되기 전에는 데이터가 메모리에만 유지됩니다.
나머지는 일반 LLM 구축입니다.
기본 벡터 스토어 생성 (기타 경우)else: vector_store = Chroma(persist_directory=f"chroma_{country_food}", embedding_function=embeddings)
위 조건에 맞지 않는 입력(한식, 양식, 일식, 중식)이 들어오면, 기본적으로 Chroma 객체를 생성하여 임베딩 모델을 사용해 데이터를 벡터화하고, 해당 디렉터리에서 데이터를 불러옵니다.
LLM 및 QA 설정llm = ChatOpenAI(model='gpt-3.5-turbo', temperature=0, streaming=True) qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=vector_store.as_retriever() )
LLM 설정: ChatOpenAI()를 사용하여 gpt-3.5-turbo 모델을 설정합니다. temperature=0은 모델의 출력을 더 정밀하게 하여, 무작위성이 적도록 설정하는 것입니다.
QA 체인 설정: RetrievalQA.from_chain_type()로 질문 응답 시스템을 설정합니다. 이 체인은 vector_store에서 벡터 검색을 통해 적절한 정보를 찾고, 그 정보를 기반으로 LLM이 답변을 생성합니다.query = "김치 볶음밥 레시피와 칼로리에 대해 설명해주세요." response = qa_chain.run(query, return_streaming_output=True) print(response, end='', flush=True)
쿼리: 사용자가 요청한 질문인 "김치 볶음밥 레시피와 칼로리에 대해 설명해주세요."를 query 변수에 저장합니다.
응답 실행: qa_chain.run()으로 해당 쿼리를 처리하고, return_streaming_output=True로 응답을 스트리밍 방식으로 받아옵니다.
응답 출력: response를 출력하여 결과를 사용자에게 보여줍니다. flush=True는 출력 버퍼를 즉시 비워주는 설정입니다.