์ฐธ๊ณ ์ž๋ฃŒ

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๋ณด๋‹ค ๋” ํฐ ๊ฐœ๋…์ด๋‹ค.

LangChain ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๊ตฌ์„ฑ

  • ์ผ๋‹จ ์ด๋Ÿฐ ๊ตฌ์„ฑ์ด ์žˆ๊ตฌ๋‚˜ ์ •๋„๋กœ ์•Œ๊ณ  ์žˆ์žโ€ฆ
  1. ๋žญ์ฒด์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(LangChain Libraries):

    • ํŒŒ์ด์ฌ๊ณผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํฌํ•จ
    • ๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ์˜ ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ†ตํ•ฉ
    • ์ด ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ฒด์ธ๊ณผ ์—์ด์ „ํŠธ๋กœ ๊ฒฐํ•ฉํ• ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ณธ ๋Ÿฐํƒ€์ž„
    • ์ฒด์ธ๊ณผ ์—์ด์ „ํŠธ์˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅ
  2. ๋žญ์ฒด์ธ ํ…œํ”Œ๋ฆฟ(LangChain Templates):

    • ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์œ„ํ•œ ์‰ฝ๊ฒŒ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋Š” ์ฐธ์กฐ ์•„ํ‚คํ…์ณ ๋ชจ์Œ์ง‘
    • ๊ฐœ๋ฐœ์ž๋“ค์ด ํŠน์ • ์ž‘์—…์— ๋งž์ถฐ ๋น ๋ฅด๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์›€
  3. ๋žญ์„œ๋ธŒ(LangServe):

    • ๋žญ์ฒด์ธ ์ฒด์ธ์„ REST API๋กœ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
    • ๊ฐœ๋ฐœ์ž๋“ค์€ ์ž์‹ ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉ ๊ฐ€๋Šฅ
  4. ๋žญ์Šค๋ฏธ์Šค(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) : ์›๋ณธ ๋ฐ์ดํ„ฐ ๋˜๋Š” ์™„์ „ํžˆ ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ตœ์ข… ๋Œ€์ƒ์œผ๋กœ ๊ฐ€์ ธ์˜ด
          • ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ์— ์ €์žฅ
  1. PDF ๋˜๋Š” ์—‘์…€ ํŒŒ์ผ๊ณผ ๊ฐ™์€ ์™ธ๋ถ€ ๋ฌธ์„œ๋ฅผ ๋กœ๋“œ
  2. ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ผ๊ด„์ ์œผ๋กœ ๋‹จ์–ด ์ž„๋ฒ ๋”ฉ์œผ๋กœ ๋ณ€ํ™˜
  3. ์ž„๋ฒ ๋”ฉ์„ ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ
  4. ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰

  • ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œ, ๋ณ€ํ™˜, ์ €์žฅ ๋ฐ ์ฟผ๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋นŒ๋”ฉ ๋ธ”๋ก์„ ์ œ๊ณต

์ฒด์ธ

  • ํ•œ ๋ชจ๋“ˆ์˜ ์ถœ๋ ฅ์ด ๋‹ค๋ฅธ ๋ชจ๋“ˆ์— ์ž…๋ ฅ์œผ๋กœ ์ „์†ก
  • ๊ฐœ๋ฐœ์ž๋Š” ์ข…์ข… ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ๋•Œ๊นŒ์ง€ LLM์„ ์‚ฌ์šฉํ•ด ์‘๋‹ต์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ณ  ์š”์•ฝํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ตฌ์„ฑ ์š”์†Œ์™€ LLM์„ ํ™œ์šฉํ•˜์—ฌ ์˜ˆ์ƒ๋˜๋Š” ์‘๋‹ต์„ ์–ป๋Š” ํšจ์œจ์ ์ธ ํŒŒ์ดํ”„ ๋ผ์ธ์„ ๊ตฌ์ถ•ํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ๋‹ค.
  • ๊ฐ„๋‹จํ•œ ์ฒด์ธ์—๋Š” ํ”„๋กฌํ”„ํŠธ์™€ LLM์ด ํฌํ•จ๋ ์ˆ˜ ์žˆ์ง€๋งŒ
  • ๋ณต์žกํ•œ ์ฒด์ธ์—๋Š” ์žฌ๊ท€์™€ ๊ฐ™์ด LLM์„ ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์–ป๋„๋ก ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณต์žกํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ LLM์„ ์ƒํ˜ธ, ๋˜๋Š” ๋‹ค๋ฅธ ๊ตฌ์„ฑ์š”์†Œ์™€ ์ฒด์ธ์œผ๋กœ ์—ฐ๊ฒฐํ•ด์•ผํ•œ๋‹ค.
    • ๋žญ์ฒด์ธ์€ ์ฒด์ธ์œผ๋กœ ์—ฐ๊ฒฐ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ์ฒด์ธ ์ธํ„ฐํŽ˜์ด์Šค ์ œ๊ณต

๋ฉ”๋ชจ๋ฆฌ

  • LLM์€ ์ƒํƒœ ๋น„์ €์žฅํ˜•์ด์ง€๋งŒ ์ •ํ™•ํ•œ ์‘๋‹ต์„ ์œ„ํ•ด ์ปจํ…์ŠคํŠธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
    • ์ƒํƒœ ์ €์žฅํ˜•: ์ด์ „ ์š”์ฒญ์„ ๊ธฐ์–ต(์ €์žฅ)
    • ์ƒํƒœ ๋น„์ €์žฅํ˜•: ์ด์ „ ์š”์ฒญ์„ ๊ธฐ์–ตโŒ
  • ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋“ˆ์€ ๋‹จ๊ธฐ ๋ฐ ์žฅ๊ธฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค.
  • ๋‹จ๊ธฐ ๋ฉ”๋ชจ๋ฆฌ๋Š” ๊ฐ„๋‹จํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ†ตํ•ด ๋Œ€ํ™”์˜ ๊ธฐ๋ก์„ ์œ ์ง€
  • ๋ฉ”์‹œ์ง€ ๊ธฐ๋ก์€ ๋ ˆ๋””์Šค(Redis)์™€ ๊ฐ™์€ ์™ธ๋ถ€ ์†Œ์Šค์— ์ €์žฅ๋˜์–ด ์žฅ๊ธฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์œ ์ง€ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋Œ€ํ™”ํ˜• ์‹œ์Šคํ…œ์€ ์–ด๋А ์ •๋„ ๊ธฐ๊ฐ„์˜ ๊ณผ๊ฑฐ ๋ฉ”์‹œ์ง€์— ์ง์ ‘ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š”๊ฒƒ์ด ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋Šฅ์ด๋‹ค.

์ฝœ๋ฐฑ

  • ๊ฐœ๋ฐœ์ž์—๊ฒŒ LLM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋‹ค์–‘ํ•œ ๋‹จ๊ณ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์ฝœ๋ฐฑ ์‹œ์Šคํ…œ์„ ์ œ๊ณต
  • ํŒŒ์ดํ”„๋ผ์ธ ๋‚ด์—์„œ ํŠน์ • ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์ฝœ๋ฐฑ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
  • ๋žญ์ฒด์ธ์˜ ๊ธฐ๋ณธ ์ฝœ๋ฐฑ์€ ๋ชจ๋“  ๋‹จ๊ณ„์˜ ์ถœ๋ ฅ์„ ์ฝ˜์†”์— ๊ฐ„๋‹จํžˆ ์ธ์‡„ํ•˜๋Š” stdout์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

์—์ด์ „ํŠธ

  • ์ผ์ข…์˜ ๋™์  ์ฒด์ธ
  • ์—์ด์ „ํŠธ์˜ ๊ธฐ๋ณธ ์ผ๋ จ์˜ ๋™์ž‘์„ ์„ ํƒํ•˜๊ธฐ ์œ„ํ•ด LLM์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • ๋™์ž‘์˜ ์ˆœ์„œ๋Š” ์ฒด์ธ(์ฝ”๋“œ)์œผ๋กœ ํ•˜๋“œ ์ฝ”๋”ฉ๋œ๋‹ค.
  • ์–ธ์–ด ๋ชจ๋ธ์€ ์—์ด์ „ํŠธ ๋‚ด์—์„œ ์ถ”๋ก  ์—”์ง„์œผ๋กœ ์‚ฌ์šฉ๋˜์–ด ์–ด๋–ค ์ˆœ์„œ๋กœ ์–ด๋–ค ๋™์ž‘์„ ์ทจํ• ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค.
  • ์‹œํ€€์Šค๋ฅผ ํ•˜๋“œ ์ฝ”๋”ฉํ•˜๋Š” ์ฒด์ธ๊ณผ ๋‹ฌ๋ฆฌ, ์—์ด์ „ํŠธ๋Š” ์–ธ์–ด ๋ชจ๋ธ์„ ์ถ”๋ก  ์—”์ง„์œผ๋กœ ์‚ฌ์šฉํ•ด ์–ด๋–ค ์ž‘์—…์„ ์–ด๋А ์ˆœ์„œ์— ๋”ฐ๋ผ ์ˆ˜ํ–‰ํ• ์ง€๋ฅผ ๊ฒฐ์ •

๊ธฐ๋ณธ LLM ์ฒด์ธ(Prompt + LLM)

๊ธฐ๋ณธ LLM ์ฒด์ธ

  • ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ(Prompt)์„ ๋ฐ›์•„ LLM์„ ํ†ตํ•ด ์ ์ ˆํ•œ ์‘๋‹ต์ด๋‚˜ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ตฌ์กฐ
  • ๋Œ€ํ™”ํ˜• AI, ์ž๋™ ๋ฌธ์„œ ์ƒ์„ฑ, ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐ ์š”์•ฝ ๋“ฑ ๋‹ค์–‘ํ•œ ์šฉ๋„๋กœ ํ™œ์šฉ ๊ฐ€๋Šฅ

1. ๊ธฐ๋ณธ LLM ์ฒด์ธ์˜ ๊ตฌ์„ฑ ์š”์†Œ

  1. ํ”„๋กฌํ”„ํŠธ(Prompt):

    • ์‚ฌ์šฉ์ž ๋˜๋Š” ์‹œ์Šคํ…œ์—์„œ ์ œ๊ณตํ•˜๋Š” ์ž…๋ ฅ
    • LLM์—๊ฒŒ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์š”์ฒญํ•˜๋Š” ์ง€์‹œ๋ฌธ
    • ์งˆ๋ฌธ, ๋ช…๋ น, ๋ฌธ์žฅ ์‹œ์ž‘ ๋ถ€๋ถ„ ๋“ฑ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋ฅผ ์ทจํ•  ์ˆ˜ ์žˆ๋‹ค.
    • LLM์˜ ์‘๋‹ต์„ ์œ ๋„ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•œ๋‹ค.
  2. LLM(Large Language Model):

    • ๋Œ€๋Ÿ‰์˜ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์—์„œ ํ•™์Šตํ•˜์—ฌ ์–ธ์–ด๋ฅผ ์ดํ•ดํ•˜๊ณ  ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ์ธ๊ณต์ง€๋Šฅ ์‹œ์Šคํ…œ
    • ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ ์ ˆํ•œ ์‘๋‹ต์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜, ์ฃผ์–ด์ง„ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

2. ์ผ๋ฐ˜์ ์ธ ์ž‘๋™ ๋ฐฉ์‹

  1. ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ:

    • ์‚ฌ์šฉ์ž์˜ ์š”๊ตฌ ์‚ฌํ•ญ์ด๋‚˜ ํŠน์ • ์ž‘์—…์„ ์ •์˜ํ•˜๋Š” ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑ
    • ์ด ํ”„๋กฌํ”„ํŠธ๋Š” LLM์—๊ฒŒ ์ „๋‹ฌ๋˜๊ธฐ ์ „
      • ์ž‘์—…์˜ ๋ชฉ์ ๊ณผ ๋งฅ๋ฝ์„ ๋ช…ํ™•ํžˆ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ์ตœ์ ํ™”๋  ์ˆ˜ ์žˆ์Œ
  2. LLM ์ฒ˜๋ฆฌ:

    • LLM์€ ์ œ๊ณต๋œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ถ„์„ํ•˜๊ณ , ํ•™์Šต๋œ ์ง€์‹์„ ๋ฐ”ํƒ•์œผ๋กœ ์ ์ ˆํ•œ ์‘๋‹ต์„ ์ƒ์„ฑ
      • ์ด ๊ณผ์ •์—์„œ
        • LLM์€ ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค์–‘ํ•œ ์–ธ์–ด ํŒจํ„ด๊ณผ ๋‚ด์™ธ๋ถ€ ์ง€์‹์„ ํ™œ์šฉํ•˜์—ฌ, ์š”์ฒญ๋œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜ ์ •๋ณด๋ฅผ ์ œ๊ณต
  3. ์‘๋‹ต ๋ฐ˜ํ™˜:

    • LLM์— ์˜ํ•ด ์ƒ์„ฑ๋œ ์‘๋‹ต์€ ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ํ•„์š”ํ•œ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜๋˜์–ด ์ œ๊ณต
    • ์ด ์‘๋‹ต์€
      • ์ง์ ‘์ ์ธ ๋‹ต๋ณ€
      • ์ƒ์„ฑ๋œ ํ…์ŠคํŠธ
      • ์š”์•ฝ๋œ ์ •๋ณด ๋“ฑ
      • ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋กœ ๊ฐ€๋Šฅ

LangChain x OpenAI ํ†ตํ•ฉ ํŒจํ‚ค์ง€ ์„ค์น˜

  • ํŒจํ‚ค์ง€ ์„ค์น˜
pip install langchain-openai
  • API์— ์—‘์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•ด์„  API ํ‚ค๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

    • APIํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์•„ .envํŒŒ์ผ์— ์ €์žฅํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์‹œ์ž‘ 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 | llm
  • PromptTemplate.from_template ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด ํ…œํ”Œ๋ฆฟ์œผ๋กœ๋ถ€ํ„ฐ PromptTemplate์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    • ์ด๋•Œ, template ๋ณ€์ˆ˜์— ์ •์˜๋œ ํ…œํ”Œ๋ฆฟ ๋ฌธ์ž์—ด์ด ์‚ฌ์šฉ๋œ๋‹ค.
  • chain์€ ์ •์˜๋œ ํ”„๋กฌํ”„ํŠธ ํ…œํ”Œ๋ฆฟ์„ LLM๊ณผ ์—ฐ๊ฒฐํ•˜์—ฌ ์ž…๋ ฅํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์–ป๋Š” ์ผ๋ จ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    • |์—ฐ์‚ฐ์ž๋Š” ํŒŒ์ดํ”„ ์—ฐ์‚ฐ์ž๋กœ, ํ”„๋กฌํ”„ํŠธ๋ฅผ LLM์— ์ž…๋ ฅํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์–ป๋Š” ๊ณผ์ •์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

ํ”„๋กฌํ”„ํŠธ ํ…œํ”Œ๋ฆฟ ํ™œ์šฉ

Reference

๋žญ์ฒด์ธLangChain ๋…ธํŠธ

LLMChain ๊ฐ์ฒด

  • LLMChain์€ ํŠน์ • PromptTemplate์™€ ์—ฐ๊ฒฐ๋œ ์ฒด์ธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • ์‚ฌ์šฉ๋ฒ•
    • chain = prompt | llm
์ŠคํŠธ๋ฆฌ๋ฐ(Streaming)
  • ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ์ „์†กํ•˜๋Š” ๋Œ€์‹ , ์ผ์ •ํ•œ ์†๋„๋กœ ์—ฐ์†์ ์œผ๋กœ ์ „์†กํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹
  • ํ† ํฐ๋ณ„(๊ธ€์ž ํ•˜๋‚˜์”ฉ) ์ถœ๋ ฅํ•œ๋‹ค๋Š” ๋œป
  • ์ŠคํŠธ๋ฆฌ๋ฐ ์˜ต์…˜์€ ์งˆ์˜์— ๋Œ€ํ•œ ๋‹ต๋ณ€์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ›์„ ๋•Œ ์œ ์šฉํ•˜๋‹ค.
  • ์žฅ์ 
    1. ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ: ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜์ž๋งˆ์ž ์ฆ‰์‹œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ๋น ๋ฅธ ๋ฐ˜์‘์ด ์š”๊ตฌ๋˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ธ์…˜์— ์ ํ•ฉํ•˜๋‹ค.
    2. ๋ฆฌ์†Œ์Šค ํšจ์œจ์„ฑ: ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ณ  ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ์™€ CPU ๋ฆฌ์†Œ์Šค๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    3. ์—ฐ์†์  ๋ถ„์„: ์ง€์†์ ์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์–ด, ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ๋Œ€์‘์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

2. Output Parsers(์ถœ๋ ฅ ํŒŒ์„œ)

Reference

๋žญ์ฒด์ธLangChain ๋…ธํŠธ ์ถœ๋ ฅํŒŒ์„œ(Output Parsers)

Output Parser

LangChain์˜ Output Parser๋Š” ์–ธ์–ด๋ชจ๋ธ(LLM)์˜ ์ถœ๋ ฅ์„ ๋” ์œ ์šฉํ•˜๊ณ  ๊ตฌ์กฐํ™”๋œ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ค‘์š”ํ•œ ์š”์†Œ์ด๋‹ค.

์—ญํ• 

  • LLM์˜ ์ถœ๋ ฅ์„ ๋ฐ›์•„ ๋” ์ ํ•ฉํ•œ ํ˜•์‹์œผ๋กœ ์ „ํ™˜
  • ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ์— ๋งค์šฐ ์œ ์šฉ
  • LangChain ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ์ถœ๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•˜๊ณ  ์ฒ˜๋ฆฌ

์ฃผ์š” ํŠน์ง•

  • ๋‹ค์–‘์„ฑ: LangChain์€ ๋งŽ์€ ์ข…๋ฅ˜์˜ ์ถœ๋ ฅ ํŒŒ์„œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • ์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์›: ๋งŽ์€ ์ถœ๋ ฅ ํŒŒ์„œ๋“ค์€ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์ง€์›ํ•œ๋‹ค.
  • ํ™•์žฅ์„ฑ: ์ตœ์†Œํ•œ์˜ ๋ชจ๋“ˆ๋ถ€ํ„ฐ ๋ณต์žกํ•œ ๋ชจ๋“ˆ๊นŒ์ง€ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

Output Parser์˜ ์ด์ 

  1. ๊ตฌ์กฐํ™”: LLM์˜ ์ž์œ  ํ˜•์‹ ํ…์ŠคํŠธ ์ถœ๋ ฅ์„ ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.
  2. ์ผ๊ด€์„ฑ: ์ถœ๋ ฅ ํ˜•์‹์„ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€ํ•˜์—ฌ ํ›„์† ์ฒ˜๋ฆฌ๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ํ•œ๋‹ค.
  3. ์œ ์—ฐ์„ฑ: ๋‹ค์–‘ํ•œ ์ถœ๋ ฅ ํ˜•์‹(JSON, List, Dictionary๋“ฑ)์œผ๋กœ ๋ณ€ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

1. PydanticOutputParser

์–ธ์–ด ๋ชจ๋ธ์˜ ์ถœ๋ ฅ์„ ๋” ๊ตฌ์กฐํ™”๋œ ์ •๋ณด๋กœ ๋ณ€ํ™˜ ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ํด๋ž˜์Šค์ด๋‹ค.
๋‹จ์ˆœ ํ…์ŠคํŠธ ํ˜•ํƒœ์˜ ์‘๋‹ต ๋Œ€์‹ , ์‚ฌ์šฉ์ž๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ์ •๋ณด๋ฅผ ๋ช…ํ™•ํ•˜๊ณ  ์ฒด๊ณ„์ ์ธ ํ˜•ํƒœ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•ต์‹ฌ ๋ฉ”์„œ๋“œ

  • get_format_instructions(): ์–ธ์–ด ๋ชจ๋ธ์ด ์ถœ๋ ฅํ•ด์•ผ ํ•  ์ •๋ณด์˜ ํ˜•์‹์„ ์ •์˜ํ•˜๋Š” ์ง€์นจ(instruction)์„ ์ œ๊ณตํ•œ๋‹ค.
    • ์˜ˆ์‹œ: ์–ธ์–ด ๋ชจ๋ธ์ด ์ถœ๋ ฅํ•ด์•ผ ํ•  ๋ฐ์ดํ„ฐ์˜ ํ•„๋“œ์™€ ๊ทธ ํ˜•ํƒœ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ์ง€์นจ์„ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ ์„ค์ •ํ•˜๋Š” instruction์˜ ์—ญํ• ์ด ์ค‘์š”ํ•˜๋‹ค. ์ด ์ง€์นจ์— ๋”ฐ๋ผ ์–ธ์–ด ๋ชจ๋ธ์€ ์ถœ๋ ฅ์„ ๊ตฌ์กฐํ™”ํ•˜๊ณ , ์ด๋ฅผ ํŠน์ • ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์— ๋งž๊ฒŒ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • parse(): ์–ธ์–ด ๋ชจ๋ธ์˜ ์ถœ๋ ฅ(๋ฌธ์ž์—ด๋กœ ๊ฐ€์ •)์„ ๋ฐ›์•„๋“ค์—ฌ ์ด๋ฅผ ํŠน์ • ๊ตฌ์กฐ๋กœ ๋ถ„์„ํ•˜๊ณ  ๋ณ€ํ™˜ํ•œ๋‹ค. Pydantic์™€ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ์ž…๋ ฅ๋œ ๋ฌธ์ž์—ด์„ ์‚ฌ์ „ ์ •์˜๋œ ์Šคํ‚ค๋งˆ์— ๋”ฐ๋ผ ๊ฒ€์ฆํ•˜๊ณ , ํ•ด๋‹น ์Šคํ‚ค๋งˆ๋ฅผ ๋”ฐ๋ฅด๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

3. Memory

Reference

๋žญ์ฒด์ธLangChain ๋…ธํŠธ ๋ฉ”๋ชจ๋ฆฌ(Memory)

1. ๋Œ€ํ™” ๋ฒ„ํผ ๋ฉ”๋ชจ๋ฆฌ (ConversationBufferMemory)

  • ์ด ๋ฉ”๋ชจ๋ฆฌ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•œ ๋‹ค์Œ ๋ณ€์ˆ˜์— ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

์˜ˆ์ œ

from langchain.memory import ConversationBufferMemory
memory = 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/AsyncDescription
invoke/ainvoke์ž…๋ ฅ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
batch/abatch๋ฐ˜๋ณต๋˜๋Š” ์ž…๋ ฅ์„ ๋ฆฌ์ŠคํŠธ๋กœ ์ž…๋ ฅํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.
stream/astreamchunk๋งˆ๋‹ค ์ถœ๋ ฅ๋˜๊ฒŒ ํ•œ๋‹ค.
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_parser

invoke/ 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)

Runnable

์ž…๋ ฅ๊ฐ’๋“ค์— ๋Œ€ํ•œ ๋ณ€ํ˜•์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์œ ์—ฐํ•˜๊ฒŒ ์ปค์Šคํ…€ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋“ค์ด๋‹ค.

์ปค์Šคํ…€ ์ฒด์ธ์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด Runnable ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•œ๋‹ค.

chat models,LLM,outputparser,retriever,prompt template๋“ฑ์„ ํฌํ•จํ•œ ๋งŽ์€ langchain์ปดํฌ๋„ŒํŠธ๊ฐ€ Runnableํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•œ๋‹ค.

์ด๋Š” ํ‘œ์ค€์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ  ์ปค์Šคํ…€ ์ฒด์ธ๋„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์Œ์„ ํฌํ•จํ•œ๋‹ค.

  • stream: ์‘๋‹ต ์ฒญํฌ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ถœ๋ ฅ
  • invoke: ์ž…๋ ฅ์„ ๋ฐ›์•„ ์ฒด์ธ์„ ํ˜ธ์ถœ
  • batch: ์ž…๋ ฅ ๋ชฉ๋ก์œผ๋กœ ์ฒด์ธ์„ ํ˜ธ์ถœ
FunctionDescription
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. ๋ถ€์‚ฐ ํƒ€์›Œ - ๋ถ€์‚ฐ์˜ ๋žœ๋“œ๋งˆํฌ๋กœ์„œ, ๋ถ€์‚ฐ ์‹œ๋‚ด์™€ ํ•ด์•ˆ๋„๋กœ๋ฅผ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ „๋ง๋Œ€์™€ ์•ผ๊ฒฝ์ด ์œ ๋ช…ํ•˜๋‹ค.'}