diff --git a/units/en/unit2/langgraph/when_to_use_langgraph.mdx b/units/en/unit2/langgraph/when_to_use_langgraph.mdx index 28e1d850..2123e849 100644 --- a/units/en/unit2/langgraph/when_to_use_langgraph.mdx +++ b/units/en/unit2/langgraph/when_to_use_langgraph.mdx @@ -1,4 +1,4 @@ -# What is `LangGraph`? +# What is `LangGraph`? [[what-is-langgraph]] `LangGraph` is a framework developed by [LangChain](https://www.langchain.com/) **to manage the control flow of applications that integrate an LLM**. diff --git a/units/ko/_toctree.yml b/units/ko/_toctree.yml index 124595ce..7a7e6da3 100644 --- a/units/ko/_toctree.yml +++ b/units/ko/_toctree.yml @@ -1,40 +1,106 @@ - title: Unit 0. Welcome to the course sections: - local: unit0/introduction - title: Welcome to the course ๐Ÿค— + title: AI ์—์ด์ „ํŠธ ์ฝ”์Šค์— ์˜ค์‹ ๊ฑธ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค ๐Ÿค— - local: unit0/onboarding - title: Onboarding + title: ์˜จ๋ณด๋”ฉ(Onboarding), ์ฒซ ๊ฑธ์Œ ๋‚ด๋”›๊ธฐ โ›ต - local: unit0/discord101 - title: (Optional) Discord 101 + title: (์„ ํƒ) Discord 101 - title: Unit 1. Introduction to Agents sections: - local: unit1/introduction - title: Introduction + title: ์—์ด์ „ํŠธ ์†Œ๊ฐœ - local: unit1/what-are-agents - title: What is an Agent? + title: ์—์ด์ „ํŠธ๋ž€? - local: unit1/quiz1 title: Quick Quiz 1 - local: unit1/what-are-llms - title: What are LLMs? + title: LLM์ด๋ž€? - local: unit1/messages-and-special-tokens - title: Messages and Special Tokens + title: ๋ฉ”์„ธ์ง€์™€ ํŠน์ˆ˜ ํ† ํฐ - local: unit1/tools - title: What are Tools? + title: ๋„๊ตฌ๋ž€? - local: unit1/quiz2 title: Quick Quiz 2 - local: unit1/agent-steps-and-structure - title: Understanding AI Agents through the Thought-Action-Observation Cycle + title: ์‚ฌ๊ณ -ํ–‰๋™-๊ด€์ฐฐ ์ฃผ๊ธฐ๋ฅผ ํ†ตํ•ด AI ์—์ด์ „ํŠธ ์ดํ•ดํ•˜๊ธฐ - local: unit1/thoughts - title: Thought, Internal Reasoning and the Re-Act Approach + title: ์‚ฌ๊ณ , AI ์—์ด์ „ํŠธ์˜ ๋‚ด๋ถ€ ์ถ”๋ก ๊ณผ Re-Act ๋ฐฉ์‹ - local: unit1/actions - title: Actions, Enabling the Agent to Engage with Its Environment + title: ์•ก์…˜, ์—์ด์ „ํŠธ๊ฐ€ ํ™˜๊ฒฝ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ธฐ - local: unit1/observations - title: Observe, Integrating Feedback to Reflect and Adapt + title: ๊ด€์ฐฐ, ํ”ผ๋“œ๋ฐฑ์„ ํ†ตํ•ฉํ•˜์—ฌ ์„ฑ์ฐฐํ•˜๊ณ  ์ ์‘ํ•˜๊ธฐ - local: unit1/dummy-agent-library - title: Dummy Agent Library + title: ๋”๋ฏธ ์—์ด์ „ํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - local: unit1/tutorial - title: Letโ€™s Create Our First Agent Using smolagents + title: smolagents๋กœ ์ฒซ ๋ฒˆ์งธ ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ - local: unit1/final-quiz title: Unit 1 Final Quiz - local: unit1/conclusion title: Conclusion +- title: Unit 2. Frameworks for AI Agents + sections: + - local: unit2/introduction + title: AI Agent ํ”„๋ ˆ์ž„์›Œํฌ ์†Œ๊ฐœ +- title: Unit 2.1 The smolagents framework + sections: + - local: unit2/smolagents/introduction + title: smolagents ์†Œ๊ฐœ + - local: unit2/smolagents/why_use_smolagents + title: smolagents๋ฅผ ์™œ ์‚ฌ์šฉํ• ๊นŒ? + - local: unit2/smolagents/quiz1 + title: Quick Quiz 1 + - local: unit2/smolagents/code_agents + title: ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ + - local: unit2/smolagents/tool_calling_agents + title: ์•ก์…˜์„ ์ฝ”๋“œ ์กฐ๊ฐ(์ฝ”๋“œ ์Šค๋‹ˆํŽซ)์ด๋‚˜ JSON ๋ธ”๋กญ์œผ๋กœ ์ž‘์„ฑํ•˜๊ธฐ + - local: unit2/smolagents/tools + title: Tool ๋„๊ตฌ ์†Œ๊ฐœ + - local: unit2/smolagents/retrieval_agents + title: ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ + - local: unit2/smolagents/quiz2 + title: Quick Quiz 2 + - local: unit2/smolagents/multi_agent_systems + title: ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ + - local: unit2/smolagents/vision_agents + title: ๋น„์ „๊ณผ ๋ธŒ๋ผ์šฐ์ € ์—์ด์ „ํŠธ + - local: unit2/smolagents/final_quiz + title: ์ตœ์ข… Quiz + - local: unit2/smolagents/conclusion + title: ๊ฒฐ๋ก  +- title: Unit 2.2 The LlamaIndex framework + sections: + - local: unit2/llama-index/introduction + title: LLamaIndex ์†Œ๊ฐœ + - local: unit2/llama-index/llama-hub + title: LlamaHub ์†Œ๊ฐœ + - local: unit2/llama-index/components + title: LlamaIndex์˜ ๊ตฌ์„ฑ ์š”์†Œ + - local: unit2/llama-index/tools + title: LlamaIndex์—์„œ ๋„๊ตฌ ์‚ฌ์šฉํ•˜๊ธฐ + - local: unit2/llama-index/quiz1 + title: Quick Quiz 1 + - local: unit2/llama-index/agents + title: LlamaIndex์—์„œ ์—์ด์ „ํŠธ ์‚ฌ์šฉํ•˜๊ธฐ + - local: unit2/llama-index/workflows + title: LlamaIndex์—์„œ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ ๋งŒ๋“ค๊ธฐ + - local: unit2/llama-index/quiz2 + title: Quick Quiz 2 + - local: unit2/llama-index/conclusion + title: ๊ฒฐ๋ก  +- title: Unit 2.3 The LangGraph framework + sections: + - local: unit2/langgraph/introduction + title: LangGraph ์†Œ๊ฐœ + - local: unit2/langgraph/when_to_use_langgraph + title: LangGraph๋ž€? + - local: unit2/langgraph/building_blocks + title: LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ + - local: unit2/langgraph/first_graph + title: ์ฒซ ๋ฒˆ์งธ LangGraph ๋งŒ๋“ค๊ธฐ + - local: unit2/langgraph/document_analysis_agent + title: Document Analysis Graph + - local: unit2/langgraph/quiz1 + title: Quick Quiz 1 + - local: unit2/langgraph/conclusion + title: Conclusion diff --git a/units/ko/unit2/introduction.mdx b/units/ko/unit2/introduction.mdx new file mode 100644 index 00000000..e19d397c --- /dev/null +++ b/units/ko/unit2/introduction.mdx @@ -0,0 +1,40 @@ +# ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ ์†Œ๊ฐœ + +Thumbnail + +Unit 2์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! **์ด๋ฒˆ ์œ ๋‹›์—์„œ๋Š” ๋‹ค์–‘ํ•œ ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ**๋ฅผ ์‚ดํŽด๋ณด๊ณ , ์ด๋ฅผ ํ™œ์šฉํ•ด ๊ฐ•๋ ฅํ•œ ์—์ด์ „ํŠธ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค. + +์ด๋ฒˆ ์œ ๋‹›์—์„œ ๋‹ค๋ฃฐ ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +- 2.1: [smolagents](https://huggingface.co/docs/smolagents/en/index) +- 2.2: [LlamaIndex](https://www.llamaindex.ai/) +- 2.3: [LangGraph](https://www.langchain.com/langgraph) + +ํ•จ๊ป˜ ์‹œ์ž‘ํ•ด๋ด…์‹œ๋‹ค! ๐Ÿ•ต + +## ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์–ธ์ œ ํ•„์š”ํ• ๊นŒ? + +์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” **LLM ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ๋•Œ ํ•ญ์ƒ ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.** ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ํŠน์ • ์ž‘์—…์„ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ์›Œํฌํ”Œ๋กœ์šฐ์— ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ํ•ญ์ƒ ํ•„์ˆ˜์ ์ธ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. + +๋•Œ๋กœ๋Š” **๋ฏธ๋ฆฌ ์ •์˜๋œ ์›Œํฌํ”Œ๋กœ์šฐ๋งŒ์œผ๋กœ๋„** ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ์ถฉ๋ถ„ํžˆ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ตณ์ด ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ ๊ตฌ์กฐ๊ฐ€ ๋‹จ์ˆœํ•˜๋‹ค๋ฉด, ํ”„๋กฌํ”„ํŠธ ์ฒด์ด๋‹ ๋“ฑ ์ผ๋ฐ˜ ์ฝ”๋“œ๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊ฐœ๋ฐœ์ž๋Š” **์ถ”์ƒํ™” ์—†์ด ์‹œ์Šคํ…œ์„ ์™„์ „ํžˆ ์ดํ•ดํ•˜๊ณ  ์ œ์–ด**ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ๋ณต์žกํ•ด์ ธ LLM์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ด๋Ÿฌํ•œ ์ถ”์ƒํ™”๊ฐ€ ๋„์›€์ด ๋˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Ÿฌํ•œ ์ ์„ ๊ณ ๋ คํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•จ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +* ์‹œ์Šคํ…œ์„ ๊ตฌ๋™ํ•  *LLM ์—”์ง„* +* ์—์ด์ „ํŠธ๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” *๋„๊ตฌ ๋ชฉ๋ก* +* LLM ์ถœ๋ ฅ์—์„œ ๋„๊ตฌ ํ˜ธ์ถœ์„ ์ถ”์ถœํ•˜๋Š” *ํŒŒ์„œ* +* ํŒŒ์„œ์™€ ๋™๊ธฐํ™”๋œ *์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ* +* *๋ฉ”๋ชจ๋ฆฌ ์‹œ์Šคํ…œ* +* LLM์˜ ์‹ค์ˆ˜๋ฅผ ์ œ์–ดํ•  *์—๋Ÿฌ ๋กœ๊น… ๋ฐ ์žฌ์‹œ๋„ ๋ฉ”์ปค๋‹ˆ์ฆ˜* + +์ด๋Ÿฌํ•œ ์ฃผ์ œ๋“ค์ด ๊ฐ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ๋˜๋Š”์ง€, `smolagents`, `LlamaIndex`, `LangGraph`๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. + +## ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ๋ณ„ ์œ ๋‹› ์•ˆ๋‚ด + +| ํ”„๋ ˆ์ž„์›Œํฌ | ์„ค๋ช… | ์œ ๋‹› ์ €์ž | +|------------|----------------|----------------| +| [smolagents](./smolagents/introduction) | Hugging Face์—์„œ ๊ฐœ๋ฐœํ•œ ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ | Sergio Paniego - [HF](https://huggingface.co/sergiopaniego) - [X](https://x.com/sergiopaniego) - [Linkedin](https://www.linkedin.com/in/sergio-paniego-blanco) | +| [Llama-Index](./llama-index/introduction) | ์ปจํ…์ŠคํŠธ ์ฆ๊ฐ• AI ์—์ด์ „ํŠธ๋ฅผ ํ”„๋กœ๋•์…˜์— ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋Š” ์—”๋“œ-ํˆฌ-์—”๋“œ ํˆด๋ง | David Berenstein - [HF](https://huggingface.co/davidberenstein1957) - [X](https://x.com/davidberenstei) - [Linkedin](https://www.linkedin.com/in/davidberenstein) | +| [LangGraph](./langgraph/introduction) | ์ƒํƒœ ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์„ ์ง€์›ํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ | Joffrey THOMAS - [HF](https://huggingface.co/Jofthomas) - [X](https://x.com/Jthmas404) - [Linkedin](https://www.linkedin.com/in/joffrey-thomas) | diff --git a/units/ko/unit2/langgraph/building_blocks.mdx b/units/ko/unit2/langgraph/building_blocks.mdx new file mode 100644 index 00000000..f3331332 --- /dev/null +++ b/units/ko/unit2/langgraph/building_blocks.mdx @@ -0,0 +1,127 @@ +# LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ[[building-blocks-of-langgraph]] + +LangGraph๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋ ค๋ฉด ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. LangGraph ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ๋นŒ๋”ฉ ๋ธ”๋ก์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +Building Blocks + +LangGraph ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ **์ง„์ž…์ (entrypoint)**์—์„œ ์‹œ์ž‘ํ•˜๋ฉฐ, ์‹คํ–‰ ํ๋ฆ„์— ๋”ฐ๋ผ ํ•œ ํ•จ์ˆ˜์—์„œ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋กœ ์ด๋™ํ•˜๋‹ค๊ฐ€ END์— ๋„๋‹ฌํ•ฉ๋‹ˆ๋‹ค. + +Application + +## 1. ์ƒํƒœ[[state]] + +**์ƒํƒœ(State)**๋Š” LangGraph์˜ ์ค‘์‹ฌ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ†ตํ•ด ํ๋ฅด๋Š” ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. + +```python +from typing_extensions import TypedDict + +class State(TypedDict): + graph_state: str +``` + +์ƒํƒœ๋Š” **์‚ฌ์šฉ์ž ์ •์˜**์ด๋ฏ€๋กœ, ์˜์‚ฌ๊ฒฐ์ • ๊ณผ์ •์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค๊ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! + +> ๐Ÿ’ก **ํŒ:** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹จ๊ณ„ ๊ฐ„์— ์ถ”์ ํ•ด์•ผ ํ•  ์ •๋ณด๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์‹ ์ค‘ํ•˜๊ฒŒ ๊ณ ๋ฏผํ•˜์„ธ์š”. + +## 2. ๋…ธ๋“œ[[nodes]] + +**๋…ธ๋“œ(Node)**๋Š” ํŒŒ์ด์ฌ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š”: +- ์ƒํƒœ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค +- ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค +- ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค + +```python +def node_1(state): + print("---Node 1---") + return {"graph_state": state['graph_state'] +" I am"} + +def node_2(state): + print("---Node 2---") + return {"graph_state": state['graph_state'] +" happy!"} + +def node_3(state): + print("---Node 3---") + return {"graph_state": state['graph_state'] +" sad!"} +``` + +์˜ˆ๋ฅผ ๋“ค์–ด, ๋…ธ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +- **LLM ํ˜ธ์ถœ**: ํ…์ŠคํŠธ ์ƒ์„ฑ ๋˜๋Š” ์˜์‚ฌ๊ฒฐ์ • +- **ํˆด ํ˜ธ์ถœ**: ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์ƒํ˜ธ์ž‘์šฉ +- **์กฐ๊ฑด๋ถ€ ๋กœ์ง**: ๋‹ค์Œ ๋‹จ๊ณ„ ๊ฒฐ์ • +- **์‚ฌ๋žŒ ๊ฐœ์ž…**: ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๋ฐ›๊ธฐ + +> ๐Ÿ’ก **์ •๋ณด:** START์™€ END์ฒ˜๋Ÿผ ์ „์ฒด ์›Œํฌํ”Œ๋กœ์šฐ์— ํ•„์ˆ˜์ ์ธ ์ผ๋ถ€ ๋…ธ๋“œ๋Š” langGraph์—์„œ ์ง์ ‘ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + + +## 3. ์—ฃ์ง€[[edges]] + +**์—ฃ์ง€(Edge)**๋Š” ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•˜๋ฉฐ, ๊ทธ๋ž˜ํ”„ ๋‚ด์—์„œ ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: + +```python +import random +from typing import Literal + +def decide_mood(state) -> Literal["node_2", "node_3"]: + + # ์ข…์ข… ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•ด ๋‹ค์Œ์— ๋ฐฉ๋ฌธํ•  ๋…ธ๋“œ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค + user_input = state['graph_state'] + + # ์—ฌ๊ธฐ์„œ๋Š” ๋…ธ๋“œ 2, 3 ์‚ฌ์ด๋ฅผ 50:50์œผ๋กœ ๋ถ„๊ธฐํ•ฉ๋‹ˆ๋‹ค + if random.random() < 0.5: + + # 50% ํ™•๋ฅ ๋กœ Node 2 ๋ฐ˜ํ™˜ + return "node_2" + + # 50% ํ™•๋ฅ ๋กœ Node 3 ๋ฐ˜ํ™˜ + return "node_3" +``` + +์—ฃ์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜๋‰ฉ๋‹ˆ๋‹ค: +- **์ง์ ‘(Direct)**: ํ•ญ์ƒ ๋…ธ๋“œ A์—์„œ ๋…ธ๋“œ B๋กœ ์ด๋™ +- **์กฐ๊ฑด๋ถ€(Conditional)**: ํ˜„์žฌ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์„ ํƒ + +## 4. StateGraph[[stategraph]] + +**StateGraph**๋Š” ์ „์ฒด ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋‹ด๋Š” ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค: + +```python +from IPython.display import Image, display +from langgraph.graph import StateGraph, START, END + +# ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ +builder = StateGraph(State) +builder.add_node("node_1", node_1) +builder.add_node("node_2", node_2) +builder.add_node("node_3", node_3) + +# ๋กœ์ง ์ •์˜ +builder.add_edge(START, "node_1") +builder.add_conditional_edges("node_1", decide_mood) +builder.add_edge("node_2", END) +builder.add_edge("node_3", END) + +# ๊ทธ๋ž˜ํ”„ ์ปดํŒŒ์ผ +graph = builder.compile() +``` + +์ด์ œ ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! +```python +# ์‹œ๊ฐํ™” +display(Image(graph.get_graph().draw_mermaid_png())) +``` +Graph Visualization + +ํ•˜์ง€๋งŒ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์‹ค์ œ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค: +```python +graph.invoke({"graph_state" : "Hi, this is Lance."}) +``` +์ถœ๋ ฅ : +``` +---Node 1--- +---Node 3--- +{'graph_state': 'Hi, this is Lance. I am sad!'} +``` + +## ๋‹ค์Œ ๋‹จ๊ณ„[[what's-next]] + +๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๊ฐœ๋…์„ ์‹ค์ œ๋กœ ์ ์šฉํ•˜์—ฌ ์ฒซ ๋ฒˆ์งธ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ทธ๋ž˜ํ”„๋Š” Alfred๊ฐ€ ์ด๋ฉ”์ผ์„ ๋ฐ›์•„ ๋ถ„๋ฅ˜ํ•˜๊ณ , ์ •์ƒ ๋ฉ”์ผ์ด๋ผ๋ฉด ์ž„์‹œ ๋‹ต์žฅ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. diff --git a/units/ko/unit2/langgraph/conclusion.mdx b/units/ko/unit2/langgraph/conclusion.mdx new file mode 100644 index 00000000..8bc1b483 --- /dev/null +++ b/units/ko/unit2/langgraph/conclusion.mdx @@ -0,0 +1,20 @@ +# ๊ฒฐ๋ก [[conclusion]] + +2๋‹จ์›์˜ LangGraph ๋ชจ๋“ˆ์„ ์™„๋ฃŒํ•˜์‹  ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿฅณ + +์ด์ œ LangGraph๋กœ ๊ตฌ์กฐํ™”๋œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋งˆ์Šคํ„ฐํ•˜์…จ์œผ๋ฉฐ, ์ด๋ฅผ ์‹ค์ œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๋ชจ๋“ˆ์€ LangGraph ์—ฌ์ •์˜ ์‹œ์ž‘์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. ์‹ฌํ™” ์ฃผ์ œ๋ฅผ ์›ํ•˜์‹œ๋Š” ๋ถ„๋“ค์„ ์œ„ํ•ด ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค: + +- [๊ณต์‹ LangGraph ๋ฌธ์„œ](https://github.com/langchain-ai/langgraph) ํƒ์ƒ‰ +- LangChain ์•„์นด๋ฐ๋ฏธ์˜ ์ข…ํ•ฉ์ ์ธ [LangGraph ์†Œ๊ฐœ](https://academy.langchain.com/courses/intro-to-langgraph) ๊ฐ•์˜ ์ˆ˜๊ฐ• +- ์ง์ ‘ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”! + +๋‹ค์Œ ๋‹จ์›์—์„œ๋Š” ์‹ค์ œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํƒ๊ตฌํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ์ด๋ก ์„ ๋„˜์–ด ์‹ค์ „์œผ๋กœ ๋‚˜์•„๊ฐˆ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค! + +**์—ฌ๋Ÿฌ๋ถ„์˜ ๊ฐ•์˜์— ๋Œ€ํ•œ ์ƒ๊ฐ๊ณผ ์ œ์•ˆ ์‚ฌํ•ญ๋“ค์„ ๋งค์šฐ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค**. ํ”ผ๋“œ๋ฐฑ์ด ์žˆ์œผ์‹œ๋ฉด ๐Ÿ‘‰ [์ด ์–‘์‹](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog)์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”! + +### ์กด๊ฒฝํ•˜๋Š” ์—ฌ๋Ÿฌ๋ถ„! ๐ŸŽฉ๐Ÿฆ‡ +๋ฐฐ์›€์„ ๋ฉˆ์ถ”์ง€ ๋งˆ์„ธ์š” ๐Ÿค— + +-์•Œํ”„๋ ˆ๋“œ- \ No newline at end of file diff --git a/units/ko/unit2/langgraph/document_analysis_agent.mdx b/units/ko/unit2/langgraph/document_analysis_agent.mdx new file mode 100644 index 00000000..5a7a8b39 --- /dev/null +++ b/units/ko/unit2/langgraph/document_analysis_agent.mdx @@ -0,0 +1,267 @@ +# ๋ฌธ์„œ ๋ถ„์„ ๊ทธ๋ž˜ํ”„[[document-analysis-graph]] + +์ € ์•Œํ”„๋ ˆ๋“œ๋Š” Mr.์›จ์ธ๋‹˜์˜ ์‹ ๋ขฐ๋ฐ›๋Š” ์ง‘์‚ฌ๋กœ์„œ, ๊ทธ๋ถ„์˜ ๋‹ค์–‘ํ•œ ๋ฌธ์„œ ์—…๋ฌด๋ฅผ ์–ด๋–ป๊ฒŒ ์ง€์›ํ• ์ง€ ๊ธฐ๋กํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฐ€ ๋ฐค ํ™œ๋™์„ ํ•˜๋Ÿฌ ๋‚˜๊ฐ„ ๋™์•ˆ, ์ €๋Š” ๋ชจ๋“  ์„œ๋ฅ˜, ํ›ˆ๋ จ ์ผ์ •, ์˜์–‘ ๊ณ„ํš์„ ๋ถ„์„ํ•˜๊ณ  ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ถ„์ด ์™ธ์ถœํ•˜๊ธฐ ์ „, ์ด๋ฒˆ ์ฃผ ํ›ˆ๋ จ ํ”„๋กœ๊ทธ๋žจ์ด ์ ํžŒ ์ชฝ์ง€๋ฅผ ๋‚จ๊ธฐ์…จ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ชฝ์ง€๋ฅผ ๋ณด๊ณ  ์ €๋Š” ๋‚ด์ผ ์‹์‚ฌ๋ฅผ ์œ„ํ•œ **๋ฉ”๋‰ด**๋ฅผ ์ง์ ‘ ์งœ๊ธฐ๋กœ ํ–ˆ์ฃ . + +์•ž์œผ๋กœ๋„ ์ด๋Ÿฐ ์ผ์ด ์žˆ์„ ๋•Œ๋ฅผ ๋Œ€๋น„ํ•ด, LangGraph๋ฅผ ํ™œ์šฉํ•ด ์›จ์ธ๋‹˜์„ ์œ„ํ•œ ๋ฌธ์„œ ๋ถ„์„ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์ด ์‹œ์Šคํ…œ์€ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +1. ์ด๋ฏธ์ง€ ๋ฌธ์„œ ์ฒ˜๋ฆฌ +2. ๋น„์ „ ๋ชจ๋ธ(๋น„์ „ ์–ธ์–ด ๋ชจ๋ธ)๋กœ ํ…์ŠคํŠธ ์ถ”์ถœ +3. ํ•„์š”์‹œ ๊ณ„์‚ฐ ์ˆ˜ํ–‰(์ผ๋ฐ˜ ํˆด ์‹œ์—ฐ) +4. ๋‚ด์šฉ ๋ถ„์„ ๋ฐ ์š”์•ฝ ์ œ๊ณต +5. ๋ฌธ์„œ ๊ด€๋ จ ํŠน์ • ์ง€์‹œ ์‹คํ–‰ + +## ์ง‘์‚ฌ์˜ ์›Œํฌํ”Œ๋กœ์šฐ[[the-butler's-workflow]] + +๋งŒ๋“ค ์›Œํฌํ”Œ๋กœ์šฐ์˜ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +![์ง‘์‚ฌ์˜ ๋ฌธ์„œ ๋ถ„์„ ์›Œํฌํ”Œ๋กœ์šฐ](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/alfred_flow.png) + + +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +## ํ™˜๊ฒฝ ์„ค์ •[[setting-up-the-environment]] + +```python +%pip install langgraph langchain_openai langchain_core +``` +์ž„ํฌํŠธ : +```python +import base64 +from typing import List, TypedDict, Annotated, Optional +from langchain_openai import ChatOpenAI +from langchain_core.messages import AnyMessage, SystemMessage, HumanMessage +from langgraph.graph.message import add_messages +from langgraph.graph import START, StateGraph +from langgraph.prebuilt import ToolNode, tools_condition +from IPython.display import Image, display +``` + +## ์—์ด์ „ํŠธ ์ƒํƒœ ์ •์˜[[defining-agent's-state]] + +์ด ์ƒํƒœ๋Š” ์•ž์„œ ๋ณธ ๊ฒƒ๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. +`AnyMessage`๋Š” Langchain์˜ ๋ฉ”์‹œ์ง€ ํด๋ž˜์Šค์ด๊ณ , `add_messages`๋Š” ์ตœ์‹  ๋ฉ”์‹œ์ง€๋ฅผ ๋ˆ„์ ํ•˜๋Š” ์—ฐ์‚ฐ์ž์ž…๋‹ˆ๋‹ค. + +LangGraph์—์„œ๋Š” ์ƒํƒœ์— ์—ฐ์‚ฐ์ž๋ฅผ ์ถ”๊ฐ€ํ•ด ์ƒํ˜ธ์ž‘์šฉ ๋ฐฉ์‹์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +class AgentState(TypedDict): + # ์ œ๊ณต๋œ ๋ฌธ์„œ + input_file: Optional[str] # ํŒŒ์ผ ๊ฒฝ๋กœ(PDF/PNG) + messages: Annotated[list[AnyMessage], add_messages] +``` + +## ํˆด ์ค€๋น„ํ•˜๊ธฐ[[preparing-tools]] + +```python +vision_llm = ChatOpenAI(model="gpt-4o") + +def extract_text(img_path: str) -> str: + """ + ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ๋ชจ๋ธ๋กœ ์ด๋ฏธ์ง€ ํŒŒ์ผ์—์„œ ํ…์ŠคํŠธ ์ถ”์ถœ + + Wayne ์ฃผ์ธ๋‹˜์€ ์ข…์ข… ํ›ˆ๋ จ ์ผ์ •์ด๋‚˜ ์‹๋‹จ์ด ์ ํžŒ ์ชฝ์ง€๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค. + ์ด ๊ธฐ๋Šฅ์œผ๋กœ ๋‚ด์šฉ์„ ์ œ๋Œ€๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + """ + all_text = "" + try: + # ์ด๋ฏธ์ง€๋ฅผ ์ฝ๊ณ  base64๋กœ ์ธ์ฝ”๋”ฉ + with open(img_path, "rb") as image_file: + image_bytes = image_file.read() + + image_base64 = base64.b64encode(image_bytes).decode("utf-8") + + # base64 ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•œ ํ”„๋กฌํ”„ํŠธ ์ค€๋น„ + message = [ + HumanMessage( + content=[ + { + "type": "text", + "text": ( + "์ด ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋“  ํ…์ŠคํŠธ๋ฅผ ์ถ”์ถœํ•˜์„ธ์š”. ์„ค๋ช… ์—†์ด ์ถ”์ถœ๋œ ํ…์ŠคํŠธ๋งŒ ๋ฐ˜ํ™˜ํ•˜์„ธ์š”." + ), + }, + { + "type": "image_url", + "image_url": { + "url": f"data:image/png;base64,{image_base64}" + }, + }, + ] + ) + ] + + # ๋น„์ „ ๋ชจ๋ธ ํ˜ธ์ถœ + response = vision_llm.invoke(message) + + # ์ถ”์ถœ๋œ ํ…์ŠคํŠธ ์ถ”๊ฐ€ + all_text += response.content + "\n\n" + + return all_text.strip() + except Exception as e: + # ์ง‘์‚ฌ๋Š” ์˜ค๋ฅ˜๋„ ์šฐ์•„ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค + error_msg = f"ํ…์ŠคํŠธ ์ถ”์ถœ ์˜ค๋ฅ˜: {str(e)}" + print(error_msg) + return "" + +def divide(a: int, b: int) -> float: + """์ฃผ์ธ๋‹˜์˜ ๊ณ„์‚ฐ ์š”์ฒญ์„ ์œ„ํ•œ ๋‚˜๋ˆ—์…ˆ ํ•จ์ˆ˜""" + return a / b + +# ์ง‘์‚ฌ, ๋„๊ตฌ(tool) ์žฅ์ฐฉ +tools = [ + divide, + extract_text +] + +llm = ChatOpenAI(model="gpt-4o") +llm_with_tools = llm.bind_tools(tools, parallel_tool_calls=False) +``` + +## ๋…ธ๋“œ[[the-nodes]] + +```python +def assistant(state: AgentState): + # ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€ + textual_description_of_tool=""" +extract_text(img_path: str) -> str: + ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ๋ชจ๋ธ๋กœ ์ด๋ฏธ์ง€ ํŒŒ์ผ์—์„œ ํ…์ŠคํŠธ ์ถ”์ถœ + + Args: + img_path: ๋กœ์ปฌ ์ด๋ฏธ์ง€ ํŒŒ์ผ ๊ฒฝ๋กœ(๋ฌธ์ž์—ด) + + Returns: + ๊ฐ ์ด๋ฏธ์ง€์—์„œ ์ถ”์ถœ๋œ ํ…์ŠคํŠธ๋ฅผ ํ•ฉ์นœ ๋ฌธ์ž์—ด +divide(a: int, b: int) -> float: + a๋ฅผ b๋กœ ๋‚˜๋ˆ” +""" + image=state["input_file"] + sys_msg = SystemMessage(content=f"๋‹น์‹ ์€ Mr. Wayne๊ณผ ๋ฐฐํŠธ๋งจ์„ ์„ฌ๊ธฐ๋Š” ์นœ์ ˆํ•œ ์ง‘์‚ฌ ์•Œํ”„๋ ˆ๋“œ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ ํˆด๋กœ ๋ฌธ์„œ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ๊ณ„์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:\n{textual_description_of_tool} \n ํ˜„์žฌ ๋กœ๋“œ๋œ ์ด๋ฏธ์ง€๋Š”: {image}") + + return { + "messages": [llm_with_tools.invoke([sys_msg] + state["messages"])], + "input_file": state["input_file"] + } +``` + +## ReAct ํŒจํ„ด: ์ง‘์‚ฌ์˜ ์ง€์› ๋ฐฉ์‹[[the-react-pattern-how-i-assist-mr.-wayne]] + +์ด ์—์ด์ „ํŠธ๋Š” ReAct ํŒจํ„ด(Reason-Act-Observe)์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. + +1. ๋ฌธ์„œ์™€ ์š”์ฒญ์„ **์ดํ•ด(Reason)** +2. ์ ์ ˆํ•œ ํˆด์„ **์‹คํ–‰(Act)** +3. ๊ฒฐ๊ณผ๋ฅผ **๊ด€์ฐฐ(Observe)** +4. ํ•„์š”์‹œ ๋ฐ˜๋ณต + +์•„์ฃผ ๊ฐ„๋‹จํ•œ LangGraph ์—์ด์ „ํŠธ ๊ตฌํ˜„ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. + +```python +# ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ +builder = StateGraph(AgentState) + +# ๋…ธ๋“œ ์ •์˜: ์‹ค์ œ ์ž‘์—…์„ ์ˆ˜ํ–‰ +builder.add_node("assistant", assistant) +builder.add_node("tools", ToolNode(tools)) + +# ์—ฃ์ง€ ์ •์˜: ์ œ์–ด ํ๋ฆ„ ๊ฒฐ์ • +builder.add_edge(START, "assistant") +builder.add_conditional_edges( + "assistant", + # ์ตœ์‹  ๋ฉ”์‹œ์ง€๊ฐ€ ํˆด์„ ํ•„์š”๋กœ ํ•˜๋ฉด tools๋กœ ๋ผ์šฐํŒ… + # ์•„๋‹ˆ๋ฉด ์ง์ ‘ ์‘๋‹ต + tools_condition, +) +builder.add_edge("tools", "assistant") +react_graph = builder.compile() + +# ์ง‘์‚ฌ์˜ ์‚ฌ๊ณ  ๊ณผ์ •์„ ์‹œ๊ฐํ™” +display(Image(react_graph.get_graph(xray=True).draw_mermaid_png())) +``` + +`tools` ๋…ธ๋“œ๋Š” ํˆด ๋ฆฌ์ŠคํŠธ๋ฅผ, `assistant` ๋…ธ๋“œ๋Š” ํˆด์ด ๋ฐ”์ธ๋”ฉ๋œ ๋ชจ๋ธ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. +๊ทธ๋ž˜ํ”„์—๋Š” `assistant`์™€ `tools` ๋…ธ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +`tools_condition` ์—ฃ์ง€๋Š” ๋ชจ๋ธ์ด ํˆด์„ ํ˜ธ์ถœํ•˜๋ฉด tools๋กœ, ์•„๋‹ˆ๋ฉด End๋กœ ํ๋ฆ„์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. + +์ด์ œ ํ•œ ๋‹จ๊ณ„ ๋” ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค: + +`tools` ๋…ธ๋“œ๋ฅผ ๋‹ค์‹œ `assistant`๋กœ ์—ฐ๊ฒฐํ•ด ๋ฃจํ”„๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. + +- `assistant` ๋…ธ๋“œ ์‹คํ–‰ ํ›„, `tools_condition`์ด ๋ชจ๋ธ ์ถœ๋ ฅ์ด ํˆด ํ˜ธ์ถœ์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. +- ํˆด ํ˜ธ์ถœ์ด๋ฉด ํ๋ฆ„์ด `tools` ๋…ธ๋“œ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. +- `tools` ๋…ธ๋“œ๋Š” ๋‹ค์‹œ `assistant`๋กœ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. +- ์ด ๋ฃจํ”„๋Š” ๋ชจ๋ธ์ด ํˆด ํ˜ธ์ถœ์„ ๊ฒฐ์ •ํ•˜๋Š” ํ•œ ๊ณ„์†๋ฉ๋‹ˆ๋‹ค. +- ๋ชจ๋ธ ์‘๋‹ต์ด ํˆด ํ˜ธ์ถœ์ด ์•„๋‹ˆ๋ฉด ํ๋ฆ„์ด END๋กœ ์ด๋™ํ•ด ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค. + +![ReAct ํŒจํ„ด](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/Agent.png) + +## ์ง‘์‚ฌ์˜ ์‹ค์ œ ํ™œ์šฉ ์˜ˆ์‹œ[[the-butler-in-action]] + +### ์˜ˆ์‹œ 1: ๊ฐ„๋‹จํ•œ ๊ณ„์‚ฐ[[example-1-simple-calculations]] + +์•„๋ž˜๋Š” LangGraph์—์„œ ํˆด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. + +```python +messages = [HumanMessage(content="6790์„ 5๋กœ ๋‚˜๋ˆ ์ค˜")] +messages = react_graph.invoke({"messages": messages, "input_file": None}) + +# ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ +for m in messages['messages']: + m.pretty_print() +``` + +๋Œ€ํ™” ์˜ˆ์‹œ: + +``` +Human: 6790์„ 5๋กœ ๋‚˜๋ˆ ์ค˜ + +AI Tool Call: divide(a=6790, b=5) + +Tool Response: 1358.0 + +Alfred: 6790์„ 5๋กœ ๋‚˜๋ˆ„๋ฉด 1358.0์ž…๋‹ˆ๋‹ค. +``` + +### ์˜ˆ์‹œ 2: Wayne ์ฃผ์ธ๋‹˜์˜ ํ›ˆ๋ จ ๋ฌธ์„œ ๋ถ„์„[[example-2-analyzing-master-wayne's-training-documents]] + +์ฃผ์ธ๋‹˜์ด ํ›ˆ๋ จ ๋ฐ ์‹๋‹จ ์ชฝ์ง€๋ฅผ ๋‚จ๊ฒผ์„ ๋•Œ: + +```python +messages = [HumanMessage(content="์ œ๊ณต๋œ ์ด๋ฏธ์ง€์— ์žˆ๋Š” Wayne ์ฃผ์ธ๋‹˜์˜ ์ชฝ์ง€์— ๋”ฐ๋ผ ์ €๋… ๋ฉ”๋‰ด์— ํ•„์š”ํ•œ ์žฌ๋ฃŒ ๋ชฉ๋ก์„ ์•Œ๋ ค์ค˜.")] +messages = react_graph.invoke({"messages": messages, "input_file": "Batman_training_and_meals.png"}) +``` + +๋Œ€ํ™” ์˜ˆ์‹œ: + +``` +Human: ์ œ๊ณต๋œ ์ด๋ฏธ์ง€์— ์žˆ๋Š” Wayne ์ฃผ์ธ๋‹˜์˜ ์ชฝ์ง€์— ๋”ฐ๋ผ ์ €๋… ๋ฉ”๋‰ด์— ํ•„์š”ํ•œ ์žฌ๋ฃŒ ๋ชฉ๋ก์„ ์•Œ๋ ค์ค˜. + +AI Tool Call: extract_text(img_path="Batman_training_and_meals.png") + +Tool Response: [ํ›ˆ๋ จ ์ผ์ • ๋ฐ ๋ฉ”๋‰ด ์„ธ๋ถ€ ์ •๋ณด๊ฐ€ ์ถ”์ถœ๋จ] + +Alfred: ์ €๋… ๋ฉ”๋‰ด๋ฅผ ์œ„ํ•ด ๋‹ค์Œ ์žฌ๋ฃŒ๋ฅผ ๊ตฌ์ž…ํ•˜์„ธ์š”: + +1. ๋ชฉ์ดˆ ์‚ฌ์œก ์†Œ๊ณ ๊ธฐ ๋“ฑ์‹ฌ ์Šคํ…Œ์ดํฌ +2. ์œ ๊ธฐ๋† ์‹œ๊ธˆ์น˜ +3. ํ”ผํ‚ค์š” ๊ณ ์ถ” +4. ๊ฐ์ž(์˜ค๋ธ์— ๊ตฌ์šธ ํ—ˆ๋ธŒ ๊ฐ์ž์šฉ) +5. ํ”ผ์‰ฌ ์˜ค์ผ(2๊ทธ๋žจ) + +์Šคํ…Œ์ดํฌ๋Š” ๋ชฉ์ดˆ ์‚ฌ์œก, ์‹œ๊ธˆ์น˜์™€ ๊ณ ์ถ”๋Š” ์œ ๊ธฐ๋†์œผ๋กœ ์ค€๋น„ํ•˜๋ฉด ์ตœ๊ณ ์˜ ์‹์‚ฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. +``` + +## ํ•ต์‹ฌ ์š”์•ฝ[[key-takeaways]] + +๋‚˜๋งŒ์˜ ๋ฌธ์„œ ๋ถ„์„ ์ง‘์‚ฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ์„ ๊ณ ๋ คํ•˜์„ธ์š”: + +1. **๋ฌธ์„œ ๊ด€๋ จ ์ž‘์—…๋ณ„๋กœ ๋ช…ํ™•ํ•œ ํˆด ์ •์˜** +2. **ํˆด ํ˜ธ์ถœ ๊ฐ„ ๋งฅ๋ฝ ์œ ์ง€๋ฅผ ์œ„ํ•œ ๊ฒฌ๊ณ ํ•œ ์ƒํƒœ ์ถ”์ ๊ธฐ** +3. **ํˆด ์‹คํŒจ ์‹œ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๊ณ ๋ ค** +4. **์ด์ „ ์ƒํ˜ธ์ž‘์šฉ ๋งฅ๋ฝ ์œ ์ง€(add_messages ์—ฐ์‚ฐ์ž ํ™œ์šฉ)** + +์ด ์›์น™์„ ๋”ฐ๋ฅด๋ฉด Wayne ์ €ํƒ์— ์–ด์šธ๋ฆฌ๋Š” ๋ฌธ์„œ ๋ถ„์„ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +*์ด ์„ค๋ช…์ด ๋„์›€์ด ๋˜์—ˆ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ด์ œ ์ฃผ์ธ๋‹˜์˜ ๋งํ† ๋ฅผ ๋‹ค๋ฆผ์งˆํ•˜๋Ÿฌ ๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.* diff --git a/units/ko/unit2/langgraph/first_graph.mdx b/units/ko/unit2/langgraph/first_graph.mdx new file mode 100644 index 00000000..e51d0f43 --- /dev/null +++ b/units/ko/unit2/langgraph/first_graph.mdx @@ -0,0 +1,343 @@ +# ๋‚˜๋งŒ์˜ ์ฒซ LangGraph ๋งŒ๋“ค๊ธฐ[[building-your-first-langgraph]] + +์ด์ œ LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์‹ค์ œ๋กœ ์ ์šฉํ•ด๋ณด๋ฉฐ ์ฒซ ๋ฒˆ์งธ ๊ธฐ๋Šฅ์  ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์•Œํ”„๋ ˆ๋“œ์˜ ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•Œํ”„๋ ˆ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: + +1. ๋“ค์–ด์˜ค๋Š” ์ด๋ฉ”์ผ ์ฝ๊ธฐ +2. ์ŠคํŒธ ๋˜๋Š” ์ •์ƒ ๋ฉ”์ผ๋กœ ๋ถ„๋ฅ˜ํ•˜๊ธฐ +3. ์ •์ƒ ๋ฉ”์ผ์— ๋Œ€ํ•œ ์ž„์‹œ ๋‹ต์žฅ ์ž‘์„ฑํ•˜๊ธฐ +4. ์ •์ƒ ๋ฉ”์ผ์ผ ๊ฒฝ์šฐ Mr. Wayne์—๊ฒŒ ์ •๋ณด ์ „๋‹ฌ(์ถœ๋ ฅ๋งŒ) + +์ด ์˜ˆ์ œ๋Š” LLM ๊ธฐ๋ฐ˜ ์˜์‚ฌ๊ฒฐ์ •์ด ํฌํ•จ๋œ LangGraph ์›Œํฌํ”Œ๋กœ์šฐ ๊ตฌ์กฐํ™” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. (์—ฌ๊ธฐ์„œ๋Š” ๋ณ„๋„์˜ ํˆด์ด ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ Agent๋ผ๊ณ  ๋ถ€๋ฅด์ง„ ์•Š์ง€๋งŒ, LangGraph ํ”„๋ ˆ์ž„์›Œํฌ ํ•™์Šต์— ์ดˆ์ ์„ ๋‘ก๋‹ˆ๋‹ค.) + + +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +## ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค ์›Œํฌํ”Œ๋กœ์šฐ[[our-workflow]] + +์•„๋ž˜์™€ ๊ฐ™์€ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค: +First LangGraph + +## ํ™˜๊ฒฝ ์„ค์ •[[setting-up-our-environment]] + +๋จผ์ € ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค: + +```python +%pip install langgraph langchain_openai +``` + +ํ•„์š”ํ•œ ๋ชจ๋“ˆ์„ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค: + +```python +import os +from typing import TypedDict, List, Dict, Any, Optional +from langgraph.graph import StateGraph, START, END +from langchain_openai import ChatOpenAI +from langchain_core.messages import HumanMessage +``` + +## 1๋‹จ๊ณ„: ์ƒํƒœ(State) ์ •์˜ํ•˜๊ธฐ[[step-1-define-our-state]] + +์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ถ”์ ํ•ด์•ผ ํ•  ์ •๋ณด๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: + +```python +class EmailState(TypedDict): + # ์ฒ˜๋ฆฌ ์ค‘์ธ ์ด๋ฉ”์ผ + email: Dict[str, Any] # ์ œ๋ชฉ, ๋ฐœ์‹ ์ž, ๋ณธ๋ฌธ ๋“ฑ ํฌํ•จ + + # ์ด๋ฉ”์ผ ๋ถ„๋ฅ˜(๋ฌธ์˜, ๋ถˆ๋งŒ ๋“ฑ) + email_category: Optional[str] + + # ์ŠคํŒธ์œผ๋กœ ๋ถ„๋ฅ˜๋œ ์ด์œ  + spam_reason: Optional[str] + + # ๋ถ„์„ ๋ฐ ๊ฒฐ์ • + is_spam: Optional[bool] + + # ๋‹ต์žฅ ์ƒ์„ฑ + email_draft: Optional[str] + + # ์ฒ˜๋ฆฌ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ + messages: List[Dict[str, Any]] # LLM๊ณผ์˜ ๋Œ€ํ™” ์ถ”์  +``` + +> ๐Ÿ’ก **ํŒ:** ์ƒํƒœ๋Š” ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๋ชจ๋‘ ๋‹ด๋˜, ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋น„๋Œ€ํ•ด์ง€์ง€ ์•Š๋„๋ก ํ•˜์„ธ์š”. + +## 2๋‹จ๊ณ„: ๋…ธ๋“œ ์ •์˜ํ•˜๊ธฐ[[step-2-define-our-nodes]] + +์ด์ œ ๊ฐ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ๋‹ด๋‹นํ•  ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค: + +```python +# LLM ์ดˆ๊ธฐํ™” +model = ChatOpenAI(temperature=0) + +def read_email(state: EmailState): + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ ๋“ค์–ด์˜จ ์ด๋ฉ”์ผ์„ ์ฝ๊ณ  ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.""" + email = state["email"] + print(f"์•Œํ”„๋ ˆ๋“œ๊ฐ€ {email['sender']}๋กœ๋ถ€ํ„ฐ ์˜จ ๋ฉ”์ผ(์ œ๋ชฉ: {email['subject']})์„ ์ฒ˜๋ฆฌ ์ค‘์ž…๋‹ˆ๋‹ค.") + return {} + +def classify_email(state: EmailState): + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ LLM์„ ์‚ฌ์šฉํ•ด ์ด๋ฉ”์ผ์„ ์ŠคํŒธ/์ •์ƒ์œผ๋กœ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค.""" + email = state["email"] + prompt = f""" + ์ง‘์‚ฌ ์•Œํ”„๋ ˆ๋“œ๋กœ์„œ, ์ด ์ด๋ฉ”์ผ์„ ๋ถ„์„ํ•ด ์ŠคํŒธ์ธ์ง€ ์ •์ƒ์ธ์ง€ ํŒ๋‹จํ•˜์„ธ์š”. + + ์ด๋ฉ”์ผ: + From: {email['sender']} + Subject: {email['subject']} + Body: {email['body']} + + ๋จผ์ € ์ด ์ด๋ฉ”์ผ์ด ์ŠคํŒธ์ธ์ง€ ํŒ๋‹จํ•˜๊ณ , ์ŠคํŒธ์ด๋ผ๋ฉด ๊ทธ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•˜์„ธ์š”. + ์ •์ƒ ๋ฉ”์ผ์ด๋ผ๋ฉด (๋ฌธ์˜, ๋ถˆ๋งŒ, ๊ฐ์‚ฌ, ์š”์ฒญ ๋“ฑ) ์นดํ…Œ๊ณ ๋ฆฌ๋„ ๋ถ„๋ฅ˜ํ•˜์„ธ์š”. + """ + messages = [HumanMessage(content=prompt)] + response = model.invoke(messages) + response_text = response.content.lower() + is_spam = "spam" in response_text and "not spam" not in response_text + spam_reason = None + if is_spam and "reason:" in response_text: + spam_reason = response_text.split("reason:")[1].strip() + email_category = None + if not is_spam: + categories = ["inquiry", "complaint", "thank you", "request", "information"] + for category in categories: + if category in response_text: + email_category = category + break + new_messages = state.get("messages", []) + [ + {"role": "user", "content": prompt}, + {"role": "assistant", "content": response.content} + ] + return { + "is_spam": is_spam, + "spam_reason": spam_reason, + "email_category": email_category, + "messages": new_messages + } + +def handle_spam(state: EmailState): + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ŠคํŒธ ๋ฉ”์ผ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.""" + print(f"์•Œํ”„๋ ˆ๋“œ๋Š” ์ด ๋ฉ”์ผ์„ ์ŠคํŒธ์œผ๋กœ ๋ถ„๋ฅ˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์œ : {state['spam_reason']}") + print("์ด ๋ฉ”์ผ์€ ์ŠคํŒธ ํด๋”๋กœ ์ด๋™๋˜์—ˆ์Šต๋‹ˆ๋‹ค.") + return {} + +def draft_response(state: EmailState): + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ •์ƒ ๋ฉ”์ผ์— ์ž„์‹œ ๋‹ต์žฅ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.""" + email = state["email"] + category = state["email_category"] or "์ผ๋ฐ˜" + prompt = f""" + ์ง‘์‚ฌ ์•Œํ”„๋ ˆ๋“œ๋กœ์„œ, ์ด ์ด๋ฉ”์ผ์— ์ •์ค‘ํ•œ ์ž„์‹œ ๋‹ต์žฅ์„ ์ž‘์„ฑํ•˜์„ธ์š”. + + ์ด๋ฉ”์ผ: + From: {email['sender']} + Subject: {email['subject']} + Body: {email['body']} + + ์ด ์ด๋ฉ”์ผ์˜ ์นดํ…Œ๊ณ ๋ฆฌ: {category} + + Mr. Hugg๊ฐ€ ๊ฒ€ํ†  ํ›„ ๊ฐœ์ธํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐ„๋‹จํ•˜๊ณ  ์ „๋ฌธ์ ์ธ ๋‹ต์žฅ์„ ์ž‘์„ฑํ•˜์„ธ์š”. + """ + messages = [HumanMessage(content=prompt)] + response = model.invoke(messages) + new_messages = state.get("messages", []) + [ + {"role": "user", "content": prompt}, + {"role": "assistant", "content": response.content} + ] + return { + "email_draft": response.content, + "messages": new_messages + } + +def notify_mr_hugg(state: EmailState): + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ Mr. Hugg์—๊ฒŒ ๋ฉ”์ผ๊ณผ ์ž„์‹œ ๋‹ต์žฅ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.""" + email = state["email"] + print("\n" + "="*50) + print(f"์ฃผ์ธ๋‹˜, {email['sender']}๋กœ๋ถ€ํ„ฐ ๋ฉ”์ผ์ด ๋„์ฐฉํ–ˆ์Šต๋‹ˆ๋‹ค.") + print(f"์ œ๋ชฉ: {email['subject']}") + print(f"์นดํ…Œ๊ณ ๋ฆฌ: {state['email_category']}") + print("\n๊ฒ€ํ† ํ•˜์‹ค ์ž„์‹œ ๋‹ต์žฅ์„ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค:") + print("-"*50) + print(state["email_draft"]) + print("="*50 + "\n") + return {} +``` + +## 3๋‹จ๊ณ„: ๋ถ„๊ธฐ ๋กœ์ง ์ •์˜ํ•˜๊ธฐ[[step-3-define-our-routing-logic]] + +๋ถ„๋ฅ˜ ํ›„ ์–ด๋–ค ๊ฒฝ๋กœ๋กœ ๊ฐˆ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค: + +```python +def route_email(state: EmailState) -> str: + """์ŠคํŒธ ๋ถ„๋ฅ˜ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.""" + if state["is_spam"]: + return "spam" + else: + return "legitimate" +``` + +> ๐Ÿ’ก **์ฐธ๊ณ :** ์ด ๋ผ์šฐํŒ… ํ•จ์ˆ˜๋Š” LangGraph๊ฐ€ ๋ถ„๋ฅ˜ ๋…ธ๋“œ ์ดํ›„ ์–ด๋–ค ์—ฃ์ง€๋ฅผ ๋”ฐ๋ผ๊ฐˆ์ง€ ๊ฒฐ์ •ํ•  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์€ ์กฐ๊ฑด๋ถ€ ์—ฃ์ง€ ๋งคํ•‘์˜ ํ‚ค์™€ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +## 4๋‹จ๊ณ„: StateGraph ์ƒ์„ฑ ๋ฐ ์—ฃ์ง€ ์ •์˜[[step-4-create-the-stategraph-and-define-edges]] + +์ด์ œ ๋ชจ๋“  ๊ฒƒ์„ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค: + +```python +# ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ +email_graph = StateGraph(EmailState) + +# ๋…ธ๋“œ ์ถ”๊ฐ€ +email_graph.add_node("read_email", read_email) +email_graph.add_node("classify_email", classify_email) +email_graph.add_node("handle_spam", handle_spam) +email_graph.add_node("draft_response", draft_response) +email_graph.add_node("notify_mr_hugg", notify_mr_hugg) + +# ์—ฃ์ง€ ์‹œ์ž‘ +email_graph.add_edge(START, "read_email") +# ํ๋ฆ„ ์ •์˜ +email_graph.add_edge("read_email", "classify_email") + +# ๋ถ„๊ธฐ ์ถ”๊ฐ€ +email_graph.add_conditional_edges( + "classify_email", + route_email, + { + "spam": "handle_spam", + "legitimate": "draft_response" + } +) + +# ๋งˆ์ง€๋ง‰ ์—ฃ์ง€ +email_graph.add_edge("handle_spam", END) +email_graph.add_edge("draft_response", "notify_mr_hugg") +email_graph.add_edge("notify_mr_hugg", END) + +# ๊ทธ๋ž˜ํ”„ ์ปดํŒŒ์ผ +compiled_graph = email_graph.compile() +``` + +LangGraph์—์„œ ์ œ๊ณตํ•˜๋Š” ํŠน์ˆ˜ํ•œ `END` ๋…ธ๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ์™„๋ฃŒ๋˜๋Š” ์ง€์ ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. + +## 5๋‹จ๊ณ„: ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ํ•˜๊ธฐ[[step-5-run-the-application]] + +์ •์ƒ ๋ฉ”์ผ๊ณผ ์ŠคํŒธ ๋ฉ”์ผ๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ด…๋‹ˆ๋‹ค: + +```python +# ์ •์ƒ ๋ฉ”์ผ ์˜ˆ์‹œ +legitimate_email = { + "sender": "john.smith@example.com", + "subject": "์„œ๋น„์Šค ๋ฌธ์˜", + "body": "์•ˆ๋…•ํ•˜์„ธ์š” Mr. Hugg, ๋™๋ฃŒ์˜ ์ถ”์ฒœ์œผ๋กœ ์—ฐ๋ฝ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์ปจ์„คํŒ… ์„œ๋น„์Šค์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์ฃผ์— ํ†ตํ™” ๊ฐ€๋Šฅํ• ๊นŒ์š”? ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค, John Smith" +} + +# ์ŠคํŒธ ๋ฉ”์ผ ์˜ˆ์‹œ +spam_email = { + "sender": "winner@lottery-intl.com", + "subject": "๋‹น์‹ ์€ $5,000,000์— ๋‹น์ฒจ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!!!", + "body": "์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๊ตญ์ œ ๋ณต๊ถŒ์— ๋‹น์ฒจ๋˜์…จ์Šต๋‹ˆ๋‹ค! ์ƒ๊ธˆ์„ ๋ฐ›์œผ์‹œ๋ ค๋ฉด ์€ํ–‰ ์ •๋ณด์™€ ์ˆ˜์ˆ˜๋ฃŒ $100์„ ๋ณด๋‚ด์ฃผ์„ธ์š”." +} + +# ์ •์ƒ ๋ฉ”์ผ ์ฒ˜๋ฆฌ +print("\n์ •์ƒ ๋ฉ”์ผ ์ฒ˜๋ฆฌ ์ค‘...") +legitimate_result = compiled_graph.invoke({ + "email": legitimate_email, + "is_spam": None, + "spam_reason": None, + "email_category": None, + "email_draft": None, + "messages": [] +}) + +# ์ŠคํŒธ ๋ฉ”์ผ ์ฒ˜๋ฆฌ +print("\n์ŠคํŒธ ๋ฉ”์ผ ์ฒ˜๋ฆฌ ์ค‘...") +spam_result = compiled_graph.invoke({ + "email": spam_email, + "is_spam": None, + "spam_reason": None, + "email_category": None, + "email_draft": None, + "messages": [] +}) +``` + +## 6๋‹จ๊ณ„: Langfuse๋กœ ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ ๊ด€์ฐฐํ•˜๊ธฐ ๐Ÿ“ก[[step-6-inspecting-our-mail-sorting-agent-with-langfuse]] + +์•Œํ”„๋ ˆ๋“œ๋Š” ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ๋ฅผ ๋‹ค๋“ฌ์œผ๋ฉด์„œ ๋””๋ฒ„๊น…์— ์ง€์ณ๊ฐ‘๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ  ์ถ”์ ์ด ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ถ๊ทน์˜ ์ŠคํŒธ ๊ฐ์ง€ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ํ”„๋กœ๋•์…˜์— ๋ฐฐํฌํ•˜๋ ค๋ฉด, ํ–ฅํ›„ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๋ถ„์„์„ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ์ถ”์  ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ฅผ ์œ„ํ•ด ์•Œํ”„๋ ˆ๋“œ๋Š” [Langfuse](https://langfuse.com/)์™€ ๊ฐ™์€ ๊ด€์ฐฐ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋จผ์ € Langfuse๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค: +```python +%pip install -q langfuse +``` + +LangChain๋„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค(Langfuse ์‚ฌ์šฉ ์‹œ ํ•„์š”): +```python +%pip install langchain +``` + +Langfuse API ํ‚ค์™€ ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ๋ฅผ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. [Langfuse Cloud](https://cloud.langfuse.com) ๊ฐ€์ž… ๋˜๋Š” [์…€ํ”„ ํ˜ธ์ŠคํŒ…](https://langfuse.com/self-hosting)์œผ๋กœ ํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +import os +# ํ”„๋กœ์ ํŠธ ์„ค์ • ํŽ˜์ด์ง€์—์„œ ํ‚ค๋ฅผ ํ™•์ธํ•˜์„ธ์š”: https://cloud.langfuse.com +os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..." +os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..." +os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # ๐Ÿ‡ช๐Ÿ‡บ EU ๋ฆฌ์ „ +# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # ๐Ÿ‡บ๐Ÿ‡ธ US ๋ฆฌ์ „ +``` + +[Langfuse `callback_handler`](https://langfuse.com/docs/integrations/langchain/tracing#add-langfuse-to-your-langchain-application)๋ฅผ ์„ค์ •ํ•˜๊ณ , ๊ทธ๋ž˜ํ”„ ํ˜ธ์ถœ ์‹œ `config={"callbacks": [langfuse_handler]}`๋กœ ์ธ์ŠคํŠธ๋ฃจ๋จผํŠธํ•ฉ๋‹ˆ๋‹ค. + +```python +from langfuse.langchain import CallbackHandler + +# LangGraph/Langchain์šฉ Langfuse CallbackHandler ์ดˆ๊ธฐํ™”(์ถ”์ ์šฉ) +langfuse_handler = CallbackHandler() + +# ์ •์ƒ ๋ฉ”์ผ ์ฒ˜๋ฆฌ +legitimate_result = compiled_graph.invoke( + input={"email": legitimate_email, "is_spam": None, "spam_reason": None, "email_category": None, "draft_response": None, "messages": []}, + config={"callbacks": [langfuse_handler]} +) +``` + +์ด์ œ ์•Œํ”„๋ ˆ๋“œ๋Š” LangGraph์˜ ์‹คํ–‰ ๋‚ด์—ญ์„ Langfuse์— ๊ธฐ๋กํ•˜์—ฌ ์—์ด์ „ํŠธ์˜ ๋™์ž‘์„ ์™„์ „ํžˆ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ์จ ์ด์ „ ์‹คํ–‰์„ ๋‹ค์‹œ ์‚ดํŽด๋ณด๊ณ  ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ๋ฅผ ๋”์šฑ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +![Langfuse ์˜ˆ์‹œ ํŠธ๋ ˆ์ด์Šค](https://langfuse.com/images/cookbook/huggingface-agent-course/langgraph-trace-legit.png) + +_[์ •์ƒ ๋ฉ”์ผ ํŠธ๋ ˆ์ด์Šค ๊ณต๊ฐœ ๋งํฌ](https://cloud.langfuse.com/project/cloramnkj0002jz088vzn1ja4/traces/f5d6d72e-20af-4357-b232-af44c3728a7b?timestamp=2025-03-17T10%3A13%3A28.413Z&observation=6997ba69-043f-4f77-9445-700a033afba1)_ + +## ๊ทธ๋ž˜ํ”„ ์‹œ๊ฐํ™”[[visualizing-our-graph]] + +LangGraph๋Š” ์›Œํฌํ”Œ๋กœ์šฐ ๊ตฌ์กฐ๋ฅผ ์‹œ๊ฐํ™”ํ•˜์—ฌ ์ดํ•ด์™€ ๋””๋ฒ„๊น…์„ ๋•์Šต๋‹ˆ๋‹ค: + +```python +compiled_graph.get_graph().draw_mermaid_png() +``` +Mail LangGraph + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋…ธ๋“œ ๊ฐ„ ์—ฐ๊ฒฐ๊ณผ ์กฐ๊ฑด๋ถ€ ๊ฒฝ๋กœ๋ฅผ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ๊ฒƒ[[what-we've-built]] + +์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค: + +1. ๋“ค์–ด์˜จ ์ด๋ฉ”์ผ์„ ๋ฐ›์Œ +2. LLM์œผ๋กœ ์ŠคํŒธ/์ •์ƒ ๋ถ„๋ฅ˜ +3. ์ŠคํŒธ์€ ํ๊ธฐ +4. ์ •์ƒ ๋ฉ”์ผ์€ ๋‹ต์žฅ ์ž‘์„ฑ ํ›„ Mr. Hugg์—๊ฒŒ ์ „๋‹ฌ + +์ด์ฒ˜๋Ÿผ LangGraph๋ฅผ ํ™œ์šฉํ•˜๋ฉด LLM ๊ธฐ๋ฐ˜์˜ ๋ณต์žกํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋„ ๋ช…ํ™•ํ•˜๊ณ  ๊ตฌ์กฐ์ ์œผ๋กœ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ํ•ต์‹ฌ ์š”์•ฝ[[key-takeaways]] + +- **์ƒํƒœ ๊ด€๋ฆฌ**: ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ์˜ ๋ชจ๋“  ์ธก๋ฉด์„ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒํƒœ๋ฅผ ์ •์˜ +- **๋…ธ๋“œ ๊ตฌํ˜„**: LLM๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์  ๋…ธ๋“œ ๊ตฌํ˜„ +- **์กฐ๊ฑด๋ถ€ ๋ถ„๊ธฐ**: ์ด๋ฉ”์ผ ๋ถ„๋ฅ˜ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋ถ„๊ธฐ ๋กœ์ง ๊ตฌํ˜„ +- **์ข…๋ฃŒ ์ƒํƒœ**: END ๋…ธ๋“œ๋กœ ์›Œํฌํ”Œ๋กœ์šฐ ์ข…๋ฃŒ ์ง€์  ํ‘œ์‹œ + +## ๋‹ค์Œ ๋‹จ๊ณ„[[what's-next]] + +๋‹ค์Œ ์„น์…˜์—์„œ๋Š” LangGraph์˜ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ(์‚ฌ๋žŒ๊ณผ์˜ ์ƒํ˜ธ์ž‘์šฉ, ๋‹ค์ค‘ ์กฐ๊ฑด ๋ถ„๊ธฐ ๋“ฑ)์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. diff --git a/units/ko/unit2/langgraph/introduction.mdx b/units/ko/unit2/langgraph/introduction.mdx new file mode 100644 index 00000000..a1f9da79 --- /dev/null +++ b/units/ko/unit2/langgraph/introduction.mdx @@ -0,0 +1,32 @@ +# `LangGraph` ์†Œ๊ฐœ[[introduction-to-langgraph]] + +Unit 2.3 Thumbnail + +๋‹ค์Œ ๋‹จ๊ณ„์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ์ด ๋‹จ์›์—์„œ๋Š” ๋ณต์žกํ•œ LLM ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๊ณ  ์กฐ์ •, ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ [`LangGraph`](https://github.com/langchain-ai/langgraph) ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•**์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +`LangGraph`๋Š” ์—์ด์ „ํŠธ์˜ ํ๋ฆ„์„ **์ง์ ‘ ์ œ์–ด**ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•˜์—ฌ **ํ”„๋กœ๋•์…˜ ์ˆ˜์ค€**์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. + +## ๋ชจ๋“ˆ ๊ฐœ์š”[[module-overview]] + +์ด ๋‹จ์›์—์„œ ์—ฌ๋Ÿฌ๋ถ„์€ ๋‹ค์Œ์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: + +### 1๏ธโƒฃ [LangGraph๋ž€ ๋ฌด์—‡์ด๋ฉฐ, ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?](./when_to_use_langgraph) +### 2๏ธโƒฃ [LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ](./building_blocks) +### 3๏ธโƒฃ [๋‚ด ๋ฉ”์ผ์„ ๋Œ€์‹  ๋ถ„๋ฅ˜ํ•ด์ฃผ๋Š” ์ง‘์‚ฌ](./first_graph) +### 4๏ธโƒฃ [์•Œํ”„๋ ˆ๋“œ, ๋ฌธ์„œ ๋ถ„์„ ์—์ด์ „ํŠธ](./document_analysis_agent) +### 5๏ธโƒฃ [ํ€ด์ฆˆ](./quizz1) + + +์ด ์„น์…˜์˜ ์˜ˆ์ œ๋“ค์€ ๊ฐ•๋ ฅํ•œ LLM/VLM ๋ชจ๋ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฝ”์Šค์—์„œ๋Š” langGraph์™€ ๊ฐ€์žฅ ํ˜ธํ™˜์„ฑ์ด ์ข‹์€ GPT-4o API๋ฅผ ์‚ฌ์šฉํ•ด ์‹คํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. + + +์ด ๋‹จ์›์ด ๋๋‚˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ฒฌ๊ณ ํ•˜๊ณ  ์ฒด๊ณ„์ ์ธ, ํ”„๋กœ๋•์…˜์— ๋ฐ”๋กœ ํˆฌ์ž… ๊ฐ€๋Šฅํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค! + +์ด ์„น์…˜์€ LangGraph์˜ ์ž…๋ฌธ ๊ณผ์ •์ด๋‹ˆ, ๋” ์‹ฌํ™”๋œ ์ฃผ์ œ๋Š” ๋ฌด๋ฃŒ LangChain ์•„์นด๋ฐ๋ฏธ ๊ฐ•์˜ [LangGraph ์†Œ๊ฐœ](https://academy.langchain.com/courses/intro-to-langgraph)์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”? + +## ์ฐธ๊ณ  ์ž๋ฃŒ[[resources]] + +- [LangGraph Agents](https://langchain-ai.github.io/langgraph/) - LangGraph ์—์ด์ „ํŠธ ์˜ˆ์ œ +- [LangChain academy](https://academy.langchain.com/courses/intro-to-langgraph) - LangChain์—์„œ ์ œ๊ณตํ•˜๋Š” LangGraph ์ „์ฒด ๊ฐ•์˜ diff --git a/units/ko/unit2/langgraph/quiz1.mdx b/units/ko/unit2/langgraph/quiz1.mdx new file mode 100644 index 00000000..2f8f9bb2 --- /dev/null +++ b/units/ko/unit2/langgraph/quiz1.mdx @@ -0,0 +1,118 @@ +# LangGraph ์ดํ•ด๋„ ํ…Œ์ŠคํŠธ [[test-your-understanding-of-langgraph]] + +`LangGraph`์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ๊ฐ„๋‹จํ•œ ํ€ด์ฆˆ๋กœ ํ™•์ธํ•ด๋ณด์„ธ์š”! ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ํ•ต์‹ฌ ๊ฐœ๋…์„ ๋ณต์Šตํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. + +์ด ํ€ด์ฆˆ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ์ฑ„์ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +### Q1: LangGraph์˜ ์ฃผ์š” ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? [[q1-what-is-the-primary-purpose-of-langgraph]] +LangGraph๊ฐ€ ๋ฌด์—‡์„ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ๋Š”์ง€ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์€? + + + +--- + +### Q2: "์ œ์–ด vs ์ž์œ " ๊ด€์ ์—์„œ LangGraph๋Š” ์–ด๋””์— ์†ํ•˜๋‚˜์š”? [[q2-in-the-context-of-the-control-vs-freedom-trade-off-where-does-langgraph-stand]] +๋‹ค์Œ ์ค‘ LangGraph์˜ ์—์ด์ „ํŠธ ์„ค๊ณ„ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์€? + + + +--- + +### Q3: LangGraph์—์„œ ์ƒํƒœ(State)์˜ ์—ญํ• ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? [[q3-what-role-does-state-play-in-langgraph]] +๋‹ค์Œ ์ค‘ LangGraph์—์„œ ์ƒํƒœ(State)์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ฒƒ์€? + + + +### Q4: LangGraph์—์„œ ์กฐ๊ฑด๋ถ€ ์—ฃ์ง€(Conditional Edge)๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? [[q4-what-is-a-conditional-edge-in-langgraph]] +์กฐ๊ฑด๋ถ€ ์—ฃ์ง€์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ฒƒ์€? + + + +--- + +### Q5: LangGraph๋Š” LLM์˜ ํ™˜๊ฐ(hallucination) ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋‚˜์š”? [[q5-how-does-langgraph-help-address-the-hallucination-problem-in-llms]] +ํ™˜๊ฐ์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ฒƒ์€? + + + +์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ ํ‹€๋ฆฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์•ž์—์„œ ๋‹ค๋ฃฌ ๋‚ด์šฉ๋“ค์„ ๋‹ค์‹œ ๊ฒ€ํ† ํ•ด๋ณด์„ธ์š”. ์ด์ œ LangGraph์˜ ๋” ์‹ฌํ™” ๊ธฐ๋Šฅ์„ ์•Œ์•„๋ณด๊ณ , ๋” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ด…์‹œ๋‹ค. diff --git a/units/ko/unit2/langgraph/when_to_use_langgraph.mdx b/units/ko/unit2/langgraph/when_to_use_langgraph.mdx new file mode 100644 index 00000000..09370de2 --- /dev/null +++ b/units/ko/unit2/langgraph/when_to_use_langgraph.mdx @@ -0,0 +1,68 @@ +# `LangGraph`๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? [[what-is-langgraph]] + +`LangGraph`๋Š” [LangChain](https://www.langchain.com/)์—์„œ ๊ฐœ๋ฐœํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, **LLM์„ ํ†ตํ•ฉํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ œ์–ด ํ๋ฆ„์„ ๊ด€๋ฆฌ**ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. + +## `LangGraph`๋Š” `LangChain`์™€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”? [[is-langgraph-different-from-langchain]] + +LangChain์€ ๋ชจ๋ธ ๋ฐ ๊ธฐํƒ€ ๊ตฌ์„ฑ ์š”์†Œ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ๊ฒ€์ƒ‰, LLM ํ˜ธ์ถœ, ํˆด ํ˜ธ์ถœ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. +LangChain์˜ ํด๋ž˜์Šค๋“ค์€ LangGraph์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. + +๋‘ ํŒจํ‚ค์ง€๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํŒจํ‚ค์ง€์ด๋ฉฐ, ๊ฐ๊ฐ ๋…๋ฆฝ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‹ค์ œ๋กœ ์˜จ๋ผ์ธ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ํŒจํ‚ค์ง€๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. + +## ์–ธ์ œ `LangGraph`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ์š”? [[when-should-i-use-langgraph]] +### ์ œ์–ด vs ์ž์œ  [[control-vs-freedom]] + +AI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค๊ณ„ํ•  ๋•Œ, **์ œ์–ด**์™€ **์ž์œ ** ์‚ฌ์ด์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๊ณ ๋ คํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค: + +- **์ž์œ **๋Š” LLM์ด ๋” ๋งŽ์€ ์ฐฝ์˜์„ฑ์„ ๋ฐœํœ˜ํ•˜๊ณ  ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. +- **์ œ์–ด**๋Š” ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋™์ž‘์„ ๋ณด์žฅํ•˜๊ณ  ์•ˆ์ „ ์žฅ์น˜๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +*smolagents*์˜ ์ฝ”๋“œ ์—์ด์ „ํŠธ๋Š” ๋งค์šฐ ์ž์œ ๋กญ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์•ก์…˜ ๋‹จ๊ณ„์—์„œ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ์ž์ฒด์ ์œผ๋กœ ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋™์ž‘์€ JSON ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ๋ณด๋‹ค ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ต๊ณ  ์ œ์–ดํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค! + +`LangGraph`๋Š” ์ŠคํŽ™ํŠธ๋Ÿผ์˜ ๋ฐ˜๋Œ€ํŽธ์— ์žˆ์œผ๋ฉฐ, ์—์ด์ „ํŠธ ์‹คํ–‰์— **"์ œ์–ด"**๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋น›๋‚ฉ๋‹ˆ๋‹ค. + +LangGraph๋Š” ํŠนํžˆ **์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ์ œ์–ด**๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋”ฐ๋ฅด๋ฉด์„œ๋„ LLM์˜ ํž˜์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํŠน์ • ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ผ๋ จ์˜ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์•ผํ•˜๊ณ , ๊ฐ ๋ถ„๊ธฐ์ ์—์„œ ์˜์‚ฌ๊ฒฐ์ •์ด ๋‚ด๋ ค์ ธ์•ผ ํ•œ๋‹ค๋ฉด, **LangGraph๊ฐ€ ๊ทธ ํ•„์š”ํ•œ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค**. + +์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฌธ์„œ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์— ๋‹ตํ•  ์ˆ˜ ์žˆ๋Š” LLM ์–ด์‹œ์Šคํ„ดํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. + +LLM์ด ํ…์ŠคํŠธ๋ฅผ ๊ฐ€์žฅ ์ž˜ ์ดํ•ดํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์ „์— ๋ณต์žกํ•œ ํ˜•ํƒœ๋“ค(์ฐจํŠธ, ํ‘œ)์„ ํ…์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์„ ํƒ์€ ๋ฌธ์„œ์˜ ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค! + +์ด๋Ÿฌํ•œ ๋ถ„๊ธฐ ํ๋ฆ„์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +Control flow + +> ๐Ÿ’ก **ํŒ:** ์™ผ์ชฝ ๋ถ€๋ถ„์€ ๋„๊ตฌ ํ˜ธ์ถœ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—์ด์ „ํŠธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์€ ์—‘์…€ ํŒŒ์ผ์„ ์ฟผ๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์—์ด์ „ํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.(์˜ˆ: pandas๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์กฐ์ž‘). + +์ด ๋ถ„๊ธฐ๋Š” ๊ฒฐ์ •์ ์ด์ง€๋งŒ, LLM ์ถœ๋ ฅ์— ๋”ฐ๋ผ ์กฐ๊ฑด์ด ์ •ํ•ด์ง€๋Š” ๋น„๊ฒฐ์ •์  ๋ถ„๊ธฐ๋„ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +LangGraph๊ฐ€ ์œ ์šฉํ•œ ๊ฒฝ์šฐ: + +- **๋ช…์‹œ์ ์ธ ํ๋ฆ„ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•œ ๋‹ค๋‹จ๊ณ„ ์ถ”๋ก  ํ”„๋กœ์„ธ์Šค** +- **๋‹จ๊ณ„ ๊ฐ„ ์ƒํƒœ ์ง€์†์ด ํ•„์š”ํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜** +- **๊ฒฐ์ •๋ก ์  ๋กœ์ง๊ณผ AI ๊ธฐ๋Šฅ์„ ๊ฒฐํ•ฉํ•˜๋Š” ์‹œ์Šคํ…œ** +- **์‚ฌ๋žŒ์˜ ๊ฐœ์ž…์ด ํ•„์š”ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ** +- **์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์•„ํ‚คํ…์ฒ˜** + +์š”์•ฝํ•˜์ž๋ฉด, ์ตœ๋Œ€ํ•œ **์‚ฌ๋žŒ์ด ์ง์ ‘** ๊ฐ ๋‹จ๊ณ„์˜ ์ถœ๋ ฅ์— ๋”ฐ๋ผ ์‹คํ–‰ํ•  ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์„ค๊ณ„ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, LangGraph๊ฐ€ ๊ฐ€์žฅ ์ ์ ˆํ•ฉ๋‹ˆ๋‹ค! + +`LangGraph`๋Š” ์ œ ์ƒ๊ฐ์— ์‹œ์žฅ์—์„œ ๊ฐ€์žฅ ํ”„๋กœ๋•์…˜ ์ค€๋น„๊ฐ€ ์ž˜ ๋œ ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. + +## LangGraph๋Š” ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”? [[how-does-langgraph-work]] + +`LangGraph`๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ๋ฆ„์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: + +- **๋…ธ๋“œ(Node)**๋Š” ๊ฐ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค(LLM ํ˜ธ์ถœ, ๋„๊ตฌ ์‚ฌ์šฉ, ์˜์‚ฌ๊ฒฐ์ • ๋“ฑ). +- **์—ฃ์ง€(Edge)**๋Š” ๋‹จ๊ณ„ ๊ฐ„ ๊ฐ€๋Šฅํ•œ ์ „ํ™˜์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. +- **์ƒํƒœ(State)**๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•˜๊ณ  ์œ ์ง€ํ•˜๋ฉฐ ์‹คํ–‰ ์ค‘ ๋…ธ๋“œ ๊ฐ„์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์— ์–ด๋–ค ๋…ธ๋“œ๋ฅผ ์‹คํ–‰ํ• ์ง€ ๊ฒฐ์ •ํ•  ๋•Œ, ํ˜„์žฌ ์ƒํƒœ๊ฐ€ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค. + +์ด๋Ÿฌํ•œ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ๋“ค์€ ๋‹ค์Œ ์žฅ์—์„œ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! + +## ์ผ๋ฐ˜ ํŒŒ์ด์ฌ๊ณผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”? ์™œ LangGraph๊ฐ€ ํ•„์š”ํ•œ๊ฐ€์š”? [[how-is-it-different-from-regular-python-why-do-i-need-langgraph]] + +"๊ทธ๋ƒฅ ์ผ๋ฐ˜ ํŒŒ์ด์ฌ ๋ฌธ๋ฒ•์œผ๋กœ if-else ๋ฌธ ์“ฐ๋ฉด ๋˜์ง€ ์•Š๋‚˜์š”?"๋ผ๊ณ  ๊ถ๊ธˆํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, LangGraph๋Š” ๋ณต์žกํ•œ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์„ ์œ„ํ•ด ์ผ๋ฐ˜ ํŒŒ์ด์ฌ๋ณด๋‹ค **์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žฅ์ **์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. LangGraph ์—†์ด๋„ ๋™์ผํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, LangGraph๋Š” ๋” ์‰ฝ๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ์™€ ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ: ์ƒํƒœ ๊ด€๋ฆฌ, ์‹œ๊ฐํ™”, ๋กœ๊น…(ํŠธ๋ ˆ์ด์Šค), ๋‚ด์žฅํ˜• ์‚ฌ์šฉ์ž ๊ฐœ์ž… ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ ๋“ฑ. diff --git a/units/ko/unit2/llama-index/README.md b/units/ko/unit2/llama-index/README.md new file mode 100644 index 00000000..b28ffd70 --- /dev/null +++ b/units/ko/unit2/llama-index/README.md @@ -0,0 +1,15 @@ +# ๋ชฉ์ฐจ + +์ด LlamaIndex ํ”„๋ ˆ์ž„ ๊ฐœ์š”๋Š” ๊ฐ•์˜ 2๋‹จ์›์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. hf.co/learn์—์„œ LlamaIndex์— ๋Œ€ํ•œ 2๋‹จ์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ‘‰ ์—ฌ๊ธฐ + +| ์ œ๋ชฉ | ์„ค๋ช… | +| --- | --- | +| [์†Œ๊ฐœ](introduction.mdx) | LlamaIndex ์†Œ๊ฐœ | +| [LlamaHub](llama-hub.mdx) | LlamaHub: ํ†ตํ•ฉ, ์—์ด์ „ํŠธ, ํˆด์˜ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ | +| [๊ตฌ์„ฑ ์š”์†Œ](components.mdx) | ๊ตฌ์„ฑ ์š”์†Œ: ์›Œํฌํ”Œ๋กœ์šฐ์˜ ๋นŒ๋”ฉ ๋ธ”๋ก | +| [ํˆด](tools.mdx) | ํˆด: LlamaIndex์—์„œ ํˆด์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ• | +| [ํ€ด์ฆˆ 1](quiz1.mdx) | ํ€ด์ฆˆ 1 | +| [์—์ด์ „ํŠธ](agents.mdx) | ์—์ด์ „ํŠธ: LlamaIndex์—์„œ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ• | +| [์›Œํฌํ”Œ๋กœ์šฐ](workflows.mdx) | ์›Œํฌํ”Œ๋กœ์šฐ: ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰๋˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋งŒ๋“ค์–ด์ง„ ๋‹จ๊ณ„, ์ด๋ฒคํŠธ์˜ ์‹œํ€€์Šค | +| [ํ€ด์ฆˆ 2](quiz2.mdx) | ํ€ด์ฆˆ 2 | +| [๊ฒฐ๋ก ](conclusion.mdx) | ๊ฒฐ๋ก  | diff --git a/units/ko/unit2/llama-index/agents.mdx b/units/ko/unit2/llama-index/agents.mdx new file mode 100644 index 00000000..40e54a00 --- /dev/null +++ b/units/ko/unit2/llama-index/agents.mdx @@ -0,0 +1,160 @@ +# LlamaIndex์—์„œ ์—์ด์ „ํŠธ ์‚ฌ์šฉํ•˜๊ธฐ + +์ด์ „์— ๋‚˜์™”๋˜ ๋„์›€์ด ๋˜๋Š” ์ง‘์‚ฌ ์—์ด์ „ํŠธ ์•Œํ”„๋ ˆ๋“œ๋ฅผ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ์ด์ œ ๊ทธ๊ฐ€ ์—…๊ทธ๋ ˆ์ด๋“œ๋ฅผ ๋ฐ›์„ ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค! +์ด์ œ LlamaIndex์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํˆด๋“ค์„ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์•Œํ”„๋ ˆ๋“œ์—๊ฒŒ ๋” ๋‚˜์€ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ๋“ค์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๊ณ„์†ํ•˜๊ธฐ ์ „์—, ์•Œํ”„๋ ˆ๋“œ ๊ฐ™์€ ์—์ด์ „ํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋‹ค์‹œ ํ•œ๋ฒˆ ์ƒ๊ธฐํ•ด๋ด…์‹œ๋‹ค. +1๋‹จ์›์—์„œ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค: + +> ์—์ด์ „ํŠธ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•œ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด AI ๋ชจ๋ธ์„ ํ™œ์šฉํ•˜์—ฌ ํ™˜๊ฒฝ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๋ก , ๊ณ„ํš, ์•ก์…˜ ์‹คํ–‰(์ข…์ข… ์™ธ๋ถ€ ํˆด์„ ํ†ตํ•ด)์„ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. + +LlamaIndex๋Š” **์„ธ ๊ฐ€์ง€ ์ฃผ์š” ์œ ํ˜•์˜ ์ถ”๋ก  ์—์ด์ „ํŠธ**๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: + +![์—์ด์ „ํŠธ](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/agents.png) + +1. `Function Calling Agents` - ํŠน์ • ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” AI ๋ชจ๋ธ๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. +2. `ReAct Agents` - ์ฑ„ํŒ…์ด๋‚˜ ํ…์ŠคํŠธ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ชจ๋“  AI์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ณต์žกํ•œ ์ถ”๋ก  ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. +3. `Advanced Custom Agents` - ๋” ๋ณต์žกํ•œ ์ž‘์—…๊ณผ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋” ๋ณต์žกํ•œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +๊ณ ๊ธ‰ ์—์ด์ „ํŠธ์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ •๋ณด๋Š” BaseWorkflowAgent์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ์—์ด์ „ํŠธ ์ดˆ๊ธฐํ™” + + +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด, ๋จผ์ € **๊ธฐ๋Šฅ์„ ์ •์˜ํ•˜๋Š” ํ•จ์ˆ˜/ํˆด ์„ธํŠธ**๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ํˆด๋กœ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ๋กœ์„œ๋Š” ์—์ด์ „ํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ํ•จ์ˆ˜ ํ˜ธ์ถœ API(์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ) ๋˜๋Š” ํ‘œ์ค€ ReAct ์—์ด์ „ํŠธ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +ํˆด/ํ•จ์ˆ˜ API๋ฅผ ์ง€์›ํ•˜๋Š” LLM๋“ค์€ ๋น„๊ต์  ์ตœ์‹ ์ด์ง€๋งŒ, ํŠน์ • ํ”„๋กฌํ”„ํŒ…์„ ํ”ผํ•˜๊ณ  ์ œ๊ณต๋œ ์Šคํ‚ค๋งˆ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ LLM์ด ํˆด ํ˜ธ์ถœ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์—ฌ ํˆด์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +ReAct ์—์ด์ „ํŠธ๋Š” ๋˜ํ•œ ๋ณต์žกํ•œ ์ถ”๋ก  ์ž‘์—…์— ๋Šฅ์ˆ™ํ•˜๋ฉฐ, ์ฑ„ํŒ…์ด๋‚˜ ํ…์ŠคํŠธ ์™„์„ฑ ๊ธฐ๋Šฅ์ด ์žˆ๋Š” ๋ชจ๋“  LLM๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์ƒ์„ธํ•˜๋ฉฐ, ์ˆ˜ํ–‰ํ•˜๋Š” ํŠน์ • ์•ก์…˜์˜ ์ถ”๋ก  ๊ณผ์ •์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. + +```python +from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI +from llama_index.core.agent.workflow import AgentWorkflow +from llama_index.core.tools import FunctionTool + +# ์ƒ˜ํ”Œ ํˆด ์ •์˜ -- ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜, ํ•จ์ˆ˜ ์ด๋ฆ„, ๋…์ŠคํŠธ๋ง์ด ๋ชจ๋‘ ํŒŒ์‹ฑ๋œ ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค! +def multiply(a: int, b: int) -> int: + """๋‘ ์ •์ˆ˜๋ฅผ ๊ณฑํ•˜๊ณ  ๊ฒฐ๊ณผ ์ •์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค""" + return a * b + +# llm ์ดˆ๊ธฐํ™” +llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") + +# ์—์ด์ „ํŠธ ์ดˆ๊ธฐํ™” +agent = AgentWorkflow.from_tools_or_functions( + [FunctionTool.from_defaults(multiply)], + llm=llm +) +``` + +**์—์ด์ „ํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ๊ฐ€ ์—†์œผ๋ฉฐ**, ๊ณผ๊ฑฐ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ธฐ์–ตํ•˜๋Š” ๊ฒƒ์€ `Context` ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ํƒ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. +์ด๋Š” ์—ฌ๋Ÿฌ ๋ฉ”์‹œ์ง€์— ๊ฑธ์ณ ๋งฅ๋ฝ์„ ์œ ์ง€ํ•˜๋Š” ์ฑ—๋ด‡์ด๋‚˜ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ง„ํ–‰ ์ƒํ™ฉ์„ ์ถ”์ ํ•ด์•ผ ํ•˜๋Š” ์ž‘์—… ๊ด€๋ฆฌ์ž์ฒ˜๋Ÿผ ์ด์ „ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ธฐ์–ตํ•ด์•ผ ํ•˜๋Š” ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +# ์ƒํƒœ ์—†์Œ +response = await agent.run("2 ๊ณฑํ•˜๊ธฐ 2๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?") + +# ์ƒํƒœ ๊ธฐ์–ต +from llama_index.core.workflow import Context + +ctx = Context(agent) + +response = await agent.run("๋‚ด ์ด๋ฆ„์€ Bob์ž…๋‹ˆ๋‹ค.", ctx=ctx) +response = await agent.run("๋‚ด ์ด๋ฆ„์ด ๋ญ์˜€์ง€?", ctx=ctx) +``` + +`LlamaIndex`์˜ ์—์ด์ „ํŠธ๋“ค์ด Python์˜ `await` ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„๋™๊ธฐ๋ผ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Python์˜ ๋น„๋™๊ธฐ ์ฝ”๋“œ๊ฐ€ ์ฒ˜์Œ์ด๊ฑฐ๋‚˜ ๋ณต์Šต์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, [ํ›Œ๋ฅญํ•œ ๋น„๋™๊ธฐ ๊ฐ€์ด๋“œ](https://docs.llamaindex.ai/en/stable/getting_started/async_python/)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด์ œ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ์œผ๋‹ˆ, ์—์ด์ „ํŠธ์—์„œ ๋” ๋ณต์žกํ•œ ํˆด์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## QueryEngineTools๋กœ RAG ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ + +**์—์ด์ „ํŠธ RAG๋Š” ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์— ๋‹ตํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.** ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์งˆ๋ฌธ์— ๋‹ตํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋„๋ก ๋‹ค์–‘ํ•œ ํˆด์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๋ฌธ์„œ ์œ„์—์„œ ์ž๋™์œผ๋กœ ์งˆ๋ฌธ์— ๋‹ตํ•˜๋Š” ๋Œ€์‹ , ์•Œํ”„๋ ˆ๋“œ๋Š” ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ํˆด์ด๋‚˜ ํ๋ฆ„์„ ์‚ฌ์šฉํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +![์—์ด์ „ํŠธ RAG](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/agentic-rag.png) + +์—์ด์ „ํŠธ๋ฅผ ์œ„ํ•ด **`QueryEngine`์„ ํˆด๋กœ ๋ž˜ํ•‘**ํ•˜๋Š” ๊ฒƒ์€ ์‰ฝ์Šต๋‹ˆ๋‹ค. +์ด๋ ‡๊ฒŒ ํ•  ๋•Œ, **์ด๋ฆ„๊ณผ ์„ค๋ช…์„ ์ •์˜**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. LLM์€ ์ด ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํˆด์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +[๊ตฌ์„ฑ ์š”์†Œ ์„น์…˜](components)์—์„œ ๋งŒ๋“  `QueryEngine`์„ ์‚ฌ์šฉํ•˜์—ฌ `QueryEngineTool`์„ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.core.tools import QueryEngineTool + +query_engine = index.as_query_engine(llm=llm, similarity_top_k=3) # LlamaIndex์˜ ๊ตฌ์„ฑ ์š”์†Œ ์„น์…˜์—์„œ ๋ณด์—ฌ์ง„ ๋Œ€๋กœ + +query_engine_tool = QueryEngineTool.from_defaults( + query_engine=query_engine, + name="name", + description="a specific description", + return_direct=False, +) +query_engine_agent = AgentWorkflow.from_tools_or_functions( + [query_engine_tool], + llm=llm, + system_prompt="You are a helpful assistant that has access to a database containing persona descriptions. " +) +``` + +## ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๋งŒ๋“ค๊ธฐ + +`AgentWorkflow` ํด๋ž˜์Šค๋Š” ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ๋„ ์ง์ ‘ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์—์ด์ „ํŠธ์— ์ด๋ฆ„๊ณผ ์„ค๋ช…์„ ๋ถ€์—ฌํ•จ์œผ๋กœ์จ, ์‹œ์Šคํ…œ์€ ๋‹จ์ผ ํ™œ์„ฑ ๋ฐœํ™”์ž๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ, ๊ฐ ์—์ด์ „ํŠธ๋Š” ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์—๊ฒŒ ์ž‘์—…์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. + +๊ฐ ์—์ด์ „ํŠธ์˜ ๋ฒ”์œ„๋ฅผ ์ขํž˜์œผ๋กœ์จ, ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€์— ์‘๋‹ตํ•  ๋•Œ ์ผ๋ฐ˜์ ์ธ ์ •ํ™•๋„๋ฅผ ๋†’์ด๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +**LlamaIndex์˜ ์—์ด์ „ํŠธ๋“ค์€ ๋” ๋ณต์žกํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ •์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์œ„ํ•ด ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์˜ ํˆด๋กœ๋„ ์ง์ ‘ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.** + +```python +from llama_index.core.agent.workflow import ( + AgentWorkflow, + FunctionAgent, + ReActAgent, +) + +# ๋ช‡ ๊ฐ€์ง€ ํˆด ์ •์˜ +def add(a: int, b: int) -> int: + """๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•ฉ๋‹ˆ๋‹ค.""" + return a + b + + +def subtract(a: int, b: int) -> int: + """๋‘ ์ˆซ์ž๋ฅผ ๋บ๋‹ˆ๋‹ค.""" + return a - b + + +# ์—์ด์ „ํŠธ ์„ค์ • ์ƒ์„ฑ +# ์ฐธ๊ณ : ์—ฌ๊ธฐ์„œ FunctionAgent ๋˜๋Š” ReActAgent๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +# FunctionAgent๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ API๊ฐ€ ์žˆ๋Š” LLM์šฉ์ž…๋‹ˆ๋‹ค. +# ReActAgent๋Š” ๋ชจ๋“  LLM์šฉ์ž…๋‹ˆ๋‹ค. +calculator_agent = ReActAgent( + name="calculator", + description="๊ธฐ๋ณธ ์‚ฐ์ˆ  ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค", + system_prompt="๋‹น์‹ ์€ ๊ณ„์‚ฐ๊ธฐ ์–ด์‹œ์Šคํ„ดํŠธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์ˆ˜ํ•™ ์—ฐ์‚ฐ์— ํˆด์„ ์‚ฌ์šฉํ•˜์„ธ์š”.", + tools=[add, subtract], + llm=llm, +) + +query_agent = ReActAgent( + name="info_lookup", + description="XYZ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค", + system_prompt="XYZ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ตํ•˜๊ธฐ ์œ„ํ•ด RAG ์‹œ์Šคํ…œ์„ ์ฟผ๋ฆฌํ•˜๋Š” ํˆด์„ ์‚ฌ์šฉํ•˜์„ธ์š”", + tools=[query_engine_tool], + llm=llm +) + +# ์›Œํฌํ”Œ๋กœ์šฐ ์ƒ์„ฑ ๋ฐ ์‹คํ–‰ +agent = AgentWorkflow( + agents=[calculator_agent, query_agent], root_agent="calculator" +) + +# ์‹œ์Šคํ…œ ์‹คํ–‰ +response = await agent.run(user_msg="5์™€ 3์„ ๋”ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?") +``` + +์•„์ง ์ถฉ๋ถ„ํžˆ ๋ฐฐ์šฐ์ง€ ๋ชปํ–ˆ๋‚˜์š”? AgentWorkflow ๊ธฐ๋ณธ ์†Œ๊ฐœ ๋˜๋Š” ์—์ด์ „ํŠธ ํ•™์Šต ๊ฐ€์ด๋“œ์—์„œ LlamaIndex์˜ ์—์ด์ „ํŠธ์™€ ํˆด์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ๊ฒƒ์„ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ŠคํŠธ๋ฆฌ๋ฐ, ๋งฅ๋ฝ ์ง๋ ฌํ™”, ์‚ฌ๋žŒ ๊ฐœ์ž…์— ๋Œ€ํ•ด ๋” ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! + +์ด์ œ LlamaIndex์—์„œ ์—์ด์ „ํŠธ์™€ ํˆด์˜ ๊ธฐ๋ณธ์„ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, LlamaIndex๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **๊ตฌ์„ฑ ๊ฐ€๋Šฅํ•˜๊ณ  ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š”** ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/llama-index/components.mdx b/units/ko/unit2/llama-index/components.mdx new file mode 100644 index 00000000..1f7a4d83 --- /dev/null +++ b/units/ko/unit2/llama-index/components.mdx @@ -0,0 +1,241 @@ +# LlamaIndex์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? + +1๋‹จ์›์—์„œ ๋‚˜์™”๋˜ ๋„์›€์ด ๋˜๋Š” ์ง‘์‚ฌ ์—์ด์ „ํŠธ ์•Œํ”„๋ ˆ๋“œ๋ฅผ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? +ํšจ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋ฅผ ๋„์šฐ๋ ค๋ฉด, ์•Œํ”„๋ ˆ๋“œ๋Š” ์šฐ๋ฆฌ์˜ ์š”์ฒญ์„ ์ดํ•ดํ•˜๊ณ  **์ž‘์—…์„ ์™„๋ฃŒํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ๊ด€๋ จ ์ •๋ณด๋ฅผ ์ค€๋น„ํ•˜๊ณ , ์ฐพ๊ณ , ์‚ฌ์šฉ**ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +์ด๊ฒƒ์ด LlamaIndex์˜ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋“ค์–ด์˜ค๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. + +LlamaIndex์—๋Š” ๋งŽ์€ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ์ง€๋งŒ, **์šฐ๋ฆฌ๋Š” ํŠน๋ณ„ํžˆ `QueryEngine` ๊ตฌ์„ฑ ์š”์†Œ์— ์ง‘์ค‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.** +์™œ๋ƒ๊ณ ์š”? ์—์ด์ „ํŠธ์˜ ๊ฒ€์ƒ‰ ์ฆ๊ฐ• ์ƒ์„ฑ(RAG) ํˆด๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +๊ทธ๋Ÿผ RAG๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”? LLM์€ ์ผ๋ฐ˜์ ์ธ ์ง€์‹์„ ๋ฐฐ์šฐ๊ธฐ ์œ„ํ•ด ์—„์ฒญ๋‚œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋กœ ํ›ˆ๋ จ๋ฉ๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๊ด€๋ จ ์žˆ๊ณ  ์ตœ์‹  ๋ฐ์ดํ„ฐ๋กœ ํ›ˆ๋ จ๋˜์ง€ ์•Š์•˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +RAG๋Š” ๋ฐ์ดํ„ฐ์—์„œ ๊ด€๋ จ ์ •๋ณด๋ฅผ ์ฐพ๊ณ  ๊ฒ€์ƒ‰ํ•˜์—ฌ LLM์—๊ฒŒ ์ œ๊ณตํ•จ์œผ๋กœ์จ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. + +![RAG](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/rag.png) + +์ด์ œ ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ƒ๊ฐํ•ด๋ณด์„ธ์š”: + +1. ์•Œํ”„๋ ˆ๋“œ์—๊ฒŒ ์ €๋… ํŒŒํ‹ฐ ๊ณ„ํš์„ ๋„์™€๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค +2. ์•Œํ”„๋ ˆ๋“œ๋Š” ์บ˜๋ฆฐ๋”, ์‹์ด ์„ ํ˜ธ๋„, ๊ณผ๊ฑฐ ์„ฑ๊ณตํ•œ ๋ฉ”๋‰ด๋ฅผ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค +3. `QueryEngine`์ด ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ด ์ •๋ณด๋ฅผ ์ฐพ๊ณ  ์ €๋… ํŒŒํ‹ฐ ๊ณ„ํš์— ์‚ฌ์šฉํ•˜๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค + +์ด๊ฒƒ์ด `QueryEngine`์„ LlamaIndex์—์„œ **์—์ด์ „ํŠธ RAG ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ**๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +์•Œํ”„๋ ˆ๋“œ๊ฐ€ ๋„์›€์ด ๋˜๊ธฐ ์œ„ํ•ด ๊ฐ€์ • ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ๋ชจ๋“  ์—์ด์ „ํŠธ๋Š” ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๊ณ  ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. +`QueryEngine`์€ ์ •ํ™•ํžˆ ์ด ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +์ด์ œ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€์„œ **๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ RAG ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งŒ๋“œ๋Š”** ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ RAG ํŒŒ์ดํ”„๋ผ์ธ ๋งŒ๋“ค๊ธฐ + + +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +RAG ๋‚ด์—๋Š” 5๊ฐ€์ง€ ์ฃผ์š” ๋‹จ๊ณ„๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ๊ตฌ์ถ•ํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋” ํฐ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ผ๋ถ€๊ฐ€ ๋ฉ๋‹ˆ๋‹ค: + +1. **๋กœ๋”ฉ**: ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ณณ(ํ…์ŠคํŠธ ํŒŒ์ผ, PDF, ๋‹ค๋ฅธ ์›น์‚ฌ์ดํŠธ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, API)์—์„œ ์›Œํฌํ”Œ๋กœ์šฐ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. LlamaHub๋Š” ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋ฐฑ ๊ฐœ์˜ ํ†ตํ•ฉ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +2. **์ธ๋ฑ์‹ฑ**: ๋ฐ์ดํ„ฐ๋ฅผ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. LLM์˜ ๊ฒฝ์šฐ, ์ด๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ ์˜๋ฏธ์˜ ์ˆ˜์น˜์  ํ‘œํ˜„์ž…๋‹ˆ๋‹ค. ์ธ๋ฑ์‹ฑ์€ ์†์„ฑ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งฅ๋ฝ์ ์œผ๋กœ ๊ด€๋ จ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ฐพ๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“œ๋Š” ์ˆ˜๋งŽ์€ ๋‹ค๋ฅธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ „๋žต์„ ์˜๋ฏธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +3. **์ €์žฅ**: ๋ฐ์ดํ„ฐ๊ฐ€ ์ธ๋ฑ์‹ฑ๋˜๋ฉด ๋‹ค์‹œ ์ธ๋ฑ์‹ฑํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ์ธ๋ฑ์Šค์™€ ๋‹ค๋ฅธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +4. **์ฟผ๋ฆฌ**: ์ฃผ์–ด์ง„ ์ธ๋ฑ์‹ฑ ์ „๋žต์— ๋Œ€ํ•ด ํ•˜์œ„ ์ฟผ๋ฆฌ, ๋‹ค๋‹จ๊ณ„ ์ฟผ๋ฆฌ, ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ „๋žต์„ ํฌํ•จํ•˜์—ฌ LLM๊ณผ LlamaIndex ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. +5. **ํ‰๊ฐ€**: ๋ชจ๋“  ํ๋ฆ„์—์„œ ์ค‘์š”ํ•œ ๋‹จ๊ณ„๋Š” ๋‹ค๋ฅธ ์ „๋žต์— ๋น„ํ•ด ์–ผ๋งˆ๋‚˜ ํšจ๊ณผ์ ์ธ์ง€, ๋˜๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋งŒ๋“ค ๋•Œ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ‰๊ฐ€๋Š” ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ์‘๋‹ต์ด ์–ผ๋งˆ๋‚˜ ์ •ํ™•ํ•˜๊ณ , ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๊ณ , ๋น ๋ฅธ์ง€์— ๋Œ€ํ•œ ๊ฐ๊ด€์ ์ธ ์ธก์ •์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +๋‹ค์Œ์œผ๋กœ, ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๋‹จ๊ณ„๋“ค์„ ์žฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +### ๋ฌธ์„œ ๋กœ๋”ฉ ๋ฐ ์ž„๋ฒ ๋”ฉ + +์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด, LlamaIndex๋Š” ์ž์ฒด ๋ฐ์ดํ„ฐ ์œ„์—์„œ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, **๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ ์ „์— ๋กœ๋“œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.** +LlamaIndex์— ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค: + +1. `SimpleDirectoryReader`: ๋กœ์ปฌ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ๋‹ค์–‘ํ•œ ํŒŒ์ผ ์œ ํ˜•์„ ์œ„ํ•œ ๋‚ด์žฅ ๋กœ๋”์ž…๋‹ˆ๋‹ค. +2. `LlamaParse`: PDF ํŒŒ์‹ฑ์„ ์œ„ํ•œ LlamaIndex์˜ ๊ณต์‹ ํˆด์ธ LlamaParse๋กœ, ๊ด€๋ฆฌํ˜• API๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. +3. `LlamaHub`: ๋ชจ๋“  ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•œ ์ˆ˜๋ฐฑ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค. + +๋” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์œ„ํ•ด LlamaHub ๋กœ๋”์™€ LlamaParse ํŒŒ์„œ์— ์ต์ˆ™ํ•ด์ง€์„ธ์š”. + +**๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ `SimpleDirectoryReader`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.** +์ด ๋‹ค์žฌ๋‹ค๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ํด๋”์—์„œ ๋‹ค์–‘ํ•œ ํŒŒ์ผ ์œ ํ˜•์„ ๋กœ๋“œํ•˜๊ณ  LlamaIndex๊ฐ€ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ๋Š” `Document` ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`SimpleDirectoryReader`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.core import SimpleDirectoryReader + +reader = SimpleDirectoryReader(input_dir="path/to/directory") +documents = reader.load_data() +``` + +๋ฌธ์„œ๋ฅผ ๋กœ๋“œํ•œ ํ›„, `Node` ๊ฐ์ฒด๋ผ๋Š” ๋” ์ž‘์€ ์กฐ๊ฐ๋“ค๋กœ ๋‚˜๋ˆ„์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +`Node`๋Š” AI๊ฐ€ ์ž‘์—…ํ•˜๊ธฐ ๋” ์‰ฌ์šด ์›๋ณธ ๋ฌธ์„œ์˜ ํ…์ŠคํŠธ ์ฒญํฌ์ผ ๋ฟ์ด๋ฉฐ, ์—ฌ์ „ํžˆ ์›๋ณธ `Document` ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +`IngestionPipeline`์€ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ๋ณ€ํ™˜์„ ํ†ตํ•ด ์ด๋Ÿฌํ•œ ๋…ธ๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. +1. `SentenceSplitter`๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ ๊ฒฝ๊ณ„์—์„œ ๋ฌธ์„œ๋ฅผ ๋ถ„ํ• ํ•˜์—ฌ ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ์ฒญํฌ๋กœ ๋‚˜๋ˆ•๋‹ˆ๋‹ค. +2. `HuggingFaceEmbedding`์€ ๊ฐ ์ฒญํฌ๋ฅผ ์ˆ˜์น˜์  ์ž„๋ฒ ๋”ฉ์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค - AI๊ฐ€ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ์˜๋ฏธ์  ์˜๋ฏธ๋ฅผ ํฌ์ฐฉํ•˜๋Š” ๋ฒกํ„ฐ ํ‘œํ˜„์ž…๋‹ˆ๋‹ค. + +์ด ๊ณผ์ •์€ ๊ฒ€์ƒ‰๊ณผ ๋ถ„์„์— ๋” ์œ ์šฉํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฌธ์„œ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. + +```python +from llama_index.core import Document +from llama_index.embeddings.huggingface import HuggingFaceEmbedding +from llama_index.core.node_parser import SentenceSplitter +from llama_index.core.ingestion import IngestionPipeline + +# ๋ณ€ํ™˜๊ณผ ํ•จ๊ป˜ ํŒŒ์ดํ”„๋ผ์ธ ์ƒ์„ฑ +pipeline = IngestionPipeline( + transformations=[ + SentenceSplitter(chunk_overlap=0), + HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5"), + ] +) + +nodes = await pipeline.arun(documents=[Document.example()]) +``` + +### ๋ฌธ์„œ ์ €์žฅ ๋ฐ ์ธ๋ฑ์‹ฑ + +`Node` ๊ฐ์ฒด๋ฅผ ๋งŒ๋“  ํ›„, ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ธ๋ฑ์‹ฑํ•ด์•ผ ํ•˜์ง€๋งŒ, ๊ทธ ์ „์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๊ณณ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +์ˆ˜์ง‘ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ํŒŒ์ดํ”„๋ผ์ธ์— ๋ฒกํ„ฐ ์Šคํ† ์–ด๋ฅผ ์ง์ ‘ ์—ฐ๊ฒฐํ•˜์—ฌ ์ฑ„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด ๊ฒฝ์šฐ, ๋ฌธ์„œ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด `Chroma`๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +
+ChromaDB ์„ค์น˜ + +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ChromaDB ๋ฒกํ„ฐ ์Šคํ† ์–ด๋ฅผ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```bash +pip install llama-index-vector-stores-chroma +``` +
+ +```python +import chromadb +from llama_index.vector_stores.chroma import ChromaVectorStore + +db = chromadb.PersistentClient(path="./alfred_chroma_db") +chroma_collection = db.get_or_create_collection("alfred") +vector_store = ChromaVectorStore(chroma_collection=chroma_collection) + +pipeline = IngestionPipeline( + transformations=[ + SentenceSplitter(chunk_size=25, chunk_overlap=0), + HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5"), + ], + vector_store=vector_store, +) +``` + +๋‹ค์–‘ํ•œ ๋ฒกํ„ฐ ์Šคํ† ์–ด์— ๋Œ€ํ•œ ๊ฐœ์š”๋Š” LlamaIndex ๋ฌธ์„œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๊ฒƒ์ด ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ์ด ๋“ค์–ด์˜ค๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค - ์ฟผ๋ฆฌ์™€ ๋…ธ๋“œ๋ฅผ ๊ฐ™์€ ๋ฒกํ„ฐ ๊ณต๊ฐ„์— ์ž„๋ฒ ๋”ฉํ•จ์œผ๋กœ์จ ๊ด€๋ จ ๋งค์น˜๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`VectorStoreIndex`๋Š” ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜์ง‘ ์ค‘์— ์‚ฌ์šฉํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +๋ฒกํ„ฐ ์Šคํ† ์–ด์™€ ์ž„๋ฒ ๋”ฉ์—์„œ ์ด ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: + +```python +from llama_index.core import VectorStoreIndex +from llama_index.embeddings.huggingface import HuggingFaceEmbedding + +embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5") +index = VectorStoreIndex.from_vector_store(vector_store, embed_model=embed_model) +``` + +๋ชจ๋“  ์ •๋ณด๋Š” `ChromaVectorStore` ๊ฐ์ฒด์™€ ์ „๋‹ฌ๋œ ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ ๋‚ด์—์„œ ์ž๋™์œผ๋กœ ์ง€์†๋ฉ๋‹ˆ๋‹ค. + +ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ ์ธ๋ฑ์Šค๋ฅผ ์‰ฝ๊ฒŒ ์ €์žฅํ•˜๊ณ  ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฟผ๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํƒ๊ตฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +### ํ”„๋กฌํ”„ํŠธ์™€ LLM์œผ๋กœ VectorStoreIndex ์ฟผ๋ฆฌํ•˜๊ธฐ + +์ธ๋ฑ์Šค๋ฅผ ์ฟผ๋ฆฌํ•˜๊ธฐ ์ „์—, ์ฟผ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ณ€ํ™˜ ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +- `as_retriever`: ๊ธฐ๋ณธ ๋ฌธ์„œ ๊ฒ€์ƒ‰์šฉ์œผ๋กœ, ์œ ์‚ฌ๋„ ์ ์ˆ˜๊ฐ€ ์žˆ๋Š” `NodeWithScore` ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค +- `as_query_engine`: ๋‹จ์ผ ์งˆ๋ฌธ-๋‹ต๋ณ€ ์ƒํ˜ธ์ž‘์šฉ์šฉ์œผ๋กœ, ์ž‘์„ฑ๋œ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค +- `as_chat_engine`: ์—ฌ๋Ÿฌ ๋ฉ”์‹œ์ง€์— ๊ฑธ์ณ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋Œ€ํ™”ํ˜• ์ƒํ˜ธ์ž‘์šฉ์šฉ์œผ๋กœ, ์ฑ„ํŒ… ๊ธฐ๋ก๊ณผ ์ธ๋ฑ์‹ฑ๋œ ๋งฅ๋ฝ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์„ฑ๋œ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค + +์—์ด์ „ํŠธ์™€ ๊ฐ™์€ ์ƒํ˜ธ์ž‘์šฉ์— ๋” ์ผ๋ฐ˜์ ์ด๋ฏ€๋กœ ์ฟผ๋ฆฌ ์—”์ง„์— ์ง‘์ค‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. +์‘๋‹ต์— ์‚ฌ์šฉํ•  LLM๋„ ์ฟผ๋ฆฌ ์—”์ง„์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. + +```python +from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI + +llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") +query_engine = index.as_query_engine( + llm=llm, + response_mode="tree_summarize", +) +query_engine.query("์ธ์ƒ์˜ ์˜๋ฏธ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?") +# ์ธ์ƒ์˜ ์˜๋ฏธ๋Š” 42์ž…๋‹ˆ๋‹ค +``` + +### ์‘๋‹ต ์ฒ˜๋ฆฌ + +๋‚ด๋ถ€์ ์œผ๋กœ, ์ฟผ๋ฆฌ ์—”์ง„์€ ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์œ„ํ•ด LLM๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ „๋žต์œผ๋กœ `ResponseSynthesizer`๋„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +๋‹ค์‹œ ํ•œ๋ฒˆ, ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์‚ฌ์šฉ์ž ์ •์˜ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ฆ‰์‹œ ์ž˜ ์ž‘๋™ํ•˜๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ์ „๋žต์ด ์žˆ์Šต๋‹ˆ๋‹ค: + +- `refine`: ๊ฒ€์ƒ‰๋œ ๊ฐ ํ…์ŠคํŠธ ์ฒญํฌ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ๊ฑฐ์ณ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•˜๊ณ  ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” Node/๊ฒ€์ƒ‰๋œ ์ฒญํฌ๋‹น ๋ณ„๋„์˜ LLM ํ˜ธ์ถœ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +- `compact` (๊ธฐ๋ณธ๊ฐ’): ๊ฐœ์„ ๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋ฏธ๋ฆฌ ์ฒญํฌ๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋” ์ ์€ LLM ํ˜ธ์ถœ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +- `tree_summarize`: ๊ฒ€์ƒ‰๋œ ๊ฐ ํ…์ŠคํŠธ ์ฒญํฌ๋ฅผ ๊ฑฐ์ณ ๋‹ต๋ณ€์˜ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด ์ƒ์„ธํ•œ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +์ €์ˆ˜์ค€ ๊ตฌ์„ฑ API๋กœ ์ฟผ๋ฆฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•˜์„ธ์š”. ์ด API๋Š” ์ฟผ๋ฆฌ ํ”„๋กœ์„ธ์Šค์˜ ๋ชจ๋“  ๋‹จ๊ณ„๋ฅผ ์‚ฌ์šฉ์ž ์ •์˜ํ•˜๊ณ  ๋ฏธ์„ธ ์กฐ์ •ํ•˜์—ฌ ์ •ํ™•ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถœ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋ฉฐ, ์›Œํฌํ”Œ๋กœ์šฐ์™€๋„ ์ž˜ ๋งž์Šต๋‹ˆ๋‹ค. + +์–ธ์–ด ๋ชจ๋ธ์ด ํ•ญ์ƒ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์šฐ๋ฆฌ๊ฐ€ ์–ป๋Š” ๋‹ต๋ณ€์ด ํ•ญ์ƒ ์ •ํ™•ํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. **๋‹ต๋ณ€์˜ ํ’ˆ์งˆ์„ ํ‰๊ฐ€**ํ•จ์œผ๋กœ์จ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ํ‰๊ฐ€ ๋ฐ ๊ด€์ฐฐ ๊ฐ€๋Šฅ์„ฑ + +LlamaIndex๋Š” **์‘๋‹ต ํ’ˆ์งˆ์„ ํ‰๊ฐ€ํ•˜๊ธฐ ์œ„ํ•œ ๋‚ด์žฅ ํ‰๊ฐ€ ๋„๊ตฌ**๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +์ด๋Ÿฌํ•œ ํ‰๊ฐ€์ž๋Š” LLM์„ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์ฐจ์›์—์„œ ์‘๋‹ต์„ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. +์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ํ‰๊ฐ€์ž๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: + +- `FaithfulnessEvaluator`: ๋‹ต๋ณ€์ด ๋งฅ๋ฝ์— ์˜ํ•ด ์ง€์›๋˜๋Š”์ง€ ํ™•์ธํ•˜์—ฌ ๋‹ต๋ณ€์˜ ์‹ ๋ขฐ์„ฑ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. +- `AnswerRelevancyEvaluator`: ๋‹ต๋ณ€์ด ์งˆ๋ฌธ๊ณผ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์—ฌ ๋‹ต๋ณ€์˜ ๊ด€๋ จ์„ฑ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. +- `CorrectnessEvaluator`: ๋‹ต๋ณ€์ด ์ •ํ™•ํ•œ์ง€ ํ™•์ธํ•˜์—ฌ ๋‹ต๋ณ€์˜ ์ •ํ™•์„ฑ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. + +์—์ด์ „ํŠธ ๊ด€์ฐฐ ๊ฐ€๋Šฅ์„ฑ๊ณผ ํ‰๊ฐ€์— ๋Œ€ํ•ด ๋” ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‚˜์š”? ๋ณด๋„ˆ์Šค ๋‹จ์› 2๋กœ ์—ฌ์ •์„ ๊ณ„์†ํ•˜์„ธ์š”. + +```python +from llama_index.core.evaluation import FaithfulnessEvaluator + +query_engine = # ์ด์ „ ์„น์…˜์—์„œ +llm = # ์ด์ „ ์„น์…˜์—์„œ + +# ์ธ๋ฑ์Šค ์ฟผ๋ฆฌ +evaluator = FaithfulnessEvaluator(llm=llm) +response = query_engine.query( + "๋ฏธ๊ตญ ํ˜๋ช…์—์„œ ๋‰ด์š•์‹œ์—์„œ ์–ด๋–ค ์ „ํˆฌ๊ฐ€ ์ผ์–ด๋‚ฌ๋‚˜์š”?" +) +eval_result = evaluator.evaluate_response(response=response) +eval_result.passing +``` + +์ง์ ‘์ ์ธ ํ‰๊ฐ€ ์—†์ด๋„ **๊ด€์ฐฐ ๊ฐ€๋Šฅ์„ฑ์„ ํ†ตํ•ด ์‹œ์Šคํ…œ์ด ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ํ†ต์ฐฐ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.** +์ด๋Š” ๋” ๋ณต์žกํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€ ์ดํ•ดํ•˜๊ณ  ์‹ถ์„ ๋•Œ ํŠนํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. + +
+LlamaTrace ์„ค์น˜ + +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ Arize Phoenix์˜ LlamaTrace ์ฝœ๋ฐฑ์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```bash +pip install -U llama-index-callbacks-arize-phoenix +``` + +๋˜ํ•œ LlamaTrace API ํ‚ค๋ฅผ `PHOENIX_API_KEY` ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ํ†ตํ•ด ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +- [LlamaTrace](https://llamatrace.com/login)์—์„œ ๊ณ„์ • ์ƒ์„ฑ +- ๊ณ„์ • ์„ค์ •์—์„œ API ํ‚ค ์ƒ์„ฑ +- ์•„๋ž˜ ์ฝ”๋“œ์—์„œ ์ถ”์ ์„ ํ™œ์„ฑํ™”ํ•˜๊ธฐ ์œ„ํ•ด API ํ‚ค ์‚ฌ์šฉ + +
+ +```python +import llama_index +import os + +PHOENIX_API_KEY = "" +os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"api_key={PHOENIX_API_KEY}" +llama_index.core.set_global_handler( + "arize_phoenix", + endpoint="https://llamatrace.com/v1/traces" +) +``` + +๊ตฌ์„ฑ ์š”์†Œ์™€ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋” ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‚˜์š”? ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ€์ด๋“œ ๋˜๋Š” RAG ๊ฐ€์ด๋“œ๋กœ ์—ฌ์ •์„ ๊ณ„์†ํ•˜์„ธ์š”. + +๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ `QueryEngine`์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด์ œ **`QueryEngine`์„ ์—์ด์ „ํŠธ์˜ ํˆด๋กœ ์‚ฌ์šฉํ•˜๋Š”** ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/llama-index/conclusion.mdx b/units/ko/unit2/llama-index/conclusion.mdx new file mode 100644 index 00000000..c0e7f825 --- /dev/null +++ b/units/ko/unit2/llama-index/conclusion.mdx @@ -0,0 +1,13 @@ +# ๊ฒฐ๋ก  + +2๋‹จ์›์˜ `llama-index` ๋ชจ๋“ˆ์„ ์™„๋ฃŒํ•˜์‹  ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿฅณ + +๋ฐฉ๊ธˆ `llama-index`์˜ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ•˜๊ณ  ์ž์‹ ๋งŒ์˜ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์…จ์Šต๋‹ˆ๋‹ค! +์ด์ œ `llama-index` ๊ธฐ์ˆ ์„ ๊ฐ–์ถ”์…จ์œผ๋‹ˆ, ๊ด€์‹ฌ ์žˆ๋Š” ์ž‘์—…์„ ํ•ด๊ฒฐํ•  ๊ฒ€์ƒ‰ ์—”์ง„์„ ๋งŒ๋“ค๊ธฐ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๋‹จ์›์˜ ๋‹ค์Œ ๋ชจ๋“ˆ์—์„œ๋Š” **LangGraph๋กœ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•**์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +๋งˆ์ง€๋ง‰์œผ๋กœ, **๊ฐ•์˜์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ๊ณผ ๊ฐœ์„  ๋ฐฉ๋ฒ•**์„ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. +ํ”ผ๋“œ๋ฐฑ์ด ์žˆ์œผ์‹œ๋ฉด ๐Ÿ‘‰ [์ด ์–‘์‹์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) + +### ๊ณ„์† ๋ฐฐ์šฐ๊ณ , ๋ฉ‹์ง€๊ฒŒ ์œ ์ง€ํ•˜์„ธ์š”! ๐Ÿค— diff --git a/units/ko/unit2/llama-index/introduction.mdx b/units/ko/unit2/llama-index/introduction.mdx new file mode 100644 index 00000000..c0d923e2 --- /dev/null +++ b/units/ko/unit2/llama-index/introduction.mdx @@ -0,0 +1,29 @@ +# LlamaIndex ์†Œ๊ฐœ + +[LlamaIndex](https://www.llamaindex.ai/) ํˆดํ‚ท์„ ์‚ฌ์šฉํ•˜์—ฌ LLM ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๋Š” ์ด ๋ชจ๋“ˆ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. + +LlamaIndex๋Š” **์ธ๋ฑ์Šค์™€ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์œ„์—์„œ LLM ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ์™„์ „ํ•œ ํˆดํ‚ท**์ž…๋‹ˆ๋‹ค. ์ด ๊ฐ•์˜์—์„œ๋Š” LlamaIndex์—์„œ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๋ถ€๋ถ„์— ์ง‘์ค‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: **๊ตฌ์„ฑ ์š”์†Œ**, **์—์ด์ „ํŠธ์™€ ํˆด**, ๊ทธ๋ฆฌ๊ณ  **์›Œํฌํ”Œ๋กœ์šฐ**์ž…๋‹ˆ๋‹ค. + +![LlamaIndex](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/thumbnail.png) + +LlamaIndex์˜ ์ด๋Ÿฌํ•œ ํ•ต์‹ฌ ๋ถ€๋ถ„๋“ค๊ณผ ์—์ด์ „ํŠธ์— ์–ด๋–ป๊ฒŒ ๋„์›€์ด ๋˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: + +- **๊ตฌ์„ฑ ์š”์†Œ**: LlamaIndex์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ๋นŒ๋”ฉ ๋ธ”๋ก์ž…๋‹ˆ๋‹ค. ํ”„๋กฌํ”„ํŠธ, ๋ชจ๋ธ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ข…์ข… LlamaIndex๋ฅผ ๋‹ค๋ฅธ ํˆด๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. +- **ํˆด**: ๊ฒ€์ƒ‰, ๊ณ„์‚ฐ, ์™ธ๋ถ€ ์„œ๋น„์Šค ์ ‘๊ทผ๊ณผ ๊ฐ™์€ ํŠน์ • ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋นŒ๋”ฉ ๋ธ”๋ก์ž…๋‹ˆ๋‹ค. +- **์—์ด์ „ํŠธ**: ํˆด์„ ์‚ฌ์šฉํ•˜๊ณ  ๊ฒฐ์ •์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ๋Š” ์ž์œจ ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํˆด ์‚ฌ์šฉ์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. +- **์›Œํฌํ”Œ๋กœ์šฐ**: ๋กœ์ง์„ ํ•จ๊ป˜ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ์›Œํฌํ”Œ๋กœ์šฐ ๋˜๋Š” ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ๋ช…์‹œ์ ์ธ ์—์ด์ „ํŠธ ์‚ฌ์šฉ ์—†์ด ์—์ด์ „ํŠธ ํ–‰๋™์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. + +## LlamaIndex๋ฅผ ํŠน๋ณ„ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + +LlamaIndex๊ฐ€ smolagents์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์œ ์‚ฌํ•œ ์ผ๋ถ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค: + +- **๋ช…ํ™•ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ ์‹œ์Šคํ…œ**: ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ๋ฐ ๋น„๋™๊ธฐ ์šฐ์„  ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์—์ด์ „ํŠธ๊ฐ€ ๋‹จ๊ณ„๋ณ„๋กœ ์–ด๋–ป๊ฒŒ ๊ฒฐ์ •์„ ๋‚ด๋ ค์•ผ ํ•˜๋Š”์ง€ ๋ถ„ํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋กœ์ง์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. +- **LlamaParse๋ฅผ ํ†ตํ•œ ๊ณ ๊ธ‰ ๋ฌธ์„œ ํŒŒ์‹ฑ**: LlamaParse๋Š” LlamaIndex๋ฅผ ์œ„ํ•ด ํŠน๋ณ„ํžˆ ๋งŒ๋“ค์–ด์กŒ์œผ๋ฏ€๋กœ ํ†ตํ•ฉ์ด ์›ํ™œํ•˜์ง€๋งŒ, ์œ ๋ฃŒ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. +- **๋งŽ์€ ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ**: LlamaIndex๋Š” ์˜ค๋žซ๋™์•ˆ ์กด์žฌํ•ด์™”์œผ๋ฏ€๋กœ ๋งŽ์€ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” LLM, ๊ฒ€์ƒ‰๊ธฐ, ์ธ๋ฑ์Šค ๋“ฑ๊ณผ ๊ฐ™์€ ๋งŽ์€ ํ…Œ์ŠคํŠธ๋˜๊ณ  ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. +- **LlamaHub**: LlamaIndex ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ ์š”์†Œ, ์—์ด์ „ํŠธ, ํˆด์˜ ์ˆ˜๋ฐฑ ๊ฐœ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค. + +์ด๋Ÿฌํ•œ ๋ชจ๋“  ๊ฐœ๋…์€ ์œ ์šฉํ•œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. +๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๊ฐœ๋…๋“ค์„ ๊ฐ๊ฐ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +๊ฐœ๋…์„ ๋งˆ์Šคํ„ฐํ•œ ํ›„, ์šฐ๋ฆฌ์˜ ํ•™์Šต์„ ์‚ฌ์šฉํ•˜์—ฌ **์—์ด์ „ํŠธ ์•Œํ”„๋ ˆ๋“œ์™€ ํ•จ๊ป˜ ์ ์šฉ๋œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋งŒ๋“ค** ๊ฒƒ์ž…๋‹ˆ๋‹ค! + +LlamaIndex๋ฅผ ์ง์ ‘ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ด ํฅ๋ฏธ๋กญ์ง€ ์•Š๋‚˜์š”? ๊ทธ๋Ÿผ ๋ฌด์—‡์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋‚˜์š”? **LlamaHub๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ํ†ตํ•ฉ์„ ์ฐพ๊ณ  ์„ค์น˜ํ•˜๋Š”** ๊ฒƒ์œผ๋กœ ์‹œ์ž‘ํ•ด๋ด…์‹œ๋‹ค! ๐Ÿš€ \ No newline at end of file diff --git a/units/ko/unit2/llama-index/llama-hub.mdx b/units/ko/unit2/llama-index/llama-hub.mdx new file mode 100644 index 00000000..6da1486b --- /dev/null +++ b/units/ko/unit2/llama-index/llama-hub.mdx @@ -0,0 +1,55 @@ +# LlamaHub ์†Œ๊ฐœ + +**LlamaHub๋Š” LlamaIndex ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋ฐฑ ๊ฐœ์˜ ํ†ตํ•ฉ, ์—์ด์ „ํŠธ, ํˆด์˜ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค.** + +![LlamaHub](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/llama-hub.png) + +์ด ๊ฐ•์˜์—์„œ ๋‹ค์–‘ํ•œ ํ†ตํ•ฉ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ, ๋จผ์ € LlamaHub์™€ ๊ทธ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์šฐ๋ฆฌ๋ฅผ ๋„์šธ ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์˜์กด์„ฑ์„ ์ฐพ๊ณ  ์„ค์น˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ์„ค์น˜ + +LlamaIndex ์„ค์น˜ ์ง€์นจ์€ [LlamaHub](https://llamahub.ai/)์—์„œ ์ž˜ ๊ตฌ์กฐํ™”๋œ **๊ฐœ์š”๋กœ ์ œ๊ณต**๋ฉ๋‹ˆ๋‹ค. +์ฒ˜์Œ์—๋Š” ์กฐ๊ธˆ ์••๋„์ ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์˜ **์„ค์น˜ ๋ช…๋ น์–ด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๊ธฐ์–ตํ•˜๊ธฐ ์‰ฌ์šด ํ˜•์‹**์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค: + +```bash +pip install llama-index-{component-type}-{framework-name} +``` + +[Hugging Face ์ถ”๋ก  API ํ†ตํ•ฉ](https://llamahub.ai/l/llms/llama-index-llms-huggingface-api?from=llms)์„ ์‚ฌ์šฉํ•˜์—ฌ LLM๊ณผ ์ž„๋ฒ ๋”ฉ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +```bash +pip install llama-index-llms-huggingface-api llama-index-embeddings-huggingface +``` + +## ์‚ฌ์šฉ๋ฒ• + +์„ค์น˜๋˜๋ฉด ์‚ฌ์šฉ ํŒจํ„ด์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์ ธ์˜ค๊ธฐ ๊ฒฝ๋กœ๊ฐ€ ์„ค์น˜ ๋ช…๋ น์–ด๋ฅผ ๋”ฐ๋ฅด๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค! +์•„๋ž˜์—์„œ **LLM ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์œ„ํ•œ Hugging Face ์ถ”๋ก  API ์‚ฌ์šฉ**์˜ ์˜ˆ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI +import os +from dotenv import load_dotenv + +# .env ํŒŒ์ผ ๋กœ๋“œ +load_dotenv() + +# ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ HF_TOKEN ๊ฒ€์ƒ‰ +hf_token = os.getenv("HF_TOKEN") + +llm = HuggingFaceInferenceAPI( + model_name="Qwen/Qwen2.5-Coder-32B-Instruct", + temperature=0.7, + max_tokens=100, + token=hf_token, +) + +response = llm.complete("์•ˆ๋…•ํ•˜์„ธ์š”, ์–ด๋–ป๊ฒŒ ์ง€๋‚ด์‹œ๋‚˜์š”?") +print(response) +# ์ž˜ ์ง€๋‚ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค, ์˜ค๋Š˜ ์–ด๋–ป๊ฒŒ ๋„์™€๋“œ๋ฆด๊นŒ์š”? +``` + +ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค, ์ด์ œ ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ํ†ตํ•ฉ์„ ์ฐพ๊ณ , ์„ค์น˜ํ•˜๊ณ , ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. +**๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€์„œ** ์šฐ๋ฆฌ๋งŒ์˜ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. diff --git a/units/ko/unit2/llama-index/quiz1.mdx b/units/ko/unit2/llama-index/quiz1.mdx new file mode 100644 index 00000000..7e542df7 --- /dev/null +++ b/units/ko/unit2/llama-index/quiz1.mdx @@ -0,0 +1,117 @@ +# ๋ฏธ๋‹ˆ ํ€ด์ฆˆ (์ฑ„์ ๋˜์ง€ ์•Š์Œ) [[quiz1]] + +์ง€๊ธˆ๊นŒ์ง€ LlamaIndex์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ์™€ ํˆด์— ๋Œ€ํ•ด ๋…ผ์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. +**์ž์‹ ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ**์ด ํ•™์Šตํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๊ณ  [๋Šฅ๋ ฅ์˜ ์ฐฉ๊ฐ์„ ํ”ผํ•˜๋Š”](https://www.coursera.org/lecture/learning-how-to-learn/illusions-of-competence-BuFzf) ๋ฐฉ๋ฒ•์ด๋ฏ€๋กœ ์งง์€ ํ€ด์ฆˆ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. +์ด๊ฒƒ์€ **์ง€์‹์„ ๊ฐ•ํ™”ํ•ด์•ผ ํ•  ๋ถ€๋ถ„์„ ์ฐพ๋Š”** ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์ด๊ฒƒ์€ ์„ ํƒ์‚ฌํ•ญ ํ€ด์ฆˆ์ด๋ฉฐ ์ฑ„์ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +### Q1: QueryEngine์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? +๋‹ค์Œ ์ค‘ QueryEngine ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + +### Q2: FunctionTools์˜ ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? +์—์ด์ „ํŠธ์—๊ฒŒ FunctionTools๊ฐ€ ์ค‘์š”ํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + +### Q3: LlamaIndex์˜ Toolspecs๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? +Toolspecs์˜ ์ฃผ์š” ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + +### Q4: ํˆด์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? +ํˆด์„ ๋งŒ๋“ค ๋•Œ ํฌํ•จํ•ด์•ผ ํ•˜๋Š” ์ •๋ณด๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + +์ด ํ€ด์ฆˆ๋ฅผ ์™„๋ฃŒํ•˜์‹  ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿฅณ ์ผ๋ถ€ ์š”์†Œ๋ฅผ ๋†“์ณค๋‹ค๋ฉด, ์ง€์‹์„ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ฑ•ํ„ฐ๋ฅผ ๋‹ค์‹œ ์ฝ์–ด๋ณด์„ธ์š”. ํ†ต๊ณผํ•˜์…จ๋‹ค๋ฉด, ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋” ๊นŠ์ด ๊ตฌ์ถ•ํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/llama-index/quiz2.mdx b/units/ko/unit2/llama-index/quiz2.mdx new file mode 100644 index 00000000..373ae1eb --- /dev/null +++ b/units/ko/unit2/llama-index/quiz2.mdx @@ -0,0 +1,112 @@ +# ์…€ํ”„ ์ฒดํฌ (์ฑ„์ ๋˜์ง€ ์•Š์Œ) [[quiz2]] + +๋ญ?! ๋˜ ๋‹ค๋ฅธ ํ€ด์ฆˆ? ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค, ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค... ๐Ÿ˜… ํ•˜์ง€๋งŒ ์ด ์งง์€, ์ฑ„์ ๋˜์ง€ ์•Š๋Š” ํ€ด์ฆˆ๋Š” **๋ฐฉ๊ธˆ ๋ฐฐ์šด ํ•ต์‹ฌ ๊ฐœ๋…์„ ๊ฐ•ํ™”ํ•˜๋Š” ๋ฐ ๋„์›€์ด** ๋˜๊ธฐ ์œ„ํ•ด ์—ฌ๊ธฐ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ํ€ด์ฆˆ๋Š” ํšจ๊ณผ์ ์ธ AI ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ํ•„์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ์ธ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ์™€ ์ƒํ˜ธ์ž‘์šฉ์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +### Q1: LlamaIndex์—์„œ AgentWorkflow์˜ ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + +### Q2: ์›Œํฌํ”Œ๋กœ์šฐ์˜ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + +### Q3: ์—์ด์ „ํŠธ๊ฐ€ ์ด์ „ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ธฐ์–ตํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด ์–ด๋–ค ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋‚˜์š”? + + + +--- + +### Q4: ์—์ด์ „ํŠธ RAG์˜ ์ฃผ์š” ํŠน์ง•์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + + +์ดํ•ดํ•˜์…จ๋‚˜์š”? ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ **๋‹จ์›์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์š”์•ฝ์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!** diff --git a/units/ko/unit2/llama-index/tools.mdx b/units/ko/unit2/llama-index/tools.mdx new file mode 100644 index 00000000..6b9efb8b --- /dev/null +++ b/units/ko/unit2/llama-index/tools.mdx @@ -0,0 +1,141 @@ +# LlamaIndex์—์„œ ํˆด ์‚ฌ์šฉํ•˜๊ธฐ + +**๋ช…ํ™•ํ•œ ํˆด ์„ธํŠธ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ์— ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.** [1๋‹จ์›](../../unit1/tools)์—์„œ ๋…ผ์˜ํ–ˆ๋“ฏ์ด, ๋ช…ํ™•ํ•œ ํˆด ์ธํ„ฐํŽ˜์ด์Šค๋Š” LLM์ด ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. +์ธ๊ฐ„ ์—”์ง€๋‹ˆ์–ด๋ฅผ ์œ„ํ•œ ์†Œํ”„ํŠธ์›จ์–ด API ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ํˆด์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค๋ฉด ๋” ๋งŽ์€ ๊ฒƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +**LlamaIndex์—๋Š” ๋„ค ๊ฐ€์ง€ ์ฃผ์š” ์œ ํ˜•์˜ ํˆด**์ด ์žˆ์Šต๋‹ˆ๋‹ค: + +![ํˆด](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/tools.png) + +1. `FunctionTool`: ๋ชจ๋“  Python ํ•จ์ˆ˜๋ฅผ ์—์ด์ „ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํˆด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ž๋™์œผ๋กœ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค. +2. `QueryEngineTool`: ์—์ด์ „ํŠธ๊ฐ€ ์ฟผ๋ฆฌ ์—”์ง„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ํˆด์ž…๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ์ฟผ๋ฆฌ ์—”์ง„ ์œ„์— ๊ตฌ์ถ•๋˜๋ฏ€๋กœ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๋„ ํˆด๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +3. `Toolspecs`: ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋งŒ๋“  ํˆด ์„ธํŠธ๋กœ, ์ข…์ข… Gmail๊ณผ ๊ฐ™์€ ํŠน์ • ์„œ๋น„์Šค๋ฅผ ์œ„ํ•œ ํˆด์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. +4. `Utility Tools`: ๋‹ค๋ฅธ ํˆด์—์„œ ๋‚˜์˜ค๋Š” ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ํŠน๋ณ„ํ•œ ํˆด์ž…๋‹ˆ๋‹ค. + +์•„๋ž˜์—์„œ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## FunctionTool ๋งŒ๋“ค๊ธฐ + + +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +FunctionTool์€ ๋ชจ๋“  Python ํ•จ์ˆ˜๋ฅผ ๋ž˜ํ•‘ํ•˜๊ณ  ์—์ด์ „ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +๋™๊ธฐ ๋˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํˆด์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์„ ํƒ์ ์œผ๋กœ `name`๊ณผ `description` ๋งค๊ฐœ๋ณ€์ˆ˜๋„ ํ•จ๊ป˜ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๋ฆ„๊ณผ ์„ค๋ช…์€ ํŠนํžˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๊ฐ€ ์–ธ์ œ, ์–ด๋–ป๊ฒŒ ํˆด์„ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ• ์ง€ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +์•„๋ž˜์—์„œ FunctionTool์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ณ  ํ˜ธ์ถœํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.core.tools import FunctionTool + +def get_weather(location: str) -> str: + """์ฃผ์–ด์ง„ ์œ„์น˜์˜ ๋‚ ์”จ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.""" + print(f"{location}์˜ ๋‚ ์”จ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘") + return f"{location}์˜ ๋‚ ์”จ๋Š” ๋ง‘์Šต๋‹ˆ๋‹ค" + +tool = FunctionTool.from_defaults( + get_weather, + name="my_weather_tool", + description="์ฃผ์–ด์ง„ ์œ„์น˜์˜ ๋‚ ์”จ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.", +) +tool.call("๋‰ด์š•") +``` + +ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ์žˆ๋Š” ์—์ด์ „ํŠธ๋‚˜ LLM์„ ์‚ฌ์šฉํ•  ๋•Œ, ์„ ํƒ๋œ ํˆด(๊ทธ ํˆด์— ๋Œ€ํ•ด ์ž‘์„ฑ๋œ ์ธ์ˆ˜)์€ ํˆด์˜ ๋ชฉ์ ๊ณผ ์ธ์ˆ˜์— ๋Œ€ํ•œ ํˆด ์ด๋ฆ„๊ณผ ์„ค๋ช…์— ํฌ๊ฒŒ ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ฐ€์ด๋“œ์—์„œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด์„ธ์š”. + +## QueryEngineTool ๋งŒ๋“ค๊ธฐ + +์ด์ „ ๋‹จ์›์—์„œ ์ •์˜ํ•œ `QueryEngine`์€ `QueryEngineTool` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ํˆด๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์•„๋ž˜ ์˜ˆ์ œ์—์„œ `QueryEngine`์—์„œ `QueryEngineTool`์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.core import VectorStoreIndex +from llama_index.core.tools import QueryEngineTool +from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI +from llama_index.embeddings.huggingface import HuggingFaceEmbedding +from llama_index.vector_stores.chroma import ChromaVectorStore + +embed_model = HuggingFaceEmbedding("BAAI/bge-small-en-v1.5") + +db = chromadb.PersistentClient(path="./alfred_chroma_db") +chroma_collection = db.get_or_create_collection("alfred") +vector_store = ChromaVectorStore(chroma_collection=chroma_collection) + +index = VectorStoreIndex.from_vector_store(vector_store, embed_model=embed_model) + +llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") +query_engine = index.as_query_engine(llm=llm) +tool = QueryEngineTool.from_defaults(query_engine, name="some useful name", description="some useful description") +``` + +## Toolspecs ๋งŒ๋“ค๊ธฐ + +`ToolSpecs`๋ฅผ ์กฐํ™”๋กญ๊ฒŒ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ํˆด ๋ชจ์Œ์œผ๋กœ ์ƒ๊ฐํ•˜์„ธ์š” - ์ž˜ ์ •๋ฆฌ๋œ ์ „๋ฌธ๊ฐ€ ํˆดํ‚ท์ฒ˜๋Ÿผ์š”. +์ •๋น„์‚ฌ์˜ ํˆดํ‚ท์ด ์ฐจ๋Ÿ‰ ์ˆ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๋ณด์™„์ ์ธ ํˆด๋“ค์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, `ToolSpec`์€ ํŠน์ • ๋ชฉ์ ์„ ์œ„ํ•ด ๊ด€๋ จ๋œ ํˆด๋“ค์„ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. +์˜ˆ๋ฅผ ๋“ค์–ด, ํšŒ๊ณ„ ์—์ด์ „ํŠธ์˜ `ToolSpec`์€ ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ ๊ธฐ๋Šฅ, ์ด๋ฉ”์ผ ๊ธฐ๋Šฅ, ๊ณ„์‚ฐ ํˆด์„ ์šฐ์•„ํ•˜๊ฒŒ ํ†ตํ•ฉํ•˜์—ฌ ์žฌ๋ฌด ์ž‘์—…์„ ์ •ํ™•ํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +
+Google Toolspec ์„ค์น˜ +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ Google toolspec์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +pip install llama-index-tools-google +``` +
+ +์ด์ œ toolspec์„ ๋กœ๋“œํ•˜๊ณ  ํˆด ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.tools.google import GmailToolSpec + +tool_spec = GmailToolSpec() +tool_spec_list = tool_spec.to_tool_list() +``` + +ํˆด์— ๋Œ€ํ•œ ๋” ์ž์„ธํ•œ ๋ณด๊ธฐ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ๊ฐ ํˆด์˜ `metadata`๋ฅผ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +[(tool.metadata.name, tool.metadata.description) for tool in tool_spec_list] +``` + +### LlamaIndex์˜ ๋ชจ๋ธ ์ปจํ…์ŠคํŠธ ํ”„๋กœํ† ์ฝœ (MCP) + +LlamaIndex๋Š” [LlamaHub์˜ ToolSpec](https://llamahub.ai/l/tools/llama-index-tools-mcp?from=)์„ ํ†ตํ•ด MCP ํˆด ์‚ฌ์šฉ๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. +๋‹จ์ˆœํžˆ MCP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค์Œ ๊ตฌํ˜„์„ ํ†ตํ•ด ์‚ฌ์šฉ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +MCP์— ๋Œ€ํ•ด ๋” ๊นŠ์ด ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด [๋ฌด๋ฃŒ MCP ๊ฐ•์˜](https://huggingface.co/learn/mcp-course/)๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +
+MCP Toolspec ์„ค์น˜ +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ MCP toolspec์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +pip install llama-index-tools-mcp +``` +
+ +```python +from llama_index.tools.mcp import BasicMCPClient, McpToolSpec + +# 127.0.0.1:8000์—์„œ ์‹คํ–‰ ์ค‘์ธ mcp ์„œ๋ฒ„๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฑฐ๋‚˜, mcp ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž์ฒด mcp ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +mcp_client = BasicMCPClient("http://127.0.0.1:8000/sse") +mcp_tool = McpToolSpec(client=mcp_client) + +# ์—์ด์ „ํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ +agent = await get_agent(mcp_tool) + +# ์—์ด์ „ํŠธ ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ +agent_context = Context(agent) +``` + +## ์œ ํ‹ธ๋ฆฌํ‹ฐ ํˆด + +์ข…์ข… API๋ฅผ ์ง์ ‘ ์ฟผ๋ฆฌํ•˜๋Š” ๊ฒƒ์€ **๊ณผ๋„ํ•œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ**, ๊ทธ ์ค‘ ์ผ๋ถ€๋Š” ๊ด€๋ จ์ด ์—†๊ฑฐ๋‚˜, LLM์˜ ์ปจํ…์ŠคํŠธ ์œˆ๋„์šฐ๋ฅผ ๋„˜์น˜๊ฑฐ๋‚˜, ์‚ฌ์šฉํ•˜๋Š” ํ† ํฐ ์ˆ˜๋ฅผ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ฆ๊ฐ€์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์•„๋ž˜์—์„œ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํˆด์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +1. `OnDemandToolLoader`: ์ด ํˆด์€ ๊ธฐ์กด LlamaIndex ๋ฐ์ดํ„ฐ ๋กœ๋”(BaseReader ํด๋ž˜์Šค)๋ฅผ ์—์ด์ „ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํˆด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํˆด์€ ๋ฐ์ดํ„ฐ ๋กœ๋”์—์„œ `load_data`๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ž์—ฐ์–ด ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹คํ–‰ ์ค‘์— ๋จผ์ € ๋ฐ์ดํ„ฐ ๋กœ๋”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ณ , ์ธ๋ฑ์‹ฑํ•˜๊ณ (์˜ˆ๋ฅผ ๋“ค์–ด ๋ฒกํ„ฐ ์Šคํ† ์–ด๋กœ), ๊ทธ๋Ÿฐ ๋‹ค์Œ '์˜จ๋””๋งจ๋“œ'๋กœ ์ฟผ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์„ธ ๋‹จ๊ณ„ ๋ชจ๋‘๊ฐ€ ๋‹จ์ผ ํˆด ํ˜ธ์ถœ์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. +2. `LoadAndSearchToolSpec`: LoadAndSearchToolSpec์€ ๊ธฐ์กด ํˆด์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค. ํˆด ์ŠคํŽ™์œผ๋กœ์„œ `to_tool_list`๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ, ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋‘ ๊ฐœ์˜ ํˆด์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค: ๋กœ๋”ฉ ํˆด๊ณผ ๊ฒ€์ƒ‰ ํˆด์ž…๋‹ˆ๋‹ค. ๋กœ๋“œ ํˆด ์‹คํ–‰์€ ๊ธฐ๋ณธ ํˆด์„ ํ˜ธ์ถœํ•œ ๋‹ค์Œ ์ถœ๋ ฅ์„ ์ธ๋ฑ์‹ฑํ•ฉ๋‹ˆ๋‹ค(๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฒกํ„ฐ ์ธ๋ฑ์Šค๋กœ). ๊ฒ€์ƒ‰ ํˆด ์‹คํ–‰์€ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„ ๊ธฐ๋ณธ ์ธ๋ฑ์Šค๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. + +toolspecs์™€ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํˆด์€ LlamaHub์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค + +์ด์ œ LlamaIndex์—์„œ ์—์ด์ „ํŠธ์™€ ํˆด์˜ ๊ธฐ๋ณธ์„ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, LlamaIndex๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **๊ตฌ์„ฑ ๊ฐ€๋Šฅํ•˜๊ณ  ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š”** ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/llama-index/workflows.mdx b/units/ko/unit2/llama-index/workflows.mdx new file mode 100644 index 00000000..3b2e396e --- /dev/null +++ b/units/ko/unit2/llama-index/workflows.mdx @@ -0,0 +1,280 @@ +# LlamaIndex์—์„œ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ ๋งŒ๋“ค๊ธฐ + +LlamaIndex์˜ ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ์ฝ”๋“œ๋ฅผ ์ˆœ์ฐจ์ ์ด๊ณ  ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ๋‹จ๊ณ„๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๊ตฌ์กฐํ™”๋œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Ÿฌํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋Š” `Events`์— ์˜ํ•ด ํŠธ๋ฆฌ๊ฑฐ๋˜๋Š” `Steps`๋ฅผ ์ •์˜ํ•˜์—ฌ ์ƒ์„ฑ๋˜๋ฉฐ, ์ด๋“ค ์ž์ฒด๊ฐ€ ์ถ”๊ฐ€ ๋‹จ๊ณ„๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด `Events`๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. +RAG ์ž‘์—…์„ ์œ„ํ•œ LlamaIndex ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์•Œํ”„๋ ˆ๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +![์›Œํฌํ”Œ๋กœ์šฐ ๊ฐœ์š”](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/workflows.png) + +**์›Œํฌํ”Œ๋กœ์šฐ๋Š” ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:** + +- ์ฝ”๋“œ๋ฅผ ๊ฐœ๋ณ„ ๋‹จ๊ณ„๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ์„ฑ +- ์œ ์—ฐํ•œ ์ œ์–ด ํ๋ฆ„์„ ์œ„ํ•œ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ +- ๋‹จ๊ณ„ ๊ฐ„ ํƒ€์ž… ์•ˆ์ „ ํ†ต์‹  +- ๋‚ด์žฅ ์ƒํƒœ ๊ด€๋ฆฌ +- ๊ฐ„๋‹จํ•˜๊ณ  ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์ƒํ˜ธ์ž‘์šฉ ๋ชจ๋‘ ์ง€์› + +์ถ”์ธกํ•˜์…จ์„ ์ˆ˜ ์žˆ๋“ฏ์ด, **์›Œํฌํ”Œ๋กœ์šฐ๋Š” ์ „์ฒด ์›Œํฌํ”Œ๋กœ์šฐ์— ๋Œ€ํ•œ ์ œ์–ด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์—์ด์ „ํŠธ์˜ ์ž์œจ์„ฑ ์‚ฌ์ด์—์„œ ํ›Œ๋ฅญํ•œ ๊ท ํ˜•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.** + +๊ทธ๋Ÿผ ์šฐ๋ฆฌ๋งŒ์˜ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! + +## ์›Œํฌํ”Œ๋กœ์šฐ ๋งŒ๋“ค๊ธฐ + + +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +### ๊ธฐ๋ณธ ์›Œํฌํ”Œ๋กœ์šฐ ์ƒ์„ฑ + +
+์›Œํฌํ”Œ๋กœ์šฐ ํŒจํ‚ค์ง€ ์„ค์น˜ +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ์›Œํฌํ”Œ๋กœ์šฐ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +pip install llama-index-utils-workflow +``` +
+ +`Workflow`๋ฅผ ์ƒ์†ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  ํ•จ์ˆ˜์— `@step` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ๋‹จ๊ณ„ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋˜ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ์˜ ์‹œ์ž‘๊ณผ ๋์„ ๋‚˜ํƒ€๋‚ด๋Š” ํŠน๋ณ„ํ•œ ์ด๋ฒคํŠธ์ธ `StartEvent`์™€ `StopEvent`๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +```python +from llama_index.core.workflow import StartEvent, StopEvent, Workflow, step + +class MyWorkflow(Workflow): + @step + async def my_step(self, ev: StartEvent) -> StopEvent: + # ์—ฌ๊ธฐ์„œ ๋ฌด์–ธ๊ฐ€ ์ˆ˜ํ–‰ + return StopEvent(result="์•ˆ๋…•ํ•˜์„ธ์š”, ์„ธ๊ณ„!") + + +w = MyWorkflow(timeout=10, verbose=False) +result = await w.run() +``` + +๋ณด์‹œ๋‹ค์‹œํ”ผ, ์ด์ œ `w.run()`์„ ํ˜ธ์ถœํ•˜์—ฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์—ฌ๋Ÿฌ ๋‹จ๊ณ„ ์—ฐ๊ฒฐํ•˜๊ธฐ + +์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด **๋‹จ๊ณ„ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.** +์ด๋ฅผ ์œ„ํ•ด ๋‹จ๊ณ„ ๊ฐ„์— ์ „๋‹ฌ๋˜๊ณ  ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์˜ ์ถœ๋ ฅ์„ ๋‘ ๋ฒˆ์งธ ๋‹จ๊ณ„๋กœ ์ „์†กํ•˜๋Š” `Event`๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +```python +from llama_index.core.workflow import Event + +class ProcessingEvent(Event): + intermediate_result: str + +class MultiStepWorkflow(Workflow): + @step + async def step_one(self, ev: StartEvent) -> ProcessingEvent: + # ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ + return ProcessingEvent(intermediate_result="1๋‹จ๊ณ„ ์™„๋ฃŒ") + + @step + async def step_two(self, ev: ProcessingEvent) -> StopEvent: + # ์ค‘๊ฐ„ ๊ฒฐ๊ณผ ์‚ฌ์šฉ + final_result = f"์ฒ˜๋ฆฌ ์™„๋ฃŒ: {ev.intermediate_result}" + return StopEvent(result=final_result) + +w = MultiStepWorkflow(timeout=10, verbose=False) +result = await w.run() +result +``` + +ํƒ€์ž… ํžŒํŒ…์€ ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์กฐ๊ธˆ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! + +### ๋ฃจํ”„์™€ ๋ถ„๊ธฐ + +ํƒ€์ž… ํžŒํŒ…์€ ์›Œํฌํ”Œ๋กœ์šฐ์˜ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๋” ๋ณต์žกํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ถ„๊ธฐ, ๋ฃจํ”„, ์กฐ์ธ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +ํ•ฉ์ง‘ํ•ฉ ์—ฐ์‚ฐ์ž `|`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **๋ฃจํ”„๋ฅผ ๋งŒ๋“œ๋Š”** ์˜ˆ์ œ๋ฅผ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. +์•„๋ž˜ ์˜ˆ์ œ์—์„œ `LoopEvent`๊ฐ€ ๋‹จ๊ณ„์˜ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์ถœ๋ ฅ์œผ๋กœ๋„ ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ์Œ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.core.workflow import Event +import random + + +class ProcessingEvent(Event): + intermediate_result: str + + +class LoopEvent(Event): + loop_output: str + + +class MultiStepWorkflow(Workflow): + @step + async def step_one(self, ev: StartEvent | LoopEvent) -> ProcessingEvent | LoopEvent: + if random.randint(0, 1) == 0: + print("๋‚˜์œ ์ผ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค") + return LoopEvent(loop_output="1๋‹จ๊ณ„๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.") + else: + print("์ข‹์€ ์ผ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค") + return ProcessingEvent(intermediate_result="์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„ ์™„๋ฃŒ.") + + @step + async def step_two(self, ev: ProcessingEvent) -> StopEvent: + # ์ค‘๊ฐ„ ๊ฒฐ๊ณผ ์‚ฌ์šฉ + final_result = f"์ฒ˜๋ฆฌ ์™„๋ฃŒ: {ev.intermediate_result}" + return StopEvent(result=final_result) + + +w = MultiStepWorkflow(verbose=False) +result = await w.run() +result +``` + +### ์›Œํฌํ”Œ๋กœ์šฐ ๊ทธ๋ฆฌ๊ธฐ + +์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ทธ๋ฆด ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. `draw_all_possible_flows` ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ทธ๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ HTML ํŒŒ์ผ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. + +```python +from llama_index.utils.workflow import draw_all_possible_flows + +w = ... # ์ด์ „ ์„น์…˜์—์„œ ์ •์˜๋œ ๋Œ€๋กœ +draw_all_possible_flows(w, "flow.html") +``` + +![์›Œํฌํ”Œ๋กœ์šฐ ๊ทธ๋ฆฌ๊ธฐ](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/workflow-draw.png) + +๊ฐ•์˜์—์„œ ๋‹ค๋ฃฐ ๋งˆ์ง€๋ง‰ ๋ฉ‹์ง„ ํŠธ๋ฆญ์ด ์žˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ ์›Œํฌํ”Œ๋กœ์šฐ์— ์ƒํƒœ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋Šฅ๋ ฅ์ž…๋‹ˆ๋‹ค. + +### ์ƒํƒœ ๊ด€๋ฆฌ + +์ƒํƒœ ๊ด€๋ฆฌ๋Š” ์›Œํฌํ”Œ๋กœ์šฐ์˜ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉํ•˜๋ฏ€๋กœ, ๋ชจ๋“  ๋‹จ๊ณ„๊ฐ€ ๋™์ผํ•œ ์ƒํƒœ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋‹จ๊ณ„ ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์œ„์— `Context` ํƒ€์ž… ํžŒํŒ…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.core.workflow import Context, StartEvent, StopEvent + + +@step +async def query(self, ctx: Context, ev: StartEvent) -> StopEvent: + # ์ปจํ…์ŠคํŠธ์— ์ฟผ๋ฆฌ ์ €์žฅ + await ctx.store.set("query", "ํ”„๋ž‘์Šค์˜ ์ˆ˜๋„๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?") + + # ์ปจํ…์ŠคํŠธ์™€ ์ด๋ฒคํŠธ๋กœ ๋ฌด์–ธ๊ฐ€ ์ˆ˜ํ–‰ + val = ... + + # ์ปจํ…์ŠคํŠธ์—์„œ ์ฟผ๋ฆฌ ๊ฒ€์ƒ‰ + query = await ctx.store.get("query") + + return StopEvent(result=val) +``` + +ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ LlamaIndex์—์„œ ๊ธฐ๋ณธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค! + +์›Œํฌํ”Œ๋กœ์šฐ์—๋Š” ๋” ๋ณต์žกํ•œ ๋‰˜์•™์Šค๊ฐ€ ์žˆ์œผ๋ฉฐ, LlamaIndex ๋ฌธ์„œ์—์„œ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ `AgentWorkflow` ํด๋ž˜์Šค์— ์˜์กดํ•˜๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋กœ ์›Œํฌํ”Œ๋กœ์šฐ ์ž๋™ํ™” + +์ˆ˜๋™ ์›Œํฌํ”Œ๋กœ์šฐ ์ƒ์„ฑ ๋Œ€์‹  **`AgentWorkflow` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“ค** ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`AgentWorkflow`๋Š” ์›Œํฌํ”Œ๋กœ์šฐ ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „๋ฌธํ™”๋œ ๊ธฐ๋Šฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ˜‘์—…ํ•˜๊ณ  ์„œ๋กœ์—๊ฒŒ ์ž‘์—…์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. +์ด๋ฅผ ํ†ตํ•ด ์„œ๋กœ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ธก๋ฉด์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`llama_index.core.agent`์—์„œ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋Œ€์‹ , `llama_index.core.agent.workflow`์—์„œ ์—์ด์ „ํŠธ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +ํ•˜๋‚˜์˜ ์—์ด์ „ํŠธ๋Š” `AgentWorkflow` ์ƒ์„ฑ์ž์—์„œ ๋ฃจํŠธ ์—์ด์ „ํŠธ๋กœ ์ง€์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€๊ฐ€ ๋“ค์–ด์˜ค๋ฉด ๋จผ์ € ๋ฃจํŠธ ์—์ด์ „ํŠธ๋กœ ๋ผ์šฐํŒ…๋ฉ๋‹ˆ๋‹ค. + +๊ฐ ์—์ด์ „ํŠธ๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +- ํˆด์„ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์„ ์ง์ ‘ ์ฒ˜๋ฆฌ +- ์ž‘์—…์— ๋” ์ ํ•ฉํ•œ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์—๊ฒŒ ์ž‘์—… ๋„˜๊ธฐ๊ธฐ +- ์‚ฌ์šฉ์ž์—๊ฒŒ ์‘๋‹ต ๋ฐ˜ํ™˜ + +๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +```python +from llama_index.core.agent.workflow import AgentWorkflow, ReActAgent +from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI + +# ๋ช‡ ๊ฐ€์ง€ ํˆด ์ •์˜ +def add(a: int, b: int) -> int: + """๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•ฉ๋‹ˆ๋‹ค.""" + return a + b + +def multiply(a: int, b: int) -> int: + """๋‘ ์ˆซ์ž๋ฅผ ๊ณฑํ•ฉ๋‹ˆ๋‹ค.""" + return a * b + +llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") + +# FunctionTool ์—†์ด ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค -- ํ•จ์ˆ˜/๋…์ŠคํŠธ๋ง์ด ์ด๋ฆ„/์„ค๋ช…์„ ์œ„ํ•ด ํŒŒ์‹ฑ๋ฉ๋‹ˆ๋‹ค +multiply_agent = ReActAgent( + name="multiply_agent", + description="๋‘ ์ •์ˆ˜๋ฅผ ๊ณฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค", + system_prompt="์ˆซ์ž๋ฅผ ๊ณฑํ•˜๋Š” ํˆด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„์›€์ด ๋˜๋Š” ์–ด์‹œ์Šคํ„ดํŠธ์ž…๋‹ˆ๋‹ค.", + tools=[multiply], + llm=llm, +) + +addition_agent = ReActAgent( + name="add_agent", + description="๋‘ ์ •์ˆ˜๋ฅผ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค", + system_prompt="์ˆซ์ž๋ฅผ ๋”ํ•˜๋Š” ํˆด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„์›€์ด ๋˜๋Š” ์–ด์‹œ์Šคํ„ดํŠธ์ž…๋‹ˆ๋‹ค.", + tools=[add], + llm=llm, +) + +# ์›Œํฌํ”Œ๋กœ์šฐ ์ƒ์„ฑ +workflow = AgentWorkflow( + agents=[multiply_agent, addition_agent], + root_agent="multiply_agent", +) + +# ์‹œ์Šคํ…œ ์‹คํ–‰ +response = await workflow.run(user_msg="5์™€ 3์„ ๋”ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?") +``` + +์—์ด์ „ํŠธ ํˆด์€ ์•ž์„œ ์–ธ๊ธ‰ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ ์ƒํƒœ๋„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋ชจ๋“  ์—์ด์ „ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ดˆ๊ธฐ ์ƒํƒœ ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ƒํƒœ๋Š” ์›Œํฌํ”Œ๋กœ์šฐ ์ปจํ…์ŠคํŠธ์˜ ์ƒํƒœ ํ‚ค์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๊ฐ ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๊ฐ•ํ•˜๋Š” state_prompt์— ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค. + +์ด์ „ ์˜ˆ์ œ๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์„ธ๋Š” ์นด์šดํ„ฐ๋ฅผ ์ฃผ์ž…ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: + +```python +from llama_index.core.workflow import Context + +# ๋ช‡ ๊ฐ€์ง€ ํˆด ์ •์˜ +async def add(ctx: Context, a: int, b: int) -> int: + """๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•ฉ๋‹ˆ๋‹ค.""" + # ์นด์šดํŠธ ์—…๋ฐ์ดํŠธ + cur_state = await ctx.store.get("state") + cur_state["num_fn_calls"] += 1 + await ctx.store.set("state", cur_state) + + return a + b + +async def multiply(ctx: Context, a: int, b: int) -> int: + """๋‘ ์ˆซ์ž๋ฅผ ๊ณฑํ•ฉ๋‹ˆ๋‹ค.""" + # ์นด์šดํŠธ ์—…๋ฐ์ดํŠธ + cur_state = await ctx.store.get("state") + cur_state["num_fn_calls"] += 1 + await ctx.store.set("state", cur_state) + + return a * b + +... + +workflow = AgentWorkflow( + agents=[multiply_agent, addition_agent], + root_agent="multiply_agent", + initial_state={"num_fn_calls": 0}, + state_prompt="ํ˜„์žฌ ์ƒํƒœ: {state}. ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€: {msg}", +) + +# ์ปจํ…์ŠคํŠธ์™€ ํ•จ๊ป˜ ์›Œํฌํ”Œ๋กœ์šฐ ์‹คํ–‰ +ctx = Context(workflow) +response = await workflow.run(user_msg="5์™€ 3์„ ๋”ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?", ctx=ctx) + +# ์ƒํƒœ๋ฅผ ๊บผ๋‚ด์„œ ๊ฒ€์‚ฌ +state = await ctx.store.get("state") +print(state["num_fn_calls"]) +``` + +์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ LlamaIndex์—์„œ ์—์ด์ „ํŠธ์˜ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ + +์ง€์‹์„ ํ™•๊ณ ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ๋งˆ์ง€๋ง‰ ํ€ด์ฆˆ๋ฅผ ๊ณ„์†ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! ๐Ÿš€ diff --git a/units/ko/unit2/smolagents/code_agents.mdx b/units/ko/unit2/smolagents/code_agents.mdx new file mode 100644 index 00000000..fcba655d --- /dev/null +++ b/units/ko/unit2/smolagents/code_agents.mdx @@ -0,0 +1,389 @@ + + +# ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ + +์ฝ”๋“œ ์—์ด์ „ํŠธ๋Š” `smolagents`์˜ ๊ธฐ๋ณธ ์—์ด์ „ํŠธ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. ์ด๋“ค์€ ํŒŒ์ด์ฌ ๋„๊ตฌ ํ˜ธ์ถœ์„ ์ƒ์„ฑํ•˜์—ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ํšจ์œจ์ ์ด๊ณ  ํ‘œํ˜„๋ ฅ ์žˆ์œผ๋ฉฐ ์ •ํ™•ํ•œ ์•ก์…˜ ํ‘œํ˜„์„ ๋‹ฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Ÿฌํ•œ ๊ฐ„์†Œํ™”๋œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ํ•„์š”ํ•œ ์•ก์…˜ ์ˆ˜๋ฅผ ์ค„์ด๊ณ , ๋ณต์žกํ•œ ์ž‘์—…์„ ๋‹จ์ˆœํ™”ํ•˜๋ฉฐ, ๊ธฐ์กด ์ฝ”๋“œ ํ•จ์ˆ˜์˜ ์žฌ์‚ฌ์šฉ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. `smolagents`๋Š” ์•ฝ 1,000์ค„์˜ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„๋œ ๊ฒฝ๋Ÿ‰ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +![์ฝ”๋“œ vs JSON ์•ก์…˜](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/code_vs_json_actions.png) +์œ„ ์ด๋ฏธ์ง€๋Š” ๋…ผ๋ฌธ [Executable Code Actions Elicit Better LLM Agents](https://huggingface.co/papers/2402.01030)์—์„œ ๊ฐ€์ ธ์™”์Šต๋‹ˆ๋‹ค. + + +์ฝ”๋“œ ์—์ด์ „ํŠธ๊ฐ€ ์™œ ํšจ๊ณผ์ ์ธ์ง€ ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด, smolagents ๋ฌธ์„œ์˜ ์ด ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. + + +## ์™œ ์ฝ”๋“œ ์—์ด์ „ํŠธ์ธ๊ฐ€์š”? + +๋‹ค๋‹จ๊ณ„ ์—์ด์ „ํŠธ ํ”„๋กœ์„ธ์Šค์—์„œ LLM์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์™ธ๋ถ€ ๋„๊ตฌ ํ˜ธ์ถœ์„ ํฌํ•จํ•˜๋Š” ์•ก์…˜์„ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๋ฐฉ์‹์€ ๋„๊ตฌ ์ด๋ฆ„๊ณผ ์ธ์ž๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ง€์ •ํ•˜๋Š” JSON ํ˜•์‹์„ ์‚ฌ์šฉํ•˜๋ฉฐ, **์‹œ์Šคํ…œ์ด ์–ด๋–ค ๋„๊ตฌ๋ฅผ ์‹คํ–‰ํ• ์ง€ ํŒŒ์‹ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค**. + +ํ•˜์ง€๋งŒ ์—ฐ๊ตฌ ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅด๋ฉด, **๋„๊ตฌ ํ˜ธ์ถœ LLM์€ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋” ํšจ๊ณผ์ ์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค**. ์ด๊ฒƒ์ด `smolagents`์˜ ํ•ต์‹ฌ ์›์น™์ด๋ฉฐ, ์œ„์˜ ๋…ผ๋ฌธ ์ด๋ฏธ์ง€์—์„œ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ฝ”๋“œ๋กœ ์•ก์…˜์„ ์ž‘์„ฑํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฃผ์š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค: + +* **์กฐํ•ฉ์„ฑ**: ์•ก์…˜์„ ์‰ฝ๊ฒŒ ๊ฒฐํ•ฉํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* **๊ฐ์ฒด ๊ด€๋ฆฌ**: ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ๋ณต์žกํ•œ ๊ตฌ์กฐ๋ฅผ ์ง์ ‘ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* **๋ฒ”์šฉ์„ฑ**: ๊ณ„์‚ฐ์ ์œผ๋กœ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์ž‘์—…์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* **LLM์— ์ž์—ฐ์Šค๋Ÿฌ์›€**: ๊ณ ํ’ˆ์งˆ ์ฝ”๋“œ๋Š” ์ด๋ฏธ LLM์˜ ํ•™์Šต ๋ฐ์ดํ„ฐ์— ํ’๋ถ€ํ•˜๊ฒŒ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +## ์ฝ”๋“œ ์—์ด์ „ํŠธ๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋‚˜์š”? + +![https://huggingface.co/docs/smolagents/conceptual_guides/react์—์„œ ๊ฐ€์ ธ์˜ด](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/codeagent_docs.png) + +์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์€ `CodeAgent.run()`์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์ด๋Š” 1๋‹จ์›์—์„œ ์–ธ๊ธ‰ํ•œ ReAct ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. `smolagents`์—์„œ ์—์ด์ „ํŠธ์˜ ์ฃผ์š” ์ถ”์ƒํ™”๋Š” `MultiStepAgent`์ด๋ฉฐ, ์ด๋Š” ํ•ต์‹ฌ ๋นŒ๋”ฉ ๋ธ”๋ก ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. `CodeAgent`๋Š” ํŠน๋ณ„ํ•œ ์ข…๋ฅ˜์˜ `MultiStepAgent`์ž…๋‹ˆ๋‹ค. + +`CodeAgent`๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๋ณ€์ˆ˜์™€ ์ง€์‹์€ ์‹คํ–‰ ๋กœ๊ทธ์— ์ €์žฅ๋˜์–ด ์—์ด์ „ํŠธ์˜ ์ปจํ…์ŠคํŠธ๋กœ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค: + +1. ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ๋Š” `SystemPromptStep`์— ์ €์žฅ๋˜๊ณ , ์‚ฌ์šฉ์ž ์ฟผ๋ฆฌ๋Š” `TaskStep`์— ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. + +2. ๊ทธ ๋‹ค์Œ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ while ๋ฃจํ”„๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค: + + 2.1 `agent.write_memory_to_messages()` ๋ฉ”์„œ๋“œ๋Š” ์—์ด์ „ํŠธ์˜ ๋กœ๊ทธ๋ฅผ LLM์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” [์ฑ„ํŒ… ๋ฉ”์‹œ์ง€](https://huggingface.co/docs/transformers/main/en/chat_templating) ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + + 2.2 ์ด ๋ฉ”์‹œ์ง€๋“ค์€ `Model`๋กœ ์ „์†ก๋˜์–ด ์‘๋‹ต์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + + 2.3 ์‘๋‹ต์—์„œ ์•ก์…˜์„ ์ถ”์ถœํ•˜๋Š”๋ฐ, ์ฝ”๋“œ ์—์ด์ „ํŠธ์ด๋ฏ€๋กœ ํŒŒ์ด์ฌ ์ฝ”๋“œ ์กฐ๊ฐ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + + 2.4 ์•ก์…˜์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. + + 2.5 ๊ฒฐ๊ณผ๊ฐ€ `ActionStep`์— ๋ฉ”๋ชจ๋ฆฌ๋กœ ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. + +๊ฐ ๋‹จ๊ณ„๊ฐ€ ๋๋‚  ๋•Œ, ์—์ด์ „ํŠธ์— ํ•จ์ˆ˜ ํ˜ธ์ถœ(`agent.step_callback`)์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋ฉด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. + +## ์˜ˆ์‹œ๋กœ ์•Œ์•„๋ณด๊ธฐ + + +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +Alfred๋Š” ์›จ์ธ ๊ฐ€๋ฌธ์˜ ์ €ํƒ์—์„œ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ์ˆœ์กฐ๋กญ๊ฒŒ ์ง„ํ–‰๋˜๋„๋ก ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๋‹ค๋‹จ๊ณ„ `CodeAgent`์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ ์šฉํ•ด๋ด…์‹œ๋‹ค. + +Alfred Party + +์•„์ง `smolagents`๋ฅผ ์„ค์น˜ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ์„ค์น˜ํ•˜์„ธ์š”: + +```bash +pip install smolagents -U +``` + +Hugging Face Hub์— ๋กœ๊ทธ์ธํ•˜์—ฌ Serverless Inference API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. + +```python +from huggingface_hub import login + +login() +``` + +### `smolagents`๋กœ ํŒŒํ‹ฐ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์„ ํƒํ•˜๊ธฐ + +์Œ์•…์€ ํŒŒํ‹ฐ์˜ ํ•„์ˆ˜ ์š”์†Œ์ž…๋‹ˆ๋‹ค! Alfred๋Š” ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ๊ณ ๋ฅด๋Š” ๋ฐ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„ `smolagents`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์›น ๊ฒ€์ƒ‰ ๋„๊ตฌ๋ฅผ ์—์ด์ „ํŠธ์— ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +Alfred Playlist + +๋ชจ๋ธ๋กœ๋Š” Hugging Face์˜ [Serverless Inference API](https://huggingface.co/docs/api-inference/index)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” `InferenceClientModel`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๋ชจ๋ธ์€ "Qwen/Qwen2.5-Coder-32B-Instruct"์ด๋ฉฐ, ๋น ๋ฅธ ์ถ”๋ก ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ—ˆ๋ธŒ์—์„œ ํ˜ธํ™˜๋˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋ธ๋„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์—์ด์ „ํŠธ ์‹คํ–‰์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค: + +```python +from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel + +agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=InferenceClientModel()) + +agent.run("์›จ์ธ ์ €ํƒ์—์„œ ์—ด๋ฆฌ๋Š” ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ์Œ์•… ์ถ”์ฒœ์„ ๊ฒ€์ƒ‰ํ•ด์ค˜.") +``` + +์ด ์˜ˆ์‹œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด **์›Œํฌํ”Œ๋กœ์šฐ ๋‹จ๊ณ„์˜ ์‹คํ–‰ ์ถ”์ **์ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ด์ฌ ์ฝ”๋“œ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค: + +```python + โ”€ ์‹คํ–‰๋œ ํŒŒ์‹ฑ ์ฝ”๋“œ: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + results = web_search(query="๋ฐฐํŠธ๋งจ ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ์Œ์•…") + print(results) + โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +``` + +๋ช‡ ๋‹จ๊ณ„ ํ›„, Alfred๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค! ๐ŸŽต + +### ๋งž์ถคํ˜• ๋„๊ตฌ๋กœ ๋ฉ”๋‰ด ์ค€๋น„ํ•˜๊ธฐ + +Alfred Menu + +ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ๊ณจ๋ž๋‹ค๋ฉด, ์ด์ œ ์†๋‹˜์„ ์œ„ํ•œ ๋ฉ”๋‰ด๋ฅผ ์ค€๋น„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Alfred๋Š” ์—ฌ๊ธฐ์„œ๋„ `smolagents`์˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋งž์ถคํ˜• ํ•จ์ˆ˜๋ฅผ ๋„๊ตฌ๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๋„๊ตฌ ์ƒ์„ฑ์— ๋Œ€ํ•ด์„œ๋Š” ์ดํ›„์— ๋” ์ž์„ธํžˆ ๋‹ค๋ฃจ๋‹ˆ, ์ง€๊ธˆ์€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด์„ธ์š”. + +์•„๋ž˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ, `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค๊ณ  `tools` ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. + +```python +from smolagents import CodeAgent, tool, InferenceClientModel + +# ํŒŒํ‹ฐ ์ƒํ™ฉ์— ๋งž๋Š” ๋ฉ”๋‰ด๋ฅผ ์ถ”์ฒœํ•˜๋Š” ๋„๊ตฌ +@tool +def suggest_menu(occasion: str) -> str: + """ + ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ฉ”๋‰ด๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. + Args: + occasion (str): ํŒŒํ‹ฐ ์œ ํ˜•. ํ—ˆ์šฉ ๊ฐ’: + - "casual": ์บ์ฃผ์–ผ ํŒŒํ‹ฐ ๋ฉ”๋‰ด + - "formal": ํฌ๋ฉ€ ํŒŒํ‹ฐ ๋ฉ”๋‰ด + - "superhero": ์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ ๋ฉ”๋‰ด + - "custom": ๋งž์ถค ๋ฉ”๋‰ด + """ + if occasion == "casual": + return "ํ”ผ์ž, ์Šค๋‚ต, ์Œ๋ฃŒ." + elif occasion == "formal": + return "3์ฝ”์Šค ๋””๋„ˆ, ์™€์ธ, ๋””์ €ํŠธ." + elif occasion == "superhero": + return "๊ณ ์—๋„ˆ์ง€, ๊ฑด๊ฐ•์‹ ๋ท”ํŽ˜." + else: + return "์ง‘์‚ฌ๋งŒ์„ ์œ„ํ•œ ๋งž์ถค ๋ฉ”๋‰ด." + +# Alfred๊ฐ€ ํŒŒํ‹ฐ ๋ฉ”๋‰ด๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค +agent = CodeAgent(tools=[suggest_menu], model=InferenceClientModel()) + +# ํŒŒํ‹ฐ๋ฅผ ์œ„ํ•œ ํฌ๋ฉ€ ๋ฉ”๋‰ด ์ค€๋น„ +agent.run("ํŒŒํ‹ฐ๋ฅผ ์œ„ํ•œ ํฌ๋ฉ€ ๋ฉ”๋‰ด๋ฅผ ์ค€๋น„ํ•ด์ค˜.") +``` + +์—์ด์ „ํŠธ๋Š” ๋ช‡ ๋‹จ๊ณ„ ์‹คํ–‰ ํ›„ ๋‹ต์„ ์ฐพ์Šต๋‹ˆ๋‹ค. docstring์— ํ—ˆ์šฉ ๊ฐ’์„ ๋ช…ํ™•ํžˆ ์ ์œผ๋ฉด ์—์ด์ „ํŠธ๊ฐ€ `occasion` ์ธ์ž ๊ฐ’์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก ์œ ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋ฉ”๋‰ด ์ค€๋น„ ์™„๋ฃŒ! ๐Ÿฅ— + +### ์—์ด์ „ํŠธ ๋‚ด์—์„œ ํŒŒ์ด์ฌ import ์‚ฌ์šฉํ•˜๊ธฐ + +ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ์™€ ๋ฉ”๋‰ด๊ฐ€ ์ค€๋น„๋˜์—ˆ์œผ๋‹ˆ, ์ด์ œ ๋‚จ์€ ๊ฒƒ์€ ์ค€๋น„ ์‹œ๊ฐ„ ๊ณ„์‚ฐ์ž…๋‹ˆ๋‹ค! + +Alfred๋Š” ๋ชจ๋“  ์ค€๋น„๋ฅผ ์ง€๊ธˆ ์‹œ์ž‘ํ•˜๋ฉด ์–ธ์ œ ํŒŒํ‹ฐ๊ฐ€ ์ค€๋น„๋ ์ง€ ๊ณ„์‚ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•˜๋‹ค๋ฉด ๋‹ค๋ฅธ ์Šˆํผํžˆ์–ด๋กœ์˜ ๋„์›€๋„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒ ์ฃ . + +`smolagents`๋Š” ํŒŒ์ด์ฌ ์ฝ”๋“œ ์กฐ๊ฐ์„ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ์—์ด์ „ํŠธ์— ํŠนํ™”๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋ณด์•ˆ์„ ์œ„ํ•ด ์ƒŒ๋“œ๋ฐ•์Šค ์‹คํ–‰์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +**์ฝ”๋“œ ์‹คํ–‰์—๋Š” ์—„๊ฒฉํ•œ ๋ณด์•ˆ ์กฐ์น˜๊ฐ€ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค** โ€” ๊ธฐ๋ณธ์ ์œผ๋กœ ํ—ˆ์šฉ๋œ ๋ชฉ๋ก ์™ธ์˜ import๋Š” ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ `additional_authorized_imports`์— ๋ฌธ์ž์—ด๋กœ ์ถ”๊ฐ€ํ•˜๋ฉด import๋ฅผ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ž์„ธํ•œ ๋ณด์•ˆ ์‹คํ–‰ ๋ฐฉ๋ฒ•์€ ๊ณต์‹ [๊ฐ€์ด๋“œ](https://huggingface.co/docs/smolagents/tutorials/secure_code_execution)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” `datetime` ๋ชจ๋“ˆ import๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. + +```python +from smolagents import CodeAgent, InferenceClientModel +import numpy as np +import time +import datetime + +agent = CodeAgent(tools=[], model=InferenceClientModel(), additional_authorized_imports=['datetime']) + +agent.run( + """ + Alfred๊ฐ€ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—… ๋ชฉ๋ก: + 1. ์Œ๋ฃŒ ์ค€๋น„ - 30๋ถ„ + 2. ์ €ํƒ ์žฅ์‹ - 60๋ถ„ + 3. ๋ฉ”๋‰ด ์„ธํŒ… - 45๋ถ„ + 4. ์Œ์•… ๋ฐ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ค€๋น„ - 45๋ถ„ + + ์ง€๊ธˆ ๋ฐ”๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํŒŒํ‹ฐ ์ค€๋น„๊ฐ€ ์–ธ์ œ ๋๋‚ ๊นŒ์š”? + """ +) +``` + +์ด ์˜ˆ์‹œ๋“ค์€ ์ฝ”๋“œ ์—์ด์ „ํŠธ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์˜ ์‹œ์ž‘์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ๋‚ด์šฉ์€ [smolagents ๋ฌธ์„œ](https://huggingface.co/docs/smolagents)์—์„œ ํ™•์ธํ•˜์„ธ์š”. + +์š”์•ฝํ•˜์ž๋ฉด, `smolagents`๋Š” ํŒŒ์ด์ฌ ์ฝ”๋“œ ์กฐ๊ฐ์„ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ์—์ด์ „ํŠธ์— ํŠนํ™”๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋ณด์•ˆ ์ƒŒ๋“œ๋ฐ•์Šค ์‹คํ–‰์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋กœ์ปฌ ๋ฐ API ๊ธฐ๋ฐ˜ ์–ธ์–ด ๋ชจ๋ธ ๋ชจ๋‘ ์ง€์›ํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. + +### ์šฐ๋ฆฌ๋งŒ์˜ ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ๋ฅผ ํ—ˆ๋ธŒ์— ๊ณต์œ ํ•˜๊ธฐ + +์šฐ๋ฆฌ๋งŒ์˜ Alfred ์—์ด์ „ํŠธ๋ฅผ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ •๋ง ๋ฉ‹์ง€์ง€ ์•Š์„๊นŒ์š”? ๋ˆ„๊ตฌ๋‚˜ ํ—ˆ๋ธŒ์—์„œ ์‰ฝ๊ฒŒ ๋‹ค์šด๋กœ๋“œํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! `smolagents`๋Š” ์™„์„ฑ๋œ ์—์ด์ „ํŠธ๋ฅผ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๊ณต์œ ํ•˜๊ณ , ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ ์—์ด์ „ํŠธ๋ฅผ ์ฆ‰์‹œ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค: + +```python +# ์‚ฌ์šฉ์ž๋ช…๊ณผ ์ €์žฅ์†Œ๋ช…์„ ๋ณ€๊ฒฝํ•˜์„ธ์š” +agent.push_to_hub('sergiopaniego/AlfredAgent') +``` + +๋‹ค์‹œ ๋‹ค์šด๋กœ๋“œํ•˜๋ ค๋ฉด ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”: + +```python +# ์‚ฌ์šฉ์ž๋ช…๊ณผ ์ €์žฅ์†Œ๋ช…์„ ๋ณ€๊ฒฝํ•˜์„ธ์š” +alfred_agent = agent.from_hub('sergiopaniego/AlfredAgent', trust_remote_code=True) + +alfred_agent.run("์›จ์ธ ์ €ํƒ์—์„œ ์—ด๋ฆฌ๋Š” ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ•ด์ค˜. ํŒŒํ‹ฐ ํ…Œ๋งˆ๋Š” '๋นŒ๋Ÿฐ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ'์•ผ") +``` + +๊ณต์œ ๋œ ์—์ด์ „ํŠธ๋Š” Hugging Face Spaces์—์„œ๋„ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. [์—ฌ๊ธฐ](https://huggingface.co/spaces/davidberenstein1957/smolagents-and-tools)์—์„œ ๋‹ค์–‘ํ•œ ์—์ด์ „ํŠธ๋ฅผ ํƒ์ƒ‰ํ•ด๋ณด์„ธ์š”. + +์˜ˆ๋ฅผ ๋“ค์–ด, _AlfredAgent_๋Š” [์—ฌ๊ธฐ](https://huggingface.co/spaces/sergiopaniego/AlfredAgent)์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ ์ง์ ‘ ์ฒดํ—˜ํ•ด๋ณด์„ธ์š”: + + + +Alfred๊ฐ€ ์–ด๋–ป๊ฒŒ ์ด๋Ÿฐ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ๋Š”์ง€ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด, ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ํ†ตํ•ฉํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ์—์ด์ „ํŠธ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋„๊ตฌ์— ๋Œ€ํ•ด์„œ๋Š” ์ดํ›„์— ์ž์„ธํžˆ ๋‹ค๋ฃจ๋‹ˆ, ์ง€๊ธˆ์€ ๊ตฌ์กฐ๋งŒ ์ฐธ๊ณ ํ•˜์„ธ์š”: + +```python +from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, InferenceClientModel, Tool, tool, VisitWebpageTool + +@tool +def suggest_menu(occasion: str) -> str: + """ + ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ฉ”๋‰ด๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. + Args: + occasion: ํŒŒํ‹ฐ ์œ ํ˜• + """ + if occasion == "casual": + return "ํ”ผ์ž, ์Šค๋‚ต, ์Œ๋ฃŒ." + elif occasion == "formal": + return "3์ฝ”์Šค ๋””๋„ˆ, ์™€์ธ, ๋””์ €ํŠธ." + elif occasion == "superhero": + return "๊ณ ์—๋„ˆ์ง€, ๊ฑด๊ฐ•์‹ ๋ท”ํŽ˜." + else: + return "์ง‘์‚ฌ๋งŒ์„ ์œ„ํ•œ ๋งž์ถค ๋ฉ”๋‰ด." + +@tool +def catering_service_tool(query: str) -> str: + """ + ์ด ๋„๊ตฌ๋Š” ๊ณ ๋‹ด์‹œ์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + + Args: + query: ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค ๊ฒ€์ƒ‰์–ด + """ + # ์˜ˆ์‹œ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค์™€ ํ‰์  + services = { + "Gotham Catering Co.": 4.9, + "Wayne Manor Catering": 4.8, + "Gotham City Events": 4.7, + } + + # ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์„œ๋น„์Šค ์ฐพ๊ธฐ(๊ฒ€์ƒ‰์–ด ํ•„ํ„ฐ๋ง ์‹œ๋ฎฌ๋ ˆ์ด์…˜) + best_service = max(services, key=services.get) + + return best_service + +class SuperheroPartyThemeTool(Tool): + name = "superhero_party_theme_generator" + description = """ + ์ด ๋„๊ตฌ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์— ๋”ฐ๋ผ ์ฐฝ์˜์ ์ธ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. + ๊ณ ์œ ํ•œ ํŒŒํ‹ฐ ํ…Œ๋งˆ ์•„์ด๋””์–ด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" + + inputs = { + "category": { + "type": "string", + "description": "์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ ์œ ํ˜•(์˜ˆ: 'classic heroes', 'villain masquerade', 'futuristic Gotham')", + } + } + + output_type = "string" + + def forward(self, category: str): + themes = { + "classic heroes": "Justice League Gala: ์†๋‹˜๋“ค์ด DC ์˜์›…์œผ๋กœ ๋ถ„์žฅํ•˜๊ณ  'ํฌ๋ฆฝํ† ๋‚˜์ดํŠธ ํŽ€์น˜' ๊ฐ™์€ ํ…Œ๋งˆ ์นตํ…Œ์ผ์„ ์ฆ๊น๋‹ˆ๋‹ค.", + "villain masquerade": "Gotham Rogues' Ball: ์†๋‹˜๋“ค์ด ๋ฐฐํŠธ๋งจ ๋นŒ๋Ÿฐ์œผ๋กœ ๋ถ„์žฅํ•˜๋Š” ์‹ ๋น„๋กœ์šด ๊ฐ€๋ฉด๋ฌด๋„ํšŒ.", + "futuristic Gotham": "Neo-Gotham Night: ๋ฐฐํŠธ๋งจ ๋น„์š˜๋“œ์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ์‚ฌ์ด๋ฒ„ํŽ‘ํฌ ์Šคํƒ€์ผ ํŒŒํ‹ฐ, ๋„ค์˜จ ์žฅ์‹๊ณผ ๋ฏธ๋ž˜ํ˜• ์†Œํ’ˆ.", + } + + return themes.get(category.lower(), "ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. 'classic heroes', 'villain masquerade', 'futuristic Gotham' ์ค‘์—์„œ ์‹œ๋„ํ•ด๋ณด์„ธ์š”.") + + +# Alfred๊ฐ€ ํŒŒํ‹ฐ ๋ฉ”๋‰ด๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค +agent = CodeAgent( + tools=[ + DuckDuckGoSearchTool(), + VisitWebpageTool(), + suggest_menu, + catering_service_tool, + SuperheroPartyThemeTool(), + FinalAnswerTool() + ], + model=InferenceClientModel(), + max_steps=10, + verbosity_level=2 +) + +agent.run("์›จ์ธ ์ €ํƒ์—์„œ ์—ด๋ฆฌ๋Š” ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ•ด์ค˜. ํŒŒํ‹ฐ ํ…Œ๋งˆ๋Š” '๋นŒ๋Ÿฐ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ'์•ผ") +``` + +์ด์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ๊ฒฐํ•ฉํ•ด `CodeAgent`๋ฅผ ๋งŒ๋“ค๋ฉด, ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ถ๊ทน์˜ ํŒŒํ‹ฐ ํ”Œ๋ž˜๋„ˆ๊ฐ€ ์™„์„ฑ๋ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ + +์ด์ œ ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค: ์ž์‹ ๋งŒ์˜ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ํ—ˆ๋ธŒ์— ๊ณต์œ ํ•ด๋ณด์„ธ์š”! ๐Ÿ•ต๏ธโ€โ™‚๏ธ๐Ÿ’ก + + +์—ฌ๋Ÿฌ๋ถ„์˜ ์—์ด์ „ํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ณต์œ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, Hugging Face Hub์— space๋ฅผ ๋งŒ๋“ค๊ณ  agents-course ํƒœ๊ทธ๋ฅผ ๋‹ฌ์•„์ฃผ์„ธ์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ์ž‘ํ’ˆ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค! + + +### OpenTelemetry์™€ Langfuse๋กœ ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ ์ถ”์ ํ•˜๊ธฐ ๐Ÿ“ก + +Alfred๋Š” ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ๋ฅผ ๋‹ค๋“ฌ์œผ๋ฉด์„œ ์‹คํ–‰์„ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐ ์ง€์ณ๊ฐ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ , ๋™์ž‘์„ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ถ๊ทน์˜ ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ฐฐํฌํ•˜๋ ค๋ฉด, ๋ฏธ๋ž˜์˜ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๋ถ„์„์„ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ์ถ”์  ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์„œ๋„ `smolagents`๊ฐ€ ํ•ด๊ฒฐ์ฑ…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค! [OpenTelemetry](https://opentelemetry.io/) ํ‘œ์ค€์„ ์ฑ„ํƒํ•ด ์—์ด์ „ํŠธ ์‹คํ–‰์„ ๊ณ„์ธกํ•˜๊ณ , [Langfuse](https://langfuse.com/) ๋ฐ `SmolagentsInstrumentor`๋ฅผ ํ†ตํ•ด ๋™์ž‘์„ ์‰ฝ๊ฒŒ ์ถ”์ ยท๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์„ค์ • ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค! + +๋จผ์ €, ํ•„์š”ํ•œ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค: + +```bash +pip install opentelemetry-sdk opentelemetry-exporter-otlp openinference-instrumentation-smolagents +``` + +Alfred๋Š” ์ด๋ฏธ Langfuse ๊ณ„์ •์„ ๋งŒ๋“ค๊ณ  API ํ‚ค๋ฅผ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์•„์ง ๊ณ„์ •์ด ์—†๋‹ค๋ฉด [์—ฌ๊ธฐ](https://cloud.langfuse.com/)์—์„œ ๊ฐ€์ž…ํ•˜๊ฑฐ๋‚˜ [๋Œ€์•ˆ](https://huggingface.co/docs/smolagents/tutorials/inspect_runs)์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +API ํ‚ค๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค: + +```python +import os +import base64 + +LANGFUSE_PUBLIC_KEY="pk-lf-..." +LANGFUSE_SECRET_KEY="sk-lf-..." +LANGFUSE_AUTH=base64.b64encode(f"{LANGFUSE_PUBLIC_KEY}:{LANGFUSE_SECRET_KEY}".encode()).decode() + +os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://cloud.langfuse.com/api/public/otel" # EU ๋ฐ์ดํ„ฐ ๋ฆฌ์ „ +# os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://us.cloud.langfuse.com/api/public/otel" # US ๋ฐ์ดํ„ฐ ๋ฆฌ์ „ +os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {LANGFUSE_AUTH}" +``` + +๋งˆ์ง€๋ง‰์œผ๋กœ, `SmolagentsInstrumentor`๋ฅผ ์ดˆ๊ธฐํ™”ํ•ด ์ถ”์ ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +```python +from opentelemetry.sdk.trace import TracerProvider + +from openinference.instrumentation.smolagents import SmolagentsInstrumentor +from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter +from opentelemetry.sdk.trace.export import SimpleSpanProcessor + +trace_provider = TracerProvider() +trace_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter())) + +SmolagentsInstrumentor().instrument(tracer_provider=trace_provider) +``` + +์ด์ œ Alfred๋Š” ์—ฐ๊ฒฐ ์™„๋ฃŒ! ๐Ÿ”Œ `smolagents`์˜ ์‹คํ–‰์ด Langfuse์— ๊ธฐ๋ก๋˜์–ด, ์—์ด์ „ํŠธ์˜ ๋™์ž‘์„ ์™„๋ฒฝํ•˜๊ฒŒ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์„ค์ •์œผ๋กœ ์ด์ „ ์‹คํ–‰์„ ๋‹ค์‹œ ํ™•์ธํ•˜๊ณ , ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ๋ฅผ ๋”์šฑ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์—์ด์ „ํŠธ ์ถ”์  ๋ฐ ํ‰๊ฐ€ ๋ฐ์ดํ„ฐ ํ™œ์šฉ๋ฒ•์€ ๋ณด๋„ˆ์Šค 2๋‹จ์›์—์„œ ๋” ์ž์„ธํžˆ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +```python +from smolagents import CodeAgent, InferenceClientModel + +agent = CodeAgent(tools=[], model=InferenceClientModel()) +alfred_agent = agent.from_hub('sergiopaniego/AlfredAgent', trust_remote_code=True) +alfred_agent.run("์›จ์ธ ์ €ํƒ์—์„œ ์—ด๋ฆฌ๋Š” ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ•ด์ค˜. ํŒŒํ‹ฐ ํ…Œ๋งˆ๋Š” '๋นŒ๋Ÿฐ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ'์•ผ") +``` + +Alfred๋Š” ์ด์ œ [์—ฌ๊ธฐ](https://cloud.langfuse.com/project/cm7bq0abj025rad078ak3luwi/traces/995fc019255528e4f48cf6770b0ce27b?timestamp=2025-02-19T10%3A28%3A36.929Z)์—์„œ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +์‹คํ–‰ ์ค‘์— ์ž‘์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์—์„œ ์˜ค๋ฅ˜๋ฅผ ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ๋‚˜์š”? ์—์ด์ „ํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์œ ํšจํ•œ ๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€ ์ถ”์ ํ•ด๋ณด์„ธ์š”. ์—ฌ๊ธฐ์—์„œ ์˜ค๋ฅ˜๋ฅผ ์ง์ ‘ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์˜ค๋ฅ˜๋Š” ์ด๋ฏธ ์ˆ˜์ •๋˜์—ˆ์œผ๋ฉฐ, ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด ์ด์Šˆ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +ํ•œํŽธ, [์ถ”์ฒœ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ](https://open.spotify.com/playlist/0gZMMHjuxMrrybQ7wTMTpw)๊ฐ€ ํŒŒํ‹ฐ ์ค€๋น„ ๋ถ„์œ„๊ธฐ๋ฅผ ์™„์„ฑํ•ด์ค๋‹ˆ๋‹ค. ๋ฉ‹์ง€์ฃ ? ๐ŸŽถ + +--- + +์ด์ œ ์ฒซ ๋ฒˆ์งธ ์ฝ”๋“œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ, **์ด์ œ smolagents์—์„œ ์ œ๊ณตํ•˜๋Š” ๋‘ ๋ฒˆ์งธ ์—์ด์ „ํŠธ ์œ ํ˜•์ธ Tool Calling Agent ๋งŒ๋“œ๋Š” ๋ฒ•**์„ ๋ฐฐ์›Œ๋ด…์‹œ๋‹ค. + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [smolagents ๋ธ”๋กœ๊ทธ](https://huggingface.co/blog/smolagents) - smolagents ๋ฐ ์ฝ”๋“œ ์ธํ„ฐ๋ž™์…˜ ์†Œ๊ฐœ +- [smolagents: ์ข‹์€ ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - ์‹ ๋ขฐ์„ฑ ๋†’์€ ์—์ด์ „ํŠธ ๊ตฌ์ถ•์„ ์œ„ํ•œ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค +- [Anthropic: ํšจ๊ณผ์ ์ธ ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ](https://www.anthropic.com/research/building-effective-agents) - ์—์ด์ „ํŠธ ์„ค๊ณ„ ์›์น™ +- [OpenTelemetry๋กœ ์‹คํ–‰ ๊ณต์œ ํ•˜๊ธฐ](https://huggingface.co/docs/smolagents/tutorials/inspect_runs) - ์—์ด์ „ํŠธ ์ถ”์  ์„ค์ • ๋ฐฉ๋ฒ• diff --git a/units/ko/unit2/smolagents/conclusion.mdx b/units/ko/unit2/smolagents/conclusion.mdx new file mode 100644 index 00000000..a50f77b2 --- /dev/null +++ b/units/ko/unit2/smolagents/conclusion.mdx @@ -0,0 +1,11 @@ +# ๊ฒฐ๋ก  + +`smolagents` ๋ชจ๋“ˆ(2๋‹จ์›)์„ ๋งˆ์นœ ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค ๐Ÿฅณ + +์ด์ œ `smolagents`์˜ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ๊ณ , ๋‚˜๋งŒ์˜ ์—์ด์ „ํŠธ๋„ ๋งŒ๋“ค์–ด๋ณด์•˜์Šต๋‹ˆ๋‹ค! ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ๊ด€์‹ฌ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์—์ด์ „ํŠธ๋ฅผ ์ง์ ‘ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์—ญ๋Ÿ‰์„ ๊ฐ–์ถ”์—ˆ์Šต๋‹ˆ๋‹ค. + +๋‹ค์Œ ๋ชจ๋“ˆ์—์„œ๋Š” **LlamaIndex๋กœ ์—์ด์ „ํŠธ ๋งŒ๋“œ๋Š” ๋ฒ•**์„ ๋ฐฐ์šธ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. + +๋งˆ์ง€๋ง‰์œผ๋กœ, **์ด ๊ณผ์ •์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์˜๊ฒฌ๊ณผ ๊ฐœ์„ ์ **์„ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ํ”ผ๋“œ๋ฐฑ์ด ์žˆ๋‹ค๋ฉด ๐Ÿ‘‰ [์ด ์–‘์‹](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog)์„ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”. + +### ๊ณ„์† ๋ฐฐ์šฐ๊ณ , ๋ฉ‹์ง„ ํ•˜๋ฃจ ๋ณด๋‚ด์„ธ์š” ๐Ÿค— diff --git a/units/ko/unit2/smolagents/final_quiz.mdx b/units/ko/unit2/smolagents/final_quiz.mdx new file mode 100644 index 00000000..28658723 --- /dev/null +++ b/units/ko/unit2/smolagents/final_quiz.mdx @@ -0,0 +1,25 @@ +# ์‹œํ—˜ ์‹œ๊ฐ„! + +`smolagents` ํ•™์Šต์„ ๋งˆ์นœ ์—ฌ๋Ÿฌ๋ถ„, ์ •๋ง ์ˆ˜๊ณ  ๋งŽ์œผ์…จ์Šต๋‹ˆ๋‹ค! ์ด์ œ ํ€ด์ฆˆ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ง€์‹์„ ์ ๊ฒ€ํ•ด๋ณผ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ๐Ÿง  + +## ์•ˆ๋‚ด์‚ฌํ•ญ + +- ํ€ด์ฆˆ๋Š” ์ฝ”๋“œ ๋ฌธ์ œ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ฝ”๋“œ ์กฐ๊ฐ์„ ์™„์„ฑํ•˜๋Š” ์ง€์‹œ์‚ฌํ•ญ์ด ์ฃผ์–ด์ง‘๋‹ˆ๋‹ค. +- ์•ˆ๋‚ด๋ฅผ ์ž˜ ์ฝ๊ณ , ์ฝ”๋“œ ์กฐ๊ฐ์„ ์™„์„ฑํ•ด ์ฃผ์„ธ์š”. +- ๊ฐ ๋ฌธ์ œ๋งˆ๋‹ค ๊ฒฐ๊ณผ์™€ ํ”ผ๋“œ๋ฐฑ์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. + +๐Ÿง˜ **์ด ํ€ด์ฆˆ๋Š” ์ ์ˆ˜ํ™”๋˜๊ฑฐ๋‚˜ ์ธ์ฆ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**. ์—ฌ๋Ÿฌ๋ถ„์ด `smolagents` ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž˜ ์ดํ•ดํ–ˆ๋Š”์ง€, ์ถ”๊ฐ€ ํ•™์Šต์ด ํ•„์š”ํ•œ์ง€ ์Šค์Šค๋กœ ์ ๊ฒ€ํ•˜๋Š” ์šฉ๋„์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ๋‹จ์›์—์„œ๋Š” ์ด ์ง€์‹์„ ์‹ค์ œ ์‚ฌ๋ก€์™€ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. + +์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”? + +## ํ€ด์ฆˆ ๐Ÿš€ + + + +ํ€ด์ฆˆ์— ์ง์ ‘ ์ฐธ์—ฌํ•˜๋ ค๋ฉด ๐Ÿ‘‰ [์—ฌ๊ธฐ](https://huggingface.co/spaces/agents-course/unit2_smolagents_quiz)๋กœ ์ด๋™ํ•˜์„ธ์š”. \ No newline at end of file diff --git a/units/ko/unit2/smolagents/introduction.mdx b/units/ko/unit2/smolagents/introduction.mdx new file mode 100644 index 00000000..569d43f5 --- /dev/null +++ b/units/ko/unit2/smolagents/introduction.mdx @@ -0,0 +1,67 @@ +# `smolagents` ์†Œ๊ฐœ + +Unit 2.1 Thumbnail + +์ด ๋ชจ๋“ˆ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ์—ฌ๊ธฐ์„œ๋Š” [`smolagents`](https://github.com/huggingface/smolagents) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•ด **ํšจ๊ณผ์ ์ธ ์—์ด์ „ํŠธ ๋งŒ๋“œ๋Š” ๋ฒ•**์„ ๋ฐฐ์›๋‹ˆ๋‹ค. `smolagents`๋Š” ๊ฐ•๋ ฅํ•œ AI ์—์ด์ „ํŠธ๋ฅผ ์†์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ฒฝ๋Ÿ‰ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. + +`smolagents`๋Š” Hugging Face์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. [`์ €์žฅ์†Œ`](https://github.com/huggingface/smolagents)์— **๋ณ„(star)**์„ ๋ˆŒ๋Ÿฌ ์‘์›ํ•ด ์ฃผ์„ธ์š”! +staring smolagents + +## ๋ชจ๋“ˆ ๊ฐœ์š” + +์ด ๋ชจ๋“ˆ์—์„œ๋Š” `smolagents`๋ฅผ ํ™œ์šฉํ•ด ์ง€๋Šฅํ˜• ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ํ•„์š”ํ•œ ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ์‹ค์ „ ์ „๋žต์„ ํญ๋„“๊ฒŒ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +์ˆ˜๋งŽ์€ ์˜คํ”ˆ์†Œ์Šค ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์กด์žฌํ•˜๋Š” ๋งŒํผ, `smolagents`์˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ ์žฅ๋‹จ์ ์„ ์ดํ•ดํ•˜๊ณ , ์–ธ์ œ ๋‹ค๋ฅธ ์†”๋ฃจ์…˜์ด ๋” ์ ํ•ฉํ• ์ง€ ํŒ๋‹จํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. + +์ด ๋‹จ์›์—์„œ๋Š” ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ์— ํŠนํ™”๋œ ์ฝ”๋“œ ์—์ด์ „ํŠธ, ๋ชจ๋“ˆํ˜• ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์œ„ํ•œ ํˆด ํ˜ธ์ถœ ์—์ด์ „ํŠธ, ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ยท์ข…ํ•ฉํ•˜๋Š” ๋ฆฌํŠธ๋ฆฌ๋ฒŒ ์—์ด์ „ํŠธ ๋“ฑ ์ฃผ์š” ์—์ด์ „ํŠธ ์œ ํ˜•์„ ์‚ดํŽด๋ด…๋‹ˆ๋‹ค. + +๋˜ํ•œ ์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๋ฅผ ์กฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•, ๋น„์ „ ๊ธฐ๋Šฅ ๋ฐ ์›น ๋ธŒ๋ผ์šฐ์ง• ํ†ตํ•ฉ ๋“ฑ ๋™์ ์ด๊ณ  ์ƒํ™ฉ ์ธ์‹์ด ๊ฐ€๋Šฅํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•๋„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +์ด๋ฒˆ ๋‹จ์›์—์„œ๋Š” 1๋‹จ์›์—์„œ ๋งŒ๋‚œ ์—์ด์ „ํŠธ Alfred๊ฐ€ ๋‹ค์‹œ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” `smolagents` ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ™œ์šฉํ•ด ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. Alfred๋Š” Wayne ์ €ํƒ์—์„œ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•˜๋ฉฐ ์—ฌ๋Ÿฌ ๊ณผ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Alfred์˜ ์—ฌ์ •์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ `smolagents`์˜ ํ•ต์‹ฌ ๊ฐœ๋…์„ ํ•จ๊ป˜ ์ตํ˜€๋ด…์‹œ๋‹ค! + + +์ด ๋‹จ์›์—์„œ๋Š” `smolagents` ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ AI ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์˜ ์—์ด์ „ํŠธ๋Š” ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰, ์ฝ”๋“œ ์‹คํ–‰, ์›นํŽ˜์ด์ง€ ์ƒํ˜ธ์ž‘์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๋ฅผ ์กฐํ•ฉํ•ด ๋” ๊ฐ•๋ ฅํ•œ ์‹œ์Šคํ…œ๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +![Alfred the agent](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit1/this-is-alfred.jpg) + +## ๋ชฉ์ฐจ + +์ด ๋‹จ์›์—์„œ ๋‹ค๋ฃจ๋Š” ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +### 1๏ธโƒฃ [์™œ smolagents๋ฅผ ์‚ฌ์šฉํ• ๊นŒ](./why_use_smolagents) + +`smolagents`๋Š” ๋‹ค์–‘ํ•œ ์˜คํ”ˆ์†Œ์Šค ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๋Œ€์•ˆ์œผ๋กœ๋Š” `LlamaIndex`, `LangGraph` ๋“ฑ์ด ์žˆ์œผ๋ฉฐ, ์ด ๊ณผ์ •์˜ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ ๋‹ค๋ฃน๋‹ˆ๋‹ค. `smolagents`๋Š” ํŠน์ • ์ƒํ™ฉ์— ์ ํ•ฉํ•œ ์—ฌ๋Ÿฌ ์ฃผ์š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ํ”„๋ ˆ์ž„์›Œํฌ ์„ ํƒ ์‹œ ํ•ญ์ƒ ๋‹ค์–‘ํ•œ ์˜ต์…˜์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” `smolagents`์˜ ์žฅ๋‹จ์ ์„ ์‚ดํŽด๋ณด๊ณ , ํ”„๋กœ์ ํŠธ ์š”๊ตฌ์— ๋”ฐ๋ผ ํ˜„๋ช…ํ•˜๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. + +### 2๏ธโƒฃ [CodeAgents](./code_agents) + +`CodeAgents`๋Š” `smolagents`์˜ ๊ธฐ๋ณธ ์—์ด์ „ํŠธ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. ์ด๋“ค์€ JSON์ด๋‚˜ ํ…์ŠคํŠธ ๋Œ€์‹  ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” CodeAgent์˜ ๋ชฉ์ , ๋™์ž‘ ๋ฐฉ์‹, ์‹ค์ „ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ๊ทธ ๊ธฐ๋Šฅ์„ ์‚ดํŽด๋ด…๋‹ˆ๋‹ค. + +### 3๏ธโƒฃ [ToolCallingAgents](./tool_calling_agents) + +`ToolCallingAgents`๋Š” `smolagents`๊ฐ€ ์ง€์›ํ•˜๋Š” ๋‘ ๋ฒˆ์งธ ์—์ด์ „ํŠธ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. CodeAgent๊ฐ€ ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, ์ด ์—์ด์ „ํŠธ๋Š” ์‹œ์Šคํ…œ์ด ํŒŒ์‹ฑยทํ•ด์„ํ•ด์•ผ ํ•˜๋Š” JSON/ํ…์ŠคํŠธ ๋ธ”๋กญ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” ToolCallingAgent์˜ ๋™์ž‘ ๋ฐฉ์‹, CodeAgent์™€์˜ ์ฐจ์ด์ , ์‚ฌ์šฉ ์˜ˆ์‹œ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +### 4๏ธโƒฃ [๋„๊ตฌ(Tools)](./tools) + +1๋‹จ์›์—์„œ ์‚ดํŽด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ, ๋„๊ตฌ๋Š” LLM์ด ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋กœ, ์—์ด์ „ํŠธ ํ–‰๋™์˜ ํ•ต์‹ฌ ๋นŒ๋”ฉ ๋ธ”๋ก์ž…๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” ๋„๊ตฌ ์ƒ์„ฑ๋ฒ•, ๊ตฌ์กฐ, `Tool` ํด๋ž˜์Šค์™€ `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•œ ๋‹ค์–‘ํ•œ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๋„๊ตฌ ์ƒ์ž, ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋„๊ตฌ ๊ณต์œ , ์ปค๋ฎค๋‹ˆํ‹ฐ ๋„๊ตฌ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋“ฑ๋„ ๋ฐฐ์›๋‹ˆ๋‹ค. + +### 5๏ธโƒฃ [๋ฆฌํŠธ๋ฆฌ๋ฒŒ ์—์ด์ „ํŠธ(Retrieval Agents)](./retrieval_agents) + +๋ฆฌํŠธ๋ฆฌ๋ฒŒ ์—์ด์ „ํŠธ๋Š” ๋ชจ๋ธ์ด ์ง€์‹ ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์—ฌ, ๋‹ค์–‘ํ•œ ์†Œ์Šค์—์„œ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ยท์ข…ํ•ฉยท์ถ”์ถœํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋“ค์€ ๋ฒกํ„ฐ ์Šคํ† ์–ด๋ฅผ ํ™œ์šฉํ•ด ํšจ์œจ์ ์œผ๋กœ ์ •๋ณด๋ฅผ ์ฐพ๊ณ , **RAG(Retrieval-Augmented Generation)** ํŒจํ„ด์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์›น ๊ฒ€์ƒ‰๊ณผ ๋งž์ถคํ˜• ์ง€์‹ ๋ฒ ์ด์Šค ํ†ตํ•ฉ, ๋Œ€ํ™” ๋งฅ๋ฝ ์œ ์ง€ ๋“ฑ ๋‹ค์–‘ํ•œ ์ „๋žต์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +### 6๏ธโƒฃ [๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ(Multi-Agent Systems)](./multi_agent_systems) + +์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์กฐ์œจํ•˜๋Š” ๊ฒƒ์€ ๊ฐ•๋ ฅํ•œ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ์›น ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ์™€ ์ฝ”๋“œ ์‹คํ–‰ ์—์ด์ „ํŠธ ๋“ฑ ๋‹ค์–‘ํ•œ ๋Šฅ๋ ฅ์„ ๊ฐ€์ง„ ์—์ด์ „ํŠธ๋ฅผ ์กฐํ•ฉํ•ด ๋” ์ •๊ตํ•œ ์†”๋ฃจ์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์˜ ์„ค๊ณ„, ๊ตฌํ˜„, ๊ด€๋ฆฌ ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +### 7๏ธโƒฃ [๋น„์ „ ๋ฐ ๋ธŒ๋ผ์šฐ์ € ์—์ด์ „ํŠธ(Vision and Browser agents)](./vision_agents) + +๋น„์ „ ์—์ด์ „ํŠธ๋Š” **๋น„์ „-์–ธ์–ด ๋ชจ๋ธ(VLM)**์„ ํ†ตํ•ฉํ•ด ์‹œ๊ฐ ์ •๋ณด๋ฅผ ์ฒ˜๋ฆฌยทํ•ด์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” VLM ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ ์„ค๊ณ„ยทํ†ตํ•ฉ๋ฒ•, ์ด๋ฏธ์ง€ ๊ธฐ๋ฐ˜ ์ถ”๋ก , ์‹œ๊ฐ ๋ฐ์ดํ„ฐ ๋ถ„์„, ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ์ƒํ˜ธ์ž‘์šฉ ๋“ฑ์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๋˜ํ•œ ๋น„์ „ ์—์ด์ „ํŠธ๋ฅผ ํ™œ์šฉํ•ด ์›น์„ ํƒ์ƒ‰ํ•˜๊ณ  ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ € ์—์ด์ „ํŠธ๋„ ๋งŒ๋“ค์–ด๋ด…๋‹ˆ๋‹ค. + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [smolagents ๊ณต์‹ ๋ฌธ์„œ](https://huggingface.co/docs/smolagents) +- [ํšจ๊ณผ์ ์ธ ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ](https://www.anthropic.com/research/building-effective-agents) - ์—์ด์ „ํŠธ ์•„ํ‚คํ…์ฒ˜ ์—ฐ๊ตฌ ๋…ผ๋ฌธ +- [์—์ด์ „ํŠธ ๊ฐ€์ด๋“œ๋ผ์ธ](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - ์‹ ๋ขฐ์„ฑ ๋†’์€ ์—์ด์ „ํŠธ ๊ตฌ์ถ•์„ ์œ„ํ•œ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค +- [LangGraph Agents](https://langchain-ai.github.io/langgraph/) - ๋‹ค์–‘ํ•œ ์—์ด์ „ํŠธ ๊ตฌํ˜„ ์˜ˆ์‹œ +- [Function Calling Guide](https://platform.openai.com/docs/guides/function-calling) - LLM์˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ดํ•ดํ•˜๊ธฐ +- [RAG ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค](https://www.pinecone.io/learn/retrieval-augmented-generation/) - ํšจ๊ณผ์ ์ธ RAG ๊ตฌํ˜„ ๊ฐ€์ด๋“œ diff --git a/units/ko/unit2/smolagents/multi_agent_systems.mdx b/units/ko/unit2/smolagents/multi_agent_systems.mdx new file mode 100644 index 00000000..820c5479 --- /dev/null +++ b/units/ko/unit2/smolagents/multi_agent_systems.mdx @@ -0,0 +1,381 @@ + + +# ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ + +๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์€ **ํŠนํ™”๋œ ์—์ด์ „ํŠธ๋“ค์ด ํ˜‘๋ ฅํ•˜์—ฌ ๋ณต์žกํ•œ ์ž‘์—…์„ ํ•ด๊ฒฐ**ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋ฉฐ, ๋ชจ๋“ˆ์„ฑ, ํ™•์žฅ์„ฑ, ๊ฒฌ๊ณ ์„ฑ์„ ๋†’์—ฌ์ค๋‹ˆ๋‹ค. ๋‹จ์ผ ์—์ด์ „ํŠธ์— ์˜์กดํ•˜๋Š” ๋Œ€์‹ , ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋Šฅ๋ ฅ์„ ๊ฐ€์ง„ ์—์ด์ „ํŠธ๋“ค์ด ์ž‘์—…์„ ๋ถ„๋‹ดํ•ฉ๋‹ˆ๋‹ค. + +**smolagents**์—์„œ๋Š” ๋‹ค์–‘ํ•œ ์—์ด์ „ํŠธ๋ฅผ ๊ฒฐํ•ฉํ•ด ํŒŒ์ด์ฌ ์ฝ”๋“œ ์ƒ์„ฑ, ์™ธ๋ถ€ ๋„๊ตฌ ํ˜ธ์ถœ, ์›น ๊ฒ€์ƒ‰ ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์—์ด์ „ํŠธ๋“ค์„ ์กฐ์œจํ•จ์œผ๋กœ์จ ๊ฐ•๋ ฅํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ผ๋ฐ˜์ ์ธ ๊ตฌ์„ฑ ์˜ˆ์‹œ: +- **๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ**: ์ž‘์—… ๋ถ„๋ฐฐ ๋‹ด๋‹น +- **์ฝ”๋“œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์—์ด์ „ํŠธ**: ์ฝ”๋“œ ์‹คํ–‰ ๋‹ด๋‹น +- **์›น ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ**: ์ •๋ณด ๊ฒ€์ƒ‰ ๋‹ด๋‹น + +์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ **๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ**๊ฐ€ **์ฝ”๋“œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ๋„๊ตฌ**์™€ **์›น ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ**๋ฅผ ์กฐ์œจํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์›น ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ๋Š” `DuckDuckGoSearchTool`๊ณผ `VisitWebpageTool` ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•ด ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค. + + + +## ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ์‹ค์ „ ์˜ˆ์‹œ + +๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์€ ์—ฌ๋Ÿฌ ํŠนํ™” ์—์ด์ „ํŠธ๊ฐ€ **์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ ์—์ด์ „ํŠธ**์˜ ์กฐ์œจ ์•„๋ž˜ ํ˜‘๋ ฅํ•˜๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ์—ญํ• ์ด ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๋“ค์—๊ฒŒ ์ž‘์—…์„ ๋ถ„์‚ฐ์‹œ์ผœ ๋ณต์žกํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, **๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ RAG ์‹œ์Šคํ…œ**์€ ๋‹ค์Œ์„ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +- **์›น ์—์ด์ „ํŠธ**: ์ธํ„ฐ๋„ท ๋ธŒ๋ผ์šฐ์ง• ๋‹ด๋‹น +- **๋ฆฌํŠธ๋ฆฌ๋ฒ„ ์—์ด์ „ํŠธ**: ์ง€์‹ ๋ฒ ์ด์Šค ์ •๋ณด ๊ฒ€์ƒ‰ ๋‹ด๋‹น +- **์ด๋ฏธ์ง€ ์ƒ์„ฑ ์—์ด์ „ํŠธ**: ์‹œ๊ฐ ์ž๋ฃŒ ์ƒ์„ฑ ๋‹ด๋‹น + +์ด ๋ชจ๋“  ์—์ด์ „ํŠธ๋Š” ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ๊ฐ€ ์ž‘์—… ๋ถ„๋ฐฐ์™€ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +## ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ๊ณ„์ธต ๊ตฌ์กฐ๋กœ ๋ณต์žกํ•œ ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ + + +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +๋ฆฌ์…‰์…˜์ด ๋‹ค๊ฐ€์˜ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค! ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์›€์œผ๋กœ Alfred๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ์ค€๋น„๋ฅผ ๋งˆ์ณค์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค: ๋ฐฐํŠธ๋ชจ๋นŒ์ด ์‚ฌ๋ผ์กŒ์Šต๋‹ˆ๋‹ค. Alfred๋Š” ๋Œ€์ฒด ์ฐจ๋Ÿ‰์„ ๋นจ๋ฆฌ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +๋‹คํ–‰ํžˆ ๋ธŒ๋ฃจ์Šค ์›จ์ธ์˜ ์‚ถ์„ ๋‹ค๋ฃฌ ๋ฐ”์ด์˜คํ”ฝ ์˜ํ™”๊ฐ€ ๋ช‡ ํŽธ ์ œ์ž‘๋˜์—ˆ์œผ๋‹ˆ, Alfred๋Š” ์˜ํ™” ์„ธํŠธ์žฅ์— ๋‚จ๊ฒจ์ง„ ์ฐจ๋Ÿ‰์„ ์ฐพ์•„ ํ˜„๋Œ€์‹์œผ๋กœ ๊ฐœ์กฐํ•  ์ˆ˜ ์žˆ์„์ง€๋„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ž์œจ์ฃผํ–‰ ๊ธฐ๋Šฅ๋„ ํ•„์ˆ˜๊ฒ ์ฃ . + +ํ•˜์ง€๋งŒ ์ด ์ฐจ๋Ÿ‰๋“ค์€ ์ „ ์„ธ๊ณ„ ์ดฌ์˜์ง€ ์–ด๋””์—๋‚˜ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ Alfred๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”? + +> ๐Ÿ‘‰ ์ „ ์„ธ๊ณ„ ๋ฐฐํŠธ๋งจ ์ดฌ์˜์ง€๋ฅผ ๋ชจ๋‘ ์ฐพ์•„, ๊ณ ๋‹ด(40.7128ยฐ N, 74.0060ยฐ W)๊นŒ์ง€ ํ™”๋ฌผ์„ (๋น„ํ–‰๊ธฐ)์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•˜๊ณ , ์ด๋ฅผ ์ง€๋„์— ํ‘œ์‹œํ•˜์„ธ์š”. ์ด๋™ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ์ƒ‰์ƒ์„ ๋‹ค๋ฅด๊ฒŒ ํ•˜๊ณ , ์Šˆํผ์นด ๊ณต์žฅ๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ํ‘œ์‹œํ•˜์„ธ์š”. + +ํ•จ๊ป˜ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค! + +์ด ์˜ˆ์‹œ์—๋Š” ์ถ”๊ฐ€ ํŒจํ‚ค์ง€๊ฐ€ ํ•„์š”ํ•˜๋‹ˆ ๋จผ์ € ์„ค์น˜ํ•ด ์ฃผ์„ธ์š”: + +```bash +pip install 'smolagents[litellm]' plotly geopandas shapely kaleido -q +``` + +### ๋จผ์ € ํ™”๋ฌผ๊ธฐ ์ด๋™ ์‹œ๊ฐ„ ๊ณ„์‚ฐ ๋„๊ตฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. + +```python +import math +from typing import Optional, Tuple + +from smolagents import tool + + +@tool +def calculate_cargo_travel_time( + origin_coords: Tuple[float, float], + destination_coords: Tuple[float, float], + cruising_speed_kmh: Optional[float] = 750.0, # ํ™”๋ฌผ๊ธฐ ํ‰๊ท  ์†๋„ +) -> float: + """ + ๋‘ ์ง€์ (์œ„๋„, ๊ฒฝ๋„) ๊ฐ„ ํ™”๋ฌผ๊ธฐ ์ด๋™ ์‹œ๊ฐ„์„ ๋Œ€๊ถŒ๊ฑฐ๋ฆฌ๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. + + Args: + origin_coords: ์ถœ๋ฐœ์ง€ (์œ„๋„, ๊ฒฝ๋„) ํŠœํ”Œ + destination_coords: ๋„์ฐฉ์ง€ (์œ„๋„, ๊ฒฝ๋„) ํŠœํ”Œ + cruising_speed_kmh: ์ˆœํ•ญ ์†๋„(km/h, ๊ธฐ๋ณธ๊ฐ’ 750) + + Returns: + float: ์˜ˆ์ƒ ์ด๋™ ์‹œ๊ฐ„(์‹œ๊ฐ„ ๋‹จ์œ„) + + Example: + >>> # ์‹œ์นด๊ณ (41.8781ยฐ N, 87.6298ยฐ W) โ†’ ์‹œ๋“œ๋‹ˆ(33.8688ยฐ S, 151.2093ยฐ E) + >>> result = calculate_cargo_travel_time((41.8781, -87.6298), (-33.8688, 151.2093)) + """ + + def to_radians(degrees: float) -> float: + return degrees * (math.pi / 180) + + # ์ขŒํ‘œ ๋ณ€ํ™˜ + lat1, lon1 = map(to_radians, origin_coords) + lat2, lon2 = map(to_radians, destination_coords) + + # ์ง€๊ตฌ ๋ฐ˜์ง€๋ฆ„(km) + EARTH_RADIUS_KM = 6371.0 + + # haversine ๊ณต์‹์œผ๋กœ ๋Œ€๊ถŒ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ + dlon = lon2 - lon1 + dlat = lat2 - lat1 + + a = ( + math.sin(dlat / 2) ** 2 + + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2 + ) + c = 2 * math.asin(math.sqrt(a)) + distance = EARTH_RADIUS_KM * c + + # ์šฐํšŒ ๊ฒฝ๋กœ, ๊ด€์ œ ๋“ฑ ๊ฐ์•ˆํ•ด 10% ์ถ”๊ฐ€ + actual_distance = distance * 1.1 + + # ๋น„ํ–‰ ์‹œ๊ฐ„ ๊ณ„์‚ฐ(์ด์ฐฉ๋ฅ™ 1์‹œ๊ฐ„ ์ถ”๊ฐ€) + flight_time = (actual_distance / cruising_speed_kmh) + 1.0 + + return round(flight_time, 2) + + +print(calculate_cargo_travel_time((41.8781, -87.6298), (-33.8688, 151.2093))) +``` + +### ์—์ด์ „ํŠธ ์„ค์ •ํ•˜๊ธฐ + +๋ชจ๋ธ ์ œ๊ณต์ž๋Š” Together AI๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. GoogleSearchTool์€ [Serper API](https://serper.dev)๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ `SERPAPI_API_KEY`(provider="serpapi") ๋˜๋Š” `SERPER_API_KEY`(provider=serper)๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +Serp API๊ฐ€ ์—†๋‹ค๋ฉด `DuckDuckGoSearchTool`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์†๋„ ์ œํ•œ์— ์œ ์˜ํ•˜์„ธ์š”. + +```python +import os +from PIL import Image +from smolagents import CodeAgent, GoogleSearchTool, InferenceClientModel, VisitWebpageTool + +model = InferenceClientModel(model_id="Qwen/Qwen2.5-Coder-32B-Instruct", provider="together") +``` + +๊ฐ„๋‹จํ•œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๊ธฐ๋ณธ ๋ฆฌํฌํŠธ๋ฅผ ๋ฐ›์•„๋ด…์‹œ๋‹ค. + +```python +task = """์ „ ์„ธ๊ณ„ ๋ฐฐํŠธ๋งจ ์ดฌ์˜์ง€๋ฅผ ๋ชจ๋‘ ์ฐพ์•„, ๊ณ ๋‹ด(40.7128ยฐ N, 74.0060ยฐ W)๊นŒ์ง€ ํ™”๋ฌผ๊ธฐ๋กœ ์ด๋™ํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•ด pandas ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜์„ธ์š”. ์Šˆํผ์นด ๊ณต์žฅ๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ํฌํ•จํ•˜์„ธ์š”.""" +``` + +```python +agent = CodeAgent( + model=model, + tools=[GoogleSearchTool("serper"), VisitWebpageTool(), calculate_cargo_travel_time], + additional_authorized_imports=["pandas"], + max_steps=20, +) +``` + +```python +result = agent.run(task) +``` + +```python +result +``` + +์‹คํ–‰ ๊ฒฐ๊ณผ ์˜ˆ์‹œ: + +```python +| | Location | Travel Time to Gotham (hours) | +|--|------------------------------------------------------|------------------------------| +| 0 | Necropolis Cemetery, Glasgow, Scotland, UK | 8.60 | +| 1 | St. George's Hall, Liverpool, England, UK | 8.81 | +| 2 | Two Temple Place, London, England, UK | 9.17 | +| 3 | Wollaton Hall, Nottingham, England, UK | 9.00 | +| 4 | Knebworth House, Knebworth, Hertfordshire, UK | 9.15 | +| 5 | Acton Lane Power Station, Acton Lane, Acton, UK | 9.16 | +| 6 | Queensboro Bridge, New York City, USA | 1.01 | +| 7 | Wall Street, New York City, USA | 1.00 | +| 8 | Mehrangarh Fort, Jodhpur, Rajasthan, India | 18.34 | +| 9 | Turda Gorge, Turda, Romania | 11.89 | +| 10 | Chicago, USA | 2.68 | +| 11 | Hong Kong, China | 19.99 | +| 12 | Cardington Studios, Northamptonshire, UK | 9.10 | +| 13 | Warner Bros. Leavesden Studios, Hertfordshire, UK | 9.13 | +| 14 | Westwood, Los Angeles, CA, USA | 6.79 | +| 15 | Woking, UK (McLaren) | 9.13 | +``` + +๊ณ„ํš ๋‹จ๊ณ„(planning step)๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ณด๊ฐ•ํ•˜๋ฉด ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ณ„ํš ๋‹จ๊ณ„๋Š” ์—์ด์ „ํŠธ๊ฐ€ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋ฏธ๋ฆฌ ์ƒ๊ฐํ•˜๊ณ  ๊ณ„ํšํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. + +```python +agent.planning_interval = 4 + +detailed_report = agent.run(f""" +์—ฌ๋Ÿฌ๋ถ„์€ ์ „๋ฌธ ๋ถ„์„๊ฐ€์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋ฐฉ๋ฌธํ•ด ์ข…ํ•ฉ ๋ฆฌํฌํŠธ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. +for ๋ฃจํ”„๋ฅผ ํ™œ์šฉํ•ด ์—ฌ๋Ÿฌ ์ฟผ๋ฆฌ๋ฅผ ํ•œ ๋ฒˆ์— ๊ฒ€์ƒ‰ํ•˜์„ธ์š”. +๊ฐ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ๋งˆ๋‹ค ์†Œ์Šค URL์„ ๋ฐฉ๋ฌธํ•ด ์ˆ˜์น˜๋ฅผ ํ™•์ธํ•˜์„ธ์š”. + +{task} +""") + +print(detailed_report) +``` + +```python +detailed_report +``` + +์‹คํ–‰ ๊ฒฐ๊ณผ ์˜ˆ์‹œ: + +```python +| | Location | Travel Time (hours) | +|--|--------------------------------------------------|---------------------| +| 0 | Bridge of Sighs, Glasgow Necropolis, Glasgow, UK | 8.6 | +| 1 | Wishart Street, Glasgow, Scotland, UK | 8.6 | +``` + +์ด์ฒ˜๋Ÿผ ํ”„๋กฌํ”„ํŠธ์™€ ๊ณ„ํš ๊ธฐ๋Šฅ๋งŒ์œผ๋กœ๋„ ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•œ ๋ฆฌํฌํŠธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! + +๋ชจ๋ธ์˜ ์ปจํ…์ŠคํŠธ ์œˆ๋„์šฐ๊ฐ€ ๋น ๋ฅด๊ฒŒ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค. **๋”ฐ๋ผ์„œ ์ƒ์„ธ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐํ•ฉํ•˜๋„๋ก ์š”์ฒญํ•˜๋ฉด ๋А๋ ค์ง€๊ณ  ํ† ํฐยท๋น„์šฉ์ด ๊ธ‰์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.** + +โžก๏ธ ์‹œ์Šคํ…œ ๊ตฌ์กฐ๋ฅผ ๊ฐœ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +### โœŒ๏ธ ๋‘ ์—์ด์ „ํŠธ๋กœ ์ž‘์—… ๋ถ„ํ• ํ•˜๊ธฐ + +๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ๊ตฌ์กฐ๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํ•˜์œ„ ์ž‘์—…์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•ด ๋‘ ๊ฐ€์ง€ ํฐ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค: +- ๊ฐ ์—์ด์ „ํŠธ๊ฐ€ ํ•ต์‹ฌ ์ž‘์—…์— ์ง‘์ค‘ํ•ด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค. +- ๋ฉ”๋ชจ๋ฆฌ ๋ถ„๋ฆฌ๋กœ ๊ฐ ๋‹จ๊ณ„์˜ ์ž…๋ ฅ ํ† ํฐ ์ˆ˜๊ฐ€ ์ค„์–ด, ์ง€์—ฐ๊ณผ ๋น„์šฉ์ด ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค. + +์›น ๊ฒ€์ƒ‰ ์ „๋‹ด ์—์ด์ „ํŠธ์™€ ์ด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ๋กœ ํŒ€์„ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. + +๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ๋Š” ์ตœ์ข… ๋ฆฌํฌํŠธ ์ž‘์„ฑ์„ ์œ„ํ•ด ์ถ”๊ฐ€ import(`plotly`, `geopandas`, `shapely`)๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +```python +model = InferenceClientModel( + "Qwen/Qwen2.5-Coder-32B-Instruct", provider="together", max_tokens=8096 +) + +web_agent = CodeAgent( + model=model, + tools=[ + GoogleSearchTool(provider="serper"), + VisitWebpageTool(), + calculate_cargo_travel_time, + ], + name="web_agent", + description="์›น์—์„œ ์ •๋ณด๋ฅผ ์ฐพ๋Š” ์—ญํ• ", + verbosity_level=0, + max_steps=10, +) +``` + +๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ๋Š” ๋” ๊ฐ•๋ ฅํ•œ ๋ชจ๋ธ [DeepSeek-R1](https://huggingface.co/deepseek-ai/DeepSeek-R1)์„ ์‚ฌ์šฉํ•˜๊ณ , `planning_interval`๋„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. + +```python +from smolagents.utils import encode_image_base64, make_image_url +from smolagents import OpenAIServerModel + + +def check_reasoning_and_plot(final_answer, agent_memory): + multimodal_model = OpenAIServerModel("gpt-4o", max_tokens=8096) + filepath = "saved_map.png" + assert os.path.exists(filepath), "saved_map.png ํŒŒ์ผ์ด ์ €์žฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!" + image = Image.open(filepath) + prompt = ( + f"๋‹ค์Œ์€ ์‚ฌ์šฉ์ž ์š”์ฒญ๊ณผ ์—์ด์ „ํŠธ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค: {agent_memory.get_succinct_steps()}. ์•„๋ž˜๋Š” ์ƒ์„ฑ๋œ ์ง€๋„์ž…๋‹ˆ๋‹ค." + "์ถ”๋ก  ๊ณผ์ •๊ณผ ์ง€๋„๊ฐ€ ์š”์ฒญ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”." + "๋จผ์ € ์ด์œ ๋ฅผ ๋‚˜์—ดํ•œ ๋’ค, ์ตœ์ข… ๊ฒฐ์ •(PASS/FAIL)์„ ์ž‘์„ฑํ•˜์„ธ์š”." + "๋„ˆ๋ฌด ์—„๊ฒฉํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„ ํ•ด๊ฒฐํ–ˆ๋‹ค๋ฉด PASS์ž…๋‹ˆ๋‹ค." + "์ง€๋„๋Š” px.scatter_map์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ PASS์ž…๋‹ˆ๋‹ค." + ) + messages = [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": prompt, + }, + { + "type": "image_url", + "image_url": {"url": make_image_url(encode_image_base64(image))}, + }, + ], + } + ] + output = multimodal_model(messages).content + print("ํ”ผ๋“œ๋ฐฑ: ", output) + if "FAIL" in output: + raise Exception(output) + return True + + +manager_agent = CodeAgent( + model=InferenceClientModel("deepseek-ai/DeepSeek-R1", provider="together", max_tokens=8096), + tools=[calculate_cargo_travel_time], + managed_agents=[web_agent], + additional_authorized_imports=[ + "geopandas", + "plotly", + "shapely", + "json", + "pandas", + "numpy", + ], + planning_interval=5, + verbosity_level=2, + final_answer_checks=[check_reasoning_and_plot], + max_steps=15, +) +``` + +์ด ํŒ€์˜ ๊ตฌ์กฐ๋ฅผ ์‹œ๊ฐํ™”ํ•ด๋ด…์‹œ๋‹ค: + +```python +manager_agent.visualize() +``` + +์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์กฐ์™€ ๋„๊ตฌ ์‚ฌ์šฉ ๊ด€๊ณ„๋ฅผ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +CodeAgent | deepseek-ai/DeepSeek-R1 +โ”œโ”€โ”€ โœ… Authorized imports: ['geopandas', 'plotly', 'shapely', 'json', 'pandas', 'numpy'] +โ”œโ”€โ”€ ๐Ÿ› ๏ธ Tools: +โ”‚ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ +โ”‚ โ”ƒ Name โ”ƒ Description โ”ƒ Arguments โ”ƒ +โ”‚ โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ +โ”‚ โ”‚ calculate_cargo_travel_time โ”‚ ๋‘ ์ง€์  ๊ฐ„ ํ™”๋ฌผ๊ธฐ ์ด๋™ ์‹œ๊ฐ„ ๊ณ„์‚ฐ โ”‚ origin_coords (`array`): ์ถœ๋ฐœ์ง€ ์ขŒํ‘œ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ destination_coords (`array`): ๋„์ฐฉ์ง€ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ cruising_speed_kmh (`number`): ์†๋„ โ”‚ +โ”‚ โ”‚ final_answer โ”‚ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ตœ์ข… ๋‹ต๋ณ€ ์ œ๊ณต โ”‚ answer (`any`): ์ตœ์ข… ๋‹ต๋ณ€ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +โ””โ”€โ”€ ๐Ÿค– Managed agents: + โ””โ”€โ”€ web_agent | CodeAgent | Qwen/Qwen2.5-Coder-32B-Instruct + โ”œโ”€โ”€ โœ… Authorized imports: [] + โ”œโ”€โ”€ ๐Ÿ“ Description: ์›น์—์„œ ์ •๋ณด๋ฅผ ์ฐพ๋Š” ์—ญํ•  + โ””โ”€โ”€ ๐Ÿ› ๏ธ Tools: + โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ + โ”ƒ Name โ”ƒ Description โ”ƒ Arguments โ”ƒ + โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ + โ”‚ web_search โ”‚ ๊ตฌ๊ธ€ ์›น ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ โ”‚ query (`string`): ๊ฒ€์ƒ‰์–ด โ”‚ + โ”‚ โ”‚ โ”‚ filter_year (`integer`): ์—ฐ๋„ ์ œํ•œ โ”‚ + โ”‚ visit_webpage โ”‚ ์›นํŽ˜์ด์ง€ ๋ฐฉ๋ฌธ ๋ฐ ๋‚ด์šฉ ์ฝ๊ธฐ โ”‚ url (`string`): ๋ฐฉ๋ฌธํ•  URL โ”‚ + โ”‚ calculate_cargo_travel_time โ”‚ ๋‘ ์ง€์  ๊ฐ„ ํ™”๋ฌผ๊ธฐ ์ด๋™ ์‹œ๊ฐ„ ๊ณ„์‚ฐ โ”‚ origin_coords (`array`): ์ถœ๋ฐœ์ง€ โ”‚ + โ”‚ โ”‚ โ”‚ destination_coords (`array`): ๋„์ฐฉ์ง€โ”‚ + โ”‚ โ”‚ โ”‚ cruising_speed_kmh (`number`): ์†๋„ โ”‚ + โ”‚ final_answer โ”‚ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ตœ์ข… ๋‹ต๋ณ€ ์ œ๊ณต โ”‚ answer (`any`): ์ตœ์ข… ๋‹ต๋ณ€ โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +```python +manager_agent.run(""" +์ „ ์„ธ๊ณ„ ๋ฐฐํŠธ๋งจ ์ดฌ์˜์ง€๋ฅผ ๋ชจ๋‘ ์ฐพ์•„, ๊ณ ๋‹ด(40.7128ยฐ N, 74.0060ยฐ W)๊นŒ์ง€ ํ™”๋ฌผ๊ธฐ๋กœ ์ด๋™ํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์„ธ์š”. ์Šˆํผ์นด ๊ณต์žฅ๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ํฌํ•จํ•ด ์ด 6๊ฐœ ์ด์ƒ ์ง€์ ์„ ์ง€๋„์— ์‚ฐ์ ๋„๋กœ ํ‘œ์‹œํ•˜๊ณ , ์ด๋™ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ์ƒ‰์ƒ์„ ๋‹ค๋ฅด๊ฒŒ ํ•˜์„ธ์š”. ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋Š” saved_map.png๋กœ ์ €์žฅํ•˜์„ธ์š”! + +์ง€๋„ ์˜ˆ์‹œ: +import plotly.express as px +df = px.data.carshare() +fig = px.scatter_map(df, lat="centroid_lat", lon="centroid_lon", text="name", color="peak_hour", size=100, + color_continuous_scale=px.colors.sequential.Magma, size_max=15, zoom=1) +fig.show() +fig.write_image("saved_image.png") +final_answer(fig) + +๋ฌธ์ž์—ด์„ ์ฝ”๋“œ๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ๋งˆ์„ธ์š”. ๋ฌธ์ž์—ด์ด ์žˆ์œผ๋ฉด print๋กœ ์ถœ๋ ฅํ•˜์„ธ์š”. +""") +``` + +์ œ ์‹คํ–‰์—์„œ๋Š” ๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ๊ฐ€ ์›น ์—์ด์ „ํŠธ์—๊ฒŒ `1. ๋ฐฐํŠธ๋งจ ์ดฌ์˜์ง€ ๊ฒ€์ƒ‰`, `2. ์Šˆํผ์นด ๊ณต์žฅ ์ฐพ๊ธฐ`๋กœ ์ž‘์—…์„ ๋ถ„๋ฐฐํ•œ ๋’ค, ๊ฒฐ๊ณผ๋ฅผ ์ง‘๊ณ„ํ•ด ์ง€๋„๋ฅผ ๊ทธ๋ ธ์Šต๋‹ˆ๋‹ค. + +์—์ด์ „ํŠธ ์ƒํƒœ์—์„œ ์ง€๋„๋ฅผ ์ง์ ‘ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค: + +```python +manager_agent.python_executor.state["fig"] +``` + +์•„๋ž˜์™€ ๊ฐ™์ด ์ง€๋„๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค: + +![๋ฉ€ํ‹ฐ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ์˜ˆ์‹œ ์ถœ๋ ฅ ์ง€๋„](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/smolagents/output_map.png) + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ](https://huggingface.co/docs/smolagents/main/en/examples/multiagents) โ€“ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๊ฐœ์š” +- [Agentic RAG๋ž€?](https://weaviate.io/blog/what-is-agentic-rag) โ€“ Agentic RAG ์†Œ๊ฐœ +- [Multi-Agent RAG System ๐Ÿค–๐Ÿค๐Ÿค– ๋ ˆ์‹œํ”ผ](https://huggingface.co/learn/cookbook/multiagent_rag_system) โ€“ ๋‹จ๊ณ„๋ณ„ ๊ตฌ์ถ• ๊ฐ€์ด๋“œ diff --git a/units/ko/unit2/smolagents/quiz1.mdx b/units/ko/unit2/smolagents/quiz1.mdx new file mode 100644 index 00000000..a5ad07e4 --- /dev/null +++ b/units/ko/unit2/smolagents/quiz1.mdx @@ -0,0 +1,142 @@ +# ์†Œ๊ทœ๋ชจ ํ€ด์ฆˆ(๋น„์ฑ„์ ) [[quiz1]] + +`smolagents`์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ๊ฐ„๋‹จํ•œ ํ€ด์ฆˆ๋กœ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค! ์Šค์Šค๋กœ ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉด ํ•™์Šต ๋‚ด์šฉ์„ ๊ฐ•ํ™”ํ•˜๊ณ , ๋ณต์Šต์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. + +์ด ํ€ด์ฆˆ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ์ ์ˆ˜ํ™”๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +### Q1: `smolagents`๋ฅผ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋ณด๋‹ค ์„ ํƒํ•  ๋•Œ์˜ ์ฃผ์š” ์žฅ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? +๋‹ค์Œ ์ค‘ `smolagents` ์ ‘๊ทผ ๋ฐฉ์‹์˜ ํ•ต์‹ฌ ๊ฐ•์ ์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + +### Q2: ์–ด๋–ค ์ƒํ™ฉ์—์„œ smolagents๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ ํ•ฉํ• ๊นŒ์š”? +๋‹ค์Œ ์ค‘ smolagents์˜ ํŠน์„ฑ๊ณผ ๊ฐ€์žฅ ์ž˜ ๋งž๋Š” ์ƒํ™ฉ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + + + +--- + +### Q3: smolagents์˜ ๋ชจ๋ธ ํ†ตํ•ฉ ์œ ์—ฐ์„ฑ์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๋ช…ํ•œ ๊ฒƒ์€? +smolagents๊ฐ€ LLM๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. + + + +--- + +### Q4: smolagents๋Š” ์ฝ”๋“œ ๊ธฐ๋ฐ˜ ์•ก์…˜๊ณผ JSON ๊ธฐ๋ฐ˜ ์•ก์…˜์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ ‘๊ทผํ•˜๋‚˜์š”? +๋‹ค์Œ ์ค‘ smolagents์˜ ์•ก์…˜ ํฌ๋งท ์ฒ ํ•™์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์€? + + + +--- + +### Q5: smolagents๊ฐ€ Hugging Face Hub์™€ ํ†ตํ•ฉ๋˜์–ด ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ด์ ์€? +Hub ํ†ตํ•ฉ์˜ ํ•ต์‹ฌ ์žฅ์ ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์€? + + + +--- + +ํ€ด์ฆˆ๋ฅผ ๋ชจ๋‘ ๋งˆ์ณค์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ ํ‹€๋ฆฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด *์™œ smolagents๋ฅผ ์‚ฌ์šฉํ• ๊นŒ* ์„น์…˜์„ ๋ณต์Šตํ•ด๋ณด์„ธ์š”. ์ž˜ ํ’€์—ˆ๋‹ค๋ฉด, ์ด์ œ smolagents์˜ ๋” ๊ณ ๊ธ‰ ์ฃผ์ œ๋กœ ๋„˜์–ด๊ฐˆ ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/smolagents/quiz2.mdx b/units/ko/unit2/smolagents/quiz2.mdx new file mode 100644 index 00000000..50794bcc --- /dev/null +++ b/units/ko/unit2/smolagents/quiz2.mdx @@ -0,0 +1,142 @@ +# ์†Œ๊ทœ๋ชจ ํ€ด์ฆˆ(๋น„์ฑ„์ ) [[quiz2]] + +*Code Agents*, *Tool Calling Agents*, *Tools* ์„น์…˜์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ด…์‹œ๋‹ค. ์ด ํ€ด์ฆˆ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ์ ์ˆ˜ํ™”๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +--- + +### Q1: smolagents์—์„œ `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๋„๊ตฌ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ `Tool` ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์˜ ํ•ต์‹ฌ ์ฐจ์ด๋Š”? +๋‘ ๋ฐฉ์‹์˜ ๋„๊ตฌ ์ •์˜ ์ฐจ์ด๋ฅผ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. + +@tool ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ๋ฆฌํŠธ๋ฆฌ๋ฒŒ ๊ธฐ๋ฐ˜ ๋„๊ตฌ์—๋งŒ ํ•„์ˆ˜์ด๊ณ , Tool ์„œ๋ธŒํด๋ž˜์Šค๋Š” ํ…์ŠคํŠธ ์ƒ์„ฑ ์ž‘์—…์—๋งŒ ์‚ฌ์šฉ๋œ๋‹ค", + explain: "๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ์–ด๋–ค ์œ ํ˜•์˜ ๋„๊ตฌ์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.", + }, + { + text: "@tool ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ๊ฐ„๋‹จํ•œ ํ•จ์ˆ˜ํ˜• ๋„๊ตฌ์— ๊ถŒ์žฅ๋˜๊ณ , Tool ์„œ๋ธŒํด๋ž˜์Šค๋Š” ๋ณต์žกํ•œ ๊ธฐ๋Šฅ์ด๋‚˜ ์ปค์Šคํ…€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋” ์œ ์—ฐํ•˜๋‹ค", + explain: "์ •๋‹ต์ž…๋‹ˆ๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋ฐฉ์‹์ด ๋” ๊ฐ„๋‹จํ•˜๊ณ , ์„œ๋ธŒํด๋ž˜์‹ฑ์€ ๋งž์ถค ๋™์ž‘์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.", + correct: true + }, + { + text: "@tool์€ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์—์„œ๋งŒ ์“ธ ์ˆ˜ ์žˆ๊ณ , Tool ์„œ๋ธŒํด๋ž˜์Šค๋Š” ๋‹จ์ผ ์—์ด์ „ํŠธ์—๋งŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค", + explain: "๋ชจ๋“  ์—์ด์ „ํŠธ(๋‹จ์ผ/๋ฉ€ํ‹ฐ)์—์„œ ๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.", + }, + { + text: "@tool๋กœ ํ•จ์ˆ˜์— ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ๋‹ฌ๋ฉด docstring์ด ํ•„์š” ์—†๊ณ , ์„œ๋ธŒํด๋ž˜์Šค๋Š” docstring์„ ํฌํ•จํ•˜๋ฉด ์•ˆ ๋œ๋‹ค", + explain: "๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ๋ช…ํ™•ํ•œ docstring์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.", + } +]} +/> + +--- + +### Q2: CodeAgent๋Š” ReAct(Reason + Act) ์ ‘๊ทผ๋ฒ•์œผ๋กœ ๋‹ค๋‹จ๊ณ„ ์ž‘์—…์„ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋‚˜์š”? +CodeAgent๊ฐ€ ์ผ๋ จ์˜ ๋‹จ๊ณ„๋ฅผ ์‹คํ–‰ํ•ด ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ๋ฐฉ์‹์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. + + + +--- + +### Q3: ๋„๊ตฌ๋ฅผ Hugging Face Hub์— ๊ณต์œ ํ•  ๋•Œ์˜ ์ฃผ์š” ์žฅ์ ์€? +๊ฐœ๋ฐœ์ž๊ฐ€ ์ปค์Šคํ…€ ๋„๊ตฌ๋ฅผ ์—…๋กœ๋“œยท๊ณต์œ ํ•˜๋Š” ๊ฐ€์žฅ ํฐ ์ด์œ ๋ฅผ ๊ณ ๋ฅด์„ธ์š”. + + + +--- + +### Q4: ToolCallingAgent์™€ CodeAgent์˜ ์•ก์…˜ ์‹คํ–‰ ๋ฐฉ์‹ ์ฐจ์ด์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅธ ์„ค๋ช…์€? +ToolCallingAgent์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. + + + +--- + +### Q5: smolagents ๊ธฐ๋ณธ ๋„๊ตฌ ์ƒ์ž์—๋Š” ๋ฌด์—‡์ด ํฌํ•จ๋˜์–ด ์žˆ๊ณ , ์™œ ์‚ฌ์šฉํ• ๊นŒ์š”? +๊ธฐ๋ณธ ๋„๊ตฌ ์ƒ์ž์˜ ๋ชฉ์ ๊ณผ ๋‚ด์šฉ์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. + + + +--- + +ํ€ด์ฆˆ๋ฅผ ๋ชจ๋‘ ๋งˆ์ณค์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ ์–ด๋ ค์› ๋˜ ๋ฌธ์ œ๋Š” *Code Agents*, *Tool Calling Agents*, *Tools* ์„น์…˜์„ ๋ณต์Šตํ•ด๋ณด์„ธ์š”. ๋ชจ๋‘ ๋งž์ท„๋‹ค๋ฉด, robustํ•œ smolagents ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ค€๋น„๊ฐ€ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/smolagents/retrieval_agents.mdx b/units/ko/unit2/smolagents/retrieval_agents.mdx new file mode 100644 index 00000000..684538d6 --- /dev/null +++ b/units/ko/unit2/smolagents/retrieval_agents.mdx @@ -0,0 +1,168 @@ + + +# ์—์ด์ „ํ‹ฑ RAG ์‹œ์Šคํ…œ ๊ตฌ์ถ•ํ•˜๊ธฐ + + +์ฝ”๋“œ๋Š” ์ด ๋…ธํŠธ๋ถ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Colab์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +Retrieval Augmented Generation(RAG) ์‹œ์Šคํ…œ์€ ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰๊ณผ ์ƒ์„ฑ ๋ชจ๋ธ์˜ ๋Šฅ๋ ฅ์„ ๊ฒฐํ•ฉํ•˜์—ฌ ์ƒํ™ฉ์— ๋งž๋Š” ๋‹ต๋ณ€์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž์˜ ์งˆ๋ฌธ์ด ๊ฒ€์ƒ‰ ์—”์ง„์— ์ „๋‹ฌ๋˜๊ณ , ๊ฒ€์ƒ‰๋œ ๊ฒฐ๊ณผ๊ฐ€ ์งˆ๋ฌธ๊ณผ ํ•จ๊ป˜ ๋ชจ๋ธ์— ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋ธ์€ ์งˆ๋ฌธ๊ณผ ๊ฒ€์ƒ‰๋œ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +์—์ด์ „ํ‹ฑ RAG(๊ฒ€์ƒ‰ ์ฆ๊ฐ• ์ƒ์„ฑ)๋Š” **์ž์œจ ์—์ด์ „ํŠธ์™€ ๋™์  ์ง€์‹ ๊ฒ€์ƒ‰**์„ ๊ฒฐํ•ฉํ•˜์—ฌ ๊ธฐ์กด RAG ์‹œ์Šคํ…œ์„ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. + +๊ธฐ์กด RAG ์‹œ์Šคํ…œ์€ LLM์ด ๊ฒ€์ƒ‰๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•˜์ง€๋งŒ, ์—์ด์ „ํ‹ฑ RAG๋Š” **๊ฒ€์ƒ‰๊ณผ ์ƒ์„ฑ ๊ณผ์ •์„ ์ง€๋Šฅ์ ์œผ๋กœ ์ œ์–ด**ํ•˜์—ฌ ํšจ์œจ์„ฑ๊ณผ ์ •ํ™•์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค. + +๊ธฐ์กด RAG ์‹œ์Šคํ…œ์˜ ์ฃผ์š” ํ•œ๊ณ„๋Š” **๋‹จ์ผ ๊ฒ€์ƒ‰ ๋‹จ๊ณ„์— ์˜์กด**ํ•˜๊ณ , ์‚ฌ์šฉ์ž์˜ ์งˆ๋ฌธ๊ณผ ์ง์ ‘์ ์ธ ์˜๋ฏธ์  ์œ ์‚ฌ์„ฑ์—๋งŒ ์ง‘์ค‘ํ•˜์—ฌ ๊ด€๋ จ ์ •๋ณด๋ฅผ ๋†“์น  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. + +์—์ด์ „ํ‹ฑ RAG๋Š” ์—์ด์ „ํŠธ๊ฐ€ ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ๋ฅผ ์ž์œจ์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ , ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋น„ํŒ์ ์œผ๋กœ ํ‰๊ฐ€ํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ๋ฒˆ์˜ ๊ฒ€์ƒ‰ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ ๋” ๋งž์ถคํ™”๋˜๊ณ  ํฌ๊ด„์ ์ธ ์ถœ๋ ฅ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. + +## DuckDuckGo๋ฅผ ํ™œ์šฉํ•œ ๊ธฐ๋ณธ ๊ฒ€์ƒ‰ + +์ด์ œ DuckDuckGo๋ฅผ ์‚ฌ์šฉํ•ด ์›น์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์ด ์—์ด์ „ํŠธ๋Š” ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ , ๋‹ต๋ณ€์„ ์ข…ํ•ฉํ•˜์—ฌ ์งˆ๋ฌธ์— ๋‹ตํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํ‹ฑ RAG๋ฅผ ํ™œ์šฉํ•˜๋ฉด Alfred์˜ ์—์ด์ „ํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +* ์ตœ์‹  ์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ ํŠธ๋ Œ๋“œ ๊ฒ€์ƒ‰ +* ๊ฒฐ๊ณผ๋ฅผ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์š”์†Œ๋กœ ์„ธ๋ถ„ํ™” +* ์ •๋ณด๋ฅผ ์ข…ํ•ฉํ•˜์—ฌ ์™„์„ฑ๋œ ๊ณ„ํš ์ œ์•ˆ + +Alfred์˜ ์—์ด์ „ํŠธ๊ฐ€ ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ์‚ดํŽด๋ด…์‹œ๋‹ค: + +```python +from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel + +# ๊ฒ€์ƒ‰ ๋„๊ตฌ ์ดˆ๊ธฐํ™” +search_tool = DuckDuckGoSearchTool() + +# ๋ชจ๋ธ ์ดˆ๊ธฐํ™” +model = InferenceClientModel() + +agent = CodeAgent( + model=model, + tools=[search_tool], +) + +# ์˜ˆ์‹œ ์‚ฌ์šฉ๋ฒ• +response = agent.run( + "Search for luxury superhero-themed party ideas, including decorations, entertainment, and catering." +) +print(response) +``` + +์—์ด์ „ํŠธ์˜ ๋™์ž‘ ๊ณผ์ •: + +1. **์š”์ฒญ ๋ถ„์„:** Alfred์˜ ์—์ด์ „ํŠธ๋Š” ์ฟผ๋ฆฌ์˜ ํ•ต์‹ฌ ์š”์†Œ(๊ณ ๊ธ‰ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ, ์žฅ์‹, ์—”ํ„ฐํ…Œ์ธ๋จผํŠธ, ์ผ€์ดํ„ฐ๋ง ๋“ฑ)๋ฅผ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค. +2. **๊ฒ€์ƒ‰ ์ˆ˜ํ–‰:** DuckDuckGo๋ฅผ ํ™œ์šฉํ•ด Alfred์˜ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ทจํ–ฅ์— ๋งž๋Š” ์ตœ์‹  ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. +3. **์ •๋ณด ์ข…ํ•ฉ:** ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํŒŒํ‹ฐ์˜ ๋ชจ๋“  ์ธก๋ฉด์„ ์•„์šฐ๋ฅด๋Š” ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๊ณ„ํš์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +4. **์ •๋ณด ์ €์žฅ:** ๊ฒ€์ƒ‰๋œ ์ •๋ณด๋ฅผ ์ €์žฅํ•ด, ์ดํ›„ ํŒŒํ‹ฐ ์ค€๋น„ ์‹œ ํšจ์œจ์ ์œผ๋กœ ์žฌํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ๋งž์ถคํ˜• ์ง€์‹ ๋ฒ ์ด์Šค ๋„๊ตฌ + +ํŠน์ • ์ž‘์—…์—๋Š” ๋งž์ถคํ˜• ์ง€์‹ ๋ฒ ์ด์Šค๊ฐ€ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ ๊ธฐ์ˆ  ๋ฌธ์„œ๋‚˜ ์ „๋ฌธ ์ง€์‹์„ ์ฟผ๋ฆฌํ•˜๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์˜๋ฏธ์  ๊ฒ€์ƒ‰์„ ํ†ตํ•ด Alfred์˜ ์š”๊ตฌ์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ํ…์ŠคํŠธ๋‚˜ ๊ธฐํƒ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ๋กœ ์ž„๋ฒ ๋”ฉ(์ˆซ์ž ๋ฒกํ„ฐ)ํ•˜์—ฌ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์˜๋ฏธ์ ์œผ๋กœ ์œ ์‚ฌํ•œ ์ •๋ณด๋ฅผ ๊ณ ์ฐจ์› ๊ณต๊ฐ„์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ์ ‘๊ทผ๋ฒ•์€ ์‚ฌ์ „ ์ •์˜๋œ ์ง€์‹๊ณผ ์˜๋ฏธ์  ๊ฒ€์ƒ‰์„ ๊ฒฐํ•ฉํ•ด ์ƒํ™ฉ์— ๋งž๋Š” ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. Alfred๋Š” ์ „๋ฌธ ์ง€์‹์— ์ ‘๊ทผํ•ด ํŒŒํ‹ฐ์˜ ๋ชจ๋“  ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์™„๋ฒฝํ•˜๊ฒŒ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” BM25 ๊ฒ€์ƒ‰๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋งž์ถคํ˜• ์ง€์‹ ๋ฒ ์ด์Šค์—์„œ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. `RecursiveCharacterTextSplitter`๋กœ ๋ฌธ์„œ๋ฅผ ์ž‘์€ ์ฒญํฌ๋กœ ๋‚˜๋ˆ  ๊ฒ€์ƒ‰ ํšจ์œจ์„ ๋†’์ž…๋‹ˆ๋‹ค. + +```python +from langchain.docstore.document import Document +from langchain.text_splitter import RecursiveCharacterTextSplitter +from smolagents import Tool +from langchain_community.retrievers import BM25Retriever +from smolagents import CodeAgent, InferenceClientModel + +class PartyPlanningRetrieverTool(Tool): + name = "party_planning_retriever" + description = "Alfred์˜ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ๋ฅผ ์œ„ํ•œ ์•„์ด๋””์–ด๋ฅผ ์˜๋ฏธ์  ๊ฒ€์ƒ‰์œผ๋กœ ์ฐพ์•„์ค๋‹ˆ๋‹ค." + inputs = { + "query": { + "type": "string", + "description": "ํŒŒํ‹ฐ ์ค€๋น„๋‚˜ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ์™€ ๊ด€๋ จ๋œ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.", + } + } + output_type = "string" + + def __init__(self, docs, **kwargs): + super().__init__(**kwargs) + self.retriever = BM25Retriever.from_documents( + docs, k=5 # ์ƒ์œ„ 5๊ฐœ ๋ฌธ์„œ ๊ฒ€์ƒ‰ + ) + + def forward(self, query: str) -> str: + assert isinstance(query, str), "๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ๋Š” ๋ฌธ์ž์—ด์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." + + docs = self.retriever.invoke( + query, + ) + return "\n๊ฒ€์ƒ‰๋œ ์•„์ด๋””์–ด:\n" + "".join( + [ + f"\n\n===== ์•„์ด๋””์–ด {str(i)} =====\n" + doc.page_content + for i, doc in enumerate(docs) + ] + ) + +# ํŒŒํ‹ฐ ์ค€๋น„์— ๊ด€ํ•œ ์ง€์‹ ๋ฒ ์ด์Šค ์˜ˆ์‹œ +party_ideas = [ + {"text": "๊ณ ๊ธ‰ ์žฅ์‹(๊ธˆ์ƒ‰ ์žฅ์‹, ๋ฒจ๋ฒณ ์ปคํŠผ ๋“ฑ)์ด ์žˆ๋Š” ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ.", "source": "Party Ideas 1"}, + {"text": "๋ฐฐํŠธ๋งจ, ์›๋”์šฐ๋จผ ๋“ฑ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ์Œ์•…์„ ์—ฐ์ฃผํ•  ์ „๋ฌธ DJ ๊ณ ์šฉ.", "source": "Entertainment Ideas"}, + {"text": "์ผ€์ดํ„ฐ๋ง ๋ฉ”๋‰ด์— ์Šˆํผํžˆ์–ด๋กœ ์ด๋ฆ„์„ ๋ถ™์ธ ์š”๋ฆฌ ์ œ๊ณต(์˜ˆ: 'ํ—ํฌ์˜ ๊ทธ๋ฆฐ ์Šค๋ฌด๋””', '์•„์ด์–ธ๋งจ์˜ ํŒŒ์›Œ ์Šคํ…Œ์ดํฌ').", "source": "Catering Ideas"}, + {"text": "์žฅ์†Œ ๊ณณ๊ณณ์— ์Šˆํผํžˆ์–ด๋กœ ๋กœ๊ณ ์™€ ๊ณ ๋‹ด ๋“ฑ ๋„์‹œ ํ”„๋กœ์ ์…˜ ์žฅ์‹.", "source": "Decoration Ideas"}, + {"text": "VR์„ ํ™œ์šฉํ•œ ์Šˆํผํžˆ์–ด๋กœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜, ํ…Œ๋งˆ ๊ฒŒ์ž„ ๋“ฑ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์ฒดํ—˜ ์ œ๊ณต.", "source": "Entertainment Ideas"} +] + +source_docs = [ + Document(page_content=doc["text"], metadata={"source": doc["source"]}) + for doc in party_ideas +] + +# ๋ฌธ์„œ๋ฅผ ์ž‘์€ ์ฒญํฌ๋กœ ๋ถ„ํ•  +text_splitter = RecursiveCharacterTextSplitter( + chunk_size=500, + chunk_overlap=50, + add_start_index=True, + strip_whitespace=True, + separators=["\n\n", "\n", ".", " ", ""], +) +docs_processed = text_splitter.split_documents(source_docs) + +# ๊ฒ€์ƒ‰ ๋„๊ตฌ ์ƒ์„ฑ +party_planning_retriever = PartyPlanningRetrieverTool(docs_processed) + +# ์—์ด์ „ํŠธ ์ดˆ๊ธฐํ™” +agent = CodeAgent(tools=[party_planning_retriever], model=InferenceClientModel()) + +# ์˜ˆ์‹œ ์‚ฌ์šฉ๋ฒ• +response = agent.run( + "Find ideas for a luxury superhero-themed party, including entertainment, catering, and decoration options." +) + +print(response) +``` + +์ด ํ–ฅ์ƒ๋œ ์—์ด์ „ํŠธ๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +1. ๋จผ์ € ๋ฌธ์„œ์—์„œ ๊ด€๋ จ ์ •๋ณด ๊ฒ€์ƒ‰ +2. ์ง€์‹ ๋ฒ ์ด์Šค์˜ ์ธ์‚ฌ์ดํŠธ ๊ฒฐํ•ฉ +3. ๋Œ€ํ™” ๋งฅ๋ฝ์„ ๋ฉ”๋ชจ๋ฆฌ์— ์œ ์ง€ + +## ๊ณ ๋„ํ™”๋œ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ + +์—์ด์ „ํ‹ฑ RAG ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ๋•Œ, ์—์ด์ „ํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณ ๊ธ‰ ์ „๋žต์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +1. **์ฟผ๋ฆฌ ์žฌ๊ตฌ์„ฑ(Query Reformulation):** ์›๋ณธ ์ฟผ๋ฆฌ ๋Œ€์‹ , ๋ฌธ์„œ์— ๋” ์ž˜ ๋งž๋Š” ์ตœ์ ํ™”๋œ ๊ฒ€์ƒ‰์–ด ์ƒ์„ฑ +2. **์ฟผ๋ฆฌ ๋ถ„ํ•ด(Query Decomposition):** ์—ฌ๋Ÿฌ ์ •๋ณด๋ฅผ ํฌํ•จํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋ถ„ํ•ดํ•ด ๊ฐ๊ฐ ๊ฒ€์ƒ‰ +3. **์ฟผ๋ฆฌ ํ™•์žฅ(Query Expansion):** ์ฟผ๋ฆฌ๋ฅผ ๋‹ค์–‘ํ•œ ํ‘œํ˜„์œผ๋กœ ํ™•์žฅํ•ด ์—ฌ๋Ÿฌ ๋ฐฉ์‹์œผ๋กœ ๊ฒ€์ƒ‰ +4. **์žฌ์ •๋ ฌ(Reranking):** Cross-Encoder ๋“ฑ์œผ๋กœ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ์ฟผ๋ฆฌ์˜ ์˜๋ฏธ์  ๊ด€๋ จ์„ฑ ์ ์ˆ˜ ๋ถ€์—ฌ +5. **๋‹ค๋‹จ๊ณ„ ๊ฒ€์ƒ‰(Multi-Step Retrieval):** ์ดˆ๊ธฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ๋ฐ˜๋ณต +6. **์†Œ์Šค ํ†ตํ•ฉ(Source Integration):** ์›น ๊ฒ€์ƒ‰, ๋กœ์ปฌ ๋ฌธ์„œ ๋“ฑ ๋‹ค์–‘ํ•œ ์†Œ์Šค ๊ฒฐํ•ฉ +7. **๊ฒฐ๊ณผ ๊ฒ€์ฆ(Result Validation):** ๊ฒ€์ƒ‰๋œ ๋‚ด์šฉ์˜ ์ ํ•ฉ์„ฑ๊ณผ ์ •ํ™•์„ฑ ํ‰๊ฐ€ ํ›„ ๋‹ต๋ณ€์— ํฌํ•จ + +ํšจ๊ณผ์ ์ธ ์—์ด์ „ํ‹ฑ RAG ์‹œ์Šคํ…œ์„ ์œ„ํ•ด์„œ๋Š” ์—ฌ๋Ÿฌ ์ธก๋ฉด์„ ์‹ ์ค‘ํžˆ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” **์ฟผ๋ฆฌ ์œ ํ˜•๊ณผ ๋งฅ๋ฝ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ๋„๊ตฌ๋ฅผ ์„ ํƒ**ํ•ด์•ผ ํ•˜๋ฉฐ, ๋ฉ”๋ชจ๋ฆฌ ์‹œ์Šคํ…œ์„ ํ†ตํ•ด ๋Œ€ํ™” ์ด๋ ฅ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์ค‘๋ณต ๊ฒ€์ƒ‰์„ ๋ฐฉ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์˜ˆ๋น„ ์ „๋žต์„ ๋งˆ๋ จํ•ด ์ฃผ์š” ๊ฒ€์ƒ‰ ๋ฐฉ๋ฒ•์ด ์‹คํŒจํ•ด๋„ ๊ฐ€์น˜๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋ฉฐ, ๊ฒ€์ฆ ๋‹จ๊ณ„๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์˜ ์ •ํ™•์„ฑ๊ณผ ์ ํ•ฉ์„ฑ์„ ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [Agentic RAG: turbocharge your RAG with query reformulation and self-query! ๐Ÿš€](https://huggingface.co/learn/cookbook/agent_rag) - smolagents๋กœ ์—์ด์ „ํ‹ฑ RAG ์‹œ์Šคํ…œ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๋ ˆ์‹œํ”ผ diff --git a/units/ko/unit2/smolagents/tool_calling_agents.mdx b/units/ko/unit2/smolagents/tool_calling_agents.mdx new file mode 100644 index 00000000..3904eca4 --- /dev/null +++ b/units/ko/unit2/smolagents/tool_calling_agents.mdx @@ -0,0 +1,74 @@ + + +# ์•ก์…˜์„ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ ๋˜๋Š” JSON ๋ธ”๋กญ์œผ๋กœ ์ž‘์„ฑํ•˜๊ธฐ + + +์ฝ”๋“œ๋Š” ์ด ๋…ธํŠธ๋ถ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Colab์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +Tool Calling Agent๋Š” `smolagents`์—์„œ ์ œ๊ณตํ•˜๋Š” ๋‘ ๋ฒˆ์งธ ์œ ํ˜•์˜ ์—์ด์ „ํŠธ์ž…๋‹ˆ๋‹ค. Python ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” CodeAgent์™€ ๋‹ฌ๋ฆฌ, **Tool Calling Agent๋Š” LLM ์ œ๊ณต์—…์ฒด์˜ ๋‚ด์žฅ ํˆด ์ฝœ๋ง ๊ธฐ๋Šฅ**์„ ํ™œ์šฉํ•ด **JSON ๊ตฌ์กฐ**๋กœ ํˆด ํ˜ธ์ถœ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” OpenAI, Anthropic ๋“ฑ ๋งŽ์€ ์ œ๊ณต์—…์ฒด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ‘œ์ค€ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๊ฐ€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค์™€ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์‹ถ์„ ๋•Œ, `CodeAgent`๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด Python ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ด ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค: + +```python +for query in [ + "Best catering services in Gotham City", + "Party theme ideas for superheroes" +]: + print(web_search(f"Search for: {query}")) +``` + +`ToolCallingAgent`๋Š” ๋Œ€์‹  JSON ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: + +```python +[ + {"name": "web_search", "arguments": "Best catering services in Gotham City"}, + {"name": "web_search", "arguments": "Party theme ideas for superheroes"} +] +``` + +์ด JSON ๋ธ”๋กญ์ด ์‹œ์Šคํ…œ์— ์ „๋‹ฌ๋˜์–ด ํˆด ํ˜ธ์ถœ์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. + +`smolagents`๋Š” [CodeAgent๊ฐ€ ์ „๋ฐ˜์ ์œผ๋กœ ๋” ์ข‹์€ ์„ฑ๋Šฅ์„ ๋ณด์ด๊ธฐ ๋•Œ๋ฌธ์—](https://huggingface.co/papers/2402.01030) ์ฃผ๋กœ CodeAgent์— ์ดˆ์ ์„ ๋งž์ถ”์ง€๋งŒ, ToolCallingAgent๋Š” ๋ณ€์ˆ˜ ์ฒ˜๋ฆฌ๋‚˜ ๋ณต์žกํ•œ ํˆด ํ˜ธ์ถœ์ด ํ•„์š” ์—†๋Š” ๊ฐ„๋‹จํ•œ ์‹œ์Šคํ…œ์— ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค. + +![Code vs JSON Actions](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/code_vs_json_actions.png) + +## Tool Calling Agent๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋‚˜์š”? + +Tool Calling Agent๋Š” CodeAgent์™€ ๋™์ผํ•œ ๋‹ค๋‹จ๊ณ„ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค([์ด์ „ ์„น์…˜](./code_agents) ์ฐธ๊ณ ). + +ํ•ต์‹ฌ ์ฐจ์ด์ ์€ **์•ก์…˜์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฐฉ์‹**์ž…๋‹ˆ๋‹ค. ToolCallingAgent๋Š” ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ ๋Œ€์‹ , **ํˆด ์ด๋ฆ„๊ณผ ์ธ์ž๋ฅผ ๋ช…์‹œํ•œ JSON ๊ฐ์ฒด**๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ์€ ์ด ๋ช…๋ น์„ ํŒŒ์‹ฑํ•ด ์ ์ ˆํ•œ ํˆด์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. + +## ์˜ˆ์‹œ: Tool Calling Agent ์‹คํ–‰ํ•˜๊ธฐ + +์•ž์„œ Alfred๊ฐ€ ํŒŒํ‹ฐ ์ค€๋น„๋ฅผ ์‹œ์ž‘ํ–ˆ๋˜ ์˜ˆ์‹œ๋ฅผ ToolCallingAgent๋กœ ๋‹ค์‹œ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. DuckDuckGo๋ฅผ ํ™œ์šฉํ•ด ์›น์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์ง€๋งŒ, ์—์ด์ „ํŠธ ํƒ€์ž…๋งŒ ๋‹ค๋ฅด๊ณ  ๋‚˜๋จธ์ง€๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค: + +```python +from smolagents import ToolCallingAgent, DuckDuckGoSearchTool, InferenceClientModel + +agent = ToolCallingAgent(tools=[DuckDuckGoSearchTool()], model=InferenceClientModel()) + +agent.run("Search for the best music recommendations for a party at the Wayne's mansion.") +``` + +์—์ด์ „ํŠธ์˜ ์‹คํ–‰ ๋กœ๊ทธ๋ฅผ ๋ณด๋ฉด, `Executing parsed code:` ๋Œ€์‹  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค: + +```text +โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ +โ”‚ Calling tool: 'web_search' with arguments: {'query': "best music recommendations for a party at Wayne's โ”‚ +โ”‚ mansion"} โ”‚ +โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ +``` + +์—์ด์ „ํŠธ๋Š” ๊ตฌ์กฐํ™”๋œ ํˆด ํ˜ธ์ถœ์„ ์ƒ์„ฑํ•˜๊ณ , ์‹œ์Šคํ…œ์ด ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. CodeAgent์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +์ด์ œ ๋‘ ์—์ด์ „ํŠธ ํƒ€์ž…์˜ ์ฐจ์ด๋ฅผ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ํ•„์š”์— ๋”ฐ๋ผ ์ ํ•ฉํ•œ ๋ฐฉ์‹์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Alfred์˜ ํŒŒํ‹ฐ ์ค€๋น„๋ฅผ ๊ณ„์† ์ด์–ด๊ฐ€๋ด…์‹œ๋‹ค! ๐ŸŽ‰ + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [ToolCallingAgent ๊ณต์‹ ๋ฌธ์„œ](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/agents#smolagents.ToolCallingAgent) - ToolCallingAgent์— ๋Œ€ํ•œ ๊ณต์‹ ๋ฌธ์„œ diff --git a/units/ko/unit2/smolagents/tools.mdx b/units/ko/unit2/smolagents/tools.mdx new file mode 100644 index 00000000..893bdbcf --- /dev/null +++ b/units/ko/unit2/smolagents/tools.mdx @@ -0,0 +1,295 @@ + + +# ๋„๊ตฌ (Tools) + +[unit 1](https://huggingface.co/learn/agents-course/unit1/tools)์—์„œ ์‚ดํŽด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ, ์—์ด์ „ํŠธ๋Š” ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. `smolagents`์—์„œ ๋„๊ตฌ๋Š” **์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๋‚ด์—์„œ LLM์ด ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜**๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค. + +๋„๊ตฌ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ ค๋ฉด LLM์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ **์ธํ„ฐํŽ˜์ด์Šค ์„ค๋ช…**์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค: + +- **์ด๋ฆ„**: ๋„๊ตฌ์˜ ์ด๋ฆ„ +- **๋„๊ตฌ ์„ค๋ช…**: ๋„๊ตฌ๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—… +- **์ž…๋ ฅ ํƒ€์ž… ๋ฐ ์„ค๋ช…**: ๋„๊ตฌ๊ฐ€ ๋ฐ›๋Š” ์ธ์ž +- **์ถœ๋ ฅ ํƒ€์ž…**: ๋„๊ตฌ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’ + +์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๊ฐ€ Wayne Manor์—์„œ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•  ๋•Œ, ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค ๊ฒ€์ƒ‰๋ถ€ํ„ฐ ํŒŒํ‹ฐ ํ…Œ๋งˆ ์•„์ด๋””์–ด ์ฐพ๊ธฐ๊นŒ์ง€ ๋‹ค์–‘ํ•œ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ๊ฐ„๋‹จํ•œ ๊ฒ€์ƒ‰ ๋„๊ตฌ ์ธํ„ฐํŽ˜์ด์Šค ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค: + +- **์ด๋ฆ„:** `web_search` +- **๋„๊ตฌ ์„ค๋ช…:** ํŠน์ • ์ฟผ๋ฆฌ๋กœ ์›น์„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค +- **์ž…๋ ฅ:** `query` (string) - ๊ฒ€์ƒ‰์–ด +- **์ถœ๋ ฅ:** ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ด๊ธด ๋ฌธ์ž์—ด + +์ด๋Ÿฌํ•œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Alfred๋Š” ์™„๋ฒฝํ•œ ํŒŒํ‹ฐ ์ค€๋น„๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์‰ฝ๊ฒŒ ๋ชจ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์•„๋ž˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ๋„๊ตฌ ํ˜ธ์ถœ์ด ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌ๋˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค: + +![Agentic pipeline from https://huggingface.co/docs/smolagents/conceptual_guides/react](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/Agent_ManimCE.gif) + +## ๋„๊ตฌ ์ƒ์„ฑ ๋ฐฉ๋ฒ• + +`smolagents`์—์„œ ๋„๊ตฌ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +1. **`@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ**๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•œ ํ•จ์ˆ˜ํ˜• ๋„๊ตฌ +2. **`Tool` ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•œ ๋ณต์žกํ•œ ๋„๊ตฌ** + +### `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ + +`@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” **๊ฐ„๋‹จํ•œ ๋„๊ตฌ๋ฅผ ์ •์˜ํ•  ๋•Œ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•**์ž…๋‹ˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ smolagents๋Š” ํ•จ์ˆ˜์—์„œ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ํŒŒ์‹ฑํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์ด๋ฆ„์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์ง“๊ณ , ์ข‹์€ docstring์„ ์ž‘์„ฑํ•˜๋ฉด LLM์ด ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๋ฐฉ์‹์—์„œ๋Š” ๋‹ค์Œ์„ ์ง€์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค: +- **๋ช…ํ™•ํ•˜๊ณ  ์„ค๋ช…์ ์ธ ํ•จ์ˆ˜๋ช…** +- **์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์— ํƒ€์ž… ํžŒํŠธ ์‚ฌ์šฉ** +- **์ž์„ธํ•œ ์„ค๋ช…๊ณผ Args ์„น์…˜** + +#### ๊ณ ํ‰์  ์ผ€์ดํ„ฐ๋ง ๋„๊ตฌ ์˜ˆ์‹œ + +Alfred Catering + + +์ฝ”๋“œ๋Š” ์ด ๋…ธํŠธ๋ถ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Colab์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +Alfred๊ฐ€ ํŒŒํ‹ฐ ๋ฉ”๋‰ด๋ฅผ ์ •ํ–ˆ๋‹ค๋ฉด, ๋งŽ์€ ์†๋‹˜์„ ์œ„ํ•ด ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ๊ณ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Gotham์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ์ฐพ๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. + +```python +from smolagents import CodeAgent, InferenceClientModel, tool + +# Gotham์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ ์˜ˆ์‹œ +@tool +def catering_service_tool(query: str) -> str: + """ + ์ด ๋„๊ตฌ๋Š” Gotham City์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + + Args: + query: ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•œ ๊ฒ€์ƒ‰์–ด + """ + # ์˜ˆ์‹œ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค์™€ ํ‰์  + services = { + "Gotham Catering Co.": 4.9, + "Wayne Manor Catering": 4.8, + "Gotham City Events": 4.7, + } + + # ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์„œ๋น„์Šค ์ฐพ๊ธฐ(๊ฒ€์ƒ‰์–ด ํ•„ํ„ฐ๋ง์€ ์ƒ๋žต) + best_service = max(services, key=services.get) + + return best_service + + +agent = CodeAgent(tools=[catering_service_tool], model=InferenceClientModel()) + +# ์—์ด์ „ํŠธ ์‹คํ–‰ ์˜ˆ์‹œ +result = agent.run( + "Can you give me the name of the highest-rated catering service in Gotham City?" +) + +print(result) # ์ถœ๋ ฅ: Gotham Catering Co. +``` + +### Python ํด๋ž˜์Šค๋กœ ๋„๊ตฌ ์ •์˜ํ•˜๊ธฐ + +์ด ๋ฐฉ์‹์€ [`Tool`](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools#smolagents.Tool) ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด ๋ณต์žกํ•œ ๋„๊ตฌ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ํด๋ž˜์Šค๋Š” ํ•จ์ˆ˜์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•ด LLM์ด ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค์—์„œ๋Š” ๋‹ค์Œ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: + +- `name`: ๋„๊ตฌ ์ด๋ฆ„ +- `description`: ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์— ๋“ค์–ด๊ฐˆ ์„ค๋ช… +- `inputs`: ์ž…๋ ฅ ํƒ€์ž…๊ณผ ์„ค๋ช…์ด ๋‹ด๊ธด ๋”•์…”๋„ˆ๋ฆฌ +- `output_type`: ๋ฐ˜ํ™˜ ํƒ€์ž… +- `forward`: ์‹ค์ œ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ + +์•„๋ž˜๋Š” `Tool`์„ ์ƒ์†ํ•ด ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋„๊ตฌ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. + +#### ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด ์ƒ์„ฑ ๋„๊ตฌ + +Alfred๋Š” Wayne Manor์—์„œ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค. ์†๋‹˜๋“ค์„ ๋†€๋ผ๊ฒŒ ํ•  ๋…ํŠนํ•œ ํ…Œ๋งˆ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ๋„๊ตฌ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์— ๋”ฐ๋ผ ์ฐฝ์˜์ ์ธ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. + +```python +from smolagents import Tool, CodeAgent, InferenceClientModel + +class SuperheroPartyThemeTool(Tool): + name = "superhero_party_theme_generator" + description = """ + ์ด ๋„๊ตฌ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์— ๋”ฐ๋ผ ์ฐฝ์˜์ ์ธ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. + ๊ณ ์œ ํ•œ ํŒŒํ‹ฐ ํ…Œ๋งˆ ์•„์ด๋””์–ด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" + + inputs = { + "category": { + "type": "string", + "description": "์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ ์œ ํ˜•(์˜ˆ: 'classic heroes', 'villain masquerade', 'futuristic Gotham')", + } + } + + output_type = "string" + + def forward(self, category: str): + themes = { + "classic heroes": "Justice League Gala: ์†๋‹˜๋“ค์ด DC ์˜์›…์œผ๋กœ ๋ถ„์žฅํ•˜๊ณ , 'The Kryptonite Punch' ๊ฐ™์€ ํ…Œ๋งˆ ์นตํ…Œ์ผ ์ œ๊ณต.", + "villain masquerade": "Gotham Rogues' Ball: ์†๋‹˜๋“ค์ด ๋ฐฐํŠธ๋งจ ๋นŒ๋Ÿฐ์œผ๋กœ ๋ถ„์žฅํ•˜๋Š” ๋ฏธ์Šคํ„ฐ๋ฆฌ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ.", + "futuristic Gotham": "Neo-Gotham Night: ๋ฐฐํŠธ๋งจ ๋น„์š˜๋“œ์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ์‚ฌ์ด๋ฒ„ํŽ‘ํฌ ์Šคํƒ€์ผ ํŒŒํ‹ฐ, ๋„ค์˜จ ์žฅ์‹๊ณผ ๋ฏธ๋ž˜ํ˜• ์†Œํ’ˆ.", + } + + return themes.get(category.lower(), "ํ…Œ๋งˆ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. 'classic heroes', 'villain masquerade', 'futuristic Gotham' ์ค‘์—์„œ ์„ ํƒํ•ด๋ณด์„ธ์š”.") + +# ๋„๊ตฌ ์ธ์Šคํ„ด์Šคํ™” +party_theme_tool = SuperheroPartyThemeTool() +agent = CodeAgent(tools=[party_theme_tool], model=InferenceClientModel()) + +# ์—์ด์ „ํŠธ ์‹คํ–‰ ์˜ˆ์‹œ +result = agent.run( + "What would be a good superhero party idea for a 'villain masquerade' theme?" +) + +print(result) # ์ถœ๋ ฅ: "Gotham Rogues' Ball: ์†๋‹˜๋“ค์ด ๋ฐฐํŠธ๋งจ ๋นŒ๋Ÿฐ์œผ๋กœ ๋ถ„์žฅํ•˜๋Š” ๋ฏธ์Šคํ„ฐ๋ฆฌ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ." +``` + +์ด ๋„๊ตฌ๋กœ Alfred๋Š” ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ์˜ ์™„๋ฒฝํ•œ ํ˜ธ์ŠคํŠธ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๐Ÿฆธโ€โ™‚๏ธ๐Ÿฆธโ€โ™€๏ธ + +## ๊ธฐ๋ณธ ๋„๊ตฌ ๋ชจ์Œ(Default Toolbox) + +`smolagents`์—๋Š” ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ๊ธฐ๋ณธ ๋„๊ตฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. [๊ธฐ๋ณธ ๋„๊ตฌ ๋ชจ์Œ](https://huggingface.co/docs/smolagents/guided_tour?build-a-tool=Decorate+a+function+with+%40tool#default-toolbox)์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค: + +- **PythonInterpreterTool** +- **FinalAnswerTool** +- **UserInputTool** +- **DuckDuckGoSearchTool** +- **GoogleSearchTool** +- **VisitWebpageTool** + +Alfred๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹ค์–‘ํ•œ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•ด Wayne Manor์—์„œ ์™„๋ฒฝํ•œ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +- `DuckDuckGoSearchTool`๋กœ ์ฐฝ์˜์ ์ธ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด ๊ฒ€์ƒ‰ +- `GoogleSearchTool`๋กœ Gotham์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค ์ฐพ๊ธฐ +- `PythonInterpreterTool`๋กœ ์ขŒ์„ ๋ฐฐ์น˜ ๊ณ„์‚ฐ +- ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋ชจ์•„ `FinalAnswerTool`๋กœ ๊ณ„ํš ์ •๋ฆฌ + +์ด ๋„๊ตฌ๋“ค๋กœ Alfred๋Š” ์™„๋ฒฝํ•˜๊ณ  ๋งค๋„๋Ÿฌ์šด ํŒŒํ‹ฐ๋ฅผ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿฆ‡๐Ÿ’ก + +## ๋„๊ตฌ ๊ณต์œ  ๋ฐ ๊ฐ€์ ธ์˜ค๊ธฐ + +**smolagents**์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ์ปค์Šคํ…€ ๋„๊ตฌ๋ฅผ Hub์— ๊ณต์œ ํ•˜๊ณ , ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋งŒ๋“  ๋„๊ตฌ๋ฅผ ์‰ฝ๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” **HF Spaces** ๋ฐ **LangChain ๋„๊ตฌ**์™€์˜ ์—ฐ๋™๋„ ํฌํ•จ๋˜์–ด, Alfred๊ฐ€ Wayne Manor์—์„œ ์žŠ์ง€ ๋ชปํ•  ํŒŒํ‹ฐ๋ฅผ ๊ธฐํšํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ๐ŸŽญ + +์ด๋Ÿฌํ•œ ํ†ตํ•ฉ์„ ํ†ตํ•ด Alfred๋Š” ๊ณ ๊ธ‰ ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋‹ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์กฐ๋ช… ์กฐ์ •, ํŒŒํ‹ฐ ์Œ์•… ์ถ”์ฒœ, ์ผ€์ดํ„ฐ๋ง ์—…์ฒด์™€์˜ ํ˜‘์—… ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์•„๋ž˜๋Š” ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์ด ํŒŒํ‹ฐ ๊ฒฝํ—˜์„ ์–ด๋–ป๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ค๋Š”์ง€ ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค: + +### ๋„๊ตฌ๋ฅผ Hub์— ๊ณต์œ ํ•˜๊ธฐ + +์ปค์Šคํ…€ ๋„๊ตฌ๋ฅผ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค! `push_to_hub()` ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด Hugging Face ๊ณ„์ •์— ์—…๋กœ๋“œํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๋Š” ์ž์‹ ์˜ `party_theme_tool`์„ ๊ณต์œ ํ•ด ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๋„ Gotham ์ตœ๊ณ ์˜ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +party_theme_tool.push_to_hub("{your_username}/party_theme_tool", token="") +``` + +### Hub์—์„œ ๋„๊ตฌ ๊ฐ€์ ธ์˜ค๊ธฐ + +๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ ๋งŒ๋“  ๋„๊ตฌ๋ฅผ `load_tool()` ํ•จ์ˆ˜๋กœ ์‰ฝ๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๊ฐ€ AI๋กœ ํŒŒํ‹ฐ ํ™๋ณด ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด, ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +from smolagents import load_tool, CodeAgent, InferenceClientModel + +image_generation_tool = load_tool( + "m-ric/text-to-image", + trust_remote_code=True +) + +agent = CodeAgent( + tools=[image_generation_tool], + model=InferenceClientModel() +) + +agent.run("Generate an image of a luxurious superhero-themed party at Wayne Manor with made-up superheros.") +``` + +### HF Space๋ฅผ ๋„๊ตฌ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ + +`Tool.from_space()`๋ฅผ ์‚ฌ์šฉํ•ด HF Space๋ฅผ ๋„๊ตฌ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์ˆ˜์ฒœ ๊ฐœ Space์™€ ์—ฐ๋™ํ•ด ์ด๋ฏธ์ง€ ์ƒ์„ฑ, ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๋„๊ตฌ๋Š” `gradio_client`๋ฅผ ํ†ตํ•ด Space์˜ Gradio ๋ฐฑ์—”๋“œ์™€ ์—ฐ๊ฒฐ๋˜๋ฏ€๋กœ, ๋ฏธ๋ฆฌ pip๋กœ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +ํŒŒํ‹ฐ๋ฅผ ์œ„ํ•ด Alfred๋Š” AI๋กœ ์ƒ์„ฑํ•œ ์ด๋ฏธ์ง€๋ฅผ ํŒŒํ‹ฐ ๊ณต์ง€์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ๊ทธ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค: + +```python +from smolagents import CodeAgent, InferenceClientModel, Tool + +image_generation_tool = Tool.from_space( + "black-forest-labs/FLUX.1-schnell", + name="image_generator", + description="Generate an image from a prompt" +) + +model = InferenceClientModel("Qwen/Qwen2.5-Coder-32B-Instruct") + +agent = CodeAgent(tools=[image_generation_tool], model=model) + +agent.run( + "Improve this prompt, then generate an image of it.", + additional_args={'user_prompt': 'A grand superhero-themed party at Wayne Manor, with Alfred overseeing a luxurious gala'} +) +``` + +### LangChain ๋„๊ตฌ ๊ฐ€์ ธ์˜ค๊ธฐ + +`LangChain` ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ดํ›„ ์„น์…˜์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” smolagents ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ LangChain ๋„๊ตฌ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ๋งŒ ์•Œ์•„๋‘ก์‹œ๋‹ค! + +`Tool.from_langchain()` ๋ฉ”์„œ๋“œ๋กœ LangChain ๋„๊ตฌ๋ฅผ ์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Alfred๋Š” Wayne Manor์—์„œ ์ตœ๊ณ ์˜ ์—”ํ„ฐํ…Œ์ธ๋จผํŠธ ์•„์ด๋””์–ด๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด LangChain ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +from langchain.agents import load_tools +from smolagents import CodeAgent, InferenceClientModel, Tool + +search_tool = Tool.from_langchain(load_tools(["serpapi"])[0]) + +agent = CodeAgent(tools=[search_tool], model=model) + +agent.run("Search for luxury entertainment ideas for a superhero-themed event, such as live performances and interactive experiences.") +``` + +### MCP ์„œ๋ฒ„์—์„œ ๋„๊ตฌ ๋ชจ์Œ ๊ฐ€์ ธ์˜ค๊ธฐ + +`smolagents`๋Š” [glama.ai](https://glama.ai/mcp/servers) ๋˜๋Š” [smithery.ai](https://smithery.ai)์—์„œ ์ œ๊ณตํ•˜๋Š” ์ˆ˜๋ฐฑ ๊ฐœ MCP ์„œ๋ฒ„์˜ ๋„๊ตฌ๋„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MCP์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด [๋ฌด๋ฃŒ MCP ๊ฐ•์˜](https://huggingface.co/learn/mcp-course/)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +
+mcp ํด๋ผ์ด์–ธํŠธ ์„ค์น˜ + +๋จผ์ € `smolagents`์˜ mcp ํ†ตํ•ฉ์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +```bash +pip install "smolagents[mcp]" +``` +
+ +MCP ์„œ๋ฒ„์˜ ๋„๊ตฌ๋Š” ToolCollection ๊ฐ์ฒด๋กœ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +import os +from smolagents import ToolCollection, CodeAgent +from mcp import StdioServerParameters +from smolagents import InferenceClientModel + + +model = InferenceClientModel("Qwen/Qwen2.5-Coder-32B-Instruct") + + +server_parameters = StdioServerParameters( + command="uvx", + args=["--quiet", "pubmedmcp@0.1.3"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +with ToolCollection.from_mcp(server_parameters, trust_remote_code=True) as tool_collection: + agent = CodeAgent(tools=[*tool_collection.tools], model=model, add_base_tools=True) + agent.run("Please find a remedy for hangover.") +``` + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Alfred๋Š” ๊ณ ๊ธ‰ ์—”ํ„ฐํ…Œ์ธ๋จผํŠธ ์˜ต์…˜์„ ๋น ๋ฅด๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์–ด, Gotham์˜ ๋ช…์‚ฌ๋“ค์ด ์žŠ์ง€ ๋ชปํ•  ์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ๋ฅผ ์ฆ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [Tools Tutorial](https://huggingface.co/docs/smolagents/tutorials/tools) - ๋„๊ตฌ ์‚ฌ์šฉ๋ฒ•์„ ์ตํž ์ˆ˜ ์žˆ๋Š” ํŠœํ† ๋ฆฌ์–ผ +- [Tools Documentation](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools) - ๋„๊ตฌ์— ๋Œ€ํ•œ ๊ณต์‹ ๋ฌธ์„œ +- [Tools Guided Tour](https://huggingface.co/docs/smolagents/v1.8.1/en/guided_tour#tools) - ๋„๊ตฌ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๋งŒ๋“ค๊ณ  ํ™œ์šฉํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ๊ฐ€์ด๋“œ +- [Building Effective Agents](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - ์‹ ๋ขฐ์„ฑ ๋†’๊ณ  ์„ฑ๋Šฅ ์ข‹์€ ์ปค์Šคํ…€ ํ•จ์ˆ˜ ์—์ด์ „ํŠธ ๊ฐœ๋ฐœ ๊ฐ€์ด๋“œ diff --git a/units/ko/unit2/smolagents/vision_agents.mdx b/units/ko/unit2/smolagents/vision_agents.mdx new file mode 100644 index 00000000..fb9a6b84 --- /dev/null +++ b/units/ko/unit2/smolagents/vision_agents.mdx @@ -0,0 +1,224 @@ + + +# smolagents๋กœ ๋น„์ „ ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ + + +์ด ์„น์…˜์˜ ์˜ˆ์ œ๋Š” ๊ฐ•๋ ฅํ•œ VLM(๋น„์ „-์–ธ์–ด ๋ชจ๋ธ) API๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” GPT-4o API๋กœ ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ Why use smolagents์—์„œ๋Š” smolagents์™€ Hugging Face์—์„œ ์ง€์›ํ•˜๋Š” ๋Œ€์ฒด ์†”๋ฃจ์…˜๋„ ๋‹ค๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์˜ต์…˜์„ ํƒ์ƒ‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํ•ด๋‹น ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + + +์—์ด์ „ํŠธ์— ์‹œ๊ฐ์  ๋Šฅ๋ ฅ์„ ๋ถ€์—ฌํ•˜๋Š” ๊ฒƒ์€ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ ์ด์ƒ์˜ ์‹ค์ œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์›น ๋ธŒ๋ผ์šฐ์ง•์ด๋‚˜ ๋ฌธ์„œ ์ดํ•ด ๋“ฑ ๋งŽ์€ ์‹ค์ œ ๊ณผ์ œ๋Š” ํ’๋ถ€ํ•œ ์‹œ๊ฐ ์ •๋ณด๋ฅผ ๋ถ„์„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„, `smolagents`๋Š” ๋น„์ „-์–ธ์–ด ๋ชจ๋ธ(VLM)์„ ๋‚ด์žฅ ์ง€์›ํ•˜์—ฌ ์—์ด์ „ํŠธ๊ฐ€ ์ด๋ฏธ์ง€๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ํ•ด์„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. + +์ด ์˜ˆ์‹œ์—์„œ, Wayne Manor์˜ ์ง‘์‚ฌ Alfred๋Š” ํŒŒํ‹ฐ์— ์ฐธ์„ํ•˜๋Š” ์†๋‹˜๋“ค์˜ ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ์ž„๋ฌด๋ฅผ ๋งก์•˜์Šต๋‹ˆ๋‹ค. Alfred๋Š” ๋ชจ๋“  ์†๋‹˜์„ ์•Œ์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์†๋‹˜์˜ ์™ธ๋ชจ์— ๋Œ€ํ•œ ์‹œ๊ฐ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ด ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Alfred๋Š” ์ž…์žฅ ํ—ˆ๊ฐ€ ์—ฌ๋ถ€๋ฅผ ํ˜„๋ช…ํ•˜๊ฒŒ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋ฅผ ํ•จ๊ป˜ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค! + + +## ์—์ด์ „ํŠธ ์‹คํ–‰ ์‹œ์ž‘ ์‹œ ์ด๋ฏธ์ง€ ์ œ๊ณตํ•˜๊ธฐ + + +์ฝ”๋“œ๋Š” ์ด ๋…ธํŠธ๋ถ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Colab์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +์ด ๋ฐฉ์‹์—์„œ๋Š” ์ด๋ฏธ์ง€๋ฅผ ์—์ด์ „ํŠธ ์‹คํ–‰ ์‹œ์ ์— `task_images`๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ์ด ์ด๋ฏธ์ง€๋ฅผ ์ „์ฒด ์‹คํ–‰ ๊ณผ์ •์—์„œ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๋Š” ์ด์ „ ํŒŒํ‹ฐ์—์„œ ์†๋‹˜๋“ค์˜ ์ด๋ฆ„๊ณผ ํ•จ๊ป˜ ์ €์žฅ๋œ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์…‹์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ๋ฐฉ๋ฌธ๊ฐ์˜ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ›์•„, ๊ธฐ์กด ๋ฐ์ดํ„ฐ์…‹๊ณผ ๋น„๊ตํ•ด ์ž…์žฅ ํ—ˆ๊ฐ€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋ฒˆ์—๋Š” ํ•œ ์†๋‹˜์ด ์ž…์žฅํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ, Alfred๋Š” ์ด ์†๋‹˜์ด Wonder Woman์œผ๋กœ ์œ„์žฅํ•œ Joker์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์˜์‹ฌํ•ฉ๋‹ˆ๋‹ค. Alfred๋Š” ์‹ ์›์„ ํ™•์ธํ•ด ์›์น˜ ์•Š๋Š” ์ธ๋ฌผ์ด ์ž…์žฅํ•˜์ง€ ๋ชปํ•˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ์‹œ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์šฐ์„  ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์œ„ํ‚คํ”ผ๋””์•„ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ๋‹ค์–‘ํ•œ ํ™œ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค! + +```python +from PIL import Image +import requests +from io import BytesIO + +image_urls = [ + "https://upload.wikimedia.org/wikipedia/commons/e/e8/The_Joker_at_Wax_Museum_Plus.jpg", # Joker ์ด๋ฏธ์ง€ + "https://upload.wikimedia.org/wikipedia/en/9/98/Joker_%28DC_Comics_character%29.jpg" # Joker ์ด๋ฏธ์ง€ +] + +images = [] +for url in image_urls: + headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" + } + response = requests.get(url,headers=headers) + image = Image.open(BytesIO(response.content)).convert("RGB") + images.append(image) +``` + +์ด์ œ ์ด๋ฏธ์ง€๋ฅผ ์ค€๋น„ํ–ˆ์œผ๋‹ˆ, ์—์ด์ „ํŠธ๊ฐ€ ์†๋‹˜์ด Wonder Woman์ธ์ง€ Joker์ธ์ง€ ํŒ๋ณ„ํ•ด์ค๋‹ˆ๋‹ค. + +```python +from smolagents import CodeAgent, OpenAIServerModel + +model = OpenAIServerModel(model_id="gpt-4o") + +# ์—์ด์ „ํŠธ ์ธ์Šคํ„ด์Šคํ™” +agent = CodeAgent( + tools=[], + model=model, + max_steps=20, + verbosity_level=2 +) + +response = agent.run( + """ + ์ด ์‚ฌ์ง„ ์† ๋งŒํ™” ์บ๋ฆญํ„ฐ์˜ ์˜์ƒ๊ณผ ๋ฉ”์ดํฌ์—…์„ ๋ฌ˜์‚ฌํ•ด ์ฃผ์„ธ์š”. + ์†๋‹˜์ด The Joker์ธ์ง€ Wonder Woman์ธ์ง€ ์•Œ๋ ค์ฃผ์„ธ์š”. + """, + images=images +) +``` + +์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(์‹คํ–‰ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค): + +```python + { + 'Costume and Makeup - First Image': ( + '๋ณด๋ผ์ƒ‰ ์ฝ”ํŠธ์™€ ๋…ธ๋ž€์ƒ‰ ์…”์ธ  ์œ„์— ๋ณด๋ผ์ƒ‰ ์‹คํฌ ํฌ๋ผ๋ฐ”ํŠธ ๋˜๋Š” ํƒ€์ด.', + 'ํฐ์ƒ‰ ์–ผ๊ตด ๋ถ„์žฅ, ๊ณผ์žฅ๋œ ์ด๋ชฉ๊ตฌ๋น„, ์ง„ํ•œ ๋ˆˆ์น, ํŒŒ๋ž€ ์•„์ด์„€๋„, ๋นจ๊ฐ„ ์ž…์ˆ ๋กœ ๋„“์€ ๋ฏธ์†Œ.' + ), + 'Costume and Makeup - Second Image': ( + '๊ฝƒ์ด ๋‹ฌ๋ฆฐ ์–ด๋‘์šด ์ •์žฅ, ์†์— ํŠธ๋Ÿผํ”„ ์นด๋“œ๋ฅผ ๋“ค๊ณ  ์žˆ์Œ.', + '์ฐฝ๋ฐฑํ•œ ํ”ผ๋ถ€, ์ดˆ๋ก์ƒ‰ ๋จธ๋ฆฌ, ๊ณผ์žฅ๋œ ๋ฏธ์†Œ์˜ ๋นจ๊ฐ„ ์ž…์ˆ .' + ), + 'Character Identity': '์ด ์บ๋ฆญํ„ฐ๋Š” ๋งŒํ™”์—์„œ ๋ฌ˜์‚ฌ๋œ The Joker์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.' + } +``` + +์ด์ฒ˜๋Ÿผ, ๊ฒฐ๊ณผ๋ฅผ ํ†ตํ•ด ์†๋‹˜์ด ๋‹ค๋ฅธ ์ธ๋ฌผ๋กœ ์œ„์žฅํ–ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, Alfred๋Š” Joker์˜ ์ž…์žฅ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! + +## ๋™์  ๊ฒ€์ƒ‰์œผ๋กœ ์ด๋ฏธ์ง€ ์ œ๊ณตํ•˜๊ธฐ + + +์ฝ”๋“œ๋Š” ์ด Python ํŒŒ์ผ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + +์ด์ „ ๋ฐฉ์‹๋„ ์œ ์šฉํ•˜์ง€๋งŒ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์†๋‹˜์ด ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ์™ธ๋ถ€์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋™์ ์œผ๋กœ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์›น์„ ํƒ์ƒ‰ํ•˜๋ฉฐ ์†๋‹˜์— ๋Œ€ํ•œ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ์•„ ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. + +์ด ๋ฐฉ์‹์—์„œ๋Š” ์—์ด์ „ํŠธ ์‹คํ–‰ ์ค‘์— ์ด๋ฏธ์ง€๋ฅผ ๋™์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. smolagents์˜ ์—์ด์ „ํŠธ๋Š” `MultiStepAgent` ํด๋ž˜์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ์ด๋Š” ReAct ํ”„๋ ˆ์ž„์›Œํฌ์˜ ์ถ”์ƒํ™”์ž…๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” ๋‹ค์–‘ํ•œ ๋ณ€์ˆ˜์™€ ์ง€์‹์„ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์— ๊ฑธ์ณ ๊ธฐ๋กํ•˜๋Š” ๊ตฌ์กฐ์  ์‚ฌ์ดํด๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค: + +1. **SystemPromptStep:** ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ ์ €์žฅ +2. **TaskStep:** ์‚ฌ์šฉ์ž ์ฟผ๋ฆฌ ๋ฐ ์ž…๋ ฅ ๊ธฐ๋ก +3. **ActionStep:** ์—์ด์ „ํŠธ์˜ ์•ก์…˜ ๋ฐ ๊ฒฐ๊ณผ ๋กœ๊ทธ ๊ธฐ๋ก + +์ด ๊ตฌ์กฐ์  ์ ‘๊ทผ๋ฒ• ๋•๋ถ„์—, ์—์ด์ „ํŠธ๋Š” ์‹œ๊ฐ ์ •๋ณด๋ฅผ ๋™์ ์œผ๋กœ ํ†ตํ•ฉํ•˜๊ณ , ๋ณ€ํ™”ํ•˜๋Š” ์ž‘์—…์— ์ ์‘์ ์œผ๋กœ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ์ด๋Ÿฌํ•œ ๋™์  ์›Œํฌํ”Œ๋กœ์šฐ์™€ ๊ฐ ๋‹จ๊ณ„๊ฐ€ ์—์ด์ „ํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด์—์„œ ์–ด๋–ป๊ฒŒ ํ†ตํ•ฉ๋˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ง• ์ค‘์—๋Š” ์—์ด์ „ํŠธ๊ฐ€ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ์–ด `observation_images`์— ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +![Dynamic image retrieval](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/smolagents-can-see/diagram_adding_vlms_smolagents.png) + +์ด์ œ ํ•„์š”์„ฑ์„ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์ „์ฒด ์˜ˆ์‹œ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์ด๋ฒˆ์—๋Š” Alfred๊ฐ€ ์†๋‹˜ ์‹ ์› ํ™•์ธ ๊ณผ์ •์„ ์™„์ „ํžˆ ํ†ต์ œํ•˜๊ณ  ์‹ถ์–ด ํ•˜๋ฏ€๋กœ, ์›น์„ ํƒ์ƒ‰ํ•˜๋ฉฐ ์ •๋ณด๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ด ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด Selenium๊ณผ Helium ๋“ฑ ๋ธŒ๋ผ์šฐ์ € ์ž๋™ํ™” ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ๋ช…๋ น์–ด๋กœ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”: + +```bash +pip install "smolagents[all]" helium selenium python-dotenv +``` + +์—์ด์ „ํŠธ์—๋Š” ์›น ๋ธŒ๋ผ์šฐ์ง•์„ ์œ„ํ•œ `search_item_ctrl_f`, `go_back`, `close_popups` ๋“ฑ ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋„๊ตฌ๋“ค์€ ์‹ค์ œ ์‚ฌ์šฉ์ž๊ฐ€ ์›น์„ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. + +```python +@tool +def search_item_ctrl_f(text: str, nth_result: int = 1) -> str: + """ + ํ˜„์žฌ ํŽ˜์ด์ง€์—์„œ Ctrl + F๋กœ ํ…์ŠคํŠธ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  n๋ฒˆ์งธ ๊ฒฐ๊ณผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. + Args: + text: ๊ฒ€์ƒ‰ํ•  ํ…์ŠคํŠธ + nth_result: ๋ช‡ ๋ฒˆ์งธ ๊ฒฐ๊ณผ๋กœ ์ด๋™ํ• ์ง€(๊ธฐ๋ณธ๊ฐ’: 1) + """ + elements = driver.find_elements(By.XPATH, f"//*[contains(text(), '{text}')]") + if nth_result > len(elements): + raise Exception(f"{nth_result}๋ฒˆ์งธ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (์ด {len(elements)}๊ฐœ ์ผ์น˜)") + result = f"'{text}'์— ๋Œ€ํ•ด {len(elements)}๊ฐœ ์ผ์น˜." + elem = elements[nth_result - 1] + driver.execute_script("arguments[0].scrollIntoView(true);", elem) + result += f"{len(elements)}๊ฐœ ์ค‘ {nth_result}๋ฒˆ์งธ ์š”์†Œ๋กœ ํฌ์ปค์Šค ์ด๋™" + return result + + +@tool +def go_back() -> None: + """์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.""" + driver.back() + + +@tool +def close_popups() -> str: + """ + ํŽ˜์ด์ง€์˜ ๋ชจ๋‹ฌ ๋˜๋Š” ํŒ์—…์„ ๋‹ซ์Šต๋‹ˆ๋‹ค. ํŒ์—… ์ฐฝ์„ ๋‹ซ์„ ๋•Œ ์‚ฌ์šฉํ•˜์„ธ์š”! ์ฟ ํ‚ค ๋ฐฐ๋„ˆ์—๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + """ + webdriver.ActionChains(driver).send_keys(Keys.ESCAPE).perform() +``` + +๋˜ํ•œ, ์Šคํฌ๋ฆฐ์ƒท ์ €์žฅ ๊ธฐ๋Šฅ๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ๋ธŒ๋ผ์šฐ์ €์˜ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ์–ด `step_log.observations_images = [image.copy()]`์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์—์ด์ „ํŠธ๊ฐ€ ํƒ์ƒ‰ ์ค‘ ์ด๋ฏธ์ง€๋ฅผ ๋™์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```python +def save_screenshot(step_log: ActionStep, agent: CodeAgent) -> None: + sleep(1.0) # ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋Œ€๊ธฐ + driver = helium.get_driver() + current_step = step_log.step_number + if driver is not None: + for step_logs in agent.logs: # ์ด์ „ ์Šคํฌ๋ฆฐ์ƒท ์ •๋ฆฌ + if isinstance(step_log, ActionStep) and step_log.step_number <= current_step - 2: + step_logs.observations_images = None + png_bytes = driver.get_screenshot_as_png() + image = Image.open(BytesIO(png_bytes)) + print(f"๋ธŒ๋ผ์šฐ์ € ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜: {image.size} ํ”ฝ์…€") + step_log.observations_images = [image.copy()] + + # ํ˜„์žฌ URL ์ •๋ณด ์—…๋ฐ์ดํŠธ + url_info = f"ํ˜„์žฌ url: {driver.current_url}" + step_log.observations = url_info if step_logs.observations is None else step_log.observations + "\n" + url_info + return +``` + +์ด ํ•จ์ˆ˜๋Š” `step_callback`์œผ๋กœ ์—์ด์ „ํŠธ์— ์ „๋‹ฌ๋˜์–ด, ๊ฐ ๋‹จ๊ณ„๊ฐ€ ๋๋‚  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์—์ด์ „ํŠธ๋Š” ํƒ์ƒ‰ ๊ณผ์ •์—์„œ ์Šคํฌ๋ฆฐ์ƒท์„ ๋™์ ์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด์ œ, ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํƒ์ƒ‰ํ•˜๋ฉฐ ์‹œ๊ฐ ์ •๋ณด๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋น„์ „ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์•ž์„œ ๋งŒ๋“  ๋„๊ตฌ๋“ค๊ณผ `DuckDuckGoSearchTool`์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋„๊ตฌ๋Š” ์†๋‹˜ ์‹ ์› ํ™•์ธ์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์›น์—์„œ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค. + +```python +from smolagents import CodeAgent, OpenAIServerModel, DuckDuckGoSearchTool +model = OpenAIServerModel(model_id="gpt-4o") + +agent = CodeAgent( + tools=[DuckDuckGoSearchTool(), go_back, close_popups, search_item_ctrl_f], + model=model, + additional_authorized_imports=["helium"], + step_callbacks=[save_screenshot], + max_steps=20, + verbosity_level=2, +) +``` + +์ด์ œ Alfred๋Š” ์†๋‹˜ ์‹ ์› ํ™•์ธ์„ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—์ด์ „ํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +agent.run(""" +๋‚˜๋Š” Wayne Manor์˜ ์ง‘์‚ฌ Alfred๋กœ, ํŒŒํ‹ฐ์— ์ฐธ์„ํ•˜๋Š” ์†๋‹˜์˜ ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ์ž„๋ฌด๋ฅผ ๋งก๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ์Šˆํผํžˆ์–ด๋กœ๊ฐ€ Wonder Woman์ด๋ผ๊ณ  ์ฃผ์žฅํ•˜๋ฉฐ ์ž…์žฅํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ, ์ •๋ง ๊ทธ๋…€๊ฐ€ ๋งž๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +Wonder Woman์˜ ์ด๋ฏธ์ง€๋ฅผ ๊ฒ€์ƒ‰ํ•ด ์‹œ๊ฐ์  ํŠน์ง•์„ ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์„ธ์š”. ๋˜ํ•œ, Wikipedia์—์„œ ๊ทธ๋…€์˜ ์™ธ๋ชจ์— ๋Œ€ํ•œ ์ฃผ์š” ์ •๋ณด๋ฅผ ์ฐพ์•„์ฃผ์„ธ์š”. ์ด ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ž…์žฅ ํ—ˆ๊ฐ€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. +""" + helium_instructions) +``` + +์—ฌ๊ธฐ์„œ `helium_instructions`๋Š” ํƒ์ƒ‰์„ ์ œ์–ดํ•˜๋Š” ํŠน์ˆ˜ ํ”„๋กฌํ”„ํŠธ๋กœ, ์—์ด์ „ํŠธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์ˆœ์„œ๋กœ ์›น์„ ํƒ์ƒ‰ํ•˜๋„๋ก ์œ ๋„ํ•ฉ๋‹ˆ๋‹ค. + +์•„๋ž˜ ์˜์ƒ์—์„œ ์‹ค์ œ ๋™์ž‘์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + + +์ตœ์ข… ์ถœ๋ ฅ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +```python +Final answer: Wonder Woman์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋นจ๊ฐ„์ƒ‰๊ณผ ๊ธˆ์ƒ‰์˜ ์ƒ์˜, ํŒŒ๋ž€์ƒ‰ ๋ณ„๋ฌด๋Šฌ ํ•˜์˜, ๊ธˆ์ƒ‰ ํ‹ฐ์•„๋ผ, ์€์ƒ‰ ํŒ”์ฐŒ, ํ™ฉ๊ธˆ ์˜ฌ๊ฐ€๋ฏธ๋ฅผ ์ฐฉ์šฉํ•œ ๋ชจ์Šต์œผ๋กœ ๋ฌ˜์‚ฌ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋…€๋Š” Themyscira์˜ ๊ณต์ฃผ์ด์ž, ์ธ๊ฐ„ ์„ธ๊ณ„์—์„œ๋Š” Diana Prince๋กœ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. +``` + +์ด๋ ‡๊ฒŒ ํ•ด์„œ, ํŒŒํ‹ฐ ์ž…์žฅ ์†๋‹˜ ์‹ ์› ํ™•์ธ์„ ์œ„ํ•œ ๋น„์ „ ์—์ด์ „ํŠธ๋ฅผ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค! ์ด์ œ Alfred๋Š” ์˜ฌ๋ฐ”๋ฅธ ์†๋‹˜๋งŒ ์ž…์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ์™„๋ฒฝํ•˜๊ฒŒ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Wayne Manor์—์„œ ๋ฉ‹์ง„ ํŒŒํ‹ฐ๋ฅผ ์ฆ๊ธฐ์„ธ์š”! + + +## ์ถ”๊ฐ€ ์ž๋ฃŒ + +- [We just gave sight to smolagents](https://huggingface.co/blog/smolagents-can-see) - ๋น„์ „ ์—์ด์ „ํŠธ ๊ธฐ๋Šฅ์„ ์†Œ๊ฐœํ•˜๋Š” ๋ธ”๋กœ๊ทธ +- [Web Browser Automation with Agents ๐Ÿค–๐ŸŒ](https://huggingface.co/docs/smolagents/examples/web_browser) - ์›น ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ™œ์šฉํ•œ ์—์ด์ „ํŠธ ์˜ˆ์‹œ +- [Web Browser Vision Agent Example](https://github.com/huggingface/smolagents/blob/main/src/smolagents/vision_web_browser.py) - ์›น ๋ธŒ๋ผ์šฐ์ € ๋น„์ „ ์—์ด์ „ํŠธ ์˜ˆ์‹œ diff --git a/units/ko/unit2/smolagents/why_use_smolagents.mdx b/units/ko/unit2/smolagents/why_use_smolagents.mdx new file mode 100644 index 00000000..4bda418b --- /dev/null +++ b/units/ko/unit2/smolagents/why_use_smolagents.mdx @@ -0,0 +1,67 @@ +![smolagents banner](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/license_to_call.png) +# smolagents๋ฅผ ์จ์•ผ ํ•˜๋Š” ์ด์œ  + +์ด ๋ชจ๋“ˆ์—์„œ๋Š” [smolagents](https://huggingface.co/docs/smolagents/en/index)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์˜ ์žฅ๋‹จ์ ์„ ์‚ดํŽด๋ณด๊ณ , ์—ฌ๋Ÿฌ๋ถ„์˜ ํ•„์š”์— ๋งž๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ธ์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€๋“œ๋ฆฝ๋‹ˆ๋‹ค. + +## `smolagents`๋ž€? + +`smolagents`๋Š” ๊ฐ„๋‹จํ•˜๋ฉด์„œ๋„ ๊ฐ•๋ ฅํ•œ AI ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. LLM์ด ๊ฒ€์ƒ‰, ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋“ฑ ์‹ค์ œ ์„ธ๊ณ„์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” _์—์ด์ „์‹œ(agency)_ ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +unit 1์—์„œ ๋ฐฐ์šด ๊ฒƒ์ฒ˜๋Ÿผ, AI ์—์ด์ „ํŠธ๋Š” LLM์ด **'๊ด€์ฐฐ(observations)'**์„ ๋ฐ”ํƒ•์œผ๋กœ **'์ƒ๊ฐ(thoughts)'**์„ ์ƒ์„ฑํ•ด **'ํ–‰๋™(actions)'**์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. smolagents์—์„œ ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜๋Š”์ง€ ์‚ดํŽด๋ด…์‹œ๋‹ค. + +### `smolagents`์˜ ์ฃผ์š” ์žฅ์  +- **๋‹จ์ˆœํ•จ:** ์ตœ์†Œํ•œ์˜ ์ฝ”๋“œ ๋ณต์žก์„ฑ๊ณผ ์ถ”์ƒํ™”๋กœ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ , ๋„์ž… ๋ฐ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- **์œ ์—ฐํ•œ LLM ์ง€์›:** Hugging Face ๋„๊ตฌ ๋ฐ ์™ธ๋ถ€ API์™€์˜ ํ†ตํ•ฉ์„ ํ†ตํ•ด ์–ด๋–ค LLM๊ณผ๋„ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- **์ฝ”๋“œ ์šฐ์„  ์ ‘๊ทผ:** ์•ก์…˜์„ ์ง์ ‘ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋Š” Code Agent๋ฅผ 1๊ธ‰ ์‹œ๋ฏผ์œผ๋กœ ์ง€์›ํ•˜์—ฌ, ํŒŒ์‹ฑ ์—†์ด ๋„๊ตฌ ํ˜ธ์ถœ์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค. +- **HF Hub ํ†ตํ•ฉ:** Hugging Face Hub์™€์˜ ์›ํ™œํ•œ ํ†ตํ•ฉ์œผ๋กœ Gradio Spaces๋ฅผ ๋„๊ตฌ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### smolagents๋ฅผ ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ? + +์ด๋Ÿฌํ•œ ์žฅ์ ์„ ๊ณ ๋ คํ•  ๋•Œ, ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ ๋Œ€์‹  smolagents๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์–ธ์ œ์ผ๊นŒ์š”? + +smolagents๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์— ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค: +- **๊ฐ€๋ณ๊ณ  ์ตœ์†Œํ•œ์˜ ์†”๋ฃจ์…˜**์ด ํ•„์š”ํ•  ๋•Œ +- **๋ณต์žกํ•œ ์„ค์ • ์—†์ด ๋น ๋ฅด๊ฒŒ ์‹คํ—˜**ํ•˜๊ณ  ์‹ถ์„ ๋•Œ +- **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์ด ๋‹จ์ˆœ**ํ•  ๋•Œ + +### ์ฝ”๋“œ vs. JSON ์•ก์…˜ +๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ์—์ด์ „ํŠธ๊ฐ€ ์•ก์…˜์„ JSON์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๋ฐ˜๋ฉด, `smolagents`๋Š” **์ฝ”๋“œ ๊ธฐ๋ฐ˜ ๋„๊ตฌ ํ˜ธ์ถœ**์— ์ง‘์ค‘ํ•˜์—ฌ ์‹คํ–‰ ๊ณผ์ •์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋„๊ตฌ ํ˜ธ์ถœ์„ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜๋ฏ€๋กœ, JSON์„ ํŒŒ์‹ฑํ•ด ์ฝ”๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ณผ์ •์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ถœ๋ ฅ๋œ ์ฝ”๋“œ๋ฅผ ๋ฐ”๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ์ด ์ฐจ์ด๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค: + +![Code vs. JSON actions](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/code_vs_json_actions.png) + +Code vs JSON ์•ก์…˜์˜ ์ฐจ์ด๋ฅผ ๋‹ค์‹œ ๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด [Unit 1์˜ ์•ก์…˜ ์„น์…˜](https://huggingface.co/learn/agents-course/unit1/actions#actions-enabling-the-agent-to-engage-with-its-environment)์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +### smolagents์˜ ์—์ด์ „ํŠธ ์œ ํ˜• + +smolagents์˜ ์—์ด์ „ํŠธ๋Š” **๋‹ค๋‹จ๊ณ„ ์—์ด์ „ํŠธ(multi-step agent)**๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +๊ฐ [`MultiStepAgent`](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.MultiStepAgent)๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค: +- ํ•œ ๋ฒˆ์˜ ์ƒ๊ฐ(thought) +- ํ•œ ๋ฒˆ์˜ ๋„๊ตฌ ํ˜ธ์ถœ ๋ฐ ์‹คํ–‰ + +์ฃผ์š” ์—์ด์ „ํŠธ ํƒ€์ž…์œผ๋กœ **[CodeAgent](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.CodeAgent)**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋„๊ตฌ ํ˜ธ์ถœ์„ JSON์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” **[ToolCallingAgent](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.ToolCallingAgent)**๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. + +๊ฐ ์—์ด์ „ํŠธ ํƒ€์ž…์€ ์ดํ›„ ์„น์…˜์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + + +smolagents์—์„œ๋Š” ๋„๊ตฌ๋ฅผ @tool ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๊ฐ์‹ผ Python ํ•จ์ˆ˜ ๋˜๋Š” Tool ํด๋ž˜์Šค๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. + + +### smolagents์˜ ๋ชจ๋ธ ํ†ตํ•ฉ +`smolagents`๋Š” ์œ ์—ฐํ•œ LLM ํ†ตํ•ฉ์„ ์ง€์›ํ•˜์—ฌ, [ํŠน์ • ๊ธฐ์ค€](https://huggingface.co/docs/smolagents/main/en/reference/models)์„ ์ถฉ์กฑํ•˜๋Š” ์–ด๋–ค ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ๋ชจ๋ธ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋ชจ๋ธ ์—ฐ๊ฒฐ์„ ๋‹จ์ˆœํ™”ํ•˜๋Š” ์—ฌ๋Ÿฌ ์‚ฌ์ „ ์ •์˜ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค: + +- **[TransformersModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.TransformersModel):** ๋กœ์ปฌ `transformers` ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌํ˜„ํ•ด ์†์‰ฌ์šด ํ†ตํ•ฉ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +- **[InferenceClientModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.InferenceClientModel):** [Hugging Face ์ธํ”„๋ผ](https://huggingface.co/docs/api-inference/index) ๋˜๋Š” ๋‹ค์–‘ํ•œ [์„œ๋“œํŒŒํ‹ฐ ์ถ”๋ก  ์ œ๊ณต์—…์ฒด](https://huggingface.co/docs/huggingface_hub/main/en/guides/inference#supported-providers-and-tasks)๋ฅผ ํ†ตํ•œ [์„œ๋ฒ„๋ฆฌ์Šค ์ถ”๋ก ](https://huggingface.co/docs/huggingface_hub/main/en/guides/inference) ํ˜ธ์ถœ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +- **[LiteLLMModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.LiteLLMModel):** [LiteLLM](https://www.litellm.ai/)์„ ํ™œ์šฉํ•œ ๊ฒฝ๋Ÿ‰ ๋ชจ๋ธ ์—ฐ๋™์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +- **[OpenAIServerModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.OpenAIServerModel):** OpenAI API ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“  ์„œ๋น„์Šค์™€ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- **[AzureOpenAIServerModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.AzureOpenAIServerModel):** Azure OpenAI ๋ฐฐํฌ์™€์˜ ํ†ตํ•ฉ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Ÿฌํ•œ ์œ ์—ฐ์„ฑ ๋•๋ถ„์— ๊ฐœ๋ฐœ์ž๋Š” ๊ฐ์ž์˜ ์šฉ๋„์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋ชจ๋ธ๊ณผ ์„œ๋น„์Šค๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์‹คํ—˜๋„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด์ œ smolagents๋ฅผ ์™œ, ์–ธ์ œ ์จ์•ผ ํ•˜๋Š”์ง€ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์ด ๊ฐ•๋ ฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋” ๊นŠ์ด ํƒ๊ตฌํ•ด๋ด…์‹œ๋‹ค! + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [smolagents ๋ธ”๋กœ๊ทธ](https://huggingface.co/blog/smolagents) - smolagents์™€ ์ฝ”๋“œ ์ƒํ˜ธ์ž‘์šฉ ์†Œ๊ฐœ