Providers
Document Providers
- class afterimage.providers.document_providers.DirectoryDocumentProvider(directory: str | Path, file_patterns: List[str] | None = None, encoding: str = 'utf-8', recursive: bool = True, min_length: int = 1, cache: bool = True, target_context_usage_count: int | None = None)[source]
Bases:
DocumentProviderSearch a directory for several filename patterns (txt/md/jsonl etc).
- class afterimage.providers.document_providers.DocumentProvider(*args, **kwargs)[source]
Bases:
ProtocolUnified DocumentProvider protocol.
- Minimal required method for implementations:
_load_documents() -> list[Document]
- Public helpers (provided by protocol defaults below):
get_documents(n: int) -> list[Document]
get_all() -> list[Document]
sample(n: int) -> list[Document]
report_doc_usage(document_id: str) -> int
set_target_context_usage_count(target_context_usage_count: int | None)
mark_fully_covered(document_id: str)
clear_cache()
__len__(), __iter__(), __getitem__(i)
- get_documents(n: int) list[Document][source]
Return up to n random documents. If n is math.inf, return all documents.
- get_target_context_usage_count() int | None[source]
Return the current target usage count, if configured.
- mark_fully_covered(document_id: str) None[source]
Exclude a document from future weighted sampling.
- class afterimage.providers.document_providers.FileSystemDocumentProvider(path_pattern: str, encoding: str = 'utf-8', recursive: bool = False, min_length: int = 1, cache: bool = True, target_context_usage_count: int | None = None)[source]
Bases:
DocumentProviderLoad text files matched by a glob pattern.
- class afterimage.providers.document_providers.InMemoryDocumentProvider(texts: list[str | Document], target_context_usage_count: int | None = None)[source]
Bases:
DocumentProviderSimple provider backed by a list of strings.
- class afterimage.providers.document_providers.JSONLDocumentProvider(path_pattern: str, content_key: str = 'text', encoding: str = 'utf-8', recursive: bool = False, cache: bool = True, max_docs: int | None = None, target_context_usage_count: int | None = None)[source]
Bases:
DocumentProviderLoad text fields from one or more JSONL files.
content_key selects which key from each JSON object to use.
- class afterimage.providers.document_providers.QdrantDocumentProvider(client: QdrantClient, collection_name: str, content_key: str = 'text', batch_size: int = 500, scroll_filter: Filter | None = None, with_payload_keys: List[str] | None = None, cache: bool = True, max_docs: int | None = None, target_context_usage_count: int | None = None)[source]
Bases:
DocumentProviderLoad text payloads from a Qdrant collection via scroll.
Note: requires qdrant-client package.
LLM Providers
- class afterimage.providers.llm_providers.AsyncGeminiChatSession(chat, model_name: str)[source]
Bases:
ChatSessionAsynchronous Gemini chat session implementation.
- async asend_message(message: str | ConversationEntry, temperature: float = 0.7, **kwargs) LLMResponse[source]
Send a message to the chat session asynchronously.
- class afterimage.providers.llm_providers.AsyncOpenAIChatSession(client: AsyncOpenAI, model_name: str, system_instruction: str | None = None, temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs)[source]
Bases:
ChatSessionAsynchronous OpenAI chat session implementation.
- async asend_message(message: str | ConversationEntry, temperature: float = 0.7, **kwargs) LLMResponse[source]
Send a message to the chat session asynchronously.
- class afterimage.providers.llm_providers.ChatSession[source]
Bases:
objectAbstract chat session interface.
- async asend_message(message: str | ConversationEntry, temperature: float = 0.7, **kwargs) LLMResponse[source]
Send a message to the chat session asynchronously.
- send_message(message: str | ConversationEntry, temperature: float = 0.7, **kwargs) LLMResponse[source]
Send a message to the chat session.
- class afterimage.providers.llm_providers.CommonLLMResponse(text: str, prompt_token_count: int, completion_token_count: int, total_token_count: int, finish_reason: str, model_name: str, raw_response: Any)[source]
Bases:
objectStandardized LLM response.
- completion_token_count: int
- finish_reason: str
- model_name: str
- prompt_token_count: int
- raw_response: Any
- text: str
- total_token_count: int
- class afterimage.providers.llm_providers.DeepSeekProvider(api_key: str | SmartKeyPool, model_name: str = 'deepseek-chat', system_instruction: str | None = None, **kwargs)[source]
Bases:
OpenAIProviderDeepSeek implementation using OpenAI-compatible API.
- BASE_URL = 'https://api.deepseek.com'
- async agenerate_structured(prompt: str, schema: Type[T], temperature: float = 0.7, **kwargs) StructuredLLMResponse[T][source]
Generate structured output that matches the given schema asynchronously.
- generate_structured(prompt: str, schema: Type[T], temperature: float = 0.7, **kwargs) StructuredLLMResponse[T][source]
Generate structured output that matches the given schema.
- class afterimage.providers.llm_providers.GeminiChatSession(chat, model_name: str)[source]
Bases:
ChatSessionGemini chat session implementation.
- send_message(message: str | ConversationEntry, temperature: float = 0.7, **kwargs) LLMResponse[source]
Send a message to the chat session.
- class afterimage.providers.llm_providers.GeminiProvider(api_key: str | SmartKeyPool, model_name: str = 'gemini-2.0-flash', system_instruction: str | None = None, safety_settings: List[Dict[str, str]] | None = None, **kwargs)[source]
Bases:
LLMProviderGoogle Gemini implementation.
- async agenerate_content(prompt: str, temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) LLMResponse[source]
Generate completion from prompt asynchronously.
- async agenerate_structured(prompt: str, schema: Type[T], temperature: float = 0.7, **kwargs) StructuredLLMResponse[T][source]
Generate structured output that matches the given schema asynchronously.
- async astart_chat(temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) ChatSession[source]
Start a new chat session asynchronously.
- generate_content(prompt: str, temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) LLMResponse[source]
Generate completion from prompt.
- generate_structured(prompt: str, schema: Type[T], temperature: float = 0.7, **kwargs) StructuredLLMResponse[T][source]
Generate structured output that matches the given schema.
- start_chat(temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) ChatSession[source]
Start a new chat session.
- class afterimage.providers.llm_providers.LLMFactory[source]
Bases:
objectFactory for creating LLM providers.
- static create(provider: str, model_name: str | None = None, api_key: str | SmartKeyPool | None = None, system_instruction: str | None = None, **kwargs) LLMProvider[source]
- class afterimage.providers.llm_providers.LLMProvider(*args, **kwargs)[source]
Bases:
ProtocolProtocol for LLM providers.
- async agenerate_content(prompt: str, temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) LLMResponse[source]
Generate completion from prompt asynchronously.
- async agenerate_structured(prompt: str, schema: Type[T], temperature: float = 0.7, **kwargs) StructuredLLMResponse[T][source]
Generate structured output that matches the given schema asynchronously.
- async astart_chat(**kwargs) ChatSession[source]
Start a new chat session asynchronously.
- generate_content(prompt: str, temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) LLMResponse[source]
Generate completion from prompt.
- generate_structured(prompt: str, schema: Type[T], temperature: float = 0.7, **kwargs) StructuredLLMResponse[T][source]
Generate structured output that matches the given schema.
- start_chat(**kwargs) ChatSession[source]
Start a new chat session.
- class afterimage.providers.llm_providers.LLMResponse(text: str, prompt_token_count: int, completion_token_count: int, total_token_count: int, finish_reason: str, model_name: str, raw_response: Any, reasoning_content: str | None = None)[source]
Bases:
CommonLLMResponse- reasoning_content: str | None = None
- class afterimage.providers.llm_providers.OpenAIChatSession(client: OpenAI, model_name: str, system_instruction: str | None = None, temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs)[source]
Bases:
ChatSessionOpenAI chat session implementation.
- send_message(message: str | ConversationEntry, temperature: float = 0.7, **kwargs) LLMResponse[source]
Send a message to the chat session.
- class afterimage.providers.llm_providers.OpenAIProvider(api_key: str | SmartKeyPool, model_name: str = 'gpt-4o', base_url: str | None = None, system_instruction: str | None = None, **kwargs)[source]
Bases:
LLMProviderOpenAI-compatible API implementation.
- async agenerate_content(prompt: str, temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) LLMResponse[source]
Generate completion from prompt asynchronously.
- async agenerate_structured(prompt: str, schema: Type[T], temperature: float = 0.7, **kwargs) StructuredLLMResponse[T][source]
Generate structured output that matches the given schema asynchronously.
- async astart_chat(temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) ChatSession[source]
Start a new chat session asynchronously.
- generate_content(prompt: str, temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) LLMResponse[source]
Generate completion from prompt.
- generate_structured(prompt: str, schema: Type[T], temperature: float = 0.7, **kwargs) StructuredLLMResponse[T][source]
Generate structured output that matches the given schema.
- start_chat(temperature: float = 0.7, max_tokens: int | None = None, stop_sequences: List[str] | None = None, **kwargs) ChatSession[source]
Start a new chat session.
- class afterimage.providers.llm_providers.StructuredLLMResponse(text: str, prompt_token_count: int, completion_token_count: int, total_token_count: int, finish_reason: str, model_name: str, raw_response: Any, parsed: T, reasoning_content: str | None = None)[source]
Bases:
CommonLLMResponse,Generic[T]Standardized LLM response with structured output.
- parsed: T
- reasoning_content: str | None = None
Embedding providers
Async text embeddings (OpenAI-compatible APIs, Gemini, and local SentenceTransformer
via a process pool). Public types are re-exported on the afterimage package.
- class afterimage.EmbeddingProvider(*args, **kwargs)[source]
Bases:
ProtocolProtocol for async text embedding backends.
Implementations return one dense vector per input string, preserve order, and may batch requests internally. Call
aclose()when the provider is no longer needed (required for process-based providers).- async aclose() None[source]
Release resources held by this provider (pools, clients).
Implementations should make this idempotent (safe to call multiple times). API-only providers may use a no-op.
- async embed(texts: list[str]) list[list[float]][source]
Embed each string into a floating-point vector.
- Parameters:
texts – Input strings. Empty list returns
[].- Returns:
Embeddings in the same order as
texts; each embedding is a list of floats (dimension is model-specific).
Note
Callers must not assume a single HTTP or IPC round trip; large inputs may be split into batches by the implementation.
- class afterimage.OpenAIEmbeddingProvider(api_key: str | SmartKeyPool, model: str = 'text-embedding-3-small', *, base_url: str | None = None, max_batch_size: int = 128, extra_create_kwargs: dict[str, Any] | None = None)[source]
Bases:
_NoOpAcloseMixinEmbeddings via the OpenAI async client (
embeddings.create).Supports OpenAI and OpenAI-compatible servers via
base_url. UsesSmartKeyPoolfor key rotation and error reporting consistent with chat providers.- async embed(texts: list[str]) list[list[float]][source]
Compute embeddings for
textsusing the configured model.- Parameters:
texts – Non-empty list of strings to embed, or empty for no work.
- Returns:
One embedding per input string, in order.
- Raises:
Exception – Propagates API errors after reporting the key to the pool.
- class afterimage.GeminiEmbeddingProvider(api_key: str | SmartKeyPool, model: str = 'text-embedding-004', *, max_batch_size: int = 128)[source]
Bases:
_NoOpAcloseMixinEmbeddings via Google Gemini
client.aio.models.embed_content.Uses the async Gemini client, closes transient HTTP resources after each
embed()call, and integrates withSmartKeyPool.- async embed(texts: list[str]) list[list[float]][source]
Compute embeddings for
textsusing the configured Gemini model.- Parameters:
texts – Non-empty list of strings to embed, or empty for no work.
- Returns:
One embedding per input string, in order.
- Raises:
ValueError – If the API returns an embedding without
values.Exception – Propagates API errors after reporting the key to the pool.
- class afterimage.ProcessEmbeddingProvider(model_name: str, *, max_workers: int = 2, max_batch_size: int = 64)[source]
Bases:
objectLocal embeddings using SentenceTransformer in a process pool.
Inference runs in child processes so the host asyncio loop is not blocked. The model is loaded once per worker via the pool initializer. Call
aclose()to shut down workers when finished.- async aclose() None[source]
Shut down the process pool and mark this provider closed.
Waits for workers to finish. Idempotent after the first call.
- async embed(texts: list[str]) list[list[float]][source]
Encode texts in worker processes via
asyncio.loop.run_in_executor().- Parameters:
texts – Non-empty list of strings to embed, or empty for no work.
- Returns:
One embedding per input string, in order.
- Raises:
RuntimeError – If the provider was closed before or during use.
ImportError – In workers if sentence-transformers is missing.
- class afterimage.EmbeddingProviderFactory[source]
Bases:
objectFactory for constructing
EmbeddingProviderinstances from config.Config dictionaries are intended to be JSON-serializable (aside from embedding-specific nested structures). Key names are matched case-insensitively.
- static create(config: dict[str, Any], *, api_key: str | None = None, key_pool: SmartKeyPool | None = None) EmbeddingProvider[source]
Build a provider from a configuration mapping.
- Parameters:
config –
Must include
type("openai","gemini", or"process"). Optional keys:model— embedding model id for API providers.model_path— HuggingFace id or path forprocess(alsomodelis accepted for process).base_url— OpenAI-compatible base URL.workers— process count forprocess(default2).max_batch_size— chunk size for batched calls.api_key— inline secret when not usingkey_pool.
api_key – Optional default API key when
key_poolis omitted (OpenAI/Gemini only).key_pool – Optional shared pool; takes precedence over
api_keyand env vars for API providers.
- Returns:
A concrete
EmbeddingProvider.- Raises:
ValueError – If
typeis missing, unknown, or required keys are absent.