Providers

The providers module is a set of optional LLM adapter classes that share a common LLMProvider protocol, letting the rest of the codebase call a single interface regardless of which underlying API — Anthropic or Google — handles the request.

Mental model

Every provider in this module is a thin async wrapper over a vendor SDK. You interact with any provider through two methods defined on LLMProvider:

Because each concrete class lazy-imports its vendor SDK, installing the core package does not pull in Anthropic or Google dependencies. You opt in with the attune-rag[claude] or attune-rag[gemini] extras.

To find and instantiate a provider without hardcoding a class import, use the two helpers the module exports:

from providers import list_available, get_provider

# See which provider SDKs are currently importable
print(list_available())          # e.g. ["claude", "gemini"]

# Get an instance by name; extra kwargs go to __init__
provider = get_provider("claude", api_key="sk-...")

list_available() returns only the names whose SDKs are importable in the current environment. get_provider() raises ValueError if you pass an unrecognised name.

Core types

Type Role
LLMProvider Protocol that ClaudeProvider and GeminiProvider both satisfy. Defines generate and generate_with_citations.
ClaudeProvider Wraps AsyncAnthropic. Accepts an api_key or a pre-built AsyncAnthropic client. Supports both generate and generate_with_citations.
GeminiProvider Wraps GenAIClient. Accepts an api_key or a pre-built GenAIClient. Supports generate; citation support is not part of its current interface.
CitationDocument A dataclass with title: str and text: str fields. Represents one source document passed to generate_with_citations.
CitedResponse A dataclass with text: str and claim_citations: tuple[ClaimCitation, ...]. Returned by generate_with_citations, pairing the answer text with structured citation data.

How the pieces fit together

When you call generate_with_citations, you assemble a list of CitationDocument objects — each holding a title and text — and pass them alongside your query. The provider sends both to the underlying API and returns a CitedResponse. The claim_citations tuple on that response lets you trace which claims in the generated text came from which source documents.

from providers.base import CitationDocument
from providers import get_provider

docs = [
    CitationDocument(title="Q3 Report", text="Revenue grew 12% YoY..."),
    CitationDocument(title="Risk Factors", text="Supply chain delays..."),
]

provider = get_provider("claude")
response = provider.generate_with_citations(docs, query="What drove revenue growth?")

print(response.text)
print(response.claim_citations)   # tuple of ClaimCitation objects

Installation requirements

Provider Extra required
ClaudeProvider attune-rag[claude]
GeminiProvider attune-rag[gemini]

Neither SDK is imported at module load time, so importing providers in an environment that has neither extra installed is safe — list_available() will simply return an empty list.

Unresolved references

Auto-generated by attune-author fact-check. Review and either fix the source code, fix this doc, or add an override.

Location Severity Issue
Line 26 (code fence) error from providers import … — module not importable
Line 52 (code fence) error from providers.base import … — module not importable