챗봇은 핵심적인 LLM 사용 사례 중 하나입니다. 챗봇의 핵심 기능은 장시간 대화가 가능하고 사용자가 알고 싶어하는 정보에 액세스할 수 있다는 것입니다.
기본적인 프롬프트와 LLM 외에도 메모리와 검색은 챗봇의 핵심 구성 요소입니다. 메모리는 챗봇이 과거의 상호작용을 기억할 수 있게 해주며, 검색은 챗봇에게 도메인별 최신 정보를 제공합니다.
채팅 모델 인터페이스는 원시 텍스트가 아닌 메시지를 기반으로 합니다. 채팅 시 고려해야 할 몇 가지 구성 요소가 중요합니다:
다음은 챗봇 인터페이스를 만드는 방법에 대한 간단한 미리보기입니다. 먼저 몇 가지 종속성을 설치하고 필요한 자격 증명을 설정해 보겠습니다:
!pip install langchain openai
Collecting langchain
Downloading langchain-0.0.348-py3-none-any.whl (2.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.0/2.0 MB 12.7 MB/s eta 0:00:00
Collecting openai
Downloading openai-1.3.7-py3-none-any.whl (221 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 221.4/221.4 kB 8.1 MB/s eta 0:00:00
# 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
# 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
# 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
# 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
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
일반 채팅 모델을 사용하면 모델에 하나 이상의 메시지를 전달하여 채팅 완료를 얻을 수 있습니다.
채팅 모델은 메시지로 응답합니다.
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
chat = ChatOpenAI()
chat(
[
HumanMessage(
content="Translate this sentence from English to French: I love programming."
)
]
)
# AIMessage(content="J'adore la programmation.")
메시지 목록을 전달하면 됩니다:
messages = [
SystemMessage(
content="You are a helpful assistant that translates English to French."
),
HumanMessage(content="I love programming."),
]
chat(messages)
# AIMessage(content="J'adore la programmation.")
그런 다음 채팅 모델을 과거 사용자 입력과 모델 출력을 기억하는 메모리가 내장된 '대화 체인'으로 감쌀 수 있습니다.
from langchain.chains import ConversationChain
conversation = ConversationChain(llm=chat)
conversation.run("Translate this sentence from English to French: I love programming.")
Je adore la programmation.
conversation.run("Translate it to German.")
# Ich liebe Programmieren.
위에서 언급했듯이 챗봇의 핵심 구성 요소는 메모리 시스템입니다. 가장 간단하고 일반적으로 사용되는 메모리 형태 중 하나는 ConversationBufferMemory
입니다:
여기서는 컨버세이션버퍼메모리에 대해 간단히 살펴보겠습니다. 다음과 같이 메모리에 몇 개의 채팅 메시지를 수동으로 추가할 수 있습니다:
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("hi!")
memory.chat_memory.add_ai_message("whats up?")
이제 메모리에서 로드할 수 있습니다. 모든 Memory 클래스가 노출하는 핵심 메서드는 load_memory_variables입니다. 이 메서드는 초기 체인 입력을 받아 체인 입력에 추가되는 메모리 변수 목록을 반환합니다.
이 간단한 메모리 유형은 메모리를 로드할 때 실제로 체인 입력을 고려하지 않으므로 지금은 빈 입력을 전달할 수 있습니다:
memory.load_memory_variables({})
# {'history': 'Human: hi!\nAI: whats up?'}
대화 버퍼 창 메모리
를 사용하여 가장 최근의 k 상호작용을 슬라이딩 창으로 보관할 수도 있습니다.
from langchain.memory import ConversationBufferWindowMemory
memory = ConversationBufferWindowMemory(k=1)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
memory.load_memory_variables({})
# {'history': 'Human: not much you\nAI: not much'}
ConversationSummaryBufferMemory
는 이 테마의 확장입니다.
이 메모리는 시간 경과에 따른 대화의 요약을 생성합니다.
이 메모리는 전체 메시지 기록이 많은 토큰을 소모하는 긴 대화에 가장 유용합니다.
from langchain.llms import OpenAI
from langchain.memory import ConversationSummaryMemory
llm = OpenAI(temperature=0)
memory = ConversationSummaryMemory(llm=llm)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context(
{"input": "im working on better docs for chatbots"},
{"output": "oh, that sounds like a lot of work"},
)
memory.save_context(
{"input": "yes, but it's worth the effort"},
{"output": "agreed, good docs are important!"},
)
memory.load_memory_variables({})
# {'history': '\nThe human greets the AI, to which the AI responds. The human then mentions they are working on better docs for chatbots, to which the AI responds that it sounds like a lot of work. The human agrees that it is worth the effort, and the AI agrees that good docs are important.'}
ConversationSummaryBufferMemory
는 이를 조금 더 확장합니다:
상호작용의 개수가 아닌 토큰 길이를 사용해 상호작용을 플러시할 시기를 결정합니다.
!pip install tiktoken
Collecting tiktoken
Downloading tiktoken-0.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.0/2.0 MB 14.3 MB/s eta 0:00:00
Requirement already satisfied: regex>=2022.1.18 in /usr/local/lib/python3.10/dist-packages (from tiktoken) (2023.6.3)
Requirement already satisfied: requests>=2.26.0 in /usr/local/lib/python3.10/dist-packages (from tiktoken) (2.31.0)
from langchain.memory import ConversationSummaryBufferMemory
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=10)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
ConversationChain
으로 내부의 내용을 풀 수 있습니다.
메모리인 ConversationSummaryMemory
를 지정하고 프롬프트를 지정할 수 있습니다.
from langchain.chains import LLMChain
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
MessagesPlaceholder,
SystemMessagePromptTemplate,
)
# LLM
llm = ChatOpenAI()
# Prompt
prompt = ChatPromptTemplate(
messages=[
SystemMessagePromptTemplate.from_template(
"You are a nice chatbot having a conversation with a human."
),
# The `variable_name` here is what must align with memory
MessagesPlaceholder(variable_name="chat_history"),
HumanMessagePromptTemplate.from_template("{question}"),
]
)
# Notice that we `return_messages=True` to fit into the MessagesPlaceholder
# Notice that `"chat_history"` aligns with the MessagesPlaceholder name
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
conversation = LLMChain(llm=llm, prompt=prompt, verbose=True, memory=memory)
# Notice that we just pass in the `question` variables - `chat_history` gets populated by memory
conversation({"question": "hi"})
> Entering new LLMChain chain...
Prompt after formatting:
System: You are a nice chatbot having a conversation with a human.
Human: hi
> Finished chain.
{'question': 'hi',
'chat_history': [HumanMessage(content='hi'),
AIMessage(content='Hello! How can I assist you today?')],
'text': 'Hello! How can I assist you today?'}
conversation(
{"question": "Translate this sentence from English to French: I love programming."}
)
> Entering new LLMChain chain...
Prompt after formatting:
System: You are a nice chatbot having a conversation with a human.
Human: hi
AI: Hello! How can I assist you today?
Human: Translate this sentence from English to French: I love programming.
> Finished chain.
{'question': 'Translate this sentence from English to French: I love programming.',
'chat_history': [HumanMessage(content='hi'),
AIMessage(content='Hello! How can I assist you today?'),
HumanMessage(content='Translate this sentence from English to French: I love programming.'),
AIMessage(content='Sure! The translation of "I love programming" from English to French is "J\'adore programmer."')],
'text': 'Sure! The translation of "I love programming" from English to French is "J\'adore programmer."'}
conversation({"question": "Now translate the sentence to German."})
> Entering new LLMChain chain...
Prompt after formatting:
System: You are a nice chatbot having a conversation with a human.
Human: hi
AI: Hello! How can I assist you today?
Human: Translate this sentence from English to French: I love programming.
AI: Sure! The translation of "I love programming" from English to French is "J'adore programmer."
Human: Now translate the sentence to German.
> Finished chain.
{'question': 'Now translate the sentence to German.',
'chat_history': [HumanMessage(content='hi'),
AIMessage(content='Hello! How can I assist you today?'),
HumanMessage(content='Translate this sentence from English to French: I love programming.'),
AIMessage(content='Sure! The translation of "I love programming" from English to French is "J\'adore programmer."'),
HumanMessage(content='Now translate the sentence to German.'),
AIMessage(content='Certainly! The translation of "I love programming" from English to German is "Ich liebe Programmieren."')],
'text': 'Certainly! The translation of "I love programming" from English to German is "Ich liebe Programmieren."'}
이제 문서와 채팅 또는 다른 지식 소스를 사용한다고 가정해 보겠습니다.
이것은 채팅과 문서 검색을 결합한 인기 있는 사용 사례입니다.
이를 통해 모델에 학습되지 않은 특정 정보에 대해 채팅할 수 있습니다.
!pip install chromadb
Collecting chromadb
Downloading chromadb-0.4.18-py3-none-any.whl (502 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 502.4/502.4 kB 6.9 MB/s eta 0:00:00
Requirement already satisfied: requests>=2.28 in /usr/local/lib/python3.10/dist-packages (from chromadb) (2.31.0)
Requirement already satisfied: pydantic>=1.9 in /usr/local/lib/python3.10/dist-packages (from chromadb) (1.10.13)
Collecting chroma-hnswlib==0.7.3 (from chromadb)
블로그 게시물을 로드합니다.
from langchain.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
data = loader.load()
이를 벡터로 분할하여 저장합니다.
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
all_splits = text_splitter.split_documents(data)
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())
all_splits
roblem solver.\nAgent System Overview In a LLM-powered autonomous agent system, LLM functions as the agent’s brain, complemented by several key components:', 'language': 'en'}),
Document(page_content='language. Essentially, the planning step is outsourced to an external tool, assuming the availability of domain-specific PDDL and a suitable planner which is common in certain robotic setups but not in many other domains.', metadata={'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'title': "LLM Powered Autonomous Agents | Lil'Log", 'description': 'Building agents with LLM (large language model) as its core controller is a cool concept. Several proof-of-concepts demos, such as AutoGPT, GPT-Engineer and BabyAGI, serve as inspiring examples. The potentiality of LLM extends beyond generating well-written copies, stories, essays and programs; it can be framed as a powerful general problem solver.\nAgent System Overview In a LLM-powered autonomous agent system, LLM functions as the agent’s brain, complemented by several key components:', 'language': 'en'}),
Document(page_content='Self-Reflection#\nSelf-reflection is a vital aspect that allows autonomous agents to improve iteratively by refining past action decisions and correcting previous mistakes. It plays a crucial role in real-world tasks where trial and error are inevitable.', metadata={'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'title': "LLM Powered Autonomous Agents | Lil'Log", 'description': 'Building agents with LLM (large language model) as its core controller is a cool concept. Several proof-of-concepts demos, such as AutoGPT, GPT-Engineer and BabyAGI, serve as inspiring examples. The potentiality of LLM extends beyond generating well-written copies, stories, essays and programs; it can be framed as a powerful general problem solver.\nAgent System Overview In a LLM-powered autonomous agent system, LLM functions as the agent’s brain, complemented by several key components:', 'language': 'en'}),
Document(page_content='ReAct (Yao et al. 2023) integrates reasoning and acting within LLM by extending the action space to be a combination of task-specific discrete actions and the language space. The former enables LLM to interact with the environment (e.g. use Wikipedia search API), while the latter prompting
이전과 마찬가지로 메모리를 생성하되,ConversationSummaryMemory
를 사용하겠습니다.
memory = ConversationSummaryMemory(
llm=llm, memory_key="chat_history", return_messages=True
)
from langchain.chains import ConversationalRetrievalChain
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI()
retriever = vectorstore.as_retriever()
qa = ConversationalRetrievalChain.from_llm(llm, retriever=retriever, memory=memory)
qa("How do agents use Task decomposition?")
{'question': 'How do agents use Task decomposition?',
'chat_history': [SystemMessage(content='')],
'answer': 'Agents can use task decomposition in multiple ways. One approach is by using Language Model-based Learning (LLM) with simple prompting. The agent can be prompted with instructions like "Steps for XYZ" or "What are the subgoals for achieving XYZ?" This allows the agent to break down a complex task into smaller, manageable subgoals.\n\nAnother approach is by providing task-specific instructions. For example, if the task is to write a novel, the agent can be instructed to "Write a story outline." This helps the agent decompose the task and plan its steps accordingly.\n\nAdditionally, task decomposition can also involve human inputs. In such cases, humans can provide guidance or input to help the agent break down the task into smaller subgoals.\n\nOverall, task decomposition enables agents to efficiently handle complex tasks by breaking them down into more manageable components.'}
qa("What are the various ways to implement memory to support it?")
{'question': 'What are the various ways to implement memory to support it?',
'chat_history': [SystemMessage(content='Task decomposition can be used by agents in multiple ways, such as through Language Model-based Learning (LLM) with simple prompting or by providing task-specific instructions. It can also involve human inputs to help break down tasks. Overall, task decomposition enables agents to efficiently handle complex tasks by breaking them down into more manageable components.')],
'answer': 'The different methods for implementing memory to support task decomposition are:\n\n1. Long Term Memory Management: This involves storing and retrieving information from a long-term memory system. The agent can use its memory to store past experiences, knowledge, and information relevant to task decomposition. This stored information can then be used to guide the agent in breaking down tasks into smaller subgoals.\n\n2. Reflection and Refinement: The agent can engage in self-criticism and self-reflection over past actions. By reflecting on previous task decomposition processes, the agent can identify mistakes or areas for improvement. This allows the agent to refine its approach to task decomposition and enhance the quality of the final results.\n\n3. GPT-3.5 Powered Agents: GPT-3.5 powered agents can be used for delegation of simple tasks. These agents can assist in task decomposition by providing suggestions, prompts, or examples for breaking down larger tasks into smaller subgoals. The agent can leverage the capabilities of GPT-3.5 to generate task-specific instructions or provide guidance during the decomposition process.\n\n4. File Output: The agent can also use file output as a method of memory to support task decomposition. It can create and save files that document the steps taken during the decomposition process. These files can serve as a reference for future tasks or for collaboration with human inputs.\n\nThese methods enable the agent to effectively decompose complex tasks into smaller, manageable subgoals, improving task handling efficiency.'}