11import asyncio
2+ import subprocess
23import time
34from typing import Any , Dict , List , Optional , Callable
45
6+ from dotenv import load_dotenv
57import requests
68
9+ from eval_protocol .directory_utils import find_eval_protocol_dir
710from eval_protocol .models import EvaluationRow , Status
811from eval_protocol .data_loader .dynamic_data_loader import DynamicDataLoader
9- from eval_protocol .types .remote_rollout_processor import InitRequest , RolloutMetadata
12+ from eval_protocol .types .remote_rollout_processor import ElasticSearchConfig , InitRequest , RolloutMetadata
1013from .rollout_processor import RolloutProcessor
1114from .types import RolloutProcessorConfig
15+ import logging
16+
1217import os
1318
19+ logger = logging .getLogger (__name__ )
20+
1421
1522class RemoteRolloutProcessor (RolloutProcessor ):
1623 """
@@ -27,6 +34,8 @@ def __init__(
2734 poll_interval : float = 1.0 ,
2835 timeout_seconds : float = 120.0 ,
2936 output_data_loader : Callable [[str ], DynamicDataLoader ],
37+ disable_elastic_search : bool = False ,
38+ elastic_search_config : Optional [ElasticSearchConfig ] = None ,
3039 ):
3140 # Prefer constructor-provided configuration. These can be overridden via
3241 # config.kwargs at call time for backward compatibility.
@@ -37,6 +46,58 @@ def __init__(
3746 self ._poll_interval = poll_interval
3847 self ._timeout_seconds = timeout_seconds
3948 self ._output_data_loader = output_data_loader
49+ self ._disable_elastic_search = disable_elastic_search
50+ self ._elastic_search_config = elastic_search_config
51+
52+ def setup (self ) -> None :
53+ if self ._disable_elastic_search :
54+ logger .info ("Elasticsearch is disabled, skipping setup" )
55+ return
56+ logger .info ("Setting up Elasticsearch" )
57+ self ._elastic_search_config = self ._setup_elastic_search ()
58+ logger .info ("Elasticsearch setup complete" )
59+
60+ def _parse_elastic_env_file (self , env_file_path : str ) -> ElasticSearchConfig :
61+ """Parse ES_LOCAL_API_KEY and ES_LOCAL_URL from .env file."""
62+ loaded = load_dotenv (env_file_path )
63+ if not loaded :
64+ raise RuntimeError ("Failed to load .env file" )
65+ api_key = os .getenv ("ES_LOCAL_API_KEY" )
66+ url = os .getenv ("ES_LOCAL_URL" )
67+ if not url or not api_key :
68+ raise RuntimeError ("Failed to parse ES_LOCAL_API_KEY and ES_LOCAL_URL from .env file" )
69+ return ElasticSearchConfig (url = url , api_key = api_key )
70+
71+ def _setup_elastic_search (self ) -> ElasticSearchConfig :
72+ eval_protocol_dir = find_eval_protocol_dir ()
73+ elastic_start_local_dir = os .path .join (eval_protocol_dir , "elastic-start-local" )
74+ env_file_path = os .path .join (elastic_start_local_dir , ".env" )
75+
76+ # if elastic-start-local directory exists, return the config
77+ if os .path .exists (elastic_start_local_dir ):
78+ # run start.sh in the elastic-start-local directory
79+ from eval_protocol .utils .subprocess_utils import run_script_and_wait
80+
81+ run_script_and_wait (
82+ script_name = "start.sh" ,
83+ working_directory = elastic_start_local_dir ,
84+ inherit_stdout = True ,
85+ )
86+ return self ._parse_elastic_env_file (env_file_path )
87+
88+ # run Elasticsearch start-local script: "curl -fsSL https://elastic.co/start-local | sh -s -- --esonly"
89+ process = subprocess .Popen (
90+ ["sh" , "-c" , "curl -fsSL https://elastic.co/start-local | sh -s -- --esonly" ],
91+ cwd = eval_protocol_dir ,
92+ stdout = subprocess .PIPE ,
93+ stderr = subprocess .STDOUT ,
94+ text = True ,
95+ )
96+ returncode = process .wait ()
97+ if returncode != 0 :
98+ raise RuntimeError ("Failed to start Elasticsearch" )
99+
100+ return self ._parse_elastic_env_file (env_file_path )
40101
41102 def __call__ (self , rows : List [EvaluationRow ], config : RolloutProcessorConfig ) -> List [asyncio .Task [EvaluationRow ]]:
42103 tasks : List [asyncio .Task [EvaluationRow ]] = []
@@ -119,6 +180,7 @@ async def _process_row(row: EvaluationRow) -> EvaluationRow:
119180 tools = row .tools ,
120181 metadata = meta ,
121182 model_base_url = model_base_url ,
183+ elastic_search_config = self ._elastic_search_config ,
122184 )
123185
124186 # Fire-and-poll
0 commit comments