fix: improve error logging for chat model configuration issues (#458)
* docs: update CHANGELOG for v1.6.0 release * fix: improve error logging for chat model configuration issues (#358) - Add detailed error logging in provision.py when model lookup fails - Add warning logging in models.py when default model is not configured - Add traceback logging in chat router exception handler - Update Ollama docs with model name configuration guidance - Update troubleshooting docs with "Failed to send message" solutions - Bump version to 1.6.1 * chore: uvlock
This commit is contained in:
parent
09a0f786aa
commit
47c513edfd
8 changed files with 210 additions and 6 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
|
@ -5,18 +5,33 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [1.6.0] - 2026-01-16
|
## [1.6.1] - 2026-01-22
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- "Failed to send message" error with unhelpful logs when chat model is not configured (#358)
|
||||||
|
- Added detailed error logging with model selection context and full traceback
|
||||||
|
- Improved error messages to guide users to Settings → Models
|
||||||
|
- Added warnings when default models are not configured
|
||||||
|
|
||||||
|
### Docs
|
||||||
|
- Ollama troubleshooting: Added "Model Name Configuration" section emphasizing exact model names from `ollama list`
|
||||||
|
- Added troubleshooting entry for "Failed to send message" error with step-by-step solutions
|
||||||
|
- Updated AI Chat Issues documentation with model configuration guidance
|
||||||
|
|
||||||
|
## [1.6.0] - 2026-01-21
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Content-type aware text chunking with automatic HTML, Markdown, and plain text detection (#350, #142)
|
- Content-type aware text chunking with automatic HTML, Markdown, and plain text detection (#350, #142)
|
||||||
- Unified embedding generation with mean pooling for large content that exceeds model context limits
|
- Unified embedding generation with mean pooling for large content that exceeds model context limits
|
||||||
- Dedicated embedding commands: `embed_note`, `embed_insight`, `embed_source`
|
- Dedicated embedding commands: `embed_note`, `embed_insight`, `embed_source`
|
||||||
- New utility modules: `chunking.py` and `embedding.py` in `open_notebook/utils/`
|
- New utility modules: `chunking.py` and `embedding.py` in `open_notebook/utils/`
|
||||||
|
- Japanese (ja-JP) language support (#450)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Embedding is now fire-and-forget: domain models submit embedding commands asynchronously after save
|
- Embedding is now fire-and-forget: domain models submit embedding commands asynchronously after save
|
||||||
- `rebuild_embeddings_command` now delegates to individual embed_* commands instead of inline processing
|
- `rebuild_embeddings_command` now delegates to individual embed_* commands instead of inline processing
|
||||||
- Chunk size reduced to 1500 characters for better compatibility with Ollama embedding models
|
- Chunk size reduced to 1500 characters for better compatibility with Ollama embedding models
|
||||||
|
- Bump Esperanto to 2.16 for increased Ollama context window support
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Legacy embedding commands: `embed_single_item_command`, `embed_chunk_command`, `vectorize_source_command`
|
- Legacy embedding commands: `embed_single_item_command`, `embed_chunk_command`, `vectorize_source_command`
|
||||||
|
|
@ -25,6 +40,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Embedding failures when content exceeds model context limits (#350, #142)
|
- Embedding failures when content exceeds model context limits (#350, #142)
|
||||||
|
- Empty note titles when saving from chat (clean thinking tags from prompt graph output)
|
||||||
|
- Orphaned embedding/insight records when deleting sources (cascade delete)
|
||||||
|
- Search results crash with null parent_id (defensive frontend check)
|
||||||
|
- Database migration 10 cleans up existing orphaned records
|
||||||
|
|
||||||
## [1.5.2] - 2026-01-15
|
## [1.5.2] - 2026-01-15
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import traceback
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from fastapi import APIRouter, HTTPException, Query
|
from fastapi import APIRouter, HTTPException, Query
|
||||||
|
|
@ -381,7 +382,13 @@ async def execute_chat(request: ExecuteChatRequest):
|
||||||
except NotFoundError:
|
except NotFoundError:
|
||||||
raise HTTPException(status_code=404, detail="Session not found")
|
raise HTTPException(status_code=404, detail="Session not found")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error executing chat: {str(e)}")
|
# Log detailed error with context for debugging
|
||||||
|
logger.error(
|
||||||
|
f"Error executing chat: {str(e)}\n"
|
||||||
|
f" Session ID: {request.session_id}\n"
|
||||||
|
f" Model override: {request.model_override}\n"
|
||||||
|
f" Traceback:\n{traceback.format_exc()}"
|
||||||
|
)
|
||||||
raise HTTPException(status_code=500, detail=f"Error executing chat: {str(e)}")
|
raise HTTPException(status_code=500, detail=f"Error executing chat: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,45 @@ ollama pull qwen3
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Model Name Configuration (Critical)
|
||||||
|
|
||||||
|
**⚠️ IMPORTANT: Model names must exactly match the output of `ollama list`**
|
||||||
|
|
||||||
|
This is the most common cause of "Failed to send message" errors. Open Notebook requires the **exact model name** as it appears in Ollama.
|
||||||
|
|
||||||
|
**Step 1: Get the exact model name**
|
||||||
|
```bash
|
||||||
|
ollama list
|
||||||
|
```
|
||||||
|
|
||||||
|
Example output:
|
||||||
|
```
|
||||||
|
NAME ID SIZE MODIFIED
|
||||||
|
mxbai-embed-large:latest 468836162de7 669 MB 7 minutes ago
|
||||||
|
gemma3:12b f4031aab637d 8.1 GB 2 months ago
|
||||||
|
qwen3:32b 030ee887880f 20 GB 9 days ago
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Use the exact name when adding the model in Open Notebook**
|
||||||
|
|
||||||
|
| ✅ Correct | ❌ Wrong |
|
||||||
|
|-----------|----------|
|
||||||
|
| `gemma3:12b` | `gemma3` (missing tag) |
|
||||||
|
| `qwen3:32b` | `qwen3-32b` (wrong format) |
|
||||||
|
| `mxbai-embed-large:latest` | `mxbai-embed-large` (missing tag) |
|
||||||
|
|
||||||
|
**Note:** Some models use `:latest` as the default tag. If `ollama list` shows `model:latest`, you must use `model:latest` in Open Notebook, not just `model`.
|
||||||
|
|
||||||
|
**Step 3: Configure in Open Notebook**
|
||||||
|
|
||||||
|
1. Go to **Settings → Models**
|
||||||
|
2. Click **Add Model**
|
||||||
|
3. Enter the **exact name** from `ollama list`
|
||||||
|
4. Select provider: `ollama`
|
||||||
|
5. Select type: `language` (for chat) or `embedding` (for search)
|
||||||
|
6. Save the model
|
||||||
|
7. Set it as the default for the appropriate task (chat, transformation, etc.)
|
||||||
|
|
||||||
### Common Issues
|
### Common Issues
|
||||||
|
|
||||||
**1. "Ollama unavailable" in Open Notebook**
|
**1. "Ollama unavailable" in Open Notebook**
|
||||||
|
|
@ -324,6 +363,50 @@ OLLAMA_HOST=0.0.0.0:8080 ollama serve
|
||||||
export OLLAMA_API_BASE=http://localhost:8080
|
export OLLAMA_API_BASE=http://localhost:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**6. "Failed to send message" in Chat**
|
||||||
|
|
||||||
|
**Symptom:** Chat shows "Failed to send message" toast notification. Logs may show:
|
||||||
|
```
|
||||||
|
Error executing chat: Model is not a LanguageModel: None
|
||||||
|
```
|
||||||
|
|
||||||
|
**Causes (in order of likelihood):**
|
||||||
|
|
||||||
|
1. **Model name mismatch**: The model name in Open Notebook doesn't exactly match `ollama list`
|
||||||
|
2. **No default model configured**: You haven't set a default chat model in Settings → Models
|
||||||
|
3. **Model was deleted**: You removed the model from Ollama but didn't update Open Notebook's defaults
|
||||||
|
4. **Model record deleted**: The model was removed from Open Notebook but is still set as default
|
||||||
|
|
||||||
|
**Solutions:**
|
||||||
|
|
||||||
|
**Check 1: Verify model names match exactly**
|
||||||
|
```bash
|
||||||
|
# Get exact model names from Ollama
|
||||||
|
ollama list
|
||||||
|
|
||||||
|
# Compare with what's configured in Open Notebook
|
||||||
|
# Go to Settings → Models and verify the names match EXACTLY
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check 2: Verify default models are set**
|
||||||
|
1. Go to **Settings → Models**
|
||||||
|
2. Scroll to **Default Models** section
|
||||||
|
3. Ensure **Default Chat Model** has a value selected
|
||||||
|
4. If empty, select an available language model
|
||||||
|
|
||||||
|
**Check 3: Refresh after changes**
|
||||||
|
If you've added/removed models in Ollama:
|
||||||
|
1. Refresh the Open Notebook page
|
||||||
|
2. Go to Settings → Models
|
||||||
|
3. Re-add any missing models with exact names from `ollama list`
|
||||||
|
4. Re-select default models if needed
|
||||||
|
|
||||||
|
**Check 4: Test the model directly**
|
||||||
|
```bash
|
||||||
|
# Verify Ollama can use the model
|
||||||
|
ollama run gemma3:12b "Hello, world"
|
||||||
|
```
|
||||||
|
|
||||||
### Docker-Specific Troubleshooting
|
### Docker-Specific Troubleshooting
|
||||||
|
|
||||||
**1. Host networking on Linux:**
|
**1. Host networking on Linux:**
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,61 @@ Problems with AI models, chat, and response quality.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## "Failed to send message" Error
|
||||||
|
|
||||||
|
**Symptom:** Chat shows "Failed to send message" toast. Logs show:
|
||||||
|
```
|
||||||
|
Error executing chat: Model is not a LanguageModel: None
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cause:** No valid language model configured for chat
|
||||||
|
|
||||||
|
**Solutions:**
|
||||||
|
|
||||||
|
### Solution 1: Check Default Model Configuration
|
||||||
|
```
|
||||||
|
1. Go to Settings → Models
|
||||||
|
2. Scroll to "Default Models" section
|
||||||
|
3. Verify "Default Chat Model" has a model selected
|
||||||
|
4. If empty, select an available language model
|
||||||
|
5. Click Save
|
||||||
|
```
|
||||||
|
|
||||||
|
### Solution 2: Verify Model Names (Ollama Users)
|
||||||
|
```bash
|
||||||
|
# Get exact model names
|
||||||
|
ollama list
|
||||||
|
|
||||||
|
# Example output:
|
||||||
|
# NAME SIZE MODIFIED
|
||||||
|
# gemma3:12b 8.1 GB 2 months ago
|
||||||
|
|
||||||
|
# The model name in Open Notebook must be EXACTLY "gemma3:12b"
|
||||||
|
# NOT "gemma3" or "gemma3-12b"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Solution 3: Re-add Missing Models
|
||||||
|
```
|
||||||
|
1. Note the exact model names from your provider
|
||||||
|
2. Go to Settings → Models
|
||||||
|
3. Delete any misconfigured models
|
||||||
|
4. Add models with exact names
|
||||||
|
5. Set new defaults
|
||||||
|
```
|
||||||
|
|
||||||
|
### Solution 4: Check Model Still Exists
|
||||||
|
```bash
|
||||||
|
# For Ollama: verify model is installed
|
||||||
|
ollama list
|
||||||
|
|
||||||
|
# For cloud providers: verify API key is valid
|
||||||
|
# and you have access to the model
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Tip:** This error often occurs when you delete a model from Ollama but forget to update the default models in Open Notebook. Always re-configure defaults after removing models.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## "Models not available" or "Models not showing"
|
## "Models not available" or "Models not showing"
|
||||||
|
|
||||||
**Symptom:** Settings → Models shows empty, or "No models configured"
|
**Symptom:** Settings → Models shows empty, or "No models configured"
|
||||||
|
|
|
||||||
|
|
@ -187,9 +187,21 @@ class ModelManager:
|
||||||
model_id = defaults.large_context_model
|
model_id = defaults.large_context_model
|
||||||
|
|
||||||
if not model_id:
|
if not model_id:
|
||||||
|
logger.warning(
|
||||||
|
f"No default model configured for type '{model_type}'. "
|
||||||
|
f"Please go to Settings → Models and set a default model."
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return await self.get_model(model_id, **kwargs)
|
try:
|
||||||
|
return await self.get_model(model_id, **kwargs)
|
||||||
|
except ValueError as e:
|
||||||
|
logger.error(
|
||||||
|
f"Failed to load default model for type '{model_type}': {e}. "
|
||||||
|
f"The configured model_id '{model_id}' may have been deleted or misconfigured. "
|
||||||
|
f"Please go to Settings → Models and reconfigure the default model."
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
model_manager = ModelManager()
|
model_manager = ModelManager()
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,45 @@ async def provision_langchain_model(
|
||||||
Otherwise, returns the default model for the given type
|
Otherwise, returns the default model for the given type
|
||||||
"""
|
"""
|
||||||
tokens = token_count(content)
|
tokens = token_count(content)
|
||||||
|
model = None
|
||||||
|
selection_reason = ""
|
||||||
|
|
||||||
if tokens > 105_000:
|
if tokens > 105_000:
|
||||||
|
selection_reason = f"large_context (content has {tokens} tokens)"
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Using large context model because the content has {tokens} tokens"
|
f"Using large context model because the content has {tokens} tokens"
|
||||||
)
|
)
|
||||||
model = await model_manager.get_default_model("large_context", **kwargs)
|
model = await model_manager.get_default_model("large_context", **kwargs)
|
||||||
elif model_id:
|
elif model_id:
|
||||||
|
selection_reason = f"explicit model_id={model_id}"
|
||||||
model = await model_manager.get_model(model_id, **kwargs)
|
model = await model_manager.get_model(model_id, **kwargs)
|
||||||
else:
|
else:
|
||||||
|
selection_reason = f"default for type={default_type}"
|
||||||
model = await model_manager.get_default_model(default_type, **kwargs)
|
model = await model_manager.get_default_model(default_type, **kwargs)
|
||||||
|
|
||||||
logger.debug(f"Using model: {model}")
|
logger.debug(f"Using model: {model}")
|
||||||
assert isinstance(model, LanguageModel), f"Model is not a LanguageModel: {model}"
|
|
||||||
|
if model is None:
|
||||||
|
logger.error(
|
||||||
|
f"Model provisioning failed: No model found. "
|
||||||
|
f"Selection reason: {selection_reason}. "
|
||||||
|
f"model_id={model_id}, default_type={default_type}. "
|
||||||
|
f"Please check Settings → Models and ensure a default model is configured for '{default_type}'."
|
||||||
|
)
|
||||||
|
raise ValueError(
|
||||||
|
f"No model configured for {selection_reason}. "
|
||||||
|
f"Please go to Settings → Models and configure a default model for '{default_type}'."
|
||||||
|
)
|
||||||
|
|
||||||
|
if not isinstance(model, LanguageModel):
|
||||||
|
logger.error(
|
||||||
|
f"Model type mismatch: Expected LanguageModel but got {type(model).__name__}. "
|
||||||
|
f"Selection reason: {selection_reason}. "
|
||||||
|
f"model_id={model_id}, default_type={default_type}."
|
||||||
|
)
|
||||||
|
raise ValueError(
|
||||||
|
f"Model is not a LanguageModel: {model}. "
|
||||||
|
f"Please check that the model configured for '{default_type}' is a language model, not an embedding or speech model."
|
||||||
|
)
|
||||||
|
|
||||||
return model.to_langchain()
|
return model.to_langchain()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "open-notebook"
|
name = "open-notebook"
|
||||||
version = "1.6.0"
|
version = "1.6.1"
|
||||||
description = "An open source implementation of a research assistant, inspired by Google Notebook LM"
|
description = "An open source implementation of a research assistant, inspired by Google Notebook LM"
|
||||||
authors = [
|
authors = [
|
||||||
{name = "Luis Novo", email = "lfnovo@gmail.com"}
|
{name = "Luis Novo", email = "lfnovo@gmail.com"}
|
||||||
|
|
|
||||||
2
uv.lock
2
uv.lock
|
|
@ -2376,7 +2376,7 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "open-notebook"
|
name = "open-notebook"
|
||||||
version = "1.6.0"
|
version = "1.6.1"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "ai-prompter" },
|
{ name = "ai-prompter" },
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue