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:
generate— sends apromptstring and returns a text response. Passcached_prefixto reuse a prompt prefix across calls without resending it to the API each time.generate_with_citations— sends a list ofCitationDocumentobjects alongside aquery, and returns aCitedResponsethat pairs the generated text with per-claim citation data.
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 |