병렬 에이전트¶
ParallelAgent
는 하위 에이전트를 동시에 실행하는 워크플로 에이전트입니다. 이는 작업이 독립적으로 수행될 수 있는 워크플로의 속도를 극적으로 향상시킵니다.
ParallelAgent
사용 시기: 속도를 우선시하고 독립적이며 리소스 집약적인 작업이 포함된 시나리오의 경우, ParallelAgent
는 효율적인 병렬 실행을 용이하게 합니다. 하위 에이전트가 종속성 없이 작동할 때, 해당 작업은 동시에 수행될 수 있으며, 전체 처리 시간을 크게 단축합니다.
다른 워크플로 에이전트와 마찬가지로, ParallelAgent
는 LLM으로 구동되지 않으므로 실행 방식이 결정론적입니다. 즉, 워크플로 에이전트는 실행(즉, 하위 에이전트를 병렬로 실행)에만 관련이 있으며 내부 로직에는 관련이 없습니다. 워크플로 에이전트의 도구나 하위 에이전트는 LLM을 활용할 수도 있고 그렇지 않을 수도 있습니다.
예제¶
이 접근 방식은 다중 소스 데이터 검색이나 과도한 계산과 같은 작업에 특히 유용하며, 병렬화는 상당한 성능 향상을 가져옵니다. 중요하게도, 이 전략은 동시에 실행되는 에이전트 간에 공유 상태나 직접적인 정보 교환이 필요 없다고 가정합니다.
작동 방식¶
ParallelAgent
의 run_async()
메서드가 호출되면:
- 동시 실행:
sub_agents
목록에 있는 각 하위 에이전트의run_async()
메서드를 동시에 시작합니다. 이는 모든 에이전트가 (거의) 동시에 실행되기 시작한다는 의미입니다. - 독립적인 분기: 각 하위 에이전트는 자체 실행 분기에서 작동합니다. 실행 중에는 이러한 분기 간에 대화 기록이나 상태가 자동으로 공유되지 않습니다.
- 결과 수집:
ParallelAgent
는 병렬 실행을 관리하며, 일반적으로 각 하위 에이전트가 완료된 후 결과를 접근할 수 있는 방법을 제공합니다(예: 결과 또는 이벤트 목록을 통해). 결과의 순서는 결정론적이지 않을 수 있습니다.
독립적인 실행 및 상태 관리¶
ParallelAgent
내의 하위 에이전트는 독립적으로 실행된다는 것을 이해하는 것이 중요합니다. 이러한 에이전트 간의 통신이나 데이터 공유가 필요하다면 명시적으로 구현해야 합니다. 가능한 접근 방식은 다음과 같습니다:
- 공유
InvocationContext
: 각 하위 에이전트에 공유InvocationContext
객체를 전달할 수 있습니다. 이 객체는 공유 데이터 저장소 역할을 할 수 있습니다. 그러나 경쟁 조건을 피하기 위해 이 공유 컨텍스트에 대한 동시 접근을 신중하게 관리해야 합니다(예: 잠금 사용). - 외부 상태 관리: 외부 데이터베이스, 메시지 큐 또는 기타 메커니즘을 사용하여 공유 상태를 관리하고 에이전트 간의 통신을 용이하게 합니다.
- 후처리: 각 분기에서 결과를 수집한 다음, 데이터를 조정하기 위한 로직을 구현합니다.
전체 예제: 병렬 웹 리서치¶
여러 주제를 동시에 연구하는 것을 상상해 보세요:
- 연구원 에이전트 1: "재생 가능 에너지원"을 연구하는
LlmAgent
입니다. - 연구원 에이전트 2: "전기 자동차 기술"을 연구하는
LlmAgent
입니다. -
연구원 에이전트 3: "탄소 포집 방법"을 연구하는
LlmAgent
입니다.
이러한 연구 작업은 독립적입니다. ParallelAgent
를 사용하면 순차적으로 실행하는 것과 비교하여 총 연구 시간을 크게 단축할 수 있습니다. 각 에이전트의 결과는 완료된 후 별도로 수집됩니다.
전체 코드
# Part of agent.py --> Follow https://google.github.io/adk-docs/get-started/quickstart/ to learn the setup
# --- 1. Define Researcher Sub-Agents (to run in parallel) ---
# Researcher 1: Renewable Energy
researcher_agent_1 = LlmAgent(
name="RenewableEnergyResearcher",
model=GEMINI_MODEL,
instruction="""You are an AI Research Assistant specializing in energy.
Research the latest advancements in 'renewable energy sources'.
Use the Google Search tool provided.
Summarize your key findings concisely (1-2 sentences).
Output *only* the summary.
""",
description="Researches renewable energy sources.",
tools=[google_search],
# Store result in state for the merger agent
output_key="renewable_energy_result"
)
# Researcher 2: Electric Vehicles
researcher_agent_2 = LlmAgent(
name="EVResearcher",
model=GEMINI_MODEL,
instruction="""You are an AI Research Assistant specializing in transportation.
Research the latest developments in 'electric vehicle technology'.
Use the Google Search tool provided.
Summarize your key findings concisely (1-2 sentences).
Output *only* the summary.
""",
description="Researches electric vehicle technology.",
tools=[google_search],
# Store result in state for the merger agent
output_key="ev_technology_result"
)
# Researcher 3: Carbon Capture
researcher_agent_3 = LlmAgent(
name="CarbonCaptureResearcher",
model=GEMINI_MODEL,
instruction="""You are an AI Research Assistant specializing in climate solutions.
Research the current state of 'carbon capture methods'.
Use the Google Search tool provided.
Summarize your key findings concisely (1-2 sentences).
Output *only* the summary.
""",
description="Researches carbon capture methods.",
tools=[google_search],
# Store result in state for the merger agent
output_key="carbon_capture_result"
)
# --- 2. Create the ParallelAgent (Runs researchers concurrently) ---
# This agent orchestrates the concurrent execution of the researchers.
# It finishes once all researchers have completed and stored their results in state.
parallel_research_agent = ParallelAgent(
name="ParallelWebResearchAgent",
sub_agents=[researcher_agent_1, researcher_agent_2, researcher_agent_3],
description="Runs multiple research agents in parallel to gather information."
)
# --- 3. Define the Merger Agent (Runs *after* the parallel agents) ---
# This agent takes the results stored in the session state by the parallel agents
# and synthesizes them into a single, structured response with attributions.
merger_agent = LlmAgent(
name="SynthesisAgent",
model=GEMINI_MODEL, # Or potentially a more powerful model if needed for synthesis
instruction="""You are an AI Assistant responsible for combining research findings into a structured report.
Your primary task is to synthesize the following research summaries, clearly attributing findings to their source areas. Structure your response using headings for each topic. Ensure the report is coherent and integrates the key points smoothly.
**Crucially: Your entire response MUST be grounded *exclusively* on the information provided in the 'Input Summaries' below. Do NOT add any external knowledge, facts, or details not present in these specific summaries.**
**Input Summaries:**
* **Renewable Energy:**
{renewable_energy_result}
* **Electric Vehicles:**
{ev_technology_result}
* **Carbon Capture:**
{carbon_capture_result}
**Output Format:**
## Summary of Recent Sustainable Technology Advancements
### Renewable Energy Findings
(Based on RenewableEnergyResearcher's findings)
[Synthesize and elaborate *only* on the renewable energy input summary provided above.]
### Electric Vehicle Findings
(Based on EVResearcher's findings)
[Synthesize and elaborate *only* on the EV input summary provided above.]
### Carbon Capture Findings
(Based on CarbonCaptureResearcher's findings)
[Synthesize and elaborate *only* on the carbon capture input summary provided above.]
### Overall Conclusion
[Provide a brief (1-2 sentence) concluding statement that connects *only* the findings presented above.]
Output *only* the structured report following this format. Do not include introductory or concluding phrases outside this structure, and strictly adhere to using only the provided input summary content.
""",
description="Combines research findings from parallel agents into a structured, cited report, strictly grounded on provided inputs.",
# No tools needed for merging
# No output_key needed here, as its direct response is the final output of the sequence
)
# --- 4. Create the SequentialAgent (Orchestrates the overall flow) ---
# This is the main agent that will be run. It first executes the ParallelAgent
# to populate the state, and then executes the MergerAgent to produce the final output.
sequential_pipeline_agent = SequentialAgent(
name="ResearchAndSynthesisPipeline",
# Run parallel research first, then merge
sub_agents=[parallel_research_agent, merger_agent],
description="Coordinates parallel research and synthesizes the results."
)
root_agent = sequential_pipeline_agent
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.ParallelAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.events.Event;
import com.google.adk.runner.InMemoryRunner;
import com.google.adk.sessions.Session;
import com.google.adk.tools.GoogleSearchTool;
import com.google.genai.types.Content;
import com.google.genai.types.Part;
import io.reactivex.rxjava3.core.Flowable;
public class ParallelResearchPipeline {
private static final String APP_NAME = "parallel_research_app";
private static final String USER_ID = "research_user_01";
private static final String GEMINI_MODEL = "gemini-2.0-flash";
// Assume google_search is an instance of the GoogleSearchTool
private static final GoogleSearchTool googleSearchTool = new GoogleSearchTool();
public static void main(String[] args) {
String query = "Summarize recent sustainable tech advancements.";
SequentialAgent sequentialPipelineAgent = initAgent();
runAgent(sequentialPipelineAgent, query);
}
public static SequentialAgent initAgent() {
// --- 1. Define Researcher Sub-Agents (to run in parallel) ---
// Researcher 1: Renewable Energy
LlmAgent researcherAgent1 = LlmAgent.builder()
.name("RenewableEnergyResearcher")
.model(GEMINI_MODEL)
.instruction("""
You are an AI Research Assistant specializing in energy.
Research the latest advancements in 'renewable energy sources'.
Use the Google Search tool provided.
Summarize your key findings concisely (1-2 sentences).
Output *only* the summary.
""")
.description("Researches renewable energy sources.")
.tools(googleSearchTool)
.outputKey("renewable_energy_result") // Store result in state
.build();
// Researcher 2: Electric Vehicles
LlmAgent researcherAgent2 = LlmAgent.builder()
.name("EVResearcher")
.model(GEMINI_MODEL)
.instruction("""
You are an AI Research Assistant specializing in transportation.
Research the latest developments in 'electric vehicle technology'.
Use the Google Search tool provided.
Summarize your key findings concisely (1-2 sentences).
Output *only* the summary.
""")
.description("Researches electric vehicle technology.")
.tools(googleSearchTool)
.outputKey("ev_technology_result") // Store result in state
.build();
// Researcher 3: Carbon Capture
LlmAgent researcherAgent3 = LlmAgent.builder()
.name("CarbonCaptureResearcher")
.model(GEMINI_MODEL)
.instruction("""
You are an AI Research Assistant specializing in climate solutions.
Research the current state of 'carbon capture methods'.
Use the Google Search tool provided.
Summarize your key findings concisely (1-2 sentences).
Output *only* the summary.
""")
.description("Researches carbon capture methods.")
.tools(googleSearchTool)
.outputKey("carbon_capture_result") // Store result in state
.build();
// --- 2. Create the ParallelAgent (Runs researchers concurrently) ---
// This agent orchestrates the concurrent execution of the researchers.
// It finishes once all researchers have completed and stored their results in state.
ParallelAgent parallelResearchAgent =
ParallelAgent.builder()
.name("ParallelWebResearchAgent")
.subAgents(researcherAgent1, researcherAgent2, researcherAgent3)
.description("Runs multiple research agents in parallel to gather information.")
.build();
// --- 3. Define the Merger Agent (Runs *after* the parallel agents) ---
// This agent takes the results stored in the session state by the parallel agents
// and synthesizes them into a single, structured response with attributions.
LlmAgent mergerAgent =
LlmAgent.builder()
.name("SynthesisAgent")
.model(GEMINI_MODEL)
.instruction(
"""
You are an AI Assistant responsible for combining research findings into a structured report.
Your primary task is to synthesize the following research summaries, clearly attributing findings to their source areas. Structure your response using headings for each topic. Ensure the report is coherent and integrates the key points smoothly.
**Crucially: Your entire response MUST be grounded *exclusively* on the information provided in the 'Input Summaries' below. Do NOT add any external knowledge, facts, or details not present in these specific summaries.**
**Input Summaries:**
* **Renewable Energy:**
{renewable_energy_result}
* **Electric Vehicles:**
{ev_technology_result}
* **Carbon Capture:**
{carbon_capture_result}
**Output Format:**
## Summary of Recent Sustainable Technology Advancements
### Renewable Energy Findings
(Based on RenewableEnergyResearcher's findings)
[Synthesize and elaborate *only* on the renewable energy input summary provided above.]
### Electric Vehicle Findings
(Based on EVResearcher's findings)
[Synthesize and elaborate *only* on the EV input summary provided above.]
### Carbon Capture Findings
(Based on CarbonCaptureResearcher's findings)
[Synthesize and elaborate *only* on the carbon capture input summary provided above.]
### Overall Conclusion
[Provide a brief (1-2 sentence) concluding statement that connects *only* the findings presented above.]
Output *only* the structured report following this format. Do not include introductory or concluding phrases outside this structure, and strictly adhere to using only the provided input summary content.
""")
.description(
"Combines research findings from parallel agents into a structured, cited report, strictly grounded on provided inputs.")
// No tools needed for merging
// No output_key needed here, as its direct response is the final output of the sequence
.build();
// --- 4. Create the SequentialAgent (Orchestrates the overall flow) ---
// This is the main agent that will be run. It first executes the ParallelAgent
// to populate the state, and then executes the MergerAgent to produce the final output.
SequentialAgent sequentialPipelineAgent =
SequentialAgent.builder()
.name("ResearchAndSynthesisPipeline")
// Run parallel research first, then merge
.subAgents(parallelResearchAgent, mergerAgent)
.description("Coordinates parallel research and synthesizes the results.")
.build();
return sequentialPipelineAgent;
}
public static void runAgent(SequentialAgent sequentialPipelineAgent, String query) {
// Create an InMemoryRunner
InMemoryRunner runner = new InMemoryRunner(sequentialPipelineAgent, APP_NAME);
// InMemoryRunner automatically creates a session service. Create a session using the service
Session session = runner.sessionService().createSession(APP_NAME, USER_ID).blockingGet();
Content userMessage = Content.fromParts(Part.fromText(query));
// Run the agent
Flowable<Event> eventStream = runner.runAsync(USER_ID, session.id(), userMessage);
// Stream event response
eventStream.blockingForEach(
event -> {
if (event.finalResponse()) {
System.out.printf("Event Author: %s \n Event Response: %s \n\n\n", event.author(), event.stringifyContent());
}
});
}
}