๐ค ์ด ๊ธ์ Claude Desktop๊ณผ MCP๋ฅผ ํ์ฉํ์ฌ AI๊ฐ ์๋์ผ๋ก ์์ฑํ LangChain ๊ฐ์ด๋์ ๋๋ค!
LangChain์ LLM(Large Language Model)์ ํ์ฉํ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ์ํ ๊ฐ๋ ฅํ ํ๋ ์์ํฌ์ ๋๋ค. ๋ณต์กํ AI ์ํฌํ๋ก์ฐ๋ฅผ ๊ฐ๋จํ๊ณ ๋ชจ๋ํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌ์ถํ ์ ์๊ฒ ํด์ค๋๋ค.
LangChain์ ์ฃผ์ ๊ตฌ์ฑ ์์๋ฅผ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค:
# LangChain ์ค์น
pip install langchain langchain-openai
# ์ถ๊ฐ ์์กด์ฑ (์ ํ์ฌํญ)
pip install langchain-community chromadb faiss-cpu
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
# LLM ์ด๊ธฐํ
llm = ChatOpenAI(temperature=0.7)
# ํ๋กฌํํธ ํ
ํ๋ฆฟ ์์ฑ
prompt = ChatPromptTemplate.from_template(
"๋ค์ ์ฃผ์ ์ ๋ํด ๊ฐ๋จํ ์ค๋ช
ํด์ฃผ์ธ์: {topic}"
)
# ์ฒด์ธ ๊ตฌ์ฑ
chain = prompt | llm | StrOutputParser()
# ์คํ
result = chain.invoke({"topic": "์์์ปดํจํ
"})
print(result)
from langchain.prompts import PromptTemplate
# ๊ธฐ๋ณธ ํ๋กฌํํธ ํ
ํ๋ฆฟ
template = """
๋น์ ์ {role}์
๋๋ค.
๋ค์ ์ง๋ฌธ์ {style} ์คํ์ผ๋ก ๋ต๋ณํด์ฃผ์ธ์:
์ง๋ฌธ: {question}
๋ต๋ณ:"""
prompt = PromptTemplate(
input_variables=["role", "style", "question"],
template=template
)
# ์ฌ์ฉ ์์
formatted_prompt = prompt.format(
role="๋ฐ์ดํฐ ์ฌ์ด์ธํฐ์คํธ",
style="์ ๋ฌธ์ ์ด๊ณ ์น๊ทผํ",
question="๋จธ์ ๋ฌ๋๊ณผ ๋ฅ๋ฌ๋์ ์ฐจ์ด์ ์?"
)
from langchain.memory import ConversationBufferWindowMemory
from langchain.chains import ConversationChain
# ๋ํ ๊ธฐ๋ก ๋ฉ๋ชจ๋ฆฌ (์ต๊ทผ 5๊ฐ ๋ฉ์์ง๋ง ์ ์ง)
memory = ConversationBufferWindowMemory(k=5)
# ๋ํ ์ฒด์ธ ์์ฑ
conversation = ConversationChain(
llm=llm,
memory=memory,
verbose=True
)
# ๋ํ ์งํ
response1 = conversation.predict(input="์๋
ํ์ธ์!")
response2 = conversation.predict(input="์ ์ด๋ฆ์ ๊น๋ฏผ๋ฒ์
๋๋ค.")
response3 = conversation.predict(input="์ ์ด๋ฆ์ด ๋ญ๋ผ๊ณ ํ์ฃ ?")
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain.tools import DuckDuckGoSearchRun
from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
# ๋๊ตฌ ์ ์
search = DuckDuckGoSearchRun()
wikipedia = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
tools = [search, wikipedia]
# ์์ด์ ํธ ์์ฑ
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# ์์ด์ ํธ ์คํ
result = agent_executor.invoke({
"input": "2024๋
๋
ธ๋ฒจ๋ฌผ๋ฆฌํ์ ์์์์ ๋ํด ์๋ ค์ฃผ์ธ์"
})
RAG๋ LangChain์ ๊ฐ์ฅ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ ์ค ํ๋์ ๋๋ค:
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
# 1. ๋ฌธ์ ๋ก๋ ๋ฐ ๋ถํ
loader = TextLoader("document.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
# 2. ์๋ฒ ๋ฉ ๋ฐ ๋ฒกํฐ ์คํ ์ด ์์ฑ
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(texts, embeddings)
# 3. RAG ์ฒด์ธ ๊ตฌ์ฑ
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever()
)
# 4. ์ง์์๋ต ์คํ
query = "๋ฌธ์์์ ์ฃผ์ ํต์ฌ ๋ด์ฉ์ด ๋ฌด์์ธ๊ฐ์?"
result = qa_chain.invoke({"query": query})
class CustomerServiceBot:
def __init__(self):
self.llm = ChatOpenAI(temperature=0.3)
self.memory = ConversationBufferWindowMemory(k=10)
self.prompt = ChatPromptTemplate.from_template("""
๋น์ ์ ์น์ ํ ๊ณ ๊ฐ ์๋น์ค ๋ด๋น์์
๋๋ค.
๊ณ ๊ฐ์ ๋ฌธ์์ ์ ํํ๊ณ ๋์์ด ๋๋ ๋ต๋ณ์ ์ ๊ณตํ์ธ์.
๋ํ ๊ธฐ๋ก: {chat_history}
๊ณ ๊ฐ ๋ฌธ์: {human_input}
๋ต๋ณ:""")
self.chain = self.prompt | self.llm | StrOutputParser()
def respond(self, user_input):
chat_history = self.memory.chat_memory.messages
response = self.chain.invoke({
"chat_history": chat_history,
"human_input": user_input
})
self.memory.chat_memory.add_user_message(user_input)
self.memory.chat_memory.add_ai_message(response)
return response
from langchain.chains.summarize import load_summarize_chain
def create_document_summarizer():
# Map-Reduce ๋ฐฉ์์ ์์ฝ ์ฒด์ธ
summarize_chain = load_summarize_chain(
llm=llm,
chain_type="map_reduce",
verbose=True
)
return summarize_chain
# ์ฌ์ฉ ์์
summarizer = create_document_summarizer()
summary = summarizer.invoke({"input_documents": documents})
class CodeReviewAssistant:
def __init__(self):
self.llm = ChatOpenAI(temperature=0.2)
self.review_prompt = ChatPromptTemplate.from_template("""
๋ค์ ์ฝ๋๋ฅผ ๋ฆฌ๋ทฐํ๊ณ ๊ฐ์ ์ฌํญ์ ์ ์ํด์ฃผ์ธ์:
์ธ์ด: {language}
์ฝ๋:
```{language}
{code}
```
๋ฆฌ๋ทฐ ๊ฒฐ๊ณผ:
1. ์ฝ๋ ํ์ง ํ๊ฐ
2. ๊ฐ์ ์ฌํญ
3. ๋ณด์ ์ด์
4. ์ฑ๋ฅ ์ต์ ํ ์ ์
""")
self.chain = self.review_prompt | self.llm | StrOutputParser()
def review_code(self, code, language="python"):
return self.chain.invoke({
"code": code,
"language": language
})
from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
def create_analysis_chain():
# ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
preprocess = RunnableLambda(lambda x: x.upper().strip())
# ๋ถ์ ํ๋กฌํํธ
analysis_prompt = ChatPromptTemplate.from_template(
"๋ค์ ํ
์คํธ๋ฅผ ๋ถ์ํ๊ณ ๊ฐ์ ๊ณผ ์ฃผ์ ํค์๋๋ฅผ ์ถ์ถํ์ธ์: {text}"
)
# ํ์ฒ๋ฆฌ
postprocess = RunnableLambda(lambda x: {
"analysis": x,
"timestamp": "2025-07-02"
})
# ์ฒด์ธ ์กฐํฉ
chain = (
{"text": preprocess}
| analysis_prompt
| llm
| StrOutputParser()
| postprocess
)
return chain
from langchain.schema.runnable import RunnableParallel
# ๋ณ๋ ฌ๋ก ์ฌ๋ฌ ์์
์ํ
parallel_chain = RunnableParallel({
"summary": summarize_chain,
"sentiment": sentiment_chain,
"keywords": keyword_chain
})
result = parallel_chain.invoke({"input": text})
from langchain.cache import InMemoryCache
from langchain.globals import set_llm_cache
# ๋ฉ๋ชจ๋ฆฌ ์บ์ ์ค์
set_llm_cache(InMemoryCache())
# ๋์ผํ ์
๋ ฅ์ ๋ํด ์บ์๋ ๊ฒฐ๊ณผ ๋ฐํ
# ์คํธ๋ฆฌ๋ฐ์ผ๋ก ์ค์๊ฐ ์๋ต ๋ฐ๊ธฐ
for chunk in chain.stream({"topic": "์ธ๊ณต์ง๋ฅ"}):
print(chunk, end="", flush=True)
import asyncio
async def async_chain_execution():
result = await chain.ainvoke({"input": "๋น๋๊ธฐ ์ฒ๋ฆฌ ํ
์คํธ"})
return result
# ์ฌ์ฉ
result = asyncio.run(async_chain_execution())
import langchain
from langchain.globals import set_debug
# ๋๋ฒ๊ทธ ๋ชจ๋ ํ์ฑํ
set_debug(True)
# ์์ธํ ๋ก๊น
langchain.debug = True
# ์ฒด์ธ ์คํ ๊ณผ์ ์ถ์
chain = prompt | llm | StrOutputParser()
result = chain.invoke({"topic": "LangChain"})
ํน์ง | LangChain | LlamaIndex | Haystack |
---|---|---|---|
์ฉ๋ | ๋ฒ์ฉ LLM ์ฑ | ๋ฐ์ดํฐ ๊ฒ์ ์ค์ฌ | ๊ธฐ์ ์ฉ NLP |
ํ์ต๊ณก์ | ๋ณดํต | ์ฌ์ | ์ด๋ ค์ |
ํ์ฅ์ฑ | ๋์ | ๋ณดํต | ๋์ |
์ปค๋ฎค๋ํฐ | ๋งค์ฐ ํ๋ฐ | ํ๋ฐ | ๋ณดํต |
# ์ค์ ํ๋ก์ ํธ ์์ - AI ์์ด์ ํธ ๋ํ ์์คํ
class BuyerAgent:
def __init__(self):
self.llm = ChatOpenAI(temperature=0.7)
self.memory = ConversationSummaryBufferMemory(llm=self.llm)
self.prompt = ChatPromptTemplate.from_template("""
๋น์ ์ {company_name}์ ๊ตฌ๋งค ๋ด๋น์์
๋๋ค.
ํ์ฌ ์ ๋ณด: {company_summary}
ํ๋งค์์ ์ง๋ฌธ์ ํ์ค์ ์ด๊ณ ๊ตฌ์ฒด์ ์ผ๋ก ๋ต๋ณํ์ธ์.
๋ํ ๊ธฐ๋ก: {chat_history}
ํ๋งค์ ์ง๋ฌธ: {seller_message}
๋ต๋ณ:""")
self.chain = self.prompt | self.llm | StrOutputParser()
async def respond(self, company_name, company_summary, seller_message):
chat_history = self.memory.chat_memory.messages
response = await self.chain.ainvoke({
"company_name": company_name,
"company_summary": company_summary,
"chat_history": chat_history,
"seller_message": seller_message
})
# ๋ฉ๋ชจ๋ฆฌ ์
๋ฐ์ดํธ
self.memory.chat_memory.add_user_message(seller_message)
self.memory.chat_memory.add_ai_message(response)
return response
# โ ์ข์ง ์์ ์
bad_prompt = "์ฝ๋๋ฅผ ๋ฆฌ๋ทฐํด์ค"
# โ
์ข์ ์
good_prompt = """
๋น์ ์ ์๋์ด ๊ฐ๋ฐ์์
๋๋ค. ๋ค์ ๊ธฐ์ค์ผ๋ก ์ฝ๋๋ฅผ ๋ฆฌ๋ทฐํด์ฃผ์ธ์:
1. ์ฝ๋ ํ์ง (๊ฐ๋
์ฑ, ์ ์ง๋ณด์์ฑ)
2. ์ฑ๋ฅ ์ต์ ํ ๊ฐ๋ฅ์ฑ
3. ๋ณด์ ์ทจ์ฝ์
4. ์ฝ๋ฉ ์ปจ๋ฒค์
์ค์
์ฝ๋:
{code}
๊ฐ ํญ๋ชฉ๋ณ๋ก ๊ตฌ์ฒด์ ์ธ ํผ๋๋ฐฑ์ ์ ๊ณตํด์ฃผ์ธ์.
"""
from langchain.schema import OutputParserException
try:
result = chain.invoke(input_data)
except OutputParserException as e:
print(f"ํ์ฑ ์ค๋ฅ: {e}")
# ๋์ฒด ๋ก์ง ์คํ
except Exception as e:
print(f"์์์น ๋ชปํ ์ค๋ฅ: {e}")
# ๋ก๊น
๋ฐ ๋ณต๊ตฌ ์ฒ๋ฆฌ
from langchain.callbacks import get_openai_callback
with get_openai_callback() as cb:
result = chain.invoke(input_data)
print(f"ํ ํฐ ์ฌ์ฉ๋: {cb.total_tokens}")
print(f"๋น์ฉ: ${cb.total_cost:.4f}")
LangChain์ AI ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ํจ๋ฌ๋ค์์ ๋ฐ๊พธ๊ณ ์์ต๋๋ค. ๋ณต์กํ AI ์ํฌํ๋ก์ฐ๋ฅผ ๋ชจ๋ํ๋ ๊ตฌ์ฑ ์์๋ก ๋๋์ด ๊ฐ๋ฐํ ์ ์๊ฒ ํด์ฃผ๋ฉฐ, RAG, ์์ด์ ํธ, ๋ฉ๋ชจ๋ฆฌ ์์คํ ๋ฑ ๋ค์ํ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
์ด ๊ธ์ด ๋์์ด ๋์ จ๋ค๋ฉด ๐ ์ข์์์ ๋๊ธ๋ก ์ํตํด์!
๋ณธ ๊ธ์ Claude Desktop + MCP ์๋ํ ์์คํ ์ผ๋ก ์์ฑ๋์์ต๋๋ค ๐ค