Skip to content

Commit 8d4ab33

Browse files
committed
Use redis container instead of runner for jobs in local runs
1 parent d39abfe commit 8d4ab33

File tree

2 files changed

+88
-83
lines changed

2 files changed

+88
-83
lines changed

llmstack/cli.py

Lines changed: 85 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -114,53 +114,62 @@ def prepare_env():
114114
with open(config_path) as f:
115115
config = toml.load(f)
116116

117-
if "generatedfiles_root" not in config:
118-
config["generatedfiles_root"] = "./generatedfiles"
119-
120-
if "use_remote_job_queue" not in config:
121-
config["use_remote_job_queue"] = True
122-
123-
if "llmstack-runner" not in config:
124-
config["llmstack-runner"] = {}
117+
with open(config_path, "w") as f:
118+
toml.dump(config, f)
125119

126-
if "host" not in config["llmstack-runner"]:
127-
config["llmstack-runner"]["host"] = "localhost"
120+
return config_path
128121

129-
if "port" not in config["llmstack-runner"]:
130-
config["llmstack-runner"]["port"] = 50051
131122

132-
if "wss_port" not in config["llmstack-runner"]:
133-
config["llmstack-runner"]["wss_port"] = 50052
123+
def pull_redis_image():
124+
"""Pull Redis image"""
125+
client = docker.from_env()
126+
image_name = "redis"
127+
image_tag = "latest"
134128

135-
if "playwright_port" not in config["llmstack-runner"]:
136-
config["llmstack-runner"]["playwright_port"] = 50053
129+
# Pull image if it is not locally available
130+
if not any(f"{image_name}:{image_tag}" in image.tags for image in client.images.list()):
131+
print(f"[Redis] Pulling {image_name}:{image_tag}")
137132

138-
if "rq_redis_port" not in config["llmstack-runner"]:
139-
config["llmstack-runner"]["rq_redis_port"] = 50379
133+
layers_status = defaultdict(dict)
134+
response = client.api.pull(
135+
image_name,
136+
tag=image_tag,
137+
stream=True,
138+
decode=True,
139+
)
140+
for line in response:
141+
if "id" in line:
142+
layer_id = line["id"]
143+
# Update the status of this layer
144+
layers_status[layer_id].update(line)
140145

141-
if "rq_redis_host" not in config["llmstack-runner"]:
142-
config["llmstack-runner"]["rq_redis_host"] = "localhost"
146+
# Print the current status of all layers
147+
for layer, status in layers_status.items():
148+
print(
149+
f"[Redis] Layer {layer}: {status.get('status', '')} {status.get('progress', '')}",
150+
)
151+
print() # Add a blank line for better readability
143152

144-
with open(config_path, "w") as f:
145-
toml.dump(config, f)
153+
elif "status" in line and "id" not in line:
154+
# Global status messages without a specific layer ID
155+
print(line["status"])
146156

147-
return config_path
157+
elif "error" in line:
158+
print(f"Error: {line['error']}")
159+
break
148160

149161

150-
def start_runner(environment):
151-
"""Start llmstack-runner container"""
152-
print("[llmstack-runner] Starting LLMStack Runner")
162+
def start_redis(environment):
163+
"""Start Redis container"""
164+
print("[Redis] Starting Redis")
153165
client = docker.from_env()
154-
runner_container = None
155-
image_name = environment.get(
156-
"RUNNER_IMAGE_NAME",
157-
"ghcr.io/trypromptly/llmstack-runner",
158-
)
159-
image_tag = environment.get("RUNNER_IMAGE_TAG", "main")
166+
redis_container = None
167+
image_name = environment.get("REDIS_IMAGE_NAME", "redis")
168+
image_tag = environment.get("REDIS_IMAGE_TAG", "latest")
160169

161170
# Pull image if it is not locally available
162171
if not any(f"{image_name}:{image_tag}" in image.tags for image in client.images.list()):
163-
print(f"[llmstack-runner] Pulling {image_name}:{image_tag}")
172+
print(f"[Redis] Pulling {image_name}:{image_tag}")
164173

165174
layers_status = defaultdict(dict)
166175
response = client.api.pull(
@@ -178,7 +187,7 @@ def start_runner(environment):
178187
# Print the current status of all layers
179188
for layer, status in layers_status.items():
180189
print(
181-
f"[llmstack-runner] Layer {layer}: {status.get('status', '')} {status.get('progress', '')}",
190+
f"[Redis] Layer {layer}: {status.get('status', '')} {status.get('progress', '')}",
182191
)
183192
print() # Add a blank line for better readability
184193

@@ -191,44 +200,41 @@ def start_runner(environment):
191200
break
192201

193202
try:
194-
runner_container = client.containers.get("llmstack-runner")
203+
redis_container = client.containers.get("llmstack-redis")
195204
except docker.errors.NotFound:
196-
runner_container = client.containers.run(
205+
redis_container = client.containers.run(
197206
f"{image_name}:{image_tag}",
198-
name="llmstack-runner",
207+
name="llmstack-redis",
199208
ports={
200-
"50051/tcp": os.environ["RUNNER_PORT"],
201-
"50052/tcp": os.environ["RUNNER_WSS_PORT"],
202-
"50053/tcp": os.environ["RUNNER_PLAYWRIGHT_PORT"],
203-
"6379/tcp": os.environ["RUNNER_RQ_REDIS_PORT"],
209+
"6379/tcp": os.environ["REDIS_PORT"],
204210
},
205211
detach=True,
206212
remove=True,
207213
environment=environment,
208214
)
209215

210-
# Start runner container if not already running
211-
print("[llmstack-runner] Started LLMStack Runner")
212-
if runner_container.status != "running":
213-
runner_container.start()
216+
# Start Redis container if not already running
217+
print("[Redis] Started Redis")
218+
if redis_container.status != "running":
219+
redis_container.start()
214220

215221
# Stream logs starting from the end to stdout
216-
for line in runner_container.logs(stream=True, follow=True):
217-
print(f'[llmstack-runner] {line.decode("utf-8").strip()}')
222+
for line in redis_container.logs(stream=True, follow=True):
223+
print(f'[Redis] {line.decode("utf-8").strip()}')
218224

219225

220-
def stop_runner():
221-
"""Stop llmstack-runner container"""
222-
print("\nStopping LLMStack Runner\n")
226+
def stop_redis():
227+
"""Stop Redis container"""
228+
print("\nStopping Redis\n")
223229
client = docker.from_env()
224-
runner_container = None
230+
redis_container = None
225231
try:
226-
runner_container = client.containers.get("llmstack-runner")
232+
redis_container = client.containers.get("llmstack-redis")
227233
except docker.errors.NotFound:
228234
pass
229235

230-
if runner_container:
231-
runner_container.stop()
236+
if redis_container:
237+
redis_container.stop()
232238

233239
client.close()
234240

@@ -237,12 +243,14 @@ def main():
237243
"""Main entry point for the application script"""
238244

239245
def signal_handler(sig, frame):
240-
stop_runner()
241-
if runner_thread.is_alive():
242-
runner_thread.join()
243246
if server_process.poll() is None: # Check if the process is still running
244247
server_process.terminate()
245248
server_process.wait()
249+
250+
stop_redis()
251+
if redis_thread.is_alive():
252+
redis_thread.join()
253+
246254
sys.exit(0)
247255

248256
# Get config file path
@@ -266,19 +274,18 @@ def signal_handler(sig, frame):
266274

267275
# Load environment variables from config under [llmstack] section
268276
llmstack_environment = {}
269-
runner_environment = {}
277+
redis_environment = {}
270278
with open(env_path) as f:
271279
config = toml.load(f)
272280
for key in config["llmstack"]:
273281
os.environ[key.upper()] = str(config["llmstack"][key])
274282
llmstack_environment[key.upper()] = str(config["llmstack"][key])
275-
for key in config["llmstack-runner"]:
276-
os.environ[f"RUNNER_{key.upper()}"] = str(
277-
config["llmstack-runner"][key],
278-
)
279-
runner_environment[f"RUNNER_{key.upper()}"] = str(
280-
config["llmstack-runner"][key],
281-
)
283+
284+
redis_environment["REDIS_PORT"] = (
285+
llmstack_environment["REDIS_PORT"] if "REDIS_PORT" in llmstack_environment else "50379"
286+
)
287+
288+
os.environ["REDIS_PORT"] = redis_environment["REDIS_PORT"]
282289

283290
# Load CLI args
284291
args = parser.parse_args()
@@ -305,6 +312,7 @@ def signal_handler(sig, frame):
305312
run_django_command(sys.argv[1:])
306313
sys.exit(0)
307314

315+
run_django_command(["manage.py", "migrate", "--fake"])
308316
run_django_command(["manage.py", "migrate", "--noinput"])
309317
run_django_command(
310318
[
@@ -322,14 +330,17 @@ def signal_handler(sig, frame):
322330
# Install default playwright browsers
323331
subprocess.run(["playwright", "install", "chromium"])
324332

325-
# Start llmstack-runner container in a separate thread
333+
# Pull redis before starting
334+
pull_redis_image()
335+
336+
# Start llmstack-redis container in a separate thread
326337
import threading
327338

328-
runner_thread = threading.Thread(
329-
target=start_runner,
330-
args=([runner_environment]),
339+
redis_thread = threading.Thread(
340+
target=start_redis,
341+
args=([redis_environment]),
331342
)
332-
runner_thread.start()
343+
redis_thread.start()
333344

334345
# Run llmstack runserver in a separate process
335346
server_process = subprocess.Popen(["llmstack", "runserver"])
@@ -372,10 +383,6 @@ def signal_handler(sig, frame):
372383
else:
373384
signal.pause()
374385

375-
# Stop runner container
376-
stop_runner()
377-
runner_thread.join()
378-
379386
# Stop server process
380387
server_process.terminate()
381388
server_process.wait()
@@ -384,6 +391,10 @@ def signal_handler(sig, frame):
384391
rqworker_process.terminate()
385392
rqworker_process.wait()
386393

394+
# Stop redis container
395+
stop_redis()
396+
redis_thread.join()
397+
387398

388399
if __name__ == "__main__":
389400
main()

llmstack/config.toml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
[llmstack]
22
llmstack_port=3000
3+
redis_host="localhost"
4+
redis_port=50379
35

46
# Platform default keys (optional)
57
default_openai_api_key=""
@@ -12,19 +14,11 @@ default_elevenlabs_api_key=""
1214
# Local installation
1315
vector_database_engine="chroma"
1416
vector_database_name="./llmstack.chromadb"
15-
use_remote_job_queue="False"
17+
use_remote_job_queue="True"
1618
cache_backend="locmem.LocMemCache"
1719
database_name="./llmstack.sqlite"
1820
database_engine="sqlite3"
1921
debug="True"
2022
playwright_url=""
2123
generatedfiles_root="./generated_files"
2224
site_url="http://localhost:3000"
23-
24-
[llmstack-runner]
25-
host = "localhost"
26-
port = 50051
27-
wss_port = 50052
28-
playwright_port = 50053
29-
rq_redis_port = 50379
30-
rq_redis_host = "localhost"

0 commit comments

Comments
 (0)