Skip to content

Commit 9f3a5e2

Browse files
authored
feat: add model existence check for Ollama integration (#227)
- Introduced a new function `check_ollama_model_exists` to verify the availability of specified Ollama models before usage. - Added a custom exception `OllamaModelNotFoundError` for better error handling. - Updated the RAG component to raise an exception if the required Ollama model is not found. - Enhanced error handling in the UI to display specific messages related to embedding model issues.
1 parent 559742e commit 9f3a5e2

File tree

11 files changed

+88
-2
lines changed

11 files changed

+88
-2
lines changed

api/ollama_patch.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,60 @@
55
import adalflow as adal
66
from adalflow.core.types import Document
77
from adalflow.core.component import DataComponent
8+
import requests
9+
import os
810

911
# Configure logging
1012
from api.logging_config import setup_logging
1113

1214
setup_logging()
1315
logger = logging.getLogger(__name__)
1416

17+
class OllamaModelNotFoundError(Exception):
18+
"""Custom exception for when Ollama model is not found"""
19+
pass
20+
21+
def check_ollama_model_exists(model_name: str, ollama_host: str = None) -> bool:
22+
"""
23+
Check if an Ollama model exists before attempting to use it.
24+
25+
Args:
26+
model_name: Name of the model to check
27+
ollama_host: Ollama host URL, defaults to localhost:11434
28+
29+
Returns:
30+
bool: True if model exists, False otherwise
31+
"""
32+
if ollama_host is None:
33+
ollama_host = os.getenv("OLLAMA_HOST", "http://localhost:11434")
34+
35+
try:
36+
# Remove /api prefix if present and add it back
37+
if ollama_host.endswith('/api'):
38+
ollama_host = ollama_host[:-4]
39+
40+
response = requests.get(f"{ollama_host}/api/tags", timeout=5)
41+
if response.status_code == 200:
42+
models_data = response.json()
43+
available_models = [model.get('name', '').split(':')[0] for model in models_data.get('models', [])]
44+
model_base_name = model_name.split(':')[0] # Remove tag if present
45+
46+
is_available = model_base_name in available_models
47+
if is_available:
48+
logger.info(f"Ollama model '{model_name}' is available")
49+
else:
50+
logger.warning(f"Ollama model '{model_name}' is not available. Available models: {available_models}")
51+
return is_available
52+
else:
53+
logger.warning(f"Could not check Ollama models, status code: {response.status_code}")
54+
return False
55+
except requests.exceptions.RequestException as e:
56+
logger.warning(f"Could not connect to Ollama to check models: {e}")
57+
return False
58+
except Exception as e:
59+
logger.warning(f"Error checking Ollama model availability: {e}")
60+
return False
61+
1562
class OllamaDocumentProcessor(DataComponent):
1663
"""
1764
Process documents for Ollama embeddings by processing one document at a time.

api/rag.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,17 @@ def __init__(self, provider="google", model=None, use_s3: bool = False): # noqa
227227
# Determine if we're using Ollama embedder based on configuration
228228
self.is_ollama_embedder = is_ollama_embedder()
229229

230+
# Check if Ollama model exists before proceeding
231+
if self.is_ollama_embedder:
232+
from api.ollama_patch import check_ollama_model_exists
233+
from api.config import get_embedder_config
234+
235+
embedder_config = get_embedder_config()
236+
if embedder_config and embedder_config.get("model_kwargs", {}).get("model"):
237+
model_name = embedder_config["model_kwargs"]["model"]
238+
if not check_ollama_model_exists(model_name):
239+
raise Exception(f"Ollama model '{model_name}' not found. Please run 'ollama pull {model_name}' to install it.")
240+
230241
# Initialize components
231242
self.memory = Memory()
232243
self.embedder = get_embedder()

src/app/[owner]/[repo]/page.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ export default function RepoWikiPage() {
214214
const [requestInProgress, setRequestInProgress] = useState(false);
215215
const [currentToken, setCurrentToken] = useState(token); // Track current effective token
216216
const [effectiveRepoInfo, setEffectiveRepoInfo] = useState(repoInfo); // Track effective repo info with cached data
217+
const [embeddingError, setEmbeddingError] = useState(false);
217218

218219
// Model selection state variables
219220
const [selectedProviderState, setSelectedProviderState] = useState(providerParam);
@@ -597,6 +598,7 @@ Remember:
597598
if (!owner || !repo) {
598599
setError('Invalid repository information. Owner and repo name are required.');
599600
setIsLoading(false);
601+
setEmbeddingError(false); // Reset embedding error state
600602
return;
601603
}
602604

@@ -836,7 +838,17 @@ IMPORTANT:
836838
}
837839
}
838840

839-
// Clean up markdown delimiters
841+
if(responseText.includes('Error preparing retriever: Environment variable OPENAI_API_KEY must be set')) {
842+
setEmbeddingError(true);
843+
throw new Error('OPENAI_API_KEY environment variable is not set. Please configure your OpenAI API key.');
844+
}
845+
846+
if(responseText.includes('Ollama model') && responseText.includes('not found')) {
847+
setEmbeddingError(true);
848+
throw new Error('The specified Ollama embedding model was not found. Please ensure the model is installed locally or select a different embedding model in the configuration.');
849+
}
850+
851+
// Clean up markdown delimiters
840852
responseText = responseText.replace(/^```(?:xml)?\s*/i, '').replace(/```\s*$/i, '');
841853

842854
// Extract wiki structure from response
@@ -1074,6 +1086,7 @@ IMPORTANT:
10741086
setGeneratedPages({});
10751087
setPagesInProgress(new Set());
10761088
setError(null);
1089+
setEmbeddingError(false); // Reset embedding error state
10771090

10781091
try {
10791092
// Set the request in progress flag
@@ -1471,6 +1484,7 @@ IMPORTANT:
14711484
} catch (err) {
14721485
console.warn('Error calling DELETE /api/wiki_cache:', err);
14731486
setIsLoading(false);
1487+
setEmbeddingError(false); // Reset embedding error state
14741488
// Optionally, inform the user about the cache clear error
14751489
// setError(\`Error clearing cache: ${err instanceof Error ? err.message : String(err)}. Trying to refresh...\`);
14761490
throw err;
@@ -1503,6 +1517,7 @@ IMPORTANT:
15031517
setGeneratedPages({});
15041518
setPagesInProgress(new Set());
15051519
setError(null);
1520+
setEmbeddingError(false); // Reset embedding error state
15061521
setIsLoading(true); // Set loading state for refresh
15071522
setLoadingMessage(messages.loading?.initializing || 'Initializing wiki generation...');
15081523

@@ -1680,6 +1695,7 @@ IMPORTANT:
16801695
setGeneratedPages(cachedData.generated_pages);
16811696
setCurrentPageId(cachedStructure.pages.length > 0 ? cachedStructure.pages[0].id : undefined);
16821697
setIsLoading(false);
1698+
setEmbeddingError(false);
16831699
setLoadingMessage(undefined);
16841700
cacheLoadedSuccessfully.current = true;
16851701
return; // Exit if cache is successfully loaded
@@ -1858,7 +1874,11 @@ IMPORTANT:
18581874
</div>
18591875
<p className="text-[var(--foreground)] text-sm mb-3">{error}</p>
18601876
<p className="text-[var(--muted)] text-xs">
1861-
{messages.repoPage?.errorMessageDefault || 'Please check that your repository exists and is public. Valid formats are "owner/repo", "https://github.com/owner/repo", "https://gitlab.com/owner/repo", "https://bitbucket.org/owner/repo", or local folder paths like "C:\\path\\to\\folder" or "/path/to/folder".'}
1877+
{embeddingError ? (
1878+
messages.repoPage?.embeddingErrorDefault || 'This error is related to the document embedding system used for analyzing your repository. Please verify your embedding model configuration, API keys, and try again. If the issue persists, consider switching to a different embedding provider in the model settings.'
1879+
) : (
1880+
messages.repoPage?.errorMessageDefault || 'Please check that your repository exists and is public. Valid formats are "owner/repo", "https://github.com/owner/repo", "https://gitlab.com/owner/repo", "https://bitbucket.org/owner/repo", or local folder paths like "C:\\path\\to\\folder" or "/path/to/folder".'
1881+
)}
18621882
</p>
18631883
<div className="mt-5">
18641884
<Link

src/messages/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
"home": "Home",
113113
"errorTitle": "Error",
114114
"errorMessageDefault": "Please check that your repository exists and is public. Valid formats are \"owner/repo\", \"https://github.com/owner/repo\", \"https://gitlab.com/owner/repo\", \"https://bitbucket.org/owner/repo\", or local folder paths like \"C:\\\\path\\\\to\\\\folder\" or \"/path/to/folder\".",
115+
"embeddingErrorDefault": "This error is related to the document embedding system used for analyzing your repository. Please verify your embedding model configuration, API keys, and try again. If the issue persists, consider switching to a different embedding provider in the model settings.",
115116
"backToHome": "Back to Home",
116117
"exportWiki": "Export Wiki",
117118
"exportAsMarkdown": "Export as Markdown",

src/messages/es.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
"home": "Inicio",
104104
"errorTitle": "Error",
105105
"errorMessageDefault": "Por favor, compruebe que su repositorio existe y es público. Los formatos válidos son \"owner/repo\", \"https://github.com/owner/repo\", \"https://gitlab.com/owner/repo\", \"https://bitbucket.org/owner/repo\", o rutas de carpetas locales como \"C:\\\\path\\\\to\\\\folder\" o \"/path/to/folder\".",
106+
"embeddingErrorDefault": "Este error está relacionado con el sistema de embebido utilizado para analizar su repositorio. Por favor, verifique la configuración del modelo de embebido, las claves de API y vuelva a intentarlo. Si el problema persiste, considere cambiar al proveedor de embebido diferente en la configuración del modelo.",
106107
"backToHome": "Volver al Inicio",
107108
"exportWiki": "Exportar Wiki",
108109
"exportAsMarkdown": "Exportar como Markdown",

src/messages/ja.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
"home": "ホーム",
104104
"errorTitle": "エラー",
105105
"errorMessageDefault": "リポジトリが存在し、公開されていることを確認してください。有効な形式は「owner/repo」、「https://github.com/owner/repo」、「https://gitlab.com/owner/repo」、「https://bitbucket.org/owner/repo」、またはローカルフォルダパス(例: 「C:\\\\path\\\\to\\\\folder」、「/path/to/folder」)です。",
106+
"embeddingErrorDefault": "このエラーは、リポジトリを分析するために使用されるドキュメント埋め込みシステムに関連しています。モデル設定で異なる埋め込みプロバイダーを試してみてください。",
106107
"backToHome": "ホームに戻る",
107108
"exportWiki": "Wikiをエクスポート",
108109
"exportAsMarkdown": "Markdownとしてエクスポート",

src/messages/kr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
"home": "",
104104
"errorTitle": "오류",
105105
"errorMessageDefault": "저장소가 존재하며 공개 상태인지 확인해 주세요. 유효한 형식은 \"owner/repo\", \"https://github.com/owner/repo\", \"https://gitlab.com/owner/repo\", \"https://bitbucket.org/owner/repo\" 또는 로컬 폴더 경로 \"C:\\\\path\\\\to\\\\folder\" 혹은 \"/path/to/folder\" 입니다.",
106+
"embeddingErrorDefault": "이 오류는 저장소를 분석하는 데 사용되는 문서 임베딩 시스템과 관련이 있습니다. 임베딩 모델 설정에서 다른 임베딩 제공자를 시도해 보세요. 문제가 지속되면 모델 설정에서 다른 임베딩 제공자를 변경해 보세요.",
106107
"backToHome": "홈으로 돌아가기",
107108
"exportWiki": "위키 내보내기",
108109
"exportAsMarkdown": "마크다운으로 내보내기",

src/messages/pt-br.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
"home": "Início",
113113
"errorTitle": "Erro",
114114
"errorMessageDefault": "Verifique se o seu repositório existe e é público. Formatos válidos são \"proprietário/repo\", \"https://github.com/proprietário/repo\", \"https://gitlab.com/proprietário/repo\", \"https://bitbucket.org/proprietário/repo\", ou caminhos de pastas locais como \"C:\\\\caminho\\\\para\\\\pasta\" ou \"/caminho/para/pasta\".",
115+
"embeddingErrorDefault": "Este erro está relacionado com o sistema de embebimento utilizado para analisar o seu repositório. Verifique a configuração do modelo de embebimento, as chaves de API e tente novamente. Se o problema persistir, considere mudar para um provedor de embebimento diferente na configuração do modelo.",
115116
"backToHome": "Voltar ao Início",
116117
"exportWiki": "Exportar Wiki",
117118
"exportAsMarkdown": "Exportar como Markdown",

src/messages/vi.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
"home": "Trang chủ",
104104
"errorTitle": "Lỗi",
105105
"errorMessageDefault": "Vui lòng kiểm tra xem repository có tồn tại và công khai hay không. Các định dạng hợp lệ là \"owner/repo\", \"https://github.com/owner/repo\", \"https://gitlab.com/owner/repo\", \"https://bitbucket.org/owner/repo\", hoặc các đường dẫn thư mục cục bộ như \"C:\\\\path\\\\to\\\\folder\" hoặc \"/path/to/folder\".",
106+
"embeddingErrorDefault": "Lỗi này liên quan đến hệ thống embedding được sử dụng để phân tích repository của bạn. Vui lòng kiểm tra cấu hình mô hình embedding, API keys và thử lại. Nếu vấn đề vẫn tiếp diễn, hãy xem xét chuyển sang nhà cung cấp embedding khác trong cấu hình mô hình.",
106107
"backToHome": "Quay lại trang chủ",
107108
"exportWiki": "Xuất Wiki",
108109
"exportAsMarkdown": "Xuất dưới dạng Markdown",

src/messages/zh-tw.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
"home": "首頁",
102102
"errorTitle": "錯誤",
103103
"errorMessageDefault": "請檢查您的儲存庫是否存在且為公開儲存庫。有效格式為 \"owner/repo\"\"https://github.com/owner/repo\"\"https://gitlab.com/owner/repo\"\"https://bitbucket.org/owner/repo\",或本機資料夾路徑,如 \"C:\\\\path\\\\to\\\\folder\"\"/path/to/folder\"",
104+
"embeddingErrorDefault": "這個錯誤與用於分析您的儲存庫的文件嵌入系統有關。請檢查您的嵌入模型配置、API 密鑰,並重試。如果問題持續存在,請考慮在模型設置中切換到不同的嵌入提供者。",
104105
"backToHome": "返回首頁",
105106
"exportWiki": "匯出 Wiki",
106107
"exportAsMarkdown": "匯出為 Markdown",

0 commit comments

Comments
 (0)