Skip to content

Commit 8f8e119

Browse files
committed
Enhanced AI diagnostics for better CI troubleshooting
- Added detailed connectivity and model availability testing to OllamaClient - Enhanced error reporting with step-by-step diagnostics - Improved GitHub Actions workflows with model pull retry logic - Added comprehensive diagnostic output to test classes - Better visibility into Ollama connection issues in CI
1 parent 844d6d8 commit 8f8e119

File tree

5 files changed

+187
-17
lines changed

5 files changed

+187
-17
lines changed

.github/workflows/ai-testing.yml

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -174,18 +174,40 @@ jobs:
174174
175175
- name: Pull AI model
176176
run: |
177-
# Pull a smaller, faster model for CI with timeout
177+
# Pull a smaller, faster model for CI with enhanced retry logic
178178
echo "📥 Pulling tinyllama model..."
179-
timeout 300 ollama pull tinyllama || {
180-
echo "❌ Failed to pull tinyllama, trying phi3-mini"
181-
timeout 300 ollama pull phi3-mini || {
182-
echo "❌ Model pull failed, using existing models"
183-
ollama list
184-
}
185-
}
186179
187-
echo "📋 Available models:"
180+
# Try pulling tinyllama with retries
181+
for attempt in {1..3}; do
182+
echo "Attempt $attempt to pull tinyllama..."
183+
if timeout 300 ollama pull tinyllama; then
184+
echo "✅ Successfully pulled tinyllama on attempt $attempt"
185+
break
186+
else
187+
echo "❌ Failed to pull tinyllama on attempt $attempt"
188+
if [ $attempt -eq 3 ]; then
189+
echo "⚠️ All attempts failed, trying alternative model"
190+
timeout 300 ollama pull phi3-mini || {
191+
echo "❌ Alternative model pull also failed"
192+
ollama list
193+
}
194+
fi
195+
sleep 10
196+
fi
197+
done
198+
199+
echo "📋 Available models after pull:"
188200
ollama list
201+
202+
# Verify the model is actually usable
203+
echo "🧪 Testing model functionality:"
204+
if ollama list | grep -q "tinyllama"; then
205+
ollama run tinyllama "Say OK" || echo "⚠️ tinyllama test failed"
206+
elif ollama list | grep -q "phi3-mini"; then
207+
ollama run phi3-mini "Say OK" || echo "⚠️ phi3-mini test failed"
208+
else
209+
echo "❌ No suitable models available"
210+
fi
189211
190212
- name: Verify Ollama setup
191213
run: |

.github/workflows/fast-ai-test.yml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,33 @@ jobs:
7878
sleep 2
7979
done
8080
81-
# Pull tiny model for speed
81+
# Pull tiny model for speed with enhanced retry
8282
echo "📥 Pulling tinyllama..."
83-
timeout 180 ollama pull tinyllama
83+
84+
for attempt in {1..2}; do
85+
echo "Attempt $attempt to pull tinyllama..."
86+
if timeout 180 ollama pull tinyllama; then
87+
echo "✅ Successfully pulled tinyllama on attempt $attempt"
88+
break
89+
else
90+
echo "❌ Failed on attempt $attempt"
91+
if [ $attempt -eq 2 ]; then
92+
echo "⚠️ Using any available models"
93+
fi
94+
sleep 5
95+
fi
96+
done
8497
8598
echo "📋 Models available:"
8699
ollama list
100+
101+
# Test model functionality
102+
echo "🧪 Testing model:"
103+
if ollama list | grep -q "tinyllama"; then
104+
ollama run tinyllama "Say OK"
105+
else
106+
echo "⚠️ tinyllama not available"
107+
fi
87108
88109
- name: Run Fast AI Test
89110
run: |

src/main/java/org/k11techlab/framework/ai/ollama/OllamaClient.java

Lines changed: 129 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
44
import org.apache.hc.client5.http.impl.classic.HttpClients;
55
import org.apache.hc.client5.http.classic.methods.HttpPost;
6+
import org.apache.hc.client5.http.classic.methods.HttpGet;
67
import org.apache.hc.core5.http.io.entity.StringEntity;
78
import org.apache.hc.core5.http.ClassicHttpResponse;
89
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
@@ -147,27 +148,149 @@ private String callOllama(String prompt) throws IOException {
147148
}
148149

149150
/**
150-
* Test connection to Ollama
151+
* Test connection to Ollama with enhanced diagnostics
151152
*/
152153
public boolean isAvailable() {
153154
try {
155+
Log.info("🔍 AI availability check starting...");
156+
System.out.println("🔍 Testing Ollama connection to: " + baseUrl + " with model: " + model);
157+
158+
// First, test basic connectivity
159+
if (!testBasicConnectivity()) {
160+
System.out.println("❌ Basic connectivity failed to Ollama service");
161+
return false;
162+
}
163+
164+
// Then test model availability
165+
if (!testModelAvailability()) {
166+
System.out.println("❌ Model '" + model + "' not available");
167+
return false;
168+
}
169+
170+
// Finally, test actual generation
154171
Log.info("Quick AI availability check for model: " + model);
155-
// Quick test with very short prompt
156172
String response = callOllama("Say OK");
157173
boolean available = response != null && response.toLowerCase().contains("ok");
158-
Log.info("AI availability: " + available + " (model: " + model + ")");
174+
175+
if (available) {
176+
Log.info("✅ AI availability: " + available + " (model: " + model + ")");
177+
System.out.println("✅ Ollama AI fully operational with model: " + model);
178+
} else {
179+
Log.info("❌ AI generation test failed (model: " + model + ")");
180+
System.out.println("❌ AI generation test failed - response: " + response);
181+
}
182+
159183
return available;
160184
} catch (Exception e) {
161-
Log.info("AI not available: " + e.getMessage() + " (model: " + model + ")");
185+
String error = "AI not available: " + e.getMessage() + " (model: " + model + ")";
186+
Log.info(error);
187+
System.out.println("❌ " + error);
188+
e.printStackTrace();
189+
return false;
190+
}
191+
}
192+
193+
/**
194+
* Test basic connectivity to Ollama service
195+
*/
196+
private boolean testBasicConnectivity() {
197+
try {
198+
HttpGet get = new HttpGet(baseUrl + "/api/tags");
199+
200+
org.apache.hc.client5.http.config.RequestConfig requestConfig =
201+
org.apache.hc.client5.http.config.RequestConfig.custom()
202+
.setConnectionRequestTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
203+
.setResponseTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
204+
.build();
205+
get.setConfig(requestConfig);
206+
207+
HttpClientResponseHandler<Boolean> responseHandler = response -> {
208+
int status = response.getCode();
209+
System.out.println("🔗 Ollama connectivity test - Status: " + status);
210+
return status >= 200 && status < 300;
211+
};
212+
213+
return httpClient.execute(get, responseHandler);
214+
} catch (Exception e) {
215+
System.out.println("🔗 Connectivity test failed: " + e.getMessage());
162216
return false;
163217
}
164218
}
165219

166220
/**
167-
* Get client status
221+
* Test if the specified model is available
222+
*/
223+
private boolean testModelAvailability() {
224+
try {
225+
HttpGet get = new HttpGet(baseUrl + "/api/tags");
226+
227+
HttpClientResponseHandler<Boolean> responseHandler = response -> {
228+
try {
229+
String responseBody = EntityUtils.toString(response.getEntity());
230+
System.out.println("📋 Available models response: " + responseBody);
231+
232+
JsonNode jsonResponse = objectMapper.readTree(responseBody);
233+
JsonNode models = jsonResponse.get("models");
234+
235+
if (models != null && models.isArray()) {
236+
for (JsonNode modelNode : models) {
237+
String modelName = modelNode.get("name").asText();
238+
System.out.println("📦 Found model: " + modelName);
239+
if (modelName.startsWith(model)) {
240+
System.out.println("✅ Target model '" + model + "' found!");
241+
return true;
242+
}
243+
}
244+
}
245+
246+
System.out.println("❌ Target model '" + model + "' not found in available models");
247+
return false;
248+
249+
} catch (Exception e) {
250+
System.out.println("❌ Failed to parse models response: " + e.getMessage());
251+
return false;
252+
}
253+
};
254+
255+
return httpClient.execute(get, responseHandler);
256+
} catch (Exception e) {
257+
System.out.println("📋 Model availability test failed: " + e.getMessage());
258+
return false;
259+
}
260+
}
261+
262+
/**
263+
* Get client status with detailed information
168264
*/
169265
public String getStatus() {
170-
return "OllamaClient - Model: " + model + ", Available: " + isAvailable();
266+
try {
267+
boolean available = isAvailable();
268+
return String.format("OllamaClient - URL: %s, Model: %s, Available: %s",
269+
baseUrl, model, available);
270+
} catch (Exception e) {
271+
return String.format("OllamaClient - URL: %s, Model: %s, Error: %s",
272+
baseUrl, model, e.getMessage());
273+
}
274+
}
275+
276+
/**
277+
* Get detailed diagnostic information
278+
*/
279+
public String getDiagnostics() {
280+
StringBuilder diag = new StringBuilder();
281+
diag.append("=== OLLAMA CLIENT DIAGNOSTICS ===\n");
282+
diag.append("Base URL: ").append(baseUrl).append("\n");
283+
diag.append("Target Model: ").append(model).append("\n");
284+
285+
try {
286+
diag.append("Basic Connectivity: ").append(testBasicConnectivity() ? "✅ OK" : "❌ FAILED").append("\n");
287+
diag.append("Model Available: ").append(testModelAvailability() ? "✅ OK" : "❌ FAILED").append("\n");
288+
} catch (Exception e) {
289+
diag.append("Diagnostics Error: ").append(e.getMessage()).append("\n");
290+
}
291+
292+
diag.append("===============================");
293+
return diag.toString();
171294
}
172295

173296
/**

src/test/java/org/k11techlab/framework_unittests/aiTests/FullAIDemo.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ public void setup() {
4242
} else {
4343
Log.info("⚠️ Ollama not available, using fallback client");
4444
System.out.println("⚠️ AI NOT AVAILABLE - using fallback client");
45+
46+
// Show detailed diagnostics when AI is not available
47+
System.out.println("\n" + ollamaClient.getDiagnostics());
4548
}
4649
System.out.println("=== SETUP COMPLETE ===");
4750

src/test/java/org/k11techlab/framework_unittests/aiTests/QuickAITest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public void testQuickAISuggestion() {
7272
System.out.println("❌ AI client is null");
7373
} else {
7474
System.out.println("❌ AI client not available: " + aiClient.getStatus());
75+
System.out.println("\n" + aiClient.getDiagnostics());
7576
}
7677
}
7778
System.out.println("=== QUICK AI TEST COMPLETE ===");

0 commit comments

Comments
 (0)