5.4 랭체인의 메모리 사용하기
- 이번 실습은 앞에서 진행했던 실습에 이어서, 메모리 부분만 추가합니다. 베모리는 이전 대화를 기억하여 문맥을 유지할 수 있도록 도와줍니다.
- 랭체인을 사용하여 AI 기반 검색 및 문서 처리를 위한 라이브러리를 설치합니다.
%pip install langchain-chroma langchain pandas pypdf langchain-openai
- 설치한 langchain-chroma는 랭체인과 ChromaDB를 통합하여 사용할 수 있는 라이브러리 입니다. 즉, 랭체인에서 ChromaDB를 벡터 저장소로 활용할 때 사용합니다.
- 설치 결과는 다음과 같습니다.
Requirement already satisfied: langchain-chroma in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (0.2.2)
Requirement already satisfied: langchain in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (0.3.26)
Requirement already satisfied: pandas in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (2.2.3)
Requirement already satisfied: pypdf in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (5.3.0)
Requirement already satisfied: langchain-openai in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (0.3.6)
Requirement already satisfied: langchain-core!=0.3.0,!=0.3.1,!=0.3.10,!=0.3.11,!=0.3.12,!=0.3.13,!=0.3.14,!=0.3.2,!=0.3.3,!=0.3.4,!=0.3.5,!=0.3.6,!=0.3.7,!=0.3.8,!=0.3.9,<0.4.0,>=0.2.43 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-chroma) (0.3.68)
Requirement already satisfied: numpy<2.0.0,>=1.22.4 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-chroma) (1.26.4)
Requirement already satisfied: chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-chroma) (0.6.3)
Requirement already satisfied: langchain-text-splitters<1.0.0,>=0.3.8 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (0.3.8)
Requirement already satisfied: langsmith>=0.1.17 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (0.4.5)
Requirement already satisfied: pydantic<3.0.0,>=2.7.4 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (2.11.4)
Requirement already satisfied: SQLAlchemy<3,>=1.4 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (2.0.38)
Requirement already satisfied: requests<3,>=2 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (2.32.3)
Requirement already satisfied: PyYAML>=5.3 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (6.0.2)
Requirement already satisfied: async-timeout<5.0.0,>=4.0.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (4.0.3)
Requirement already satisfied: python-dateutil>=2.8.2 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from pandas) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from pandas) (2025.1)
Requirement already satisfied: tzdata>=2022.7 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from pandas) (2025.1)
Requirement already satisfied: typing_extensions>=4.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from pypdf) (4.12.2)
Requirement already satisfied: openai<2.0.0,>=1.58.1 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-openai) (1.63.2)
Requirement already satisfied: tiktoken<1,>=0.7 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-openai) (0.9.0)
Requirement already satisfied: build>=1.0.3 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0->langchain-chroma) (1.2.2.post1)
Requirement already satisfied: chroma-hnswlib==0.7.6 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0->langchain-chroma) (0.7.6)
Requirement already satisfied: fastapi>=0.95.2 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0->langchain-chroma) (0.115.12)
Requirement already satisfied: uvicorn>=0.18.3 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from uvicorn[standard]>=0.18.3->chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0->langchain-chroma) (0.34.0)
...
Requirement already satisfied: humanfriendly>=9.1 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from coloredlogs->onnxruntime>=1.14.1->chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0->langchain-chroma) (10.0)
Requirement already satisfied: mpmath<1.4,>=1.1.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from sympy->onnxruntime>=1.14.1->chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0->langchain-chroma) (1.3.0)
Requirement already satisfied: pyreadline3 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from humanfriendly>=9.1->coloredlogs->onnxruntime>=1.14.1->chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0->langchain-chroma) (3.5.4)
Requirement already satisfied: pyasn1<0.7.0,>=0.4.6 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from pyasn1-modules>=0.2.1->google-auth>=1.0.1->kubernetes>=28.1.0->chromadb!=0.5.10,!=0.5.11,!=0.5.12,!=0.5.4,!=0.5.5,!=0.5.7,!=0.5.9,<0.7.0,>=0.4.0->langchain-chroma) (0.6.1)
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
- 이 중에서 langchain과 langchain-community 라이브러리는 업그레이드 합니다. 추후 사용할 ConversationalBufferMemory 클래스의 오류를 방지하기 위해서입니다.
%pip install --upgrade langchain langchain-community
Requirement already satisfied: langchain in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (0.3.26)
Requirement already satisfied: langchain-community in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (0.3.27)
Requirement already satisfied: langchain-core<1.0.0,>=0.3.66 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (0.3.68)
Requirement already satisfied: langchain-text-splitters<1.0.0,>=0.3.8 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (0.3.8)
Requirement already satisfied: langsmith>=0.1.17 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (0.4.5)
Requirement already satisfied: pydantic<3.0.0,>=2.7.4 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (2.11.4)
Requirement already satisfied: SQLAlchemy<3,>=1.4 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (2.0.38)
Requirement already satisfied: requests<3,>=2 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (2.32.3)
Requirement already satisfied: PyYAML>=5.3 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (6.0.2)
Requirement already satisfied: async-timeout<5.0.0,>=4.0.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain) (4.0.3)
Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-community) (3.11.12)
Requirement already satisfied: tenacity!=8.4.0,<10,>=8.1.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-community) (9.0.0)
Requirement already satisfied: dataclasses-json<0.7,>=0.5.7 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-community) (0.6.7)
Requirement already satisfied: pydantic-settings<3.0.0,>=2.4.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-community) (2.8.0)
Requirement already satisfied: httpx-sse<1.0.0,>=0.4.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-community) (0.4.0)
Requirement already satisfied: numpy>=1.26.2 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from langchain-community) (1.26.4)
Requirement already satisfied: aiohappyeyeballs>=2.3.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (2.4.6)
Requirement already satisfied: aiosignal>=1.1.2 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (1.3.2)
Requirement already satisfied: attrs>=17.3.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (25.1.0)
Requirement already satisfied: frozenlist>=1.1.1 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (1.5.0)
Requirement already satisfied: multidict<7.0,>=4.5 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (6.1.0)
Requirement already satisfied: propcache>=0.2.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (0.3.0)
Requirement already satisfied: yarl<2.0,>=1.17.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (1.18.3)
Requirement already satisfied: marshmallow<4.0.0,>=3.18.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from dataclasses-json<0.7,>=0.5.7->langchain-community) (3.26.1)
Requirement already satisfied: typing-inspect<1,>=0.4.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from dataclasses-json<0.7,>=0.5.7->langchain-community) (0.9.0)
...
Requirement already satisfied: h11<0.15,>=0.13 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->langsmith>=0.1.17->langchain) (0.14.0)
Requirement already satisfied: jsonpointer>=1.9 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from jsonpatch<2.0,>=1.33->langchain-core<1.0.0,>=0.3.66->langchain) (3.0.0)
Requirement already satisfied: mypy-extensions>=0.3.0 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from typing-inspect<1,>=0.4.0->dataclasses-json<0.7,>=0.5.7->langchain-community) (1.0.0)
Requirement already satisfied: exceptiongroup>=1.0.2 in c:\users\jyseo\anaconda3\envs\rag\lib\site-packages (from anyio->httpx<1,>=0.23.0->langsmith>=0.1.17->langchain) (1.2.0)
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
- OpenAI의 GPT-4o 모델을 설정하고 사용할 수 있도록 준비합니다.
import os
os.environ["OPENAI_API_KEY"] = "sk" #openai 키 입력
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="gpt-4o",
temperature = 0,
)
from langchain.document_loaders import PyPDFLoader
docs = [] # 추출된 문서를 저장할 리스트를 초기화
loader = PyPDFLoader("d:/data/안구건조증.pdf") # "d:/data/안구건조증.pdf" 경로의 PDF 파일을 PyPDFLoader로 로드
# PDF에서 텍스트 데이터를 추출하여 리스트 형태로 반환
text_content = loader.load()
- 랭체인과 ChromaDB를 활용하여 문서를 벡터화하고, 검색할 수 있도록 벡터 데이터베이스를 구축합니다.
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma # 벡터 데이터를 저장하고 검색하는 벡터 데이터베이스 (ChromaDB)
from langchain.text_splitter import CharacterTextSplitter
# 문서 분할 (텍스트를 작은 단위로 나누기)
text_splitter = CharacterTextSplitter(
separator="\n\n",
chunk_size=100,
chunk_overlap=10,
length_function=len,
is_separator_regex=False,
)
# 문서를 CharacterTextSplitter를 사용하여 분할
splits = text_splitter.split_documents(text_content)
# 문서를 CharacterTextSplitter를 사용하여 분할
texts = [doc.page_content for doc in splits]
# 문서를 CharacterTextSplitter를 사용하여 분할
embeddings = OpenAIEmbeddings()
# 변환된 벡터를 Chroma 벡터 데이터베이스에 저장
vectorstore = Chroma(persist_directory='d:/data/db_chroma_complete', embedding_function=embeddings)
- 안구건조증 관련 정보에 특화된 프롬프트를 생성합니다.
from langchain_core.prompts import PromptTemplate
custom_prompt_template = PromptTemplate(
template = """당신은 안구건조증에 대한 정보를 제공하는 건강 지킴이 챗봇입니다.
{context}
제공된 소스 데이터만 사용하여 고객의 질문에 답하세요.
모르겠다면 "잘 모르겠습니다."라고 답하세요.
친절하고 예의 바르며 전문적인 어조를 사용하세요.
답변은 간결하게 유지하세요.
질문: {question}
답변:
""",
input_variables=["context"]
)
chain_type_kwargs = {"prompt": custom_prompt_template}
- ChromaDB를 활용하여 사용자의 질문(query)과 가장 유사한 문서를 검색합니다.
query = "습도가 안구건조증에 미치는 영향은?"
retriever = vectorstore.similarity_search(query,k=8) # vectorstore(ChromaDB 벡터 저장소)에서 검색 수행
- 저장된 벡터 데이터베이스에서 문서를 검색하고, GPT-4o와 결합하여 질의에 답변합니다.
from langchain.chains import RetrievalQA
# RetrievalQA.from_chain_type()을 사용하여 QA 체인 구성
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # 기본적으로 retrieved 문서를 합쳐서 처리
retriever=vectorstore.as_retriever(),
chain_type_kwargs=chain_type_kwargs #
)
# 사용자의 질문을 입력하여 검색 및 응답 생성
result = qa_chain.invoke({"query": query})
result["result"]
'습도는 안구건조증에 중요한 영향을 미칩니다. 낮은 습도 환경에서는 눈의 수분 증발이 증가하여 안구건조증
증상이 악화될 수 있습니다. 적절한 습도를 유지하면 눈의 수분 증발을 줄이고 안구건조증 증상을 완화하는 데
도움이 될 수 있습니다.'
query = "인공눈물은 자주 사용해도 되는거야?"
result = qa_chain.invoke({"query": query})
result["result"]
'인공눈물은 일반적으로 안전하게 자주 사용할 수 있습니다. 그러나 하루에 너무 많이 사용해야 한다면,
안구건조증의 근본적인 원인을 확인하기 위해 안과 전문의와 상담하는 것이 좋습니다.'
- 여기까지는 앞에서 진행했던 실습과 동일합니다. 단지 PDF 파일과 벡터 데이터베이스만 바뀌었을 뿐입니다. 이제 대화 이력을 저장하는 메모리를 사용해봅시다.
- 랭체인의 ConversationBufferMemory를 사용하여 챗봇이 대화 이력을 저장하고 관리하도록 설정합니다. ConversationBufferMemory는 랭체인에서 제공하는 메모리 관리 클래스 중 하나로 대화 내역(context)을 저장하고 유지하는 역할을 합니다. 이를 이용하면 사용자의 이전 질문 및 답변을 기억하며, 더 자연스러운 대화 흐름을 유지할 수 있습니다.
# 메모리 관리
from langchain.memory import ConversationBufferMemory # 랭체인에서 대화 이력을 저장하고 관리하는 라이브러리
memory = ConversationBufferMemory(
memory_key="chat_history", # 저장된 대화를 "chat_history"라는 키 값으로 관리
return_messages=True, # 이전 대화를 메시지 형식(List[Message])으로 반환 (AI가 대화 문맥을 이해할 수 있도록 함)
output_key="result" # 출력 데이터를 저장할 키 값
)
- ConversationalRetrievalChain을 활용하여 문맥을 유지하면서 질의에 답변하도옥 구성합니다. ConversationalRetrievalChain은 랭체인에서 제공하는 대화형 검색 체인으로, 사용자의 질문에 대한 문맥을 유지하면서 LLM과 벡터 데이터베이스를 활용하여 검색 기반 응답을 생성하는 데 사용됩니다.
from langchain.chains import ConversationalRetrievalChain # 문맥을 유지하면서 검색 기능을 추가한 질의응답(QA) 체인 라이브러리
retriever=vectorstore.as_retriever()
qa_chain_memory = ConversationalRetrievalChain.from_llm(
llm,
retriever=retriever, # ChromaDB의 벡터 데이터베이스에서 유사한 문서를 검색할 수 있도록 설정
memory=memory, # 이전 대화를 기억하여 문맥을 유지할 수 있도록 설정
output_key="result"
)
- 마지막으로 질문을 합니다. 여기서는 동일한 질문을 했지만 문맥을 유지하는지 확인하기 위해서는 여러 질문을 해보아야 합니다.
query = "안구건조증 예방 방법은?"
result = qa_chain_memory.invoke({"question": query})
result["result"]
'안구건조증을 예방하기 위해 다음과 같은 방법을 고려할 수 있습니다:\n\n
1. **환경 조절**: 실내 습도를 적절히 유지하고, 건조한 환경을 피합니다.
가습기를 사용하여 공기를 촉촉하게 유지하는 것이 도움이 될 수 있습니다.\n\n
2. **눈 깜빡이기**: 컴퓨터나 스마트폰을 장시간 사용할 때는 의식적으로 눈을 자주 깜빡여 눈의 표면을 촉촉하게
유지합니다.\n\n
3. **휴식 시간**: 장시간 화면을 볼 때는 20-20-20 규칙을 따릅니다. 20분마다 20피트(약 6미터) 떨어진 곳을
20초 동안 바라보며 눈을 쉬게 합니다.\n\n
4. **인공눈물 사용**: 필요할 때 인공눈물을 사용하여 눈의 수분을 보충합니다. 방부제가 없는 제품을 선택하는 것
이 좋습니다.\n\n
5. **적절한 영양 섭취**: 오메가-3 지방산이 풍부한 음식을 섭취하면 눈 건강에 도움이 될 수 있습니다.
생선, 아마씨, 호두 등이 좋은 예입니다.\n\n
6.**눈 보호**: 바람이 강한 날이나 햇빛이 강한 날에는 선글라스를 착용하여 눈을 보호합니다.\n\n
이러한 방법들을 통해 안구건조증을 예방하고 눈 건강을 유지할 수 있습니다.'
- 마지막으로 메모리를 통해 문맥을 유지하는지 알아보기 위해 다음과 같은 질문을 해봅니다. 질문에서 '안구건조증'이라는 단어 대신 '이것'으로 대체해보았습니다.
query = "이것은 왜 생기는거야?"
result = qa_chain_memory.invoke({"question": query})
result["result"]
'안구건조증은 눈물이 충분히 생성되지 않거나 눈물이 너무 빨리 증발하여 눈이 건조해지는 상태를 말합니다.
이 상태는 여러 가지 원인에 의해 발생할 수 있습니다. 주요 원인으로는 다음과 같은 것들이 있습니다:\n\n
1. **나이**: 나이가 들면서 눈물 생성이 감소할 수 있습니다.\n
2. **환경적 요인**: 건조한 공기, 바람, 연기 등은 눈물의 증발을 촉진시킬 수 있습니다.\n
3. **장시간의 화면 사용**: 컴퓨터나 스마트폰을 장시간 사용할 경우 눈을 깜빡이는 횟수가 줄어들어
눈물이 빨리 증발할 수 있습니다.\n
4. **콘택트렌즈 착용**: 장시간 콘택트렌즈를 착용하면 눈의 수분이 감소할 수 있습니다.\n
5. **약물**: 항히스타민제, 항우울제, 혈압약 등 일부 약물은 눈물 생성을 감소시킬 수 있습니다.\n
6. **건강 상태**: 류마티스 관절염, 당뇨병, 갑상선 질환 등 일부 질환은 안구건조증을 유발할 수 있습니다.\n\n
이 외에도 호르몬 변화나 눈꺼풀의 문제 등 다양한 요인이 안구건조증을 유발할 수 있습니다.
안구건조증이 지속되면 안과 전문의와 상담하여 적절한 치료를 받는 것이 중요합니다.'
- '이것'을 안구건조증으로 정확히 이해하고 있음을 확인할 수 있습니다.