์ฐธ๊ณ ์๋ฃ
Langchain ์ํค๋ ์ค
Python Langchain Documentation
LangChain์ ์ ๊ด๋ จ ๋ธ๋ก๊ทธ
LangChain๋ชจ๋ ๊ด๋ จ ๋ธ๋ก๊ทธ
LangChain ๊ด๋ จ IDG Article
SDK์ API์ ์ฐจ์ด์
๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ(ETL๊ณผ ELT)
์ํ ์ ์ฅํ ๊ณผ ๋น์ ์ฅํ
LangChain์ด๋?
- ๋๊ท๋ชจ ์ธ์ด ๋ชจ๋ธ(LLMs)์ ์ด์ฉํ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ์ํ ์ข ํฉ์ ์ธ ํ๋ ์์ํฌ
- ์ด ํ๋ ์์ํฌ๋ LLM ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ฒด ์๋ช
์ฃผ๊ธฐ๋ฅผ ๊ฐ์ํํ๊ณ ์ต์ ํํ๋ ๊ฒ์ ๋ชฉํ๋ก ํจ.
- ๊ฐ๋ฐ์์๋ถํฐ ํ๋ก๋์ ๋จ๊ณ, ๊ทธ๋ฆฌ๊ณ ์ต์ข ๋ฐฐํฌ๊น์ง LLM ๊ธฐ๋ฐ ์๋น์ค ๊ตฌ์ถ์ ๋ชจ๋ ๋จ๊ณ๋ฅผ ์ง์
- ๋๊ท๋ชจ ์ธ์ด ๋ชจ๋ธ๊ณผ ์ ํ๋ฆฌ์ผ์ด์
์ ํตํฉ์ ๊ฐ์ํํ๋ SDK์ด๋ค.
- SDK(Software Development Kit) : ์ํํธ์จ์ด ๊ฐ๋ฐ ๋๊ตฌ ๋ชจ์
- API, IDE, ๋ฌธ์, ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ์ฝ๋ ์ํ ๋ฐ ๊ธฐํ ์ ํธ๋ฆฌํฐ ํฌํจ
- ํ๋ก๊ทธ๋จ ๋ฐ ์์ฉ ํ๋ก๊ทธ๋จ ๊ฐ๋ฐ์ ๋ณต์ก์ฑ์ ์ค์ด๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ ์งํฉ
- API(Application Programming Interface)
- ๋ชจ๋ํํ์ฌ ๋ง๋ค์ด์ง, ์ด๋ค ๊ธฐ๋ฅ์ ์ ์ด/์ ๊ณตํ๋ ์ธํฐํ์ด์ค
- API๋ SDK์ ์ผ๋ถ๊ฐ ๋ ์ ์๋ค๋์ ์์ SDK๊ฐ API๋ณด๋ค ๋ ํฐ ๊ฐ๋ ์ด๋ค.
- SDK(Software Development Kit) : ์ํํธ์จ์ด ๊ฐ๋ฐ ๋๊ตฌ ๋ชจ์
LangChain ํ๋ ์์ํฌ์ ๊ตฌ์ฑ
- ์ผ๋จ ์ด๋ฐ ๊ตฌ์ฑ์ด ์๊ตฌ๋ ์ ๋๋ก ์๊ณ ์์โฆ
-
๋ญ์ฒด์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(LangChain Libraries):
- ํ์ด์ฌ๊ณผ ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํฌํจ
- ๋ค์ํ ์ปดํฌ๋ํธ์ ์ธํฐํ์ด์ค์ ํตํฉ
- ์ด ์ปดํฌ๋ํธ๋ค์ ์ฒด์ธ๊ณผ ์์ด์ ํธ๋ก ๊ฒฐํฉํ ์ ์๋ ๊ธฐ๋ณธ ๋ฐํ์
- ์ฒด์ธ๊ณผ ์์ด์ ํธ์ ์ฌ์ฉ ๊ฐ๋ฅํ ๊ตฌํ์ด ๊ฐ๋ฅ
-
๋ญ์ฒด์ธ ํ ํ๋ฆฟ(LangChain Templates):
- ๋ค์ํ ์์ ์ ์ํ ์ฝ๊ฒ ๋ฐฐํฌํ ์ ์๋ ์ฐธ์กฐ ์ํคํ ์ณ ๋ชจ์์ง
- ๊ฐ๋ฐ์๋ค์ด ํน์ ์์ ์ ๋ง์ถฐ ๋น ๋ฅด๊ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์๋๋ก ๋์
-
๋ญ์๋ธ(LangServe):
- ๋ญ์ฒด์ธ ์ฒด์ธ์ REST API๋ก ๋ฐฐํฌํ ์ ์๊ฒ ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ๊ฐ๋ฐ์๋ค์ ์์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ธ๋ถ ์์คํ ๊ณผ ์ฝ๊ฒ ํตํฉ ๊ฐ๋ฅ
-
๋ญ์ค๋ฏธ์ค(LangSmith):
- ๊ฐ๋ฐ์ ํ๋ซํผ
- LLM ํ๋ ์์ํฌ์์ ๊ตฌ์ถ๋ ์ฒด์ธ์ ๋๋ฒ๊น , ํ ์คํธ, ํ๊ฐ, ๋ชจ๋ํฐ๋ง
- ๋ญ์ฒด์ธ๊ณผ์ ์ํํ ํตํฉ์ ์ง์
LangChain ํ๋ฆ๋

- ๋ญ์ฒด์ธ์ด ์ด๋ป๊ฒ LLM์์ ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ ์ํ ํ๋ฆ์ ์กฐ์จํ๋์ง ๋ํ๋ธ ๊ทธ๋ฆผ์ด๋ค.
๋ฐ์ดํฐ ์์ค(Data Sources)
- ์ ํ๋ฆฌ์ผ์ด์
์ด LLM์ ๋ํ ์ปจํ
์คํธ๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํด PDF, ์นํ์ด์ง, CSV, ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ ์ธ๋ถ ์์ค์์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํด์ผํ๋ ๊ฒฝ์ฐ
- ๋ญ์ฒด์ธ์ ์๋ก ๋ค๋ฅธ ์์ค์์ ๋ฐ์ดํฐ์ ์ก์ธ์คํ๊ณ ๊ฒ์ํ ์ ์๋ ๋ชจ๋๊ณผ ์ํํ๊ฒ ํตํฉํ๋ค.
๋จ์ด ์๋ฒ ๋ฉ(Word Embeddings)
- ์ผ๋ถ ์ธ๋ถ ์์ค์์ ๊ฒ์๋ ๋ฐ์ดํฐ๋ ๋ฒกํฐ๋ก ๋ณํ๋์ด์ผํ๋ค.
- ํ ์คํธ๋ฅผ LLM๊ณผ ๊ด๋ จ๋ ๋จ์ด ์๋ฒ ๋ฉ ๋ชจ๋ธ์ ์ ๋ฌํ๊ฒ ๋๋ค.
- ๋ญ์ฒด์ธ์ ์ ํํ LLM์ ๊ธฐ๋ฐ์ผ๋ก ์ต์ ์ ์๋ฒ ๋ฉ ๋ชจ๋ธ์ ์ ํํ๋ค.
๋ฒกํฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค(Vector Database)
- ์์ฑ๋ ์๋ฒ ๋ฉ์ ์ ์ฌ์ฑ ๊ฒ์์ ์ํด ๋ฒกํฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋๋ค.
- ๋ญ์ฒด์ธ์ ๋งค๋ชจ๋ฆฌ ๋ด ๋ฐฐ์ด๋ถํฐ ํ์ธ์ฝ(Pinecone)๊ณผ ๊ฐ์ ํธ์คํ ๋ฒกํฐ ๋ฐ์ดํฐ๋ฒ ์ค์ ์ด๋ฅด๊ธฐ๊น์ง ๋ค์ํ ์์ค์์ ๋ฒกํฐ๋ฅผ ์ฝ๊ฒ ์ ์ฅํ๊ณ ๊ฒ์ํ ์ ์๋๋ก ์ง์ํ๋ค.
๋๊ท๋ชจ ์ธ์ด๋ชจ๋ธ(LLM)
- ๋ญ์ฒด์ธ์ OpenAI, ์ฝํ์ด(Cohere), AI21์์ ์ ๊ณตํ๋ ์ฃผ๋ฅ LLM๊ณผ ํ๊น ํ์ด์ค(Hugging Face)์์ ์ ๊ณต๋๋ ์คํ์์ค LLM์ ์ง์ํ๋ค.
- ์ง์๋๋ ๋ชจ๋ธ๊ณผ API ์๋ํฌ์ธํธ ๋ชฉ๋ก์ ๋น ๋ฅด๊ฒ ์ฆ๊ฐํ๊ณ ์๋ค.
LangChain ํ๋ ์์ํฌ

- ์์ ์ด๋ฏธ์ง๋ ๋ญ์ฒด์ธ ํ๋ ์์ํฌ์ ํต์ฌ์ด๋ค.
- ์คํ ์๋จ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ด์ฌ ๋๋ ์๋ฐ์คํฌ๋ฆฝํธ SDK๋ฅผ ํตํด ์ฌ๋ฌ ๋ญ์ฒด์ธ ๋ชจ๋์ค ํ๋์ ์ํธ ์์ฉํ๋ค.
LangChain ๋ชจ๋
๋ชจ๋ธ I/O
- ๋๊ท๋ชจ ์ธ์ด ๋ชจ๋ธ๊ณผ์ ์ธํฐํ์ด์ค
- ํจ๊ณผ์ ์ธ ํ๋กฌํํธ ์์ฑ
- ๋ชจ๋ธ API๋ฅผ ํธ์ถ
- ๊ฒฐ๊ณผ ํด์์ ๋๋๋ค.
- ์์ฑํ AI์ ํต์ฌ์ธ ํ๋กฌํํธ ์์ง๋์ด๋ง์ด ๋ญ์ฒด์ธ์์ ์์ฒ๋ฆฌ๋๋ค.
- LLM ์ ๊ณต์๊ฐ ๋ ธ์ถํ๋ ์ธ์ฆ, API ๋งค๊ฐ๋ณ์, ์๋ํฌ์ธํธ๋ฅผ ์์ฝํ๋ค.
- ๋ชจ๋ธ์์ ๋ณด๋ธ ์๋ต์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉํ ์ ์๋ ์ํ๋ ๋ฐฉ์์ผ๋ก ํด์ํ๋ ์์ ์ ๋๋๋ค.

- ํ๋กฌํํธ๋ฅผ ๊ด๋ฆฌํ๊ณ ๊ณตํต ์ธํฐํ์ด์ค๋ฅผ ํตํด ์ธ์ด ๋ชจ๋ธ์ ํธ์ถํ๊ณ ๋ชจ๋ธ ์ถ๋ ฅ์์ ์ ๋ณด๋ฅผ ์ถ์ถ ๊ฐ๋ฅ
๋ฐ์ดํฐ ์ฐ๊ฒฐ
- ๋ญ์ฒด์ธ์ ๊ฐ์ฅ ์ค์ํ ๊ตฌ์ฑ ์์
- LLM ์ ํ๋ฆฌ์ผ์ด์
์ ETL ํ์ดํ๋ผ์ธ์ด๋ค.
- ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ :
- ํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋จ๊ณ์ ์ถ๋ ฅ์ด ๋ค์ ๋จ๊ณ์ ์ ๋ ฅ์ผ๋ก ์ด์ด์ง๋ ํํ๋ก ์ฐ๊ฒฐ๋ ๊ตฌ์กฐ
- ๋ฐ์ดํฐ๋ฅผ ํ ์ฅ์์์ ๋ค๋ฅธ ์ฅ์๋ก ์ฎ๊ธฐ๋ ๊ฒ
- ๋ฐ์ดํฐ๋ฅผ ์ด๋์ํฌ ์ ์๋ ํต๋ก๋ฅผ ๋ง๋๋ ๊ฒ
- ๋ฐ์ดํฐ๋ฅผ ์์ฑํด์ ์ ์ฅํ๊ธฐ๊น์ง์ ์ผ๋ จ์ ๊ณผ์
- ETL
- ์ถ์ถ(Extract) : ๋ค์ํ ์์ค์์ ๋ฐ์ดํฐ๋ฅผ ์์ง, ์๋ณธ ๋ฐ์ดํฐ ์์ค์์ ๋ฐ์ดํฐ๋ฅผ ๋ฝ์๋
- ๋ณํ(Transformation) : ๋ถ์๊ฐ, ์๊ฐํ ๋๊ตฌ ๋๋ ํ์ดํ๋ผ์ธ์ด ์ ๊ณตํ๋ ๋ชจ๋ ์ฌ์ฉ ์ฌ๋ก์ ์ ์ฉํ๊ฒ ์ธ ์ ์๊ฒ ๊ฐ ์์ค ์์คํ ์ ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ๊ฒฐํฉํ๊ณ ํ์์ ์ง์ ํ๋ ๋จ๊ณ
- ๋ก๋(Load) : ์๋ณธ ๋ฐ์ดํฐ ๋๋ ์์ ํ ๋ณํ๋ ๋ฐ์ดํฐ๋ฅผ ์ต์ข
๋์์ผ๋ก ๊ฐ์ ธ์ด
- ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ดํฐ ์ ์ฅ์์ ์ ์ฅ
- ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ :
- PDF ๋๋ ์์ ํ์ผ๊ณผ ๊ฐ์ ์ธ๋ถ ๋ฌธ์๋ฅผ ๋ก๋
- ์ด๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ผ๊ด์ ์ผ๋ก ๋จ์ด ์๋ฒ ๋ฉ์ผ๋ก ๋ณํ
- ์๋ฒ ๋ฉ์ ๋ฒกํฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ
- ์ฟผ๋ฆฌ๋ฅผ ํตํด ๊ฒ์

- ๋ฐ์ดํฐ๋ฅผ ๋ก๋, ๋ณํ, ์ ์ฅ ๋ฐ ์ฟผ๋ฆฌํ๊ธฐ ์ํ ๋น๋ฉ ๋ธ๋ก์ ์ ๊ณต
์ฒด์ธ
- ํ ๋ชจ๋์ ์ถ๋ ฅ์ด ๋ค๋ฅธ ๋ชจ๋์ ์ ๋ ฅ์ผ๋ก ์ ์ก
- ๊ฐ๋ฐ์๋ ์ข ์ข ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ๋๊น์ง LLM์ ์ฌ์ฉํด ์๋ต์ ๋ช ํํ๊ฒ ํ๊ณ ์์ฝํด์ผ ํ๋ค.
- ๊ตฌ์ฑ ์์์ LLM์ ํ์ฉํ์ฌ ์์๋๋ ์๋ต์ ์ป๋ ํจ์จ์ ์ธ ํ์ดํ ๋ผ์ธ์ ๊ตฌ์ถํ๋๋ก ์ค๊ณ๋์๋ค.
- ๊ฐ๋จํ ์ฒด์ธ์๋ ํ๋กฌํํธ์ LLM์ด ํฌํจ๋ ์ ์์ง๋ง
- ๋ณต์กํ ์ฒด์ธ์๋ ์ฌ๊ท์ ๊ฐ์ด LLM์ ์ฌ๋ฌ๋ฒ ํธ์ถํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ์ป๋๋ก ๊ตฌ์ถํ ์ ์๋ค.
- ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์
์ LLM์ ์ํธ, ๋๋ ๋ค๋ฅธ ๊ตฌ์ฑ์์์ ์ฒด์ธ์ผ๋ก ์ฐ๊ฒฐํด์ผํ๋ค.
- ๋ญ์ฒด์ธ์
์ฒด์ธ์ผ๋ก ์ฐ๊ฒฐ๋์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ์ฒด์ธ ์ธํฐํ์ด์ค ์ ๊ณต
- ๋ญ์ฒด์ธ์
๋ฉ๋ชจ๋ฆฌ
- LLM์ ์ํ ๋น์ ์ฅํ์ด์ง๋ง ์ ํํ ์๋ต์ ์ํด ์ปจํ
์คํธ๊ฐ ํ์ํ๋ค.
- ์ํ ์ ์ฅํ: ์ด์ ์์ฒญ์ ๊ธฐ์ต(์ ์ฅ)
- ์ํ ๋น์ ์ฅํ: ์ด์ ์์ฒญ์ ๊ธฐ์ตโ
- ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋์ ๋จ๊ธฐ ๋ฐ ์ฅ๊ธฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฝ๊ฒ ์ถ๊ฐํ ์ ์๋๋ก ๋์์ค๋ค.
- ๋จ๊ธฐ ๋ฉ๋ชจ๋ฆฌ๋ ๊ฐ๋จํ ๋ฉ์ปค๋์ฆ์ ํตํด ๋ํ์ ๊ธฐ๋ก์ ์ ์ง
- ๋ฉ์์ง ๊ธฐ๋ก์ ๋ ๋์ค(Redis)์ ๊ฐ์ ์ธ๋ถ ์์ค์ ์ ์ฅ๋์ด ์ฅ๊ธฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ง ๊ฐ๋ฅํ๋ค.
- ๋ํํ ์์คํ ์ ์ด๋ ์ ๋ ๊ธฐ๊ฐ์ ๊ณผ๊ฑฐ ๋ฉ์์ง์ ์ง์ ์ก์ธ์คํ ์ ์๊ฒ ํ๋๊ฒ์ด ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฅ์ด๋ค.
์ฝ๋ฐฑ
- ๊ฐ๋ฐ์์๊ฒ LLM ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ํ ๋จ๊ณ์ ์ฐ๊ฒฐํ ์ ์๋ ์ฝ๋ฐฑ ์์คํ ์ ์ ๊ณต
- ํ์ดํ๋ผ์ธ ๋ด์์ ํน์ ์ํฉ์ด ๋ฐ์ํ ๋ ํธ์ถ๋๋ ์ฌ์ฉ์ ์ง์ ์ฝ๋ฐฑ ํธ๋ค๋ฌ๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ค๋ค.
- ๋ญ์ฒด์ธ์ ๊ธฐ๋ณธ ์ฝ๋ฐฑ์ ๋ชจ๋ ๋จ๊ณ์ ์ถ๋ ฅ์ ์ฝ์์ ๊ฐ๋จํ ์ธ์ํ๋ stdout์ ๊ฐ๋ฆฌํจ๋ค.
์์ด์ ํธ
- ์ผ์ข ์ ๋์ ์ฒด์ธ
- ์์ด์ ํธ์ ๊ธฐ๋ณธ ์ผ๋ จ์ ๋์์ ์ ํํ๊ธฐ ์ํด LLM์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
- ๋์์ ์์๋ ์ฒด์ธ(์ฝ๋)์ผ๋ก ํ๋ ์ฝ๋ฉ๋๋ค.
- ์ธ์ด ๋ชจ๋ธ์ ์์ด์ ํธ ๋ด์์ ์ถ๋ก ์์ง์ผ๋ก ์ฌ์ฉ๋์ด ์ด๋ค ์์๋ก ์ด๋ค ๋์์ ์ทจํ ์ง ๊ฒฐ์ ํ๋ค.
- ์ํ์ค๋ฅผ ํ๋ ์ฝ๋ฉํ๋ ์ฒด์ธ๊ณผ ๋ฌ๋ฆฌ, ์์ด์ ํธ๋ ์ธ์ด ๋ชจ๋ธ์ ์ถ๋ก ์์ง์ผ๋ก ์ฌ์ฉํด ์ด๋ค ์์ ์ ์ด๋ ์์์ ๋ฐ๋ผ ์ํํ ์ง๋ฅผ ๊ฒฐ์
๊ธฐ๋ณธ LLM ์ฒด์ธ(Prompt + LLM)
๊ธฐ๋ณธ LLM ์ฒด์ธ
- ์ฌ์ฉ์์ ์ ๋ ฅ(Prompt)์ ๋ฐ์ LLM์ ํตํด ์ ์ ํ ์๋ต์ด๋ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๋ ๊ตฌ์กฐ
- ๋ํํ AI, ์๋ ๋ฌธ์ ์์ฑ, ๋ฐ์ดํฐ ๋ถ์ ๋ฐ ์์ฝ ๋ฑ ๋ค์ํ ์ฉ๋๋ก ํ์ฉ ๊ฐ๋ฅ
1. ๊ธฐ๋ณธ LLM ์ฒด์ธ์ ๊ตฌ์ฑ ์์
-
ํ๋กฌํํธ(Prompt):
- ์ฌ์ฉ์ ๋๋ ์์คํ ์์ ์ ๊ณตํ๋ ์ ๋ ฅ
- LLM์๊ฒ ํน์ ์์ ์ ์ํํ๋๋ก ์์ฒญํ๋ ์ง์๋ฌธ
- ์ง๋ฌธ, ๋ช ๋ น, ๋ฌธ์ฅ ์์ ๋ถ๋ถ ๋ฑ ๋ค์ํ ํํ๋ฅผ ์ทจํ ์ ์๋ค.
- LLM์ ์๋ต์ ์ ๋ํ๋ ๋ฐ ์ค์ํ ์ญํ ์ ํ๋ค.
-
LLM(Large Language Model):
- ๋๋์ ํ ์คํธ ๋ฐ์ดํฐ์์ ํ์ตํ์ฌ ์ธ์ด๋ฅผ ์ดํดํ๊ณ ์์ฑํ ์ ์๋ ์ธ๊ณต์ง๋ฅ ์์คํ
- ํ๋กฌํํธ๋ฅผ ๋ฐํ์ผ๋ก ์ ์ ํ ์๋ต์ ์์ฑํ๊ฑฐ๋, ์ฃผ์ด์ง ์์ ์ ์ํํ๋๋ฐ ์ฌ์ฉ๋๋ค.
2. ์ผ๋ฐ์ ์ธ ์๋ ๋ฐฉ์
-
ํ๋กฌํํธ ์์ฑ:
- ์ฌ์ฉ์์ ์๊ตฌ ์ฌํญ์ด๋ ํน์ ์์ ์ ์ ์ํ๋ ํ๋กฌํํธ๋ฅผ ์์ฑ
- ์ด ํ๋กฌํํธ๋ LLM์๊ฒ ์ ๋ฌ๋๊ธฐ ์
- ์์ ์ ๋ชฉ์ ๊ณผ ๋งฅ๋ฝ์ ๋ช ํํ ์ ๋ฌํ๊ธฐ ์ํด ์ต์ ํ๋ ์ ์์
-
LLM ์ฒ๋ฆฌ:
- LLM์ ์ ๊ณต๋ ํ๋กฌํํธ๋ฅผ ๋ถ์ํ๊ณ , ํ์ต๋ ์ง์์ ๋ฐํ์ผ๋ก ์ ์ ํ ์๋ต์ ์์ฑ
- ์ด ๊ณผ์ ์์
- LLM์ ๋ด๋ถ์ ์ผ๋ก ๋ค์ํ ์ธ์ด ํจํด๊ณผ ๋ด์ธ๋ถ ์ง์์ ํ์ฉํ์ฌ, ์์ฒญ๋ ์์ ์ ์ํํ๊ฑฐ๋ ์ ๋ณด๋ฅผ ์ ๊ณต
- ์ด ๊ณผ์ ์์
- LLM์ ์ ๊ณต๋ ํ๋กฌํํธ๋ฅผ ๋ถ์ํ๊ณ , ํ์ต๋ ์ง์์ ๋ฐํ์ผ๋ก ์ ์ ํ ์๋ต์ ์์ฑ
-
์๋ต ๋ฐํ:
- LLM์ ์ํด ์์ฑ๋ ์๋ต์ ์ต์ข ์ฌ์ฉ์์๊ฒ ํ์ํ ํํ๋ก ๋ณํ๋์ด ์ ๊ณต
- ์ด ์๋ต์
- ์ง์ ์ ์ธ ๋ต๋ณ
- ์์ฑ๋ ํ ์คํธ
- ์์ฝ๋ ์ ๋ณด ๋ฑ
- ๋ค์ํ ํํ๋ก ๊ฐ๋ฅ
LangChain x OpenAI ํตํฉ ํจํค์ง ์ค์น
- ํจํค์ง ์ค์น
pip install langchain-openai
-
API์ ์์ธ์คํ๊ธฐ ์ํด์ API ํค๊ฐ ํ์ํ๋ค.
- APIํค๋ฅผ ๋ฐ๊ธ๋ฐ์
.envํ์ผ์ ์ ์ฅํด์ ์ฌ์ฉํ ์ ์๋ค.
- APIํค๋ฅผ ๋ฐ๊ธ๋ฐ์
-
์์ Setting
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
# API ์ธ์ฆํค ๋ฐ๊ธฐ
load_dotenv()
# ์ธ์ด ๋ชจ๋ธ ์ด๊ธฐํ
llm = ChatOpenAI()1. Prompt
์์
sentence = "์ด๊ฑฐ ๊ฐ์ฌ๋ฐ์"
prompt = f"""\
{sentence}๋ฅผ '๊ธ์ ', '๋ถ์ '์ผ๋ก ํ๋จํด์ ์ด๋ฅผ '๊ธ์ ','๋ถ์ '์ผ๋ก ๋ต๋ณํด์ค ย ย
"""
llm.invoke(prompt)- ์ถ๋ ฅ๊ฐ
AIMessage(content='๊ธ์ ', response_metadata={'token_usage': {'completion_tokens': 3, 'prompt_tokens': 52, 'total_tokens': 55}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-59d3bd3d-8771-4cae-92cd-6cb69e4a9e6d-0', usage_metadata={'input_tokens': 52, 'output_tokens': 3, 'total_tokens': 55})
prompt = f"""\f๋ ๋์ ์ธ ๋ฐ์ดํฐ๋ฅผ ๋ฌธ์์ด๋ก ํํํ ๋ ์ฐ๋ ๋ฐฉ๋ฒ\๋ ์ค์ด ๋๋ ์ง๋ ๊ฒ์ด ์๋ ํ์ค๋ก ์ด์ ๋ ์ฐ๋ ๋ฐฉ๋ฒ
- ์ถ๋ ฅ๊ฐ์
content๋ ๊ฒฐ๊ณผ๊ฐ- ์์ฑ์๊ฐ ์ํ๋ ๊ฒฐ๊ณผ๊ฐ์ ๊ฐ์ ธ์ค๋ ๊ณณ์ด
content
- ์์ฑ์๊ฐ ์ํ๋ ๊ฒฐ๊ณผ๊ฐ์ ๊ฐ์ ธ์ค๋ ๊ณณ์ด
ํ๋กฌํํธ ์์ฑ ์์น
์ถ์ฒ
1. ๋ช ํ์ฑ๊ณผ ๊ตฌ์ฒด์ฑ
- ์ง๋ฌธ์ ๋ช ํํ๊ณ ๊ตฌ์ฒด์ ์ด์ด์ผ ํ๋ค.
- ๋ชจํธํ ์ง๋ฌธ์ LLM ๋ชจ๋ธ์ ํผ๋์ ์ด๋ํ ์ ์๋ค.
- ์์:
- โ๋ค์์ฃผ ์ฃผ์ ์์ฅ์ ์ํฅ์ ์ค ์ ์๋ ์์ ๋ ์ด๋ฒคํธ๋ค์ ๋ฌด์์ผ๊น์?โ๋
- โ์ฃผ์ ์์ฅ์ ๋ํด ์๋ ค์ฃผ์ธ์โ ๋ณด๋ค ๋ ๊ตฌ์ฒด์ ์ด๊ณ ๋ช ํํ ์ง๋ฌธ์ด๋ค.
2. ๋ฐฐ๊ฒฝ ์ ๋ณด๋ฅผ ํฌํจ
- ๋ชจ๋ธ์ด ๋ฌธ๋งฅ์ ์ดํดํ ์ ์๋๋ก ํ์ํ ๋ฐฐ๊ฒฝ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ์ข๋ค.
- ์ด๋ ํ๊ฐ ํ์(hallucination)์ด ๋ฐ์ํ ์ํ์ ๋ฎ์ถ๊ณ , ๊ด๋ จ์ฑ ๋์ ์๋ต์ ์์ฑํ๋๋ฐ ๋์์ ์ค๋ค.
- ์์:
- โ2020๋ ๋ฏธ๊ตญ ๋์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ์ผ๋ก ํ์ฌ ์ ์น ์ํฉ์ ๋ํ ๋ถ์์ ํด์ฃผ์ธ์.โ
3. ๊ฐ๊ฒฐํจ
- ํต์ฌ ์ ๋ณด์ ์ด์ ์ ๋ง์ถ๊ณ , ๋ถํ์ํ ์ ๋ณด๋ ๋ฐฐ์ ํ๋ค.
- ํ๋กฌํํธ๊ฐ ๊ธธ์ด์ง๋ฉด ๋ชจ๋ธ์ด ๋ ์ค์ํ ๋ถ๋ถ์ ์ง์คํ๊ฑฐ๋ ์๋นํ ์ํฅ์ ๋ฐ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ ๊ฐ๋ฅ
- ์์:
- โ2021๋ ์ ๋ฐํ๋ ์ผ์ฑ์ ์์ ESG ๋ณด๊ณ ์๋ฅผ ์์ฝํด์ฃผ์ธ์โ
4. ์ด๋ฆฐ ์ง๋ฌธ ์ฌ์ฉ
- ์ด๋ฆฐ ์ง๋ฌธ์ ํตํด ๋ชจ๋ธ์ด ์์ธํ๊ณ ํ๋ถํ ๋ต๋ณ์ ์ ๊ณตํ๋๋ก ์ ๋ํ๋ค.
- ๋จ์ํ โ์โ ๋๋ โ์๋์คโ๋ก ๋๋ตํ ์ ์๋ ์ง๋ฌธ๋ณด๋ค๋ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ์ง๋ฌธ์ด ์ข๋ค.
- ์์:
- โ์ ์ฌ์์๋์ง์ ๋ํ ์ต์ ์ฐ๊ตฌ ๋ํฅ์ ๋ฌด์์ธ๊ฐ์?โ
5. ๋ช ํํ ๋ชฉํ ์ค์
- ์ป๊ณ ์ ํ๋ ์ ๋ณด๋ ๊ฒฐ๊ณผ์ ์ ํ์ ์ ํํ๊ฒ ์ ์ํ๋ค.
- ๋ชจ๋ธ์ด ๋ช ํํ ์ง์นจ์ ๋ฐ๋ผ ์๋ต์ ์์ฑํ๋๋ก ๋๋๋ค.
- ์์:
- โAI ์ค๋ฆฌ์ ๋ํ ๋ฌธ์ ์ ๊ณผ ํด๊ฒฐ ๋ฐฉ์์ ์์ฝํ์ฌ ์ค๋ช ํด์ฃผ์ธ์.โ
6. ์ธ์ด์ ๋ฌธ์ฒด
- ๋ํ์ ๋งฅ๋ฝ์ ์ ํฉํ ์ธ์ด์ ๋ฌธ์ ๋ฅผ ์ ํํ๋ค.
- ๋ชจ๋ธ์ด ์ํฉ์ ๋ง๋ ํํ์ ์ ํํ๋๋ฐ ๋์์ด ๋ฉ๋๋ค.
- ์์:
- ๊ณต์์ ์ธ ๋ณด๊ณ ์๋ฅผ ์์ฒญํ๋ ๊ฒฝ์ฐ
- โXX๋ณด๊ณ ์์ ๋ํ ์ ๋ฌธ์ ์ธ ์์ฝ์ ๋ถํ๋๋ฆฝ๋๋ค.โ โ ์ ์คํ ๋ฌธ์ฒด ์ฌ์ฉ
- ๊ณต์์ ์ธ ๋ณด๊ณ ์๋ฅผ ์์ฒญํ๋ ๊ฒฝ์ฐ
ํ๋กฌํํธ ํ ํ๋ฆฟ
PromptTemplate
- ๋จ์ผ ๋ฌธ์ฅ ๋๋ ๊ฐ๋จํ ๋ช ๋ น์ ์ ๋ ฅํ์ฌ ๋จ์ผ ๋ฌธ์ฅ ๋๋ ๊ฐ๋จํ ์๋ต์ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋๋ ํ๋กฌํํธ๋ฅผ ๊ตฌ์ฑํ ์ ์๋ ๋ฌธ์์ด ํ ํ๋ฆฟ
- Python์ ๋ฌธ์์ด ํฌ๋ฉงํ ์ ์ฌ์ฉํ์ฌ ๋์ ์ผ๋ก ํน์ ํ ์์น์ ์ ๋ ฅ ๊ฐ์ ํฌํจ์ํฌ ์ ์๋ค.
1. ๊ตฌ์ฑ์์
- LLM ๋ชจ๋ธ์ ์
๋ ฅํ ํฌ๋ฆํํธ๋ฅผ ๊ตฌ์ฑํ ๋
์ง์,์์,๋งฅ๋ฝ,์ง๋ฌธ๊ณผ ๊ฐ์ ๋ค์ํ ๊ตฌ์ฑ์์๋ฅผ ์กฐํฉ ๊ฐ๋ฅํ๋ค.
| ๊ตฌ๋ถ | ๋ด์ฉ |
|---|---|
| ์ง์ | ์ธ์ด ๋ชจ๋ธ์๊ฒ ์ด๋ค ์์ ์ ์ํํ๋๋ก ์์ฒญํ๋ ๊ตฌ์ฒด์ ์ธ ์ง์. |
| ์์ | ์์ฒญ๋ ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ํ๋ ์ด์์ ์์. |
| ๋งฅ๋ฝ | ํน์ ์์ ์ ์ํํ๊ธฐ ์ํ ์ถ๊ฐ์ ์ธ ๋งฅ๋ฝ |
| ์ง๋ฌธ | ์ด๋ค ๋ต๋ณ์ ์๊ตฌํ๋ ๊ตฌ์ฒด์ ์ธ ์ง๋ฌธ |
- ์์
- ์ง์: โ์๋ ์ ๊ณต๋ ์ ํ ๋ฆฌ๋ทฐ๋ฅผ ์์ฝํด์ฃผ์ธ์.โ
- ์์: โ์๋ฅผ ๋ค์ด, โ์ด ์ ํ์ ๋งค์ฐ ์ฌ์ฉํ๊ธฐ ํธ๋ฆฌํ๋ฉฐ ๋ฐฐํฐ๋ฆฌ ์๋ช ์ด ๊ธธ๋ค.โ๋ผ๋ ๋ฆฌ๋ทฐ๋ โ์ฌ์ฉ ํธ๋ฆฌ์ฑ๊ณผ ๊ธด ๋ฐฐํฐ๋ฆฌ ์๋ช ์ด ํน์งโ์ผ๋ก ์์ฝํ ์ ์์ต๋๋ค.โ
- ๋งฅ๋ฝ: โ๋ฆฌ๋ทฐ๋ ์ค๋งํธ ์์น์ ๋ํ ๊ฒ์ด๋ฉฐ, ์ฌ์ฉ์ ๊ฒฝํ์ ์ด์ ์ ๋ง์ถ๊ณ ์์ต๋๋ค.โ
- ์ง๋ฌธ: โ์ด ๋ฆฌ๋ทฐ๋ฅผ ๋ฐํ์ผ๋ก ์ค๋งํธ ์์น์ ์ฃผ์ ์ฅ์ ์ ๋์ธ ๋ฌธ์ฅ์ผ๋ก ์์ฝํด์ฃผ์ธ์.โ
2. ๋ฌธ์์ด ํ ํ๋ฆฟ
langchain_core.prompts๋ชจ๋์PromptTemplateํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค.- ์ด ์์ ๋ ๋ด๊ฐ ์ค์ตํ๋ ์ ํ๋ธ ํฌ๋กค๋ง ๊ณผ์ ๋ฅผ ํ ๋ ๊ธ์ /๋ถ์ ๋ถ๋ฅ๊ธฐ๋ก ์ด ๋ฌธ์์ด ํ ํ๋ฆฟ์ด๋ค.
from langchain_core.prompts import PromptTemplate
template = """\
# INSTRUCTION
- ๋น์ ์ ๊ธ/๋ถ์ ๋ถ๋ฅ๊ธฐ์
๋๋ค.
- SENTENCE๋ฅผ ["๊ธ์ ", "๋ถ์ "] ์ค ํ๋๋ก ํ๋์ ๋ฌธ์์ด๋ก ๋ถ๋ฅํ์ธ์.
# SENTENCE: {sentence}
"""
prompt = PromptTemplate.from_template(template)
chain = prompt | llmPromptTemplate.from_template๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์์ด ํ ํ๋ฆฟ์ผ๋ก๋ถํฐPromptTemplate์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค.- ์ด๋,
template๋ณ์์ ์ ์๋ ํ ํ๋ฆฟ ๋ฌธ์์ด์ด ์ฌ์ฉ๋๋ค.
- ์ด๋,
- chain์ ์ ์๋ ํ๋กฌํํธ ํ
ํ๋ฆฟ์ LLM๊ณผ ์ฐ๊ฒฐํ์ฌ ์
๋ ฅํ๋กฌํํธ๋ฅผ ์์ฑํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ป๋ ์ผ๋ จ์ ์์
์ ์ํํ๋ค.
|์ฐ์ฐ์๋ ํ์ดํ ์ฐ์ฐ์๋ก, ํ๋กฌํํธ๋ฅผ LLM์ ์ ๋ ฅํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ป๋ ๊ณผ์ ์ ๋ํ๋ธ๋ค.
ํ๋กฌํํธ ํ ํ๋ฆฟ ํ์ฉ
Reference
LLMChain ๊ฐ์ฒด
- LLMChain์ ํน์ PromptTemplate์ ์ฐ๊ฒฐ๋ ์ฒด์ธ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
- ์ฌ์ฉ๋ฒ
chain = prompt | llm
์คํธ๋ฆฌ๋ฐ(Streaming)
- ๋๊ท๋ชจ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์ ์กํ๋ ๋์ , ์ผ์ ํ ์๋๋ก ์ฐ์์ ์ผ๋ก ์ ์กํ์ฌ ์ฒ๋ฆฌํ๋ ๋ฐฉ์
- ํ ํฐ๋ณ(๊ธ์ ํ๋์ฉ) ์ถ๋ ฅํ๋ค๋ ๋ป
- ์คํธ๋ฆฌ๋ฐ ์ต์ ์ ์ง์์ ๋ํ ๋ต๋ณ์ ์ค์๊ฐ์ผ๋ก ๋ฐ์ ๋ ์ ์ฉํ๋ค.
- ์ฅ์
- ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ: ๋ฐ์ดํฐ๋ฅผ ์์ ํ์๋ง์ ์ฆ์ ์ฒ๋ฆฌํ ์ ์์ด ๋น ๋ฅธ ๋ฐ์์ด ์๊ตฌ๋๋ ์ ํ๋ฆฌ์ผ์ธ์ ์ ์ ํฉํ๋ค.
- ๋ฆฌ์์ค ํจ์จ์ฑ: ๋๊ท๋ชจ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํ์ง ์๊ณ ๋๋์ด ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ์ CPU ๋ฆฌ์์ค๋ฅผ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
- ์ฐ์์ ๋ถ์: ์ง์์ ์ผ๋ก ๋ค์ด์ค๋ ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํ ์ ์์ด, ์ค์๊ฐ ๋ชจ๋ํฐ๋ง ๋ฐ ๋์์ด ๊ฐ๋ฅํ๋ค.
2. Output Parsers(์ถ๋ ฅ ํ์)
Reference
Output Parser
LangChain์ Output Parser๋ ์ธ์ด๋ชจ๋ธ(LLM)์ ์ถ๋ ฅ์ ๋ ์ ์ฉํ๊ณ ๊ตฌ์กฐํ๋ ํํ๋ก ๋ณํํ๋ ์ค์ํ ์์์ด๋ค.
์ญํ
- LLM์ ์ถ๋ ฅ์ ๋ฐ์ ๋ ์ ํฉํ ํ์์ผ๋ก ์ ํ
- ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ ์์ฑ์ ๋งค์ฐ ์ ์ฉ
- LangChain ํ๋ ์์ํฌ์์ ๋ค์ํ ์ข ๋ฅ์ ์ถ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ๊ณ ์ฒ๋ฆฌ
์ฃผ์ ํน์ง
- ๋ค์์ฑ: LangChain์ ๋ง์ ์ข ๋ฅ์ ์ถ๋ ฅ ํ์๋ฅผ ์ ๊ณตํ๋ค.
- ์คํธ๋ฆฌ๋ฐ ์ง์: ๋ง์ ์ถ๋ ฅ ํ์๋ค์ ์คํธ๋ฆฌ๋ฐ์ ์ง์ํ๋ค.
- ํ์ฅ์ฑ: ์ต์ํ์ ๋ชจ๋๋ถํฐ ๋ณต์กํ ๋ชจ๋๊น์ง ํ์ฅ ๊ฐ๋ฅํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ค.
Output Parser์ ์ด์
- ๊ตฌ์กฐํ: LLM์ ์์ ํ์ ํ ์คํธ ์ถ๋ ฅ์ ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ๋ก ๋ณํํ๋ค.
- ์ผ๊ด์ฑ: ์ถ๋ ฅ ํ์์ ์ผ๊ด๋๊ฒ ์ ์งํ์ฌ ํ์ ์ฒ๋ฆฌ๋ฅผ ์ฉ์ดํ๊ฒ ํ๋ค.
- ์ ์ฐ์ฑ: ๋ค์ํ ์ถ๋ ฅ ํ์(JSON, List, Dictionary๋ฑ)์ผ๋ก ๋ณํ์ด ๊ฐ๋ฅํ๋ค.
1. PydanticOutputParser
์ธ์ด ๋ชจ๋ธ์ ์ถ๋ ฅ์ ๋ ๊ตฌ์กฐํ๋ ์ ๋ณด๋ก ๋ณํ ํ๋ ๋ฐ ๋์์ด ๋๋ ํด๋์ค์ด๋ค.
๋จ์ ํ
์คํธ ํํ์ ์๋ต ๋์ , ์ฌ์ฉ์๊ฐ ํ์๋ก ํ๋ ์ ๋ณด๋ฅผ ๋ช
ํํ๊ณ ์ฒด๊ณ์ ์ธ ํํ๋ก ์ ๊ณตํ ์ ์๋ค.
ํต์ฌ ๋ฉ์๋
get_format_instructions(): ์ธ์ด ๋ชจ๋ธ์ด ์ถ๋ ฅํด์ผ ํ ์ ๋ณด์ ํ์์ ์ ์ํ๋ ์ง์นจ(instruction)์ ์ ๊ณตํ๋ค.- ์์: ์ธ์ด ๋ชจ๋ธ์ด ์ถ๋ ฅํด์ผ ํ ๋ฐ์ดํฐ์ ํ๋์ ๊ทธ ํํ๋ฅผ ์ค๋ช ํ๋ ์ง์นจ์ ๋ฌธ์์ด๋ก ๋ฐํํ ์ ์๋ค. ์ด๋ ์ค์ ํ๋ instruction์ ์ญํ ์ด ์ค์ํ๋ค. ์ด ์ง์นจ์ ๋ฐ๋ผ ์ธ์ด ๋ชจ๋ธ์ ์ถ๋ ฅ์ ๊ตฌ์กฐํํ๊ณ , ์ด๋ฅผ ํน์ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ๋ง๊ฒ ๋ณํํ ์ ์๋ค.
parse(): ์ธ์ด ๋ชจ๋ธ์ ์ถ๋ ฅ(๋ฌธ์์ด๋ก ๊ฐ์ )์ ๋ฐ์๋ค์ฌ ์ด๋ฅผ ํน์ ๊ตฌ์กฐ๋ก ๋ถ์ํ๊ณ ๋ณํํ๋ค. Pydantic์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ, ์ ๋ ฅ๋ ๋ฌธ์์ด์ ์ฌ์ ์ ์๋ ์คํค๋ง์ ๋ฐ๋ผ ๊ฒ์ฆํ๊ณ , ํด๋น ์คํค๋ง๋ฅผ ๋ฐ๋ฅด๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ก ๋ณํํ๋ค.
3. Memory
Reference
1. ๋ํ ๋ฒํผ ๋ฉ๋ชจ๋ฆฌ (ConversationBufferMemory)
- ์ด ๋ฉ๋ชจ๋ฆฌ๋ ๋ฉ์์ง๋ฅผ ์ ์ฅํ ๋ค์ ๋ณ์์ ๋ฉ์์ง๋ฅผ ์ถ์ถํ ์ ์๊ฒ ํ๋ค.
์์
from langchain.memory import ConversationBufferMemorymemory = ConversationBufferMemory()
memory.save_context(
inputs={
"human": "์๋
ํ์ธ์, ๋น๋๋ฉด์ผ๋ก ์ํ ๊ณ์ข๋ฅผ ๊ฐ์คํ๊ณ ์ถ์ต๋๋ค. ์ด๋ป๊ฒ ์์ํด์ผ ํ๋์?"
},
outputs={
"ai": "์๋
ํ์ธ์! ๊ณ์ข ๊ฐ์ค์ ์ํ์ ๋ค๋ ๊ธฐ์ฉ๋๋ค. ๋จผ์ , ๋ณธ์ธ ์ธ์ฆ์ ์ํด ์ ๋ถ์ฆ์ ์ค๋นํด ์ฃผ์๊ฒ ์ด์?"
},
)- memory์
load_memory_variables({})ํจ์๋ ๋ฉ์์ง ํ์คํ ๋ฆฌ๋ฅผ ๋ฐํํ๋ค.
# 'history' ํค์ ์ ์ฅ๋ ๋ํ ๊ธฐ๋ก์ ํ์ธํฉ๋๋ค.
memory.load_memory_variables({})# ์ถ๋ ฅ๊ฐ
{'history': 'Human: ์๋
ํ์ธ์, ๋น๋๋ฉด์ผ๋ก ์ํ ๊ณ์ข๋ฅผ ๊ฐ์คํ๊ณ ์ถ์ต๋๋ค. ์ด๋ป๊ฒ ์์ํด์ผ ํ๋์?\nAI: ์๋
ํ์ธ์! ๊ณ์ข ๊ฐ์ค์ ์ํ์ ๋ค๋ ๊ธฐ์ฉ๋๋ค. ๋จผ์ , ๋ณธ์ธ ์ธ์ฆ์ ์ํด ์ ๋ถ์ฆ์ ์ค๋นํด ์ฃผ์๊ฒ ์ด์?'}
save_context(inputs, outputs)๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ํ ๊ธฐ๋ก์ ์ ์ฅํ ์ ์๋ค.- ์ด ๋ฉ์๋๋
inputs์outputs๋ ๊ฐ์ ์ธ์๋ฅผ ๋ฐ๋๋ค. inputs์ ์ฌ์ฉ์์ ์ ๋ ฅ์,outputs๋ AI์ ์ถ๋ ฅ์ ์ ์ฅํ๋ค.- ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ํ ๊ธฐ๋ก์ด
historyํค์ ์ ์ฅ๋๋ค. - ์ดํ
load_memory_variables๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฅ๋ ๋ํ ๊ธฐ๋ก์ ํ์ธํ ์ ์๋ค.
- ์ด ๋ฉ์๋๋
# inputs: dictionary(key: "human" or "ai", value: ์ง๋ฌธ)
# outputs: dictionary(key: "ai" or "human", value: ๋ต๋ณ)
memory.save_context(
inputs={"human": "๋ค, ์ ๋ถ์ฆ์ ์ค๋นํ์ต๋๋ค. ์ด์ ๋ฌด์์ ํด์ผ ํ๋์?"},
outputs={
"ai": "๊ฐ์ฌํฉ๋๋ค. ์ ๋ถ์ฆ ์๋ค๋ฅผ ๋ช
ํํ๊ฒ ์ดฌ์ํ์ฌ ์
๋ก๋ํด ์ฃผ์ธ์. ์ดํ ๋ณธ์ธ ์ธ์ฆ ์ ์ฐจ๋ฅผ ์งํํ๊ฒ ์ต๋๋ค."
},
)# 2๊ฐ์ ๋ํ๋ฅผ ์ ์ฅํฉ๋๋ค.
memory.save_context(
inputs={"human": "์ฌ์ง์ ์
๋ก๋ํ์ต๋๋ค. ๋ณธ์ธ ์ธ์ฆ์ ์ด๋ป๊ฒ ์งํ๋๋์?"},
outputs={
"ai": "์
๋ก๋ํด ์ฃผ์ ์ฌ์ง์ ํ์ธํ์ต๋๋ค. ์ด์ ํด๋ํฐ์ ํตํ ๋ณธ์ธ ์ธ์ฆ์ ์งํํด ์ฃผ์ธ์. ๋ฌธ์๋ก ๋ฐ์ก๋ ์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํด ์ฃผ์๋ฉด ๋ฉ๋๋ค."
},
)
memory.save_context(
inputs={"human": "์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํ์ต๋๋ค. ๊ณ์ข ๊ฐ์ค์ ์ด์ ์ด๋ป๊ฒ ํ๋์?"},
outputs={
"ai": "๋ณธ์ธ ์ธ์ฆ์ด ์๋ฃ๋์์ต๋๋ค. ์ด์ ์ํ์๋ ๊ณ์ข ์ข
๋ฅ๋ฅผ ์ ํํ๊ณ ํ์ํ ์ ๋ณด๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์. ์๊ธ ์ข
๋ฅ, ํตํ ์ข
๋ฅ ๋ฑ์ ์ ํํ ์ ์์ต๋๋ค."
},
)# history์ ์ ์ฅ๋ ๋ํ ๊ธฐ๋ก์ ํ์ธํฉ๋๋ค.
print(memory.load_memory_variables({})["history"])# ์ถ๋ ฅ๊ฐ
Human: ์๋
ํ์ธ์, ๋น๋๋ฉด์ผ๋ก ์ํ ๊ณ์ข๋ฅผ ๊ฐ์คํ๊ณ ์ถ์ต๋๋ค. ์ด๋ป๊ฒ ์์ํด์ผ ํ๋์?
AI: ์๋
ํ์ธ์! ๊ณ์ข ๊ฐ์ค์ ์ํ์ ๋ค๋ ๊ธฐ์ฉ๋๋ค. ๋จผ์ , ๋ณธ์ธ ์ธ์ฆ์ ์ํด ์ ๋ถ์ฆ์ ์ค๋นํด ์ฃผ์๊ฒ ์ด์?
Human: ์ฌ์ง์ ์
๋ก๋ํ์ต๋๋ค. ๋ณธ์ธ ์ธ์ฆ์ ์ด๋ป๊ฒ ์งํ๋๋์?
AI: ์
๋ก๋ํด ์ฃผ์ ์ฌ์ง์ ํ์ธํ์ต๋๋ค. ์ด์ ํด๋ํฐ์ ํตํ ๋ณธ์ธ ์ธ์ฆ์ ์งํํด ์ฃผ์ธ์. ๋ฌธ์๋ก ๋ฐ์ก๋ ์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํด ์ฃผ์๋ฉด ๋ฉ๋๋ค.
Human: ์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํ์ต๋๋ค. ๊ณ์ข ๊ฐ์ค์ ์ด์ ์ด๋ป๊ฒ ํ๋์?
AI: ๋ณธ์ธ ์ธ์ฆ์ด ์๋ฃ๋์์ต๋๋ค. ์ด์ ์ํ์๋ ๊ณ์ข ์ข
๋ฅ๋ฅผ ์ ํํ๊ณ ํ์ํ ์ ๋ณด๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์. ์๊ธ ์ข
๋ฅ, ํตํ ์ข
๋ฅ ๋ฑ์ ์ ํํ ์ ์์ต๋๋ค.
# ์ถ๊ฐ๋ก 2๊ฐ์ ๋ํ๋ฅผ ์ ์ฅํฉ๋๋ค.
memory.save_context(
inputs={"human": "์ ๋ณด๋ฅผ ๋ชจ๋ ์
๋ ฅํ์ต๋๋ค. ๋ค์ ๋จ๊ณ๋ ๋ฌด์์ธ๊ฐ์?"},
outputs={
"ai": "์
๋ ฅํด ์ฃผ์ ์ ๋ณด๋ฅผ ํ์ธํ์ต๋๋ค. ๊ณ์ข ๊ฐ์ค ์ ์ฐจ๊ฐ ๊ฑฐ์ ๋๋ฌ์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก ์ด์ฉ ์ฝ๊ด์ ๋์ํด ์ฃผ์๊ณ , ๊ณ์ข ๊ฐ์ค์ ์ต์ข
ํ์ธํด ์ฃผ์ธ์."
},
)
memory.save_context(
inputs={"human": "๋ชจ๋ ์ ์ฐจ๋ฅผ ์๋ฃํ์ต๋๋ค. ๊ณ์ข๊ฐ ๊ฐ์ค๋ ๊ฑด๊ฐ์?"},
outputs={
"ai": "๋ค, ๊ณ์ข ๊ฐ์ค์ด ์๋ฃ๋์์ต๋๋ค. ๊ณ ๊ฐ๋์ ๊ณ์ข ๋ฒํธ์ ๊ด๋ จ ์ ๋ณด๋ ๋ฑ๋กํ์ ์ด๋ฉ์ผ๋ก ๋ฐ์ก๋์์ต๋๋ค. ์ถ๊ฐ์ ์ธ ๋์์ด ํ์ํ์๋ฉด ์ธ์ ๋ ์ง ๋ฌธ์ํด ์ฃผ์ธ์. ๊ฐ์ฌํฉ๋๋ค!"
},
)# history์ ์ ์ฅ๋ ๋ํ ๊ธฐ๋ก์ ํ์ธํฉ๋๋ค.
print(memory.load_memory_variables({})["history"])# ์ถ๋ ฅ๊ฐ
Human: ์๋
ํ์ธ์, ๋น๋๋ฉด์ผ๋ก ์ํ ๊ณ์ข๋ฅผ ๊ฐ์คํ๊ณ ์ถ์ต๋๋ค. ์ด๋ป๊ฒ ์์ํด์ผ ํ๋์?
AI: ์๋
ํ์ธ์! ๊ณ์ข ๊ฐ์ค์ ์ํ์ ๋ค๋ ๊ธฐ์ฉ๋๋ค. ๋จผ์ , ๋ณธ์ธ ์ธ์ฆ์ ์ํด ์ ๋ถ์ฆ์ ์ค๋นํด ์ฃผ์๊ฒ ์ด์?
Human: ์ฌ์ง์ ์
๋ก๋ํ์ต๋๋ค. ๋ณธ์ธ ์ธ์ฆ์ ์ด๋ป๊ฒ ์งํ๋๋์?
AI: ์
๋ก๋ํด ์ฃผ์ ์ฌ์ง์ ํ์ธํ์ต๋๋ค. ์ด์ ํด๋ํฐ์ ํตํ ๋ณธ์ธ ์ธ์ฆ์ ์งํํด ์ฃผ์ธ์. ๋ฌธ์๋ก ๋ฐ์ก๋ ์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํด ์ฃผ์๋ฉด ๋ฉ๋๋ค.
Human: ์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํ์ต๋๋ค. ๊ณ์ข ๊ฐ์ค์ ์ด์ ์ด๋ป๊ฒ ํ๋์?
AI: ๋ณธ์ธ ์ธ์ฆ์ด ์๋ฃ๋์์ต๋๋ค. ์ด์ ์ํ์๋ ๊ณ์ข ์ข
๋ฅ๋ฅผ ์ ํํ๊ณ ํ์ํ ์ ๋ณด๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์. ์๊ธ ์ข
๋ฅ, ํตํ ์ข
๋ฅ ๋ฑ์ ์ ํํ ์ ์์ต๋๋ค.
Human: ์ ๋ณด๋ฅผ ๋ชจ๋ ์
๋ ฅํ์ต๋๋ค. ๋ค์ ๋จ๊ณ๋ ๋ฌด์์ธ๊ฐ์?
AI: ์
๋ ฅํด ์ฃผ์ ์ ๋ณด๋ฅผ ํ์ธํ์ต๋๋ค. ๊ณ์ข ๊ฐ์ค ์ ์ฐจ๊ฐ ๊ฑฐ์ ๋๋ฌ์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก ์ด์ฉ ์ฝ๊ด์ ๋์ํด ์ฃผ์๊ณ , ๊ณ์ข ๊ฐ์ค์ ์ต์ข
ํ์ธํด ์ฃผ์ธ์.
Human: ๋ชจ๋ ์ ์ฐจ๋ฅผ ์๋ฃํ์ต๋๋ค. ๊ณ์ข๊ฐ ๊ฐ์ค๋ ๊ฑด๊ฐ์?
AI: ๋ค, ๊ณ์ข ๊ฐ์ค์ด ์๋ฃ๋์์ต๋๋ค. ๊ณ ๊ฐ๋์ ๊ณ์ข ๋ฒํธ์ ๊ด๋ จ ์ ๋ณด๋ ๋ฑ๋กํ์ ์ด๋ฉ์ผ๋ก ๋ฐ์ก๋์์ต๋๋ค. ์ถ๊ฐ์ ์ธ ๋์์ด ํ์ํ์๋ฉด ์ธ์ ๋ ์ง ๋ฌธ์ํด ์ฃผ์ธ์. ๊ฐ์ฌํฉ๋๋ค!
return_messages=True๋ก ์ค์ ํ๋ฉดHumanMessage์AIMessage๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
memory = ConversationBufferMemory(return_messages=True)
memory.save_context(
inputs={
"human": "์๋
ํ์ธ์, ๋น๋๋ฉด์ผ๋ก ์ํ ๊ณ์ข๋ฅผ ๊ฐ์คํ๊ณ ์ถ์ต๋๋ค. ์ด๋ป๊ฒ ์์ํด์ผ ํ๋์?"
},
outputs={
"ai": "์๋
ํ์ธ์! ๊ณ์ข ๊ฐ์ค์ ์ํ์ ๋ค๋ ๊ธฐ์ฉ๋๋ค. ๋จผ์ , ๋ณธ์ธ ์ธ์ฆ์ ์ํด ์ ๋ถ์ฆ์ ์ค๋นํด ์ฃผ์๊ฒ ์ด์?"
},
)
memory.save_context(
inputs={"human": "๋ค, ์ ๋ถ์ฆ์ ์ค๋นํ์ต๋๋ค. ์ด์ ๋ฌด์์ ํด์ผ ํ๋์?"},
outputs={
"ai": "๊ฐ์ฌํฉ๋๋ค. ์ ๋ถ์ฆ ์๋ค๋ฅผ ๋ช
ํํ๊ฒ ์ดฌ์ํ์ฌ ์
๋ก๋ํด ์ฃผ์ธ์. ์ดํ ๋ณธ์ธ ์ธ์ฆ ์ ์ฐจ๋ฅผ ์งํํ๊ฒ ์ต๋๋ค."
},
)
memory.save_context(
inputs={"human": "์ฌ์ง์ ์
๋ก๋ํ์ต๋๋ค. ๋ณธ์ธ ์ธ์ฆ์ ์ด๋ป๊ฒ ์งํ๋๋์?"},
outputs={
"ai": "์
๋ก๋ํด ์ฃผ์ ์ฌ์ง์ ํ์ธํ์ต๋๋ค. ์ด์ ํด๋ํฐ์ ํตํ ๋ณธ์ธ ์ธ์ฆ์ ์งํํด ์ฃผ์ธ์. ๋ฌธ์๋ก ๋ฐ์ก๋ ์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํด ์ฃผ์๋ฉด ๋ฉ๋๋ค."
},
)# history์ ์ ์ฅ๋ ๋ํ ๊ธฐ๋ก์ ํ์ธํฉ๋๋ค.
memory.load_memory_variables({})["history"]# ์ถ๋ ฅ๊ฐ
[HumanMessage(content='์๋
ํ์ธ์, ๋น๋๋ฉด์ผ๋ก ์ํ ๊ณ์ข๋ฅผ ๊ฐ์คํ๊ณ ์ถ์ต๋๋ค. ์ด๋ป๊ฒ ์์ํด์ผ ํ๋์?'), AIMessage(content='์๋
ํ์ธ์! ๊ณ์ข ๊ฐ์ค์ ์ํ์ ๋ค๋ ๊ธฐ์ฉ๋๋ค. ๋จผ์ , ๋ณธ์ธ ์ธ์ฆ์ ์ํด ์ ๋ถ์ฆ์ ์ค๋นํด ์ฃผ์๊ฒ ์ด์?'), HumanMessage(content='๋ค, ์ ๋ถ์ฆ์ ์ค๋นํ์ต๋๋ค. ์ด์ ๋ฌด์์ ํด์ผ ํ๋์?'), AIMessage(content='๊ฐ์ฌํฉ๋๋ค. ์ ๋ถ์ฆ ์๋ค๋ฅผ ๋ช
ํํ๊ฒ ์ดฌ์ํ์ฌ ์
๋ก๋ํด ์ฃผ์ธ์. ์ดํ ๋ณธ์ธ ์ธ์ฆ ์ ์ฐจ๋ฅผ ์งํํ๊ฒ ์ต๋๋ค.'), HumanMessage(content='์ฌ์ง์ ์
๋ก๋ํ์ต๋๋ค. ๋ณธ์ธ ์ธ์ฆ์ ์ด๋ป๊ฒ ์งํ๋๋์?'), AIMessage(content='์
๋ก๋ํด ์ฃผ์ ์ฌ์ง์ ํ์ธํ์ต๋๋ค. ์ด์ ํด๋ํฐ์ ํตํ ๋ณธ์ธ ์ธ์ฆ์ ์งํํด ์ฃผ์ธ์. ๋ฌธ์๋ก ๋ฐ์ก๋ ์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํด ์ฃผ์๋ฉด ๋ฉ๋๋ค.')]
Chain์ ์ ์ฉ
from langchain_openai import ChatOpenAI
from langchain.chains import ConversationChain
# LLM ๋ชจ๋ธ์ ์์ฑํฉ๋๋ค.
llm = ChatOpenAI(temperature=0)
# ConversationChain์ ์์ฑํฉ๋๋ค.
conversation = ConversationChain(
# ConversationBufferMemory๋ฅผ ์ฌ์ฉํฉ๋๋ค.
llm=llm,
memory=ConversationBufferMemory(),
)ConversationChain์ ์ฌ์ฉํ์ฌ ๋ํ๋ฅผ ์งํํ๋ค.
# ๋ํ๋ฅผ ์์ํฉ๋๋ค.
response = conversation.predict(
input="์๋
ํ์ธ์, ๋น๋๋ฉด์ผ๋ก ์ํ ๊ณ์ข๋ฅผ ๊ฐ์คํ๊ณ ์ถ์ต๋๋ค. ์ด๋ป๊ฒ ์์ํด์ผ ํ๋์?"
)
print(response)# ์ถ๋ ฅ๊ฐ
์๋
ํ์ธ์! ์ํ ๊ณ์ข๋ฅผ ๊ฐ์คํ๋ ค๋ฉด ๋จผ์ ํด๋น ์ํ์ ๊ณต์ ์น์ฌ์ดํธ์ ์ ์ํ์
์ ์จ๋ผ์ธ ๊ฐ์ค ์ ์ฐจ๋ฅผ ๋ฐ๋ผ์ผ ํฉ๋๋ค. ๋ณดํต ๊ฐ์ธ ์ ๋ณด, ์ ๋ถ์ฆ ์ฌ๋ณธ, ์ฃผ์์ฆ๋ช
์ ๋ฑ์ ๋ฌธ์๋ฅผ ์ ์ถํด์ผ ํ๋ฉฐ, ์จ๋ผ์ธ ์์์ ์์ฑํ๊ณ ์ ์ ์๋ช
์ ํด์ผ ํฉ๋๋ค. ๊ทธ ํ์ ์ํ์์ ์ ๊ณตํ๋ ์๋ด์ ๋ฐ๋ผ ์ถ๊ฐ ๋จ๊ณ๋ฅผ ์งํํ์๋ฉด ๋ฉ๋๋ค. ํน์ ์ด๋ค ์ํ์ ๊ณ ๋ คํ๊ณ ๊ณ์ ๊ฐ์?
- ์ด์ ์ ๋ํ ๊ธฐ๋ก์ ๊ธฐ์ตํ๊ณ ์๋์ง ํ์ธํ๋ค.
# ์ด์ ๋ํ๋ด์ฉ์ ๋ถ๋ ํฌ์ธํธ๋ก ์ ๋ฆฌํด ๋ฌ๋ผ๋ ์์ฒญ์ ๋ณด๋
๋๋ค.
response = conversation.predict(
input="์ด์ ๋ต๋ณ์ ๋ถ๋ ํฌ์ธํธ ํ์์ผ๋ก ์ ๋ฆฌํ์ฌ ์๋ ค์ฃผ์ธ์."
)
print(response)# ์ถ๋ ฅ๊ฐ
1. ํด๋น ์ํ์ ๊ณต์ ์น์ฌ์ดํธ์ ์ ์
2. ์จ๋ผ์ธ ๊ฐ์ค ์ ์ฐจ ๋ฐ๋ฅด๊ธฐ
3. ๊ฐ์ธ ์ ๋ณด, ์ ๋ถ์ฆ ์ฌ๋ณธ, ์ฃผ์์ฆ๋ช
์ ๋ฑ ์ ์ถ
4. ์จ๋ผ์ธ ์์ ์์ฑ ๋ฐ ์ ์ ์๋ช
5. ์ํ ์๋ด์ ๋ฐ๋ผ ์ถ๊ฐ ๋จ๊ณ ์งํ
LCEL (๋ํ๋ด์ฉ ๊ธฐ์ตํ๊ธฐ): ๋ฉ๋ชจ๋ฆฌ ์ถ๊ฐ
- ์์์ ์ฒด์ธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋ค. ํ์ฌ ๋ฉ๋ชจ๋ฆฌ ํด๋์ค๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง ์๋์ผ๋ก ์ฐ๊ฒฐ ํด์ผํ๋ค.
from operator import itemgetter
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_openai import ChatOpenAI
# ChatOpenAI ๋ชจ๋ธ์ ์ด๊ธฐํํฉ๋๋ค.
model = ChatOpenAI()
# ๋ํํ ํ๋กฌํํธ๋ฅผ ์์ฑํฉ๋๋ค. ์ด ํ๋กฌํํธ๋ ์์คํ
๋ฉ์์ง, ์ด์ ๋ํ ๋ด์ญ, ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์ ์
๋ ฅ์ ํฌํจํฉ๋๋ค.
prompt = ChatPromptTemplate.from_messages(
[
("system", "You are a helpful chatbot"),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}"),
]
)- ๋ํ๋ด์ฉ์ ์ ์ฅํ ๋ฉ๋ชจ๋ฆฌ์ธ
ConversationBufferMemory์์ฑํ๊ณreturn_messages๋งค๊ฐ๋ณ์๋ฅผTrue๋ก ์ค์ ํ์ฌ, ์์ฑ๋ ์ธ์คํด์ค๊ฐ ๋ฉ์์ง๋ฅผ ๋ฐํํ๋๋ก ํ๋ค. memory_key์ค์ : ์ถํ Chain์prompt์์ ๋์ ๋ key๋ค. ๋ณ๊ฒฝํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
# ๋ํ ๋ฒํผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์์ฑํ๊ณ , ๋ฉ์์ง ๋ฐํ ๊ธฐ๋ฅ์ ํ์ฑํํฉ๋๋ค.
memory = ConversationBufferMemory(
return_messages=True, memory_key="chat_history")RunnablePassthrough.assign์ ์ฌ์ฉํ์ฌchat_history๋ณ์์memory.load_memory_variablesํจ์์ ๊ฒฐ๊ณผ๋ฅผ ํ ๋นํ๊ณ , ์ด ๊ฒฐ๊ณผ์์chat_historyํค์ ํด๋นํ๋ ๊ฐ์ ์ถ์ถํ๋ค.
runnable = RunnablePassthrough.assign(
chat_history=RunnableLambda(memory.load_memory_variables)
| itemgetter("chat_history") # memory_key ์ ๋์ผํ๊ฒ ์
๋ ฅํฉ๋๋ค.
)runnable์ ์ฒซ ๋ฒ์งธ ๋ํ๋ฅผ ์์ํ๋ค.input: ์ฌ์ฉ์ ์ ๋ ฅ ๋ํ๊ฐ ์ ๋ฌ๋๋ค.chat_history: ๋ํ ๊ธฐ๋ก์ด ์ ๋ฌ๋๋ค.
runnable.invoke({"input": "hi!"})# ์ถ๋ ฅ๊ฐ
{'input': 'hi!', 'chat_history': []}
chain = runnable | prompt | model์ฒซ ๋ฒ์งธ ๋ํ๋ฅผ ์งํํ๋ค.
# chain ๊ฐ์ฒด์ invoke ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์
๋ ฅ์ ๋ํ ์๋ต์ ์์ฑํฉ๋๋ค.
response = chain.invoke({"input": "๋ง๋์ ๋ฐ๊ฐ์ต๋๋ค. ์ ์ด๋ฆ์ ํ
๋์
๋๋ค."})
print(response) # ์์ฑ๋ ์๋ต์ ์ถ๋ ฅํฉ๋๋ค.content='๋ง๋์ ๋ฐ๊ฐ์์, ํ
๋๋! ๋ฌด์์ ๋์๋๋ฆด๊น์?' response_metadata={'finish_reason': 'stop', 'logprobs': None}
memory.save_contextํจ์๋ ์ ๋ ฅ ๋ฐ์ดํฐ(inputs)์ ์๋ต ๋ด์ฉ(response.content)์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๋ ์ญํ- ์ด๋ AI ๋ชจ๋ธ์ ํ์ต ๊ณผ์ ์์ ํ์ฌ ์ํ๋ฅผ ๊ธฐ๋กํ๊ฑฐ๋, ์ฌ์ฉ์์ ์์ฒญ๊ณผ ์์คํ ์ ์๋ต์ ์ถ์ ํ๋๋ฐ ์ฌ์ฉ๋ ์ ์๋ค.
# ์
๋ ฅ๋ ๋ฐ์ดํฐ์ ์๋ต ๋ด์ฉ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํฉ๋๋ค.
memory.save_context(
{"inputs": "๋ง๋์ ๋ฐ๊ฐ์ต๋๋ค. ์ ์ด๋ฆ์ ํ
๋์
๋๋ค."}, {"output": response.content}
)
# ์ ์ฅ๋ ๋ํ๊ธฐ๋ก์ ์ถ๋ ฅํฉ๋๋ค.
memory.load_memory_variables({})# ์ถ๋ ฅ๊ฐ
{'chat_history': [HumanMessage(content='๋ง๋์ ๋ฐ๊ฐ์ต๋๋ค. ์ ์ด๋ฆ์ ํ
๋์
๋๋ค.'), AIMessage(content='๋ง๋์ ๋ฐ๊ฐ์์, ํ
๋๋! ๋ฌด์์ ๋์๋๋ฆด๊น์?')]}
์ด๋ฆ์ ๊ธฐ์ตํ๊ณ ์๋์ง ์ถ๊ฐ ์ง์ํ๋ค.
# ์ด๋ฆ์ ๊ธฐ์ตํ๊ณ ์๋์ง ์ถ๊ฐ ์ง์ํฉ๋๋ค.
response = chain.invoke({"input": "์ ์ด๋ฆ์ด ๋ฌด์์ด์๋์ง ๊ธฐ์ตํ์ธ์?"})
# ๋ต๋ณ์ ์ถ๋ ฅํฉ๋๋ค.
print(response.content)# ์ถ๋ ฅ๊ฐ
๋ค, ํ
๋๋์ด์ธ์. ์ด๋ป๊ฒ ๋์๋๋ฆด๊น์?
4. LCEL(LangChain Expression Language)
์ฐธ๊ณ ์๋ฃ
์ฐ๊ตฌ์๋ LLM ์ฐ๊ตฌ๋ ธํธ
LangChain ๊ณต์ ๋ฌธ์
๋ญ์ฒด์ธLangChain ๋ ธํธ langchain LCEL๊ณผ Runnable
LCEL(LangChain Expression Language)์ ํ๋กฌํํธ ๊ตฌ์ฑ, ๋ชจ๋ธ ์ธ์คํด์ค ์์ฑ, ์ถ๋ ฅ ์์ฑ์ ๊ณผ์ ์ Chain ์ผ๋ก ๋ฌถ์ด ๋ณต์กํ ์ํฌํ๋ก์ฐ๋ฅผ ์ฝ๊ณ ์ง๊ด์ ์ผ๋ก ๊ตฌ์ถํ ์ ์๋๋ก ๋๋ ์ธํฐํ์ด์ค์ด๋ค.
ํน์๋ฌธ์(|)๋ฅผ ํ์ฉํ์ฌ ๋ณธ์ธ๋ง์ Chain์ ๊ตฌ์ถํ ์ ์๋ค.
1. Methods
| Sync/Async | Description |
|---|---|
invoke/ainvoke | ์ ๋ ฅ์ ๋ํ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค. |
batch/abatch | ๋ฐ๋ณต๋๋ ์ ๋ ฅ์ ๋ฆฌ์คํธ๋ก ์ ๋ ฅํ์ฌ ์ฒ๋ฆฌํ๋ค. |
stream/astream | chunk๋ง๋ค ์ถ๋ ฅ๋๊ฒ ํ๋ค. |
astream_log | ์ค๊ฐ ๋จ๊ณ๋ฅผ ์คํธ๋ฆฌ๋ฐํ๋ค. |
# ๊ธฐ๋ณธ ์ฝ๋
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = PromptTemplate.from_template("{input}์ ๋ํด ํ๊ตญ์ด๋ก ํ ์ค๋ก ์ค๋ช
ํด์ค")
model = ChatOpenAI(model_name = "gpt-3.5-turbo")
output_parser = StrOutputParser()
chain = prompt | model | output_parserinvoke/ ainvoke
import time
import asyncio
def run_sync(input_list):
"""invoke ์คํ ํจ์"""
start_time = time.time()
for input in input_list:
result = chain.invoke(input)
print(result)
end_time = time.time()
print("="*100)
print(f"Sync execution time: {end_time - start_time:.2f} seconds")
async def run_async(input_list):
"""ainvoke ์คํ ํจ์"""
start_time = time.time()
tasks = [chain.ainvoke(input) for input in input_list]
results = await asyncio.gather(*tasks)
end_time = time.time()
print(f"Async execution time: {end_time - start_time:.2f} seconds")
print("="*100)
for result in results:
print(result)
run_sync(input_list)
await run_async(input_list)# ์ถ๋ ฅ๊ฐ
# Sync execution time: 7.13 seconds
# Async execution time: 1.58 seconds
batch / abatch
batch์ abatch์ ์๋ ์ฐจ์ด๊ฐ ํฌ๊ฒ ๋์ง ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง, ๋ณด๋ค ๋ ๋ณต์กํ ์ฝ๋์์๋ ์ฐจ์ด๊ฐ ๋ ๊ฒ์ด๋ค.
import time
import asyncio
def run_sync(input_list):
"""batch ์คํ ํจ์"""
start_time = time.time()
result = chain.batch(input_list)
end_time = time.time()
print(f"Sync execution time: {end_time - start_time:.2f} seconds")
print("="*100)
print("\n".join(result))
async def run_async():
"""abatch ์คํ ํจ์"""
start_time = time.time()
tasks = chain.abatch(input_list)
result = await tasks
end_time = time.time()
print(f"Async execution time: {end_time - start_time:.2f} seconds")
print("="*100)
print("\n".join(result))
run_sync(input_list)
await run_async(input_list)# ์ถ๋ ฅ๊ฐ
# Sync execution time: 1.78 seconds
# Async execution time: 1.65 seconds
stream / astream
generator๋ก ์ถ๋ ฅ๋์ด for๋ฌธ์ผ๋ก printํ๋ฉด chunk๋ณ๋ก streaming๋๋ค.
# generator๋ก ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธ
chain.stream({"input":"ํ์ด์ฌ"})
# ์ถ๋ ฅ๊ฐ
# <generator object RunnableSequence.stream at 0x0000014E37FB6650># stream
for chunk in chain.stream({"input":"ํ์ด์ฌ"}):
print(chunk, end="", flush=True)
# astream
for chunk in chain.stream({"input":"ํ์ด์ฌ"}):
print(chunk, end="", flush=True)stream_log
chain ์คํ๊ณผ์ ์ ๋ก๊น ํ๋ ํจ์๋ก ๋๋ฒ๊น ํ ๋ ์ฉ์ดํ๋ค.
stream = chain.astream_log({"input":"ํ์ด์ฌ"})
async for chunk in stream:
print(chunk)
print("="*100)์ฝ๋ ๊ฒฐ๊ณผ
>> RunLogPatch({'op': 'replace', 'path': '', 'value': {'final_output': None, 'id': '7e312a61-7190-46b7-8f04-c88ab333f58d', 'logs': {}, 'name': 'RunnableSequence', 'streamed_output': [], 'type': 'chain'}}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/PromptTemplate', 'value': {'end_time': None, 'final_output': None, 'id': 'aec36f3d-a8ea-4b51-8c74-e0ab0d56b3b6', 'metadata': {}, 'name': 'PromptTemplate', 'start_time': '2024-06-27T01:56:14.017+00:00', 'streamed_output': [], 'streamed_output_str': [], 'tags': ['seq:step:1'], 'type': 'prompt'}}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/PromptTemplate/final_output', 'value': StringPromptValue(text='ํ์ด์ฌ์ ๋ํด ํ๊ตญ์ด๋ก ํ ์ค๋ก ์ค๋ช ํด์ค')}, {'op': 'add', 'path': '/logs/PromptTemplate/end_time', 'value': '2024-06-27T01:56:14.023+00:00'}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI', 'value': {'end_time': None, 'final_output': None, 'id': 'b0736693-8368-4871-8021-62c6c0f3255f', 'metadata': {}, 'name': 'ChatOpenAI', 'start_time': '2024-06-27T01:56:14.030+00:00', 'streamed_output': [], 'streamed_output_str': [], 'tags': ['seq:step:2'], 'type': 'llm'}}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output_str/-', 'value': ''}, {'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output/-', 'value': AIMessageChunk(content='', id='run-b0736693-8368-4871-8021-62c6c0f3255f')}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/StrOutputParser', 'value': {'end_time': None, 'final_output': None, 'id': '202ac825-a78c-47c7-bf02-bbe3e8e3b798', 'metadata': {}, 'name': 'StrOutputParser', 'start_time': '2024-06-27T01:56:14.866+00:00', 'streamed_output': [], 'streamed_output_str': [], 'tags': ['seq:step:3'], 'type': 'parser'}}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/StrOutputParser/streamed_output/-', 'value': ''}) ================================================== RunLogPatch({'op': 'add', 'path': '/streamed_output/-', 'value': ''}, {'op': 'replace', 'path': '/final_output', 'value': ''}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output_str/-', 'value': 'ํ'}, {'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output/-', 'value': AIMessageChunk(content='ํ', id='run-b0736693-8368-4871-8021-62c6c0f3255f')}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/StrOutputParser/streamed_output/-', 'value': 'ํ'}) ================================================== RunLogPatch({'op': 'add', 'path': '/streamed_output/-', 'value': 'ํ'}, {'op': 'replace', 'path': '/final_output', 'value': 'ํ'}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output_str/-', 'value': '์ด'}, {'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output/-', 'value': AIMessageChunk(content='์ด', id='run-b0736693-8368-4871-8021-62c6c0f3255f')}) ================================================== RunLogPatch({'op': 'add', 'path': '/logs/StrOutputParser/streamed_output/-', 'value': '์ด'}) ================================================== RunLogPatch({'op': 'add', 'path': '/streamed_output/-', 'value': '์ด'}, {'op': 'replace', 'path': '/final_output', 'value': 'ํ์ด'}) ==================================================
Runnable
์ ๋ ฅ๊ฐ๋ค์ ๋ํ ๋ณํ์ด ํ์ํ ๊ฒฝ์ฐ ์ ์ฐํ๊ฒ ์ปค์คํ ํ ์ ์๋ ๋๊ตฌ๋ค์ด๋ค.
์ปค์คํ
์ฒด์ธ์ ์ฝ๊ฒ ๋ง๋ค๊ธฐ ์ํด Runnable ํ๋กํ ์ฝ์ ์ฌ์ฉํ๋ค.
chat models,LLM,outputparser,retriever,prompt template๋ฑ์ ํฌํจํ ๋ง์ langchain์ปดํฌ๋ํธ๊ฐ Runnableํ๋กํ ์ฝ์ ์ฌ์ฉํ๋ค.
์ด๋ ํ์ค์ ์ธ ๋ฐฉ์์ผ๋ก ์คํํ ์ ์๊ณ ์ปค์คํ ์ฒด์ธ๋ ์ฝ๊ฒ ๋ง๋ค ์ ์๋ ์ธํฐํ์ด์ค์ด๋ค.
ํ์ค ์ธํฐํ์ด์ค๋ ๋ค์์ ํฌํจํ๋ค.
- stream: ์๋ต ์ฒญํฌ๋ฅผ ์คํธ๋ฆผ์ผ๋ก ์ถ๋ ฅ
- invoke: ์ ๋ ฅ์ ๋ฐ์ ์ฒด์ธ์ ํธ์ถ
- batch: ์ ๋ ฅ ๋ชฉ๋ก์ผ๋ก ์ฒด์ธ์ ํธ์ถ
| Function | Description |
|---|---|
RunnablePassthrough() | ์ ๋ ฅ๋ ๊ฐ์ ๊ทธ๋๋ก ์ ๋ฌํ๋ค. |
RunnablePassthrough.assign() | ์ ๋ ฅ๋ ๊ฐ์ ๋ณํํ๊ฑฐ๋ ์๋ก์ด ๋ณ์๋ฅผ ๋ง๋ ๋ค. |
RunnableLambda() | ์ ๋ ฅ๋ ๊ฐ์ ์ด์ํด์ ํจ์๋ก ์๋ก์ด ๋ณ์๋ฅผ ๋ง๋ ๋ค. |
RunnableParallel() | ๋์ผํ ์ ๋ ฅ์ ๊ฐ์ง chain์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ๋ค. |
# ๊ธฐ๋ณธ ์ฝ๋
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = PromptTemplate.from_template("'{input}'์ ์์ด๋ก ๋ฒ์ญํด์ฃผ์ธ์")
model = ChatOpenAI(model_name = "gpt-3.5-turbo")
output_parser = StrOutputParser()RunnablePassthrough()
์ ๋ ฅ๋ ๊ฐ์ ๊ทธ๋๋ก ์ ๋ฌํ๋ค. / ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ์ญํ
๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ํ์ดํ๋ผ์ธ์ ๋ค์ ๋จ๊ณ๋ก ์ ๋ฌํ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์๋ค.
RunnablePassthrough๋ ๋ค์๊ณผ ๊ฐ์ ์๋๋ฆฌ์ค์์ ์ ์ฉํ ์ ์๋ค.
- ๋ฐ์ดํฐ๋ฅผ ๋ณํํ๊ฑฐ๋ ์์ ํ ํ์๊ฐ ์๋ ๊ฒฝ์ฐ
- ํ์ดํ๋ผ์ธ์ ํน์ ๋จ๊ณ๋ฅผ ๊ฑด๋๋ฐ์ด์ผ ํ๋ ๊ฒฝ์ฐ
- ๋๋ฒ๊น ๋๋ ํ ์คํธ ๋ชฉ์ ์ผ๋ก ๋ฐ์ดํฐ ํ๋ฆ์ ๋ชจ๋ํฐ๋งํด์ผ ํ๋ ๊ฒฝ์ฐ
์๋๋ ๋์
๋๋ฆฌ๋ก ์
๋ ฅํด์ผ ํ์ง๋ง, ๋ฌธ์์ด๋ก ์
๋ ฅ ๋ฐ์ runnable์์ ๋์
๋๋ฆฌ๋ฅผ ๋ง๋ ํ ํ๋กฌํํธ์ ์ ๋ฌ ํ ์ ์๋ค.
runnable = {"input": RunnablePassthrough()}
chain = runnable | prompt | model | output_parser
chain.invoke("๋ค๋์ฅ")
# ์ถ๋ ฅ๊ฐ
# 'Squirrel'๋ค๋ฅธ ์์
prompt = PromptTemplate.from_template("{num} x 9๋?")
llm = ChatOpenAI()
chain = prompt | llm | StrOutputParser()
response = chain.invoke({"num": 9})
print(response)
# ์ถ๋ ฅ๊ฐ
# 81์
๋๋ค.์ฌ๊ธฐ์ invoke์ {"num":9}์ธ ๋์
๋๋ฆฌ ํ์
์ผ๋ก ๊ฐ์ ๋ฃ์๋๋ฐ num์ด ์๋ ๊ทธ๋ฅ 9๋ก ์
๋ ฅํ๋ ค๋ฉด RunnablePassthrough๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. ์ฆ, num์ RunnablePassthrough()๋ก ์ง์ ํ๋ฉด ๋งค๊ฐ๋ณ์๋ก ๊ฐ์ ๋๊ธธ ์ ์๋ค๋ ๊ฒ์ด๋ค.
prompt = PromptTemplate.from_template("{num} x 9๋?")
llm = ChatOpenAI()
# chain = prompt | llm | StrOutputParser()
chain = {"num": RunnablePassthrough()} | prompt | llm | StrOutputParser()
response = chain.invoke(3)
print(response)
# ์ถ๋ ฅ๊ฐ
# 81์
๋๋ค.RunnablePassthrough.assign()
์ ๋ ฅ๊ฐ์ ๋ณํํ๊ฑฐ๋ ์๋ก์ด ์ ๋ ฅ๊ฐ์ ๋ง๋ค ์ ์๋ค.
add_runnable = RunnablePassthrough.assign(input = lambda x: x["input"] + "๋ฅผ ๋ณด์์ต๋๋ค")
add_runnable.invoke({"input": "๋ค๋์ฅ"})
# ์ถ๋ ฅ๊ฐ
# {'input': '๋ค๋์ฅ๋ฅผ ๋ณด์์ต๋๋ค'}RunnableLambda()
RunnableLambda๋ ์ฌ์ฉ์ ์ ์ ํจ์๋ฅผ ์คํํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
์ด๋ฅผ ํตํด ๊ฐ๋ฐ์๋ ์์ ๋ง์ ํจ์๋ฅผ ์ ์ํ๊ณ , ํด๋น ํจ์๋ฅผ RunnableLambda๋ฅผ ์ฌ์ฉํ์ฌ ์คํํ ์ ์๋ค.
ํจ์๋ฅผ ๋ง๋ค์ด ์ ๋ ฅ๊ฐ์ ๋ณํํ ์ ์๋ค.
from langchain_core.runnables import RunnableLambda
def add_text(input):
return "์ธ์์์ ๊ฐ์ฅ ์์ " + input
runnable = {"input": RunnableLambda(add_text)}
chain = runnable | prompt | model | output_parser
chain.invoke("๋ค๋์ฅ")
# ์ถ๋ ฅ๊ฐ
# 'The smallest squirrel in the world'RunnableParallel()
์ ๋ ฅ๊ฐ์ด ๋์ผํ ์ฌ๋ฌ ๊ฐ์ ์ฒด์ธ์ ๋ณ๋ ฌ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค.
prompt1 = PromptTemplate.from_template("{country}์ ์ฃผ์ ์ธ์ด๋ฅผ ์๋ ค์ค")
prompt2 = PromptTemplate.from_template("{country}์ ๋ํ์ ์ธ ๋๋๋งํฌ 3๊ฐ๋ฅผ ์๋ ค์ค")
chain1 = prompt1 | model | output_parser
chain2 = prompt2 | model | output_parser
combined = RunnableParallel(
language = chain1,
landmarks = chain2
)
combined.invoke({"country":"ํ๊ตญ"})
# ์ถ๋ ฅ๊ฐ
# {'language': 'ํ๊ตญ์ ์ฃผ์ ์ธ์ด๋ ํ๊ตญ์ด์
๋๋ค. ํ๊ตญ์ด๋ ๋๋ถ๋ถ์ ํ๊ตญ ์ฌ๋๋ค์ด ์ฌ์ฉํ๋ ์ธ์ด๋ก, ๊ตญ๋ด์์๋ ๊ณต์ ์ธ์ด๋ก ์ฌ์ฉ๋๊ณ ์์ต๋๋ค. ๋ํ, ์์ด๋ ๋ง์ ์ฌ๋๋ค์ด ํ์ตํ๊ณ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ, ์ค๊ตญ์ด์ ์ผ๋ณธ์ด๋ ์ผ๋ถ ์ง์ญ์์ ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.',
# ย 'landmarks': '1. ๋จ์ฐํ์ - ์์ธ์ ๋ํ์ ์ธ ๋๋๋งํฌ๋ก์, ์์ธ ์๋ด์ ํ๊ฐ์ ํ๋์ ๋ณผ ์ ์๋ ์ ๋ง๋๊ฐ ์ ๋ช
ํ๋ค.\n2. ๊ฒฝ๋ณต๊ถ - ์์ธ์ ์์นํ ์กฐ์ ์๋์ ๊ถ๊ถ๋ก์, ์๋ฆ๋ค์ด ์ ํต ํ์ฅ ๊ฑด๋ฌผ๊ณผ ๊ทผ์ ์ , ๊ฒฝํ๋ฃจ ๋ฑ์ ๋ณผ ์ ์๋ค.\n3. ๋ถ์ฐ ํ์ - ๋ถ์ฐ์ ๋๋๋งํฌ๋ก์, ๋ถ์ฐ ์๋ด์ ํด์๋๋ก๋ฅผ ํ๋์ ๋ณผ ์ ์๋ ์ ๋ง๋์ ์ผ๊ฒฝ์ด ์ ๋ช
ํ๋ค.'}