update the codebase poc ver1
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import subprocess
|
||||
import time
|
||||
import requests
|
||||
import modal
|
||||
|
||||
OLLAMA_PORT = 11434
|
||||
MODEL_NAME = "medgemma:4b"
|
||||
|
||||
# Persist downloaded models
|
||||
ollama_volume = modal.Volume.from_name(
|
||||
"ollama-model-cache",
|
||||
create_if_missing=True,
|
||||
)
|
||||
|
||||
image = (
|
||||
modal.Image.debian_slim()
|
||||
.pip_install("requests") # <--- THIS IS MISSING
|
||||
.run_commands(
|
||||
"apt-get update",
|
||||
"apt-get install -y curl zstd ca-certificates",
|
||||
"curl -fsSL https://ollama.com/install.sh | sh",
|
||||
|
||||
)
|
||||
.env(
|
||||
{
|
||||
"OLLAMA_HOST": "0.0.0.0"
|
||||
}
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
app = modal.App("ollama-medgemma")
|
||||
|
||||
|
||||
@app.cls(
|
||||
image=image,
|
||||
gpu="l4",
|
||||
min_containers=1,
|
||||
max_containers=3,
|
||||
scaledown_window=300,
|
||||
volumes={"/root/.ollama": ollama_volume},
|
||||
)
|
||||
class OllamaServer:
|
||||
|
||||
@modal.enter()
|
||||
def start_server(self):
|
||||
print("Starting Ollama server...")
|
||||
|
||||
self.process = subprocess.Popen(
|
||||
["ollama", "serve"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True,
|
||||
)
|
||||
|
||||
try:
|
||||
self.wait_until_ready()
|
||||
|
||||
print(f"Checking model: {MODEL_NAME}")
|
||||
|
||||
installed = subprocess.run(
|
||||
["ollama", "list"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
if MODEL_NAME not in installed.stdout:
|
||||
print(f"Downloading {MODEL_NAME}...")
|
||||
subprocess.run(
|
||||
["ollama", "pull", MODEL_NAME],
|
||||
check=True,
|
||||
)
|
||||
else:
|
||||
print("Model already cached.")
|
||||
|
||||
print("Ollama ready.")
|
||||
|
||||
response = requests.post(
|
||||
"http://0.0.0.0:11434/api/generate",
|
||||
json={
|
||||
"model": MODEL_NAME,
|
||||
"prompt": "",
|
||||
"stream": False,
|
||||
"keep_alive": -1,
|
||||
},
|
||||
timeout=120,
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
print(response.json())
|
||||
except Exception:
|
||||
self.process.kill()
|
||||
raise
|
||||
|
||||
def wait_until_ready(self):
|
||||
|
||||
deadline = time.time() + 180
|
||||
|
||||
while time.time() < deadline:
|
||||
try:
|
||||
r = requests.get(
|
||||
f"http://0.0.0.0:{OLLAMA_PORT}/api/tags",
|
||||
timeout=2,
|
||||
)
|
||||
|
||||
if r.status_code == 200:
|
||||
return
|
||||
|
||||
except requests.RequestException:
|
||||
pass
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
raise RuntimeError("Ollama failed to start.")
|
||||
|
||||
@modal.web_server(port=OLLAMA_PORT)
|
||||
def web(self):
|
||||
pass
|
||||
|
||||
@modal.exit()
|
||||
def shutdown(self):
|
||||
print("Stopping Ollama...")
|
||||
|
||||
if self.process.poll() is None:
|
||||
self.process.terminate()
|
||||
|
||||
try:
|
||||
self.process.wait(timeout=10)
|
||||
except subprocess.TimeoutExpired:
|
||||
self.process.kill()
|
||||
@@ -188,6 +188,12 @@ async def proxy_all_triton_request(path: str, request: Request):
|
||||
status_code=502
|
||||
)
|
||||
|
||||
@web_app.get("/v2/models")
|
||||
async def forward_list_models():
|
||||
async with httpx.AsyncClient() as client:
|
||||
r = await client.get("http://127.0.0.1:8000/v2/models")
|
||||
return Response(content=r.content, status_code=r.status_code, media_type=r.headers.get("content-type"))
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# THE UNIFIED SERVICE FUNCTION (1 Container, 1 GPU, 1 Triton Process)
|
||||
# -------------------------------------------------------------
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
cd ../PILOT_PROJECT/workspace/sprint_1_2/CODEBASE/infra/implementation/triton_run
|
||||
modal deploy PILOT_PROJECT/workspace/sprint_1_2/codebase/infra/implementation/triton_run/modal_triton.py
|
||||
MODAL_PROFILE=dtj-tran modal deploy PILOT_PROJECT/workspace/sprint_1_2/codebase/infra/implementation/triton_run/modal_triton.py
|
||||
Reference in New Issue
Block a user