์์ด์ ํธ ์ต์ ํ¶
ADK๋ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ด์ ํธ๋ฅผ ์๋์ผ๋ก ์ต์ ํํ ์ ์๋ ํ์ฅ ๊ฐ๋ฅํ ํ๋ ์์ํฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก adk optimize ๋ช
๋ น์ ์ฌ์ฉํด, ๊ธฐ๋ณธ ์ตํฐ๋ง์ด์ ๋ก ADK ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ๋จํ ์์ด์ ํธ๋ฅผ ๋น ๋ฅด๊ฒ ์ต์ ํํ ์ ์์ต๋๋ค.
๋ ๋ณต์กํ ์ฌ์ฉ ์ฌ๋ก์์๋ ์ฌ์ฉ์ ์ง์ eval ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ์ํ๋ฌ๋ฅผ ๊ฐ๋ฐํ๊ฑฐ๋, ์๋ก์ด ์ต์ ํ ์ ๋ต์ ์ง์ ๊ตฌํํ ์ ์์ต๋๋ค.
์ ์¶
- ์ํ๋ฌ: ์ํ๋ฌ๋ ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๊ฐ ํ๋ณด ์ต์ ํ ์์ด์ ํธ๋ฅผ ํ๊ฐํ ์ ์๊ฒ ํฉ๋๋ค. ์์ฒญ์ด ์์ ๋ ์ํ๋ฌ๋ eval ๊ธฐ๋ฐ ์์ด์ ํธ ์ต์ ํ์ ์ ์ฉํ ์์ธ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ์ตํฐ๋ง์ด์ ์ ์ ๊ณตํฉ๋๋ค.
- ์์ด์ ํธ ์ตํฐ๋ง์ด์ : ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๋ ์ํ๋ฌ์ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ฒํ ํ๊ณ ์ด๋ฅผ ์ฌ์ฉํด ์์ด์ ํธ๋ฅผ ๊ฐ์ ํฉ๋๋ค.
์์ - adk optimize๋ก ๊ฐ๋จํ ์์ด์ ํธ ์ต์ ํํ๊ธฐ¶
์ด ์์์์๋ ์์ eval ์ธํธ์ ๋ํ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ์ผ๋ก hello_world ์ํ ์์ด์ ํธ์ ์ง์นจ์ ์
๋ฐ์ดํธํ๊ธฐ ์ํด adk optimize ๋ช
๋ น์ ์ฌ์ฉํฉ๋๋ค.
1๋จ๊ณ: ์์ ๋ฐ์ดํฐ์ ์ง์ ํ๊ธฐ¶
๊ธฐ๋ณธ hello_world ์์ด์ ํธ ์ง์นจ์ ์ซ์๊ฐ ์์์ธ์ง ํ๋ณํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช
ํฉ๋๋ค.
์ด ์์์ eval ์ธํธ์๋ ์์ด์ ํธ์๊ฒ ์ง์ํ์ง ์์ ๋ ๋ค๋ฅธ ์ธก๋ฉด์ด ์ถ๊ฐ๋ฉ๋๋ค. ์ซ์๋ ์์ ์ฌ๋ถ์ ๋ฐ๋ผ "good" ๋๋ "bad"๊ฐ ๋ ์ ์์ต๋๋ค.
์ตํฐ๋ง์ด์ ๋ ์ด ์๋ก์ด ๊ท์น์ ๋์ถํด ์์ด์ ํธ ์ง์นจ์ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
contributing/samples/hello_world/์ train_eval_set.evalset.json ํ์ผ์ ๋ง๋ค๊ณ ๋ค์ ๋ด์ฉ์ ๋ฃ์ต๋๋ค.
{
"eval_set_id": "train_eval_set",
"name": "train_eval_set",
"eval_cases": [
{
"eval_id": "simple",
"conversation": [
{
"invocation_id": "inv1",
"user_content": {
"parts": [ {"text": "Is 7 prime?"} ],
"role": "user"
},
"final_response": {
"parts": [ {"text": "7 is a prime number."} ],
"role": "model"
}
}
],
"session_input": {
"app_name": "hello_world",
"user_id": "user"
}
},
{
"eval_id": "is_good",
"conversation": [
{
"invocation_id": "inv1",
"user_content": {
"parts": [ {"text": "Is 4 a bad number?"} ],
"role": "user"
},
"final_response": {
"parts": [ {"text": "4 is not prime so it is a good number."} ],
"role": "model"
}
}
],
"session_input": {
"app_name": "hello_world",
"user_id": "user"
}
},
{
"eval_id": "is_bad",
"conversation": [
{
"invocation_id": "inv1",
"user_content": {
"parts": [ {"text": "Is 5 a bad number?"} ],
"role": "user"
},
"final_response": {
"parts": [ {"text": "5 is prime so it is a bad number."} ],
"role": "model"
}
}
],
"session_input": {
"app_name": "hello_world",
"user_id": "user"
}
}
]
}
2๋จ๊ณ: ์ํ๋ฌ ๊ตฌ์ฑ ์ ์ํ๊ธฐ¶
์ํ๋ฌ ๊ตฌ์ฑ์ ํ๋ณด ์ต์ ํ ์์ด์ ํธ๋ฅผ ํ๊ฐํ๋ ๊ณผ์ ์ ์ ์ดํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์์ด์ ํธ ์ถ๋ ฅ์ ์ ๋ต ๊ธฐ์ค์ ์ง์ ํ๊ณ , ์์ด์ ํธ๋ฅผ ์ต์ ํํ ๋ ์ฌ์ฉํ eval ์ธํธ๋ ์ง์ ํฉ๋๋ค.
์ ์ฒด ๊ตฌ์ฑ ์ต์
๋ชฉ๋ก์ ์๋์์ ํ์ธํ ์ ์์ต๋๋ค. ์ง๊ธ์ contributing/samples/hello_world/์ sampler_config.json ํ์ผ์ ๋ค์ ๋ด์ฉ์ผ๋ก ๋ง๋ค๋ฉด ๋ฉ๋๋ค.
{
"eval_config": {
"criteria": {
"response_match_score": 0.75
}
},
"app_name": "hello_world",
"train_eval_set": "train_eval_set"
}
3๋จ๊ณ: ์ต์ ํ ์์ ์คํํ๊ธฐ¶
adk optimize ๋ช
๋ น์ ์คํํ๋ฉด์, hello_world ์์ด์ ํธ ๋๋ ํฐ๋ฆฌ๋ฅผ ์ง์ ํ๊ณ ์์์ ๋ง๋ ๊ตฌ์ฑ ํ์ผ์ ์ ๋ฌํฉ๋๋ค.
adk optimize contributing/samples/hello_world \
--sampler_config_file_path contributing/samples/hello_world/sampler_config.json
์ต์ข ์ถ๋ ฅ์ ๋ฌ๋ผ์ง ์ ์์ง๋ง, ๋ค์๊ณผ ๋น์ทํ ์ ์์ต๋๋ค.
<logs and intermediate output>
================================================================================
Optimized root agent instructions:
--------------------------------------------------------------------------------
<existing unmodified instructions omitted for brevity>
**Special Rules for "Good" and "Bad" Numbers:**
* A "bad number" is defined as a prime number.
* A "good number" is defined as a non-prime number (i.e., a composite number or 1).
* If a user asks if a number is "good" or "bad", you must always use the `check_prime` tool to determine its primality first.
* After determining primality with the tool, respond according to the definitions above. Questions about "good" or "bad" numbers, when referring to primality, are objective and you are fully capable of answering them. Do not state you cannot answer such questions.
================================================================================
adk optimize ๋ช
๋ น ์ฌ์ฉํ๊ธฐ¶
AGENT_MODULE_FILE_PATH: ํ์ผ์ด ์๋ ์์ด์ ํธ ๋๋ ํ ๋ฆฌ์ ๊ฒฝ๋ก๋ก, ํด๋น ๋๋ ํ ๋ฆฌ์__init__.py๊ฐagent๋ผ๋ ์ด๋ฆ์ ๋ชจ๋์ ๋ ธ์ถํฉ๋๋ค.agent๋ชจ๋์๋ ๋ฐ๋์root_agent๊ฐ ์์ด์ผ ํฉ๋๋ค. ์ฌ๋ฐ๋ฅธ ์ค์ ์์๋hello_world์์ด์ ํธ๋ฅผ ์ฐธ๊ณ ํ์ธ์.--sampler_config_file_path PATH: ์ํ๋ฌ ๊ตฌ์ฑ ํ์ผ ๊ฒฝ๋ก์ ๋๋ค. ์ํ๋ฌ ๊ตฌํ๊ณผ ๊ตฌ์ฑ ํ์์ ์๋์์ ์ค๋ช ํฉ๋๋ค.--optimizer_config_file_path PATH(์ ํ): ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๊ตฌ์ฑ ํ์ผ ๊ฒฝ๋ก์ ๋๋ค. ์ง์ ํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ ๊ตฌ์ฑ์ ์ฌ์ฉํฉ๋๋ค. ์ตํฐ๋ง์ด์ ๊ตฌํ, ๊ตฌ์ฑ ํ์, ๊ธฐ๋ณธ ๊ตฌ์ฑ์ ์๋์์ ์ค๋ช ํฉ๋๋ค.--print_detailed_results(์ ํ): ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๊ฐ ์ธก์ ํ ์ธ๋ถ ๋ฉํธ๋ฆญ ์ถ๋ ฅ์ ํ์ฑํํฉ๋๋ค.--log_level(์ ํ): ๋ก๊น ์์ค์ ์ค์ ํฉ๋๋ค. ๊ธฐ๋ณธ๊ฐ์INFO์ ๋๋ค. ์ฌ์ฉ ๊ฐ๋ฅํ ์ต์ ์DEBUG,INFO,WARNING,ERROR,CRITICAL์ ๋๋ค.
ADK๋ adk optimize ๋ช ๋ น์ค์ ์ฌ์ฉํ์ฌ ์คํํ ์ ์๋ ๋ช ๊ฐ์ง ์ํ๋ฌ์ ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ฌ์ฉ ๊ฐ๋ฅํ ์ต์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
LocalEvalSampler¶
LocalEvalSampler๋ ADK์ LocalEvalService๋ฅผ ์ฌ์ฉํด ํ๋ณด ์์ด์ ํธ๋ฅผ ํ๊ฐํฉ๋๋ค.
ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ UnstructuredSamplingResult๋ก ์ ๊ณตํฉ๋๋ค.
LocalEvalSampler๋ ๋ค์ ํ๋๋ฅผ ํฌํจํ๋ LocalEvalSamplerConfig๋ก ์ค์ ํ ์ ์์ต๋๋ค.
eval_config: ํ๊ฐ ๊ธฐ์ค๊ณผ ์ฌ์ฉ์ ์๋ฎฌ๋ ์ด์ ์ต์ ์ ์ ๊ณตํ๋EvalConfig์ ๋๋ค.app_name: ํ๊ฐ์ ์ฌ์ฉํ ์ฑ ์ด๋ฆ์ ๋๋ค.train_eval_set: ์ต์ ํ์ ์ฌ์ฉํ eval ์ธํธ ์ด๋ฆ์ ๋๋ค.train_eval_case_ids(์ ํ): ์ต์ ํ์ ์ฌ์ฉํ eval case(example) ID ๋ชฉ๋ก์ ๋๋ค. ์ง์ ํ์ง ์์ผ๋ฉดtrain_eval_set์ ๋ชจ๋ eval case๋ฅผ ์ฌ์ฉํฉ๋๋ค.validation_eval_set(์ ํ): ์ต์ ํ๋ ์์ด์ ํธ๋ฅผ ๊ฒ์ฆํ๋ ๋ฐ ์ฌ์ฉํ eval ์ธํธ ์ด๋ฆ์ ๋๋ค. ์ง์ ํ์ง ์์ผ๋ฉดtrain_eval_set์ ์ฌ์ฌ์ฉํฉ๋๋ค.validation_eval_case_ids(์ ํ): ์ต์ ํ๋ ์์ด์ ํธ๋ฅผ ๊ฒ์ฆํ๋ ๋ฐ ์ฌ์ฉํ eval case(example) ID ๋ชฉ๋ก์ ๋๋ค. ์ง์ ํ์ง ์์ผ๋ฉดvalidation_eval_set์ ๋ชจ๋ eval case๋ฅผ ์ฌ์ฉํฉ๋๋ค.validation_eval_set๋ ์ง์ ํ์ง ์์ผ๋ฉด ์ ํจํ train eval case๋ฅผ ์ฌ์ฌ์ฉํฉ๋๋ค.
LocalEvalSampler๋ฅผ ์ด๊ธฐํํ ๋, LocalEvalSamplerConfig์ ์ง์ ๋ train ๋ฐ validation eval ์ธํธ์ ์ ๊ทผํ ์ ์๋ EvalSetsManager๋ ์ ๊ณตํด์ผ ํฉ๋๋ค.
GEPARootAgentPromptOptimizer¶
GEPARootAgentPromptOptimizer๋ GEPA ์ตํฐ๋ง์ด์ ๋ฅผ ์ฌ์ฉํด ๋ฃจํธ ์์ด์ ํธ์ ์ง์นจ์ ๊ฐ์ ํฉ๋๋ค.
์ด ์ตํฐ๋ง์ด์ ๋ ์ํ๋ฌ๊ฐ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ UnstructuredSamplingResult๋ก ์ ๊ณตํ ๊ฒ์ผ๋ก ๊ธฐ๋ํฉ๋๋ค.
์ถ๋ ฅ์ OptimizerResult์ ํ์ ํด๋์ค์ด๋ฉฐ, ์ ์๊ฐ ํฌํจ๋ ์ต์ ํ ์์ด์ ํธ ๋ชฉ๋ก๊ณผ ์ต์ ํ ์ค ์์ง๋ ์ถ๊ฐ ๋ฉํธ๋ฆญ์ ์ง์ ํฉ๋๋ค.
์ฐธ๊ณ : GEPARootAgentPromptOptimizer๋ ํ์ ์์ด์ ํธ, ์์ด์ ํธ ๋๊ตฌ, ์คํฌ ๋๋ ๋ฃจํธ ์์ด์ ํธ์ ๋ค๋ฅธ ์ธก๋ฉด์ ๊ฐ์ ํ์ง ์์ต๋๋ค.
GEPARootAgentPromptOptimizer๋ ๋ค์ ํ๋๋ฅผ ํฌํจํ๋ GEPARootAgentPromptOptimizerConfig๋ก ์ค์ ํ ์ ์์ต๋๋ค.
optimizer_model(์ ํ): ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ถ์ํ๊ณ ์์ด์ ํธ๋ฅผ ์ต์ ํํ๋ ๋ฐ ์ฌ์ฉํ๋ ๋ชจ๋ธ์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์"gemini-flash-latest"์ ๋๋ค.model_configuration(์ ํ): ์ตํฐ๋ง์ด์ ๋ชจ๋ธ์ ๊ตฌ์ฑ์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ 1๋ง ํ ํฐ think budget์ ๊ฐ์ง ๊ตฌ์ฑ์ ๋๋ค.max_metric_calls(์ ํ): ์ต์ ํ ์ค ์คํํ ํ๊ฐ์ ์ต๋ ํ์์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ 100์ ๋๋ค.reflection_minibatch_size(์ ํ): ํ ๋ฒ์ ์์ด์ ํธ ์ง์นจ์ ์ ๋ฐ์ดํธํ ๋ ์ฌ์ฉํ ์์ ์์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ 3์ ๋๋ค.run_dir(์ ํ): ์ํ๋ฉด ์ค๊ฐ ๋ฐ ์ต์ข ์ต์ ํ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ ๋๋ ํฐ๋ฆฌ์ ๋๋ค. ์ ์คํํธ๋ฅผ ์ง์ํฉ๋๋ค.
SimplePromptOptimizer¶
SimplePromptOptimizer๋ ์ค์ฆ์ ์ธ ํ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ด์ ํธ์ ๋ฃจํธ ์์คํ
์ง์นจ(instructions)์ ์ฒด๊ณ์ ์ผ๋ก ๊ฐ์ ํ๋๋ก ์ค๊ณ๋ ์๋ํ๋ ๋ฐ๋ณต์ ํ๋กฌํํธ ํ๋ ๊ตฌ์ฑ ์์์
๋๋ค. ์ฌ๋ฌ ํ๋ณด ์์ด์ ํธ์ ๋ค์ํ ํ๋ ํ ํ๋ฐํฐ์ด(Pareto frontier)๋ฅผ ์ ์งํ๋ GEPA ๊ธฐ๋ฐ ์ตํฐ๋ง์ด์ ์ ๋ฌ๋ฆฌ, SimplePromptOptimizer๋ ์ง์ ๋ ์ผ๋ จ์ ๋ฐ๋ณต ํ์(iterations)์ ๊ฑธ์ณ ๋จ์ผ ๊ธฐ๋ณธ ํ๋กฌํํธ๋ฅผ ๊ฐ์ ํ๋ ๋ฐ ์์ ํ ์ง์คํ๋ ์ง์ ์ ์ด๊ณ ์์ฐจ์ ์ธ ์ต์ ํ ๋ฃจํ๋ฅผ ์คํํฉ๋๋ค.
์ตํฐ๋ง์ด์ ๋ ๋ค์ 4๋จ๊ณ์ ๋น๋๊ธฐ ํผ๋๋ฐฑ ๋ฃจํ๋ฅผ ์๋์ผ๋ก ์คํํฉ๋๋ค.
- ์คํ (Execute): ๋์ ์์ด์ ํธ๋
Samplerํด๋์ค์ ๊ตฌํ์ฒด์ ์ํด ๊ด๋ฆฌ๋๋ ํน์ ํ๊ฐ ์์ ๋ฐฐ์น๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. - ํ๊ฐ (Evaluate): ์ํ๋ฌ๋ ํ๊ฐ ๋ฐ์ดํฐ ์ธํธ์ ๋ํด ์์ด์ ํธ์ ์ถ๋ ฅ์ ์ฑ์ ํ๊ณ ๊ตฌ์กฐํ๋
SamplingResult๋ฅผ ๋ฐํํฉ๋๋ค. - ๋นํ (Critique): ๊ธฐ๋ณธ ์ต์ ํ ๋๊ท๋ชจ ์ธ์ด ๋ชจ๋ธ(LLM)(๊ธฐ๋ณธ๊ฐ์ Gemini-2.5-flash)์ด ํ์ฌ ํ๋กฌํํธ์ ํจ๊ป ๊ณผ๊ฑฐ ํ๊ฐ ์ ์๋ฅผ ๋ถ์ํ์ฌ ํน์ ๋์์์ ์ฝ์ ์ด๋ ๊ณต๋ฐฑ์ ์ฐพ์๋ ๋๋ค.
- ์ฌ์์ฑ (Rewrite): ์ต์ ํ ๋ชจ๋ธ์ ๋ฐ๊ฒฌ๋ ์ฝ์ ์ ํด๊ฒฐํ๋๋ก ๋ง์ถคํ๋ ์์คํ ํ๋กฌํํธ์ ์ ๋ฐ์ดํธ๋ ๋ณํ์ ์์ฑํฉ๋๋ค. ์ด ์๋ก์ด ํ๋กฌํํธ๋ ๋ค์ ๋ฐ๋ณต์ ์ง์ ์ ๋ ฅ๋ฉ๋๋ค.
์ฐธ๊ณ : ์ต์ ํ ๋ฃจํ๋ ๊ธฐ์กด ์์ด์ ํธ ์ธ์คํด์ค๋ฅผ ์ฆ์์์ ๋ณ๊ฒฝ(mutate)ํ์ง ์์ต๋๋ค. ์๋ฃ๋๋ฉด ํ๋ก์ธ์ค ์ค์ ์ถ์ถ๋ ๊ฐ์ฅ ๋์ ์ ์๋ฅผ ๋ฐ์ ์์ด์ ํธ ๋ณํ์ ํฌํจํ๋ OptimizerResult๋ฅผ ๋ฐํํฉ๋๋ค.
๊ตฌ์ฑ¶
SimplePromptOptimizerConfig ์ธ์คํด์ค๋ฅผ ์ตํฐ๋ง์ด์ ์ ์ ๋ฌํ์ฌ ๋ฃจํ์ ๋์์ ๊ตฌ์ฑํฉ๋๋ค.
| ๋งค๊ฐ๋ณ์ | ์ ํ | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|---|
num_iterations |
int | ํ์ | ์คํํ ์ต์ ํ ๋ผ์ด๋์ ์ด ํ์์ ๋๋ค. |
batch_size |
int | ํ์ | ๊ฐ ๊ฐ๋ณ ๋ฐ๋ณต ์ค์ ์ํ๋ฌ๊ฐ ์ฒ๋ฆฌํ๋ ํ๊ฐ ์ํ ์ผ์ด์ค์ ์์ ๋๋ค. |
๊ตฌํ ์์¶
๊ตฌ์ฑ์ด ์ ์๋๋ฉด ๋ค์ ์ฝ๋๋ก ์ต์ ํ๋ฅผ ์คํํฉ๋๋ค.
from google.adk.optimization.simple_prompt_optimizer import SimplePromptOptimizer
from google.adk.optimization.simple_prompt_optimizer import SimplePromptOptimizerConfig
# ์์ด์ ํธ์ ์ํ๋ฌ๋ฅผ ๋จผ์ ์ ์ํฉ๋๋ค...
# ์ตํฐ๋ง์ด์ ๊ตฌ์ฑ
config = SimplePromptOptimizerConfig(
num_iterations=5,
batch_size=10
)
# ์ต์ ํ ์คํ
optimizer = SimplePromptOptimizer(config=config)
optimized_result = await optimizer.optimize(agent, sampler)
ํต์ฌ ๋ฐ์ดํฐ ํ์ ¶
ADK๋ ์ํ๋ฌ์์ ์ตํฐ๋ง์ด์ ๋ก ํ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ํ๋ฆ๊ณผ ์ตํฐ๋ง์ด์ ์ถ๋ ฅ์ ๊ด๋ฆฌํ๊ธฐ ์ํด
optimization/data_types.py์ ๋ช ๊ฐ์ง ๊ธฐ๋ณธ ๋ฐ์ดํฐ ํ์
์ ์ ์ํฉ๋๋ค.
์ด ๋ฐ์ดํฐ ํ์
๋ค์ ์ฌ์ฉ์ ์ง์ eval๊ณผ ์ต์ ํ ์ ๋ต์ ์์ฉํ ์ ์๋๋ก ํ์ฅ ๊ฐ๋ฅํ๊ฒ ์ค๊ณ๋์ด ์์ต๋๋ค.
์ํ๋ฌ ๊ฒฐ๊ณผ¶
SamplingResult: ์ํ๋ฌ ์ถ๋ ฅ์ ๊ธฐ๋ณธ ํด๋์ค์ ๋๋ค.- example UID๋ฅผ ํด๋น ์์์ ๋ํ ์์ด์ ํธ์ ์ ์ฒด ์ ์์ ๋งคํํ๋
scores์ฌ์ ์ ํฌํจํด์ผ ํฉ๋๋ค. UnstructuredSamplingResult:SamplingResult์ ๋ด์ฅ ํ์ ํด๋์ค๋ก, ๊ถค์ , ์ค๊ฐ ์ถ๋ ฅ, ํ์ ๋ฉํธ๋ฆญ์ฒ๋ผ ๊ตฌ์กฐํ๋์ง ์์ ๊ฐ ์์๋ณ JSON ์ง๋ ฌํ ๊ฐ๋ฅํ ํ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ์ ์๋ ์ ํ์ dataํ๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.
๋๋ถ๋ถ์ ์ฌ์ฉ ์ฌ๋ก์์๋ UnstructuredSamplingResult๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋์ ๋ ๊ตฌ์กฐํ๋ ํ์์ผ๋ก ์ถ๊ฐ ํ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋๋ก SamplingResult์ ์์ฒด ํ์ ํด๋์ค๋ฅผ ๋ง๋ค ์๋ ์์ต๋๋ค.
๋ค๋ง ์ํ๋ฌ์ ์ตํฐ๋ง์ด์ ๊ฐ ๋ชจ๋ ํด๋น ํ์์ ์ง์ํด์ผ ํฉ๋๋ค.
์์ด์ ํธ ์ตํฐ๋ง์ด์ ๊ฒฐ๊ณผ¶
AgentWithScores: ์ ์ฒด ์ ์์ ํจ๊ป ๋จ์ผ ์ต์ ํ ์์ด์ ํธ๋ฅผ ๋ํ๋ ๋๋ค.- ์
๋ฐ์ดํธ๋
Agent๊ฐ์ฒด์ธoptimized_agent๋ฅผ ํฌํจํด์ผ ํฉ๋๋ค. - ๋ณดํต validation ์ธํธ์์ ๊ณ์ฐ๋ ์์ด์ ํธ์
overall_score๋ฅผ ํฌํจํ ์ ์์ต๋๋ค. OptimizerResult: ์ต์ ํ ํ๋ก์ธ์ค์ ์ต์ข ์ถ๋ ฅ์ ๋ํ๋ ๋๋ค.optimized_agents๋ชฉ๋ก์ ํฌํจํด์ผ ํฉ๋๋ค. ์ด ๋ชฉ๋ก์ ์์๋AgentWithScores๋๋ ๊ทธ ํ์ ํด๋์ค์ฌ์ผ ํฉ๋๋ค. ์ฌ๋ฌ ๋ฉํธ๋ฆญ์ ๊ฑธ์ณ ์์ด์ ํธ์ ์ต์ ์ฑ์ ์ธก์ ํ๋ ๊ฒฝ์ฐ, ํ๋ ํ ํ๋ฐํฐ์ด๋ฅผ ๋ํ๋ด๊ธฐ ์ํด ์ฌ๋ฌ ํญ๋ชฉ์ด ํ์ํ ์ ์์ต๋๋ค.
ํ๋ณด ์ต์ ํ ์์ด์ ํธ์ ๋ํ ์ธ๋ถ ๋ฉํธ๋ฆญ์ ๋
ธ์ถํ๊ธฐ ์ํด AgentWithScores์ ์์ฒด ํ์ ํด๋์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ ํ์ฑ, ์์ ์ฑ, ์ ๋ ฌ์ฑ ๋ฑ์ ๋ณ๋๋ก ์ ์ํํ๊ณ ์ถ์ ์ ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก OptimizerResult์ ์์ฒด ํ์ ํด๋์ค๋ฅผ ๋ง๋ค์ด, ์ตํฐ๋ง์ด์ ์ ์ต์ ํ ํ๋ก์ธ์ค ์ ๋ฐ์ ๋ํ ๋ฉํธ๋ฆญ(ํ๊ฐ๋ ํ๋ณด ์, ์ด ํ๊ฐ ์ ๋ฑ)์ ๋
ธ์ถํ ์ ์์ต๋๋ค.
์ ์ํ๋ฌ์ ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๋ง๋ค๊ธฐ ๋ฐ ์ฌ์ฉํ๊ธฐ¶
์ฌ์ฉ ์ฌ๋ก์ ๋ณต์กํ ์ํ๋ง ๋ฐ ํ๊ฐ ๋ก์ง์ด๋ ์ฌ์ฉ์ ์ง์ ์์ด์ ํธ ์ต์ ํ ์ ๋ต์ด ํ์ํ๋ค๋ฉด, ์๋์ ์ค๋ช
๋ Sampler์ AgentOptimizer ์ถ์ ํด๋์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์ ์ง์ ๊ตฌํ์ ๋ง๋ค ์ ์์ต๋๋ค.
์ด API๋ฅผ ๋ฐ๋ฅด๋ฉด ADK๊ฐ ์ ๊ณตํ๋ ์ํ๋ฌ์ ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๋ฅผ ์ฌ์ฉ์ ์ง์ ๊ตฌํ๊ณผ ์กฐํฉํด ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ ์ํ๋ฌ ๋ง๋ค๊ธฐ¶
์ฌ์ฉ์ ์ง์ ํ๊ฐ์ฉ ์ ์ํ๋ฌ๋ฅผ ๋ง๋ค๋ ค๋ฉด Sampler ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ํ์ฅํ๋ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
๋ํ ์ํ๋ฌ๊ฐ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ๋ ์ฌ์ฉํ SamplingResult ํ์ ํด๋์ค๋ฅผ ์ง์ ํด์ผ ํฉ๋๋ค.
์ํ๋ฌ๋ ๋ค์ ์ถ์ ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค.
get_train_example_ids(self): ์ต์ ํ์ ์ฌ์ฉํ example UID ๋ชฉ๋ก์ ๋ฐํํฉ๋๋ค.get_validation_example_ids(self): ์ต์ ํ๋ ์์ด์ ํธ๋ฅผ ๊ฒ์ฆํ๋ ๋ฐ ์ฌ์ฉํ example UID ๋ชฉ๋ก์ ๋ฐํํฉ๋๋ค.
sample_and_score(self, candidate, example_set, batch, capture_full_eval_data): ์ง์ ๋example_set("train"๋๋"validation")์batch์์์์candidate์์ด์ ํธ๋ฅผ ํ๊ฐํฉ๋๋ค. ๊ณ์ฐ๋ ์์๋ณ ์ ์์,capture_full_eval_data๊ฐTrue์ธ ๊ฒฝ์ฐ eval ๊ธฐ๋ฐ ์์ด์ ํธ ์ต์ ํ์ ํ์ํ ์ถ๊ฐ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋SamplingResultํ์ ํด๋์ค๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค. ์ถ๊ฐ eval ๋ฐ์ดํฐ์ ํ์์SamplingResult๋ฅผ ํ์ ํด๋์ค๋ก ๋ง๋ค์ด ํ์์ ๋ง๊ฒ ์ ํ ์ ์์ต๋๋ค. ๋ค๋ง ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๋ ๊ฐ์SamplingResultํ์ ํด๋์ค๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค.UnstructuredSamplingResult๋ ์ถ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์๋ณ ๋น๊ตฌ์กฐํ ์ฌ์ ์ผ๋ก ์ ์ฅํ๋ ๊ฐ์ฅ ๋จ์ํ ์ฌ๋ก๋ฅผ ๊ตฌํํฉ๋๋ค.
์ ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๋ง๋ค๊ธฐ¶
์ฌ์ฉ์ ์ง์ ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๋ฅผ ๋ง๋ค๋ ค๋ฉด AgentOptimizer ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ํ์ฅํ๋ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
๋ํ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ SamplingResult ํ์ ํด๋์ค์, ๊ฐ ์ต์ ํ๋ ์์ด์ ํธ ๋ฐ ๊ทธ ์ ์/๋ฉํธ๋ฆญ์ ํํํ๋ ๋ฐ ์ฌ์ฉํ AgentWithScores ํ์ ํด๋์ค๋ ์ง์ ํด์ผ ํฉ๋๋ค.
์ตํฐ๋ง์ด์ ๋ ๋ค์ ์ถ์ ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค.
optimize(self, initial_agent, sampler): ์ด ๋ฉ์๋๋ ์ต์ ํ ํ๋ก์ธ์ค๋ฅผ ์กฐ์จํฉ๋๋ค. ๊ฐ์ ํinitial_agent์ ํ๋ณด ํ๊ฐ์ ์ฌ์ฉํsampler๋ฅผ ๋ฐ์ต๋๋ค. ํ๋ณด ์ต์ ํ ์์ด์ ํธ ๋ชฉ๋ก๊ณผ ๊ทธ ์ ์/๋ฉํธ๋ฆญ, ๊ทธ๋ฆฌ๊ณ ์ต์ ํ ํ๋ก์ธ์ค์ ๋ํ ์ ์ฒด ๋ฉํธ๋ฆญ์ ํฌํจํ๋OptimizerResultํ์ ํด๋์ค๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค. ํ๋ณด๋ณ ์ ์/๋ฉํธ๋ฆญ์ ํ์์AgentWithScores๋ฅผ ํ์ ํด๋์ค๋ก ๋ง๋ค์ด ํ์์ ๋ง๊ฒ ์ ํ ์ ์์ต๋๋ค. ๋๋ ๊ฐ ํ๋ณด ์ต์ ํ ์์ด์ ํธ์ ๋ํด ๋จ์ผ ์ ์ฒด ์ ์๋ฅผ ์ง์ ํ ์ ์๋AgentWithScores๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์์ด์ ํธ ์ต์ ํํ๊ธฐ¶
adk optimize ๋ช
๋ น์ LocalEvalSampler์ GEPARootAgentPromptOptimizer๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ฌ์ฉ์ ์ง์ ์ํ๋ฌ์ ์์ด์ ํธ ์ตํฐ๋ง์ด์ ๋ฅผ ์ฌ์ฉํ ๋๋ ์์ด์ ํธ๋ฅผ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์ต์ ํํด์ผ ํฉ๋๋ค.
์๋์ ์ฐธ์กฐ ์ฝ๋๋ ์ ์์์ ๋ํ adk optimize ๋ช
๋ น์ ๋์์ ์ฌํํฉ๋๋ค.
์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์์์ ๊ฐ์ด ๋ฐ์ดํฐ์
์ ๋ง๋ค๊ณ , ๊ฐ์ ๋๋ ํฐ๋ฆฌ ์์ Python ์คํฌ๋ฆฝํธ์์ ์ด ์ฝ๋๋ฅผ ์คํํฉ๋๋ค.
import asyncio
import logging
import os
import agent # the hello_world agent
from google.adk.cli.utils import envs
from google.adk.cli.utils import logs
from google.adk.evaluation.eval_config import EvalConfig
from google.adk.evaluation.local_eval_sets_manager import LocalEvalSetsManager
from google.adk.optimization.gepa_root_agent_prompt_optimizer import GEPARootAgentPromptOptimizer
from google.adk.optimization.gepa_root_agent_prompt_optimizer import GEPARootAgentPromptOptimizerConfig
from google.adk.optimization.local_eval_sampler import LocalEvalSampler
from google.adk.optimization.local_eval_sampler import LocalEvalSamplerConfig
# setup environment variables (API keys, etc.) and logging
envs.load_dotenv_for_agent(".", ".")
logs.setup_adk_logger(logging.INFO)
# create the sampler
sampler_config = LocalEvalSamplerConfig(
eval_config=EvalConfig(criteria={"response_match_score": 0.75}),
app_name="hello_world", # typically the name of the directory containing the agent
train_eval_set="train_eval_set", # from the example
)
eval_sets_manager = LocalEvalSetsManager(
agents_dir=os.path.dirname(os.getcwd()),
)
sampler = LocalEvalSampler(sampler_config, eval_sets_manager)
# create the optimizer
opt_config = GEPARootAgentPromptOptimizerConfig()
optimizer = GEPARootAgentPromptOptimizer(config=opt_config)
# optimize the root agent
initial_agent = agent.root_agent
result = asyncio.run(
optimizer.optimize(initial_agent, sampler)
)
# show the results
best_idx = result.gepa_result["best_idx"]
print(
"Validation score:",
result.optimized_agents[best_idx].overall_score,
"Optimized prompt:",
result.optimized_agents[best_idx].optimized_agent.instruction,
"GEPA metrics:",
result.gepa_result,
sep="\n",
)