Esperanto AI Interface

repository·main·Indexed 42 days ago

https://github.com/lfnovo/esperanto

A lightweight, production-ready Python library providing a unified interface for AI model providers including OpenAI, Anthropic, Google, and local options like Ollama and Transformers. Version 2.27.0 uses direct HTTP communication via httpx to minimize dependencies. It supports LLMs, Embeddings, Reranking, Speech-to-Text (STT), and Text-to-Speech (TTS) through a standardized AIFactory pattern and unified tool calling.

Tokens
129K
Snippets
398
Records
491
Agent score
52%

What's inside Esperanto

  1. Overview of Esperanto capabilities

    main

    Esperanto provides a unified interface for the following AI capabilities:

    • Language Models (LLM): Text generation, chat, and reasoning.
    • Embeddings: Vector representations for semantic search.
    • Reranking: Improving search relevance.
    • Speech-to-Text (STT): Audio transcription.
    • Text-to-Speech (TTS): Voice generation.
  2. Use the OpenAI-Compatible provider for custom or local endpoints

    main

    The openai-compatible provider allows you to connect to any service implementing the OpenAI API format. This is ideal for local deployments (like LM Studio, Ollama, vLLM, or LocalAI) and custom cloud services.

    Supported Capabilities:

    • Language Models (LLM): Supported via chat completions endpoints.
    • Embeddings: Supported.
    • Speech-to-Text (STT): Supported.
    • Text-to-Speech (TTS): Supported.
    • Reranking: Not supported.

    To use a local service like LM Studio, ensure the server is running (e.g., at http://localhost:1234) before attempting to connect.

    from esperanto.factory import AIFactory
    
    # Language model
    model = AIFactory.create_language(
        "openai-compatible",
        "your-model-name",
        config={"base_url": "http://localhost:1234/v1"}
    )
  3. Optimize Transformers model for memory and performance

    main

    When working with the transformers provider, consider the following for resource management:

    Memory Usage

    • Large Models: Models like Qwen/Qwen3-Embedding-4B require significant GPU memory.
    • Low Memory Environments: Use smaller models (e.g., sentence-transformers/all-MiniLM-L6-v2) and force the device to cpu.
    • Dimension Reduction: Reducing output_dimensions can help manage memory.

    Processing Speed

    • Late Chunking: Adds processing overhead for long documents.
    • PCA: Dimension reduction via PCA has a one-time fitting cost.
    • Batching: Always use batch processing (model.embed(list_of_texts)) instead of individual calls for better efficiency.

    Model Caching

    • Models are cached using the HuggingFace cache system.
    • Use the HF_HOME environment variable to change the cache location.
    # Set custom cache directory
    export HF_HOME=/path/to/cache
    # For limited memory environments
    model = AIFactory.create_embedding(
        "transformers",
        "sentence-transformers/all-MiniLM-L6-v2",
        config={
            "device": "cpu",
            "output_dimensions": 256
        }
    )
    
    # Efficient batch processing
    texts = ["text1", "text2", "text3"]
    embeddings = model.embed(texts)
  4. Understand how Esperanto handles unsupported features and model quirks

    main

    Esperanto distinguishes between two types of non-standard behavior to maintain a reliable API:

    1. Unsupported Features: If a provider fundamentally cannot support a feature (e.g., a provider that does not support streaming), Esperanto will raise a clear error. This prevents you from assuming a feature is working when it is not.
    2. Model-Specific Quirks: If a model has a specific request-shape quirk (e.g., Claude rejecting temperature and top_p simultaneously), the provider's request-builder will automatically sanitize the request and log a debug message. You do not need to manually handle these quirks in your application code.
  5. Use provider-specific environment variables for OpenAI-compatible providers

    main

    Esperanto supports specialized environment variables for OpenAI-compatible providers to allow granular configuration of different model types (LLM, Embedding, STT, TTS).

    When configuring an OpenAI-compatible provider, you can use generic variables or type-specific variables. The precedence order for configuration is:

    1. Direct parameters (passed directly to the class/method constructor) - Highest priority
    2. Configuration dictionary
    3. Provider-specific environment variables (e.g., OPENAI_COMPATIBLE_BASE_URL_LLM)
    4. Generic environment variables (e.g., OPENAI_COMPATIBLE_BASE_URL) - Lowest priority
    ### Precedence Order (Highest to Lowest):
    1. Direct Parameters
    2. Config Dict
    3. `OPENAI_COMPATIBLE_<TYPE>_BASE_URL` / `OPENAI_COMPATIBLE_<TYPE>_API_KEY`
    4. `OPENAI_COMPATIBLE_BASE_URL` / `OPENAI_COMPATIBLE_API_KEY`
  6. Understand the RerankResponse structure

    main

    All reranker providers return a standardized RerankResponse object. The results attribute contains a list of objects with the following fields:

    • document: The original text of the document.
    • relevance_score: A normalized score between 0.0 and 1.0 (higher is more relevant).
    • index: The original position of the document in the input list.

    The response also includes a model field indicating the model name used.

    Note on Scores: Scores are relative within a single rerank call and are always sorted by score in descending order.

    response = reranker.rerank(query, documents, top_k=3)
    
    # Accessing fields
    first_doc = response.results[0].document
    first_score = response.results[0].relevance_score
    first_index = response.results[0].index
    model_used = response.model
  7. Use async methods for AI operations

    main

    All model methods in Esperanto have asynchronous equivalents. To use the async version of a method, prefix the method name with a and use the await keyword.

    Example:

    # Synchronous call
    response = model.chat_complete(messages)
    
    # Asynchronous call
    response = await model.achat_complete(messages)
    response = await model.achat_complete(messages)
  8. Use Jina Task-Optimized Embeddings

    main

    Jina supports native task optimization. Use EmbeddingTaskType to map your intent to the correct Jina API parameter. This is highly recommended for RAG systems to ensure queries and documents are in the same vector space.

    Task Type Mappings:

    • EmbeddingTaskType.RETRIEVAL_QUERY $\rightarrow$ "retrieval.query" (Optimize for search queries)
    • EmbeddingTaskType.RETRIEVAL_DOCUMENT $\rightarrow$ "retrieval.passage" (Optimize for document storage)
    • EmbeddingTaskType.CLASSIFICATION $\rightarrow$ "classification"
    • EmbeddingTaskType.CLUSTERING $\rightarrow$ "separation"
    • EmbeddingTaskType.SIMILARITY $\rightarrow$ "text-matching"
    • EmbeddingTaskType.CODE_RETRIEVAL $\rightarrow$ "code.query" (Optimize for code search)
    from esperanto.common_types.task_type import EmbeddingTaskType
    from esperanto.factory import AIFactory
    
    # Optimize for search queries
    query_model = AIFactory.create_embedding(
        "jina",
        "jina-embeddings-v3",
        config={"task_type": EmbeddingTaskType.RETRIEVAL_QUERY}
    )
    
    # Optimize for document storage
    document_model = AIFactory.create_embedding(
        "jina",
        "jina-embeddings-v3",
        config={"task_type": EmbeddingTaskType.RETRIEVAL_DOCUMENT}
    )
  9. What are task-aware embeddings and why use them?

    main

    Task-aware embeddings optimize vector representations for specific semantic purposes rather than using a single generic model for all inputs. This is crucial because queries (short, intent-focused) and documents (long, information-rich) have different semantic patterns. Using specialized task types can improve search relevance by 15-30%.

    Esperanto provides a unified interface to apply these optimizations across different providers, whether they support it natively (like Jina or Google) or via intelligent prefix emulation (like OpenAI).

  10. Important: Use Deployment Names instead of Model Names

    main

    In Azure OpenAI, you interact with deployment names rather than the underlying model names. When using Esperanto, the model_name parameter (or the second argument in AIFactory methods) must correspond to your specific Azure deployment name.

    For example, if your GPT-4 deployment is named my-gpt4-deployment, you must use that string in your code.

    # Correct usage using the deployment name
    model = AIFactory.create_language("azure", "my-gpt4-deployment")
  11. List available Deepgram voices

    main

    You can discover available voices in two ways:

    1. Access the DEEPGRAM_VOICES constant in esperanto.providers.tts.deepgram.
    2. Use the available_voices property on an existing model instance.

    Deepgram supports the Aura-2 family (English, Spanish, French, German, Italian, Japanese, Dutch) and the legacy Aura-1 family (English only).

  12. Best practices for timeout configuration

    main

    When configuring timeouts in Esperanto, follow these guidelines:

    1. Set Appropriate Defaults: Use reasonable timeouts based on the use case (e.g., 60s for standard chat) rather than excessively long ones (e.g., 3600s).
    2. Match Provider Speed: Use shorter timeouts for fast providers (e.g., groq at 30s) and longer timeouts for slower providers (e.g., anthropic at 120s).
    3. Consider Content Length: Assign longer timeouts for complex tasks like document analysis or long prompts, and shorter timeouts for quick queries.
    4. Use Environment Variables: Set global defaults using ESPERANTO_LLM_TIMEOUT and ESPERANTO_EMBEDDING_TIMEOUT to simplify configuration.