How Open Notebook Integrates the Esperanto Library with 18+ AI Providers (Including Ollama and LM Studio)

Open Notebook uses a centralized ModelManager class in open_notebook/ai/models.py to normalize provider configurations and route all AI requests through the Esperanto library's AIFactory, enabling seamless support for over 18 providers including local servers like Ollama and LM Studio.

The lfnovo/open-notebook repository leverages the Esperanto library to abstract away provider-specific implementation details, allowing users to switch between cloud APIs and local LLM servers without code changes. This integration handles everything from credential management to model discovery, supporting diverse AI capabilities including chat completion, embeddings, speech-to-text, and text-to-speech across more than 18 different providers.

Provider-Agnostic Architecture via ModelManager

The integration centers on the ModelManager class defined in open_notebook/ai/models.py. This manager reads model definitions from SurrealDB tables and constructs provider-specific configurations at runtime.

When loading a model record, the manager normalizes provider names to match Esperanto's expectations. The database stores provider names with underscores (e.g., ollama_local or lm_studio), while Esperanto requires hyphenated format. The code performs this transformation automatically:

provider = model.provider.replace("_", "-")

This normalization occurs in open_notebook/ai/models.py (lines 47-49) before every factory call, ensuring compatibility across all 18+ supported providers.

Credential Handling and Configuration

The system supports two configuration paths: stored credentials in SurrealDB or environment variable fallbacks.

Stored Credentials

When a model record links to a credential, Model.get_credential_obj() loads the Credential record from open_notebook/domain/credential.py. The credential object converts to Esperanto configuration via Credential.to_esperanto_config(). For Ollama-specific deployments, this includes critical overrides like num_ctx (context window size), which is defined in the Credential class schema (line 80).

Environment Fallback

If no credential exists, open_notebook/ai/key_provider.py falls back to environment variables (e.g., OLLAMA_BASE_URL or OPENAI_API_KEY) and injects them into the Esperanto configuration object. This allows immediate local testing without database setup.

The Esperanto Factory Pattern

Depending on the model's type field, ModelManager invokes one of four Esperanto constructors from AIFactory:

  • AIFactory.create_language for LLM chat completions
  • AIFactory.create_embedding for vector store operations
  • AIFactory.create_speech_to_text for transcription services
  • AIFactory.create_text_to_speech for TTS generation

These calls automatically cache the underlying provider client, so subsequent requests reuse the same connection (see open_notebook/ai/models.py, lines 50-57). The rest of the Open Notebook codebase interacts with generic LanguageModel or EmbeddingModel interfaces, remaining unaware of whether the backend is OpenAI, Anthropic, Ollama, or LM Studio.

Local AI Support: Ollama and LM Studio

Open Notebook provides first-class support for local inference through specialized handling in open_notebook/ai/model_discovery.py and URL validation.

URL Validation for Local Endpoints

The API accepts localhost and private IP URLs for local providers. Unit tests in tests/test_url_validation.py (lines 11-49) explicitly confirm that "localhost should be allowed for Ollama" and similar local services.

Automatic Model Discovery

The model_discovery.py module contacts running Ollama instances at /api/tags to populate the database with available models (lines 295-322). This auto-discovery eliminates manual configuration when local models are added or updated.

Context Window Overrides

For Ollama deployments, the Credential schema includes a num_ctx field that merges into the Esperanto config (see open_notebook/domain/credential.py, line 80). This allows users to request larger context windows than the default 8,000 tokens, critical for processing long documents.

Practical Implementation Examples

Instantiating Any Language Model

from open_notebook.ai.models import ModelManager

async def get_chat_model():
    manager = ModelManager()
    # model_id refers to a SurrealDB record in the model table

    llm = await manager.get_model(
        model_id="model:my-ollama-gpt4",
        temperature=0.7,
    )
    # Returns an Esperanto LanguageModel instance

    response = await llm.generate("Explain the difference between Ollama and LM Studio.")
    return response

The get_model method internally calls AIFactory.create_language to instantiate the concrete client.

Connecting to Local Ollama with Custom Context

from open_notebook.ai.models import ModelManager

async def chat_with_local_llm():
    manager = ModelManager()
    # Discovers models from http://localhost:11434 automatically

    model = await manager.get_model(
        model_id="model:ollama:llama2",
        num_ctx=16384,  # Overrides default 8k context window

    )
    return await model.generate("Summarize this research paper.")

Credential Configuration for Ollama


# Example Credential record in SurrealDB

{
    "name": "Local Ollama",
    "provider": "ollama",
    "num_ctx": 16384,
    "config": {}
}

# When loaded, Credential.to_esperanto_config() produces:

# {"num_ctx": 16384, "base_url": "http://localhost:11434"}

This configuration merges with Esperanto's provider defaults before instantiation.

Summary

  • Centralized abstraction: The ModelManager class in open_notebook/ai/models.py provides a single interface for all AI operations across 18+ providers.
  • Name normalization: Provider names are automatically converted from underscores to hyphens to match Esperanto's naming conventions.
  • Flexible credentialing: Supports both database-stored credentials with provider-specific overrides (like num_ctx for Ollama) and environment variable fallbacks.
  • Local server support: Built-in URL validation allows localhost/private IPs, while model_discovery.py automatically detects available Ollama models via /api/tags.
  • Factory pattern: Uses AIFactory.create_language, create_embedding, and related methods to generate cached, provider-specific clients without exposing implementation details to the application layer.

Frequently Asked Questions

How does Open Notebook normalize provider names for the Esperanto library?

Open Notebook stores provider names with underscores in SurrealDB (e.g., ollama_local), but Esperanto expects hyphenated names (e.g., ollama-local). The ModelManager performs this transformation automatically using provider = model.provider.replace("_", "-") before every AIFactory call in open_notebook/ai/models.py.

What is the purpose of the num_ctx field in Ollama credentials?

The num_ctx field in the Credential schema allows users to override the default context window size for Ollama models. When to_esperanto_config() is called in open_notebook/domain/credential.py, this value merges into the configuration dictionary, enabling context windows larger than the standard 8,000 tokens for local LLM inference.

How does model discovery work for local Ollama instances?

The open_notebook/ai/model_discovery.py module queries the Ollama API endpoint /api/tags on http://localhost:11434 to retrieve a list of available models (lines 295-322). It then automatically registers these models in the SurrealDB model table, making them immediately available through the ModelManager without manual configuration.

Can I use environment variables instead of stored credentials for AI providers?

Yes. If a model record has no linked credential, open_notebook/ai/key_provider.py falls back to environment variables such as OLLAMA_BASE_URL or OPENAI_API_KEY. These variables are injected into the Esperanto configuration object, allowing immediate connections to providers without database credential records.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →