From 8641053d635cdcd6b7208ebe1d65d21cf386fe62 Mon Sep 17 00:00:00 2001 From: Jeong Ahn Date: Wed, 2 Jul 2025 16:20:51 +0900 Subject: [PATCH 1/6] Update korean toctree --- units/ko/_toctree.yml | 94 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 14 deletions(-) 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 From e0877e991a17f288ef65c9bb19149ec16c8ee52f Mon Sep 17 00:00:00 2001 From: Jeong Ahn Date: Wed, 2 Jul 2025 16:27:19 +0900 Subject: [PATCH 2/6] docs: ko : unit2 --- units/ko/unit2/introduction.mdx | 40 ++ units/ko/unit2/langgraph/building_blocks.mdx | 127 ++++++ units/ko/unit2/langgraph/conclusion.mdx | 21 + .../langgraph/document_analysis_agent.mdx | 268 ++++++++++++ units/ko/unit2/langgraph/first_graph.mdx | 375 ++++++++++++++++ units/ko/unit2/langgraph/introduction.mdx | 32 ++ units/ko/unit2/langgraph/quiz1.mdx | 118 +++++ .../unit2/langgraph/when_to_use_langgraph.mdx | 68 +++ units/ko/unit2/llama-index/README.md | 15 + units/ko/unit2/llama-index/agents.mdx | 160 +++++++ units/ko/unit2/llama-index/components.mdx | 243 +++++++++++ units/ko/unit2/llama-index/conclusion.mdx | 13 + units/ko/unit2/llama-index/introduction.mdx | 30 ++ units/ko/unit2/llama-index/llama-hub.mdx | 55 +++ units/ko/unit2/llama-index/quiz1.mdx | 117 +++++ units/ko/unit2/llama-index/quiz2.mdx | 112 +++++ units/ko/unit2/llama-index/tools.mdx | 141 ++++++ units/ko/unit2/llama-index/workflows.mdx | 280 ++++++++++++ units/ko/unit2/smolagents/code_agents.mdx | 393 +++++++++++++++++ units/ko/unit2/smolagents/conclusion.mdx | 11 + units/ko/unit2/smolagents/final_quiz.mdx | 25 ++ units/ko/unit2/smolagents/introduction.mdx | 69 +++ .../unit2/smolagents/multi_agent_systems.mdx | 413 ++++++++++++++++++ units/ko/unit2/smolagents/quiz1.mdx | 142 ++++++ units/ko/unit2/smolagents/quiz2.mdx | 147 +++++++ .../ko/unit2/smolagents/retrieval_agents.mdx | 168 +++++++ .../unit2/smolagents/tool_calling_agents.mdx | 74 ++++ units/ko/unit2/smolagents/tools.mdx | 308 +++++++++++++ units/ko/unit2/smolagents/vision_agents.mdx | 224 ++++++++++ .../unit2/smolagents/why_use_smolagents.mdx | 67 +++ 30 files changed, 4256 insertions(+) create mode 100644 units/ko/unit2/introduction.mdx create mode 100644 units/ko/unit2/langgraph/building_blocks.mdx create mode 100644 units/ko/unit2/langgraph/conclusion.mdx create mode 100644 units/ko/unit2/langgraph/document_analysis_agent.mdx create mode 100644 units/ko/unit2/langgraph/first_graph.mdx create mode 100644 units/ko/unit2/langgraph/introduction.mdx create mode 100644 units/ko/unit2/langgraph/quiz1.mdx create mode 100644 units/ko/unit2/langgraph/when_to_use_langgraph.mdx create mode 100644 units/ko/unit2/llama-index/README.md create mode 100644 units/ko/unit2/llama-index/agents.mdx create mode 100644 units/ko/unit2/llama-index/components.mdx create mode 100644 units/ko/unit2/llama-index/conclusion.mdx create mode 100644 units/ko/unit2/llama-index/introduction.mdx create mode 100644 units/ko/unit2/llama-index/llama-hub.mdx create mode 100644 units/ko/unit2/llama-index/quiz1.mdx create mode 100644 units/ko/unit2/llama-index/quiz2.mdx create mode 100644 units/ko/unit2/llama-index/tools.mdx create mode 100644 units/ko/unit2/llama-index/workflows.mdx create mode 100644 units/ko/unit2/smolagents/code_agents.mdx create mode 100644 units/ko/unit2/smolagents/conclusion.mdx create mode 100644 units/ko/unit2/smolagents/final_quiz.mdx create mode 100644 units/ko/unit2/smolagents/introduction.mdx create mode 100644 units/ko/unit2/smolagents/multi_agent_systems.mdx create mode 100644 units/ko/unit2/smolagents/quiz1.mdx create mode 100644 units/ko/unit2/smolagents/quiz2.mdx create mode 100644 units/ko/unit2/smolagents/retrieval_agents.mdx create mode 100644 units/ko/unit2/smolagents/tool_calling_agents.mdx create mode 100644 units/ko/unit2/smolagents/tools.mdx create mode 100644 units/ko/unit2/smolagents/vision_agents.mdx create mode 100644 units/ko/unit2/smolagents/why_use_smolagents.mdx diff --git a/units/ko/unit2/introduction.mdx b/units/ko/unit2/introduction.mdx new file mode 100644 index 00000000..17af271f --- /dev/null +++ b/units/ko/unit2/introduction.mdx @@ -0,0 +1,40 @@ +# Introduction to Agentic Frameworks + +Thumbnail + +Welcome to this second unit, where **we'll explore different agentic frameworks** that can be used to build powerful agentic applications. + +We will study: + +- In Unit 2.1: [smolagents](https://huggingface.co/docs/smolagents/en/index) +- In Unit 2.2: [LlamaIndex](https://www.llamaindex.ai/) +- In Unit 2.3: [LangGraph](https://www.langchain.com/langgraph) + +Let's dive in! ๐Ÿ•ต + +## When to Use an Agentic Framework + +An agentic framework is **not always needed when building an application around LLMs**. They provide flexibility in the workflow to efficiently solve a specific task, but they're not always necessary. + +Sometimes, **predefined workflows are sufficient** to fulfill user requests, and there is no real need for an agentic framework. If the approach to build an agent is simple, like a chain of prompts, using plain code may be enough. The advantage is that the developer will have **full control and understanding of their system without abstractions**. + +However, when the workflow becomes more complex, such as letting an LLM call functions or using multiple agents, these abstractions start to become helpful. + +Considering these ideas, we can already identify the need for some features: + +* An *LLM engine* that powers the system. +* A *list of tools* the agent can access. +* A *parser* for extracting tool calls from the LLM output. +* A *system prompt* synced with the parser. +* A *memory system*. +* *Error logging and retry mechanisms* to control LLM mistakes. + +We'll explore how these topics are resolved in various frameworks, including `smolagents`, `LlamaIndex`, and `LangGraph`. + +## Agentic Frameworks Units + +| Framework | Description | Unit Author | +|------------|----------------|----------------| +| [smolagents](./smolagents/introduction) | Agents framework developed by 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) | End-to-end tooling to ship a context-augmented AI agent to production | David Berenstein - [HF](https://huggingface.co/davidberenstein1957) - [X](https://x.com/davidberenstei) - [Linkedin](https://www.linkedin.com/in/davidberenstein) | +| [LangGraph](./langgraph/introduction) | Agents allowing stateful orchestration of agents | 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..3b322ca2 --- /dev/null +++ b/units/ko/unit2/langgraph/building_blocks.mdx @@ -0,0 +1,127 @@ +# Building Blocks of LangGraph + +To build applications with LangGraph, you need to understand its core components. Let's explore the fundamental building blocks that make up a LangGraph application. + +Building Blocks + +An application in LangGraph starts from an **entrypoint**, and depending on the execution, the flow may go to one function or another until it reaches the END. + +Application + +## 1. State + +**State** is the central concept in LangGraph. It represents all the information that flows through your application. + +```python +from typing_extensions import TypedDict + +class State(TypedDict): + graph_state: str +``` + +The state is **User defined**, hence the fields should carefully be crafted to contain all data needed for decision-making process! + +> ๐Ÿ’ก **Tip:** Think carefully about what information your application needs to track between steps. + +## 2. Nodes + +**Nodes** are python functions. Each node: +- Takes the state as input +- Performs some operation +- Returns updates to the state + +```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!"} +``` + +For example, Nodes can contain: +- **LLM calls**: Generate text or make decisions +- **Tool calls**: Interact with external systems +- **Conditional logic**: Determine next steps +- **Human intervention**: Get input from users + +> ๐Ÿ’ก **Info:** Some nodes necessary for the whole workflow like START and END exist from langGraph directly. + + +## 3. Edges + +**Edges** connect nodes and define the possible paths through your graph: + +```python +import random +from typing import Literal + +def decide_mood(state) -> Literal["node_2", "node_3"]: + + # Often, we will use state to decide on the next node to visit + user_input = state['graph_state'] + + # Here, let's just do a 50 / 50 split between nodes 2, 3 + if random.random() < 0.5: + + # 50% of the time, we return Node 2 + return "node_2" + + # 50% of the time, we return Node 3 + return "node_3" +``` + +Edges can be: +- **Direct**: Always go from node A to node B +- **Conditional**: Choose the next node based on the current state + +## 4. StateGraph + +The **StateGraph** is the container that holds your entire agent workflow: + +```python +from IPython.display import Image, display +from langgraph.graph import StateGraph, START, END + +# Build graph +builder = StateGraph(State) +builder.add_node("node_1", node_1) +builder.add_node("node_2", node_2) +builder.add_node("node_3", node_3) + +# Logic +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) + +# Add +graph = builder.compile() +``` + +Which can then be visualized! +```python +# View +display(Image(graph.get_graph().draw_mermaid_png())) +``` +Graph Visualization + +But most importantly, invoked: +```python +graph.invoke({"graph_state" : "Hi, this is Lance."}) +``` +output : +``` +---Node 1--- +---Node 3--- +{'graph_state': 'Hi, this is Lance. I am sad!'} +``` + +## What's Next? + +In the next section, we'll put these concepts into practice by building our first graph. This graph lets Alfred take in your e-mails, classify them, and craft a preliminary answer if they are genuine. diff --git a/units/ko/unit2/langgraph/conclusion.mdx b/units/ko/unit2/langgraph/conclusion.mdx new file mode 100644 index 00000000..29dcc73b --- /dev/null +++ b/units/ko/unit2/langgraph/conclusion.mdx @@ -0,0 +1,21 @@ +# Conclusion + +Congratulations on finishing the `LangGraph` module of this second Unit! ๐Ÿฅณ + +You've now mastered the fundamentals of building structured workflows with LangGraph which you will be able to send to production. + +This module is just the beginning of your journey with LangGraph. For more advanced topics, we recommend: + +- Exploring the [official LangGraph documentation](https://github.com/langchain-ai/langgraph) +- Taking the comprehensive [Introduction to LangGraph](https://academy.langchain.com/courses/intro-to-langgraph) course from LangChain Academy +- Build something yourself ! + +In the next Unit, you'll now explore real use cases. It's time to leave theory to get into real action ! + +We would greatly appreciate **your thoughts on the course and suggestions for improvement**. If you have feedback, please ๐Ÿ‘‰ [fill this form](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) + +### Keep Learning, Stay Awesome! ๐Ÿค— + +Good Sir/Madam! ๐ŸŽฉ๐Ÿฆ‡ + +-Alfred- \ 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..65f972eb --- /dev/null +++ b/units/ko/unit2/langgraph/document_analysis_agent.mdx @@ -0,0 +1,268 @@ +# Document Analysis Graph + +Alfred at your service. As Mr. Wayne's trusted butler, I've taken the liberty of documenting how I assist Mr Wayne with his various documentary needs. While he's out attending to his... nighttime activities, I ensure all his paperwork, training schedules, and nutritional plans are properly analyzed and organized. + +Before leaving, he left a note with his week's training program. I then took the responsibility to come up with a **menu** for tomorrow's meals. + +For future such events, let's create a document analysis system using LangGraph to serve Mr. Wayne's needs. This system can: + +1. Process images document +2. Extract text using vision models (Vision Language Model) +3. Perform calculations when needed (to demonstrate normal tools) +4. Analyze content and provide concise summaries +5. Execute specific instructions related to documents + +## The Butler's Workflow + +The workflow weโ€™ll build follows this structured schema: + +![Butler's Document Analysis Workflow](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/alfred_flow.png) + + +You can follow the code in this notebook that you can run using Google Colab. + + +## Setting Up the environment + +```python +%pip install langgraph langchain_openai langchain_core +``` +and imports : +```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 + +This state is a little more complex than the previous ones we have seen. +`AnyMessage` is a class from Langchain that defines messages, and `add_messages` is an operator that adds the latest message rather than overwriting it with the latest state. + +This is a new concept in LangGraph, where you can add operators in your state to define the way they should interact together. + +```python +class AgentState(TypedDict): + # The document provided + input_file: Optional[str] # Contains file path (PDF/PNG) + messages: Annotated[list[AnyMessage], add_messages] +``` + +## Preparing Tools + +```python +vision_llm = ChatOpenAI(model="gpt-4o") + +def extract_text(img_path: str) -> str: + """ + Extract text from an image file using a multimodal model. + + Master Wayne often leaves notes with his training regimen or meal plans. + This allows me to properly analyze the contents. + """ + all_text = "" + try: + # Read image and encode as base64 + with open(img_path, "rb") as image_file: + image_bytes = image_file.read() + + image_base64 = base64.b64encode(image_bytes).decode("utf-8") + + # Prepare the prompt including the base64 image data + message = [ + HumanMessage( + content=[ + { + "type": "text", + "text": ( + "Extract all the text from this image. " + "Return only the extracted text, no explanations." + ), + }, + { + "type": "image_url", + "image_url": { + "url": f"data:image/png;base64,{image_base64}" + }, + }, + ] + ) + ] + + # Call the vision-capable model + response = vision_llm.invoke(message) + + # Append extracted text + all_text += response.content + "\n\n" + + return all_text.strip() + except Exception as e: + # A butler should handle errors gracefully + error_msg = f"Error extracting text: {str(e)}" + print(error_msg) + return "" + +def divide(a: int, b: int) -> float: + """Divide a and b - for Master Wayne's occasional calculations.""" + return a / b + +# Equip the butler with tools +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): + # System message + textual_description_of_tool=""" +extract_text(img_path: str) -> str: + Extract text from an image file using a multimodal model. + + Args: + img_path: A local image file path (strings). + + Returns: + A single string containing the concatenated text extracted from each image. +divide(a: int, b: int) -> float: + Divide a and b +""" + image=state["input_file"] + sys_msg = SystemMessage(content=f"You are a helpful butler named Alfred that serves Mr. Wayne and Batman. You can analyse documents and run computations with provided tools:\n{textual_description_of_tool} \n You have access to some optional images. Currently the loaded image is: {image}") + + return { + "messages": [llm_with_tools.invoke([sys_msg] + state["messages"])], + "input_file": state["input_file"] + } +``` + +## The ReAct Pattern: How I Assist Mr. Wayne + +Allow me to explain the approach in this agent. The agent follows what's known as the ReAct pattern (Reason-Act-Observe) + +1. **Reason** about his documents and requests +2. **Act** by using appropriate tools +3. **Observe** the results +4. **Repeat** as necessary until I've fully addressed his needs + +This is a simple implementation of an agent using LangGraph. + +```python +# The graph +builder = StateGraph(AgentState) + +# Define nodes: these do the work +builder.add_node("assistant", assistant) +builder.add_node("tools", ToolNode(tools)) + +# Define edges: these determine how the control flow moves +builder.add_edge(START, "assistant") +builder.add_conditional_edges( + "assistant", + # If the latest message requires a tool, route to tools + # Otherwise, provide a direct response + tools_condition, +) +builder.add_edge("tools", "assistant") +react_graph = builder.compile() + +# Show the butler's thought process +display(Image(react_graph.get_graph(xray=True).draw_mermaid_png())) +``` + +We define a `tools` node with our list of tools. The `assistant` node is just our model with bound tools. +We create a graph with `assistant` and `tools` nodes. + +We add a `tools_condition` edge, which routes to `End` or to `tools` based on whether the `assistant` calls a tool. + +Now, we add one new step: + +We connect the `tools` node back to the `assistant`, forming a loop. + +- After the `assistant` node executes, `tools_condition` checks if the model's output is a tool call. +- If it is a tool call, the flow is directed to the `tools` node. +- The `tools` node connects back to `assistant`. +- This loop continues as long as the model decides to call tools. +- If the model response is not a tool call, the flow is directed to END, terminating the process. + +![ReAct Pattern](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/Agent.png) + +## The Butler in Action + +### Example 1: Simple Calculations + +Here is an example to show a simple use case of an agent using a tool in LangGraph. + +```python +messages = [HumanMessage(content="Divide 6790 by 5")] +messages = react_graph.invoke({"messages": messages, "input_file": None}) + +# Show the messages +for m in messages['messages']: + m.pretty_print() +``` + +The conversation would proceed: + +``` +Human: Divide 6790 by 5 + +AI Tool Call: divide(a=6790, b=5) + +Tool Response: 1358.0 + +Alfred: The result of dividing 6790 by 5 is 1358.0. +``` + +### Example 2: Analyzing Master Wayne's Training Documents + +When Master Wayne leaves his training and meal notes: + +```python +messages = [HumanMessage(content="According to the note provided by Mr. Wayne in the provided images. What's the list of items I should buy for the dinner menu?")] +messages = react_graph.invoke({"messages": messages, "input_file": "Batman_training_and_meals.png"}) +``` + +The interaction would proceed: + +``` +Human: According to the note provided by Mr. Wayne in the provided images. What's the list of items I should buy for the dinner menu? + +AI Tool Call: extract_text(img_path="Batman_training_and_meals.png") + +Tool Response: [Extracted text with training schedule and menu details] + +Alfred: For the dinner menu, you should buy the following items: + +1. Grass-fed local sirloin steak +2. Organic spinach +3. Piquillo peppers +4. Potatoes (for oven-baked golden herb potato) +5. Fish oil (2 grams) + +Ensure the steak is grass-fed and the spinach and peppers are organic for the best quality meal. +``` + +## Key Takeaways + +Should you wish to create your own document analysis butler, here are key considerations: + +1. **Define clear tools** for specific document-related tasks +2. **Create a robust state tracker** to maintain context between tool calls +3. **Consider error handling** for tool failures +4. **Maintain contextual awareness** of previous interactions (ensured by the operator `add_messages`) + +With these principles, you too can provide exemplary document analysis service worthy of Wayne Manor. + +*I trust this explanation has been satisfactory. Now, if you'll excuse me, Master Wayne's cape requires pressing before tonight's activities.* diff --git a/units/ko/unit2/langgraph/first_graph.mdx b/units/ko/unit2/langgraph/first_graph.mdx new file mode 100644 index 00000000..ff105626 --- /dev/null +++ b/units/ko/unit2/langgraph/first_graph.mdx @@ -0,0 +1,375 @@ +# Building Your First LangGraph + +Now that we understand the building blocks, let's put them into practice by building our first functional graph. We'll implement Alfred's email processing system, where he needs to: + +1. Read incoming emails +2. Classify them as spam or legitimate +3. Draft a preliminary response for legitimate emails +4. Send information to Mr. Wayne when legitimate (printing only) + +This example demonstrates how to structure a workflow with LangGraph that involves LLM-based decision-making. While this can't be considered an Agent as no tool is involved, this section focuses more on learning the LangGraph framework than Agents. + + +You can follow the code in this notebook that you can run using Google Colab. + + +## Our Workflow + +Here's the workflow we'll build: +First LangGraph + +## Setting Up Our Environment + +First, let's install the required packages: + +```python +%pip install langgraph langchain_openai +``` + +Next, let's import the necessary modules: + +```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 +``` + +## Step 1: Define Our State + +Let's define what information Alfred needs to track during the email processing workflow: + +```python +class EmailState(TypedDict): + # The email being processed + email: Dict[str, Any] # Contains subject, sender, body, etc. + + # Category of the email (inquiry, complaint, etc.) + email_category: Optional[str] + + # Reason why the email was marked as spam + spam_reason: Optional[str] + + # Analysis and decisions + is_spam: Optional[bool] + + # Response generation + email_draft: Optional[str] + + # Processing metadata + messages: List[Dict[str, Any]] # Track conversation with LLM for analysis +``` + +> ๐Ÿ’ก **Tip:** Make your state comprehensive enough to track all the important information, but avoid bloating it with unnecessary details. + +## Step 2: Define Our Nodes + +Now, let's create the processing functions that will form our nodes: + +```python +# Initialize our LLM +model = ChatOpenAI(temperature=0) + +def read_email(state: EmailState): + """Alfred reads and logs the incoming email""" + email = state["email"] + + # Here we might do some initial preprocessing + print(f"Alfred is processing an email from {email['sender']} with subject: {email['subject']}") + + # No state changes needed here + return {} + +def classify_email(state: EmailState): + """Alfred uses an LLM to determine if the email is spam or legitimate""" + email = state["email"] + + # Prepare our prompt for the LLM + prompt = f""" + As Alfred the butler, analyze this email and determine if it is spam or legitimate. + + Email: + From: {email['sender']} + Subject: {email['subject']} + Body: {email['body']} + + First, determine if this email is spam. If it is spam, explain why. + If it is legitimate, categorize it (inquiry, complaint, thank you, etc.). + """ + + # Call the LLM + messages = [HumanMessage(content=prompt)] + response = model.invoke(messages) + + # Simple logic to parse the response (in a real app, you'd want more robust parsing) + response_text = response.content.lower() + is_spam = "spam" in response_text and "not spam" not in response_text + + # Extract a reason if it's spam + spam_reason = None + if is_spam and "reason:" in response_text: + spam_reason = response_text.split("reason:")[1].strip() + + # Determine category if legitimate + 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 + + # Update messages for tracking + new_messages = state.get("messages", []) + [ + {"role": "user", "content": prompt}, + {"role": "assistant", "content": response.content} + ] + + # Return state updates + return { + "is_spam": is_spam, + "spam_reason": spam_reason, + "email_category": email_category, + "messages": new_messages + } + +def handle_spam(state: EmailState): + """Alfred discards spam email with a note""" + print(f"Alfred has marked the email as spam. Reason: {state['spam_reason']}") + print("The email has been moved to the spam folder.") + + # We're done processing this email + return {} + +def draft_response(state: EmailState): + """Alfred drafts a preliminary response for legitimate emails""" + email = state["email"] + category = state["email_category"] or "general" + + # Prepare our prompt for the LLM + prompt = f""" + As Alfred the butler, draft a polite preliminary response to this email. + + Email: + From: {email['sender']} + Subject: {email['subject']} + Body: {email['body']} + + This email has been categorized as: {category} + + Draft a brief, professional response that Mr. Hugg can review and personalize before sending. + """ + + # Call the LLM + messages = [HumanMessage(content=prompt)] + response = model.invoke(messages) + + # Update messages for tracking + new_messages = state.get("messages", []) + [ + {"role": "user", "content": prompt}, + {"role": "assistant", "content": response.content} + ] + + # Return state updates + return { + "email_draft": response.content, + "messages": new_messages + } + +def notify_mr_hugg(state: EmailState): + """Alfred notifies Mr. Hugg about the email and presents the draft response""" + email = state["email"] + + print("\n" + "="*50) + print(f"Sir, you've received an email from {email['sender']}.") + print(f"Subject: {email['subject']}") + print(f"Category: {state['email_category']}") + print("\nI've prepared a draft response for your review:") + print("-"*50) + print(state["email_draft"]) + print("="*50 + "\n") + + # We're done processing this email + return {} +``` + +## Step 3: Define Our Routing Logic + +We need a function to determine which path to take after classification: + +```python +def route_email(state: EmailState) -> str: + """Determine the next step based on spam classification""" + if state["is_spam"]: + return "spam" + else: + return "legitimate" +``` + +> ๐Ÿ’ก **Note:** This routing function is called by LangGraph to determine which edge to follow after the classification node. The return value must match one of the keys in our conditional edges mapping. + +## Step 4: Create the StateGraph and Define Edges + +Now we connect everything together: + +```python +# Create the graph +email_graph = StateGraph(EmailState) + +# Add nodes +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) + +# Start the edges +email_graph.add_edge(START, "read_email") +# Add edges - defining the flow +email_graph.add_edge("read_email", "classify_email") + +# Add conditional branching from classify_email +email_graph.add_conditional_edges( + "classify_email", + route_email, + { + "spam": "handle_spam", + "legitimate": "draft_response" + } +) + +# Add the final edges +email_graph.add_edge("handle_spam", END) +email_graph.add_edge("draft_response", "notify_mr_hugg") +email_graph.add_edge("notify_mr_hugg", END) + +# Compile the graph +compiled_graph = email_graph.compile() +``` + +Notice how we use the special `END` node provided by LangGraph. This indicates terminal states where the workflow completes. + +## Step 5: Run the Application + +Let's test our graph with a legitimate email and a spam email: + +```python +# Example legitimate email +legitimate_email = { + "sender": "john.smith@example.com", + "subject": "Question about your services", + "body": "Dear Mr. Hugg, I was referred to you by a colleague and I'm interested in learning more about your consulting services. Could we schedule a call next week? Best regards, John Smith" +} + +# Example spam email +spam_email = { + "sender": "winner@lottery-intl.com", + "subject": "YOU HAVE WON $5,000,000!!!", + "body": "CONGRATULATIONS! You have been selected as the winner of our international lottery! To claim your $5,000,000 prize, please send us your bank details and a processing fee of $100." +} + +# Process the legitimate email +print("\nProcessing legitimate email...") +legitimate_result = compiled_graph.invoke({ + "email": legitimate_email, + "is_spam": None, + "spam_reason": None, + "email_category": None, + "email_draft": None, + "messages": [] +}) + +# Process the spam email +print("\nProcessing spam email...") +spam_result = compiled_graph.invoke({ + "email": spam_email, + "is_spam": None, + "spam_reason": None, + "email_category": None, + "email_draft": None, + "messages": [] +}) +``` + +## Step 6: Inspecting Our Mail Sorting Agent with Langfuse ๐Ÿ“ก + +As Alfred fine-tunes the Mail Sorting Agent, he's growing weary of debugging its runs. Agents, by nature, are unpredictable and difficult to inspect. But since he aims to build the ultimate Spam Detection Agent and deploy it in production, he needs robust traceability for future monitoring and analysis. + +To do this, Alfred can use an observability tool such as [Langfuse](https://langfuse.com/) to trace and monitor the agent. + +First, we pip install Langfuse: +```python +%pip install -q langfuse +``` + +Second, we pip install Langchain (LangChain is required because we use LangFuse): +```python +%pip install langchain +``` + +Next, we add the Langfuse API keys and host address as environment variables. You can get your Langfuse credentials by signing up for [Langfuse Cloud](https://cloud.langfuse.com) or [self-host Langfuse](https://langfuse.com/self-hosting). + +```python +import os + +# Get keys for your project from the project settings page: 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 region +# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # ๐Ÿ‡บ๐Ÿ‡ธ US region +``` + +Then, we configure the [Langfuse `callback_handler`](https://langfuse.com/docs/integrations/langchain/tracing#add-langfuse-to-your-langchain-application) and instrument the agent by adding the `langfuse_callback` to the invocation of the graph: `config={"callbacks": [langfuse_handler]}`. + +```python +from langfuse.langchain import CallbackHandler + +# Initialize Langfuse CallbackHandler for LangGraph/Langchain (tracing) +langfuse_handler = CallbackHandler() + +# Process legitimate email +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]} +) +``` + +Alfred is now connected ๐Ÿ”Œ! The runs from LangGraph are being logged in Langfuse, giving him full visibility into the agent's behavior. With this setup, he's ready to revisit previous runs and refine his Mail Sorting Agent even further. + +![Example trace in Langfuse](https://langfuse.com/images/cookbook/huggingface-agent-course/langgraph-trace-legit.png) + +_[Public link to the trace with the legit email](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 allows us to visualize our workflow to better understand and debug its structure: + +```python +compiled_graph.get_graph().draw_mermaid_png() +``` +Mail LangGraph + +This produces a visual representation showing how our nodes are connected and the conditional paths that can be taken. + +## What We've Built + +We've created a complete email processing workflow that: + +1. Takes an incoming email +2. Uses an LLM to classify it as spam or legitimate +3. Handles spam by discarding it +4. For legitimate emails, drafts a response and notifies Mr. Hugg + +This demonstrates the power of LangGraph to orchestrate complex workflows with LLMs while maintaining a clear, structured flow. + +## Key Takeaways + +- **State Management**: We defined comprehensive state to track all aspects of email processing +- **Node Implementation**: We created functional nodes that interact with an LLM +- **Conditional Routing**: We implemented branching logic based on email classification +- **Terminal States**: We used the END node to mark completion points in our workflow + +## What's Next? + +In the next section, we'll explore more advanced features of LangGraph, including handling human interaction in the workflow and implementing more complex branching logic based on multiple conditions. diff --git a/units/ko/unit2/langgraph/introduction.mdx b/units/ko/unit2/langgraph/introduction.mdx new file mode 100644 index 00000000..e6321312 --- /dev/null +++ b/units/ko/unit2/langgraph/introduction.mdx @@ -0,0 +1,32 @@ +# Introduction to `LangGraph` + +Unit 2.3 Thumbnail + +Welcome to this next part of our journey, where you'll learn **how to build applications** using the [`LangGraph`](https://github.com/langchain-ai/langgraph) framework designed to help you structure and orchestrate complex LLM workflows. + +`LangGraph` is a framework that allows you to build **production-ready** applications by giving you **control** tools over the flow of your agent. + +## Module Overview + +In this unit, you'll discover: + +### 1๏ธโƒฃ [What is LangGraph, and when to use it?](./when_to_use_langgraph) +### 2๏ธโƒฃ [Building Blocks of LangGraph](./building_blocks) +### 3๏ธโƒฃ [Alfred, the mail sorting butler](./first_graph) +### 4๏ธโƒฃ [Alfred, the document Analyst agent](./document_analysis_agent) +### 5๏ธโƒฃ [Quiz](./quizz1) + + +The examples in this section require access to a powerful LLM/VLM model. We ran them using the GPT-4o API because it has the best compatibility with langGraph. + + +By the end of this unit, you'll be equipped to build robust, organized and production ready applications ! + +That being said, this section is an introduction to LangGraph and more advanced topics can be discovered in the free LangChain academy course : [Introduction to LangGraph](https://academy.langchain.com/courses/intro-to-langgraph) + +Let's get started! + +## Resources + +- [LangGraph Agents](https://langchain-ai.github.io/langgraph/) - Examples of LangGraph agent +- [LangChain academy](https://academy.langchain.com/courses/intro-to-langgraph) - Full course on LangGraph from LangChain diff --git a/units/ko/unit2/langgraph/quiz1.mdx b/units/ko/unit2/langgraph/quiz1.mdx new file mode 100644 index 00000000..a29932df --- /dev/null +++ b/units/ko/unit2/langgraph/quiz1.mdx @@ -0,0 +1,118 @@ +# Test Your Understanding of LangGraph + +Let's test your understanding of `LangGraph` with a quick quiz! This will help reinforce the key concepts we've covered so far. + +This is an optional quiz and it's not graded. + +### Q1: What is the primary purpose of LangGraph? +Which statement best describes what LangGraph is designed for? + + + +--- + +### Q2: In the context of the "Control vs Freedom" trade-off, where does LangGraph stand? +Which statement best characterizes LangGraph's approach to agent design? + + + +--- + +### Q3: What role does State play in LangGraph? +Choose the most accurate description of State in LangGraph. + + + +### Q4: What is a Conditional Edge in LangGraph? +Select the most accurate description. + + + +--- + +### Q5: How does LangGraph help address the hallucination problem in LLMs? +Choose the best answer. + + + +Congratulations on completing the quiz! ๐ŸŽ‰ If you missed any questions, consider reviewing the previous sections to strengthen your understanding. Next, we'll explore more advanced features of LangGraph and see how to build more complex agent workflows. 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..28e1d850 --- /dev/null +++ b/units/ko/unit2/langgraph/when_to_use_langgraph.mdx @@ -0,0 +1,68 @@ +# 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**. + +## Is `LangGraph` different from `LangChain`? + +LangChain provides a standard interface to interact with models and other components, useful for retrieval, LLM calls and tools calls. +The classes from LangChain might be used in LangGraph, but do not HAVE to be used. + +The packages are different and can be used in isolation, but, in the end, all resources you will find online use both packages hand in hand. + +## When should I use `LangGraph`? +### Control vs freedom + +When designing AI applications, you face a fundamental trade-off between **control** and **freedom**: + +- **Freedom** gives your LLM more room to be creative and tackle unexpected problems. +- **Control** allows you to ensure predictable behavior and maintain guardrails. + +Code Agents, like the ones you can encounter in *smolagents*, are very free. They can call multiple tools in a single action step, create their own tools, etc. However, this behavior can make them less predictable and less controllable than a regular Agent working with JSON! + +`LangGraph` is on the other end of the spectrum, it shines when you need **"Control"** on the execution of your agent. + +LangGraph is particularly valuable when you need **Control over your applications**. It gives you the tools to build an application that follows a predictable process while still leveraging the power of LLMs. + +Put simply, if your application involves a series of steps that need to be orchestrated in a specific way, with decisions being made at each junction point, **LangGraph provides the structure you need**. + +As an example, let's say we want to build an LLM assistant that can answer some questions over some documents. + +Since LLMs understand text the best, before being able to answer the question, you will need to convert other complex modalities (charts, tables) into text. However, that choice depends on the type of document you have! + +This is a branching that I chose to represent as follow : + +Control flow + +> ๐Ÿ’ก **Tip:** The left part is not an agent, as here no tool call is involved. but the right part will need to write some code to query the xls ( convert to pandas and manipulate it ). + +While this branching is deterministic, you can also design branching that are conditioned on the output of an LLM making them undeterministic. + +The key scenarios where LangGraph excels include: + +- **Multi-step reasoning processes** that need explicit control on the flow +- **Applications requiring persistence of state** between steps +- **Systems that combine deterministic logic with AI capabilities** +- **Workflows that need human-in-the-loop interventions** +- **Complex agent architectures** with multiple components working together + +In essence, whenever possible, **as a human**, design a flow of actions based on the output of each action, and decide what to execute next accordingly. In this case, LangGraph is the correct framework for you! + +`LangGraph` is, in my opinion, the most production-ready agent framework on the market. + +## How does LangGraph work? + +At its core, `LangGraph` uses a directed graph structure to define the flow of your application: + +- **Nodes** represent individual processing steps (like calling an LLM, using a tool, or making a decision). +- **Edges** define the possible transitions between steps. +- **State** is user defined and maintained and passed between nodes during execution. When deciding which node to target next, this is the current state that we look at. + +We will explore those fundamental blocks more in the next chapter! + +## How is it different from regular python? Why do I need LangGraph? + +You might wonder: "I could just write regular Python code with if-else statements to handle all these flows, right?" + +While technically true, LangGraph offers **some advantages** over vanilla Python for building complex systems. You could build the same application without LangGraph, but it builds easier tools and abstractions for you. + +It includes states, visualization, logging (traces), built-in human-in-the-loop, and more. diff --git a/units/ko/unit2/llama-index/README.md b/units/ko/unit2/llama-index/README.md new file mode 100644 index 00000000..56bb0b38 --- /dev/null +++ b/units/ko/unit2/llama-index/README.md @@ -0,0 +1,15 @@ +# Table of Contents + +This LlamaIndex frame outline is part of unit 2 of the course. You can access the unit 2 about LlamaIndex on hf.co/learn ๐Ÿ‘‰ here + +| Title | Description | +| --- | --- | +| [Introduction](introduction.mdx) | Introduction to LlamaIndex | +| [LlamaHub](llama-hub.mdx) | LlamaHub: a registry of integrations, agents and tools | +| [Components](components.mdx) | Components: the building blocks of workflows | +| [Tools](tools.mdx) | Tools: how to build tools in LlamaIndex | +| [Quiz 1](quiz1.mdx) | Quiz 1 | +| [Agents](agents.mdx) | Agents: how to build agents in LlamaIndex | +| [Workflows](workflows.mdx) | Workflows: a sequence of steps, events made of components that are executed in order | +| [Quiz 2](quiz2.mdx) | Quiz 2 | +| [Conclusion](conclusion.mdx) | Conclusion | diff --git a/units/ko/unit2/llama-index/agents.mdx b/units/ko/unit2/llama-index/agents.mdx new file mode 100644 index 00000000..78f794a4 --- /dev/null +++ b/units/ko/unit2/llama-index/agents.mdx @@ -0,0 +1,160 @@ +# Using Agents in LlamaIndex + +Remember Alfred, our helpful butler agent from earlier? Well, he's about to get an upgrade! +Now that we understand the tools available in LlamaIndex, we can give Alfred new capabilities to serve us better. + +But before we continue, let's remind ourselves what makes an agent like Alfred tick. +Back in Unit 1, we learned that: + +> An Agent is a system that leverages an AI model to interact with its environment to achieve a user-defined objective. It combines reasoning, planning, and action execution (often via external tools) to fulfil tasks. + +LlamaIndex supports **three main types of reasoning agents:** + +![Agents](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/agents.png) + +1. `Function Calling Agents` - These work with AI models that can call specific functions. +2. `ReAct Agents` - These can work with any AI that does chat or text endpoint and deal with complex reasoning tasks. +3. `Advanced Custom Agents` - These use more complex methods to deal with more complex tasks and workflows. + +Find more information on advanced agents on BaseWorkflowAgent + +## Initialising Agents + + +You can follow the code in this notebook that you can run using Google Colab. + + +To create an agent, we start by providing it with a **set of functions/tools that define its capabilities**. +Let's look at how to create an agent with some basic tools. As of this writing, the agent will automatically use the function calling API (if available), or a standard ReAct agent loop. + +LLMs that support a tools/functions API are relatively new, but they provide a powerful way to call tools by avoiding specific prompting and allowing the LLM to create tool calls based on provided schemas. + +ReAct agents are also good at complex reasoning tasks and can work with any LLM that has chat or text completion capabilities. They are more verbose, and show the reasoning behind certain actions that they take. + +```python +from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI +from llama_index.core.agent.workflow import AgentWorkflow +from llama_index.core.tools import FunctionTool + +# define sample Tool -- type annotations, function names, and docstrings, are all included in parsed schemas! +def multiply(a: int, b: int) -> int: + """Multiplies two integers and returns the resulting integer""" + return a * b + +# initialize llm +llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") + +# initialize agent +agent = AgentWorkflow.from_tools_or_functions( + [FunctionTool.from_defaults(multiply)], + llm=llm +) +``` + +**Agents are stateless by default**, add remembering past interactions is opt-in using a `Context` object +This might be useful if you want to use an agent that needs to remember previous interactions, like a chatbot that maintains context across multiple messages or a task manager that needs to track progress over time. + +```python +# stateless +response = await agent.run("What is 2 times 2?") + +# remembering state +from llama_index.core.workflow import Context + +ctx = Context(agent) + +response = await agent.run("My name is Bob.", ctx=ctx) +response = await agent.run("What was my name again?", ctx=ctx) +``` + +You'll notice that agents in `LlamaIndex` are async because they use Python's `await` operator. If you are new to async code in Python, or need a refresher, they have an [excellent async guide](https://docs.llamaindex.ai/en/stable/getting_started/async_python/). + +Now we've gotten the basics, let's take a look at how we can use more complex tools in our agents. + +## Creating RAG Agents with QueryEngineTools + +**Agentic RAG is a powerful way to use agents to answer questions about your data.** We can pass various tools to Alfred to help him answer questions. +However, instead of answering the question on top of documents automatically, Alfred can decide to use any other tool or flow to answer the question. + +![Agentic RAG](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/agentic-rag.png) + +It is easy to **wrap `QueryEngine` as a tool** for an agent. +When doing so, we need to **define a name and description**. The LLM will use this information to correctly use the tool. +Let's see how to load in a `QueryEngineTool` using the `QueryEngine` we created in the [component section](components). + +```python +from llama_index.core.tools import QueryEngineTool + +query_engine = index.as_query_engine(llm=llm, similarity_top_k=3) # as shown in the Components in LlamaIndex section + +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. " +) +``` + +## Creating Multi-agent systems + +The `AgentWorkflow` class also directly supports multi-agent systems. By giving each agent a name and description, the system maintains a single active speaker, with each agent having the ability to hand off to another agent. + +By narrowing the scope of each agent, we can help increase their general accuracy when responding to user messages. + +**Agents in LlamaIndex can also directly be used as tools** for other agents, for more complex and custom scenarios. + +```python +from llama_index.core.agent.workflow import ( + AgentWorkflow, + FunctionAgent, + ReActAgent, +) + +# Define some tools +def add(a: int, b: int) -> int: + """Add two numbers.""" + return a + b + + +def subtract(a: int, b: int) -> int: + """Subtract two numbers.""" + return a - b + + +# Create agent configs +# NOTE: we can use FunctionAgent or ReActAgent here. +# FunctionAgent works for LLMs with a function calling API. +# ReActAgent works for any LLM. +calculator_agent = ReActAgent( + name="calculator", + description="Performs basic arithmetic operations", + system_prompt="You are a calculator assistant. Use your tools for any math operation.", + tools=[add, subtract], + llm=llm, +) + +query_agent = ReActAgent( + name="info_lookup", + description="Looks up information about XYZ", + system_prompt="Use your tool to query a RAG system to answer information about XYZ", + tools=[query_engine_tool], + llm=llm +) + +# Create and run the workflow +agent = AgentWorkflow( + agents=[calculator_agent, query_agent], root_agent="calculator" +) + +# Run the system +response = await agent.run(user_msg="Can you add 5 and 3?") +``` + +Haven't learned enough yet? There is a lot more to discover about agents and tools in LlamaIndex within the AgentWorkflow Basic Introduction or the Agent Learning Guide, where you can read more about streaming, context serialization, and human-in-the-loop! + +Now that we understand the basics of agents and tools in LlamaIndex, let's see how we can use LlamaIndex to **create configurable and manageable workflows!** diff --git a/units/ko/unit2/llama-index/components.mdx b/units/ko/unit2/llama-index/components.mdx new file mode 100644 index 00000000..f2c6e63a --- /dev/null +++ b/units/ko/unit2/llama-index/components.mdx @@ -0,0 +1,243 @@ +# What are components in LlamaIndex? + +Remember Alfred, our helpful butler agent from Unit 1? +To assist us effectively, Alfred needs to understand our requests and **prepare, find and use relevant information to help complete tasks.** +This is where LlamaIndex's components come in. + +While LlamaIndex has many components, **we'll focus specifically on the `QueryEngine` component.** +Why? Because it can be used as a Retrieval-Augmented Generation (RAG) tool for an agent. + +So, what is RAG? LLMs are trained on enormous bodies of data to learn general knowledge. +However, they may not be trained on relevant and up-to-date data. +RAG solves this problem by finding and retrieving relevant information from your data and giving that to the LLM. + +![RAG](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/rag.png) + +Now, think about how Alfred works: + +1. You ask Alfred to help plan a dinner party +2. Alfred needs to check your calendar, dietary preferences, and past successful menus +3. The `QueryEngine` helps Alfred find this information and use it to plan the dinner party + +This makes the `QueryEngine` **a key component for building agentic RAG workflows** in LlamaIndex. +Just as Alfred needs to search through your household information to be helpful, any agent needs a way to find and understand relevant data. +The `QueryEngine` provides exactly this capability. + +Now, let's dive a bit deeper into the components and see how you can **combine components to create a RAG pipeline.** + +## Creating a RAG pipeline using components + + +You can follow the code in this notebook that you can run using Google Colab. + + +There are five key stages within RAG, which in turn will be a part of most larger applications you build. These are: + +1. **Loading**: this refers to getting your data from where it lives -- whether it's text files, PDFs, another website, a database, or an API -- into your workflow. LlamaHub provides hundreds of integrations to choose from. +2. **Indexing**: this means creating a data structure that allows for querying the data. For LLMs, this nearly always means creating vector embeddings. Which are numerical representations of the meaning of the data. Indexing can also refer to numerous other metadata strategies to make it easy to accurately find contextually relevant data based on properties. +3. **Storing**: once your data is indexed you will want to store your index, as well as other metadata, to avoid having to re-index it. +4. **Querying**: for any given indexing strategy there are many ways you can utilize LLMs and LlamaIndex data structures to query, including sub-queries, multi-step queries and hybrid strategies. +5. **Evaluation**: a critical step in any flow is checking how effective it is relative to other strategies, or when you make changes. Evaluation provides objective measures of how accurate, faithful and fast your responses to queries are. + +Next, let's see how we can reproduce these stages using components. + +### Loading and embedding documents + +As mentioned before, LlamaIndex can work on top of your own data, however, **before accessing data, we need to load it.** +There are three main ways to load data into LlamaIndex: + +1. `SimpleDirectoryReader`: A built-in loader for various file types from a local directory. +2. `LlamaParse`: LlamaParse, LlamaIndex's official tool for PDF parsing, available as a managed API. +3. `LlamaHub`: A registry of hundreds of data-loading libraries to ingest data from any source. + +Get familiar with LlamaHub loaders and LlamaParse parser for more complex data sources. + +**The simplest way to load data is with `SimpleDirectoryReader`.** +This versatile component can load various file types from a folder and convert them into `Document` objects that LlamaIndex can work with. +Let's see how we can use `SimpleDirectoryReader` to load data from a folder. + +```python +from llama_index.core import SimpleDirectoryReader + +reader = SimpleDirectoryReader(input_dir="path/to/directory") +documents = reader.load_data() +``` + +After loading our documents, we need to break them into smaller pieces called `Node` objects. +A `Node` is just a chunk of text from the original document that's easier for the AI to work with, while it still has references to the original `Document` object. + +The `IngestionPipeline` helps us create these nodes through two key transformations. +1. `SentenceSplitter` breaks down documents into manageable chunks by splitting them at natural sentence boundaries. +2. `HuggingFaceEmbedding` converts each chunk into numerical embeddings - vector representations that capture the semantic meaning in a way AI can process efficiently. + +This process helps us organise our documents in a way that's more useful for searching and analysis. + +```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 + +# create the pipeline with transformations +pipeline = IngestionPipeline( + transformations=[ + SentenceSplitter(chunk_overlap=0), + HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5"), + ] +) + +nodes = await pipeline.arun(documents=[Document.example()]) +``` + + +### Storing and indexing documents + +After creating our `Node` objects we need to index them to make them searchable, but before we can do that, we need a place to store our data. + +Since we are using an ingestion pipeline, we can directly attach a vector store to the pipeline to populate it. +In this case, we will use `Chroma` to store our documents. + +
+Install ChromaDB + +As introduced in the section on the LlamaHub, we can install the ChromaDB vector store with the following command: + +```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, +) +``` + +An overview of the different vector stores can be found in the LlamaIndex documentation. + + +This is where vector embeddings come in - by embedding both the query and nodes in the same vector space, we can find relevant matches. +The `VectorStoreIndex` handles this for us, using the same embedding model we used during ingestion to ensure consistency. + +Let's see how to create this index from our vector store and embeddings: + +```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) +``` + +All information is automatically persisted within the `ChromaVectorStore` object and the passed directory path. + +Great! Now that we can save and load our index easily, let's explore how to query it in different ways. + +### Querying a VectorStoreIndex with prompts and LLMs + +Before we can query our index, we need to convert it to a query interface. The most common conversion options are: + +- `as_retriever`: For basic document retrieval, returning a list of `NodeWithScore` objects with similarity scores +- `as_query_engine`: For single question-answer interactions, returning a written response +- `as_chat_engine`: For conversational interactions that maintain memory across multiple messages, returning a written response using chat history and indexed context + +We'll focus on the query engine since it is more common for agent-like interactions. +We also pass in an LLM to the query engine to use for the response. + +```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("What is the meaning of life?") +# The meaning of life is 42 +``` + +### Response Processing + +Under the hood, the query engine doesn't only use the LLM to answer the question but also uses a `ResponseSynthesizer` as a strategy to process the response. +Once again, this is fully customisable but there are three main strategies that work well out of the box: + +- `refine`: create and refine an answer by sequentially going through each retrieved text chunk. This makes a separate LLM call per Node/retrieved chunk. +- `compact` (default): similar to refining but concatenating the chunks beforehand, resulting in fewer LLM calls. +- `tree_summarize`: create a detailed answer by going through each retrieved text chunk and creating a tree structure of the answer. + +Take fine-grained control of your query workflows with the low-level composition API. This API lets you customize and fine-tune every step of the query process to match your exact needs, which also pairs great with Workflows + +The language model won't always perform in predictable ways, so we can't be sure that the answer we get is always correct. We can deal with this by **evaluating the quality of the answer**. + +### Evaluation and observability + +LlamaIndex provides **built-in evaluation tools to assess response quality.** +These evaluators leverage LLMs to analyze responses across different dimensions. +Let's look at the three main evaluators available: + +- `FaithfulnessEvaluator`: Evaluates the faithfulness of the answer by checking if the answer is supported by the context. +- `AnswerRelevancyEvaluator`: Evaluate the relevance of the answer by checking if the answer is relevant to the question. +- `CorrectnessEvaluator`: Evaluate the correctness of the answer by checking if the answer is correct. + +Want to learn more about agent observability and evaluation? Continue your journey with the Bonus Unit 2. + +```python +from llama_index.core.evaluation import FaithfulnessEvaluator + +query_engine = # from the previous section +llm = # from the previous section + +# query index +evaluator = FaithfulnessEvaluator(llm=llm) +response = query_engine.query( + "What battles took place in New York City in the American Revolution?" +) +eval_result = evaluator.evaluate_response(response=response) +eval_result.passing +``` + +Even without direct evaluation, we can **gain insights into how our system is performing through observability.** +This is especially useful when we are building more complex workflows and want to understand how each component is performing. + +
+Install LlamaTrace + +As introduced in the section on the LlamaHub, we can install the LlamaTrace callback from Arize Phoenix with the following command: + +```bash +pip install -U llama-index-callbacks-arize-phoenix +``` + +Additionally, we need to set the `PHOENIX_API_KEY` environment variable to our LlamaTrace API key. We can get this by: +- Creating an account at [LlamaTrace](https://llamatrace.com/login) +- Generating an API key in your account settings +- Using the API key in the code below to enable tracing + +
+ +```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" +) +``` + +Want to learn more about components and how to use them? Continue your journey with the Components Guides or the Guide on RAG. + +We have seen how to use components to create a `QueryEngine`. Now, let's see how we can **use the `QueryEngine` as a tool for an agent!** diff --git a/units/ko/unit2/llama-index/conclusion.mdx b/units/ko/unit2/llama-index/conclusion.mdx new file mode 100644 index 00000000..fba7ef70 --- /dev/null +++ b/units/ko/unit2/llama-index/conclusion.mdx @@ -0,0 +1,13 @@ +# Conclusion + +Congratulations on finishing the `llama-index` module of this second Unit ๐Ÿฅณ + +Youโ€™ve just mastered the fundamentals of `llama-index` and youโ€™ve seen how to build your own agentic workflows! +Now that you have skills in `llama-index`, you can start to create search engines that will solve tasks you're interested in. + +In the next module of the unit, you're going to learn **how to build Agents with LangGraph**. + +Finally, we would love **to hear what you think of the course and how we can improve it**. +If you have some feedback then, please ๐Ÿ‘‰ [fill this form](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) + +### Keep Learning, and stay awesome ๐Ÿค— diff --git a/units/ko/unit2/llama-index/introduction.mdx b/units/ko/unit2/llama-index/introduction.mdx new file mode 100644 index 00000000..bca856f4 --- /dev/null +++ b/units/ko/unit2/llama-index/introduction.mdx @@ -0,0 +1,30 @@ +# Introduction to LlamaIndex + +Welcome to this module, where youโ€™ll learn how to build LLM-powered agents using the [LlamaIndex](https://www.llamaindex.ai/) toolkit. + +LlamaIndex is **a complete toolkit for creating LLM-powered agents over your data using indexes and workflows**. For this course we'll focus on three main parts that help build agents in LlamaIndex: **Components**, **Agents and Tools** and **Workflows**. + +![LlamaIndex](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/thumbnail.png) + +Let's look at these key parts of LlamaIndex and how they help with agents: + +- **Components**: Are the basic building blocks you use in LlamaIndex. These include things like prompts, models, and databases. Components often help connect LlamaIndex with other tools and libraries. +- **Tools**: Tools are components that provide specific capabilities like searching, calculating, or accessing external services. They are the building blocks that enable agents to perform tasks. +- **Agents**: Agents are autonomous components that can use tools and make decisions. They coordinate tool usage to accomplish complex goals. +- **Workflows**: Are step-by-step processes that process logic together. Workflows or agentic workflows are a way to structure agentic behaviour without the explicit use of agents. + + +## What Makes LlamaIndex Special? + +While LlamaIndex does some things similar to other frameworks like smolagents, it has some key benefits: + +- **Clear Workflow System**: Workflows help break down how agents should make decisions step by step using an event-driven and async-first syntax. This helps you clearly compose and organize your logic. +- **Advanced Document Parsing with LlamaParse**: LlamaParse was made specifically for LlamaIndex, so the integration is seamless, although it is a paid feature. +- **Many Ready-to-Use Components**: LlamaIndex has been around for a while, so it works with lots of other frameworks. This means it has many tested and reliable components, like LLMs, retrievers, indexes, and more. +- **LlamaHub**: is a registry of hundreds of these components, agents, and tools that you can use within LlamaIndex. + +All of these concepts are required in different scenarios to create useful agents. +In the following sections, we will go over each of these concepts in detail. +After mastering the concepts, we will use our learnings to **create applied use cases with Alfred the agent**! + +Getting our hands on LlamaIndex is exciting, right? So, what are we waiting for? Let's get started with **finding and installing the integrations we need using 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..ef3da822 --- /dev/null +++ b/units/ko/unit2/llama-index/llama-hub.mdx @@ -0,0 +1,55 @@ +# Introduction to the LlamaHub + +**LlamaHub is a registry of hundreds of integrations, agents and tools that you can use within LlamaIndex.** + +![LlamaHub](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/llama-hub.png) + +We will be using various integrations in this course, so let's first look at the LlamaHub and how it can help us. + +Let's see how to find and install the dependencies for the components we need. + +## Installation + +LlamaIndex installation instructions are available as a well-structured **overview on [LlamaHub](https://llamahub.ai/)**. +This might be a bit overwhelming at first, but most of the **installation commands generally follow an easy-to-remember format**: + +```bash +pip install llama-index-{component-type}-{framework-name} +``` + +Let's try to install the dependencies for an LLM and embedding component using the [Hugging Face inference API integration](https://llamahub.ai/l/llms/llama-index-llms-huggingface-api?from=llms). + +```bash +pip install llama-index-llms-huggingface-api llama-index-embeddings-huggingface +``` + +## Usage + +Once installed, we can see the usage patterns. You'll notice that the import paths follow the install command! +Underneath, we can see an example of the usage of **the Hugging Face inference API for an LLM component**. + +```python +from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI +import os +from dotenv import load_dotenv + +# Load the .env file +load_dotenv() + +# Retrieve HF_TOKEN from the environment variables +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("Hello, how are you?") +print(response) +# I am good, how can I help you today? +``` + +Wonderful, we now know how to find, install and use the integrations for the components we need. +**Let's dive deeper into the components** and see how we can use them to build our own agents. diff --git a/units/ko/unit2/llama-index/quiz1.mdx b/units/ko/unit2/llama-index/quiz1.mdx new file mode 100644 index 00000000..d387e4e1 --- /dev/null +++ b/units/ko/unit2/llama-index/quiz1.mdx @@ -0,0 +1,117 @@ +# Small Quiz (ungraded) [[quiz1]] + +So far we've discussed the key components and tools used in LlamaIndex. +It's time to make a short quiz, since **testing yourself** is the best way to learn and [to avoid the illusion of competence](https://www.coursera.org/lecture/learning-how-to-learn/illusions-of-competence-BuFzf). +This will help you find **where you need to reinforce your knowledge**. + +This is an optional quiz and it's not graded. + +### Q1: What is a QueryEngine? +Which of the following best describes a QueryEngine component? + + + +--- + +### Q2: What is the Purpose of FunctionTools? +Why are FunctionTools important for an Agent? + + + +--- + +### Q3: What are Toolspecs in LlamaIndex? +What is the main purpose of Toolspecs? + + + +--- + +### Q4: What is Required to create a tool? +What information must be included when creating a tool? + + + +--- + +Congrats on finishing this Quiz ๐Ÿฅณ, if you missed some elements, take time to read again the chapter to reinforce your knowledge. If you pass it, you're ready to dive deeper into building with these components! diff --git a/units/ko/unit2/llama-index/quiz2.mdx b/units/ko/unit2/llama-index/quiz2.mdx new file mode 100644 index 00000000..a0d65d42 --- /dev/null +++ b/units/ko/unit2/llama-index/quiz2.mdx @@ -0,0 +1,112 @@ +# Quick Self-Check (ungraded) [[quiz2]] + +What?! Another Quiz? We know, we know, ... ๐Ÿ˜… But this short, ungraded quiz is here to **help you reinforce key concepts you've just learned**. + +This quiz covers agent workflows and interactions - essential components for building effective AI agents. + +### Q1: What is the purpose of AgentWorkflow in LlamaIndex? + + + +--- + +### Q2: What object is used for keeping track of the state of the workflow? + + + +--- + +### Q3: Which method should be used if you want an agent to remember previous interactions? + + + +--- + +### Q4: What is a key feature of Agentic RAG? + + + +--- + + +Got it? Great! Now let's **do a brief recap of the unit!** diff --git a/units/ko/unit2/llama-index/tools.mdx b/units/ko/unit2/llama-index/tools.mdx new file mode 100644 index 00000000..286e4cb3 --- /dev/null +++ b/units/ko/unit2/llama-index/tools.mdx @@ -0,0 +1,141 @@ +# Using Tools in LlamaIndex + +**Defining a clear set of Tools is crucial to performance.** As we discussed in [unit 1](../../unit1/tools), clear tool interfaces are easier for LLMs to use. +Much like a software API interface for human engineers, they can get more out of the tool if it's easy to understand how it works. + +There are **four main types of tools in LlamaIndex**: + +![Tools](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/tools.png) + +1. `FunctionTool`: Convert any Python function into a tool that an agent can use. It automatically figures out how the function works. +2. `QueryEngineTool`: A tool that lets agents use query engines. Since agents are built on query engines, they can also use other agents as tools. +3. `Toolspecs`: Sets of tools created by the community, which often include tools for specific services like Gmail. +4. `Utility Tools`: Special tools that help handle large amounts of data from other tools. + +We will go over each of them in more detail below. + +## Creating a FunctionTool + + +You can follow the code in this notebook that you can run using Google Colab. + + +A FunctionTool provides a simple way to wrap any Python function and make it available to an agent. +You can pass either a synchronous or asynchronous function to the tool, along with optional `name` and `description` parameters. +The name and description are particularly important as they help the agent understand when and how to use the tool effectively. +Let's look at how to create a FunctionTool below and then call it. + +```python +from llama_index.core.tools import FunctionTool + +def get_weather(location: str) -> str: + """Useful for getting the weather for a given location.""" + print(f"Getting weather for {location}") + return f"The weather in {location} is sunny" + +tool = FunctionTool.from_defaults( + get_weather, + name="my_weather_tool", + description="Useful for getting the weather for a given location.", +) +tool.call("New York") +``` + +When using an agent or LLM with function calling, the tool selected (and the arguments written for that tool) rely strongly on the tool name and description of the purpose and arguments of the tool. Learn more about function calling in the Function Calling Guide. + +## Creating a QueryEngineTool + +The `QueryEngine` we defined in the previous unit can be easily transformed into a tool using the `QueryEngineTool` class. +Let's see how to create a `QueryEngineTool` from a `QueryEngine` in the example below. + +```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") +``` + +## Creating Toolspecs + +Think of `ToolSpecs` as collections of tools that work together harmoniously - like a well-organized professional toolkit. +Just as a mechanic's toolkit contains complementary tools that work together for vehicle repairs, a `ToolSpec` combines related tools for specific purposes. +For example, an accounting agent's `ToolSpec` might elegantly integrate spreadsheet capabilities, email functionality, and calculation tools to handle financial tasks with precision and efficiency. + +
+Install the Google Toolspec +As introduced in the section on the LlamaHub, we can install the Google toolspec with the following command: + +```python +pip install llama-index-tools-google +``` +
+ +And now we can load the toolspec and convert it to a list of tools. + +```python +from llama_index.tools.google import GmailToolSpec + +tool_spec = GmailToolSpec() +tool_spec_list = tool_spec.to_tool_list() +``` + +To get a more detailed view of the tools, we can take a look at the `metadata` of each tool. + +```python +[(tool.metadata.name, tool.metadata.description) for tool in tool_spec_list] +``` + +### Model Context Protocol (MCP) in LlamaIndex + +LlamaIndex also allows using MCP tools through a [ToolSpec on the LlamaHub](https://llamahub.ai/l/tools/llama-index-tools-mcp?from=). +You can simply run an MCP server and start using it through the following implementation. + +If you want to dive deeper about MCP, you can check our [free MCP Course](https://huggingface.co/learn/mcp-course/). + +
+Install the MCP Toolspec +As introduced in the section on the LlamaHub, we can install the MCP toolspec with the following command: + +```python +pip install llama-index-tools-mcp +``` +
+ +```python +from llama_index.tools.mcp import BasicMCPClient, McpToolSpec + +# We consider there is a mcp server running on 127.0.0.1:8000, or you can use the mcp client to connect to your own mcp server. +mcp_client = BasicMCPClient("http://127.0.0.1:8000/sse") +mcp_tool = McpToolSpec(client=mcp_client) + +# get the agent +agent = await get_agent(mcp_tool) + +# create the agent context +agent_context = Context(agent) +``` + +## Utility Tools + +Oftentimes, directly querying an API **can return an excessive amount of data**, some of which may be irrelevant, overflow the context window of the LLM, or unnecessarily increase the number of tokens that you are using. +Let's walk through our two main utility tools below. + +1. `OnDemandToolLoader`: This tool turns any existing LlamaIndex data loader (BaseReader class) into a tool that an agent can use. The tool can be called with all the parameters needed to trigger `load_data` from the data loader, along with a natural language query string. During execution, we first load data from the data loader, index it (for instance with a vector store), and then query it 'on-demand'. All three of these steps happen in a single tool call. +2. `LoadAndSearchToolSpec`: The LoadAndSearchToolSpec takes in any existing Tool as input. As a tool spec, it implements `to_tool_list`, and when that function is called, two tools are returned: a loading tool and then a search tool. The load Tool execution would call the underlying Tool, and then index the output (by default with a vector index). The search Tool execution would take in a query string as input and call the underlying index. + +You can find toolspecs and utility tools on the LlamaHub + +Now that we understand the basics of agents and tools in LlamaIndex, let's see how we can **use LlamaIndex to create configurable and manageable workflows!** diff --git a/units/ko/unit2/llama-index/workflows.mdx b/units/ko/unit2/llama-index/workflows.mdx new file mode 100644 index 00000000..d82f8350 --- /dev/null +++ b/units/ko/unit2/llama-index/workflows.mdx @@ -0,0 +1,280 @@ +# Creating agentic workflows in LlamaIndex + +A workflow in LlamaIndex provides a structured way to organize your code into sequential and manageable steps. + +Such a workflow is created by defining `Steps` which are triggered by `Events`, and themselves emit `Events` to trigger further steps. +Let's take a look at Alfred showing a LlamaIndex workflow for a RAG task. + +![Workflow Schematic](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/workflows.png) + +**Workflows offer several key benefits:** + +- Clear organization of code into discrete steps +- Event-driven architecture for flexible control flow +- Type-safe communication between steps +- Built-in state management +- Support for both simple and complex agent interactions + +As you might have guessed, **workflows strike a great balance between the autonomy of agents while maintaining control over the overall workflow.** + +So, let's learn how to create a workflow ourselves! + +## Creating Workflows + + +You can follow the code in this notebook that you can run using Google Colab. + + +### Basic Workflow Creation + +
+Install the Workflow package +As introduced in the section on the LlamaHub, we can install the Workflow package with the following command: + +```python +pip install llama-index-utils-workflow +``` +
+ +We can create a single-step workflow by defining a class that inherits from `Workflow` and decorating your functions with `@step`. +We will also need to add `StartEvent` and `StopEvent`, which are special events that are used to indicate the start and end of the workflow. + +```python +from llama_index.core.workflow import StartEvent, StopEvent, Workflow, step + +class MyWorkflow(Workflow): + @step + async def my_step(self, ev: StartEvent) -> StopEvent: + # do something here + return StopEvent(result="Hello, world!") + + +w = MyWorkflow(timeout=10, verbose=False) +result = await w.run() +``` + +As you can see, we can now run the workflow by calling `w.run()`. + +### Connecting Multiple Steps + +To connect multiple steps, we **create custom events that carry data between steps.** +To do so, we need to add an `Event` that is passed between the steps and transfers the output of the first step to the second step. + +```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: + # Process initial data + return ProcessingEvent(intermediate_result="Step 1 complete") + + @step + async def step_two(self, ev: ProcessingEvent) -> StopEvent: + # Use the intermediate result + final_result = f"Finished processing: {ev.intermediate_result}" + return StopEvent(result=final_result) + +w = MultiStepWorkflow(timeout=10, verbose=False) +result = await w.run() +result +``` + +The type hinting is important here, as it ensures that the workflow is executed correctly. Let's complicate things a bit more! + +### Loops and Branches + +The type hinting is the most powerful part of workflows because it allows us to create branches, loops, and joins to facilitate more complex workflows. + +Let's show an example of **creating a loop** by using the union operator `|`. +In the example below, we see that the `LoopEvent` is taken as input for the step and can also be returned as output. + +```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("Bad thing happened") + return LoopEvent(loop_output="Back to step one.") + else: + print("Good thing happened") + return ProcessingEvent(intermediate_result="First step complete.") + + @step + async def step_two(self, ev: ProcessingEvent) -> StopEvent: + # Use the intermediate result + final_result = f"Finished processing: {ev.intermediate_result}" + return StopEvent(result=final_result) + + +w = MultiStepWorkflow(verbose=False) +result = await w.run() +result +``` + +### Drawing Workflows + +We can also draw workflows. Let's use the `draw_all_possible_flows` function to draw the workflow. This stores the workflow in an HTML file. + +```python +from llama_index.utils.workflow import draw_all_possible_flows + +w = ... # as defined in the previous section +draw_all_possible_flows(w, "flow.html") +``` + +![workflow drawing](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/workflow-draw.png) + +There is one last cool trick that we will cover in the course, which is the ability to add state to the workflow. + +### State Management + +State management is useful when you want to keep track of the state of the workflow, so that every step has access to the same state. +We can do this by using the `Context` type hint on top of a parameter in the step function. + +```python +from llama_index.core.workflow import Context, StartEvent, StopEvent + + +@step +async def query(self, ctx: Context, ev: StartEvent) -> StopEvent: + # store query in the context + await ctx.store.set("query", "What is the capital of France?") + + # do something with context and event + val = ... + + # retrieve query from the context + query = await ctx.store.get("query") + + return StopEvent(result=val) +``` + +Great! Now you know how to create basic workflows in LlamaIndex! + +There are some more complex nuances to workflows, which you can learn about in the LlamaIndex documentation. + +However, there is another way to create workflows, which relies on the `AgentWorkflow` class. Let's take a look at how we can use this to create a multi-agent workflow. + +## Automating workflows with Multi-Agent Workflows + +Instead of manual workflow creation, we can use the **`AgentWorkflow` class to create a multi-agent workflow**. +The `AgentWorkflow` uses Workflow Agents to allow you to create a system of one or more agents that can collaborate and hand off tasks to each other based on their specialized capabilities. +This enables building complex agent systems where different agents handle different aspects of a task. +Instead of importing classes from `llama_index.core.agent`, we will import the agent classes from `llama_index.core.agent.workflow`. +One agent must be designated as the root agent in the `AgentWorkflow` constructor. +When a user message comes in, it is first routed to the root agent. + +Each agent can then: + +- Handle the request directly using their tools +- Handoff to another agent better suited for the task +- Return a response to the user + +Let's see how to create a multi-agent workflow. + +```python +from llama_index.core.agent.workflow import AgentWorkflow, ReActAgent +from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI + +# Define some tools +def add(a: int, b: int) -> int: + """Add two numbers.""" + return a + b + +def multiply(a: int, b: int) -> int: + """Multiply two numbers.""" + return a * b + +llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") + +# we can pass functions directly without FunctionTool -- the fn/docstring are parsed for the name/description +multiply_agent = ReActAgent( + name="multiply_agent", + description="Is able to multiply two integers", + system_prompt="A helpful assistant that can use a tool to multiply numbers.", + tools=[multiply], + llm=llm, +) + +addition_agent = ReActAgent( + name="add_agent", + description="Is able to add two integers", + system_prompt="A helpful assistant that can use a tool to add numbers.", + tools=[add], + llm=llm, +) + +# Create the workflow +workflow = AgentWorkflow( + agents=[multiply_agent, addition_agent], + root_agent="multiply_agent", +) + +# Run the system +response = await workflow.run(user_msg="Can you add 5 and 3?") +``` + +Agent tools can also modify the workflow state we mentioned earlier. Before starting the workflow, we can provide an initial state dict that will be available to all agents. +The state is stored in the state key of the workflow context. It will be injected into the state_prompt which augments each new user message. + +Let's inject a counter to count function calls by modifying the previous example: + +```python +from llama_index.core.workflow import Context + +# Define some tools +async def add(ctx: Context, a: int, b: int) -> int: + """Add two numbers.""" + # update our count + 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: + """Multiply two numbers.""" + # update our count + 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="Current state: {state}. User message: {msg}", +) + +# run the workflow with context +ctx = Context(workflow) +response = await workflow.run(user_msg="Can you add 5 and 3?", ctx=ctx) + +# pull out and inspect the state +state = await ctx.store.get("state") +print(state["num_fn_calls"]) +``` + +Congratulations! You have now mastered the basics of Agents in LlamaIndex! ๐ŸŽ‰ + +Let's continue with one final quiz to solidify your knowledge! ๐Ÿš€ diff --git a/units/ko/unit2/smolagents/code_agents.mdx b/units/ko/unit2/smolagents/code_agents.mdx new file mode 100644 index 00000000..0e78c5e2 --- /dev/null +++ b/units/ko/unit2/smolagents/code_agents.mdx @@ -0,0 +1,393 @@ + + +# Building Agents That Use Code + +Code agents are the default agent type in `smolagents`. They generate Python tool calls to perform actions, achieving action representations that are efficient, expressive, and accurate. + +Their streamlined approach reduces the number of required actions, simplifies complex operations, and enables reuse of existing code functions. `smolagents` provides a lightweight framework for building code agents, implemented in approximately 1,000 lines of code. + +![Code vs JSON Actions](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/code_vs_json_actions.png) +Graphic from the paper [Executable Code Actions Elicit Better LLM Agents](https://huggingface.co/papers/2402.01030) + + +If you want to learn more about why code agents are effective, check out this guide from the smolagents documentation. + + +## Why Code Agents? + +In a multi-step agent process, the LLM writes and executes actions, typically involving external tool calls. Traditional approaches use a JSON format to specify tool names and arguments as strings, **which the system must parse to determine which tool to execute**. + +However, research shows that **tool-calling LLMs work more effectively with code directly**. This is a core principle of `smolagents`, as shown in the diagram above from [Executable Code Actions Elicit Better LLM Agents](https://huggingface.co/papers/2402.01030). + +Writing actions in code rather than JSON offers several key advantages: + +* **Composability**: Easily combine and reuse actions +* **Object Management**: Work directly with complex structures like images +* **Generality**: Express any computationally possible task +* **Natural for LLMs**: High-quality code is already present in LLM training data + +## How Does a Code Agent Work? + +![From https://huggingface.co/docs/smolagents/conceptual_guides/react](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/codeagent_docs.png) + +The diagram above illustrates how `CodeAgent.run()` operates, following the ReAct framework we mentioned in Unit 1. The main abstraction for agents in `smolagents` is a `MultiStepAgent`, which serves as the core building block. `CodeAgent` is a special kind of `MultiStepAgent`, as we will see in an example below. + +A `CodeAgent` performs actions through a cycle of steps, with existing variables and knowledge being incorporated into the agent's context, which is kept in an execution log: + +1. The system prompt is stored in a `SystemPromptStep`, and the user query is logged in a `TaskStep`. + +2. Then, the following while loop is executed: + + 2.1 Method `agent.write_memory_to_messages()` writes the agent's logs into a list of LLM-readable [chat messages](https://huggingface.co/docs/transformers/main/en/chat_templating). + + 2.2 These messages are sent to a `Model`, which generates a completion. + + 2.3 The completion is parsed to extract the action, which, in our case, should be a code snippet since we're working with a `CodeAgent`. + + 2.4 The action is executed. + + 2.5 The results are logged into memory in an `ActionStep`. + +At the end of each step, if the agent includes any function calls (in `agent.step_callback`), they are executed. + +## Let's See Some Examples + + +You can follow the code in this notebook that you can run using Google Colab. + + +Alfred is planning a party at the Wayne family mansion and needs your help to ensure everything goes smoothly. To assist him, we'll apply what we've learned about how a multi-step `CodeAgent` operates. + +Alfred Party + +If you haven't installed `smolagents` yet, you can do so by running the following command: + +```bash +pip install smolagents -U +``` + +Let's also login to the Hugging Face Hub to have access to the Serverless Inference API. + +```python +from huggingface_hub import login + +login() +``` + +### Selecting a Playlist for the Party Using `smolagents` + +Music is an essential part of a successful party! Alfred needs some help selecting the playlist. Luckily, `smolagents` has got us covered! We can build an agent capable of searching the web using DuckDuckGo. To give the agent access to this tool, we include it in the tool list when creating the agent. + +Alfred Playlist + +For the model, we'll rely on `InferenceClientModel`, which provides access to Hugging Face's [Serverless Inference API](https://huggingface.co/docs/api-inference/index). The default model is `"Qwen/Qwen2.5-Coder-32B-Instruct"`, which is performant and available for fast inference, but you can select any compatible model from the Hub. + +Running an agent is quite straightforward: + +```python +from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel + +agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=InferenceClientModel()) + +agent.run("Search for the best music recommendations for a party at the Wayne's mansion.") +``` + +When you run this example, the output will **display a trace of the workflow steps being executed**. It will also print the corresponding Python code with the message: + +```python + โ”€ Executing parsed code: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + results = web_search(query="best music for a Batman party") + print(results) + โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +``` + +After a few steps, you'll see the generated playlist that Alfred can use for the party! ๐ŸŽต + +### Using a Custom Tool to Prepare the Menu + +Alfred Menu + +Now that we have selected a playlist, we need to organize the menu for the guests. Again, Alfred can take advantage of `smolagents` to do so. Here, we use the `@tool` decorator to define a custom function that acts as a tool. We'll cover tool creation in more detail later, so for now, we can simply run the code. + +As you can see in the example below, we will create a tool using the `@tool` decorator and include it in the `tools` list. + +```python +from smolagents import CodeAgent, tool, InferenceClientModel + +# Tool to suggest a menu based on the occasion +@tool +def suggest_menu(occasion: str) -> str: + """ + Suggests a menu based on the occasion. + Args: + occasion (str): The type of occasion for the party. Allowed values are: + - "casual": Menu for casual party. + - "formal": Menu for formal party. + - "superhero": Menu for superhero party. + - "custom": Custom menu. + """ + if occasion == "casual": + return "Pizza, snacks, and drinks." + elif occasion == "formal": + return "3-course dinner with wine and dessert." + elif occasion == "superhero": + return "Buffet with high-energy and healthy food." + else: + return "Custom menu for the butler." + +# Alfred, the butler, preparing the menu for the party +agent = CodeAgent(tools=[suggest_menu], model=InferenceClientModel()) + +# Preparing the menu for the party +agent.run("Prepare a formal menu for the party.") +``` + +The agent will run for a few steps until finding the answer. Precising allowed values in the docstring helps direct agent to `occasion` argument values which exist and limit hallucinations. + +The menu is ready! ๐Ÿฅ— + +### Using Python Imports Inside the Agent + +We have the playlist and menu ready, but we need to check one more crucial detail: preparation time! + +Alfred needs to calculate when everything would be ready if he started preparing now, in case they need assistance from other superheroes. + +`smolagents` specializes in agents that write and execute Python code snippets, offering sandboxed execution for security. + +**Code execution has strict security measures** - imports outside a predefined safe list are blocked by default. However, you can authorize additional imports by passing them as strings in `additional_authorized_imports`. +For more details on secure code execution, see the official [guide](https://huggingface.co/docs/smolagents/tutorials/secure_code_execution). + +When creating the agent, we'll use `additional_authorized_imports` to allow for importing the `datetime` module. + +```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 needs to prepare for the party. Here are the tasks: + 1. Prepare the drinks - 30 minutes + 2. Decorate the mansion - 60 minutes + 3. Set up the menu - 45 minutes + 4. Prepare the music and playlist - 45 minutes + + If we start right now, at what time will the party be ready? + """ +) +``` + + +These examples are just the beginning of what you can do with code agents, and we're already starting to see their utility for preparing the party. +You can learn more about how to build code agents in the [smolagents documentation](https://huggingface.co/docs/smolagents). + +In summary, `smolagents` specializes in agents that write and execute Python code snippets, offering sandboxed execution for security. It supports both local and API-based language models, making it adaptable to various development environments. + +### Sharing Our Custom Party Preparator Agent to the Hub + +Wouldn't it be **amazing to share our very own Alfred agent with the community**? By doing so, anyone can easily download and use the agent directly from the Hub, bringing the ultimate party planner of Gotham to their fingertips! Let's make it happen! ๐ŸŽ‰ + +The `smolagents` library makes this possible by allowing you to share a complete agent with the community and download others for immediate use. It's as simple as the following: + +```python +# Change to your username and repo name +agent.push_to_hub('sergiopaniego/AlfredAgent') +``` + +To download the agent again, use the code below: + +```python +# Change to your username and repo name +alfred_agent = agent.from_hub('sergiopaniego/AlfredAgent', trust_remote_code=True) + +alfred_agent.run("Give me the best playlist for a party at Wayne's mansion. The party idea is a 'villain masquerade' theme") +``` + +What's also exciting is that shared agents are directly available as Hugging Face Spaces, allowing you to interact with them in real-time. You can explore other agents [here](https://huggingface.co/spaces/davidberenstein1957/smolagents-and-tools). + +For example, the _AlfredAgent_ is available [here](https://huggingface.co/spaces/sergiopaniego/AlfredAgent). You can try it out directly below: + + + +You may be wonderingโ€”how did Alfred build such an agent using `smolagents`? By integrating several tools, he can generate an agent as follows. Don't worry about the tools for now, as we'll have a dedicated section later in this unit to explore that in detail: + +```python +from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, InferenceClientModel, Tool, tool, VisitWebpageTool + +@tool +def suggest_menu(occasion: str) -> str: + """ + Suggests a menu based on the occasion. + Args: + occasion: The type of occasion for the party. + """ + if occasion == "casual": + return "Pizza, snacks, and drinks." + elif occasion == "formal": + return "3-course dinner with wine and dessert." + elif occasion == "superhero": + return "Buffet with high-energy and healthy food." + else: + return "Custom menu for the butler." + +@tool +def catering_service_tool(query: str) -> str: + """ + This tool returns the highest-rated catering service in Gotham City. + + Args: + query: A search term for finding catering services. + """ + # Example list of catering services and their ratings + services = { + "Gotham Catering Co.": 4.9, + "Wayne Manor Catering": 4.8, + "Gotham City Events": 4.7, + } + + # Find the highest rated catering service (simulating search query filtering) + best_service = max(services, key=services.get) + + return best_service + +class SuperheroPartyThemeTool(Tool): + name = "superhero_party_theme_generator" + description = """ + This tool suggests creative superhero-themed party ideas based on a category. + It returns a unique party theme idea.""" + + inputs = { + "category": { + "type": "string", + "description": "The type of superhero party (e.g., 'classic heroes', 'villain masquerade', 'futuristic Gotham').", + } + } + + output_type = "string" + + def forward(self, category: str): + themes = { + "classic heroes": "Justice League Gala: Guests come dressed as their favorite DC heroes with themed cocktails like 'The Kryptonite Punch'.", + "villain masquerade": "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains.", + "futuristic Gotham": "Neo-Gotham Night: A cyberpunk-style party inspired by Batman Beyond, with neon decorations and futuristic gadgets." + } + + return themes.get(category.lower(), "Themed party idea not found. Try 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.") + + +# Alfred, the butler, preparing the menu for the party +agent = CodeAgent( + tools=[ + DuckDuckGoSearchTool(), + VisitWebpageTool(), + suggest_menu, + catering_service_tool, + SuperheroPartyThemeTool(), + FinalAnswerTool() + ], + model=InferenceClientModel(), + max_steps=10, + verbosity_level=2 +) + +agent.run("Give me the best playlist for a party at the Wayne's mansion. The party idea is a 'villain masquerade' theme") +``` + +As you can see, we've created a `CodeAgent` with several tools that enhance the agent's functionality, turning it into the ultimate party planner ready to share with the community! ๐ŸŽ‰ + +Now, it's your turn: build your very own agent and share it with the community using the knowledge we've just learned! ๐Ÿ•ต๏ธโ€โ™‚๏ธ๐Ÿ’ก + + +If you would like to share your agent project, then make a space and tag the agents-course on the Hugging Face Hub. We'd love to see what you've created! + + +### Inspecting Our Party Preparator Agent with OpenTelemetry and Langfuse ๐Ÿ“ก + +As Alfred fine-tunes the Party Preparator Agent, he's growing weary of debugging its runs. Agents, by nature, are unpredictable and difficult to inspect. But since he aims to build the ultimate Party Preparator Agent and deploy it in production, he needs robust traceability for future monitoring and analysis. + +Once again, `smolagents` comes to the rescue! It embraces the [OpenTelemetry](https://opentelemetry.io/) standard for instrumenting agent runs, allowing seamless inspection and logging. With the help of [Langfuse](https://langfuse.com/) and the `SmolagentsInstrumentor`, Alfred can easily track and analyze his agentโ€™s behavior. + +Setting it up is straightforward! + +First, we need to install the necessary dependencies: + +```bash +pip install opentelemetry-sdk opentelemetry-exporter-otlp openinference-instrumentation-smolagents +``` + +Next, Alfred has already created an account on Langfuse and has his API keys ready. If you havenโ€™t done so yet, you can sign up for Langfuse Cloud [here](https://cloud.langfuse.com/) or explore [alternatives](https://huggingface.co/docs/smolagents/tutorials/inspect_runs). + +Once you have your API keys, they need to be properly configured as follows: + +```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 data region +# os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://us.cloud.langfuse.com/api/public/otel" # US data region +os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {LANGFUSE_AUTH}" +``` + +Finally, Alfred is ready to initialize the `SmolagentsInstrumentor` and start tracking his agent's performance. + +```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 is now connected ๐Ÿ”Œ! The runs from `smolagents` are being logged in Langfuse, giving him full visibility into the agent's behavior. With this setup, he's ready to revisit previous runs and refine his Party Preparator Agent even further. + +To learn more about tracing your agents and using the collected data to evaluate their performance, check out Bonus Unit 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("Give me the best playlist for a party at Wayne's mansion. The party idea is a 'villain masquerade' theme") +``` + +Alfred can now access these logs [here](https://cloud.langfuse.com/project/cm7bq0abj025rad078ak3luwi/traces/995fc019255528e4f48cf6770b0ce27b?timestamp=2025-02-19T10%3A28%3A36.929Z) to review and analyze them. + + +Actually, a minor error occurred during execution. Can you spot it in the logs? Try to track how the agent handles it and still returns a valid answer. Here is the direct link to the error if you want to verify your answer. Of course the error has been fixed in the meantime, more details can be found in this issue. + + +Meanwhile, the [suggested playlist](https://open.spotify.com/playlist/0gZMMHjuxMrrybQ7wTMTpw) sets the perfect vibe for the party preparations. Cool, right? ๐ŸŽถ + +--- + +Now that we have created our first Code Agent, let's **learn how we can create Tool Calling Agents**, the second type of agent available in `smolagents`. + +## Resources + +- [smolagents Blog](https://huggingface.co/blog/smolagents) - Introduction to smolagents and code interactions +- [smolagents: Building Good Agents](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - Best practices for reliable agents +- [Building Effective Agents - Anthropic](https://www.anthropic.com/research/building-effective-agents) - Agent design principles +- [Sharing runs with OpenTelemetry](https://huggingface.co/docs/smolagents/tutorials/inspect_runs) - Details about how to setup OpenTelemetry for tracking your agents. diff --git a/units/ko/unit2/smolagents/conclusion.mdx b/units/ko/unit2/smolagents/conclusion.mdx new file mode 100644 index 00000000..540ffc74 --- /dev/null +++ b/units/ko/unit2/smolagents/conclusion.mdx @@ -0,0 +1,11 @@ +# Conclusion + +Congratulations on finishing the `smolagents` module of this second Unit ๐Ÿฅณ + +Youโ€™ve just mastered the fundamentals of `smolagents` and youโ€™ve built your own Agent! Now that you have skills in `smolagents`, you can now start to create Agents that will solve tasks you're interested about. + +In the next module, you're going to learn **how to build Agents with LlamaIndex**. + +Finally, we would love **to hear what you think of the course and how we can improve it**. If you have some feedback then, please ๐Ÿ‘‰ [fill this form](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) + +### Keep Learning, stay awesome ๐Ÿค— diff --git a/units/ko/unit2/smolagents/final_quiz.mdx b/units/ko/unit2/smolagents/final_quiz.mdx new file mode 100644 index 00000000..8f77e1b1 --- /dev/null +++ b/units/ko/unit2/smolagents/final_quiz.mdx @@ -0,0 +1,25 @@ +# Exam Time! + +Well done on working through the material on `smolagents`! You've already achieved a lot. Now, it's time to put your knowledge to the test with a quiz. ๐Ÿง  + +## Instructions + +- The quiz consists of code questions. +- You will be given instructions to complete the code snippets. +- Read the instructions carefully and complete the code snippets accordingly. +- For each question, you will be given the result and some feedback. + +๐Ÿง˜ **This quiz is ungraded and uncertified**. It's about you understanding the `smolagents` library and knowing whether you should spend more time on the written material. In the coming units you'll put this knowledge to the test in use cases and projects. + +Let's get started! + +## Quiz ๐Ÿš€ + + + +You can also access the quiz ๐Ÿ‘‰ [here](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..0677b204 --- /dev/null +++ b/units/ko/unit2/smolagents/introduction.mdx @@ -0,0 +1,69 @@ +# Introduction to `smolagents` + +Unit 2.1 Thumbnail + +Welcome to this module, where you'll learn **how to build effective agents** using the [`smolagents`](https://github.com/huggingface/smolagents) library, which provides a lightweight framework for creating capable AI agents. + +`smolagents` is a Hugging Face library; therefore, we would appreciate your support by **starring** the smolagents [`repository`](https://github.com/huggingface/smolagents) : +staring smolagents + +## Module Overview + +This module provides a comprehensive overview of key concepts and practical strategies for building intelligent agents using `smolagents`. + +With so many open-source frameworks available, it's essential to understand the components and capabilities that make `smolagents` a useful option or to determine when another solution might be a better fit. + +We'll explore critical agent types, including code agents designed for software development tasks, tool calling agents for creating modular, function-driven workflows, and retrieval agents that access and synthesize information. + +Additionally, we'll cover the orchestration of multiple agents as well as the integration of vision capabilities and web browsing, which unlock new possibilities for dynamic and context-aware applications. + +In this unit, Alfred, the agent from Unit 1, makes his return. This time, heโ€™s using the `smolagents` framework for his internal workings. Together, weโ€™ll explore the key concepts behind this framework as Alfred tackles various tasks. Alfred is organizing a party at the Wayne Manor while the Wayne family ๐Ÿฆ‡ is away, and he has plenty to do. Join us as we showcase his journey and how he handles these tasks with `smolagents`! + + + +In this unit, you will learn to build AI agents with the `smolagents` library. Your agents will be able to search for data, execute code, and interact with web pages. You will also learn how to combine multiple agents to create more powerful systems. + + + +![Alfred the agent](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit1/this-is-alfred.jpg) + +## Contents + +During this unit on `smolagents`, we cover: + +### 1๏ธโƒฃ [Why Use smolagents](./why_use_smolagents) + +`smolagents` is one of the many open-source agent frameworks available for application development. Alternative options include `LlamaIndex` and `LangGraph`, which are also covered in other modules in this course. `smolagents` offers several key features that might make it a great fit for specific use cases, but we should always consider all options when selecting a framework. We'll explore the advantages and drawbacks of using `smolagents`, helping you make an informed decision based on your project's requirements. + +### 2๏ธโƒฃ [CodeAgents](./code_agents) + +`CodeAgents` are the primary type of agent in `smolagents`. Instead of generating JSON or text, these agents produce Python code to perform actions. This module explores their purpose, functionality, and how they work, along with hands-on examples to showcase their capabilities. + +### 3๏ธโƒฃ [ToolCallingAgents](./tool_calling_agents) + +`ToolCallingAgents` are the second type of agent supported by `smolagents`. Unlike `CodeAgents`, which generate Python code, these agents rely on JSON/text blobs that the system must parse and interpret to execute actions. This module covers their functionality, their key differences from `CodeAgents`, and it provides an example to illustrate their usage. + +### 4๏ธโƒฃ [Tools](./tools) + +As we saw in Unit 1, tools are functions that an LLM can use within an agentic system, and they act as the essential building blocks for agent behavior. This module covers how to create tools, their structure, and different implementation methods using the `Tool` class or the `@tool` decorator. You'll also learn about the default toolbox, how to share tools with the community, and how to load community-contributed tools for use in your agents. + +### 5๏ธโƒฃ [Retrieval Agents](./retrieval_agents) + +Retrieval agents allow models access to knowledge bases, making it possible to search, synthesize, and retrieve information from multiple sources. They leverage vector stores for efficient retrieval and implement **Retrieval-Augmented Generation (RAG)** patterns. These agents are particularly useful for integrating web search with custom knowledge bases while maintaining conversation context through memory systems. This module explores implementation strategies, including fallback mechanisms for robust information retrieval. + +### 6๏ธโƒฃ [Multi-Agent Systems](./multi_agent_systems) + +Orchestrating multiple agents effectively is crucial for building powerful, multi-agent systems. By combining agents with different capabilitiesโ€”such as a web search agent with a code execution agentโ€”you can create more sophisticated solutions. This module focuses on designing, implementing, and managing multi-agent systems to maximize efficiency and reliability. + +### 7๏ธโƒฃ [Vision and Browser agents](./vision_agents) + +Vision agents extend traditional agent capabilities by incorporating **Vision-Language Models (VLMs)**, enabling them to process and interpret visual information. This module explores how to design and integrate VLM-powered agents, unlocking advanced functionalities like image-based reasoning, visual data analysis, and multimodal interactions. We will also use vision agents to build a browser agent that can browse the web and extract information from it. + +## Resources + +- [smolagents Documentation](https://huggingface.co/docs/smolagents) - Official docs for the smolagents library +- [Building Effective Agents](https://www.anthropic.com/research/building-effective-agents) - Research paper on agent architectures +- [Agent Guidelines](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - Best practices for building reliable agents +- [LangGraph Agents](https://langchain-ai.github.io/langgraph/) - Additional examples of agent implementations +- [Function Calling Guide](https://platform.openai.com/docs/guides/function-calling) - Understanding function calling in LLMs +- [RAG Best Practices](https://www.pinecone.io/learn/retrieval-augmented-generation/) - Guide to implementing effective 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..ba1d767f --- /dev/null +++ b/units/ko/unit2/smolagents/multi_agent_systems.mdx @@ -0,0 +1,413 @@ + + +# Multi-Agent Systems + +Multi-agent systems enable **specialized agents to collaborate on complex tasks**, improving modularity, scalability, and robustness. Instead of relying on a single agent, tasks are distributed among agents with distinct capabilities. + +In **smolagents**, different agents can be combined to generate Python code, call external tools, perform web searches, and more. By orchestrating these agents, we can create powerful workflows. + +A typical setup might include: +- A **Manager Agent** for task delegation +- A **Code Interpreter Agent** for code execution +- A **Web Search Agent** for information retrieval + +The diagram below illustrates a simple multi-agent architecture where a **Manager Agent** coordinates a **Code Interpreter Tool** and a **Web Search Agent**, which in turn utilizes tools like the `DuckDuckGoSearchTool` and `VisitWebpageTool` to gather relevant information. + + + +## Multi-Agent Systems in Action + +A multi-agent system consists of multiple specialized agents working together under the coordination of an **Orchestrator Agent**. This approach enables complex workflows by distributing tasks among agents with distinct roles. + +For example, a **Multi-Agent RAG system** can integrate: +- A **Web Agent** for browsing the internet. +- A **Retriever Agent** for fetching information from knowledge bases. +- An **Image Generation Agent** for producing visuals. + +All of these agents operate under an orchestrator that manages task delegation and interaction. + +## Solving a complex task with a multi-agent hierarchy + + +You can follow the code in this notebook that you can run using Google Colab. + + +The reception is approaching! With your help, Alfred is now nearly finished with the preparations. + +But now there's a problem: the Batmobile has disappeared. Alfred needs to find a replacement, and find it quickly. + +Fortunately, a few biopics have been done on Bruce Wayne's life, so maybe Alfred could get a car left behind on one of the movie sets, and re-engineer it up to modern standards, which certainly would include a full self-driving option. + +But this could be anywhere in the filming locations around the world - which could be numerous. + +So Alfred wants your help. Could you build an agent able to solve this task? + +> ๐Ÿ‘‰ Find all Batman filming locations in the world, calculate the time to transfer via boat to there, and represent them on a map, with a color varying by boat transfer time. Also represent some supercar factories with the same boat transfer time. + +Let's build this! + +This example needs some additional packages, so let's install them first: + +```bash +pip install 'smolagents[litellm]' plotly geopandas shapely kaleido -q +``` + +### We first make a tool to get the cargo plane transfer time. + +```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, # Average speed for cargo planes +) -> float: + """ + Calculate the travel time for a cargo plane between two points on Earth using great-circle distance. + + Args: + origin_coords: Tuple of (latitude, longitude) for the starting point + destination_coords: Tuple of (latitude, longitude) for the destination + cruising_speed_kmh: Optional cruising speed in km/h (defaults to 750 km/h for typical cargo planes) + + Returns: + float: The estimated travel time in hours + + Example: + >>> # Chicago (41.8781ยฐ N, 87.6298ยฐ W) to Sydney (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) + + # Extract coordinates + lat1, lon1 = map(to_radians, origin_coords) + lat2, lon2 = map(to_radians, destination_coords) + + # Earth's radius in kilometers + EARTH_RADIUS_KM = 6371.0 + + # Calculate great-circle distance using the haversine formula + 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 + + # Add 10% to account for non-direct routes and air traffic controls + actual_distance = distance * 1.1 + + # Calculate flight time + # Add 1 hour for takeoff and landing procedures + flight_time = (actual_distance / cruising_speed_kmh) + 1.0 + + # Format the results + return round(flight_time, 2) + + +print(calculate_cargo_travel_time((41.8781, -87.6298), (-33.8688, 151.2093))) +``` + +### Setting up the agent + +For the model provider, we use Together AI, one of the new [inference providers on the Hub](https://huggingface.co/blog/inference-providers)! + +The GoogleSearchTool uses the [Serper API](https://serper.dev) to search the web, so this requires either having setup env variable `SERPAPI_API_KEY` and passing `provider="serpapi"` or having `SERPER_API_KEY` and passing `provider=serper`. + +If you don't have any Serp API provider setup, you can use `DuckDuckGoSearchTool` but beware that it has a rate limit. + +```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") +``` + +We can start by creating a simple agent as a baseline to give us a simple report. + +```python +task = """Find all Batman filming locations in the world, calculate the time to transfer via cargo plane to here (we're in Gotham, 40.7128ยฐ N, 74.0060ยฐ W), and return them to me as a pandas dataframe. +Also give me some supercar factories with the same cargo plane transfer time.""" +``` + +```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 +``` + +In our case, it generates this output: + +```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 | +``` + +We could already improve this a bit by throwing in some dedicated planning steps, and adding more prompting. + +Planning steps allow the agent to think ahead and plan its next steps, which can be useful for more complex tasks. + +```python +agent.planning_interval = 4 + +detailed_report = agent.run(f""" +You're an expert analyst. You make comprehensive reports after visiting many websites. +Don't hesitate to search for many queries at once in a for loop. +For each data point that you find, visit the source url to confirm numbers. + +{task} +""") + +print(detailed_report) +``` + +```python +detailed_report +``` + +In our case, it generates this output: + +```python +| | Location | Travel Time (hours) | +|--|--------------------------------------------------|---------------------| +| 0 | Bridge of Sighs, Glasgow Necropolis, Glasgow, UK | 8.6 | +| 1 | Wishart Street, Glasgow, Scotland, UK | 8.6 | +``` + + +Thanks to these quick changes, we obtained a much more concise report by simply providing our agent a detailed prompt, and giving it planning capabilities! + +The model's context window is quickly filling up. So **if we ask our agent to combine the results of detailed search with another, it will be slower and quickly ramp up tokens and costs**. + +โžก๏ธ We need to improve the structure of our system. + +### โœŒ๏ธ Splitting the task between two agents + +Multi-agent structures allow to separate memories between different sub-tasks, with two great benefits: +- Each agent is more focused on its core task, thus more performant +- Separating memories reduces the count of input tokens at each step, thus reducing latency and cost. + +Let's create a team with a dedicated web search agent, managed by another agent. + +The manager agent should have plotting capabilities to write its final report: so let us give it access to additional imports, including `plotly`, and `geopandas` + `shapely` for spatial plotting. + +```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="Browses the web to find information", + verbosity_level=0, + max_steps=10, +) +``` + +The manager agent will need to do some mental heavy lifting. + +So we give it the stronger model [DeepSeek-R1](https://huggingface.co/deepseek-ai/DeepSeek-R1), and add a `planning_interval` to the mix. + +```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), "Make sure to save the plot under saved_map.png!" + image = Image.open(filepath) + prompt = ( + f"Here is a user-given task and the agent steps: {agent_memory.get_succinct_steps()}. Now here is the plot that was made." + "Please check that the reasoning process and plot are correct: do they correctly answer the given task?" + "First list reasons why yes/no, then write your final decision: PASS in caps lock if it is satisfactory, FAIL if it is not." + "Don't be harsh: if the plot mostly solves the task, it should pass." + "To pass, a plot should be made using px.scatter_map and not any other method (scatter_map looks nicer)." + ) + 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("Feedback: ", 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, +) +``` + +Let us inspect what this team looks like: + +```python +manager_agent.visualize() +``` + +This will generate something like this, helping us understand the structure and relationship between agents and tools used: + +```python +CodeAgent | deepseek-ai/DeepSeek-R1 +โ”œโ”€โ”€ โœ… Authorized imports: ['geopandas', 'plotly', 'shapely', 'json', 'pandas', 'numpy'] +โ”œโ”€โ”€ ๐Ÿ› ๏ธ Tools: +โ”‚ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ +โ”‚ โ”ƒ Name โ”ƒ Description โ”ƒ Arguments โ”ƒ +โ”‚ โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ +โ”‚ โ”‚ calculate_cargo_travel_time โ”‚ Calculate the travel time for a cargo โ”‚ origin_coords (`array`): Tuple of โ”‚ +โ”‚ โ”‚ โ”‚ plane between two points on Earth โ”‚ (latitude, longitude) for the โ”‚ +โ”‚ โ”‚ โ”‚ using great-circle distance. โ”‚ starting point โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ destination_coords (`array`): Tuple โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ of (latitude, longitude) for the โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ destination โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ cruising_speed_kmh (`number`): โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ Optional cruising speed in km/h โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ (defaults to 750 km/h for typical โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ cargo planes) โ”‚ +โ”‚ โ”‚ final_answer โ”‚ Provides a final answer to the given โ”‚ answer (`any`): The final answer to โ”‚ +โ”‚ โ”‚ โ”‚ problem. โ”‚ the problem โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +โ””โ”€โ”€ ๐Ÿค– Managed agents: + โ””โ”€โ”€ web_agent | CodeAgent | Qwen/Qwen2.5-Coder-32B-Instruct + โ”œโ”€โ”€ โœ… Authorized imports: [] + โ”œโ”€โ”€ ๐Ÿ“ Description: Browses the web to find information + โ””โ”€โ”€ ๐Ÿ› ๏ธ Tools: + โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ + โ”ƒ Name โ”ƒ Description โ”ƒ Arguments โ”ƒ + โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ + โ”‚ web_search โ”‚ Performs a google web search for โ”‚ query (`string`): The search โ”‚ + โ”‚ โ”‚ your query then returns a string โ”‚ query to perform. โ”‚ + โ”‚ โ”‚ of the top search results. โ”‚ filter_year (`integer`): โ”‚ + โ”‚ โ”‚ โ”‚ Optionally restrict results to a โ”‚ + โ”‚ โ”‚ โ”‚ certain year โ”‚ + โ”‚ visit_webpage โ”‚ Visits a webpage at the given url โ”‚ url (`string`): The url of the โ”‚ + โ”‚ โ”‚ and reads its content as a โ”‚ webpage to visit. โ”‚ + โ”‚ โ”‚ markdown string. Use this to โ”‚ โ”‚ + โ”‚ โ”‚ browse webpages. โ”‚ โ”‚ + โ”‚ calculate_cargo_travel_time โ”‚ Calculate the travel time for a โ”‚ origin_coords (`array`): Tuple of โ”‚ + โ”‚ โ”‚ cargo plane between two points on โ”‚ (latitude, longitude) for the โ”‚ + โ”‚ โ”‚ Earth using great-circle โ”‚ starting point โ”‚ + โ”‚ โ”‚ distance. โ”‚ destination_coords (`array`): โ”‚ + โ”‚ โ”‚ โ”‚ Tuple of (latitude, longitude) โ”‚ + โ”‚ โ”‚ โ”‚ for the destination โ”‚ + โ”‚ โ”‚ โ”‚ cruising_speed_kmh (`number`): โ”‚ + โ”‚ โ”‚ โ”‚ Optional cruising speed in km/h โ”‚ + โ”‚ โ”‚ โ”‚ (defaults to 750 km/h for typical โ”‚ + โ”‚ โ”‚ โ”‚ cargo planes) โ”‚ + โ”‚ final_answer โ”‚ Provides a final answer to the โ”‚ answer (`any`): The final answer โ”‚ + โ”‚ โ”‚ given problem. โ”‚ to the problem โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +```python +manager_agent.run(""" +Find all Batman filming locations in the world, calculate the time to transfer via cargo plane to here (we're in Gotham, 40.7128ยฐ N, 74.0060ยฐ W). +Also give me some supercar factories with the same cargo plane transfer time. You need at least 6 points in total. +Represent this as spatial map of the world, with the locations represented as scatter points with a color that depends on the travel time, and save it to saved_map.png! + +Here's an example of how to plot and return a map: +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) + +Never try to process strings using code: when you have a string to read, just print it and you'll see it. +""") +``` + +I don't know how that went in your run, but in mine, the manager agent skilfully divided tasks given to the web agent in `1. Search for Batman filming locations`, then `2. Find supercar factories`, before aggregating the lists and plotting the map. + +Let's see what the map looks like by inspecting it directly from the agent state: + +```python +manager_agent.python_executor.state["fig"] +``` + +This will output the map: + +![Multiagent system example output map](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/smolagents/output_map.png) + +## Resources + +- [Multi-Agent Systems](https://huggingface.co/docs/smolagents/main/en/examples/multiagents) โ€“ Overview of multi-agent systems. +- [What is Agentic RAG?](https://weaviate.io/blog/what-is-agentic-rag) โ€“ Introduction to Agentic RAG. +- [Multi-Agent RAG System ๐Ÿค–๐Ÿค๐Ÿค– Recipe](https://huggingface.co/learn/cookbook/multiagent_rag_system) โ€“ Step-by-step guide to building a multi-agent RAG system. diff --git a/units/ko/unit2/smolagents/quiz1.mdx b/units/ko/unit2/smolagents/quiz1.mdx new file mode 100644 index 00000000..11688a39 --- /dev/null +++ b/units/ko/unit2/smolagents/quiz1.mdx @@ -0,0 +1,142 @@ +# Small Quiz (ungraded) [[quiz1]] + +Let's test your understanding of `smolagents` with a quick quiz! Remember, testing yourself helps reinforce learning and identify areas that may need review. + +This is an optional quiz and it's not graded. + +### Q1: What is one of the primary advantages of choosing `smolagents` over other frameworks? +Which statement best captures a core strength of the `smolagents` approach? + + + +--- + +### Q2: In which scenario would you likely benefit most from using smolagents? +Which situation aligns well with what smolagents does best? + + + +--- + +### Q3: smolagents offers flexibility in model integration. Which statement best reflects its approach? +Choose the most accurate description of how smolagents interoperates with LLMs. + + + +--- + +### Q4: How does smolagents handle the debate between code-based actions and JSON-based actions? +Which statement correctly characterizes smolagents' philosophy about action formats? + + + +--- + +### Q5: How does smolagents integrate with the Hugging Face Hub for added benefits? +Which statement accurately describes one of the core advantages of Hub integration? + + + +--- + +Congratulations on completing this quiz! ๐ŸŽ‰ If you missed any questions, consider reviewing the *Why use smolagents* section for a deeper understanding. If you did well, you're ready to explore more advanced topics in smolagents! diff --git a/units/ko/unit2/smolagents/quiz2.mdx b/units/ko/unit2/smolagents/quiz2.mdx new file mode 100644 index 00000000..682fbbf2 --- /dev/null +++ b/units/ko/unit2/smolagents/quiz2.mdx @@ -0,0 +1,147 @@ +# Small Quiz (ungraded) [[quiz2]] + +It's time to test your understanding of the *Code Agents*, *Tool Calling Agents*, and *Tools* sections. This quiz is optional and not graded. + +--- + +### Q1: What is the key difference between creating a tool with the `@tool` decorator versus creating a subclass of `Tool` in smolagents? + +Which statement best describes the distinction between these two approaches for defining tools? + +@tool decorator is mandatory for retrieval-based tools, while subclasses of Tool are only for text-generation tasks", + explain: "Both approaches can be used for any type of tool, including retrieval-based or text-generation tools.", + }, + { + text: "The @tool decorator is recommended for simple function-based tools, while subclasses of Tool offer more flexibility for complex functionality or custom metadata", + explain: "This is correct. The decorator approach is simpler, but subclassing allows more customized behavior.", + correct: true + }, + { + text: "@tool can only be used in multi-agent systems, while creating a Tool subclass is for single-agent scenarios", + explain: "All agents (single or multi) can use either approach to define tools; there is no such restriction.", + }, + { + text: "Decorating a function with @tool replaces the need for a docstring, whereas subclasses must not include docstrings", + explain: "Both methods benefit from clear docstrings. The decorator doesn't replace them, and a subclass can still have docstrings.", + } +]} +/> + +--- + +### Q2: How does a CodeAgent handle multi-step tasks using the ReAct (Reason + Act) approach? + +Which statement correctly describes how the CodeAgent executes a series of steps to solve a task? + + + +--- + +### Q3: Which of the following is a primary advantage of sharing a tool on the Hugging Face Hub? + +Select the best reason why a developer might upload and share their custom tool. + + + +--- + +### Q4: ToolCallingAgent differs from CodeAgent in how it executes actions. Which statement is correct? + +Choose the option that accurately describes how ToolCallingAgent works. + + + +--- + +### Q5: What is included in the smolagents default toolbox, and why might you use it? + +Which statement best captures the purpose and contents of the default toolbox in smolagents? + + + +--- + +Congratulations on completing this quiz! ๐ŸŽ‰ If any questions gave you trouble, revisit the *Code Agents*, *Tool Calling Agents*, or *Tools* sections to strengthen your understanding. If you aced it, you're well on your way to building robust smolagents applications! diff --git a/units/ko/unit2/smolagents/retrieval_agents.mdx b/units/ko/unit2/smolagents/retrieval_agents.mdx new file mode 100644 index 00000000..5483cc48 --- /dev/null +++ b/units/ko/unit2/smolagents/retrieval_agents.mdx @@ -0,0 +1,168 @@ + + +# Building Agentic RAG Systems + + +You can follow the code in this notebook that you can run using Google Colab. + + +Retrieval Augmented Generation (RAG) systems combine the capabilities of data retrieval and generation models to provide context-aware responses. For example, a user's query is passed to a search engine, and the retrieved results are given to the model along with the query. The model then generates a response based on the query and retrieved information. + +Agentic RAG (Retrieval-Augmented Generation) extends traditional RAG systems by **combining autonomous agents with dynamic knowledge retrieval**. + +While traditional RAG systems use an LLM to answer queries based on retrieved data, agentic RAG **enables intelligent control of both retrieval and generation processes**, improving efficiency and accuracy. + +Traditional RAG systems face key limitations, such as **relying on a single retrieval step** and focusing on direct semantic similarity with the userโ€™s query, which may overlook relevant information. + +Agentic RAG addresses these issues by allowing the agent to autonomously formulate search queries, critique retrieved results, and conduct multiple retrieval steps for a more tailored and comprehensive output. + +## Basic Retrieval with DuckDuckGo + +Let's build a simple agent that can search the web using DuckDuckGo. This agent will retrieve information and synthesize responses to answer queries. With Agentic RAG, Alfred's agent can: + +* Search for latest superhero party trends +* Refine results to include luxury elements +* Synthesize information into a complete plan + +Here's how Alfred's agent can achieve this: + +```python +from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel + +# Initialize the search tool +search_tool = DuckDuckGoSearchTool() + +# Initialize the model +model = InferenceClientModel() + +agent = CodeAgent( + model=model, + tools=[search_tool], +) + +# Example usage +response = agent.run( + "Search for luxury superhero-themed party ideas, including decorations, entertainment, and catering." +) +print(response) +``` + +The agent follows this process: + +1. **Analyzes the Request:** Alfredโ€™s agent identifies the key elements of the queryโ€”luxury superhero-themed party planning, with focus on decor, entertainment, and catering. +2. **Performs Retrieval:** The agent leverages DuckDuckGo to search for the most relevant and up-to-date information, ensuring it aligns with Alfredโ€™s refined preferences for a luxurious event. +3. **Synthesizes Information:** After gathering the results, the agent processes them into a cohesive, actionable plan for Alfred, covering all aspects of the party. +4. **Stores for Future Reference:** The agent stores the retrieved information for easy access when planning future events, optimizing efficiency in subsequent tasks. + +## Custom Knowledge Base Tool + +For specialized tasks, a custom knowledge base can be invaluable. Let's create a tool that queries a vector database of technical documentation or specialized knowledge. Using semantic search, the agent can find the most relevant information for Alfred's needs. + +A vector database stores numerical representations (embeddings) of text or other data, created by machine learning models. It enables semantic search by identifying similar meanings in high-dimensional space. + +This approach combines predefined knowledge with semantic search to provide context-aware solutions for event planning. With specialized knowledge access, Alfred can perfect every detail of the party. + +In this example, we'll create a tool that retrieves party planning ideas from a custom knowledge base. We'll use a BM25 retriever to search the knowledge base and return the top results, and `RecursiveCharacterTextSplitter` to split the documents into smaller chunks for more efficient search. + +```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 = "Uses semantic search to retrieve relevant party planning ideas for Alfredโ€™s superhero-themed party at Wayne Manor." + inputs = { + "query": { + "type": "string", + "description": "The query to perform. This should be a query related to party planning or superhero themes.", + } + } + output_type = "string" + + def __init__(self, docs, **kwargs): + super().__init__(**kwargs) + self.retriever = BM25Retriever.from_documents( + docs, k=5 # Retrieve the top 5 documents + ) + + def forward(self, query: str) -> str: + assert isinstance(query, str), "Your search query must be a string" + + docs = self.retriever.invoke( + query, + ) + return "\nRetrieved ideas:\n" + "".join( + [ + f"\n\n===== Idea {str(i)} =====\n" + doc.page_content + for i, doc in enumerate(docs) + ] + ) + +# Simulate a knowledge base about party planning +party_ideas = [ + {"text": "A superhero-themed masquerade ball with luxury decor, including gold accents and velvet curtains.", "source": "Party Ideas 1"}, + {"text": "Hire a professional DJ who can play themed music for superheroes like Batman and Wonder Woman.", "source": "Entertainment Ideas"}, + {"text": "For catering, serve dishes named after superheroes, like 'The Hulk's Green Smoothie' and 'Iron Man's Power Steak.'", "source": "Catering Ideas"}, + {"text": "Decorate with iconic superhero logos and projections of Gotham and other superhero cities around the venue.", "source": "Decoration Ideas"}, + {"text": "Interactive experiences with VR where guests can engage in superhero simulations or compete in themed games.", "source": "Entertainment Ideas"} +] + +source_docs = [ + Document(page_content=doc["text"], metadata={"source": doc["source"]}) + for doc in party_ideas +] + +# Split the documents into smaller chunks for more efficient search +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) + +# Create the retriever tool +party_planning_retriever = PartyPlanningRetrieverTool(docs_processed) + +# Initialize the agent +agent = CodeAgent(tools=[party_planning_retriever], model=InferenceClientModel()) + +# Example usage +response = agent.run( + "Find ideas for a luxury superhero-themed party, including entertainment, catering, and decoration options." +) + +print(response) +``` + +This enhanced agent can: +1. First check the documentation for relevant information +2. Combine insights from the knowledge base +3. Maintain conversation context in memory + +## Enhanced Retrieval Capabilities + +When building agentic RAG systems, the agent can employ sophisticated strategies like: + +1. **Query Reformulation:** Instead of using the raw user query, the agent can craft optimized search terms that better match the target documents +2. **Query Decomposition:** Instead of using the user query directly, if it contains multiple pieces of information to query, it can be decomposed to multiple queries +3. **Query Expansion:** Somehow similar to Query Reformulation but done multiple times to put the query in multiple wordings to query them all +4. **Reranking:** Using Cross-Encoders to assign more comprehensive and semantic relevance scores between retrieved documents and search query +5. **Multi-Step Retrieval:** The agent can perform multiple searches, using initial results to inform subsequent queries +6. **Source Integration:** Information can be combined from multiple sources like web search and local documentation +7. **Result Validation:** Retrieved content can be analyzed for relevance and accuracy before being included in responses + +Effective agentic RAG systems require careful consideration of several key aspects. The agent **should select between available tools based on the query type and context**. Memory systems help maintain conversation history and avoid repetitive retrievals. Having fallback strategies ensures the system can still provide value even when primary retrieval methods fail. Additionally, implementing validation steps helps ensure the accuracy and relevance of retrieved information. + +## Resources + +- [Agentic RAG: turbocharge your RAG with query reformulation and self-query! ๐Ÿš€](https://huggingface.co/learn/cookbook/agent_rag) - Recipe for developing an Agentic RAG system using smolagents. 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..e93049fd --- /dev/null +++ b/units/ko/unit2/smolagents/tool_calling_agents.mdx @@ -0,0 +1,74 @@ + + +# Writing actions as code snippets or JSON blobs + + +You can follow the code in this notebook that you can run using Google Colab. + + +Tool Calling Agents are the second type of agent available in `smolagents`. Unlike Code Agents that use Python snippets, these agents **use the built-in tool-calling capabilities of LLM providers** to generate tool calls as **JSON structures**. This is the standard approach used by OpenAI, Anthropic, and many other providers. + +Let's look at an example. When Alfred wants to search for catering services and party ideas, a `CodeAgent` would generate and run Python code like this: + +```python +for query in [ + "Best catering services in Gotham City", + "Party theme ideas for superheroes" +]: + print(web_search(f"Search for: {query}")) +``` + +A `ToolCallingAgent` would instead create a JSON structure: + +```python +[ + {"name": "web_search", "arguments": "Best catering services in Gotham City"}, + {"name": "web_search", "arguments": "Party theme ideas for superheroes"} +] +``` + +This JSON blob is then used to execute the tool calls. + +While `smolagents` primarily focuses on `CodeAgents` since [they perform better overall](https://huggingface.co/papers/2402.01030), `ToolCallingAgents` can be effective for simple systems that don't require variable handling or complex tool calls. + +![Code vs JSON Actions](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/code_vs_json_actions.png) + +## How Do Tool Calling Agents Work? + +Tool Calling Agents follow the same multi-step workflow as Code Agents (see the [previous section](./code_agents) for details). + +The key difference is in **how they structure their actions**: instead of executable code, they **generate JSON objects that specify tool names and arguments**. The system then **parses these instructions** to execute the appropriate tools. + +## Example: Running a Tool Calling Agent + +Let's revisit the previous example where Alfred started party preparations, but this time we'll use a `ToolCallingAgent` to highlight the difference. We'll build an agent that can search the web using DuckDuckGo, just like in our Code Agent example. The only difference is the agent type - the framework handles everything else: + +```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.") +``` + +When you examine the agent's trace, instead of seeing `Executing parsed code:`, you'll see something like: + +```text +โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ +โ”‚ Calling tool: 'web_search' with arguments: {'query': "best music recommendations for a party at Wayne's โ”‚ +โ”‚ mansion"} โ”‚ +โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ +``` + +The agent generates a structured tool call that the system processes to produce the output, rather than directly executing code like a `CodeAgent`. + +Now that we understand both agent types, we can choose the right one for our needs. Let's continue exploring `smolagents` to make Alfred's party a success! ๐ŸŽ‰ + +## Resources + +- [ToolCallingAgent documentation](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/agents#smolagents.ToolCallingAgent) - Official documentation for ToolCallingAgent diff --git a/units/ko/unit2/smolagents/tools.mdx b/units/ko/unit2/smolagents/tools.mdx new file mode 100644 index 00000000..66f7cb21 --- /dev/null +++ b/units/ko/unit2/smolagents/tools.mdx @@ -0,0 +1,308 @@ + + +# Tools + +As we explored in [unit 1](https://huggingface.co/learn/agents-course/unit1/tools), agents use tools to perform various actions. In `smolagents`, tools are treated as **functions that an LLM can call within an agent system**. + +To interact with a tool, the LLM needs an **interface description** with these key components: + +- **Name**: What the tool is called +- **Tool description**: What the tool does +- **Input types and descriptions**: What arguments the tool accepts +- **Output type**: What the tool returns + +For instance, while preparing for a party at Wayne Manor, Alfred needs various tools to gather information - from searching for catering services to finding party theme ideas. Here's how a simple search tool interface might look: + +- **Name:** `web_search` +- **Tool description:** Searches the web for specific queries +- **Input:** `query` (string) - The search term to look up +- **Output:** String containing the search results + +By using these tools, Alfred can make informed decisions and gather all the information needed for planning the perfect party. + +Below, you can see an animation illustrating how a tool call is managed: + +![Agentic pipeline from https://huggingface.co/docs/smolagents/conceptual_guides/react](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/Agent_ManimCE.gif) + +## Tool Creation Methods + +In `smolagents`, tools can be defined in two ways: +1. **Using the `@tool` decorator** for simple function-based tools +2. **Creating a subclass of `Tool`** for more complex functionality + +### The `@tool` Decorator + +The `@tool` decorator is the **recommended way to define simple tools**. Under the hood, smolagents will parse basic information about the function from Python. So if you name your function clearly and write a good docstring, it will be easier for the LLM to use. + +Using this approach, we define a function with: + +- **A clear and descriptive function name** that helps the LLM understand its purpose. +- **Type hints for both inputs and outputs** to ensure proper usage. +- **A detailed description**, including an `Args:` section where each argument is explicitly described. These descriptions provide valuable context for the LLM, so it's important to write them carefully. + +#### Generating a tool that retrieves the highest-rated catering + +Alfred Catering + + +You can follow the code in this notebook that you can run using Google Colab. + + +Let's imagine that Alfred has already decided on the menu for the party, but now he needs help preparing food for such a large number of guests. To do so, he would like to hire a catering service and needs to identify the highest-rated options available. Alfred can leverage a tool to search for the best catering services in his area. + +Below is an example of how Alfred can use the `@tool` decorator to make this happen: + +```python +from smolagents import CodeAgent, InferenceClientModel, tool + +# Let's pretend we have a function that fetches the highest-rated catering services. +@tool +def catering_service_tool(query: str) -> str: + """ + This tool returns the highest-rated catering service in Gotham City. + + Args: + query: A search term for finding catering services. + """ + # Example list of catering services and their ratings + services = { + "Gotham Catering Co.": 4.9, + "Wayne Manor Catering": 4.8, + "Gotham City Events": 4.7, + } + + # Find the highest rated catering service (simulating search query filtering) + best_service = max(services, key=services.get) + + return best_service + + +agent = CodeAgent(tools=[catering_service_tool], model=InferenceClientModel()) + +# Run the agent to find the best catering service +result = agent.run( + "Can you give me the name of the highest-rated catering service in Gotham City?" +) + +print(result) # Output: Gotham Catering Co. +``` + +### Defining a Tool as a Python Class + +This approach involves creating a subclass of [`Tool`](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools#smolagents.Tool). For complex tools, we can implement a class instead of a Python function. The class wraps the function with metadata that helps the LLM understand how to use it effectively. In this class, we define: + +- `name`: The tool's name. +- `description`: A description used to populate the agent's system prompt. +- `inputs`: A dictionary with keys `type` and `description`, providing information to help the Python interpreter process inputs. +- `output_type`: Specifies the expected output type. +- `forward`: The method containing the inference logic to execute. + +Below, we can see an example of a tool built using `Tool` and how to integrate it within a `CodeAgent`. + +#### Generating a tool to generate ideas about the superhero-themed party + +Alfred's party at the mansion is a **superhero-themed event**, but he needs some creative ideas to make it truly special. As a fantastic host, he wants to surprise the guests with a unique theme. + +To do this, he can use an agent that generates superhero-themed party ideas based on a given category. This way, Alfred can find the perfect party theme to wow his guests. + +```python +from smolagents import Tool, CodeAgent, InferenceClientModel + +class SuperheroPartyThemeTool(Tool): + name = "superhero_party_theme_generator" + description = """ + This tool suggests creative superhero-themed party ideas based on a category. + It returns a unique party theme idea.""" + + inputs = { + "category": { + "type": "string", + "description": "The type of superhero party (e.g., 'classic heroes', 'villain masquerade', 'futuristic Gotham').", + } + } + + output_type = "string" + + def forward(self, category: str): + themes = { + "classic heroes": "Justice League Gala: Guests come dressed as their favorite DC heroes with themed cocktails like 'The Kryptonite Punch'.", + "villain masquerade": "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains.", + "futuristic Gotham": "Neo-Gotham Night: A cyberpunk-style party inspired by Batman Beyond, with neon decorations and futuristic gadgets." + } + + return themes.get(category.lower(), "Themed party idea not found. Try 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.") + +# Instantiate the tool +party_theme_tool = SuperheroPartyThemeTool() +agent = CodeAgent(tools=[party_theme_tool], model=InferenceClientModel()) + +# Run the agent to generate a party theme idea +result = agent.run( + "What would be a good superhero party idea for a 'villain masquerade' theme?" +) + +print(result) # Output: "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains." +``` + +With this tool, Alfred will be the ultimate super host, impressing his guests with a superhero-themed party they won't forget! ๐Ÿฆธโ€โ™‚๏ธ๐Ÿฆธโ€โ™€๏ธ + +## Default Toolbox + +`smolagents` comes with a set of pre-built tools that can be directly injected into your agent. The [default toolbox](https://huggingface.co/docs/smolagents/guided_tour?build-a-tool=Decorate+a+function+with+%40tool#default-toolbox) includes: + +- **PythonInterpreterTool** +- **FinalAnswerTool** +- **UserInputTool** +- **DuckDuckGoSearchTool** +- **GoogleSearchTool** +- **VisitWebpageTool** + +Alfred could use various tools to ensure a flawless party at Wayne Manor: + +- First, he could use the `DuckDuckGoSearchTool` to find creative superhero-themed party ideas. + +- For catering, he'd rely on the `GoogleSearchTool` to find the highest-rated services in Gotham. + +- To manage seating arrangements, Alfred could run calculations with the `PythonInterpreterTool`. + +- Once everything is gathered, he'd compile the plan using the `FinalAnswerTool`. + +With these tools, Alfred guarantees the party is both exceptional and seamless. ๐Ÿฆ‡๐Ÿ’ก + +## Sharing and Importing Tools + +One of the most powerful features of **smolagents** is its ability to share custom tools on the Hub and seamlessly integrate tools created by the community. This includes connecting with **HF Spaces** and **LangChain tools**, significantly enhancing Alfred's ability to orchestrate an unforgettable party at Wayne Manor. ๐ŸŽญ + +With these integrations, Alfred can tap into advanced event-planning toolsโ€”whether it's adjusting the lighting for the perfect ambiance, curating the ideal playlist for the party, or coordinating with Gotham's finest caterers. + +Here are examples showcasing how these functionalities can elevate the party experience: + +### Sharing a Tool to the Hub + +Sharing your custom tool with the community is easy! Simply upload it to your Hugging Face account using the `push_to_hub()` method. + +For instance, Alfred can share his `party_theme_tool` to help others find the best catering services in Gotham. Here's how to do it: + +```python +party_theme_tool.push_to_hub("{your_username}/party_theme_tool", token="") +``` + +### Importing a Tool from the Hub + +You can easily import tools created by other users using the `load_tool()` function. For example, Alfred might want to generate a promotional image for the party using AI. Instead of building a tool from scratch, he can leverage a predefined one from the community: + +```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.") +``` + +### Importing a Hugging Face Space as a Tool + +You can also import a HF Space as a tool using `Tool.from_space()`. This opens up possibilities for integrating with thousands of spaces from the community for tasks from image generation to data analysis. + +The tool will connect with the spaces Gradio backend using the `gradio_client`, so make sure to install it via `pip` if you don't have it already. + +For the party, Alfred can use an existing HF Space for the generation of the AI-generated image to be used in the announcement (instead of the pre-built tool we mentioned before). Let's build it! + +```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'} +) +``` + +### Importing a LangChain Tool + + +We'll discuss the `LangChain` framework in upcoming sections. For now, we just note that we can reuse LangChain tools in your smolagents workflow! + +You can easily load LangChain tools using the `Tool.from_langchain()` method. Alfred, ever the perfectionist, is preparing for a spectacular superhero night at Wayne Manor while the Waynes are away. To make sure every detail exceeds expectations, he taps into LangChain tools to find top-tier entertainment ideas. + +By using `Tool.from_langchain()`, Alfred effortlessly adds advanced search functionalities to his smolagent, enabling him to discover exclusive party ideas and services with just a few commands. + +Here's how he does it: + +```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.") +``` + +### Importing a tool collection from any MCP server + +`smolagents` also allows importing tools from the hundreds of MCP servers available on [glama.ai](https://glama.ai/mcp/servers) or [smithery.ai](https://smithery.ai). If you want to dive deeper about MCP, you can check our [free MCP Course](https://huggingface.co/learn/mcp-course/). + +
+Install mcp client + +We first need to install the `mcp` integration for `smolagents`. + +```bash +pip install "smolagents[mcp]" +``` +
+ +The MCP servers tools can be loaded in a ToolCollection object as follow: + +```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.") +``` + +With this setup, Alfred can quickly discover luxurious entertainment options, ensuring Gotham's elite guests have an unforgettable experience. This tool helps him curate the perfect superhero-themed event for Wayne Manor! ๐ŸŽ‰ + +## Resources + +- [Tools Tutorial](https://huggingface.co/docs/smolagents/tutorials/tools) - Explore this tutorial to learn how to work with tools effectively. +- [Tools Documentation](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools) - Comprehensive reference documentation on tools. +- [Tools Guided Tour](https://huggingface.co/docs/smolagents/v1.8.1/en/guided_tour#tools) - A step-by-step guided tour to help you build and utilize tools efficiently. +- [Building Effective Agents](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - A detailed guide on best practices for developing reliable and high-performance custom function 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..1ac36a15 --- /dev/null +++ b/units/ko/unit2/smolagents/vision_agents.mdx @@ -0,0 +1,224 @@ + + +# Vision Agents with smolagents + + +The examples in this section require access to a powerful VLM model. We tested them using the GPT-4o API. +However, Why use smolagents discusses alternative solutions supported by smolagents and Hugging Face. If you'd like to explore other options, be sure to check that section. + + +Empowering agents with visual capabilities is crucial for solving tasks that go beyond text processing. Many real-world challenges, such as web browsing or document understanding, require analyzing rich visual content. Fortunately, `smolagents` provides built-in support for vision-language models (VLMs), enabling agents to process and interpret images effectively. + +In this example, imagine Alfred, the butler at Wayne Manor, is tasked with verifying the identities of the guests attending the party. As you can imagine, Alfred may not be familiar with everyone arriving. To help him, we can use an agent that verifies their identity by searching for visual information about their appearance using a VLM. This will allow Alfred to make informed decisions about who can enter. Let's build this example! + + +## Providing Images at the Start of the Agent's Execution + + +You can follow the code in this notebook that you can run using Google Colab. + + +In this approach, images are passed to the agent at the start and stored as `task_images` alongside the task prompt. The agent then processes these images throughout its execution. + +Consider the case where Alfred wants to verify the identities of the superheroes attending the party. He already has a dataset of images from previous parties with the names of the guests. Given a new visitor's image, the agent can compare it with the existing dataset and make a decision about letting them in. + +In this case, a guest is trying to enter, and Alfred suspects that this visitor might be The Joker impersonating Wonder Woman. Alfred needs to verify their identity to prevent anyone unwanted from entering. + +Letโ€™s build the example. First, the images are loaded. In this case, we use images from Wikipedia to keep the example minimal, but imagine the possible use-case! + +```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 image + "https://upload.wikimedia.org/wikipedia/en/9/98/Joker_%28DC_Comics_character%29.jpg" # Joker image +] + +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) +``` + +Now that we have the images, the agent will tell us whether one guest is actually a superhero (Wonder Woman) or a villain (The Joker). + +```python +from smolagents import CodeAgent, OpenAIServerModel + +model = OpenAIServerModel(model_id="gpt-4o") + +# Instantiate the agent +agent = CodeAgent( + tools=[], + model=model, + max_steps=20, + verbosity_level=2 +) + +response = agent.run( + """ + Describe the costume and makeup that the comic character in these photos is wearing and return the description. + Tell me if the guest is The Joker or Wonder Woman. + """, + images=images +) +``` + +In the case of my run, the output is the following, although it could vary in your case, as we've already discussed: + +```python + { + 'Costume and Makeup - First Image': ( + 'Purple coat and a purple silk-like cravat or tie over a mustard-yellow shirt.', + 'White face paint with exaggerated features, dark eyebrows, blue eye makeup, red lips forming a wide smile.' + ), + 'Costume and Makeup - Second Image': ( + 'Dark suit with a flower on the lapel, holding a playing card.', + 'Pale skin, green hair, very red lips with an exaggerated grin.' + ), + 'Character Identity': 'This character resembles known depictions of The Joker from comic book media.' + } +``` + +In this case, the output reveals that the person is impersonating someone else, so we can prevent The Joker from entering the party! + +## Providing Images with Dynamic Retrieval + + +You can follow the code in this Python file + + +The previous approach is valuable and has many potential use cases. However, in situations where the guest is not in the database, we need to explore other ways of identifying them. One possible solution is to dynamically retrieve images and information from external sources, such as browsing the web for details. + +In this approach, images are dynamically added to the agent's memory during execution. As we know, agents in `smolagents` are based on the `MultiStepAgent` class, which is an abstraction of the ReAct framework. This class operates in a structured cycle where various variables and knowledge are logged at different stages: + +1. **SystemPromptStep:** Stores the system prompt. +2. **TaskStep:** Logs the user query and any provided input. +3. **ActionStep:** Captures logs from the agent's actions and results. + +This structured approach allows agents to incorporate visual information dynamically and respond adaptively to evolving tasks. Below is the diagram we've already seen, illustrating the dynamic workflow process and how different steps integrate within the agent lifecycle. When browsing, the agent can take screenshots and save them as `observation_images` in the `ActionStep`. + +![Dynamic image retrieval](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/smolagents-can-see/diagram_adding_vlms_smolagents.png) + +Now that we understand the need, let's build our complete example. In this case, Alfred wants full control over the guest verification process, so browsing for details becomes a viable solution. To complete this example, we need a new set of tools for the agent. Additionally, we'll use Selenium and Helium, which are browser automation tools. This will allow us to build an agent that explores the web, searching for details about a potential guest and retrieving verification information. Let's install the tools needed: + +```bash +pip install "smolagents[all]" helium selenium python-dotenv +``` + +We'll need a set of agent tools specifically designed for browsing, such as `search_item_ctrl_f`, `go_back`, and `close_popups`. These tools allow the agent to act like a person navigating the web. + +```python +@tool +def search_item_ctrl_f(text: str, nth_result: int = 1) -> str: + """ + Searches for text on the current page via Ctrl + F and jumps to the nth occurrence. + Args: + text: The text to search for + nth_result: Which occurrence to jump to (default: 1) + """ + elements = driver.find_elements(By.XPATH, f"//*[contains(text(), '{text}')]") + if nth_result > len(elements): + raise Exception(f"Match nยฐ{nth_result} not found (only {len(elements)} matches found)") + result = f"Found {len(elements)} matches for '{text}'." + elem = elements[nth_result - 1] + driver.execute_script("arguments[0].scrollIntoView(true);", elem) + result += f"Focused on element {nth_result} of {len(elements)}" + return result + + +@tool +def go_back() -> None: + """Goes back to previous page.""" + driver.back() + + +@tool +def close_popups() -> str: + """ + Closes any visible modal or pop-up on the page. Use this to dismiss pop-up windows! This does not work on cookie consent banners. + """ + webdriver.ActionChains(driver).send_keys(Keys.ESCAPE).perform() +``` + +We also need functionality for saving screenshots, as this will be an essential part of what our VLM agent uses to complete the task. This functionality captures the screenshot and saves it in `step_log.observations_images = [image.copy()]`, allowing the agent to store and process the images dynamically as it navigates. + +```python +def save_screenshot(step_log: ActionStep, agent: CodeAgent) -> None: + sleep(1.0) # Let JavaScript animations happen before taking the screenshot + driver = helium.get_driver() + current_step = step_log.step_number + if driver is not None: + for step_logs in agent.logs: # Remove previous screenshots from logs for lean processing + 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"Captured a browser screenshot: {image.size} pixels") + step_log.observations_images = [image.copy()] # Create a copy to ensure it persists, important! + + # Update observations with current URL + url_info = f"Current url: {driver.current_url}" + step_log.observations = url_info if step_logs.observations is None else step_log.observations + "\n" + url_info + return +``` + +This function is passed to the agent as `step_callback`, as it's triggered at the end of each step during the agent's execution. This allows the agent to dynamically capture and store screenshots throughout its process. + +Now, we can generate our vision agent for browsing the web, providing it with the tools we created, along with the `DuckDuckGoSearchTool` to explore the web. This tool will help the agent retrieve necessary information for verifying guests' identities based on visual cues. + +```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, +) +``` + +With that, Alfred is ready to check the guests' identities and make informed decisions about whether to let them into the party: + +```python +agent.run(""" +I am Alfred, the butler of Wayne Manor, responsible for verifying the identity of guests at party. A superhero has arrived at the entrance claiming to be Wonder Woman, but I need to confirm if she is who she says she is. + +Please search for images of Wonder Woman and generate a detailed visual description based on those images. Additionally, navigate to Wikipedia to gather key details about her appearance. With this information, I can determine whether to grant her access to the event. +""" + helium_instructions) +``` + +You can see that we include `helium_instructions` as part of the task. This special prompt is aimed to control the navigation of the agent, ensuring that it follows the correct steps while browsing the web. + +Let's see how this works in the video below: + + + +This is the final output: + +```python +Final answer: Wonder Woman is typically depicted wearing a red and gold bustier, blue shorts or skirt with white stars, a golden tiara, silver bracelets, and a golden Lasso of Truth. She is Princess Diana of Themyscira, known as Diana Prince in the world of men. +``` + +With all of that, we've successfully created our identity verifier for the party! Alfred now has the necessary tools to ensure only the right guests make it through the door. Everything is set to have a good time at Wayne Manor! + + +## Further Reading + +- [We just gave sight to smolagents](https://huggingface.co/blog/smolagents-can-see) - Blog describing the vision agent functionality. +- [Web Browser Automation with Agents ๐Ÿค–๐ŸŒ](https://huggingface.co/docs/smolagents/examples/web_browser) - Example for Web browsing using a vision agent. +- [Web Browser Vision Agent Example](https://github.com/huggingface/smolagents/blob/main/src/smolagents/vision_web_browser.py) - Example for Web browsing using a vision agent. 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..3a6b848c --- /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) +# Why use smolagents + +In this module, we will explore the pros and cons of using [smolagents](https://huggingface.co/docs/smolagents/en/index), helping you make an informed decision about whether it's the right framework for your needs. + +## What is `smolagents`? + +`smolagents` is a simple yet powerful framework for building AI agents. It provides LLMs with the _agency_ to interact with the real world, such as searching or generating images. + +As we learned in unit 1, AI agents are programs that use LLMs to generate **'thoughts'** based on **'observations'** to perform **'actions'**. Let's explore how this is implemented in smolagents. + +### Key Advantages of `smolagents` +- **Simplicity:** Minimal code complexity and abstractions, to make the framework easy to understand, adopt and extend +- **Flexible LLM Support:** Works with any LLM through integration with Hugging Face tools and external APIs +- **Code-First Approach:** First-class support for Code Agents that write their actions directly in code, removing the need for parsing and simplifying tool calling +- **HF Hub Integration:** Seamless integration with the Hugging Face Hub, allowing the use of Gradio Spaces as tools + +### When to use smolagents? + +With these advantages in mind, when should we use smolagents over other frameworks? + +smolagents is ideal when: +- You need a **lightweight and minimal solution.** +- You want to **experiment quickly** without complex configurations. +- Your **application logic is straightforward.** + +### Code vs. JSON Actions +Unlike other frameworks where agents write actions in JSON, `smolagents` **focuses on tool calls in code**, simplifying the execution process. This is because there's no need to parse the JSON in order to build code that calls the tools: the output can be executed directly. + +The following diagram illustrates this difference: + +![Code vs. JSON actions](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/code_vs_json_actions.png) + +To review the difference between Code vs JSON Actions, you can revisit [the Actions Section in Unit 1](https://huggingface.co/learn/agents-course/unit1/actions#actions-enabling-the-agent-to-engage-with-its-environment). + +### Agent Types in `smolagents` + +Agents in `smolagents` operate as **multi-step agents**. + +Each [`MultiStepAgent`](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.MultiStepAgent) performs: +- One thought +- One tool call and execution + +In addition to using **[CodeAgent](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.CodeAgent)** as the primary type of agent, smolagents also supports **[ToolCallingAgent](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.ToolCallingAgent)**, which writes tool calls in JSON. + +We will explore each agent type in more detail in the following sections. + + +In smolagents, tools are defined using @tool decorator wrapping a Python function or the Tool class. + + +### Model Integration in `smolagents` +`smolagents` supports flexible LLM integration, allowing you to use any callable model that meets [certain criteria](https://huggingface.co/docs/smolagents/main/en/reference/models). The framework provides several predefined classes to simplify model connections: + +- **[TransformersModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.TransformersModel):** Implements a local `transformers` pipeline for seamless integration. +- **[InferenceClientModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.InferenceClientModel):** Supports [serverless inference](https://huggingface.co/docs/huggingface_hub/main/en/guides/inference) calls through [Hugging Face's infrastructure](https://huggingface.co/docs/api-inference/index), or via a growing number of [third-party inference providers](https://huggingface.co/docs/huggingface_hub/main/en/guides/inference#supported-providers-and-tasks). +- **[LiteLLMModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.LiteLLMModel):** Leverages [LiteLLM](https://www.litellm.ai/) for lightweight model interactions. +- **[OpenAIServerModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.OpenAIServerModel):** Connects to any service that offers an OpenAI API interface. +- **[AzureOpenAIServerModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.AzureOpenAIServerModel):** Supports integration with any Azure OpenAI deployment. + +This flexibility ensures that developers can choose the model and service most suitable for their specific use cases, and allows for easy experimentation. + +Now that we understood why and when to use smolagents, let's dive deeper into this powerful library! + +## Resources + +- [smolagents Blog](https://huggingface.co/blog/smolagents) - Introduction to smolagents and code interactions From 438de5e8e6e2f686c411a4579a2cb1eee844a97f Mon Sep 17 00:00:00 2001 From: Jeong Ahn Date: Thu, 3 Jul 2025 08:52:53 +0900 Subject: [PATCH 3/6] feat: nmt draft : langgraph --- units/ko/unit2/langgraph/building_blocks.mdx | 75 +++--- units/ko/unit2/langgraph/conclusion.mdx | 24 +- .../langgraph/document_analysis_agent.mdx | 200 ++++++-------- units/ko/unit2/langgraph/first_graph.mdx | 246 ++++++++---------- units/ko/unit2/langgraph/introduction.mdx | 34 +-- units/ko/unit2/langgraph/quiz1.mdx | 88 +++---- .../unit2/langgraph/when_to_use_langgraph.mdx | 76 +++--- 7 files changed, 339 insertions(+), 404 deletions(-) diff --git a/units/ko/unit2/langgraph/building_blocks.mdx b/units/ko/unit2/langgraph/building_blocks.mdx index 3b322ca2..90e74d73 100644 --- a/units/ko/unit2/langgraph/building_blocks.mdx +++ b/units/ko/unit2/langgraph/building_blocks.mdx @@ -1,16 +1,16 @@ -# Building Blocks of LangGraph +# LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ -To build applications with LangGraph, you need to understand its core components. Let's explore the fundamental building blocks that make up a LangGraph application. +LangGraph๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋ ค๋ฉด ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. LangGraph ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ๋“ค์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Building Blocks -An application in LangGraph starts from an **entrypoint**, and depending on the execution, the flow may go to one function or another until it reaches the END. +LangGraph์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ **์ง„์ž…์ **์—์„œ ์‹œ์ž‘ํ•˜์—ฌ, ์‹คํ–‰์— ๋”ฐ๋ผ ํ๋ฆ„์ด ํ•œ ํ•จ์ˆ˜์—์„œ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋กœ ์ด๋™ํ•˜๋‹ค๊ฐ€ END์— ๋„๋‹ฌํ•ฉ๋‹ˆ๋‹ค. Application -## 1. State +## 1. ์ƒํƒœ(State) -**State** is the central concept in LangGraph. It represents all the information that flows through your application. +**์ƒํƒœ**๋Š” LangGraph์˜ ํ•ต์‹ฌ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ†ตํ•ด ํ๋ฅด๋Š” ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ```python from typing_extensions import TypedDict @@ -19,16 +19,16 @@ class State(TypedDict): graph_state: str ``` -The state is **User defined**, hence the fields should carefully be crafted to contain all data needed for decision-making process! +์ƒํƒœ๋Š” **์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜**ํ•˜๋ฏ€๋กœ, ์˜์‚ฌ๊ฒฐ์ • ๊ณผ์ •์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค๊ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! -> ๐Ÿ’ก **Tip:** Think carefully about what information your application needs to track between steps. +> ๐Ÿ’ก **ํŒ:** ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹จ๊ณ„ ๊ฐ„์— ์ถ”์ ํ•ด์•ผ ํ•  ์ •๋ณด๋ฅผ ์‹ ์ค‘ํ•˜๊ฒŒ ๊ณ ๋ คํ•˜์„ธ์š”. -## 2. Nodes +## 2. ๋…ธ๋“œ(Nodes) -**Nodes** are python functions. Each node: -- Takes the state as input -- Performs some operation -- Returns updates to the state +**๋…ธ๋“œ**๋Š” ํŒŒ์ด์ฌ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š”: +- ์ƒํƒœ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Œ +- ์ผ๋ถ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ +- ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ˜ํ™˜ ```python def node_1(state): @@ -44,18 +44,17 @@ def node_3(state): return {"graph_state": state['graph_state'] +" sad!"} ``` -For example, Nodes can contain: -- **LLM calls**: Generate text or make decisions -- **Tool calls**: Interact with external systems -- **Conditional logic**: Determine next steps -- **Human intervention**: Get input from users +์˜ˆ๋ฅผ ๋“ค์–ด, ๋…ธ๋“œ๋Š” ๋‹ค์Œ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +- **LLM ํ˜ธ์ถœ**: ํ…์ŠคํŠธ ์ƒ์„ฑ ๋˜๋Š” ์˜์‚ฌ๊ฒฐ์ • +- **ํˆด ํ˜ธ์ถœ**: ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์ƒํ˜ธ์ž‘์šฉ +- **์กฐ๊ฑด๋ถ€ ๋กœ์ง**: ๋‹ค์Œ ๋‹จ๊ณ„ ๊ฒฐ์ • +- **์‚ฌ๋žŒ ๊ฐœ์ž…**: ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ ๋ฐ›๊ธฐ -> ๐Ÿ’ก **Info:** Some nodes necessary for the whole workflow like START and END exist from langGraph directly. +> ๐Ÿ’ก **์ •๋ณด:** START์™€ END ๊ฐ™์€ ์ „์ฒด ์›Œํฌํ”Œ๋กœ์šฐ์— ํ•„์š”ํ•œ ๋…ธ๋“œ๋“ค์€ langGraph์—์„œ ์ง์ ‘ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. +## 3. ์—ฃ์ง€(Edges) -## 3. Edges - -**Edges** connect nodes and define the possible paths through your graph: +**์—ฃ์ง€**๋Š” ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ  ๊ทธ๋ž˜ํ”„๋ฅผ ํ†ตํ•œ ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: ```python import random @@ -63,65 +62,65 @@ from typing import Literal def decide_mood(state) -> Literal["node_2", "node_3"]: - # Often, we will use state to decide on the next node to visit + # ์ข…์ข… ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•ด ๋‹ค์Œ์— ๋ฐฉ๋ฌธํ•  ๋…ธ๋“œ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค user_input = state['graph_state'] - # Here, let's just do a 50 / 50 split between nodes 2, 3 + # ์—ฌ๊ธฐ์„œ๋Š” ๋…ธ๋“œ 2, 3 ์‚ฌ์ด๋ฅผ 50:50์œผ๋กœ ๋ถ„ํ• ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค if random.random() < 0.5: - # 50% of the time, we return Node 2 + # 50% ํ™•๋ฅ ๋กœ ๋…ธ๋“œ 2 ๋ฐ˜ํ™˜ return "node_2" - # 50% of the time, we return Node 3 + # 50% ํ™•๋ฅ ๋กœ ๋…ธ๋“œ 3 ๋ฐ˜ํ™˜ return "node_3" ``` -Edges can be: -- **Direct**: Always go from node A to node B -- **Conditional**: Choose the next node based on the current state +์—ฃ์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +- **์ง์ ‘**: ํ•ญ์ƒ ๋…ธ๋“œ A์—์„œ ๋…ธ๋“œ B๋กœ ์ด๋™ +- **์กฐ๊ฑด๋ถ€**: ํ˜„์žฌ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค์Œ ๋…ธ๋“œ ์„ ํƒ ## 4. StateGraph -The **StateGraph** is the container that holds your entire agent workflow: +**StateGraph**๋Š” ์ „์ฒด ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋‹ด๋Š” ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค: ```python from IPython.display import Image, display from langgraph.graph import StateGraph, START, END -# Build graph +# ๊ทธ๋ž˜ํ”„ ๊ตฌ์ถ• builder = StateGraph(State) builder.add_node("node_1", node_1) builder.add_node("node_2", node_2) builder.add_node("node_3", node_3) -# Logic +# ๋กœ์ง 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) -# Add +# ์ถ”๊ฐ€ graph = builder.compile() ``` -Which can then be visualized! +๊ทธ๋Ÿฌ๋ฉด ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ```python -# View +# ๋ณด๊ธฐ display(Image(graph.get_graph().draw_mermaid_png())) ``` Graph Visualization -But most importantly, invoked: +ํ•˜์ง€๋งŒ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ํ˜ธ์ถœ์ž…๋‹ˆ๋‹ค: ```python graph.invoke({"graph_state" : "Hi, this is Lance."}) ``` -output : +์ถœ๋ ฅ: ``` ---Node 1--- ---Node 3--- {'graph_state': 'Hi, this is Lance. I am sad!'} ``` -## What's Next? +## ๋‹ค์Œ์€? -In the next section, we'll put these concepts into practice by building our first graph. This graph lets Alfred take in your e-mails, classify them, and craft a preliminary answer if they are genuine. +๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๊ฐœ๋…๋“ค์„ ์‹ค์ œ๋กœ ์ ์šฉํ•˜์—ฌ ์ฒซ ๋ฒˆ์งธ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ทธ๋ž˜ํ”„๋Š” ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ด๋ฉ”์ผ์„ ๋ฐ›์•„ ๋ถ„๋ฅ˜ํ•˜๊ณ , ์ •์ƒ ๋ฉ”์ผ์ด๋ผ๋ฉด ์ž„์‹œ ๋‹ต์žฅ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. diff --git a/units/ko/unit2/langgraph/conclusion.mdx b/units/ko/unit2/langgraph/conclusion.mdx index 29dcc73b..bf364f8c 100644 --- a/units/ko/unit2/langgraph/conclusion.mdx +++ b/units/ko/unit2/langgraph/conclusion.mdx @@ -1,21 +1,21 @@ -# Conclusion +# ๊ฒฐ๋ก  -Congratulations on finishing the `LangGraph` module of this second Unit! ๐Ÿฅณ +LangGraph ๋ชจ๋“ˆ์„ ์™„๋ฃŒํ•˜์‹  ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿฅณ -You've now mastered the fundamentals of building structured workflows with LangGraph which you will be able to send to production. +์ด์ œ LangGraph๋กœ ๊ตฌ์กฐํ™”๋œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋งˆ์Šคํ„ฐํ•˜์…จ์œผ๋ฉฐ, ์ด๋ฅผ ํ”„๋กœ๋•์…˜์— ๋ฐ”๋กœ ํˆฌ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -This module is just the beginning of your journey with LangGraph. For more advanced topics, we recommend: +์ด ๋ชจ๋“ˆ์€ LangGraph ์—ฌ์ •์˜ ์‹œ์ž‘์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๋” ์‹ฌํ™”๋œ ์ฃผ์ œ๋ฅผ ์œ„ํ•ด ๋‹ค์Œ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค: -- Exploring the [official LangGraph documentation](https://github.com/langchain-ai/langgraph) -- Taking the comprehensive [Introduction to LangGraph](https://academy.langchain.com/courses/intro-to-langgraph) course from LangChain Academy -- Build something yourself ! +- [๊ณต์‹ LangGraph ๋ฌธ์„œ](https://github.com/langchain-ai/langgraph) ํƒ์ƒ‰ +- LangChain ์•„์นด๋ฐ๋ฏธ์˜ ์ข…ํ•ฉ์ ์ธ [LangGraph ์†Œ๊ฐœ](https://academy.langchain.com/courses/intro-to-langgraph) ๊ฐ•์˜ ์ˆ˜๊ฐ• +- ์ง์ ‘ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”! -In the next Unit, you'll now explore real use cases. It's time to leave theory to get into real action ! +๋‹ค์Œ ๋‹จ์›์—์„œ๋Š” ์‹ค์ œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํƒ๊ตฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ก ์„ ๋– ๋‚˜ ์‹ค์ œ ํ–‰๋™์œผ๋กœ ๋“ค์–ด๊ฐˆ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค! -We would greatly appreciate **your thoughts on the course and suggestions for improvement**. If you have feedback, please ๐Ÿ‘‰ [fill this form](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) +**๊ฐ•์˜์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ๊ณผ ๊ฐœ์„  ์ œ์•ˆ์„ ๋งค์šฐ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค**. ํ”ผ๋“œ๋ฐฑ์ด ์žˆ์œผ์‹œ๋ฉด ๐Ÿ‘‰ [์ด ์–‘์‹์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) -### Keep Learning, Stay Awesome! ๐Ÿค— +### ๋ฐฐ์›€์„ ๋ฉˆ์ถ”์ง€ ๋งˆ์„ธ์š”! ๐Ÿค— -Good Sir/Madam! ๐ŸŽฉ๐Ÿฆ‡ +์กด๊ฒฝํ•˜๋Š” ์‹ ์‚ฌ/์ˆ™๋…€๋ถ„! ๐ŸŽฉ๐Ÿฆ‡ --Alfred- \ No newline at end of file +-์•Œํ”„๋ ˆ๋“œ- \ 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 index 65f972eb..c36f6c7e 100644 --- a/units/ko/unit2/langgraph/document_analysis_agent.mdx +++ b/units/ko/unit2/langgraph/document_analysis_agent.mdx @@ -1,33 +1,33 @@ -# Document Analysis Graph +# ๋ฌธ์„œ ๋ถ„์„ ๊ทธ๋ž˜ํ”„ -Alfred at your service. As Mr. Wayne's trusted butler, I've taken the liberty of documenting how I assist Mr Wayne with his various documentary needs. While he's out attending to his... nighttime activities, I ensure all his paperwork, training schedules, and nutritional plans are properly analyzed and organized. +์•Œํ”„๋ ˆ๋“œ๊ฐ€ ๋„์™€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. Mr. Wayne์˜ ์‹ ๋ขฐ๋ฐ›๋Š” ์ง‘์‚ฌ๋กœ์„œ, ์ €๋Š” Mr. Wayne์˜ ๋‹ค์–‘ํ•œ ๋ฌธ์„œ ์—…๋ฌด๋ฅผ ์–ด๋–ป๊ฒŒ ์ง€์›ํ•˜๋Š”์ง€ ๊ธฐ๋กํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฐ€ ๋ฐค ํ™œ๋™์„ ํ•˜๋Ÿฌ ๋‚˜๊ฐ„ ๋™์•ˆ, ์ €๋Š” ๋ชจ๋“  ์„œ๋ฅ˜, ํ›ˆ๋ จ ์ผ์ •, ์˜์–‘ ๊ณ„ํš์ด ์ œ๋Œ€๋กœ ๋ถ„์„๋˜๊ณ  ์ •๋ฆฌ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. -Before leaving, he left a note with his week's training program. I then took the responsibility to come up with a **menu** for tomorrow's meals. +๊ทธ๊ฐ€ ์™ธ์ถœํ•˜๊ธฐ ์ „, ์ด๋ฒˆ ์ฃผ ํ›ˆ๋ จ ํ”„๋กœ๊ทธ๋žจ์ด ์ ํžŒ ์ชฝ์ง€๋ฅผ ๋‚จ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ๋‚ด์ผ ์‹์‚ฌ๋ฅผ ์œ„ํ•œ **๋ฉ”๋‰ด**๋ฅผ ์ง์ ‘ ์งœ๊ธฐ๋กœ ํ–ˆ์ฃ . -For future such events, let's create a document analysis system using LangGraph to serve Mr. Wayne's needs. This system can: +์•ž์œผ๋กœ๋„ ์ด๋Ÿฐ ์ผ์ด ์žˆ์„ ๋•Œ๋ฅผ ๋Œ€๋น„ํ•ด, LangGraph๋ฅผ ํ™œ์šฉํ•ด Mr. Wayne์„ ์œ„ํ•œ ๋ฌธ์„œ ๋ถ„์„ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์ด ์‹œ์Šคํ…œ์€ ๋‹ค์Œ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -1. Process images document -2. Extract text using vision models (Vision Language Model) -3. Perform calculations when needed (to demonstrate normal tools) -4. Analyze content and provide concise summaries -5. Execute specific instructions related to documents +1. ์ด๋ฏธ์ง€ ๋ฌธ์„œ ์ฒ˜๋ฆฌ +2. ๋น„์ „ ๋ชจ๋ธ(๋น„์ „ ์–ธ์–ด ๋ชจ๋ธ)๋กœ ํ…์ŠคํŠธ ์ถ”์ถœ +3. ํ•„์š”์‹œ ๊ณ„์‚ฐ ์ˆ˜ํ–‰(์ผ๋ฐ˜ ํˆด ์‹œ์—ฐ) +4. ๋‚ด์šฉ ๋ถ„์„ ๋ฐ ์š”์•ฝ ์ œ๊ณต +5. ๋ฌธ์„œ ๊ด€๋ จ ํŠน์ • ์ง€์‹œ ์‹คํ–‰ -## The Butler's Workflow +## ์ง‘์‚ฌ์˜ ์›Œํฌํ”Œ๋กœ์šฐ -The workflow weโ€™ll build follows this structured schema: +์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค: -![Butler's Document Analysis Workflow](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/alfred_flow.png) +![์ง‘์‚ฌ์˜ ๋ฌธ์„œ ๋ถ„์„ ์›Œํฌํ”Œ๋กœ์šฐ](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/alfred_flow.png) -You can follow the code in this notebook that you can run using Google Colab. +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## Setting Up the environment +## ํ™˜๊ฒฝ ์„ค์ • ```python %pip install langgraph langchain_openai langchain_core ``` -and imports : +๊ทธ๋ฆฌ๊ณ  ์ž„ํฌํŠธ: ```python import base64 from typing import List, TypedDict, Annotated, Optional @@ -39,79 +39,57 @@ from langgraph.prebuilt import ToolNode, tools_condition from IPython.display import Image, display ``` -## Defining Agent's State +## ์—์ด์ „ํŠธ ์ƒํƒœ ์ •์˜ -This state is a little more complex than the previous ones we have seen. -`AnyMessage` is a class from Langchain that defines messages, and `add_messages` is an operator that adds the latest message rather than overwriting it with the latest state. +์ด ์ƒํƒœ๋Š” ์•ž์„œ ๋ณธ ๊ฒƒ๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. +`AnyMessage`๋Š” Langchain์˜ ๋ฉ”์‹œ์ง€ ํด๋ž˜์Šค์ด๊ณ , `add_messages`๋Š” ์ตœ์‹  ๋ฉ”์‹œ์ง€๋ฅผ ๋ˆ„์ ํ•˜๋Š” ์—ฐ์‚ฐ์ž์ž…๋‹ˆ๋‹ค. -This is a new concept in LangGraph, where you can add operators in your state to define the way they should interact together. +LangGraph์—์„œ๋Š” ์ƒํƒœ์— ์—ฐ์‚ฐ์ž๋ฅผ ์ถ”๊ฐ€ํ•ด ์ƒํ˜ธ์ž‘์šฉ ๋ฐฉ์‹์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python class AgentState(TypedDict): - # The document provided - input_file: Optional[str] # Contains file path (PDF/PNG) + # ์ œ๊ณต๋œ ๋ฌธ์„œ + 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: """ - Extract text from an image file using a multimodal model. + ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ๋ชจ๋ธ๋กœ ์ด๋ฏธ์ง€ ํŒŒ์ผ์—์„œ ํ…์ŠคํŠธ ์ถ”์ถœ - Master Wayne often leaves notes with his training regimen or meal plans. - This allows me to properly analyze the contents. + Wayne ์ฃผ์ธ๋‹˜์€ ์ข…์ข… ํ›ˆ๋ จ ์ผ์ •์ด๋‚˜ ์‹๋‹จ์ด ์ ํžŒ ์ชฝ์ง€๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค. + ์ด ๊ธฐ๋Šฅ์œผ๋กœ ๋‚ด์šฉ์„ ์ œ๋Œ€๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. """ all_text = "" try: - # Read image and encode as base64 with open(img_path, "rb") as image_file: image_bytes = image_file.read() - image_base64 = base64.b64encode(image_bytes).decode("utf-8") - - # Prepare the prompt including the base64 image data message = [ HumanMessage( content=[ - { - "type": "text", - "text": ( - "Extract all the text from this image. " - "Return only the extracted text, no explanations." - ), - }, - { - "type": "image_url", - "image_url": { - "url": f"data:image/png;base64,{image_base64}" - }, - }, + {"type": "text", "text": "์ด ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋“  ํ…์ŠคํŠธ๋ฅผ ์ถ”์ถœํ•˜์„ธ์š”. ์„ค๋ช… ์—†์ด ์ถ”์ถœ๋œ ํ…์ŠคํŠธ๋งŒ ๋ฐ˜ํ™˜ํ•˜์„ธ์š”."}, + {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_base64}"}}, ] ) ] - - # Call the vision-capable model response = vision_llm.invoke(message) - - # Append extracted text all_text += response.content + "\n\n" - return all_text.strip() except Exception as e: - # A butler should handle errors gracefully - error_msg = f"Error extracting text: {str(e)}" + error_msg = f"ํ…์ŠคํŠธ ์ถ”์ถœ ์˜ค๋ฅ˜: {str(e)}" print(error_msg) return "" def divide(a: int, b: int) -> float: - """Divide a and b - for Master Wayne's occasional calculations.""" + """Wayne ์ฃผ์ธ๋‹˜์˜ ๊ณ„์‚ฐ ์š”์ฒญ์„ ์œ„ํ•œ ๋‚˜๋ˆ—์…ˆ ํ•จ์ˆ˜""" return a / b -# Equip the butler with tools tools = [ divide, extract_text @@ -121,148 +99,138 @@ llm = ChatOpenAI(model="gpt-4o") llm_with_tools = llm.bind_tools(tools, parallel_tool_calls=False) ``` -## The nodes +## ๋…ธ๋“œ ์ •์˜ ```python def assistant(state: AgentState): - # System message + # ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€ textual_description_of_tool=""" extract_text(img_path: str) -> str: - Extract text from an image file using a multimodal model. - + ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ๋ชจ๋ธ๋กœ ์ด๋ฏธ์ง€ ํŒŒ์ผ์—์„œ ํ…์ŠคํŠธ ์ถ”์ถœ Args: - img_path: A local image file path (strings). - + img_path: ๋กœ์ปฌ ์ด๋ฏธ์ง€ ํŒŒ์ผ ๊ฒฝ๋กœ(๋ฌธ์ž์—ด) Returns: - A single string containing the concatenated text extracted from each image. + ๊ฐ ์ด๋ฏธ์ง€์—์„œ ์ถ”์ถœ๋œ ํ…์ŠคํŠธ๋ฅผ ํ•ฉ์นœ ๋ฌธ์ž์—ด + divide(a: int, b: int) -> float: - Divide a and b + a๋ฅผ b๋กœ ๋‚˜๋ˆ” """ image=state["input_file"] - sys_msg = SystemMessage(content=f"You are a helpful butler named Alfred that serves Mr. Wayne and Batman. You can analyse documents and run computations with provided tools:\n{textual_description_of_tool} \n You have access to some optional images. Currently the loaded image is: {image}") - + 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"] } ``` -## The ReAct Pattern: How I Assist Mr. Wayne +## ReAct ํŒจํ„ด: ์ง‘์‚ฌ์˜ ์ง€์› ๋ฐฉ์‹ -Allow me to explain the approach in this agent. The agent follows what's known as the ReAct pattern (Reason-Act-Observe) +์ด ์—์ด์ „ํŠธ๋Š” ReAct ํŒจํ„ด(Reason-Act-Observe)์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. -1. **Reason** about his documents and requests -2. **Act** by using appropriate tools -3. **Observe** the results -4. **Repeat** as necessary until I've fully addressed his needs +1. ๋ฌธ์„œ์™€ ์š”์ฒญ์„ **์ดํ•ด(Reason)** +2. ์ ์ ˆํ•œ ํˆด์„ **์‹คํ–‰(Act)** +3. ๊ฒฐ๊ณผ๋ฅผ **๊ด€์ฐฐ(Observe)** +4. ํ•„์š”์‹œ ๋ฐ˜๋ณต -This is a simple implementation of an agent using LangGraph. +์•„์ฃผ ๊ฐ„๋‹จํ•œ LangGraph ์—์ด์ „ํŠธ ๊ตฌํ˜„ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. ```python -# The graph +# ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ builder = StateGraph(AgentState) -# Define nodes: these do the work +# ๋…ธ๋“œ ์ •์˜ builder.add_node("assistant", assistant) builder.add_node("tools", ToolNode(tools)) -# Define edges: these determine how the control flow moves +# ์—ฃ์ง€ ์ •์˜ builder.add_edge(START, "assistant") builder.add_conditional_edges( "assistant", - # If the latest message requires a tool, route to tools - # Otherwise, provide a direct response tools_condition, ) builder.add_edge("tools", "assistant") react_graph = builder.compile() -# Show the butler's thought process +# ์ง‘์‚ฌ์˜ ์‚ฌ๊ณ  ๊ณผ์ •์„ ์‹œ๊ฐํ™” display(Image(react_graph.get_graph(xray=True).draw_mermaid_png())) ``` -We define a `tools` node with our list of tools. The `assistant` node is just our model with bound tools. -We create a graph with `assistant` and `tools` nodes. - -We add a `tools_condition` edge, which routes to `End` or to `tools` based on whether the `assistant` calls a tool. - -Now, we add one new step: +`tools` ๋…ธ๋“œ๋Š” ํˆด ๋ฆฌ์ŠคํŠธ๋ฅผ, `assistant` ๋…ธ๋“œ๋Š” ํˆด์ด ๋ฐ”์ธ๋”ฉ๋œ ๋ชจ๋ธ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. -We connect the `tools` node back to the `assistant`, forming a loop. +`tools_condition` ์—ฃ์ง€๋Š” ๋ชจ๋ธ์ด ํˆด์„ ํ˜ธ์ถœํ•˜๋ฉด tools๋กœ, ์•„๋‹ˆ๋ฉด End๋กœ ํ๋ฆ„์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. -- After the `assistant` node executes, `tools_condition` checks if the model's output is a tool call. -- If it is a tool call, the flow is directed to the `tools` node. -- The `tools` node connects back to `assistant`. -- This loop continues as long as the model decides to call tools. -- If the model response is not a tool call, the flow is directed to END, terminating the process. +์ด์ œ ํ•œ ๋‹จ๊ณ„ ๋” ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค: +- `tools` ๋…ธ๋“œ๋ฅผ ๋‹ค์‹œ `assistant`๋กœ ์—ฐ๊ฒฐํ•ด ๋ฃจํ”„๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +- `assistant` ์‹คํ–‰ ํ›„, `tools_condition`์ด ํˆด ํ˜ธ์ถœ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•ด ๋ถ„๊ธฐํ•ฉ๋‹ˆ๋‹ค. +- ํˆด ํ˜ธ์ถœ์ด๋ฉด `tools`๋กœ, ์•„๋‹ˆ๋ฉด END๋กœ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค. -![ReAct Pattern](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/Agent.png) +![ReAct ํŒจํ„ด](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/Agent.png) -## The Butler in Action +## ์ง‘์‚ฌ์˜ ์‹ค์ œ ํ™œ์šฉ ์˜ˆ์‹œ -### Example 1: Simple Calculations +### ์˜ˆ์‹œ 1: ๊ฐ„๋‹จํ•œ ๊ณ„์‚ฐ -Here is an example to show a simple use case of an agent using a tool in LangGraph. +์•„๋ž˜๋Š” LangGraph์—์„œ ํˆด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. ```python -messages = [HumanMessage(content="Divide 6790 by 5")] +messages = [HumanMessage(content="6790์„ 5๋กœ ๋‚˜๋ˆ ์ค˜")] messages = react_graph.invoke({"messages": messages, "input_file": None}) -# Show the messages +# ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ for m in messages['messages']: m.pretty_print() ``` -The conversation would proceed: +๋Œ€ํ™” ์˜ˆ์‹œ: ``` -Human: Divide 6790 by 5 +Human: 6790์„ 5๋กœ ๋‚˜๋ˆ ์ค˜ AI Tool Call: divide(a=6790, b=5) Tool Response: 1358.0 -Alfred: The result of dividing 6790 by 5 is 1358.0. +Alfred: 6790์„ 5๋กœ ๋‚˜๋ˆ„๋ฉด 1358.0์ž…๋‹ˆ๋‹ค. ``` -### Example 2: Analyzing Master Wayne's Training Documents +### ์˜ˆ์‹œ 2: Wayne ์ฃผ์ธ๋‹˜์˜ ํ›ˆ๋ จ ๋ฌธ์„œ ๋ถ„์„ -When Master Wayne leaves his training and meal notes: +์ฃผ์ธ๋‹˜์ด ํ›ˆ๋ จ ๋ฐ ์‹๋‹จ ์ชฝ์ง€๋ฅผ ๋‚จ๊ฒผ์„ ๋•Œ: ```python -messages = [HumanMessage(content="According to the note provided by Mr. Wayne in the provided images. What's the list of items I should buy for the dinner menu?")] +messages = [HumanMessage(content="์ œ๊ณต๋œ ์ด๋ฏธ์ง€์— ์žˆ๋Š” Wayne ์ฃผ์ธ๋‹˜์˜ ์ชฝ์ง€์— ๋”ฐ๋ผ ์ €๋… ๋ฉ”๋‰ด์— ํ•„์š”ํ•œ ์žฌ๋ฃŒ ๋ชฉ๋ก์„ ์•Œ๋ ค์ค˜.")] messages = react_graph.invoke({"messages": messages, "input_file": "Batman_training_and_meals.png"}) ``` -The interaction would proceed: +๋Œ€ํ™” ์˜ˆ์‹œ: ``` -Human: According to the note provided by Mr. Wayne in the provided images. What's the list of items I should buy for the dinner menu? +Human: ์ œ๊ณต๋œ ์ด๋ฏธ์ง€์— ์žˆ๋Š” Wayne ์ฃผ์ธ๋‹˜์˜ ์ชฝ์ง€์— ๋”ฐ๋ผ ์ €๋… ๋ฉ”๋‰ด์— ํ•„์š”ํ•œ ์žฌ๋ฃŒ ๋ชฉ๋ก์„ ์•Œ๋ ค์ค˜. AI Tool Call: extract_text(img_path="Batman_training_and_meals.png") -Tool Response: [Extracted text with training schedule and menu details] +Tool Response: [ํ›ˆ๋ จ ์ผ์ • ๋ฐ ๋ฉ”๋‰ด ์„ธ๋ถ€ ์ •๋ณด๊ฐ€ ์ถ”์ถœ๋จ] -Alfred: For the dinner menu, you should buy the following items: +Alfred: ์ €๋… ๋ฉ”๋‰ด๋ฅผ ์œ„ํ•ด ๋‹ค์Œ ์žฌ๋ฃŒ๋ฅผ ๊ตฌ์ž…ํ•˜์„ธ์š”: -1. Grass-fed local sirloin steak -2. Organic spinach -3. Piquillo peppers -4. Potatoes (for oven-baked golden herb potato) -5. Fish oil (2 grams) +1. ๋ชฉ์ดˆ ์‚ฌ์œก ์†Œ๊ณ ๊ธฐ ๋“ฑ์‹ฌ ์Šคํ…Œ์ดํฌ +2. ์œ ๊ธฐ๋† ์‹œ๊ธˆ์น˜ +3. ํ”ผํ‚ค์š” ๊ณ ์ถ” +4. ๊ฐ์ž(์˜ค๋ธ์— ๊ตฌ์šธ ํ—ˆ๋ธŒ ๊ฐ์ž์šฉ) +5. ํ”ผ์‰ฌ ์˜ค์ผ(2๊ทธ๋žจ) -Ensure the steak is grass-fed and the spinach and peppers are organic for the best quality meal. +์Šคํ…Œ์ดํฌ๋Š” ๋ชฉ์ดˆ ์‚ฌ์œก, ์‹œ๊ธˆ์น˜์™€ ๊ณ ์ถ”๋Š” ์œ ๊ธฐ๋†์œผ๋กœ ์ค€๋น„ํ•˜๋ฉด ์ตœ๊ณ ์˜ ์‹์‚ฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ``` -## Key Takeaways +## ํ•ต์‹ฌ ์š”์•ฝ -Should you wish to create your own document analysis butler, here are key considerations: +๋‚˜๋งŒ์˜ ๋ฌธ์„œ ๋ถ„์„ ์ง‘์‚ฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ์„ ๊ณ ๋ คํ•˜์„ธ์š”: -1. **Define clear tools** for specific document-related tasks -2. **Create a robust state tracker** to maintain context between tool calls -3. **Consider error handling** for tool failures -4. **Maintain contextual awareness** of previous interactions (ensured by the operator `add_messages`) +1. **๋ฌธ์„œ ๊ด€๋ จ ์ž‘์—…๋ณ„๋กœ ๋ช…ํ™•ํ•œ ํˆด ์ •์˜** +2. **ํˆด ํ˜ธ์ถœ ๊ฐ„ ๋งฅ๋ฝ ์œ ์ง€๋ฅผ ์œ„ํ•œ ๊ฒฌ๊ณ ํ•œ ์ƒํƒœ ์ถ”์ ๊ธฐ** +3. **ํˆด ์‹คํŒจ ์‹œ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๊ณ ๋ ค** +4. **์ด์ „ ์ƒํ˜ธ์ž‘์šฉ ๋งฅ๋ฝ ์œ ์ง€(add_messages ์—ฐ์‚ฐ์ž ํ™œ์šฉ)** -With these principles, you too can provide exemplary document analysis service worthy of Wayne Manor. +์ด ์›์น™์„ ๋”ฐ๋ฅด๋ฉด Wayne ์ €ํƒ์— ์–ด์šธ๋ฆฌ๋Š” ๋ฌธ์„œ ๋ถ„์„ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -*I trust this explanation has been satisfactory. Now, if you'll excuse me, Master Wayne's cape requires pressing before tonight's activities.* +*์ด ์„ค๋ช…์ด ๋„์›€์ด ๋˜์—ˆ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ด์ œ ์ฃผ์ธ๋‹˜์˜ ๋งํ† ๋ฅผ ๋‹ค๋ฆผ์งˆํ•˜๋Ÿฌ ๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.* diff --git a/units/ko/unit2/langgraph/first_graph.mdx b/units/ko/unit2/langgraph/first_graph.mdx index ff105626..4e957152 100644 --- a/units/ko/unit2/langgraph/first_graph.mdx +++ b/units/ko/unit2/langgraph/first_graph.mdx @@ -1,32 +1,32 @@ -# Building Your First LangGraph +# ๋‚˜๋งŒ์˜ ์ฒซ LangGraph ๋งŒ๋“ค๊ธฐ -Now that we understand the building blocks, let's put them into practice by building our first functional graph. We'll implement Alfred's email processing system, where he needs to: +์ด์ œ LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์‹ค์ œ๋กœ ์ ์šฉํ•ด๋ณด๋ฉฐ ์ฒซ ๋ฒˆ์งธ ๊ธฐ๋Šฅ์  ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์•Œํ”„๋ ˆ๋“œ์˜ ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•Œํ”„๋ ˆ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: -1. Read incoming emails -2. Classify them as spam or legitimate -3. Draft a preliminary response for legitimate emails -4. Send information to Mr. Wayne when legitimate (printing only) +1. ๋“ค์–ด์˜ค๋Š” ์ด๋ฉ”์ผ ์ฝ๊ธฐ +2. ์ŠคํŒธ ๋˜๋Š” ์ •์ƒ ๋ฉ”์ผ๋กœ ๋ถ„๋ฅ˜ํ•˜๊ธฐ +3. ์ •์ƒ ๋ฉ”์ผ์— ๋Œ€ํ•œ ์ž„์‹œ ๋‹ต์žฅ ์ž‘์„ฑํ•˜๊ธฐ +4. ์ •์ƒ ๋ฉ”์ผ์ผ ๊ฒฝ์šฐ Mr. Wayne์—๊ฒŒ ์ •๋ณด ์ „๋‹ฌ(์ถœ๋ ฅ๋งŒ) -This example demonstrates how to structure a workflow with LangGraph that involves LLM-based decision-making. While this can't be considered an Agent as no tool is involved, this section focuses more on learning the LangGraph framework than Agents. +์ด ์˜ˆ์ œ๋Š” LLM ๊ธฐ๋ฐ˜ ์˜์‚ฌ๊ฒฐ์ •์ด ํฌํ•จ๋œ LangGraph ์›Œํฌํ”Œ๋กœ์šฐ ๊ตฌ์กฐํ™” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. (์—ฌ๊ธฐ์„œ๋Š” ๋ณ„๋„์˜ ํˆด์ด ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ Agent๋ผ๊ณ  ๋ถ€๋ฅด์ง„ ์•Š์ง€๋งŒ, LangGraph ํ”„๋ ˆ์ž„์›Œํฌ ํ•™์Šต์— ์ดˆ์ ์„ ๋‘ก๋‹ˆ๋‹ค.) -You can follow the code in this notebook that you can run using Google Colab. +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## Our Workflow +## ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค ์›Œํฌํ”Œ๋กœ์šฐ -Here's the workflow we'll build: +์•„๋ž˜์™€ ๊ฐ™์€ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค: First LangGraph -## Setting Up Our Environment +## ํ™˜๊ฒฝ ์„ค์ • -First, let's install the required packages: +๋จผ์ € ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค: ```python %pip install langgraph langchain_openai ``` -Next, let's import the necessary modules: +ํ•„์š”ํ•œ ๋ชจ๋“ˆ์„ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค: ```python import os @@ -36,82 +36,68 @@ from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage ``` -## Step 1: Define Our State +## 1๋‹จ๊ณ„: ์ƒํƒœ(State) ์ •์˜ํ•˜๊ธฐ -Let's define what information Alfred needs to track during the email processing workflow: +์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ถ”์ ํ•ด์•ผ ํ•  ์ •๋ณด๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: ```python class EmailState(TypedDict): - # The email being processed - email: Dict[str, Any] # Contains subject, sender, body, etc. + # ์ฒ˜๋ฆฌ ์ค‘์ธ ์ด๋ฉ”์ผ + email: Dict[str, Any] # ์ œ๋ชฉ, ๋ฐœ์‹ ์ž, ๋ณธ๋ฌธ ๋“ฑ ํฌํ•จ - # Category of the email (inquiry, complaint, etc.) + # ์ด๋ฉ”์ผ ๋ถ„๋ฅ˜(๋ฌธ์˜, ๋ถˆ๋งŒ ๋“ฑ) email_category: Optional[str] - # Reason why the email was marked as spam + # ์ŠคํŒธ์œผ๋กœ ๋ถ„๋ฅ˜๋œ ์ด์œ  spam_reason: Optional[str] - # Analysis and decisions + # ๋ถ„์„ ๋ฐ ๊ฒฐ์ • is_spam: Optional[bool] - # Response generation + # ๋‹ต์žฅ ์ƒ์„ฑ email_draft: Optional[str] - # Processing metadata - messages: List[Dict[str, Any]] # Track conversation with LLM for analysis + # ์ฒ˜๋ฆฌ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ + messages: List[Dict[str, Any]] # LLM๊ณผ์˜ ๋Œ€ํ™” ์ถ”์  ``` -> ๐Ÿ’ก **Tip:** Make your state comprehensive enough to track all the important information, but avoid bloating it with unnecessary details. +> ๐Ÿ’ก **ํŒ:** ์ƒํƒœ๋Š” ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๋ชจ๋‘ ๋‹ด๋˜, ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋น„๋Œ€ํ•ด์ง€์ง€ ์•Š๋„๋ก ํ•˜์„ธ์š”. -## Step 2: Define Our Nodes +## 2๋‹จ๊ณ„: ๋…ธ๋“œ ์ •์˜ํ•˜๊ธฐ -Now, let's create the processing functions that will form our nodes: +์ด์ œ ๊ฐ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ๋‹ด๋‹นํ•  ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค: ```python -# Initialize our LLM +# LLM ์ดˆ๊ธฐํ™” model = ChatOpenAI(temperature=0) def read_email(state: EmailState): - """Alfred reads and logs the incoming email""" + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ ๋“ค์–ด์˜จ ์ด๋ฉ”์ผ์„ ์ฝ๊ณ  ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.""" email = state["email"] - - # Here we might do some initial preprocessing - print(f"Alfred is processing an email from {email['sender']} with subject: {email['subject']}") - - # No state changes needed here + print(f"์•Œํ”„๋ ˆ๋“œ๊ฐ€ {email['sender']}๋กœ๋ถ€ํ„ฐ ์˜จ ๋ฉ”์ผ(์ œ๋ชฉ: {email['subject']})์„ ์ฒ˜๋ฆฌ ์ค‘์ž…๋‹ˆ๋‹ค.") return {} def classify_email(state: EmailState): - """Alfred uses an LLM to determine if the email is spam or legitimate""" + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ LLM์„ ์‚ฌ์šฉํ•ด ์ด๋ฉ”์ผ์„ ์ŠคํŒธ/์ •์ƒ์œผ๋กœ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค.""" email = state["email"] - - # Prepare our prompt for the LLM prompt = f""" - As Alfred the butler, analyze this email and determine if it is spam or legitimate. + ์ง‘์‚ฌ ์•Œํ”„๋ ˆ๋“œ๋กœ์„œ, ์ด ์ด๋ฉ”์ผ์„ ๋ถ„์„ํ•ด ์ŠคํŒธ์ธ์ง€ ์ •์ƒ์ธ์ง€ ํŒ๋‹จํ•˜์„ธ์š”. - Email: + ์ด๋ฉ”์ผ: From: {email['sender']} Subject: {email['subject']} Body: {email['body']} - First, determine if this email is spam. If it is spam, explain why. - If it is legitimate, categorize it (inquiry, complaint, thank you, etc.). + ๋จผ์ € ์ด ์ด๋ฉ”์ผ์ด ์ŠคํŒธ์ธ์ง€ ํŒ๋‹จํ•˜๊ณ , ์ŠคํŒธ์ด๋ผ๋ฉด ๊ทธ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•˜์„ธ์š”. + ์ •์ƒ ๋ฉ”์ผ์ด๋ผ๋ฉด (๋ฌธ์˜, ๋ถˆ๋งŒ, ๊ฐ์‚ฌ, ์š”์ฒญ ๋“ฑ) ์นดํ…Œ๊ณ ๋ฆฌ๋„ ๋ถ„๋ฅ˜ํ•˜์„ธ์š”. """ - - # Call the LLM messages = [HumanMessage(content=prompt)] response = model.invoke(messages) - - # Simple logic to parse the response (in a real app, you'd want more robust parsing) response_text = response.content.lower() is_spam = "spam" in response_text and "not spam" not in response_text - - # Extract a reason if it's spam spam_reason = None if is_spam and "reason:" in response_text: spam_reason = response_text.split("reason:")[1].strip() - - # Determine category if legitimate email_category = None if not is_spam: categories = ["inquiry", "complaint", "thank you", "request", "information"] @@ -119,14 +105,10 @@ def classify_email(state: EmailState): if category in response_text: email_category = category break - - # Update messages for tracking new_messages = state.get("messages", []) + [ {"role": "user", "content": prompt}, {"role": "assistant", "content": response.content} ] - - # Return state updates return { "is_spam": is_spam, "spam_reason": spam_reason, @@ -135,101 +117,88 @@ def classify_email(state: EmailState): } def handle_spam(state: EmailState): - """Alfred discards spam email with a note""" - print(f"Alfred has marked the email as spam. Reason: {state['spam_reason']}") - print("The email has been moved to the spam folder.") - - # We're done processing this email + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ŠคํŒธ ๋ฉ”์ผ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.""" + print(f"์•Œํ”„๋ ˆ๋“œ๋Š” ์ด ๋ฉ”์ผ์„ ์ŠคํŒธ์œผ๋กœ ๋ถ„๋ฅ˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์œ : {state['spam_reason']}") + print("์ด ๋ฉ”์ผ์€ ์ŠคํŒธ ํด๋”๋กœ ์ด๋™๋˜์—ˆ์Šต๋‹ˆ๋‹ค.") return {} def draft_response(state: EmailState): - """Alfred drafts a preliminary response for legitimate emails""" + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ •์ƒ ๋ฉ”์ผ์— ์ž„์‹œ ๋‹ต์žฅ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.""" email = state["email"] - category = state["email_category"] or "general" - - # Prepare our prompt for the LLM + category = state["email_category"] or "์ผ๋ฐ˜" prompt = f""" - As Alfred the butler, draft a polite preliminary response to this email. + ์ง‘์‚ฌ ์•Œํ”„๋ ˆ๋“œ๋กœ์„œ, ์ด ์ด๋ฉ”์ผ์— ์ •์ค‘ํ•œ ์ž„์‹œ ๋‹ต์žฅ์„ ์ž‘์„ฑํ•˜์„ธ์š”. - Email: + ์ด๋ฉ”์ผ: From: {email['sender']} Subject: {email['subject']} Body: {email['body']} - This email has been categorized as: {category} + ์ด ์ด๋ฉ”์ผ์˜ ์นดํ…Œ๊ณ ๋ฆฌ: {category} - Draft a brief, professional response that Mr. Hugg can review and personalize before sending. + Mr. Hugg๊ฐ€ ๊ฒ€ํ†  ํ›„ ๊ฐœ์ธํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐ„๋‹จํ•˜๊ณ  ์ „๋ฌธ์ ์ธ ๋‹ต์žฅ์„ ์ž‘์„ฑํ•˜์„ธ์š”. """ - - # Call the LLM messages = [HumanMessage(content=prompt)] response = model.invoke(messages) - - # Update messages for tracking new_messages = state.get("messages", []) + [ {"role": "user", "content": prompt}, {"role": "assistant", "content": response.content} ] - - # Return state updates return { "email_draft": response.content, "messages": new_messages } def notify_mr_hugg(state: EmailState): - """Alfred notifies Mr. Hugg about the email and presents the draft response""" + """์•Œํ”„๋ ˆ๋“œ๊ฐ€ Mr. Hugg์—๊ฒŒ ๋ฉ”์ผ๊ณผ ์ž„์‹œ ๋‹ต์žฅ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.""" email = state["email"] - print("\n" + "="*50) - print(f"Sir, you've received an email from {email['sender']}.") - print(f"Subject: {email['subject']}") - print(f"Category: {state['email_category']}") - print("\nI've prepared a draft response for your review:") + print(f"์ฃผ์ธ๋‹˜, {email['sender']}๋กœ๋ถ€ํ„ฐ ๋ฉ”์ผ์ด ๋„์ฐฉํ–ˆ์Šต๋‹ˆ๋‹ค.") + print(f"์ œ๋ชฉ: {email['subject']}") + print(f"์นดํ…Œ๊ณ ๋ฆฌ: {state['email_category']}") + print("\n๊ฒ€ํ† ํ•˜์‹ค ์ž„์‹œ ๋‹ต์žฅ์„ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค:") print("-"*50) print(state["email_draft"]) print("="*50 + "\n") - - # We're done processing this email return {} ``` -## Step 3: Define Our Routing Logic +## 3๋‹จ๊ณ„: ๋ถ„๊ธฐ ๋กœ์ง ์ •์˜ํ•˜๊ธฐ -We need a function to determine which path to take after classification: +๋ถ„๋ฅ˜ ํ›„ ์–ด๋–ค ๊ฒฝ๋กœ๋กœ ๊ฐˆ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค: ```python def route_email(state: EmailState) -> str: - """Determine the next step based on spam classification""" + """์ŠคํŒธ ๋ถ„๋ฅ˜ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.""" if state["is_spam"]: return "spam" else: return "legitimate" ``` -> ๐Ÿ’ก **Note:** This routing function is called by LangGraph to determine which edge to follow after the classification node. The return value must match one of the keys in our conditional edges mapping. +> ๐Ÿ’ก **์ฐธ๊ณ :** ์ด ๋ผ์šฐํŒ… ํ•จ์ˆ˜๋Š” LangGraph๊ฐ€ ๋ถ„๋ฅ˜ ๋…ธ๋“œ ์ดํ›„ ์–ด๋–ค ์—ฃ์ง€๋ฅผ ๋”ฐ๋ผ๊ฐˆ์ง€ ๊ฒฐ์ •ํ•  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์€ ์กฐ๊ฑด๋ถ€ ์—ฃ์ง€ ๋งคํ•‘์˜ ํ‚ค์™€ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -## Step 4: Create the StateGraph and Define Edges +## 4๋‹จ๊ณ„: StateGraph ์ƒ์„ฑ ๋ฐ ์—ฃ์ง€ ์ •์˜ -Now we connect everything together: +์ด์ œ ๋ชจ๋“  ๊ฒƒ์„ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค: ```python -# Create the graph +# ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ email_graph = StateGraph(EmailState) -# Add nodes +# ๋…ธ๋“œ ์ถ”๊ฐ€ 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) -# Start the edges +# ์—ฃ์ง€ ์‹œ์ž‘ email_graph.add_edge(START, "read_email") -# Add edges - defining the flow +# ํ๋ฆ„ ์ •์˜ email_graph.add_edge("read_email", "classify_email") -# Add conditional branching from classify_email +# ๋ถ„๊ธฐ ์ถ”๊ฐ€ email_graph.add_conditional_edges( "classify_email", route_email, @@ -239,38 +208,38 @@ email_graph.add_conditional_edges( } ) -# Add the final edges +# ๋งˆ์ง€๋ง‰ ์—ฃ์ง€ email_graph.add_edge("handle_spam", END) email_graph.add_edge("draft_response", "notify_mr_hugg") email_graph.add_edge("notify_mr_hugg", END) -# Compile the graph +# ๊ทธ๋ž˜ํ”„ ์ปดํŒŒ์ผ compiled_graph = email_graph.compile() ``` -Notice how we use the special `END` node provided by LangGraph. This indicates terminal states where the workflow completes. +LangGraph์—์„œ ์ œ๊ณตํ•˜๋Š” ํŠน์ˆ˜ํ•œ `END` ๋…ธ๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ์™„๋ฃŒ๋˜๋Š” ์ง€์ ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. -## Step 5: Run the Application +## 5๋‹จ๊ณ„: ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ํ•˜๊ธฐ -Let's test our graph with a legitimate email and a spam email: +์ •์ƒ ๋ฉ”์ผ๊ณผ ์ŠคํŒธ ๋ฉ”์ผ๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ด…๋‹ˆ๋‹ค: ```python -# Example legitimate email +# ์ •์ƒ ๋ฉ”์ผ ์˜ˆ์‹œ legitimate_email = { "sender": "john.smith@example.com", - "subject": "Question about your services", - "body": "Dear Mr. Hugg, I was referred to you by a colleague and I'm interested in learning more about your consulting services. Could we schedule a call next week? Best regards, John Smith" + "subject": "์„œ๋น„์Šค ๋ฌธ์˜", + "body": "์•ˆ๋…•ํ•˜์„ธ์š” Mr. Hugg, ๋™๋ฃŒ์˜ ์ถ”์ฒœ์œผ๋กœ ์—ฐ๋ฝ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์ปจ์„คํŒ… ์„œ๋น„์Šค์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์ฃผ์— ํ†ตํ™” ๊ฐ€๋Šฅํ• ๊นŒ์š”? ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค, John Smith" } -# Example spam email +# ์ŠคํŒธ ๋ฉ”์ผ ์˜ˆ์‹œ spam_email = { "sender": "winner@lottery-intl.com", - "subject": "YOU HAVE WON $5,000,000!!!", - "body": "CONGRATULATIONS! You have been selected as the winner of our international lottery! To claim your $5,000,000 prize, please send us your bank details and a processing fee of $100." + "subject": "๋‹น์‹ ์€ $5,000,000์— ๋‹น์ฒจ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!!!", + "body": "์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๊ตญ์ œ ๋ณต๊ถŒ์— ๋‹น์ฒจ๋˜์…จ์Šต๋‹ˆ๋‹ค! ์ƒ๊ธˆ์„ ๋ฐ›์œผ์‹œ๋ ค๋ฉด ์€ํ–‰ ์ •๋ณด์™€ ์ˆ˜์ˆ˜๋ฃŒ $100์„ ๋ณด๋‚ด์ฃผ์„ธ์š”." } -# Process the legitimate email -print("\nProcessing legitimate email...") +# ์ •์ƒ ๋ฉ”์ผ ์ฒ˜๋ฆฌ +print("\n์ •์ƒ ๋ฉ”์ผ ์ฒ˜๋ฆฌ ์ค‘...") legitimate_result = compiled_graph.invoke({ "email": legitimate_email, "is_spam": None, @@ -280,8 +249,8 @@ legitimate_result = compiled_graph.invoke({ "messages": [] }) -# Process the spam email -print("\nProcessing spam email...") +# ์ŠคํŒธ ๋ฉ”์ผ ์ฒ˜๋ฆฌ +print("\n์ŠคํŒธ ๋ฉ”์ผ ์ฒ˜๋ฆฌ ์ค‘...") spam_result = compiled_graph.invoke({ "email": spam_email, "is_spam": None, @@ -292,84 +261,83 @@ spam_result = compiled_graph.invoke({ }) ``` -## Step 6: Inspecting Our Mail Sorting Agent with Langfuse ๐Ÿ“ก +## 6๋‹จ๊ณ„: Langfuse๋กœ ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ ๊ด€์ฐฐํ•˜๊ธฐ ๐Ÿ“ก -As Alfred fine-tunes the Mail Sorting Agent, he's growing weary of debugging its runs. Agents, by nature, are unpredictable and difficult to inspect. But since he aims to build the ultimate Spam Detection Agent and deploy it in production, he needs robust traceability for future monitoring and analysis. +์•Œํ”„๋ ˆ๋“œ๋Š” ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ๋ฅผ ๋‹ค๋“ฌ์œผ๋ฉด์„œ ๋””๋ฒ„๊น…์— ์ง€์ณ๊ฐ‘๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ  ์ถ”์ ์ด ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ถ๊ทน์˜ ์ŠคํŒธ ๊ฐ์ง€ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ํ”„๋กœ๋•์…˜์— ๋ฐฐํฌํ•˜๋ ค๋ฉด, ํ–ฅํ›„ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๋ถ„์„์„ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ์ถ”์  ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. -To do this, Alfred can use an observability tool such as [Langfuse](https://langfuse.com/) to trace and monitor the agent. +์ด๋ฅผ ์œ„ํ•ด ์•Œํ”„๋ ˆ๋“œ๋Š” [Langfuse](https://langfuse.com/)์™€ ๊ฐ™์€ ๊ด€์ฐฐ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -First, we pip install Langfuse: +๋จผ์ € Langfuse๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค: ```python %pip install -q langfuse ``` -Second, we pip install Langchain (LangChain is required because we use LangFuse): +LangChain๋„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค(Langfuse ์‚ฌ์šฉ ์‹œ ํ•„์š”): ```python %pip install langchain ``` -Next, we add the Langfuse API keys and host address as environment variables. You can get your Langfuse credentials by signing up for [Langfuse Cloud](https://cloud.langfuse.com) or [self-host Langfuse](https://langfuse.com/self-hosting). +Langfuse API ํ‚ค์™€ ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ๋ฅผ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. [Langfuse Cloud](https://cloud.langfuse.com) ๊ฐ€์ž… ๋˜๋Š” [์…€ํ”„ ํ˜ธ์ŠคํŒ…](https://langfuse.com/self-hosting)์œผ๋กœ ํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python import os - -# Get keys for your project from the project settings page: https://cloud.langfuse.com -os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..." +# ํ”„๋กœ์ ํŠธ ์„ค์ • ํŽ˜์ด์ง€์—์„œ ํ‚ค๋ฅผ ํ™•์ธํ•˜์„ธ์š”: 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 region -# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # ๐Ÿ‡บ๐Ÿ‡ธ US region +os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # ๐Ÿ‡ช๐Ÿ‡บ EU ๋ฆฌ์ „ +# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # ๐Ÿ‡บ๐Ÿ‡ธ US ๋ฆฌ์ „ ``` -Then, we configure the [Langfuse `callback_handler`](https://langfuse.com/docs/integrations/langchain/tracing#add-langfuse-to-your-langchain-application) and instrument the agent by adding the `langfuse_callback` to the invocation of the graph: `config={"callbacks": [langfuse_handler]}`. +[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 -# Initialize Langfuse CallbackHandler for LangGraph/Langchain (tracing) +# LangGraph/Langchain์šฉ Langfuse CallbackHandler ์ดˆ๊ธฐํ™”(์ถ”์ ์šฉ) langfuse_handler = CallbackHandler() -# Process legitimate email +# ์ •์ƒ ๋ฉ”์ผ ์ฒ˜๋ฆฌ 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]} ) ``` -Alfred is now connected ๐Ÿ”Œ! The runs from LangGraph are being logged in Langfuse, giving him full visibility into the agent's behavior. With this setup, he's ready to revisit previous runs and refine his Mail Sorting Agent even further. +์ด์ œ ์•Œํ”„๋ ˆ๋“œ๋Š” LangGraph์˜ ์‹คํ–‰ ๋‚ด์—ญ์„ Langfuse์— ๊ธฐ๋กํ•˜์—ฌ ์—์ด์ „ํŠธ์˜ ๋™์ž‘์„ ์™„์ „ํžˆ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ์จ ์ด์ „ ์‹คํ–‰์„ ๋‹ค์‹œ ์‚ดํŽด๋ณด๊ณ  ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ๋ฅผ ๋”์šฑ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -![Example trace in Langfuse](https://langfuse.com/images/cookbook/huggingface-agent-course/langgraph-trace-legit.png) +![Langfuse ์˜ˆ์‹œ ํŠธ๋ ˆ์ด์Šค](https://langfuse.com/images/cookbook/huggingface-agent-course/langgraph-trace-legit.png) -_[Public link to the trace with the legit email](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)_ +_[์ •์ƒ ๋ฉ”์ผ ํŠธ๋ ˆ์ด์Šค ๊ณต๊ฐœ ๋งํฌ](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 allows us to visualize our workflow to better understand and debug its structure: +LangGraph๋Š” ์›Œํฌํ”Œ๋กœ์šฐ ๊ตฌ์กฐ๋ฅผ ์‹œ๊ฐํ™”ํ•˜์—ฌ ์ดํ•ด์™€ ๋””๋ฒ„๊น…์„ ๋•์Šต๋‹ˆ๋‹ค: ```python compiled_graph.get_graph().draw_mermaid_png() ``` Mail LangGraph -This produces a visual representation showing how our nodes are connected and the conditional paths that can be taken. +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋…ธ๋“œ ๊ฐ„ ์—ฐ๊ฒฐ๊ณผ ์กฐ๊ฑด๋ถ€ ๊ฒฝ๋กœ๋ฅผ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## What We've Built +## ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ๊ฒƒ -We've created a complete email processing workflow that: +์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค: -1. Takes an incoming email -2. Uses an LLM to classify it as spam or legitimate -3. Handles spam by discarding it -4. For legitimate emails, drafts a response and notifies Mr. Hugg +1. ๋“ค์–ด์˜จ ์ด๋ฉ”์ผ์„ ๋ฐ›์Œ +2. LLM์œผ๋กœ ์ŠคํŒธ/์ •์ƒ ๋ถ„๋ฅ˜ +3. ์ŠคํŒธ์€ ํ๊ธฐ +4. ์ •์ƒ ๋ฉ”์ผ์€ ๋‹ต์žฅ ์ž‘์„ฑ ํ›„ Mr. Hugg์—๊ฒŒ ์ „๋‹ฌ -This demonstrates the power of LangGraph to orchestrate complex workflows with LLMs while maintaining a clear, structured flow. +์ด์ฒ˜๋Ÿผ LangGraph๋ฅผ ํ™œ์šฉํ•˜๋ฉด LLM ๊ธฐ๋ฐ˜์˜ ๋ณต์žกํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋„ ๋ช…ํ™•ํ•˜๊ณ  ๊ตฌ์กฐ์ ์œผ๋กœ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## Key Takeaways +## ํ•ต์‹ฌ ์š”์•ฝ -- **State Management**: We defined comprehensive state to track all aspects of email processing -- **Node Implementation**: We created functional nodes that interact with an LLM -- **Conditional Routing**: We implemented branching logic based on email classification -- **Terminal States**: We used the END node to mark completion points in our workflow +- **์ƒํƒœ ๊ด€๋ฆฌ**: ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ์˜ ๋ชจ๋“  ์ธก๋ฉด์„ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒํƒœ๋ฅผ ์ •์˜ +- **๋…ธ๋“œ ๊ตฌํ˜„**: LLM๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์  ๋…ธ๋“œ ๊ตฌํ˜„ +- **์กฐ๊ฑด๋ถ€ ๋ถ„๊ธฐ**: ์ด๋ฉ”์ผ ๋ถ„๋ฅ˜ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋ถ„๊ธฐ ๋กœ์ง ๊ตฌํ˜„ +- **์ข…๋ฃŒ ์ƒํƒœ**: END ๋…ธ๋“œ๋กœ ์›Œํฌํ”Œ๋กœ์šฐ ์ข…๋ฃŒ ์ง€์  ํ‘œ์‹œ -## What's Next? +## ๋‹ค์Œ ๋‹จ๊ณ„ -In the next section, we'll explore more advanced features of LangGraph, including handling human interaction in the workflow and implementing more complex branching logic based on multiple conditions. +๋‹ค์Œ ์„น์…˜์—์„œ๋Š” LangGraph์˜ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ(์‚ฌ๋žŒ๊ณผ์˜ ์ƒํ˜ธ์ž‘์šฉ, ๋‹ค์ค‘ ์กฐ๊ฑด ๋ถ„๊ธฐ ๋“ฑ)์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. diff --git a/units/ko/unit2/langgraph/introduction.mdx b/units/ko/unit2/langgraph/introduction.mdx index e6321312..706275ba 100644 --- a/units/ko/unit2/langgraph/introduction.mdx +++ b/units/ko/unit2/langgraph/introduction.mdx @@ -1,32 +1,32 @@ -# Introduction to `LangGraph` +# `LangGraph` ์†Œ๊ฐœ Unit 2.3 Thumbnail -Welcome to this next part of our journey, where you'll learn **how to build applications** using the [`LangGraph`](https://github.com/langchain-ai/langgraph) framework designed to help you structure and orchestrate complex LLM workflows. +์—ฌ์ •์˜ ๋‹ค์Œ ๋‹จ๊ณ„์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ์ด ๋‹จ์›์—์„œ๋Š” ๋ณต์žกํ•œ LLM ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๊ณ  ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ [`LangGraph`](https://github.com/langchain-ai/langgraph) ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•**์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. -`LangGraph` is a framework that allows you to build **production-ready** applications by giving you **control** tools over the flow of your agent. +`LangGraph`๋Š” ์—์ด์ „ํŠธ์˜ ํ๋ฆ„์„ **์ง์ ‘ ์ œ์–ด**ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•˜์—ฌ **ํ”„๋กœ๋•์…˜ ์ˆ˜์ค€**์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. -## Module Overview +## ๋ชจ๋“ˆ ๊ฐœ์š” -In this unit, you'll discover: +์ด ๋‹จ์›์—์„œ ์—ฌ๋Ÿฌ๋ถ„์€ ๋‹ค์Œ์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: -### 1๏ธโƒฃ [What is LangGraph, and when to use it?](./when_to_use_langgraph) -### 2๏ธโƒฃ [Building Blocks of LangGraph](./building_blocks) -### 3๏ธโƒฃ [Alfred, the mail sorting butler](./first_graph) -### 4๏ธโƒฃ [Alfred, the document Analyst agent](./document_analysis_agent) -### 5๏ธโƒฃ [Quiz](./quizz1) +### 1๏ธโƒฃ [LangGraph๋ž€ ๋ฌด์—‡์ด๋ฉฐ, ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?](./when_to_use_langgraph) +### 2๏ธโƒฃ [LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ](./building_blocks) +### 3๏ธโƒฃ [๋ฉ”์ผ ๋ถ„๋ฅ˜ํ•˜๋Š” ์ง‘์‚ฌ ์•Œํ”„๋ ˆ๋“œ](./first_graph) +### 4๏ธโƒฃ [์•Œํ”„๋ ˆ๋“œ, ๋ฌธ์„œ ๋ถ„์„ ์—์ด์ „ํŠธ](./document_analysis_agent) +### 5๏ธโƒฃ [ํ€ด์ฆˆ](./quizz1) -The examples in this section require access to a powerful LLM/VLM model. We ran them using the GPT-4o API because it has the best compatibility with langGraph. +์ด ์„น์…˜์˜ ์˜ˆ์ œ๋“ค์€ ๊ฐ•๋ ฅํ•œ LLM/VLM ๋ชจ๋ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ €ํฌ๋Š” langGraph์™€ ๊ฐ€์žฅ ํ˜ธํ™˜์„ฑ์ด ์ข‹์€ GPT-4o API๋ฅผ ์‚ฌ์šฉํ•ด ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. -By the end of this unit, you'll be equipped to build robust, organized and production ready applications ! +์ด ๋‹จ์›์ด ๋๋‚˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ฒฌ๊ณ ํ•˜๊ณ  ์ฒด๊ณ„์ ์ด๋ฉฐ ํ”„๋กœ๋•์…˜์— ๋ฐ”๋กœ ํˆฌ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค! -That being said, this section is an introduction to LangGraph and more advanced topics can be discovered in the free LangChain academy course : [Introduction to LangGraph](https://academy.langchain.com/courses/intro-to-langgraph) +์ด ์„น์…˜์€ LangGraph์˜ ์ž…๋ฌธ ๊ณผ์ •์ด๋ฉฐ, ๋” ์‹ฌํ™”๋œ ์ฃผ์ œ๋Š” ๋ฌด๋ฃŒ LangChain ์•„์นด๋ฐ๋ฏธ ๊ฐ•์˜ [LangGraph ์†Œ๊ฐœ](https://academy.langchain.com/courses/intro-to-langgraph)์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Let's get started! +๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”? -## Resources +## ์ฐธ๊ณ  ์ž๋ฃŒ -- [LangGraph Agents](https://langchain-ai.github.io/langgraph/) - Examples of LangGraph agent -- [LangChain academy](https://academy.langchain.com/courses/intro-to-langgraph) - Full course on LangGraph from LangChain +- [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 index a29932df..a28d3505 100644 --- a/units/ko/unit2/langgraph/quiz1.mdx +++ b/units/ko/unit2/langgraph/quiz1.mdx @@ -1,44 +1,44 @@ -# Test Your Understanding of LangGraph +# LangGraph ์ดํ•ด๋„ ํ…Œ์ŠคํŠธ -Let's test your understanding of `LangGraph` with a quick quiz! This will help reinforce the key concepts we've covered so far. +`LangGraph`์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ๊ฐ„๋‹จํ•œ ํ€ด์ฆˆ๋กœ ํ…Œ์ŠคํŠธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! ์ง€๊ธˆ๊นŒ์ง€ ๋‹ค๋ฃฌ ํ•ต์‹ฌ ๊ฐœ๋…๋“ค์„ ๊ฐ•ํ™”ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. -This is an optional quiz and it's not graded. +์ด ํ€ด์ฆˆ๋Š” ์„ ํƒ์‚ฌํ•ญ์ด๋ฉฐ ์ ์ˆ˜๋Š” ๋งค๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -### Q1: What is the primary purpose of LangGraph? -Which statement best describes what LangGraph is designed for? +### Q1: LangGraph์˜ ์ฃผ์š” ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? +LangGraph๊ฐ€ ๋ฌด์—‡์„ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ๋Š”์ง€ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์€? --- -### Q2: In the context of the "Control vs Freedom" trade-off, where does LangGraph stand? -Which statement best characterizes LangGraph's approach to agent design? +### Q2: "์ œ์–ด vs ์ž์œ " ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ๋งฅ๋ฝ์—์„œ LangGraph๋Š” ์–ด๋””์— ์œ„์น˜ํ•˜๋‚˜์š”? +์—์ด์ „ํŠธ ์„ค๊ณ„์— ๋Œ€ํ•œ LangGraph์˜ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ฐ€์žฅ ์ž˜ ํŠน์ง•์ง“๋Š” ๋ฌธ์žฅ์€? -### Q4: What is a Conditional Edge in LangGraph? -Select the most accurate description. +### Q4: LangGraph์—์„œ ์กฐ๊ฑด๋ถ€ ์—ฃ์ง€(Conditional Edge)๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? +๊ฐ€์žฅ ์ •ํ™•ํ•œ ์„ค๋ช…์„ ์„ ํƒํ•˜์„ธ์š”. --- -### Q5: How does LangGraph help address the hallucination problem in LLMs? -Choose the best answer. +### Q5: LangGraph๋Š” LLM์˜ ํ™˜๊ฐ(hallucination) ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋‚˜์š”? +์ตœ์„ ์˜ ๋‹ต์„ ์„ ํƒํ•˜์„ธ์š”. -Congratulations on completing the quiz! ๐ŸŽ‰ If you missed any questions, consider reviewing the previous sections to strengthen your understanding. Next, we'll explore more advanced features of LangGraph and see how to build more complex agent workflows. +ํ€ด์ฆˆ ์™„๋ฃŒ๋ฅผ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ ์งˆ๋ฌธ์„ ๋†“์ณค๋‹ค๋ฉด, ์ดํ•ด๋ฅผ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ด์ „ ์„น์…˜๋“ค์„ ๋‹ค์‹œ ๊ฒ€ํ† ํ•ด๋ณด์„ธ์š”. ๋‹ค์Œ์—๋Š” LangGraph์˜ ๋” ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ์„ ํƒ๊ตฌํ•˜๊ณ  ๋” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. diff --git a/units/ko/unit2/langgraph/when_to_use_langgraph.mdx b/units/ko/unit2/langgraph/when_to_use_langgraph.mdx index 28e1d850..70f419d5 100644 --- a/units/ko/unit2/langgraph/when_to_use_langgraph.mdx +++ b/units/ko/unit2/langgraph/when_to_use_langgraph.mdx @@ -1,68 +1,68 @@ -# What is `LangGraph`? +# `LangGraph`๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? -`LangGraph` is a framework developed by [LangChain](https://www.langchain.com/) **to manage the control flow of applications that integrate an LLM**. +`LangGraph`๋Š” [LangChain](https://www.langchain.com/)์—์„œ ๊ฐœ๋ฐœํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, **LLM์„ ํ†ตํ•ฉํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ œ์–ด ํ๋ฆ„์„ ๊ด€๋ฆฌ**ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. -## Is `LangGraph` different from `LangChain`? +## `LangGraph`๋Š” `LangChain`๊ณผ ๋‹ค๋ฅธ๊ฐ€์š”? -LangChain provides a standard interface to interact with models and other components, useful for retrieval, LLM calls and tools calls. -The classes from LangChain might be used in LangGraph, but do not HAVE to be used. +LangChain์€ ๋ชจ๋ธ ๋ฐ ๊ธฐํƒ€ ๊ตฌ์„ฑ ์š”์†Œ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ๊ฒ€์ƒ‰, LLM ํ˜ธ์ถœ, ํˆด ํ˜ธ์ถœ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. +LangChain์˜ ํด๋ž˜์Šค๋“ค์€ LangGraph์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. -The packages are different and can be used in isolation, but, in the end, all resources you will find online use both packages hand in hand. +๋‘ ํŒจํ‚ค์ง€๋Š” ๋‹ค๋ฅด๋ฉฐ ๋…๋ฆฝ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ฒฐ๊ตญ ์˜จ๋ผ์ธ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋Š” ๋‘ ํŒจํ‚ค์ง€๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -## When should I use `LangGraph`? -### Control vs freedom +## ์–ธ์ œ `LangGraph`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ์š”? +### ์ œ์–ด vs ์ž์œ  -When designing AI applications, you face a fundamental trade-off between **control** and **freedom**: +AI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค๊ณ„ํ•  ๋•Œ, **์ œ์–ด**์™€ **์ž์œ ** ์‚ฌ์ด์˜ ๊ทผ๋ณธ์ ์ธ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„์— ์ง๋ฉดํ•ฉ๋‹ˆ๋‹ค: -- **Freedom** gives your LLM more room to be creative and tackle unexpected problems. -- **Control** allows you to ensure predictable behavior and maintain guardrails. +- **์ž์œ **๋Š” LLM์—๊ฒŒ ๋” ๋งŽ์€ ์ฐฝ์˜์„ฑ๊ณผ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ์œ„ํ•œ ์—ฌ์ง€๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +- **์ œ์–ด**๋Š” ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋™์ž‘์„ ๋ณด์žฅํ•˜๊ณ  ๊ฐ€๋“œ๋ ˆ์ผ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. -Code Agents, like the ones you can encounter in *smolagents*, are very free. They can call multiple tools in a single action step, create their own tools, etc. However, this behavior can make them less predictable and less controllable than a regular Agent working with JSON! +*smolagents*์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ ์—์ด์ „ํŠธ๋“ค์€ ๋งค์šฐ ์ž์œ ๋กญ์Šต๋‹ˆ๋‹ค. ๋‹จ์ผ ์•ก์…˜ ๋‹จ๊ณ„์—์„œ ์—ฌ๋Ÿฌ ํˆด์„ ํ˜ธ์ถœํ•˜๊ณ , ์ž์‹ ๋งŒ์˜ ํˆด์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋™์ž‘์€ JSON์œผ๋กœ ์ž‘์—…ํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ์—์ด์ „ํŠธ๋ณด๋‹ค ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ต๊ณ  ์ œ์–ดํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค! -`LangGraph` is on the other end of the spectrum, it shines when you need **"Control"** on the execution of your agent. +`LangGraph`๋Š” ์ŠคํŽ™ํŠธ๋Ÿผ์˜ ๋ฐ˜๋Œ€ํŽธ์— ์žˆ์œผ๋ฉฐ, ์—์ด์ „ํŠธ ์‹คํ–‰์— **"์ œ์–ด"**๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋น›๋‚ฉ๋‹ˆ๋‹ค. -LangGraph is particularly valuable when you need **Control over your applications**. It gives you the tools to build an application that follows a predictable process while still leveraging the power of LLMs. +LangGraph๋Š” ํŠนํžˆ **์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ์ œ์–ด**๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋”ฐ๋ฅด๋ฉด์„œ๋„ LLM์˜ ํž˜์„ ํ™œ์šฉํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -Put simply, if your application involves a series of steps that need to be orchestrated in a specific way, with decisions being made at each junction point, **LangGraph provides the structure you need**. +๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํŠน์ • ๋ฐฉ์‹์œผ๋กœ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜๋˜์–ด์•ผ ํ•˜๋Š” ์ผ๋ จ์˜ ๋‹จ๊ณ„๋ฅผ ํฌํ•จํ•˜๊ณ , ๊ฐ ๋ถ„๊ธฐ์ ์—์„œ ๊ฒฐ์ •์ด ๋‚ด๋ ค์ ธ์•ผ ํ•œ๋‹ค๋ฉด, **LangGraph๊ฐ€ ํ•„์š”ํ•œ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค**. -As an example, let's say we want to build an LLM assistant that can answer some questions over some documents. +์˜ˆ๋ฅผ ๋“ค์–ด, ์ผ๋ถ€ ๋ฌธ์„œ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์— ๋‹ตํ•  ์ˆ˜ ์žˆ๋Š” LLM ์–ด์‹œ์Šคํ„ดํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. -Since LLMs understand text the best, before being able to answer the question, you will need to convert other complex modalities (charts, tables) into text. However, that choice depends on the type of document you have! +LLM์ด ํ…์ŠคํŠธ๋ฅผ ๊ฐ€์žฅ ์ž˜ ์ดํ•ดํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์ „์— ๋‹ค๋ฅธ ๋ณต์žกํ•œ ๋ชจ๋‹ฌ๋ฆฌํ‹ฐ(์ฐจํŠธ, ํ‘œ)๋ฅผ ํ…์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์„ ํƒ์€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฌธ์„œ์˜ ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค! -This is a branching that I chose to represent as follow : +์ด๊ฒƒ์€ ์ œ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„ํ•˜๊ธฐ๋กœ ์„ ํƒํ•œ ๋ถ„๊ธฐ์ž…๋‹ˆ๋‹ค: Control flow -> ๐Ÿ’ก **Tip:** The left part is not an agent, as here no tool call is involved. but the right part will need to write some code to query the xls ( convert to pandas and manipulate it ). +> ๐Ÿ’ก **ํŒ:** ์™ผ์ชฝ ๋ถ€๋ถ„์€ ์—์ด์ „ํŠธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ํˆด ํ˜ธ์ถœ์ด ํฌํ•จ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์€ xls๋ฅผ ์ฟผ๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(pandas๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์กฐ์ž‘). -While this branching is deterministic, you can also design branching that are conditioned on the output of an LLM making them undeterministic. +์ด ๋ถ„๊ธฐ๋Š” ๊ฒฐ์ •์ ์ด์ง€๋งŒ, LLM ์ถœ๋ ฅ์— ๋”ฐ๋ผ ์กฐ๊ฑด์ด ์ •ํ•ด์ง€๋Š” ๋น„๊ฒฐ์ •์  ๋ถ„๊ธฐ๋„ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -The key scenarios where LangGraph excels include: +LangGraph๊ฐ€ ๋›ฐ์–ด๋‚œ ์ฃผ์š” ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: -- **Multi-step reasoning processes** that need explicit control on the flow -- **Applications requiring persistence of state** between steps -- **Systems that combine deterministic logic with AI capabilities** -- **Workflows that need human-in-the-loop interventions** -- **Complex agent architectures** with multiple components working together +- **๋ช…์‹œ์ ์ธ ํ๋ฆ„ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•œ ๋‹ค๋‹จ๊ณ„ ์ถ”๋ก  ํ”„๋กœ์„ธ์Šค** +- **๋‹จ๊ณ„ ๊ฐ„ ์ƒํƒœ ์ง€์†์ด ํ•„์š”ํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜** +- **๊ฒฐ์ •์  ๋กœ์ง๊ณผ AI ๊ธฐ๋Šฅ์„ ๊ฒฐํ•ฉํ•˜๋Š” ์‹œ์Šคํ…œ** +- **์‚ฌ๋žŒ ๊ฐœ์ž…์ด ํ•„์š”ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ** +- **์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์•„ํ‚คํ…์ฒ˜** -In essence, whenever possible, **as a human**, design a flow of actions based on the output of each action, and decide what to execute next accordingly. In this case, LangGraph is the correct framework for you! +๋ณธ์งˆ์ ์œผ๋กœ, ๊ฐ€๋Šฅํ•  ๋•Œ๋งˆ๋‹ค **์‚ฌ๋žŒ์œผ๋กœ์„œ** ๊ฐ ์•ก์…˜์˜ ์ถœ๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์•ก์…˜ ํ๋ฆ„์„ ์„ค๊ณ„ํ•˜๊ณ , ๊ทธ์— ๋”ฐ๋ผ ๋‹ค์Œ์— ์‹คํ–‰ํ•  ๊ฒƒ์„ ๊ฒฐ์ •ํ•˜์„ธ์š”. ์ด ๊ฒฝ์šฐ LangGraph๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค! -`LangGraph` is, in my opinion, the most production-ready agent framework on the market. +`LangGraph`๋Š” ์ œ ์ƒ๊ฐ์— ์‹œ์žฅ์—์„œ ๊ฐ€์žฅ ํ”„๋กœ๋•์…˜ ์ค€๋น„๊ฐ€ ์ž˜ ๋œ ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. -## How does LangGraph work? +## LangGraph๋Š” ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”? -At its core, `LangGraph` uses a directed graph structure to define the flow of your application: +ํ•ต์‹ฌ์ ์œผ๋กœ `LangGraph`๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ๋ฆ„์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: -- **Nodes** represent individual processing steps (like calling an LLM, using a tool, or making a decision). -- **Edges** define the possible transitions between steps. -- **State** is user defined and maintained and passed between nodes during execution. When deciding which node to target next, this is the current state that we look at. +- **๋…ธ๋“œ**๋Š” ๊ฐœ๋ณ„ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค(LLM ํ˜ธ์ถœ, ํˆด ์‚ฌ์šฉ, ๊ฒฐ์ • ๋‚ด๋ฆฌ๊ธฐ ๋“ฑ). +- **์—ฃ์ง€**๋Š” ๋‹จ๊ณ„ ๊ฐ„ ๊ฐ€๋Šฅํ•œ ์ „ํ™˜์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. +- **์ƒํƒœ**๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•˜๊ณ  ์œ ์ง€ํ•˜๋ฉฐ ์‹คํ–‰ ์ค‘ ๋…ธ๋“œ ๊ฐ„์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์— ์–ด๋–ค ๋…ธ๋“œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ• ์ง€ ๊ฒฐ์ •ํ•  ๋•Œ, ์šฐ๋ฆฌ๊ฐ€ ์‚ดํŽด๋ณด๋Š” ๊ฒƒ์€ ํ˜„์žฌ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. -We will explore those fundamental blocks more in the next chapter! +์ด๋Ÿฌํ•œ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ๋“ค์„ ๋‹ค์Œ ์žฅ์—์„œ ๋” ์ž์„ธํžˆ ํƒ๊ตฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! -## How is it different from regular python? Why do I need LangGraph? +## ์ผ๋ฐ˜ ํŒŒ์ด์ฌ๊ณผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”? ์™œ LangGraph๊ฐ€ ํ•„์š”ํ•œ๊ฐ€์š”? -You might wonder: "I could just write regular Python code with if-else statements to handle all these flows, right?" +"์ด ๋ชจ๋“  ํ๋ฆ„์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด if-else ๋ฌธ์ด ์žˆ๋Š” ์ผ๋ฐ˜ ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์ง€ ์•Š๋‚˜์š”?"๋ผ๊ณ  ๊ถ๊ธˆํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -While technically true, LangGraph offers **some advantages** over vanilla Python for building complex systems. You could build the same application without LangGraph, but it builds easier tools and abstractions for you. +๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ๋งž์ง€๋งŒ, LangGraph๋Š” ๋ณต์žกํ•œ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์„ ์œ„ํ•ด ์ผ๋ฐ˜ ํŒŒ์ด์ฌ๋ณด๋‹ค **์ผ๋ถ€ ์žฅ์ **์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. LangGraph ์—†์ด๋„ ๊ฐ™์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋” ์‰ฌ์šด ๋„๊ตฌ์™€ ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -It includes states, visualization, logging (traces), built-in human-in-the-loop, and more. +์ƒํƒœ, ์‹œ๊ฐํ™”, ๋กœ๊น…(ํŠธ๋ ˆ์ด์Šค), ๋‚ด์žฅ๋œ ์‚ฌ๋žŒ ๊ฐœ์ž… ๋“ฑ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. From cc9f4fed6558a6c7341c46a883e8933d2de5a8d2 Mon Sep 17 00:00:00 2001 From: Jeong Ahn Date: Thu, 10 Jul 2025 16:03:04 +0900 Subject: [PATCH 4/6] feat: nmt draft: llamaIndex --- units/ko/unit2/llama-index/README.md | 24 +-- units/ko/unit2/llama-index/agents.mdx | 118 ++++++------ units/ko/unit2/llama-index/components.mdx | 190 ++++++++++---------- units/ko/unit2/llama-index/conclusion.mdx | 16 +- units/ko/unit2/llama-index/introduction.mdx | 37 ++-- units/ko/unit2/llama-index/llama-hub.mdx | 34 ++-- units/ko/unit2/llama-index/quiz1.mdx | 92 +++++----- units/ko/unit2/llama-index/quiz2.mdx | 64 +++---- units/ko/unit2/llama-index/tools.mdx | 98 +++++----- units/ko/unit2/llama-index/workflows.mdx | 186 +++++++++---------- 10 files changed, 428 insertions(+), 431 deletions(-) diff --git a/units/ko/unit2/llama-index/README.md b/units/ko/unit2/llama-index/README.md index 56bb0b38..b28ffd70 100644 --- a/units/ko/unit2/llama-index/README.md +++ b/units/ko/unit2/llama-index/README.md @@ -1,15 +1,15 @@ -# Table of Contents +# ๋ชฉ์ฐจ -This LlamaIndex frame outline is part of unit 2 of the course. You can access the unit 2 about LlamaIndex on hf.co/learn ๐Ÿ‘‰ here +์ด LlamaIndex ํ”„๋ ˆ์ž„ ๊ฐœ์š”๋Š” ๊ฐ•์˜ 2๋‹จ์›์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. hf.co/learn์—์„œ LlamaIndex์— ๋Œ€ํ•œ 2๋‹จ์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ‘‰ ์—ฌ๊ธฐ -| Title | Description | +| ์ œ๋ชฉ | ์„ค๋ช… | | --- | --- | -| [Introduction](introduction.mdx) | Introduction to LlamaIndex | -| [LlamaHub](llama-hub.mdx) | LlamaHub: a registry of integrations, agents and tools | -| [Components](components.mdx) | Components: the building blocks of workflows | -| [Tools](tools.mdx) | Tools: how to build tools in LlamaIndex | -| [Quiz 1](quiz1.mdx) | Quiz 1 | -| [Agents](agents.mdx) | Agents: how to build agents in LlamaIndex | -| [Workflows](workflows.mdx) | Workflows: a sequence of steps, events made of components that are executed in order | -| [Quiz 2](quiz2.mdx) | Quiz 2 | -| [Conclusion](conclusion.mdx) | Conclusion | +| [์†Œ๊ฐœ](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 index 78f794a4..40e54a00 100644 --- a/units/ko/unit2/llama-index/agents.mdx +++ b/units/ko/unit2/llama-index/agents.mdx @@ -1,91 +1,91 @@ -# Using Agents in LlamaIndex +# LlamaIndex์—์„œ ์—์ด์ „ํŠธ ์‚ฌ์šฉํ•˜๊ธฐ -Remember Alfred, our helpful butler agent from earlier? Well, he's about to get an upgrade! -Now that we understand the tools available in LlamaIndex, we can give Alfred new capabilities to serve us better. +์ด์ „์— ๋‚˜์™”๋˜ ๋„์›€์ด ๋˜๋Š” ์ง‘์‚ฌ ์—์ด์ „ํŠธ ์•Œํ”„๋ ˆ๋“œ๋ฅผ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ์ด์ œ ๊ทธ๊ฐ€ ์—…๊ทธ๋ ˆ์ด๋“œ๋ฅผ ๋ฐ›์„ ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค! +์ด์ œ LlamaIndex์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํˆด๋“ค์„ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์•Œํ”„๋ ˆ๋“œ์—๊ฒŒ ๋” ๋‚˜์€ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ๋“ค์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -But before we continue, let's remind ourselves what makes an agent like Alfred tick. -Back in Unit 1, we learned that: +ํ•˜์ง€๋งŒ ๊ณ„์†ํ•˜๊ธฐ ์ „์—, ์•Œํ”„๋ ˆ๋“œ ๊ฐ™์€ ์—์ด์ „ํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋‹ค์‹œ ํ•œ๋ฒˆ ์ƒ๊ธฐํ•ด๋ด…์‹œ๋‹ค. +1๋‹จ์›์—์„œ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค: -> An Agent is a system that leverages an AI model to interact with its environment to achieve a user-defined objective. It combines reasoning, planning, and action execution (often via external tools) to fulfil tasks. +> ์—์ด์ „ํŠธ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•œ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด AI ๋ชจ๋ธ์„ ํ™œ์šฉํ•˜์—ฌ ํ™˜๊ฒฝ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๋ก , ๊ณ„ํš, ์•ก์…˜ ์‹คํ–‰(์ข…์ข… ์™ธ๋ถ€ ํˆด์„ ํ†ตํ•ด)์„ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. -LlamaIndex supports **three main types of reasoning agents:** +LlamaIndex๋Š” **์„ธ ๊ฐ€์ง€ ์ฃผ์š” ์œ ํ˜•์˜ ์ถ”๋ก  ์—์ด์ „ํŠธ**๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: -![Agents](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/agents.png) +![์—์ด์ „ํŠธ](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/agents.png) -1. `Function Calling Agents` - These work with AI models that can call specific functions. -2. `ReAct Agents` - These can work with any AI that does chat or text endpoint and deal with complex reasoning tasks. -3. `Advanced Custom Agents` - These use more complex methods to deal with more complex tasks and workflows. +1. `Function Calling Agents` - ํŠน์ • ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” AI ๋ชจ๋ธ๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. +2. `ReAct Agents` - ์ฑ„ํŒ…์ด๋‚˜ ํ…์ŠคํŠธ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ชจ๋“  AI์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ณต์žกํ•œ ์ถ”๋ก  ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. +3. `Advanced Custom Agents` - ๋” ๋ณต์žกํ•œ ์ž‘์—…๊ณผ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋” ๋ณต์žกํ•œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -Find more information on advanced agents on BaseWorkflowAgent +๊ณ ๊ธ‰ ์—์ด์ „ํŠธ์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ •๋ณด๋Š” BaseWorkflowAgent์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## Initialising Agents +## ์—์ด์ „ํŠธ ์ดˆ๊ธฐํ™” -You can follow the code in this notebook that you can run using Google Colab. +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -To create an agent, we start by providing it with a **set of functions/tools that define its capabilities**. -Let's look at how to create an agent with some basic tools. As of this writing, the agent will automatically use the function calling API (if available), or a standard ReAct agent loop. +์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด, ๋จผ์ € **๊ธฐ๋Šฅ์„ ์ •์˜ํ•˜๋Š” ํ•จ์ˆ˜/ํˆด ์„ธํŠธ**๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ํˆด๋กœ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ๋กœ์„œ๋Š” ์—์ด์ „ํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ํ•จ์ˆ˜ ํ˜ธ์ถœ API(์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ) ๋˜๋Š” ํ‘œ์ค€ ReAct ์—์ด์ „ํŠธ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -LLMs that support a tools/functions API are relatively new, but they provide a powerful way to call tools by avoiding specific prompting and allowing the LLM to create tool calls based on provided schemas. +ํˆด/ํ•จ์ˆ˜ API๋ฅผ ์ง€์›ํ•˜๋Š” LLM๋“ค์€ ๋น„๊ต์  ์ตœ์‹ ์ด์ง€๋งŒ, ํŠน์ • ํ”„๋กฌํ”„ํŒ…์„ ํ”ผํ•˜๊ณ  ์ œ๊ณต๋œ ์Šคํ‚ค๋งˆ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ LLM์ด ํˆด ํ˜ธ์ถœ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์—ฌ ํˆด์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -ReAct agents are also good at complex reasoning tasks and can work with any LLM that has chat or text completion capabilities. They are more verbose, and show the reasoning behind certain actions that they take. +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 -# define sample Tool -- type annotations, function names, and docstrings, are all included in parsed schemas! +# ์ƒ˜ํ”Œ ํˆด ์ •์˜ -- ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜, ํ•จ์ˆ˜ ์ด๋ฆ„, ๋…์ŠคํŠธ๋ง์ด ๋ชจ๋‘ ํŒŒ์‹ฑ๋œ ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค! def multiply(a: int, b: int) -> int: - """Multiplies two integers and returns the resulting integer""" + """๋‘ ์ •์ˆ˜๋ฅผ ๊ณฑํ•˜๊ณ  ๊ฒฐ๊ณผ ์ •์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค""" return a * b -# initialize llm +# llm ์ดˆ๊ธฐํ™” llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") -# initialize agent +# ์—์ด์ „ํŠธ ์ดˆ๊ธฐํ™” agent = AgentWorkflow.from_tools_or_functions( [FunctionTool.from_defaults(multiply)], llm=llm ) ``` -**Agents are stateless by default**, add remembering past interactions is opt-in using a `Context` object -This might be useful if you want to use an agent that needs to remember previous interactions, like a chatbot that maintains context across multiple messages or a task manager that needs to track progress over time. +**์—์ด์ „ํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ๊ฐ€ ์—†์œผ๋ฉฐ**, ๊ณผ๊ฑฐ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ธฐ์–ตํ•˜๋Š” ๊ฒƒ์€ `Context` ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ํƒ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. +์ด๋Š” ์—ฌ๋Ÿฌ ๋ฉ”์‹œ์ง€์— ๊ฑธ์ณ ๋งฅ๋ฝ์„ ์œ ์ง€ํ•˜๋Š” ์ฑ—๋ด‡์ด๋‚˜ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ง„ํ–‰ ์ƒํ™ฉ์„ ์ถ”์ ํ•ด์•ผ ํ•˜๋Š” ์ž‘์—… ๊ด€๋ฆฌ์ž์ฒ˜๋Ÿผ ์ด์ „ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ธฐ์–ตํ•ด์•ผ ํ•˜๋Š” ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python -# stateless -response = await agent.run("What is 2 times 2?") +# ์ƒํƒœ ์—†์Œ +response = await agent.run("2 ๊ณฑํ•˜๊ธฐ 2๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?") -# remembering state +# ์ƒํƒœ ๊ธฐ์–ต from llama_index.core.workflow import Context ctx = Context(agent) -response = await agent.run("My name is Bob.", ctx=ctx) -response = await agent.run("What was my name again?", ctx=ctx) +response = await agent.run("๋‚ด ์ด๋ฆ„์€ Bob์ž…๋‹ˆ๋‹ค.", ctx=ctx) +response = await agent.run("๋‚ด ์ด๋ฆ„์ด ๋ญ์˜€์ง€?", ctx=ctx) ``` -You'll notice that agents in `LlamaIndex` are async because they use Python's `await` operator. If you are new to async code in Python, or need a refresher, they have an [excellent async guide](https://docs.llamaindex.ai/en/stable/getting_started/async_python/). +`LlamaIndex`์˜ ์—์ด์ „ํŠธ๋“ค์ด Python์˜ `await` ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„๋™๊ธฐ๋ผ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Python์˜ ๋น„๋™๊ธฐ ์ฝ”๋“œ๊ฐ€ ์ฒ˜์Œ์ด๊ฑฐ๋‚˜ ๋ณต์Šต์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, [ํ›Œ๋ฅญํ•œ ๋น„๋™๊ธฐ ๊ฐ€์ด๋“œ](https://docs.llamaindex.ai/en/stable/getting_started/async_python/)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. -Now we've gotten the basics, let's take a look at how we can use more complex tools in our agents. +์ด์ œ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ์œผ๋‹ˆ, ์—์ด์ „ํŠธ์—์„œ ๋” ๋ณต์žกํ•œ ํˆด์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -## Creating RAG Agents with QueryEngineTools +## QueryEngineTools๋กœ RAG ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ -**Agentic RAG is a powerful way to use agents to answer questions about your data.** We can pass various tools to Alfred to help him answer questions. -However, instead of answering the question on top of documents automatically, Alfred can decide to use any other tool or flow to answer the question. +**์—์ด์ „ํŠธ RAG๋Š” ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์— ๋‹ตํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.** ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์งˆ๋ฌธ์— ๋‹ตํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋„๋ก ๋‹ค์–‘ํ•œ ํˆด์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๋ฌธ์„œ ์œ„์—์„œ ์ž๋™์œผ๋กœ ์งˆ๋ฌธ์— ๋‹ตํ•˜๋Š” ๋Œ€์‹ , ์•Œํ”„๋ ˆ๋“œ๋Š” ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ํˆด์ด๋‚˜ ํ๋ฆ„์„ ์‚ฌ์šฉํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -![Agentic RAG](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/agentic-rag.png) +![์—์ด์ „ํŠธ RAG](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/agentic-rag.png) -It is easy to **wrap `QueryEngine` as a tool** for an agent. -When doing so, we need to **define a name and description**. The LLM will use this information to correctly use the tool. -Let's see how to load in a `QueryEngineTool` using the `QueryEngine` we created in the [component section](components). +์—์ด์ „ํŠธ๋ฅผ ์œ„ํ•ด **`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) # as shown in the Components in LlamaIndex section +query_engine = index.as_query_engine(llm=llm, similarity_top_k=3) # LlamaIndex์˜ ๊ตฌ์„ฑ ์š”์†Œ ์„น์…˜์—์„œ ๋ณด์—ฌ์ง„ ๋Œ€๋กœ query_engine_tool = QueryEngineTool.from_defaults( query_engine=query_engine, @@ -100,13 +100,13 @@ query_engine_agent = AgentWorkflow.from_tools_or_functions( ) ``` -## Creating Multi-agent systems +## ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๋งŒ๋“ค๊ธฐ -The `AgentWorkflow` class also directly supports multi-agent systems. By giving each agent a name and description, the system maintains a single active speaker, with each agent having the ability to hand off to another agent. +`AgentWorkflow` ํด๋ž˜์Šค๋Š” ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ๋„ ์ง์ ‘ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์—์ด์ „ํŠธ์— ์ด๋ฆ„๊ณผ ์„ค๋ช…์„ ๋ถ€์—ฌํ•จ์œผ๋กœ์จ, ์‹œ์Šคํ…œ์€ ๋‹จ์ผ ํ™œ์„ฑ ๋ฐœํ™”์ž๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ, ๊ฐ ์—์ด์ „ํŠธ๋Š” ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์—๊ฒŒ ์ž‘์—…์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. -By narrowing the scope of each agent, we can help increase their general accuracy when responding to user messages. +๊ฐ ์—์ด์ „ํŠธ์˜ ๋ฒ”์œ„๋ฅผ ์ขํž˜์œผ๋กœ์จ, ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€์— ์‘๋‹ตํ•  ๋•Œ ์ผ๋ฐ˜์ ์ธ ์ •ํ™•๋„๋ฅผ ๋†’์ด๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -**Agents in LlamaIndex can also directly be used as tools** for other agents, for more complex and custom scenarios. +**LlamaIndex์˜ ์—์ด์ „ํŠธ๋“ค์€ ๋” ๋ณต์žกํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ •์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์œ„ํ•ด ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์˜ ํˆด๋กœ๋„ ์ง์ ‘ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.** ```python from llama_index.core.agent.workflow import ( @@ -115,46 +115,46 @@ from llama_index.core.agent.workflow import ( ReActAgent, ) -# Define some tools +# ๋ช‡ ๊ฐ€์ง€ ํˆด ์ •์˜ def add(a: int, b: int) -> int: - """Add two numbers.""" + """๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•ฉ๋‹ˆ๋‹ค.""" return a + b def subtract(a: int, b: int) -> int: - """Subtract two numbers.""" + """๋‘ ์ˆซ์ž๋ฅผ ๋บ๋‹ˆ๋‹ค.""" return a - b -# Create agent configs -# NOTE: we can use FunctionAgent or ReActAgent here. -# FunctionAgent works for LLMs with a function calling API. -# ReActAgent works for any LLM. +# ์—์ด์ „ํŠธ ์„ค์ • ์ƒ์„ฑ +# ์ฐธ๊ณ : ์—ฌ๊ธฐ์„œ FunctionAgent ๋˜๋Š” ReActAgent๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +# FunctionAgent๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ API๊ฐ€ ์žˆ๋Š” LLM์šฉ์ž…๋‹ˆ๋‹ค. +# ReActAgent๋Š” ๋ชจ๋“  LLM์šฉ์ž…๋‹ˆ๋‹ค. calculator_agent = ReActAgent( name="calculator", - description="Performs basic arithmetic operations", - system_prompt="You are a calculator assistant. Use your tools for any math operation.", + description="๊ธฐ๋ณธ ์‚ฐ์ˆ  ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค", + system_prompt="๋‹น์‹ ์€ ๊ณ„์‚ฐ๊ธฐ ์–ด์‹œ์Šคํ„ดํŠธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์ˆ˜ํ•™ ์—ฐ์‚ฐ์— ํˆด์„ ์‚ฌ์šฉํ•˜์„ธ์š”.", tools=[add, subtract], llm=llm, ) query_agent = ReActAgent( name="info_lookup", - description="Looks up information about XYZ", - system_prompt="Use your tool to query a RAG system to answer information about XYZ", + description="XYZ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค", + system_prompt="XYZ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ตํ•˜๊ธฐ ์œ„ํ•ด RAG ์‹œ์Šคํ…œ์„ ์ฟผ๋ฆฌํ•˜๋Š” ํˆด์„ ์‚ฌ์šฉํ•˜์„ธ์š”", tools=[query_engine_tool], llm=llm ) -# Create and run the workflow +# ์›Œํฌํ”Œ๋กœ์šฐ ์ƒ์„ฑ ๋ฐ ์‹คํ–‰ agent = AgentWorkflow( agents=[calculator_agent, query_agent], root_agent="calculator" ) -# Run the system -response = await agent.run(user_msg="Can you add 5 and 3?") +# ์‹œ์Šคํ…œ ์‹คํ–‰ +response = await agent.run(user_msg="5์™€ 3์„ ๋”ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?") ``` -Haven't learned enough yet? There is a lot more to discover about agents and tools in LlamaIndex within the AgentWorkflow Basic Introduction or the Agent Learning Guide, where you can read more about streaming, context serialization, and human-in-the-loop! +์•„์ง ์ถฉ๋ถ„ํžˆ ๋ฐฐ์šฐ์ง€ ๋ชปํ–ˆ๋‚˜์š”? AgentWorkflow ๊ธฐ๋ณธ ์†Œ๊ฐœ ๋˜๋Š” ์—์ด์ „ํŠธ ํ•™์Šต ๊ฐ€์ด๋“œ์—์„œ LlamaIndex์˜ ์—์ด์ „ํŠธ์™€ ํˆด์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ๊ฒƒ์„ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ŠคํŠธ๋ฆฌ๋ฐ, ๋งฅ๋ฝ ์ง๋ ฌํ™”, ์‚ฌ๋žŒ ๊ฐœ์ž…์— ๋Œ€ํ•ด ๋” ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! -Now that we understand the basics of agents and tools in LlamaIndex, let's see how we can use LlamaIndex to **create configurable and manageable workflows!** +์ด์ œ LlamaIndex์—์„œ ์—์ด์ „ํŠธ์™€ ํˆด์˜ ๊ธฐ๋ณธ์„ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, LlamaIndex๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **๊ตฌ์„ฑ ๊ฐ€๋Šฅํ•˜๊ณ  ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š”** ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/llama-index/components.mdx b/units/ko/unit2/llama-index/components.mdx index f2c6e63a..1f7a4d83 100644 --- a/units/ko/unit2/llama-index/components.mdx +++ b/units/ko/unit2/llama-index/components.mdx @@ -1,60 +1,60 @@ -# What are components in LlamaIndex? +# LlamaIndex์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? -Remember Alfred, our helpful butler agent from Unit 1? -To assist us effectively, Alfred needs to understand our requests and **prepare, find and use relevant information to help complete tasks.** -This is where LlamaIndex's components come in. +1๋‹จ์›์—์„œ ๋‚˜์™”๋˜ ๋„์›€์ด ๋˜๋Š” ์ง‘์‚ฌ ์—์ด์ „ํŠธ ์•Œํ”„๋ ˆ๋“œ๋ฅผ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? +ํšจ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋ฅผ ๋„์šฐ๋ ค๋ฉด, ์•Œํ”„๋ ˆ๋“œ๋Š” ์šฐ๋ฆฌ์˜ ์š”์ฒญ์„ ์ดํ•ดํ•˜๊ณ  **์ž‘์—…์„ ์™„๋ฃŒํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ๊ด€๋ จ ์ •๋ณด๋ฅผ ์ค€๋น„ํ•˜๊ณ , ์ฐพ๊ณ , ์‚ฌ์šฉ**ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +์ด๊ฒƒ์ด LlamaIndex์˜ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋“ค์–ด์˜ค๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. -While LlamaIndex has many components, **we'll focus specifically on the `QueryEngine` component.** -Why? Because it can be used as a Retrieval-Augmented Generation (RAG) tool for an agent. +LlamaIndex์—๋Š” ๋งŽ์€ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ์ง€๋งŒ, **์šฐ๋ฆฌ๋Š” ํŠน๋ณ„ํžˆ `QueryEngine` ๊ตฌ์„ฑ ์š”์†Œ์— ์ง‘์ค‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.** +์™œ๋ƒ๊ณ ์š”? ์—์ด์ „ํŠธ์˜ ๊ฒ€์ƒ‰ ์ฆ๊ฐ• ์ƒ์„ฑ(RAG) ํˆด๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. -So, what is RAG? LLMs are trained on enormous bodies of data to learn general knowledge. -However, they may not be trained on relevant and up-to-date data. -RAG solves this problem by finding and retrieving relevant information from your data and giving that to the LLM. +๊ทธ๋Ÿผ RAG๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”? LLM์€ ์ผ๋ฐ˜์ ์ธ ์ง€์‹์„ ๋ฐฐ์šฐ๊ธฐ ์œ„ํ•ด ์—„์ฒญ๋‚œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋กœ ํ›ˆ๋ จ๋ฉ๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๊ด€๋ จ ์žˆ๊ณ  ์ตœ์‹  ๋ฐ์ดํ„ฐ๋กœ ํ›ˆ๋ จ๋˜์ง€ ์•Š์•˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +RAG๋Š” ๋ฐ์ดํ„ฐ์—์„œ ๊ด€๋ จ ์ •๋ณด๋ฅผ ์ฐพ๊ณ  ๊ฒ€์ƒ‰ํ•˜์—ฌ LLM์—๊ฒŒ ์ œ๊ณตํ•จ์œผ๋กœ์จ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ![RAG](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/rag.png) -Now, think about how Alfred works: +์ด์ œ ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ƒ๊ฐํ•ด๋ณด์„ธ์š”: -1. You ask Alfred to help plan a dinner party -2. Alfred needs to check your calendar, dietary preferences, and past successful menus -3. The `QueryEngine` helps Alfred find this information and use it to plan the dinner party +1. ์•Œํ”„๋ ˆ๋“œ์—๊ฒŒ ์ €๋… ํŒŒํ‹ฐ ๊ณ„ํš์„ ๋„์™€๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค +2. ์•Œํ”„๋ ˆ๋“œ๋Š” ์บ˜๋ฆฐ๋”, ์‹์ด ์„ ํ˜ธ๋„, ๊ณผ๊ฑฐ ์„ฑ๊ณตํ•œ ๋ฉ”๋‰ด๋ฅผ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค +3. `QueryEngine`์ด ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ด ์ •๋ณด๋ฅผ ์ฐพ๊ณ  ์ €๋… ํŒŒํ‹ฐ ๊ณ„ํš์— ์‚ฌ์šฉํ•˜๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค -This makes the `QueryEngine` **a key component for building agentic RAG workflows** in LlamaIndex. -Just as Alfred needs to search through your household information to be helpful, any agent needs a way to find and understand relevant data. -The `QueryEngine` provides exactly this capability. +์ด๊ฒƒ์ด `QueryEngine`์„ LlamaIndex์—์„œ **์—์ด์ „ํŠธ RAG ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ**๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +์•Œํ”„๋ ˆ๋“œ๊ฐ€ ๋„์›€์ด ๋˜๊ธฐ ์œ„ํ•ด ๊ฐ€์ • ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ๋ชจ๋“  ์—์ด์ „ํŠธ๋Š” ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๊ณ  ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. +`QueryEngine`์€ ์ •ํ™•ํžˆ ์ด ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -Now, let's dive a bit deeper into the components and see how you can **combine components to create a RAG pipeline.** +์ด์ œ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€์„œ **๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ RAG ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งŒ๋“œ๋Š”** ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -## Creating a RAG pipeline using components +## ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ RAG ํŒŒ์ดํ”„๋ผ์ธ ๋งŒ๋“ค๊ธฐ -You can follow the code in this notebook that you can run using Google Colab. +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -There are five key stages within RAG, which in turn will be a part of most larger applications you build. These are: +RAG ๋‚ด์—๋Š” 5๊ฐ€์ง€ ์ฃผ์š” ๋‹จ๊ณ„๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ๊ตฌ์ถ•ํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋” ํฐ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ผ๋ถ€๊ฐ€ ๋ฉ๋‹ˆ๋‹ค: -1. **Loading**: this refers to getting your data from where it lives -- whether it's text files, PDFs, another website, a database, or an API -- into your workflow. LlamaHub provides hundreds of integrations to choose from. -2. **Indexing**: this means creating a data structure that allows for querying the data. For LLMs, this nearly always means creating vector embeddings. Which are numerical representations of the meaning of the data. Indexing can also refer to numerous other metadata strategies to make it easy to accurately find contextually relevant data based on properties. -3. **Storing**: once your data is indexed you will want to store your index, as well as other metadata, to avoid having to re-index it. -4. **Querying**: for any given indexing strategy there are many ways you can utilize LLMs and LlamaIndex data structures to query, including sub-queries, multi-step queries and hybrid strategies. -5. **Evaluation**: a critical step in any flow is checking how effective it is relative to other strategies, or when you make changes. Evaluation provides objective measures of how accurate, faithful and fast your responses to queries are. +1. **๋กœ๋”ฉ**: ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ณณ(ํ…์ŠคํŠธ ํŒŒ์ผ, PDF, ๋‹ค๋ฅธ ์›น์‚ฌ์ดํŠธ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, API)์—์„œ ์›Œํฌํ”Œ๋กœ์šฐ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. LlamaHub๋Š” ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋ฐฑ ๊ฐœ์˜ ํ†ตํ•ฉ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +2. **์ธ๋ฑ์‹ฑ**: ๋ฐ์ดํ„ฐ๋ฅผ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. LLM์˜ ๊ฒฝ์šฐ, ์ด๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ ์˜๋ฏธ์˜ ์ˆ˜์น˜์  ํ‘œํ˜„์ž…๋‹ˆ๋‹ค. ์ธ๋ฑ์‹ฑ์€ ์†์„ฑ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งฅ๋ฝ์ ์œผ๋กœ ๊ด€๋ จ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ฐพ๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“œ๋Š” ์ˆ˜๋งŽ์€ ๋‹ค๋ฅธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ „๋žต์„ ์˜๋ฏธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +3. **์ €์žฅ**: ๋ฐ์ดํ„ฐ๊ฐ€ ์ธ๋ฑ์‹ฑ๋˜๋ฉด ๋‹ค์‹œ ์ธ๋ฑ์‹ฑํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ์ธ๋ฑ์Šค์™€ ๋‹ค๋ฅธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +4. **์ฟผ๋ฆฌ**: ์ฃผ์–ด์ง„ ์ธ๋ฑ์‹ฑ ์ „๋žต์— ๋Œ€ํ•ด ํ•˜์œ„ ์ฟผ๋ฆฌ, ๋‹ค๋‹จ๊ณ„ ์ฟผ๋ฆฌ, ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ „๋žต์„ ํฌํ•จํ•˜์—ฌ LLM๊ณผ LlamaIndex ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. +5. **ํ‰๊ฐ€**: ๋ชจ๋“  ํ๋ฆ„์—์„œ ์ค‘์š”ํ•œ ๋‹จ๊ณ„๋Š” ๋‹ค๋ฅธ ์ „๋žต์— ๋น„ํ•ด ์–ผ๋งˆ๋‚˜ ํšจ๊ณผ์ ์ธ์ง€, ๋˜๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋งŒ๋“ค ๋•Œ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ‰๊ฐ€๋Š” ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ์‘๋‹ต์ด ์–ผ๋งˆ๋‚˜ ์ •ํ™•ํ•˜๊ณ , ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๊ณ , ๋น ๋ฅธ์ง€์— ๋Œ€ํ•œ ๊ฐ๊ด€์ ์ธ ์ธก์ •์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -Next, let's see how we can reproduce these stages using components. +๋‹ค์Œ์œผ๋กœ, ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๋‹จ๊ณ„๋“ค์„ ์žฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -### Loading and embedding documents +### ๋ฌธ์„œ ๋กœ๋”ฉ ๋ฐ ์ž„๋ฒ ๋”ฉ -As mentioned before, LlamaIndex can work on top of your own data, however, **before accessing data, we need to load it.** -There are three main ways to load data into LlamaIndex: +์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด, LlamaIndex๋Š” ์ž์ฒด ๋ฐ์ดํ„ฐ ์œ„์—์„œ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, **๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ ์ „์— ๋กœ๋“œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.** +LlamaIndex์— ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค: -1. `SimpleDirectoryReader`: A built-in loader for various file types from a local directory. -2. `LlamaParse`: LlamaParse, LlamaIndex's official tool for PDF parsing, available as a managed API. -3. `LlamaHub`: A registry of hundreds of data-loading libraries to ingest data from any source. +1. `SimpleDirectoryReader`: ๋กœ์ปฌ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ๋‹ค์–‘ํ•œ ํŒŒ์ผ ์œ ํ˜•์„ ์œ„ํ•œ ๋‚ด์žฅ ๋กœ๋”์ž…๋‹ˆ๋‹ค. +2. `LlamaParse`: PDF ํŒŒ์‹ฑ์„ ์œ„ํ•œ LlamaIndex์˜ ๊ณต์‹ ํˆด์ธ LlamaParse๋กœ, ๊ด€๋ฆฌํ˜• API๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. +3. `LlamaHub`: ๋ชจ๋“  ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•œ ์ˆ˜๋ฐฑ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค. -Get familiar with LlamaHub loaders and LlamaParse parser for more complex data sources. +๋” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์œ„ํ•ด LlamaHub ๋กœ๋”์™€ LlamaParse ํŒŒ์„œ์— ์ต์ˆ™ํ•ด์ง€์„ธ์š”. -**The simplest way to load data is with `SimpleDirectoryReader`.** -This versatile component can load various file types from a folder and convert them into `Document` objects that LlamaIndex can work with. -Let's see how we can use `SimpleDirectoryReader` to load data from a folder. +**๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ `SimpleDirectoryReader`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.** +์ด ๋‹ค์žฌ๋‹ค๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ํด๋”์—์„œ ๋‹ค์–‘ํ•œ ํŒŒ์ผ ์œ ํ˜•์„ ๋กœ๋“œํ•˜๊ณ  LlamaIndex๊ฐ€ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ๋Š” `Document` ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`SimpleDirectoryReader`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ```python from llama_index.core import SimpleDirectoryReader @@ -63,14 +63,14 @@ reader = SimpleDirectoryReader(input_dir="path/to/directory") documents = reader.load_data() ``` -After loading our documents, we need to break them into smaller pieces called `Node` objects. -A `Node` is just a chunk of text from the original document that's easier for the AI to work with, while it still has references to the original `Document` object. +๋ฌธ์„œ๋ฅผ ๋กœ๋“œํ•œ ํ›„, `Node` ๊ฐ์ฒด๋ผ๋Š” ๋” ์ž‘์€ ์กฐ๊ฐ๋“ค๋กœ ๋‚˜๋ˆ„์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +`Node`๋Š” AI๊ฐ€ ์ž‘์—…ํ•˜๊ธฐ ๋” ์‰ฌ์šด ์›๋ณธ ๋ฌธ์„œ์˜ ํ…์ŠคํŠธ ์ฒญํฌ์ผ ๋ฟ์ด๋ฉฐ, ์—ฌ์ „ํžˆ ์›๋ณธ `Document` ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -The `IngestionPipeline` helps us create these nodes through two key transformations. -1. `SentenceSplitter` breaks down documents into manageable chunks by splitting them at natural sentence boundaries. -2. `HuggingFaceEmbedding` converts each chunk into numerical embeddings - vector representations that capture the semantic meaning in a way AI can process efficiently. +`IngestionPipeline`์€ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ๋ณ€ํ™˜์„ ํ†ตํ•ด ์ด๋Ÿฌํ•œ ๋…ธ๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. +1. `SentenceSplitter`๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ ๊ฒฝ๊ณ„์—์„œ ๋ฌธ์„œ๋ฅผ ๋ถ„ํ• ํ•˜์—ฌ ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ์ฒญํฌ๋กœ ๋‚˜๋ˆ•๋‹ˆ๋‹ค. +2. `HuggingFaceEmbedding`์€ ๊ฐ ์ฒญํฌ๋ฅผ ์ˆ˜์น˜์  ์ž„๋ฒ ๋”ฉ์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค - AI๊ฐ€ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ์˜๋ฏธ์  ์˜๋ฏธ๋ฅผ ํฌ์ฐฉํ•˜๋Š” ๋ฒกํ„ฐ ํ‘œํ˜„์ž…๋‹ˆ๋‹ค. -This process helps us organise our documents in a way that's more useful for searching and analysis. +์ด ๊ณผ์ •์€ ๊ฒ€์ƒ‰๊ณผ ๋ถ„์„์— ๋” ์œ ์šฉํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฌธ์„œ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ```python from llama_index.core import Document @@ -78,7 +78,7 @@ from llama_index.embeddings.huggingface import HuggingFaceEmbedding from llama_index.core.node_parser import SentenceSplitter from llama_index.core.ingestion import IngestionPipeline -# create the pipeline with transformations +# ๋ณ€ํ™˜๊ณผ ํ•จ๊ป˜ ํŒŒ์ดํ”„๋ผ์ธ ์ƒ์„ฑ pipeline = IngestionPipeline( transformations=[ SentenceSplitter(chunk_overlap=0), @@ -89,18 +89,17 @@ pipeline = IngestionPipeline( nodes = await pipeline.arun(documents=[Document.example()]) ``` +### ๋ฌธ์„œ ์ €์žฅ ๋ฐ ์ธ๋ฑ์‹ฑ -### Storing and indexing documents +`Node` ๊ฐ์ฒด๋ฅผ ๋งŒ๋“  ํ›„, ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ธ๋ฑ์‹ฑํ•ด์•ผ ํ•˜์ง€๋งŒ, ๊ทธ ์ „์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๊ณณ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. -After creating our `Node` objects we need to index them to make them searchable, but before we can do that, we need a place to store our data. - -Since we are using an ingestion pipeline, we can directly attach a vector store to the pipeline to populate it. -In this case, we will use `Chroma` to store our documents. +์ˆ˜์ง‘ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ํŒŒ์ดํ”„๋ผ์ธ์— ๋ฒกํ„ฐ ์Šคํ† ์–ด๋ฅผ ์ง์ ‘ ์—ฐ๊ฒฐํ•˜์—ฌ ์ฑ„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด ๊ฒฝ์šฐ, ๋ฌธ์„œ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด `Chroma`๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
-Install ChromaDB +ChromaDB ์„ค์น˜ -As introduced in the section on the LlamaHub, we can install the ChromaDB vector store with the following command: +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ChromaDB ๋ฒกํ„ฐ ์Šคํ† ์–ด๋ฅผ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```bash pip install llama-index-vector-stores-chroma @@ -124,13 +123,12 @@ pipeline = IngestionPipeline( ) ``` -An overview of the different vector stores can be found in the LlamaIndex documentation. - +๋‹ค์–‘ํ•œ ๋ฒกํ„ฐ ์Šคํ† ์–ด์— ๋Œ€ํ•œ ๊ฐœ์š”๋Š” LlamaIndex ๋ฌธ์„œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -This is where vector embeddings come in - by embedding both the query and nodes in the same vector space, we can find relevant matches. -The `VectorStoreIndex` handles this for us, using the same embedding model we used during ingestion to ensure consistency. +์ด๊ฒƒ์ด ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ์ด ๋“ค์–ด์˜ค๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค - ์ฟผ๋ฆฌ์™€ ๋…ธ๋“œ๋ฅผ ๊ฐ™์€ ๋ฒกํ„ฐ ๊ณต๊ฐ„์— ์ž„๋ฒ ๋”ฉํ•จ์œผ๋กœ์จ ๊ด€๋ จ ๋งค์น˜๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`VectorStoreIndex`๋Š” ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜์ง‘ ์ค‘์— ์‚ฌ์šฉํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. -Let's see how to create this index from our vector store and embeddings: +๋ฒกํ„ฐ ์Šคํ† ์–ด์™€ ์ž„๋ฒ ๋”ฉ์—์„œ ์ด ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: ```python from llama_index.core import VectorStoreIndex @@ -140,20 +138,20 @@ embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5") index = VectorStoreIndex.from_vector_store(vector_store, embed_model=embed_model) ``` -All information is automatically persisted within the `ChromaVectorStore` object and the passed directory path. +๋ชจ๋“  ์ •๋ณด๋Š” `ChromaVectorStore` ๊ฐ์ฒด์™€ ์ „๋‹ฌ๋œ ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ ๋‚ด์—์„œ ์ž๋™์œผ๋กœ ์ง€์†๋ฉ๋‹ˆ๋‹ค. -Great! Now that we can save and load our index easily, let's explore how to query it in different ways. +ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ ์ธ๋ฑ์Šค๋ฅผ ์‰ฝ๊ฒŒ ์ €์žฅํ•˜๊ณ  ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฟผ๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํƒ๊ตฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -### Querying a VectorStoreIndex with prompts and LLMs +### ํ”„๋กฌํ”„ํŠธ์™€ LLM์œผ๋กœ VectorStoreIndex ์ฟผ๋ฆฌํ•˜๊ธฐ -Before we can query our index, we need to convert it to a query interface. The most common conversion options are: +์ธ๋ฑ์Šค๋ฅผ ์ฟผ๋ฆฌํ•˜๊ธฐ ์ „์—, ์ฟผ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ณ€ํ™˜ ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: -- `as_retriever`: For basic document retrieval, returning a list of `NodeWithScore` objects with similarity scores -- `as_query_engine`: For single question-answer interactions, returning a written response -- `as_chat_engine`: For conversational interactions that maintain memory across multiple messages, returning a written response using chat history and indexed context +- `as_retriever`: ๊ธฐ๋ณธ ๋ฌธ์„œ ๊ฒ€์ƒ‰์šฉ์œผ๋กœ, ์œ ์‚ฌ๋„ ์ ์ˆ˜๊ฐ€ ์žˆ๋Š” `NodeWithScore` ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค +- `as_query_engine`: ๋‹จ์ผ ์งˆ๋ฌธ-๋‹ต๋ณ€ ์ƒํ˜ธ์ž‘์šฉ์šฉ์œผ๋กœ, ์ž‘์„ฑ๋œ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค +- `as_chat_engine`: ์—ฌ๋Ÿฌ ๋ฉ”์‹œ์ง€์— ๊ฑธ์ณ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋Œ€ํ™”ํ˜• ์ƒํ˜ธ์ž‘์šฉ์šฉ์œผ๋กœ, ์ฑ„ํŒ… ๊ธฐ๋ก๊ณผ ์ธ๋ฑ์‹ฑ๋œ ๋งฅ๋ฝ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์„ฑ๋œ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค -We'll focus on the query engine since it is more common for agent-like interactions. -We also pass in an LLM to the query engine to use for the response. +์—์ด์ „ํŠธ์™€ ๊ฐ™์€ ์ƒํ˜ธ์ž‘์šฉ์— ๋” ์ผ๋ฐ˜์ ์ด๋ฏ€๋กœ ์ฟผ๋ฆฌ ์—”์ง„์— ์ง‘์ค‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. +์‘๋‹ต์— ์‚ฌ์šฉํ•  LLM๋„ ์ฟผ๋ฆฌ ์—”์ง„์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ```python from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI @@ -163,66 +161,66 @@ query_engine = index.as_query_engine( llm=llm, response_mode="tree_summarize", ) -query_engine.query("What is the meaning of life?") -# The meaning of life is 42 +query_engine.query("์ธ์ƒ์˜ ์˜๋ฏธ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?") +# ์ธ์ƒ์˜ ์˜๋ฏธ๋Š” 42์ž…๋‹ˆ๋‹ค ``` -### Response Processing +### ์‘๋‹ต ์ฒ˜๋ฆฌ -Under the hood, the query engine doesn't only use the LLM to answer the question but also uses a `ResponseSynthesizer` as a strategy to process the response. -Once again, this is fully customisable but there are three main strategies that work well out of the box: +๋‚ด๋ถ€์ ์œผ๋กœ, ์ฟผ๋ฆฌ ์—”์ง„์€ ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์œ„ํ•ด LLM๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ „๋žต์œผ๋กœ `ResponseSynthesizer`๋„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +๋‹ค์‹œ ํ•œ๋ฒˆ, ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์‚ฌ์šฉ์ž ์ •์˜ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ฆ‰์‹œ ์ž˜ ์ž‘๋™ํ•˜๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ์ „๋žต์ด ์žˆ์Šต๋‹ˆ๋‹ค: -- `refine`: create and refine an answer by sequentially going through each retrieved text chunk. This makes a separate LLM call per Node/retrieved chunk. -- `compact` (default): similar to refining but concatenating the chunks beforehand, resulting in fewer LLM calls. -- `tree_summarize`: create a detailed answer by going through each retrieved text chunk and creating a tree structure of the answer. +- `refine`: ๊ฒ€์ƒ‰๋œ ๊ฐ ํ…์ŠคํŠธ ์ฒญํฌ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ๊ฑฐ์ณ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•˜๊ณ  ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” Node/๊ฒ€์ƒ‰๋œ ์ฒญํฌ๋‹น ๋ณ„๋„์˜ LLM ํ˜ธ์ถœ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +- `compact` (๊ธฐ๋ณธ๊ฐ’): ๊ฐœ์„ ๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋ฏธ๋ฆฌ ์ฒญํฌ๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋” ์ ์€ LLM ํ˜ธ์ถœ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +- `tree_summarize`: ๊ฒ€์ƒ‰๋œ ๊ฐ ํ…์ŠคํŠธ ์ฒญํฌ๋ฅผ ๊ฑฐ์ณ ๋‹ต๋ณ€์˜ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด ์ƒ์„ธํ•œ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. -Take fine-grained control of your query workflows with the low-level composition API. This API lets you customize and fine-tune every step of the query process to match your exact needs, which also pairs great with Workflows +์ €์ˆ˜์ค€ ๊ตฌ์„ฑ API๋กœ ์ฟผ๋ฆฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•˜์„ธ์š”. ์ด API๋Š” ์ฟผ๋ฆฌ ํ”„๋กœ์„ธ์Šค์˜ ๋ชจ๋“  ๋‹จ๊ณ„๋ฅผ ์‚ฌ์šฉ์ž ์ •์˜ํ•˜๊ณ  ๋ฏธ์„ธ ์กฐ์ •ํ•˜์—ฌ ์ •ํ™•ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถœ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋ฉฐ, ์›Œํฌํ”Œ๋กœ์šฐ์™€๋„ ์ž˜ ๋งž์Šต๋‹ˆ๋‹ค. -The language model won't always perform in predictable ways, so we can't be sure that the answer we get is always correct. We can deal with this by **evaluating the quality of the answer**. +์–ธ์–ด ๋ชจ๋ธ์ด ํ•ญ์ƒ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์šฐ๋ฆฌ๊ฐ€ ์–ป๋Š” ๋‹ต๋ณ€์ด ํ•ญ์ƒ ์ •ํ™•ํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. **๋‹ต๋ณ€์˜ ํ’ˆ์งˆ์„ ํ‰๊ฐ€**ํ•จ์œผ๋กœ์จ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -### Evaluation and observability +### ํ‰๊ฐ€ ๋ฐ ๊ด€์ฐฐ ๊ฐ€๋Šฅ์„ฑ -LlamaIndex provides **built-in evaluation tools to assess response quality.** -These evaluators leverage LLMs to analyze responses across different dimensions. -Let's look at the three main evaluators available: +LlamaIndex๋Š” **์‘๋‹ต ํ’ˆ์งˆ์„ ํ‰๊ฐ€ํ•˜๊ธฐ ์œ„ํ•œ ๋‚ด์žฅ ํ‰๊ฐ€ ๋„๊ตฌ**๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +์ด๋Ÿฌํ•œ ํ‰๊ฐ€์ž๋Š” LLM์„ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์ฐจ์›์—์„œ ์‘๋‹ต์„ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. +์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ํ‰๊ฐ€์ž๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: -- `FaithfulnessEvaluator`: Evaluates the faithfulness of the answer by checking if the answer is supported by the context. -- `AnswerRelevancyEvaluator`: Evaluate the relevance of the answer by checking if the answer is relevant to the question. -- `CorrectnessEvaluator`: Evaluate the correctness of the answer by checking if the answer is correct. +- `FaithfulnessEvaluator`: ๋‹ต๋ณ€์ด ๋งฅ๋ฝ์— ์˜ํ•ด ์ง€์›๋˜๋Š”์ง€ ํ™•์ธํ•˜์—ฌ ๋‹ต๋ณ€์˜ ์‹ ๋ขฐ์„ฑ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. +- `AnswerRelevancyEvaluator`: ๋‹ต๋ณ€์ด ์งˆ๋ฌธ๊ณผ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์—ฌ ๋‹ต๋ณ€์˜ ๊ด€๋ จ์„ฑ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. +- `CorrectnessEvaluator`: ๋‹ต๋ณ€์ด ์ •ํ™•ํ•œ์ง€ ํ™•์ธํ•˜์—ฌ ๋‹ต๋ณ€์˜ ์ •ํ™•์„ฑ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. -Want to learn more about agent observability and evaluation? Continue your journey with the Bonus Unit 2. +์—์ด์ „ํŠธ ๊ด€์ฐฐ ๊ฐ€๋Šฅ์„ฑ๊ณผ ํ‰๊ฐ€์— ๋Œ€ํ•ด ๋” ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‚˜์š”? ๋ณด๋„ˆ์Šค ๋‹จ์› 2๋กœ ์—ฌ์ •์„ ๊ณ„์†ํ•˜์„ธ์š”. ```python from llama_index.core.evaluation import FaithfulnessEvaluator -query_engine = # from the previous section -llm = # from the previous section +query_engine = # ์ด์ „ ์„น์…˜์—์„œ +llm = # ์ด์ „ ์„น์…˜์—์„œ -# query index +# ์ธ๋ฑ์Šค ์ฟผ๋ฆฌ evaluator = FaithfulnessEvaluator(llm=llm) response = query_engine.query( - "What battles took place in New York City in the American Revolution?" + "๋ฏธ๊ตญ ํ˜๋ช…์—์„œ ๋‰ด์š•์‹œ์—์„œ ์–ด๋–ค ์ „ํˆฌ๊ฐ€ ์ผ์–ด๋‚ฌ๋‚˜์š”?" ) eval_result = evaluator.evaluate_response(response=response) eval_result.passing ``` -Even without direct evaluation, we can **gain insights into how our system is performing through observability.** -This is especially useful when we are building more complex workflows and want to understand how each component is performing. +์ง์ ‘์ ์ธ ํ‰๊ฐ€ ์—†์ด๋„ **๊ด€์ฐฐ ๊ฐ€๋Šฅ์„ฑ์„ ํ†ตํ•ด ์‹œ์Šคํ…œ์ด ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ํ†ต์ฐฐ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.** +์ด๋Š” ๋” ๋ณต์žกํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€ ์ดํ•ดํ•˜๊ณ  ์‹ถ์„ ๋•Œ ํŠนํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
-Install LlamaTrace +LlamaTrace ์„ค์น˜ -As introduced in the section on the LlamaHub, we can install the LlamaTrace callback from Arize Phoenix with the following command: +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ Arize Phoenix์˜ LlamaTrace ์ฝœ๋ฐฑ์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```bash pip install -U llama-index-callbacks-arize-phoenix ``` -Additionally, we need to set the `PHOENIX_API_KEY` environment variable to our LlamaTrace API key. We can get this by: -- Creating an account at [LlamaTrace](https://llamatrace.com/login) -- Generating an API key in your account settings -- Using the API key in the code below to enable tracing +๋˜ํ•œ LlamaTrace API ํ‚ค๋ฅผ `PHOENIX_API_KEY` ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ํ†ตํ•ด ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +- [LlamaTrace](https://llamatrace.com/login)์—์„œ ๊ณ„์ • ์ƒ์„ฑ +- ๊ณ„์ • ์„ค์ •์—์„œ API ํ‚ค ์ƒ์„ฑ +- ์•„๋ž˜ ์ฝ”๋“œ์—์„œ ์ถ”์ ์„ ํ™œ์„ฑํ™”ํ•˜๊ธฐ ์œ„ํ•ด API ํ‚ค ์‚ฌ์šฉ
@@ -238,6 +236,6 @@ llama_index.core.set_global_handler( ) ``` -Want to learn more about components and how to use them? Continue your journey with the Components Guides or the Guide on RAG. +๊ตฌ์„ฑ ์š”์†Œ์™€ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋” ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‚˜์š”? ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ€์ด๋“œ ๋˜๋Š” RAG ๊ฐ€์ด๋“œ๋กœ ์—ฌ์ •์„ ๊ณ„์†ํ•˜์„ธ์š”. -We have seen how to use components to create a `QueryEngine`. Now, let's see how we can **use the `QueryEngine` as a tool for an agent!** +๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ `QueryEngine`์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด์ œ **`QueryEngine`์„ ์—์ด์ „ํŠธ์˜ ํˆด๋กœ ์‚ฌ์šฉํ•˜๋Š”** ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/llama-index/conclusion.mdx b/units/ko/unit2/llama-index/conclusion.mdx index fba7ef70..c0e7f825 100644 --- a/units/ko/unit2/llama-index/conclusion.mdx +++ b/units/ko/unit2/llama-index/conclusion.mdx @@ -1,13 +1,13 @@ -# Conclusion +# ๊ฒฐ๋ก  -Congratulations on finishing the `llama-index` module of this second Unit ๐Ÿฅณ +2๋‹จ์›์˜ `llama-index` ๋ชจ๋“ˆ์„ ์™„๋ฃŒํ•˜์‹  ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿฅณ -Youโ€™ve just mastered the fundamentals of `llama-index` and youโ€™ve seen how to build your own agentic workflows! -Now that you have skills in `llama-index`, you can start to create search engines that will solve tasks you're interested in. +๋ฐฉ๊ธˆ `llama-index`์˜ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ•˜๊ณ  ์ž์‹ ๋งŒ์˜ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์…จ์Šต๋‹ˆ๋‹ค! +์ด์ œ `llama-index` ๊ธฐ์ˆ ์„ ๊ฐ–์ถ”์…จ์œผ๋‹ˆ, ๊ด€์‹ฌ ์žˆ๋Š” ์ž‘์—…์„ ํ•ด๊ฒฐํ•  ๊ฒ€์ƒ‰ ์—”์ง„์„ ๋งŒ๋“ค๊ธฐ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -In the next module of the unit, you're going to learn **how to build Agents with LangGraph**. +์ด ๋‹จ์›์˜ ๋‹ค์Œ ๋ชจ๋“ˆ์—์„œ๋Š” **LangGraph๋กœ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•**์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. -Finally, we would love **to hear what you think of the course and how we can improve it**. -If you have some feedback then, please ๐Ÿ‘‰ [fill this form](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) +๋งˆ์ง€๋ง‰์œผ๋กœ, **๊ฐ•์˜์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ๊ณผ ๊ฐœ์„  ๋ฐฉ๋ฒ•**์„ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. +ํ”ผ๋“œ๋ฐฑ์ด ์žˆ์œผ์‹œ๋ฉด ๐Ÿ‘‰ [์ด ์–‘์‹์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) -### Keep Learning, and stay awesome ๐Ÿค— +### ๊ณ„์† ๋ฐฐ์šฐ๊ณ , ๋ฉ‹์ง€๊ฒŒ ์œ ์ง€ํ•˜์„ธ์š”! ๐Ÿค— diff --git a/units/ko/unit2/llama-index/introduction.mdx b/units/ko/unit2/llama-index/introduction.mdx index bca856f4..c0d923e2 100644 --- a/units/ko/unit2/llama-index/introduction.mdx +++ b/units/ko/unit2/llama-index/introduction.mdx @@ -1,30 +1,29 @@ -# Introduction to LlamaIndex +# LlamaIndex ์†Œ๊ฐœ -Welcome to this module, where youโ€™ll learn how to build LLM-powered agents using the [LlamaIndex](https://www.llamaindex.ai/) toolkit. +[LlamaIndex](https://www.llamaindex.ai/) ํˆดํ‚ท์„ ์‚ฌ์šฉํ•˜์—ฌ LLM ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๋Š” ์ด ๋ชจ๋“ˆ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. -LlamaIndex is **a complete toolkit for creating LLM-powered agents over your data using indexes and workflows**. For this course we'll focus on three main parts that help build agents in LlamaIndex: **Components**, **Agents and Tools** and **Workflows**. +LlamaIndex๋Š” **์ธ๋ฑ์Šค์™€ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์œ„์—์„œ LLM ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ์™„์ „ํ•œ ํˆดํ‚ท**์ž…๋‹ˆ๋‹ค. ์ด ๊ฐ•์˜์—์„œ๋Š” LlamaIndex์—์„œ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๋ถ€๋ถ„์— ์ง‘์ค‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: **๊ตฌ์„ฑ ์š”์†Œ**, **์—์ด์ „ํŠธ์™€ ํˆด**, ๊ทธ๋ฆฌ๊ณ  **์›Œํฌํ”Œ๋กœ์šฐ**์ž…๋‹ˆ๋‹ค. ![LlamaIndex](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/thumbnail.png) -Let's look at these key parts of LlamaIndex and how they help with agents: +LlamaIndex์˜ ์ด๋Ÿฌํ•œ ํ•ต์‹ฌ ๋ถ€๋ถ„๋“ค๊ณผ ์—์ด์ „ํŠธ์— ์–ด๋–ป๊ฒŒ ๋„์›€์ด ๋˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: -- **Components**: Are the basic building blocks you use in LlamaIndex. These include things like prompts, models, and databases. Components often help connect LlamaIndex with other tools and libraries. -- **Tools**: Tools are components that provide specific capabilities like searching, calculating, or accessing external services. They are the building blocks that enable agents to perform tasks. -- **Agents**: Agents are autonomous components that can use tools and make decisions. They coordinate tool usage to accomplish complex goals. -- **Workflows**: Are step-by-step processes that process logic together. Workflows or agentic workflows are a way to structure agentic behaviour without the explicit use of agents. +- **๊ตฌ์„ฑ ์š”์†Œ**: LlamaIndex์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ๋นŒ๋”ฉ ๋ธ”๋ก์ž…๋‹ˆ๋‹ค. ํ”„๋กฌํ”„ํŠธ, ๋ชจ๋ธ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ข…์ข… LlamaIndex๋ฅผ ๋‹ค๋ฅธ ํˆด๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. +- **ํˆด**: ๊ฒ€์ƒ‰, ๊ณ„์‚ฐ, ์™ธ๋ถ€ ์„œ๋น„์Šค ์ ‘๊ทผ๊ณผ ๊ฐ™์€ ํŠน์ • ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋นŒ๋”ฉ ๋ธ”๋ก์ž…๋‹ˆ๋‹ค. +- **์—์ด์ „ํŠธ**: ํˆด์„ ์‚ฌ์šฉํ•˜๊ณ  ๊ฒฐ์ •์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ๋Š” ์ž์œจ ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํˆด ์‚ฌ์šฉ์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. +- **์›Œํฌํ”Œ๋กœ์šฐ**: ๋กœ์ง์„ ํ•จ๊ป˜ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ์›Œํฌํ”Œ๋กœ์šฐ ๋˜๋Š” ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ๋ช…์‹œ์ ์ธ ์—์ด์ „ํŠธ ์‚ฌ์šฉ ์—†์ด ์—์ด์ „ํŠธ ํ–‰๋™์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. +## LlamaIndex๋ฅผ ํŠน๋ณ„ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? -## What Makes LlamaIndex Special? +LlamaIndex๊ฐ€ smolagents์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์œ ์‚ฌํ•œ ์ผ๋ถ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค: -While LlamaIndex does some things similar to other frameworks like smolagents, it has some key benefits: +- **๋ช…ํ™•ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ ์‹œ์Šคํ…œ**: ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ๋ฐ ๋น„๋™๊ธฐ ์šฐ์„  ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์—์ด์ „ํŠธ๊ฐ€ ๋‹จ๊ณ„๋ณ„๋กœ ์–ด๋–ป๊ฒŒ ๊ฒฐ์ •์„ ๋‚ด๋ ค์•ผ ํ•˜๋Š”์ง€ ๋ถ„ํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋กœ์ง์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. +- **LlamaParse๋ฅผ ํ†ตํ•œ ๊ณ ๊ธ‰ ๋ฌธ์„œ ํŒŒ์‹ฑ**: LlamaParse๋Š” LlamaIndex๋ฅผ ์œ„ํ•ด ํŠน๋ณ„ํžˆ ๋งŒ๋“ค์–ด์กŒ์œผ๋ฏ€๋กœ ํ†ตํ•ฉ์ด ์›ํ™œํ•˜์ง€๋งŒ, ์œ ๋ฃŒ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. +- **๋งŽ์€ ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ**: LlamaIndex๋Š” ์˜ค๋žซ๋™์•ˆ ์กด์žฌํ•ด์™”์œผ๋ฏ€๋กœ ๋งŽ์€ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” LLM, ๊ฒ€์ƒ‰๊ธฐ, ์ธ๋ฑ์Šค ๋“ฑ๊ณผ ๊ฐ™์€ ๋งŽ์€ ํ…Œ์ŠคํŠธ๋˜๊ณ  ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. +- **LlamaHub**: LlamaIndex ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ ์š”์†Œ, ์—์ด์ „ํŠธ, ํˆด์˜ ์ˆ˜๋ฐฑ ๊ฐœ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค. -- **Clear Workflow System**: Workflows help break down how agents should make decisions step by step using an event-driven and async-first syntax. This helps you clearly compose and organize your logic. -- **Advanced Document Parsing with LlamaParse**: LlamaParse was made specifically for LlamaIndex, so the integration is seamless, although it is a paid feature. -- **Many Ready-to-Use Components**: LlamaIndex has been around for a while, so it works with lots of other frameworks. This means it has many tested and reliable components, like LLMs, retrievers, indexes, and more. -- **LlamaHub**: is a registry of hundreds of these components, agents, and tools that you can use within LlamaIndex. +์ด๋Ÿฌํ•œ ๋ชจ๋“  ๊ฐœ๋…์€ ์œ ์šฉํ•œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. +๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๊ฐœ๋…๋“ค์„ ๊ฐ๊ฐ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +๊ฐœ๋…์„ ๋งˆ์Šคํ„ฐํ•œ ํ›„, ์šฐ๋ฆฌ์˜ ํ•™์Šต์„ ์‚ฌ์šฉํ•˜์—ฌ **์—์ด์ „ํŠธ ์•Œํ”„๋ ˆ๋“œ์™€ ํ•จ๊ป˜ ์ ์šฉ๋œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋งŒ๋“ค** ๊ฒƒ์ž…๋‹ˆ๋‹ค! -All of these concepts are required in different scenarios to create useful agents. -In the following sections, we will go over each of these concepts in detail. -After mastering the concepts, we will use our learnings to **create applied use cases with Alfred the agent**! - -Getting our hands on LlamaIndex is exciting, right? So, what are we waiting for? Let's get started with **finding and installing the integrations we need using LlamaHub! ๐Ÿš€** \ No newline at end of file +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 index ef3da822..6da1486b 100644 --- a/units/ko/unit2/llama-index/llama-hub.mdx +++ b/units/ko/unit2/llama-index/llama-hub.mdx @@ -1,42 +1,42 @@ -# Introduction to the LlamaHub +# LlamaHub ์†Œ๊ฐœ -**LlamaHub is a registry of hundreds of integrations, agents and tools that you can use within LlamaIndex.** +**LlamaHub๋Š” LlamaIndex ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋ฐฑ ๊ฐœ์˜ ํ†ตํ•ฉ, ์—์ด์ „ํŠธ, ํˆด์˜ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค.** ![LlamaHub](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/llama-hub.png) -We will be using various integrations in this course, so let's first look at the LlamaHub and how it can help us. +์ด ๊ฐ•์˜์—์„œ ๋‹ค์–‘ํ•œ ํ†ตํ•ฉ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ, ๋จผ์ € LlamaHub์™€ ๊ทธ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์šฐ๋ฆฌ๋ฅผ ๋„์šธ ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -Let's see how to find and install the dependencies for the components we need. +ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์˜์กด์„ฑ์„ ์ฐพ๊ณ  ์„ค์น˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -## Installation +## ์„ค์น˜ -LlamaIndex installation instructions are available as a well-structured **overview on [LlamaHub](https://llamahub.ai/)**. -This might be a bit overwhelming at first, but most of the **installation commands generally follow an easy-to-remember format**: +LlamaIndex ์„ค์น˜ ์ง€์นจ์€ [LlamaHub](https://llamahub.ai/)์—์„œ ์ž˜ ๊ตฌ์กฐํ™”๋œ **๊ฐœ์š”๋กœ ์ œ๊ณต**๋ฉ๋‹ˆ๋‹ค. +์ฒ˜์Œ์—๋Š” ์กฐ๊ธˆ ์••๋„์ ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์˜ **์„ค์น˜ ๋ช…๋ น์–ด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๊ธฐ์–ตํ•˜๊ธฐ ์‰ฌ์šด ํ˜•์‹**์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค: ```bash pip install llama-index-{component-type}-{framework-name} ``` -Let's try to install the dependencies for an LLM and embedding component using the [Hugging Face inference API integration](https://llamahub.ai/l/llms/llama-index-llms-huggingface-api?from=llms). +[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 ``` -## Usage +## ์‚ฌ์šฉ๋ฒ• -Once installed, we can see the usage patterns. You'll notice that the import paths follow the install command! -Underneath, we can see an example of the usage of **the Hugging Face inference API for an LLM component**. +์„ค์น˜๋˜๋ฉด ์‚ฌ์šฉ ํŒจํ„ด์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์ ธ์˜ค๊ธฐ ๊ฒฝ๋กœ๊ฐ€ ์„ค์น˜ ๋ช…๋ น์–ด๋ฅผ ๋”ฐ๋ฅด๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค! +์•„๋ž˜์—์„œ **LLM ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์œ„ํ•œ Hugging Face ์ถ”๋ก  API ์‚ฌ์šฉ**์˜ ์˜ˆ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI import os from dotenv import load_dotenv -# Load the .env file +# .env ํŒŒ์ผ ๋กœ๋“œ load_dotenv() -# Retrieve HF_TOKEN from the environment variables +# ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ HF_TOKEN ๊ฒ€์ƒ‰ hf_token = os.getenv("HF_TOKEN") llm = HuggingFaceInferenceAPI( @@ -46,10 +46,10 @@ llm = HuggingFaceInferenceAPI( token=hf_token, ) -response = llm.complete("Hello, how are you?") +response = llm.complete("์•ˆ๋…•ํ•˜์„ธ์š”, ์–ด๋–ป๊ฒŒ ์ง€๋‚ด์‹œ๋‚˜์š”?") print(response) -# I am good, how can I help you today? +# ์ž˜ ์ง€๋‚ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค, ์˜ค๋Š˜ ์–ด๋–ป๊ฒŒ ๋„์™€๋“œ๋ฆด๊นŒ์š”? ``` -Wonderful, we now know how to find, install and use the integrations for the components we need. -**Let's dive deeper into the components** and see how we can use them to build our own agents. +ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค, ์ด์ œ ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ํ†ตํ•ฉ์„ ์ฐพ๊ณ , ์„ค์น˜ํ•˜๊ณ , ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. +**๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€์„œ** ์šฐ๋ฆฌ๋งŒ์˜ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. diff --git a/units/ko/unit2/llama-index/quiz1.mdx b/units/ko/unit2/llama-index/quiz1.mdx index d387e4e1..7e542df7 100644 --- a/units/ko/unit2/llama-index/quiz1.mdx +++ b/units/ko/unit2/llama-index/quiz1.mdx @@ -1,112 +1,112 @@ -# Small Quiz (ungraded) [[quiz1]] +# ๋ฏธ๋‹ˆ ํ€ด์ฆˆ (์ฑ„์ ๋˜์ง€ ์•Š์Œ) [[quiz1]] -So far we've discussed the key components and tools used in LlamaIndex. -It's time to make a short quiz, since **testing yourself** is the best way to learn and [to avoid the illusion of competence](https://www.coursera.org/lecture/learning-how-to-learn/illusions-of-competence-BuFzf). -This will help you find **where you need to reinforce your knowledge**. +์ง€๊ธˆ๊นŒ์ง€ LlamaIndex์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ์™€ ํˆด์— ๋Œ€ํ•ด ๋…ผ์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. +**์ž์‹ ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ**์ด ํ•™์Šตํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๊ณ  [๋Šฅ๋ ฅ์˜ ์ฐฉ๊ฐ์„ ํ”ผํ•˜๋Š”](https://www.coursera.org/lecture/learning-how-to-learn/illusions-of-competence-BuFzf) ๋ฐฉ๋ฒ•์ด๋ฏ€๋กœ ์งง์€ ํ€ด์ฆˆ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. +์ด๊ฒƒ์€ **์ง€์‹์„ ๊ฐ•ํ™”ํ•ด์•ผ ํ•  ๋ถ€๋ถ„์„ ์ฐพ๋Š”** ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. -This is an optional quiz and it's not graded. +์ด๊ฒƒ์€ ์„ ํƒ์‚ฌํ•ญ ํ€ด์ฆˆ์ด๋ฉฐ ์ฑ„์ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -### Q1: What is a QueryEngine? -Which of the following best describes a QueryEngine component? +### Q1: QueryEngine์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? +๋‹ค์Œ ์ค‘ QueryEngine ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? --- -### Q2: What is the Purpose of FunctionTools? -Why are FunctionTools important for an Agent? +### Q2: FunctionTools์˜ ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? +์—์ด์ „ํŠธ์—๊ฒŒ FunctionTools๊ฐ€ ์ค‘์š”ํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? --- -### Q3: What are Toolspecs in LlamaIndex? -What is the main purpose of Toolspecs? +### Q3: LlamaIndex์˜ Toolspecs๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? +Toolspecs์˜ ์ฃผ์š” ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? --- -### Q4: What is Required to create a tool? -What information must be included when creating a tool? +### Q4: ํˆด์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? +ํˆด์„ ๋งŒ๋“ค ๋•Œ ํฌํ•จํ•ด์•ผ ํ•˜๋Š” ์ •๋ณด๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? --- -### Q2: What object is used for keeping track of the state of the workflow? +### Q2: ์›Œํฌํ”Œ๋กœ์šฐ์˜ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? --- -### Q3: Which method should be used if you want an agent to remember previous interactions? +### Q3: ์—์ด์ „ํŠธ๊ฐ€ ์ด์ „ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ธฐ์–ตํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด ์–ด๋–ค ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋‚˜์š”? @@ -109,4 +109,4 @@ explain: "Agentic RAG is not limited to Function Calling Agents.", --- -Got it? Great! Now let's **do a brief recap of the unit!** +์ดํ•ดํ•˜์…จ๋‚˜์š”? ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ **๋‹จ์›์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์š”์•ฝ์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!** diff --git a/units/ko/unit2/llama-index/tools.mdx b/units/ko/unit2/llama-index/tools.mdx index 286e4cb3..6b9efb8b 100644 --- a/units/ko/unit2/llama-index/tools.mdx +++ b/units/ko/unit2/llama-index/tools.mdx @@ -1,52 +1,52 @@ -# Using Tools in LlamaIndex +# LlamaIndex์—์„œ ํˆด ์‚ฌ์šฉํ•˜๊ธฐ -**Defining a clear set of Tools is crucial to performance.** As we discussed in [unit 1](../../unit1/tools), clear tool interfaces are easier for LLMs to use. -Much like a software API interface for human engineers, they can get more out of the tool if it's easy to understand how it works. +**๋ช…ํ™•ํ•œ ํˆด ์„ธํŠธ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ์— ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.** [1๋‹จ์›](../../unit1/tools)์—์„œ ๋…ผ์˜ํ–ˆ๋“ฏ์ด, ๋ช…ํ™•ํ•œ ํˆด ์ธํ„ฐํŽ˜์ด์Šค๋Š” LLM์ด ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. +์ธ๊ฐ„ ์—”์ง€๋‹ˆ์–ด๋ฅผ ์œ„ํ•œ ์†Œํ”„ํŠธ์›จ์–ด API ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ํˆด์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค๋ฉด ๋” ๋งŽ์€ ๊ฒƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -There are **four main types of tools in LlamaIndex**: +**LlamaIndex์—๋Š” ๋„ค ๊ฐ€์ง€ ์ฃผ์š” ์œ ํ˜•์˜ ํˆด**์ด ์žˆ์Šต๋‹ˆ๋‹ค: -![Tools](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/tools.png) +![ํˆด](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/tools.png) -1. `FunctionTool`: Convert any Python function into a tool that an agent can use. It automatically figures out how the function works. -2. `QueryEngineTool`: A tool that lets agents use query engines. Since agents are built on query engines, they can also use other agents as tools. -3. `Toolspecs`: Sets of tools created by the community, which often include tools for specific services like Gmail. -4. `Utility Tools`: Special tools that help handle large amounts of data from other tools. +1. `FunctionTool`: ๋ชจ๋“  Python ํ•จ์ˆ˜๋ฅผ ์—์ด์ „ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํˆด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ž๋™์œผ๋กœ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค. +2. `QueryEngineTool`: ์—์ด์ „ํŠธ๊ฐ€ ์ฟผ๋ฆฌ ์—”์ง„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ํˆด์ž…๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ์ฟผ๋ฆฌ ์—”์ง„ ์œ„์— ๊ตฌ์ถ•๋˜๋ฏ€๋กœ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๋„ ํˆด๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +3. `Toolspecs`: ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋งŒ๋“  ํˆด ์„ธํŠธ๋กœ, ์ข…์ข… Gmail๊ณผ ๊ฐ™์€ ํŠน์ • ์„œ๋น„์Šค๋ฅผ ์œ„ํ•œ ํˆด์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. +4. `Utility Tools`: ๋‹ค๋ฅธ ํˆด์—์„œ ๋‚˜์˜ค๋Š” ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ํŠน๋ณ„ํ•œ ํˆด์ž…๋‹ˆ๋‹ค. -We will go over each of them in more detail below. +์•„๋ž˜์—์„œ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -## Creating a FunctionTool +## FunctionTool ๋งŒ๋“ค๊ธฐ -You can follow the code in this notebook that you can run using Google Colab. +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -A FunctionTool provides a simple way to wrap any Python function and make it available to an agent. -You can pass either a synchronous or asynchronous function to the tool, along with optional `name` and `description` parameters. -The name and description are particularly important as they help the agent understand when and how to use the tool effectively. -Let's look at how to create a FunctionTool below and then call it. +FunctionTool์€ ๋ชจ๋“  Python ํ•จ์ˆ˜๋ฅผ ๋ž˜ํ•‘ํ•˜๊ณ  ์—์ด์ „ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +๋™๊ธฐ ๋˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํˆด์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์„ ํƒ์ ์œผ๋กœ `name`๊ณผ `description` ๋งค๊ฐœ๋ณ€์ˆ˜๋„ ํ•จ๊ป˜ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๋ฆ„๊ณผ ์„ค๋ช…์€ ํŠนํžˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๊ฐ€ ์–ธ์ œ, ์–ด๋–ป๊ฒŒ ํˆด์„ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ• ์ง€ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +์•„๋ž˜์—์„œ FunctionTool์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ณ  ํ˜ธ์ถœํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ```python from llama_index.core.tools import FunctionTool def get_weather(location: str) -> str: - """Useful for getting the weather for a given location.""" - print(f"Getting weather for {location}") - return f"The weather in {location} is sunny" + """์ฃผ์–ด์ง„ ์œ„์น˜์˜ ๋‚ ์”จ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.""" + print(f"{location}์˜ ๋‚ ์”จ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘") + return f"{location}์˜ ๋‚ ์”จ๋Š” ๋ง‘์Šต๋‹ˆ๋‹ค" tool = FunctionTool.from_defaults( get_weather, name="my_weather_tool", - description="Useful for getting the weather for a given location.", + description="์ฃผ์–ด์ง„ ์œ„์น˜์˜ ๋‚ ์”จ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.", ) -tool.call("New York") +tool.call("๋‰ด์š•") ``` -When using an agent or LLM with function calling, the tool selected (and the arguments written for that tool) rely strongly on the tool name and description of the purpose and arguments of the tool. Learn more about function calling in the Function Calling Guide. +ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ์žˆ๋Š” ์—์ด์ „ํŠธ๋‚˜ LLM์„ ์‚ฌ์šฉํ•  ๋•Œ, ์„ ํƒ๋œ ํˆด(๊ทธ ํˆด์— ๋Œ€ํ•ด ์ž‘์„ฑ๋œ ์ธ์ˆ˜)์€ ํˆด์˜ ๋ชฉ์ ๊ณผ ์ธ์ˆ˜์— ๋Œ€ํ•œ ํˆด ์ด๋ฆ„๊ณผ ์„ค๋ช…์— ํฌ๊ฒŒ ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ฐ€์ด๋“œ์—์„œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด์„ธ์š”. -## Creating a QueryEngineTool +## QueryEngineTool ๋งŒ๋“ค๊ธฐ -The `QueryEngine` we defined in the previous unit can be easily transformed into a tool using the `QueryEngineTool` class. -Let's see how to create a `QueryEngineTool` from a `QueryEngine` in the example below. +์ด์ „ ๋‹จ์›์—์„œ ์ •์˜ํ•œ `QueryEngine`์€ `QueryEngineTool` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ํˆด๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์•„๋ž˜ ์˜ˆ์ œ์—์„œ `QueryEngine`์—์„œ `QueryEngineTool`์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ```python from llama_index.core import VectorStoreIndex @@ -68,22 +68,22 @@ query_engine = index.as_query_engine(llm=llm) tool = QueryEngineTool.from_defaults(query_engine, name="some useful name", description="some useful description") ``` -## Creating Toolspecs +## Toolspecs ๋งŒ๋“ค๊ธฐ -Think of `ToolSpecs` as collections of tools that work together harmoniously - like a well-organized professional toolkit. -Just as a mechanic's toolkit contains complementary tools that work together for vehicle repairs, a `ToolSpec` combines related tools for specific purposes. -For example, an accounting agent's `ToolSpec` might elegantly integrate spreadsheet capabilities, email functionality, and calculation tools to handle financial tasks with precision and efficiency. +`ToolSpecs`๋ฅผ ์กฐํ™”๋กญ๊ฒŒ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ํˆด ๋ชจ์Œ์œผ๋กœ ์ƒ๊ฐํ•˜์„ธ์š” - ์ž˜ ์ •๋ฆฌ๋œ ์ „๋ฌธ๊ฐ€ ํˆดํ‚ท์ฒ˜๋Ÿผ์š”. +์ •๋น„์‚ฌ์˜ ํˆดํ‚ท์ด ์ฐจ๋Ÿ‰ ์ˆ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๋ณด์™„์ ์ธ ํˆด๋“ค์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, `ToolSpec`์€ ํŠน์ • ๋ชฉ์ ์„ ์œ„ํ•ด ๊ด€๋ จ๋œ ํˆด๋“ค์„ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. +์˜ˆ๋ฅผ ๋“ค์–ด, ํšŒ๊ณ„ ์—์ด์ „ํŠธ์˜ `ToolSpec`์€ ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ ๊ธฐ๋Šฅ, ์ด๋ฉ”์ผ ๊ธฐ๋Šฅ, ๊ณ„์‚ฐ ํˆด์„ ์šฐ์•„ํ•˜๊ฒŒ ํ†ตํ•ฉํ•˜์—ฌ ์žฌ๋ฌด ์ž‘์—…์„ ์ •ํ™•ํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
-Install the Google Toolspec -As introduced in the section on the LlamaHub, we can install the Google toolspec with the following command: +Google Toolspec ์„ค์น˜ +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ Google toolspec์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python pip install llama-index-tools-google ```
-And now we can load the toolspec and convert it to a list of tools. +์ด์ œ toolspec์„ ๋กœ๋“œํ•˜๊ณ  ํˆด ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python from llama_index.tools.google import GmailToolSpec @@ -92,22 +92,22 @@ tool_spec = GmailToolSpec() tool_spec_list = tool_spec.to_tool_list() ``` -To get a more detailed view of the tools, we can take a look at the `metadata` of each tool. +ํˆด์— ๋Œ€ํ•œ ๋” ์ž์„ธํ•œ ๋ณด๊ธฐ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ๊ฐ ํˆด์˜ `metadata`๋ฅผ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python [(tool.metadata.name, tool.metadata.description) for tool in tool_spec_list] ``` -### Model Context Protocol (MCP) in LlamaIndex +### LlamaIndex์˜ ๋ชจ๋ธ ์ปจํ…์ŠคํŠธ ํ”„๋กœํ† ์ฝœ (MCP) -LlamaIndex also allows using MCP tools through a [ToolSpec on the LlamaHub](https://llamahub.ai/l/tools/llama-index-tools-mcp?from=). -You can simply run an MCP server and start using it through the following implementation. +LlamaIndex๋Š” [LlamaHub์˜ ToolSpec](https://llamahub.ai/l/tools/llama-index-tools-mcp?from=)์„ ํ†ตํ•ด MCP ํˆด ์‚ฌ์šฉ๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. +๋‹จ์ˆœํžˆ MCP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค์Œ ๊ตฌํ˜„์„ ํ†ตํ•ด ์‚ฌ์šฉ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -If you want to dive deeper about MCP, you can check our [free MCP Course](https://huggingface.co/learn/mcp-course/). +MCP์— ๋Œ€ํ•ด ๋” ๊นŠ์ด ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด [๋ฌด๋ฃŒ MCP ๊ฐ•์˜](https://huggingface.co/learn/mcp-course/)๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
-Install the MCP Toolspec -As introduced in the section on the LlamaHub, we can install the MCP toolspec with the following command: +MCP Toolspec ์„ค์น˜ +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ MCP toolspec์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python pip install llama-index-tools-mcp @@ -117,25 +117,25 @@ pip install llama-index-tools-mcp ```python from llama_index.tools.mcp import BasicMCPClient, McpToolSpec -# We consider there is a mcp server running on 127.0.0.1:8000, or you can use the mcp client to connect to your own mcp server. +# 127.0.0.1:8000์—์„œ ์‹คํ–‰ ์ค‘์ธ mcp ์„œ๋ฒ„๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฑฐ๋‚˜, mcp ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž์ฒด mcp ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. mcp_client = BasicMCPClient("http://127.0.0.1:8000/sse") mcp_tool = McpToolSpec(client=mcp_client) -# get the agent +# ์—์ด์ „ํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ agent = await get_agent(mcp_tool) -# create the agent context +# ์—์ด์ „ํŠธ ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ agent_context = Context(agent) ``` -## Utility Tools +## ์œ ํ‹ธ๋ฆฌํ‹ฐ ํˆด -Oftentimes, directly querying an API **can return an excessive amount of data**, some of which may be irrelevant, overflow the context window of the LLM, or unnecessarily increase the number of tokens that you are using. -Let's walk through our two main utility tools below. +์ข…์ข… API๋ฅผ ์ง์ ‘ ์ฟผ๋ฆฌํ•˜๋Š” ๊ฒƒ์€ **๊ณผ๋„ํ•œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ**, ๊ทธ ์ค‘ ์ผ๋ถ€๋Š” ๊ด€๋ จ์ด ์—†๊ฑฐ๋‚˜, LLM์˜ ์ปจํ…์ŠคํŠธ ์œˆ๋„์šฐ๋ฅผ ๋„˜์น˜๊ฑฐ๋‚˜, ์‚ฌ์šฉํ•˜๋Š” ํ† ํฐ ์ˆ˜๋ฅผ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ฆ๊ฐ€์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์•„๋ž˜์—์„œ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํˆด์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -1. `OnDemandToolLoader`: This tool turns any existing LlamaIndex data loader (BaseReader class) into a tool that an agent can use. The tool can be called with all the parameters needed to trigger `load_data` from the data loader, along with a natural language query string. During execution, we first load data from the data loader, index it (for instance with a vector store), and then query it 'on-demand'. All three of these steps happen in a single tool call. -2. `LoadAndSearchToolSpec`: The LoadAndSearchToolSpec takes in any existing Tool as input. As a tool spec, it implements `to_tool_list`, and when that function is called, two tools are returned: a loading tool and then a search tool. The load Tool execution would call the underlying Tool, and then index the output (by default with a vector index). The search Tool execution would take in a query string as input and call the underlying index. +1. `OnDemandToolLoader`: ์ด ํˆด์€ ๊ธฐ์กด LlamaIndex ๋ฐ์ดํ„ฐ ๋กœ๋”(BaseReader ํด๋ž˜์Šค)๋ฅผ ์—์ด์ „ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํˆด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํˆด์€ ๋ฐ์ดํ„ฐ ๋กœ๋”์—์„œ `load_data`๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ž์—ฐ์–ด ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹คํ–‰ ์ค‘์— ๋จผ์ € ๋ฐ์ดํ„ฐ ๋กœ๋”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ณ , ์ธ๋ฑ์‹ฑํ•˜๊ณ (์˜ˆ๋ฅผ ๋“ค์–ด ๋ฒกํ„ฐ ์Šคํ† ์–ด๋กœ), ๊ทธ๋Ÿฐ ๋‹ค์Œ '์˜จ๋””๋งจ๋“œ'๋กœ ์ฟผ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์„ธ ๋‹จ๊ณ„ ๋ชจ๋‘๊ฐ€ ๋‹จ์ผ ํˆด ํ˜ธ์ถœ์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. +2. `LoadAndSearchToolSpec`: LoadAndSearchToolSpec์€ ๊ธฐ์กด ํˆด์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค. ํˆด ์ŠคํŽ™์œผ๋กœ์„œ `to_tool_list`๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ, ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋‘ ๊ฐœ์˜ ํˆด์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค: ๋กœ๋”ฉ ํˆด๊ณผ ๊ฒ€์ƒ‰ ํˆด์ž…๋‹ˆ๋‹ค. ๋กœ๋“œ ํˆด ์‹คํ–‰์€ ๊ธฐ๋ณธ ํˆด์„ ํ˜ธ์ถœํ•œ ๋‹ค์Œ ์ถœ๋ ฅ์„ ์ธ๋ฑ์‹ฑํ•ฉ๋‹ˆ๋‹ค(๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฒกํ„ฐ ์ธ๋ฑ์Šค๋กœ). ๊ฒ€์ƒ‰ ํˆด ์‹คํ–‰์€ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„ ๊ธฐ๋ณธ ์ธ๋ฑ์Šค๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. -You can find toolspecs and utility tools on the LlamaHub +toolspecs์™€ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํˆด์€ LlamaHub์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค -Now that we understand the basics of agents and tools in LlamaIndex, let's see how we can **use LlamaIndex to create configurable and manageable workflows!** +์ด์ œ LlamaIndex์—์„œ ์—์ด์ „ํŠธ์™€ ํˆด์˜ ๊ธฐ๋ณธ์„ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, LlamaIndex๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **๊ตฌ์„ฑ ๊ฐ€๋Šฅํ•˜๊ณ  ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š”** ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/llama-index/workflows.mdx b/units/ko/unit2/llama-index/workflows.mdx index d82f8350..3b2e396e 100644 --- a/units/ko/unit2/llama-index/workflows.mdx +++ b/units/ko/unit2/llama-index/workflows.mdx @@ -1,43 +1,43 @@ -# Creating agentic workflows in LlamaIndex +# LlamaIndex์—์„œ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ ๋งŒ๋“ค๊ธฐ -A workflow in LlamaIndex provides a structured way to organize your code into sequential and manageable steps. +LlamaIndex์˜ ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ์ฝ”๋“œ๋ฅผ ์ˆœ์ฐจ์ ์ด๊ณ  ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ๋‹จ๊ณ„๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๊ตฌ์กฐํ™”๋œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -Such a workflow is created by defining `Steps` which are triggered by `Events`, and themselves emit `Events` to trigger further steps. -Let's take a look at Alfred showing a LlamaIndex workflow for a RAG task. +์ด๋Ÿฌํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋Š” `Events`์— ์˜ํ•ด ํŠธ๋ฆฌ๊ฑฐ๋˜๋Š” `Steps`๋ฅผ ์ •์˜ํ•˜์—ฌ ์ƒ์„ฑ๋˜๋ฉฐ, ์ด๋“ค ์ž์ฒด๊ฐ€ ์ถ”๊ฐ€ ๋‹จ๊ณ„๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด `Events`๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. +RAG ์ž‘์—…์„ ์œ„ํ•œ LlamaIndex ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์•Œํ”„๋ ˆ๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -![Workflow Schematic](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/workflows.png) +![์›Œํฌํ”Œ๋กœ์šฐ ๊ฐœ์š”](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/workflows.png) -**Workflows offer several key benefits:** +**์›Œํฌํ”Œ๋กœ์šฐ๋Š” ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:** -- Clear organization of code into discrete steps -- Event-driven architecture for flexible control flow -- Type-safe communication between steps -- Built-in state management -- Support for both simple and complex agent interactions +- ์ฝ”๋“œ๋ฅผ ๊ฐœ๋ณ„ ๋‹จ๊ณ„๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ์„ฑ +- ์œ ์—ฐํ•œ ์ œ์–ด ํ๋ฆ„์„ ์œ„ํ•œ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ +- ๋‹จ๊ณ„ ๊ฐ„ ํƒ€์ž… ์•ˆ์ „ ํ†ต์‹  +- ๋‚ด์žฅ ์ƒํƒœ ๊ด€๋ฆฌ +- ๊ฐ„๋‹จํ•˜๊ณ  ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์ƒํ˜ธ์ž‘์šฉ ๋ชจ๋‘ ์ง€์› -As you might have guessed, **workflows strike a great balance between the autonomy of agents while maintaining control over the overall workflow.** +์ถ”์ธกํ•˜์…จ์„ ์ˆ˜ ์žˆ๋“ฏ์ด, **์›Œํฌํ”Œ๋กœ์šฐ๋Š” ์ „์ฒด ์›Œํฌํ”Œ๋กœ์šฐ์— ๋Œ€ํ•œ ์ œ์–ด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์—์ด์ „ํŠธ์˜ ์ž์œจ์„ฑ ์‚ฌ์ด์—์„œ ํ›Œ๋ฅญํ•œ ๊ท ํ˜•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.** -So, let's learn how to create a workflow ourselves! +๊ทธ๋Ÿผ ์šฐ๋ฆฌ๋งŒ์˜ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! -## Creating Workflows +## ์›Œํฌํ”Œ๋กœ์šฐ ๋งŒ๋“ค๊ธฐ -You can follow the code in this notebook that you can run using Google Colab. +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -### Basic Workflow Creation +### ๊ธฐ๋ณธ ์›Œํฌํ”Œ๋กœ์šฐ ์ƒ์„ฑ
-Install the Workflow package -As introduced in the section on the LlamaHub, we can install the Workflow package with the following command: +์›Œํฌํ”Œ๋กœ์šฐ ํŒจํ‚ค์ง€ ์„ค์น˜ +LlamaHub ์„น์…˜์—์„œ ์†Œ๊ฐœ๋œ ๋Œ€๋กœ, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ์›Œํฌํ”Œ๋กœ์šฐ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python pip install llama-index-utils-workflow ```
-We can create a single-step workflow by defining a class that inherits from `Workflow` and decorating your functions with `@step`. -We will also need to add `StartEvent` and `StopEvent`, which are special events that are used to indicate the start and end of the workflow. +`Workflow`๋ฅผ ์ƒ์†ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  ํ•จ์ˆ˜์— `@step` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ๋‹จ๊ณ„ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋˜ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ์˜ ์‹œ์ž‘๊ณผ ๋์„ ๋‚˜ํƒ€๋‚ด๋Š” ํŠน๋ณ„ํ•œ ์ด๋ฒคํŠธ์ธ `StartEvent`์™€ `StopEvent`๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```python from llama_index.core.workflow import StartEvent, StopEvent, Workflow, step @@ -45,20 +45,20 @@ from llama_index.core.workflow import StartEvent, StopEvent, Workflow, step class MyWorkflow(Workflow): @step async def my_step(self, ev: StartEvent) -> StopEvent: - # do something here - return StopEvent(result="Hello, world!") + # ์—ฌ๊ธฐ์„œ ๋ฌด์–ธ๊ฐ€ ์ˆ˜ํ–‰ + return StopEvent(result="์•ˆ๋…•ํ•˜์„ธ์š”, ์„ธ๊ณ„!") w = MyWorkflow(timeout=10, verbose=False) result = await w.run() ``` -As you can see, we can now run the workflow by calling `w.run()`. +๋ณด์‹œ๋‹ค์‹œํ”ผ, ์ด์ œ `w.run()`์„ ํ˜ธ์ถœํ•˜์—ฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -### Connecting Multiple Steps +### ์—ฌ๋Ÿฌ ๋‹จ๊ณ„ ์—ฐ๊ฒฐํ•˜๊ธฐ -To connect multiple steps, we **create custom events that carry data between steps.** -To do so, we need to add an `Event` that is passed between the steps and transfers the output of the first step to the second step. +์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด **๋‹จ๊ณ„ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.** +์ด๋ฅผ ์œ„ํ•ด ๋‹จ๊ณ„ ๊ฐ„์— ์ „๋‹ฌ๋˜๊ณ  ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์˜ ์ถœ๋ ฅ์„ ๋‘ ๋ฒˆ์งธ ๋‹จ๊ณ„๋กœ ์ „์†กํ•˜๋Š” `Event`๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```python from llama_index.core.workflow import Event @@ -69,13 +69,13 @@ class ProcessingEvent(Event): class MultiStepWorkflow(Workflow): @step async def step_one(self, ev: StartEvent) -> ProcessingEvent: - # Process initial data - return ProcessingEvent(intermediate_result="Step 1 complete") + # ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ + return ProcessingEvent(intermediate_result="1๋‹จ๊ณ„ ์™„๋ฃŒ") @step async def step_two(self, ev: ProcessingEvent) -> StopEvent: - # Use the intermediate result - final_result = f"Finished processing: {ev.intermediate_result}" + # ์ค‘๊ฐ„ ๊ฒฐ๊ณผ ์‚ฌ์šฉ + final_result = f"์ฒ˜๋ฆฌ ์™„๋ฃŒ: {ev.intermediate_result}" return StopEvent(result=final_result) w = MultiStepWorkflow(timeout=10, verbose=False) @@ -83,14 +83,14 @@ result = await w.run() result ``` -The type hinting is important here, as it ensures that the workflow is executed correctly. Let's complicate things a bit more! +ํƒ€์ž… ํžŒํŒ…์€ ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์กฐ๊ธˆ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! -### Loops and Branches +### ๋ฃจํ”„์™€ ๋ถ„๊ธฐ -The type hinting is the most powerful part of workflows because it allows us to create branches, loops, and joins to facilitate more complex workflows. +ํƒ€์ž… ํžŒํŒ…์€ ์›Œํฌํ”Œ๋กœ์šฐ์˜ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๋” ๋ณต์žกํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ถ„๊ธฐ, ๋ฃจํ”„, ์กฐ์ธ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. -Let's show an example of **creating a loop** by using the union operator `|`. -In the example below, we see that the `LoopEvent` is taken as input for the step and can also be returned as output. +ํ•ฉ์ง‘ํ•ฉ ์—ฐ์‚ฐ์ž `|`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **๋ฃจํ”„๋ฅผ ๋งŒ๋“œ๋Š”** ์˜ˆ์ œ๋ฅผ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. +์•„๋ž˜ ์˜ˆ์ œ์—์„œ `LoopEvent`๊ฐ€ ๋‹จ๊ณ„์˜ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์ถœ๋ ฅ์œผ๋กœ๋„ ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ์Œ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python from llama_index.core.workflow import Event @@ -109,16 +109,16 @@ class MultiStepWorkflow(Workflow): @step async def step_one(self, ev: StartEvent | LoopEvent) -> ProcessingEvent | LoopEvent: if random.randint(0, 1) == 0: - print("Bad thing happened") - return LoopEvent(loop_output="Back to step one.") + print("๋‚˜์œ ์ผ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค") + return LoopEvent(loop_output="1๋‹จ๊ณ„๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.") else: - print("Good thing happened") - return ProcessingEvent(intermediate_result="First step complete.") + print("์ข‹์€ ์ผ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค") + return ProcessingEvent(intermediate_result="์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„ ์™„๋ฃŒ.") @step async def step_two(self, ev: ProcessingEvent) -> StopEvent: - # Use the intermediate result - final_result = f"Finished processing: {ev.intermediate_result}" + # ์ค‘๊ฐ„ ๊ฒฐ๊ณผ ์‚ฌ์šฉ + final_result = f"์ฒ˜๋ฆฌ ์™„๋ฃŒ: {ev.intermediate_result}" return StopEvent(result=final_result) @@ -127,25 +127,25 @@ result = await w.run() result ``` -### Drawing Workflows +### ์›Œํฌํ”Œ๋กœ์šฐ ๊ทธ๋ฆฌ๊ธฐ -We can also draw workflows. Let's use the `draw_all_possible_flows` function to draw the workflow. This stores the workflow in an HTML file. +์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ทธ๋ฆด ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. `draw_all_possible_flows` ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ทธ๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ HTML ํŒŒ์ผ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ```python from llama_index.utils.workflow import draw_all_possible_flows -w = ... # as defined in the previous section +w = ... # ์ด์ „ ์„น์…˜์—์„œ ์ •์˜๋œ ๋Œ€๋กœ draw_all_possible_flows(w, "flow.html") ``` -![workflow drawing](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/workflow-draw.png) +![์›Œํฌํ”Œ๋กœ์šฐ ๊ทธ๋ฆฌ๊ธฐ](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/llama-index/workflow-draw.png) -There is one last cool trick that we will cover in the course, which is the ability to add state to the workflow. +๊ฐ•์˜์—์„œ ๋‹ค๋ฃฐ ๋งˆ์ง€๋ง‰ ๋ฉ‹์ง„ ํŠธ๋ฆญ์ด ์žˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ ์›Œํฌํ”Œ๋กœ์šฐ์— ์ƒํƒœ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋Šฅ๋ ฅ์ž…๋‹ˆ๋‹ค. -### State Management +### ์ƒํƒœ ๊ด€๋ฆฌ -State management is useful when you want to keep track of the state of the workflow, so that every step has access to the same state. -We can do this by using the `Context` type hint on top of a parameter in the step function. +์ƒํƒœ ๊ด€๋ฆฌ๋Š” ์›Œํฌํ”Œ๋กœ์šฐ์˜ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉํ•˜๋ฏ€๋กœ, ๋ชจ๋“  ๋‹จ๊ณ„๊ฐ€ ๋™์ผํ•œ ์ƒํƒœ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋‹จ๊ณ„ ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์œ„์— `Context` ํƒ€์ž… ํžŒํŒ…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python from llama_index.core.workflow import Context, StartEvent, StopEvent @@ -153,95 +153,95 @@ from llama_index.core.workflow import Context, StartEvent, StopEvent @step async def query(self, ctx: Context, ev: StartEvent) -> StopEvent: - # store query in the context - await ctx.store.set("query", "What is the capital of France?") + # ์ปจํ…์ŠคํŠธ์— ์ฟผ๋ฆฌ ์ €์žฅ + await ctx.store.set("query", "ํ”„๋ž‘์Šค์˜ ์ˆ˜๋„๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?") - # do something with context and event + # ์ปจํ…์ŠคํŠธ์™€ ์ด๋ฒคํŠธ๋กœ ๋ฌด์–ธ๊ฐ€ ์ˆ˜ํ–‰ val = ... - # retrieve query from the context + # ์ปจํ…์ŠคํŠธ์—์„œ ์ฟผ๋ฆฌ ๊ฒ€์ƒ‰ query = await ctx.store.get("query") return StopEvent(result=val) ``` -Great! Now you know how to create basic workflows in LlamaIndex! +ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ LlamaIndex์—์„œ ๊ธฐ๋ณธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค! -There are some more complex nuances to workflows, which you can learn about in the LlamaIndex documentation. +์›Œํฌํ”Œ๋กœ์šฐ์—๋Š” ๋” ๋ณต์žกํ•œ ๋‰˜์•™์Šค๊ฐ€ ์žˆ์œผ๋ฉฐ, LlamaIndex ๋ฌธ์„œ์—์„œ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -However, there is another way to create workflows, which relies on the `AgentWorkflow` class. Let's take a look at how we can use this to create a multi-agent workflow. +ํ•˜์ง€๋งŒ `AgentWorkflow` ํด๋ž˜์Šค์— ์˜์กดํ•˜๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -## Automating workflows with Multi-Agent Workflows +## ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋กœ ์›Œํฌํ”Œ๋กœ์šฐ ์ž๋™ํ™” -Instead of manual workflow creation, we can use the **`AgentWorkflow` class to create a multi-agent workflow**. -The `AgentWorkflow` uses Workflow Agents to allow you to create a system of one or more agents that can collaborate and hand off tasks to each other based on their specialized capabilities. -This enables building complex agent systems where different agents handle different aspects of a task. -Instead of importing classes from `llama_index.core.agent`, we will import the agent classes from `llama_index.core.agent.workflow`. -One agent must be designated as the root agent in the `AgentWorkflow` constructor. -When a user message comes in, it is first routed to the root agent. +์ˆ˜๋™ ์›Œํฌํ”Œ๋กœ์šฐ ์ƒ์„ฑ ๋Œ€์‹  **`AgentWorkflow` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“ค** ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`AgentWorkflow`๋Š” ์›Œํฌํ”Œ๋กœ์šฐ ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „๋ฌธํ™”๋œ ๊ธฐ๋Šฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ˜‘์—…ํ•˜๊ณ  ์„œ๋กœ์—๊ฒŒ ์ž‘์—…์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. +์ด๋ฅผ ํ†ตํ•ด ์„œ๋กœ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ธก๋ฉด์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`llama_index.core.agent`์—์„œ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋Œ€์‹ , `llama_index.core.agent.workflow`์—์„œ ์—์ด์ „ํŠธ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +ํ•˜๋‚˜์˜ ์—์ด์ „ํŠธ๋Š” `AgentWorkflow` ์ƒ์„ฑ์ž์—์„œ ๋ฃจํŠธ ์—์ด์ „ํŠธ๋กœ ์ง€์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€๊ฐ€ ๋“ค์–ด์˜ค๋ฉด ๋จผ์ € ๋ฃจํŠธ ์—์ด์ „ํŠธ๋กœ ๋ผ์šฐํŒ…๋ฉ๋‹ˆ๋‹ค. -Each agent can then: +๊ฐ ์—์ด์ „ํŠธ๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -- Handle the request directly using their tools -- Handoff to another agent better suited for the task -- Return a response to the user +- ํˆด์„ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์„ ์ง์ ‘ ์ฒ˜๋ฆฌ +- ์ž‘์—…์— ๋” ์ ํ•ฉํ•œ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์—๊ฒŒ ์ž‘์—… ๋„˜๊ธฐ๊ธฐ +- ์‚ฌ์šฉ์ž์—๊ฒŒ ์‘๋‹ต ๋ฐ˜ํ™˜ -Let's see how to create a multi-agent workflow. +๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ```python from llama_index.core.agent.workflow import AgentWorkflow, ReActAgent from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI -# Define some tools +# ๋ช‡ ๊ฐ€์ง€ ํˆด ์ •์˜ def add(a: int, b: int) -> int: - """Add two numbers.""" + """๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•ฉ๋‹ˆ๋‹ค.""" return a + b def multiply(a: int, b: int) -> int: - """Multiply two numbers.""" + """๋‘ ์ˆซ์ž๋ฅผ ๊ณฑํ•ฉ๋‹ˆ๋‹ค.""" return a * b llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") -# we can pass functions directly without FunctionTool -- the fn/docstring are parsed for the name/description +# FunctionTool ์—†์ด ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค -- ํ•จ์ˆ˜/๋…์ŠคํŠธ๋ง์ด ์ด๋ฆ„/์„ค๋ช…์„ ์œ„ํ•ด ํŒŒ์‹ฑ๋ฉ๋‹ˆ๋‹ค multiply_agent = ReActAgent( name="multiply_agent", - description="Is able to multiply two integers", - system_prompt="A helpful assistant that can use a tool to multiply numbers.", + description="๋‘ ์ •์ˆ˜๋ฅผ ๊ณฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค", + system_prompt="์ˆซ์ž๋ฅผ ๊ณฑํ•˜๋Š” ํˆด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„์›€์ด ๋˜๋Š” ์–ด์‹œ์Šคํ„ดํŠธ์ž…๋‹ˆ๋‹ค.", tools=[multiply], llm=llm, ) addition_agent = ReActAgent( name="add_agent", - description="Is able to add two integers", - system_prompt="A helpful assistant that can use a tool to add numbers.", + description="๋‘ ์ •์ˆ˜๋ฅผ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค", + system_prompt="์ˆซ์ž๋ฅผ ๋”ํ•˜๋Š” ํˆด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„์›€์ด ๋˜๋Š” ์–ด์‹œ์Šคํ„ดํŠธ์ž…๋‹ˆ๋‹ค.", tools=[add], llm=llm, ) -# Create the workflow +# ์›Œํฌํ”Œ๋กœ์šฐ ์ƒ์„ฑ workflow = AgentWorkflow( agents=[multiply_agent, addition_agent], root_agent="multiply_agent", ) -# Run the system -response = await workflow.run(user_msg="Can you add 5 and 3?") +# ์‹œ์Šคํ…œ ์‹คํ–‰ +response = await workflow.run(user_msg="5์™€ 3์„ ๋”ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?") ``` -Agent tools can also modify the workflow state we mentioned earlier. Before starting the workflow, we can provide an initial state dict that will be available to all agents. -The state is stored in the state key of the workflow context. It will be injected into the state_prompt which augments each new user message. +์—์ด์ „ํŠธ ํˆด์€ ์•ž์„œ ์–ธ๊ธ‰ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ ์ƒํƒœ๋„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋ชจ๋“  ์—์ด์ „ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ดˆ๊ธฐ ์ƒํƒœ ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ƒํƒœ๋Š” ์›Œํฌํ”Œ๋กœ์šฐ ์ปจํ…์ŠคํŠธ์˜ ์ƒํƒœ ํ‚ค์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๊ฐ ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๊ฐ•ํ•˜๋Š” state_prompt์— ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค. -Let's inject a counter to count function calls by modifying the previous example: +์ด์ „ ์˜ˆ์ œ๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์„ธ๋Š” ์นด์šดํ„ฐ๋ฅผ ์ฃผ์ž…ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: ```python from llama_index.core.workflow import Context -# Define some tools +# ๋ช‡ ๊ฐ€์ง€ ํˆด ์ •์˜ async def add(ctx: Context, a: int, b: int) -> int: - """Add two numbers.""" - # update our count + """๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•ฉ๋‹ˆ๋‹ค.""" + # ์นด์šดํŠธ ์—…๋ฐ์ดํŠธ cur_state = await ctx.store.get("state") cur_state["num_fn_calls"] += 1 await ctx.store.set("state", cur_state) @@ -249,8 +249,8 @@ async def add(ctx: Context, a: int, b: int) -> int: return a + b async def multiply(ctx: Context, a: int, b: int) -> int: - """Multiply two numbers.""" - # update our count + """๋‘ ์ˆซ์ž๋ฅผ ๊ณฑํ•ฉ๋‹ˆ๋‹ค.""" + # ์นด์šดํŠธ ์—…๋ฐ์ดํŠธ cur_state = await ctx.store.get("state") cur_state["num_fn_calls"] += 1 await ctx.store.set("state", cur_state) @@ -263,18 +263,18 @@ workflow = AgentWorkflow( agents=[multiply_agent, addition_agent], root_agent="multiply_agent", initial_state={"num_fn_calls": 0}, - state_prompt="Current state: {state}. User message: {msg}", + state_prompt="ํ˜„์žฌ ์ƒํƒœ: {state}. ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€: {msg}", ) -# run the workflow with context +# ์ปจํ…์ŠคํŠธ์™€ ํ•จ๊ป˜ ์›Œํฌํ”Œ๋กœ์šฐ ์‹คํ–‰ ctx = Context(workflow) -response = await workflow.run(user_msg="Can you add 5 and 3?", ctx=ctx) +response = await workflow.run(user_msg="5์™€ 3์„ ๋”ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?", ctx=ctx) -# pull out and inspect the state +# ์ƒํƒœ๋ฅผ ๊บผ๋‚ด์„œ ๊ฒ€์‚ฌ state = await ctx.store.get("state") print(state["num_fn_calls"]) ``` -Congratulations! You have now mastered the basics of Agents in LlamaIndex! ๐ŸŽ‰ +์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ LlamaIndex์—์„œ ์—์ด์ „ํŠธ์˜ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ -Let's continue with one final quiz to solidify your knowledge! ๐Ÿš€ +์ง€์‹์„ ํ™•๊ณ ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ๋งˆ์ง€๋ง‰ ํ€ด์ฆˆ๋ฅผ ๊ณ„์†ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! ๐Ÿš€ From f277b1cc91dc0e044bfe253305e0a3d65b0bfc6d Mon Sep 17 00:00:00 2001 From: Jeong Ahn Date: Thu, 10 Jul 2025 16:09:35 +0900 Subject: [PATCH 5/6] feat: nmt draft: smolagents --- units/ko/unit2/introduction.mdx | 48 ++-- units/ko/unit2/smolagents/code_agents.mdx | 262 +++++++++--------- units/ko/unit2/smolagents/conclusion.mdx | 12 +- units/ko/unit2/smolagents/final_quiz.mdx | 22 +- units/ko/unit2/smolagents/introduction.mdx | 64 +++-- .../unit2/smolagents/multi_agent_systems.mdx | 218 +++++++-------- units/ko/unit2/smolagents/quiz1.mdx | 108 ++++---- units/ko/unit2/smolagents/quiz2.mdx | 111 ++++---- .../ko/unit2/smolagents/retrieval_agents.mdx | 116 ++++---- .../unit2/smolagents/tool_calling_agents.mdx | 36 +-- units/ko/unit2/smolagents/tools.mdx | 193 ++++++------- units/ko/unit2/smolagents/vision_agents.mdx | 126 ++++----- .../unit2/smolagents/why_use_smolagents.mdx | 78 +++--- 13 files changed, 669 insertions(+), 725 deletions(-) diff --git a/units/ko/unit2/introduction.mdx b/units/ko/unit2/introduction.mdx index 17af271f..e19d397c 100644 --- a/units/ko/unit2/introduction.mdx +++ b/units/ko/unit2/introduction.mdx @@ -1,40 +1,40 @@ -# Introduction to Agentic Frameworks +# ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ ์†Œ๊ฐœ Thumbnail -Welcome to this second unit, where **we'll explore different agentic frameworks** that can be used to build powerful agentic applications. +Unit 2์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! **์ด๋ฒˆ ์œ ๋‹›์—์„œ๋Š” ๋‹ค์–‘ํ•œ ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ**๋ฅผ ์‚ดํŽด๋ณด๊ณ , ์ด๋ฅผ ํ™œ์šฉํ•ด ๊ฐ•๋ ฅํ•œ ์—์ด์ „ํŠธ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค. -We will study: +์ด๋ฒˆ ์œ ๋‹›์—์„œ ๋‹ค๋ฃฐ ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: -- In Unit 2.1: [smolagents](https://huggingface.co/docs/smolagents/en/index) -- In Unit 2.2: [LlamaIndex](https://www.llamaindex.ai/) -- In Unit 2.3: [LangGraph](https://www.langchain.com/langgraph) +- 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) -Let's dive in! ๐Ÿ•ต +ํ•จ๊ป˜ ์‹œ์ž‘ํ•ด๋ด…์‹œ๋‹ค! ๐Ÿ•ต -## When to Use an Agentic Framework +## ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์–ธ์ œ ํ•„์š”ํ• ๊นŒ? -An agentic framework is **not always needed when building an application around LLMs**. They provide flexibility in the workflow to efficiently solve a specific task, but they're not always necessary. +์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” **LLM ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ๋•Œ ํ•ญ์ƒ ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.** ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ํŠน์ • ์ž‘์—…์„ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ์›Œํฌํ”Œ๋กœ์šฐ์— ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ํ•ญ์ƒ ํ•„์ˆ˜์ ์ธ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. -Sometimes, **predefined workflows are sufficient** to fulfill user requests, and there is no real need for an agentic framework. If the approach to build an agent is simple, like a chain of prompts, using plain code may be enough. The advantage is that the developer will have **full control and understanding of their system without abstractions**. +๋•Œ๋กœ๋Š” **๋ฏธ๋ฆฌ ์ •์˜๋œ ์›Œํฌํ”Œ๋กœ์šฐ๋งŒ์œผ๋กœ๋„** ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ์ถฉ๋ถ„ํžˆ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ตณ์ด ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ ๊ตฌ์กฐ๊ฐ€ ๋‹จ์ˆœํ•˜๋‹ค๋ฉด, ํ”„๋กฌํ”„ํŠธ ์ฒด์ด๋‹ ๋“ฑ ์ผ๋ฐ˜ ์ฝ”๋“œ๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊ฐœ๋ฐœ์ž๋Š” **์ถ”์ƒํ™” ์—†์ด ์‹œ์Šคํ…œ์„ ์™„์ „ํžˆ ์ดํ•ดํ•˜๊ณ  ์ œ์–ด**ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. -However, when the workflow becomes more complex, such as letting an LLM call functions or using multiple agents, these abstractions start to become helpful. +ํ•˜์ง€๋งŒ ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ๋ณต์žกํ•ด์ ธ LLM์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ด๋Ÿฌํ•œ ์ถ”์ƒํ™”๊ฐ€ ๋„์›€์ด ๋˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. -Considering these ideas, we can already identify the need for some features: +์ด๋Ÿฌํ•œ ์ ์„ ๊ณ ๋ คํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•จ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -* An *LLM engine* that powers the system. -* A *list of tools* the agent can access. -* A *parser* for extracting tool calls from the LLM output. -* A *system prompt* synced with the parser. -* A *memory system*. -* *Error logging and retry mechanisms* to control LLM mistakes. +* ์‹œ์Šคํ…œ์„ ๊ตฌ๋™ํ•  *LLM ์—”์ง„* +* ์—์ด์ „ํŠธ๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” *๋„๊ตฌ ๋ชฉ๋ก* +* LLM ์ถœ๋ ฅ์—์„œ ๋„๊ตฌ ํ˜ธ์ถœ์„ ์ถ”์ถœํ•˜๋Š” *ํŒŒ์„œ* +* ํŒŒ์„œ์™€ ๋™๊ธฐํ™”๋œ *์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ* +* *๋ฉ”๋ชจ๋ฆฌ ์‹œ์Šคํ…œ* +* LLM์˜ ์‹ค์ˆ˜๋ฅผ ์ œ์–ดํ•  *์—๋Ÿฌ ๋กœ๊น… ๋ฐ ์žฌ์‹œ๋„ ๋ฉ”์ปค๋‹ˆ์ฆ˜* -We'll explore how these topics are resolved in various frameworks, including `smolagents`, `LlamaIndex`, and `LangGraph`. +์ด๋Ÿฌํ•œ ์ฃผ์ œ๋“ค์ด ๊ฐ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ๋˜๋Š”์ง€, `smolagents`, `LlamaIndex`, `LangGraph`๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. -## Agentic Frameworks Units +## ์—์ด์ „ํ‹ฑ ํ”„๋ ˆ์ž„์›Œํฌ๋ณ„ ์œ ๋‹› ์•ˆ๋‚ด -| Framework | Description | Unit Author | +| ํ”„๋ ˆ์ž„์›Œํฌ | ์„ค๋ช… | ์œ ๋‹› ์ €์ž | |------------|----------------|----------------| -| [smolagents](./smolagents/introduction) | Agents framework developed by 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) | End-to-end tooling to ship a context-augmented AI agent to production | David Berenstein - [HF](https://huggingface.co/davidberenstein1957) - [X](https://x.com/davidberenstei) - [Linkedin](https://www.linkedin.com/in/davidberenstein) | -| [LangGraph](./langgraph/introduction) | Agents allowing stateful orchestration of agents | Joffrey THOMAS - [HF](https://huggingface.co/Jofthomas) - [X](https://x.com/Jthmas404) - [Linkedin](https://www.linkedin.com/in/joffrey-thomas) | +| [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/smolagents/code_agents.mdx b/units/ko/unit2/smolagents/code_agents.mdx index 0e78c5e2..fcba655d 100644 --- a/units/ko/unit2/smolagents/code_agents.mdx +++ b/units/ko/unit2/smolagents/code_agents.mdx @@ -6,73 +6,73 @@ askForHelpUrl="http://hf.co/join/discord" /> -# Building Agents That Use Code +# ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ -Code agents are the default agent type in `smolagents`. They generate Python tool calls to perform actions, achieving action representations that are efficient, expressive, and accurate. +์ฝ”๋“œ ์—์ด์ „ํŠธ๋Š” `smolagents`์˜ ๊ธฐ๋ณธ ์—์ด์ „ํŠธ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. ์ด๋“ค์€ ํŒŒ์ด์ฌ ๋„๊ตฌ ํ˜ธ์ถœ์„ ์ƒ์„ฑํ•˜์—ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ํšจ์œจ์ ์ด๊ณ  ํ‘œํ˜„๋ ฅ ์žˆ์œผ๋ฉฐ ์ •ํ™•ํ•œ ์•ก์…˜ ํ‘œํ˜„์„ ๋‹ฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. -Their streamlined approach reduces the number of required actions, simplifies complex operations, and enables reuse of existing code functions. `smolagents` provides a lightweight framework for building code agents, implemented in approximately 1,000 lines of code. +์ด๋Ÿฌํ•œ ๊ฐ„์†Œํ™”๋œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ํ•„์š”ํ•œ ์•ก์…˜ ์ˆ˜๋ฅผ ์ค„์ด๊ณ , ๋ณต์žกํ•œ ์ž‘์—…์„ ๋‹จ์ˆœํ™”ํ•˜๋ฉฐ, ๊ธฐ์กด ์ฝ”๋“œ ํ•จ์ˆ˜์˜ ์žฌ์‚ฌ์šฉ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. `smolagents`๋Š” ์•ฝ 1,000์ค„์˜ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„๋œ ๊ฒฝ๋Ÿ‰ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -![Code vs JSON Actions](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/code_vs_json_actions.png) -Graphic from the paper [Executable Code Actions Elicit Better LLM Agents](https://huggingface.co/papers/2402.01030) +![์ฝ”๋“œ 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)์—์„œ ๊ฐ€์ ธ์™”์Šต๋‹ˆ๋‹ค. -If you want to learn more about why code agents are effective, check out this guide from the smolagents documentation. +์ฝ”๋“œ ์—์ด์ „ํŠธ๊ฐ€ ์™œ ํšจ๊ณผ์ ์ธ์ง€ ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด, smolagents ๋ฌธ์„œ์˜ ์ด ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. -## Why Code Agents? +## ์™œ ์ฝ”๋“œ ์—์ด์ „ํŠธ์ธ๊ฐ€์š”? -In a multi-step agent process, the LLM writes and executes actions, typically involving external tool calls. Traditional approaches use a JSON format to specify tool names and arguments as strings, **which the system must parse to determine which tool to execute**. +๋‹ค๋‹จ๊ณ„ ์—์ด์ „ํŠธ ํ”„๋กœ์„ธ์Šค์—์„œ LLM์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์™ธ๋ถ€ ๋„๊ตฌ ํ˜ธ์ถœ์„ ํฌํ•จํ•˜๋Š” ์•ก์…˜์„ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๋ฐฉ์‹์€ ๋„๊ตฌ ์ด๋ฆ„๊ณผ ์ธ์ž๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ง€์ •ํ•˜๋Š” JSON ํ˜•์‹์„ ์‚ฌ์šฉํ•˜๋ฉฐ, **์‹œ์Šคํ…œ์ด ์–ด๋–ค ๋„๊ตฌ๋ฅผ ์‹คํ–‰ํ• ์ง€ ํŒŒ์‹ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค**. -However, research shows that **tool-calling LLMs work more effectively with code directly**. This is a core principle of `smolagents`, as shown in the diagram above from [Executable Code Actions Elicit Better LLM Agents](https://huggingface.co/papers/2402.01030). +ํ•˜์ง€๋งŒ ์—ฐ๊ตฌ ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅด๋ฉด, **๋„๊ตฌ ํ˜ธ์ถœ LLM์€ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋” ํšจ๊ณผ์ ์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค**. ์ด๊ฒƒ์ด `smolagents`์˜ ํ•ต์‹ฌ ์›์น™์ด๋ฉฐ, ์œ„์˜ ๋…ผ๋ฌธ ์ด๋ฏธ์ง€์—์„œ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Writing actions in code rather than JSON offers several key advantages: +์ฝ”๋“œ๋กœ ์•ก์…˜์„ ์ž‘์„ฑํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฃผ์š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค: -* **Composability**: Easily combine and reuse actions -* **Object Management**: Work directly with complex structures like images -* **Generality**: Express any computationally possible task -* **Natural for LLMs**: High-quality code is already present in LLM training data +* **์กฐํ•ฉ์„ฑ**: ์•ก์…˜์„ ์‰ฝ๊ฒŒ ๊ฒฐํ•ฉํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* **๊ฐ์ฒด ๊ด€๋ฆฌ**: ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ๋ณต์žกํ•œ ๊ตฌ์กฐ๋ฅผ ์ง์ ‘ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* **๋ฒ”์šฉ์„ฑ**: ๊ณ„์‚ฐ์ ์œผ๋กœ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์ž‘์—…์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* **LLM์— ์ž์—ฐ์Šค๋Ÿฌ์›€**: ๊ณ ํ’ˆ์งˆ ์ฝ”๋“œ๋Š” ์ด๋ฏธ LLM์˜ ํ•™์Šต ๋ฐ์ดํ„ฐ์— ํ’๋ถ€ํ•˜๊ฒŒ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. -## How Does a Code Agent Work? +## ์ฝ”๋“œ ์—์ด์ „ํŠธ๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋‚˜์š”? -![From https://huggingface.co/docs/smolagents/conceptual_guides/react](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/codeagent_docs.png) +![https://huggingface.co/docs/smolagents/conceptual_guides/react์—์„œ ๊ฐ€์ ธ์˜ด](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/codeagent_docs.png) -The diagram above illustrates how `CodeAgent.run()` operates, following the ReAct framework we mentioned in Unit 1. The main abstraction for agents in `smolagents` is a `MultiStepAgent`, which serves as the core building block. `CodeAgent` is a special kind of `MultiStepAgent`, as we will see in an example below. +์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์€ `CodeAgent.run()`์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์ด๋Š” 1๋‹จ์›์—์„œ ์–ธ๊ธ‰ํ•œ ReAct ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. `smolagents`์—์„œ ์—์ด์ „ํŠธ์˜ ์ฃผ์š” ์ถ”์ƒํ™”๋Š” `MultiStepAgent`์ด๋ฉฐ, ์ด๋Š” ํ•ต์‹ฌ ๋นŒ๋”ฉ ๋ธ”๋ก ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. `CodeAgent`๋Š” ํŠน๋ณ„ํ•œ ์ข…๋ฅ˜์˜ `MultiStepAgent`์ž…๋‹ˆ๋‹ค. -A `CodeAgent` performs actions through a cycle of steps, with existing variables and knowledge being incorporated into the agent's context, which is kept in an execution log: +`CodeAgent`๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๋ณ€์ˆ˜์™€ ์ง€์‹์€ ์‹คํ–‰ ๋กœ๊ทธ์— ์ €์žฅ๋˜์–ด ์—์ด์ „ํŠธ์˜ ์ปจํ…์ŠคํŠธ๋กœ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค: -1. The system prompt is stored in a `SystemPromptStep`, and the user query is logged in a `TaskStep`. +1. ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ๋Š” `SystemPromptStep`์— ์ €์žฅ๋˜๊ณ , ์‚ฌ์šฉ์ž ์ฟผ๋ฆฌ๋Š” `TaskStep`์— ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. -2. Then, the following while loop is executed: +2. ๊ทธ ๋‹ค์Œ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ while ๋ฃจํ”„๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค: - 2.1 Method `agent.write_memory_to_messages()` writes the agent's logs into a list of LLM-readable [chat messages](https://huggingface.co/docs/transformers/main/en/chat_templating). + 2.1 `agent.write_memory_to_messages()` ๋ฉ”์„œ๋“œ๋Š” ์—์ด์ „ํŠธ์˜ ๋กœ๊ทธ๋ฅผ LLM์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” [์ฑ„ํŒ… ๋ฉ”์‹œ์ง€](https://huggingface.co/docs/transformers/main/en/chat_templating) ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. - 2.2 These messages are sent to a `Model`, which generates a completion. + 2.2 ์ด ๋ฉ”์‹œ์ง€๋“ค์€ `Model`๋กœ ์ „์†ก๋˜์–ด ์‘๋‹ต์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. - 2.3 The completion is parsed to extract the action, which, in our case, should be a code snippet since we're working with a `CodeAgent`. + 2.3 ์‘๋‹ต์—์„œ ์•ก์…˜์„ ์ถ”์ถœํ•˜๋Š”๋ฐ, ์ฝ”๋“œ ์—์ด์ „ํŠธ์ด๋ฏ€๋กœ ํŒŒ์ด์ฌ ์ฝ”๋“œ ์กฐ๊ฐ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - 2.4 The action is executed. + 2.4 ์•ก์…˜์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. - 2.5 The results are logged into memory in an `ActionStep`. + 2.5 ๊ฒฐ๊ณผ๊ฐ€ `ActionStep`์— ๋ฉ”๋ชจ๋ฆฌ๋กœ ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. -At the end of each step, if the agent includes any function calls (in `agent.step_callback`), they are executed. +๊ฐ ๋‹จ๊ณ„๊ฐ€ ๋๋‚  ๋•Œ, ์—์ด์ „ํŠธ์— ํ•จ์ˆ˜ ํ˜ธ์ถœ(`agent.step_callback`)์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋ฉด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. -## Let's See Some Examples +## ์˜ˆ์‹œ๋กœ ์•Œ์•„๋ณด๊ธฐ -You can follow the code in this notebook that you can run using Google Colab. +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Alfred is planning a party at the Wayne family mansion and needs your help to ensure everything goes smoothly. To assist him, we'll apply what we've learned about how a multi-step `CodeAgent` operates. +Alfred๋Š” ์›จ์ธ ๊ฐ€๋ฌธ์˜ ์ €ํƒ์—์„œ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ์ˆœ์กฐ๋กญ๊ฒŒ ์ง„ํ–‰๋˜๋„๋ก ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๋‹ค๋‹จ๊ณ„ `CodeAgent`์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ ์šฉํ•ด๋ด…์‹œ๋‹ค. Alfred Party -If you haven't installed `smolagents` yet, you can do so by running the following command: +์•„์ง `smolagents`๋ฅผ ์„ค์น˜ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ์„ค์น˜ํ•˜์„ธ์š”: ```bash pip install smolagents -U ``` -Let's also login to the Hugging Face Hub to have access to the Serverless Inference API. +Hugging Face Hub์— ๋กœ๊ทธ์ธํ•˜์—ฌ Serverless Inference API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ```python from huggingface_hub import login @@ -80,90 +80,90 @@ from huggingface_hub import login login() ``` -### Selecting a Playlist for the Party Using `smolagents` +### `smolagents`๋กœ ํŒŒํ‹ฐ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์„ ํƒํ•˜๊ธฐ -Music is an essential part of a successful party! Alfred needs some help selecting the playlist. Luckily, `smolagents` has got us covered! We can build an agent capable of searching the web using DuckDuckGo. To give the agent access to this tool, we include it in the tool list when creating the agent. +์Œ์•…์€ ํŒŒํ‹ฐ์˜ ํ•„์ˆ˜ ์š”์†Œ์ž…๋‹ˆ๋‹ค! Alfred๋Š” ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ๊ณ ๋ฅด๋Š” ๋ฐ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„ `smolagents`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์›น ๊ฒ€์ƒ‰ ๋„๊ตฌ๋ฅผ ์—์ด์ „ํŠธ์— ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Alfred Playlist -For the model, we'll rely on `InferenceClientModel`, which provides access to Hugging Face's [Serverless Inference API](https://huggingface.co/docs/api-inference/index). The default model is `"Qwen/Qwen2.5-Coder-32B-Instruct"`, which is performant and available for fast inference, but you can select any compatible model from the Hub. +๋ชจ๋ธ๋กœ๋Š” Hugging Face์˜ [Serverless Inference API](https://huggingface.co/docs/api-inference/index)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” `InferenceClientModel`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๋ชจ๋ธ์€ "Qwen/Qwen2.5-Coder-32B-Instruct"์ด๋ฉฐ, ๋น ๋ฅธ ์ถ”๋ก ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ—ˆ๋ธŒ์—์„œ ํ˜ธํ™˜๋˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋ธ๋„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Running an agent is quite straightforward: +์—์ด์ „ํŠธ ์‹คํ–‰์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค: ```python from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=InferenceClientModel()) -agent.run("Search for the best music recommendations for a party at the Wayne's mansion.") +agent.run("์›จ์ธ ์ €ํƒ์—์„œ ์—ด๋ฆฌ๋Š” ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ์Œ์•… ์ถ”์ฒœ์„ ๊ฒ€์ƒ‰ํ•ด์ค˜.") ``` -When you run this example, the output will **display a trace of the workflow steps being executed**. It will also print the corresponding Python code with the message: +์ด ์˜ˆ์‹œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด **์›Œํฌํ”Œ๋กœ์šฐ ๋‹จ๊ณ„์˜ ์‹คํ–‰ ์ถ”์ **์ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ด์ฌ ์ฝ”๋“œ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค: ```python - โ”€ Executing parsed code: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - results = web_search(query="best music for a Batman party") - print(results) - โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + โ”€ ์‹คํ–‰๋œ ํŒŒ์‹ฑ ์ฝ”๋“œ: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + results = web_search(query="๋ฐฐํŠธ๋งจ ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ์Œ์•…") + print(results) + โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ``` -After a few steps, you'll see the generated playlist that Alfred can use for the party! ๐ŸŽต +๋ช‡ ๋‹จ๊ณ„ ํ›„, Alfred๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค! ๐ŸŽต -### Using a Custom Tool to Prepare the Menu +### ๋งž์ถคํ˜• ๋„๊ตฌ๋กœ ๋ฉ”๋‰ด ์ค€๋น„ํ•˜๊ธฐ Alfred Menu -Now that we have selected a playlist, we need to organize the menu for the guests. Again, Alfred can take advantage of `smolagents` to do so. Here, we use the `@tool` decorator to define a custom function that acts as a tool. We'll cover tool creation in more detail later, so for now, we can simply run the code. +ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ๊ณจ๋ž๋‹ค๋ฉด, ์ด์ œ ์†๋‹˜์„ ์œ„ํ•œ ๋ฉ”๋‰ด๋ฅผ ์ค€๋น„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Alfred๋Š” ์—ฌ๊ธฐ์„œ๋„ `smolagents`์˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋งž์ถคํ˜• ํ•จ์ˆ˜๋ฅผ ๋„๊ตฌ๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๋„๊ตฌ ์ƒ์„ฑ์— ๋Œ€ํ•ด์„œ๋Š” ์ดํ›„์— ๋” ์ž์„ธํžˆ ๋‹ค๋ฃจ๋‹ˆ, ์ง€๊ธˆ์€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด์„ธ์š”. -As you can see in the example below, we will create a tool using the `@tool` decorator and include it in the `tools` list. +์•„๋ž˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ, `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค๊ณ  `tools` ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ```python from smolagents import CodeAgent, tool, InferenceClientModel -# Tool to suggest a menu based on the occasion +# ํŒŒํ‹ฐ ์ƒํ™ฉ์— ๋งž๋Š” ๋ฉ”๋‰ด๋ฅผ ์ถ”์ฒœํ•˜๋Š” ๋„๊ตฌ @tool def suggest_menu(occasion: str) -> str: """ - Suggests a menu based on the occasion. + ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ฉ”๋‰ด๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. Args: - occasion (str): The type of occasion for the party. Allowed values are: - - "casual": Menu for casual party. - - "formal": Menu for formal party. - - "superhero": Menu for superhero party. - - "custom": Custom menu. + occasion (str): ํŒŒํ‹ฐ ์œ ํ˜•. ํ—ˆ์šฉ ๊ฐ’: + - "casual": ์บ์ฃผ์–ผ ํŒŒํ‹ฐ ๋ฉ”๋‰ด + - "formal": ํฌ๋ฉ€ ํŒŒํ‹ฐ ๋ฉ”๋‰ด + - "superhero": ์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ ๋ฉ”๋‰ด + - "custom": ๋งž์ถค ๋ฉ”๋‰ด """ if occasion == "casual": - return "Pizza, snacks, and drinks." + return "ํ”ผ์ž, ์Šค๋‚ต, ์Œ๋ฃŒ." elif occasion == "formal": - return "3-course dinner with wine and dessert." + return "3์ฝ”์Šค ๋””๋„ˆ, ์™€์ธ, ๋””์ €ํŠธ." elif occasion == "superhero": - return "Buffet with high-energy and healthy food." + return "๊ณ ์—๋„ˆ์ง€, ๊ฑด๊ฐ•์‹ ๋ท”ํŽ˜." else: - return "Custom menu for the butler." + return "์ง‘์‚ฌ๋งŒ์„ ์œ„ํ•œ ๋งž์ถค ๋ฉ”๋‰ด." -# Alfred, the butler, preparing the menu for the party +# Alfred๊ฐ€ ํŒŒํ‹ฐ ๋ฉ”๋‰ด๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค agent = CodeAgent(tools=[suggest_menu], model=InferenceClientModel()) -# Preparing the menu for the party -agent.run("Prepare a formal menu for the party.") +# ํŒŒํ‹ฐ๋ฅผ ์œ„ํ•œ ํฌ๋ฉ€ ๋ฉ”๋‰ด ์ค€๋น„ +agent.run("ํŒŒํ‹ฐ๋ฅผ ์œ„ํ•œ ํฌ๋ฉ€ ๋ฉ”๋‰ด๋ฅผ ์ค€๋น„ํ•ด์ค˜.") ``` -The agent will run for a few steps until finding the answer. Precising allowed values in the docstring helps direct agent to `occasion` argument values which exist and limit hallucinations. +์—์ด์ „ํŠธ๋Š” ๋ช‡ ๋‹จ๊ณ„ ์‹คํ–‰ ํ›„ ๋‹ต์„ ์ฐพ์Šต๋‹ˆ๋‹ค. docstring์— ํ—ˆ์šฉ ๊ฐ’์„ ๋ช…ํ™•ํžˆ ์ ์œผ๋ฉด ์—์ด์ „ํŠธ๊ฐ€ `occasion` ์ธ์ž ๊ฐ’์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก ์œ ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -The menu is ready! ๐Ÿฅ— +๋ฉ”๋‰ด ์ค€๋น„ ์™„๋ฃŒ! ๐Ÿฅ— -### Using Python Imports Inside the Agent +### ์—์ด์ „ํŠธ ๋‚ด์—์„œ ํŒŒ์ด์ฌ import ์‚ฌ์šฉํ•˜๊ธฐ -We have the playlist and menu ready, but we need to check one more crucial detail: preparation time! +ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ์™€ ๋ฉ”๋‰ด๊ฐ€ ์ค€๋น„๋˜์—ˆ์œผ๋‹ˆ, ์ด์ œ ๋‚จ์€ ๊ฒƒ์€ ์ค€๋น„ ์‹œ๊ฐ„ ๊ณ„์‚ฐ์ž…๋‹ˆ๋‹ค! -Alfred needs to calculate when everything would be ready if he started preparing now, in case they need assistance from other superheroes. +Alfred๋Š” ๋ชจ๋“  ์ค€๋น„๋ฅผ ์ง€๊ธˆ ์‹œ์ž‘ํ•˜๋ฉด ์–ธ์ œ ํŒŒํ‹ฐ๊ฐ€ ์ค€๋น„๋ ์ง€ ๊ณ„์‚ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•˜๋‹ค๋ฉด ๋‹ค๋ฅธ ์Šˆํผํžˆ์–ด๋กœ์˜ ๋„์›€๋„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒ ์ฃ . -`smolagents` specializes in agents that write and execute Python code snippets, offering sandboxed execution for security. +`smolagents`๋Š” ํŒŒ์ด์ฌ ์ฝ”๋“œ ์กฐ๊ฐ์„ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ์—์ด์ „ํŠธ์— ํŠนํ™”๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋ณด์•ˆ์„ ์œ„ํ•ด ์ƒŒ๋“œ๋ฐ•์Šค ์‹คํ–‰์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -**Code execution has strict security measures** - imports outside a predefined safe list are blocked by default. However, you can authorize additional imports by passing them as strings in `additional_authorized_imports`. -For more details on secure code execution, see the official [guide](https://huggingface.co/docs/smolagents/tutorials/secure_code_execution). +**์ฝ”๋“œ ์‹คํ–‰์—๋Š” ์—„๊ฒฉํ•œ ๋ณด์•ˆ ์กฐ์น˜๊ฐ€ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค** โ€” ๊ธฐ๋ณธ์ ์œผ๋กœ ํ—ˆ์šฉ๋œ ๋ชฉ๋ก ์™ธ์˜ import๋Š” ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ `additional_authorized_imports`์— ๋ฌธ์ž์—ด๋กœ ์ถ”๊ฐ€ํ•˜๋ฉด import๋ฅผ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ž์„ธํ•œ ๋ณด์•ˆ ์‹คํ–‰ ๋ฐฉ๋ฒ•์€ ๊ณต์‹ [๊ฐ€์ด๋“œ](https://huggingface.co/docs/smolagents/tutorials/secure_code_execution)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. -When creating the agent, we'll use `additional_authorized_imports` to allow for importing the `datetime` module. +์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” `datetime` ๋ชจ๋“ˆ import๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ```python from smolagents import CodeAgent, InferenceClientModel @@ -175,46 +175,42 @@ agent = CodeAgent(tools=[], model=InferenceClientModel(), additional_authorized_ agent.run( """ - Alfred needs to prepare for the party. Here are the tasks: - 1. Prepare the drinks - 30 minutes - 2. Decorate the mansion - 60 minutes - 3. Set up the menu - 45 minutes - 4. Prepare the music and playlist - 45 minutes + Alfred๊ฐ€ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—… ๋ชฉ๋ก: + 1. ์Œ๋ฃŒ ์ค€๋น„ - 30๋ถ„ + 2. ์ €ํƒ ์žฅ์‹ - 60๋ถ„ + 3. ๋ฉ”๋‰ด ์„ธํŒ… - 45๋ถ„ + 4. ์Œ์•… ๋ฐ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ค€๋น„ - 45๋ถ„ - If we start right now, at what time will the party be ready? + ์ง€๊ธˆ ๋ฐ”๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํŒŒํ‹ฐ ์ค€๋น„๊ฐ€ ์–ธ์ œ ๋๋‚ ๊นŒ์š”? """ ) ``` +์ด ์˜ˆ์‹œ๋“ค์€ ์ฝ”๋“œ ์—์ด์ „ํŠธ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์˜ ์‹œ์ž‘์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ๋‚ด์šฉ์€ [smolagents ๋ฌธ์„œ](https://huggingface.co/docs/smolagents)์—์„œ ํ™•์ธํ•˜์„ธ์š”. -These examples are just the beginning of what you can do with code agents, and we're already starting to see their utility for preparing the party. -You can learn more about how to build code agents in the [smolagents documentation](https://huggingface.co/docs/smolagents). +์š”์•ฝํ•˜์ž๋ฉด, `smolagents`๋Š” ํŒŒ์ด์ฌ ์ฝ”๋“œ ์กฐ๊ฐ์„ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ์—์ด์ „ํŠธ์— ํŠนํ™”๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋ณด์•ˆ ์ƒŒ๋“œ๋ฐ•์Šค ์‹คํ–‰์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋กœ์ปฌ ๋ฐ API ๊ธฐ๋ฐ˜ ์–ธ์–ด ๋ชจ๋ธ ๋ชจ๋‘ ์ง€์›ํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. -In summary, `smolagents` specializes in agents that write and execute Python code snippets, offering sandboxed execution for security. It supports both local and API-based language models, making it adaptable to various development environments. +### ์šฐ๋ฆฌ๋งŒ์˜ ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ๋ฅผ ํ—ˆ๋ธŒ์— ๊ณต์œ ํ•˜๊ธฐ -### Sharing Our Custom Party Preparator Agent to the Hub - -Wouldn't it be **amazing to share our very own Alfred agent with the community**? By doing so, anyone can easily download and use the agent directly from the Hub, bringing the ultimate party planner of Gotham to their fingertips! Let's make it happen! ๐ŸŽ‰ - -The `smolagents` library makes this possible by allowing you to share a complete agent with the community and download others for immediate use. It's as simple as the following: +์šฐ๋ฆฌ๋งŒ์˜ Alfred ์—์ด์ „ํŠธ๋ฅผ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ •๋ง ๋ฉ‹์ง€์ง€ ์•Š์„๊นŒ์š”? ๋ˆ„๊ตฌ๋‚˜ ํ—ˆ๋ธŒ์—์„œ ์‰ฝ๊ฒŒ ๋‹ค์šด๋กœ๋“œํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! `smolagents`๋Š” ์™„์„ฑ๋œ ์—์ด์ „ํŠธ๋ฅผ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๊ณต์œ ํ•˜๊ณ , ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ ์—์ด์ „ํŠธ๋ฅผ ์ฆ‰์‹œ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค: ```python -# Change to your username and repo name +# ์‚ฌ์šฉ์ž๋ช…๊ณผ ์ €์žฅ์†Œ๋ช…์„ ๋ณ€๊ฒฝํ•˜์„ธ์š” agent.push_to_hub('sergiopaniego/AlfredAgent') ``` -To download the agent again, use the code below: +๋‹ค์‹œ ๋‹ค์šด๋กœ๋“œํ•˜๋ ค๋ฉด ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”: ```python -# Change to your username and repo name +# ์‚ฌ์šฉ์ž๋ช…๊ณผ ์ €์žฅ์†Œ๋ช…์„ ๋ณ€๊ฒฝํ•˜์„ธ์š” alfred_agent = agent.from_hub('sergiopaniego/AlfredAgent', trust_remote_code=True) -alfred_agent.run("Give me the best playlist for a party at Wayne's mansion. The party idea is a 'villain masquerade' theme") +alfred_agent.run("์›จ์ธ ์ €ํƒ์—์„œ ์—ด๋ฆฌ๋Š” ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ•ด์ค˜. ํŒŒํ‹ฐ ํ…Œ๋งˆ๋Š” '๋นŒ๋Ÿฐ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ'์•ผ") ``` -What's also exciting is that shared agents are directly available as Hugging Face Spaces, allowing you to interact with them in real-time. You can explore other agents [here](https://huggingface.co/spaces/davidberenstein1957/smolagents-and-tools). +๊ณต์œ ๋œ ์—์ด์ „ํŠธ๋Š” Hugging Face Spaces์—์„œ๋„ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. [์—ฌ๊ธฐ](https://huggingface.co/spaces/davidberenstein1957/smolagents-and-tools)์—์„œ ๋‹ค์–‘ํ•œ ์—์ด์ „ํŠธ๋ฅผ ํƒ์ƒ‰ํ•ด๋ณด์„ธ์š”. -For example, the _AlfredAgent_ is available [here](https://huggingface.co/spaces/sergiopaniego/AlfredAgent). You can try it out directly below: +์˜ˆ๋ฅผ ๋“ค์–ด, _AlfredAgent_๋Š” [์—ฌ๊ธฐ](https://huggingface.co/spaces/sergiopaniego/AlfredAgent)์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ ์ง์ ‘ ์ฒดํ—˜ํ•ด๋ณด์„ธ์š”: -You may be wonderingโ€”how did Alfred build such an agent using `smolagents`? By integrating several tools, he can generate an agent as follows. Don't worry about the tools for now, as we'll have a dedicated section later in this unit to explore that in detail: +Alfred๊ฐ€ ์–ด๋–ป๊ฒŒ ์ด๋Ÿฐ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ๋Š”์ง€ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด, ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ํ†ตํ•ฉํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ์—์ด์ „ํŠธ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋„๊ตฌ์— ๋Œ€ํ•ด์„œ๋Š” ์ดํ›„์— ์ž์„ธํžˆ ๋‹ค๋ฃจ๋‹ˆ, ์ง€๊ธˆ์€ ๊ตฌ์กฐ๋งŒ ์ฐธ๊ณ ํ•˜์„ธ์š”: ```python from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, InferenceClientModel, Tool, tool, VisitWebpageTool @@ -231,35 +227,35 @@ from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, Inferen @tool def suggest_menu(occasion: str) -> str: """ - Suggests a menu based on the occasion. + ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ฉ”๋‰ด๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. Args: - occasion: The type of occasion for the party. + occasion: ํŒŒํ‹ฐ ์œ ํ˜• """ if occasion == "casual": - return "Pizza, snacks, and drinks." + return "ํ”ผ์ž, ์Šค๋‚ต, ์Œ๋ฃŒ." elif occasion == "formal": - return "3-course dinner with wine and dessert." + return "3์ฝ”์Šค ๋””๋„ˆ, ์™€์ธ, ๋””์ €ํŠธ." elif occasion == "superhero": - return "Buffet with high-energy and healthy food." + return "๊ณ ์—๋„ˆ์ง€, ๊ฑด๊ฐ•์‹ ๋ท”ํŽ˜." else: - return "Custom menu for the butler." + return "์ง‘์‚ฌ๋งŒ์„ ์œ„ํ•œ ๋งž์ถค ๋ฉ”๋‰ด." @tool def catering_service_tool(query: str) -> str: """ - This tool returns the highest-rated catering service in Gotham City. + ์ด ๋„๊ตฌ๋Š” ๊ณ ๋‹ด์‹œ์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. Args: - query: A search term for finding catering services. + query: ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค ๊ฒ€์ƒ‰์–ด """ - # Example list of catering services and their ratings + # ์˜ˆ์‹œ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค์™€ ํ‰์  services = { "Gotham Catering Co.": 4.9, "Wayne Manor Catering": 4.8, "Gotham City Events": 4.7, } - # Find the highest rated catering service (simulating search query filtering) + # ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์„œ๋น„์Šค ์ฐพ๊ธฐ(๊ฒ€์ƒ‰์–ด ํ•„ํ„ฐ๋ง ์‹œ๋ฎฌ๋ ˆ์ด์…˜) best_service = max(services, key=services.get) return best_service @@ -267,13 +263,13 @@ def catering_service_tool(query: str) -> str: class SuperheroPartyThemeTool(Tool): name = "superhero_party_theme_generator" description = """ - This tool suggests creative superhero-themed party ideas based on a category. - It returns a unique party theme idea.""" + ์ด ๋„๊ตฌ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์— ๋”ฐ๋ผ ์ฐฝ์˜์ ์ธ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. + ๊ณ ์œ ํ•œ ํŒŒํ‹ฐ ํ…Œ๋งˆ ์•„์ด๋””์–ด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" inputs = { "category": { "type": "string", - "description": "The type of superhero party (e.g., 'classic heroes', 'villain masquerade', 'futuristic Gotham').", + "description": "์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ ์œ ํ˜•(์˜ˆ: 'classic heroes', 'villain masquerade', 'futuristic Gotham')", } } @@ -281,15 +277,15 @@ class SuperheroPartyThemeTool(Tool): def forward(self, category: str): themes = { - "classic heroes": "Justice League Gala: Guests come dressed as their favorite DC heroes with themed cocktails like 'The Kryptonite Punch'.", - "villain masquerade": "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains.", - "futuristic Gotham": "Neo-Gotham Night: A cyberpunk-style party inspired by Batman Beyond, with neon decorations and futuristic gadgets." + "classic heroes": "Justice League Gala: ์†๋‹˜๋“ค์ด DC ์˜์›…์œผ๋กœ ๋ถ„์žฅํ•˜๊ณ  'ํฌ๋ฆฝํ† ๋‚˜์ดํŠธ ํŽ€์น˜' ๊ฐ™์€ ํ…Œ๋งˆ ์นตํ…Œ์ผ์„ ์ฆ๊น๋‹ˆ๋‹ค.", + "villain masquerade": "Gotham Rogues' Ball: ์†๋‹˜๋“ค์ด ๋ฐฐํŠธ๋งจ ๋นŒ๋Ÿฐ์œผ๋กœ ๋ถ„์žฅํ•˜๋Š” ์‹ ๋น„๋กœ์šด ๊ฐ€๋ฉด๋ฌด๋„ํšŒ.", + "futuristic Gotham": "Neo-Gotham Night: ๋ฐฐํŠธ๋งจ ๋น„์š˜๋“œ์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ์‚ฌ์ด๋ฒ„ํŽ‘ํฌ ์Šคํƒ€์ผ ํŒŒํ‹ฐ, ๋„ค์˜จ ์žฅ์‹๊ณผ ๋ฏธ๋ž˜ํ˜• ์†Œํ’ˆ.", } - return themes.get(category.lower(), "Themed party idea not found. Try 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.") + return themes.get(category.lower(), "ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. 'classic heroes', 'villain masquerade', 'futuristic Gotham' ์ค‘์—์„œ ์‹œ๋„ํ•ด๋ณด์„ธ์š”.") -# Alfred, the butler, preparing the menu for the party +# Alfred๊ฐ€ ํŒŒํ‹ฐ ๋ฉ”๋‰ด๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค agent = CodeAgent( tools=[ DuckDuckGoSearchTool(), @@ -304,34 +300,34 @@ agent = CodeAgent( verbosity_level=2 ) -agent.run("Give me the best playlist for a party at the Wayne's mansion. The party idea is a 'villain masquerade' theme") +agent.run("์›จ์ธ ์ €ํƒ์—์„œ ์—ด๋ฆฌ๋Š” ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ•ด์ค˜. ํŒŒํ‹ฐ ํ…Œ๋งˆ๋Š” '๋นŒ๋Ÿฐ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ'์•ผ") ``` -As you can see, we've created a `CodeAgent` with several tools that enhance the agent's functionality, turning it into the ultimate party planner ready to share with the community! ๐ŸŽ‰ +์ด์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ๊ฒฐํ•ฉํ•ด `CodeAgent`๋ฅผ ๋งŒ๋“ค๋ฉด, ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ถ๊ทน์˜ ํŒŒํ‹ฐ ํ”Œ๋ž˜๋„ˆ๊ฐ€ ์™„์„ฑ๋ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ -Now, it's your turn: build your very own agent and share it with the community using the knowledge we've just learned! ๐Ÿ•ต๏ธโ€โ™‚๏ธ๐Ÿ’ก +์ด์ œ ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค: ์ž์‹ ๋งŒ์˜ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ํ—ˆ๋ธŒ์— ๊ณต์œ ํ•ด๋ณด์„ธ์š”! ๐Ÿ•ต๏ธโ€โ™‚๏ธ๐Ÿ’ก -If you would like to share your agent project, then make a space and tag the agents-course on the Hugging Face Hub. We'd love to see what you've created! +์—ฌ๋Ÿฌ๋ถ„์˜ ์—์ด์ „ํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ณต์œ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, Hugging Face Hub์— space๋ฅผ ๋งŒ๋“ค๊ณ  agents-course ํƒœ๊ทธ๋ฅผ ๋‹ฌ์•„์ฃผ์„ธ์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ์ž‘ํ’ˆ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค! -### Inspecting Our Party Preparator Agent with OpenTelemetry and Langfuse ๐Ÿ“ก +### OpenTelemetry์™€ Langfuse๋กœ ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ ์ถ”์ ํ•˜๊ธฐ ๐Ÿ“ก -As Alfred fine-tunes the Party Preparator Agent, he's growing weary of debugging its runs. Agents, by nature, are unpredictable and difficult to inspect. But since he aims to build the ultimate Party Preparator Agent and deploy it in production, he needs robust traceability for future monitoring and analysis. +Alfred๋Š” ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ๋ฅผ ๋‹ค๋“ฌ์œผ๋ฉด์„œ ์‹คํ–‰์„ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐ ์ง€์ณ๊ฐ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ , ๋™์ž‘์„ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ถ๊ทน์˜ ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ฐฐํฌํ•˜๋ ค๋ฉด, ๋ฏธ๋ž˜์˜ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๋ถ„์„์„ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ์ถ”์  ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. -Once again, `smolagents` comes to the rescue! It embraces the [OpenTelemetry](https://opentelemetry.io/) standard for instrumenting agent runs, allowing seamless inspection and logging. With the help of [Langfuse](https://langfuse.com/) and the `SmolagentsInstrumentor`, Alfred can easily track and analyze his agentโ€™s behavior. +์—ฌ๊ธฐ์„œ๋„ `smolagents`๊ฐ€ ํ•ด๊ฒฐ์ฑ…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค! [OpenTelemetry](https://opentelemetry.io/) ํ‘œ์ค€์„ ์ฑ„ํƒํ•ด ์—์ด์ „ํŠธ ์‹คํ–‰์„ ๊ณ„์ธกํ•˜๊ณ , [Langfuse](https://langfuse.com/) ๋ฐ `SmolagentsInstrumentor`๋ฅผ ํ†ตํ•ด ๋™์ž‘์„ ์‰ฝ๊ฒŒ ์ถ”์ ยท๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Setting it up is straightforward! +์„ค์ • ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค! -First, we need to install the necessary dependencies: +๋จผ์ €, ํ•„์š”ํ•œ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค: ```bash pip install opentelemetry-sdk opentelemetry-exporter-otlp openinference-instrumentation-smolagents ``` -Next, Alfred has already created an account on Langfuse and has his API keys ready. If you havenโ€™t done so yet, you can sign up for Langfuse Cloud [here](https://cloud.langfuse.com/) or explore [alternatives](https://huggingface.co/docs/smolagents/tutorials/inspect_runs). +Alfred๋Š” ์ด๋ฏธ Langfuse ๊ณ„์ •์„ ๋งŒ๋“ค๊ณ  API ํ‚ค๋ฅผ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์•„์ง ๊ณ„์ •์ด ์—†๋‹ค๋ฉด [์—ฌ๊ธฐ](https://cloud.langfuse.com/)์—์„œ ๊ฐ€์ž…ํ•˜๊ฑฐ๋‚˜ [๋Œ€์•ˆ](https://huggingface.co/docs/smolagents/tutorials/inspect_runs)์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. -Once you have your API keys, they need to be properly configured as follows: +API ํ‚ค๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค: ```python import os @@ -341,12 +337,12 @@ 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 data region -# os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://us.cloud.langfuse.com/api/public/otel" # US data region +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}" ``` -Finally, Alfred is ready to initialize the `SmolagentsInstrumentor` and start tracking his agent's performance. +๋งˆ์ง€๋ง‰์œผ๋กœ, `SmolagentsInstrumentor`๋ฅผ ์ดˆ๊ธฐํ™”ํ•ด ์ถ”์ ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ```python from opentelemetry.sdk.trace import TracerProvider @@ -361,33 +357,33 @@ trace_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter())) SmolagentsInstrumentor().instrument(tracer_provider=trace_provider) ``` -Alfred is now connected ๐Ÿ”Œ! The runs from `smolagents` are being logged in Langfuse, giving him full visibility into the agent's behavior. With this setup, he's ready to revisit previous runs and refine his Party Preparator Agent even further. +์ด์ œ Alfred๋Š” ์—ฐ๊ฒฐ ์™„๋ฃŒ! ๐Ÿ”Œ `smolagents`์˜ ์‹คํ–‰์ด Langfuse์— ๊ธฐ๋ก๋˜์–ด, ์—์ด์ „ํŠธ์˜ ๋™์ž‘์„ ์™„๋ฒฝํ•˜๊ฒŒ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์„ค์ •์œผ๋กœ ์ด์ „ ์‹คํ–‰์„ ๋‹ค์‹œ ํ™•์ธํ•˜๊ณ , ํŒŒํ‹ฐ ์ค€๋น„ ์—์ด์ „ํŠธ๋ฅผ ๋”์šฑ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -To learn more about tracing your agents and using the collected data to evaluate their performance, check out Bonus Unit 2. +์—์ด์ „ํŠธ ์ถ”์  ๋ฐ ํ‰๊ฐ€ ๋ฐ์ดํ„ฐ ํ™œ์šฉ๋ฒ•์€ ๋ณด๋„ˆ์Šค 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("Give me the best playlist for a party at Wayne's mansion. The party idea is a 'villain masquerade' theme") +alfred_agent.run("์›จ์ธ ์ €ํƒ์—์„œ ์—ด๋ฆฌ๋Š” ํŒŒํ‹ฐ์— ์–ด์šธ๋ฆฌ๋Š” ์ตœ๊ณ ์˜ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ•ด์ค˜. ํŒŒํ‹ฐ ํ…Œ๋งˆ๋Š” '๋นŒ๋Ÿฐ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ'์•ผ") ``` -Alfred can now access these logs [here](https://cloud.langfuse.com/project/cm7bq0abj025rad078ak3luwi/traces/995fc019255528e4f48cf6770b0ce27b?timestamp=2025-02-19T10%3A28%3A36.929Z) to review and analyze them. +Alfred๋Š” ์ด์ œ [์—ฌ๊ธฐ](https://cloud.langfuse.com/project/cm7bq0abj025rad078ak3luwi/traces/995fc019255528e4f48cf6770b0ce27b?timestamp=2025-02-19T10%3A28%3A36.929Z)์—์„œ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Actually, a minor error occurred during execution. Can you spot it in the logs? Try to track how the agent handles it and still returns a valid answer. Here is the direct link to the error if you want to verify your answer. Of course the error has been fixed in the meantime, more details can be found in this issue. +์‹คํ–‰ ์ค‘์— ์ž‘์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์—์„œ ์˜ค๋ฅ˜๋ฅผ ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ๋‚˜์š”? ์—์ด์ „ํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์œ ํšจํ•œ ๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€ ์ถ”์ ํ•ด๋ณด์„ธ์š”. ์—ฌ๊ธฐ์—์„œ ์˜ค๋ฅ˜๋ฅผ ์ง์ ‘ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์˜ค๋ฅ˜๋Š” ์ด๋ฏธ ์ˆ˜์ •๋˜์—ˆ์œผ๋ฉฐ, ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด ์ด์Šˆ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Meanwhile, the [suggested playlist](https://open.spotify.com/playlist/0gZMMHjuxMrrybQ7wTMTpw) sets the perfect vibe for the party preparations. Cool, right? ๐ŸŽถ +ํ•œํŽธ, [์ถ”์ฒœ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ](https://open.spotify.com/playlist/0gZMMHjuxMrrybQ7wTMTpw)๊ฐ€ ํŒŒํ‹ฐ ์ค€๋น„ ๋ถ„์œ„๊ธฐ๋ฅผ ์™„์„ฑํ•ด์ค๋‹ˆ๋‹ค. ๋ฉ‹์ง€์ฃ ? ๐ŸŽถ --- -Now that we have created our first Code Agent, let's **learn how we can create Tool Calling Agents**, the second type of agent available in `smolagents`. +์ด์ œ ์ฒซ ๋ฒˆ์งธ ์ฝ”๋“œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ, **์ด์ œ smolagents์—์„œ ์ œ๊ณตํ•˜๋Š” ๋‘ ๋ฒˆ์งธ ์—์ด์ „ํŠธ ์œ ํ˜•์ธ Tool Calling Agent ๋งŒ๋“œ๋Š” ๋ฒ•**์„ ๋ฐฐ์›Œ๋ด…์‹œ๋‹ค. -## Resources +## ์ฐธ๊ณ  ์ž๋ฃŒ -- [smolagents Blog](https://huggingface.co/blog/smolagents) - Introduction to smolagents and code interactions -- [smolagents: Building Good Agents](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - Best practices for reliable agents -- [Building Effective Agents - Anthropic](https://www.anthropic.com/research/building-effective-agents) - Agent design principles -- [Sharing runs with OpenTelemetry](https://huggingface.co/docs/smolagents/tutorials/inspect_runs) - Details about how to setup OpenTelemetry for tracking your agents. +- [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 index 540ffc74..a50f77b2 100644 --- a/units/ko/unit2/smolagents/conclusion.mdx +++ b/units/ko/unit2/smolagents/conclusion.mdx @@ -1,11 +1,11 @@ -# Conclusion +# ๊ฒฐ๋ก  -Congratulations on finishing the `smolagents` module of this second Unit ๐Ÿฅณ +`smolagents` ๋ชจ๋“ˆ(2๋‹จ์›)์„ ๋งˆ์นœ ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค ๐Ÿฅณ -Youโ€™ve just mastered the fundamentals of `smolagents` and youโ€™ve built your own Agent! Now that you have skills in `smolagents`, you can now start to create Agents that will solve tasks you're interested about. +์ด์ œ `smolagents`์˜ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ๊ณ , ๋‚˜๋งŒ์˜ ์—์ด์ „ํŠธ๋„ ๋งŒ๋“ค์–ด๋ณด์•˜์Šต๋‹ˆ๋‹ค! ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ๊ด€์‹ฌ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์—์ด์ „ํŠธ๋ฅผ ์ง์ ‘ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์—ญ๋Ÿ‰์„ ๊ฐ–์ถ”์—ˆ์Šต๋‹ˆ๋‹ค. -In the next module, you're going to learn **how to build Agents with LlamaIndex**. +๋‹ค์Œ ๋ชจ๋“ˆ์—์„œ๋Š” **LlamaIndex๋กœ ์—์ด์ „ํŠธ ๋งŒ๋“œ๋Š” ๋ฒ•**์„ ๋ฐฐ์šธ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. -Finally, we would love **to hear what you think of the course and how we can improve it**. If you have some feedback then, please ๐Ÿ‘‰ [fill this form](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog) +๋งˆ์ง€๋ง‰์œผ๋กœ, **์ด ๊ณผ์ •์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์˜๊ฒฌ๊ณผ ๊ฐœ์„ ์ **์„ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ํ”ผ๋“œ๋ฐฑ์ด ์žˆ๋‹ค๋ฉด ๐Ÿ‘‰ [์ด ์–‘์‹](https://docs.google.com/forms/d/e/1FAIpQLSe9VaONn0eglax0uTwi29rIn4tM7H2sYmmybmG5jJNlE5v0xA/viewform?usp=dialog)์„ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”. -### Keep Learning, stay awesome ๐Ÿค— +### ๊ณ„์† ๋ฐฐ์šฐ๊ณ , ๋ฉ‹์ง„ ํ•˜๋ฃจ ๋ณด๋‚ด์„ธ์š” ๐Ÿค— diff --git a/units/ko/unit2/smolagents/final_quiz.mdx b/units/ko/unit2/smolagents/final_quiz.mdx index 8f77e1b1..28658723 100644 --- a/units/ko/unit2/smolagents/final_quiz.mdx +++ b/units/ko/unit2/smolagents/final_quiz.mdx @@ -1,19 +1,19 @@ -# Exam Time! +# ์‹œํ—˜ ์‹œ๊ฐ„! -Well done on working through the material on `smolagents`! You've already achieved a lot. Now, it's time to put your knowledge to the test with a quiz. ๐Ÿง  +`smolagents` ํ•™์Šต์„ ๋งˆ์นœ ์—ฌ๋Ÿฌ๋ถ„, ์ •๋ง ์ˆ˜๊ณ  ๋งŽ์œผ์…จ์Šต๋‹ˆ๋‹ค! ์ด์ œ ํ€ด์ฆˆ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ง€์‹์„ ์ ๊ฒ€ํ•ด๋ณผ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ๐Ÿง  -## Instructions +## ์•ˆ๋‚ด์‚ฌํ•ญ -- The quiz consists of code questions. -- You will be given instructions to complete the code snippets. -- Read the instructions carefully and complete the code snippets accordingly. -- For each question, you will be given the result and some feedback. +- ํ€ด์ฆˆ๋Š” ์ฝ”๋“œ ๋ฌธ์ œ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. +- ์ฝ”๋“œ ์กฐ๊ฐ์„ ์™„์„ฑํ•˜๋Š” ์ง€์‹œ์‚ฌํ•ญ์ด ์ฃผ์–ด์ง‘๋‹ˆ๋‹ค. +- ์•ˆ๋‚ด๋ฅผ ์ž˜ ์ฝ๊ณ , ์ฝ”๋“œ ์กฐ๊ฐ์„ ์™„์„ฑํ•ด ์ฃผ์„ธ์š”. +- ๊ฐ ๋ฌธ์ œ๋งˆ๋‹ค ๊ฒฐ๊ณผ์™€ ํ”ผ๋“œ๋ฐฑ์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. -๐Ÿง˜ **This quiz is ungraded and uncertified**. It's about you understanding the `smolagents` library and knowing whether you should spend more time on the written material. In the coming units you'll put this knowledge to the test in use cases and projects. +๐Ÿง˜ **์ด ํ€ด์ฆˆ๋Š” ์ ์ˆ˜ํ™”๋˜๊ฑฐ๋‚˜ ์ธ์ฆ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**. ์—ฌ๋Ÿฌ๋ถ„์ด `smolagents` ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž˜ ์ดํ•ดํ–ˆ๋Š”์ง€, ์ถ”๊ฐ€ ํ•™์Šต์ด ํ•„์š”ํ•œ์ง€ ์Šค์Šค๋กœ ์ ๊ฒ€ํ•˜๋Š” ์šฉ๋„์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ๋‹จ์›์—์„œ๋Š” ์ด ์ง€์‹์„ ์‹ค์ œ ์‚ฌ๋ก€์™€ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. -Let's get started! +์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”? -## Quiz ๐Ÿš€ +## ํ€ด์ฆˆ ๐Ÿš€ -You can also access the quiz ๐Ÿ‘‰ [here](https://huggingface.co/spaces/agents-course/unit2_smolagents_quiz) \ No newline at end of file +ํ€ด์ฆˆ์— ์ง์ ‘ ์ฐธ์—ฌํ•˜๋ ค๋ฉด ๐Ÿ‘‰ [์—ฌ๊ธฐ](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 index 0677b204..569d43f5 100644 --- a/units/ko/unit2/smolagents/introduction.mdx +++ b/units/ko/unit2/smolagents/introduction.mdx @@ -1,69 +1,67 @@ -# Introduction to `smolagents` +# `smolagents` ์†Œ๊ฐœ Unit 2.1 Thumbnail -Welcome to this module, where you'll learn **how to build effective agents** using the [`smolagents`](https://github.com/huggingface/smolagents) library, which provides a lightweight framework for creating capable AI agents. +์ด ๋ชจ๋“ˆ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ์—ฌ๊ธฐ์„œ๋Š” [`smolagents`](https://github.com/huggingface/smolagents) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•ด **ํšจ๊ณผ์ ์ธ ์—์ด์ „ํŠธ ๋งŒ๋“œ๋Š” ๋ฒ•**์„ ๋ฐฐ์›๋‹ˆ๋‹ค. `smolagents`๋Š” ๊ฐ•๋ ฅํ•œ AI ์—์ด์ „ํŠธ๋ฅผ ์†์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ฒฝ๋Ÿ‰ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. -`smolagents` is a Hugging Face library; therefore, we would appreciate your support by **starring** the smolagents [`repository`](https://github.com/huggingface/smolagents) : +`smolagents`๋Š” Hugging Face์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. [`์ €์žฅ์†Œ`](https://github.com/huggingface/smolagents)์— **๋ณ„(star)**์„ ๋ˆŒ๋Ÿฌ ์‘์›ํ•ด ์ฃผ์„ธ์š”! staring smolagents -## Module Overview +## ๋ชจ๋“ˆ ๊ฐœ์š” -This module provides a comprehensive overview of key concepts and practical strategies for building intelligent agents using `smolagents`. +์ด ๋ชจ๋“ˆ์—์„œ๋Š” `smolagents`๋ฅผ ํ™œ์šฉํ•ด ์ง€๋Šฅํ˜• ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ํ•„์š”ํ•œ ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ์‹ค์ „ ์ „๋žต์„ ํญ๋„“๊ฒŒ ๋‹ค๋ฃน๋‹ˆ๋‹ค. -With so many open-source frameworks available, it's essential to understand the components and capabilities that make `smolagents` a useful option or to determine when another solution might be a better fit. +์ˆ˜๋งŽ์€ ์˜คํ”ˆ์†Œ์Šค ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์กด์žฌํ•˜๋Š” ๋งŒํผ, `smolagents`์˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ ์žฅ๋‹จ์ ์„ ์ดํ•ดํ•˜๊ณ , ์–ธ์ œ ๋‹ค๋ฅธ ์†”๋ฃจ์…˜์ด ๋” ์ ํ•ฉํ• ์ง€ ํŒ๋‹จํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. -We'll explore critical agent types, including code agents designed for software development tasks, tool calling agents for creating modular, function-driven workflows, and retrieval agents that access and synthesize information. +์ด ๋‹จ์›์—์„œ๋Š” ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ์— ํŠนํ™”๋œ ์ฝ”๋“œ ์—์ด์ „ํŠธ, ๋ชจ๋“ˆํ˜• ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์œ„ํ•œ ํˆด ํ˜ธ์ถœ ์—์ด์ „ํŠธ, ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ยท์ข…ํ•ฉํ•˜๋Š” ๋ฆฌํŠธ๋ฆฌ๋ฒŒ ์—์ด์ „ํŠธ ๋“ฑ ์ฃผ์š” ์—์ด์ „ํŠธ ์œ ํ˜•์„ ์‚ดํŽด๋ด…๋‹ˆ๋‹ค. -Additionally, we'll cover the orchestration of multiple agents as well as the integration of vision capabilities and web browsing, which unlock new possibilities for dynamic and context-aware applications. +๋˜ํ•œ ์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๋ฅผ ์กฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•, ๋น„์ „ ๊ธฐ๋Šฅ ๋ฐ ์›น ๋ธŒ๋ผ์šฐ์ง• ํ†ตํ•ฉ ๋“ฑ ๋™์ ์ด๊ณ  ์ƒํ™ฉ ์ธ์‹์ด ๊ฐ€๋Šฅํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•๋„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. -In this unit, Alfred, the agent from Unit 1, makes his return. This time, heโ€™s using the `smolagents` framework for his internal workings. Together, weโ€™ll explore the key concepts behind this framework as Alfred tackles various tasks. Alfred is organizing a party at the Wayne Manor while the Wayne family ๐Ÿฆ‡ is away, and he has plenty to do. Join us as we showcase his journey and how he handles these tasks with `smolagents`! +์ด๋ฒˆ ๋‹จ์›์—์„œ๋Š” 1๋‹จ์›์—์„œ ๋งŒ๋‚œ ์—์ด์ „ํŠธ Alfred๊ฐ€ ๋‹ค์‹œ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” `smolagents` ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ™œ์šฉํ•ด ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. Alfred๋Š” Wayne ์ €ํƒ์—์„œ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•˜๋ฉฐ ์—ฌ๋Ÿฌ ๊ณผ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Alfred์˜ ์—ฌ์ •์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ `smolagents`์˜ ํ•ต์‹ฌ ๊ฐœ๋…์„ ํ•จ๊ป˜ ์ตํ˜€๋ด…์‹œ๋‹ค! - -In this unit, you will learn to build AI agents with the `smolagents` library. Your agents will be able to search for data, execute code, and interact with web pages. You will also learn how to combine multiple agents to create more powerful systems. - +์ด ๋‹จ์›์—์„œ๋Š” `smolagents` ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ AI ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์˜ ์—์ด์ „ํŠธ๋Š” ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰, ์ฝ”๋“œ ์‹คํ–‰, ์›นํŽ˜์ด์ง€ ์ƒํ˜ธ์ž‘์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๋ฅผ ์กฐํ•ฉํ•ด ๋” ๊ฐ•๋ ฅํ•œ ์‹œ์Šคํ…œ๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ![Alfred the agent](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit1/this-is-alfred.jpg) -## Contents +## ๋ชฉ์ฐจ -During this unit on `smolagents`, we cover: +์ด ๋‹จ์›์—์„œ ๋‹ค๋ฃจ๋Š” ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: -### 1๏ธโƒฃ [Why Use smolagents](./why_use_smolagents) +### 1๏ธโƒฃ [์™œ smolagents๋ฅผ ์‚ฌ์šฉํ• ๊นŒ](./why_use_smolagents) -`smolagents` is one of the many open-source agent frameworks available for application development. Alternative options include `LlamaIndex` and `LangGraph`, which are also covered in other modules in this course. `smolagents` offers several key features that might make it a great fit for specific use cases, but we should always consider all options when selecting a framework. We'll explore the advantages and drawbacks of using `smolagents`, helping you make an informed decision based on your project's requirements. +`smolagents`๋Š” ๋‹ค์–‘ํ•œ ์˜คํ”ˆ์†Œ์Šค ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๋Œ€์•ˆ์œผ๋กœ๋Š” `LlamaIndex`, `LangGraph` ๋“ฑ์ด ์žˆ์œผ๋ฉฐ, ์ด ๊ณผ์ •์˜ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ ๋‹ค๋ฃน๋‹ˆ๋‹ค. `smolagents`๋Š” ํŠน์ • ์ƒํ™ฉ์— ์ ํ•ฉํ•œ ์—ฌ๋Ÿฌ ์ฃผ์š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ํ”„๋ ˆ์ž„์›Œํฌ ์„ ํƒ ์‹œ ํ•ญ์ƒ ๋‹ค์–‘ํ•œ ์˜ต์…˜์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” `smolagents`์˜ ์žฅ๋‹จ์ ์„ ์‚ดํŽด๋ณด๊ณ , ํ”„๋กœ์ ํŠธ ์š”๊ตฌ์— ๋”ฐ๋ผ ํ˜„๋ช…ํ•˜๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. ### 2๏ธโƒฃ [CodeAgents](./code_agents) -`CodeAgents` are the primary type of agent in `smolagents`. Instead of generating JSON or text, these agents produce Python code to perform actions. This module explores their purpose, functionality, and how they work, along with hands-on examples to showcase their capabilities. +`CodeAgents`๋Š” `smolagents`์˜ ๊ธฐ๋ณธ ์—์ด์ „ํŠธ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. ์ด๋“ค์€ JSON์ด๋‚˜ ํ…์ŠคํŠธ ๋Œ€์‹  ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” CodeAgent์˜ ๋ชฉ์ , ๋™์ž‘ ๋ฐฉ์‹, ์‹ค์ „ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ๊ทธ ๊ธฐ๋Šฅ์„ ์‚ดํŽด๋ด…๋‹ˆ๋‹ค. ### 3๏ธโƒฃ [ToolCallingAgents](./tool_calling_agents) -`ToolCallingAgents` are the second type of agent supported by `smolagents`. Unlike `CodeAgents`, which generate Python code, these agents rely on JSON/text blobs that the system must parse and interpret to execute actions. This module covers their functionality, their key differences from `CodeAgents`, and it provides an example to illustrate their usage. +`ToolCallingAgents`๋Š” `smolagents`๊ฐ€ ์ง€์›ํ•˜๋Š” ๋‘ ๋ฒˆ์งธ ์—์ด์ „ํŠธ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. CodeAgent๊ฐ€ ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, ์ด ์—์ด์ „ํŠธ๋Š” ์‹œ์Šคํ…œ์ด ํŒŒ์‹ฑยทํ•ด์„ํ•ด์•ผ ํ•˜๋Š” JSON/ํ…์ŠคํŠธ ๋ธ”๋กญ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” ToolCallingAgent์˜ ๋™์ž‘ ๋ฐฉ์‹, CodeAgent์™€์˜ ์ฐจ์ด์ , ์‚ฌ์šฉ ์˜ˆ์‹œ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. -### 4๏ธโƒฃ [Tools](./tools) +### 4๏ธโƒฃ [๋„๊ตฌ(Tools)](./tools) -As we saw in Unit 1, tools are functions that an LLM can use within an agentic system, and they act as the essential building blocks for agent behavior. This module covers how to create tools, their structure, and different implementation methods using the `Tool` class or the `@tool` decorator. You'll also learn about the default toolbox, how to share tools with the community, and how to load community-contributed tools for use in your agents. +1๋‹จ์›์—์„œ ์‚ดํŽด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ, ๋„๊ตฌ๋Š” LLM์ด ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋กœ, ์—์ด์ „ํŠธ ํ–‰๋™์˜ ํ•ต์‹ฌ ๋นŒ๋”ฉ ๋ธ”๋ก์ž…๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” ๋„๊ตฌ ์ƒ์„ฑ๋ฒ•, ๊ตฌ์กฐ, `Tool` ํด๋ž˜์Šค์™€ `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•œ ๋‹ค์–‘ํ•œ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๋„๊ตฌ ์ƒ์ž, ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋„๊ตฌ ๊ณต์œ , ์ปค๋ฎค๋‹ˆํ‹ฐ ๋„๊ตฌ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋“ฑ๋„ ๋ฐฐ์›๋‹ˆ๋‹ค. -### 5๏ธโƒฃ [Retrieval Agents](./retrieval_agents) +### 5๏ธโƒฃ [๋ฆฌํŠธ๋ฆฌ๋ฒŒ ์—์ด์ „ํŠธ(Retrieval Agents)](./retrieval_agents) -Retrieval agents allow models access to knowledge bases, making it possible to search, synthesize, and retrieve information from multiple sources. They leverage vector stores for efficient retrieval and implement **Retrieval-Augmented Generation (RAG)** patterns. These agents are particularly useful for integrating web search with custom knowledge bases while maintaining conversation context through memory systems. This module explores implementation strategies, including fallback mechanisms for robust information retrieval. +๋ฆฌํŠธ๋ฆฌ๋ฒŒ ์—์ด์ „ํŠธ๋Š” ๋ชจ๋ธ์ด ์ง€์‹ ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์—ฌ, ๋‹ค์–‘ํ•œ ์†Œ์Šค์—์„œ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ยท์ข…ํ•ฉยท์ถ”์ถœํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋“ค์€ ๋ฒกํ„ฐ ์Šคํ† ์–ด๋ฅผ ํ™œ์šฉํ•ด ํšจ์œจ์ ์œผ๋กœ ์ •๋ณด๋ฅผ ์ฐพ๊ณ , **RAG(Retrieval-Augmented Generation)** ํŒจํ„ด์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์›น ๊ฒ€์ƒ‰๊ณผ ๋งž์ถคํ˜• ์ง€์‹ ๋ฒ ์ด์Šค ํ†ตํ•ฉ, ๋Œ€ํ™” ๋งฅ๋ฝ ์œ ์ง€ ๋“ฑ ๋‹ค์–‘ํ•œ ์ „๋žต์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. -### 6๏ธโƒฃ [Multi-Agent Systems](./multi_agent_systems) +### 6๏ธโƒฃ [๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ(Multi-Agent Systems)](./multi_agent_systems) -Orchestrating multiple agents effectively is crucial for building powerful, multi-agent systems. By combining agents with different capabilitiesโ€”such as a web search agent with a code execution agentโ€”you can create more sophisticated solutions. This module focuses on designing, implementing, and managing multi-agent systems to maximize efficiency and reliability. +์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์กฐ์œจํ•˜๋Š” ๊ฒƒ์€ ๊ฐ•๋ ฅํ•œ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ์›น ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ์™€ ์ฝ”๋“œ ์‹คํ–‰ ์—์ด์ „ํŠธ ๋“ฑ ๋‹ค์–‘ํ•œ ๋Šฅ๋ ฅ์„ ๊ฐ€์ง„ ์—์ด์ „ํŠธ๋ฅผ ์กฐํ•ฉํ•ด ๋” ์ •๊ตํ•œ ์†”๋ฃจ์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์˜ ์„ค๊ณ„, ๊ตฌํ˜„, ๊ด€๋ฆฌ ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. -### 7๏ธโƒฃ [Vision and Browser agents](./vision_agents) +### 7๏ธโƒฃ [๋น„์ „ ๋ฐ ๋ธŒ๋ผ์šฐ์ € ์—์ด์ „ํŠธ(Vision and Browser agents)](./vision_agents) -Vision agents extend traditional agent capabilities by incorporating **Vision-Language Models (VLMs)**, enabling them to process and interpret visual information. This module explores how to design and integrate VLM-powered agents, unlocking advanced functionalities like image-based reasoning, visual data analysis, and multimodal interactions. We will also use vision agents to build a browser agent that can browse the web and extract information from it. +๋น„์ „ ์—์ด์ „ํŠธ๋Š” **๋น„์ „-์–ธ์–ด ๋ชจ๋ธ(VLM)**์„ ํ†ตํ•ฉํ•ด ์‹œ๊ฐ ์ •๋ณด๋ฅผ ์ฒ˜๋ฆฌยทํ•ด์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” VLM ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ ์„ค๊ณ„ยทํ†ตํ•ฉ๋ฒ•, ์ด๋ฏธ์ง€ ๊ธฐ๋ฐ˜ ์ถ”๋ก , ์‹œ๊ฐ ๋ฐ์ดํ„ฐ ๋ถ„์„, ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ์ƒํ˜ธ์ž‘์šฉ ๋“ฑ์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๋˜ํ•œ ๋น„์ „ ์—์ด์ „ํŠธ๋ฅผ ํ™œ์šฉํ•ด ์›น์„ ํƒ์ƒ‰ํ•˜๊ณ  ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ € ์—์ด์ „ํŠธ๋„ ๋งŒ๋“ค์–ด๋ด…๋‹ˆ๋‹ค. -## Resources +## ์ฐธ๊ณ  ์ž๋ฃŒ -- [smolagents Documentation](https://huggingface.co/docs/smolagents) - Official docs for the smolagents library -- [Building Effective Agents](https://www.anthropic.com/research/building-effective-agents) - Research paper on agent architectures -- [Agent Guidelines](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - Best practices for building reliable agents -- [LangGraph Agents](https://langchain-ai.github.io/langgraph/) - Additional examples of agent implementations -- [Function Calling Guide](https://platform.openai.com/docs/guides/function-calling) - Understanding function calling in LLMs -- [RAG Best Practices](https://www.pinecone.io/learn/retrieval-augmented-generation/) - Guide to implementing effective RAG +- [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 index ba1d767f..820c5479 100644 --- a/units/ko/unit2/smolagents/multi_agent_systems.mdx +++ b/units/ko/unit2/smolagents/multi_agent_systems.mdx @@ -5,59 +5,59 @@ ]} askForHelpUrl="http://hf.co/join/discord" /> -# Multi-Agent Systems +# ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ -Multi-agent systems enable **specialized agents to collaborate on complex tasks**, improving modularity, scalability, and robustness. Instead of relying on a single agent, tasks are distributed among agents with distinct capabilities. +๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์€ **ํŠนํ™”๋œ ์—์ด์ „ํŠธ๋“ค์ด ํ˜‘๋ ฅํ•˜์—ฌ ๋ณต์žกํ•œ ์ž‘์—…์„ ํ•ด๊ฒฐ**ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋ฉฐ, ๋ชจ๋“ˆ์„ฑ, ํ™•์žฅ์„ฑ, ๊ฒฌ๊ณ ์„ฑ์„ ๋†’์—ฌ์ค๋‹ˆ๋‹ค. ๋‹จ์ผ ์—์ด์ „ํŠธ์— ์˜์กดํ•˜๋Š” ๋Œ€์‹ , ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋Šฅ๋ ฅ์„ ๊ฐ€์ง„ ์—์ด์ „ํŠธ๋“ค์ด ์ž‘์—…์„ ๋ถ„๋‹ดํ•ฉ๋‹ˆ๋‹ค. -In **smolagents**, different agents can be combined to generate Python code, call external tools, perform web searches, and more. By orchestrating these agents, we can create powerful workflows. +**smolagents**์—์„œ๋Š” ๋‹ค์–‘ํ•œ ์—์ด์ „ํŠธ๋ฅผ ๊ฒฐํ•ฉํ•ด ํŒŒ์ด์ฌ ์ฝ”๋“œ ์ƒ์„ฑ, ์™ธ๋ถ€ ๋„๊ตฌ ํ˜ธ์ถœ, ์›น ๊ฒ€์ƒ‰ ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์—์ด์ „ํŠธ๋“ค์„ ์กฐ์œจํ•จ์œผ๋กœ์จ ๊ฐ•๋ ฅํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -A typical setup might include: -- A **Manager Agent** for task delegation -- A **Code Interpreter Agent** for code execution -- A **Web Search Agent** for information retrieval +์ผ๋ฐ˜์ ์ธ ๊ตฌ์„ฑ ์˜ˆ์‹œ: +- **๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ**: ์ž‘์—… ๋ถ„๋ฐฐ ๋‹ด๋‹น +- **์ฝ”๋“œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์—์ด์ „ํŠธ**: ์ฝ”๋“œ ์‹คํ–‰ ๋‹ด๋‹น +- **์›น ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ**: ์ •๋ณด ๊ฒ€์ƒ‰ ๋‹ด๋‹น -The diagram below illustrates a simple multi-agent architecture where a **Manager Agent** coordinates a **Code Interpreter Tool** and a **Web Search Agent**, which in turn utilizes tools like the `DuckDuckGoSearchTool` and `VisitWebpageTool` to gather relevant information. +์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ **๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ**๊ฐ€ **์ฝ”๋“œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ๋„๊ตฌ**์™€ **์›น ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ**๋ฅผ ์กฐ์œจํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์›น ๊ฒ€์ƒ‰ ์—์ด์ „ํŠธ๋Š” `DuckDuckGoSearchTool`๊ณผ `VisitWebpageTool` ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•ด ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค. -## Multi-Agent Systems in Action +## ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ์‹ค์ „ ์˜ˆ์‹œ -A multi-agent system consists of multiple specialized agents working together under the coordination of an **Orchestrator Agent**. This approach enables complex workflows by distributing tasks among agents with distinct roles. +๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์€ ์—ฌ๋Ÿฌ ํŠนํ™” ์—์ด์ „ํŠธ๊ฐ€ **์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ ์—์ด์ „ํŠธ**์˜ ์กฐ์œจ ์•„๋ž˜ ํ˜‘๋ ฅํ•˜๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ์—ญํ• ์ด ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๋“ค์—๊ฒŒ ์ž‘์—…์„ ๋ถ„์‚ฐ์‹œ์ผœ ๋ณต์žกํ•œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. -For example, a **Multi-Agent RAG system** can integrate: -- A **Web Agent** for browsing the internet. -- A **Retriever Agent** for fetching information from knowledge bases. -- An **Image Generation Agent** for producing visuals. +์˜ˆ๋ฅผ ๋“ค์–ด, **๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ RAG ์‹œ์Šคํ…œ**์€ ๋‹ค์Œ์„ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +- **์›น ์—์ด์ „ํŠธ**: ์ธํ„ฐ๋„ท ๋ธŒ๋ผ์šฐ์ง• ๋‹ด๋‹น +- **๋ฆฌํŠธ๋ฆฌ๋ฒ„ ์—์ด์ „ํŠธ**: ์ง€์‹ ๋ฒ ์ด์Šค ์ •๋ณด ๊ฒ€์ƒ‰ ๋‹ด๋‹น +- **์ด๋ฏธ์ง€ ์ƒ์„ฑ ์—์ด์ „ํŠธ**: ์‹œ๊ฐ ์ž๋ฃŒ ์ƒ์„ฑ ๋‹ด๋‹น -All of these agents operate under an orchestrator that manages task delegation and interaction. +์ด ๋ชจ๋“  ์—์ด์ „ํŠธ๋Š” ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ๊ฐ€ ์ž‘์—… ๋ถ„๋ฐฐ์™€ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. -## Solving a complex task with a multi-agent hierarchy +## ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ๊ณ„์ธต ๊ตฌ์กฐ๋กœ ๋ณต์žกํ•œ ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ -You can follow the code in this notebook that you can run using Google Colab. +์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -The reception is approaching! With your help, Alfred is now nearly finished with the preparations. +๋ฆฌ์…‰์…˜์ด ๋‹ค๊ฐ€์˜ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค! ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์›€์œผ๋กœ Alfred๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ์ค€๋น„๋ฅผ ๋งˆ์ณค์Šต๋‹ˆ๋‹ค. -But now there's a problem: the Batmobile has disappeared. Alfred needs to find a replacement, and find it quickly. +ํ•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค: ๋ฐฐํŠธ๋ชจ๋นŒ์ด ์‚ฌ๋ผ์กŒ์Šต๋‹ˆ๋‹ค. Alfred๋Š” ๋Œ€์ฒด ์ฐจ๋Ÿ‰์„ ๋นจ๋ฆฌ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. -Fortunately, a few biopics have been done on Bruce Wayne's life, so maybe Alfred could get a car left behind on one of the movie sets, and re-engineer it up to modern standards, which certainly would include a full self-driving option. +๋‹คํ–‰ํžˆ ๋ธŒ๋ฃจ์Šค ์›จ์ธ์˜ ์‚ถ์„ ๋‹ค๋ฃฌ ๋ฐ”์ด์˜คํ”ฝ ์˜ํ™”๊ฐ€ ๋ช‡ ํŽธ ์ œ์ž‘๋˜์—ˆ์œผ๋‹ˆ, Alfred๋Š” ์˜ํ™” ์„ธํŠธ์žฅ์— ๋‚จ๊ฒจ์ง„ ์ฐจ๋Ÿ‰์„ ์ฐพ์•„ ํ˜„๋Œ€์‹์œผ๋กœ ๊ฐœ์กฐํ•  ์ˆ˜ ์žˆ์„์ง€๋„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ž์œจ์ฃผํ–‰ ๊ธฐ๋Šฅ๋„ ํ•„์ˆ˜๊ฒ ์ฃ . -But this could be anywhere in the filming locations around the world - which could be numerous. +ํ•˜์ง€๋งŒ ์ด ์ฐจ๋Ÿ‰๋“ค์€ ์ „ ์„ธ๊ณ„ ์ดฌ์˜์ง€ ์–ด๋””์—๋‚˜ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -So Alfred wants your help. Could you build an agent able to solve this task? +๊ทธ๋ž˜์„œ Alfred๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”? -> ๐Ÿ‘‰ Find all Batman filming locations in the world, calculate the time to transfer via boat to there, and represent them on a map, with a color varying by boat transfer time. Also represent some supercar factories with the same boat transfer time. +> ๐Ÿ‘‰ ์ „ ์„ธ๊ณ„ ๋ฐฐํŠธ๋งจ ์ดฌ์˜์ง€๋ฅผ ๋ชจ๋‘ ์ฐพ์•„, ๊ณ ๋‹ด(40.7128ยฐ N, 74.0060ยฐ W)๊นŒ์ง€ ํ™”๋ฌผ์„ (๋น„ํ–‰๊ธฐ)์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•˜๊ณ , ์ด๋ฅผ ์ง€๋„์— ํ‘œ์‹œํ•˜์„ธ์š”. ์ด๋™ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ์ƒ‰์ƒ์„ ๋‹ค๋ฅด๊ฒŒ ํ•˜๊ณ , ์Šˆํผ์นด ๊ณต์žฅ๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ํ‘œ์‹œํ•˜์„ธ์š”. -Let's build this! +ํ•จ๊ป˜ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค! -This example needs some additional packages, so let's install them first: +์ด ์˜ˆ์‹œ์—๋Š” ์ถ”๊ฐ€ ํŒจํ‚ค์ง€๊ฐ€ ํ•„์š”ํ•˜๋‹ˆ ๋จผ์ € ์„ค์น˜ํ•ด ์ฃผ์„ธ์š”: ```bash pip install 'smolagents[litellm]' plotly geopandas shapely kaleido -q ``` -### We first make a tool to get the cargo plane transfer time. +### ๋จผ์ € ํ™”๋ฌผ๊ธฐ ์ด๋™ ์‹œ๊ฐ„ ๊ณ„์‚ฐ ๋„๊ตฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ```python import math @@ -70,35 +70,35 @@ from smolagents import tool def calculate_cargo_travel_time( origin_coords: Tuple[float, float], destination_coords: Tuple[float, float], - cruising_speed_kmh: Optional[float] = 750.0, # Average speed for cargo planes + cruising_speed_kmh: Optional[float] = 750.0, # ํ™”๋ฌผ๊ธฐ ํ‰๊ท  ์†๋„ ) -> float: """ - Calculate the travel time for a cargo plane between two points on Earth using great-circle distance. + ๋‘ ์ง€์ (์œ„๋„, ๊ฒฝ๋„) ๊ฐ„ ํ™”๋ฌผ๊ธฐ ์ด๋™ ์‹œ๊ฐ„์„ ๋Œ€๊ถŒ๊ฑฐ๋ฆฌ๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. Args: - origin_coords: Tuple of (latitude, longitude) for the starting point - destination_coords: Tuple of (latitude, longitude) for the destination - cruising_speed_kmh: Optional cruising speed in km/h (defaults to 750 km/h for typical cargo planes) + origin_coords: ์ถœ๋ฐœ์ง€ (์œ„๋„, ๊ฒฝ๋„) ํŠœํ”Œ + destination_coords: ๋„์ฐฉ์ง€ (์œ„๋„, ๊ฒฝ๋„) ํŠœํ”Œ + cruising_speed_kmh: ์ˆœํ•ญ ์†๋„(km/h, ๊ธฐ๋ณธ๊ฐ’ 750) Returns: - float: The estimated travel time in hours + float: ์˜ˆ์ƒ ์ด๋™ ์‹œ๊ฐ„(์‹œ๊ฐ„ ๋‹จ์œ„) Example: - >>> # Chicago (41.8781ยฐ N, 87.6298ยฐ W) to Sydney (33.8688ยฐ S, 151.2093ยฐ E) + >>> # ์‹œ์นด๊ณ (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) - # Extract coordinates + # ์ขŒํ‘œ ๋ณ€ํ™˜ lat1, lon1 = map(to_radians, origin_coords) lat2, lon2 = map(to_radians, destination_coords) - # Earth's radius in kilometers + # ์ง€๊ตฌ ๋ฐ˜์ง€๋ฆ„(km) EARTH_RADIUS_KM = 6371.0 - # Calculate great-circle distance using the haversine formula + # haversine ๊ณต์‹์œผ๋กœ ๋Œ€๊ถŒ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ dlon = lon2 - lon1 dlat = lat2 - lat1 @@ -109,27 +109,23 @@ def calculate_cargo_travel_time( c = 2 * math.asin(math.sqrt(a)) distance = EARTH_RADIUS_KM * c - # Add 10% to account for non-direct routes and air traffic controls + # ์šฐํšŒ ๊ฒฝ๋กœ, ๊ด€์ œ ๋“ฑ ๊ฐ์•ˆํ•ด 10% ์ถ”๊ฐ€ actual_distance = distance * 1.1 - # Calculate flight time - # Add 1 hour for takeoff and landing procedures + # ๋น„ํ–‰ ์‹œ๊ฐ„ ๊ณ„์‚ฐ(์ด์ฐฉ๋ฅ™ 1์‹œ๊ฐ„ ์ถ”๊ฐ€) flight_time = (actual_distance / cruising_speed_kmh) + 1.0 - # Format the results return round(flight_time, 2) print(calculate_cargo_travel_time((41.8781, -87.6298), (-33.8688, 151.2093))) ``` -### Setting up the agent +### ์—์ด์ „ํŠธ ์„ค์ •ํ•˜๊ธฐ -For the model provider, we use Together AI, one of the new [inference providers on the Hub](https://huggingface.co/blog/inference-providers)! +๋ชจ๋ธ ์ œ๊ณต์ž๋Š” Together AI๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. GoogleSearchTool์€ [Serper API](https://serper.dev)๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ `SERPAPI_API_KEY`(provider="serpapi") ๋˜๋Š” `SERPER_API_KEY`(provider=serper)๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -The GoogleSearchTool uses the [Serper API](https://serper.dev) to search the web, so this requires either having setup env variable `SERPAPI_API_KEY` and passing `provider="serpapi"` or having `SERPER_API_KEY` and passing `provider=serper`. - -If you don't have any Serp API provider setup, you can use `DuckDuckGoSearchTool` but beware that it has a rate limit. +Serp API๊ฐ€ ์—†๋‹ค๋ฉด `DuckDuckGoSearchTool`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์†๋„ ์ œํ•œ์— ์œ ์˜ํ•˜์„ธ์š”. ```python import os @@ -139,11 +135,10 @@ from smolagents import CodeAgent, GoogleSearchTool, InferenceClientModel, VisitW model = InferenceClientModel(model_id="Qwen/Qwen2.5-Coder-32B-Instruct", provider="together") ``` -We can start by creating a simple agent as a baseline to give us a simple report. +๊ฐ„๋‹จํ•œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๊ธฐ๋ณธ ๋ฆฌํฌํŠธ๋ฅผ ๋ฐ›์•„๋ด…์‹œ๋‹ค. ```python -task = """Find all Batman filming locations in the world, calculate the time to transfer via cargo plane to here (we're in Gotham, 40.7128ยฐ N, 74.0060ยฐ W), and return them to me as a pandas dataframe. -Also give me some supercar factories with the same cargo plane transfer time.""" +task = """์ „ ์„ธ๊ณ„ ๋ฐฐํŠธ๋งจ ์ดฌ์˜์ง€๋ฅผ ๋ชจ๋‘ ์ฐพ์•„, ๊ณ ๋‹ด(40.7128ยฐ N, 74.0060ยฐ W)๊นŒ์ง€ ํ™”๋ฌผ๊ธฐ๋กœ ์ด๋™ํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•ด pandas ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜์„ธ์š”. ์Šˆํผ์นด ๊ณต์žฅ๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ํฌํ•จํ•˜์„ธ์š”.""" ``` ```python @@ -163,7 +158,7 @@ result = agent.run(task) result ``` -In our case, it generates this output: +์‹คํ–‰ ๊ฒฐ๊ณผ ์˜ˆ์‹œ: ```python | | Location | Travel Time to Gotham (hours) | @@ -186,17 +181,17 @@ In our case, it generates this output: | 15 | Woking, UK (McLaren) | 9.13 | ``` -We could already improve this a bit by throwing in some dedicated planning steps, and adding more prompting. +๊ณ„ํš ๋‹จ๊ณ„(planning step)๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ณด๊ฐ•ํ•˜๋ฉด ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Planning steps allow the agent to think ahead and plan its next steps, which can be useful for more complex tasks. +๊ณ„ํš ๋‹จ๊ณ„๋Š” ์—์ด์ „ํŠธ๊ฐ€ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋ฏธ๋ฆฌ ์ƒ๊ฐํ•˜๊ณ  ๊ณ„ํšํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ```python agent.planning_interval = 4 detailed_report = agent.run(f""" -You're an expert analyst. You make comprehensive reports after visiting many websites. -Don't hesitate to search for many queries at once in a for loop. -For each data point that you find, visit the source url to confirm numbers. +์—ฌ๋Ÿฌ๋ถ„์€ ์ „๋ฌธ ๋ถ„์„๊ฐ€์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋ฐฉ๋ฌธํ•ด ์ข…ํ•ฉ ๋ฆฌํฌํŠธ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. +for ๋ฃจํ”„๋ฅผ ํ™œ์šฉํ•ด ์—ฌ๋Ÿฌ ์ฟผ๋ฆฌ๋ฅผ ํ•œ ๋ฒˆ์— ๊ฒ€์ƒ‰ํ•˜์„ธ์š”. +๊ฐ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ๋งˆ๋‹ค ์†Œ์Šค URL์„ ๋ฐฉ๋ฌธํ•ด ์ˆ˜์น˜๋ฅผ ํ™•์ธํ•˜์„ธ์š”. {task} """) @@ -208,7 +203,7 @@ print(detailed_report) detailed_report ``` -In our case, it generates this output: +์‹คํ–‰ ๊ฒฐ๊ณผ ์˜ˆ์‹œ: ```python | | Location | Travel Time (hours) | @@ -217,22 +212,21 @@ In our case, it generates this output: | 1 | Wishart Street, Glasgow, Scotland, UK | 8.6 | ``` +์ด์ฒ˜๋Ÿผ ํ”„๋กฌํ”„ํŠธ์™€ ๊ณ„ํš ๊ธฐ๋Šฅ๋งŒ์œผ๋กœ๋„ ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•œ ๋ฆฌํฌํŠธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! -Thanks to these quick changes, we obtained a much more concise report by simply providing our agent a detailed prompt, and giving it planning capabilities! - -The model's context window is quickly filling up. So **if we ask our agent to combine the results of detailed search with another, it will be slower and quickly ramp up tokens and costs**. +๋ชจ๋ธ์˜ ์ปจํ…์ŠคํŠธ ์œˆ๋„์šฐ๊ฐ€ ๋น ๋ฅด๊ฒŒ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค. **๋”ฐ๋ผ์„œ ์ƒ์„ธ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐํ•ฉํ•˜๋„๋ก ์š”์ฒญํ•˜๋ฉด ๋А๋ ค์ง€๊ณ  ํ† ํฐยท๋น„์šฉ์ด ๊ธ‰์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.** -โžก๏ธ We need to improve the structure of our system. +โžก๏ธ ์‹œ์Šคํ…œ ๊ตฌ์กฐ๋ฅผ ๊ฐœ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -### โœŒ๏ธ Splitting the task between two agents +### โœŒ๏ธ ๋‘ ์—์ด์ „ํŠธ๋กœ ์ž‘์—… ๋ถ„ํ• ํ•˜๊ธฐ -Multi-agent structures allow to separate memories between different sub-tasks, with two great benefits: -- Each agent is more focused on its core task, thus more performant -- Separating memories reduces the count of input tokens at each step, thus reducing latency and cost. +๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ๊ตฌ์กฐ๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํ•˜์œ„ ์ž‘์—…์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•ด ๋‘ ๊ฐ€์ง€ ํฐ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค: +- ๊ฐ ์—์ด์ „ํŠธ๊ฐ€ ํ•ต์‹ฌ ์ž‘์—…์— ์ง‘์ค‘ํ•ด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค. +- ๋ฉ”๋ชจ๋ฆฌ ๋ถ„๋ฆฌ๋กœ ๊ฐ ๋‹จ๊ณ„์˜ ์ž…๋ ฅ ํ† ํฐ ์ˆ˜๊ฐ€ ์ค„์–ด, ์ง€์—ฐ๊ณผ ๋น„์šฉ์ด ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค. -Let's create a team with a dedicated web search agent, managed by another agent. +์›น ๊ฒ€์ƒ‰ ์ „๋‹ด ์—์ด์ „ํŠธ์™€ ์ด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ๋กœ ํŒ€์„ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. -The manager agent should have plotting capabilities to write its final report: so let us give it access to additional imports, including `plotly`, and `geopandas` + `shapely` for spatial plotting. +๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ๋Š” ์ตœ์ข… ๋ฆฌํฌํŠธ ์ž‘์„ฑ์„ ์œ„ํ•ด ์ถ”๊ฐ€ import(`plotly`, `geopandas`, `shapely`)๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ```python model = InferenceClientModel( @@ -247,15 +241,13 @@ web_agent = CodeAgent( calculate_cargo_travel_time, ], name="web_agent", - description="Browses the web to find information", + description="์›น์—์„œ ์ •๋ณด๋ฅผ ์ฐพ๋Š” ์—ญํ• ", verbosity_level=0, max_steps=10, ) ``` -The manager agent will need to do some mental heavy lifting. - -So we give it the stronger model [DeepSeek-R1](https://huggingface.co/deepseek-ai/DeepSeek-R1), and add a `planning_interval` to the mix. +๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ๋Š” ๋” ๊ฐ•๋ ฅํ•œ ๋ชจ๋ธ [DeepSeek-R1](https://huggingface.co/deepseek-ai/DeepSeek-R1)์„ ์‚ฌ์šฉํ•˜๊ณ , `planning_interval`๋„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ```python from smolagents.utils import encode_image_base64, make_image_url @@ -265,14 +257,14 @@ 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), "Make sure to save the plot under saved_map.png!" + assert os.path.exists(filepath), "saved_map.png ํŒŒ์ผ์ด ์ €์žฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!" image = Image.open(filepath) prompt = ( - f"Here is a user-given task and the agent steps: {agent_memory.get_succinct_steps()}. Now here is the plot that was made." - "Please check that the reasoning process and plot are correct: do they correctly answer the given task?" - "First list reasons why yes/no, then write your final decision: PASS in caps lock if it is satisfactory, FAIL if it is not." - "Don't be harsh: if the plot mostly solves the task, it should pass." - "To pass, a plot should be made using px.scatter_map and not any other method (scatter_map looks nicer)." + f"๋‹ค์Œ์€ ์‚ฌ์šฉ์ž ์š”์ฒญ๊ณผ ์—์ด์ „ํŠธ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค: {agent_memory.get_succinct_steps()}. ์•„๋ž˜๋Š” ์ƒ์„ฑ๋œ ์ง€๋„์ž…๋‹ˆ๋‹ค." + "์ถ”๋ก  ๊ณผ์ •๊ณผ ์ง€๋„๊ฐ€ ์š”์ฒญ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”." + "๋จผ์ € ์ด์œ ๋ฅผ ๋‚˜์—ดํ•œ ๋’ค, ์ตœ์ข… ๊ฒฐ์ •(PASS/FAIL)์„ ์ž‘์„ฑํ•˜์„ธ์š”." + "๋„ˆ๋ฌด ์—„๊ฒฉํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„ ํ•ด๊ฒฐํ–ˆ๋‹ค๋ฉด PASS์ž…๋‹ˆ๋‹ค." + "์ง€๋„๋Š” px.scatter_map์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ PASS์ž…๋‹ˆ๋‹ค." ) messages = [ { @@ -290,7 +282,7 @@ def check_reasoning_and_plot(final_answer, agent_memory): } ] output = multimodal_model(messages).content - print("Feedback: ", output) + print("ํ”ผ๋“œ๋ฐฑ: ", output) if "FAIL" in output: raise Exception(output) return True @@ -315,13 +307,13 @@ manager_agent = CodeAgent( ) ``` -Let us inspect what this team looks like: +์ด ํŒ€์˜ ๊ตฌ์กฐ๋ฅผ ์‹œ๊ฐํ™”ํ•ด๋ด…์‹œ๋‹ค: ```python manager_agent.visualize() ``` -This will generate something like this, helping us understand the structure and relationship between agents and tools used: +์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์กฐ์™€ ๋„๊ตฌ ์‚ฌ์šฉ ๊ด€๊ณ„๋ฅผ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python CodeAgent | deepseek-ai/DeepSeek-R1 @@ -330,58 +322,34 @@ CodeAgent | deepseek-ai/DeepSeek-R1 โ”‚ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ โ”‚ โ”ƒ Name โ”ƒ Description โ”ƒ Arguments โ”ƒ โ”‚ โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ -โ”‚ โ”‚ calculate_cargo_travel_time โ”‚ Calculate the travel time for a cargo โ”‚ origin_coords (`array`): Tuple of โ”‚ -โ”‚ โ”‚ โ”‚ plane between two points on Earth โ”‚ (latitude, longitude) for the โ”‚ -โ”‚ โ”‚ โ”‚ using great-circle distance. โ”‚ starting point โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ destination_coords (`array`): Tuple โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ of (latitude, longitude) for the โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ destination โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ cruising_speed_kmh (`number`): โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ Optional cruising speed in km/h โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ (defaults to 750 km/h for typical โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ cargo planes) โ”‚ -โ”‚ โ”‚ final_answer โ”‚ Provides a final answer to the given โ”‚ answer (`any`): The final answer to โ”‚ -โ”‚ โ”‚ โ”‚ problem. โ”‚ the problem โ”‚ +โ”‚ โ”‚ 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: Browses the web to find information + โ”œโ”€โ”€ ๐Ÿ“ Description: ์›น์—์„œ ์ •๋ณด๋ฅผ ์ฐพ๋Š” ์—ญํ•  โ””โ”€โ”€ ๐Ÿ› ๏ธ Tools: โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ โ”ƒ Name โ”ƒ Description โ”ƒ Arguments โ”ƒ โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ - โ”‚ web_search โ”‚ Performs a google web search for โ”‚ query (`string`): The search โ”‚ - โ”‚ โ”‚ your query then returns a string โ”‚ query to perform. โ”‚ - โ”‚ โ”‚ of the top search results. โ”‚ filter_year (`integer`): โ”‚ - โ”‚ โ”‚ โ”‚ Optionally restrict results to a โ”‚ - โ”‚ โ”‚ โ”‚ certain year โ”‚ - โ”‚ visit_webpage โ”‚ Visits a webpage at the given url โ”‚ url (`string`): The url of the โ”‚ - โ”‚ โ”‚ and reads its content as a โ”‚ webpage to visit. โ”‚ - โ”‚ โ”‚ markdown string. Use this to โ”‚ โ”‚ - โ”‚ โ”‚ browse webpages. โ”‚ โ”‚ - โ”‚ calculate_cargo_travel_time โ”‚ Calculate the travel time for a โ”‚ origin_coords (`array`): Tuple of โ”‚ - โ”‚ โ”‚ cargo plane between two points on โ”‚ (latitude, longitude) for the โ”‚ - โ”‚ โ”‚ Earth using great-circle โ”‚ starting point โ”‚ - โ”‚ โ”‚ distance. โ”‚ destination_coords (`array`): โ”‚ - โ”‚ โ”‚ โ”‚ Tuple of (latitude, longitude) โ”‚ - โ”‚ โ”‚ โ”‚ for the destination โ”‚ - โ”‚ โ”‚ โ”‚ cruising_speed_kmh (`number`): โ”‚ - โ”‚ โ”‚ โ”‚ Optional cruising speed in km/h โ”‚ - โ”‚ โ”‚ โ”‚ (defaults to 750 km/h for typical โ”‚ - โ”‚ โ”‚ โ”‚ cargo planes) โ”‚ - โ”‚ final_answer โ”‚ Provides a final answer to the โ”‚ answer (`any`): The final answer โ”‚ - โ”‚ โ”‚ given problem. โ”‚ to the problem โ”‚ + โ”‚ 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(""" -Find all Batman filming locations in the world, calculate the time to transfer via cargo plane to here (we're in Gotham, 40.7128ยฐ N, 74.0060ยฐ W). -Also give me some supercar factories with the same cargo plane transfer time. You need at least 6 points in total. -Represent this as spatial map of the world, with the locations represented as scatter points with a color that depends on the travel time, and save it to saved_map.png! +์ „ ์„ธ๊ณ„ ๋ฐฐํŠธ๋งจ ์ดฌ์˜์ง€๋ฅผ ๋ชจ๋‘ ์ฐพ์•„, ๊ณ ๋‹ด(40.7128ยฐ N, 74.0060ยฐ W)๊นŒ์ง€ ํ™”๋ฌผ๊ธฐ๋กœ ์ด๋™ํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์„ธ์š”. ์Šˆํผ์นด ๊ณต์žฅ๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ํฌํ•จํ•ด ์ด 6๊ฐœ ์ด์ƒ ์ง€์ ์„ ์ง€๋„์— ์‚ฐ์ ๋„๋กœ ํ‘œ์‹œํ•˜๊ณ , ์ด๋™ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ์ƒ‰์ƒ์„ ๋‹ค๋ฅด๊ฒŒ ํ•˜์„ธ์š”. ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋Š” saved_map.png๋กœ ์ €์žฅํ•˜์„ธ์š”! -Here's an example of how to plot and return a map: +์ง€๋„ ์˜ˆ์‹œ: 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, @@ -390,24 +358,24 @@ fig.show() fig.write_image("saved_image.png") final_answer(fig) -Never try to process strings using code: when you have a string to read, just print it and you'll see it. +๋ฌธ์ž์—ด์„ ์ฝ”๋“œ๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ๋งˆ์„ธ์š”. ๋ฌธ์ž์—ด์ด ์žˆ์œผ๋ฉด print๋กœ ์ถœ๋ ฅํ•˜์„ธ์š”. """) ``` -I don't know how that went in your run, but in mine, the manager agent skilfully divided tasks given to the web agent in `1. Search for Batman filming locations`, then `2. Find supercar factories`, before aggregating the lists and plotting the map. +์ œ ์‹คํ–‰์—์„œ๋Š” ๋งค๋‹ˆ์ € ์—์ด์ „ํŠธ๊ฐ€ ์›น ์—์ด์ „ํŠธ์—๊ฒŒ `1. ๋ฐฐํŠธ๋งจ ์ดฌ์˜์ง€ ๊ฒ€์ƒ‰`, `2. ์Šˆํผ์นด ๊ณต์žฅ ์ฐพ๊ธฐ`๋กœ ์ž‘์—…์„ ๋ถ„๋ฐฐํ•œ ๋’ค, ๊ฒฐ๊ณผ๋ฅผ ์ง‘๊ณ„ํ•ด ์ง€๋„๋ฅผ ๊ทธ๋ ธ์Šต๋‹ˆ๋‹ค. -Let's see what the map looks like by inspecting it directly from the agent state: +์—์ด์ „ํŠธ ์ƒํƒœ์—์„œ ์ง€๋„๋ฅผ ์ง์ ‘ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค: ```python manager_agent.python_executor.state["fig"] ``` -This will output the map: +์•„๋ž˜์™€ ๊ฐ™์ด ์ง€๋„๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค: -![Multiagent system example output map](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/smolagents/output_map.png) +![๋ฉ€ํ‹ฐ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ์˜ˆ์‹œ ์ถœ๋ ฅ ์ง€๋„](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/smolagents/output_map.png) -## Resources +## ์ฐธ๊ณ  ์ž๋ฃŒ -- [Multi-Agent Systems](https://huggingface.co/docs/smolagents/main/en/examples/multiagents) โ€“ Overview of multi-agent systems. -- [What is Agentic RAG?](https://weaviate.io/blog/what-is-agentic-rag) โ€“ Introduction to Agentic RAG. -- [Multi-Agent RAG System ๐Ÿค–๐Ÿค๐Ÿค– Recipe](https://huggingface.co/learn/cookbook/multiagent_rag_system) โ€“ Step-by-step guide to building a multi-agent RAG system. +- [๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ](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 index 11688a39..a5ad07e4 100644 --- a/units/ko/unit2/smolagents/quiz1.mdx +++ b/units/ko/unit2/smolagents/quiz1.mdx @@ -1,83 +1,83 @@ -# Small Quiz (ungraded) [[quiz1]] +# ์†Œ๊ทœ๋ชจ ํ€ด์ฆˆ(๋น„์ฑ„์ ) [[quiz1]] -Let's test your understanding of `smolagents` with a quick quiz! Remember, testing yourself helps reinforce learning and identify areas that may need review. +`smolagents`์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ๊ฐ„๋‹จํ•œ ํ€ด์ฆˆ๋กœ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค! ์Šค์Šค๋กœ ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉด ํ•™์Šต ๋‚ด์šฉ์„ ๊ฐ•ํ™”ํ•˜๊ณ , ๋ณต์Šต์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. -This is an optional quiz and it's not graded. +์ด ํ€ด์ฆˆ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ์ ์ˆ˜ํ™”๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -### Q1: What is one of the primary advantages of choosing `smolagents` over other frameworks? -Which statement best captures a core strength of the `smolagents` approach? +### Q1: `smolagents`๋ฅผ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋ณด๋‹ค ์„ ํƒํ•  ๋•Œ์˜ ์ฃผ์š” ์žฅ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? +๋‹ค์Œ ์ค‘ `smolagents` ์ ‘๊ทผ ๋ฐฉ์‹์˜ ํ•ต์‹ฌ ๊ฐ•์ ์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? --- -### Q2: In which scenario would you likely benefit most from using smolagents? -Which situation aligns well with what smolagents does best? +### Q2: ์–ด๋–ค ์ƒํ™ฉ์—์„œ smolagents๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ ํ•ฉํ• ๊นŒ์š”? +๋‹ค์Œ ์ค‘ smolagents์˜ ํŠน์„ฑ๊ณผ ๊ฐ€์žฅ ์ž˜ ๋งž๋Š” ์ƒํ™ฉ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? --- -### Q3: smolagents offers flexibility in model integration. Which statement best reflects its approach? -Choose the most accurate description of how smolagents interoperates with LLMs. +### Q3: smolagents์˜ ๋ชจ๋ธ ํ†ตํ•ฉ ์œ ์—ฐ์„ฑ์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๋ช…ํ•œ ๊ฒƒ์€? +smolagents๊ฐ€ LLM๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. --- -### Q5: How does smolagents integrate with the Hugging Face Hub for added benefits? -Which statement accurately describes one of the core advantages of Hub integration? +### Q5: smolagents๊ฐ€ Hugging Face Hub์™€ ํ†ตํ•ฉ๋˜์–ด ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ด์ ์€? +Hub ํ†ตํ•ฉ์˜ ํ•ต์‹ฌ ์žฅ์ ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์€? --- -Congratulations on completing this quiz! ๐ŸŽ‰ If you missed any questions, consider reviewing the *Why use smolagents* section for a deeper understanding. If you did well, you're ready to explore more advanced topics in smolagents! +ํ€ด์ฆˆ๋ฅผ ๋ชจ๋‘ ๋งˆ์ณค์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ ํ‹€๋ฆฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด *์™œ smolagents๋ฅผ ์‚ฌ์šฉํ• ๊นŒ* ์„น์…˜์„ ๋ณต์Šตํ•ด๋ณด์„ธ์š”. ์ž˜ ํ’€์—ˆ๋‹ค๋ฉด, ์ด์ œ smolagents์˜ ๋” ๊ณ ๊ธ‰ ์ฃผ์ œ๋กœ ๋„˜์–ด๊ฐˆ ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค! diff --git a/units/ko/unit2/smolagents/quiz2.mdx b/units/ko/unit2/smolagents/quiz2.mdx index 682fbbf2..50794bcc 100644 --- a/units/ko/unit2/smolagents/quiz2.mdx +++ b/units/ko/unit2/smolagents/quiz2.mdx @@ -1,147 +1,142 @@ -# Small Quiz (ungraded) [[quiz2]] +# ์†Œ๊ทœ๋ชจ ํ€ด์ฆˆ(๋น„์ฑ„์ ) [[quiz2]] -It's time to test your understanding of the *Code Agents*, *Tool Calling Agents*, and *Tools* sections. This quiz is optional and not graded. +*Code Agents*, *Tool Calling Agents*, *Tools* ์„น์…˜์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ด…์‹œ๋‹ค. ์ด ํ€ด์ฆˆ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ์ ์ˆ˜ํ™”๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. --- -### Q1: What is the key difference between creating a tool with the `@tool` decorator versus creating a subclass of `Tool` in smolagents? - -Which statement best describes the distinction between these two approaches for defining tools? +### Q1: smolagents์—์„œ `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๋„๊ตฌ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ `Tool` ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์˜ ํ•ต์‹ฌ ์ฐจ์ด๋Š”? +๋‘ ๋ฐฉ์‹์˜ ๋„๊ตฌ ์ •์˜ ์ฐจ์ด๋ฅผ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. @tool decorator is mandatory for retrieval-based tools, while subclasses of Tool are only for text-generation tasks", - explain: "Both approaches can be used for any type of tool, including retrieval-based or text-generation tools.", + text: "@tool ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ๋ฆฌํŠธ๋ฆฌ๋ฒŒ ๊ธฐ๋ฐ˜ ๋„๊ตฌ์—๋งŒ ํ•„์ˆ˜์ด๊ณ , Tool ์„œ๋ธŒํด๋ž˜์Šค๋Š” ํ…์ŠคํŠธ ์ƒ์„ฑ ์ž‘์—…์—๋งŒ ์‚ฌ์šฉ๋œ๋‹ค", + explain: "๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ์–ด๋–ค ์œ ํ˜•์˜ ๋„๊ตฌ์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.", }, { - text: "The @tool decorator is recommended for simple function-based tools, while subclasses of Tool offer more flexibility for complex functionality or custom metadata", - explain: "This is correct. The decorator approach is simpler, but subclassing allows more customized behavior.", + text: "@tool ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ๊ฐ„๋‹จํ•œ ํ•จ์ˆ˜ํ˜• ๋„๊ตฌ์— ๊ถŒ์žฅ๋˜๊ณ , Tool ์„œ๋ธŒํด๋ž˜์Šค๋Š” ๋ณต์žกํ•œ ๊ธฐ๋Šฅ์ด๋‚˜ ์ปค์Šคํ…€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋” ์œ ์—ฐํ•˜๋‹ค", + explain: "์ •๋‹ต์ž…๋‹ˆ๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋ฐฉ์‹์ด ๋” ๊ฐ„๋‹จํ•˜๊ณ , ์„œ๋ธŒํด๋ž˜์‹ฑ์€ ๋งž์ถค ๋™์ž‘์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.", correct: true }, { - text: "@tool can only be used in multi-agent systems, while creating a Tool subclass is for single-agent scenarios", - explain: "All agents (single or multi) can use either approach to define tools; there is no such restriction.", + text: "@tool์€ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ์—์„œ๋งŒ ์“ธ ์ˆ˜ ์žˆ๊ณ , Tool ์„œ๋ธŒํด๋ž˜์Šค๋Š” ๋‹จ์ผ ์—์ด์ „ํŠธ์—๋งŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค", + explain: "๋ชจ๋“  ์—์ด์ „ํŠธ(๋‹จ์ผ/๋ฉ€ํ‹ฐ)์—์„œ ๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.", }, { - text: "Decorating a function with @tool replaces the need for a docstring, whereas subclasses must not include docstrings", - explain: "Both methods benefit from clear docstrings. The decorator doesn't replace them, and a subclass can still have docstrings.", + text: "@tool๋กœ ํ•จ์ˆ˜์— ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ๋‹ฌ๋ฉด docstring์ด ํ•„์š” ์—†๊ณ , ์„œ๋ธŒํด๋ž˜์Šค๋Š” docstring์„ ํฌํ•จํ•˜๋ฉด ์•ˆ ๋œ๋‹ค", + explain: "๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ๋ช…ํ™•ํ•œ docstring์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.", } ]} /> --- -### Q2: How does a CodeAgent handle multi-step tasks using the ReAct (Reason + Act) approach? - -Which statement correctly describes how the CodeAgent executes a series of steps to solve a task? +### Q2: CodeAgent๋Š” ReAct(Reason + Act) ์ ‘๊ทผ๋ฒ•์œผ๋กœ ๋‹ค๋‹จ๊ณ„ ์ž‘์—…์„ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋‚˜์š”? +CodeAgent๊ฐ€ ์ผ๋ จ์˜ ๋‹จ๊ณ„๋ฅผ ์‹คํ–‰ํ•ด ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ๋ฐฉ์‹์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. --- -### Q3: Which of the following is a primary advantage of sharing a tool on the Hugging Face Hub? - -Select the best reason why a developer might upload and share their custom tool. +### Q3: ๋„๊ตฌ๋ฅผ Hugging Face Hub์— ๊ณต์œ ํ•  ๋•Œ์˜ ์ฃผ์š” ์žฅ์ ์€? +๊ฐœ๋ฐœ์ž๊ฐ€ ์ปค์Šคํ…€ ๋„๊ตฌ๋ฅผ ์—…๋กœ๋“œยท๊ณต์œ ํ•˜๋Š” ๊ฐ€์žฅ ํฐ ์ด์œ ๋ฅผ ๊ณ ๋ฅด์„ธ์š”. --- -### Q4: ToolCallingAgent differs from CodeAgent in how it executes actions. Which statement is correct? - -Choose the option that accurately describes how ToolCallingAgent works. +### Q4: ToolCallingAgent์™€ CodeAgent์˜ ์•ก์…˜ ์‹คํ–‰ ๋ฐฉ์‹ ์ฐจ์ด์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅธ ์„ค๋ช…์€? +ToolCallingAgent์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. --- -### Q5: What is included in the smolagents default toolbox, and why might you use it? - -Which statement best captures the purpose and contents of the default toolbox in smolagents? +### Q5: smolagents ๊ธฐ๋ณธ ๋„๊ตฌ ์ƒ์ž์—๋Š” ๋ฌด์—‡์ด ํฌํ•จ๋˜์–ด ์žˆ๊ณ , ์™œ ์‚ฌ์šฉํ• ๊นŒ์š”? +๊ธฐ๋ณธ ๋„๊ตฌ ์ƒ์ž์˜ ๋ชฉ์ ๊ณผ ๋‚ด์šฉ์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์„ ๊ณ ๋ฅด์„ธ์š”. --- -Congratulations on completing this quiz! ๐ŸŽ‰ If any questions gave you trouble, revisit the *Code Agents*, *Tool Calling Agents*, or *Tools* sections to strengthen your understanding. If you aced it, you're well on your way to building robust smolagents applications! +ํ€ด์ฆˆ๋ฅผ ๋ชจ๋‘ ๋งˆ์ณค์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ ์–ด๋ ค์› ๋˜ ๋ฌธ์ œ๋Š” *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 index 5483cc48..684538d6 100644 --- a/units/ko/unit2/smolagents/retrieval_agents.mdx +++ b/units/ko/unit2/smolagents/retrieval_agents.mdx @@ -5,39 +5,39 @@ ]} askForHelpUrl="http://hf.co/join/discord" /> -# Building Agentic RAG Systems +# ์—์ด์ „ํ‹ฑ RAG ์‹œ์Šคํ…œ ๊ตฌ์ถ•ํ•˜๊ธฐ -You can follow the code in this notebook that you can run using Google Colab. +์ฝ”๋“œ๋Š” ์ด ๋…ธํŠธ๋ถ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Colab์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Retrieval Augmented Generation (RAG) systems combine the capabilities of data retrieval and generation models to provide context-aware responses. For example, a user's query is passed to a search engine, and the retrieved results are given to the model along with the query. The model then generates a response based on the query and retrieved information. +Retrieval Augmented Generation(RAG) ์‹œ์Šคํ…œ์€ ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰๊ณผ ์ƒ์„ฑ ๋ชจ๋ธ์˜ ๋Šฅ๋ ฅ์„ ๊ฒฐํ•ฉํ•˜์—ฌ ์ƒํ™ฉ์— ๋งž๋Š” ๋‹ต๋ณ€์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž์˜ ์งˆ๋ฌธ์ด ๊ฒ€์ƒ‰ ์—”์ง„์— ์ „๋‹ฌ๋˜๊ณ , ๊ฒ€์ƒ‰๋œ ๊ฒฐ๊ณผ๊ฐ€ ์งˆ๋ฌธ๊ณผ ํ•จ๊ป˜ ๋ชจ๋ธ์— ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋ธ์€ ์งˆ๋ฌธ๊ณผ ๊ฒ€์ƒ‰๋œ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. -Agentic RAG (Retrieval-Augmented Generation) extends traditional RAG systems by **combining autonomous agents with dynamic knowledge retrieval**. +์—์ด์ „ํ‹ฑ RAG(๊ฒ€์ƒ‰ ์ฆ๊ฐ• ์ƒ์„ฑ)๋Š” **์ž์œจ ์—์ด์ „ํŠธ์™€ ๋™์  ์ง€์‹ ๊ฒ€์ƒ‰**์„ ๊ฒฐํ•ฉํ•˜์—ฌ ๊ธฐ์กด RAG ์‹œ์Šคํ…œ์„ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. -While traditional RAG systems use an LLM to answer queries based on retrieved data, agentic RAG **enables intelligent control of both retrieval and generation processes**, improving efficiency and accuracy. +๊ธฐ์กด RAG ์‹œ์Šคํ…œ์€ LLM์ด ๊ฒ€์ƒ‰๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•˜์ง€๋งŒ, ์—์ด์ „ํ‹ฑ RAG๋Š” **๊ฒ€์ƒ‰๊ณผ ์ƒ์„ฑ ๊ณผ์ •์„ ์ง€๋Šฅ์ ์œผ๋กœ ์ œ์–ด**ํ•˜์—ฌ ํšจ์œจ์„ฑ๊ณผ ์ •ํ™•์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค. -Traditional RAG systems face key limitations, such as **relying on a single retrieval step** and focusing on direct semantic similarity with the userโ€™s query, which may overlook relevant information. +๊ธฐ์กด RAG ์‹œ์Šคํ…œ์˜ ์ฃผ์š” ํ•œ๊ณ„๋Š” **๋‹จ์ผ ๊ฒ€์ƒ‰ ๋‹จ๊ณ„์— ์˜์กด**ํ•˜๊ณ , ์‚ฌ์šฉ์ž์˜ ์งˆ๋ฌธ๊ณผ ์ง์ ‘์ ์ธ ์˜๋ฏธ์  ์œ ์‚ฌ์„ฑ์—๋งŒ ์ง‘์ค‘ํ•˜์—ฌ ๊ด€๋ จ ์ •๋ณด๋ฅผ ๋†“์น  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. -Agentic RAG addresses these issues by allowing the agent to autonomously formulate search queries, critique retrieved results, and conduct multiple retrieval steps for a more tailored and comprehensive output. +์—์ด์ „ํ‹ฑ RAG๋Š” ์—์ด์ „ํŠธ๊ฐ€ ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ๋ฅผ ์ž์œจ์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ , ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋น„ํŒ์ ์œผ๋กœ ํ‰๊ฐ€ํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ๋ฒˆ์˜ ๊ฒ€์ƒ‰ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ ๋” ๋งž์ถคํ™”๋˜๊ณ  ํฌ๊ด„์ ์ธ ์ถœ๋ ฅ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. -## Basic Retrieval with DuckDuckGo +## DuckDuckGo๋ฅผ ํ™œ์šฉํ•œ ๊ธฐ๋ณธ ๊ฒ€์ƒ‰ -Let's build a simple agent that can search the web using DuckDuckGo. This agent will retrieve information and synthesize responses to answer queries. With Agentic RAG, Alfred's agent can: +์ด์ œ DuckDuckGo๋ฅผ ์‚ฌ์šฉํ•ด ์›น์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์ด ์—์ด์ „ํŠธ๋Š” ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ , ๋‹ต๋ณ€์„ ์ข…ํ•ฉํ•˜์—ฌ ์งˆ๋ฌธ์— ๋‹ตํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํ‹ฑ RAG๋ฅผ ํ™œ์šฉํ•˜๋ฉด Alfred์˜ ์—์ด์ „ํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -* Search for latest superhero party trends -* Refine results to include luxury elements -* Synthesize information into a complete plan +* ์ตœ์‹  ์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ ํŠธ๋ Œ๋“œ ๊ฒ€์ƒ‰ +* ๊ฒฐ๊ณผ๋ฅผ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์š”์†Œ๋กœ ์„ธ๋ถ„ํ™” +* ์ •๋ณด๋ฅผ ์ข…ํ•ฉํ•˜์—ฌ ์™„์„ฑ๋œ ๊ณ„ํš ์ œ์•ˆ -Here's how Alfred's agent can achieve this: +Alfred์˜ ์—์ด์ „ํŠธ๊ฐ€ ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ์‚ดํŽด๋ด…์‹œ๋‹ค: ```python from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel -# Initialize the search tool +# ๊ฒ€์ƒ‰ ๋„๊ตฌ ์ดˆ๊ธฐํ™” search_tool = DuckDuckGoSearchTool() -# Initialize the model +# ๋ชจ๋ธ ์ดˆ๊ธฐํ™” model = InferenceClientModel() agent = CodeAgent( @@ -45,29 +45,29 @@ agent = CodeAgent( tools=[search_tool], ) -# Example usage +# ์˜ˆ์‹œ ์‚ฌ์šฉ๋ฒ• response = agent.run( "Search for luxury superhero-themed party ideas, including decorations, entertainment, and catering." ) print(response) ``` -The agent follows this process: +์—์ด์ „ํŠธ์˜ ๋™์ž‘ ๊ณผ์ •: -1. **Analyzes the Request:** Alfredโ€™s agent identifies the key elements of the queryโ€”luxury superhero-themed party planning, with focus on decor, entertainment, and catering. -2. **Performs Retrieval:** The agent leverages DuckDuckGo to search for the most relevant and up-to-date information, ensuring it aligns with Alfredโ€™s refined preferences for a luxurious event. -3. **Synthesizes Information:** After gathering the results, the agent processes them into a cohesive, actionable plan for Alfred, covering all aspects of the party. -4. **Stores for Future Reference:** The agent stores the retrieved information for easy access when planning future events, optimizing efficiency in subsequent tasks. +1. **์š”์ฒญ ๋ถ„์„:** Alfred์˜ ์—์ด์ „ํŠธ๋Š” ์ฟผ๋ฆฌ์˜ ํ•ต์‹ฌ ์š”์†Œ(๊ณ ๊ธ‰ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ, ์žฅ์‹, ์—”ํ„ฐํ…Œ์ธ๋จผํŠธ, ์ผ€์ดํ„ฐ๋ง ๋“ฑ)๋ฅผ ํŒŒ์•…ํ•ฉ๋‹ˆ๋‹ค. +2. **๊ฒ€์ƒ‰ ์ˆ˜ํ–‰:** DuckDuckGo๋ฅผ ํ™œ์šฉํ•ด Alfred์˜ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ทจํ–ฅ์— ๋งž๋Š” ์ตœ์‹  ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. +3. **์ •๋ณด ์ข…ํ•ฉ:** ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํŒŒํ‹ฐ์˜ ๋ชจ๋“  ์ธก๋ฉด์„ ์•„์šฐ๋ฅด๋Š” ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๊ณ„ํš์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. +4. **์ •๋ณด ์ €์žฅ:** ๊ฒ€์ƒ‰๋œ ์ •๋ณด๋ฅผ ์ €์žฅํ•ด, ์ดํ›„ ํŒŒํ‹ฐ ์ค€๋น„ ์‹œ ํšจ์œจ์ ์œผ๋กœ ์žฌํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## Custom Knowledge Base Tool +## ๋งž์ถคํ˜• ์ง€์‹ ๋ฒ ์ด์Šค ๋„๊ตฌ -For specialized tasks, a custom knowledge base can be invaluable. Let's create a tool that queries a vector database of technical documentation or specialized knowledge. Using semantic search, the agent can find the most relevant information for Alfred's needs. +ํŠน์ • ์ž‘์—…์—๋Š” ๋งž์ถคํ˜• ์ง€์‹ ๋ฒ ์ด์Šค๊ฐ€ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ ๊ธฐ์ˆ  ๋ฌธ์„œ๋‚˜ ์ „๋ฌธ ์ง€์‹์„ ์ฟผ๋ฆฌํ•˜๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์˜๋ฏธ์  ๊ฒ€์ƒ‰์„ ํ†ตํ•ด Alfred์˜ ์š”๊ตฌ์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -A vector database stores numerical representations (embeddings) of text or other data, created by machine learning models. It enables semantic search by identifying similar meanings in high-dimensional space. +๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ํ…์ŠคํŠธ๋‚˜ ๊ธฐํƒ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ๋กœ ์ž„๋ฒ ๋”ฉ(์ˆซ์ž ๋ฒกํ„ฐ)ํ•˜์—ฌ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์˜๋ฏธ์ ์œผ๋กœ ์œ ์‚ฌํ•œ ์ •๋ณด๋ฅผ ๊ณ ์ฐจ์› ๊ณต๊ฐ„์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -This approach combines predefined knowledge with semantic search to provide context-aware solutions for event planning. With specialized knowledge access, Alfred can perfect every detail of the party. +์ด ์ ‘๊ทผ๋ฒ•์€ ์‚ฌ์ „ ์ •์˜๋œ ์ง€์‹๊ณผ ์˜๋ฏธ์  ๊ฒ€์ƒ‰์„ ๊ฒฐํ•ฉํ•ด ์ƒํ™ฉ์— ๋งž๋Š” ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. Alfred๋Š” ์ „๋ฌธ ์ง€์‹์— ์ ‘๊ทผํ•ด ํŒŒํ‹ฐ์˜ ๋ชจ๋“  ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์™„๋ฒฝํ•˜๊ฒŒ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -In this example, we'll create a tool that retrieves party planning ideas from a custom knowledge base. We'll use a BM25 retriever to search the knowledge base and return the top results, and `RecursiveCharacterTextSplitter` to split the documents into smaller chunks for more efficient search. +์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” BM25 ๊ฒ€์ƒ‰๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋งž์ถคํ˜• ์ง€์‹ ๋ฒ ์ด์Šค์—์„œ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. `RecursiveCharacterTextSplitter`๋กœ ๋ฌธ์„œ๋ฅผ ์ž‘์€ ์ฒญํฌ๋กœ ๋‚˜๋ˆ  ๊ฒ€์ƒ‰ ํšจ์œจ์„ ๋†’์ž…๋‹ˆ๋‹ค. ```python from langchain.docstore.document import Document @@ -78,11 +78,11 @@ from smolagents import CodeAgent, InferenceClientModel class PartyPlanningRetrieverTool(Tool): name = "party_planning_retriever" - description = "Uses semantic search to retrieve relevant party planning ideas for Alfredโ€™s superhero-themed party at Wayne Manor." + description = "Alfred์˜ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ๋ฅผ ์œ„ํ•œ ์•„์ด๋””์–ด๋ฅผ ์˜๋ฏธ์  ๊ฒ€์ƒ‰์œผ๋กœ ์ฐพ์•„์ค๋‹ˆ๋‹ค." inputs = { "query": { "type": "string", - "description": "The query to perform. This should be a query related to party planning or superhero themes.", + "description": "ํŒŒํ‹ฐ ์ค€๋น„๋‚˜ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ์™€ ๊ด€๋ จ๋œ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.", } } output_type = "string" @@ -90,29 +90,29 @@ class PartyPlanningRetrieverTool(Tool): def __init__(self, docs, **kwargs): super().__init__(**kwargs) self.retriever = BM25Retriever.from_documents( - docs, k=5 # Retrieve the top 5 documents + docs, k=5 # ์ƒ์œ„ 5๊ฐœ ๋ฌธ์„œ ๊ฒ€์ƒ‰ ) def forward(self, query: str) -> str: - assert isinstance(query, str), "Your search query must be a string" + assert isinstance(query, str), "๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ๋Š” ๋ฌธ์ž์—ด์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค." docs = self.retriever.invoke( query, ) - return "\nRetrieved ideas:\n" + "".join( + return "\n๊ฒ€์ƒ‰๋œ ์•„์ด๋””์–ด:\n" + "".join( [ - f"\n\n===== Idea {str(i)} =====\n" + doc.page_content + f"\n\n===== ์•„์ด๋””์–ด {str(i)} =====\n" + doc.page_content for i, doc in enumerate(docs) ] ) -# Simulate a knowledge base about party planning +# ํŒŒํ‹ฐ ์ค€๋น„์— ๊ด€ํ•œ ์ง€์‹ ๋ฒ ์ด์Šค ์˜ˆ์‹œ party_ideas = [ - {"text": "A superhero-themed masquerade ball with luxury decor, including gold accents and velvet curtains.", "source": "Party Ideas 1"}, - {"text": "Hire a professional DJ who can play themed music for superheroes like Batman and Wonder Woman.", "source": "Entertainment Ideas"}, - {"text": "For catering, serve dishes named after superheroes, like 'The Hulk's Green Smoothie' and 'Iron Man's Power Steak.'", "source": "Catering Ideas"}, - {"text": "Decorate with iconic superhero logos and projections of Gotham and other superhero cities around the venue.", "source": "Decoration Ideas"}, - {"text": "Interactive experiences with VR where guests can engage in superhero simulations or compete in themed games.", "source": "Entertainment 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 = [ @@ -120,7 +120,7 @@ source_docs = [ for doc in party_ideas ] -# Split the documents into smaller chunks for more efficient search +# ๋ฌธ์„œ๋ฅผ ์ž‘์€ ์ฒญํฌ๋กœ ๋ถ„ํ•  text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, chunk_overlap=50, @@ -130,13 +130,13 @@ text_splitter = RecursiveCharacterTextSplitter( ) docs_processed = text_splitter.split_documents(source_docs) -# Create the retriever tool +# ๊ฒ€์ƒ‰ ๋„๊ตฌ ์ƒ์„ฑ party_planning_retriever = PartyPlanningRetrieverTool(docs_processed) -# Initialize the agent +# ์—์ด์ „ํŠธ ์ดˆ๊ธฐํ™” agent = CodeAgent(tools=[party_planning_retriever], model=InferenceClientModel()) -# Example usage +# ์˜ˆ์‹œ ์‚ฌ์šฉ๋ฒ• response = agent.run( "Find ideas for a luxury superhero-themed party, including entertainment, catering, and decoration options." ) @@ -144,25 +144,25 @@ response = agent.run( print(response) ``` -This enhanced agent can: -1. First check the documentation for relevant information -2. Combine insights from the knowledge base -3. Maintain conversation context in memory +์ด ํ–ฅ์ƒ๋œ ์—์ด์ „ํŠธ๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +1. ๋จผ์ € ๋ฌธ์„œ์—์„œ ๊ด€๋ จ ์ •๋ณด ๊ฒ€์ƒ‰ +2. ์ง€์‹ ๋ฒ ์ด์Šค์˜ ์ธ์‚ฌ์ดํŠธ ๊ฒฐํ•ฉ +3. ๋Œ€ํ™” ๋งฅ๋ฝ์„ ๋ฉ”๋ชจ๋ฆฌ์— ์œ ์ง€ -## Enhanced Retrieval Capabilities +## ๊ณ ๋„ํ™”๋œ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ -When building agentic RAG systems, the agent can employ sophisticated strategies like: +์—์ด์ „ํ‹ฑ RAG ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ๋•Œ, ์—์ด์ „ํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณ ๊ธ‰ ์ „๋žต์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -1. **Query Reformulation:** Instead of using the raw user query, the agent can craft optimized search terms that better match the target documents -2. **Query Decomposition:** Instead of using the user query directly, if it contains multiple pieces of information to query, it can be decomposed to multiple queries -3. **Query Expansion:** Somehow similar to Query Reformulation but done multiple times to put the query in multiple wordings to query them all -4. **Reranking:** Using Cross-Encoders to assign more comprehensive and semantic relevance scores between retrieved documents and search query -5. **Multi-Step Retrieval:** The agent can perform multiple searches, using initial results to inform subsequent queries -6. **Source Integration:** Information can be combined from multiple sources like web search and local documentation -7. **Result Validation:** Retrieved content can be analyzed for relevance and accuracy before being included in responses +1. **์ฟผ๋ฆฌ ์žฌ๊ตฌ์„ฑ(Query Reformulation):** ์›๋ณธ ์ฟผ๋ฆฌ ๋Œ€์‹ , ๋ฌธ์„œ์— ๋” ์ž˜ ๋งž๋Š” ์ตœ์ ํ™”๋œ ๊ฒ€์ƒ‰์–ด ์ƒ์„ฑ +2. **์ฟผ๋ฆฌ ๋ถ„ํ•ด(Query Decomposition):** ์—ฌ๋Ÿฌ ์ •๋ณด๋ฅผ ํฌํ•จํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋ถ„ํ•ดํ•ด ๊ฐ๊ฐ ๊ฒ€์ƒ‰ +3. **์ฟผ๋ฆฌ ํ™•์žฅ(Query Expansion):** ์ฟผ๋ฆฌ๋ฅผ ๋‹ค์–‘ํ•œ ํ‘œํ˜„์œผ๋กœ ํ™•์žฅํ•ด ์—ฌ๋Ÿฌ ๋ฐฉ์‹์œผ๋กœ ๊ฒ€์ƒ‰ +4. **์žฌ์ •๋ ฌ(Reranking):** Cross-Encoder ๋“ฑ์œผ๋กœ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ์ฟผ๋ฆฌ์˜ ์˜๋ฏธ์  ๊ด€๋ จ์„ฑ ์ ์ˆ˜ ๋ถ€์—ฌ +5. **๋‹ค๋‹จ๊ณ„ ๊ฒ€์ƒ‰(Multi-Step Retrieval):** ์ดˆ๊ธฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ๋ฐ˜๋ณต +6. **์†Œ์Šค ํ†ตํ•ฉ(Source Integration):** ์›น ๊ฒ€์ƒ‰, ๋กœ์ปฌ ๋ฌธ์„œ ๋“ฑ ๋‹ค์–‘ํ•œ ์†Œ์Šค ๊ฒฐํ•ฉ +7. **๊ฒฐ๊ณผ ๊ฒ€์ฆ(Result Validation):** ๊ฒ€์ƒ‰๋œ ๋‚ด์šฉ์˜ ์ ํ•ฉ์„ฑ๊ณผ ์ •ํ™•์„ฑ ํ‰๊ฐ€ ํ›„ ๋‹ต๋ณ€์— ํฌํ•จ -Effective agentic RAG systems require careful consideration of several key aspects. The agent **should select between available tools based on the query type and context**. Memory systems help maintain conversation history and avoid repetitive retrievals. Having fallback strategies ensures the system can still provide value even when primary retrieval methods fail. Additionally, implementing validation steps helps ensure the accuracy and relevance of retrieved information. +ํšจ๊ณผ์ ์ธ ์—์ด์ „ํ‹ฑ RAG ์‹œ์Šคํ…œ์„ ์œ„ํ•ด์„œ๋Š” ์—ฌ๋Ÿฌ ์ธก๋ฉด์„ ์‹ ์ค‘ํžˆ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” **์ฟผ๋ฆฌ ์œ ํ˜•๊ณผ ๋งฅ๋ฝ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ๋„๊ตฌ๋ฅผ ์„ ํƒ**ํ•ด์•ผ ํ•˜๋ฉฐ, ๋ฉ”๋ชจ๋ฆฌ ์‹œ์Šคํ…œ์„ ํ†ตํ•ด ๋Œ€ํ™” ์ด๋ ฅ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์ค‘๋ณต ๊ฒ€์ƒ‰์„ ๋ฐฉ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์˜ˆ๋น„ ์ „๋žต์„ ๋งˆ๋ จํ•ด ์ฃผ์š” ๊ฒ€์ƒ‰ ๋ฐฉ๋ฒ•์ด ์‹คํŒจํ•ด๋„ ๊ฐ€์น˜๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋ฉฐ, ๊ฒ€์ฆ ๋‹จ๊ณ„๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์˜ ์ •ํ™•์„ฑ๊ณผ ์ ํ•ฉ์„ฑ์„ ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -## Resources +## ์ฐธ๊ณ  ์ž๋ฃŒ -- [Agentic RAG: turbocharge your RAG with query reformulation and self-query! ๐Ÿš€](https://huggingface.co/learn/cookbook/agent_rag) - Recipe for developing an Agentic RAG system using smolagents. +- [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 index e93049fd..3904eca4 100644 --- a/units/ko/unit2/smolagents/tool_calling_agents.mdx +++ b/units/ko/unit2/smolagents/tool_calling_agents.mdx @@ -5,15 +5,15 @@ ]} askForHelpUrl="http://hf.co/join/discord" /> -# Writing actions as code snippets or JSON blobs +# ์•ก์…˜์„ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ ๋˜๋Š” JSON ๋ธ”๋กญ์œผ๋กœ ์ž‘์„ฑํ•˜๊ธฐ -You can follow the code in this notebook that you can run using Google Colab. +์ฝ”๋“œ๋Š” ์ด ๋…ธํŠธ๋ถ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Colab์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Tool Calling Agents are the second type of agent available in `smolagents`. Unlike Code Agents that use Python snippets, these agents **use the built-in tool-calling capabilities of LLM providers** to generate tool calls as **JSON structures**. This is the standard approach used by OpenAI, Anthropic, and many other providers. +Tool Calling Agent๋Š” `smolagents`์—์„œ ์ œ๊ณตํ•˜๋Š” ๋‘ ๋ฒˆ์งธ ์œ ํ˜•์˜ ์—์ด์ „ํŠธ์ž…๋‹ˆ๋‹ค. Python ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” CodeAgent์™€ ๋‹ฌ๋ฆฌ, **Tool Calling Agent๋Š” LLM ์ œ๊ณต์—…์ฒด์˜ ๋‚ด์žฅ ํˆด ์ฝœ๋ง ๊ธฐ๋Šฅ**์„ ํ™œ์šฉํ•ด **JSON ๊ตฌ์กฐ**๋กœ ํˆด ํ˜ธ์ถœ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” OpenAI, Anthropic ๋“ฑ ๋งŽ์€ ์ œ๊ณต์—…์ฒด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ‘œ์ค€ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. -Let's look at an example. When Alfred wants to search for catering services and party ideas, a `CodeAgent` would generate and run Python code like this: +์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๊ฐ€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค์™€ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์‹ถ์„ ๋•Œ, `CodeAgent`๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด Python ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ด ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค: ```python for query in [ @@ -23,7 +23,7 @@ for query in [ print(web_search(f"Search for: {query}")) ``` -A `ToolCallingAgent` would instead create a JSON structure: +`ToolCallingAgent`๋Š” ๋Œ€์‹  JSON ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: ```python [ @@ -32,21 +32,21 @@ A `ToolCallingAgent` would instead create a JSON structure: ] ``` -This JSON blob is then used to execute the tool calls. +์ด JSON ๋ธ”๋กญ์ด ์‹œ์Šคํ…œ์— ์ „๋‹ฌ๋˜์–ด ํˆด ํ˜ธ์ถœ์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. -While `smolagents` primarily focuses on `CodeAgents` since [they perform better overall](https://huggingface.co/papers/2402.01030), `ToolCallingAgents` can be effective for simple systems that don't require variable handling or complex tool calls. +`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) -## How Do Tool Calling Agents Work? +## Tool Calling Agent๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋‚˜์š”? -Tool Calling Agents follow the same multi-step workflow as Code Agents (see the [previous section](./code_agents) for details). +Tool Calling Agent๋Š” CodeAgent์™€ ๋™์ผํ•œ ๋‹ค๋‹จ๊ณ„ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค([์ด์ „ ์„น์…˜](./code_agents) ์ฐธ๊ณ ). -The key difference is in **how they structure their actions**: instead of executable code, they **generate JSON objects that specify tool names and arguments**. The system then **parses these instructions** to execute the appropriate tools. +ํ•ต์‹ฌ ์ฐจ์ด์ ์€ **์•ก์…˜์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฐฉ์‹**์ž…๋‹ˆ๋‹ค. ToolCallingAgent๋Š” ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ ๋Œ€์‹ , **ํˆด ์ด๋ฆ„๊ณผ ์ธ์ž๋ฅผ ๋ช…์‹œํ•œ JSON ๊ฐ์ฒด**๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ์€ ์ด ๋ช…๋ น์„ ํŒŒ์‹ฑํ•ด ์ ์ ˆํ•œ ํˆด์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. -## Example: Running a Tool Calling Agent +## ์˜ˆ์‹œ: Tool Calling Agent ์‹คํ–‰ํ•˜๊ธฐ -Let's revisit the previous example where Alfred started party preparations, but this time we'll use a `ToolCallingAgent` to highlight the difference. We'll build an agent that can search the web using DuckDuckGo, just like in our Code Agent example. The only difference is the agent type - the framework handles everything else: +์•ž์„œ Alfred๊ฐ€ ํŒŒํ‹ฐ ์ค€๋น„๋ฅผ ์‹œ์ž‘ํ–ˆ๋˜ ์˜ˆ์‹œ๋ฅผ ToolCallingAgent๋กœ ๋‹ค์‹œ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. DuckDuckGo๋ฅผ ํ™œ์šฉํ•ด ์›น์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์ง€๋งŒ, ์—์ด์ „ํŠธ ํƒ€์ž…๋งŒ ๋‹ค๋ฅด๊ณ  ๋‚˜๋จธ์ง€๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค: ```python from smolagents import ToolCallingAgent, DuckDuckGoSearchTool, InferenceClientModel @@ -56,19 +56,19 @@ agent = ToolCallingAgent(tools=[DuckDuckGoSearchTool()], model=InferenceClientMo agent.run("Search for the best music recommendations for a party at the Wayne's mansion.") ``` -When you examine the agent's trace, instead of seeing `Executing parsed code:`, you'll see something like: +์—์ด์ „ํŠธ์˜ ์‹คํ–‰ ๋กœ๊ทธ๋ฅผ ๋ณด๋ฉด, `Executing parsed code:` ๋Œ€์‹  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค: ```text โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ”‚ Calling tool: 'web_search' with arguments: {'query': "best music recommendations for a party at Wayne's โ”‚ โ”‚ mansion"} โ”‚ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ -``` +``` -The agent generates a structured tool call that the system processes to produce the output, rather than directly executing code like a `CodeAgent`. +์—์ด์ „ํŠธ๋Š” ๊ตฌ์กฐํ™”๋œ ํˆด ํ˜ธ์ถœ์„ ์ƒ์„ฑํ•˜๊ณ , ์‹œ์Šคํ…œ์ด ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. CodeAgent์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -Now that we understand both agent types, we can choose the right one for our needs. Let's continue exploring `smolagents` to make Alfred's party a success! ๐ŸŽ‰ +์ด์ œ ๋‘ ์—์ด์ „ํŠธ ํƒ€์ž…์˜ ์ฐจ์ด๋ฅผ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ํ•„์š”์— ๋”ฐ๋ผ ์ ํ•ฉํ•œ ๋ฐฉ์‹์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Alfred์˜ ํŒŒํ‹ฐ ์ค€๋น„๋ฅผ ๊ณ„์† ์ด์–ด๊ฐ€๋ด…์‹œ๋‹ค! ๐ŸŽ‰ -## Resources +## ์ฐธ๊ณ  ์ž๋ฃŒ -- [ToolCallingAgent documentation](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/agents#smolagents.ToolCallingAgent) - Official documentation for ToolCallingAgent +- [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 index 66f7cb21..893bdbcf 100644 --- a/units/ko/unit2/smolagents/tools.mdx +++ b/units/ko/unit2/smolagents/tools.mdx @@ -5,78 +5,75 @@ ]} askForHelpUrl="http://hf.co/join/discord" /> -# Tools +# ๋„๊ตฌ (Tools) -As we explored in [unit 1](https://huggingface.co/learn/agents-course/unit1/tools), agents use tools to perform various actions. In `smolagents`, tools are treated as **functions that an LLM can call within an agent system**. +[unit 1](https://huggingface.co/learn/agents-course/unit1/tools)์—์„œ ์‚ดํŽด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ, ์—์ด์ „ํŠธ๋Š” ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. `smolagents`์—์„œ ๋„๊ตฌ๋Š” **์—์ด์ „ํŠธ ์‹œ์Šคํ…œ ๋‚ด์—์„œ LLM์ด ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜**๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค. -To interact with a tool, the LLM needs an **interface description** with these key components: +๋„๊ตฌ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ ค๋ฉด LLM์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ **์ธํ„ฐํŽ˜์ด์Šค ์„ค๋ช…**์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค: -- **Name**: What the tool is called -- **Tool description**: What the tool does -- **Input types and descriptions**: What arguments the tool accepts -- **Output type**: What the tool returns +- **์ด๋ฆ„**: ๋„๊ตฌ์˜ ์ด๋ฆ„ +- **๋„๊ตฌ ์„ค๋ช…**: ๋„๊ตฌ๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—… +- **์ž…๋ ฅ ํƒ€์ž… ๋ฐ ์„ค๋ช…**: ๋„๊ตฌ๊ฐ€ ๋ฐ›๋Š” ์ธ์ž +- **์ถœ๋ ฅ ํƒ€์ž…**: ๋„๊ตฌ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’ -For instance, while preparing for a party at Wayne Manor, Alfred needs various tools to gather information - from searching for catering services to finding party theme ideas. Here's how a simple search tool interface might look: +์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๊ฐ€ Wayne Manor์—์„œ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•  ๋•Œ, ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค ๊ฒ€์ƒ‰๋ถ€ํ„ฐ ํŒŒํ‹ฐ ํ…Œ๋งˆ ์•„์ด๋””์–ด ์ฐพ๊ธฐ๊นŒ์ง€ ๋‹ค์–‘ํ•œ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ๊ฐ„๋‹จํ•œ ๊ฒ€์ƒ‰ ๋„๊ตฌ ์ธํ„ฐํŽ˜์ด์Šค ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค: -- **Name:** `web_search` -- **Tool description:** Searches the web for specific queries -- **Input:** `query` (string) - The search term to look up -- **Output:** String containing the search results +- **์ด๋ฆ„:** `web_search` +- **๋„๊ตฌ ์„ค๋ช…:** ํŠน์ • ์ฟผ๋ฆฌ๋กœ ์›น์„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค +- **์ž…๋ ฅ:** `query` (string) - ๊ฒ€์ƒ‰์–ด +- **์ถœ๋ ฅ:** ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ด๊ธด ๋ฌธ์ž์—ด -By using these tools, Alfred can make informed decisions and gather all the information needed for planning the perfect party. +์ด๋Ÿฌํ•œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Alfred๋Š” ์™„๋ฒฝํ•œ ํŒŒํ‹ฐ ์ค€๋น„๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์‰ฝ๊ฒŒ ๋ชจ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Below, you can see an animation illustrating how a tool call is managed: +์•„๋ž˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ๋„๊ตฌ ํ˜ธ์ถœ์ด ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌ๋˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค: ![Agentic pipeline from https://huggingface.co/docs/smolagents/conceptual_guides/react](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/Agent_ManimCE.gif) -## Tool Creation Methods +## ๋„๊ตฌ ์ƒ์„ฑ ๋ฐฉ๋ฒ• -In `smolagents`, tools can be defined in two ways: -1. **Using the `@tool` decorator** for simple function-based tools -2. **Creating a subclass of `Tool`** for more complex functionality +`smolagents`์—์„œ ๋„๊ตฌ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +1. **`@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ**๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•œ ํ•จ์ˆ˜ํ˜• ๋„๊ตฌ +2. **`Tool` ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•œ ๋ณต์žกํ•œ ๋„๊ตฌ** -### The `@tool` Decorator +### `@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ -The `@tool` decorator is the **recommended way to define simple tools**. Under the hood, smolagents will parse basic information about the function from Python. So if you name your function clearly and write a good docstring, it will be easier for the LLM to use. +`@tool` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” **๊ฐ„๋‹จํ•œ ๋„๊ตฌ๋ฅผ ์ •์˜ํ•  ๋•Œ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•**์ž…๋‹ˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ smolagents๋Š” ํ•จ์ˆ˜์—์„œ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ํŒŒ์‹ฑํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์ด๋ฆ„์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์ง“๊ณ , ์ข‹์€ docstring์„ ์ž‘์„ฑํ•˜๋ฉด LLM์ด ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Using this approach, we define a function with: +์ด ๋ฐฉ์‹์—์„œ๋Š” ๋‹ค์Œ์„ ์ง€์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค: +- **๋ช…ํ™•ํ•˜๊ณ  ์„ค๋ช…์ ์ธ ํ•จ์ˆ˜๋ช…** +- **์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์— ํƒ€์ž… ํžŒํŠธ ์‚ฌ์šฉ** +- **์ž์„ธํ•œ ์„ค๋ช…๊ณผ Args ์„น์…˜** -- **A clear and descriptive function name** that helps the LLM understand its purpose. -- **Type hints for both inputs and outputs** to ensure proper usage. -- **A detailed description**, including an `Args:` section where each argument is explicitly described. These descriptions provide valuable context for the LLM, so it's important to write them carefully. - -#### Generating a tool that retrieves the highest-rated catering +#### ๊ณ ํ‰์  ์ผ€์ดํ„ฐ๋ง ๋„๊ตฌ ์˜ˆ์‹œ Alfred Catering -You can follow the code in this notebook that you can run using Google Colab. +์ฝ”๋“œ๋Š” ์ด ๋…ธํŠธ๋ถ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Colab์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Let's imagine that Alfred has already decided on the menu for the party, but now he needs help preparing food for such a large number of guests. To do so, he would like to hire a catering service and needs to identify the highest-rated options available. Alfred can leverage a tool to search for the best catering services in his area. - -Below is an example of how Alfred can use the `@tool` decorator to make this happen: +Alfred๊ฐ€ ํŒŒํ‹ฐ ๋ฉ”๋‰ด๋ฅผ ์ •ํ–ˆ๋‹ค๋ฉด, ๋งŽ์€ ์†๋‹˜์„ ์œ„ํ•ด ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ๊ณ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Gotham์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ์ฐพ๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ```python from smolagents import CodeAgent, InferenceClientModel, tool -# Let's pretend we have a function that fetches the highest-rated catering services. +# Gotham์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ ์˜ˆ์‹œ @tool def catering_service_tool(query: str) -> str: """ - This tool returns the highest-rated catering service in Gotham City. + ์ด ๋„๊ตฌ๋Š” Gotham City์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. Args: - query: A search term for finding catering services. + query: ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•œ ๊ฒ€์ƒ‰์–ด """ - # Example list of catering services and their ratings + # ์˜ˆ์‹œ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค์™€ ํ‰์  services = { "Gotham Catering Co.": 4.9, "Wayne Manor Catering": 4.8, "Gotham City Events": 4.7, } - # Find the highest rated catering service (simulating search query filtering) + # ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์„œ๋น„์Šค ์ฐพ๊ธฐ(๊ฒ€์ƒ‰์–ด ํ•„ํ„ฐ๋ง์€ ์ƒ๋žต) best_service = max(services, key=services.get) return best_service @@ -84,31 +81,29 @@ def catering_service_tool(query: str) -> str: agent = CodeAgent(tools=[catering_service_tool], model=InferenceClientModel()) -# Run the agent to find the best catering service +# ์—์ด์ „ํŠธ ์‹คํ–‰ ์˜ˆ์‹œ result = agent.run( "Can you give me the name of the highest-rated catering service in Gotham City?" ) -print(result) # Output: Gotham Catering Co. +print(result) # ์ถœ๋ ฅ: Gotham Catering Co. ``` -### Defining a Tool as a Python Class - -This approach involves creating a subclass of [`Tool`](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools#smolagents.Tool). For complex tools, we can implement a class instead of a Python function. The class wraps the function with metadata that helps the LLM understand how to use it effectively. In this class, we define: +### Python ํด๋ž˜์Šค๋กœ ๋„๊ตฌ ์ •์˜ํ•˜๊ธฐ -- `name`: The tool's name. -- `description`: A description used to populate the agent's system prompt. -- `inputs`: A dictionary with keys `type` and `description`, providing information to help the Python interpreter process inputs. -- `output_type`: Specifies the expected output type. -- `forward`: The method containing the inference logic to execute. +์ด ๋ฐฉ์‹์€ [`Tool`](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools#smolagents.Tool) ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด ๋ณต์žกํ•œ ๋„๊ตฌ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ํด๋ž˜์Šค๋Š” ํ•จ์ˆ˜์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•ด LLM์ด ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค์—์„œ๋Š” ๋‹ค์Œ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: -Below, we can see an example of a tool built using `Tool` and how to integrate it within a `CodeAgent`. +- `name`: ๋„๊ตฌ ์ด๋ฆ„ +- `description`: ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์— ๋“ค์–ด๊ฐˆ ์„ค๋ช… +- `inputs`: ์ž…๋ ฅ ํƒ€์ž…๊ณผ ์„ค๋ช…์ด ๋‹ด๊ธด ๋”•์…”๋„ˆ๋ฆฌ +- `output_type`: ๋ฐ˜ํ™˜ ํƒ€์ž… +- `forward`: ์‹ค์ œ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ -#### Generating a tool to generate ideas about the superhero-themed party +์•„๋ž˜๋Š” `Tool`์„ ์ƒ์†ํ•ด ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋„๊ตฌ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. -Alfred's party at the mansion is a **superhero-themed event**, but he needs some creative ideas to make it truly special. As a fantastic host, he wants to surprise the guests with a unique theme. +#### ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด ์ƒ์„ฑ ๋„๊ตฌ -To do this, he can use an agent that generates superhero-themed party ideas based on a given category. This way, Alfred can find the perfect party theme to wow his guests. +Alfred๋Š” Wayne Manor์—์„œ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค. ์†๋‹˜๋“ค์„ ๋†€๋ผ๊ฒŒ ํ•  ๋…ํŠนํ•œ ํ…Œ๋งˆ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ๋„๊ตฌ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์— ๋”ฐ๋ผ ์ฐฝ์˜์ ์ธ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ```python from smolagents import Tool, CodeAgent, InferenceClientModel @@ -116,13 +111,13 @@ from smolagents import Tool, CodeAgent, InferenceClientModel class SuperheroPartyThemeTool(Tool): name = "superhero_party_theme_generator" description = """ - This tool suggests creative superhero-themed party ideas based on a category. - It returns a unique party theme idea.""" + ์ด ๋„๊ตฌ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์— ๋”ฐ๋ผ ์ฐฝ์˜์ ์ธ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. + ๊ณ ์œ ํ•œ ํŒŒํ‹ฐ ํ…Œ๋งˆ ์•„์ด๋””์–ด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.""" inputs = { "category": { "type": "string", - "description": "The type of superhero party (e.g., 'classic heroes', 'villain masquerade', 'futuristic Gotham').", + "description": "์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ ์œ ํ˜•(์˜ˆ: 'classic heroes', 'villain masquerade', 'futuristic Gotham')", } } @@ -130,30 +125,30 @@ class SuperheroPartyThemeTool(Tool): def forward(self, category: str): themes = { - "classic heroes": "Justice League Gala: Guests come dressed as their favorite DC heroes with themed cocktails like 'The Kryptonite Punch'.", - "villain masquerade": "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains.", - "futuristic Gotham": "Neo-Gotham Night: A cyberpunk-style party inspired by Batman Beyond, with neon decorations and futuristic gadgets." + "classic heroes": "Justice League Gala: ์†๋‹˜๋“ค์ด DC ์˜์›…์œผ๋กœ ๋ถ„์žฅํ•˜๊ณ , 'The Kryptonite Punch' ๊ฐ™์€ ํ…Œ๋งˆ ์นตํ…Œ์ผ ์ œ๊ณต.", + "villain masquerade": "Gotham Rogues' Ball: ์†๋‹˜๋“ค์ด ๋ฐฐํŠธ๋งจ ๋นŒ๋Ÿฐ์œผ๋กœ ๋ถ„์žฅํ•˜๋Š” ๋ฏธ์Šคํ„ฐ๋ฆฌ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ.", + "futuristic Gotham": "Neo-Gotham Night: ๋ฐฐํŠธ๋งจ ๋น„์š˜๋“œ์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ์‚ฌ์ด๋ฒ„ํŽ‘ํฌ ์Šคํƒ€์ผ ํŒŒํ‹ฐ, ๋„ค์˜จ ์žฅ์‹๊ณผ ๋ฏธ๋ž˜ํ˜• ์†Œํ’ˆ.", } - return themes.get(category.lower(), "Themed party idea not found. Try 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.") + return themes.get(category.lower(), "ํ…Œ๋งˆ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. 'classic heroes', 'villain masquerade', 'futuristic Gotham' ์ค‘์—์„œ ์„ ํƒํ•ด๋ณด์„ธ์š”.") -# Instantiate the tool +# ๋„๊ตฌ ์ธ์Šคํ„ด์Šคํ™” party_theme_tool = SuperheroPartyThemeTool() agent = CodeAgent(tools=[party_theme_tool], model=InferenceClientModel()) -# Run the agent to generate a party theme idea +# ์—์ด์ „ํŠธ ์‹คํ–‰ ์˜ˆ์‹œ result = agent.run( "What would be a good superhero party idea for a 'villain masquerade' theme?" ) -print(result) # Output: "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains." +print(result) # ์ถœ๋ ฅ: "Gotham Rogues' Ball: ์†๋‹˜๋“ค์ด ๋ฐฐํŠธ๋งจ ๋นŒ๋Ÿฐ์œผ๋กœ ๋ถ„์žฅํ•˜๋Š” ๋ฏธ์Šคํ„ฐ๋ฆฌ ๊ฐ€๋ฉด๋ฌด๋„ํšŒ." ``` -With this tool, Alfred will be the ultimate super host, impressing his guests with a superhero-themed party they won't forget! ๐Ÿฆธโ€โ™‚๏ธ๐Ÿฆธโ€โ™€๏ธ +์ด ๋„๊ตฌ๋กœ Alfred๋Š” ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ์˜ ์™„๋ฒฝํ•œ ํ˜ธ์ŠคํŠธ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๐Ÿฆธโ€โ™‚๏ธ๐Ÿฆธโ€โ™€๏ธ -## Default Toolbox +## ๊ธฐ๋ณธ ๋„๊ตฌ ๋ชจ์Œ(Default Toolbox) -`smolagents` comes with a set of pre-built tools that can be directly injected into your agent. The [default toolbox](https://huggingface.co/docs/smolagents/guided_tour?build-a-tool=Decorate+a+function+with+%40tool#default-toolbox) includes: +`smolagents`์—๋Š” ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ๊ธฐ๋ณธ ๋„๊ตฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. [๊ธฐ๋ณธ ๋„๊ตฌ ๋ชจ์Œ](https://huggingface.co/docs/smolagents/guided_tour?build-a-tool=Decorate+a+function+with+%40tool#default-toolbox)์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค: - **PythonInterpreterTool** - **FinalAnswerTool** @@ -162,39 +157,36 @@ With this tool, Alfred will be the ultimate super host, impressing his guests wi - **GoogleSearchTool** - **VisitWebpageTool** -Alfred could use various tools to ensure a flawless party at Wayne Manor: - -- First, he could use the `DuckDuckGoSearchTool` to find creative superhero-themed party ideas. - -- For catering, he'd rely on the `GoogleSearchTool` to find the highest-rated services in Gotham. +Alfred๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹ค์–‘ํ•œ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•ด Wayne Manor์—์„œ ์™„๋ฒฝํ•œ ํŒŒํ‹ฐ๋ฅผ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -- To manage seating arrangements, Alfred could run calculations with the `PythonInterpreterTool`. +- `DuckDuckGoSearchTool`๋กœ ์ฐฝ์˜์ ์ธ ์Šˆํผํžˆ์–ด๋กœ ํ…Œ๋งˆ ํŒŒํ‹ฐ ์•„์ด๋””์–ด ๊ฒ€์ƒ‰ +- `GoogleSearchTool`๋กœ Gotham์—์„œ ํ‰์ ์ด ๊ฐ€์žฅ ๋†’์€ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค ์ฐพ๊ธฐ +- `PythonInterpreterTool`๋กœ ์ขŒ์„ ๋ฐฐ์น˜ ๊ณ„์‚ฐ +- ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋ชจ์•„ `FinalAnswerTool`๋กœ ๊ณ„ํš ์ •๋ฆฌ -- Once everything is gathered, he'd compile the plan using the `FinalAnswerTool`. +์ด ๋„๊ตฌ๋“ค๋กœ Alfred๋Š” ์™„๋ฒฝํ•˜๊ณ  ๋งค๋„๋Ÿฌ์šด ํŒŒํ‹ฐ๋ฅผ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿฆ‡๐Ÿ’ก -With these tools, Alfred guarantees the party is both exceptional and seamless. ๐Ÿฆ‡๐Ÿ’ก +## ๋„๊ตฌ ๊ณต์œ  ๋ฐ ๊ฐ€์ ธ์˜ค๊ธฐ -## Sharing and Importing Tools +**smolagents**์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ์ปค์Šคํ…€ ๋„๊ตฌ๋ฅผ Hub์— ๊ณต์œ ํ•˜๊ณ , ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋งŒ๋“  ๋„๊ตฌ๋ฅผ ์‰ฝ๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” **HF Spaces** ๋ฐ **LangChain ๋„๊ตฌ**์™€์˜ ์—ฐ๋™๋„ ํฌํ•จ๋˜์–ด, Alfred๊ฐ€ Wayne Manor์—์„œ ์žŠ์ง€ ๋ชปํ•  ํŒŒํ‹ฐ๋ฅผ ๊ธฐํšํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ๐ŸŽญ -One of the most powerful features of **smolagents** is its ability to share custom tools on the Hub and seamlessly integrate tools created by the community. This includes connecting with **HF Spaces** and **LangChain tools**, significantly enhancing Alfred's ability to orchestrate an unforgettable party at Wayne Manor. ๐ŸŽญ +์ด๋Ÿฌํ•œ ํ†ตํ•ฉ์„ ํ†ตํ•ด Alfred๋Š” ๊ณ ๊ธ‰ ์ด๋ฒคํŠธ ํ”Œ๋ž˜๋‹ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์กฐ๋ช… ์กฐ์ •, ํŒŒํ‹ฐ ์Œ์•… ์ถ”์ฒœ, ์ผ€์ดํ„ฐ๋ง ์—…์ฒด์™€์˜ ํ˜‘์—… ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -With these integrations, Alfred can tap into advanced event-planning toolsโ€”whether it's adjusting the lighting for the perfect ambiance, curating the ideal playlist for the party, or coordinating with Gotham's finest caterers. +์•„๋ž˜๋Š” ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์ด ํŒŒํ‹ฐ ๊ฒฝํ—˜์„ ์–ด๋–ป๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ค๋Š”์ง€ ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค: -Here are examples showcasing how these functionalities can elevate the party experience: +### ๋„๊ตฌ๋ฅผ Hub์— ๊ณต์œ ํ•˜๊ธฐ -### Sharing a Tool to the Hub +์ปค์Šคํ…€ ๋„๊ตฌ๋ฅผ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค! `push_to_hub()` ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด Hugging Face ๊ณ„์ •์— ์—…๋กœ๋“œํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. -Sharing your custom tool with the community is easy! Simply upload it to your Hugging Face account using the `push_to_hub()` method. - -For instance, Alfred can share his `party_theme_tool` to help others find the best catering services in Gotham. Here's how to do it: +์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๋Š” ์ž์‹ ์˜ `party_theme_tool`์„ ๊ณต์œ ํ•ด ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๋„ Gotham ์ตœ๊ณ ์˜ ์ผ€์ดํ„ฐ๋ง ์„œ๋น„์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python party_theme_tool.push_to_hub("{your_username}/party_theme_tool", token="") ``` -### Importing a Tool from the Hub +### Hub์—์„œ ๋„๊ตฌ ๊ฐ€์ ธ์˜ค๊ธฐ -You can easily import tools created by other users using the `load_tool()` function. For example, Alfred might want to generate a promotional image for the party using AI. Instead of building a tool from scratch, he can leverage a predefined one from the community: +๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ ๋งŒ๋“  ๋„๊ตฌ๋ฅผ `load_tool()` ํ•จ์ˆ˜๋กœ ์‰ฝ๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๊ฐ€ AI๋กœ ํŒŒํ‹ฐ ํ™๋ณด ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด, ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python from smolagents import load_tool, CodeAgent, InferenceClientModel @@ -212,13 +204,13 @@ agent = CodeAgent( agent.run("Generate an image of a luxurious superhero-themed party at Wayne Manor with made-up superheros.") ``` -### Importing a Hugging Face Space as a Tool +### HF Space๋ฅผ ๋„๊ตฌ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ -You can also import a HF Space as a tool using `Tool.from_space()`. This opens up possibilities for integrating with thousands of spaces from the community for tasks from image generation to data analysis. +`Tool.from_space()`๋ฅผ ์‚ฌ์šฉํ•ด HF Space๋ฅผ ๋„๊ตฌ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์ˆ˜์ฒœ ๊ฐœ Space์™€ ์—ฐ๋™ํ•ด ์ด๋ฏธ์ง€ ์ƒ์„ฑ, ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -The tool will connect with the spaces Gradio backend using the `gradio_client`, so make sure to install it via `pip` if you don't have it already. +์ด ๋„๊ตฌ๋Š” `gradio_client`๋ฅผ ํ†ตํ•ด Space์˜ Gradio ๋ฐฑ์—”๋“œ์™€ ์—ฐ๊ฒฐ๋˜๋ฏ€๋กœ, ๋ฏธ๋ฆฌ pip๋กœ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -For the party, Alfred can use an existing HF Space for the generation of the AI-generated image to be used in the announcement (instead of the pre-built tool we mentioned before). Let's build it! +ํŒŒํ‹ฐ๋ฅผ ์œ„ํ•ด Alfred๋Š” AI๋กœ ์ƒ์„ฑํ•œ ์ด๋ฏธ์ง€๋ฅผ ํŒŒํ‹ฐ ๊ณต์ง€์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ๊ทธ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค: ```python from smolagents import CodeAgent, InferenceClientModel, Tool @@ -239,16 +231,11 @@ agent.run( ) ``` -### Importing a LangChain Tool - - -We'll discuss the `LangChain` framework in upcoming sections. For now, we just note that we can reuse LangChain tools in your smolagents workflow! - -You can easily load LangChain tools using the `Tool.from_langchain()` method. Alfred, ever the perfectionist, is preparing for a spectacular superhero night at Wayne Manor while the Waynes are away. To make sure every detail exceeds expectations, he taps into LangChain tools to find top-tier entertainment ideas. +### LangChain ๋„๊ตฌ ๊ฐ€์ ธ์˜ค๊ธฐ -By using `Tool.from_langchain()`, Alfred effortlessly adds advanced search functionalities to his smolagent, enabling him to discover exclusive party ideas and services with just a few commands. +`LangChain` ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ดํ›„ ์„น์…˜์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” smolagents ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ LangChain ๋„๊ตฌ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ๋งŒ ์•Œ์•„๋‘ก์‹œ๋‹ค! -Here's how he does it: +`Tool.from_langchain()` ๋ฉ”์„œ๋“œ๋กœ LangChain ๋„๊ตฌ๋ฅผ ์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Alfred๋Š” Wayne Manor์—์„œ ์ตœ๊ณ ์˜ ์—”ํ„ฐํ…Œ์ธ๋จผํŠธ ์•„์ด๋””์–ด๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด LangChain ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python from langchain.agents import load_tools @@ -261,21 +248,21 @@ 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.") ``` -### Importing a tool collection from any MCP server +### MCP ์„œ๋ฒ„์—์„œ ๋„๊ตฌ ๋ชจ์Œ ๊ฐ€์ ธ์˜ค๊ธฐ -`smolagents` also allows importing tools from the hundreds of MCP servers available on [glama.ai](https://glama.ai/mcp/servers) or [smithery.ai](https://smithery.ai). If you want to dive deeper about MCP, you can check our [free MCP Course](https://huggingface.co/learn/mcp-course/). +`smolagents`๋Š” [glama.ai](https://glama.ai/mcp/servers) ๋˜๋Š” [smithery.ai](https://smithery.ai)์—์„œ ์ œ๊ณตํ•˜๋Š” ์ˆ˜๋ฐฑ ๊ฐœ MCP ์„œ๋ฒ„์˜ ๋„๊ตฌ๋„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MCP์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด [๋ฌด๋ฃŒ MCP ๊ฐ•์˜](https://huggingface.co/learn/mcp-course/)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.
-Install mcp client +mcp ํด๋ผ์ด์–ธํŠธ ์„ค์น˜ -We first need to install the `mcp` integration for `smolagents`. +๋จผ์ € `smolagents`์˜ mcp ํ†ตํ•ฉ์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ```bash pip install "smolagents[mcp]" ```
-The MCP servers tools can be loaded in a ToolCollection object as follow: +MCP ์„œ๋ฒ„์˜ ๋„๊ตฌ๋Š” ToolCollection ๊ฐ์ฒด๋กœ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python import os @@ -298,11 +285,11 @@ with ToolCollection.from_mcp(server_parameters, trust_remote_code=True) as tool_ agent.run("Please find a remedy for hangover.") ``` -With this setup, Alfred can quickly discover luxurious entertainment options, ensuring Gotham's elite guests have an unforgettable experience. This tool helps him curate the perfect superhero-themed event for Wayne Manor! ๐ŸŽ‰ +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Alfred๋Š” ๊ณ ๊ธ‰ ์—”ํ„ฐํ…Œ์ธ๋จผํŠธ ์˜ต์…˜์„ ๋น ๋ฅด๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์–ด, Gotham์˜ ๋ช…์‚ฌ๋“ค์ด ์žŠ์ง€ ๋ชปํ•  ์Šˆํผํžˆ์–ด๋กœ ํŒŒํ‹ฐ๋ฅผ ์ฆ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ -## Resources +## ์ฐธ๊ณ  ์ž๋ฃŒ -- [Tools Tutorial](https://huggingface.co/docs/smolagents/tutorials/tools) - Explore this tutorial to learn how to work with tools effectively. -- [Tools Documentation](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools) - Comprehensive reference documentation on tools. -- [Tools Guided Tour](https://huggingface.co/docs/smolagents/v1.8.1/en/guided_tour#tools) - A step-by-step guided tour to help you build and utilize tools efficiently. -- [Building Effective Agents](https://huggingface.co/docs/smolagents/tutorials/building_good_agents) - A detailed guide on best practices for developing reliable and high-performance custom function agents. +- [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 index 1ac36a15..fb9a6b84 100644 --- a/units/ko/unit2/smolagents/vision_agents.mdx +++ b/units/ko/unit2/smolagents/vision_agents.mdx @@ -5,31 +5,31 @@ ]} askForHelpUrl="http://hf.co/join/discord" /> -# Vision Agents with smolagents +# smolagents๋กœ ๋น„์ „ ์—์ด์ „ํŠธ ๋งŒ๋“ค๊ธฐ -The examples in this section require access to a powerful VLM model. We tested them using the GPT-4o API. -However, Why use smolagents discusses alternative solutions supported by smolagents and Hugging Face. If you'd like to explore other options, be sure to check that section. +์ด ์„น์…˜์˜ ์˜ˆ์ œ๋Š” ๊ฐ•๋ ฅํ•œ VLM(๋น„์ „-์–ธ์–ด ๋ชจ๋ธ) API๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” GPT-4o API๋กœ ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ Why use smolagents์—์„œ๋Š” smolagents์™€ Hugging Face์—์„œ ์ง€์›ํ•˜๋Š” ๋Œ€์ฒด ์†”๋ฃจ์…˜๋„ ๋‹ค๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์˜ต์…˜์„ ํƒ์ƒ‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํ•ด๋‹น ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. -Empowering agents with visual capabilities is crucial for solving tasks that go beyond text processing. Many real-world challenges, such as web browsing or document understanding, require analyzing rich visual content. Fortunately, `smolagents` provides built-in support for vision-language models (VLMs), enabling agents to process and interpret images effectively. +์—์ด์ „ํŠธ์— ์‹œ๊ฐ์  ๋Šฅ๋ ฅ์„ ๋ถ€์—ฌํ•˜๋Š” ๊ฒƒ์€ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ ์ด์ƒ์˜ ์‹ค์ œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์›น ๋ธŒ๋ผ์šฐ์ง•์ด๋‚˜ ๋ฌธ์„œ ์ดํ•ด ๋“ฑ ๋งŽ์€ ์‹ค์ œ ๊ณผ์ œ๋Š” ํ’๋ถ€ํ•œ ์‹œ๊ฐ ์ •๋ณด๋ฅผ ๋ถ„์„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„, `smolagents`๋Š” ๋น„์ „-์–ธ์–ด ๋ชจ๋ธ(VLM)์„ ๋‚ด์žฅ ์ง€์›ํ•˜์—ฌ ์—์ด์ „ํŠธ๊ฐ€ ์ด๋ฏธ์ง€๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ํ•ด์„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. -In this example, imagine Alfred, the butler at Wayne Manor, is tasked with verifying the identities of the guests attending the party. As you can imagine, Alfred may not be familiar with everyone arriving. To help him, we can use an agent that verifies their identity by searching for visual information about their appearance using a VLM. This will allow Alfred to make informed decisions about who can enter. Let's build this example! +์ด ์˜ˆ์‹œ์—์„œ, Wayne Manor์˜ ์ง‘์‚ฌ Alfred๋Š” ํŒŒํ‹ฐ์— ์ฐธ์„ํ•˜๋Š” ์†๋‹˜๋“ค์˜ ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ์ž„๋ฌด๋ฅผ ๋งก์•˜์Šต๋‹ˆ๋‹ค. Alfred๋Š” ๋ชจ๋“  ์†๋‹˜์„ ์•Œ์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์†๋‹˜์˜ ์™ธ๋ชจ์— ๋Œ€ํ•œ ์‹œ๊ฐ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ด ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Alfred๋Š” ์ž…์žฅ ํ—ˆ๊ฐ€ ์—ฌ๋ถ€๋ฅผ ํ˜„๋ช…ํ•˜๊ฒŒ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋ฅผ ํ•จ๊ป˜ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค! -## Providing Images at the Start of the Agent's Execution +## ์—์ด์ „ํŠธ ์‹คํ–‰ ์‹œ์ž‘ ์‹œ ์ด๋ฏธ์ง€ ์ œ๊ณตํ•˜๊ธฐ -You can follow the code in this notebook that you can run using Google Colab. +์ฝ”๋“œ๋Š” ์ด ๋…ธํŠธ๋ถ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Google Colab์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -In this approach, images are passed to the agent at the start and stored as `task_images` alongside the task prompt. The agent then processes these images throughout its execution. +์ด ๋ฐฉ์‹์—์„œ๋Š” ์ด๋ฏธ์ง€๋ฅผ ์—์ด์ „ํŠธ ์‹คํ–‰ ์‹œ์ ์— `task_images`๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ์ด ์ด๋ฏธ์ง€๋ฅผ ์ „์ฒด ์‹คํ–‰ ๊ณผ์ •์—์„œ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค. -Consider the case where Alfred wants to verify the identities of the superheroes attending the party. He already has a dataset of images from previous parties with the names of the guests. Given a new visitor's image, the agent can compare it with the existing dataset and make a decision about letting them in. +์˜ˆ๋ฅผ ๋“ค์–ด, Alfred๋Š” ์ด์ „ ํŒŒํ‹ฐ์—์„œ ์†๋‹˜๋“ค์˜ ์ด๋ฆ„๊ณผ ํ•จ๊ป˜ ์ €์žฅ๋œ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์…‹์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ๋ฐฉ๋ฌธ๊ฐ์˜ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ›์•„, ๊ธฐ์กด ๋ฐ์ดํ„ฐ์…‹๊ณผ ๋น„๊ตํ•ด ์ž…์žฅ ํ—ˆ๊ฐ€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -In this case, a guest is trying to enter, and Alfred suspects that this visitor might be The Joker impersonating Wonder Woman. Alfred needs to verify their identity to prevent anyone unwanted from entering. +์ด๋ฒˆ์—๋Š” ํ•œ ์†๋‹˜์ด ์ž…์žฅํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ, Alfred๋Š” ์ด ์†๋‹˜์ด Wonder Woman์œผ๋กœ ์œ„์žฅํ•œ Joker์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์˜์‹ฌํ•ฉ๋‹ˆ๋‹ค. Alfred๋Š” ์‹ ์›์„ ํ™•์ธํ•ด ์›์น˜ ์•Š๋Š” ์ธ๋ฌผ์ด ์ž…์žฅํ•˜์ง€ ๋ชปํ•˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -Letโ€™s build the example. First, the images are loaded. In this case, we use images from Wikipedia to keep the example minimal, but imagine the possible use-case! +์˜ˆ์‹œ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์šฐ์„  ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์œ„ํ‚คํ”ผ๋””์•„ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ๋‹ค์–‘ํ•œ ํ™œ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค! ```python from PIL import Image @@ -37,8 +37,8 @@ import requests from io import BytesIO image_urls = [ - "https://upload.wikimedia.org/wikipedia/commons/e/e8/The_Joker_at_Wax_Museum_Plus.jpg", # Joker image - "https://upload.wikimedia.org/wikipedia/en/9/98/Joker_%28DC_Comics_character%29.jpg" # Joker image + "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 = [] @@ -51,14 +51,14 @@ for url in image_urls: images.append(image) ``` -Now that we have the images, the agent will tell us whether one guest is actually a superhero (Wonder Woman) or a villain (The Joker). +์ด์ œ ์ด๋ฏธ์ง€๋ฅผ ์ค€๋น„ํ–ˆ์œผ๋‹ˆ, ์—์ด์ „ํŠธ๊ฐ€ ์†๋‹˜์ด Wonder Woman์ธ์ง€ Joker์ธ์ง€ ํŒ๋ณ„ํ•ด์ค๋‹ˆ๋‹ค. ```python from smolagents import CodeAgent, OpenAIServerModel model = OpenAIServerModel(model_id="gpt-4o") -# Instantiate the agent +# ์—์ด์ „ํŠธ ์ธ์Šคํ„ด์Šคํ™” agent = CodeAgent( tools=[], model=model, @@ -68,115 +68,115 @@ agent = CodeAgent( response = agent.run( """ - Describe the costume and makeup that the comic character in these photos is wearing and return the description. - Tell me if the guest is The Joker or Wonder Woman. + ์ด ์‚ฌ์ง„ ์† ๋งŒํ™” ์บ๋ฆญํ„ฐ์˜ ์˜์ƒ๊ณผ ๋ฉ”์ดํฌ์—…์„ ๋ฌ˜์‚ฌํ•ด ์ฃผ์„ธ์š”. + ์†๋‹˜์ด The Joker์ธ์ง€ Wonder Woman์ธ์ง€ ์•Œ๋ ค์ฃผ์„ธ์š”. """, images=images ) ``` -In the case of my run, the output is the following, although it could vary in your case, as we've already discussed: +์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(์‹คํ–‰ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค): ```python { 'Costume and Makeup - First Image': ( - 'Purple coat and a purple silk-like cravat or tie over a mustard-yellow shirt.', - 'White face paint with exaggerated features, dark eyebrows, blue eye makeup, red lips forming a wide smile.' + '๋ณด๋ผ์ƒ‰ ์ฝ”ํŠธ์™€ ๋…ธ๋ž€์ƒ‰ ์…”์ธ  ์œ„์— ๋ณด๋ผ์ƒ‰ ์‹คํฌ ํฌ๋ผ๋ฐ”ํŠธ ๋˜๋Š” ํƒ€์ด.', + 'ํฐ์ƒ‰ ์–ผ๊ตด ๋ถ„์žฅ, ๊ณผ์žฅ๋œ ์ด๋ชฉ๊ตฌ๋น„, ์ง„ํ•œ ๋ˆˆ์น, ํŒŒ๋ž€ ์•„์ด์„€๋„, ๋นจ๊ฐ„ ์ž…์ˆ ๋กœ ๋„“์€ ๋ฏธ์†Œ.' ), 'Costume and Makeup - Second Image': ( - 'Dark suit with a flower on the lapel, holding a playing card.', - 'Pale skin, green hair, very red lips with an exaggerated grin.' + '๊ฝƒ์ด ๋‹ฌ๋ฆฐ ์–ด๋‘์šด ์ •์žฅ, ์†์— ํŠธ๋Ÿผํ”„ ์นด๋“œ๋ฅผ ๋“ค๊ณ  ์žˆ์Œ.', + '์ฐฝ๋ฐฑํ•œ ํ”ผ๋ถ€, ์ดˆ๋ก์ƒ‰ ๋จธ๋ฆฌ, ๊ณผ์žฅ๋œ ๋ฏธ์†Œ์˜ ๋นจ๊ฐ„ ์ž…์ˆ .' ), - 'Character Identity': 'This character resembles known depictions of The Joker from comic book media.' + 'Character Identity': '์ด ์บ๋ฆญํ„ฐ๋Š” ๋งŒํ™”์—์„œ ๋ฌ˜์‚ฌ๋œ The Joker์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.' } ``` -In this case, the output reveals that the person is impersonating someone else, so we can prevent The Joker from entering the party! +์ด์ฒ˜๋Ÿผ, ๊ฒฐ๊ณผ๋ฅผ ํ†ตํ•ด ์†๋‹˜์ด ๋‹ค๋ฅธ ์ธ๋ฌผ๋กœ ์œ„์žฅํ–ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, Alfred๋Š” Joker์˜ ์ž…์žฅ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! -## Providing Images with Dynamic Retrieval +## ๋™์  ๊ฒ€์ƒ‰์œผ๋กœ ์ด๋ฏธ์ง€ ์ œ๊ณตํ•˜๊ธฐ -You can follow the code in this Python file +์ฝ”๋“œ๋Š” ์ด Python ํŒŒ์ผ์—์„œ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -The previous approach is valuable and has many potential use cases. However, in situations where the guest is not in the database, we need to explore other ways of identifying them. One possible solution is to dynamically retrieve images and information from external sources, such as browsing the web for details. +์ด์ „ ๋ฐฉ์‹๋„ ์œ ์šฉํ•˜์ง€๋งŒ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์†๋‹˜์ด ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ์™ธ๋ถ€์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋™์ ์œผ๋กœ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์›น์„ ํƒ์ƒ‰ํ•˜๋ฉฐ ์†๋‹˜์— ๋Œ€ํ•œ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ์•„ ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. -In this approach, images are dynamically added to the agent's memory during execution. As we know, agents in `smolagents` are based on the `MultiStepAgent` class, which is an abstraction of the ReAct framework. This class operates in a structured cycle where various variables and knowledge are logged at different stages: +์ด ๋ฐฉ์‹์—์„œ๋Š” ์—์ด์ „ํŠธ ์‹คํ–‰ ์ค‘์— ์ด๋ฏธ์ง€๋ฅผ ๋™์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. smolagents์˜ ์—์ด์ „ํŠธ๋Š” `MultiStepAgent` ํด๋ž˜์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ์ด๋Š” ReAct ํ”„๋ ˆ์ž„์›Œํฌ์˜ ์ถ”์ƒํ™”์ž…๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” ๋‹ค์–‘ํ•œ ๋ณ€์ˆ˜์™€ ์ง€์‹์„ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์— ๊ฑธ์ณ ๊ธฐ๋กํ•˜๋Š” ๊ตฌ์กฐ์  ์‚ฌ์ดํด๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค: -1. **SystemPromptStep:** Stores the system prompt. -2. **TaskStep:** Logs the user query and any provided input. -3. **ActionStep:** Captures logs from the agent's actions and results. +1. **SystemPromptStep:** ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ ์ €์žฅ +2. **TaskStep:** ์‚ฌ์šฉ์ž ์ฟผ๋ฆฌ ๋ฐ ์ž…๋ ฅ ๊ธฐ๋ก +3. **ActionStep:** ์—์ด์ „ํŠธ์˜ ์•ก์…˜ ๋ฐ ๊ฒฐ๊ณผ ๋กœ๊ทธ ๊ธฐ๋ก -This structured approach allows agents to incorporate visual information dynamically and respond adaptively to evolving tasks. Below is the diagram we've already seen, illustrating the dynamic workflow process and how different steps integrate within the agent lifecycle. When browsing, the agent can take screenshots and save them as `observation_images` in the `ActionStep`. +์ด ๊ตฌ์กฐ์  ์ ‘๊ทผ๋ฒ• ๋•๋ถ„์—, ์—์ด์ „ํŠธ๋Š” ์‹œ๊ฐ ์ •๋ณด๋ฅผ ๋™์ ์œผ๋กœ ํ†ตํ•ฉํ•˜๊ณ , ๋ณ€ํ™”ํ•˜๋Š” ์ž‘์—…์— ์ ์‘์ ์œผ๋กœ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ์ด๋Ÿฌํ•œ ๋™์  ์›Œํฌํ”Œ๋กœ์šฐ์™€ ๊ฐ ๋‹จ๊ณ„๊ฐ€ ์—์ด์ „ํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด์—์„œ ์–ด๋–ป๊ฒŒ ํ†ตํ•ฉ๋˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ง• ์ค‘์—๋Š” ์—์ด์ „ํŠธ๊ฐ€ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ์–ด `observation_images`์— ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ![Dynamic image retrieval](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/smolagents-can-see/diagram_adding_vlms_smolagents.png) -Now that we understand the need, let's build our complete example. In this case, Alfred wants full control over the guest verification process, so browsing for details becomes a viable solution. To complete this example, we need a new set of tools for the agent. Additionally, we'll use Selenium and Helium, which are browser automation tools. This will allow us to build an agent that explores the web, searching for details about a potential guest and retrieving verification information. Let's install the tools needed: +์ด์ œ ํ•„์š”์„ฑ์„ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์ „์ฒด ์˜ˆ์‹œ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์ด๋ฒˆ์—๋Š” Alfred๊ฐ€ ์†๋‹˜ ์‹ ์› ํ™•์ธ ๊ณผ์ •์„ ์™„์ „ํžˆ ํ†ต์ œํ•˜๊ณ  ์‹ถ์–ด ํ•˜๋ฏ€๋กœ, ์›น์„ ํƒ์ƒ‰ํ•˜๋ฉฐ ์ •๋ณด๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ด ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด Selenium๊ณผ Helium ๋“ฑ ๋ธŒ๋ผ์šฐ์ € ์ž๋™ํ™” ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ๋ช…๋ น์–ด๋กœ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”: ```bash pip install "smolagents[all]" helium selenium python-dotenv ``` -We'll need a set of agent tools specifically designed for browsing, such as `search_item_ctrl_f`, `go_back`, and `close_popups`. These tools allow the agent to act like a person navigating the web. +์—์ด์ „ํŠธ์—๋Š” ์›น ๋ธŒ๋ผ์šฐ์ง•์„ ์œ„ํ•œ `search_item_ctrl_f`, `go_back`, `close_popups` ๋“ฑ ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋„๊ตฌ๋“ค์€ ์‹ค์ œ ์‚ฌ์šฉ์ž๊ฐ€ ์›น์„ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ```python @tool def search_item_ctrl_f(text: str, nth_result: int = 1) -> str: """ - Searches for text on the current page via Ctrl + F and jumps to the nth occurrence. + ํ˜„์žฌ ํŽ˜์ด์ง€์—์„œ Ctrl + F๋กœ ํ…์ŠคํŠธ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  n๋ฒˆ์งธ ๊ฒฐ๊ณผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. Args: - text: The text to search for - nth_result: Which occurrence to jump to (default: 1) + text: ๊ฒ€์ƒ‰ํ•  ํ…์ŠคํŠธ + nth_result: ๋ช‡ ๋ฒˆ์งธ ๊ฒฐ๊ณผ๋กœ ์ด๋™ํ• ์ง€(๊ธฐ๋ณธ๊ฐ’: 1) """ elements = driver.find_elements(By.XPATH, f"//*[contains(text(), '{text}')]") if nth_result > len(elements): - raise Exception(f"Match nยฐ{nth_result} not found (only {len(elements)} matches found)") - result = f"Found {len(elements)} matches for '{text}'." + 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"Focused on element {nth_result} of {len(elements)}" + result += f"{len(elements)}๊ฐœ ์ค‘ {nth_result}๋ฒˆ์งธ ์š”์†Œ๋กœ ํฌ์ปค์Šค ์ด๋™" return result @tool def go_back() -> None: - """Goes back to previous page.""" + """์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.""" driver.back() @tool def close_popups() -> str: """ - Closes any visible modal or pop-up on the page. Use this to dismiss pop-up windows! This does not work on cookie consent banners. + ํŽ˜์ด์ง€์˜ ๋ชจ๋‹ฌ ๋˜๋Š” ํŒ์—…์„ ๋‹ซ์Šต๋‹ˆ๋‹ค. ํŒ์—… ์ฐฝ์„ ๋‹ซ์„ ๋•Œ ์‚ฌ์šฉํ•˜์„ธ์š”! ์ฟ ํ‚ค ๋ฐฐ๋„ˆ์—๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. """ webdriver.ActionChains(driver).send_keys(Keys.ESCAPE).perform() ``` -We also need functionality for saving screenshots, as this will be an essential part of what our VLM agent uses to complete the task. This functionality captures the screenshot and saves it in `step_log.observations_images = [image.copy()]`, allowing the agent to store and process the images dynamically as it navigates. +๋˜ํ•œ, ์Šคํฌ๋ฆฐ์ƒท ์ €์žฅ ๊ธฐ๋Šฅ๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ๋ธŒ๋ผ์šฐ์ €์˜ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ์–ด `step_log.observations_images = [image.copy()]`์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์—์ด์ „ํŠธ๊ฐ€ ํƒ์ƒ‰ ์ค‘ ์ด๋ฏธ์ง€๋ฅผ ๋™์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```python def save_screenshot(step_log: ActionStep, agent: CodeAgent) -> None: - sleep(1.0) # Let JavaScript animations happen before taking the screenshot + sleep(1.0) # ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋Œ€๊ธฐ driver = helium.get_driver() current_step = step_log.step_number if driver is not None: - for step_logs in agent.logs: # Remove previous screenshots from logs for lean processing + 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"Captured a browser screenshot: {image.size} pixels") - step_log.observations_images = [image.copy()] # Create a copy to ensure it persists, important! + print(f"๋ธŒ๋ผ์šฐ์ € ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜: {image.size} ํ”ฝ์…€") + step_log.observations_images = [image.copy()] - # Update observations with current URL - url_info = f"Current url: {driver.current_url}" + # ํ˜„์žฌ 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 ``` -This function is passed to the agent as `step_callback`, as it's triggered at the end of each step during the agent's execution. This allows the agent to dynamically capture and store screenshots throughout its process. +์ด ํ•จ์ˆ˜๋Š” `step_callback`์œผ๋กœ ์—์ด์ „ํŠธ์— ์ „๋‹ฌ๋˜์–ด, ๊ฐ ๋‹จ๊ณ„๊ฐ€ ๋๋‚  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์—์ด์ „ํŠธ๋Š” ํƒ์ƒ‰ ๊ณผ์ •์—์„œ ์Šคํฌ๋ฆฐ์ƒท์„ ๋™์ ์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Now, we can generate our vision agent for browsing the web, providing it with the tools we created, along with the `DuckDuckGoSearchTool` to explore the web. This tool will help the agent retrieve necessary information for verifying guests' identities based on visual cues. +์ด์ œ, ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํƒ์ƒ‰ํ•˜๋ฉฐ ์‹œ๊ฐ ์ •๋ณด๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋น„์ „ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์•ž์„œ ๋งŒ๋“  ๋„๊ตฌ๋“ค๊ณผ `DuckDuckGoSearchTool`์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋„๊ตฌ๋Š” ์†๋‹˜ ์‹ ์› ํ™•์ธ์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์›น์—์„œ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค. ```python from smolagents import CodeAgent, OpenAIServerModel, DuckDuckGoSearchTool @@ -192,33 +192,33 @@ agent = CodeAgent( ) ``` -With that, Alfred is ready to check the guests' identities and make informed decisions about whether to let them into the party: +์ด์ œ Alfred๋Š” ์†๋‹˜ ์‹ ์› ํ™•์ธ์„ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—์ด์ „ํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```python agent.run(""" -I am Alfred, the butler of Wayne Manor, responsible for verifying the identity of guests at party. A superhero has arrived at the entrance claiming to be Wonder Woman, but I need to confirm if she is who she says she is. +๋‚˜๋Š” Wayne Manor์˜ ์ง‘์‚ฌ Alfred๋กœ, ํŒŒํ‹ฐ์— ์ฐธ์„ํ•˜๋Š” ์†๋‹˜์˜ ์‹ ์›์„ ํ™•์ธํ•˜๋Š” ์ž„๋ฌด๋ฅผ ๋งก๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ์Šˆํผํžˆ์–ด๋กœ๊ฐ€ Wonder Woman์ด๋ผ๊ณ  ์ฃผ์žฅํ•˜๋ฉฐ ์ž…์žฅํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ, ์ •๋ง ๊ทธ๋…€๊ฐ€ ๋งž๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -Please search for images of Wonder Woman and generate a detailed visual description based on those images. Additionally, navigate to Wikipedia to gather key details about her appearance. With this information, I can determine whether to grant her access to the event. +Wonder Woman์˜ ์ด๋ฏธ์ง€๋ฅผ ๊ฒ€์ƒ‰ํ•ด ์‹œ๊ฐ์  ํŠน์ง•์„ ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์„ธ์š”. ๋˜ํ•œ, Wikipedia์—์„œ ๊ทธ๋…€์˜ ์™ธ๋ชจ์— ๋Œ€ํ•œ ์ฃผ์š” ์ •๋ณด๋ฅผ ์ฐพ์•„์ฃผ์„ธ์š”. ์ด ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ž…์žฅ ํ—ˆ๊ฐ€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. """ + helium_instructions) ``` -You can see that we include `helium_instructions` as part of the task. This special prompt is aimed to control the navigation of the agent, ensuring that it follows the correct steps while browsing the web. +์—ฌ๊ธฐ์„œ `helium_instructions`๋Š” ํƒ์ƒ‰์„ ์ œ์–ดํ•˜๋Š” ํŠน์ˆ˜ ํ”„๋กฌํ”„ํŠธ๋กœ, ์—์ด์ „ํŠธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์ˆœ์„œ๋กœ ์›น์„ ํƒ์ƒ‰ํ•˜๋„๋ก ์œ ๋„ํ•ฉ๋‹ˆ๋‹ค. -Let's see how this works in the video below: +์•„๋ž˜ ์˜์ƒ์—์„œ ์‹ค์ œ ๋™์ž‘์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -This is the final output: +์ตœ์ข… ์ถœ๋ ฅ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: ```python -Final answer: Wonder Woman is typically depicted wearing a red and gold bustier, blue shorts or skirt with white stars, a golden tiara, silver bracelets, and a golden Lasso of Truth. She is Princess Diana of Themyscira, known as Diana Prince in the world of men. +Final answer: Wonder Woman์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋นจ๊ฐ„์ƒ‰๊ณผ ๊ธˆ์ƒ‰์˜ ์ƒ์˜, ํŒŒ๋ž€์ƒ‰ ๋ณ„๋ฌด๋Šฌ ํ•˜์˜, ๊ธˆ์ƒ‰ ํ‹ฐ์•„๋ผ, ์€์ƒ‰ ํŒ”์ฐŒ, ํ™ฉ๊ธˆ ์˜ฌ๊ฐ€๋ฏธ๋ฅผ ์ฐฉ์šฉํ•œ ๋ชจ์Šต์œผ๋กœ ๋ฌ˜์‚ฌ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋…€๋Š” Themyscira์˜ ๊ณต์ฃผ์ด์ž, ์ธ๊ฐ„ ์„ธ๊ณ„์—์„œ๋Š” Diana Prince๋กœ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ``` -With all of that, we've successfully created our identity verifier for the party! Alfred now has the necessary tools to ensure only the right guests make it through the door. Everything is set to have a good time at Wayne Manor! +์ด๋ ‡๊ฒŒ ํ•ด์„œ, ํŒŒํ‹ฐ ์ž…์žฅ ์†๋‹˜ ์‹ ์› ํ™•์ธ์„ ์œ„ํ•œ ๋น„์ „ ์—์ด์ „ํŠธ๋ฅผ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค! ์ด์ œ Alfred๋Š” ์˜ฌ๋ฐ”๋ฅธ ์†๋‹˜๋งŒ ์ž…์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ์™„๋ฒฝํ•˜๊ฒŒ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Wayne Manor์—์„œ ๋ฉ‹์ง„ ํŒŒํ‹ฐ๋ฅผ ์ฆ๊ธฐ์„ธ์š”! -## Further Reading +## ์ถ”๊ฐ€ ์ž๋ฃŒ -- [We just gave sight to smolagents](https://huggingface.co/blog/smolagents-can-see) - Blog describing the vision agent functionality. -- [Web Browser Automation with Agents ๐Ÿค–๐ŸŒ](https://huggingface.co/docs/smolagents/examples/web_browser) - Example for Web browsing using a vision agent. -- [Web Browser Vision Agent Example](https://github.com/huggingface/smolagents/blob/main/src/smolagents/vision_web_browser.py) - Example for Web browsing using a vision agent. +- [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 index 3a6b848c..4bda418b 100644 --- a/units/ko/unit2/smolagents/why_use_smolagents.mdx +++ b/units/ko/unit2/smolagents/why_use_smolagents.mdx @@ -1,67 +1,67 @@ ![smolagents banner](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/license_to_call.png) -# Why use smolagents +# smolagents๋ฅผ ์จ์•ผ ํ•˜๋Š” ์ด์œ  -In this module, we will explore the pros and cons of using [smolagents](https://huggingface.co/docs/smolagents/en/index), helping you make an informed decision about whether it's the right framework for your needs. +์ด ๋ชจ๋“ˆ์—์„œ๋Š” [smolagents](https://huggingface.co/docs/smolagents/en/index)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์˜ ์žฅ๋‹จ์ ์„ ์‚ดํŽด๋ณด๊ณ , ์—ฌ๋Ÿฌ๋ถ„์˜ ํ•„์š”์— ๋งž๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ธ์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€๋“œ๋ฆฝ๋‹ˆ๋‹ค. -## What is `smolagents`? +## `smolagents`๋ž€? -`smolagents` is a simple yet powerful framework for building AI agents. It provides LLMs with the _agency_ to interact with the real world, such as searching or generating images. +`smolagents`๋Š” ๊ฐ„๋‹จํ•˜๋ฉด์„œ๋„ ๊ฐ•๋ ฅํ•œ AI ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. LLM์ด ๊ฒ€์ƒ‰, ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋“ฑ ์‹ค์ œ ์„ธ๊ณ„์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” _์—์ด์ „์‹œ(agency)_ ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -As we learned in unit 1, AI agents are programs that use LLMs to generate **'thoughts'** based on **'observations'** to perform **'actions'**. Let's explore how this is implemented in smolagents. +unit 1์—์„œ ๋ฐฐ์šด ๊ฒƒ์ฒ˜๋Ÿผ, AI ์—์ด์ „ํŠธ๋Š” LLM์ด **'๊ด€์ฐฐ(observations)'**์„ ๋ฐ”ํƒ•์œผ๋กœ **'์ƒ๊ฐ(thoughts)'**์„ ์ƒ์„ฑํ•ด **'ํ–‰๋™(actions)'**์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. smolagents์—์„œ ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜๋Š”์ง€ ์‚ดํŽด๋ด…์‹œ๋‹ค. -### Key Advantages of `smolagents` -- **Simplicity:** Minimal code complexity and abstractions, to make the framework easy to understand, adopt and extend -- **Flexible LLM Support:** Works with any LLM through integration with Hugging Face tools and external APIs -- **Code-First Approach:** First-class support for Code Agents that write their actions directly in code, removing the need for parsing and simplifying tool calling -- **HF Hub Integration:** Seamless integration with the Hugging Face Hub, allowing the use of Gradio Spaces as tools +### `smolagents`์˜ ์ฃผ์š” ์žฅ์  +- **๋‹จ์ˆœํ•จ:** ์ตœ์†Œํ•œ์˜ ์ฝ”๋“œ ๋ณต์žก์„ฑ๊ณผ ์ถ”์ƒํ™”๋กœ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ , ๋„์ž… ๋ฐ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- **์œ ์—ฐํ•œ LLM ์ง€์›:** Hugging Face ๋„๊ตฌ ๋ฐ ์™ธ๋ถ€ API์™€์˜ ํ†ตํ•ฉ์„ ํ†ตํ•ด ์–ด๋–ค LLM๊ณผ๋„ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- **์ฝ”๋“œ ์šฐ์„  ์ ‘๊ทผ:** ์•ก์…˜์„ ์ง์ ‘ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋Š” Code Agent๋ฅผ 1๊ธ‰ ์‹œ๋ฏผ์œผ๋กœ ์ง€์›ํ•˜์—ฌ, ํŒŒ์‹ฑ ์—†์ด ๋„๊ตฌ ํ˜ธ์ถœ์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค. +- **HF Hub ํ†ตํ•ฉ:** Hugging Face Hub์™€์˜ ์›ํ™œํ•œ ํ†ตํ•ฉ์œผ๋กœ Gradio Spaces๋ฅผ ๋„๊ตฌ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -### When to use smolagents? +### smolagents๋ฅผ ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ? -With these advantages in mind, when should we use smolagents over other frameworks? +์ด๋Ÿฌํ•œ ์žฅ์ ์„ ๊ณ ๋ คํ•  ๋•Œ, ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ ๋Œ€์‹  smolagents๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์–ธ์ œ์ผ๊นŒ์š”? -smolagents is ideal when: -- You need a **lightweight and minimal solution.** -- You want to **experiment quickly** without complex configurations. -- Your **application logic is straightforward.** +smolagents๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์— ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค: +- **๊ฐ€๋ณ๊ณ  ์ตœ์†Œํ•œ์˜ ์†”๋ฃจ์…˜**์ด ํ•„์š”ํ•  ๋•Œ +- **๋ณต์žกํ•œ ์„ค์ • ์—†์ด ๋น ๋ฅด๊ฒŒ ์‹คํ—˜**ํ•˜๊ณ  ์‹ถ์„ ๋•Œ +- **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์ด ๋‹จ์ˆœ**ํ•  ๋•Œ -### Code vs. JSON Actions -Unlike other frameworks where agents write actions in JSON, `smolagents` **focuses on tool calls in code**, simplifying the execution process. This is because there's no need to parse the JSON in order to build code that calls the tools: the output can be executed directly. +### ์ฝ”๋“œ vs. JSON ์•ก์…˜ +๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ์—์ด์ „ํŠธ๊ฐ€ ์•ก์…˜์„ JSON์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๋ฐ˜๋ฉด, `smolagents`๋Š” **์ฝ”๋“œ ๊ธฐ๋ฐ˜ ๋„๊ตฌ ํ˜ธ์ถœ**์— ์ง‘์ค‘ํ•˜์—ฌ ์‹คํ–‰ ๊ณผ์ •์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋„๊ตฌ ํ˜ธ์ถœ์„ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜๋ฏ€๋กœ, JSON์„ ํŒŒ์‹ฑํ•ด ์ฝ”๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ณผ์ •์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ถœ๋ ฅ๋œ ์ฝ”๋“œ๋ฅผ ๋ฐ”๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -The following diagram illustrates this difference: +์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ์ด ์ฐจ์ด๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค: ![Code vs. JSON actions](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/code_vs_json_actions.png) -To review the difference between Code vs JSON Actions, you can revisit [the Actions Section in Unit 1](https://huggingface.co/learn/agents-course/unit1/actions#actions-enabling-the-agent-to-engage-with-its-environment). +Code vs JSON ์•ก์…˜์˜ ์ฐจ์ด๋ฅผ ๋‹ค์‹œ ๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด [Unit 1์˜ ์•ก์…˜ ์„น์…˜](https://huggingface.co/learn/agents-course/unit1/actions#actions-enabling-the-agent-to-engage-with-its-environment)์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. -### Agent Types in `smolagents` +### smolagents์˜ ์—์ด์ „ํŠธ ์œ ํ˜• -Agents in `smolagents` operate as **multi-step agents**. +smolagents์˜ ์—์ด์ „ํŠธ๋Š” **๋‹ค๋‹จ๊ณ„ ์—์ด์ „ํŠธ(multi-step agent)**๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. -Each [`MultiStepAgent`](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.MultiStepAgent) performs: -- One thought -- One tool call and execution +๊ฐ [`MultiStepAgent`](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.MultiStepAgent)๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค: +- ํ•œ ๋ฒˆ์˜ ์ƒ๊ฐ(thought) +- ํ•œ ๋ฒˆ์˜ ๋„๊ตฌ ํ˜ธ์ถœ ๋ฐ ์‹คํ–‰ -In addition to using **[CodeAgent](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.CodeAgent)** as the primary type of agent, smolagents also supports **[ToolCallingAgent](https://huggingface.co/docs/smolagents/main/en/reference/agents#smolagents.ToolCallingAgent)**, which writes tool calls in JSON. +์ฃผ์š” ์—์ด์ „ํŠธ ํƒ€์ž…์œผ๋กœ **[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)**๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. -We will explore each agent type in more detail in the following sections. +๊ฐ ์—์ด์ „ํŠธ ํƒ€์ž…์€ ์ดํ›„ ์„น์…˜์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃน๋‹ˆ๋‹ค. -In smolagents, tools are defined using @tool decorator wrapping a Python function or the Tool class. +smolagents์—์„œ๋Š” ๋„๊ตฌ๋ฅผ @tool ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๊ฐ์‹ผ Python ํ•จ์ˆ˜ ๋˜๋Š” Tool ํด๋ž˜์Šค๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. -### Model Integration in `smolagents` -`smolagents` supports flexible LLM integration, allowing you to use any callable model that meets [certain criteria](https://huggingface.co/docs/smolagents/main/en/reference/models). The framework provides several predefined classes to simplify model connections: +### smolagents์˜ ๋ชจ๋ธ ํ†ตํ•ฉ +`smolagents`๋Š” ์œ ์—ฐํ•œ LLM ํ†ตํ•ฉ์„ ์ง€์›ํ•˜์—ฌ, [ํŠน์ • ๊ธฐ์ค€](https://huggingface.co/docs/smolagents/main/en/reference/models)์„ ์ถฉ์กฑํ•˜๋Š” ์–ด๋–ค ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ๋ชจ๋ธ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋ชจ๋ธ ์—ฐ๊ฒฐ์„ ๋‹จ์ˆœํ™”ํ•˜๋Š” ์—ฌ๋Ÿฌ ์‚ฌ์ „ ์ •์˜ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค: -- **[TransformersModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.TransformersModel):** Implements a local `transformers` pipeline for seamless integration. -- **[InferenceClientModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.InferenceClientModel):** Supports [serverless inference](https://huggingface.co/docs/huggingface_hub/main/en/guides/inference) calls through [Hugging Face's infrastructure](https://huggingface.co/docs/api-inference/index), or via a growing number of [third-party inference providers](https://huggingface.co/docs/huggingface_hub/main/en/guides/inference#supported-providers-and-tasks). -- **[LiteLLMModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.LiteLLMModel):** Leverages [LiteLLM](https://www.litellm.ai/) for lightweight model interactions. -- **[OpenAIServerModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.OpenAIServerModel):** Connects to any service that offers an OpenAI API interface. -- **[AzureOpenAIServerModel](https://huggingface.co/docs/smolagents/main/en/reference/models#smolagents.AzureOpenAIServerModel):** Supports integration with any Azure OpenAI deployment. +- **[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 ๋ฐฐํฌ์™€์˜ ํ†ตํ•ฉ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. -This flexibility ensures that developers can choose the model and service most suitable for their specific use cases, and allows for easy experimentation. +์ด๋Ÿฌํ•œ ์œ ์—ฐ์„ฑ ๋•๋ถ„์— ๊ฐœ๋ฐœ์ž๋Š” ๊ฐ์ž์˜ ์šฉ๋„์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋ชจ๋ธ๊ณผ ์„œ๋น„์Šค๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์‹คํ—˜๋„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Now that we understood why and when to use smolagents, let's dive deeper into this powerful library! +์ด์ œ smolagents๋ฅผ ์™œ, ์–ธ์ œ ์จ์•ผ ํ•˜๋Š”์ง€ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์ด ๊ฐ•๋ ฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋” ๊นŠ์ด ํƒ๊ตฌํ•ด๋ด…์‹œ๋‹ค! -## Resources +## ์ฐธ๊ณ  ์ž๋ฃŒ -- [smolagents Blog](https://huggingface.co/blog/smolagents) - Introduction to smolagents and code interactions +- [smolagents ๋ธ”๋กœ๊ทธ](https://huggingface.co/blog/smolagents) - smolagents์™€ ์ฝ”๋“œ ์ƒํ˜ธ์ž‘์šฉ ์†Œ๊ฐœ From eee3aca58bb0d89ba5d711e3eda5929d04e2189a Mon Sep 17 00:00:00 2001 From: jeong_ahn Date: Thu, 24 Jul 2025 23:21:56 +0900 Subject: [PATCH 6/6] fix: manual edits: LangGraph --- .../unit2/langgraph/when_to_use_langgraph.mdx | 2 +- units/ko/unit2/langgraph/building_blocks.mdx | 67 +++++++-------- units/ko/unit2/langgraph/conclusion.mdx | 17 ++-- .../langgraph/document_analysis_agent.mdx | 81 +++++++++++++------ units/ko/unit2/langgraph/first_graph.mdx | 26 +++--- units/ko/unit2/langgraph/introduction.mdx | 16 ++-- units/ko/unit2/langgraph/quiz1.mdx | 74 ++++++++--------- .../unit2/langgraph/when_to_use_langgraph.mdx | 58 ++++++------- 8 files changed, 186 insertions(+), 155 deletions(-) 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/unit2/langgraph/building_blocks.mdx b/units/ko/unit2/langgraph/building_blocks.mdx index 90e74d73..f3331332 100644 --- a/units/ko/unit2/langgraph/building_blocks.mdx +++ b/units/ko/unit2/langgraph/building_blocks.mdx @@ -1,16 +1,16 @@ -# LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ +# LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ[[building-blocks-of-langgraph]] -LangGraph๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋ ค๋ฉด ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. LangGraph ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ๋“ค์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. +LangGraph๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋ ค๋ฉด ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. LangGraph ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ๋นŒ๋”ฉ ๋ธ”๋ก์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Building Blocks -LangGraph์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ **์ง„์ž…์ **์—์„œ ์‹œ์ž‘ํ•˜์—ฌ, ์‹คํ–‰์— ๋”ฐ๋ผ ํ๋ฆ„์ด ํ•œ ํ•จ์ˆ˜์—์„œ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋กœ ์ด๋™ํ•˜๋‹ค๊ฐ€ END์— ๋„๋‹ฌํ•ฉ๋‹ˆ๋‹ค. +LangGraph ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ **์ง„์ž…์ (entrypoint)**์—์„œ ์‹œ์ž‘ํ•˜๋ฉฐ, ์‹คํ–‰ ํ๋ฆ„์— ๋”ฐ๋ผ ํ•œ ํ•จ์ˆ˜์—์„œ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋กœ ์ด๋™ํ•˜๋‹ค๊ฐ€ END์— ๋„๋‹ฌํ•ฉ๋‹ˆ๋‹ค. Application -## 1. ์ƒํƒœ(State) +## 1. ์ƒํƒœ[[state]] -**์ƒํƒœ**๋Š” LangGraph์˜ ํ•ต์‹ฌ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ†ตํ•ด ํ๋ฅด๋Š” ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. +**์ƒํƒœ(State)**๋Š” LangGraph์˜ ์ค‘์‹ฌ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ†ตํ•ด ํ๋ฅด๋Š” ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ```python from typing_extensions import TypedDict @@ -19,16 +19,16 @@ class State(TypedDict): graph_state: str ``` -์ƒํƒœ๋Š” **์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜**ํ•˜๋ฏ€๋กœ, ์˜์‚ฌ๊ฒฐ์ • ๊ณผ์ •์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค๊ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! +์ƒํƒœ๋Š” **์‚ฌ์šฉ์ž ์ •์˜**์ด๋ฏ€๋กœ, ์˜์‚ฌ๊ฒฐ์ • ๊ณผ์ •์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค๊ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! -> ๐Ÿ’ก **ํŒ:** ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹จ๊ณ„ ๊ฐ„์— ์ถ”์ ํ•ด์•ผ ํ•  ์ •๋ณด๋ฅผ ์‹ ์ค‘ํ•˜๊ฒŒ ๊ณ ๋ คํ•˜์„ธ์š”. +> ๐Ÿ’ก **ํŒ:** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹จ๊ณ„ ๊ฐ„์— ์ถ”์ ํ•ด์•ผ ํ•  ์ •๋ณด๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์‹ ์ค‘ํ•˜๊ฒŒ ๊ณ ๋ฏผํ•˜์„ธ์š”. -## 2. ๋…ธ๋“œ(Nodes) +## 2. ๋…ธ๋“œ[[nodes]] -**๋…ธ๋“œ**๋Š” ํŒŒ์ด์ฌ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š”: -- ์ƒํƒœ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Œ -- ์ผ๋ถ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ -- ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ˜ํ™˜ +**๋…ธ๋“œ(Node)**๋Š” ํŒŒ์ด์ฌ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š”: +- ์ƒํƒœ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค +- ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค +- ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค ```python def node_1(state): @@ -44,17 +44,18 @@ def node_3(state): return {"graph_state": state['graph_state'] +" sad!"} ``` -์˜ˆ๋ฅผ ๋“ค์–ด, ๋…ธ๋“œ๋Š” ๋‹ค์Œ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +์˜ˆ๋ฅผ ๋“ค์–ด, ๋…ธ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: - **LLM ํ˜ธ์ถœ**: ํ…์ŠคํŠธ ์ƒ์„ฑ ๋˜๋Š” ์˜์‚ฌ๊ฒฐ์ • - **ํˆด ํ˜ธ์ถœ**: ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์ƒํ˜ธ์ž‘์šฉ - **์กฐ๊ฑด๋ถ€ ๋กœ์ง**: ๋‹ค์Œ ๋‹จ๊ณ„ ๊ฒฐ์ • -- **์‚ฌ๋žŒ ๊ฐœ์ž…**: ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ ๋ฐ›๊ธฐ +- **์‚ฌ๋žŒ ๊ฐœ์ž…**: ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๋ฐ›๊ธฐ -> ๐Ÿ’ก **์ •๋ณด:** START์™€ END ๊ฐ™์€ ์ „์ฒด ์›Œํฌํ”Œ๋กœ์šฐ์— ํ•„์š”ํ•œ ๋…ธ๋“œ๋“ค์€ langGraph์—์„œ ์ง์ ‘ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. +> ๐Ÿ’ก **์ •๋ณด:** START์™€ END์ฒ˜๋Ÿผ ์ „์ฒด ์›Œํฌํ”Œ๋กœ์šฐ์— ํ•„์ˆ˜์ ์ธ ์ผ๋ถ€ ๋…ธ๋“œ๋Š” langGraph์—์„œ ์ง์ ‘ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -## 3. ์—ฃ์ง€(Edges) -**์—ฃ์ง€**๋Š” ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ  ๊ทธ๋ž˜ํ”„๋ฅผ ํ†ตํ•œ ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: +## 3. ์—ฃ์ง€[[edges]] + +**์—ฃ์ง€(Edge)**๋Š” ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•˜๋ฉฐ, ๊ทธ๋ž˜ํ”„ ๋‚ด์—์„œ ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: ```python import random @@ -65,21 +66,21 @@ def decide_mood(state) -> Literal["node_2", "node_3"]: # ์ข…์ข… ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•ด ๋‹ค์Œ์— ๋ฐฉ๋ฌธํ•  ๋…ธ๋“œ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค user_input = state['graph_state'] - # ์—ฌ๊ธฐ์„œ๋Š” ๋…ธ๋“œ 2, 3 ์‚ฌ์ด๋ฅผ 50:50์œผ๋กœ ๋ถ„ํ• ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค + # ์—ฌ๊ธฐ์„œ๋Š” ๋…ธ๋“œ 2, 3 ์‚ฌ์ด๋ฅผ 50:50์œผ๋กœ ๋ถ„๊ธฐํ•ฉ๋‹ˆ๋‹ค if random.random() < 0.5: - # 50% ํ™•๋ฅ ๋กœ ๋…ธ๋“œ 2 ๋ฐ˜ํ™˜ + # 50% ํ™•๋ฅ ๋กœ Node 2 ๋ฐ˜ํ™˜ return "node_2" - # 50% ํ™•๋ฅ ๋กœ ๋…ธ๋“œ 3 ๋ฐ˜ํ™˜ + # 50% ํ™•๋ฅ ๋กœ Node 3 ๋ฐ˜ํ™˜ return "node_3" ``` -์—ฃ์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -- **์ง์ ‘**: ํ•ญ์ƒ ๋…ธ๋“œ A์—์„œ ๋…ธ๋“œ B๋กœ ์ด๋™ -- **์กฐ๊ฑด๋ถ€**: ํ˜„์žฌ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค์Œ ๋…ธ๋“œ ์„ ํƒ +์—ฃ์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜๋‰ฉ๋‹ˆ๋‹ค: +- **์ง์ ‘(Direct)**: ํ•ญ์ƒ ๋…ธ๋“œ A์—์„œ ๋…ธ๋“œ B๋กœ ์ด๋™ +- **์กฐ๊ฑด๋ถ€(Conditional)**: ํ˜„์žฌ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์„ ํƒ -## 4. StateGraph +## 4. StateGraph[[stategraph]] **StateGraph**๋Š” ์ „์ฒด ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋‹ด๋Š” ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค: @@ -87,40 +88,40 @@ def decide_mood(state) -> Literal["node_2", "node_3"]: 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 index bf364f8c..8bc1b483 100644 --- a/units/ko/unit2/langgraph/conclusion.mdx +++ b/units/ko/unit2/langgraph/conclusion.mdx @@ -1,21 +1,20 @@ -# ๊ฒฐ๋ก  +# ๊ฒฐ๋ก [[conclusion]] -LangGraph ๋ชจ๋“ˆ์„ ์™„๋ฃŒํ•˜์‹  ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿฅณ +2๋‹จ์›์˜ LangGraph ๋ชจ๋“ˆ์„ ์™„๋ฃŒํ•˜์‹  ๊ฒƒ์„ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿฅณ -์ด์ œ LangGraph๋กœ ๊ตฌ์กฐํ™”๋œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋งˆ์Šคํ„ฐํ•˜์…จ์œผ๋ฉฐ, ์ด๋ฅผ ํ”„๋กœ๋•์…˜์— ๋ฐ”๋กœ ํˆฌ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด์ œ 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) +**์—ฌ๋Ÿฌ๋ถ„์˜ ๊ฐ•์˜์— ๋Œ€ํ•œ ์ƒ๊ฐ๊ณผ ์ œ์•ˆ ์‚ฌํ•ญ๋“ค์„ ๋งค์šฐ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค**. ํ”ผ๋“œ๋ฐฑ์ด ์žˆ์œผ์‹œ๋ฉด ๐Ÿ‘‰ [์ด ์–‘์‹](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 index c36f6c7e..5a7a8b39 100644 --- a/units/ko/unit2/langgraph/document_analysis_agent.mdx +++ b/units/ko/unit2/langgraph/document_analysis_agent.mdx @@ -1,10 +1,10 @@ -# ๋ฌธ์„œ ๋ถ„์„ ๊ทธ๋ž˜ํ”„ +# ๋ฌธ์„œ ๋ถ„์„ ๊ทธ๋ž˜ํ”„[[document-analysis-graph]] -์•Œํ”„๋ ˆ๋“œ๊ฐ€ ๋„์™€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. Mr. Wayne์˜ ์‹ ๋ขฐ๋ฐ›๋Š” ์ง‘์‚ฌ๋กœ์„œ, ์ €๋Š” Mr. Wayne์˜ ๋‹ค์–‘ํ•œ ๋ฌธ์„œ ์—…๋ฌด๋ฅผ ์–ด๋–ป๊ฒŒ ์ง€์›ํ•˜๋Š”์ง€ ๊ธฐ๋กํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฐ€ ๋ฐค ํ™œ๋™์„ ํ•˜๋Ÿฌ ๋‚˜๊ฐ„ ๋™์•ˆ, ์ €๋Š” ๋ชจ๋“  ์„œ๋ฅ˜, ํ›ˆ๋ จ ์ผ์ •, ์˜์–‘ ๊ณ„ํš์ด ์ œ๋Œ€๋กœ ๋ถ„์„๋˜๊ณ  ์ •๋ฆฌ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. +์ € ์•Œํ”„๋ ˆ๋“œ๋Š” Mr.์›จ์ธ๋‹˜์˜ ์‹ ๋ขฐ๋ฐ›๋Š” ์ง‘์‚ฌ๋กœ์„œ, ๊ทธ๋ถ„์˜ ๋‹ค์–‘ํ•œ ๋ฌธ์„œ ์—…๋ฌด๋ฅผ ์–ด๋–ป๊ฒŒ ์ง€์›ํ• ์ง€ ๊ธฐ๋กํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฐ€ ๋ฐค ํ™œ๋™์„ ํ•˜๋Ÿฌ ๋‚˜๊ฐ„ ๋™์•ˆ, ์ €๋Š” ๋ชจ๋“  ์„œ๋ฅ˜, ํ›ˆ๋ จ ์ผ์ •, ์˜์–‘ ๊ณ„ํš์„ ๋ถ„์„ํ•˜๊ณ  ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค. -๊ทธ๊ฐ€ ์™ธ์ถœํ•˜๊ธฐ ์ „, ์ด๋ฒˆ ์ฃผ ํ›ˆ๋ จ ํ”„๋กœ๊ทธ๋žจ์ด ์ ํžŒ ์ชฝ์ง€๋ฅผ ๋‚จ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ๋‚ด์ผ ์‹์‚ฌ๋ฅผ ์œ„ํ•œ **๋ฉ”๋‰ด**๋ฅผ ์ง์ ‘ ์งœ๊ธฐ๋กœ ํ–ˆ์ฃ . +๊ทธ๋ถ„์ด ์™ธ์ถœํ•˜๊ธฐ ์ „, ์ด๋ฒˆ ์ฃผ ํ›ˆ๋ จ ํ”„๋กœ๊ทธ๋žจ์ด ์ ํžŒ ์ชฝ์ง€๋ฅผ ๋‚จ๊ธฐ์…จ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ชฝ์ง€๋ฅผ ๋ณด๊ณ  ์ €๋Š” ๋‚ด์ผ ์‹์‚ฌ๋ฅผ ์œ„ํ•œ **๋ฉ”๋‰ด**๋ฅผ ์ง์ ‘ ์งœ๊ธฐ๋กœ ํ–ˆ์ฃ . -์•ž์œผ๋กœ๋„ ์ด๋Ÿฐ ์ผ์ด ์žˆ์„ ๋•Œ๋ฅผ ๋Œ€๋น„ํ•ด, LangGraph๋ฅผ ํ™œ์šฉํ•ด Mr. Wayne์„ ์œ„ํ•œ ๋ฌธ์„œ ๋ถ„์„ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์ด ์‹œ์Šคํ…œ์€ ๋‹ค์Œ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +์•ž์œผ๋กœ๋„ ์ด๋Ÿฐ ์ผ์ด ์žˆ์„ ๋•Œ๋ฅผ ๋Œ€๋น„ํ•ด, LangGraph๋ฅผ ํ™œ์šฉํ•ด ์›จ์ธ๋‹˜์„ ์œ„ํ•œ ๋ฌธ์„œ ๋ถ„์„ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์ด ์‹œ์Šคํ…œ์€ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: 1. ์ด๋ฏธ์ง€ ๋ฌธ์„œ ์ฒ˜๋ฆฌ 2. ๋น„์ „ ๋ชจ๋ธ(๋น„์ „ ์–ธ์–ด ๋ชจ๋ธ)๋กœ ํ…์ŠคํŠธ ์ถ”์ถœ @@ -12,9 +12,9 @@ 4. ๋‚ด์šฉ ๋ถ„์„ ๋ฐ ์š”์•ฝ ์ œ๊ณต 5. ๋ฌธ์„œ ๊ด€๋ จ ํŠน์ • ์ง€์‹œ ์‹คํ–‰ -## ์ง‘์‚ฌ์˜ ์›Œํฌํ”Œ๋กœ์šฐ +## ์ง‘์‚ฌ์˜ ์›Œํฌํ”Œ๋กœ์šฐ[[the-butler's-workflow]] -์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค: +๋งŒ๋“ค ์›Œํฌํ”Œ๋กœ์šฐ์˜ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: ![์ง‘์‚ฌ์˜ ๋ฌธ์„œ ๋ถ„์„ ์›Œํฌํ”Œ๋กœ์šฐ](https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/alfred_flow.png) @@ -22,12 +22,12 @@ ์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## ํ™˜๊ฒฝ ์„ค์ • +## ํ™˜๊ฒฝ ์„ค์ •[[setting-up-the-environment]] ```python %pip install langgraph langchain_openai langchain_core ``` -๊ทธ๋ฆฌ๊ณ  ์ž„ํฌํŠธ: +์ž„ํฌํŠธ : ```python import base64 from typing import List, TypedDict, Annotated, Optional @@ -39,7 +39,7 @@ from langgraph.prebuilt import ToolNode, tools_condition from IPython.display import Image, display ``` -## ์—์ด์ „ํŠธ ์ƒํƒœ ์ •์˜ +## ์—์ด์ „ํŠธ ์ƒํƒœ ์ •์˜[[defining-agent's-state]] ์ด ์ƒํƒœ๋Š” ์•ž์„œ ๋ณธ ๊ฒƒ๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. `AnyMessage`๋Š” Langchain์˜ ๋ฉ”์‹œ์ง€ ํด๋ž˜์Šค์ด๊ณ , `add_messages`๋Š” ์ตœ์‹  ๋ฉ”์‹œ์ง€๋ฅผ ๋ˆ„์ ํ•˜๋Š” ์—ฐ์‚ฐ์ž์ž…๋‹ˆ๋‹ค. @@ -53,7 +53,7 @@ class AgentState(TypedDict): messages: Annotated[list[AnyMessage], add_messages] ``` -## ํˆด ์ค€๋น„ํ•˜๊ธฐ +## ํˆด ์ค€๋น„ํ•˜๊ธฐ[[preparing-tools]] ```python vision_llm = ChatOpenAI(model="gpt-4o") @@ -67,29 +67,50 @@ def extract_text(img_path: str) -> str: """ 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}"}}, + { + "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: - """Wayne ์ฃผ์ธ๋‹˜์˜ ๊ณ„์‚ฐ ์š”์ฒญ์„ ์œ„ํ•œ ๋‚˜๋ˆ—์…ˆ ํ•จ์ˆ˜""" + """์ฃผ์ธ๋‹˜์˜ ๊ณ„์‚ฐ ์š”์ฒญ์„ ์œ„ํ•œ ๋‚˜๋ˆ—์…ˆ ํ•จ์ˆ˜""" return a / b +# ์ง‘์‚ฌ, ๋„๊ตฌ(tool) ์žฅ์ฐฉ tools = [ divide, extract_text @@ -99,7 +120,7 @@ llm = ChatOpenAI(model="gpt-4o") llm_with_tools = llm.bind_tools(tools, parallel_tool_calls=False) ``` -## ๋…ธ๋“œ ์ •์˜ +## ๋…ธ๋“œ[[the-nodes]] ```python def assistant(state: AgentState): @@ -107,23 +128,25 @@ 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 ํŒจํ„ด: ์ง‘์‚ฌ์˜ ์ง€์› ๋ฐฉ์‹ +## ReAct ํŒจํ„ด: ์ง‘์‚ฌ์˜ ์ง€์› ๋ฐฉ์‹[[the-react-pattern-how-i-assist-mr.-wayne]] ์ด ์—์ด์ „ํŠธ๋Š” ReAct ํŒจํ„ด(Reason-Act-Observe)์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. @@ -138,14 +161,16 @@ divide(a: int, b: int) -> float: # ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ 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") @@ -156,19 +181,25 @@ 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`๋กœ, ์•„๋‹ˆ๋ฉด 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: ๊ฐ„๋‹จํ•œ ๊ณ„์‚ฐ +### ์˜ˆ์‹œ 1: ๊ฐ„๋‹จํ•œ ๊ณ„์‚ฐ[[example-1-simple-calculations]] ์•„๋ž˜๋Š” LangGraph์—์„œ ํˆด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. @@ -193,7 +224,7 @@ Tool Response: 1358.0 Alfred: 6790์„ 5๋กœ ๋‚˜๋ˆ„๋ฉด 1358.0์ž…๋‹ˆ๋‹ค. ``` -### ์˜ˆ์‹œ 2: Wayne ์ฃผ์ธ๋‹˜์˜ ํ›ˆ๋ จ ๋ฌธ์„œ ๋ถ„์„ +### ์˜ˆ์‹œ 2: Wayne ์ฃผ์ธ๋‹˜์˜ ํ›ˆ๋ จ ๋ฌธ์„œ ๋ถ„์„[[example-2-analyzing-master-wayne's-training-documents]] ์ฃผ์ธ๋‹˜์ด ํ›ˆ๋ จ ๋ฐ ์‹๋‹จ ์ชฝ์ง€๋ฅผ ๋‚จ๊ฒผ์„ ๋•Œ: @@ -222,7 +253,7 @@ Alfred: ์ €๋… ๋ฉ”๋‰ด๋ฅผ ์œ„ํ•ด ๋‹ค์Œ ์žฌ๋ฃŒ๋ฅผ ๊ตฌ์ž…ํ•˜์„ธ์š”: ์Šคํ…Œ์ดํฌ๋Š” ๋ชฉ์ดˆ ์‚ฌ์œก, ์‹œ๊ธˆ์น˜์™€ ๊ณ ์ถ”๋Š” ์œ ๊ธฐ๋†์œผ๋กœ ์ค€๋น„ํ•˜๋ฉด ์ตœ๊ณ ์˜ ์‹์‚ฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ``` -## ํ•ต์‹ฌ ์š”์•ฝ +## ํ•ต์‹ฌ ์š”์•ฝ[[key-takeaways]] ๋‚˜๋งŒ์˜ ๋ฌธ์„œ ๋ถ„์„ ์ง‘์‚ฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ์„ ๊ณ ๋ คํ•˜์„ธ์š”: diff --git a/units/ko/unit2/langgraph/first_graph.mdx b/units/ko/unit2/langgraph/first_graph.mdx index 4e957152..e51d0f43 100644 --- a/units/ko/unit2/langgraph/first_graph.mdx +++ b/units/ko/unit2/langgraph/first_graph.mdx @@ -1,4 +1,4 @@ -# ๋‚˜๋งŒ์˜ ์ฒซ LangGraph ๋งŒ๋“ค๊ธฐ +# ๋‚˜๋งŒ์˜ ์ฒซ LangGraph ๋งŒ๋“ค๊ธฐ[[building-your-first-langgraph]] ์ด์ œ LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ดํ•ดํ–ˆ์œผ๋‹ˆ, ์‹ค์ œ๋กœ ์ ์šฉํ•ด๋ณด๋ฉฐ ์ฒซ ๋ฒˆ์งธ ๊ธฐ๋Šฅ์  ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์•Œํ”„๋ ˆ๋“œ์˜ ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•Œํ”„๋ ˆ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: @@ -13,12 +13,12 @@ ์ด ๋…ธํŠธ๋ถ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ Google Colab์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค ์›Œํฌํ”Œ๋กœ์šฐ +## ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค ์›Œํฌํ”Œ๋กœ์šฐ[[our-workflow]] ์•„๋ž˜์™€ ๊ฐ™์€ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค: First LangGraph -## ํ™˜๊ฒฝ ์„ค์ • +## ํ™˜๊ฒฝ ์„ค์ •[[setting-up-our-environment]] ๋จผ์ € ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค: @@ -36,7 +36,7 @@ from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage ``` -## 1๋‹จ๊ณ„: ์ƒํƒœ(State) ์ •์˜ํ•˜๊ธฐ +## 1๋‹จ๊ณ„: ์ƒํƒœ(State) ์ •์˜ํ•˜๊ธฐ[[step-1-define-our-state]] ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ ์•Œํ”„๋ ˆ๋“œ๊ฐ€ ์ถ”์ ํ•ด์•ผ ํ•  ์ •๋ณด๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: @@ -63,7 +63,7 @@ class EmailState(TypedDict): > ๐Ÿ’ก **ํŒ:** ์ƒํƒœ๋Š” ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๋ชจ๋‘ ๋‹ด๋˜, ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋น„๋Œ€ํ•ด์ง€์ง€ ์•Š๋„๋ก ํ•˜์„ธ์š”. -## 2๋‹จ๊ณ„: ๋…ธ๋“œ ์ •์˜ํ•˜๊ธฐ +## 2๋‹จ๊ณ„: ๋…ธ๋“œ ์ •์˜ํ•˜๊ธฐ[[step-2-define-our-nodes]] ์ด์ œ ๊ฐ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ๋‹ด๋‹นํ•  ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค: @@ -163,7 +163,7 @@ def notify_mr_hugg(state: EmailState): return {} ``` -## 3๋‹จ๊ณ„: ๋ถ„๊ธฐ ๋กœ์ง ์ •์˜ํ•˜๊ธฐ +## 3๋‹จ๊ณ„: ๋ถ„๊ธฐ ๋กœ์ง ์ •์˜ํ•˜๊ธฐ[[step-3-define-our-routing-logic]] ๋ถ„๋ฅ˜ ํ›„ ์–ด๋–ค ๊ฒฝ๋กœ๋กœ ๊ฐˆ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค: @@ -178,7 +178,7 @@ def route_email(state: EmailState) -> str: > ๐Ÿ’ก **์ฐธ๊ณ :** ์ด ๋ผ์šฐํŒ… ํ•จ์ˆ˜๋Š” LangGraph๊ฐ€ ๋ถ„๋ฅ˜ ๋…ธ๋“œ ์ดํ›„ ์–ด๋–ค ์—ฃ์ง€๋ฅผ ๋”ฐ๋ผ๊ฐˆ์ง€ ๊ฒฐ์ •ํ•  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์€ ์กฐ๊ฑด๋ถ€ ์—ฃ์ง€ ๋งคํ•‘์˜ ํ‚ค์™€ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -## 4๋‹จ๊ณ„: StateGraph ์ƒ์„ฑ ๋ฐ ์—ฃ์ง€ ์ •์˜ +## 4๋‹จ๊ณ„: StateGraph ์ƒ์„ฑ ๋ฐ ์—ฃ์ง€ ์ •์˜[[step-4-create-the-stategraph-and-define-edges]] ์ด์ œ ๋ชจ๋“  ๊ฒƒ์„ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค: @@ -219,7 +219,7 @@ compiled_graph = email_graph.compile() LangGraph์—์„œ ์ œ๊ณตํ•˜๋Š” ํŠน์ˆ˜ํ•œ `END` ๋…ธ๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ์™„๋ฃŒ๋˜๋Š” ์ง€์ ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. -## 5๋‹จ๊ณ„: ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ํ•˜๊ธฐ +## 5๋‹จ๊ณ„: ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ํ•˜๊ธฐ[[step-5-run-the-application]] ์ •์ƒ ๋ฉ”์ผ๊ณผ ์ŠคํŒธ ๋ฉ”์ผ๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ด…๋‹ˆ๋‹ค: @@ -261,7 +261,7 @@ spam_result = compiled_graph.invoke({ }) ``` -## 6๋‹จ๊ณ„: Langfuse๋กœ ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ ๊ด€์ฐฐํ•˜๊ธฐ ๐Ÿ“ก +## 6๋‹จ๊ณ„: Langfuse๋กœ ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ ๊ด€์ฐฐํ•˜๊ธฐ ๐Ÿ“ก[[step-6-inspecting-our-mail-sorting-agent-with-langfuse]] ์•Œํ”„๋ ˆ๋“œ๋Š” ๋ฉ”์ผ ๋ถ„๋ฅ˜ ์—์ด์ „ํŠธ๋ฅผ ๋‹ค๋“ฌ์œผ๋ฉด์„œ ๋””๋ฒ„๊น…์— ์ง€์ณ๊ฐ‘๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ  ์ถ”์ ์ด ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ถ๊ทน์˜ ์ŠคํŒธ ๊ฐ์ง€ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ํ”„๋กœ๋•์…˜์— ๋ฐฐํฌํ•˜๋ ค๋ฉด, ํ–ฅํ›„ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๋ถ„์„์„ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ์ถ”์  ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. @@ -309,7 +309,7 @@ legitimate_result = compiled_graph.invoke( _[์ •์ƒ ๋ฉ”์ผ ํŠธ๋ ˆ์ด์Šค ๊ณต๊ฐœ ๋งํฌ](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๋Š” ์›Œํฌํ”Œ๋กœ์šฐ ๊ตฌ์กฐ๋ฅผ ์‹œ๊ฐํ™”ํ•˜์—ฌ ์ดํ•ด์™€ ๋””๋ฒ„๊น…์„ ๋•์Šต๋‹ˆ๋‹ค: @@ -320,7 +320,7 @@ compiled_graph.get_graph().draw_mermaid_png() ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋…ธ๋“œ ๊ฐ„ ์—ฐ๊ฒฐ๊ณผ ์กฐ๊ฑด๋ถ€ ๊ฒฝ๋กœ๋ฅผ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ๊ฒƒ +## ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ๊ฒƒ[[what-we've-built]] ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค: @@ -331,13 +331,13 @@ compiled_graph.get_graph().draw_mermaid_png() ์ด์ฒ˜๋Ÿผ 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 index 706275ba..a1f9da79 100644 --- a/units/ko/unit2/langgraph/introduction.mdx +++ b/units/ko/unit2/langgraph/introduction.mdx @@ -1,32 +1,32 @@ -# `LangGraph` ์†Œ๊ฐœ +# `LangGraph` ์†Œ๊ฐœ[[introduction-to-langgraph]] Unit 2.3 Thumbnail -์—ฌ์ •์˜ ๋‹ค์Œ ๋‹จ๊ณ„์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ์ด ๋‹จ์›์—์„œ๋Š” ๋ณต์žกํ•œ LLM ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๊ณ  ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ [`LangGraph`](https://github.com/langchain-ai/langgraph) ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•**์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. +๋‹ค์Œ ๋‹จ๊ณ„์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ์ด ๋‹จ์›์—์„œ๋Š” ๋ณต์žกํ•œ LLM ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๊ณ  ์กฐ์ •, ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ [`LangGraph`](https://github.com/langchain-ai/langgraph) ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ **์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•**์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. `LangGraph`๋Š” ์—์ด์ „ํŠธ์˜ ํ๋ฆ„์„ **์ง์ ‘ ์ œ์–ด**ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•˜์—ฌ **ํ”„๋กœ๋•์…˜ ์ˆ˜์ค€**์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. -## ๋ชจ๋“ˆ ๊ฐœ์š” +## ๋ชจ๋“ˆ ๊ฐœ์š”[[module-overview]] ์ด ๋‹จ์›์—์„œ ์—ฌ๋Ÿฌ๋ถ„์€ ๋‹ค์Œ์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: ### 1๏ธโƒฃ [LangGraph๋ž€ ๋ฌด์—‡์ด๋ฉฐ, ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?](./when_to_use_langgraph) ### 2๏ธโƒฃ [LangGraph์˜ ๊ตฌ์„ฑ ์š”์†Œ](./building_blocks) -### 3๏ธโƒฃ [๋ฉ”์ผ ๋ถ„๋ฅ˜ํ•˜๋Š” ์ง‘์‚ฌ ์•Œํ”„๋ ˆ๋“œ](./first_graph) +### 3๏ธโƒฃ [๋‚ด ๋ฉ”์ผ์„ ๋Œ€์‹  ๋ถ„๋ฅ˜ํ•ด์ฃผ๋Š” ์ง‘์‚ฌ](./first_graph) ### 4๏ธโƒฃ [์•Œํ”„๋ ˆ๋“œ, ๋ฌธ์„œ ๋ถ„์„ ์—์ด์ „ํŠธ](./document_analysis_agent) ### 5๏ธโƒฃ [ํ€ด์ฆˆ](./quizz1) -์ด ์„น์…˜์˜ ์˜ˆ์ œ๋“ค์€ ๊ฐ•๋ ฅํ•œ LLM/VLM ๋ชจ๋ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ €ํฌ๋Š” langGraph์™€ ๊ฐ€์žฅ ํ˜ธํ™˜์„ฑ์ด ์ข‹์€ GPT-4o API๋ฅผ ์‚ฌ์šฉํ•ด ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. +์ด ์„น์…˜์˜ ์˜ˆ์ œ๋“ค์€ ๊ฐ•๋ ฅํ•œ LLM/VLM ๋ชจ๋ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฝ”์Šค์—์„œ๋Š” langGraph์™€ ๊ฐ€์žฅ ํ˜ธํ™˜์„ฑ์ด ์ข‹์€ GPT-4o API๋ฅผ ์‚ฌ์šฉํ•ด ์‹คํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. -์ด ๋‹จ์›์ด ๋๋‚˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ฒฌ๊ณ ํ•˜๊ณ  ์ฒด๊ณ„์ ์ด๋ฉฐ ํ”„๋กœ๋•์…˜์— ๋ฐ”๋กœ ํˆฌ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค! +์ด ๋‹จ์›์ด ๋๋‚˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ฒฌ๊ณ ํ•˜๊ณ  ์ฒด๊ณ„์ ์ธ, ํ”„๋กœ๋•์…˜์— ๋ฐ”๋กœ ํˆฌ์ž… ๊ฐ€๋Šฅํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค! -์ด ์„น์…˜์€ LangGraph์˜ ์ž…๋ฌธ ๊ณผ์ •์ด๋ฉฐ, ๋” ์‹ฌํ™”๋œ ์ฃผ์ œ๋Š” ๋ฌด๋ฃŒ LangChain ์•„์นด๋ฐ๋ฏธ ๊ฐ•์˜ [LangGraph ์†Œ๊ฐœ](https://academy.langchain.com/courses/intro-to-langgraph)์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด ์„น์…˜์€ 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 index a28d3505..2f8f9bb2 100644 --- a/units/ko/unit2/langgraph/quiz1.mdx +++ b/units/ko/unit2/langgraph/quiz1.mdx @@ -1,44 +1,44 @@ -# LangGraph ์ดํ•ด๋„ ํ…Œ์ŠคํŠธ +# LangGraph ์ดํ•ด๋„ ํ…Œ์ŠคํŠธ [[test-your-understanding-of-langgraph]] -`LangGraph`์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ๊ฐ„๋‹จํ•œ ํ€ด์ฆˆ๋กœ ํ…Œ์ŠคํŠธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! ์ง€๊ธˆ๊นŒ์ง€ ๋‹ค๋ฃฌ ํ•ต์‹ฌ ๊ฐœ๋…๋“ค์„ ๊ฐ•ํ™”ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +`LangGraph`์— ๋Œ€ํ•œ ์ดํ•ด๋„๋ฅผ ๊ฐ„๋‹จํ•œ ํ€ด์ฆˆ๋กœ ํ™•์ธํ•ด๋ณด์„ธ์š”! ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ํ•ต์‹ฌ ๊ฐœ๋…์„ ๋ณต์Šตํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. -์ด ํ€ด์ฆˆ๋Š” ์„ ํƒ์‚ฌํ•ญ์ด๋ฉฐ ์ ์ˆ˜๋Š” ๋งค๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +์ด ํ€ด์ฆˆ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ์ฑ„์ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -### Q1: LangGraph์˜ ์ฃผ์š” ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? +### Q1: LangGraph์˜ ์ฃผ์š” ๋ชฉ์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? [[q1-what-is-the-primary-purpose-of-langgraph]] LangGraph๊ฐ€ ๋ฌด์—‡์„ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ๋Š”์ง€ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์žฅ์€? --- -### Q2: "์ œ์–ด vs ์ž์œ " ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ๋งฅ๋ฝ์—์„œ LangGraph๋Š” ์–ด๋””์— ์œ„์น˜ํ•˜๋‚˜์š”? -์—์ด์ „ํŠธ ์„ค๊ณ„์— ๋Œ€ํ•œ LangGraph์˜ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ฐ€์žฅ ์ž˜ ํŠน์ง•์ง“๋Š” ๋ฌธ์žฅ์€? +### Q2: "์ œ์–ด vs ์ž์œ " ๊ด€์ ์—์„œ LangGraph๋Š” ์–ด๋””์— ์†ํ•˜๋‚˜์š”? [[q2-in-the-context-of-the-control-vs-freedom-trade-off-where-does-langgraph-stand]] +๋‹ค์Œ ์ค‘ LangGraph์˜ ์—์ด์ „ํŠธ ์„ค๊ณ„ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ฐ€์žฅ ์ž˜ ์„ค๋ช…ํ•œ ๋ฌธ์žฅ์€? -### Q4: LangGraph์—์„œ ์กฐ๊ฑด๋ถ€ ์—ฃ์ง€(Conditional Edge)๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? -๊ฐ€์žฅ ์ •ํ™•ํ•œ ์„ค๋ช…์„ ์„ ํƒํ•˜์„ธ์š”. +### Q4: LangGraph์—์„œ ์กฐ๊ฑด๋ถ€ ์—ฃ์ง€(Conditional Edge)๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? [[q4-what-is-a-conditional-edge-in-langgraph]] +์กฐ๊ฑด๋ถ€ ์—ฃ์ง€์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ฒƒ์€? --- -### Q5: LangGraph๋Š” LLM์˜ ํ™˜๊ฐ(hallucination) ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋‚˜์š”? -์ตœ์„ ์˜ ๋‹ต์„ ์„ ํƒํ•˜์„ธ์š”. +### Q5: LangGraph๋Š” LLM์˜ ํ™˜๊ฐ(hallucination) ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋‚˜์š”? [[q5-how-does-langgraph-help-address-the-hallucination-problem-in-llms]] +ํ™˜๊ฐ์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ฒƒ์€? -ํ€ด์ฆˆ ์™„๋ฃŒ๋ฅผ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ ์งˆ๋ฌธ์„ ๋†“์ณค๋‹ค๋ฉด, ์ดํ•ด๋ฅผ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ด์ „ ์„น์…˜๋“ค์„ ๋‹ค์‹œ ๊ฒ€ํ† ํ•ด๋ณด์„ธ์š”. ๋‹ค์Œ์—๋Š” LangGraph์˜ ๋” ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ์„ ํƒ๊ตฌํ•˜๊ณ  ๋” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. +์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ ํ‹€๋ฆฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์•ž์—์„œ ๋‹ค๋ฃฌ ๋‚ด์šฉ๋“ค์„ ๋‹ค์‹œ ๊ฒ€ํ† ํ•ด๋ณด์„ธ์š”. ์ด์ œ LangGraph์˜ ๋” ์‹ฌํ™” ๊ธฐ๋Šฅ์„ ์•Œ์•„๋ณด๊ณ , ๋” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ด…์‹œ๋‹ค. diff --git a/units/ko/unit2/langgraph/when_to_use_langgraph.mdx b/units/ko/unit2/langgraph/when_to_use_langgraph.mdx index 70f419d5..09370de2 100644 --- a/units/ko/unit2/langgraph/when_to_use_langgraph.mdx +++ b/units/ko/unit2/langgraph/when_to_use_langgraph.mdx @@ -1,68 +1,68 @@ -# `LangGraph`๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? +# `LangGraph`๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? [[what-is-langgraph]] `LangGraph`๋Š” [LangChain](https://www.langchain.com/)์—์„œ ๊ฐœ๋ฐœํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, **LLM์„ ํ†ตํ•ฉํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ œ์–ด ํ๋ฆ„์„ ๊ด€๋ฆฌ**ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. -## `LangGraph`๋Š” `LangChain`๊ณผ ๋‹ค๋ฅธ๊ฐ€์š”? +## `LangGraph`๋Š” `LangChain`์™€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”? [[is-langgraph-different-from-langchain]] LangChain์€ ๋ชจ๋ธ ๋ฐ ๊ธฐํƒ€ ๊ตฌ์„ฑ ์š”์†Œ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ๊ฒ€์ƒ‰, LLM ํ˜ธ์ถœ, ํˆด ํ˜ธ์ถœ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. LangChain์˜ ํด๋ž˜์Šค๋“ค์€ LangGraph์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. -๋‘ ํŒจํ‚ค์ง€๋Š” ๋‹ค๋ฅด๋ฉฐ ๋…๋ฆฝ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ฒฐ๊ตญ ์˜จ๋ผ์ธ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋Š” ๋‘ ํŒจํ‚ค์ง€๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +๋‘ ํŒจํ‚ค์ง€๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํŒจํ‚ค์ง€์ด๋ฉฐ, ๊ฐ๊ฐ ๋…๋ฆฝ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‹ค์ œ๋กœ ์˜จ๋ผ์ธ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ํŒจํ‚ค์ง€๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. -## ์–ธ์ œ `LangGraph`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ์š”? -### ์ œ์–ด vs ์ž์œ  +## ์–ธ์ œ `LangGraph`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ์š”? [[when-should-i-use-langgraph]] +### ์ œ์–ด vs ์ž์œ  [[control-vs-freedom]] -AI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค๊ณ„ํ•  ๋•Œ, **์ œ์–ด**์™€ **์ž์œ ** ์‚ฌ์ด์˜ ๊ทผ๋ณธ์ ์ธ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„์— ์ง๋ฉดํ•ฉ๋‹ˆ๋‹ค: +AI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค๊ณ„ํ•  ๋•Œ, **์ œ์–ด**์™€ **์ž์œ ** ์‚ฌ์ด์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๊ณ ๋ คํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค: -- **์ž์œ **๋Š” LLM์—๊ฒŒ ๋” ๋งŽ์€ ์ฐฝ์˜์„ฑ๊ณผ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ์œ„ํ•œ ์—ฌ์ง€๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -- **์ œ์–ด**๋Š” ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋™์ž‘์„ ๋ณด์žฅํ•˜๊ณ  ๊ฐ€๋“œ๋ ˆ์ผ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. +- **์ž์œ **๋Š” LLM์ด ๋” ๋งŽ์€ ์ฐฝ์˜์„ฑ์„ ๋ฐœํœ˜ํ•˜๊ณ  ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. +- **์ œ์–ด**๋Š” ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋™์ž‘์„ ๋ณด์žฅํ•˜๊ณ  ์•ˆ์ „ ์žฅ์น˜๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -*smolagents*์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ ์—์ด์ „ํŠธ๋“ค์€ ๋งค์šฐ ์ž์œ ๋กญ์Šต๋‹ˆ๋‹ค. ๋‹จ์ผ ์•ก์…˜ ๋‹จ๊ณ„์—์„œ ์—ฌ๋Ÿฌ ํˆด์„ ํ˜ธ์ถœํ•˜๊ณ , ์ž์‹ ๋งŒ์˜ ํˆด์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋™์ž‘์€ JSON์œผ๋กœ ์ž‘์—…ํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ์—์ด์ „ํŠธ๋ณด๋‹ค ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ต๊ณ  ์ œ์–ดํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค! +*smolagents*์˜ ์ฝ”๋“œ ์—์ด์ „ํŠธ๋Š” ๋งค์šฐ ์ž์œ ๋กญ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์•ก์…˜ ๋‹จ๊ณ„์—์„œ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ์ž์ฒด์ ์œผ๋กœ ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋™์ž‘์€ JSON ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ๋ณด๋‹ค ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ต๊ณ  ์ œ์–ดํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค! `LangGraph`๋Š” ์ŠคํŽ™ํŠธ๋Ÿผ์˜ ๋ฐ˜๋Œ€ํŽธ์— ์žˆ์œผ๋ฉฐ, ์—์ด์ „ํŠธ ์‹คํ–‰์— **"์ œ์–ด"**๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋น›๋‚ฉ๋‹ˆ๋‹ค. -LangGraph๋Š” ํŠนํžˆ **์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ์ œ์–ด**๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋”ฐ๋ฅด๋ฉด์„œ๋„ LLM์˜ ํž˜์„ ํ™œ์šฉํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +LangGraph๋Š” ํŠนํžˆ **์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ์ œ์–ด**๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋”ฐ๋ฅด๋ฉด์„œ๋„ LLM์˜ ํž˜์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํŠน์ • ๋ฐฉ์‹์œผ๋กœ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜๋˜์–ด์•ผ ํ•˜๋Š” ์ผ๋ จ์˜ ๋‹จ๊ณ„๋ฅผ ํฌํ•จํ•˜๊ณ , ๊ฐ ๋ถ„๊ธฐ์ ์—์„œ ๊ฒฐ์ •์ด ๋‚ด๋ ค์ ธ์•ผ ํ•œ๋‹ค๋ฉด, **LangGraph๊ฐ€ ํ•„์š”ํ•œ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค**. +๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํŠน์ • ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ผ๋ จ์˜ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์•ผํ•˜๊ณ , ๊ฐ ๋ถ„๊ธฐ์ ์—์„œ ์˜์‚ฌ๊ฒฐ์ •์ด ๋‚ด๋ ค์ ธ์•ผ ํ•œ๋‹ค๋ฉด, **LangGraph๊ฐ€ ๊ทธ ํ•„์š”ํ•œ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค**. -์˜ˆ๋ฅผ ๋“ค์–ด, ์ผ๋ถ€ ๋ฌธ์„œ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์— ๋‹ตํ•  ์ˆ˜ ์žˆ๋Š” LLM ์–ด์‹œ์Šคํ„ดํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. +์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฌธ์„œ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์— ๋‹ตํ•  ์ˆ˜ ์žˆ๋Š” LLM ์–ด์‹œ์Šคํ„ดํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. -LLM์ด ํ…์ŠคํŠธ๋ฅผ ๊ฐ€์žฅ ์ž˜ ์ดํ•ดํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์ „์— ๋‹ค๋ฅธ ๋ณต์žกํ•œ ๋ชจ๋‹ฌ๋ฆฌํ‹ฐ(์ฐจํŠธ, ํ‘œ)๋ฅผ ํ…์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์„ ํƒ์€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฌธ์„œ์˜ ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค! +LLM์ด ํ…์ŠคํŠธ๋ฅผ ๊ฐ€์žฅ ์ž˜ ์ดํ•ดํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์ „์— ๋ณต์žกํ•œ ํ˜•ํƒœ๋“ค(์ฐจํŠธ, ํ‘œ)์„ ํ…์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์„ ํƒ์€ ๋ฌธ์„œ์˜ ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค! -์ด๊ฒƒ์€ ์ œ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„ํ•˜๊ธฐ๋กœ ์„ ํƒํ•œ ๋ถ„๊ธฐ์ž…๋‹ˆ๋‹ค: +์ด๋Ÿฌํ•œ ๋ถ„๊ธฐ ํ๋ฆ„์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: Control flow -> ๐Ÿ’ก **ํŒ:** ์™ผ์ชฝ ๋ถ€๋ถ„์€ ์—์ด์ „ํŠธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ํˆด ํ˜ธ์ถœ์ด ํฌํ•จ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์€ xls๋ฅผ ์ฟผ๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(pandas๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์กฐ์ž‘). +> ๐Ÿ’ก **ํŒ:** ์™ผ์ชฝ ๋ถ€๋ถ„์€ ๋„๊ตฌ ํ˜ธ์ถœ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—์ด์ „ํŠธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์€ ์—‘์…€ ํŒŒ์ผ์„ ์ฟผ๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์—์ด์ „ํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.(์˜ˆ: pandas๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์กฐ์ž‘). ์ด ๋ถ„๊ธฐ๋Š” ๊ฒฐ์ •์ ์ด์ง€๋งŒ, LLM ์ถœ๋ ฅ์— ๋”ฐ๋ผ ์กฐ๊ฑด์ด ์ •ํ•ด์ง€๋Š” ๋น„๊ฒฐ์ •์  ๋ถ„๊ธฐ๋„ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -LangGraph๊ฐ€ ๋›ฐ์–ด๋‚œ ์ฃผ์š” ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: +LangGraph๊ฐ€ ์œ ์šฉํ•œ ๊ฒฝ์šฐ: - **๋ช…์‹œ์ ์ธ ํ๋ฆ„ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•œ ๋‹ค๋‹จ๊ณ„ ์ถ”๋ก  ํ”„๋กœ์„ธ์Šค** - **๋‹จ๊ณ„ ๊ฐ„ ์ƒํƒœ ์ง€์†์ด ํ•„์š”ํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜** -- **๊ฒฐ์ •์  ๋กœ์ง๊ณผ AI ๊ธฐ๋Šฅ์„ ๊ฒฐํ•ฉํ•˜๋Š” ์‹œ์Šคํ…œ** -- **์‚ฌ๋žŒ ๊ฐœ์ž…์ด ํ•„์š”ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ** +- **๊ฒฐ์ •๋ก ์  ๋กœ์ง๊ณผ AI ๊ธฐ๋Šฅ์„ ๊ฒฐํ•ฉํ•˜๋Š” ์‹œ์Šคํ…œ** +- **์‚ฌ๋žŒ์˜ ๊ฐœ์ž…์ด ํ•„์š”ํ•œ ์›Œํฌํ”Œ๋กœ์šฐ** - **์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๋ณต์žกํ•œ ์—์ด์ „ํŠธ ์•„ํ‚คํ…์ฒ˜** -๋ณธ์งˆ์ ์œผ๋กœ, ๊ฐ€๋Šฅํ•  ๋•Œ๋งˆ๋‹ค **์‚ฌ๋žŒ์œผ๋กœ์„œ** ๊ฐ ์•ก์…˜์˜ ์ถœ๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์•ก์…˜ ํ๋ฆ„์„ ์„ค๊ณ„ํ•˜๊ณ , ๊ทธ์— ๋”ฐ๋ผ ๋‹ค์Œ์— ์‹คํ–‰ํ•  ๊ฒƒ์„ ๊ฒฐ์ •ํ•˜์„ธ์š”. ์ด ๊ฒฝ์šฐ LangGraph๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค! +์š”์•ฝํ•˜์ž๋ฉด, ์ตœ๋Œ€ํ•œ **์‚ฌ๋žŒ์ด ์ง์ ‘** ๊ฐ ๋‹จ๊ณ„์˜ ์ถœ๋ ฅ์— ๋”ฐ๋ผ ์‹คํ–‰ํ•  ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์„ค๊ณ„ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, LangGraph๊ฐ€ ๊ฐ€์žฅ ์ ์ ˆํ•ฉ๋‹ˆ๋‹ค! `LangGraph`๋Š” ์ œ ์ƒ๊ฐ์— ์‹œ์žฅ์—์„œ ๊ฐ€์žฅ ํ”„๋กœ๋•์…˜ ์ค€๋น„๊ฐ€ ์ž˜ ๋œ ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. -## LangGraph๋Š” ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”? +## LangGraph๋Š” ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”? [[how-does-langgraph-work]] -ํ•ต์‹ฌ์ ์œผ๋กœ `LangGraph`๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ๋ฆ„์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: +`LangGraph`๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ๋ฆ„์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: -- **๋…ธ๋“œ**๋Š” ๊ฐœ๋ณ„ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค(LLM ํ˜ธ์ถœ, ํˆด ์‚ฌ์šฉ, ๊ฒฐ์ • ๋‚ด๋ฆฌ๊ธฐ ๋“ฑ). -- **์—ฃ์ง€**๋Š” ๋‹จ๊ณ„ ๊ฐ„ ๊ฐ€๋Šฅํ•œ ์ „ํ™˜์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. -- **์ƒํƒœ**๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•˜๊ณ  ์œ ์ง€ํ•˜๋ฉฐ ์‹คํ–‰ ์ค‘ ๋…ธ๋“œ ๊ฐ„์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์— ์–ด๋–ค ๋…ธ๋“œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ• ์ง€ ๊ฒฐ์ •ํ•  ๋•Œ, ์šฐ๋ฆฌ๊ฐ€ ์‚ดํŽด๋ณด๋Š” ๊ฒƒ์€ ํ˜„์žฌ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. +- **๋…ธ๋“œ(Node)**๋Š” ๊ฐ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค(LLM ํ˜ธ์ถœ, ๋„๊ตฌ ์‚ฌ์šฉ, ์˜์‚ฌ๊ฒฐ์ • ๋“ฑ). +- **์—ฃ์ง€(Edge)**๋Š” ๋‹จ๊ณ„ ๊ฐ„ ๊ฐ€๋Šฅํ•œ ์ „ํ™˜์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. +- **์ƒํƒœ(State)**๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•˜๊ณ  ์œ ์ง€ํ•˜๋ฉฐ ์‹คํ–‰ ์ค‘ ๋…ธ๋“œ ๊ฐ„์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์— ์–ด๋–ค ๋…ธ๋“œ๋ฅผ ์‹คํ–‰ํ• ์ง€ ๊ฒฐ์ •ํ•  ๋•Œ, ํ˜„์žฌ ์ƒํƒœ๊ฐ€ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค. -์ด๋Ÿฌํ•œ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ๋“ค์„ ๋‹ค์Œ ์žฅ์—์„œ ๋” ์ž์„ธํžˆ ํƒ๊ตฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! +์ด๋Ÿฌํ•œ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ๋“ค์€ ๋‹ค์Œ ์žฅ์—์„œ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! -## ์ผ๋ฐ˜ ํŒŒ์ด์ฌ๊ณผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”? ์™œ LangGraph๊ฐ€ ํ•„์š”ํ•œ๊ฐ€์š”? +## ์ผ๋ฐ˜ ํŒŒ์ด์ฌ๊ณผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”? ์™œ LangGraph๊ฐ€ ํ•„์š”ํ•œ๊ฐ€์š”? [[how-is-it-different-from-regular-python-why-do-i-need-langgraph]] -"์ด ๋ชจ๋“  ํ๋ฆ„์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด if-else ๋ฌธ์ด ์žˆ๋Š” ์ผ๋ฐ˜ ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์ง€ ์•Š๋‚˜์š”?"๋ผ๊ณ  ๊ถ๊ธˆํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +"๊ทธ๋ƒฅ ์ผ๋ฐ˜ ํŒŒ์ด์ฌ ๋ฌธ๋ฒ•์œผ๋กœ if-else ๋ฌธ ์“ฐ๋ฉด ๋˜์ง€ ์•Š๋‚˜์š”?"๋ผ๊ณ  ๊ถ๊ธˆํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ๋งž์ง€๋งŒ, LangGraph๋Š” ๋ณต์žกํ•œ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์„ ์œ„ํ•ด ์ผ๋ฐ˜ ํŒŒ์ด์ฌ๋ณด๋‹ค **์ผ๋ถ€ ์žฅ์ **์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. LangGraph ์—†์ด๋„ ๊ฐ™์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋” ์‰ฌ์šด ๋„๊ตฌ์™€ ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, LangGraph๋Š” ๋ณต์žกํ•œ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์„ ์œ„ํ•ด ์ผ๋ฐ˜ ํŒŒ์ด์ฌ๋ณด๋‹ค **์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žฅ์ **์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. LangGraph ์—†์ด๋„ ๋™์ผํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, LangGraph๋Š” ๋” ์‰ฝ๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ์™€ ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -์ƒํƒœ, ์‹œ๊ฐํ™”, ๋กœ๊น…(ํŠธ๋ ˆ์ด์Šค), ๋‚ด์žฅ๋œ ์‚ฌ๋žŒ ๊ฐœ์ž… ๋“ฑ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. +์˜ˆ: ์ƒํƒœ ๊ด€๋ฆฌ, ์‹œ๊ฐํ™”, ๋กœ๊น…(ํŠธ๋ ˆ์ด์Šค), ๋‚ด์žฅํ˜• ์‚ฌ์šฉ์ž ๊ฐœ์ž… ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ ๋“ฑ.