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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The

## [Unreleased]

### Added

- **Retrieval-provider capability: embeddings** (proposal 0059, retrieval-provider §3 / §4 + observability §5.5.8 / §8.4.5). A new capability alongside llm-provider and prompt-management. The `EmbeddingProvider` protocol (`embed(input, *, config)` over an arbitrary-length input list, returning one vector per input in input order) plus its `EmbeddingResponse` / `EmbeddingUsage` / `EmbeddingRuntimeConfig` types, and `OpenAIEmbeddingProvider` as the reference provider (`POST {base_url}/v1/embeddings`, index-keyed input-order mapping, `dimensions` / `input_type`, base_url override for any OpenAI-compatible backend). Provider calls dispatch typed `EmbeddingEvent` / `EmbeddingFailedEvent` (graph-engine §6), which the bundled observers render: the OTel observer emits an `openarmature.embedding.complete` span, and the Langfuse observer a dedicated Embedding observation. In v0.15.0 proposal 0059 rode as `not-yet` (only its cross-spec `disable_provider_payload` flag rename was adopted); the capability itself lands here. Conformance fixtures for the embed mapping and the embedding observability (074-083, 137) run in `test_observability` and the retrieval-provider suite.
- **Retrieval-provider capability: rerank** (proposal 0060, retrieval-provider §5 / §6 + observability §5.5.13 / §8.4.7, spec v0.70.0). The `RerankProvider` protocol (`rerank(query, documents, *, config)` returning results ranked by relevance) plus its `RerankResponse` / `RerankUsage` / `ScoredDocument` / `RerankRuntimeConfig` types, and `CohereRerankProvider` as the reference reranker (`POST {base_url}/v2/rerank`, response-only echo shape, `top_n`, `search_units` usage). Provider calls dispatch typed `RerankEvent` / `RerankFailedEvent`; the OTel observer emits an `openarmature.rerank.complete` span and the Langfuse observer a dedicated Retriever observation (`asType="retriever"`, via a new `retriever()` client surface, with `LangfuseUsage.search_units`). The rerank result's output surface (`RerankEvent.output_results` / `EmbeddingEvent.output_vectors`) follows proposal 0089's typed-event output-shape rule (scalar lineage; spec v0.84.0). Rode as `not-yet` in v0.15.0; lands here. Conformance fixtures 099-108, 138, 141, 142 run in `test_observability`, plus the rerank retrieval-provider fixtures.
- **Vendor §8 wire mappings for four providers** (proposals 0077 / 0078 / 0079 / 0090 / 0091, retrieval-provider §8). Concrete, live-tested wire mappings realizing the embed and rerank protocols against real vendor APIs: **TEI** (§8.1, spec v0.72.0) `TeiEmbeddingProvider` + `TeiRerankProvider` (bare-array `/embed`, cross-encoder `/rerank` with client-side chunk-and-stitch, `input_type` via `prompt_name` or a client-side prefix); **Jina** (§8.2, spec v0.73.0) `JinaEmbeddingProvider` + `JinaRerankProvider` (`input_type` realized as Jina's native `task` over a closed set, 429 to rate_limit, 422 to invalid_request); **OpenAI** (§8.3, spec v0.74.0) formalized over `OpenAIEmbeddingProvider` (base_url defaults to `https://api.openai.com`, `dimensions` to the wire, `input_type` as a client-side prefix that is a wire no-op on the symmetric OpenAI surface); **Cohere** (§8.4) `CohereRerankProvider` rerank (spec v0.85.0) and a from-scratch `CohereEmbeddingProvider` `/v2/embed` (spec v0.86.0, mandatory `input_type`, `dimensions` to `output_dimension`, base_url defaults to `https://api.cohere.com`). Introduces the shared wire-mapping primitives in `retrieval/_wire.py` (endpoint normalization, the client-side `input_type` prefix, the rerank document echo, batch chunking) and a general wire-capture conformance harness (request method / path / origin / body-key-set / headers assertions). The rerank document echo follows proposal 0097's §6 shape rule (string verbatim including `""`, `TextDoc` unwrap, a non-object scalar raises `provider_invalid_response`), and `RerankResponse.raw` / `EmbeddingResponse.raw` carry the provider body verbatim as a `dict | list` (proposal 0096). Each mapping is live-tested against its real endpoint.
- **Embedding batch chunking** (proposal 0092, retrieval-provider §8, spec v0.87.0). A general rule so `embed()` accepts an arbitrary-length input list against a capped wire: the mapping splits into consecutive `<= cap` slices preserving order, issues one request per slice with every non-input field identical, concatenates the per-chunk vectors in input order, combines usage all-or-nothing (sum when every chunk reports one, else `null`), and takes the response identity from the first chunk. The shared `chunk_and_stitch_embed` helper in `retrieval/_wire.py` realizes it mapping-agnostically; TEI `/embed` (its `max-client-batch-size`), Cohere `/v2/embed` (a fixed 96) and OpenAI `/v1/embeddings` (a fixed 2048) all chunk through it. Fixture 038 (TEI) plus the Cohere and OpenAI unit tests pin the over-cap behavior.
- **Nullable provider usage records** (proposal 0093, retrieval-provider §4 / §6 + observability §5.5.8 / §8.4.5, spec v0.88.0). `EmbeddingResponse.usage` and `RerankResponse.usage` are `record | null` (a usage record when the provider reports one, `null` when it does not), giving one uniform "no usage reported" model across both response types and the typed events. A mapping must not fabricate a record (no empty record, no zero, no client-side estimate); a reported zero is a real record carrying 0, an absent or malformed figure is `null`, and a corrupt-but-present figure logs a warning. The bundled observers emit the embedding usage conditionally (OTel `gen_ai.usage.input_tokens` and Langfuse `usageDetails.input` omitted when no record is reported). Conformance fixtures 139 / 140 (embedding no-usage) join 141 / 142 (rerank no-usage).

### Changed

- **Pinned spec advances v0.70.1 → v0.88.0** across the v0.16.0 cycle. The retrieval-provider capability proposals are implemented: v0.72.0 (0077, TEI wire), v0.73.0 (0078, Jina wire), v0.74.0 (0079, OpenAI-compatible embed wire), v0.84.0 (0089, typed-event output surface), v0.85.0 (0090, Cohere rerank wire), v0.86.0 (0091, Cohere embed wire), v0.87.0 (0092, embed batch chunking), and v0.88.0 (0093, nullable usage records), all recorded `implemented` in `conformance.toml`, alongside 0059 / 0060 (embedding + rerank capability, within the prior pin, flipped from `not-yet` to `implemented` this cycle). The cross-cutting engine / observability proposals in the same range mostly ride as `not-yet`, deferred to v0.17.0: v0.71.0 (0062, LLM completion streaming), v0.75.0 (0080), v0.77.0 / v0.78.0 (0082), v0.81.0 (0084), v0.82.0 (0087), and v0.83.0 (0088). Two differ: v0.76.0 (0081) is `textual-only` (a spec-text change with no python-observable behavior), and v0.80.0 (0085) is `partial`: its save-side fan-out-instance checkpoint keying shipped (the nested-fan-out concurrency fix in Fixed below), with the resume round-trip deferred. Interleaved patches carry clarifications or coverage for already-shipped behavior (v0.73.1, v0.74.1, v0.76.1, v0.79.0). Proposals 0096 (raw is `dict | list`) and 0097 (rerank document-echo shape) were adopted in code ahead of their pin; their conformance formalization rides the later pin bump. No further submodule pin bump ships in this release (0094 and 0099 ride v0.17.0).

### Fixed

- **OTel: an orphaned LLM span inside a fan-out instance now parents under the per-instance dispatch span** (observability §5.5). An LLM provider span whose calling node has no open span (for example a provider call originating from middleware or a wrapper) and which fires inside a fan-out instance now parents under the per-instance fan-out dispatch span, matching the Langfuse observer, instead of falling through to the subgraph or invocation span. This resolves a divergence between the two observers. The generalized nearest-open-ancestor fallback (nested instances at any depth, and the instance-vs-deeper-subgraph ordering) is pending a spec clause and fixture; this aligns the top-level instance case now.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ build-backend = "hatchling.build"

[project]
name = "openarmature"
version = "0.15.0"
version = "0.16.0"
description = "Workflow framework for LLM pipelines and tool-calling agents."
readme = "README.md"
requires-python = ">=3.12"
Expand Down
2 changes: 1 addition & 1 deletion src/openarmature/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OpenArmature — Agent documentation

*This is the agent guide bundled with the openarmature Python package, version 0.15.0 (spec v0.88.0). For the full docs site see [openarmature.ai](https://openarmature.ai). For the canonical spec text see [openarmature.org/capabilities](https://openarmature.org/capabilities/). For project-specific conventions for the code you're editing, see the host project's `AGENTS.md` or `CLAUDE.md`.*
*This is the agent guide bundled with the openarmature Python package, version 0.16.0 (spec v0.88.0). For the full docs site see [openarmature.ai](https://openarmature.ai). For the canonical spec text see [openarmature.org/capabilities](https://openarmature.org/capabilities/). For project-specific conventions for the code you're editing, see the host project's `AGENTS.md` or `CLAUDE.md`.*

## TL;DR

Expand Down
2 changes: 1 addition & 1 deletion src/openarmature/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
sessions opening the project find the bundled docs automatically.
"""

__version__ = "0.15.0"
__version__ = "0.16.0"
__spec_version__ = "0.88.0"
# Proposal 0052 (spec observability §5.1 / §8.4.1): canonical
# package-registry name for this implementation. Surfaces on every
Expand Down
2 changes: 1 addition & 1 deletion tests/test_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


def test_package_versions() -> None:
assert openarmature.__version__ == "0.15.0"
assert openarmature.__version__ == "0.16.0"
assert openarmature.__spec_version__ == "0.88.0"


Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading