Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## [v0.4.11] - 2025-06-30

- **LLM Settings Simplification**: Streamlined LLM choice system by removing complex `for_object_direct`, `for_object_list`, and `for_object_list_direct` options. LLM selection now uses a simpler fallback pattern: specific choice β†’ text choice β†’ overrides β†’ defaults.
- **Image Model Updates**: Renamed `image_bytes` field to `base_64` in `PromptImageTypedBytes` for better consistency. Updated to use `CustomBaseModel` base class to benefit from bytes truncation when printing.

## [v0.4.10] - 2025-06-30

- Fixed a bad import statement
Expand Down
11 changes: 6 additions & 5 deletions pipelex/cogt/image/prompt_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

from pipelex.tools.misc.attribute_utils import AttributePolisher
from pipelex.tools.misc.filetype_utils import FileType, detect_file_type_from_base64, detect_file_type_from_path
from pipelex.tools.typing.pydantic_utils import CustomBaseModel


class PromptImageTypedBytes(BaseModel):
image_bytes: bytes
class PromptImageTypedBytes(CustomBaseModel):
base_64: bytes
file_type: FileType


Expand Down Expand Up @@ -37,7 +38,7 @@ class PromptImageUrl(PromptImage):
@override
def __str__(self) -> str:
truncated_url = AttributePolisher.get_truncated_value(name="url", value=self.url)
return f"PromptImageUrl(url='{truncated_url}')"
return f"PromptImageUrl(url='{truncated_url!r}')"

@override
def __format__(self, format_spec: str) -> str:
Expand All @@ -54,7 +55,7 @@ def get_file_type(self) -> FileType:
def __str__(self) -> str:
base_64_str = str(self.base_64)
truncated_base_64 = AttributePolisher.get_truncated_value(name="base_64", value=base_64_str)
return f"PromptImageBytes(image_bytes={truncated_base_64})"
return f"PromptImageBytes(image_bytes={truncated_base_64!r})"

@override
def __repr__(self) -> str:
Expand All @@ -65,4 +66,4 @@ def __format__(self, format_spec: str) -> str:
return self.__str__()

def make_prompt_image_typed_bytes(self) -> PromptImageTypedBytes:
return PromptImageTypedBytes(image_bytes=self.base_64, file_type=self.get_file_type())
return PromptImageTypedBytes(base_64=self.base_64, file_type=self.get_file_type())
92 changes: 0 additions & 92 deletions pipelex/cogt/llm/llm_models/llm_deck.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from pydantic import field_validator, model_validator
from typing_extensions import Self, override

from pipelex import log
from pipelex.cogt.exceptions import LLMDeckValidatonError, LLMHandleNotFoundError, LLMPresetNotFoundError, LLMSettingsValidationError
from pipelex.cogt.llm.llm_models.llm_deck_abstract import LLMDeckAbstract
from pipelex.cogt.llm.llm_models.llm_engine_blueprint import LLMEngineBlueprint
Expand Down Expand Up @@ -51,80 +50,6 @@ def get_llm_setting(self, llm_setting_or_preset_id: LLMSettingOrPresetId) -> LLM
raise LLMPresetNotFoundError(f"LLM preset '{llm_setting_or_preset_id}' not found in deck")
return the_llm_preset

@override
def get_llm_setting_for_text(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
llm_setting: LLMSettingOrPresetId
if replacement := self.llm_choice_overrides.for_text:
log.warning(f"General llm setting override for text, '{self.llm_choice_defaults.for_text}' -> '{replacement}'")
llm_setting = replacement
elif override and (provided_override_for_text := override.for_text):
llm_setting = provided_override_for_text
elif self.llm_choice_defaults.for_text is None:
raise ConfigValidationError("llm_choices.for_text cannot be None")
else:
llm_setting = self.llm_choice_defaults.for_text

return self.get_llm_setting(llm_setting_or_preset_id=llm_setting)

@override
def get_llm_setting_for_object(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
log.debug(f"Getting LLM setting for object with provided_override: {override}")
llm_setting: LLMSettingOrPresetId
if replacement := self.llm_choice_overrides.for_object:
log.warning(f"General llm setting override for object, '{self.llm_choice_defaults.for_object}' -> '{replacement}'")
llm_setting = replacement
elif override and (provided_override_for_object := override.for_object):
llm_setting = provided_override_for_object
elif self.llm_choice_defaults.for_object is None:
raise ConfigValidationError("llm_choices.for_object cannot be None")
else:
llm_setting = self.llm_choice_defaults.for_object

return self.get_llm_setting(llm_setting_or_preset_id=llm_setting)

@override
def get_llm_setting_for_object_direct(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
log.debug(f"Getting LLM preset for object direct with provided_override: {override}")
llm_setting: LLMSettingOrPresetId
if replacement := self.llm_choice_overrides.for_object_direct:
log.warning(f"General choice override for LLM preset for structured, '{self.llm_choice_defaults.for_object_direct}' -> '{replacement}'")
llm_setting = replacement
elif override and (provided_override_for_object_direct := override.for_object_direct):
llm_setting = provided_override_for_object_direct
elif self.llm_choice_defaults.for_object_direct is None:
raise ConfigValidationError("llm_choices.for_object_direct cannot be None")
else:
llm_setting = self.llm_choice_defaults.for_object_direct

return self.get_llm_setting(llm_setting_or_preset_id=llm_setting)

@override
def get_llm_setting_for_object_list(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
llm_setting: LLMSettingOrPresetId
if replacement := self.llm_choice_overrides.for_object_list:
log.warning(f"General choice override for LLM preset for structured, '{self.llm_choice_defaults.for_object_list}' -> '{replacement}'")
llm_setting = replacement
elif override and (provided_override_for_object_list := override.for_object_list):
llm_setting = provided_override_for_object_list
elif self.llm_choice_defaults.for_object_list is None:
raise ConfigValidationError("llm_choices.for_object_list cannot be None")
else:
llm_setting = self.llm_choice_defaults.for_object_list

return self.get_llm_setting(llm_setting_or_preset_id=llm_setting)

@override
def get_llm_setting_for_object_list_direct(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
llm_setting: LLMSettingOrPresetId
if override and (provided_override_for_object_list_direct := override.for_object_list_direct):
llm_setting = provided_override_for_object_list_direct
elif self.llm_choice_defaults.for_object_list_direct is None:
raise ConfigValidationError("llm_choices.for_object_list_direct cannot be None")
else:
llm_setting = self.llm_choice_defaults.for_object_list_direct

return self.get_llm_setting(llm_setting_or_preset_id=llm_setting)

@override
def find_llm_model(self, llm_handle: str) -> LLMModel:
llm_models_provider = get_llm_models_provider()
Expand Down Expand Up @@ -202,12 +127,6 @@ def validate_llm_choice_defaults(cls, llm_choice_defaults: LLMSettingChoices) ->
raise ConfigValidationError("llm_choice_defaults.for_text cannot be None")
if llm_choice_defaults.for_object is None:
raise ConfigValidationError("llm_choice_defaults.for_object cannot be None")
if llm_choice_defaults.for_object_direct is None:
raise ConfigValidationError("llm_choice_defaults.for_object_direct cannot be None")
if llm_choice_defaults.for_object_list is None:
raise ConfigValidationError("llm_choice_defaults.for_object_list cannot be None")
if llm_choice_defaults.for_object_list_direct is None:
raise ConfigValidationError("llm_choice_defaults.for_object_list_direct cannot be None")
return llm_choice_defaults

@field_validator("llm_choice_overrides", mode="after")
Expand All @@ -217,12 +136,6 @@ def validate_llm_choice_overrides(cls, value: LLMSettingChoices) -> LLMSettingCh
value.for_text = None
if value.for_object == LLM_PRESET_DISABLED:
value.for_object = None
if value.for_object_direct == LLM_PRESET_DISABLED:
value.for_object_direct = None
if value.for_object_list == LLM_PRESET_DISABLED:
value.for_object_list = None
if value.for_object_list_direct == LLM_PRESET_DISABLED:
value.for_object_list_direct = None
return value

def add_llm_name_as_handle_with_defaults(self, llm_name: str):
Expand All @@ -237,11 +150,6 @@ def validate_llm_presets(self) -> Self:
raise LLMHandleNotFoundError(f"llm_handle '{llm_setting.llm_handle}' for llm_preset '{llm_preset_id}' not found in deck")
return self

@model_validator(mode="after")
def validate_llm_default_choices(self) -> Self:
self._validate_llm_choices(llm_choices=self.llm_choice_defaults)
return self

@model_validator(mode="after")
def validate_llm_setting_overrides(self) -> Self:
self._validate_llm_choices(llm_choices=self.llm_choice_overrides)
Expand Down
27 changes: 2 additions & 25 deletions pipelex/cogt/llm/llm_models/llm_deck_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@

from pipelex.cogt.llm.llm_models.llm_engine_blueprint import LLMEngineBlueprint
from pipelex.cogt.llm.llm_models.llm_model import LLMModel
from pipelex.cogt.llm.llm_models.llm_setting import LLMSetting, LLMSettingChoices, LLMSettingOrPresetId
from pipelex.cogt.llm.llm_models.llm_setting import LLMSetting, LLMSettingChoices, LLMSettingChoicesDefaults, LLMSettingOrPresetId


class LLMDeckAbstract(ABC):
llm_handles: Dict[str, LLMEngineBlueprint] = Field(default_factory=dict)
llm_external_handles: List[str] = Field(default_factory=list)
llm_presets: Dict[str, LLMSetting] = Field(default_factory=dict)
llm_choice_defaults: LLMSettingChoices
llm_choice_defaults: LLMSettingChoicesDefaults
llm_choice_overrides: LLMSettingChoices = LLMSettingChoices(
for_text=None,
for_object=None,
for_object_direct=None,
for_object_list=None,
for_object_list_direct=None,
)

@abstractmethod
Expand All @@ -34,26 +31,6 @@ def get_llm_engine_blueprint(self, llm_handle: str) -> LLMEngineBlueprint:
def get_llm_setting(self, llm_setting_or_preset_id: LLMSettingOrPresetId) -> LLMSetting:
pass

@abstractmethod
def get_llm_setting_for_text(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
pass

@abstractmethod
def get_llm_setting_for_object(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
pass

@abstractmethod
def get_llm_setting_for_object_direct(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
pass

@abstractmethod
def get_llm_setting_for_object_list(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
pass

@abstractmethod
def get_llm_setting_for_object_list_direct(self, override: Optional[LLMSettingChoices] = None) -> LLMSetting:
pass

@abstractmethod
def find_llm_model(self, llm_handle: str) -> LLMModel:
pass
Expand Down
17 changes: 5 additions & 12 deletions pipelex/cogt/llm/llm_models/llm_setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@ def desc(self) -> str:
LLMSettingOrPresetId = Union[LLMSetting, str]


class LLMSettingChoicesDefaults(ConfigModel):
for_text: LLMSettingOrPresetId
for_object: LLMSettingOrPresetId


class LLMSettingChoices(ConfigModel):
for_text: Optional[LLMSettingOrPresetId]
for_object: Optional[LLMSettingOrPresetId]
for_object_direct: Optional[LLMSettingOrPresetId]
for_object_list: Optional[LLMSettingOrPresetId]
for_object_list_direct: Optional[LLMSettingOrPresetId]

def list_used_presets(self) -> Set[str]:
return set(
Expand All @@ -69,9 +71,6 @@ def list_used_presets(self) -> Set[str]:
for setting in [
self.for_text,
self.for_object,
self.for_object_direct,
self.for_object_list,
self.for_object_list_direct,
]
if isinstance(setting, str)
]
Expand All @@ -82,14 +81,8 @@ def make_completed_with_defaults(
cls,
for_text: Optional[LLMSettingOrPresetId] = None,
for_object: Optional[LLMSettingOrPresetId] = None,
for_object_direct: Optional[LLMSettingOrPresetId] = None,
for_object_list: Optional[LLMSettingOrPresetId] = None,
for_object_list_direct: Optional[LLMSettingOrPresetId] = None,
) -> Self:
return cls(
for_text=for_text,
for_object=for_object,
for_object_direct=for_object_direct,
for_object_list=for_object_list,
for_object_list_direct=for_object_list_direct,
)
3 changes: 0 additions & 3 deletions pipelex/libraries/llm_deck/base_llm_deck.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,3 @@ llm_to_extract_tables = { llm_handle = "best-claude", temperature = 0.1 }
[llm_choice_defaults]
for_text = "cheap_llm_for_text"
for_object = "cheap_llm_for_object"
for_object_direct = "cheap_llm_for_object"
for_object_list = "cheap_llm_for_object"
for_object_list_direct = "cheap_llm_for_object"
3 changes: 0 additions & 3 deletions pipelex/libraries/llm_deck/overrides.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,3 @@
[llm_choice_overrides]
for_text = "disabled"
for_object = "disabled"
for_object_direct = "disabled"
for_object_list = "disabled"
for_object_list_direct = "disabled"
Loading