Providers: LLM & Embedder Configuration

April 12, 2026 ยท View on GitHub

GraphRAG SDK uses two provider types: LLM (for text generation and extraction) and Embedder (for vector embeddings). Both are abstract base classes with built-in implementations for LiteLLM and OpenRouter.

Provider Overview

ProviderLLM ClassEmbedder ClassInstall ExtraModels Supported
LiteLLMLiteLLMLiteLLMEmbedderpip install graphrag-sdk[litellm]Azure OpenAI, OpenAI, Anthropic, Cohere, 100+
OpenRouterOpenRouterLLMOpenRouterEmbedderpip install graphrag-sdk[openrouter]All OpenRouter models
CustomSubclass LLMInterfaceSubclass Embedder--Anything

LiteLLM provides a unified interface to 100+ LLM providers. It is the recommended default.

LLM

from graphrag_sdk import LiteLLM

# Azure OpenAI
llm = LiteLLM(
    model="azure/gpt-4.1",
    api_key="your-azure-key",
    api_base="https://your-resource.openai.azure.com/",
    api_version="2024-12-01-preview",
    temperature=0.0,      # default: 0.0
    max_tokens=None,      # default: None (provider default)
)

# OpenAI direct
llm = LiteLLM(
    model="gpt-4o",
    api_key="your-openai-key",
)

# Anthropic
llm = LiteLLM(
    model="anthropic/claude-sonnet-4-20250514",
    api_key="your-anthropic-key",
)

Parameters:

ParameterTypeDefaultDescription
modelstrrequiredModel identifier (use provider/model format for non-OpenAI)
api_keystr | NoneNoneAPI key (or set via environment variable)
api_basestr | NoneNoneBase URL (required for Azure)
api_versionstr | NoneNoneAPI version (required for Azure)
temperaturefloat0.0Sampling temperature
max_tokensint | NoneNoneMax output tokens

Embedder

from graphrag_sdk import LiteLLMEmbedder

# Azure OpenAI
embedder = LiteLLMEmbedder(
    model="azure/text-embedding-ada-002",
    api_key="your-azure-key",
    api_base="https://your-resource.openai.azure.com/",
    api_version="2024-12-01-preview",
)

# OpenAI direct
embedder = LiteLLMEmbedder(
    model="text-embedding-3-small",
    api_key="your-openai-key",
)

Parameters:

ParameterTypeDefaultDescription
modelstrrequiredEmbedding model identifier
api_keystr | NoneNoneAPI key
api_basestr | NoneNoneBase URL
api_versionstr | NoneNoneAPI version

OpenRouter

OpenRouter aggregates models from multiple providers behind a single API.

LLM

from graphrag_sdk import OpenRouterLLM

llm = OpenRouterLLM(
    model="anthropic/claude-sonnet-4-20250514",
    api_key="your-openrouter-key",      # or set OPENROUTER_API_KEY env var
    temperature=0.0,
    max_tokens=None,
    extra_headers={},                    # optional custom headers
)

Embedder

from graphrag_sdk import OpenRouterEmbedder

embedder = OpenRouterEmbedder(
    model="openai/text-embedding-ada-002",
    api_key="your-openrouter-key",
    extra_headers={},
)

LLMInterface ABC

To integrate a provider not covered by LiteLLM or OpenRouter, subclass LLMInterface.

Required Method

from graphrag_sdk import LLMInterface
from graphrag_sdk.core.models import LLMResponse

class MyLLM(LLMInterface):
    def __init__(self, model_name: str = "my-model", **kwargs):
        super().__init__(model_name=model_name)
        # Initialize your client

    def invoke(self, prompt: str, **kwargs) -> LLMResponse:
        """Synchronous text generation. REQUIRED."""
        response = my_client.generate(prompt)
        return LLMResponse(content=response.text)

Optional Overrides

MethodDefault BehaviorOverride When
ainvoke(prompt, max_retries=3)Runs invoke() in a thread pool with retryYou have a native async client
ainvoke_messages(messages, max_retries=3)Concatenates messages into a single prompt and calls ainvoke()You have a native multi-turn chat API
invoke_with_model(prompt, response_model)Calls invoke() and parses JSON into Pydantic modelYour provider has native structured output
ainvoke_with_model(prompt, response_model)Calls ainvoke() and parses JSONSame, async version
abatch_invoke(prompts, max_concurrency)Concurrent ainvoke() with semaphoreYou have a native batch API

ainvoke_messages() is called by completion() when conversation history is provided. Override it to pass messages natively to your LLM's chat API for proper multi-turn handling:

from graphrag_sdk.core.models import ChatMessage, LLMResponse

class MyLLM(LLMInterface):
    def invoke(self, prompt: str, **kwargs) -> LLMResponse:
        response = my_client.generate(prompt)
        return LLMResponse(content=response.text)

    async def ainvoke_messages(self, messages: list[ChatMessage], *, max_retries=3, **kwargs) -> LLMResponse:
        """Native multi-turn โ€” pass messages directly to your chat API."""
        response = await my_client.chat(
            messages=[m.to_dict() for m in messages],
        )
        return LLMResponse(content=response.text)

Constructor Parameters

LLMInterface.__init__(
    model_name: str,                    # Model identifier
    model_params: dict | None = None,   # Provider-specific params
    max_concurrency: int = 12,          # Parallel call limit for abatch_invoke
)

Embedder ABC

Required Methods

from graphrag_sdk import Embedder

class MyEmbedder(Embedder):
    @property
    def model_name(self) -> str:
        """Identifier for the embedding model. REQUIRED."""
        return "my-embedding-model"

    def embed_query(self, text: str, **kwargs) -> list[float]:
        """Embed a single text. REQUIRED."""
        return my_model.encode(text).tolist()

The model_name property is used by the graph config node to validate that the same embedding model is used for ingestion and retrieval.

Optional Overrides

MethodDefault BehaviorOverride When
aembed_query(text)Runs embed_query() in thread poolYou have async embedding
embed_documents(texts)Sequential embed_query() per textYou can batch embeddings
aembed_documents(texts)Runs embed_documents() in thread poolYou have async batch

Batch Embedding

The embed_documents() and aembed_documents() methods are critical for performance. The ingestion pipeline calls them with hundreds or thousands of texts. If your provider supports batch embedding, always override these methods:

class MyEmbedder(Embedder):
    def embed_query(self, text: str, **kwargs) -> list[float]:
        return self.model.encode(text).tolist()

    def embed_documents(self, texts: list[str], **kwargs) -> list[list[float]]:
        # Batch embedding -- much faster than sequential
        return self.model.encode(texts).tolist()

Environment Variables

For convenience, you can configure providers via environment variables instead of passing parameters directly. LiteLLM respects standard environment variables:

VariableProvider
OPENAI_API_KEYOpenAI
AZURE_API_KEY, AZURE_API_BASE, AZURE_API_VERSIONAzure OpenAI
ANTHROPIC_API_KEYAnthropic
COHERE_API_KEYCohere
OPENROUTER_API_KEYOpenRouter

See the LiteLLM documentation for the full list of supported providers and their environment variables.

Choosing a Provider

Use CaseRecommendation
Production (Azure)LiteLLM with azure/ prefix
Development (OpenAI)LiteLLM with OpenAI models
Budget-consciousOpenRouterLLM for model price comparison
Local modelsCustom LLMInterface wrapping Ollama, vLLM, etc.
Local embeddingsCustom Embedder wrapping sentence-transformers