카테고리 없음

스파르타 AI-8기 TIL(1/5)-TeamProject

kimjunki-8 2025. 1. 5. 21:13

오늘 완성한 코드

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. 사용자 입력 처리
country_food = input('정하세요: ').replace(" ", "_").replace("&", "_")​
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는 출력 버퍼를 즉시 비워주는 설정입니다.