Data Science How-To's

LangChain으로 챗봇을 만드는 방법

Read this post in other languages:

이 글은 딥러닝 엔지니어이자 17년의 경력을 보유한 Python 프로그래머인 Dido Grigorov가 기고했습니다.

챗봇은 이제 단순한 Q&A 도구 이상으로 발전했습니다. 대형 언어 모델(LLM)을 활용하여 대화의 맥락을 이해하고 인간과 비슷한 답변을 생성할 수 있어 고객 지원 분야 및 기타 가상 지원 분야에서 매우 유용하게 사용되고 있습니다.

오픈 소스 프레임워크인 LangChain은 원활한 모델 통합, 컨텍스트 관리 및 프롬프트 엔지니어링용 도구를 다양하게 제공하여 대화형 챗봇의 구축 과정을 간소화합니다.

이 블로그 글에서는 LangChain의 작동 방식과 챗봇이 LLM과 어떻게 상호 작용하는지 알아보겠습니다. 또한, LangChain과 GPT-3를 기반으로 컨텍스트를 인식하여 정확하고 관련성이 높은 답변을 제공하는 챗봇을 만드는 방법도 단계적으로 안내해 드리겠습니다.

LLM 분야에서 챗봇이란?

LLM 분야에서 챗봇이란 텍스트나 음성 수단을 통하여 사용자와 사람처럼 대화하는 것을 시뮬레이션할 수 있는 첨단 소프트웨어를 말합니다. 이러한 챗봇은 다양한 입력 프롬프트에 사람처럼 응답할 수 있도록 막대한 양의 텍스트 데이터로 훈련된 신경망인 LLM의 고급 기능을 활용합니다.

무엇보다 LLM 기반의 챗봇은 답변을 생성할 때 대화의 맥락을 고려할 수 있습니다. 즉, 오고 가는 대화에서 일관성을 유지할 수 있고, 복잡한 쿼리도 처리해서 사용자의 의도에 맞는 결과물을 제공할 수 있습니다. 또한 챗봇은 사용자가 입력한 내용에서 감정적 어조를 평가하고 사용자의 감정에 맞춰 응답을 조정합니다.

챗봇은 조정하고 개인화할 수 있는 폭이 매우 넓습니다. 챗봇은 사용자가 자신과 상호 작용하는 방식을 학습하여 개인의 선호도와 요구 사항에 따라 응답을 조정하면서 개선합니다.

LangChain이란?

LangChain은 대형 언어 모델(LLM)을 사용하는 앱 제작을 지원하도록 개발된 오픈 소스 프레임워크입니다. 정확도와 관련성을 유지하면서도 모델이 생성한 정보를 더욱 개인화하기 위한 도구와 추상화가 포함되어 있습니다.

LLM에 관해 읽다 보면 ‘프롬프트 체인’이라는 용어를 자주 접하게 됩니다. 프롬프트 체인이란 인공지능이나 머신러닝 분야에서 사용되는 일련의 프롬프트나 명령어를 의미하며, 여러 단계로 구성된 프로세스를 통해 AI 모델이 더 정확하고, 상세하며 정제된 결과물을 내도록 유도하는 것이 목적입니다. 이 방식은 작성, 문제 해결 또는 코드 생성을 포함한 다양한 작업에 적용될 수 있습니다.

LangChain을 활용하면 새로운 프롬프트 체인을 생성할 수 있으며, 이는 LangChain의 가장 강력한 특징 중 하나입니다. 새로운 데이터세트를 사용할 때 모델을 다시 훈련할 필요 없이 기존의 프롬프트 템플릿을 수정할 수도 있습니다.

LangChain의 작동 방식

LangChain은 언어 모델을 활용하는 애플리케이션의 개발을 간소화하기 위해 설계된 프레임워크입니다. 자연어 처리(NLP)와 대형 언어 모델과 관련된 애플리케이션을 개발자가 효율적으로 개발하고 관리할 수 있도록 다양한 도구도 제공합니다. 원하는 결과(챗봇, 작업 자동화, 가상 어시스턴트, 고객 지원 등)를 얻기 위해 필요한 단계를 정의하고 LangChain을 사용하여 언어 모델을 유연하게 특정 비즈니스 맥락에 맞도록 조정할 수 있습니다.

다음은 LangChain의 작동 방식에 관한 대략적인 설명입니다.

모델 통합

LangChain은 OpenAI, Hugging Face, Cohere, Anyscale, Azure Models, Databricks, Ollama, Llama, GPT4All, Spacy, Pinecone, AWS Bedrock, MistralAI 등이 제공하는 다양한 언어 모델을 지원하여 개발자가 손쉽게 모델을 전환하거나 다양한 모델을 하나의 애플리케이션에서 사용할 수 있습니다. 자체 개발한 모델 통합 솔루션을 구축하여 특정 애플리케이션에 맞는 특정 기능을 활용할 수도 있습니다.

체인

LangChain의 핵심 개념은 체인입니다. 체인은 컨텍스트를 고려하는 응답을 할 수 있도록 서로 다른 AI 구성 요소를 하나로 묶어 줍니다. 체인은 사용자의 프롬프트와 최종 모델 결과물 간의 자동화된 액션을 의미합니다. LangChain에는 두 가지 체인이 있습니다.

  • 순차 체인: 순차 체인은 모델이나 함수의 결과물이 다른 모델이나 함수에 입력으로 사용되도록 허용합니다. 여러 단계로 구성되고 서로 의존성이 있는 프로세스를 만들 때 특히 유용합니다.
  • 병렬 체인: 병렬 체인은 다수의 작업이 동시에 실행되고 결과물이 마지막에 병합되도록 허용합니다. 작업이 완전히 독립적인 하위 작업으로 분할될 수 있을 때 매우 효과적입니다.

메모리

LangChain은 다양한 상호 작용에서 정보 저장과 검색을 도와줍니다. 이는 챗봇이나 대화형 에이전트와 같이 컨텍스트가 지속되어야 하는 경우에 필수적입니다. 메모리도 두 가지를 사용할 수 있습니다.

  • 단기 메모리 – 최근 세션을 추적하는 데 좋습니다.
  • 장기 메모리 – 이전 세션의 정보를 유지하도록 허용하여 이전 채팅이나 사용자의 설정을 시스템이 호출할 때 성능을 개선합니다.

도구와 유틸리티

LangChain이 제공하는 다양한 도구 중에서 가장 많이 사용되는 도구는 Prompt Engineering, Data Loaders와 Evaluators입니다.  Prompt Engineering의 경우 언어 모델에서 최상의 응답을 얻기 위해 필요한 고품질의 프롬프트를 개발할 때 사용할 수 있는 유틸리티가 포함되어 있습니다.

csv, pdf 또는 다른 형식의 파일을 불러오려는 경우 Data Loaders를 사용하면 다양한 형식의 데이터를 불러와 전처리하여 모델 상호 작용에 사용할 수 있도록 만들 수 있습니다.

머신러닝 모델과 대형 언어 모델로 작업할 때 평가는 필수적입니다. 같은 맥락에서 LangChain은 Evaluators를 제공합니다. 이는 생성된 결과가 필수 기준을 충족하도록 언어 모델과 체인을 테스트할 때 사용되는 도구로, 다음이 포함될 수 있습니다.

데이터세트 기준:

  • 수동으로 선별된 예시: 다양한 고품질 입력으로 시작합니다.
  • 기존 로그: 실제 사용자 데이터와 피드백을 사용합니다.
  • 합성 데이터: 초기 데이터를 기반으로 예시를 생성합니다.

평가 종류:

  • 인간: 수동 채점 및 피드백입니다.
  • 휴리스틱: 규칙 기반의 함수로, 참조가 없거나 참조 기반일 수 있습니다.
  • LLM 기반 평가: 인코딩된 기준을 바탕으로 LLM이 출력물을 채점합니다.
  • 쌍으로 비교: 두 개의 출력물을 비교하여 나은 것을 선택합니다.

애플리케이션 평가:

  • 유닛 테스트: 휴리스틱 기반의 빠른 검사입니다.
  • 회귀 테스트: 시간의 흐름에 따른 성능 변화를 측정합니다.
  • 백테스트: 새로운 버전으로 프로덕션 데이터를 다시 실행합니다.
  • 온라인 평가: 실시간으로 안전 지표 또는 분류를 평가합니다.

에이전트
LangChain 에이전트는 기본적으로 자율적인 엔티티로서 LLM을 활용하여 사용자와 상호 작용하고, 작업을 수행하고, 자연어 입력 기반으로 결정을 내립니다.

액션 기반 에이전트는 언어 모델을 사용하여 최적의 액션을 판단하고 사전에 정의된 작업을 수행합니다. 반면에 대화형 에이전트 또는 챗봇과 같은 대화형 애플리케이션은 이러한 에이전트를 활용하는 동시에 쿼리에 응답할 때 사용자의 입력과 저장된 메모리도 고려합니다.

챗봇의 LLM 활용 방식

챗봇의 기반이 되는 LLM은 자연어 이해(NLU)와 자연어 생성(NLU)을 활용하며, 이는 방대한 텍스트 데이터로 사전에 트레이닝했기 때문에 가능합니다.

자연어 이해(NLU)

  • 컨텍스트 인식: LLM은 대화 속의 미묘한 어감이나 은유도 이해할 수 있으며, 오고 가는 대화의 흐름도 추적할 수 있습니다. 이를 통해 챗봇은 논리적이고 문맥에 맞는 응답을 사용자에게 제공할 수 있습니다.
  • 의도 인식: 이러한 모델은 언어가 구체적이든 두루뭉술하든 쿼리에서 사용자의 의도를 파악할 수 있습니다. 사용자가 무엇을 하려는지 파악하고 그 목표를 달성하는 데 도움을 주는 가장 좋은 방법을 판단할 수 있습니다.
  • 감정 분석: 챗봇은 사용된 언어의 어조를 통해 사용자의 감정을 파악하고 사용자의 감정 상태에 맞춰 사용자의 참여도를 높일 수 있습니다.

자연어 생성(NLG)

  • 응답 생성: LLM이 질문을 받아 제공하는 답변은 문법과 문맥 측면에서 모두 정확합니다. 이러한 모델은 방대한 양의 자연어 텍스트 데이터를 기반으로 트레이닝되고, 생성하는 응답이 인간의 대화를 모방하기 때문입니다.
  • 창의성과 유연성: 간단한 답변 외에도 LLM 기반의 챗봇은 스토리텔링, 시 쓰기는 물론 기술적인 문제를 상세히 설명할 수도 있습니다. 따라서 매우 유연하게 자료를 제공할 수 있다고 볼 수 있습니다.

개인화와 응용력

  • 상호 작용을 통한 학습: 챗봇이 상호 작용을 개인화할 수 있는 이유는 사용자의 행동과 선택을 보고 배울 수 있기 때문입니다. 지속적으로 학습하면서 갈수록 효율적이고 정확한 답변을 할 수 있다고 말할 수 있습니다.
  • 여러 분야에 적응: LLM은 특정 영역이나 전문 분야에 특화시켜 고객 관계, 기술 지원 또는 의료 분야의 주제 전문가 역할을 수행하도록 할 수 있습니다.

LLM은 다양한 언어로 된 텍스트를 이해하고 생성할 수 있기 때문에 다양한 언어적 맥락의 애플리케이션에 적용할 수 있습니다.

LangChain으로 나만의 챗봇을 만드는 5단계

이 프로젝트의 목적은 GPT-3를 활용하여 문서에서 답을 찾는 챗봇을 만드는 것입니다. 먼저, 온라인 기사에서 콘텐츠를 긁어와서 작은 청크로 쪼갠 다음 임베딩을 연산하고 Deep Lake에 저장합니다. 그런 다음 사용자 쿼리를 사용하여 Deep Lake로부터 가장 관련성이 높은 청크를 가져옵니다. 이러한 청크는 LLM으로 최종 답변을 생성하기 위해 프롬프트에 포함됩니다.

LLM은 오해의 소지가 있거나 잘못된 정보를 생성할 우려가 있다는 점에 유의하세요. 이러한 오류는 대부분의 고객 지원 상황에서는 용인될 수 없겠지만, 여전히 챗봇의 답변 초안은 상담원에게 큰 도움이 되며 상담원은 답변을 사용자에게 보내기 전에 검증할 수 있습니다.

다음으로 GPT-3로 대화를 관리하는 방법과 이 워크플로의 효율성을 보여주는 몇 가지 예시를 살펴보겠습니다.

1단계: 프로젝트 생성, 사전 준비와 필수 라이브러리 설치

먼저 챗봇을 만들 PyCharm 프로젝트를 생성합니다. Pycharm을 열고 ‘New project'(새 프로젝트)를 클릭합니다. 그런 다음, 프로젝트 이름을 입력합니다.

PyCharm 프로젝트 생성

프로젝트 설정이 완료되면 OpenAI API 플랫폼 웹사이트에 로그인하고(로그인하기 위해 OpenAI 웹사이트에 가입) ‘OPENAI_API_KEY‘를 생성합니다. 생성하려면 왼쪽 탐색 메뉴에서 ‘API Keys'(API 키) 섹션으로 이동한 다음 ‘+Create new secret key'(+새 비밀 키 생성) 버튼을 클릭합니다. 잊지 말고 키를 복사하세요.

그런 다음 Activeloop 웹사이트에 가입하고 ‘ACTIVELOOP_TOKEN‘을 받습니다. 로그인한 다음 ‘Create API Token'(API 토큰 생성) 버튼을 클릭하여 토큰 생성 페이지로 이동합니다. 이 토큰도 복사하세요.

토큰과 키를 모두 확보한 다음 PyCharm에서 실행 및 디버그 버튼 옆에 있는 점 세 개 버튼을 클릭하여 구성 설정을 열고 ‘Edit'(편집)을 선택합니다. 다음 창이 표시됩니다.

PyCharm의 실행/디버그 구성

이제 ‘Environment variables'(환경 변수) 필드를 찾은 다음 필드의 오른쪽에 있는 아이콘을 찾습니다. 아이콘을 클릭하면 다음 창이 표시됩니다.

PyCharm의 환경 변수

이제 + 버튼을 클릭하고 이름을 정확하게 입력하여 환경 변수를 추가합니다. 위에 언급된 ‘OPENAI_API_KEY‘ 및 ‘ACTIVELOOP_TOKEN‘과 동일해야 합니다. 준비되면 처음 표시된 창에서 OK(확인)를 클릭한 다음 두 번째 창에서 ‘Apply'(적용)와 ‘OK’를 클릭합니다.

이는 개인적으로 참 좋아하는 PyCharm의 매우 큰 장점입니다. 환경 변수를 추가적으로 호출하지 않아도 자동 처리되기 때문에 코드의 창의적 부분에 더 집중할 수 있습니다.

참고: Activeloop는 머신러닝과 인공지능용 데이터 인프라와 도구 개발 전문 기술 회사입니다. 이 회사는 특히 딥러닝 및 기타 AI 애플리케이션에서 대규모 데이터세트를 관리, 저장 및 처리하는 프로세스를 간소화하는 것을 목표로 하고 있습니다.

Deep Lake는 Activeloop의 대표 제품으로, 효율적인 데이터 저장, 관리 및 액세스 기능을 AI 분야에서 자주 사용되는 대규모 데이터세트에 최적화하여 제공합니다.

필요한 라이브러리 설치

여기서는 LangChain의 ‘SeleniumURLLoader‘ 클래스를 사용할 예정입니다. 이 클래스는 Python 라이브러리인 ‘unstructured‘와 ‘selenium‘을 사용합니다. pip를 사용해서 설치해 주세요.  이 코드는 0.7.7 버전으로 테스트되었지만 최신 버전을 설치하는 것이 좋습니다.

설치를 위해 PyCharm 터미널에서 다음의 명령어를 사용합니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
pip install unstructured selenium
pip install unstructured selenium
pip install unstructured selenium

이제 langchain, deeplake, openai를 설치해야 합니다. 설치하려면 터미널에서(Selenium을 설치할 때 썼던 창) 이 명령어를 사용하고, 설치가 모두 완료될 때까지 잠시 기다립니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
pip install langchain==0.0.208 deeplake openai==0.27.8 psutil tiktoken
pip install langchain==0.0.208 deeplake openai==0.27.8 psutil tiktoken
pip install langchain==0.0.208 deeplake openai==0.27.8 psutil tiktoken

모든 라이브러리가 올바르게 설치되었는지 확인한 후, 챗봇 앱에 필요한 다음 줄을 추가하고 실행 버튼을 클릭합니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import DeepLake
from langchain.text_splitter import CharacterTextSplitter
from langchain import OpenAI
from langchain.document_loaders import SeleniumURLLoader
from langchain import PromptTemplate
from langchain.embeddings.openai import OpenAIEmbeddings from langchain.vectorstores import DeepLake from langchain.text_splitter import CharacterTextSplitter from langchain import OpenAI from langchain.document_loaders import SeleniumURLLoader from langchain import PromptTemplate
from langchain.embeddings.openai import OpenAIEmbeddings

from langchain.vectorstores import DeepLake

from langchain.text_splitter import CharacterTextSplitter

from langchain import OpenAI

from langchain.document_loaders import SeleniumURLLoader

from langchain import PromptTemplate

PyCharm의 설정을 통해서도 라이브러리를 설치할 수 있습니다. 설정을 연 다음 Project(프로젝트) -> Python Interpreter(Python 인터프리터) 섹션으로 이동합니다. 그런 다음 + 버튼을 누르고 패키지를 찾은 다음 ‘Install Package'(패키지 설치) 버튼을 누릅니다. 준비가 완료된 후 창을 닫고 다음 창에서 ‘Apply'(적용)을 누르고 ‘OK'(확인)를 누릅니다.

PyCharm의 Python 인터프리터

2단계: 콘텐츠를 여러 청크로 나누고 임베딩 연산

앞서 말했듯이 이 챗봇은 온라인 기사의 콘텐츠를 사용하여 ‘소통’합니다. 그래서 시작할 때 Digitaltrends.com을 데이터 소스로 삼고 8개 기사를 선택했습니다. 기사는 모두 Python 목록으로 정리되어 ‘articles’라는 변수에 할당되었습니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
articles = ['https://www.digitaltrends.com/computing/claude-sonnet-vs-gpt-4o-comparison/',
'https://www.digitaltrends.com/computing/apple-intelligence-proves-that-macbooks-need-something-more/',
'https://www.digitaltrends.com/computing/how-to-use-openai-chatgpt-text-generation-chatbot/',
'https://www.digitaltrends.com/computing/character-ai-how-to-use/',
'https://www.digitaltrends.com/computing/how-to-upload-pdf-to-chatgpt/']
articles = ['https://www.digitaltrends.com/computing/claude-sonnet-vs-gpt-4o-comparison/', 'https://www.digitaltrends.com/computing/apple-intelligence-proves-that-macbooks-need-something-more/', 'https://www.digitaltrends.com/computing/how-to-use-openai-chatgpt-text-generation-chatbot/', 'https://www.digitaltrends.com/computing/character-ai-how-to-use/', 'https://www.digitaltrends.com/computing/how-to-upload-pdf-to-chatgpt/']
articles = ['https://www.digitaltrends.com/computing/claude-sonnet-vs-gpt-4o-comparison/',
           'https://www.digitaltrends.com/computing/apple-intelligence-proves-that-macbooks-need-something-more/',
           'https://www.digitaltrends.com/computing/how-to-use-openai-chatgpt-text-generation-chatbot/',
           'https://www.digitaltrends.com/computing/character-ai-how-to-use/',
           'https://www.digitaltrends.com/computing/how-to-upload-pdf-to-chatgpt/']

제공된 URL로부터 문서를 불러온 다음 ‘CharacterTextSplitter‘를 사용하여 겹치는 부분 없이 크기가 1,000인 청크로 분할합니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Use the selenium to load the documents
loader = SeleniumURLLoader(urls=articles)
docs_not_splitted = loader.load()
# Split the documents into smaller chunks
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(docs_not_splitted)
# Use the selenium to load the documents loader = SeleniumURLLoader(urls=articles) docs_not_splitted = loader.load() # Split the documents into smaller chunks text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) docs = text_splitter.split_documents(docs_not_splitted)
# Use the selenium to load the documents
loader = SeleniumURLLoader(urls=articles)
docs_not_splitted = loader.load()

# Split the documents into smaller chunks
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(docs_not_splitted)

지금까지의 코드를 실행하고 모두 잘 동작한다면 다음과 같은 출력이 나옵니다.

[Document(page_content="techcrunchnntechcrunchnnWe, TechCrunch, are part of the Yahoo family of brandsThe sites and apps that we own and operate, including Yahoo and AOL, and our digital advertising service, Yahoo Advertising.Yahoo family of brands.nn    When you use our sites and apps, we use nnCookiesCookies (including similar technologies such as web storage) allow the operators of websites and apps to store and read information from your device. Learn more in our cookie policy.cookies to:nnprovide our sites and apps to younnauthenticate users, apply security measures, and prevent spam and abuse, andnnmeasure your use of our sites and appsnn    If you click '", metadata={'source': ……………]

그런 다음 OpenAIEmbeddings를 사용하여 임베딩을 생성한 다음 클라우드에 호스팅된 DeepLake 벡터 저장소에 저장합니다. 프로덕션 환경에서 웹사이트나 교육 과정 전체를 DeepLake 데이터세트로 업로드하면 수천, 수백만 건의 문서가 검색되도록 할 수 있기 때문에 좋습니다.

클라우드의 서버리스 Deep Lake 데이터세트를 활용하면 전용 시스템에 벡터 저장소를 설정하지 않아도 다양한 위치의 애플리케이션이 중앙 데이터세트에 액세스할 수 있습니다.

임베딩과 청크 처리된 문서가 필요한 이유

LangChain으로 챗봇을 만들 때는 챗봇의 효율성, 정확도 및 성능과 관련된 몇 가지 이유로 인해 임베딩과 청크 처리된 문서가 필수적입니다.

임베딩이란 의미론적인 뜻을 담고 있는 텍스트(단어, 문장, 문단 또는 문서)를 벡터로 표현한 것입니다. 단어의 문맥과 의미를 숫자 형태로 담고 있습니다. 챗봇은 이를 활용해 뉘앙스, 동의어와 단어 간 관계를 파악하여 텍스트를 이해하고 문맥에 맞는 응답을 생성합니다.

임베딩 덕분에 챗봇은 사용자 쿼리에 사용된 단어가 달라도 의미론적으로 가장 관련성이 높은 정보 청크와 일치시킬 수 있기 때문에 가장 관련성이 높은 답변이나 정보를 지식 베이스에서 빠르게 식별하고 가져올 수 있습니다.

한편, 청크 처리는 큰 문서를 작고 관리하기 용이한 조각 또는 청크로 나누는 것입니다. 청크가 작으면 대용량 모놀리식 문서보다 더 빠르게 처리하고 분석할 수 있고, 챗봇의 응답 시간이 빨라집니다.

문서를 청크로 나누면 출력의 관련성도 높일 수 있습니다. 사용자의 질문은 문서의 특정 부분만 관련된 경우가 많습니다. 청크 처리를 하면 시스템이 관련이 있는 부분만 찾아서 가져올 수 있어서 챗봇이 더 정확한 답변을 제공할 수 있습니다.

이제 우리의 애플리케이션으로 돌아가서 다음 코드에 Activeloop 조직 ID를 추가하여 업데이트해 보겠습니다. 기본적으로 조직 ID는 사용자 이름과 동일합니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# TODO: use your organization id here. (by default, org id is your username)
my_activeloop_org_id = "didogrigorov"
my_activeloop_dataset_name = "jetbrains_article_dataset"
dataset_path = f"hub://{my_activeloop_org_id}/{my_activeloop_dataset_name}"
db = DeepLake(dataset_path=dataset_path, embedding_function=embeddings)
# add documents to our Deep Lake dataset
db.add_documents(docs)
# TODO: use your organization id here. (by default, org id is your username) my_activeloop_org_id = "didogrigorov" my_activeloop_dataset_name = "jetbrains_article_dataset" dataset_path = f"hub://{my_activeloop_org_id}/{my_activeloop_dataset_name}" db = DeepLake(dataset_path=dataset_path, embedding_function=embeddings) # add documents to our Deep Lake dataset db.add_documents(docs)
# TODO: use your organization id here. (by default, org id is your username)
my_activeloop_org_id = "didogrigorov"
my_activeloop_dataset_name = "jetbrains_article_dataset"
dataset_path = f"hub://{my_activeloop_org_id}/{my_activeloop_dataset_name}"
db = DeepLake(dataset_path=dataset_path, embedding_function=embeddings)


# add documents to our Deep Lake dataset
db.add_documents(docs)

제가 PyCharm에서 좋아하는 또 다른 훌륭한 기능은 Python 주석에 TODO 메모를 바로 추가하는 옵션입니다. 대문자로 TODO를 입력하기만 하면 PyCharm의 한 섹션에 모든 메모가 모여 한 눈에 볼 수 있습니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# TODO: use your organization id here. (by default, org id is your username)
# TODO: use your organization id here. (by default, org id is your username)
# TODO: use your organization id here. (by default, org id is your username)

메모를 클릭하면 해당 메모가 코드의 어디에 있는지 PyCharm에 바로 표시됩니다. 개발자에게 매우 편리한 기능이고 저는 매번 사용하고 있습니다.

PyCharm 내 Python 주석의 TODO 메모

코드를 실행하고 모두 정상 작동한다면 다음과 같은 출력이 나옵니다.

PyCharm에서 챗봇 코드 실행

쿼리와 가장 유사한 청크를 찾기 위해 Deep Lake 벡터 저장소가 제공하는 similarity_search 메서드를 활용할 수 있습니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Check the top relevant documents to a specific query
query = "how to check disk usage in linux?"
docs = db.similarity_search(query)
print(docs[0].page_content)
# Check the top relevant documents to a specific query query = "how to check disk usage in linux?" docs = db.similarity_search(query) print(docs[0].page_content)
# Check the top relevant documents to a specific query
query = "how to check disk usage in linux?"
docs = db.similarity_search(query)
print(docs[0].page_content)

3단계: GPT-3용 프롬프트 만들기

역할 프롬프팅, 영속적인 지식 베이스 데이터와 사용자의 질문을 통합하는 프롬프트 템플릿을 설계해 보겠습니다. 이 템플릿은 챗봇의 페르소나를 우수한 고객 지원 상담원으로 설정합니다. 사전에 서식이 지정된 기사 발췌문을 포함하는 chunks_formatted와 고객의 질문인 쿼리를 2개 입력 변수로 취합니다. 여기서 목표는 날조되거나 잘못된 정보는 방지하면서 주어진 청크만으로 정확한 답변을 생성하는 것입니다.

4단계: 챗봇 기능 만들기

응답을 생성하기 위해 사용자의 쿼리와 가장 유사한 top-k(예: top-3) 청크를 검색하면서 시작하겠습니다. 이러한 청크는 서식이 지정되어 프롬프트로 만들어지며 온도가 0으로 설정된 GPT-3 모델로 전달됩니다.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# user question
query = "How to check disk usage in linux?"
# retrieve relevant chunks
docs = db.similarity_search(query)
retrieved_chunks = [doc.page_content for doc in docs]
# format the prompt
chunks_formatted = "nn".join(retrieved_chunks)
prompt_formatted = prompt.format(chunks_formatted=chunks_formatted, query=query)
# generate answer
llm = OpenAI(model="gpt-3.5-turbo-instruct", temperature=0)
answer = llm(prompt_formatted)
print(answer)
# user question query = "How to check disk usage in linux?" # retrieve relevant chunks docs = db.similarity_search(query) retrieved_chunks = [doc.page_content for doc in docs] # format the prompt chunks_formatted = "nn".join(retrieved_chunks) prompt_formatted = prompt.format(chunks_formatted=chunks_formatted, query=query) # generate answer llm = OpenAI(model="gpt-3.5-turbo-instruct", temperature=0) answer = llm(prompt_formatted) print(answer)
# user question
query = "How to check disk usage in linux?"

# retrieve relevant chunks
docs = db.similarity_search(query)
retrieved_chunks = [doc.page_content for doc in docs]

# format the prompt
chunks_formatted = "nn".join(retrieved_chunks)
prompt_formatted = prompt.format(chunks_formatted=chunks_formatted, query=query)

# generate answer
llm = OpenAI(model="gpt-3.5-turbo-instruct", temperature=0)
answer = llm(prompt_formatted)
print(answer)

잘 동작한다면 다음과 같은 출력이 나옵니다.

PDF을 ChatGPT에 업로드하려면, 먼저 웹사이트에 로그인한 다음 텍스트 입력 필드 옆에 있는 클립 아이콘을 클릭하세요. 그런 다음 로컬 하드 드라이브, Google Drive 또는 Microsoft OneDrive에서 PDF를 선택합니다. 첨부가 완료되면 프롬프트 필드에 쿼리나 질문을 입력한 다음 업로드 버튼을 클릭합니다. 시스템이 PDF를 분석하고 응답을 줄 때까지는 시간이 조금 소요됩니다.

5단계: 대화 기록 만들기

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Create conversational memory
memory = ConversationBufferMemory(memory_key="chat_history", input_key="input")
# Define a prompt template that includes memory
template = """You are an exceptional customer support chatbot that gently answers questions.
{chat_history}
You know the following context information.
{chunks_formatted}
Answer the following question from a customer. Use only information from the previous context information. Do not invent stuff.
Question: {input}
Answer:"""
prompt = PromptTemplate(
input_variables=["chat_history", "chunks_formatted", "input"],
template=template,
)
# Initialize the OpenAI model
llm = OpenAI(openai_api_key="YOUR API KEY", model="gpt-3.5-turbo-instruct", temperature=0)
# Create the LLMChain with memory
chain = LLMChain(
llm=llm,
prompt=prompt,
memory=memory
)
# User query
query = "What was the 5th point about on the question how to remove spotify account?"
# Retrieve relevant chunks
docs = db.similarity_search(query)
retrieved_chunks = [doc.page_content for doc in docs]
# Format the chunks for the prompt
chunks_formatted = "nn".join(retrieved_chunks)
# Prepare the input for the chain
input_data = {
"input": query,
"chunks_formatted": chunks_formatted,
"chat_history": memory.buffer
}
# Simulate a conversation
response = chain.predict(**input_data)
print(response)
# Create conversational memory memory = ConversationBufferMemory(memory_key="chat_history", input_key="input") # Define a prompt template that includes memory template = """You are an exceptional customer support chatbot that gently answers questions. {chat_history} You know the following context information. {chunks_formatted} Answer the following question from a customer. Use only information from the previous context information. Do not invent stuff. Question: {input} Answer:""" prompt = PromptTemplate( input_variables=["chat_history", "chunks_formatted", "input"], template=template, ) # Initialize the OpenAI model llm = OpenAI(openai_api_key="YOUR API KEY", model="gpt-3.5-turbo-instruct", temperature=0) # Create the LLMChain with memory chain = LLMChain( llm=llm, prompt=prompt, memory=memory ) # User query query = "What was the 5th point about on the question how to remove spotify account?" # Retrieve relevant chunks docs = db.similarity_search(query) retrieved_chunks = [doc.page_content for doc in docs] # Format the chunks for the prompt chunks_formatted = "nn".join(retrieved_chunks) # Prepare the input for the chain input_data = { "input": query, "chunks_formatted": chunks_formatted, "chat_history": memory.buffer } # Simulate a conversation response = chain.predict(**input_data) print(response)
# Create conversational memory
memory = ConversationBufferMemory(memory_key="chat_history", input_key="input")

# Define a prompt template that includes memory
template = """You are an exceptional customer support chatbot that gently answers questions.

{chat_history}

You know the following context information.

{chunks_formatted}

Answer the following question from a customer. Use only information from the previous context information. Do not invent stuff.

Question: {input}

Answer:"""

prompt = PromptTemplate(
    input_variables=["chat_history", "chunks_formatted", "input"],
    template=template,
)

# Initialize the OpenAI model
llm = OpenAI(openai_api_key="YOUR API KEY", model="gpt-3.5-turbo-instruct", temperature=0)

# Create the LLMChain with memory
chain = LLMChain(
    llm=llm,
    prompt=prompt,
    memory=memory
)

# User query
query = "What was the 5th point about on the question how to remove spotify account?"

# Retrieve relevant chunks
docs = db.similarity_search(query)
retrieved_chunks = [doc.page_content for doc in docs]

# Format the chunks for the prompt
chunks_formatted = "nn".join(retrieved_chunks)

# Prepare the input for the chain
input_data = {
    "input": query,
    "chunks_formatted": chunks_formatted,
    "chat_history": memory.buffer
}

# Simulate a conversation
response = chain.predict(**input_data)

print(response)

조금 더 대화형 방식으로 코드를 살펴보겠습니다.

처음에는 ‘'ConversationBufferMemory‘를 사용하여 대화형 메모리를 설정합니다. 이렇게 하면 챗봇이 현재 진행 중인 대화 기록을 기억할 수 있으며 ‘input_key=”input”‘을 사용하여 들어오는 사용자의 입력을 관리합니다.

다음으로 프롬프트 템플릿을 설계해 보겠습니다. 이 템플릿은 일종의 챗봇을 위한 스크립트로, 채팅 기록, 수집한 정보 청크와 현재의 사용자 질문(입력)이 포함됩니다. 이 구조를 통해 챗봇이 정확한 컨텍스트가 무엇이고 어떤 질문에 답해야 하는지 파악할 수 있습니다.

이제 언어 모델 체인, 즉 ‘LLMChain‘을 초기화하겠습니다. 이 과정은 구성 요소를 조립하는 것이라고 생각하면 됩니다. 프롬프트 템플릿, 언어 모델, 설정했던 메모리를 가져다가 하나의 워크플로로 조합하겠습니다.

사용자 쿼리를 처리할 때가 되면 입력을 준비합니다. 그러려면 사용자의 질문(‘input‘)과 관련된 정보 청크(‘chunks_formatted‘)를 포함하는 딕셔너리를 생성해야 합니다. 이 설정을 통해 챗봇은 올바른 정보를 기반으로 한 응답을 만드는 데 필요한 모든 상세 정보를 확보할 수 있습니다.

마지막으로 응답을 생성합니다. 준비된 입력 데이터를 전달하면서 ‘chain.predict‘ 메서드를 호출합니다. 이 메서드는 우리가 만든 워크플로를 통해 입력을 처리하며, 화면에 표시되는 챗봇의 답변을 출력합니다.

이러한 방식으로 챗봇이 과거의 상호 작용을 기억하고 컨텍스트에 따라 관련성 높은 답변을 제공하여 매끄럽고 정보가 풍부한 대화를 지속하도록 만들 수 있습니다.

이 기능을 만들 때 크게 도움이 되고 제가 좋아하는 또 다른 PyCharm 기술은 커서를 메서드 위에 올려놓고 ‘CTRL’ 키를 누르면서 클릭하는 것입니다.

커서를 메서드 위에 올려놓기

결론

GPT-3는 프롬프트에 입력된 컨텍스트 정보를 바탕으로 구체적인 질문에 답할 수 있는 대화형 챗봇을 만들 때 매우 좋습니다. 그러나 모델이 이 컨텍스트에만 의존하면서 답변을 생성하도록 하면 오해의 소지가 있는 정보가 발생하기도 하므로(즉, 새로운 허위 사실을 생성할 수 있음) 문제가 생길 수 있습니다. 이러한 허위 정보의 영향력은 사용 사례에 따라 다릅니다.

정리하겠습니다. 지금까지 제공된 코드와 전략에 따라 LangChain을 사용하여 컨텍스트를 인식하여 질문에 답변하는 시스템을 만들어 보았습니다. 이 프로세스는 문서를 청크로 나누고, 임베딩을 연산하고, 유사한 청크를 찾는 검색 도구를 구현하고, GPT-3 프롬프트를 만든 다음 GPT-3 모델을 사용하여 텍스트를 생성합니다. 이러한 방식은 GPT-3를 활용하여 컨텍스트에 맞게 정확히 답하고 성능이 뛰어난 챗봇을 만들 수 있음을 보여주는 한편, 허위 정보가 생성될 수 있는 위험을 항상 유념해야 함을 강조합니다.

저자 정보

Dido Grigorov

Dido Grigorov

Dido는 업계 경력이 17년이나 되는 숙련된 딥러닝 엔지니어이자 Python 프로그래머입니다. 현재 명문대인 Stanford University에서 대학원을 다니고 있으며, Andrew Ng, Christopher Manning, Fei-Fei Li나 Chelsea Finn와 같은 저명한 전문가가 이끄는 첨단 AI 과정을 들으며 탁월한 인사이트를 얻고 멘토링을 받고 있습니다.

Dido의 인공지능에 대한 열정은 업무 및 실험에 전념을 다하는 모습에 드러나 있습니다. Dido는 수년간 머신러닝 모델을 설계, 구현 및 최적화하는 분야에서 전문성을 구축했습니다. 뛰어난 Python 실력으로 복잡한 문제을 해결하고 다양한 분야에서 혁신적인 AI 솔루션을 만드는 데 기여해 왔습니다.

게시물 원문 작성자

Evgenia Verbina

Evgenia Verbina

image description

Discover more