Spaces:
Runtime error
Runtime error
tech-envision
commited on
Commit
·
9f82d8d
1
Parent(s):
100e82d
feat(vm): persist containers across sessions
Browse files
README.md
CHANGED
|
@@ -13,8 +13,11 @@ conversations can be resumed with context. One example tool is included:
|
|
| 13 |
Execution happens asynchronously so the assistant can continue responding
|
| 14 |
while the command runs.
|
| 15 |
The VM is created when a chat session starts and reused for all subsequent
|
| 16 |
-
tool calls.
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
Sessions share state through an in-memory registry so that only one generation
|
| 20 |
can run at a time. Messages sent while a response is being produced are
|
|
@@ -77,6 +80,9 @@ back to ``python:3.11-slim``. This base image includes Python and ``pip`` so
|
|
| 77 |
packages can be installed immediately. The container has network access enabled
|
| 78 |
which allows fetching additional dependencies as needed.
|
| 79 |
|
|
|
|
|
|
|
|
|
|
| 80 |
To use a fully featured Ubuntu environment, build a custom Docker image and set
|
| 81 |
``VM_IMAGE`` to that image. An example ``docker/Dockerfile.vm`` is provided:
|
| 82 |
|
|
|
|
| 13 |
Execution happens asynchronously so the assistant can continue responding
|
| 14 |
while the command runs.
|
| 15 |
The VM is created when a chat session starts and reused for all subsequent
|
| 16 |
+
tool calls. When ``PERSIST_VMS`` is enabled (default), each user keeps the
|
| 17 |
+
same container across multiple chat sessions so any installed packages and
|
| 18 |
+
filesystem changes remain available. The environment includes Python and
|
| 19 |
+
``pip`` so complex tasks can be scripted using Python directly inside the
|
| 20 |
+
terminal.
|
| 21 |
|
| 22 |
Sessions share state through an in-memory registry so that only one generation
|
| 23 |
can run at a time. Messages sent while a response is being produced are
|
|
|
|
| 80 |
packages can be installed immediately. The container has network access enabled
|
| 81 |
which allows fetching additional dependencies as needed.
|
| 82 |
|
| 83 |
+
Set ``PERSIST_VMS=0`` to revert to the previous behaviour where containers are
|
| 84 |
+
stopped once no sessions are using them.
|
| 85 |
+
|
| 86 |
To use a fully featured Ubuntu environment, build a custom Docker image and set
|
| 87 |
``VM_IMAGE`` to that image. An example ``docker/Dockerfile.vm`` is provided:
|
| 88 |
|
run.py
CHANGED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
| 3 |
import asyncio
|
| 4 |
|
| 5 |
from src.chat import ChatSession
|
|
|
|
| 6 |
|
| 7 |
|
| 8 |
async def _main() -> None:
|
|
@@ -24,3 +25,5 @@ if __name__ == "__main__":
|
|
| 24 |
asyncio.run(_main())
|
| 25 |
except KeyboardInterrupt:
|
| 26 |
pass
|
|
|
|
|
|
|
|
|
| 3 |
import asyncio
|
| 4 |
|
| 5 |
from src.chat import ChatSession
|
| 6 |
+
from src.vm import VMRegistry
|
| 7 |
|
| 8 |
|
| 9 |
async def _main() -> None:
|
|
|
|
| 25 |
asyncio.run(_main())
|
| 26 |
except KeyboardInterrupt:
|
| 27 |
pass
|
| 28 |
+
finally:
|
| 29 |
+
VMRegistry.shutdown_all()
|
src/config.py
CHANGED
|
@@ -10,6 +10,7 @@ MAX_TOOL_CALL_DEPTH: Final[int] = 5
|
|
| 10 |
NUM_CTX: Final[int] = int(os.getenv("OLLAMA_NUM_CTX", "32000"))
|
| 11 |
UPLOAD_DIR: Final[str] = os.getenv("UPLOAD_DIR", str(Path.cwd() / "uploads"))
|
| 12 |
VM_IMAGE: Final[str] = os.getenv("VM_IMAGE", "python:3.11")
|
|
|
|
| 13 |
|
| 14 |
SYSTEM_PROMPT: Final[str] = (
|
| 15 |
"You are Starlette, a professional AI assistant with advanced tool orchestration. "
|
|
|
|
| 10 |
NUM_CTX: Final[int] = int(os.getenv("OLLAMA_NUM_CTX", "32000"))
|
| 11 |
UPLOAD_DIR: Final[str] = os.getenv("UPLOAD_DIR", str(Path.cwd() / "uploads"))
|
| 12 |
VM_IMAGE: Final[str] = os.getenv("VM_IMAGE", "python:3.11")
|
| 13 |
+
PERSIST_VMS: Final[bool] = os.getenv("PERSIST_VMS", "1") == "1"
|
| 14 |
|
| 15 |
SYSTEM_PROMPT: Final[str] = (
|
| 16 |
"You are Starlette, a professional AI assistant with advanced tool orchestration. "
|
src/vm.py
CHANGED
|
@@ -8,7 +8,7 @@ from pathlib import Path
|
|
| 8 |
|
| 9 |
from threading import Lock
|
| 10 |
|
| 11 |
-
from .config import UPLOAD_DIR, VM_IMAGE
|
| 12 |
|
| 13 |
from .log import get_logger
|
| 14 |
|
|
@@ -180,6 +180,18 @@ class VMRegistry:
|
|
| 180 |
|
| 181 |
cls._counts[username] -= 1
|
| 182 |
if cls._counts[username] <= 0:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
vm.stop()
|
| 184 |
-
|
| 185 |
-
|
|
|
|
| 8 |
|
| 9 |
from threading import Lock
|
| 10 |
|
| 11 |
+
from .config import UPLOAD_DIR, VM_IMAGE, PERSIST_VMS
|
| 12 |
|
| 13 |
from .log import get_logger
|
| 14 |
|
|
|
|
| 180 |
|
| 181 |
cls._counts[username] -= 1
|
| 182 |
if cls._counts[username] <= 0:
|
| 183 |
+
cls._counts[username] = 0
|
| 184 |
+
if not PERSIST_VMS:
|
| 185 |
+
vm.stop()
|
| 186 |
+
del cls._vms[username]
|
| 187 |
+
del cls._counts[username]
|
| 188 |
+
|
| 189 |
+
@classmethod
|
| 190 |
+
def shutdown_all(cls) -> None:
|
| 191 |
+
"""Stop and remove all managed VMs."""
|
| 192 |
+
|
| 193 |
+
with cls._lock:
|
| 194 |
+
for vm in cls._vms.values():
|
| 195 |
vm.stop()
|
| 196 |
+
cls._vms.clear()
|
| 197 |
+
cls._counts.clear()
|