LangChain์ ๋๊ท๋ชจ ์ธ์ด ๋ชจ๋ธ(LLM, Large Language Model) ์ ํ์ฉํ
AI ์ ํ๋ฆฌ์ผ์ด์
์ ๋น ๋ฅด๊ณ ํจ์จ์ ์ผ๋ก ๊ตฌ์ถํ ์ ์๋๋ก ๋์์ฃผ๋ ์คํ์์ค ํ๋ ์์ํฌ์.
LLM(GPT, Claude, Gemini ๋ฑ)์ ์ด๋ฏธ ๋ค์ํ ์ง์์ ๊ธฐ๋ฐํด ํ
์คํธ๋ฅผ ์์ฑํ ์ ์์ง๋ง,
ํน์ ๋๋ฉ์ธ ๋ฐ์ดํฐ๋ ์ฌ๋ด ๋ฌธ์์ฒ๋ผ ํ๋ จ์ ํฌํจ๋์ง ์์ ์ ๋ณด๋ฅผ ํ์ฉํ๊ธฐ๋ ์ด๋ ต๋ค๋ ํ๊ณ๊ฐ ์์.
LangChain์ ์ด๋ฐ LLM์ ํ๊ณ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด,
์ธ๋ถ ๋ฐ์ดํฐ ์์ค ์ฐ๊ฒฐ, ํ๋กฌํํธ ์ฒด์ธ ๊ตฌ์ฑ, RAG ๊ฒ์ ๊ตฌ์กฐ ํตํฉ ๋ฑ์ ์ง์
์ฆ, ๋จ์ํ ๋ชจ๋ธ์ ํธ์ถํ๋ ์์ค์ ๋์ด,
โLLM์ ํ์ฉํ ์ค์ ์๋น์ค ๊ฐ๋ฐ์ ์ํ ์์งโ ์ญํ ์ ์ํ
LLM์ ์ผ๋ฐ์ ์ธ ์ง๋ฌธ์๋ ์ ๋ตํ์ง๋ง,
์กฐ์ง ๋ด๋ถ ๋ฐ์ดํฐ๋ ์ต์ ์ ๋ณด์ ๊ด๋ จ๋ ์ง๋ฌธ์๋ ์ทจ์ฝํจ.
์๋ฅผ ๋ค์ด:
โ์ฐ๋ฆฌ ํ์ฌ์์ ํ๋งค ์ค์ธ X1000 ๋ชจ๋ธ์ ๋จ๊ฐ๊ฐ ์ผ๋ง์ธ๊ฐ์?โ
โ GPT๋ ์ด ์ ๋ณด๋ฅผ ๋ชจ๋ฆ.
ํ์ง๋ง LangChain์ ์ฌ์ฉํ๋ฉด ์ฌ๋ด DB๋ ๋ฌธ์์์ ์ด ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํด
์ ํํ ๋ต๋ณ์ ์์ฑํ ์ ์์
์ฆ, LangChain์
| ํญ๋ชฉ | ์ค๋ช |
|---|---|
| LLM ์ฌํ๋ จ ๋ถํ์ | ๊ธฐ์กด ๋ชจ๋ธ์ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฉฐ ์ธ๋ถ ๋ฐ์ดํฐ ์ฐ๊ฒฐ๋ก ํ์ฅ ๊ฐ๋ฅ |
| ๋น ๋ฅธ ํ๋กํ ํ์ดํ | RAG, QA ์ฑ๋ด, ์์ฝ๊ธฐ ๋ฑ์ ๋น ๋ฅด๊ฒ ๊ตฌํ ๊ฐ๋ฅ |
| ์ ์ฐํ ๊ตฌ์กฐ | ์ฒด์ธยท์์ด์ ํธยท๋ฉ๋ชจ๋ฆฌ ๋ฑ ๋ชจ๋ ์กฐํฉ์ผ๋ก ๋ค์ํ ์ํฌํ๋ก ์ค๊ณ |
| ๊ฐ๋ ฅํ ์ปค๋ฎค๋ํฐ | ํ๋ฐํ ์คํ์์ค ์ํ๊ณ์ ๋ฌธ์, ์์ ์ฝ๋ ํ๋ถ |
| ๊ตฌ์ฑ ์์ | ์ค๋ช |
|---|---|
| LLM ์ธํฐํ์ด์ค | GPT, Claude, PaLM ๋ฑ ๋ค์ํ ์ธ์ด ๋ชจ๋ธ๊ณผ ์ฐ๊ฒฐํ๊ธฐ ์ํ ํ์คํ๋ API ์ ๊ณต. ๋ชจ๋ธ ๊ต์ฒด ์ ์ฝ๋ ์์ ์ต์ํ ๊ฐ๋ฅ |
| ํ๋กฌํํธ ํ ํ๋ฆฟ (PromptTemplate) | ์ผ๊ด๋ ์ง์ ํ์์ ์ ์ํ์ฌ ๋ชจ๋ธ ์ ๋ ฅ์ ๊ตฌ์กฐํํ๊ณ , ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํ๋กฌํํธ๋ฅผ ์์ฑํจ |
| ์ฒด์ธ (Chain) | ์ฌ๋ฌ ์์ ๋จ๊ณ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฐ๊ฒฐํด ํ๋์ ์๋ํ๋ ์๋ต ํ์ดํ๋ผ์ธ(workflow)์ ๊ตฌ์ฑํจ |
| ์์ด์ ํธ (Agent) | ๋ชจ๋ธ์ด ์ค์ค๋ก ํ์ํ ๋๊ตฌ๋ ๋จ๊ณ๋ฅผ ํ๋จํ์ฌ ์คํ ์์๋ฅผ ๊ฒฐ์ ํ๋๋ก ํจ |
| ๊ฒ์ ๋ชจ๋ (Retriever) | ์ธ๋ถ ๋ฐ์ดํฐ(๋ฌธ์, DB, ์น ๋ฑ)๋ฅผ ์๋ฒ ๋ฉ ํ, ์๋ฏธ ๊ธฐ๋ฐ ๊ฒ์(Semantic Search)์ผ๋ก ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํจ |
| ๋ฉ๋ชจ๋ฆฌ (Memory) | ๋ํ ์ด๋ ฅ์ด๋ ๊ณผ๊ฑฐ ์ ๋ณด๋ฅผ ์ ์ฅยทํ์ฉํ์ฌ ๋ฌธ๋งฅ์ ์ ์งํ๊ณ ์๋ต์ ์ผ๊ด์ฑ์ ํ๋ณดํจ |
| ์ฝ๋ฐฑ (Callback) | ์ฒด์ธ ์คํ ์ค ๋ฐ์ํ๋ ์ด๋ฒคํธ, ์ค๋ฅ, ๋ก๊ทธ๋ฅผ ๋ชจ๋ํฐ๋งํ๊ณ ๋๋ฒ๊น ํ ์ ์๋๋ก ์ง์ํจ |
GPT, Claude, PaLM ๋ฑ ๋ค์ํ ๋ชจ๋ธ๊ณผ ์ฐ๊ฒฐํ ์ ์๋ ํ์ค API๋ฅผ ์ ๊ณต
โ ๋ชจ๋ธ ๊ต์ฒด ์ ์ฝ๋ ์์ ์ต์ํ
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o", temperature=0)
LangChain์ ์ค์ฌ์ ์ฒด์ธ(Chain)
์ฒด์ธ์ ์ฌ์ฉ์์ ์
๋ ฅ๋ถํฐ ๋ชจ๋ธ์ ์ถ๋ ฅ๊น์ง, ํ๋์ ํ์ดํ๋ผ์ธ(workflow)์ ์๋ฏธ
๊ทธ๋ฆฌ๊ณ ์ฒด์ธ์ ์ด๋ฃจ๋ ๋งํฌ(Link)
๋งํฌ๋ ์ฒด์ธ์ ๊ตฌ์ฑํ๋ ํ๋์ ๋จ์ ์์
(step) ์ผ๋ก,
์ฌ๋ฌ ๋งํฌ๊ฐ ์์ฐจ์ ์ผ๋ก ์ฐ๊ฒฐ๋์ด ์ ์ฒด ํ์ดํ๋ผ์ธ(์ฒด์ธ)์ ํ์ฑ
์ฆ,
์ฌ๋ฌ ๊ฐ์ ์์ (๋งํฌ)์ ์์ฐจ์ ์ผ๋ก ์ฐ๊ฒฐํ ์คํ ํ๋ฆ(์ฒด์ธ)
์๋ฅผ ๋ค์ด, ๋ค์๊ณผ ๊ฐ์ ๋จ๊ณ๋ฅผ ์ฒด์ธ์ผ๋ก ๋ฌถ์ ์ ์์
LangChain์์๋ ์ด ์ผ๋ จ์ ๋จ๊ณ๋ฅผ chain() ํจ์๋ก ์ ์ํ ์ ์์
chain([
retrieve_data_from_database(),
send_data_to_language_model(),
format_output(),
translate_output_in_target_language()
])
์ด์ฒ๋ผ ์ฌ๋ฌ ๋งํฌ(Link) ๋ฅผ ์ฐ๊ฒฐํ์ฌ ํ๋์ ์ฒด์ธ์ผ๋ก ๊ตฌ์ฑํ ์ ์์
๊ฐ ๋งํฌ๋ ์์ ๋จ์์ ์์ ์ด๋ฉฐ, ์์์ ๊ตฌ์ฑ์ ์์ ๋กญ๊ฒ ๋ฐ๊ฟ ์ ์์
์ง๋ฌธ ๊ตฌ์กฐ๋ฅผ ํ ํ๋ฆฟ์ผ๋ก ์ ์ํ์ฌ, ์ผ๊ด๋๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ง์ ํํ๋ฅผ ์์ฑ
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_template(
"๋๋ HR ๋์ฐ๋ฏธ์ผ. ์ฌ์ฉ์ ์ง๋ฌธ: {question}"
)
prompt = template.format(question="์ฐ์ฐจ ๊ท์ ์๋ ค์ค")
์์ด์ ํธ๋ ๋จ์ํ ๋ต๋ณ์ ์์ฑํ๋ ๊ฒ์ ๋์ด,
์ค์ค๋ก ์ด๋ค ๋๊ตฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋์ง ํ๋จํ๊ณ ๊ทธ ๊ณผ์ ์ ์ํํ๋ ๊ฒ
์ฆ, ์ ํด์ง ์์๋๋ก ์คํํ๋ ์ฒด์ธ(Chain) ๊ณผ ๋ฌ๋ฆฌ,
์์ด์ ํธ๋ ์ํฉ์ ๋ฐ๋ผ ์ด๋ค ๋จ๊ณ์ ๋๊ตฌ๋ฅผ ์ธ์ง ์ค์ค๋ก ํ๋จ
# pip install langchain langchain-openai
from langchain.agents import initialize_agent, load_tools
from langchain_openai import ChatOpenAI
# 1) ์ฌ์ฉํ LLM ์ ์
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 2) ์ฌ์ฉํ ๋๊ตฌ(tool) ๋ถ๋ฌ์ค๊ธฐ
# LangChain์ 'tools'๋ผ๋ ํ์ค ๋ชจ๋์ ๋ค์ํ ๊ธฐ๋ฅ์ด ๋ฑ๋ก๋์ด ์์
tools = load_tools(["serpapi", "llm-math"], llm=llm)
# - serpapi: ์น ๊ฒ์์ฉ API
# - llm-math: ์ํ ๊ณ์ฐ๊ธฐ ๊ธฐ๋ฅ
# 3) ์์ด์ ํธ ์ด๊ธฐํ
agent = initialize_agent(
tools=tools,
llm=llm,
agent_type="zero-shot-react-description", # ReAct ํจํด ๊ธฐ๋ฐ
verbose=True
)
# 4) ์คํ ์์
query = "๋ํ๋ฏผ๊ตญ ์๋์ ์๋์ 5๋ฅผ ๋ํ๋ฉด ์ผ๋ง์ผ?"
agent.run(query)
# LLM์ด ์ง์ โ๊ฒ์ โ ๊ณ์ฐ โ ๋ต๋ณ ์์ฑโ ๊ณผ์ ์ ์ฒด๋ฅผ ์ค์ค๋ก ํ๋จํ๊ณ ์คํ
RAG(Retrieval-Augmented Generation) ๊ตฌํ์ ํต์ฌ ๊ตฌ์ฑ์์
๋ฌธ์, PDF, DB, ์น ๋ฑ ๋ค์ํ ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ ๋ฒกํฐ ์๋ฒ ๋ฉ์ผ๋ก ์ ์ฅํ๊ณ ,
์ฌ์ฉ์ ์ง์์ ์๋ฏธ์ ์ผ๋ก ์ ์ฌํ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์
# โ
0. ํจํค์ง ์ค์น
# pip install langchain langchain-openai faiss-cpu
# โ
1. ์์ ๋ฌธ์ ์ ์
docs = [
"์ฐ์ฐจ๋ ์
์ฌ ์ ๊ธฐ์ค์ผ๋ก ๋ฐ์ํ๋ฉฐ, ์ต๋ 25์ผ๊น์ง ๋์ ๊ฐ๋ฅํจ.",
"๊ฒฝ์กฐ์ฌ ํด๊ฐ ๊ท์ : ๊ฒฐํผ ์ 5์ผ, ๋ถ๋ชจ์ 7์ผ, ์๋
์ถ์ฐ 3์ผ ๋ถ์ฌ๋จ.",
"์ถ์ฅ๋น๋ ์ฌ์ ์น์ธ ํ ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉฐ, ์์์ฆ ์ ์ถ์ด ํ์์."
]
# โ
2. ๋ฌธ์๋ฅผ ๋ฒกํฐ๋ก ๋ณํ (Embedding)
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
embedding = OpenAIEmbeddings() # OpenAI์ ์๋ฒ ๋ฉ ๋ชจ๋ธ ์ฌ์ฉ
vector_db = FAISS.from_texts(docs, embedding) # ๋ฌธ์ ์๋ฒ ๋ฉ ํ ๋ฒกํฐDB(Faiss)์ ์ ์ฅ
# โ
3. ๊ฒ์๊ธฐ (Retriever) ๊ตฌ์ฑ
retriever = vector_db.as_retriever(search_kwargs={"k": 2}) # ์ ์ฌ ๋ฌธ์ 2๊ฐ ๋ฐํ ์ค์
# โ
4. ์์ ์ง์ ์ํ
query = "๊ฒฐํผํ๋ฉด ๋ฉฐ์น ํด๊ฐ์?"
similar_docs = retriever.get_relevant_documents(query)
# โ
5. ๊ฒฐ๊ณผ ์ถ๋ ฅ
print("๐งพ [์ง๋ฌธ]", query)
for i, doc in enumerate(similar_docs, 1):
print(f"{i}. {doc.page_content}")
๋ํํ ์ ํ๋ฆฌ์ผ์ด์
์์๋ ์ด์ ๋ํ ๋งฅ๋ฝ์ด ํ์ํจ
LangChain์ ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋์ ์ด๋ฌํ ๋ํ ์ด๋ ฅ ์ ์ง ๋ฐ ์ฐธ์กฐ๋ฅผ ์ง์ํจ
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory()
LangChain ๋ด๋ถ ์คํ ๊ณผ์ (์: ์ฒด์ธ ํธ์ถ, ์๋ฌ, ์๋ต ์๊ฐ ๋ฑ)์
๋ก๊น
ํ๊ณ ๋ชจ๋ํฐ๋งํ๋ ์ด๋ฒคํธ ํ
์์คํ
.
from langchain.callbacks import StdOutCallbackHandler
handler = StdOutCallbackHandler()
# โ
ํจํค์ง ์ค์น
# pip install langchain langchain-openai faiss-cpu tiktoken
# 1๏ธโฃ LLM ์ธํฐํ์ด์ค
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 2๏ธโฃ ํ๋กฌํํธ ํ
ํ๋ฆฟ
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_template(
"๋๋ HR ๋์ฐ๋ฏธ์ผ. ์๋ ์ ๋ณด๋ฅผ ์ฐธ๊ณ ํด์ ์ฌ์ฉ์์ ์ง๋ฌธ์ ๋ต๋ณํด์ค.\n\n"
"์ง๋ฌธ: {question}\n"
"์ฐธ๊ณ ์ ๋ณด: {context}\n\n"
"๋ต๋ณ:"
)
# 3๏ธโฃ ๋ฌธ์ โ ๋ฒกํฐDB ๊ตฌ์ฑ (Retrieval)
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
docs = [
"์ฐ์ฐจ๋ ์
์ฌ ์ ๊ธฐ์ค์ผ๋ก ๋ฐ์ํ๋ฉฐ ์ต๋ 25์ผ๊น์ง ๋์ ๊ฐ๋ฅํจ.",
"๊ฒฝ์กฐ์ฌ ํด๊ฐ ๊ท์ : ๊ฒฐํผ ์ 5์ผ, ๋ถ๋ชจ์ 7์ผ, ์๋
์ถ์ฐ 3์ผ ๋ถ์ฌ๋จ.",
"์ถ์ฅ๋น๋ ์ฌ์ ์น์ธ ํ ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉฐ, ์์์ฆ ์ ์ถ์ด ํ์์."
]
embedding = OpenAIEmbeddings()
vdb = FAISS.from_texts(docs, embedding)
retriever = vdb.as_retriever(search_kwargs={"k": 2})
# 4๏ธโฃ ๋ฉ๋ชจ๋ฆฌ (์ด์ ๋ํ ์ ์ง)
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 5๏ธโฃ ์ฝ๋ฐฑ (์คํ ๋ก๊ทธ ์ถ๋ ฅ)
from langchain.callbacks import StdOutCallbackHandler
handler = StdOutCallbackHandler()
# 6๏ธโฃ ์ฒด์ธ ๊ตฌ์ฑ (๊ฒ์ + ํ๋กฌํํธ + LLM)
from langchain.chains import RetrievalQA
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
chain_type="stuff",
return_source_documents=True,
verbose=True
)
# 7๏ธโฃ ์์ด์ ํธ ๊ตฌ์ฑ (๊ฒ์๊ธฐ + ๊ณ์ฐ๊ธฐ ๋ฑ ๋๊ตฌ ์กฐํฉ)
from langchain.agents import initialize_agent, load_tools
tools = load_tools(["llm-math"], llm=llm)
agent = initialize_agent(
tools=tools + [{"name": "retriever", "description": "ํ์ฌ ๋ฌธ์ ๊ฒ์", "func": qa_chain.run}],
llm=llm,
agent_type="zero-shot-react-description",
verbose=True,
memory=memory,
handle_parsing_errors=True
)
# 8๏ธโฃ ์์ ์คํ
query1 = "๊ฒฐํผํ๋ฉด ํด๊ฐ ๋ฉฐ์น ๋ฐ์ ์ ์์ด?"
response1 = agent.run(query1, callbacks=[handler])
query2 = "์ด์ ๋ํ์์ ๋งํ ๊ท์ ๊ธฐ์ค์ผ๋ก ์ถ์ฅ๋น ๊ท์ ๋ ์๋ ค์ค."
response2 = agent.run(query2, callbacks=[handler])
print("\n๐ฌ [1์ฐจ ๋ต๋ณ]", response1)
print("๐ฌ [2์ฐจ ๋ต๋ณ]", response2)