Skip to content

Commit 42ca138

Browse files
committed
Applying fixes to resolve PR comments
1 parent ceb424e commit 42ca138

File tree

3 files changed

+211
-54
lines changed

3 files changed

+211
-54
lines changed

ai/ai-starter-kit/helm-chart/ai-starter-kit/files/multi-agent-ollama.ipynb

Lines changed: 86 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -228,36 +228,91 @@
228228
"with open('/tmp/ollama_wrapper.py', 'w') as f:\n",
229229
" f.write(api_wrapper_code)\n",
230230
"\n",
231-
"!pkill -f ollama_wrapper.py 2>/dev/null || true\n",
232-
"\n",
233-
"env_vars = f\"\"\"\n",
234-
"export OLLAMA_HOST=\"{os.getenv('OLLAMA_HOST', 'http://ai-starter-kit-ollama:11434')}\"\n",
235-
"export MODEL_NAME=\"qwen2.5:1.5b\"\n",
236-
"export MLFLOW_TRACKING_URI=\"{os.getenv('MLFLOW_TRACKING_URI', 'http://ai-starter-kit-mlflow:5000')}\"\n",
237-
"\"\"\"\n",
238-
"\n",
239-
"!echo '{env_vars}' > /tmp/env_vars.sh\n",
240-
"!bash -c 'source /tmp/env_vars.sh && nohup python /tmp/ollama_wrapper.py > /tmp/wrapper.log 2>&1 &'\n",
231+
"print(\"Checking if wrapper script was written...\")\n",
232+
"if not os.path.exists('/tmp/ollama_wrapper.py'):\n",
233+
" print(\"ERROR: Failed to write wrapper script!\")\n",
234+
" raise Exception(\"Cannot proceed without wrapper script\")\n",
235+
"print(\" Wrapper script created\")\n",
241236
"\n",
242-
"print(\"Starting API wrapper...\")\n",
237+
"print(\"\\nKilling existing wrapper processes...\")\n",
238+
"!pkill -f ollama_wrapper.py 2>/dev/null || true\n",
239+
"time.sleep(2)\n",
240+
"\n",
241+
"log_file = '/tmp/wrapper.log'\n",
242+
"print(f\"\\nPreparing log file: {log_file}\")\n",
243+
"!touch /tmp/wrapper.log\n",
244+
"!chmod 666 /tmp/wrapper.log\n",
245+
"\n",
246+
"if not os.path.exists(log_file):\n",
247+
" print(f\"ERROR: Could not create log file at {log_file}\")\n",
248+
" raise Exception(\"Cannot create log file\")\n",
249+
"print(\" Log file ready\")\n",
250+
"\n",
251+
"env_vars = {\n",
252+
" 'OLLAMA_HOST': os.getenv('OLLAMA_HOST', 'http://ai-starter-kit-ollama:11434'),\n",
253+
" 'MODEL_NAME': 'qwen2.5:1.5b',\n",
254+
" 'MLFLOW_TRACKING_URI': os.getenv('MLFLOW_TRACKING_URI', 'http://ai-starter-kit-mlflow:5000')\n",
255+
"}\n",
256+
"\n",
257+
"print(\"\\nEnvironment variables:\")\n",
258+
"for k, v in env_vars.items():\n",
259+
" print(f\" {k}={v}\")\n",
260+
"\n",
261+
"print(\"\\nStarting API wrapper...\")\n",
262+
"with open(log_file, 'w') as log:\n",
263+
" process = subprocess.Popen(\n",
264+
" ['python', '/tmp/ollama_wrapper.py'],\n",
265+
" stdout=log,\n",
266+
" stderr=subprocess.STDOUT,\n",
267+
" env={**os.environ, **env_vars},\n",
268+
" start_new_session=True\n",
269+
" )\n",
270+
" \n",
271+
"print(f\"Process started with PID: {process.pid}\")\n",
272+
"\n",
273+
"time.sleep(2)\n",
274+
"if process.poll() is not None:\n",
275+
" print(f\"\\nERROR: Process died immediately with exit code {process.poll()}\")\n",
276+
" print(\"\\nLog contents:\")\n",
277+
" !cat /tmp/wrapper.log\n",
278+
" raise Exception(\"API wrapper failed to start\")\n",
279+
"print(\" Process is running\")\n",
280+
"\n",
281+
"print(\"\\nWaiting for API to respond...\")\n",
282+
"api_ready = False\n",
243283
"for i in range(30):\n",
244284
" time.sleep(1)\n",
245285
" try:\n",
246286
" r = requests.get(\"http://localhost:8000/v1/healthz\", timeout=1)\n",
247287
" if r.status_code == 200:\n",
248-
" print(\"API Status:\", r.json())\n",
288+
" print(f\"\\n API is ready! Response: {r.json()}\")\n",
249289
" print(f\"\\nOpenAI-compatible API running at: http://localhost:8000/v1\")\n",
250290
" print(f\"Health: http://localhost:8000/v1/healthz\")\n",
251291
" print(f\"Chat: http://localhost:8000/v1/chat/completions\")\n",
292+
" api_ready = True\n",
252293
" break\n",
253-
" except:\n",
294+
" except requests.exceptions.ConnectionError:\n",
254295
" if i % 5 == 0:\n",
255-
" print(f\" Waiting for API to start... ({i}s)\")\n",
256-
" continue\n",
257-
"else:\n",
258-
" print(\"\\nAPI wrapper failed to start. Checking logs:\")\n",
259-
" !tail -20 /tmp/wrapper.log\n",
260-
" print(\"\\nYou can still use direct Ollama API in the next cells.\")"
296+
" print(f\" Waiting for API... ({i}s)\")\n",
297+
" except Exception as e:\n",
298+
" print(f\" Unexpected error: {e}\")\n",
299+
"\n",
300+
"if not api_ready:\n",
301+
" print(\"\\nAPI wrapper failed to start within 30 seconds\")\n",
302+
" print(\"\\nChecking if process is still alive...\")\n",
303+
" if process.poll() is not None:\n",
304+
" print(f\"Process died with exit code: {process.poll()}\")\n",
305+
" else:\n",
306+
" print(\"Process is still running but not responding\")\n",
307+
" \n",
308+
" print(\"\\nLast 50 lines of logs:\")\n",
309+
" !tail -50 /tmp/wrapper.log\n",
310+
" \n",
311+
" print(\"\\nChecking if port 8000 is in use:\")\n",
312+
" !netstat -tlnp 2>/dev/null | grep 8000 || echo \"No process on port 8000\"\n",
313+
" \n",
314+
" print(\"\\nChecking Python processes:\")\n",
315+
" !ps aux | grep python | grep -v grep"
261316
]
262317
},
263318
{
@@ -279,15 +334,23 @@
279334
"source": [
280335
"import os, time, requests, json\n",
281336
"\n",
282-
"USE_WRAPPER = True\n",
283-
"BASE_URL = \"http://localhost:8000/v1\" if USE_WRAPPER else os.getenv(\"OLLAMA_HOST\", \"http://ai-starter-kit-ollama:11434\")\n",
337+
"BASE_URL = \"http://localhost:8000/v1\"\n",
338+
"OLLAMA_DIRECT = os.getenv(\"OLLAMA_HOST\", \"http://ai-starter-kit-ollama:11434\")\n",
339+
"\n",
340+
"try:\n",
341+
" r = requests.get(f\"{BASE_URL}/healthz\", timeout=2)\n",
342+
" USE_WRAPPER = r.status_code == 200\n",
343+
" print(\"✓ Using: OpenAI-compatible wrapper\")\n",
344+
"except:\n",
345+
" USE_WRAPPER = False\n",
346+
" print(\"✓ Using: Direct Ollama API (wrapper not available)\")\n",
284347
"\n",
285348
"def health():\n",
286349
" if USE_WRAPPER:\n",
287350
" r = requests.get(f\"{BASE_URL}/healthz\", timeout=10)\n",
288351
" print(\"Health:\", r.status_code, r.json())\n",
289352
" else:\n",
290-
" r = requests.get(f\"{BASE_URL}/api/tags\", timeout=10)\n",
353+
" r = requests.get(f\"{OLLAMA_DIRECT}/api/tags\", timeout=10)\n",
291354
" print(\"Health:\", r.status_code, \"Models available:\", len(r.json().get('models', [])))\n",
292355
"\n",
293356
"def chat(prompt, temperature=0.4, max_tokens=220):\n",
@@ -315,7 +378,7 @@
315378
" \"num_predict\": max_tokens\n",
316379
" }\n",
317380
" }\n",
318-
" endpoint = f\"{BASE_URL}/api/chat\"\n",
381+
" endpoint = f\"{OLLAMA_DIRECT}/api/chat\"\n",
319382
" \n",
320383
" t0 = time.time()\n",
321384
" r = requests.post(endpoint, json=body, timeout=120)\n",

ai/ai-starter-kit/helm-chart/ai-starter-kit/files/multi-agent-ramalama.ipynb

Lines changed: 109 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@
5959
"outputs": [],
6060
"source": [
6161
"import requests, os, json\n",
62-
"\n",
6362
"RAMALAMA_HOST = os.environ.get('RAMALAMA_HOST', 'http://ai-starter-kit-ramalama:8080')\n",
6463
"MODEL_NAME = \"qwen2.5:1.5b\"\n",
6564
"\n",
@@ -73,14 +72,38 @@
7372
"if check_ramalama():\n",
7473
" print(\"RamaLama service is running\")\n",
7574
" \n",
75+
" print(f\"\\nChecking model {MODEL_NAME}...\")\n",
7676
" try:\n",
7777
" r = requests.get(f\"{RAMALAMA_HOST}/v1/models\")\n",
7878
" models = r.json().get('data', [])\n",
79-
" model_exists = any(m.get('id') == MODEL_NAME for m in models) \n",
80-
" if model_exists:\n",
81-
" print(f\"Model {MODEL_NAME} already available\")\n",
79+
" model_exists = any(m.get('id') == MODEL_NAME for m in models)\n",
80+
" \n",
81+
" if not model_exists:\n",
82+
" print(f\"Pulling model {MODEL_NAME}...\")\n",
83+
" \n",
84+
" try:\n",
85+
" test_body = {\n",
86+
" \"model\": MODEL_NAME,\n",
87+
" \"messages\": [{\"role\": \"user\", \"content\": \"test\"}],\n",
88+
" \"max_tokens\": 1\n",
89+
" }\n",
90+
" r = requests.post(f\"{RAMALAMA_HOST}/v1/chat/completions\", json=test_body, timeout=300)\n",
91+
" \n",
92+
" if r.status_code == 200:\n",
93+
" print(f\"Model {MODEL_NAME} loaded successfully\")\n",
94+
" else:\n",
95+
" print(f\"Failed to load model. Status: {r.status_code}\")\n",
96+
" print(\"You may need to pull the model manually in the RamaLama deployment\")\n",
97+
" \n",
98+
" except requests.exceptions.Timeout:\n",
99+
" print(\"Model pull timed out. Large models may take longer.\")\n",
100+
" print(\"Check RamaLama logs to monitor progress\")\n",
101+
" except Exception as e:\n",
102+
" print(f\"Error pulling model: {e}\")\n",
103+
" print(\"You may need to pull the model manually in the RamaLama deployment\")\n",
82104
" else:\n",
83-
" print(f\"Model {MODEL_NAME} not found; ensure it's pulled in the deployment\")\n",
105+
" print(f\"Model {MODEL_NAME} already available\")\n",
106+
" \n",
84107
" except Exception as e:\n",
85108
" print(f\"Error checking model: {e}\")\n",
86109
"else:\n",
@@ -107,7 +130,7 @@
107130
"source": [
108131
"!pip -q install fastapi uvicorn mlflow --disable-pip-version-check\n",
109132
"\n",
110-
"import os, threading, time, json\n",
133+
"import os, subprocess, time, json, requests\n",
111134
"from pathlib import Path\n",
112135
"\n",
113136
"api_wrapper_code = '''\n",
@@ -128,7 +151,7 @@
128151
" pass\n",
129152
"\n",
130153
"app = FastAPI()\n",
131-
"RAMALAMA_HOST = os.getenv(\"RAMALAMA_HOST\", \"http://127.0.0.1:8080\")\n",
154+
"RAMALAMA_HOST = os.getenv(\"RAMALAMA_HOST\", \"http://ai-starter-kit-ramalama:8080\")\n",
132155
"MODEL_NAME = os.getenv(\"MODEL_NAME\", \"qwen2.5:1.5b\")\n",
133156
"\n",
134157
"@app.get(\"/v1/healthz\")\n",
@@ -206,32 +229,88 @@
206229
"with open('/tmp/ramalama_wrapper.py', 'w') as f:\n",
207230
" f.write(api_wrapper_code)\n",
208231
"\n",
209-
"def run_api():\n",
210-
" subprocess.run([\"python\", \"/tmp/ramalama_wrapper.py\"], capture_output=True)\n",
211-
"\n",
212-
"import subprocess\n",
213-
"api_process = subprocess.Popen(\n",
214-
" [\"python\", \"/tmp/ramalama_wrapper.py\"],\n",
215-
" env={**os.environ, \n",
216-
" \"RAMALAMA_HOST\": os.getenv(\"RAMALAMA_HOST\", \"http://127.0.0.1:8080\"),\n",
217-
" \"MODEL_NAME\": MODEL_NAME,\n",
218-
" \"MLFLOW_TRACKING_URI\": MLFLOW_URI},\n",
219-
" stdout=subprocess.DEVNULL,\n",
220-
" stderr=subprocess.DEVNULL\n",
221-
")\n",
232+
"print(\"Wrapper script created\")\n",
233+
"\n",
234+
"print(\"Killing existing wrapper processes...\")\n",
235+
"!pkill -f ramalama_wrapper.py 2>/dev/null || true\n",
236+
"time.sleep(2)\n",
222237
"\n",
223-
"time.sleep(3)\n",
238+
"log_file = '/tmp/ramalama_wrapper.log'\n",
239+
"!touch /tmp/ramalama_wrapper.log\n",
240+
"!chmod 666 /tmp/ramalama_wrapper.log\n",
241+
"print(\"Log file ready\")\n",
224242
"\n",
243+
"MODEL_NAME = \"qwen2.5:1.5b\"\n",
244+
"MLFLOW_URI = os.getenv(\"MLFLOW_TRACKING_URI\", \"http://ai-starter-kit-mlflow:5000\")\n",
245+
"RAMALAMA_HOST = os.getenv(\"RAMALAMA_HOST\", \"http://ai-starter-kit-ramalama:8080\")\n",
246+
"\n",
247+
"env_vars = {\n",
248+
" 'RAMALAMA_HOST': RAMALAMA_HOST,\n",
249+
" 'MODEL_NAME': MODEL_NAME,\n",
250+
" 'MLFLOW_TRACKING_URI': MLFLOW_URI\n",
251+
"}\n",
252+
"\n",
253+
"print(\"\\nEnvironment variables:\")\n",
254+
"for k, v in env_vars.items():\n",
255+
" print(f\" {k}={v}\")\n",
256+
"\n",
257+
"print(\"\\nStarting API wrapper...\")\n",
258+
"with open(log_file, 'w') as log:\n",
259+
" api_process = subprocess.Popen(\n",
260+
" [\"python\", \"/tmp/ramalama_wrapper.py\"],\n",
261+
" stdout=log,\n",
262+
" stderr=subprocess.STDOUT,\n",
263+
" env={**os.environ, **env_vars},\n",
264+
" start_new_session=True\n",
265+
" )\n",
266+
"\n",
267+
"print(f\"Process started with PID: {api_process.pid}\")\n",
268+
"\n",
269+
"time.sleep(2)\n",
270+
"if api_process.poll() is not None:\n",
271+
" print(f\"\\nERROR: Process died immediately with exit code {api_process.poll()}\")\n",
272+
" print(\"\\nLog contents:\")\n",
273+
" !cat /tmp/ramalama_wrapper.log\n",
274+
" raise Exception(\"API wrapper failed to start\")\n",
275+
"print(\"Process is running\")\n",
276+
"\n",
277+
"print(\"\\nWaiting for API to respond...\")\n",
225278
"API_URL = \"http://localhost:8000\"\n",
226-
"try:\n",
227-
" r = requests.get(f\"{API_URL}/v1/healthz\", timeout=5)\n",
228-
" print(\"API Status:\", r.json())\n",
229-
" print(f\"\\nOpenAI-compatible API running at: {API_URL}/v1\")\n",
230-
" print(f\"Health: {API_URL}/v1/healthz\")\n",
231-
" print(f\"Chat: {API_URL}/v1/chat/completions\")\n",
232-
"except Exception as e:\n",
233-
" print(f\"Warning: API wrapper not responding: {e}\")\n",
234-
" print(\"You may need to run the wrapper manually\")"
279+
"api_ready = False\n",
280+
"\n",
281+
"for i in range(30):\n",
282+
" time.sleep(1)\n",
283+
" try:\n",
284+
" r = requests.get(f\"{API_URL}/v1/healthz\", timeout=1)\n",
285+
" if r.status_code == 200:\n",
286+
" print(f\"\\nAPI is ready! Response: {r.json()}\")\n",
287+
" print(f\"\\nOpenAI-compatible API running at: {API_URL}/v1\")\n",
288+
" print(f\"Health: {API_URL}/v1/healthz\")\n",
289+
" print(f\"Chat: {API_URL}/v1/chat/completions\")\n",
290+
" api_ready = True\n",
291+
" break\n",
292+
" except requests.exceptions.ConnectionError:\n",
293+
" if i % 5 == 0:\n",
294+
" print(f\" Waiting for API... ({i}s)\")\n",
295+
" except Exception as e:\n",
296+
" if i % 10 == 0:\n",
297+
" print(f\" Unexpected error: {e}\")\n",
298+
"\n",
299+
"if not api_ready:\n",
300+
" print(\"\\nAPI wrapper failed to start within 30 seconds\")\n",
301+
" print(\"\\nChecking if process is still alive...\")\n",
302+
" if api_process.poll() is not None:\n",
303+
" print(f\"Process died with exit code: {api_process.poll()}\")\n",
304+
" else:\n",
305+
" print(\"Process is still running but not responding\")\n",
306+
" \n",
307+
" print(\"\\nLast 50 lines of logs:\")\n",
308+
" !tail -50 /tmp/ramalama_wrapper.log\n",
309+
" \n",
310+
" print(\"\\nChecking if port 8000 is in use:\")\n",
311+
" !netstat -tlnp 2>/dev/null | grep 8000 || echo \"No process on port 8000\"\n",
312+
" \n",
313+
" print(\"\\nNote: You can re-run this cell - the API might just need more time to start\")"
235314
]
236315
},
237316
{

ai/ai-starter-kit/helm-chart/ai-starter-kit/files/welcome.ipynb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,22 @@
55
"id": "5af4f666",
66
"metadata": {},
77
"source": [
8-
"Welcome Notebook - Notebook used to verify basic jupyterhub functionality and inference"
8+
"### Welcome Notebook - Notebook used to verify basic jupyterhub functionality and inference"
9+
]
10+
},
11+
{
12+
"cell_type": "markdown",
13+
"id": "c85b6901",
14+
"metadata": {},
15+
"source": [
16+
"**Purpose**: This notebook demonstrates semantic similarity search using the Qwen3-Embedding-0.6B model. It shows how to:\n",
17+
"\n",
18+
"1. Generate embeddings for search queries and documents.\n",
19+
"2. Use instructed queries (queries with task descriptions) to improve retrieval quality.\n",
20+
"3. Calculate similarity scores between queries and documents.\n",
21+
"4. Identify which documents are most relevant to which queries.\n",
22+
"\n",
23+
"Use Case: Testing embedding model functionality in your JupyterHub environment. The example compares two queries (\"What is the capital of China?\" and \"Explain gravity\") against two documents to find the best matches. High scores (like 0.76) indicate strong semantic similarity."
924
]
1025
},
1126
{

0 commit comments

Comments
 (0)