Chat models
zenpyre.chat_models ¶
Contain chat models.
zenpyre.chat_models.CachingChatModel ¶
Bases: BaseChatModel
Wrap a chat model to cache its output, keyed by a hash of the messages, stop words, and call kwargs.
Unlike :class:~zenpyre.runnables.CachingRunnable, this class is a
genuine :class:~langchain_core.language_models.BaseChatModel
subclass -- it can be used anywhere a chat model is expected, and
bind_tools returns another CachingChatModel wrapping the
bound inner model, so caching keeps working after tools are bound.
On each call, a cache key is derived from (messages, stop,
kwargs) and used to look up a previously cached ChatResult in
response_cache. On a cache hit, the cached result is returned
without calling the wrapped chat model. On a cache miss, the
wrapped chat model is invoked and its result is stored in
response_cache before being returned. If response_cache is
None, caching is disabled entirely and every call goes straight
to the wrapped chat model.
The field is named response_cache rather than cache because
:class:~langchain_core.language_models.BaseChatModel already
declares a cache: BaseCache | bool | None field for its own,
unrelated built-in caching (langchain.cache); reusing that name
would silently collide with it and break LangChain's cache-lookup
hooks (_generate_with_cache / _agenerate_with_cache), which
read self.cache expecting that type.
response_cache must already be open (via
:meth:~persista.cache.Cache.open / :meth:~persista.cache.Cache.aopen,
or used as a context manager) before it is passed in --
CachingChatModel does not manage its lifecycle, since the same
cache instance is typically shared across multiple wrappers or
callers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chat_model
|
The chat model whose output should be cached. |
required | |
response_cache
|
The :class: |
required | |
key_fn
|
A function that derives a cache key from a
|
required |
Example
>>> from langchain_core.language_models import FakeListChatModel
>>> from persista.cache import Cache
>>> from zenpyre.chat_models import CachingChatModel
>>> with Cache() as cache:
... chat_model = CachingChatModel(
... chat_model=FakeListChatModel(responses=["hello"]),
... response_cache=cache,
... )
... chat_model.invoke("hi").content
...
'hello'
zenpyre.chat_models.ChatModelConfig
dataclass
¶
Bases: ExtraFieldsConfig
A generic chat model configuration.
to_kwargs(), the extra/field-name collision check, and
__hash__ are all inherited from
:class:~zenpyre.utils.config.ExtraFieldsConfig; this class only
needs to declare its own typed field(s).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
str
|
The model identifier. |
required |
extra
|
dict[str, Any]
|
Additional keyword arguments merged into
:meth: |
dict()
|
Example
>>> from zenpyre.chat_models import ChatModelConfig
>>> cfg = ChatModelConfig(model="gpt-4", extra={"temperature": 0.2})
>>> cfg.model
'gpt-4'
>>> cfg.to_kwargs()
{'model': 'gpt-4', 'temperature': 0.2}
zenpyre.chat_models.ChatModelConfig.from_kwargs
classmethod
¶
from_kwargs(model: str, **kwargs: Any) -> Self
Construct a :class:ChatModelConfig from a model identifier
and arbitrary keyword arguments.
A convenience alternative to the regular constructor's
extra={...} dict, letting callers pass extra fields
directly as keyword arguments instead:
ChatModelConfig.from_kwargs("gpt-4", temperature=0.2) is
equivalent to
ChatModelConfig(model="gpt-4", extra={"temperature": 0.2}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
str
|
The model identifier. |
required |
**kwargs
|
Any
|
Additional keyword arguments, stored as
|
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
A new :class: |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Example
>>> from zenpyre.chat_models import ChatModelConfig
>>> cfg = ChatModelConfig.from_kwargs("gpt-4", temperature=0.2)
>>> cfg.to_kwargs()
{'model': 'gpt-4', 'temperature': 0.2}
zenpyre.chat_models.ainvoke_structured_llm
async
¶
ainvoke_structured_llm(
*,
chat_model: BaseChatModel,
output_type: type[BaseModel],
system_prompt: str,
user_content: str,
timeblock_message: str = "LLM generated answer in {time}"
) -> tuple[Any, dict[str, Any]]
Invoke chat_model for a structured output_type response.
Shared by every agent's single-shot structured LLM call (adaptive query planning, assessment, judging): build the structured-output runnable, invoke it with a system/user message pair, and log token usage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chat_model
|
BaseChatModel
|
LangChain chat model to invoke. |
required |
output_type
|
type[BaseModel]
|
Pydantic model the response must conform to. |
required |
system_prompt
|
str
|
System prompt for the call. |
required |
user_content
|
str
|
User message content for the call. |
required |
timeblock_message
|
str
|
Message template passed to :func: |
'LLM generated answer in {time}'
|
Returns:
| Type | Description |
|---|---|
Any
|
A tuple |
dict[str, Any]
|
structured output ( |
tuple[Any, dict[str, Any]]
|
|
tuple[Any, dict[str, Any]]
|
that need to inspect |
tuple[Any, dict[str, Any]]
|
failure. |
zenpyre.chat_models.invoke_structured_llm ¶
invoke_structured_llm(
*,
chat_model: BaseChatModel,
output_type: type[BaseModel],
system_prompt: str,
user_content: str,
timeblock_message: str = "LLM generated answer in {time}"
) -> tuple[Any, dict[str, Any]]
Invoke chat_model for a structured output_type response.
Shared by every agent's single-shot structured LLM call (adaptive query planning, assessment, judging): build the structured-output runnable, invoke it with a system/user message pair, and log token usage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chat_model
|
BaseChatModel
|
LangChain chat model to invoke. |
required |
output_type
|
type[BaseModel]
|
Pydantic model the response must conform to. |
required |
system_prompt
|
str
|
System prompt for the call. |
required |
user_content
|
str
|
User message content for the call. |
required |
timeblock_message
|
str
|
Message template passed to :func: |
'LLM generated answer in {time}'
|
Returns:
| Type | Description |
|---|---|
Any
|
A tuple |
dict[str, Any]
|
structured output ( |
tuple[Any, dict[str, Any]]
|
|
tuple[Any, dict[str, Any]]
|
that need to inspect |
tuple[Any, dict[str, Any]]
|
failure. |
zenpyre.chat_models.resolve_chat_model ¶
resolve_chat_model(
chat_model: BaseChatModel | dict[str, Any] | BaseConfig,
) -> BaseChatModel
Resolve a LangChain
:class:~langchain_core.language_models.BaseChatModel instance from
an existing object, a configuration dictionary, or a
:class:~zenpyre.utils.config.BaseConfig.
If chat_model is already a
:class:~langchain_core.language_models.BaseChatModel instance
it is returned as-is. If it is a :class:dict or a
:class:~zenpyre.utils.config.BaseConfig, it is treated as an
objectory factory configuration and instantiated via
:func:objectory.factory. See
:func:~zenpyre.utils.resolve.resolve_object for details.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chat_model
|
BaseChatModel | dict[str, Any] | BaseConfig
|
Either a fully configured
:class: |
required |
Returns:
| Type | Description |
|---|---|
BaseChatModel
|
A configured |
BaseChatModel
|
class: |
BaseChatModel
|
instance. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the resolved object is not a
:class: |
Example
>>> from langchain_core.language_models import FakeListChatModel
>>> from zenpyre.chat_models import resolve_chat_model
>>> # From an existing instance:
>>> chat_model = resolve_chat_model(FakeListChatModel(responses=["hello"]))
>>> # From a configuration dictionary:
>>> chat_model = resolve_chat_model( # doctest: +SKIP
... {
... "_target_": "langchain_core.language_models.FakeListChatModel",
... "responses": ["hello"],
... }
... )
zenpyre.chat_models.factory ¶
Contain factories for chat models.
zenpyre.chat_models.factory.BaseChatModelFactory ¶
Bases: ABC
Abstract base class for LangChain
:class:~langchain_core.language_models.BaseChatModel factories.
Subclasses implement :meth:make_chat_model to instantiate and
return a configured
:class:~langchain_core.language_models.BaseChatModel object.
This pattern decouples chat model creation from the rest of the
codebase, making it easy to swap chat models (e.g. OpenAI,
Anthropic, a fake model for testing) without changing call sites.
Example
>>> from langchain_core.language_models import BaseChatModel, FakeListChatModel
>>> from zenpyre.chat_models.factory import BaseChatModelFactory
>>> class MyChatModelFactory(BaseChatModelFactory):
... def make_chat_model(self) -> BaseChatModel:
... return FakeListChatModel(responses=["hello"])
...
>>> factory = MyChatModelFactory()
>>> chat_model = factory.make_chat_model()
zenpyre.chat_models.factory.BaseChatModelFactory.make_chat_model
abstractmethod
¶
make_chat_model() -> BaseChatModel
Create and return a configured BaseChatModel instance.
Returns:
| Name | Type | Description |
|---|---|---|
A |
BaseChatModel
|
class: |
BaseChatModel
|
instance ready for use. |
zenpyre.chat_models.factory.CachingChatModelFactory ¶
Bases: BaseChatModelFactory, MultilineDisplayMixin
A concrete chat model factory that wraps another chat model
factory and caches the resulting model's outputs via
:class:~zenpyre.chat_models.CachingChatModel.
The wrapped chat model is built by delegating to the inner
factory, then wrapped in a
:class:~zenpyre.chat_models.CachingChatModel so every call to the
model transparently reads from and writes to cache. Unlike
:class:~zenpyre.runnables.CachingRunnable, the returned object is
a genuine :class:~langchain_core.language_models.BaseChatModel
instance, so bind_tools and other BaseChatModel-specific
methods keep working after wrapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chat_model_factory
|
BaseChatModelFactory | dict[str, Any] | BaseConfig
|
The wrapped chat model factory, an
objectory configuration, or a :class: |
required |
cache
|
Cache | None
|
The :class: |
None
|
key_fn
|
Callable[[Any], str] | None
|
A function that derives a cache key from an input. See
:class: |
None
|
Example
>>> from langchain_core.language_models import FakeListChatModel
>>> from persista.cache import Cache
>>> from zenpyre.chat_models.factory import CachingChatModelFactory, ChatModelFactory
>>> factory = CachingChatModelFactory(
... chat_model_factory=ChatModelFactory(FakeListChatModel(responses=["hello"])),
... cache=Cache(),
... )
>>> chat_model = factory.make_chat_model()
zenpyre.chat_models.factory.ChatModelFactory ¶
Bases: BaseChatModelFactory, MultilineDisplayMixin
A concrete BaseChatModel factory that wraps a pre-built
:class:~langchain_core.language_models.BaseChatModel instance.
Use this when the chat model is already instantiated and you
simply want to wrap it in the :class:~BaseChatModelFactory
interface — for example, when injecting a fixed chat model into a
component that expects a factory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chat_model
|
BaseChatModel
|
A fully configured
:class: |
required |
Example
>>> from langchain_core.language_models import FakeListChatModel
>>> from zenpyre.chat_models.factory import ChatModelFactory
>>> factory = ChatModelFactory(FakeListChatModel(responses=["hello"]))
>>> chat_model = factory.make_chat_model()
zenpyre.chat_models.factory.ConfigurableChatModelFactory ¶
Bases: BaseChatModelFactory, MultilineDisplayMixin
A concrete BaseChatModel factory that accepts either a pre-built
:class:~langchain_core.language_models.BaseChatModel instance or a
configuration dictionary.
When a dict is provided it is resolved at each
:meth:make_chat_model call via
:func:~zenpyre.chat_models.resolve.resolve_chat_model, which
uses objectory to instantiate the configured class. When an
instance is provided it is returned as-is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chat_model
|
BaseChatModel | dict[str, Any]
|
A fully configured
:class: |
required |
Example
>>> from langchain_core.language_models import FakeListChatModel
>>> from zenpyre.chat_models.factory import ConfigurableChatModelFactory
>>> factory = ConfigurableChatModelFactory(FakeListChatModel(responses=["hello"]))
>>> chat_model = factory.make_chat_model()
zenpyre.chat_models.factory.InitChatModelFactory ¶
Bases: BaseChatModelFactory, MultilineDisplayMixin
A concrete BaseChatModel factory that wraps
langchain.chat_models.init_chat_model, building a fresh chat
model on each :meth:make_chat_model call.
Each call to :meth:make_chat_model forwards model and any
additional keyword arguments to init_chat_model, which
resolves the appropriate provider integration (e.g. from a
"provider:model" string or model_provider) and
instantiates it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
str | None
|
The model name, optionally prefixed with its provider
(e.g. |
None
|
**kwargs
|
Any
|
Additional keyword arguments forwarded as-is to
|
{}
|
Example
>>> from zenpyre.chat_models.factory import InitChatModelFactory
>>> factory = InitChatModelFactory(model="openai:gpt-4o-mini", api_key="sk-...")
>>> chat_model = factory.make_chat_model()