Перейти к содержанию

Интеграции

Ядро protoprompt остаётся без обязательных зависимостей. Всё внешнее подключается через опциональные экстра — импорт внутри конструкторов, поэтому сам пакет protoprompt.integrations ставится мгновенно.

LLM-клиенты

Полные клиенты реализуют совместимый LLMClientProtocol (chat + embed). Узкие интеграции могут реализовать только ChatClientProtocol или EmbeddingClientProtocol; независимые возможности объединяет CompositeLLMClient.

Класс Экстра Адресаты
integrations.OpenAIClient [openai] OpenAI, LiteLLM, vLLM (через base_url)
integrations.OllamaClient [ollama] локальный/удалённый Ollama (/api/chat, /api/embed)
integrations.HttpxLLMClient [http] любой OpenAI-совместимый REST (LM Studio, llama.cpp)
integrations.AnthropicClient [anthropic] нативный Anthropic Messages API (chat)
integrations.GoogleGenAIClient [google] Gemini Developer API / Vertex AI (chat + embed)
integrations.BedrockConverseClient [bedrock] Amazon Bedrock Converse (chat)

Нативный token counting, auth-семантика, PydanticAI/LlamaIndex и решение по Google ADK собраны в матрице провайдеров и фреймворков.

from protoprompt import ContextBuilder, ContextInput, InMemStore
from protoprompt.integrations import OllamaClient

llm = OllamaClient(host="http://localhost:11434")
builder = ContextBuilder(InMemStore(), llm)

HttpxLLMClient принимает transport= (например httpx.MockTransport) — удобно для тестов без сети.

Эмбеддинги без API

Классы реализуют только EmbeddingClientProtocol и не притворяются chat-моделями.

Класс Экстра Комментарий
SentenceTransformersClient [local] HF-модели на CPU/GPU
FastEmbedClient [fastembed] ONNX, лёгкая установка

Оба кодируют батчи в рабочем потоке (asyncio.to_thread), не блокируя событийный цикл.

from protoprompt import CompositeLLMClient
from protoprompt.integrations import FastEmbedClient, OpenAIClient

llm = CompositeLLMClient(
    chat_client=OpenAIClient(),
    embedding_client=FastEmbedClient(),
)

Хранилища

Класс Откуда Особенности
SqliteStore (ядро) без зависимостей персистентность, replace-on-add
QdrantStore [qdrant] сервер (url=), локальный режим (path=), in-memory
ChromaStore [chroma] как раньше
PgVectorStore [postgres] async pgvector, явный setup схемы
PostgresMemoryLedger [postgres] экспериментальный sync Ledger; fresh-v7 выделенная schema
ElasticsearchStore [elasticsearch] dense vectors Elasticsearch 9
OpenSearchStore [opensearch] OpenSearch Lucene HNSW

Redis даёт embedding cache, session и profile adapters, но не vector retrieval. PostgresMemoryLedger — не vector store и не async adapter: он явно provision-ит изолированную PostgreSQL schema и сериализует записи Ledger transaction-scoped advisory lock-ом. См. PostgreSQL, Redis и Elasticsearch/OpenSearch.

Управляемые credential stores: AWSSecretsManagerStore ([aws-secrets]) и GCPSecretManagerStore ([gcp-secrets]), подробности в Secrets. Локальное ingestion документов и framework converters описаны в Readers, authenticated service recipe — в FastAPI.

Изоляция tenant/user/thread

MemoryScope закрепляется host-приложением на DocumentIndexer, Retriever, ContextBuilder и Pipeline. Модель не получает параметр, которым можно переключить tenant. Scope одинаково отображается в metadata любого стора, а внутренний doc_id получает детерминированный namespace: одинаковые логические ID разных пользователей не перезаписывают друг друга.

from protoprompt import ContextBuilder, MemoryScope, Pipeline
from protoprompt.rag import DocumentIndexer

scope = MemoryScope(tenant="acme", user="u-42", thread="support-chat")
indexer = DocumentIndexer(store, embedding_client, scope=scope)
builder = ContextBuilder(store, embedding_client, scope=scope)
pipeline = Pipeline(
    store,
    chat_client=chat_client,
    embedding_client=embedding_client,
    scope=scope,
)

Пустой MemoryScope() и отсутствие scope сохраняют layout 0.3: это позволяет мигрировать по одному tenant без массового переноса данных. Поле kind можно использовать для одноцелевых адаптеров; для билдера, который одновременно читает RAG и session memory, обычно оставляют kind="".

Async-хранилища

Любой стор может работать асинхронно:

from protoprompt import as_async, AsyncInMemStore

# готовый async-двойник InMemStore
store = AsyncInMemStore()

# или обёртка над синхронным бэкендом: каждый вызов уходит в поток
store = as_async(ChromaStore(persist_dir="./chroma"))

Билдеры и Pipeline принимают синхронные и асинхронные сторы одинаково.

Кэш эмбеддингов

from protoprompt import CachedLLMClient, InMemoryEmbeddingCache

cached = CachedLLMClient(OllamaClient(), InMemoryEmbeddingCache(capacity=4096))
# повторные build() с тем же query больше не ходят в модель

Хуки наблюдаемости

Для новых интеграций используйте typed events: ContextEvent, RetrieveEvent, CompressEvent, ProfileEvent, RecallEvent, EvictEvent и CacheEvent. Все они несут trace_id, непрозрачный scope_id, длительность и безопасные метрики. EventDispatcher по умолчанию рекурсивно редактирует поля prompt, content, document, profile, secret, token и другие content-bearing значения.

from protoprompt import ContextBuilder, EventDispatcher

events = EventDispatcher(lambda event: telemetry.emit(event.to_dict()))
builder = ContextBuilder(store, embeddings, scope=scope, event_sink=events)

Старые ContextHooks и PipelineHooks сохранены: typed event отправляется первым, затем вызывается совместимый hook. Ошибка любого observer логируется и не прерывает основной поток.

from protoprompt import ContextHooks, PipelineHooks, TokenBudgetedContextBuilder

hooks = ContextHooks(
    on_section_used=lambda label, tokens: print(f"+{tokens} {label}"),
    on_block_dropped=lambda label, reason: print(f"-{label} ({reason})"),
    on_build_done=lambda report: print(f"итог: {report.used_tokens}"),
)
builder = TokenBudgetedContextBuilder(store, llm, hooks=hooks)

В legacy hooks могут передаваться исходные Session/BudgetReport, поэтому их следует считать доверенным in-process API. Для внешнего экспорта используйте typed events.

Contract kit для авторов адаптеров

protoprompt.testing содержит исполняемые контракты для chat-клиентов, эмбеддингов, vector/profile/secret stores. Они не зависят от pytest и одинаково проверяют sync и async реализации:

from protoprompt.testing import check_chat_client, check_vector_store

await check_chat_client(client)
report = await check_vector_store(store)
print(report.checks)

Официальные адаптеры проходят эти же контракты в CI. Live credentials не нужны: HTTP-клиенты тестируются через локальный transport, а server-backed stores — через изолированную тестовую collection.

Владение и deprecation

Адаптеры из дистрибутива protoprompt сопровождает группа EnergoAI Hub/core maintainers. Поддерживаемые диапазоны upstream зафиксированы в pyproject.toml, а обязательная граница приёмки — contract tests и минимум один runnable example. Community adapter без активного владельца остаётся внешним recipe и не объявляется официально поддерживаемым.

Официальный adapter помечается deprecated в документации и changelog минимум за один minor-релиз до удаления. Удаление обычно ждёт следующего major и должно иметь replacement или migration path и явный откат. При срочной уязвимости небезопасное поведение может быть отключено раньше, но migration и rollback note выходят в том же релизе.