Conversation
|
Warning Rate limit exceeded@KaQuMiQ has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 4 minutes and 14 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (48)
WalkthroughReplaces the Instructions subsystem with a Templates subsystem across the codebase. Adds Template and TemplateDeclaration types, template variable parsing/resolution utilities, in-memory/File/Postgres TemplatesRepository backends, tests for template variable handling, and documentation (Templates guide, mkdocs). Removes instruction-related modules, types, repository implementations, and public exports. Updates numerous call sites and public signatures to accept Template | ModelInstructions and to resolve via TemplatesRepository.resolve_str. Also bumps pyproject version and updates the Makefile (removed Estimated code review effort🎯 5 (Critical) | ⏱️ ~150 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
Makefile (2)
23-30: Harden uv install/update: avoidcurl | shand masked failures.Current pipelines can succeed even when download fails (no
pipefailinsh). Replace with explicit download + guarded execution.Apply this diff to both install and update blocks:
- echo '...installing uv...'; \ - curl -fLsS https://astral.sh/uv/install.sh | sh; \ - if [ $$? -ne 0 ]; then \ - echo "...installing uv failed!"; \ - exit 1; \ - fi; \ + echo '...installing uv...'; \ + tmp="$$(mktemp)"; \ + if ! curl -fLsS https://astral.sh/uv/install.sh -o "$$tmp"; then \ + echo "...downloading uv installer failed!"; exit 1; \ + fi; \ + if ! sh "$$tmp"; then \ + echo "...installing uv failed!"; exit 1; \ + fi; \ + rm -f "$$tmp"; \- echo '...updating uv...'; \ - curl -fLsS https://astral.sh/uv/install.sh | sh; \ - if [ $$? -ne 0 ]; then \ - echo "...updating uv failed!"; \ - exit 1; \ - fi; \ + echo '...updating uv...'; \ + tmp="$$(mktemp)"; \ + if ! curl -fLsS https://astral.sh/uv/install.sh -o "$$tmp"; then \ + echo "...downloading uv installer failed!"; exit 1; \ + fi; \ + if ! sh "$$tmp"; then \ + echo "...updating uv failed!"; exit 1; \ + fi; \ + rm -f "$$tmp"; \Also applies to: 33-45
33-36:sort -Vis not portable to macOS/BSD and will fail in CI onmacos-latestrunners.The CI workflow explicitly tests on both
ubuntu-latestandmacos-latest(see.github/workflows/ci.yml). BSDsortlacks the-Vflag, and the Makefile'suv_checktarget runs unconditionally without fallback logic, which will cause CI failures on macOS runners.The test script output showing
sort -V availablewas from an Ubuntu environment (which has GNU sort). This doesn't apply to macOS runners where BSD sort is the default.Recommended fix: Either (1) gate
sort -Vwith a portable comparator (Python,awk, or similar), (2) detect OS and usegsortif available on macOS, or (3) use a version-agnostic comparison method.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (6)
Makefile(1 hunks)pyproject.toml(1 hunks)src/draive/multimodal/templates/repository.py(1 hunks)src/draive/multimodal/templates/types.py(1 hunks)src/draive/multimodal/templates/variables.py(1 hunks)tests/test_multimodal_template_variables.py(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use Python 3.12+ features and syntax across the codebase
Format code exclusively with Ruff (make format); do not use other formatters
Skip module-level docstrings
Files:
tests/test_multimodal_template_variables.pysrc/draive/multimodal/templates/variables.pysrc/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/repository.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Do not perform real network I/O in unit tests; mock providers/HTTP
Keep tests fast and focused on changed code; start with unit tests around new types/functions/adapters
Use fixtures from tests/ or add focused ones; avoid heavy integration scaffolding
Use pytest-asyncio for coroutine tests (@pytest.mark.asyncio)
Prefer scoping with ctx.scope(...) in async tests and bind required State instances explicitly
Avoid real I/O and network in async tests; stub provider calls and HTTP
Files:
tests/test_multimodal_template_variables.py
{pyproject.toml,pyrightconfig.json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Ruff, Bandit, and Pyright (strict) via make lint
Files:
pyproject.toml
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly (from haiway import State, ctx)
Use ctx.scope(...) to bind scoped Disposables and active State; avoid global state
Route all logs through ctx.log_debug/info/warn/error; do not use print
Use latest, most strict typing syntax (Python 3.12+), with strict typing only for public APIs
Avoid loose Any except at explicit third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
Prefer Mapping/Sequence/Iterable in public types over dict/list/set
Use final where applicable; avoid inheritance and prefer composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Model immutable data/config and facades with haiway.State; provide ergonomic classmethods like .of(...)
Avoid in-place mutation; use State.updated(...) or functional builders to produce new instances
Access active state via haiway.ctx inside async scopes (ctx.scope(...))
Use @statemethod for public state methods that dispatch on the active instance
Log around generation calls, tool dispatch, and provider requests/responses without leaking secrets; prefer structured/concise messages
Add metrics via ctx.record where applicable
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks
Use structured concurrency and valid coroutine usage; rely on haiway/asyncio; avoid custom threading
Construct multimodal content with MultimodalContent.of(...) and compose blocks explicitly
Use ResourceContent/ResourceReference for media/data blobs
Wrap custom types/data within ArtifactContent; use hidden when needed
Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings on internal helpers; keep names self-explanatory
Keep docstrings high-quality; mkdocstrings pulls them into API reference
Never log secrets or full request bodies containing keys/tokens
Files:
src/draive/multimodal/templates/variables.pysrc/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/repository.py
src/draive/multimodal/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Files:
src/draive/multimodal/templates/variables.pysrc/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/repository.py
🧬 Code graph analysis (3)
tests/test_multimodal_template_variables.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(13-37)resolve_multimodal_template(93-146)resolve_text_template(40-90)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/multimodal/templates/variables.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
of(29-41)of(78-92)
src/draive/multimodal/templates/repository.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (8)
Template(27-72)TemplateDeclaration(76-97)TemplateDefining(119-128)TemplateListing(101-105)TemplateLoading(109-115)TemplateMissing(14-23)of(29-41)of(78-92)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(13-37)resolve_multimodal_template(93-146)resolve_text_template(40-90)
🔇 Additional comments (5)
Makefile (1)
12-14: UV_VERSION bump looks fine.pyproject.toml (1)
8-8: Version bump to 0.90.0: OK.tests/test_multimodal_template_variables.py (1)
1-203: Comprehensive and focused tests. LGTM.Covers edge cases, error paths, and multimodal specifics without real I/O.
src/draive/multimodal/templates/repository.py (1)
440-451: Code uses correct logging API — no changes needed.The actual haiway API method name is
ctx.log_warning, notctx.log_warn. The codebase confirms this consistently: a search acrosssrc/draive/found 20+ instances ofctx.log_warningand zero instances ofctx.log_warn. The code at lines 440–451 correctly uses bothctx.log_warning()andctx.log_error()as per the haiway API.src/draive/multimodal/templates/types.py (1)
14-23: LGTM!The exception implementation follows best practices with
__slots__, clear error messaging, and proper attribute storage.
aaf87e6 to
41456ab
Compare
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (15)
src/draive/helpers/instruction_preparation.py (2)
68-80: Unify tag naming with prompt examples (“VARIABLES” vs “TASK_VARIABLES”).Examples in PREPARE_INSTRUCTION use …. Consider matching to reduce model confusion.
- if not instruction.variables: - return "<TASK_VARIABLES>N/A</TASK_VARIABLES>" + if not instruction.variables: + return "<VARIABLES>N/A</VARIABLES>" ... - return f"<TASK_VARIABLES>\n{arguments}\n</TASK_VARIABLES>" + return f"<VARIABLES>\n{arguments}\n</VARIABLES>"
15-23: Add NumPy‑style docstrings for public API (exception and function).Please document InstructionPreparationAmbiguity and prepare_instructions (Parameters/Returns/Raises, brief rationale).
As per coding guidelines.
Also applies to: 25-31
docs/guides/Postgres.md (3)
14-21: Remove PostgresInstructionsRepository from imports.It’s no longer exported in draive.postgres and will break the example. Keep PostgresTemplatesRepository.
Apply this diff:
from draive.postgres import ( Postgres, PostgresConnectionPool, - PostgresConfigurationRepository, - PostgresInstructionsRepository, + PostgresConfigurationRepository, PostgresModelMemory, PostgresTemplatesRepository, )
25-33: Drop PostgresInstructionsRepository from the scope example and fix typo.“use use” typo and outdated repository reference.
Apply this diff:
- PostgresConfigurationRepository(), # use use postgres configurations - PostgresInstructionsRepository(), # use postgres instructions + PostgresConfigurationRepository(), # use postgres configurations PostgresTemplatesRepository(), # use postgres templates
1-257: Remove outdated PostgresInstructionsRepository references and non-existent resolve_as_text method from docs.The class
PostgresInstructionsRepositoryand its correspondingresolve_as_textmethod no longer exist in the codebase. Updatedocs/guides/Postgres.mdto:
- Remove
PostgresInstructionsRepositoryfrom the imports (line 18)- Remove its instantiation from the context scope (line 26)
- Delete the entire "InstructionsRepository implementation" section (lines 67–88)
- Update line 119 to remove the reference to
resolve_as_text(template)methodsrc/draive/models/generative.py (1)
615-699: Fix signature and docstring inconsistency.The method signature declares
instructions: ModelInstructions(lines 620, 631, 642) but the docstring at line 656 claims it acceptsTemplate | ModelInstructions. Additionally, line 657 mentions the obsoleteInstructionsRepository.Other similar methods across the codebase (e.g.,
src/draive/conversation/realtime/state.py,src/draive/generation/image/state.py) acceptTemplate | ModelInstructions, suggesting this is an incomplete migration.Apply this diff to align the signature with the docstring and other similar APIs:
@overload @classmethod async def session( cls, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "", memory: ModelMemory | ModelContext = (), tools: ModelToolsDeclaration = ModelToolsDeclaration.none, output: ModelSessionOutputSelection = "auto", **extra: Any, ) -> ModelSessionScope: ... @overload async def session( self, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "", memory: ModelMemory | ModelContext = (), tools: ModelToolsDeclaration = ModelToolsDeclaration.none, output: ModelSessionOutputSelection = "auto", **extra: Any, ) -> ModelSessionScope: ... @statemethod async def session( self, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "", memory: ModelMemory | ModelContext = (), tools: ModelToolsDeclaration = ModelToolsDeclaration.none, output: ModelSessionOutputSelection = "auto", **extra: Any, ) -> ModelSessionScope: """Prepare and open a realtime session. - Resolves ``instructions`` (via ``InstructionsRepository``), normalizes the provided - ``memory`` into a ``ModelMemory`` if a raw context is given, and delegates to the - provider's ``session_preparing`` to obtain a ``ModelSessionScope``. + Normalizes the provided ``memory`` into a ``ModelMemory`` if a raw context is given, + and delegates to the provider's ``session_preparing`` to obtain a ``ModelSessionScope``. Parameters ---------- instructions : Template | ModelInstructions, optional - Instructions or an instruction reference resolvable by ``InstructionsRepository``. + Instructions to steer the session.Also add the Template import at the top of the file:
+from draive.multimodal import Templatesrc/draive/generation/model/default.py (2)
28-31: Makeexamplesoptional (non-breaking API).Requiring
examplesforces all callers to pass an iterable even when unused. Default it to an empty tuple.
[seek_conciseness]Apply:
- examples: Iterable[tuple[MultimodalContent, Generated]], + examples: Iterable[tuple[MultimodalContent, Generated]] = (),
20-31: Add NumPy-style docstring for public API.
generate_modelis exported via__all__; per guidelines, document Parameters/Returns/Raises.As per coding guidelines
src/draive/conversation/realtime/default.py (1)
51-57: Pass**extrainto template resolution.Some repositories may rely on these kwargs (e.g., routing, tenancy).
Apply:
- session_scope: ModelSessionScope = await RealtimeGenerativeModel.session( - instructions=await TemplatesRepository.resolve_str(instructions), + session_scope: ModelSessionScope = await RealtimeGenerativeModel.session( + instructions=await TemplatesRepository.resolve_str(instructions, **extra), memory=memory, tools=toolbox.available_tools_declaration(), output=output, **extra, )src/draive/conversation/completion/default.py (3)
96-103: Template variables are not applied;arguments=kw is ignored byresolve_str.
TemplatesRepository.resolve_strdoes not take anargumentsparameter; it only usesTemplate.arguments. As written, memory variables are never merged, so placeholders won’t resolve. Merge memory variables into the Template first, then resolve; mirror this in streaming.Apply this diff:
- result: ModelOutput = await GenerativeModel.loop( - instructions=instructions - if isinstance(instructions, str) - else await TemplatesRepository.resolve_str( - instructions, - arguments=memory_recall.variables, - ), + merged: str + if isinstance(instructions, Template): + # do not override explicitly provided template arguments + merged_template = instructions.with_arguments( + **{k: v for k, v in memory_recall.variables.items() if k not in instructions.arguments} + ) + merged = await TemplatesRepository.resolve_str(merged_template) + else: + merged = instructions # ModelInstructions (str) + + result: ModelOutput = await GenerativeModel.loop( + instructions=merged, toolbox=toolbox, context=context, **extra, )Based on coding guidelines.
143-149: Streaming path drops memory variables.
resolve_str(instructions)doesn’t incorporate memory variables. Merge them into the Template as above to keep behavior consistent.Apply this diff:
- async for chunk in await GenerativeModel.loop( - instructions=await TemplatesRepository.resolve_str(instructions), + # merge memory variables if a Template is used + resolved_instructions = ( + await TemplatesRepository.resolve_str( + instructions.with_arguments( + **{k: v for k, v in memory_recall.variables.items() if isinstance(instructions, Template) and k not in instructions.arguments} + ) + ) + if isinstance(instructions, Template) + else instructions + ) + + async for chunk in await GenerativeModel.loop( + instructions=resolved_instructions, toolbox=toolbox, context=context, stream=True, **extra, ):Based on coding guidelines.
160-162: Asserting away tool requests may break streaming under tools.If
GenerativeModel.loop(stream=True)can yieldModelToolRequest, this assert will crash. Either handle or skip such chunks explicitly.Example minimal handling:
- else: - assert not isinstance(chunk, ModelToolRequest) # nosec: B101 - yield ConversationOutputChunk.of(chunk) + else: + if isinstance(chunk, ModelToolRequest): + # either ignore, or surface as a dedicated chunk type + continue + yield ConversationOutputChunk.of(chunk)Please confirm the loop’s guarantees in this module’s contract. Based on coding guidelines.
src/draive/stages/stage.py (1)
2054-2060: Routing prompt has typos/formatting issues.
- “Respond with with” → duplicate word.
- Example hint lacks a closing parenthesis and is a bit awkward.
Apply this diff:
- instructions: str = ( - "Based on the provided context and the current result," # nosec: B608 - false positive - " select the most appropriate option from the following:" - f"\n\n{options_text}" - "\n\nRespond with with the exact option name within SELECTION xml tag" - f" like (e.g., '<SELECTION>{next(iter(options.keys()))}</SELECTION>'" - ) + instructions: str = ( + "Based on the provided context and the current result, " # nosec: B608 - false positive + "select the most appropriate option from the following:" + f"\n\n{options_text}" + "\n\nRespond with the exact option name within a SELECTION xml tag, " + f"e.g., '<SELECTION>{next(iter(options.keys()))}</SELECTION>'." + )Based on coding guidelines.
src/draive/helpers/instruction_refinement.py (2)
561-571: Avoid logging full refined instructions content.This can leak sensitive/internal prompt content. Log a preview and length instead.
Apply this diff:
- ctx.log_info(f"Prepared updated instructions using {strategy_name}") - ctx.log_debug(f"Updated instruction for {strategy_name}: {updated_instruction}") + ctx.log_info(f"Prepared updated instructions using {strategy_name}") + preview = (updated_instruction[:200] + "…") if len(updated_instruction) > 200 else updated_instruction + ctx.log_debug( + "Updated instruction for %s (len=%d): %s", + strategy_name, + len(updated_instruction), + preview, + )Based on coding guidelines.
135-158: Repository patching is sound; minor enhancement suggestion.Current patch intentionally disables defining. Consider also copying
meta=repository.metato preserve provenance for observability.- return TemplatesRepository( + return TemplatesRepository( listing=repository.listing, # keep current listing loading=instructions_loading, # replace loading # do not allow modifications - use default noop implementation + meta=repository.meta, )Based on coding guidelines.
♻️ Duplicate comments (8)
src/draive/multimodal/templates/types.py (4)
51-62: Use Map for merged arguments to preserve immutability and type consistency.Returning a plain dict breaks the Map-based pattern used in of() and may degrade State immutability guarantees. Replace with Map.
Apply:
return self.__class__( identifier=self.identifier, - arguments={**self.arguments, **arguments}, + arguments=Map({**self.arguments, **arguments}), meta=self.meta, )Based on learnings.
30-76: Add NumPy‑style docstrings for public Template API.Template.of, with_arguments, and with_meta are public and should include Parameters/Returns/Raises per guidelines.
As per coding guidelines.
98-101: Add NumPy‑style docstrings for TemplateDeclaration and its of() constructor.Public symbol; document fields and constructor Parameters/Returns (short).
As per coding guidelines.
104-132: Document public runtime‑checkable protocols.Add brief NumPy‑style docstrings describing purpose, parameters, and return types for TemplateListing, TemplateLoading, and TemplateDefining.
As per coding guidelines.
src/draive/multimodal/templates/variables.py (1)
6-10: Fix all: add resolve_text_template, remove duplicate.Currently lists resolve_multimodal_template twice and omits resolve_text_template.
__all__ = ( - "parse_template_variables", - "resolve_multimodal_template", - "resolve_multimodal_template", + "parse_template_variables", + "resolve_text_template", + "resolve_multimodal_template", )src/draive/multimodal/templates/repository.py (3)
301-305: Return templates in a stable order.Sort declarations by identifier to avoid nondeterministic listings and flaky tests. This mirrors an earlier suggestion.
Apply this diff:
- return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
372-381: Return templates in a stable order (FileStorage).Same determinism concern as above; sort by identifier.
Apply this diff:
- assert self._declarations is not None # nosec: B101 - return tuple(self._declarations.values()) + assert self._declarations is not None # nosec: B101 + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
475-486: Persist in a deterministic order to minimize config churn.Sorting declarations before serialization makes file diffs stable.
Apply this diff:
- file_contents: bytes = json.dumps( - [ - { - "identifier": declaration.identifier, - "description": declaration.description, - "variables": declaration.variables, - "content": self._contents[declaration.identifier], - "meta": declaration.meta.to_mapping(), - } - for declaration in self._declarations.values() - ] - ).encode() + file_contents: bytes = json.dumps( + [ + { + "identifier": declaration.identifier, + "description": declaration.description, + "variables": declaration.variables, + "content": self._contents[declaration.identifier], + "meta": declaration.meta.to_mapping(), + } + for declaration in sorted(self._declarations.values(), key=lambda d: d.identifier) + ] + ).encode()
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (41)
Makefile(1 hunks)docs/guides/Postgres.md(2 hunks)pyproject.toml(1 hunks)src/draive/__init__.py(3 hunks)src/draive/conversation/completion/default.py(7 hunks)src/draive/conversation/completion/state.py(5 hunks)src/draive/conversation/completion/types.py(4 hunks)src/draive/conversation/realtime/default.py(3 hunks)src/draive/conversation/realtime/state.py(3 hunks)src/draive/conversation/realtime/types.py(2 hunks)src/draive/generation/audio/default.py(1 hunks)src/draive/generation/audio/state.py(4 hunks)src/draive/generation/audio/types.py(2 hunks)src/draive/generation/image/default.py(1 hunks)src/draive/generation/image/state.py(4 hunks)src/draive/generation/image/types.py(2 hunks)src/draive/generation/model/default.py(3 hunks)src/draive/generation/model/state.py(4 hunks)src/draive/generation/model/types.py(2 hunks)src/draive/generation/text/default.py(1 hunks)src/draive/generation/text/state.py(4 hunks)src/draive/generation/text/types.py(2 hunks)src/draive/helpers/instruction_preparation.py(3 hunks)src/draive/helpers/instruction_refinement.py(5 hunks)src/draive/models/__init__.py(0 hunks)src/draive/models/generative.py(5 hunks)src/draive/models/instructions/__init__.py(0 hunks)src/draive/models/instructions/repository.py(0 hunks)src/draive/models/instructions/template.py(0 hunks)src/draive/models/instructions/types.py(0 hunks)src/draive/multimodal/__init__.py(2 hunks)src/draive/multimodal/templates/__init__.py(1 hunks)src/draive/multimodal/templates/repository.py(1 hunks)src/draive/multimodal/templates/types.py(1 hunks)src/draive/multimodal/templates/variables.py(1 hunks)src/draive/openai/images.py(3 hunks)src/draive/postgres/__init__.py(2 hunks)src/draive/postgres/instructions.py(0 hunks)src/draive/postgres/templates.py(1 hunks)src/draive/stages/stage.py(15 hunks)tests/test_multimodal_template_variables.py(1 hunks)
💤 Files with no reviewable changes (6)
- src/draive/models/instructions/types.py
- src/draive/models/instructions/template.py
- src/draive/models/init.py
- src/draive/models/instructions/init.py
- src/draive/postgres/instructions.py
- src/draive/models/instructions/repository.py
🧰 Additional context used
📓 Path-based instructions (12)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use Python 3.12+ features and syntax across the codebase
Format code exclusively with Ruff (make format); do not use other formatters
Skip module-level docstrings
Files:
src/draive/multimodal/templates/types.pysrc/draive/generation/audio/types.pysrc/draive/conversation/realtime/types.pysrc/draive/generation/text/default.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/generation/image/types.pysrc/draive/generation/model/types.pysrc/draive/conversation/realtime/default.pysrc/draive/generation/model/state.pysrc/draive/postgres/__init__.pysrc/draive/conversation/realtime/state.pysrc/draive/generation/audio/state.pysrc/draive/generation/image/default.pysrc/draive/generation/image/state.pysrc/draive/models/generative.pysrc/draive/postgres/templates.pysrc/draive/__init__.pytests/test_multimodal_template_variables.pysrc/draive/generation/audio/default.pysrc/draive/stages/stage.pysrc/draive/conversation/completion/default.pysrc/draive/openai/images.pysrc/draive/generation/model/default.pysrc/draive/multimodal/__init__.pysrc/draive/generation/text/state.pysrc/draive/multimodal/templates/repository.pysrc/draive/helpers/instruction_preparation.pysrc/draive/generation/text/types.pysrc/draive/multimodal/templates/variables.pysrc/draive/helpers/instruction_refinement.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly (from haiway import State, ctx)
Use ctx.scope(...) to bind scoped Disposables and active State; avoid global state
Route all logs through ctx.log_debug/info/warn/error; do not use print
Use latest, most strict typing syntax (Python 3.12+), with strict typing only for public APIs
Avoid loose Any except at explicit third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
Prefer Mapping/Sequence/Iterable in public types over dict/list/set
Use final where applicable; avoid inheritance and prefer composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Model immutable data/config and facades with haiway.State; provide ergonomic classmethods like .of(...)
Avoid in-place mutation; use State.updated(...) or functional builders to produce new instances
Access active state via haiway.ctx inside async scopes (ctx.scope(...))
Use @statemethod for public state methods that dispatch on the active instance
Log around generation calls, tool dispatch, and provider requests/responses without leaking secrets; prefer structured/concise messages
Add metrics via ctx.record where applicable
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks
Use structured concurrency and valid coroutine usage; rely on haiway/asyncio; avoid custom threading
Construct multimodal content with MultimodalContent.of(...) and compose blocks explicitly
Use ResourceContent/ResourceReference for media/data blobs
Wrap custom types/data within ArtifactContent; use hidden when needed
Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings on internal helpers; keep names self-explanatory
Keep docstrings high-quality; mkdocstrings pulls them into API reference
Never log secrets or full request bodies containing keys/tokens
Files:
src/draive/multimodal/templates/types.pysrc/draive/generation/audio/types.pysrc/draive/conversation/realtime/types.pysrc/draive/generation/text/default.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/generation/image/types.pysrc/draive/generation/model/types.pysrc/draive/conversation/realtime/default.pysrc/draive/generation/model/state.pysrc/draive/postgres/__init__.pysrc/draive/conversation/realtime/state.pysrc/draive/generation/audio/state.pysrc/draive/generation/image/default.pysrc/draive/generation/image/state.pysrc/draive/models/generative.pysrc/draive/postgres/templates.pysrc/draive/__init__.pysrc/draive/generation/audio/default.pysrc/draive/stages/stage.pysrc/draive/conversation/completion/default.pysrc/draive/openai/images.pysrc/draive/generation/model/default.pysrc/draive/multimodal/__init__.pysrc/draive/generation/text/state.pysrc/draive/multimodal/templates/repository.pysrc/draive/helpers/instruction_preparation.pysrc/draive/generation/text/types.pysrc/draive/multimodal/templates/variables.pysrc/draive/helpers/instruction_refinement.py
src/draive/multimodal/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Files:
src/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/multimodal/__init__.pysrc/draive/multimodal/templates/repository.pysrc/draive/multimodal/templates/variables.py
src/draive/conversation/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement higher-level chat/realtime conversations under draive/conversation/
Files:
src/draive/conversation/realtime/types.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/types.pysrc/draive/conversation/realtime/default.pysrc/draive/conversation/realtime/state.pysrc/draive/conversation/completion/default.py
docs/**/*
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*: When behavior/API changes, update relevant docs under docs/ and examples as applicable
When adding public APIs, update examples/guides and ensure cross-links render
Files:
docs/guides/Postgres.md
src/draive/{httpx,mcp,postgres,opentelemetry}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Place integrations under draive/httpx, draive/mcp, draive/postgres, draive/opentelemetry
Files:
src/draive/postgres/__init__.pysrc/draive/postgres/templates.py
src/draive/models/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Files:
src/draive/models/generative.py
src/draive/__init__.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/__init__.py: Centralize public exports in src/draive/init.py
Update src/draive/init.py exports when API surface changes
Files:
src/draive/__init__.py
{pyproject.toml,pyrightconfig.json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Ruff, Bandit, and Pyright (strict) via make lint
Files:
pyproject.toml
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Do not perform real network I/O in unit tests; mock providers/HTTP
Keep tests fast and focused on changed code; start with unit tests around new types/functions/adapters
Use fixtures from tests/ or add focused ones; avoid heavy integration scaffolding
Use pytest-asyncio for coroutine tests (@pytest.mark.asyncio)
Prefer scoping with ctx.scope(...) in async tests and bind required State instances explicitly
Avoid real I/O and network in async tests; stub provider calls and HTTP
Files:
tests/test_multimodal_template_variables.py
src/draive/stages/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement pipeline stage abstractions and helpers under draive/stages/
Files:
src/draive/stages/stage.py
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py: Provider-specific feature modules live under their respective provider directories
Translate provider/SDK errors into typed exceptions; do not raise bare Exception and preserve context
Use environment variables for credentials and resolve via helper functions like getenv_str
Files:
src/draive/openai/images.py
🧠 Learnings (6)
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Applied to files:
src/draive/multimodal/templates/types.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in src/draive/__init__.py
Applied to files:
src/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Update src/draive/__init__.py exports when API surface changes
Applied to files:
src/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/models/**/*.py : Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Applied to files:
src/draive/__init__.pysrc/draive/stages/stage.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/multimodal/**/*.py : Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Applied to files:
src/draive/__init__.pysrc/draive/multimodal/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Import Haiway symbols directly (from haiway import State, ctx)
Applied to files:
src/draive/helpers/instruction_preparation.py
🧬 Code graph analysis (31)
src/draive/multimodal/templates/types.py (1)
src/draive/stages/stage.py (1)
with_meta(1390-1435)
src/draive/generation/audio/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/realtime/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)src/draive/models/generative.py (5)
loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/conversation/completion/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/completion/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/multimodal/templates/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-294)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/generation/image/types.py (1)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)
src/draive/generation/model/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/realtime/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)
src/draive/generation/model/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/postgres/__init__.py (2)
src/draive/multimodal/templates/repository.py (3)
templates(105-108)templates(111-114)templates(117-121)src/draive/postgres/templates.py (1)
PostgresTemplatesRepository(28-173)
src/draive/conversation/realtime/state.py (4)
src/draive/models/types.py (2)
ModelMemoryRecall(719-766)ModelOutput(573-672)src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/audio/state.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/image/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-294)resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)src/draive/openai/images.py (1)
generate_image(21-60)
src/draive/generation/image/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/postgres/templates.py (2)
src/draive/multimodal/templates/repository.py (11)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-294)listing(301-305)listing(372-380)load(235-250)loading(307-313)loading(382-392)defining(315-330)defining(394-413)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)
src/draive/__init__.py (2)
src/draive/multimodal/templates/types.py (3)
Template(31-76)TemplateDeclaration(80-101)TemplateMissing(18-27)src/draive/multimodal/templates/repository.py (1)
TemplatesRepository(61-294)
tests/test_multimodal_template_variables.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(13-37)resolve_multimodal_template(87-134)resolve_text_template(40-84)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/generation/audio/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)src/draive/models/generative.py (5)
completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)
src/draive/stages/stage.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-294)resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)
src/draive/conversation/completion/default.py (4)
src/draive/models/types.py (1)
ModelToolRequest(311-353)src/draive/multimodal/artifact.py (1)
ArtifactContent(11-96)src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-294)resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)
src/draive/openai/images.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-294)resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)
src/draive/generation/model/default.py (4)
src/draive/multimodal/templates/types.py (2)
Template(31-76)with_arguments(51-62)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)src/draive/parameters/model.py (2)
json_schema(443-451)simplified_schema(433-440)src/draive/parameters/schema.py (1)
simplified_schema(9-26)
src/draive/multimodal/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-294)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/generation/text/state.py (4)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/multimodal/templates/repository.py (4)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (8)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)of(33-45)of(82-96)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(13-37)resolve_multimodal_template(87-134)resolve_text_template(40-84)src/draive/postgres/templates.py (4)
listing(51-82)loading(121-126)defining(128-166)load(88-119)
src/draive/helpers/instruction_preparation.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)
src/draive/generation/text/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/multimodal/templates/variables.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
of(33-45)of(82-96)
src/draive/helpers/instruction_refinement.py (5)
src/draive/multimodal/content.py (2)
MultimodalContent(25-592)MultimodalTag(599-700)src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-294)loading(307-313)loading(382-392)load(235-250)src/draive/multimodal/text.py (1)
TextContent(11-82)src/draive/postgres/templates.py (2)
loading(121-126)load(88-119)
🪛 GitHub Actions: CI
tests/test_multimodal_template_variables.py
[error] 1-1: Pytest failure: TypeError in resolve_text_template() takes 1 positional argument but 2 were given during test_resolve_text_template_replaces_all_placeholders. This may indicate an API/signature mismatch in the function.
[error] 1-1: Pytest failure: TypeError in resolve_text_template() takes 1 positional argument but 2 were given during multiple tests involving text template resolution.
[error] 1-1: Pytest failure: TypeError in resolve_multimodal_template() takes 1 positional argument but 2 were given during tests of multimodal template resolution.
[error] 1-1: Overall test run ended with 13 failing tests and 325 passing tests due to object signature errors in template resolution helpers.
🔇 Additional comments (36)
src/draive/multimodal/templates/types.py (1)
8-15: Exports look complete.all now includes Template, TemplateDeclaration, TemplateDefining, TemplateListing, TemplateLoading, TemplateMissing. Good.
Makefile (1)
13-13: LGTM: bump UV_VERSION to 0.9.4.Version guard using sort -V still correctly upgrades when current < required.
pyproject.toml (1)
8-8: Version bump acknowledged.0.90.0 aligns with the templates migration. Ensure CHANGELOG and docs reflect public API changes.
src/draive/helpers/instruction_preparation.py (1)
25-41: Migration to TemplateDeclaration looks correct.Type hints and instantiation path are consistent; logging uses ctx.scope/info/error as required.
Also applies to: 34-45
src/draive/multimodal/templates/variables.py (1)
40-85: Resolvers read well.Clear missing‑argument checks and normalized assembly via MultimodalContent.of/empty. No issues spotted.
Also applies to: 87-135
src/draive/generation/audio/types.py (1)
3-7: LGTM — protocol updated to Template | ModelInstructions.Verification confirms no outdated
ResolveableInstructionsusage exists in the codebase. Signature aligns with new templates flow; imports are correct and consistent with all dependent call sites.src/draive/postgres/__init__.py (1)
12-24: LGTM — export is correct, stale symbol properly removed.From the verification: PostgresTemplatesRepository is correctly implemented at
src/draive/postgres/templates.py:28and ready for export. PostgresInstructionsRepository is not defined anywhere insrc/draive/postgres/— it has been cleanly removed from the codebase. The references to it indocs/guides/Postgres.mdare stale documentation that should be updated separately, but the export logic itself is sound.src/draive/multimodal/__init__.py (1)
8-16: LGTM! Clean template API integration.The new template-related imports and exports are well-structured and properly expose the Templates subsystem through the multimodal package.
Also applies to: 25-31
src/draive/generation/text/default.py (1)
6-13: LGTM! Clean migration to template-based instruction resolution.The switch from
InstructionsRepository.resolvetoTemplatesRepository.resolve_stris correct, and the updated type signature properly accepts bothTemplateandModelInstructions(which is a string alias).Also applies to: 20-20, 28-28
src/draive/generation/audio/default.py (1)
5-11: LGTM! Consistent template migration.The audio generation module follows the same clean pattern as text generation, correctly migrating to
Template | ModelInstructionsandTemplatesRepository.resolve_str.Also applies to: 19-19, 25-25
src/draive/generation/model/types.py (1)
4-5: LGTM! Protocol signature correctly updated.The
ModelGeneratingprotocol now properly acceptsTemplate | ModelInstructions, aligning with the implementation changes across generation modules.Also applies to: 29-29
src/draive/conversation/realtime/types.py (1)
12-13: LGTM! Realtime conversation protocol updated consistently.The
RealtimeConversationPreparingprotocol correctly adopts the newTemplate | ModelInstructionstype, maintaining consistency across the conversation layer.Also applies to: 130-130
src/draive/generation/audio/state.py (1)
7-8: LGTM! Type annotations updated consistently.The
AudioGeneration.generatemethod and its overloads correctly adoptTemplate | ModelInstructions, maintaining consistency with the broader template migration.Also applies to: 20-20, 29-29, 38-38
src/draive/generation/text/state.py (1)
8-9: LGTM! Type annotations updated consistently.The
TextGeneration.generatemethod and its overloads correctly adoptTemplate | ModelInstructions, completing the consistent type migration across all generation modules.Also applies to: 20-20, 31-31, 42-42
tests/test_multimodal_template_variables.py (1)
129-203: Critical: Fix keyword-only argument calls for resolve_multimodal_template.All calls to
resolve_multimodal_templateincorrectly passargumentsas a positional parameter. The function signature requires it as a keyword-only argument.Additionally, lines 159-161 test for unused argument detection with
ValueError, but the implementation snippet (lines 86-133) shows onlyKeyErroris raised for missing arguments, with no validation for unused arguments shown.Apply this pattern to fix all calls:
- result = resolve_multimodal_template(template, arguments) + result = resolve_multimodal_template(template, arguments=arguments)And verify the unused argument test at lines 159-161:
def test_resolve_multimodal_template_detects_unused_argument() -> None: - with raises(ValueError, match="Unused template arguments provided: extra"): - resolve_multimodal_template("Plain text", {"extra": TextContent.of("value")}) + # TODO: Implement unused argument detection or remove this test + passLikely an incorrect or invalid review comment.
src/draive/multimodal/templates/__init__.py (1)
1-19: LGTM!The package exports are well-organized and consistent. All imported symbols are properly listed in
__all__.src/draive/conversation/realtime/state.py (2)
14-14: LGTM!Import changes align with the Template system migration.
Also applies to: 22-22
37-87: LGTM!The method signature and docstring have been updated consistently to accept
Template | ModelInstructions. The instructions are correctly passed through to the preparing implementation.src/draive/generation/image/state.py (2)
7-8: LGTM!Import updates align with the Template system migration.
15-48: LGTM!The method signatures are consistently updated across all overloads and the implementation.
src/draive/generation/image/types.py (1)
1-18: LGTM!Protocol signature correctly updated to match the new Template system. Imports are appropriate.
src/draive/openai/images.py (2)
8-9: LGTM!Import changes appropriately support the Template system migration.
21-60: LGTM!The method signature has been updated to accept
Template | ModelInstructions, and the resolution correctly usesTemplatesRepository.resolve_strto convert the instructions to a string prompt.src/draive/generation/model/state.py (2)
8-9: LGTM!Import changes align with the Template system migration.
16-72: LGTM!Method signatures are consistently updated across all overloads and the implementation to accept
Template | ModelInstructions.src/draive/generation/image/default.py (2)
8-8: LGTM!Import changes support the Template system migration.
Also applies to: 11-11
17-34: LGTM!The function signature has been updated to accept
Template | ModelInstructions, and the instructions are correctly resolved viaTemplatesRepository.resolve_strbefore being passed to the underlyingGenerativeModel.completion.src/draive/conversation/completion/state.py (1)
32-43: Typing changes LGTM.Expanded
instructionstoTemplate | ModelInstructionsacross overloads and impl without behavior changes. Default""maintains backward compatibility.Also applies to: 45-56, 58-68
src/draive/conversation/completion/types.py (1)
22-33: Protocol update LGTM.Signatures now accept
Template | ModelInstructionsconsistently across overloads and impl.Also applies to: 34-45, 46-55
src/draive/postgres/templates.py (1)
163-166: Verifyclear_cache()async behavior against haiway 0.35.3 documentation.The code at lines 164–165 awaits
clear_cache()on cached function wrappers. Without direct access to the haiway 0.35.3 source or type stubs, I cannot definitively confirm whetherclear_cache()is async or sync. Please check:
- haiway version 0.35.3 cache module source (GitHub: miquido/haiway)
- Whether
clear_cache()is defined asasync defordef- If sync, remove
await; if async, the code is correctsrc/draive/stages/stage.py (4)
355-361: OK on template resolution.Calling
TemplatesRepository.resolve_strhere aligns with the new template system.
447-452: OK on prompting path resolution.Consistent with completion; no issues.
537-542: OK on loopback path resolution.Consistent with completion; no issues.
606-611: OK on result path resolution.Consistent with completion; no issues.
src/draive/helpers/instruction_refinement.py (2)
244-247: Good: loading initial content viaTemplatesRepository.load.This uses the new API correctly and cleanly separates identifier from content.
422-424: Nice use of a patched repository for focused evaluation.Ensures that evaluators transparently see the refined content.
41456ab to
05f22c5
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (15)
src/draive/conversation/realtime/state.py (1)
69-79: Typing: use full Generator params or Iterator to satisfy type checkers.
collections.abc.Generatorrequires 3 type args. UseIterator[...]or specifyGenerator[Yield, Send, Return].Apply:
-from collections.abc import Generator, Iterable +from collections.abc import Iterator, Iterable @@ - def model_context_elements() -> Generator[ModelInput | ModelOutput]: + def model_context_elements() -> Iterator[ModelInput | ModelOutput]:src/draive/generation/image/state.py (1)
14-23: LGTM — signatures match Template | ModelInstructions. Add brief docstrings.Public API is consistent. Consider a short NumPy-style docstring for
ImageGeneration.generate(params, returns, raises) for API docs.src/draive/openai/images.py (1)
21-41: Bug:inputis ignored when building the OpenAI image prompt. Also pass**extratoresolve_str.Only
instructionsare sent asprompt, dropping userinput. This degrades results. Combine resolved instructions with the textual input (and feed input as template args for Template cases). Also forward**extrato repository backends.Apply:
@@ async def generate_image( self, *, - instructions: Template | ModelInstructions, + instructions: Template | ModelInstructions, input: MultimodalContent, # noqa: A002 config: OpenAIImageGenerationConfig | None = None, **extra: Any, ) -> ResourceContent | ResourceReference: @@ - response: ImagesResponse = await self._client.images.generate( + # Build prompt from instructions and input + if isinstance(instructions, str): + resolved_prompt = f"{instructions}\n\n{input.to_str()}" + else: + # Provide common aliases so templates can refer to the input + input_text = input.to_str() + resolved_prompt = await TemplatesRepository.resolve_str( + instructions.with_arguments(input=input_text, prompt=input_text), + **extra, + ) + + response: ImagesResponse = await self._client.images.generate( model=generation_config.model, n=1, - prompt=await TemplatesRepository.resolve_str(instructions), + prompt=resolved_prompt, quality=generation_config.quality, size=generation_config.size, style=generation_config.style, response_format=generation_config.result, )src/draive/generation/image/default.py (1)
23-29: Forward**extratoTemplatesRepository.resolve_strfor backend context.Aligns behavior across backends (e.g., Postgres/file). No semantic change otherwise.
Apply:
- result: ModelOutput = await GenerativeModel.completion( - instructions=await TemplatesRepository.resolve_str(instructions), + result: ModelOutput = await GenerativeModel.completion( + instructions=await TemplatesRepository.resolve_str( + instructions, + **extra, + ),src/draive/helpers/instruction_preparation.py (1)
63-66: Do not include full generated content in exceptions.Raising
ValueError(f"...: {result.to_str()}")risks leaking sensitive data to logs/telemetry.Apply:
- ctx.log_error("...instruction preparation failed!") - raise ValueError(f"Failed to prepare instruction: {result.to_str()}") + ctx.log_error("...instruction preparation failed!") + raise ValueError("Failed to prepare instruction")Optionally emit a redacted debug log with metadata (length, has_artifacts) if needed. Based on coding guidelines.
src/draive/generation/audio/state.py (1)
14-41: Add NumPy‑style docstrings for public APIs.
AudioGeneration.generate(...)is public; add concise Parameters/Returns/Raises per guidelines. As per coding guidelines.src/draive/generation/model/state.py (2)
23-30: Default "" not assignable to Template | ModelInstructions; include str in the union (or change the default).Same issue as audio. Keep API consistent and type-correct.
Apply:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",Also applies to: 38-45, 53-60
15-71: Add NumPy‑style docstrings for public API.
ModelGeneration.generate[...]is public; add Parameters/Returns/Raises. As per coding guidelines.src/draive/conversation/completion/state.py (1)
119-136: Normalize tools before calling Toolbox.of to avoid None bug.Passing None into Toolbox.of may raise; guard once and reuse.
Apply:
if stream: - return await ctx.state(cls).completing( - instructions=instructions, - toolbox=Toolbox.of(tools), + toolbox_obj: Toolbox = Toolbox.of(()) if tools is None else Toolbox.of(tools) + return await ctx.state(cls).completing( + instructions=instructions, + toolbox=toolbox_obj, memory=conversation_memory, input=conversation_message, stream=True, **extra, ) else: - return await ctx.state(cls).completing( - instructions=instructions, - toolbox=Toolbox.of(tools), + toolbox_obj: Toolbox = Toolbox.of(()) if tools is None else Toolbox.of(tools) + return await ctx.state(cls).completing( + instructions=instructions, + toolbox=toolbox_obj, memory=conversation_memory, input=conversation_message, **extra, )src/draive/models/generative.py (4)
34-35: Import Template and TemplatesRepository for session instruction resolution.-from draive.multimodal import ArtifactContent, MultimodalContent, MultimodalContentPart, TextContent +from draive.multimodal import ( + ArtifactContent, + MultimodalContent, + MultimodalContentPart, + TextContent, + Template, + TemplatesRepository, +)
615-626: Align typing with docs: accept Template | ModelInstructions in session overloads.async def session( cls, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "", @@ async def session( self, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "", @@ async def session( self, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "",Also applies to: 627-637, 638-648
650-658: Doc fix: update resolution path (TemplatesRepository), drop InstructionsRepository.- Resolves ``instructions`` (via ``InstructionsRepository``), normalizes the provided - ``memory`` into a ``ModelMemory`` if a raw context is given, and delegates to the + Resolves ``instructions`` when a ``Template`` is provided (via + ``TemplatesRepository.resolve_str``), normalizes the provided ``memory`` into a + ``ModelMemory`` if a raw context is given, and delegates to the provider's ``session_preparing`` to obtain a ``ModelSessionScope``.
679-699: <!-- [scratchpad_start]
[task review_verification FINAL]
Complete analysis ready for conclusion[key_findings_summary]
- REAL ISSUE: Method signature accepts only
ModelInstructions(str), but docstring claimsTemplate | ModelInstructions- PATTERN MISMATCH: Codebase-wide pattern (stages, generation, conversation) all resolve Templates before downstream use
- MISSING IMPORTS: Template and TemplatesRepository not imported in generative.py
- PROPOSED FIX FLAW:
instructions.with_arguments(**{k: str(v) ...})has type mismatch - with_arguments expects Multimodal, not str- MEMORY VARIABLES: Still marked as TODO; merging adds complexity not required for core fix
[verification_result]
✓ Issue exists: Template support missing from RealtimeGenerativeModel.session()
✓ Imports needed: Template, TemplatesRepository
✓ Resolution needed: Template → str via TemplatesRepository.resolve_str()
✗ Proposed memory merging: Type-incompatible (with_arguments expects Multimodal not str)[corrected_approach]
Simpler fix: just resolve Template to str (no memory variable merging)
- Update signature:
instructions: Template | ModelInstructions = ""- Add imports
- Check isinstance(instructions, Template) and resolve
- Pass string result to session_preparing
- Leave memory variable merging as TODO (requires separate design)
[categorization]
- Real issue exists, but proposed fix has implementation bugs
[done]
-->Fix Template and TemplatesRepository resolution; signature/implementation mismatch.
The method signature accepts only
ModelInstructionsbut docstring and codebase pattern (stages, generation, conversation) indicateTemplate | ModelInstructionssupport. Additionally, Template is not resolved to string before passing tosession_preparing, which expectsModelInstructions(str).However, the proposed fix has a type mismatch:
Template.with_arguments(**{k: str(v) ...})expectsMultimodalvalues, not strings. The memory variable merging also remains a TODO with unclear requirements.Corrected approach:
+from draive.multimodal import Template, TemplatesRepository @statemethod async def session( self, *, instructions: Template | ModelInstructions = "", memory: ModelMemory | ModelContext = (), tools: ModelToolsDeclaration = ModelToolsDeclaration.none, output: ModelSessionOutputSelection = "auto", **extra: Any, ) -> ModelSessionScope: """...""" session_memory: ModelMemory if isinstance(memory, Sequence): session_memory = ModelMemory.constant( ModelMemoryRecall( context=memory, variables={}, meta=META_EMPTY, ) ) else: session_memory = memory + # Resolve Template to string; pass other instruction types through + if isinstance(instructions, Template): + resolved_instructions: ModelInstructions = await TemplatesRepository.resolve_str(instructions) + else: + resolved_instructions = instructions + return await self.session_preparing( - # TODO: FIXME: pass memory_recall.variables ?? - instructions=instructions, + instructions=resolved_instructions, memory=session_memory, output=output, tools=tools, **extra, )Note: Memory variable injection marked TODO; defer to separate task with proper type design.
src/draive/conversation/completion/default.py (2)
137-150: Drop invalidawaitbefore async generator; also normalize instructions like non‑stream path.
GenerativeModel.loop(..., stream=True)returns an async generator; do not await it. Also apply the same Template resolution with memory variables.- async for chunk in await GenerativeModel.loop( - instructions=await TemplatesRepository.resolve_str(instructions), + async for chunk in GenerativeModel.loop( + instructions=( + await TemplatesRepository.resolve_str( + instructions.with_arguments( + **{ + k: str(v) + for k, v in (memory_recall.variables or {}).items() + if k not in instructions.arguments + } + ) + ) + if isinstance(instructions, Template) + else instructions + ), toolbox=toolbox, context=context, stream=True, **extra, ):Also applies to: 150-161
81-107: Fix template resolution to inject memory variables via.with_arguments()instead of ignoredarguments=kwarg.The
resolve_strmethod signature accepts onlytemplate,default, and**extraparameters, meaning thearguments=kwarg is silently captured but ignored. Template has awith_arguments()method that should be used to inject variables before resolution. The current code also has an inverted isinstance check (should beTemplate, notstr).result: ModelOutput = await GenerativeModel.loop( - instructions=instructions - if isinstance(instructions, str) - else await TemplatesRepository.resolve_str( - instructions, - arguments=memory_recall.variables, - ), + instructions=( + await TemplatesRepository.resolve_str( + instructions.with_arguments( + **{ + k: str(v) + for k, v in (memory_recall.variables or {}).items() + if k not in instructions.arguments + } + ) + ) + if isinstance(instructions, Template) + else instructions + ), toolbox=toolbox, context=context, **extra, )
♻️ Duplicate comments (17)
src/draive/postgres/templates.py (1)
148-155: SQL syntax error: missing comma between$4::JSONBand$5::JSONB.This will fail at runtime.
Apply:
VALUES ( $1::TEXT, $2::TEXT, $3::TEXT, - $4::JSONB - $5::JSONB + $4::JSONB, + $5::JSONB );docs/guides/Postgres.md (1)
119-119: Duplicate: API naming issue already flagged.Line 119 incorrectly references
resolve_as_text; the correct method name isresolve_str. This issue was already identified in a previous review comment.src/draive/generation/text/types.py (1)
10-20: Protocol update is correct; keep docs in sync.Type changes look good. Please add a concise docstring to
TextGeneratingdescribing parameters and return type for reference.src/draive/generation/model/default.py (1)
35-63: Unify resolution via repository and pass**extra(handles both str and Template).Keeps semantics consistent and lets backends use context; mirrors prior feedback.
Apply:
@@ - case "full": - if isinstance(instructions, str): - resolved_instructions = instructions.format( - model_schema=generated.json_schema(indent=2), - ) - else: - resolved_instructions = await TemplatesRepository.resolve_str( - instructions.with_arguments( - model_schema=generated.json_schema(indent=2), - ) - ) + case "full": + schema = generated.json_schema(indent=2) + if isinstance(instructions, str): + resolved_instructions = await TemplatesRepository.resolve_str( + Template.of("__inline__", arguments={"model_schema": schema}), + default=instructions, + **extra, + ) + else: + resolved_instructions = await TemplatesRepository.resolve_str( + instructions.with_arguments(model_schema=schema), + **extra, + ) @@ - case "simplified": - if isinstance(instructions, str): - resolved_instructions = instructions.format( - model_schema=generated.simplified_schema(indent=2), - ) - else: - resolved_instructions = await TemplatesRepository.resolve_str( - instructions.with_arguments( - model_schema=generated.simplified_schema(indent=2), - ) - ) + case "simplified": + schema = generated.simplified_schema(indent=2) + if isinstance(instructions, str): + resolved_instructions = await TemplatesRepository.resolve_str( + Template.of("__inline__", arguments={"model_schema": schema}), + default=instructions, + **extra, + ) + else: + resolved_instructions = await TemplatesRepository.resolve_str( + instructions.with_arguments(model_schema=schema), + **extra, + ) @@ - case "skip": # instruction is not modified - resolved_instructions = await TemplatesRepository.resolve_str(instructions) + case "skip": # instruction is not modified + resolved_instructions = await TemplatesRepository.resolve_str( + instructions, + **extra, + )src/draive/multimodal/templates/variables.py (1)
6-10: Fix__all__: missingresolve_text_template, duplicate entry.Export the intended public API.
Apply:
__all__ = ( - "parse_template_variables", - "resolve_multimodal_template", - "resolve_multimodal_template", + "parse_template_variables", + "resolve_text_template", + "resolve_multimodal_template", )src/draive/__init__.py (1)
289-293: DuplicateModelInstructionsin all. Remove one."ModelInputInvalid", - "ModelInstructions", - "ModelInstructions", + "ModelInstructions", "ModelMemory",src/draive/conversation/completion/default.py (1)
18-20: Import from public API (draive.models), not internal.types.-from draive.models.types import ModelInstructions, ModelToolRequest +from draive.models import ModelInstructions, ModelToolRequestAs per coding guidelines.
src/draive/multimodal/templates/repository.py (5)
301-306: Return stable, deterministic template order.- return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
376-381: Return stable, deterministic template order (file backend).- return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
213-229: Don’t rebuild the same arguments dict twice.- if loaded is not None: - return resolve_text_template( - loaded, - arguments={ - name: value if isinstance(value, str) else value.to_str() - for name, value in template.arguments.items() - }, - ) - - elif default is not None: - return resolve_text_template( - default, - arguments={ - name: value if isinstance(value, str) else value.to_str() - for name, value in template.arguments.items() - }, - ) + args = { + name: (value if isinstance(value, str) else value.to_str()) + for name, value in template.arguments.items() + } + if loaded is not None: + return resolve_text_template(loaded, arguments=args) + elif default is not None: + return resolve_text_template(default, arguments=args)
446-448: Use ctx.log_warn, not ctx.log_warning (would raise at runtime).- ctx.log_warning( + ctx.log_warn( "Invalid templates file storage element, skipping..." )
60-88: Add NumPy‑style docstrings for public API.Public class/methods lack required docstrings (Parameters/Returns/Raises). Please document TemplatesRepository and its public methods.
Based on learnings.
Also applies to: 103-173, 174-233, 234-251, 252-290
src/draive/multimodal/templates/types.py (5)
30-76: Add NumPy-style docstrings for public API.The
Templateclass and its methods (of,with_arguments,with_meta) are part of the public API but still lack docstrings. This was previously flagged and remains unaddressed.As per coding guidelines.
58-62: UseMap()for consistency and immutability.Line 60 constructs a plain dict, but the initialization pattern (line 43) uses
Map(). This inconsistency was previously flagged and remains unaddressed.Apply this diff:
return self.__class__( identifier=self.identifier, - arguments={**self.arguments, **arguments}, + arguments=Map({**self.arguments, **arguments}), meta=self.meta, )
79-101: Add NumPy-style docstrings for public API.The
TemplateDeclarationclass and itsof()method are part of the public API but still lack docstrings. This was previously flagged and remains unaddressed.As per coding guidelines.
91-96: PreferMap()for consistency with immutable State pattern.Line 94 initializes
variableswith a plain dict{}, inconsistent with theMap()pattern used elsewhere. This was previously flagged and remains unaddressed.Apply this diff:
return cls( identifier=identifier, description=description, - variables=variables if variables is not None else {}, + variables=variables if variables is not None else Map(), meta=Meta.of(meta), )
104-132: Add NumPy-style docstrings for public protocols.The runtime-checkable protocols (
TemplateListing,TemplateLoading,TemplateDefining) are part of the public API and define contracts for external implementations, but still lack docstrings. This was previously flagged and remains unaddressed.As per coding guidelines.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (41)
Makefile(1 hunks)docs/guides/Postgres.md(2 hunks)pyproject.toml(1 hunks)src/draive/__init__.py(3 hunks)src/draive/conversation/completion/default.py(7 hunks)src/draive/conversation/completion/state.py(5 hunks)src/draive/conversation/completion/types.py(4 hunks)src/draive/conversation/realtime/default.py(3 hunks)src/draive/conversation/realtime/state.py(3 hunks)src/draive/conversation/realtime/types.py(2 hunks)src/draive/generation/audio/default.py(1 hunks)src/draive/generation/audio/state.py(4 hunks)src/draive/generation/audio/types.py(2 hunks)src/draive/generation/image/default.py(1 hunks)src/draive/generation/image/state.py(4 hunks)src/draive/generation/image/types.py(2 hunks)src/draive/generation/model/default.py(3 hunks)src/draive/generation/model/state.py(4 hunks)src/draive/generation/model/types.py(2 hunks)src/draive/generation/text/default.py(1 hunks)src/draive/generation/text/state.py(4 hunks)src/draive/generation/text/types.py(2 hunks)src/draive/helpers/instruction_preparation.py(3 hunks)src/draive/helpers/instruction_refinement.py(5 hunks)src/draive/models/__init__.py(0 hunks)src/draive/models/generative.py(5 hunks)src/draive/models/instructions/__init__.py(0 hunks)src/draive/models/instructions/repository.py(0 hunks)src/draive/models/instructions/template.py(0 hunks)src/draive/models/instructions/types.py(0 hunks)src/draive/multimodal/__init__.py(2 hunks)src/draive/multimodal/templates/__init__.py(1 hunks)src/draive/multimodal/templates/repository.py(1 hunks)src/draive/multimodal/templates/types.py(1 hunks)src/draive/multimodal/templates/variables.py(1 hunks)src/draive/openai/images.py(3 hunks)src/draive/postgres/__init__.py(2 hunks)src/draive/postgres/instructions.py(0 hunks)src/draive/postgres/templates.py(1 hunks)src/draive/stages/stage.py(15 hunks)tests/test_multimodal_template_variables.py(1 hunks)
💤 Files with no reviewable changes (6)
- src/draive/models/instructions/template.py
- src/draive/models/init.py
- src/draive/models/instructions/init.py
- src/draive/models/instructions/types.py
- src/draive/postgres/instructions.py
- src/draive/models/instructions/repository.py
🧰 Additional context used
📓 Path-based instructions (12)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use Python 3.12+ features and syntax across the codebase
Format code exclusively with Ruff (make format); do not use other formatters
Skip module-level docstrings
Files:
src/draive/stages/stage.pysrc/draive/postgres/templates.pysrc/draive/generation/image/types.pysrc/draive/generation/text/default.pysrc/draive/helpers/instruction_refinement.pysrc/draive/multimodal/__init__.pysrc/draive/conversation/realtime/types.pysrc/draive/generation/image/state.pysrc/draive/openai/images.pysrc/draive/generation/image/default.pysrc/draive/multimodal/templates/variables.pysrc/draive/conversation/completion/state.pysrc/draive/generation/model/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/conversation/completion/default.pysrc/draive/generation/audio/types.pytests/test_multimodal_template_variables.pysrc/draive/conversation/realtime/default.pysrc/draive/models/generative.pysrc/draive/generation/audio/default.pysrc/draive/postgres/__init__.pysrc/draive/generation/text/types.pysrc/draive/multimodal/templates/repository.pysrc/draive/generation/text/state.pysrc/draive/conversation/completion/types.pysrc/draive/conversation/realtime/state.pysrc/draive/generation/model/default.pysrc/draive/generation/model/state.pysrc/draive/__init__.pysrc/draive/generation/audio/state.pysrc/draive/helpers/instruction_preparation.pysrc/draive/multimodal/templates/types.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly (from haiway import State, ctx)
Use ctx.scope(...) to bind scoped Disposables and active State; avoid global state
Route all logs through ctx.log_debug/info/warn/error; do not use print
Use latest, most strict typing syntax (Python 3.12+), with strict typing only for public APIs
Avoid loose Any except at explicit third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
Prefer Mapping/Sequence/Iterable in public types over dict/list/set
Use final where applicable; avoid inheritance and prefer composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Model immutable data/config and facades with haiway.State; provide ergonomic classmethods like .of(...)
Avoid in-place mutation; use State.updated(...) or functional builders to produce new instances
Access active state via haiway.ctx inside async scopes (ctx.scope(...))
Use @statemethod for public state methods that dispatch on the active instance
Log around generation calls, tool dispatch, and provider requests/responses without leaking secrets; prefer structured/concise messages
Add metrics via ctx.record where applicable
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks
Use structured concurrency and valid coroutine usage; rely on haiway/asyncio; avoid custom threading
Construct multimodal content with MultimodalContent.of(...) and compose blocks explicitly
Use ResourceContent/ResourceReference for media/data blobs
Wrap custom types/data within ArtifactContent; use hidden when needed
Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings on internal helpers; keep names self-explanatory
Keep docstrings high-quality; mkdocstrings pulls them into API reference
Never log secrets or full request bodies containing keys/tokens
Files:
src/draive/stages/stage.pysrc/draive/postgres/templates.pysrc/draive/generation/image/types.pysrc/draive/generation/text/default.pysrc/draive/helpers/instruction_refinement.pysrc/draive/multimodal/__init__.pysrc/draive/conversation/realtime/types.pysrc/draive/generation/image/state.pysrc/draive/openai/images.pysrc/draive/generation/image/default.pysrc/draive/multimodal/templates/variables.pysrc/draive/conversation/completion/state.pysrc/draive/generation/model/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/conversation/completion/default.pysrc/draive/generation/audio/types.pysrc/draive/conversation/realtime/default.pysrc/draive/models/generative.pysrc/draive/generation/audio/default.pysrc/draive/postgres/__init__.pysrc/draive/generation/text/types.pysrc/draive/multimodal/templates/repository.pysrc/draive/generation/text/state.pysrc/draive/conversation/completion/types.pysrc/draive/conversation/realtime/state.pysrc/draive/generation/model/default.pysrc/draive/generation/model/state.pysrc/draive/__init__.pysrc/draive/generation/audio/state.pysrc/draive/helpers/instruction_preparation.pysrc/draive/multimodal/templates/types.py
src/draive/stages/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement pipeline stage abstractions and helpers under draive/stages/
Files:
src/draive/stages/stage.py
src/draive/{httpx,mcp,postgres,opentelemetry}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Place integrations under draive/httpx, draive/mcp, draive/postgres, draive/opentelemetry
Files:
src/draive/postgres/templates.pysrc/draive/postgres/__init__.py
src/draive/multimodal/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Files:
src/draive/multimodal/__init__.pysrc/draive/multimodal/templates/variables.pysrc/draive/multimodal/templates/__init__.pysrc/draive/multimodal/templates/repository.pysrc/draive/multimodal/templates/types.py
src/draive/conversation/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement higher-level chat/realtime conversations under draive/conversation/
Files:
src/draive/conversation/realtime/types.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/default.pysrc/draive/conversation/realtime/default.pysrc/draive/conversation/completion/types.pysrc/draive/conversation/realtime/state.py
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py: Provider-specific feature modules live under their respective provider directories
Translate provider/SDK errors into typed exceptions; do not raise bare Exception and preserve context
Use environment variables for credentials and resolve via helper functions like getenv_str
Files:
src/draive/openai/images.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Do not perform real network I/O in unit tests; mock providers/HTTP
Keep tests fast and focused on changed code; start with unit tests around new types/functions/adapters
Use fixtures from tests/ or add focused ones; avoid heavy integration scaffolding
Use pytest-asyncio for coroutine tests (@pytest.mark.asyncio)
Prefer scoping with ctx.scope(...) in async tests and bind required State instances explicitly
Avoid real I/O and network in async tests; stub provider calls and HTTP
Files:
tests/test_multimodal_template_variables.py
src/draive/models/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Files:
src/draive/models/generative.py
{pyproject.toml,pyrightconfig.json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Ruff, Bandit, and Pyright (strict) via make lint
Files:
pyproject.toml
docs/**/*
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*: When behavior/API changes, update relevant docs under docs/ and examples as applicable
When adding public APIs, update examples/guides and ensure cross-links render
Files:
docs/guides/Postgres.md
src/draive/__init__.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/__init__.py: Centralize public exports in src/draive/init.py
Update src/draive/init.py exports when API surface changes
Files:
src/draive/__init__.py
🧠 Learnings (6)
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/models/**/*.py : Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Applied to files:
src/draive/stages/stage.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in src/draive/__init__.py
Applied to files:
src/draive/multimodal/__init__.pysrc/draive/multimodal/templates/__init__.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/multimodal/**/*.py : Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Applied to files:
src/draive/multimodal/__init__.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Applied to files:
src/draive/multimodal/templates/repository.pysrc/draive/multimodal/templates/types.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Update src/draive/__init__.py exports when API surface changes
Applied to files:
src/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Import Haiway symbols directly (from haiway import State, ctx)
Applied to files:
src/draive/helpers/instruction_preparation.py
🧬 Code graph analysis (31)
src/draive/stages/stage.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)
src/draive/postgres/templates.py (3)
src/draive/multimodal/templates/repository.py (11)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-294)listing(301-305)listing(372-380)load(235-250)loading(307-313)loading(382-392)defining(315-330)defining(394-413)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)src/draive/parameters/model.py (2)
from_json(454-469)to_json(501-517)
src/draive/generation/image/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)src/draive/models/generative.py (5)
loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/helpers/instruction_refinement.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-294)loading(307-313)loading(382-392)load(235-250)
src/draive/multimodal/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-294)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/conversation/realtime/types.py (1)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)
src/draive/generation/image/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/openai/images.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-294)resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)
src/draive/generation/image/default.py (4)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-294)resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)src/draive/openai/images.py (1)
generate_image(21-60)src/draive/conversation/completion/state.py (3)
completion(34-43)completion(47-56)completion(59-136)
src/draive/multimodal/templates/variables.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
of(33-45)of(82-96)
src/draive/conversation/completion/state.py (4)
src/draive/models/types.py (1)
ModelMemoryRecall(719-766)src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/model/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/multimodal/templates/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-294)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/conversation/completion/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)
src/draive/generation/audio/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
tests/test_multimodal_template_variables.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(13-37)resolve_multimodal_template(87-134)resolve_text_template(40-84)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/conversation/realtime/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)
src/draive/generation/audio/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)src/draive/models/generative.py (5)
completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)
src/draive/postgres/__init__.py (2)
src/draive/multimodal/templates/repository.py (3)
templates(105-108)templates(111-114)templates(117-121)src/draive/postgres/templates.py (1)
PostgresTemplatesRepository(28-173)
src/draive/generation/text/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/multimodal/templates/repository.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (8)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)of(33-45)of(82-96)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(13-37)resolve_multimodal_template(87-134)resolve_text_template(40-84)
src/draive/generation/text/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/completion/types.py (1)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)
src/draive/conversation/realtime/state.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/model/default.py (4)
src/draive/multimodal/templates/types.py (2)
Template(31-76)with_arguments(51-62)src/draive/multimodal/templates/repository.py (3)
resolve_str(176-183)resolve_str(186-193)resolve_str(196-232)src/draive/parameters/model.py (2)
json_schema(443-451)simplified_schema(433-440)src/draive/parameters/schema.py (1)
simplified_schema(9-26)
src/draive/generation/model/state.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/__init__.py (2)
src/draive/multimodal/templates/types.py (3)
Template(31-76)TemplateDeclaration(80-101)TemplateMissing(18-27)src/draive/multimodal/templates/repository.py (1)
TemplatesRepository(61-294)
src/draive/generation/audio/state.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/helpers/instruction_preparation.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)
src/draive/multimodal/templates/types.py (1)
src/draive/stages/stage.py (1)
with_meta(1390-1435)
🔇 Additional comments (27)
pyproject.toml (1)
8-8: LGTM! Version bump aligns with feature addition.The minor version increment from 0.89.5 to 0.90.0 appropriately reflects the introduction of the Templates subsystem as a new feature.
Makefile (2)
13-13: LGTM! UV version update is a routine maintenance bump.
9-10: No action required—.envremoval is intentional.The documentation confirms that environment variables are loaded by the application code via
draive.load_env(), not through the Makefile. Multiple guides consistently instruct users to create a.envfile and then callload_env()during startup. No build scripts or shell configurations depend on the Makefile loading.env, so this removal does not break the build process or environment configuration workflow.src/draive/stages/stage.py (4)
39-39: LGTM! Import updates align with Templates subsystem.The imports correctly add
ModelInstructionsand the newTemplateandTemplatesRepositorytypes, supporting the transition from the Instructions subsystem to Templates.Also applies to: 49-49
293-356: LGTM! Consistent Template | ModelInstructions handling in completion stage.The
completionmethod correctly:
- Accepts
instructionsasTemplate | ModelInstructions- Resolves templates via
await TemplatesRepository.resolve_str(instructions)before passing toGenerativeModel.loop- Handles both template resolution and plain string instructions uniformly
380-447: LGTM! Consistent template resolution across all completion variants.The
prompting_completion,loopback_completion, andresult_completionmethods all follow the same pattern:
- Accept
instructions: Template | ModelInstructions- Resolve via
await TemplatesRepository.resolve_str(instructions)- Pass resolved string to
GenerativeModel.loopThis consistency ensures uniform template handling across all stage completion operations.
Also applies to: 469-537, 559-606
2045-2093: LGTM! Model routing correctly resolves instructions.The
_model_routinghelper constructs routing instructions as a plain string and correctly resolves it viaawait TemplatesRepository.resolve_str(instructions)at line 2075 before passing toGenerativeModel.loop.src/draive/helpers/instruction_refinement.py (4)
13-20: LGTM! Import updates align with Templates subsystem.The imports correctly transition from instruction-centric types to the new Template-based types, including
TemplateandTemplatesRepository.
27-100: LGTM! Function signature updated for Templates subsystem.The
refine_instructionsfunction correctly:
- Accepts
instructions: Templateparameter- Handles optional
instructions_content: ModelInstructions | Nonefor pre-loaded content- Returns
ModelInstructions(the refined string content)This aligns with the broader Templates subsystem refactor.
135-158: LGTM! Template interception pattern correctly implemented.The
patched_instructions_repositoryproperty cleverly intercepts template loading to inject refined instructions during evaluation:
- Retrieves the active
TemplatesRepositoryfrom context- Wraps the
loadingmethod to return updated content when the identifier matches- Falls back to original repository loading for other templates
- Preserves listing and disables defining (appropriate for evaluation contexts)
This enables evaluating refined instructions without persisting them.
244-249: LGTM! Correct use of TemplatesRepository.load.When
instructions_contentis not provided, the code correctly usesawait TemplatesRepository.load(instructions)to fetch the template content.src/draive/generation/audio/types.py (2)
3-4: LGTM! Import updates align with Templates subsystem.
15-15: LGTM! Protocol signature updated for Template support.The
AudioGeneratingprotocol now acceptsinstructions: Template | ModelInstructions, consistent with the broader Templates subsystem refactor across other generation modules.src/draive/multimodal/__init__.py (2)
8-16: LGTM! Template subsystem exports added.The imports correctly expose the new Template-related types from the
draive.multimodal.templatessubmodule.
25-31: LGTM! Public API expansion for Templates subsystem.The
__all__list correctly includes all Template-related types (Template,TemplateDeclaration,TemplateDefining,TemplateListing,TemplateLoading,TemplateMissing,TemplatesRepository), making them part of the public multimodal API surface. This aligns with the coding guideline to centralize public exports.Based on learnings.
src/draive/generation/text/default.py (2)
6-13: LGTM! Import updates align with Templates subsystem.The imports correctly add
ModelInstructions,Template, andTemplatesRepository, replacing the old Instructions-based imports.
18-28: LGTM! Consistent Template | ModelInstructions handling.The
generate_textfunction correctly:
- Accepts
instructions: Template | ModelInstructions- Resolves templates via
await TemplatesRepository.resolve_str(instructions)before passing toGenerativeModel.loopThis pattern is consistent with the Templates subsystem implementation across other generation and stage modules.
src/draive/generation/audio/default.py (1)
8-8: LGTM! Template system migration applied correctly.The switch from
InstructionsRepository.resolvetoTemplatesRepository.resolve_strand the broadenedinstructionsparameter type (Template | ModelInstructions) align with the repository-wide template system changes. The resolution path correctly handles bothTemplateobjects and plain strings.Also applies to: 11-11, 19-19, 25-25
src/draive/generation/model/types.py (1)
4-5: LGTM! Protocol signature updated consistently.The
ModelGeneratingprotocol now acceptsTemplate | ModelInstructionsfor theinstructionsparameter, aligning with the broader template system migration across generation modules.Also applies to: 29-29
src/draive/conversation/realtime/types.py (1)
12-13: LGTM! Realtime conversation protocol updated consistently.The
RealtimeConversationPreparingprotocol now acceptsTemplate | ModelInstructions, maintaining consistency with the template system migration across the codebase.Also applies to: 130-130
src/draive/generation/image/types.py (1)
3-4: LGTM! Image generation protocol updated consistently.The
ImageGeneratingprotocol signature now acceptsTemplate | ModelInstructions, aligning with the template system migration applied across generation modules.Also applies to: 15-15
src/draive/multimodal/templates/__init__.py (1)
1-19: LGTM! Public API surface correctly defined.The template subsystem exports are comprehensive and properly centralized, exposing all essential types (
Template,TemplateDeclaration,TemplateMissing) and protocols (TemplateDefining,TemplateListing,TemplateLoading,TemplatesRepository) for the new template system.Based on learnings.
tests/test_multimodal_template_variables.py (1)
1-207: LGTM! Comprehensive test coverage with past critical issue resolved.The test suite thoroughly exercises template variable parsing and resolution (text and multimodal), covering edge cases like empty templates, missing arguments, repeated placeholders, metadata boundaries, and malformed markers. All calls to
resolve_text_templatenow correctly use keyword-onlyarguments=syntax, and the unused-argument test (lines 110-113) correctly verifies that extra arguments are ignored rather than raising errors, matching the implementation behavior.src/draive/conversation/realtime/state.py (1)
36-46: API update looks consistent.
instructions: Template | ModelInstructions = ""and docstring align with the repo-wide refactor. No behavior regressions spotted.src/draive/generation/text/state.py (1)
38-47: LGTM — consistent typing and forwarding.
Template | ModelInstructionsis applied across overloads;Toolbox.of(...)and example normalization look correct.src/draive/conversation/completion/types.py (1)
22-33: Align instructions typing across public APIs (allow str or remove str defaults elsewhere).Here the Protocol requires
Template | ModelInstructions, while other modules still accept/ default tostr. Decide a single policy:
- Option A (compat): widen to
Template | ModelInstructions | str.- Option B (strict): keep as-is and remove str defaults from other APIs.
Confirm direction and apply consistently. As per coding guidelines.
Also applies to: 35-45, 46-55
src/draive/conversation/realtime/default.py (1)
37-45: ****The review comment is incorrect. ModelInstructions is defined as a type alias for str, not a separate incompatible type. The current code is already correct because:
TemplatesRepository.resolve_stracceptsTemplate | strrealtime_conversation_preparingreceivesinstructions: Template | ModelInstructions- Since
ModelInstructions = str, the parameter type is effectivelyTemplate | str, which exactly matches whatresolve_straccepts- No type guard or refactoring is needed
The code at line 52 (and the referenced lines 51–57, which are part of the same function) will work correctly without modification.
Likely an incorrect or invalid review comment.
05f22c5 to
1719705
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/draive/conversation/realtime/default.py (1)
51-56: Pass**extratoTemplatesRepository.resolve_strfor backend context.Enables file/postgres backends to use context (e.g., tenant, locale).
- session_scope: ModelSessionScope = await RealtimeGenerativeModel.session( - instructions=await TemplatesRepository.resolve_str(instructions), + session_scope: ModelSessionScope = await RealtimeGenerativeModel.session( + instructions=await TemplatesRepository.resolve_str(instructions, **extra), memory=memory, tools=toolbox.available_tools_declaration(), output=output, **extra, )src/draive/models/generative.py (1)
650-668: Docstring drift: remove InstructionsRepository mention and fix param type.The method signature is
instructions: ModelInstructions = "", but docs sayTemplate | ModelInstructionsand referenceInstructionsRepository. Update docs for accuracy.- Resolves ``instructions`` (via ``InstructionsRepository``), normalizes the provided - ``memory`` into a ``ModelMemory`` if a raw context is given, and delegates to the - provider's ``session_preparing`` to obtain a ``ModelSessionScope``. + Normalizes the provided ``memory`` into a ``ModelMemory`` if a raw context is given, + then delegates to the provider's ``session_preparing`` to obtain a ``ModelSessionScope``. @@ - instructions : Template | ModelInstructions, optional - Instructions or an instruction reference resolvable by ``InstructionsRepository``. + instructions : ModelInstructions, optional + System/task instructions (string or provider-structured) forwarded to the provider.src/draive/helpers/instruction_refinement.py (1)
135-158: Preserve repository meta when patching loading.The wrapped
TemplatesRepositorydropsmeta, losing backend/source info. Keepmeta=repository.meta.- return TemplatesRepository( - listing=repository.listing, # keep current listing - loading=instructions_loading, # replace loading - # do not allow modifications - use default noop implementation - ) + return TemplatesRepository( + listing=repository.listing, # keep current listing + loading=instructions_loading, # replace loading + # intentionally keep default noop `defining` + meta=repository.meta, # preserve source/meta + )
♻️ Duplicate comments (16)
src/draive/multimodal/templates/types.py (2)
51-62: UseMap()for consistency and immutability.Line 60 constructs a plain dict for merged arguments, which is inconsistent with line 43's use of
Map()and breaks the immutability pattern expected forStateclasses.Apply this diff:
def with_arguments( self, **arguments: Multimodal, ) -> Self: if not arguments: return self return self.__class__( identifier=self.identifier, - arguments={**self.arguments, **arguments}, + arguments=Map({**self.arguments, **arguments}), meta=self.meta, )As per coding guidelines: use
Mapfor immutable state attributes.
79-96: PreferMap()for immutability and consistency.Line 94 initializes
variableswith a plain dict{}, which is inconsistent with theMap()-based pattern used elsewhere in the codebase for immutable state.Apply this diff:
return cls( identifier=identifier, description=description, - variables=variables if variables is not None else {}, + variables=Map(variables) if variables is not None else Map(), meta=Meta.of(meta), )As per coding guidelines: use
Mapfor immutable state attributes.src/draive/multimodal/templates/variables.py (1)
1-1: Use built-inset[str]per Python 3.12+ guidelines.The file imports
Setfromcollections.abcand usesSet[str]in type annotations. Per coding guidelines, Python 3.12+ projects should use built-in generics (set[str]) instead.Apply this diff:
-from collections.abc import Generator, Mapping, MutableSequence, Set +from collections.abc import Generator, Mapping, MutableSequence from haiway import Immutable from draive.multimodal.content import Multimodal, MultimodalContent __all__ = ( "parse_template_variables", "resolve_multimodal_template", "resolve_multimodal_template", ) def parse_template_variables( template: str, -) -> Set[str]: +) -> set[str]: return { segment.name for segment in _split_template(template) if isinstance(segment, TemplateVariable) }As per coding guidelines: use Python 3.12+ built-in generics.
Also applies to: 14-21
docs/guides/Postgres.md (1)
119-120: API naming: use resolve_str, not resolve_as_text.The documentation references
resolve_as_text(template), but the actualTemplatesRepositoryAPI exposesresolve_str. Update all references to match the public API.Apply this diff:
-- `resolve(template)` and `resolve_as_text(template)` reuse a cached loader keyed by identifier to - pull the latest template body before rendering arguments. +- `resolve(template)` and `resolve_str(template)` reuse a cached loader keyed by identifier to pull + the latest template body before rendering arguments.src/draive/postgres/__init__.py (1)
12-12: Export change is correct, but PostgresTemplatesRepository contains a critical SQL syntax error.The replacement of
PostgresInstructionsRepositorywithPostgresTemplatesRepositoryaligns with the template system migration. However, the exportedPostgresTemplatesRepositoryimplementation contains a critical SQL syntax error insrc/draive/postgres/templates.py(lines 137-145) that will cause runtime failures whendefine()is called—a missing comma between$4::JSONBand$5::JSONBin the INSERT VALUES clause.Also applies to: 23-23
src/draive/postgres/templates.py (1)
128-166: LGTM — Define implementation with cache invalidation.The SQL INSERT properly parameterizes all values, and cache clearing (lines 164-165) ensures consistency after defining new templates. The past review comment about a missing comma between
$4::JSONBand$5::JSONBhas been addressed — line 153 shows the comma is present.src/draive/helpers/instruction_preparation.py (1)
26-44: LGTM — Function signature and instantiation updated for TemplateDeclaration.The parameter type change and instantiation logic correctly migrate from
InstructionsDeclarationtoTemplateDeclaration. The past review comment about preferringTemplateDeclaration.of(...)over direct construction (lines 37-40) remains a valid refinement for consistency with State constructor patterns.src/draive/conversation/completion/state.py (1)
37-43: Type default mismatch: add| strtoinstructions(3 sites).Defaults are
""but the annotation excludesstr. Align types across overloads and impl.- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",Also applies to: 50-56, 62-68
src/draive/generation/model/state.py (1)
23-30: Type default mismatch: add| strtoinstructions(3 sites).Defaults use
""; includestrto match runtime and prior API.- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",Also applies to: 38-45, 53-60
src/draive/generation/model/default.py (1)
36-46: Unify resolution via TemplatesRepository and pass through**extra.Avoid
str.format(...)and keep a single resolution path so string/Template behave identically and repository backends can use extra context. Also reuse computed schema variable. This mirrors the earlier guidance.@@ - case "full": - if isinstance(instructions, str): - resolved_instructions = instructions.format( - model_schema=generated.json_schema(indent=2), - ) - else: - resolved_instructions = await TemplatesRepository.resolve_str( - instructions.with_arguments( - model_schema=generated.json_schema(indent=2), - ) - ) + case "full": + schema = generated.json_schema(indent=2) + if isinstance(instructions, str): + # Resolve via repository for consistent placeholder semantics + resolved_instructions = await TemplatesRepository.resolve_str( + Template.of("__inline__", arguments={"model_schema": schema}), + default=instructions, + **extra, + ) + else: + resolved_instructions = await TemplatesRepository.resolve_str( + instructions.with_arguments(model_schema=schema), + **extra, + ) @@ - case "simplified": - if isinstance(instructions, str): - resolved_instructions = instructions.format( - model_schema=generated.simplified_schema(indent=2), - ) - else: - resolved_instructions = await TemplatesRepository.resolve_str( - instructions.with_arguments( - model_schema=generated.simplified_schema(indent=2), - ) - ) + case "simplified": + schema = generated.simplified_schema(indent=2) + if isinstance(instructions, str): + resolved_instructions = await TemplatesRepository.resolve_str( + Template.of("__inline__", arguments={"model_schema": schema}), + default=instructions, + **extra, + ) + else: + resolved_instructions = await TemplatesRepository.resolve_str( + instructions.with_arguments(model_schema=schema), + **extra, + ) @@ - case "skip": # instruction is not modified - resolved_instructions = await TemplatesRepository.resolve_str(instructions) + case "skip": # instruction is not modified + resolved_instructions = await TemplatesRepository.resolve_str( + instructions, + **extra, + )Also applies to: 49-59, 61-63
src/draive/__init__.py (1)
290-293: Remove duplicate entry in all.
ModelInstructionsappears twice, which is noisy and can confuse tooling."ModelInputInvalid", - "ModelInstructions", - "ModelInstructions", + "ModelInstructions", "ModelMemory",src/draive/conversation/completion/default.py (1)
18-20: Import core types from the public API.Use
draive.modelsinstead of the internaldraive.models.types.-from draive.models.types import ModelInstructions, ModelToolRequest +from draive.models import ModelInstructions, ModelToolRequestsrc/draive/multimodal/templates/repository.py (4)
313-318: Return templates in a stable order.Dict iteration order isn’t guaranteed across processes; sort by identifier to avoid flakiness.
- return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))- return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))Also applies to: 391-393
487-498: Write templates deterministically for reproducible files.Sort declarations and JSON keys to keep file content stable across writes.
- file_contents: bytes = json.dumps( - [ - { - "identifier": declaration.identifier, - "description": declaration.description, - "variables": declaration.variables, - "content": self._contents[declaration.identifier], - "meta": declaration.meta.to_mapping(), - } - for declaration in self._declarations.values() - ] - ).encode() + ordered = sorted(self._declarations.values(), key=lambda d: d.identifier) + file_contents: bytes = json.dumps( + [ + { + "identifier": d.identifier, + "description": d.description, + "variables": d.variables, + "content": self._contents[d.identifier], + "meta": d.meta.to_mapping(), + } + for d in ordered + ], + sort_keys=True, + ).encode()
60-88: Add concise NumPy‑style docstrings to public API.Public class/methods lack docstrings (Parameters/Returns/Raises). Please add them for
TemplatesRepositoryand its public methods.I can draft minimal docstrings aligned with current behavior if helpful.
Also applies to: 103-121, 146-182, 206-245, 246-263, 285-301
458-460: Usectx.log_warn, notctx.log_warning(runtime error risk).
ctx.log_warninglikely doesn’t exist; this will raise at runtime. Usectx.log_warn.- ctx.log_warning( + ctx.log_warn( "Invalid templates file storage element, skipping..." )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (41)
Makefile(1 hunks)docs/guides/Postgres.md(2 hunks)pyproject.toml(1 hunks)src/draive/__init__.py(3 hunks)src/draive/conversation/completion/default.py(7 hunks)src/draive/conversation/completion/state.py(5 hunks)src/draive/conversation/completion/types.py(4 hunks)src/draive/conversation/realtime/default.py(3 hunks)src/draive/conversation/realtime/state.py(3 hunks)src/draive/conversation/realtime/types.py(2 hunks)src/draive/generation/audio/default.py(1 hunks)src/draive/generation/audio/state.py(4 hunks)src/draive/generation/audio/types.py(2 hunks)src/draive/generation/image/default.py(1 hunks)src/draive/generation/image/state.py(4 hunks)src/draive/generation/image/types.py(2 hunks)src/draive/generation/model/default.py(3 hunks)src/draive/generation/model/state.py(4 hunks)src/draive/generation/model/types.py(2 hunks)src/draive/generation/text/default.py(1 hunks)src/draive/generation/text/state.py(4 hunks)src/draive/generation/text/types.py(2 hunks)src/draive/helpers/instruction_preparation.py(3 hunks)src/draive/helpers/instruction_refinement.py(5 hunks)src/draive/models/__init__.py(0 hunks)src/draive/models/generative.py(5 hunks)src/draive/models/instructions/__init__.py(0 hunks)src/draive/models/instructions/repository.py(0 hunks)src/draive/models/instructions/template.py(0 hunks)src/draive/models/instructions/types.py(0 hunks)src/draive/multimodal/__init__.py(2 hunks)src/draive/multimodal/templates/__init__.py(1 hunks)src/draive/multimodal/templates/repository.py(1 hunks)src/draive/multimodal/templates/types.py(1 hunks)src/draive/multimodal/templates/variables.py(1 hunks)src/draive/openai/images.py(3 hunks)src/draive/postgres/__init__.py(2 hunks)src/draive/postgres/instructions.py(0 hunks)src/draive/postgres/templates.py(1 hunks)src/draive/stages/stage.py(15 hunks)tests/test_multimodal_template_variables.py(1 hunks)
💤 Files with no reviewable changes (6)
- src/draive/models/instructions/template.py
- src/draive/postgres/instructions.py
- src/draive/models/instructions/init.py
- src/draive/models/instructions/types.py
- src/draive/models/instructions/repository.py
- src/draive/models/init.py
🧰 Additional context used
📓 Path-based instructions (12)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use Python 3.12+ features and syntax across the codebase
Format code exclusively with Ruff (make format); do not use other formatters
Skip module-level docstrings
Files:
src/draive/stages/stage.pysrc/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/variables.pysrc/draive/generation/model/types.pysrc/draive/generation/image/state.pysrc/draive/generation/audio/default.pysrc/draive/models/generative.pysrc/draive/generation/audio/types.pysrc/draive/conversation/realtime/state.pysrc/draive/__init__.pysrc/draive/conversation/realtime/types.pysrc/draive/generation/text/types.pysrc/draive/postgres/templates.pysrc/draive/multimodal/templates/__init__.pysrc/draive/generation/audio/state.pysrc/draive/postgres/__init__.pysrc/draive/generation/model/state.pysrc/draive/conversation/completion/state.pysrc/draive/generation/model/default.pysrc/draive/conversation/completion/types.pysrc/draive/generation/text/state.pysrc/draive/generation/text/default.pysrc/draive/openai/images.pytests/test_multimodal_template_variables.pysrc/draive/generation/image/types.pysrc/draive/conversation/completion/default.pysrc/draive/generation/image/default.pysrc/draive/conversation/realtime/default.pysrc/draive/multimodal/__init__.pysrc/draive/multimodal/templates/repository.pysrc/draive/helpers/instruction_refinement.pysrc/draive/helpers/instruction_preparation.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly (from haiway import State, ctx)
Use ctx.scope(...) to bind scoped Disposables and active State; avoid global state
Route all logs through ctx.log_debug/info/warn/error; do not use print
Use latest, most strict typing syntax (Python 3.12+), with strict typing only for public APIs
Avoid loose Any except at explicit third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
Prefer Mapping/Sequence/Iterable in public types over dict/list/set
Use final where applicable; avoid inheritance and prefer composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Model immutable data/config and facades with haiway.State; provide ergonomic classmethods like .of(...)
Avoid in-place mutation; use State.updated(...) or functional builders to produce new instances
Access active state via haiway.ctx inside async scopes (ctx.scope(...))
Use @statemethod for public state methods that dispatch on the active instance
Log around generation calls, tool dispatch, and provider requests/responses without leaking secrets; prefer structured/concise messages
Add metrics via ctx.record where applicable
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks
Use structured concurrency and valid coroutine usage; rely on haiway/asyncio; avoid custom threading
Construct multimodal content with MultimodalContent.of(...) and compose blocks explicitly
Use ResourceContent/ResourceReference for media/data blobs
Wrap custom types/data within ArtifactContent; use hidden when needed
Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings on internal helpers; keep names self-explanatory
Keep docstrings high-quality; mkdocstrings pulls them into API reference
Never log secrets or full request bodies containing keys/tokens
Files:
src/draive/stages/stage.pysrc/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/variables.pysrc/draive/generation/model/types.pysrc/draive/generation/image/state.pysrc/draive/generation/audio/default.pysrc/draive/models/generative.pysrc/draive/generation/audio/types.pysrc/draive/conversation/realtime/state.pysrc/draive/__init__.pysrc/draive/conversation/realtime/types.pysrc/draive/generation/text/types.pysrc/draive/postgres/templates.pysrc/draive/multimodal/templates/__init__.pysrc/draive/generation/audio/state.pysrc/draive/postgres/__init__.pysrc/draive/generation/model/state.pysrc/draive/conversation/completion/state.pysrc/draive/generation/model/default.pysrc/draive/conversation/completion/types.pysrc/draive/generation/text/state.pysrc/draive/generation/text/default.pysrc/draive/openai/images.pysrc/draive/generation/image/types.pysrc/draive/conversation/completion/default.pysrc/draive/generation/image/default.pysrc/draive/conversation/realtime/default.pysrc/draive/multimodal/__init__.pysrc/draive/multimodal/templates/repository.pysrc/draive/helpers/instruction_refinement.pysrc/draive/helpers/instruction_preparation.py
src/draive/stages/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement pipeline stage abstractions and helpers under draive/stages/
Files:
src/draive/stages/stage.py
src/draive/multimodal/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Files:
src/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/variables.pysrc/draive/multimodal/templates/__init__.pysrc/draive/multimodal/__init__.pysrc/draive/multimodal/templates/repository.py
src/draive/models/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Files:
src/draive/models/generative.py
src/draive/conversation/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement higher-level chat/realtime conversations under draive/conversation/
Files:
src/draive/conversation/realtime/state.pysrc/draive/conversation/realtime/types.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/types.pysrc/draive/conversation/completion/default.pysrc/draive/conversation/realtime/default.py
docs/**/*
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*: When behavior/API changes, update relevant docs under docs/ and examples as applicable
When adding public APIs, update examples/guides and ensure cross-links render
Files:
docs/guides/Postgres.md
src/draive/__init__.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/__init__.py: Centralize public exports in src/draive/init.py
Update src/draive/init.py exports when API surface changes
Files:
src/draive/__init__.py
src/draive/{httpx,mcp,postgres,opentelemetry}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Place integrations under draive/httpx, draive/mcp, draive/postgres, draive/opentelemetry
Files:
src/draive/postgres/templates.pysrc/draive/postgres/__init__.py
{pyproject.toml,pyrightconfig.json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Ruff, Bandit, and Pyright (strict) via make lint
Files:
pyproject.toml
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py: Provider-specific feature modules live under their respective provider directories
Translate provider/SDK errors into typed exceptions; do not raise bare Exception and preserve context
Use environment variables for credentials and resolve via helper functions like getenv_str
Files:
src/draive/openai/images.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Do not perform real network I/O in unit tests; mock providers/HTTP
Keep tests fast and focused on changed code; start with unit tests around new types/functions/adapters
Use fixtures from tests/ or add focused ones; avoid heavy integration scaffolding
Use pytest-asyncio for coroutine tests (@pytest.mark.asyncio)
Prefer scoping with ctx.scope(...) in async tests and bind required State instances explicitly
Avoid real I/O and network in async tests; stub provider calls and HTTP
Files:
tests/test_multimodal_template_variables.py
🧠 Learnings (6)
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/models/**/*.py : Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Applied to files:
src/draive/stages/stage.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Applied to files:
src/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/repository.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in src/draive/__init__.py
Applied to files:
src/draive/__init__.pysrc/draive/multimodal/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Update src/draive/__init__.py exports when API surface changes
Applied to files:
src/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/multimodal/**/*.py : Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Applied to files:
src/draive/__init__.pysrc/draive/multimodal/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Import Haiway symbols directly (from haiway import State, ctx)
Applied to files:
src/draive/helpers/instruction_preparation.py
🧬 Code graph analysis (31)
src/draive/stages/stage.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/multimodal/templates/types.py (1)
src/draive/stages/stage.py (1)
with_meta(1390-1435)
src/draive/multimodal/templates/variables.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
of(33-45)of(82-96)
src/draive/generation/model/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/image/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/audio/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/models/generative.py (5)
completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)
src/draive/generation/audio/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/realtime/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/__init__.py (2)
src/draive/multimodal/templates/types.py (3)
Template(31-76)TemplateDeclaration(80-101)TemplateMissing(18-27)src/draive/multimodal/templates/repository.py (1)
TemplatesRepository(61-306)
src/draive/conversation/realtime/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/postgres/templates.py (3)
src/draive/multimodal/templates/repository.py (11)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)listing(313-317)listing(384-392)load(247-262)loading(319-325)loading(394-404)defining(327-342)defining(406-425)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)src/draive/parameters/model.py (2)
from_json(454-469)to_json(501-517)
src/draive/multimodal/templates/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/generation/audio/state.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/postgres/__init__.py (2)
src/draive/multimodal/templates/repository.py (3)
templates(105-108)templates(111-114)templates(117-121)src/draive/postgres/templates.py (1)
PostgresTemplatesRepository(28-173)
src/draive/generation/model/state.py (4)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/completion/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/model/default.py (4)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
Template(31-76)with_arguments(51-62)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/parameters/model.py (2)
json_schema(443-451)simplified_schema(433-440)
src/draive/conversation/completion/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/models/generative.py (5)
loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/openai/images.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
tests/test_multimodal_template_variables.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/generation/image/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/completion/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/models/generative.py (5)
loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/generation/image/default.py (4)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/openai/images.py (1)
generate_image(21-60)src/draive/conversation/completion/state.py (3)
completion(34-43)completion(47-56)completion(59-136)
src/draive/conversation/realtime/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/multimodal/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/multimodal/templates/repository.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (8)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)of(33-45)of(82-96)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)
src/draive/helpers/instruction_refinement.py (5)
src/draive/multimodal/content.py (2)
MultimodalContent(25-592)MultimodalTag(599-700)src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)loading(319-325)loading(394-404)load(247-262)src/draive/multimodal/text.py (1)
TextContent(11-82)src/draive/postgres/templates.py (2)
loading(121-126)load(88-119)
src/draive/helpers/instruction_preparation.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)
🔇 Additional comments (49)
src/draive/multimodal/templates/types.py (1)
1-15: LGTM!The imports are clean and the
__all__exports now correctly include all public types including protocols and declarations.src/draive/multimodal/templates/variables.py (2)
7-11: Verify__all__fix was applied.The
__all__tuple appears to still have a duplicate"resolve_multimodal_template"entry and is missing"resolve_text_template". Past review comment indicated this was addressed in commit 05f22c5, but the code still shows the issue.Please confirm whether the fix from commit 05f22c5 was applied. The correct
__all__should be:__all__ = ( "parse_template_variables", "resolve_text_template", "resolve_multimodal_template", )
70-112: LGTM!The template parsing logic correctly handles edge cases including missing closing markers, whitespace validation, and proper cursor advancement. The
{% variable %}syntax is clearly defined and robustly implemented.pyproject.toml (1)
8-8: LGTM!Version bump to 0.90.0 is appropriate for this major feature addition (Templates subsystem). The semver increment reflects the significant API surface changes documented in the PR.
Makefile (2)
10-10: Verify intentional removal of.envloading.The
-include .envdirective was removed (or commented out). This might affect local development workflows that rely on environment variables from.envfiles.Please confirm this removal is intentional and document if developers need to source
.envmanually or if environment configuration has moved elsewhere.
13-13: LGTM!UV version bump from 0.9.0 to 0.9.4 brings in patch-level improvements and bug fixes.
src/draive/stages/stage.py (6)
49-49: LGTM!Import correctly adds
TemplateandTemplatesRepositoryfrom the new multimodal templates subsystem.
288-372: LGTM!The
completionmethod correctly migrated to acceptTemplate | ModelInstructionsand resolves instructions viaawait TemplatesRepository.resolve_str(instructions). The resolution is properly awaited and the result is passed toGenerativeModel.loop.
374-463: LGTM!The
prompting_completionmethod follows the same consistent pattern ascompletion, correctly handlingTemplate | ModelInstructionsresolution.
465-553: LGTM!The
loopback_completionmethod correctly implements template resolution following the established pattern.
555-622: LGTM!The
result_completionmethod completes the consistent migration pattern across all completion methods.
2045-2093: LGTM!The
_model_routinghelper correctly constructs routing instructions and resolves them viaTemplatesRepository.resolve_str. The method properly handles the case whereinstructionsis a plain string (resolve_str returns it as-is per the implementation).src/draive/multimodal/__init__.py (1)
8-16: LGTM!Template-related symbols are correctly imported from
draive.multimodal.templatesand exported via__all__. This properly expands the public API surface for the new Templates subsystem.Based on learnings: centralizing public exports in package
__init__.pyfiles.Also applies to: 25-31
src/draive/generation/audio/default.py (2)
8-11: LGTM!Imports correctly updated to include
ModelInstructionsfrom models andTemplate,TemplatesRepositoryfrom multimodal, replacing the old Instructions subsystem.
17-29: LGTM!The
generate_audiofunction correctly migrated to acceptTemplate | ModelInstructionsand resolves instructions viaawait TemplatesRepository.resolve_str(instructions)before passing toGenerativeModel.completion. The async resolution is properly awaited.src/draive/generation/audio/types.py (1)
3-4: LGTM!The
AudioGeneratingprotocol signature correctly updated to acceptTemplate | ModelInstructions, maintaining consistency with the implementation indefault.pyand the broader Templates subsystem migration.Also applies to: 15-15
src/draive/generation/model/types.py (2)
4-5: LGTM: Import updates align with template-based refactor.The imports correctly reflect the transition from
ResolveableInstructionstoTemplateandModelInstructions, consistent with the broader subsystem migration.
29-29: LGTM: Type signature broadened to support Template | ModelInstructions.The updated parameter type expands the acceptable instruction representations while maintaining backward compatibility with
ModelInstructions.src/draive/conversation/realtime/types.py (2)
12-13: LGTM: Import updates support template-based instructions.The imports correctly add
TemplateandModelInstructionsto support the refactored instruction handling.
130-130: LGTM: Protocol signature updated to accept Template | ModelInstructions.The parameter type change aligns with the subsystem migration and maintains consistency across realtime conversation interfaces.
src/draive/generation/image/types.py (2)
3-4: LGTM: Imports updated for template-based instructions.The import changes correctly reflect the migration from
ResolveableInstructionstoTemplateandModelInstructions.
15-15: LGTM: ImageGenerating protocol accepts Template | ModelInstructions.The broadened parameter type maintains consistency with the template subsystem refactor.
src/draive/multimodal/templates/__init__.py (1)
1-19: LGTM: Clean public API exposure for the templates subsystem.The module correctly exports all essential Template-related types and the
TemplatesRepository, following standard Python packaging conventions.src/draive/conversation/realtime/state.py (2)
14-14: LGTM: Imports updated to support Template | ModelInstructions.The import additions correctly support the refactored instruction parameter type.
Also applies to: 22-22
40-40: LGTM: Parameter type and docstring updated consistently.The
instructionsparameter type and documentation accurately reflect the Template | ModelInstructions union, maintaining consistency with the broader refactor.Also applies to: 50-50
tests/test_multimodal_template_variables.py (3)
12-86: LGTM: Comprehensive variable parsing tests.The test suite thoroughly covers:
- Unique variable extraction with deduplication
- Edge cases: empty templates, unmatched/unclosed delimiters, whitespace/padding, empty names
- Adjacent placeholders and symbolic names with hyphens
- Literal brace handling
88-127: LGTM: Text template resolution tests are thorough.The tests correctly verify:
- Placeholder substitution and repetition
- Missing argument detection with specific
KeyErrormessage- Unused arguments are silently ignored (correct behavior per implementation)
- Edge-position placeholders and empty template handling
- All calls use correct keyword argument syntax (
arguments=arguments)
129-207: LGTM: Multimodal template resolution tests are excellent.The test coverage validates:
- String and
TextContentargument handling- Proper
MultimodalContentconstruction and flattening- Missing/unused argument behavior consistent with text templates
- Nested content flattening
- Metadata boundary preservation (lines 180-201 provide particularly strong validation)
- Empty template returning
MultimodalContent.emptyAll calls correctly use keyword argument syntax.
src/draive/generation/text/default.py (2)
9-13: LGTM — Imports align with Template subsystem migration.The updated imports correctly bring in
ModelInstructions,Template, andTemplatesRepositoryto support the new template-based instruction flow.
20-28: LGTM — Parameter type and resolution logic updated consistently.The signature now accepts
Template | ModelInstructions, and the resolution correctly usesTemplatesRepository.resolve_str(instructions)to produce the final instruction string. The flow is consistent with the broader Template subsystem adoption.src/draive/generation/image/default.py (2)
8-11: LGTM — Imports updated for Template subsystem.Correctly imports
ModelInstructions,Template, andTemplatesRepositoryconsistent with the migration.
19-25: LGTM — Signature and resolution align with Template subsystem.The parameter type change and resolution call match the pattern used in other generation modules.
src/draive/generation/image/state.py (2)
7-9: LGTM — Imports updated for Template support.Correct imports for
ModelInstructionsandTemplate.
20-38: LGTM — Overloads and implementation signature consistent.All three signatures (classmethod overload, instance overload, and implementation) now accept
Template | ModelInstructions, maintaining type consistency throughout the public API surface.src/draive/generation/text/types.py (2)
4-5: LGTM — Imports updated for Template subsystem.Correctly imports
ModelInstructionsandTemplate.
15-20: LGTM — Protocol signature updated consistently.The
__call__signature now acceptsTemplate | ModelInstructionsfor instructions and includes**extra: Anyfor provider-specific parameters, matching the implementation pattern across generation modules.src/draive/postgres/templates.py (4)
28-45: LGTM — Well-documented factory with clear parameters.The docstring follows NumPy style and clearly documents the caching parameters and return type.
47-82: LGTM — Listing implementation with appropriate caching.The query uses
DISTINCT ON (identifier)withORDER BY created DESCto fetch the latest version of each template. Caching (limit=1, expiration=600s) is reasonable for listing operations. JSON parsing for variables and Meta includes safe fallbacks.
84-126: LGTM — Load implementation with proper caching strategy.The load function caches individual templates (limit=32) and logs status appropriately. The loading wrapper delegates to load, maintaining the expected interface.
168-173: LGTM — Repository construction wired correctly.The factory returns a properly configured
TemplatesRepositorywith all required callbacks and metadata.src/draive/openai/images.py (2)
8-9: LGTM — Imports updated for Template subsystem.Correctly imports
ModelInstructions,Template, andTemplatesRepository.
24-36: LGTM — OpenAI image generation aligned with Template flow.The parameter type and resolution call match the pattern used across generation modules. The prompt is correctly resolved via
TemplatesRepository.resolve_str(instructions)before passing to the OpenAI API.src/draive/generation/text/state.py (2)
8-9: LGTM — Imports updated for Template subsystem.Correctly imports
ModelInstructionsandTemplate.
20-42: LGTM — Signatures updated consistently across overloads.All three signatures (classmethod overload at line 20, instance overload at line 31, and implementation at line 42) now accept
Template | ModelInstructions, ensuring type consistency throughout the public API.src/draive/helpers/instruction_preparation.py (2)
5-6: LGTM — Imports updated for Template subsystem.Correctly imports
ModelInstructionsandTemplateDeclaration.
68-77: LGTM — Variable formatting updated for TemplateDeclaration.The function now correctly operates on
TemplateDeclaration.variablesinstead ofarguments, maintaining the same formatting logic.src/draive/conversation/completion/types.py (1)
8-10: LGTM — protocol types aligned with Template/ModelInstructions.Signatures look consistent; no default/typing mismatch here.
Also applies to: 26-55
src/draive/__init__.py (1)
172-183: Top‑level Template exports look correct.Re-exporting
Template,TemplateDeclaration,TemplateMissing, andTemplatesRepositoryfromdraive.multimodaland listing them in__all__is consistent with the centralized public API strategy.Also applies to: 351-354
src/draive/conversation/completion/default.py (1)
81-107: Template-based resolution and loop wiring LGTM.The switch to
Template | ModelInstructionsandTemplatesRepository.resolve_str(...)is clean, and pre-resolving in non‑streaming path is appropriate.Please ensure all other call sites use the same
Template | ModelInstructionsunion and do not rely on removed Instructions APIs.Also applies to: 134-141
1719705 to
e771562
Compare
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (10)
src/draive/stages/stage.py (1)
794-801:tool_callAPI contradicts itself: exposes*argsbut forbids them.Signature advertises positional args, docstring documents them, yet runtime asserts they’re not supported. Remove
*args(or support them end‑to‑end).Minimal fix (remove
*argsand update docs):- def tool_call[**Args, Result]( + def tool_call[**Args, Result]( cls, _tool: FunctionTool[Args, Result], /, - *args: Args.args, **kwargs: Args.kwargs, ) -> Self: @@ - *args : Args.args - Positional arguments to pass to the tool. **kwargs : Args.kwargs Keyword arguments to pass to the tool. @@ - assert not args, "Positional arguments are not supported" # nosec: B101 + # Only keyword arguments are supported for tool callsIf you prefer supporting positionals, forward them to
_tool.call(request_id, *args, **kwargs)and drop the assert.Also applies to: 813-826, 835-835
Makefile (1)
43-44: Wording nit: make version check message accurate.Current message says “up‑to‑date” even when current > minimum. Suggest:
- echo '...uv version is up-to-date!'; \ + echo '...uv meets minimum version $(UV_VERSION)!'; \src/draive/openai/images.py (1)
33-41: Thread input into template resolution for prompt composition.Allow templates to reference the input by passing it as an argument.
- prompt=await TemplatesRepository.resolve_str(instructions), + prompt=await TemplatesRepository.resolve_str( + instructions, + arguments={"input": input}, + ),src/draive/generation/text/types.py (1)
10-20: Add a short API docstring to TextGenerating.Public protocols should be documented for mkdocstrings.
@runtime_checkable class TextGenerating(Protocol): + """Protocol for text generation callables. + + Parameters + ---------- + instructions : Template | ModelInstructions + Templated system instruction or prepared instruction string. + input : MultimodalContent + Normalized input content. + toolbox : Toolbox + Tools available for function calling. + examples : Iterable[tuple[MultimodalContent, str]] + Few-shot examples as (input, expected_output). + **extra : Any + Provider- or pipeline-specific extras. + + Returns + ------- + str + Generated text. + """ async def __call__(src/draive/generation/text/state.py (2)
14-14: Document the TextGeneration state.Add a concise class docstring for API reference.
class TextGeneration(State): + """Facade for text generation. + + Use `TextGeneration.generate(...)` to invoke the active generator. + """
38-47: Docstring for generate to clarify parameters and defaults.Document parameters, defaults, and return type.
@statemethod async def generate( self, *, instructions: Template | ModelInstructions = "", input: Multimodal, # noqa: A002 tools: Toolbox | Iterable[Tool] = (), examples: Iterable[tuple[Multimodal, str]] = (), **extra: Any, ) -> str: + """Generate text using the active generator. + + Parameters + ---------- + instructions : Template | ModelInstructions, default "" + System instruction template or prepared string. + input : Multimodal + Input content (normalized to MultimodalContent). + tools : Toolbox | Iterable[Tool], default () + Tools available for function calling. + examples : Iterable[tuple[Multimodal, str]], default () + Few-shot examples as (input, expected_output). + **extra : Any + Provider/pipeline-specific extras. + + Returns + ------- + str + Generated text. + """src/draive/generation/image/state.py (1)
20-41: Type-default mismatch: add| strto the union.The
instructionsparameter has a default value of""(empty string), but the type annotationTemplate | ModelInstructionsdoes not includestr. This creates a type inconsistency unlessModelInstructionsis an alias forstr.Based on the past review comment on
src/draive/generation/audio/state.py(lines 20-23), this is a known issue. Add| strto all three signatures to match the default value.Apply this diff:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",src/draive/generation/model/state.py (1)
23-60: Type-default mismatch: add| strto the union.The
instructionsparameter has a default value of""but the type annotationTemplate | ModelInstructionsdoes not includestr. Add| strto all three signatures for consistency with the default value.Apply this diff:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",src/draive/conversation/completion/state.py (1)
37-73: Type-default mismatch: add| strto the union.The
instructionsparameter has a default value of""but the type annotationTemplate | ModelInstructionsdoes not includestr. Add| strto all three signatures and update the docstring on line 73 accordingly.Apply this diff:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions : Template | ModelInstructions, optional + instructions : Template | ModelInstructions | str, optionalsrc/draive/models/generative.py (1)
642-657: Resolve signature-documentation mismatch.The signature on line 642 declares
instructions: ModelInstructions = ""but the documentation on line 656 statesTemplate | ModelInstructions. This inconsistency should be resolved.If the signature should accept both types (consistent with other generation methods in the codebase), update the signature:
- instructions: ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",Otherwise, update the documentation to match the signature:
- instructions : Template | ModelInstructions, optional + instructions : ModelInstructions, optionalNote: If accepting the union type, you may need to add resolution logic before passing to
session_preparing(see line 694).
♻️ Duplicate comments (18)
src/draive/multimodal/templates/variables.py (2)
7-11: Fix__all__: addresolve_text_template, remove duplicate.Export the intended public API.
__all__ = ( "parse_template_variables", - "resolve_multimodal_template", - "resolve_multimodal_template", + "resolve_text_template", + "resolve_multimodal_template", )
1-1: Use built‑in generics (set[str]) and dropSetimport (Python 3.12).Modernize annotations per guidelines.
-from collections.abc import Generator, Mapping, MutableSequence, Set +from collections.abc import Generator, Mapping, MutableSequence @@ -def parse_template_variables( - template: str, -) -> Set[str]: +def parse_template_variables( + template: str, +) -> set[str]:As per coding guidelines.
Also applies to: 14-16
src/draive/multimodal/templates/types.py (5)
91-96: UseMap()forTemplateDeclaration.variablesby default.Align with immutable Map pattern; wrap provided mappings as needed.
) -> Self: return cls( identifier=identifier, description=description, - variables=variables if variables is not None else {}, + variables=Map(variables) if variables is not None else Map(), meta=Meta.of(meta), )
18-28: Add docstring for public exceptionTemplateMissing.Brief NumPy‑style docstring improves API clarity.
class TemplateMissing(Exception): + """ + Raised when a requested template cannot be found. + + Parameters + ---------- + identifier : str + Identifier of the missing template. + """ __slots__ = ("identifier",)
79-97: Add NumPy‑style docstring toTemplateDeclaration.Describe attributes and usage (identifier, description, variables, meta).
58-62: Preserve immutability: useMap()when mergingarguments.Avoid returning a plain dict; keep
Mapfor consistency withState.return self.__class__( identifier=self.identifier, - arguments={**self.arguments, **arguments}, + arguments=Map({**self.arguments, **arguments}), meta=self.meta, )As per coding guidelines.
30-50: Add NumPy‑style docstring toTemplate(public API).Document purpose and attributes per guidelines. Example:
@final class Template(State): + """ + Immutable reference to a named template with bound arguments. + + Attributes + ---------- + identifier : str + Template identifier to resolve from a repository. + arguments : Mapping[str, Multimodal] + Default arguments bound to this template. + meta : Meta + Metadata used when resolving/loading. + """src/draive/multimodal/templates/repository.py (3)
458-458: Use ctx.log_warn instead of ctx.log_warning.The haiway logging API provides
ctx.log_debug,ctx.log_info,ctx.log_warn, andctx.log_error. The methodctx.log_warningdoes not exist and will raiseAttributeErrorat runtime.Apply this diff:
- ctx.log_warning( + ctx.log_warn( "Invalid templates file storage element, skipping..." )
487-498: Write templates in a stable order for reproducible files.Dict insertion order can vary, causing non-deterministic file output. Sort declarations by identifier before serializing.
Apply this diff:
+ ordered = sorted(self._declarations.values(), key=lambda d: d.identifier) file_contents: bytes = json.dumps( [ { - "identifier": declaration.identifier, - "description": declaration.description, - "variables": declaration.variables, - "content": self._contents[declaration.identifier], - "meta": declaration.meta.to_mapping(), + "identifier": d.identifier, + "description": d.description, + "variables": d.variables, + "content": self._contents[d.identifier], + "meta": d.meta.to_mapping(), } - for declaration in self._declarations.values() + for d in ordered ] ).encode()
313-317: Return templates in a stable order.Dict ordering can cause non-deterministic behavior in tests and client code. Sort by identifier for reproducibility.
Apply this diff:
- return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))docs/guides/Postgres.md (1)
84-91: API naming: use resolve_str, not resolve_as_text.Replace resolve_as_text with resolve_str for consistency with the public API.
-– `resolve(template)` and `resolve_as_text(template)` reuse a cached loader keyed by identifier to - pull the latest template body before rendering arguments. +– `resolve(template)` and `resolve_str(template)` reuse a cached loader keyed by identifier to pull + the latest template body before rendering arguments.src/draive/helpers/instruction_preparation.py (1)
37-41: Use State constructor helper TemplateDeclaration.of for consistency.Prefer the
.of(...)constructor over direct dataclass instantiation.- instruction_declaration = TemplateDeclaration( - identifier="instruction", - description=description, - variables={}, - ) + instruction_declaration = TemplateDeclaration.of( + identifier="instruction", + description=description, + variables={}, + )src/draive/generation/model/default.py (1)
36-62: Pass**extratoTemplatesRepository.resolve_strand unify resolution path.The past review comment (marked as addressed in commit 1719705) requested:
- Passing
**extratoTemplatesRepository.resolve_strso backends can access additional context.- Unifying the resolution path so string and Template instructions use consistent placeholder semantics.
However, the current code still:
- Does not pass
**extrato any of the threeTemplatesRepository.resolve_strcalls (lines 42-46, 55-59, 62).- Uses
.format()for string instructions (lines 37-39, 50-52) butTemplatesRepository.resolve_strfor Templates, creating inconsistent placeholder handling.Apply the fix from the previous review:
case "full": - if isinstance(instructions, str): - resolved_instructions = instructions.format( - model_schema=generated.json_schema(indent=2), - ) - - else: - resolved_instructions = await TemplatesRepository.resolve_str( - instructions.with_arguments( - model_schema=generated.json_schema(indent=2), - ) - ) + schema = generated.json_schema(indent=2) + if isinstance(instructions, str): + resolved_instructions = await TemplatesRepository.resolve_str( + Template.of("__inline__", arguments={"model_schema": schema}), + default=instructions, + **extra, + ) + else: + resolved_instructions = await TemplatesRepository.resolve_str( + instructions.with_arguments(model_schema=schema), + **extra, + ) case "simplified": - if isinstance(instructions, str): - resolved_instructions = instructions.format( - model_schema=generated.simplified_schema(indent=2), - ) - - else: - resolved_instructions = await TemplatesRepository.resolve_str( - instructions.with_arguments( - model_schema=generated.simplified_schema(indent=2), - ) - ) + schema = generated.simplified_schema(indent=2) + if isinstance(instructions, str): + resolved_instructions = await TemplatesRepository.resolve_str( + Template.of("__inline__", arguments={"model_schema": schema}), + default=instructions, + **extra, + ) + else: + resolved_instructions = await TemplatesRepository.resolve_str( + instructions.with_arguments(model_schema=schema), + **extra, + ) case "skip": # instruction is not modified - resolved_instructions = await TemplatesRepository.resolve_str(instructions) + resolved_instructions = await TemplatesRepository.resolve_str( + instructions, + **extra, + )src/draive/generation/audio/state.py (1)
20-41: Type-default mismatch: add| strto the union.The
instructionsparameter has a default value of""but the type annotationTemplate | ModelInstructionsdoes not includestr. This was flagged in a previous review as a type-default mismatch.Add
| strto all three signatures.Apply this diff:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "", @@ - instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",src/draive/conversation/completion/default.py (3)
18-19: Import core types from the publicdraive.modelsAPI.Imports should use the centralized public exports rather than internal module paths.
Apply this diff:
-from draive.models.types import ModelInstructions, ModelToolRequest +from draive.models import ModelInstructions, ModelToolRequestBased on coding guidelines.
96-104: Normalize template variables withto_str()when available.Avoid
str(value)on multimodal values; prefervalue.to_str()if present. Building the mapping once improves consistency with the streaming path.Apply this diff:
+ args = ( + { + key: ( + value + if isinstance(value, str) + else (value.to_str() if hasattr(value, "to_str") else str(value)) + ) + for key, value in memory_recall.variables.items() + } + if memory_recall.variables + else None + ) + resolved_instructions: str = await TemplatesRepository.resolve_str( instructions, - arguments={ - key: value if isinstance(value, str) else str(value) - for key, value in memory_recall.variables.items() - } - if memory_recall.variables - else None, + arguments=args, )
149-157: Normalize template variables withto_str()when available.Same concern as in the non-streaming path: prefer
value.to_str()overstr(value)for multimodal values, and build the mapping once for reuse.Apply this diff:
+ args = ( + { + key: ( + value + if isinstance(value, str) + else (value.to_str() if hasattr(value, "to_str") else str(value)) + ) + for key, value in memory_recall.variables.items() + } + if memory_recall.variables + else None + ) + async for chunk in await GenerativeModel.loop( - instructions=await TemplatesRepository.resolve_str( + instructions=await TemplatesRepository.resolve_str( instructions, - arguments={ - key: value if isinstance(value, str) else str(value) - for key, value in memory_recall.variables.items() - } - if memory_recall.variables - else None, + arguments=args, ),src/draive/__init__.py (1)
290-291: Remove duplicateModelInstructionsentry.
ModelInstructionsappears twice in__all__, which is redundant and may confuse tooling.Apply this diff:
"ModelInstructions", - "ModelInstructions", "ModelMemory",Based on learnings.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (44)
Makefile(1 hunks)docs/guides/ComprehensiveEvaluation.md(3 hunks)docs/guides/Postgres.md(3 hunks)docs/guides/Templates.md(1 hunks)mkdocs.yml(1 hunks)pyproject.toml(1 hunks)src/draive/__init__.py(3 hunks)src/draive/conversation/completion/default.py(7 hunks)src/draive/conversation/completion/state.py(5 hunks)src/draive/conversation/completion/types.py(4 hunks)src/draive/conversation/realtime/default.py(3 hunks)src/draive/conversation/realtime/state.py(3 hunks)src/draive/conversation/realtime/types.py(2 hunks)src/draive/generation/audio/default.py(1 hunks)src/draive/generation/audio/state.py(4 hunks)src/draive/generation/audio/types.py(2 hunks)src/draive/generation/image/default.py(1 hunks)src/draive/generation/image/state.py(4 hunks)src/draive/generation/image/types.py(2 hunks)src/draive/generation/model/default.py(3 hunks)src/draive/generation/model/state.py(4 hunks)src/draive/generation/model/types.py(2 hunks)src/draive/generation/text/default.py(1 hunks)src/draive/generation/text/state.py(4 hunks)src/draive/generation/text/types.py(2 hunks)src/draive/helpers/instruction_preparation.py(3 hunks)src/draive/helpers/instruction_refinement.py(5 hunks)src/draive/models/__init__.py(0 hunks)src/draive/models/generative.py(5 hunks)src/draive/models/instructions/__init__.py(0 hunks)src/draive/models/instructions/repository.py(0 hunks)src/draive/models/instructions/template.py(0 hunks)src/draive/models/instructions/types.py(0 hunks)src/draive/multimodal/__init__.py(2 hunks)src/draive/multimodal/templates/__init__.py(1 hunks)src/draive/multimodal/templates/repository.py(1 hunks)src/draive/multimodal/templates/types.py(1 hunks)src/draive/multimodal/templates/variables.py(1 hunks)src/draive/openai/images.py(3 hunks)src/draive/postgres/__init__.py(2 hunks)src/draive/postgres/instructions.py(0 hunks)src/draive/postgres/templates.py(1 hunks)src/draive/stages/stage.py(15 hunks)tests/test_multimodal_template_variables.py(1 hunks)
💤 Files with no reviewable changes (6)
- src/draive/postgres/instructions.py
- src/draive/models/instructions/init.py
- src/draive/models/instructions/types.py
- src/draive/models/instructions/template.py
- src/draive/models/init.py
- src/draive/models/instructions/repository.py
🧰 Additional context used
📓 Path-based instructions (13)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use Python 3.12+ features and syntax across the codebase
Format code exclusively with Ruff (make format); do not use other formatters
Skip module-level docstrings
Files:
src/draive/stages/stage.pysrc/draive/helpers/instruction_refinement.pysrc/draive/multimodal/templates/__init__.pysrc/draive/multimodal/__init__.pysrc/draive/conversation/realtime/types.pysrc/draive/helpers/instruction_preparation.pysrc/draive/multimodal/templates/variables.pysrc/draive/generation/audio/state.pysrc/draive/generation/text/types.pysrc/draive/postgres/templates.pysrc/draive/openai/images.pysrc/draive/conversation/realtime/default.pysrc/draive/multimodal/templates/repository.pysrc/draive/generation/model/state.pysrc/draive/conversation/completion/types.pysrc/draive/generation/text/state.pysrc/draive/generation/audio/default.pysrc/draive/conversation/completion/state.pysrc/draive/models/generative.pysrc/draive/generation/model/default.pysrc/draive/generation/model/types.pysrc/draive/generation/audio/types.pysrc/draive/conversation/completion/default.pysrc/draive/generation/image/default.pysrc/draive/__init__.pytests/test_multimodal_template_variables.pysrc/draive/conversation/realtime/state.pysrc/draive/generation/image/types.pysrc/draive/generation/text/default.pysrc/draive/postgres/__init__.pysrc/draive/generation/image/state.pysrc/draive/multimodal/templates/types.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly (from haiway import State, ctx)
Use ctx.scope(...) to bind scoped Disposables and active State; avoid global state
Route all logs through ctx.log_debug/info/warn/error; do not use print
Use latest, most strict typing syntax (Python 3.12+), with strict typing only for public APIs
Avoid loose Any except at explicit third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
Prefer Mapping/Sequence/Iterable in public types over dict/list/set
Use final where applicable; avoid inheritance and prefer composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Model immutable data/config and facades with haiway.State; provide ergonomic classmethods like .of(...)
Avoid in-place mutation; use State.updated(...) or functional builders to produce new instances
Access active state via haiway.ctx inside async scopes (ctx.scope(...))
Use @statemethod for public state methods that dispatch on the active instance
Log around generation calls, tool dispatch, and provider requests/responses without leaking secrets; prefer structured/concise messages
Add metrics via ctx.record where applicable
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks
Use structured concurrency and valid coroutine usage; rely on haiway/asyncio; avoid custom threading
Construct multimodal content with MultimodalContent.of(...) and compose blocks explicitly
Use ResourceContent/ResourceReference for media/data blobs
Wrap custom types/data within ArtifactContent; use hidden when needed
Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings on internal helpers; keep names self-explanatory
Keep docstrings high-quality; mkdocstrings pulls them into API reference
Never log secrets or full request bodies containing keys/tokens
Files:
src/draive/stages/stage.pysrc/draive/helpers/instruction_refinement.pysrc/draive/multimodal/templates/__init__.pysrc/draive/multimodal/__init__.pysrc/draive/conversation/realtime/types.pysrc/draive/helpers/instruction_preparation.pysrc/draive/multimodal/templates/variables.pysrc/draive/generation/audio/state.pysrc/draive/generation/text/types.pysrc/draive/postgres/templates.pysrc/draive/openai/images.pysrc/draive/conversation/realtime/default.pysrc/draive/multimodal/templates/repository.pysrc/draive/generation/model/state.pysrc/draive/conversation/completion/types.pysrc/draive/generation/text/state.pysrc/draive/generation/audio/default.pysrc/draive/conversation/completion/state.pysrc/draive/models/generative.pysrc/draive/generation/model/default.pysrc/draive/generation/model/types.pysrc/draive/generation/audio/types.pysrc/draive/conversation/completion/default.pysrc/draive/generation/image/default.pysrc/draive/__init__.pysrc/draive/conversation/realtime/state.pysrc/draive/generation/image/types.pysrc/draive/generation/text/default.pysrc/draive/postgres/__init__.pysrc/draive/generation/image/state.pysrc/draive/multimodal/templates/types.py
src/draive/stages/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement pipeline stage abstractions and helpers under draive/stages/
Files:
src/draive/stages/stage.py
src/draive/multimodal/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Files:
src/draive/multimodal/templates/__init__.pysrc/draive/multimodal/__init__.pysrc/draive/multimodal/templates/variables.pysrc/draive/multimodal/templates/repository.pysrc/draive/multimodal/templates/types.py
src/draive/conversation/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement higher-level chat/realtime conversations under draive/conversation/
Files:
src/draive/conversation/realtime/types.pysrc/draive/conversation/realtime/default.pysrc/draive/conversation/completion/types.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/default.pysrc/draive/conversation/realtime/state.py
mkdocs.yml
📄 CodeRabbit inference engine (AGENTS.md)
Register documentation navigation updates in mkdocs.yml (nav section) when adding/adjusting pages
Files:
mkdocs.yml
docs/**/*
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*: When behavior/API changes, update relevant docs under docs/ and examples as applicable
When adding public APIs, update examples/guides and ensure cross-links render
Files:
docs/guides/Postgres.mddocs/guides/Templates.mddocs/guides/ComprehensiveEvaluation.md
src/draive/{httpx,mcp,postgres,opentelemetry}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Place integrations under draive/httpx, draive/mcp, draive/postgres, draive/opentelemetry
Files:
src/draive/postgres/templates.pysrc/draive/postgres/__init__.py
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py: Provider-specific feature modules live under their respective provider directories
Translate provider/SDK errors into typed exceptions; do not raise bare Exception and preserve context
Use environment variables for credentials and resolve via helper functions like getenv_str
Files:
src/draive/openai/images.py
src/draive/models/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Files:
src/draive/models/generative.py
{pyproject.toml,pyrightconfig.json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Ruff, Bandit, and Pyright (strict) via make lint
Files:
pyproject.toml
src/draive/__init__.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/__init__.py: Centralize public exports in src/draive/init.py
Update src/draive/init.py exports when API surface changes
Files:
src/draive/__init__.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Do not perform real network I/O in unit tests; mock providers/HTTP
Keep tests fast and focused on changed code; start with unit tests around new types/functions/adapters
Use fixtures from tests/ or add focused ones; avoid heavy integration scaffolding
Use pytest-asyncio for coroutine tests (@pytest.mark.asyncio)
Prefer scoping with ctx.scope(...) in async tests and bind required State instances explicitly
Avoid real I/O and network in async tests; stub provider calls and HTTP
Files:
tests/test_multimodal_template_variables.py
🧠 Learnings (6)
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/models/**/*.py : Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Applied to files:
src/draive/stages/stage.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in src/draive/__init__.py
Applied to files:
src/draive/multimodal/templates/__init__.pysrc/draive/multimodal/__init__.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/multimodal/**/*.py : Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Applied to files:
src/draive/multimodal/__init__.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Import Haiway symbols directly (from haiway import State, ctx)
Applied to files:
src/draive/helpers/instruction_preparation.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Applied to files:
src/draive/multimodal/templates/repository.pysrc/draive/multimodal/templates/types.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Update src/draive/__init__.py exports when API surface changes
Applied to files:
src/draive/__init__.py
🧬 Code graph analysis (31)
src/draive/stages/stage.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/helpers/instruction_refinement.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)loading(319-325)loading(394-404)load(247-262)
src/draive/multimodal/templates/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/multimodal/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/conversation/realtime/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/helpers/instruction_preparation.py (1)
src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)
src/draive/multimodal/templates/variables.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
of(33-45)of(82-96)
src/draive/generation/audio/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/postgres/templates.py (3)
src/draive/multimodal/templates/repository.py (11)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)listing(313-317)listing(384-392)load(247-262)loading(319-325)loading(394-404)defining(327-342)defining(406-425)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)src/draive/parameters/model.py (2)
from_json(454-469)to_json(501-517)
src/draive/openai/images.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/conversation/realtime/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/multimodal/templates/repository.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (7)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateLoading(113-119)TemplateMissing(18-27)of(33-45)of(82-96)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)
src/draive/generation/model/state.py (4)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/completion/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/audio/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/models/generative.py (5)
completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)
src/draive/conversation/completion/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/model/default.py (5)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
Template(31-76)with_arguments(51-62)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/parameters/model.py (2)
json_schema(443-451)simplified_schema(433-440)src/draive/parameters/schema.py (1)
simplified_schema(9-26)
src/draive/generation/model/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/audio/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/completion/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/models/generative.py (6)
GenerativeModel(45-515)loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/generation/image/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/__init__.py (2)
src/draive/multimodal/templates/types.py (3)
Template(31-76)TemplateDeclaration(80-101)TemplateMissing(18-27)src/draive/multimodal/templates/repository.py (1)
TemplatesRepository(61-306)
tests/test_multimodal_template_variables.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/conversation/realtime/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/image/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/models/generative.py (5)
loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/postgres/__init__.py (1)
src/draive/postgres/templates.py (1)
PostgresTemplatesRepository(28-173)
src/draive/generation/image/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/multimodal/templates/types.py (1)
src/draive/stages/stage.py (1)
with_meta(1390-1435)
🪛 LanguageTool
docs/guides/Templates.md
[style] ~104-~104: It’s more common nowadays to write this noun as one word.
Context: ...fining templates programmatically, pass variables={"user": "User name"} to document expected arguments. This...
(RECOMMENDED_COMPOUNDS)
🔇 Additional comments (38)
pyproject.toml (1)
8-8: Version bump is appropriate for a minor feature release.The version increment from 0.89.5 to 0.90.0 correctly reflects a minor version bump for the Templates subsystem feature addition, following semantic versioning conventions. No breaking changes to external dependencies or tool configurations are introduced.
src/draive/stages/stage.py (2)
49-50: Import update looks good.Switch to
Template/TemplatesRepositoryaligns with the new Templates subsystem.
293-299: Review comment is incorrect; no type mismatch exists.Since
ModelInstructionsis a type alias forstr, passingTemplate | ModelInstructionsto a function expectingTemplate | stris type-safe. Pyright treats type aliases as their underlying types, soTemplate | ModelInstructionsis compatible withTemplate | strwithout wideningTemplatesRepository.resolve_stror adding casts.No changes needed.
Likely an incorrect or invalid review comment.
docs/guides/ComprehensiveEvaluation.md (1)
3-5: LGTM — formatting only.Readability improvements; no semantic changes.
Also applies to: 9-14, 66-68, 282-283
src/draive/helpers/instruction_refinement.py (3)
13-41: LGTM!The migration from Instructions to Templates is correctly applied. The
instructionsparameter now acceptsTemplatewhileinstructions_contentholds the actual string content.
103-158: LGTM!The
patched_instructions_repositorycorrectly overrides template loading for the refined instructions while preserving access to other templates. The pattern properly isolates refined content during evaluation.
223-280: LGTM!The template loading correctly uses
TemplatesRepository.loadas a classmethod (enabled by@statemethod). The initialization properly handles both explicitinstructions_contentand on-demand template loading.mkdocs.yml (1)
101-101: LGTM!The Templates guide is correctly added to the navigation structure under the Guides section.
src/draive/generation/image/types.py (1)
10-18: LGTM!The parameter type correctly broadens to
Template | ModelInstructions, aligning with the Templates migration across the generation subsystem.src/draive/multimodal/__init__.py (1)
8-33: LGTM!The Template-related symbols are correctly imported and exported, expanding the public API surface. This aligns with the coding guideline to centralize public exports.
As per coding guidelines.
src/draive/generation/audio/default.py (1)
17-29: LGTM!The function correctly migrates to accept
Template | ModelInstructionsand resolves instructions viaTemplatesRepository.resolve_str. This aligns with the Templates subsystem migration.src/draive/generation/model/types.py (1)
23-36: LGTM!The
ModelGeneratingprotocol correctly updates theinstructionsparameter toTemplate | ModelInstructions, maintaining consistency with the broader Templates migration.src/draive/conversation/realtime/types.py (1)
123-134: LGTM!The
RealtimeConversationPreparingprotocol correctly updates theinstructionsparameter toTemplate | ModelInstructions, aligning with the Templates subsystem migration across conversation components.src/draive/multimodal/templates/__init__.py (1)
1-19: LGTM! Clean module exports.The template subsystem exports are well-organized and complete. All symbols are properly imported and exposed via
__all__.Based on learnings: Consider also centralizing these exports in
src/draive/__init__.pyfor top-level access, as noted in the learning that public exports should be centralized at the top level.src/draive/generation/audio/types.py (2)
3-5: LGTM! Import changes align with template migration.The replacement of
ResolveableInstructionswithModelInstructionsand addition ofTemplatecorrectly supports the new template subsystem.
15-15: LGTM! Type signature correctly updated.The parameter type
Template | ModelInstructionsproperly reflects the new instruction format, allowing callers to pass either a template reference or direct model instructions.src/draive/postgres/__init__.py (2)
12-12: LGTM! Import correctly updated for template migration.The import of
PostgresTemplatesRepositoryfrom the newtemplatesmodule aligns with the subsystem refactoring.
23-23: LGTM! Export correctly reflects template subsystem.The replacement of
PostgresInstructionsRepositorywithPostgresTemplatesRepositoryin the public API surface is consistent with the migration to the templates-based workflow.tests/test_multimodal_template_variables.py (3)
1-86: LGTM! Comprehensive parsing tests.The
parse_template_variablestest suite thoroughly covers:
- Unique name extraction with repeated placeholders
- Adjacent placeholders without separators
- Symbolic names (hyphens, numbers)
- Edge cases: empty templates, malformed syntax, whitespace handling, literal braces
88-127: LGTM! Text resolution tests are thorough.The
resolve_text_templatetests correctly validate:
- Placeholder substitution with string arguments
- Repeated placeholder expansion
- Missing argument detection (KeyError)
- Unused arguments (correctly ignored per implementation)
- Edge positions and empty templates
All calls correctly use
arguments=...keyword syntax.
129-207: LGTM! Multimodal resolution tests are excellent.The
resolve_multimodal_templatetests comprehensively verify:
- String and
TextContentconcatenation intoMultimodalContent- Nested content flattening
- Metadata boundary preservation across text parts
- Missing/unused argument handling
- Empty template edge case
The metadata preservation test (lines 180-202) is particularly valuable for validating multimodal correctness.
src/draive/generation/text/default.py (3)
9-13: LGTM! Imports correctly updated for template subsystem.The removal of
InstructionsRepositoryand addition ofTemplateandTemplatesRepositoryalign with the migration to the templates-based instruction resolution.
20-20: LGTM! Parameter type correctly broadened.The
Template | ModelInstructionsunion allows callers to pass either template references or direct model instructions, providing flexibility while maintaining type safety.
28-28: LGTM! Resolution correctly delegates to TemplatesRepository.The switch from
InstructionsRepository.resolvetoTemplatesRepository.resolve_strproperly integrates with the new template resolution pipeline while flattening to the string format required by the model.docs/guides/Templates.md (1)
1-122: LGTM! Comprehensive and well-structured documentation.This guide effectively documents the Templates subsystem:
- Clear explanation of template basics and immutable API design
- Coverage of all storage backends (volatile, file, Postgres, custom)
- Practical examples for resolution and runtime usage
- Migration guidance from
InstructionsRepositorywith placeholder syntax changesThe migration section (lines 107-120) is particularly valuable for developers updating existing code.
src/draive/generation/image/default.py (3)
8-11: LGTM! Imports correctly updated.The import changes align with the template migration pattern used consistently across other generation modules.
19-19: LGTM! Parameter type correctly updated.The
Template | ModelInstructionstype properly reflects the new instruction format for image generation.
25-25: LGTM! Resolution correctly integrated.The use of
TemplatesRepository.resolve_strproperly resolves templates while maintaining the text-based instruction format required by the image generation flow.src/draive/conversation/realtime/state.py (3)
14-22: LGTM! Imports correctly updated.The addition of
ModelInstructionsandTemplateimports aligns with the type signature update for thepreparemethod.
40-40: LGTM! Parameter type correctly broadened.The
Template | ModelInstructionsunion provides flexibility for callers while maintaining type safety in realtime conversation preparation.
50-50: LGTM! Docstring correctly reflects parameter type.The parameter documentation accurately describes the updated
instructionstype.src/draive/openai/images.py (1)
24-24: Code is correct; no runtime type incompatibility exists.ModelInstructions is a direct type alias to
str(line 76, src/draive/models/types.py), makingTemplate | ModelInstructionsequivalent toTemplate | strat runtime. This matches the parameter type expected byresolve_str, which acceptsTemplate | str. No type coercion or verification is needed.src/draive/conversation/completion/types.py (1)
26-55: LGTM!The Protocol definition correctly updates the type signatures to accept
Template | ModelInstructions. Since this is a protocol with no default values, there are no type-default mismatches.src/draive/conversation/completion/default.py (3)
27-27: LGTM!The function signature correctly accepts
Template | ModelInstructions, aligning with the new Templates subsystem.Also applies to: 39-39, 50-50
82-82: LGTM!Internal function signatures correctly updated to match the public API.
Also applies to: 135-135
106-111: LGTM!The resolved instruction string is correctly passed to
GenerativeModel.loop.src/draive/__init__.py (2)
178-181: LGTM!The Template family is correctly imported from
draive.multimodalfor public re-export.
351-354: LGTM!The Template family is correctly exposed in
__all__, properly extending the public API surface.
e771562 to
031f8d4
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/draive/helpers/instruction_preparation.py (1)
46-46: Validate description before assert to prevent runtime errors.The function accepts
TemplateDeclarationwhich allowsdescription=None, but line 46 asserts it must not be None. When a caller passes aTemplateDeclarationwithdescription=None, this assert will fail without a clear error message. Validate upfront and raise a descriptiveValueErrorinstead.Apply this diff to add proper validation:
case declaration: instruction_declaration = declaration + if instruction_declaration.description is None: + raise ValueError("TemplateDeclaration must have a non-None description") + - assert instruction_declaration.description is not None # nosec: B101 result: MultimodalContent = await Stage.completion(src/draive/models/generative.py (1)
620-642: Update docstring to reflect actual parameter type and behavior:instructionsaccepts onlyModelInstructions, with no in-method resolution.The docstring at line 656 incorrectly claims the parameter accepts
Template | ModelInstructionsand that the method resolves instructions viaInstructionsRepository. However:
- All three signatures (lines 620, 631, 642) declare
instructions: ModelInstructions = ""- The implementation passes instructions directly to
session_preparing(line 694) without any resolution- Call sites (e.g., src/draive/conversation/realtime/default.py:52) resolve templates upstream via
TemplatesRepository.resolve_str(...)before calling.session()Update the docstring parameter description to:
instructions : ModelInstructions, optionaland remove the false claim about in-method resolution.
♻️ Duplicate comments (18)
src/draive/helpers/instruction_preparation.py (2)
25-30: Add a NumPy-style docstring to this public function.This public helper requires documentation of parameters, return value, and raises behavior per coding guidelines.
As per coding guidelines.
37-41: Use TemplateDeclaration.of() for consistency.Direct dataclass construction should be replaced with the State constructor helper.
As per coding guidelines.
src/draive/multimodal/templates/types.py (5)
18-27: Add NumPy-style docstring for public exception class.
TemplateMissingis a public exception but lacks a docstring explaining its purpose and theidentifierparameter.As per coding guidelines.
30-76: Add NumPy-style docstrings for Template class and its methods.The
Templateclass and its public methods (of,with_arguments,with_meta) lack docstrings. Per coding guidelines, public API symbols require NumPy-style docstrings with Parameters/Returns sections.As per coding guidelines.
79-101: Add NumPy-style docstrings and prefer Map() for variables.
TemplateDeclarationlacks docstrings and initializesvariableswith{}instead ofMap(). For consistency with the immutability pattern used elsewhere in the codebase, consider usingMap().As per coding guidelines.
104-132: Add NumPy-style docstrings for runtime-checkable protocols.The three protocols (
TemplateListing,TemplateLoading,TemplateDefining) lack docstrings explaining their purpose, parameters, and return values.As per coding guidelines.
51-62: Use Map() for consistency with State immutability semantics.Line 60 constructs a plain dict, but the
ofmethod at line 43 passes the raw dict/mapping directly. For consistency with haiway'sStateimmutability guarantees, consider whether arguments should be wrapped inMap()at construction time.docs/guides/Postgres.md (1)
88-89: Use correct API method name: resolve_str, not resolve_as_text.The documentation references
resolve_as_text, but the actualTemplatesRepositoryAPI method isresolve_str.Apply this diff:
-- `resolve(template)` and `resolve_as_text(template)` reuse a cached loader keyed by identifier to - pull the latest template body before rendering arguments. +- `resolve(template)` and `resolve_str(template)` reuse a cached loader keyed by identifier to + pull the latest template body before rendering arguments.src/draive/postgres/templates.py (1)
74-82: Prefer TemplateDeclaration.of() for consistency.Direct construction of
TemplateDeclarationbypasses the conventional factory pattern used throughout the codebase. UsingTemplateDeclaration.of()ensures consistent state initialization and future-proofing.Apply this diff:
return tuple( - TemplateDeclaration( - identifier=cast(str, result["identifier"]), + TemplateDeclaration.of( + cast(str, result["identifier"]), description=cast(str | None, result["description"]), variables=json.loads(cast(str, result["variables"] or "{}")), meta=Meta.from_json(cast(str, result["meta"] or "{}")), ) for result in results )src/draive/generation/text/types.py (1)
11-20: Consider adding a docstring to the protocol.For API reference completeness, add a brief docstring documenting the protocol's parameters and return type.
As per coding guidelines
@runtime_checkable class TextGenerating(Protocol): """Generate text given instructions, input, toolbox, and examples. Parameters ---------- instructions : Template | ModelInstructions Prompt template or direct instructions for generation. input : MultimodalContent Input content to process. toolbox : Toolbox Available tools for model invocation. examples : Iterable[tuple[MultimodalContent, str]] Example input-output pairs for few-shot learning. **extra : Any Additional provider-specific parameters. Returns ------- str Generated text output. """ async def __call__( self, *, instructions: Template | ModelInstructions, input: MultimodalContent, # noqa: A002 toolbox: Toolbox, examples: Iterable[tuple[MultimodalContent, str]], **extra: Any, ) -> str: ...src/draive/generation/audio/state.py (1)
20-20: Type-default mismatch: includestrin the union.All three signatures provide a default of
""(str), but the type annotationTemplate | ModelInstructionsdoes not includestr. This causes a type inconsistency.Apply this fix to all three signatures:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",Also applies to: 29-29, 38-38
src/draive/conversation/realtime/default.py (1)
52-56: Pass**extraintoresolve_strto enable backend-aware resolution.Propagate the received context to the repository. Previously noted.
Apply:
- instructions=await TemplatesRepository.resolve_str(instructions), + instructions=await TemplatesRepository.resolve_str(instructions, **extra),src/draive/generation/model/default.py (1)
34-63: Unify resolution viaTemplatesRepository.resolve_strand pass**extra.Avoid mixing
.formatwith template resolution and ensure backends receive context. This was flagged earlier.Apply:
@@ match schema_injection: case "full": - if isinstance(instructions, str): - resolved_instructions = instructions.format( - model_schema=generated.json_schema(indent=2), - ) - else: - resolved_instructions = await TemplatesRepository.resolve_str( - instructions.with_arguments( - model_schema=generated.json_schema(indent=2), - ) - ) + schema = generated.json_schema(indent=2) + if isinstance(instructions, str): + resolved_instructions = await TemplatesRepository.resolve_str( + Template.of("__inline__", arguments={"model_schema": schema}), + default=instructions, + **extra, + ) + else: + resolved_instructions = await TemplatesRepository.resolve_str( + instructions.with_arguments(model_schema=schema), + **extra, + ) case "simplified": - if isinstance(instructions, str): - resolved_instructions = instructions.format( - model_schema=generated.simplified_schema(indent=2), - ) - else: - resolved_instructions = await TemplatesRepository.resolve_str( - instructions.with_arguments( - model_schema=generated.simplified_schema(indent=2), - ) - ) + schema = generated.simplified_schema(indent=2) + if isinstance(instructions, str): + resolved_instructions = await TemplatesRepository.resolve_str( + Template.of("__inline__", arguments={"model_schema": schema}), + default=instructions, + **extra, + ) + else: + resolved_instructions = await TemplatesRepository.resolve_str( + instructions.with_arguments(model_schema=schema), + **extra, + ) case "skip": # instruction is not modified - resolved_instructions = await TemplatesRepository.resolve_str(instructions) + resolved_instructions = await TemplatesRepository.resolve_str( + instructions, + **extra, + )#!/bin/bash # List all resolve_str calls with context to spot missing **extra rg -nC2 -P 'TemplatesRepository\.resolve_str\(' # Grep for remaining direct string formatting of model_schema rg -nP -C2 '\.format\s*\(\s*model_schema='src/draive/conversation/completion/default.py (1)
97-105: Preferto_str()for multimodal variable conversion.The template variable mapping uses
str(value)for all non-string values. ForMultimodaltypes that implementto_str(), this method should be preferred as it provides proper multimodal-to-text conversion semantics.Apply this pattern:
resolved_instructions: str = await TemplatesRepository.resolve_str( instructions, arguments={ - key: value if isinstance(value, str) else str(value) + key: ( + value + if isinstance(value, str) + else (value.to_str() if hasattr(value, "to_str") else str(value)) + ) for key, value in memory_recall.variables.items() } if memory_recall.variables else None, )Also apply the same pattern at lines 150-158 in the streaming path.
Based on coding guidelines.
src/draive/multimodal/templates/repository.py (4)
457-460: Use ctx.log_warn instead of ctx.log_warning (runtime error risk).The haiway logging API is
ctx.log_debug/info/warn/error.ctx.log_warningdoes not exist and will raiseAttributeErrorat runtime.Apply this diff:
case _: # skip with warning - ctx.log_warning( + ctx.log_warn( "Invalid templates file storage element, skipping..." )
313-318: Return templates in a stable order.Dict value ordering can cause non-deterministic behavior. Sort by identifier for reproducibility.
Apply this diff:
async def listing( self, **extra: Any, ) -> Sequence[TemplateDeclaration]: - return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
384-392: Return templates in a stable order.Dict value ordering can cause non-deterministic behavior. Sort by identifier for reproducibility.
Apply this diff:
async def listing( self, **extra: Any, ) -> Sequence[TemplateDeclaration]: if self._declarations is None: await self._load_file() assert self._declarations is not None # nosec: B101 - return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
483-501: Write templates in a stable order for reproducible files.Non-deterministic dict ordering causes diff noise and non-reproducible file output. Sort declarations by identifier and use
sort_keys=Trueinjson.dumps.Apply this diff:
async def _save_file(self) -> None: if self._declarations is None or self._contents is None: return # nothing to save + ordered = sorted(self._declarations.values(), key=lambda d: d.identifier) file_contents: bytes = json.dumps( [ { - "identifier": declaration.identifier, - "description": declaration.description, - "variables": declaration.variables, - "content": self._contents[declaration.identifier], - "meta": declaration.meta.to_mapping(), + "identifier": d.identifier, + "description": d.description, + "variables": d.variables, + "content": self._contents[d.identifier], + "meta": d.meta.to_mapping(), } - for declaration in self._declarations.values() - ] + for d in ordered + ], + sort_keys=True, ).encode() async with ctx.disposables(FileAccess.open(self._path, create=True)): await File.write(file_contents)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (48)
Makefile(1 hunks)docs/guides/ComprehensiveEvaluation.md(3 hunks)docs/guides/Postgres.md(3 hunks)docs/guides/Templates.md(1 hunks)mkdocs.yml(1 hunks)pyproject.toml(1 hunks)src/draive/__init__.py(2 hunks)src/draive/conversation/completion/default.py(7 hunks)src/draive/conversation/completion/state.py(5 hunks)src/draive/conversation/completion/types.py(4 hunks)src/draive/conversation/realtime/default.py(3 hunks)src/draive/conversation/realtime/state.py(3 hunks)src/draive/conversation/realtime/types.py(2 hunks)src/draive/generation/audio/default.py(1 hunks)src/draive/generation/audio/state.py(4 hunks)src/draive/generation/audio/types.py(2 hunks)src/draive/generation/image/default.py(1 hunks)src/draive/generation/image/state.py(4 hunks)src/draive/generation/image/types.py(2 hunks)src/draive/generation/model/default.py(3 hunks)src/draive/generation/model/state.py(4 hunks)src/draive/generation/model/types.py(2 hunks)src/draive/generation/text/default.py(1 hunks)src/draive/generation/text/state.py(4 hunks)src/draive/generation/text/types.py(2 hunks)src/draive/helpers/instruction_preparation.py(3 hunks)src/draive/helpers/instruction_refinement.py(5 hunks)src/draive/models/__init__.py(0 hunks)src/draive/models/generative.py(5 hunks)src/draive/models/instructions/__init__.py(0 hunks)src/draive/models/instructions/repository.py(0 hunks)src/draive/models/instructions/template.py(0 hunks)src/draive/models/instructions/types.py(0 hunks)src/draive/multimodal/__init__.py(2 hunks)src/draive/multimodal/templates/__init__.py(1 hunks)src/draive/multimodal/templates/repository.py(1 hunks)src/draive/multimodal/templates/types.py(1 hunks)src/draive/multimodal/templates/variables.py(1 hunks)src/draive/openai/images.py(3 hunks)src/draive/openai/responses.py(1 hunks)src/draive/postgres/__init__.py(2 hunks)src/draive/postgres/instructions.py(0 hunks)src/draive/postgres/memory.py(1 hunks)src/draive/postgres/templates.py(1 hunks)src/draive/stages/stage.py(15 hunks)tests/test_generative_merge.py(1 hunks)tests/test_multimodal_template_variables.py(1 hunks)tests/test_toolbox.py(1 hunks)
💤 Files with no reviewable changes (6)
- src/draive/models/instructions/repository.py
- src/draive/models/instructions/init.py
- src/draive/models/init.py
- src/draive/postgres/instructions.py
- src/draive/models/instructions/template.py
- src/draive/models/instructions/types.py
🧰 Additional context used
📓 Path-based instructions (13)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use Python 3.12+ features and syntax across the codebase
Format code exclusively with Ruff (make format); do not use other formatters
Skip module-level docstrings
Files:
src/draive/generation/model/types.pytests/test_generative_merge.pysrc/draive/multimodal/__init__.pysrc/draive/helpers/instruction_preparation.pysrc/draive/postgres/templates.pysrc/draive/generation/audio/state.pytests/test_multimodal_template_variables.pysrc/draive/conversation/realtime/types.pysrc/draive/openai/responses.pysrc/draive/openai/images.pysrc/draive/postgres/memory.pysrc/draive/generation/model/state.pysrc/draive/generation/text/types.pysrc/draive/generation/text/state.pysrc/draive/multimodal/templates/types.pysrc/draive/conversation/realtime/default.pysrc/draive/multimodal/templates/__init__.pysrc/draive/generation/model/default.pysrc/draive/generation/image/default.pysrc/draive/generation/audio/types.pysrc/draive/generation/text/default.pysrc/draive/multimodal/templates/variables.pysrc/draive/conversation/completion/default.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/realtime/state.pysrc/draive/helpers/instruction_refinement.pysrc/draive/postgres/__init__.pysrc/draive/conversation/completion/types.pytests/test_toolbox.pysrc/draive/generation/audio/default.pysrc/draive/generation/image/state.pysrc/draive/__init__.pysrc/draive/models/generative.pysrc/draive/stages/stage.pysrc/draive/generation/image/types.pysrc/draive/multimodal/templates/repository.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly (from haiway import State, ctx)
Use ctx.scope(...) to bind scoped Disposables and active State; avoid global state
Route all logs through ctx.log_debug/info/warn/error; do not use print
Use latest, most strict typing syntax (Python 3.12+), with strict typing only for public APIs
Avoid loose Any except at explicit third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
Prefer Mapping/Sequence/Iterable in public types over dict/list/set
Use final where applicable; avoid inheritance and prefer composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Model immutable data/config and facades with haiway.State; provide ergonomic classmethods like .of(...)
Avoid in-place mutation; use State.updated(...) or functional builders to produce new instances
Access active state via haiway.ctx inside async scopes (ctx.scope(...))
Use @statemethod for public state methods that dispatch on the active instance
Log around generation calls, tool dispatch, and provider requests/responses without leaking secrets; prefer structured/concise messages
Add metrics via ctx.record where applicable
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks
Use structured concurrency and valid coroutine usage; rely on haiway/asyncio; avoid custom threading
Construct multimodal content with MultimodalContent.of(...) and compose blocks explicitly
Use ResourceContent/ResourceReference for media/data blobs
Wrap custom types/data within ArtifactContent; use hidden when needed
Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings on internal helpers; keep names self-explanatory
Keep docstrings high-quality; mkdocstrings pulls them into API reference
Never log secrets or full request bodies containing keys/tokens
Files:
src/draive/generation/model/types.pysrc/draive/multimodal/__init__.pysrc/draive/helpers/instruction_preparation.pysrc/draive/postgres/templates.pysrc/draive/generation/audio/state.pysrc/draive/conversation/realtime/types.pysrc/draive/openai/responses.pysrc/draive/openai/images.pysrc/draive/postgres/memory.pysrc/draive/generation/model/state.pysrc/draive/generation/text/types.pysrc/draive/generation/text/state.pysrc/draive/multimodal/templates/types.pysrc/draive/conversation/realtime/default.pysrc/draive/multimodal/templates/__init__.pysrc/draive/generation/model/default.pysrc/draive/generation/image/default.pysrc/draive/generation/audio/types.pysrc/draive/generation/text/default.pysrc/draive/multimodal/templates/variables.pysrc/draive/conversation/completion/default.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/realtime/state.pysrc/draive/helpers/instruction_refinement.pysrc/draive/postgres/__init__.pysrc/draive/conversation/completion/types.pysrc/draive/generation/audio/default.pysrc/draive/generation/image/state.pysrc/draive/__init__.pysrc/draive/models/generative.pysrc/draive/stages/stage.pysrc/draive/generation/image/types.pysrc/draive/multimodal/templates/repository.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Do not perform real network I/O in unit tests; mock providers/HTTP
Keep tests fast and focused on changed code; start with unit tests around new types/functions/adapters
Use fixtures from tests/ or add focused ones; avoid heavy integration scaffolding
Use pytest-asyncio for coroutine tests (@pytest.mark.asyncio)
Prefer scoping with ctx.scope(...) in async tests and bind required State instances explicitly
Avoid real I/O and network in async tests; stub provider calls and HTTP
Files:
tests/test_generative_merge.pytests/test_multimodal_template_variables.pytests/test_toolbox.py
src/draive/multimodal/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Files:
src/draive/multimodal/__init__.pysrc/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/multimodal/templates/variables.pysrc/draive/multimodal/templates/repository.py
docs/**/*
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*: When behavior/API changes, update relevant docs under docs/ and examples as applicable
When adding public APIs, update examples/guides and ensure cross-links render
Files:
docs/guides/Templates.mddocs/guides/ComprehensiveEvaluation.mddocs/guides/Postgres.md
src/draive/{httpx,mcp,postgres,opentelemetry}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Place integrations under draive/httpx, draive/mcp, draive/postgres, draive/opentelemetry
Files:
src/draive/postgres/templates.pysrc/draive/postgres/memory.pysrc/draive/postgres/__init__.py
src/draive/conversation/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement higher-level chat/realtime conversations under draive/conversation/
Files:
src/draive/conversation/realtime/types.pysrc/draive/conversation/realtime/default.pysrc/draive/conversation/completion/default.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/realtime/state.pysrc/draive/conversation/completion/types.py
mkdocs.yml
📄 CodeRabbit inference engine (AGENTS.md)
Register documentation navigation updates in mkdocs.yml (nav section) when adding/adjusting pages
Files:
mkdocs.yml
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py: Provider-specific feature modules live under their respective provider directories
Translate provider/SDK errors into typed exceptions; do not raise bare Exception and preserve context
Use environment variables for credentials and resolve via helper functions like getenv_str
Files:
src/draive/openai/responses.pysrc/draive/openai/images.py
{pyproject.toml,pyrightconfig.json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Ruff, Bandit, and Pyright (strict) via make lint
Files:
pyproject.toml
src/draive/__init__.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/__init__.py: Centralize public exports in src/draive/init.py
Update src/draive/init.py exports when API surface changes
Files:
src/draive/__init__.py
src/draive/models/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Files:
src/draive/models/generative.py
src/draive/stages/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement pipeline stage abstractions and helpers under draive/stages/
Files:
src/draive/stages/stage.py
🧠 Learnings (6)
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in src/draive/__init__.py
Applied to files:
src/draive/multimodal/__init__.pysrc/draive/multimodal/templates/__init__.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/multimodal/**/*.py : Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Applied to files:
src/draive/multimodal/__init__.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Import Haiway symbols directly (from haiway import State, ctx)
Applied to files:
src/draive/helpers/instruction_preparation.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Applied to files:
src/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/repository.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Update src/draive/__init__.py exports when API surface changes
Applied to files:
src/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/models/**/*.py : Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Applied to files:
src/draive/__init__.pysrc/draive/stages/stage.py
🧬 Code graph analysis (34)
src/draive/generation/model/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
tests/test_generative_merge.py (1)
src/draive/models/types.py (2)
ModelReasoning(518-562)ModelToolRequest(311-353)
src/draive/multimodal/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/helpers/instruction_preparation.py (1)
src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)
src/draive/postgres/templates.py (2)
src/draive/multimodal/templates/repository.py (11)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)listing(313-317)listing(384-392)load(247-262)loading(319-325)loading(394-404)defining(327-342)defining(406-425)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(80-101)
src/draive/generation/audio/state.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
tests/test_multimodal_template_variables.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/conversation/realtime/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/openai/responses.py (1)
src/draive/models/types.py (1)
ModelReasoning(518-562)
src/draive/openai/images.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/postgres/memory.py (1)
src/draive/models/types.py (3)
ModelInput(429-501)ModelMemoryRecall(719-766)ModelOutput(573-672)
src/draive/generation/model/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/state.py (2)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/multimodal/templates/types.py (2)
tests/test_toolbox.py (4)
meta(109-110)meta(310-311)description(97-98)description(298-299)src/draive/stages/stage.py (1)
with_meta(1390-1435)
src/draive/conversation/realtime/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/multimodal/templates/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(105-108)templates(111-114)templates(117-121)TemplatesRepository(61-306)src/draive/multimodal/templates/types.py (6)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)
src/draive/generation/model/default.py (4)
src/draive/multimodal/templates/types.py (2)
Template(31-76)with_arguments(51-62)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/parameters/model.py (2)
json_schema(443-451)simplified_schema(433-440)src/draive/parameters/schema.py (1)
simplified_schema(9-26)
src/draive/generation/image/default.py (4)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/openai/images.py (1)
generate_image(21-60)src/draive/models/generative.py (6)
GenerativeModel(45-515)completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)
src/draive/generation/audio/types.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/text/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/models/generative.py (6)
GenerativeModel(45-515)loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/multimodal/templates/variables.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
of(33-45)of(82-96)
src/draive/conversation/completion/default.py (4)
src/draive/models/types.py (2)
ModelMemoryRecall(719-766)ModelOutput(573-672)src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)src/draive/models/generative.py (5)
loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/conversation/completion/state.py (4)
src/draive/models/types.py (2)
ModelMemoryRecall(719-766)ModelOutput(573-672)src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/conversation/realtime/state.py (4)
src/draive/models/types.py (2)
ModelMemoryRecall(719-766)ModelOutput(573-672)src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/helpers/instruction_refinement.py (4)
src/draive/multimodal/content.py (2)
MultimodalContent(25-592)MultimodalTag(599-700)src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-306)loading(319-325)loading(394-404)load(247-262)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/postgres/__init__.py (2)
src/draive/multimodal/templates/repository.py (3)
templates(105-108)templates(111-114)templates(117-121)src/draive/postgres/templates.py (1)
PostgresTemplatesRepository(28-173)
src/draive/conversation/completion/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/generation/audio/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/generation/image/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/__init__.py (2)
src/draive/multimodal/templates/types.py (3)
Template(31-76)TemplateDeclaration(80-101)TemplateMissing(18-27)src/draive/multimodal/templates/repository.py (1)
TemplatesRepository(61-306)
src/draive/stages/stage.py (2)
src/draive/multimodal/templates/types.py (1)
Template(31-76)src/draive/multimodal/templates/repository.py (3)
resolve_str(185-193)resolve_str(196-204)resolve_str(207-244)
src/draive/generation/image/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(31-76)
src/draive/multimodal/templates/repository.py (4)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (8)
Template(31-76)TemplateDeclaration(80-101)TemplateDefining(123-132)TemplateListing(105-109)TemplateLoading(113-119)TemplateMissing(18-27)of(33-45)of(82-96)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)src/draive/postgres/templates.py (3)
listing(51-82)defining(128-166)load(88-119)
🪛 LanguageTool
docs/guides/Templates.md
[style] ~104-~104: It’s more common nowadays to write this noun as one word.
Context: ...fining templates programmatically, pass variables={"user": "User name"} to document expected arguments. This...
(RECOMMENDED_COMPOUNDS)
🔇 Additional comments (35)
Makefile (2)
9-10: Inconsistency with AI summary:.envinclusion is still present.The AI summary states ".env inclusion" was removed, but lines 9–10 show the
-include .envdirective and its comment are still present in the code. Please clarify whether this change was intended to be removed or if the summary reflects an abandoned change.
13-13: UV version bump looks good.The patch/minor version bump from
0.9.0to0.9.4is straightforward and safe. The version-checking logic in theuv_checktarget (lines 33–45) correctly handles version comparisons, so this update will integrate seamlessly.src/draive/postgres/memory.py (1)
9-15: LGTM! Import addition is correct and necessary.The
ModelOutputimport is properly added and used at line 275 in the_decode_contextfunction. The multi-line import format is consistent with the existing style.mkdocs.yml (1)
101-101: LGTM!The Templates guide is correctly added to the documentation navigation.
pyproject.toml (1)
8-8: LGTM!The version bump to 0.90.0 is appropriate for the introduction of the new Templates subsystem.
src/draive/postgres/__init__.py (1)
12-12: LGTM!The import and export of
PostgresTemplatesRepositorycorrectly replaces the previous Instructions-based repository.src/draive/generation/audio/types.py (1)
3-15: LGTM!The protocol signature correctly accepts both
TemplateandModelInstructions, aligning with the new Templates subsystem while maintaining compatibility.tests/test_toolbox.py (1)
14-14: LGTM!The import path consolidation from
draive.models.typestodraive.modelscorrectly reflects the module reorganization.src/draive/openai/responses.py (1)
84-84: LGTM! Import path consolidated.The import path for
ModelReasoninghas been updated to use the parent module, aligning with the public API surface consolidation across the codebase.tests/test_generative_merge.py (1)
1-1: LGTM! Test imports aligned with new public API.Import path updated to match the consolidated public API surface. Test logic remains unchanged.
src/draive/generation/model/state.py (2)
8-9: Public API evolution to support Templates.Imports updated to introduce
TemplatealongsideModelInstructions, replacing the previousResolveableInstructionstype as part of the Templates subsystem rollout.
23-23: Signature expanded to accept Template | ModelInstructions.All overloads and the
statemethodnow acceptTemplate | ModelInstructions, broadening the API to support template-based instruction resolution while maintaining backward compatibility with direct string instructions.Also applies to: 38-38, 53-53
docs/guides/ComprehensiveEvaluation.md (1)
3-5: LGTM! Formatting refinements only.Text rewrapping for consistency with no semantic changes.
Also applies to: 9-14, 66-67, 282-283
src/draive/openai/images.py (2)
8-9: Imports updated for Templates subsystem.Replaced
InstructionsRepositoryand legacy instruction types withTemplate,TemplatesRepository, andModelInstructionsto support the new template-based resolution flow.
24-24: Resolution mechanism migrated to TemplatesRepository.The signature now accepts
Template | ModelInstructions, and resolution is performed viaTemplatesRepository.resolve_str, which correctly handles both template references and direct string instructions.Also applies to: 36-36
src/draive/generation/image/types.py (2)
3-4: Protocol imports aligned with Templates subsystem.Replaced
ResolveableInstructionswithModelInstructionsand addedTemplateto support the new instruction handling approach.
15-15: Protocol signature broadened to Template | ModelInstructions.The
ImageGeneratingprotocol now accepts the expanded instruction types, maintaining compatibility with implementations that use the new template resolution flow.src/draive/multimodal/__init__.py (1)
8-16: Public API surface expanded with Templates subsystem.The Template family (
Template,TemplateDeclaration,TemplatesRepository, etc.) is now exposed fromdraive.multimodal, making template-based content resolution available to consumers. This aligns with the goal of centralizing public exports.Based on learnings
Also applies to: 25-31
src/draive/generation/model/types.py (2)
4-5: Protocol imports migrated to Templates surface.Imports updated to replace
ResolveableInstructionswithModelInstructionsand addTemplate, supporting the template-based instruction handling approach.
29-29: Protocol contract expanded for Template support.The
ModelGeneratingprotocol now acceptsTemplate | ModelInstructions, enabling implementations to leverage template resolution while maintaining compatibility with direct string instructions.src/draive/conversation/realtime/types.py (1)
12-13: LGTM — Type union aligns with Template-based refactor.The signature change to
Template | ModelInstructionsis consistent with the broader migration away fromResolveableInstructions. Imports are correct.Also applies to: 130-130
src/draive/multimodal/templates/__init__.py (1)
1-19: LGTM — Public exports are complete and follow conventions.All Template-related types and the repository are correctly imported and included in
__all__. Aligns with the learning about centralizing public exports in__init__.py.Based on learnings
src/draive/generation/audio/default.py (1)
8-11: LGTM — Template resolution integrated correctly.The migration from
InstructionsRepositorytoTemplatesRepository.resolve_stris correct, and theTemplate | ModelInstructionstype union aligns with the broader refactor. The async call is properly awaited.Also applies to: 19-19, 25-25
tests/test_multimodal_template_variables.py (1)
1-207: LGTM — Comprehensive test coverage for template variables.The tests thoroughly cover parsing (unique names, adjacent placeholders, symbolic names, edge cases) and resolution (text and multimodal, missing/unused arguments, metadata preservation). All keyword-only arguments are correctly passed as
arguments=....src/draive/generation/text/default.py (1)
9-9: LGTM — Template resolution follows established pattern.The migration mirrors the audio generation module: correct imports, consistent
Template | ModelInstructionstyping, and proper async resolution viaTemplatesRepository.resolve_str.Also applies to: 13-13, 20-20, 28-28
src/draive/generation/text/types.py (1)
4-5: LGTM — Protocol type updated correctly.The
Template | ModelInstructionsunion is consistent with the migration. Imports are correct.Also applies to: 15-15
src/draive/conversation/realtime/state.py (1)
40-51: Type update toTemplate | ModelInstructionslooks good.Signature and docstring align with the new template-based flow.
src/draive/generation/text/state.py (1)
20-25: Consistent typing migration acknowledged.Overloads and impl now accept
Template | ModelInstructions; wrapper composes inputs and delegates. No further changes needed here.If
generate_textresolves viaTemplatesRepository.resolve_str, we’re good. Otherwise, confirm resolution is centralized there.Also applies to: 31-36, 42-48
src/draive/generation/image/state.py (1)
20-23: Typing migration LGTM.Wrappers now accept
Template | ModelInstructionsand delegate correctly.Also applies to: 29-33, 38-41
src/draive/conversation/completion/types.py (1)
8-9: LGTM! Type signatures correctly updated to Template | ModelInstructions.The parameter type changes across all overloads and the main signature are consistent with the broader Template-based refactor. The import updates align with the new multimodal Template API.
Also applies to: 26-26, 38-38, 49-49
src/draive/conversation/completion/state.py (1)
11-11: LGTM! Conversation.completion correctly updated to use Template | ModelInstructions.The type signature changes across all overloads, main implementation, and docstring are consistent with the Template-based API surface.
Also applies to: 18-18, 37-37, 50-50, 62-62, 73-73
src/draive/stages/stage.py (1)
39-39: LGTM! Stage methods consistently updated to Template-based API.All completion-related stage methods (completion, prompting_completion, loopback_completion, result_completion) and the internal _model_routing function correctly:
- Accept
Template | ModelInstructionsparameters- Resolve templates via
await TemplatesRepository.resolve_str(instructions)before passing toGenerativeModel.loopThe refactor is thorough and consistent across the module.
Also applies to: 49-49, 293-293, 313-313, 356-356, 380-380, 401-401, 447-447, 469-469, 484-484, 537-537, 559-559, 573-573, 606-606, 2054-2054, 2075-2075
src/draive/helpers/instruction_refinement.py (1)
13-20: LGTM! Instruction refinement correctly migrated to Template-based API.The refactor consistently updates:
- Data types from
InstructionstoTemplate- Repository from
InstructionsRepositorytoTemplatesRepository- Identifier-based loading (line 144) instead of name-based
- Loading pathway via
TemplatesRepository.load(line 246)The patched repository pattern (lines 135-158) correctly intercepts template loading to provide refined instruction content during evaluation.
Also applies to: 28-28, 105-105, 135-158, 246-246
src/draive/__init__.py (1)
178-181: LGTM! Public API correctly updated to expose Template-based surface.The top-level exports now include:
Template,TemplateDeclaration,TemplateMissing,TemplatesRepositoryfromdraive.multimodal- Removed Instructions-related symbols
This aligns with the repository-wide migration from Instructions to Templates subsystem.
Based on learnings.
Also applies to: 350-353
src/draive/multimodal/templates/repository.py (1)
1-32: LGTM!Imports follow coding guidelines with direct haiway imports and appropriate module structure.
031f8d4 to
92beca4
Compare
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/draive/models/generative.py (2)
620-642: Inconsistency between parameter type and docstring.The parameter
instructionsis typed asModelInstructions(lines 620, 631, 642), but the docstring at line 656 claimsTemplate | ModelInstructions. Update the parameter type to match the docstring or vice versa for consistency with other methods in the PR.Apply this diff to align the signature with the docstring:
@overload @classmethod async def session( cls, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "", memory: ModelMemory | ModelContext = (), tools: ModelToolsDeclaration = ModelToolsDeclaration.none, output: ModelSessionOutputSelection = "auto", **extra: Any, ) -> ModelSessionScope: ... @overload async def session( self, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "", memory: ModelMemory | ModelContext = (), tools: ModelToolsDeclaration = ModelToolsDeclaration.none, output: ModelSessionOutputSelection = "auto", **extra: Any, ) -> ModelSessionScope: ... @statemethod async def session( self, *, - instructions: ModelInstructions = "", + instructions: Template | ModelInstructions = "", memory: ModelMemory | ModelContext = (), tools: ModelToolsDeclaration = ModelToolsDeclaration.none, output: ModelSessionOutputSelection = "auto", **extra: Any, ) -> ModelSessionScope:
648-678: <!-- [scratchpad_start]
[task verification_1/1 conclusion_confirmation]
[observations]
- ModelSessionPreparing protocol (types.py:1100):
instructions : ModelInstructions(NOT Template)- session() method signature (generative.py:656):
instructions : Template | ModelInstructions- session() implementation (generative.py:692-694): direct pass-through without resolution
- Docstring (line 650): "Resolves
instructions(viaInstructionsRepository)" - FALSE- Pattern throughout codebase: Callers use
await TemplatesRepository.resolve_str(instructions)BEFORE calling GenerativeModel methods- Examples: stages/stage.py, generation/*.py, conversation/realtime/default.py (line 52), conversation/completion/default.py (line 97-98)
[analysis]
- Review comment is CORRECT: docstring falsely claims resolution
- The real issue: signature accepts Template but protocol expects ModelInstructions
- Current implementation: passes instructions unresolved to provider
- Expected pattern: callers should resolve before calling session()
- This is a design inconsistency or incomplete implementation
[conclusion]
The review comment accurately identifies that the docstring is wrong. The code doesn't resolve instructions. However, the issue is even deeper:
- Docstring should be corrected (no resolution happens)
- Method should either resolve instructions itself OR not accept Template union type
- Looking at the pattern, callers are responsible for resolution
[done]
[scratchpad_start] -->Docstring is outdated—session() does not resolve instructions.
The docstring claims "Resolves
instructions(viaInstructionsRepository)" but the implementation at line 692–699 passesinstructionsdirectly tosession_preparingwithout any transformation. The protocol definition expectsModelInstructions(notTemplate), and the codebase pattern shows that resolution is the caller's responsibility—seeconversation/realtime/default.py:52and other callers usingawait TemplatesRepository.resolve_str(instructions)before invoking this method.Update the docstring to remove the false resolution claim, or alternatively, implement instruction resolution in the method body to match the
Template | ModelInstructionsparameter type.src/draive/helpers/instruction_refinement.py (1)
27-100: Update docstring to document conditional TemplatesRepository context requirement.The function uses
@statemethodpatterns correctly, but the docstring omits an important constraint:TemplatesRepositorymust be active in context wheninstructions_contentisNone(line 246). Ifinstructions_contentis provided, no context is required. This conditional dependency should be documented to prevent runtime errors for callers.Update the docstring (lines 43–59) to clarify:
- TemplatesRepository dependency and when it applies (only if instructions_content is None)
- Suggest pairing with instructions_content parameter when context setup is difficult
♻️ Duplicate comments (20)
src/draive/multimodal/templates/variables.py (2)
7-11: Fix__all__: duplicate entry still present.The duplicate
"resolve_multimodal_template"entry remains, and"resolve_text_template"is missing despite being a public function used byrepository.py.Apply this diff:
__all__ = ( "parse_template_variables", - "resolve_multimodal_template", - "resolve_multimodal_template", + "resolve_text_template", + "resolve_multimodal_template", )
1-1: Use built-inset[str]instead ofSetfrom collections.abc.Python 3.12+ supports built-in generic syntax; remove the
Setimport and update all annotations to useset[str].Apply this diff:
-from collections.abc import Generator, Mapping, MutableSequence, Set +from collections.abc import Generator, Mapping, MutableSequenceThen update line 16:
def parse_template_variables( template: str, -) -> Set[str]: +) -> set[str]:As per coding guidelines.
src/draive/helpers/instruction_preparation.py (2)
37-41: PreferTemplateDeclaration.of(...)for consistency.Direct dataclass construction bypasses the factory method. Use
.of()to match State construction patterns across the codebase.Apply this diff:
- instruction_declaration = TemplateDeclaration( - identifier="instruction", + instruction_declaration = TemplateDeclaration.of( + identifier="instruction", description=description, variables={}, )As per coding guidelines.
25-30: Add NumPy-style docstring to public helper.
prepare_instructionsis a public function but lacks documentation explaining its behavior, particularly the ambiguity handling viaInstructionPreparationAmbiguity.Example docstring:
async def prepare_instructions( instruction: TemplateDeclaration | str, /, *, guidelines: str | None = None, ) -> ModelInstructions: """Prepare precise model instructions from a task description or declaration. Parameters ---------- instruction Either a template declaration (with variables and description) or a raw task description string. guidelines Optional guidance appended to the preparation prompt. Returns ------- ModelInstructions Prepared instruction string ready for model consumption. Raises ------ InstructionPreparationAmbiguity When the task requires clarification questions. ValueError When instruction preparation fails unexpectedly. """As per coding guidelines.
src/draive/multimodal/templates/types.py (2)
109-113: Consider usingMap()for immutability consistency.Line 111 constructs a plain dict while other State initializers use
Map()for immutable mappings. UsingMap()would align with Haiway's immutability patterns.Apply this diff if Map is preferred:
return self.__class__( identifier=self.identifier, - arguments={**self.arguments, **arguments}, + arguments=Map({**self.arguments, **arguments}), meta=self.meta, )Note: Verify
Mapis imported fromhaiwayif applying this change.
189-194: Consider usingMap()forvariablesdefault.Line 192 uses a plain
{}while other immutable State attributes typically useMap(). This improves consistency with Haiway's immutability patterns.Apply this diff if Map is preferred:
return cls( identifier=identifier, description=description, - variables=variables if variables is not None else {}, + variables=variables if variables is not None else Map(), meta=Meta.of(meta), )Note: Ensure
Mapis imported fromhaiwayif applying this change.src/draive/multimodal/templates/repository.py (5)
578-580: Critical: Usectx.log_warninstead ofctx.log_warning.Haiway's logging API provides
ctx.log_debug/info/warn/error. The methodctx.log_warningdoes not exist and will raiseAttributeErrorat runtime.Apply this diff:
case _: # skip with warning - ctx.log_warning( + ctx.log_warn( "Invalid templates file storage element, skipping..." )As per coding guidelines.
433-437: Return templates in deterministic order.Non-deterministic dict ordering can cause flaky tests and inconsistent behavior. Sort declarations by identifier for reproducibility.
Apply this diff:
async def listing( self, **extra: Any, ) -> Sequence[TemplateDeclaration]: - return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
508-512: Return templates in deterministic order.Same issue as
VolatileStorage: dict value order is non-deterministic. Sort for stable, reproducible results.Apply this diff:
assert self._declarations is not None # nosec: B101 - return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
607-618: Write templates in deterministic order for reproducible files.Non-deterministic dict iteration causes file content to vary across runs, breaking reproducibility and complicating version control diffs.
Apply this diff:
- file_contents: bytes = json.dumps( + ordered = sorted(self._declarations.values(), key=lambda d: d.identifier) + file_contents: bytes = json.dumps( [ { - "identifier": declaration.identifier, - "description": declaration.description, - "variables": declaration.variables, - "content": self._contents[declaration.identifier], - "meta": declaration.meta.to_mapping(), + "identifier": d.identifier, + "description": d.description, + "variables": d.variables, + "content": self._contents[d.identifier], + "meta": d.meta.to_mapping(), } - for declaration in self._declarations.values() - ] + for d in ordered + ], + sort_keys=True, ).encode()Note: Adding
sort_keys=Trueensures nested dict keys are also stable.
464-471: Rename parameternametoidentifierfor consistency.The codebase consistently uses
identifierfor template names (seelisting,loading,definingmethods). Usingnamehere breaks that convention.Apply this diff:
async def removing( self, - name: str, + identifier: str, meta: Meta, **extra: Any, ) -> None: - del self._declarations[name] - del self._contents[name] + del self._declarations[identifier] + del self._contents[identifier]docs/guides/Templates.md (1)
1-122: Excellent documentation structure and coverage.The guide provides clear explanations of Template basics, storage backends, runtime resolution, and migration paths. Code examples are well-chosen and demonstrate key patterns effectively.
Note: The minor style suggestion about "User name" vs "username" at line 104 has already been flagged in a previous review.
src/draive/generation/text/types.py (1)
4-20: Protocol signature correctly updated for Template support.The
TextGeneratingprotocol now acceptsTemplate | ModelInstructionsand includes**extrafor extensibility, consistent with the broader migration.Note: A previous review suggested adding a docstring for API reference purposes, which remains a minor optional improvement.
src/draive/generation/image/default.py (1)
25-25: Forward**extrato template resolution for backend context.As flagged in a previous review,
TemplatesRepository.resolve_straccepts**extrato allow backends to receive contextual parameters. The function forwards**extratoGenerativeModel.completionbut not to template resolution.Apply this diff:
- instructions=await TemplatesRepository.resolve_str(instructions), + instructions=await TemplatesRepository.resolve_str(instructions, **extra),docs/guides/Postgres.md (1)
88-88: API naming: useresolve_str, notresolve_as_text.The documentation references
resolve_as_text, but the actual API method isresolve_str. Update for consistency.Apply this diff:
-- `resolve(template)` and `resolve_as_text(template)` reuse a cached loader keyed by identifier to +- `resolve(template)` and `resolve_str(template)` reuse a cached loader keyed by identifier tosrc/draive/generation/audio/state.py (1)
20-20: Type-default mismatch: add| strto union.The
instructionsparameter defaults to""(astr), but the unionTemplate | ModelInstructionsdoes not includestr. This creates a type inconsistency across all three signatures.Apply this diff to all three locations:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",Also applies to: 29-29, 38-38
src/draive/generation/model/default.py (1)
36-62: Forward**extraand consider unifying resolution paths.The function receives
**extra(line 30) but does not forward it toTemplatesRepository.resolve_strin any branch. Additionally, the string andTemplateresolution paths diverge (str.formatvs.resolve_str), which creates inconsistent placeholder semantics.Apply this diff to forward
**extraand optionally unify the paths:case "full": if isinstance(instructions, str): resolved_instructions = instructions.format( model_schema=generated.json_schema(indent=2), ) else: resolved_instructions = await TemplatesRepository.resolve_str( instructions.with_arguments( model_schema=generated.json_schema(indent=2), - ) + ), + **extra, ) case "simplified": if isinstance(instructions, str): resolved_instructions = instructions.format( model_schema=generated.simplified_schema(indent=2), ) else: resolved_instructions = await TemplatesRepository.resolve_str( instructions.with_arguments( model_schema=generated.simplified_schema(indent=2), - ) + ), + **extra, ) case "skip": # instruction is not modified - resolved_instructions = await TemplatesRepository.resolve_str(instructions) + resolved_instructions = await TemplatesRepository.resolve_str( + instructions, + **extra, + )src/draive/postgres/templates.py (1)
74-82: PreferTemplateDeclaration.offor State construction.Direct constructor calls bypass any validation or normalization logic in the
.of()helper. Use the classmethod for consistency and future-proofing.Apply this diff:
return tuple( - TemplateDeclaration( + TemplateDeclaration.of( identifier=cast(str, result["identifier"]), description=cast(str | None, result["description"]), variables=json.loads(cast(str, result["variables"] or "{}")), meta=Meta.from_json(cast(str, result["meta"] or "{}")), ) for result in results )src/draive/conversation/realtime/default.py (1)
52-52: Forward**extratoTemplatesRepository.resolve_str.The function receives
**extra(line 43) but does not pass it to the repository call. Backends such as Postgres may require this context for template resolution.Apply this diff:
- instructions=await TemplatesRepository.resolve_str(instructions), + instructions=await TemplatesRepository.resolve_str(instructions, **extra),src/draive/conversation/completion/default.py (1)
97-105: Use to_str() for multimodal values and build the mapping once.The current code converts all non-string values using
str(value), but multimodal values should prefervalue.to_str()when available. Also, the mapping is built inline; consider building it once in a local variable for reuse and clarity.Apply this diff:
+ args = ( + { + key: ( + value + if isinstance(value, str) + else (value.to_str() if hasattr(value, "to_str") else str(value)) + ) + for key, value in memory_recall.variables.items() + } + if memory_recall.variables + else None + ) + resolved_instructions: str = await TemplatesRepository.resolve_str( instructions, - arguments={ - key: value if isinstance(value, str) else str(value) - for key, value in memory_recall.variables.items() - } - if memory_recall.variables - else None, + arguments=args, )Also applies to lines 150-158.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (48)
Makefile(1 hunks)docs/guides/ComprehensiveEvaluation.md(3 hunks)docs/guides/Postgres.md(3 hunks)docs/guides/Templates.md(1 hunks)mkdocs.yml(1 hunks)pyproject.toml(1 hunks)src/draive/__init__.py(2 hunks)src/draive/conversation/completion/default.py(7 hunks)src/draive/conversation/completion/state.py(5 hunks)src/draive/conversation/completion/types.py(4 hunks)src/draive/conversation/realtime/default.py(3 hunks)src/draive/conversation/realtime/state.py(3 hunks)src/draive/conversation/realtime/types.py(2 hunks)src/draive/generation/audio/default.py(1 hunks)src/draive/generation/audio/state.py(4 hunks)src/draive/generation/audio/types.py(2 hunks)src/draive/generation/image/default.py(1 hunks)src/draive/generation/image/state.py(4 hunks)src/draive/generation/image/types.py(2 hunks)src/draive/generation/model/default.py(3 hunks)src/draive/generation/model/state.py(4 hunks)src/draive/generation/model/types.py(2 hunks)src/draive/generation/text/default.py(1 hunks)src/draive/generation/text/state.py(4 hunks)src/draive/generation/text/types.py(2 hunks)src/draive/helpers/instruction_preparation.py(3 hunks)src/draive/helpers/instruction_refinement.py(5 hunks)src/draive/models/__init__.py(0 hunks)src/draive/models/generative.py(5 hunks)src/draive/models/instructions/__init__.py(0 hunks)src/draive/models/instructions/repository.py(0 hunks)src/draive/models/instructions/template.py(0 hunks)src/draive/models/instructions/types.py(0 hunks)src/draive/multimodal/__init__.py(2 hunks)src/draive/multimodal/templates/__init__.py(1 hunks)src/draive/multimodal/templates/repository.py(1 hunks)src/draive/multimodal/templates/types.py(1 hunks)src/draive/multimodal/templates/variables.py(1 hunks)src/draive/openai/images.py(3 hunks)src/draive/openai/responses.py(1 hunks)src/draive/postgres/__init__.py(2 hunks)src/draive/postgres/instructions.py(0 hunks)src/draive/postgres/memory.py(1 hunks)src/draive/postgres/templates.py(1 hunks)src/draive/stages/stage.py(15 hunks)tests/test_generative_merge.py(1 hunks)tests/test_multimodal_template_variables.py(1 hunks)tests/test_toolbox.py(1 hunks)
💤 Files with no reviewable changes (6)
- src/draive/models/instructions/repository.py
- src/draive/postgres/instructions.py
- src/draive/models/instructions/template.py
- src/draive/models/init.py
- src/draive/models/instructions/types.py
- src/draive/models/instructions/init.py
🧰 Additional context used
📓 Path-based instructions (13)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use Python 3.12+ features and syntax across the codebase
Format code exclusively with Ruff (make format); do not use other formatters
Skip module-level docstrings
Files:
src/draive/multimodal/templates/variables.pysrc/draive/generation/audio/default.pysrc/draive/postgres/__init__.pytests/test_multimodal_template_variables.pysrc/draive/openai/responses.pysrc/draive/generation/text/default.pysrc/draive/multimodal/templates/types.pysrc/draive/generation/audio/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/helpers/instruction_refinement.pysrc/draive/multimodal/templates/repository.pysrc/draive/generation/text/types.pysrc/draive/generation/image/state.pysrc/draive/conversation/completion/types.pytests/test_toolbox.pysrc/draive/postgres/memory.pysrc/draive/generation/image/default.pysrc/draive/openai/images.pysrc/draive/generation/model/state.pysrc/draive/conversation/realtime/types.pysrc/draive/__init__.pysrc/draive/postgres/templates.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/default.pysrc/draive/models/generative.pysrc/draive/generation/model/default.pysrc/draive/generation/image/types.pysrc/draive/stages/stage.pysrc/draive/generation/text/state.pysrc/draive/generation/audio/state.pytests/test_generative_merge.pysrc/draive/helpers/instruction_preparation.pysrc/draive/generation/model/types.pysrc/draive/conversation/realtime/default.pysrc/draive/conversation/realtime/state.pysrc/draive/multimodal/__init__.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly (from haiway import State, ctx)
Use ctx.scope(...) to bind scoped Disposables and active State; avoid global state
Route all logs through ctx.log_debug/info/warn/error; do not use print
Use latest, most strict typing syntax (Python 3.12+), with strict typing only for public APIs
Avoid loose Any except at explicit third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
Prefer Mapping/Sequence/Iterable in public types over dict/list/set
Use final where applicable; avoid inheritance and prefer composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Model immutable data/config and facades with haiway.State; provide ergonomic classmethods like .of(...)
Avoid in-place mutation; use State.updated(...) or functional builders to produce new instances
Access active state via haiway.ctx inside async scopes (ctx.scope(...))
Use @statemethod for public state methods that dispatch on the active instance
Log around generation calls, tool dispatch, and provider requests/responses without leaking secrets; prefer structured/concise messages
Add metrics via ctx.record where applicable
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks
Use structured concurrency and valid coroutine usage; rely on haiway/asyncio; avoid custom threading
Construct multimodal content with MultimodalContent.of(...) and compose blocks explicitly
Use ResourceContent/ResourceReference for media/data blobs
Wrap custom types/data within ArtifactContent; use hidden when needed
Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings on internal helpers; keep names self-explanatory
Keep docstrings high-quality; mkdocstrings pulls them into API reference
Never log secrets or full request bodies containing keys/tokens
Files:
src/draive/multimodal/templates/variables.pysrc/draive/generation/audio/default.pysrc/draive/postgres/__init__.pysrc/draive/openai/responses.pysrc/draive/generation/text/default.pysrc/draive/multimodal/templates/types.pysrc/draive/generation/audio/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/helpers/instruction_refinement.pysrc/draive/multimodal/templates/repository.pysrc/draive/generation/text/types.pysrc/draive/generation/image/state.pysrc/draive/conversation/completion/types.pysrc/draive/postgres/memory.pysrc/draive/generation/image/default.pysrc/draive/openai/images.pysrc/draive/generation/model/state.pysrc/draive/conversation/realtime/types.pysrc/draive/__init__.pysrc/draive/postgres/templates.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/default.pysrc/draive/models/generative.pysrc/draive/generation/model/default.pysrc/draive/generation/image/types.pysrc/draive/stages/stage.pysrc/draive/generation/text/state.pysrc/draive/generation/audio/state.pysrc/draive/helpers/instruction_preparation.pysrc/draive/generation/model/types.pysrc/draive/conversation/realtime/default.pysrc/draive/conversation/realtime/state.pysrc/draive/multimodal/__init__.py
src/draive/multimodal/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Files:
src/draive/multimodal/templates/variables.pysrc/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/__init__.pysrc/draive/multimodal/templates/repository.pysrc/draive/multimodal/__init__.py
src/draive/{httpx,mcp,postgres,opentelemetry}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Place integrations under draive/httpx, draive/mcp, draive/postgres, draive/opentelemetry
Files:
src/draive/postgres/__init__.pysrc/draive/postgres/memory.pysrc/draive/postgres/templates.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Do not perform real network I/O in unit tests; mock providers/HTTP
Keep tests fast and focused on changed code; start with unit tests around new types/functions/adapters
Use fixtures from tests/ or add focused ones; avoid heavy integration scaffolding
Use pytest-asyncio for coroutine tests (@pytest.mark.asyncio)
Prefer scoping with ctx.scope(...) in async tests and bind required State instances explicitly
Avoid real I/O and network in async tests; stub provider calls and HTTP
Files:
tests/test_multimodal_template_variables.pytests/test_toolbox.pytests/test_generative_merge.py
mkdocs.yml
📄 CodeRabbit inference engine (AGENTS.md)
Register documentation navigation updates in mkdocs.yml (nav section) when adding/adjusting pages
Files:
mkdocs.yml
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py: Provider-specific feature modules live under their respective provider directories
Translate provider/SDK errors into typed exceptions; do not raise bare Exception and preserve context
Use environment variables for credentials and resolve via helper functions like getenv_str
Files:
src/draive/openai/responses.pysrc/draive/openai/images.py
{pyproject.toml,pyrightconfig.json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Ruff, Bandit, and Pyright (strict) via make lint
Files:
pyproject.toml
docs/**/*
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*: When behavior/API changes, update relevant docs under docs/ and examples as applicable
When adding public APIs, update examples/guides and ensure cross-links render
Files:
docs/guides/Templates.mddocs/guides/ComprehensiveEvaluation.mddocs/guides/Postgres.md
src/draive/conversation/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement higher-level chat/realtime conversations under draive/conversation/
Files:
src/draive/conversation/completion/types.pysrc/draive/conversation/realtime/types.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/default.pysrc/draive/conversation/realtime/default.pysrc/draive/conversation/realtime/state.py
src/draive/__init__.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/__init__.py: Centralize public exports in src/draive/init.py
Update src/draive/init.py exports when API surface changes
Files:
src/draive/__init__.py
src/draive/models/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Files:
src/draive/models/generative.py
src/draive/stages/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement pipeline stage abstractions and helpers under draive/stages/
Files:
src/draive/stages/stage.py
🧠 Learnings (6)
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Applied to files:
src/draive/multimodal/templates/types.pysrc/draive/multimodal/templates/repository.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in src/draive/__init__.py
Applied to files:
src/draive/multimodal/templates/__init__.pysrc/draive/__init__.pysrc/draive/multimodal/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Update src/draive/__init__.py exports when API surface changes
Applied to files:
src/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/models/**/*.py : Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Applied to files:
src/draive/__init__.pysrc/draive/stages/stage.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/multimodal/**/*.py : Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Applied to files:
src/draive/__init__.pysrc/draive/multimodal/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Import Haiway symbols directly (from haiway import State, ctx)
Applied to files:
src/draive/helpers/instruction_preparation.py
🧬 Code graph analysis (34)
src/draive/multimodal/templates/variables.py (1)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)
src/draive/generation/audio/default.py (5)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-426)resolve_str(252-260)resolve_str(263-271)resolve_str(274-334)src/draive/models/generative.py (6)
GenerativeModel(45-515)completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)src/draive/conversation/completion/state.py (3)
completion(34-43)completion(47-56)completion(59-136)src/draive/stages/stage.py (1)
completion(288-372)
src/draive/postgres/__init__.py (2)
src/draive/multimodal/templates/repository.py (3)
templates(137-140)templates(143-146)templates(149-165)src/draive/postgres/templates.py (1)
PostgresTemplatesRepository(28-173)
tests/test_multimodal_template_variables.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/openai/responses.py (1)
src/draive/models/types.py (1)
ModelReasoning(518-562)
src/draive/generation/text/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-426)resolve_str(252-260)resolve_str(263-271)resolve_str(274-334)src/draive/models/generative.py (5)
loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/multimodal/templates/types.py (2)
tests/test_toolbox.py (4)
meta(109-110)meta(310-311)description(97-98)description(298-299)src/draive/stages/stage.py (1)
with_meta(1390-1435)
src/draive/generation/audio/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/multimodal/templates/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(137-140)templates(143-146)templates(149-165)TemplatesRepository(61-426)src/draive/multimodal/templates/types.py (6)
Template(39-139)TemplateDeclaration(143-199)TemplateDefining(225-236)TemplateListing(203-209)TemplateLoading(213-221)TemplateMissing(18-35)
src/draive/helpers/instruction_refinement.py (5)
src/draive/multimodal/content.py (2)
MultimodalContent(25-592)MultimodalTag(599-700)src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-426)loading(439-445)loading(514-524)load(337-371)src/draive/multimodal/text.py (1)
TextContent(11-82)src/draive/postgres/templates.py (2)
loading(121-126)load(88-119)
src/draive/multimodal/templates/repository.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (8)
Template(39-139)TemplateDeclaration(143-199)TemplateDefining(225-236)TemplateListing(203-209)TemplateLoading(213-221)TemplateMissing(18-35)of(56-84)of(162-194)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)
src/draive/generation/text/types.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/generation/image/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/conversation/completion/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/postgres/memory.py (1)
src/draive/models/types.py (3)
ModelInput(429-501)ModelMemoryRecall(719-766)ModelOutput(573-672)
src/draive/generation/image/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (3)
resolve_str(252-260)resolve_str(263-271)resolve_str(274-334)src/draive/models/generative.py (5)
completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)
src/draive/openai/images.py (2)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-426)resolve_str(252-260)resolve_str(263-271)resolve_str(274-334)
src/draive/generation/model/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/conversation/realtime/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/__init__.py (2)
src/draive/multimodal/templates/types.py (3)
Template(39-139)TemplateDeclaration(143-199)TemplateMissing(18-35)src/draive/multimodal/templates/repository.py (1)
TemplatesRepository(61-426)
src/draive/postgres/templates.py (2)
src/draive/multimodal/templates/repository.py (11)
templates(137-140)templates(143-146)templates(149-165)TemplatesRepository(61-426)listing(433-437)listing(504-512)load(337-371)loading(439-445)loading(514-524)defining(447-462)defining(526-545)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(143-199)
src/draive/conversation/completion/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/conversation/completion/default.py (5)
src/draive/models/types.py (4)
ModelMemoryRecall(719-766)ModelOutput(573-672)ModelReasoning(518-562)ModelToolRequest(311-353)src/draive/multimodal/artifact.py (1)
ArtifactContent(11-96)src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (3)
resolve_str(252-260)resolve_str(263-271)resolve_str(274-334)src/draive/models/generative.py (6)
GenerativeModel(45-515)loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/generation/model/default.py (4)
src/draive/multimodal/templates/types.py (2)
Template(39-139)with_arguments(90-113)src/draive/multimodal/templates/repository.py (3)
resolve_str(252-260)resolve_str(263-271)resolve_str(274-334)src/draive/parameters/model.py (2)
json_schema(443-451)simplified_schema(433-440)src/draive/parameters/schema.py (1)
simplified_schema(9-26)
src/draive/generation/image/types.py (1)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)
src/draive/stages/stage.py (2)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-426)resolve_str(252-260)resolve_str(263-271)resolve_str(274-334)
src/draive/generation/text/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/generation/audio/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
tests/test_generative_merge.py (1)
src/draive/models/types.py (2)
ModelReasoning(518-562)ModelToolRequest(311-353)
src/draive/helpers/instruction_preparation.py (1)
src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(143-199)
src/draive/generation/model/types.py (3)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/conversation/realtime/default.py (2)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (3)
resolve_str(252-260)resolve_str(263-271)resolve_str(274-334)
src/draive/conversation/realtime/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/multimodal/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(137-140)templates(143-146)templates(149-165)TemplatesRepository(61-426)src/draive/multimodal/templates/types.py (6)
Template(39-139)TemplateDeclaration(143-199)TemplateDefining(225-236)TemplateListing(203-209)TemplateLoading(213-221)TemplateMissing(18-35)
🪛 LanguageTool
docs/guides/Templates.md
[style] ~104-~104: It’s more common nowadays to write this noun as one word.
Context: ...fining templates programmatically, pass variables={"user": "User name"} to document expected arguments. This...
(RECOMMENDED_COMPOUNDS)
92beca4 to
a9ef300
Compare
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (9)
src/draive/stages/stage.py (1)
2054-2078: Template resolution on plain string is safe but potentially unnecessary.Line 2054 creates a plain string without template variables, and line 2075 resolves it via
TemplatesRepository.resolve_str(). Since the input is a plain string, the resolution will return it as-is (based on the repository implementation in relevant snippets).This works correctly but adds unnecessary overhead. Consider passing the string directly to
GenerativeModel.loop()or verify if future template variable substitution is intended.If no template variables are needed, apply this diff:
- instructions: str = ( + routing_instructions: str = ( "Based on the provided context and the current result," # nosec: B608 - false positive " select the most appropriate option from the following:" f"\n\n{options_text}" "\n\nRespond with with the exact option name within SELECTION xml tag" f" like (e.g., '<SELECTION>{next(iter(options.keys()))}</SELECTION>'" ) # Create routing context with the current result as input routing_context: list[ModelContextElement] = [ *state.context, ModelInput.of( MultimodalContent.of( "<RESULT>", state.result, "</RESULT>", ) ), ] result: ModelOutput = await GenerativeModel.loop( - instructions=await TemplatesRepository.resolve_str(instructions), + instructions=routing_instructions, context=routing_context, output="text", )src/draive/generation/model/state.py (1)
15-16: Add NumPy‑style docstrings for the public API.
Please document ModelGeneration.generate parameters/returns/raises for mkdocstrings.As per coding guidelines
Also applies to: 47-60
src/draive/generation/model/types.py (1)
14-20: Document public protocols.
Please add brief docstrings to ModelGenerationDecoder and ModelGenerating describing parameters and return types.As per coding guidelines
Also applies to: 22-36
src/draive/generation/audio/default.py (1)
24-29: Forward**extrato template resolution.
Template backends may rely on this context; not forwarding can break resolution.Apply:
- instructions=await TemplatesRepository.resolve_str(instructions), + instructions=await TemplatesRepository.resolve_str(instructions, **extra),src/draive/conversation/realtime/default.py (1)
70-75: Usectx.log_warn, notctx.log_warning(runtime error risk).haiway exposes ctx.log_debug/info/warn/error. log_warning likely does not exist.
Apply:
- ctx.log_warning( + ctx.log_warn( f"Tool handling `{response.handling}` is not supported in" " realtime conversation, using regular result handling instead" )As per coding guidelines.
src/draive/models/generative.py (2)
650-666: Update docstring: no longer resolved via InstructionsRepository.Implementation passes
instructionsthrough; resolution happens in callers (e.g., realtime default). Remove outdated paragraph.Apply:
- Resolves ``instructions`` (via ``InstructionsRepository``), normalizes the provided - ``memory`` into a ``ModelMemory`` if a raw context is given, and delegates to the - provider's ``session_preparing`` to obtain a ``ModelSessionScope``. + Normalizes the provided ``memory`` into a ``ModelMemory`` if a raw context is + given, and delegates to the provider's ``session_preparing`` to obtain a + ``ModelSessionScope``.
398-404: Nit: fix typo in comment.Apply:
- # contunue to the next round with results + # continue to the next round with resultssrc/draive/conversation/completion/state.py (1)
37-43: Includestrininstructionsunion and docs.Default is
""; types excludestr. Fix all 3 signatures and the docstring param type.Apply:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",And in the docstring:
- instructions : Template | ModelInstructions, optional + instructions : Template | ModelInstructions | str, optionalAlso applies to: 50-56, 62-69, 73-75
src/draive/conversation/completion/default.py (1)
175-176: Avoid assert for runtime filtering of ModelToolRequest.Asserts can be stripped with -O; filter explicitly or log.
Apply this diff:
- else: - assert not isinstance(chunk, ModelToolRequest) # nosec: B101 - yield ConversationOutputChunk.of(chunk) + else: + if isinstance(chunk, ModelToolRequest): + ctx.log_warn("Dropping unexpected ModelToolRequest chunk in conversation stream") + continue + yield ConversationOutputChunk.of(chunk)
♻️ Duplicate comments (23)
src/draive/multimodal/templates/variables.py (5)
7-11: Fix__all__: duplicate export and missing function.The
__all__tuple exports"resolve_multimodal_template"twice and omits"resolve_text_template". Although a past review indicated this was addressed, the current code still has the issue.Apply this diff:
__all__ = ( "parse_template_variables", - "resolve_multimodal_template", - "resolve_multimodal_template", + "resolve_text_template", + "resolve_multimodal_template", )
1-1: Use built-in generics (set[str]) instead ofSetfromcollections.abc.Per coding guidelines for Python 3.12+, use built-in generic types.
Apply this diff:
-from collections.abc import Generator, Mapping, MutableSequence, Set +from collections.abc import Generator, Mapping, MutableSequenceThen update all occurrences of
Set[str]toset[str]at lines 16, and in the implementation where needed.As per coding guidelines.
14-21: Add NumPy-style docstring for public function.Public functions require NumPy-style documentation per coding guidelines.
Example docstring:
def parse_template_variables( template: str, ) -> set[str]: """Extract variable names from a template string. Parameters ---------- template : str Template string containing variable placeholders in {%name%} format. Returns ------- set[str] Set of unique variable names found in the template. """As per coding guidelines.
24-45: Add NumPy-style docstring for public function.Public functions require NumPy-style documentation per coding guidelines.
Example docstring:
def resolve_text_template( template: str, *, arguments: Mapping[str, Multimodal], ) -> str: """Resolve template variables into a text string. Parameters ---------- template : str Template string with {%variable%} placeholders. arguments : Mapping[str, Multimodal] Mapping of variable names to multimodal values. Returns ------- str Resolved template string with all variables substituted. Raises ------ KeyError When a required template variable is missing from arguments. """As per coding guidelines.
48-67: Add NumPy-style docstring for public function.Public functions require NumPy-style documentation per coding guidelines.
Example docstring:
def resolve_multimodal_template( template: str, *, arguments: Mapping[str, Multimodal], ) -> MultimodalContent: """Resolve template variables into multimodal content. Parameters ---------- template : str Template string with {%variable%} placeholders. arguments : Mapping[str, Multimodal] Mapping of variable names to multimodal content or strings. Returns ------- MultimodalContent Normalized multimodal content with variables resolved. Raises ------ KeyError When a required template variable is missing from arguments. """As per coding guidelines.
src/draive/generation/text/types.py (1)
10-20: Add a concise docstring to TextGenerating.
Document parameters/return type for API reference.As per coding guidelines
src/draive/generation/image/default.py (1)
24-29: Forward**extratoTemplatesRepository.resolve_str.
Required for backends needing context; currently dropped.Apply:
- instructions=await TemplatesRepository.resolve_str(instructions), + instructions=await TemplatesRepository.resolve_str(instructions, **extra),src/draive/openai/images.py (1)
33-41: Pass**extraintoTemplatesRepository.resolve_str.
Currently omitted; can cause template resolution failures.Apply:
- prompt=await TemplatesRepository.resolve_str(instructions), + prompt=await TemplatesRepository.resolve_str(instructions, **extra),src/draive/generation/text/default.py (1)
28-28: Forward**extrato template resolution for backend context.
TemplatesRepository.resolve_straccepts**extrato allow backends (e.g., PostgreSQL, custom adapters) to receive contextual parameters such as revision hints, cache controls, or tenant identifiers. Currently,**extrais forwarded toGenerativeModel.loopbut not to template resolution, which may prevent advanced template backends from functioning correctly.Apply this diff:
- instructions=await TemplatesRepository.resolve_str(instructions), + instructions=await TemplatesRepository.resolve_str(instructions, **extra),src/draive/generation/text/state.py (1)
20-20: Type-default mismatch: add| strto union.The
instructionsparameter has a default value of""(astr), but the type annotationTemplate | ModelInstructionsdoes not includestr. This causes a type inconsistency across all three signatures.Apply this diff to fix all three signatures:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",Also applies to: 31-31, 42-42
src/draive/generation/audio/state.py (1)
20-20: Type-default mismatch: include| strwhere default is"".The
instructionsparameter has a default of""(astr), butstris not in the union. Add| strto all three signatures to keep the API consistent and satisfy typing.Apply this diff:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",Also applies to: 29-29, 38-38
src/draive/helpers/instruction_preparation.py (2)
25-30: Add NumPy-style docstring to public helper.Public helper
prepare_instructionslacks documentation. Per coding guidelines, add a NumPy-style docstring documenting inputs, outputs, and the ambiguity behavior.Apply this diff:
async def prepare_instructions( instruction: TemplateDeclaration | str, /, *, guidelines: str | None = None, ) -> ModelInstructions: + """Prepare precise model instructions from a description or declaration. + + Parameters + ---------- + instruction : TemplateDeclaration | str + Either a template declaration (variables + description) or raw task description. + guidelines : str | None, optional + Extra guidance appended to the preparation prompt. + + Returns + ------- + ModelInstructions + Prepared instruction string. + + Raises + ------ + InstructionPreparationAmbiguity + When clarification questions are required. + ValueError + On unexpected preparation result. + """
37-40: PreferTemplateDeclaration.of(...)for State construction.Use the
.of()constructor helper rather than direct dataclass construction for consistency with State construction patterns across the codebase.Apply this diff:
- instruction_declaration = TemplateDeclaration( - identifier="instruction", + instruction_declaration = TemplateDeclaration.of( + identifier="instruction", description=description, variables={}, )src/draive/postgres/templates.py (1)
74-82: PreferTemplateDeclaration.of(...)for State construction.Use the
.of()constructor helper rather than direct dataclass construction for consistency with State construction patterns and future-proofing.Apply this diff:
return tuple( - TemplateDeclaration( + TemplateDeclaration.of( identifier=cast(str, result["identifier"]), description=cast(str | None, result["description"]), variables=json.loads(cast(str, result["variables"] or "{}")), meta=Meta.from_json(cast(str, result["meta"] or "{}")), ) for result in results )src/draive/conversation/realtime/default.py (1)
52-56: Forward context: pass**extratoTemplatesRepository.resolve_str.Backends may require extra context (tenant, locale). Not forwarding it can mis-resolve templates.
Apply:
- instructions=await TemplatesRepository.resolve_str(instructions), + instructions=await TemplatesRepository.resolve_str(instructions, **extra),src/draive/generation/image/state.py (1)
20-23: Type-default mismatch: includestrininstructionsunion.Default is
""; annotation excludesstr. Fix all three signatures.Apply:
- instructions: Template | ModelInstructions = "", + instructions: Template | ModelInstructions | str = "",(repeat for Lines 29 and 38)
Also applies to: 29-33, 38-41
src/draive/multimodal/templates/repository.py (5)
436-441: Return a stable order.Sort declarations by identifier to avoid nondeterminism/flaky tests.
Apply:
- return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
511-516: Return a stable order.Same as VolatileStorage.listing — sort by identifier.
Apply:
- return tuple(self._declarations.values()) + return tuple(sorted(self._declarations.values(), key=lambda d: d.identifier))
581-583: Usectx.log_warn(notctx.log_warning).Wrong method name risks runtime failure.
Apply:
- ctx.log_warning( + ctx.log_warn( "Invalid templates file storage element, skipping..." )As per coding guidelines.
467-475: Consistent naming: useidentifierinstead ofname.Keep API coherent with
listing/loading/defining.Apply:
- async def removing( - self, - name: str, + async def removing( + self, + identifier: str, meta: Meta, **extra: Any, ) -> None: - del self._declarations[name] - del self._contents[name] + del self._declarations[identifier] + del self._contents[identifier]
610-621: Write templates in a stable, reproducible order.Sort declarations and consider
sort_keys=Trueto stabilize nested dicts.Apply:
- file_contents: bytes = json.dumps( - [ - { - "identifier": declaration.identifier, - "description": declaration.description, - "variables": declaration.variables, - "content": self._contents[declaration.identifier], - "meta": declaration.meta.to_mapping(), - } - for declaration in self._declarations.values() - ] - ).encode() + ordered = sorted(self._declarations.values(), key=lambda d: d.identifier) + file_contents: bytes = json.dumps( + [ + { + "identifier": d.identifier, + "description": d.description, + "variables": d.variables, + "content": self._contents[d.identifier], + "meta": d.meta.to_mapping(), + } + for d in ordered + ], + sort_keys=True, + ).encode()src/draive/conversation/completion/default.py (1)
97-105: Normalize template-variable conversion and build the mapping once.Prefer value.to_str() when available; reuse the mapping. This was suggested earlier.
Apply this diff for the non‑streaming path:
- resolved_instructions: str = await TemplatesRepository.resolve_str( - instructions, - arguments={ - key: value if isinstance(value, str) else str(value) - for key, value in memory_recall.variables.items() - } - if memory_recall.variables - else None, - ) + args = ( + { + key: ( + value + if isinstance(value, str) + else (value.to_str() if hasattr(value, "to_str") else str(value)) + ) + for key, value in memory_recall.variables.items() + } + if memory_recall.variables + else None + ) + resolved_instructions: str = await TemplatesRepository.resolve_str( + instructions, + arguments=args, + )And in the streaming path (after adopting the previous fix), ensure you pass the same args var (already included in that diff).
Also applies to: 150-158
src/draive/multimodal/templates/types.py (1)
228-236: Align TemplateDefining parameter order with repository usage.Keep (identifier, description, variables, content, meta) for clarity and consistency. Previously raised.
Apply this diff:
@runtime_checkable class TemplateDefining(Protocol): """Callable protocol that upserts template content and metadata.""" async def __call__( self, identifier: str, description: str | None, - content: str, variables: Mapping[str, str], + content: str, meta: Meta, **extra: Any, ) -> None: ...
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (48)
Makefile(1 hunks)docs/guides/ComprehensiveEvaluation.md(3 hunks)docs/guides/Postgres.md(3 hunks)docs/guides/Templates.md(1 hunks)mkdocs.yml(1 hunks)pyproject.toml(1 hunks)src/draive/__init__.py(2 hunks)src/draive/conversation/completion/default.py(7 hunks)src/draive/conversation/completion/state.py(5 hunks)src/draive/conversation/completion/types.py(4 hunks)src/draive/conversation/realtime/default.py(3 hunks)src/draive/conversation/realtime/state.py(3 hunks)src/draive/conversation/realtime/types.py(2 hunks)src/draive/generation/audio/default.py(1 hunks)src/draive/generation/audio/state.py(4 hunks)src/draive/generation/audio/types.py(2 hunks)src/draive/generation/image/default.py(1 hunks)src/draive/generation/image/state.py(4 hunks)src/draive/generation/image/types.py(2 hunks)src/draive/generation/model/default.py(3 hunks)src/draive/generation/model/state.py(4 hunks)src/draive/generation/model/types.py(2 hunks)src/draive/generation/text/default.py(1 hunks)src/draive/generation/text/state.py(4 hunks)src/draive/generation/text/types.py(2 hunks)src/draive/helpers/instruction_preparation.py(3 hunks)src/draive/helpers/instruction_refinement.py(5 hunks)src/draive/models/__init__.py(0 hunks)src/draive/models/generative.py(5 hunks)src/draive/models/instructions/__init__.py(0 hunks)src/draive/models/instructions/repository.py(0 hunks)src/draive/models/instructions/template.py(0 hunks)src/draive/models/instructions/types.py(0 hunks)src/draive/multimodal/__init__.py(2 hunks)src/draive/multimodal/templates/__init__.py(1 hunks)src/draive/multimodal/templates/repository.py(1 hunks)src/draive/multimodal/templates/types.py(1 hunks)src/draive/multimodal/templates/variables.py(1 hunks)src/draive/openai/images.py(3 hunks)src/draive/openai/responses.py(1 hunks)src/draive/postgres/__init__.py(2 hunks)src/draive/postgres/instructions.py(0 hunks)src/draive/postgres/memory.py(1 hunks)src/draive/postgres/templates.py(1 hunks)src/draive/stages/stage.py(15 hunks)tests/test_generative_merge.py(1 hunks)tests/test_multimodal_template_variables.py(1 hunks)tests/test_toolbox.py(1 hunks)
💤 Files with no reviewable changes (6)
- src/draive/models/instructions/repository.py
- src/draive/models/instructions/init.py
- src/draive/models/init.py
- src/draive/models/instructions/types.py
- src/draive/postgres/instructions.py
- src/draive/models/instructions/template.py
🧰 Additional context used
📓 Path-based instructions (13)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use Python 3.12+ features and syntax across the codebase
Format code exclusively with Ruff (make format); do not use other formatters
Skip module-level docstrings
Files:
src/draive/multimodal/templates/variables.pysrc/draive/multimodal/__init__.pysrc/draive/helpers/instruction_refinement.pysrc/draive/helpers/instruction_preparation.pysrc/draive/postgres/__init__.pytests/test_toolbox.pysrc/draive/generation/model/types.pysrc/draive/generation/audio/state.pysrc/draive/generation/audio/types.pysrc/draive/generation/audio/default.pysrc/draive/stages/stage.pysrc/draive/postgres/templates.pysrc/draive/generation/image/types.pysrc/draive/conversation/realtime/state.pysrc/draive/conversation/realtime/default.pysrc/draive/models/generative.pysrc/draive/generation/text/default.pysrc/draive/multimodal/templates/__init__.pysrc/draive/conversation/completion/types.pysrc/draive/postgres/memory.pysrc/draive/openai/images.pysrc/draive/generation/model/state.pysrc/draive/__init__.pytests/test_generative_merge.pysrc/draive/conversation/realtime/types.pysrc/draive/openai/responses.pysrc/draive/generation/image/default.pysrc/draive/generation/text/state.pysrc/draive/multimodal/templates/repository.pysrc/draive/conversation/completion/state.pysrc/draive/generation/text/types.pysrc/draive/conversation/completion/default.pytests/test_multimodal_template_variables.pysrc/draive/generation/image/state.pysrc/draive/multimodal/templates/types.pysrc/draive/generation/model/default.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly (from haiway import State, ctx)
Use ctx.scope(...) to bind scoped Disposables and active State; avoid global state
Route all logs through ctx.log_debug/info/warn/error; do not use print
Use latest, most strict typing syntax (Python 3.12+), with strict typing only for public APIs
Avoid loose Any except at explicit third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
Prefer Mapping/Sequence/Iterable in public types over dict/list/set
Use final where applicable; avoid inheritance and prefer composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Model immutable data/config and facades with haiway.State; provide ergonomic classmethods like .of(...)
Avoid in-place mutation; use State.updated(...) or functional builders to produce new instances
Access active state via haiway.ctx inside async scopes (ctx.scope(...))
Use @statemethod for public state methods that dispatch on the active instance
Log around generation calls, tool dispatch, and provider requests/responses without leaking secrets; prefer structured/concise messages
Add metrics via ctx.record where applicable
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks
Use structured concurrency and valid coroutine usage; rely on haiway/asyncio; avoid custom threading
Construct multimodal content with MultimodalContent.of(...) and compose blocks explicitly
Use ResourceContent/ResourceReference for media/data blobs
Wrap custom types/data within ArtifactContent; use hidden when needed
Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings on internal helpers; keep names self-explanatory
Keep docstrings high-quality; mkdocstrings pulls them into API reference
Never log secrets or full request bodies containing keys/tokens
Files:
src/draive/multimodal/templates/variables.pysrc/draive/multimodal/__init__.pysrc/draive/helpers/instruction_refinement.pysrc/draive/helpers/instruction_preparation.pysrc/draive/postgres/__init__.pysrc/draive/generation/model/types.pysrc/draive/generation/audio/state.pysrc/draive/generation/audio/types.pysrc/draive/generation/audio/default.pysrc/draive/stages/stage.pysrc/draive/postgres/templates.pysrc/draive/generation/image/types.pysrc/draive/conversation/realtime/state.pysrc/draive/conversation/realtime/default.pysrc/draive/models/generative.pysrc/draive/generation/text/default.pysrc/draive/multimodal/templates/__init__.pysrc/draive/conversation/completion/types.pysrc/draive/postgres/memory.pysrc/draive/openai/images.pysrc/draive/generation/model/state.pysrc/draive/__init__.pysrc/draive/conversation/realtime/types.pysrc/draive/openai/responses.pysrc/draive/generation/image/default.pysrc/draive/generation/text/state.pysrc/draive/multimodal/templates/repository.pysrc/draive/conversation/completion/state.pysrc/draive/generation/text/types.pysrc/draive/conversation/completion/default.pysrc/draive/generation/image/state.pysrc/draive/multimodal/templates/types.pysrc/draive/generation/model/default.py
src/draive/multimodal/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Files:
src/draive/multimodal/templates/variables.pysrc/draive/multimodal/__init__.pysrc/draive/multimodal/templates/__init__.pysrc/draive/multimodal/templates/repository.pysrc/draive/multimodal/templates/types.py
docs/**/*
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*: When behavior/API changes, update relevant docs under docs/ and examples as applicable
When adding public APIs, update examples/guides and ensure cross-links render
Files:
docs/guides/ComprehensiveEvaluation.mddocs/guides/Postgres.mddocs/guides/Templates.md
src/draive/{httpx,mcp,postgres,opentelemetry}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Place integrations under draive/httpx, draive/mcp, draive/postgres, draive/opentelemetry
Files:
src/draive/postgres/__init__.pysrc/draive/postgres/templates.pysrc/draive/postgres/memory.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Do not perform real network I/O in unit tests; mock providers/HTTP
Keep tests fast and focused on changed code; start with unit tests around new types/functions/adapters
Use fixtures from tests/ or add focused ones; avoid heavy integration scaffolding
Use pytest-asyncio for coroutine tests (@pytest.mark.asyncio)
Prefer scoping with ctx.scope(...) in async tests and bind required State instances explicitly
Avoid real I/O and network in async tests; stub provider calls and HTTP
Files:
tests/test_toolbox.pytests/test_generative_merge.pytests/test_multimodal_template_variables.py
src/draive/stages/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement pipeline stage abstractions and helpers under draive/stages/
Files:
src/draive/stages/stage.py
mkdocs.yml
📄 CodeRabbit inference engine (AGENTS.md)
Register documentation navigation updates in mkdocs.yml (nav section) when adding/adjusting pages
Files:
mkdocs.yml
src/draive/conversation/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Implement higher-level chat/realtime conversations under draive/conversation/
Files:
src/draive/conversation/realtime/state.pysrc/draive/conversation/realtime/default.pysrc/draive/conversation/completion/types.pysrc/draive/conversation/realtime/types.pysrc/draive/conversation/completion/state.pysrc/draive/conversation/completion/default.py
src/draive/models/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Files:
src/draive/models/generative.py
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/**/*.py: Provider-specific feature modules live under their respective provider directories
Translate provider/SDK errors into typed exceptions; do not raise bare Exception and preserve context
Use environment variables for credentials and resolve via helper functions like getenv_str
Files:
src/draive/openai/images.pysrc/draive/openai/responses.py
src/draive/__init__.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/__init__.py: Centralize public exports in src/draive/init.py
Update src/draive/init.py exports when API surface changes
Files:
src/draive/__init__.py
{pyproject.toml,pyrightconfig.json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Ruff, Bandit, and Pyright (strict) via make lint
Files:
pyproject.toml
🧠 Learnings (6)
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in src/draive/__init__.py
Applied to files:
src/draive/multimodal/__init__.pysrc/draive/multimodal/templates/__init__.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/multimodal/**/*.py : Implement content types and helpers (MultimodalContent, TextContent, ArtifactContent) under draive/multimodal/
Applied to files:
src/draive/multimodal/__init__.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Import Haiway symbols directly (from haiway import State, ctx)
Applied to files:
src/draive/helpers/instruction_preparation.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/models/**/*.py : Keep core abstractions (GenerativeModel, tools, instructions) under draive/models/
Applied to files:
src/draive/stages/stage.pysrc/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/__init__.py : Update src/draive/__init__.py exports when API surface changes
Applied to files:
src/draive/__init__.py
📚 Learning: 2025-10-03T08:51:45.502Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-10-03T08:51:45.502Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings for public symbols with Parameters/Returns/Raises and rationale when non-obvious
Applied to files:
src/draive/multimodal/templates/repository.pysrc/draive/multimodal/templates/types.py
🧬 Code graph analysis (34)
src/draive/multimodal/templates/variables.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
of(56-84)of(162-194)
src/draive/multimodal/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(137-140)templates(143-146)templates(149-165)TemplatesRepository(61-429)src/draive/multimodal/templates/types.py (6)
Template(39-139)TemplateDeclaration(143-199)TemplateDefining(225-236)TemplateListing(203-209)TemplateLoading(213-221)TemplateMissing(18-35)
src/draive/helpers/instruction_refinement.py (4)
src/draive/multimodal/content.py (2)
MultimodalContent(25-592)MultimodalTag(599-700)src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-429)loading(442-448)loading(517-527)load(340-374)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/helpers/instruction_preparation.py (1)
src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(143-199)
src/draive/postgres/__init__.py (2)
src/draive/multimodal/templates/repository.py (3)
templates(137-140)templates(143-146)templates(149-165)src/draive/postgres/templates.py (1)
PostgresTemplatesRepository(28-173)
src/draive/generation/model/types.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/generation/audio/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/generation/audio/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/generation/audio/default.py (4)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-429)resolve_str(252-260)resolve_str(263-271)resolve_str(274-337)src/draive/models/generative.py (6)
GenerativeModel(45-515)completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)src/draive/stages/stage.py (1)
completion(288-372)
src/draive/stages/stage.py (2)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-429)resolve_str(252-260)resolve_str(263-271)resolve_str(274-337)
src/draive/postgres/templates.py (3)
src/draive/multimodal/templates/repository.py (11)
templates(137-140)templates(143-146)templates(149-165)TemplatesRepository(61-429)listing(436-440)listing(507-515)load(340-374)loading(442-448)loading(517-527)defining(450-465)defining(529-548)src/draive/multimodal/templates/types.py (1)
TemplateDeclaration(143-199)src/draive/parameters/model.py (2)
from_json(454-469)to_json(501-517)
src/draive/generation/image/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/conversation/realtime/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/conversation/realtime/default.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/generation/text/default.py (3)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-429)resolve_str(252-260)resolve_str(263-271)resolve_str(274-337)src/draive/models/generative.py (6)
GenerativeModel(45-515)loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
src/draive/multimodal/templates/__init__.py (2)
src/draive/multimodal/templates/repository.py (4)
templates(137-140)templates(143-146)templates(149-165)TemplatesRepository(61-429)src/draive/multimodal/templates/types.py (6)
Template(39-139)TemplateDeclaration(143-199)TemplateDefining(225-236)TemplateListing(203-209)TemplateLoading(213-221)TemplateMissing(18-35)
src/draive/conversation/completion/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/postgres/memory.py (1)
src/draive/models/types.py (3)
ModelInput(429-501)ModelMemoryRecall(719-766)ModelOutput(573-672)
src/draive/openai/images.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/generation/model/state.py (3)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/__init__.py (2)
src/draive/multimodal/templates/types.py (3)
Template(39-139)TemplateDeclaration(143-199)TemplateMissing(18-35)src/draive/multimodal/templates/repository.py (1)
TemplatesRepository(61-429)
tests/test_generative_merge.py (1)
src/draive/models/types.py (2)
ModelReasoning(518-562)ModelToolRequest(311-353)
src/draive/conversation/realtime/types.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/openai/responses.py (1)
src/draive/models/types.py (1)
ModelReasoning(518-562)
src/draive/generation/image/default.py (4)
src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-429)resolve_str(252-260)resolve_str(263-271)resolve_str(274-337)src/draive/openai/images.py (1)
generate_image(21-60)src/draive/models/generative.py (5)
completion(62-71)completion(74-83)completion(87-96)completion(99-108)completion(111-181)
src/draive/generation/text/state.py (2)
src/draive/models/tools/types.py (1)
Tool(76-104)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/multimodal/templates/repository.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (7)
Template(39-139)TemplateDeclaration(143-199)TemplateDefining(225-236)TemplateLoading(213-221)TemplateMissing(18-35)of(56-84)of(162-194)
src/draive/conversation/completion/state.py (2)
src/draive/models/tools/toolbox.py (1)
Toolbox(20-467)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/generation/text/types.py (2)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/conversation/completion/default.py (5)
src/draive/models/types.py (4)
ModelMemoryRecall(719-766)ModelOutput(573-672)ModelReasoning(518-562)ModelToolRequest(311-353)src/draive/multimodal/artifact.py (1)
ArtifactContent(11-96)src/draive/multimodal/templates/types.py (1)
Template(39-139)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-429)resolve_str(252-260)resolve_str(263-271)resolve_str(274-337)src/draive/models/generative.py (6)
GenerativeModel(45-515)loop(185-194)loop(197-206)loop(210-219)loop(222-231)loop(234-306)
tests/test_multimodal_template_variables.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/variables.py (3)
parse_template_variables(14-21)resolve_multimodal_template(48-67)resolve_text_template(24-45)src/draive/multimodal/text.py (1)
TextContent(11-82)
src/draive/generation/image/state.py (1)
src/draive/multimodal/templates/types.py (1)
Template(39-139)
src/draive/multimodal/templates/types.py (2)
tests/test_toolbox.py (4)
meta(109-110)meta(310-311)description(97-98)description(298-299)src/draive/stages/stage.py (1)
with_meta(1390-1435)
src/draive/generation/model/default.py (3)
src/draive/multimodal/content.py (1)
MultimodalContent(25-592)src/draive/multimodal/templates/types.py (2)
Template(39-139)with_arguments(90-113)src/draive/multimodal/templates/repository.py (4)
TemplatesRepository(61-429)resolve_str(252-260)resolve_str(263-271)resolve_str(274-337)
🪛 LanguageTool
docs/guides/Templates.md
[style] ~104-~104: It’s more common nowadays to write this noun as one word.
Context: ...fining templates programmatically, pass variables={"user": "User name"} to document expected arguments. This...
(RECOMMENDED_COMPOUNDS)
🔇 Additional comments (42)
pyproject.toml (2)
8-8: Version bump is appropriate for the scope of changes.The bump to 0.90.0 correctly reflects the major refactor replacing the Instructions subsystem with Templates throughout the codebase.
71-100: Tool configuration is properly set up for enforcing code quality standards.Ruff (lines 71-84) and Pyright strict mode (lines 86-100) are configured to catch both style issues and type safety violations as intended by the coding guidelines.
Makefile (2)
10-10: Inconsistency between summary and code:.envinclude not removed.The AI-generated summary claims the
.envinclude was deleted, but Line 10 shows-include .envis still present and unchanged (no~marker). This is a discrepancy between the summary and the actual code state.
13-13: UV 0.9.4 is the current latest stable version and available for use.UV 0.9.4 was released on Oct 17, 2025 as the latest stable version. Key improvements in this release include CUDA 13.0 support, auto-detection for Intel GPU on Windows, implementation of RFC 9457 HTTP error contexts display, and a bug fix for token obfuscation in
uv auth tokenoutput. The patch-level bump from 0.9.0 to 0.9.4 carries minimal breaking change risk.However, verify that this version aligns with your project's CI/CD pipeline requirements and any specific GPU or authentication workflows you depend on.
src/draive/helpers/instruction_refinement.py (7)
13-20: LGTM: Imports correctly updated for Templates subsystem.The imports properly bring in the new Template types and repository while preserving ModelInstructions for the string content type.
27-41: LGTM: Function signature correctly updated.The signature properly accepts a
Templatereference with optional pre-loadedinstructions_content, allowing callers to avoid redundant loads while maintaining type safety.
135-158: LGTM: Elegant repository patching mechanism.The
patched_instructions_repositoryproperty correctly intercepts template loading to inject refined instructions while transparently delegating to the original repository for other templates. The implementation properly omits thedefiningparameter to use the default no-op, preventing modifications during evaluation.
422-423: LGTM: Correct context management.The use of
ctx.updated(...)correctly scopes the patched repository for evaluation, ensuring the refined instructions are used without affecting global state.
100-100: LGTM: Correct return type conversion.Properly converts the final
MultimodalContentresult to string viato_str(), matching theModelInstructionsreturn type.
68-73: LGTM: Logging follows best practices.All logging correctly uses
ctx.log_*methods with structured, informative messages. No secrets or sensitive data are logged.Also applies to: 99-99, 238-238, 242-242, 379-382, 420-421, 440-450, 561-562, 674-677
27-41: LGTM: Type annotations follow Python 3.12+ best practices.Type hints are precise, use modern union syntax (
|), and properly constrain generic parameters. The annotations provide clear contracts for the public API.Also applies to: 103-113, 135-135
docs/guides/ComprehensiveEvaluation.md (1)
3-5: LGTM!The formatting and wording improvements enhance clarity and readability without changing the technical content.
Also applies to: 9-10, 66-67
tests/test_toolbox.py (1)
14-14: LGTM! Import path updated correctly.The import consolidation aligns with the broader refactoring to standardize on importing from
draive.models.src/draive/openai/responses.py (1)
70-89: LGTM! Import path consolidation is correct.The addition of
ModelReasoningto thedraive.modelsimport block aligns with the API surface consolidation effort.src/draive/stages/stage.py (3)
39-39: LGTM! Template system imports added correctly.The new imports support the migration from raw instruction strings to the Template system.
Also applies to: 49-49
287-372: LGTM! Template system integration inStage.completionis correct.The parameter type
Template | ModelInstructionsallows both template references and raw strings. The resolution viaawait TemplatesRepository.resolve_str(instructions)at line 356 correctly handles both cases.
374-463: LGTM! Template system integration is consistent across all completion methods.All completion variants (
prompting_completion,loopback_completion,result_completion) correctly:
- Accept
Template | ModelInstructionsparameters- Resolve via
await TemplatesRepository.resolve_str()- Pass resolved strings to
GenerativeModel.loop()Also applies to: 465-553, 555-622
mkdocs.yml (1)
101-101: LGTM! Templates guide added to navigation.The new navigation entry correctly links to the Templates documentation.
tests/test_generative_merge.py (1)
1-1: Import consolidation is correct and complete.Both
ModelReasoningandModelToolRequestare properly re-exported fromdraive.modelsin the__init__.pyfile and included in the__all__tuple. The import path change is valid.src/draive/postgres/memory.py (1)
9-15: LGTM! All imported symbols are properly re-exported fromdraive.models.Verification confirms all five types (
ModelContextElement,ModelInput,ModelMemory,ModelMemoryRecall,ModelOutput) are correctly imported fromdraive.models.typesand listed in the module's__all__tuple. The import consolidation improves readability with no issues.src/draive/postgres/__init__.py (1)
12-12: LGTM! Clean migration from Instructions to Templates.The import and export updates correctly reflect the transition from
PostgresInstructionsRepositorytoPostgresTemplatesRepository, maintaining consistency with the broader Templates subsystem migration.Also applies to: 23-23
src/draive/multimodal/__init__.py (1)
8-16: LGTM! Template symbols properly exposed.The new imports and exports correctly expose the Templates subsystem through the multimodal package, aligning with the codebase's public API organization pattern.
Also applies to: 25-31
src/draive/generation/image/types.py (1)
3-4: LGTM! Protocol signature correctly updated.The
ImageGeneratingprotocol now acceptsTemplate | ModelInstructions, properly reflecting the migration from the legacyResolveableInstructionstype. The imports are correct and consistent with the Templates subsystem.Also applies to: 15-15
src/draive/multimodal/templates/__init__.py (1)
1-19: LGTM! Clean public API definition.The module properly establishes the public API surface for the Templates subsystem, re-exporting all necessary types and protocols from the implementation modules.
docs/guides/Templates.md (1)
1-122: LGTM! Comprehensive and accurate documentation.The Templates guide provides clear, well-structured documentation covering:
- Template basics and immutability
- Storage backends (volatile, file, Postgres, custom)
- Runtime resolution with
resolveandresolve_str- Template management and listing
- Migration path from
InstructionsRepositoryThe examples accurately reflect the implementation and the documentation will serve as a valuable reference for users transitioning to the Templates subsystem.
src/draive/generation/audio/types.py (1)
3-4: LGTM! Protocol signature correctly updated.The
AudioGeneratingprotocol now acceptsTemplate | ModelInstructions, consistent with the Templates migration across all generation types. Imports are correct.Also applies to: 15-15
src/draive/conversation/realtime/types.py (1)
12-13: LGTM! Protocol signature correctly updated.The
RealtimeConversationPreparingprotocol now acceptsTemplate | ModelInstructionsfor the instructions parameter, aligning with the Templates subsystem migration. The imports are correct and the change is consistent with other protocol updates across the codebase.Also applies to: 130-130
tests/test_multimodal_template_variables.py (3)
12-86: LGTM! Comprehensive edge-case coverage for variable parsing.The tests thoroughly validate
parse_template_variablesbehavior across various edge cases including:
- Unique variable deduplication
- Handling of malformed placeholders (unclosed, unmatched, empty names)
- Whitespace validation
- Adjacent placeholders
- Literal braces
88-127: LGTM! Thorough text template resolution tests.The tests correctly validate text template resolution including:
- Placeholder replacement
- Repeated placeholder handling
- Missing argument detection (raises
KeyError)- Ignoring unused arguments (correct behavior per implementation)
- Edge position handling
All calls correctly use keyword syntax (
arguments=...) per the function signature.
129-207: LGTM! Excellent multimodal template resolution coverage.The tests comprehensively validate multimodal template behavior:
- Concatenation of mixed string and
TextContentparts- Missing argument detection
- Unused argument handling
- Nested content flattening
- Metadata boundary preservation (crucial for multimodal correctness)
- Empty template handling
The metadata preservation test (lines 180-201) is particularly valuable for ensuring metadata boundaries are maintained during template resolution.
src/draive/generation/model/state.py (1)
23-30: LGTM — instruction union and overloads align with the new Templates API.
Types and conversions (MultimodalContent.of/Toolbox.of) look consistent.Also applies to: 38-45, 53-60
src/draive/generation/model/types.py (1)
29-36: Protocol signature update looks correct.
Matches the refactor and downstream usage.src/draive/generation/audio/default.py (1)
19-21: LGTM — type union for instructions matches the new API.
[supporting note only]src/draive/generation/text/types.py (1)
15-20: LGTM — protocol now matchesTemplate | ModelInstructions.src/draive/generation/image/default.py (1)
19-21: LGTM — instruction union change is consistent.src/draive/openai/images.py (1)
24-28: LGTM — signature updated to acceptTemplate | ModelInstructions.src/draive/conversation/completion/types.py (3)
26-33: LGTM — overload typing updated correctly.
38-45: LGTM — streaming overload matches non-streaming update.
49-55: LGTM — Protocol signature consistent with overloads.src/draive/conversation/realtime/default.py (1)
39-44: Remove the entire review comment—the concern is based on an incorrect assumption.The
resolve_strfunction acceptstemplate: Template | str, and the parameterinstructions: Template | ModelInstructionsexpands toTemplate | strbecauseModelInstructions = str. The types match exactly, so there is no type contract violation. The code is type-safe and correct as-is.Likely an incorrect or invalid review comment.
src/draive/__init__.py (2)
178-182: Top-level re-exports for Template family look good.Consistent with the new Templates subsystem; import surface is clear.
350-354: all updated to include Template, TemplateDeclaration, TemplateMissing, TemplatesRepository.Public API centralized as per guidelines; no duplicate entries observed.
| resolved_instructions = await TemplatesRepository.resolve_str( | ||
| instructions.with_arguments( | ||
| model_schema=generated.json_schema(indent=2), | ||
| ) | ||
| ) |
There was a problem hiding this comment.
Forward **extra to all template resolution calls.
TemplatesRepository.resolve_str accepts **extra to allow backends (e.g., PostgreSQL, custom adapters) to receive contextual parameters such as revision hints, cache controls, or tenant identifiers. All three resolution paths ("full", "simplified", "skip") should forward **extra to enable backend context propagation.
Apply this diff:
else:
resolved_instructions = await TemplatesRepository.resolve_str(
instructions.with_arguments(
model_schema=generated.json_schema(indent=2),
- )
+ ),
+ **extra,
) else:
resolved_instructions = await TemplatesRepository.resolve_str(
instructions.with_arguments(
model_schema=generated.simplified_schema(indent=2),
- )
+ ),
+ **extra,
) case "skip": # instruction is not modified
- resolved_instructions = await TemplatesRepository.resolve_str(instructions)
+ resolved_instructions = await TemplatesRepository.resolve_str(instructions, **extra)Also applies to: 55-59, 62-62
🤖 Prompt for AI Agents
In src/draive/generation/model/default.py around lines 42-46 (also apply same
change at 55-59 and line 62), the TemplatesRepository.resolve_str calls need to
forward the **extra keyword args so backend adapters receive contextual
parameters; update each resolve_str invocation to pass **extra (e.g.,
TemplatesRepository.resolve_str(..., **extra)) and ensure the surrounding
function signature/stack provides an `extra` mapping to be forwarded unchanged
to these calls.
a9ef300 to
de698f2
Compare
de698f2 to
410b480
Compare
No description provided.