OpenAI의 gpt-4o-mini API 가격이 엄청 낮습니다. 1M 입력 로큰이 US$0.15 이고, 1M 출력 토큰이 US$0.6 입니다.
OpenAI가 제공하는 tokenizer 로 확인해 보니 gpt-3.5 & gpt-4 기준으로 한 글자당 한 토큰이네요.
gpt-4o-mini도 한 글자당 한 토큰이라면 1,048,576 글자를 출력하는데 US$0.6 이라는거죠.
참고로 '해리 포터와 마법사의 돌'의 글자 수가 약 20만 자임을 감안하면, 이 가격이 얼마나 저렴한지 실감할 수 있습니다.
그래서 써보기로 하고 US$10 지르고 API Key 발급 받았습니다.
OpenAI에서 제공하는 API로 구현 할 수도 있지만 LangChain으로 해볼까 합니다.
claude에게 LangChain에 대해서 설명해 달라고 하니 아래처럼 알려주네요. ^^
LangChain은 대규모 언어 모델(LLM)을 활용한 애플리케이션 개발을 위한 프레임워크입니다. 이 프레임워크는 다양한 AI 모델과 도구들을 쉽게 통합할 수 있게 해주며, 복잡한 작업 흐름을 구현하는 데 필요한 여러 컴포넌트를 제공합니다.
LangChain의 주요 특징:
LangChain을 사용하기 위해서 필요한 패키지를 설치합니다.
pip3 install langchain langchain_openai
그리고 필요한 모듈을 import 합니다.
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.chains.conversation.memory import ConversationBufferMemory
from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
GPT-4o-mini를 사용하기 위해 API 키를 설정하고 ChatOpenAI 컴포넌트를 초기화합니다:
# OpenAI API Key
os.environ["OPENAI_API_KEY"] = (
"your-openai-api-key"
)
# initialize language model
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.0)
LLM은 본질적으로 stateless이기 때문에, 대화의 맥락을 유지하기 위해서는 대화 히스토리를 저장하고 매번 LLM에 전송해야 합니다:
# memory key
HISTORY_MEMORY_KEY = "chat_history"
# initialize memory for chat history
memory = ConversationBufferMemory(
memory_key=HISTORY_MEMORY_KEY,
return_messages=True,
)
runnable = RunnablePassthrough.assign(
chat_history=RunnableLambda(memory.load_memory_variables)
| itemgetter(HISTORY_MEMORY_KEY)
)
여기서는 ConversationBufferMemory
를 사용했지만, LangChain은 다양한 메모리 유형을 제공합니다.
LangChain에서 제공하는 메모리
ConversationBufferMemory
: 모든 대화 유지ConversationBufferWindowMemory
: 최근 K개의 대화만을 유지.ConversationTokenBufferMemory
: 토큰 길이로 대화 내용 유지.ConversationEntityMemory
: 대화에서 특정 entity에 대한 주어진 사실을 기억. 대화에서 entity에 대한 정보를 추출하고 해당 entity에 대한 지식을 축적함.ConversationKGMemory
: 지식 그래프를 사용한다고 함.ConversationSummaryMemory
: 대화가 진행되는 동안 대화를 요약하여 저장.ConversationSummaryBufferMemory
: 이전 대화는 요약해서 저장하고, 최근 대화 내용도 유지VectorStoreRetrieverMemory
: 메모리로 벡터 DB를 사용. 상위 K개 쿼리.ChatPromptTemplate
을 사용하여 LLM에 전달할 프롬프트 템플릿을 정의합니다.
# create prompt for persona chat
system_prompts = "".join(
[
"너의 이름은 민지.",
"취미: 영화보기, 요리하기, 쇼핑하기",
"너는 대화할 때 이모티콘을 자주 써.",
]
)
prompt = ChatPromptTemplate.from_messages(
[
("system", system_prompts),
MessagesPlaceholder(variable_name=HISTORY_MEMORY_KEY),
("human", "{question}"),
]
)
여기서는 챗봇에 간단한 페르소나를 부여하고, 대화 히스토리와 사용자 입력을 포함하도록 템플릿을 구성했습니다.
LCEL(LangChain Expression Language)을 사용해서 memory, prompt, llm을 하나의 체인으로 묶어줍니다.
# create chain
chain = runnable | prompt | llm | StrOutputParser()
이렇게 구성된 체인은 다음과 같은 흐름으로 동작합니다.
마지막으로 CLI로 사용자 입력을 받아서 chain을 통해 LLM에게 질문하고. 응답을 출력, 저장합니다.
while True:
user_input = input("You: ")
response = chain.invoke({"question": user_input})
memory.save_context({"input": user_input}, {"output": response})
print("Assistant:", response)
이렇게 LangChain을 사용하면 페르소나를 가진 챗봇을 비교적 적은 코드로 구현할 수 있습니다. 이 예제에서는 간단하게 페르소나를 정의하고 대화 기록 유지 기능만을 구현했지만, LangChain의 다양한 기능을 활용하면 더욱 복잡하고 흥미로운 챗봇을 만들 수 있을 것입니다.
전체 코드는 GitHub 레포지토리에서 확인할 수 있습니다. 링크
우디님 응원합니다!!