-
Notifications
You must be signed in to change notification settings - Fork 12
Rework MediaContent #395
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework MediaContent #395
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,16 +5,45 @@ Rules for coding agents to contribute correctly and safely. | |||||||||||||
| ## Development Toolchain | ||||||||||||||
|
|
||||||||||||||
| - Python: 3.12 | ||||||||||||||
| - Virtualenv: managed by uv, available at `./.venv` | ||||||||||||||
| - Formatting: Ruff formatter (`make format`). No other formatter | ||||||||||||||
| - Virtualenv: managed by uv, available at `./.venv`, assume already set up and working within venv | ||||||||||||||
| - Formatting: Ruff formatter (`make format`), no other formatter | ||||||||||||||
| - Linters/Type-checkers: Ruff, Bandit, Pyright (strict). Run via `make lint` | ||||||||||||||
| - Tests: `make test` or targeted `pytest tests/test_...::test_...` | ||||||||||||||
|
|
||||||||||||||
| ## Framework Foundation (Haiway) | ||||||||||||||
|
|
||||||||||||||
| - Draive is built on top of Haiway (state, context, observability, config). See: https://github.com/miquido/haiway | ||||||||||||||
| - Import symbols from `haiway` directly: `from haiway import State, ctx` | ||||||||||||||
| - Use context scoping (`ctx.scope(...)`) to bind active `State` instances and avoid global state | ||||||||||||||
| - All logs go through `ctx.log_*`; do not use `print`. | ||||||||||||||
|
|
||||||||||||||
| ## Project Layout | ||||||||||||||
|
|
||||||||||||||
| Top-level code lives under `src/draive/`, key packages and what they contain: | ||||||||||||||
|
|
||||||||||||||
| - `draive/models/` — core model abstractions: `GenerativeModel`, tools (`models/tools`), instructions handling | ||||||||||||||
| - `draive/generation/` — typed generation facades for text, image, audio, and model wiring (`state.py`, `types.py`, `default.py`) | ||||||||||||||
| - `draive/conversation/` — higher-level chat/realtime conversations (completion and realtime sessions) | ||||||||||||||
| - `draive/multimodal/` — content types and helpers: `MultimodalContent`, `TextContent`, `ArtifactContent` | ||||||||||||||
| - `draive/resources/` — resource references and blobs: `ResourceContent`, `ResourceReference`, repository interfaces | ||||||||||||||
| - `draive/parameters/` — strongly-typed parameter schemas and validation helpers | ||||||||||||||
| - `draive/embedding/` — vector operations, similarity, indexing, and typed embedding states | ||||||||||||||
| - `draive/guardrails/` — moderation, privacy, quality verification states and types | ||||||||||||||
| - `draive/stages/` — pipeline stages abstractions and helpers | ||||||||||||||
| - `draive/utils/` — utilities (e.g., `Memory`, `VectorIndex`) | ||||||||||||||
| - Provider adapters — unified shape per provider: | ||||||||||||||
| - `draive/openai/`, `draive/anthropic/`, `draive/mistral/`, `draive/gemini/`, `draive/vllm/`, `draive/ollama/`, `draive/bedrock/`, `draive/cohere/` | ||||||||||||||
| - Each has `config.py`, `client.py`, `api.py`, and feature-specific modules. | ||||||||||||||
| - Integrations: `draive/httpx/`, `draive/mcp/`, `draive/opentelemetry/` (opt-in extras) | ||||||||||||||
|
|
||||||||||||||
| Public exports are centralized in `src/draive/__init__.py`. | ||||||||||||||
|
|
||||||||||||||
| ## Style & Patterns | ||||||||||||||
|
|
||||||||||||||
| ### Typing & Immutability | ||||||||||||||
|
|
||||||||||||||
| - Strict typing only: no untyped public APIs, no loose `Any` unless required by third-party boundaries | ||||||||||||||
| - Prefer explicit attribute access with static types. Avoid dynamic `getattr` except at narrow boundaries. | ||||||||||||||
| - Prefer abstract immutable protocols: `Mapping`, `Sequence`, `Iterable` over `dict`/`list`/`set` in public types | ||||||||||||||
| - Use `final` where applicable; avoid complex inheritance, prefer type composition | ||||||||||||||
| - Use precise unions (`|`) and narrow with `match`/`isinstance`, avoid `cast` unless provably safe and localized | ||||||||||||||
|
|
@@ -26,6 +55,50 @@ Rules for coding agents to contribute correctly and safely. | |||||||||||||
| - Access active state through `haiway.ctx` inside async scopes (`ctx.scope(...)`). | ||||||||||||||
| - Public state methods that dispatch on the active instance should use `@statemethod` (see `GenerativeModel`). | ||||||||||||||
|
|
||||||||||||||
| #### Examples: | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Remove trailing colon in heading. Fix MD026. -#### Examples:
+#### Examples📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.17.2)58-58: Trailing punctuation in heading (MD026, no-trailing-punctuation) 🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| State with instantiation helper: | ||||||||||||||
| ```python | ||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
| from typing import Self | ||||||||||||||
| from haiway import State, statemethod, Meta, MetaValues | ||||||||||||||
|
|
||||||||||||||
| class Counter(State): | ||||||||||||||
| @classmethod | ||||||||||||||
| def of( | ||||||||||||||
| cls, | ||||||||||||||
| *, | ||||||||||||||
| start: int = 0, | ||||||||||||||
| meta: Meta | MetaValues | None = None, | ||||||||||||||
| ) -> Self: | ||||||||||||||
| return cls( | ||||||||||||||
| value=start, | ||||||||||||||
| meta=Meta.of(meta), | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| value: int | ||||||||||||||
| meta: Meta | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| State with statemethod helper: | ||||||||||||||
| ```python | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Add blank lines around fenced code block. Fix MD031 (before/after the fence). -State with statemethod helper:
-```python
+State with statemethod helper:
+
+```python
...
-```
+```
+🧰 Tools🪛 markdownlint-cli2 (0.17.2)83-83: Fenced code blocks should be surrounded by blank lines (MD031, blanks-around-fences) 🤖 Prompt for AI Agents |
||||||||||||||
| from typing import Self, Protocol | ||||||||||||||
| from haiway import State, statemethod | ||||||||||||||
|
|
||||||||||||||
| class Printing(Protocol): | ||||||||||||||
| async def __call__(self, text: str) -> None: ... | ||||||||||||||
|
|
||||||||||||||
| class Printer(State): | ||||||||||||||
| @statemethod | ||||||||||||||
| async def print( | ||||||||||||||
| self, | ||||||||||||||
| *, | ||||||||||||||
| value: str | int | float, | ||||||||||||||
| ) -> None: | ||||||||||||||
| await self.printing(str(value)) | ||||||||||||||
|
|
||||||||||||||
| printing: Printing | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### Observability & Logging | ||||||||||||||
|
|
||||||||||||||
| - Use `ctx.log_debug/info/warn/error` for logs; do not use `print` | ||||||||||||||
|
|
@@ -36,16 +109,19 @@ Rules for coding agents to contribute correctly and safely. | |||||||||||||
| ### Concurrency & Async | ||||||||||||||
|
|
||||||||||||||
| - All I/O is async, keep boundaries async and use `ctx.spawn` for detached tasks | ||||||||||||||
| - Rely on asyncio package and coroutines, avoid custom threading | ||||||||||||||
| - Ensure structured concurrency concepts and valid coroutine usage | ||||||||||||||
| - Rely on haiway and asyncio packages with coroutines, avoid custom threading | ||||||||||||||
|
|
||||||||||||||
| ### Exceptions & Error Translation | ||||||||||||||
|
|
||||||||||||||
| - Translate provider/SDK errors into appropriate typed exceptions | ||||||||||||||
| - Don’t raise bare `Exception`, preserve provider/model identifiers in exception construction | ||||||||||||||
| - Don’t raise bare `Exception`, preserve contextual information in exception construction | ||||||||||||||
|
|
||||||||||||||
| ### Multimodal | ||||||||||||||
|
|
||||||||||||||
| - Build content with `MultimodalContent.of(...)` and prefer composing content blocks explicitly. | ||||||||||||||
| - Build content with `MultimodalContent.of(...)` and prefer composing content blocks explicitly | ||||||||||||||
| - Use ResourceContent/Reference for media and data blobs | ||||||||||||||
| - Wrap custom types and data within ArtifactContent, use hidden when needed | ||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+122
to
125
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Clarify naming: ResourceReference Spell out ResourceReference to match API nouns elsewhere. -- Use ResourceContent/Reference for media and data blobs
+- Use ResourceContent/ResourceReference for media and data blobs📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| ## Testing & CI | ||||||||||||||
|
|
||||||||||||||
|
|
@@ -54,15 +130,50 @@ Rules for coding agents to contribute correctly and safely. | |||||||||||||
| - Use fixtures from `tests/` or add focused ones; avoid heavy integration scaffolding | ||||||||||||||
| - Linting/type gates must be clean: `make format` then `make lint` | ||||||||||||||
|
|
||||||||||||||
| ### Async tests | ||||||||||||||
|
|
||||||||||||||
| - Use `pytest-asyncio` for coroutine tests (`@pytest.mark.asyncio`). | ||||||||||||||
| - Prefer scoping with `ctx.scope(...)` and bind required `State` instances explicitly. | ||||||||||||||
| - Avoid real I/O and network; stub provider calls and HTTP. | ||||||||||||||
|
|
||||||||||||||
| #### Examples | ||||||||||||||
|
|
||||||||||||||
| ```python | ||||||||||||||
| import pytest | ||||||||||||||
| from draive import State, ctx | ||||||||||||||
|
|
||||||||||||||
| class Example(State): | ||||||||||||||
| name: str | ||||||||||||||
|
|
||||||||||||||
| @pytest.mark.asyncio | ||||||||||||||
| async def test_greeter_returns_greeting() -> None: | ||||||||||||||
| async with ctx.scope(Example(name="Ada")): | ||||||||||||||
| example: Example = ctx.state(Example) | ||||||||||||||
| assert example.name == "Ada" | ||||||||||||||
| ``` | ||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
|
|
||||||||||||||
| ### Self verification | ||||||||||||||
|
|
||||||||||||||
| - Ensure type checking soundness as a part of the workflow | ||||||||||||||
| - Do not mute or ignore errors, double check correctness and seek for solutions | ||||||||||||||
| - Verify code correctness with unit tests or by running ad-hoc scripts | ||||||||||||||
| - Ask for additional guidance and confirmation when uncertain or about to modify additional elements | ||||||||||||||
|
|
||||||||||||||
| ## Documentation | ||||||||||||||
|
|
||||||||||||||
| - Public symbols: add NumPy-style docstrings. Include Parameters/Returns/Raises sections and rationale when not obvious | ||||||||||||||
| - Internal helpers: avoid docstrings, keep names self-explanatory | ||||||||||||||
| - If behavior/API changes, update relevant docs under `docs/` and examples if applicable. | ||||||||||||||
| - If behavior/API changes, update relevant docs under `docs/` and examples if applicable | ||||||||||||||
| - Skip module docstrings | ||||||||||||||
|
|
||||||||||||||
| ## Public API & Deprecations | ||||||||||||||
| ### Docs (MkDocs) | ||||||||||||||
|
|
||||||||||||||
| - Export new public types/functions via `src/draive/__init__.py` and relevant package `__init__.py`. | ||||||||||||||
| - Site is built with MkDocs + Material and `mkdocstrings` for API docs. | ||||||||||||||
| - Author pages under `docs/` and register navigation in `mkdocs.yml` (`nav:` section). | ||||||||||||||
| - Preview locally: `make docs-server` (serves at http://127.0.0.1:8000). | ||||||||||||||
| - Build static site: `make docs` (outputs to `site/`). | ||||||||||||||
| - Keep docstrings high‑quality; `mkdocstrings` pulls them into reference pages. | ||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
| - When adding public APIs, update examples/guides as needed and ensure cross‑links render. | ||||||||||||||
|
|
||||||||||||||
| ## Security & Secrets | ||||||||||||||
|
|
||||||||||||||
|
|
@@ -77,11 +188,31 @@ Rules for coding agents to contribute correctly and safely. | |||||||||||||
| - Types: strict, no ignores, no loosening of typing | ||||||||||||||
| - API surface: update `__init__.py` exports and docs if needed | ||||||||||||||
|
|
||||||||||||||
| ## Extras | ||||||||||||||
| ## Code Search (ast-grep) | ||||||||||||||
|
|
||||||||||||||
| Use ast-grep for precise, structural search and refactors. Prefer `rg` for simple text matches. | ||||||||||||||
|
|
||||||||||||||
| - Invocation: `sg run --lang python --pattern "<PATTERN>" [FLAGS]` | ||||||||||||||
| - Useful patterns for this repo: | ||||||||||||||
| - `ctx.scope($X)` — find context scopes | ||||||||||||||
| - `@statemethod` — find state-dispatched classmethods | ||||||||||||||
| - `class $NAME(State)` — locate `haiway.State` subclasses | ||||||||||||||
| - `MultimodalContent.of($X)` — multimodal composition sites | ||||||||||||||
| - `$FUNC(meta=$META)` — functions receiving `meta` | ||||||||||||||
| - Common flags: | ||||||||||||||
| - `--json` — machine-readable results | ||||||||||||||
| - `--selector field_declaration` — restrict matches (e.g., type fields) | ||||||||||||||
| - `--rewrite "<REWRITE>"` — propose changes; always review diffs first | ||||||||||||||
|
|
||||||||||||||
| ### Examples: | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Remove trailing colon in heading. Fix MD026. -### Examples:
+### Examples📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.17.2)207-207: Trailing punctuation in heading (MD026, no-trailing-punctuation) 🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| # Where do we open context scopes? | ||||||||||||||
| sg run --lang python --pattern "ctx.scope($X)" src | ||||||||||||||
|
|
||||||||||||||
| ### Code Search (ast-grep) | ||||||||||||||
| # Find all State types | ||||||||||||||
| sg run --lang python --pattern "class $NAME(State)" src | ||||||||||||||
|
|
||||||||||||||
| - Use for precise AST queries and code search; prefer `rg` for simple text search | ||||||||||||||
| - Command: `sg run --lang python --pattern "<PATTERN>"` | ||||||||||||||
| - Patterns: `Meta.of($VAR)`, `meta: Meta`, `$FUNC(meta=$META)`, `class $NAME(Meta)` | ||||||||||||||
| - Flags: `--selector field_declaration`, `--json`, `--rewrite <FIX>` (review diffs) | ||||||||||||||
| # Find multimodal builders | ||||||||||||||
| sg run --lang python --pattern "MultimodalContent.of($X)" src | ||||||||||||||
| ``` | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,7 @@ TESTS_PATH := tests | |
| -include .env | ||
|
|
||
| ifndef UV_VERSION | ||
| UV_VERSION := 0.8.14 | ||
| UV_VERSION := 0.8.17 | ||
| endif | ||
|
|
||
| .PHONY: uv_check venv sync update format lint test docs docs-server release | ||
|
|
@@ -22,7 +22,7 @@ uv_check: | |
| # Install if not present | ||
| @if ! command -v uv > /dev/null; then \ | ||
| echo '...installing uv...'; \ | ||
| curl -fLsS https://astral.sh/uv/install.sh | sh -s -- --version $(UV_VERSION); \ | ||
| curl -fLsS https://astral.sh/uv/install.sh | sh; \ | ||
| if [ $$? -ne 0 ]; then \ | ||
|
Comment on lines
+25
to
26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Installer no longer pins UV_VERSION — breaks reproducibility You compare against UV_VERSION but install “latest” (no --version), which may overshoot the desired version and diverge across machines/CI. Pin install/update to UV_VERSION: - curl -fLsS https://astral.sh/uv/install.sh | sh; \
+ curl -fLsS https://astral.sh/uv/install.sh | sh -s -- --version $(UV_VERSION); \
...
- curl -fLsS https://astral.sh/uv/install.sh | sh; \
+ curl -fLsS https://astral.sh/uv/install.sh | sh -s -- --version $(UV_VERSION); \Also applies to: 37-38 🤖 Prompt for AI Agents |
||
| echo "...installing uv failed!"; \ | ||
| exit 1; \ | ||
|
|
@@ -34,7 +34,7 @@ uv_check: | |
| CURRENT_VERSION=$$(uv --version | head -n1 | cut -d" " -f2); \ | ||
| if [ "$$(printf "%s\n%s" "$(UV_VERSION)" "$$CURRENT_VERSION" | sort -V | head -n1)" != "$(UV_VERSION)" ]; then \ | ||
| echo '...updating uv...'; \ | ||
| curl -fLsS https://astral.sh/uv/install.sh | sh -s -- --version $(UV_VERSION); \ | ||
| curl -fLsS https://astral.sh/uv/install.sh | sh; \ | ||
| if [ $$? -ne 0 ]; then \ | ||
| echo "...updating uv failed!"; \ | ||
| exit 1; \ | ||
|
|
@@ -62,7 +62,7 @@ sync: uv_check | |
| @echo '...finished!' | ||
|
|
||
| # Update and lock dependencies from pyproject.toml | ||
| update: | ||
| update: uv_check | ||
| @echo '# Updating dependencies...' | ||
| @uv sync --all-groups --all-extras --upgrade | ||
| @echo '...finished!' | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Replace bare URL with Markdown link.
Avoid MD034.
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
15-15: Bare URL used
(MD034, no-bare-urls)
🤖 Prompt for AI Agents