From 392c74039b2ccbc75e19899335e17f58766c48b8 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Thu, 21 May 2026 13:20:54 +0300 Subject: [PATCH 1/4] bump pydantic-ai-slim to 1.100 and haiku.skills to 0.17 Migrate off two APIs slated for removal in pydantic-ai 2.0: - Agent(tool_retries=, output_retries=) -> Agent(retries={"tools": ..., "output": ...}) in the LLM-as-judge evaluator. - Evaluator.evaluation_name class attribute -> overriding get_default_evaluation_name() on the citation MRR / MAP evaluators. haiku.skills 0.17.0 already migrated its internal AGUIAdapter, MCPToolset and ProcessEventStream usage; no further changes needed on our side beyond the pin bumps. --- CHANGELOG.md | 1 + .../evaluations/evaluators/citation.py | 6 ++-- evaluations/evaluations/evaluators/judge.py | 3 +- evaluations/tests/test_citation_evaluators.py | 4 +-- haiku_rag_slim/pyproject.toml | 4 +-- uv.lock | 36 +++++++++---------- 6 files changed, 28 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df8b76f1..122329db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Changed +- Bump `haiku.skills>=0.17.0` and `pydantic-ai-slim>=1.100.0` (the last pre-2.0 release). Migrate off two APIs slated for removal in pydantic-ai 2.0: `Agent(tool_retries=, output_retries=)` → `Agent(retries={"tools": …, "output": …})` in the LLM-as-judge evaluator, and `Evaluator.evaluation_name` class attribute → overriding `get_default_evaluation_name()` on `CitationMRREvaluator` / `CitationMAPEvaluator`. - Documentation generator swapped from `mkdocs-material` to `zensical`. Drops `mkdocs` / `mkdocs-material` dev deps, replaces `mkdocs.yml` with `zensical.toml`, adds `overrides/main.html` (OG/Twitter share meta) and `docs/stylesheets/extra.css`. `build-docs` workflow now runs `uv run zensical build` and publishes via the GitHub Pages artifact actions instead of `mkdocs gh-deploy`. ### Fixed diff --git a/evaluations/evaluations/evaluators/citation.py b/evaluations/evaluations/evaluators/citation.py index 9f226704..b17a1b61 100644 --- a/evaluations/evaluations/evaluators/citation.py +++ b/evaluations/evaluations/evaluators/citation.py @@ -25,7 +25,8 @@ class CitationMRREvaluator(Evaluator): Use for single-document datasets, mirroring :class:`MRREvaluator`. """ - evaluation_name: str = "cited_mrr" + def get_default_evaluation_name(self) -> str: + return "cited_mrr" def evaluate(self, ctx: EvaluatorContext) -> float: relevant = _relevant_uris(ctx) @@ -43,7 +44,8 @@ class CitationMAPEvaluator(Evaluator): datasets, mirroring :class:`MAPEvaluator`. """ - evaluation_name: str = "cited_map" + def get_default_evaluation_name(self) -> str: + return "cited_map" def evaluate(self, ctx: EvaluatorContext) -> float: relevant = _relevant_uris(ctx) diff --git a/evaluations/evaluations/evaluators/judge.py b/evaluations/evaluations/evaluators/judge.py index 6c5e23c9..a7094212 100644 --- a/evaluations/evaluations/evaluators/judge.py +++ b/evaluations/evaluations/evaluators/judge.py @@ -51,8 +51,7 @@ class LLMJudge: model=model_obj, output_type=LLMJudgeResponseSchema, system_prompt=ANSWER_EQUIVALENCE_RUBRIC, - tool_retries=3, - output_retries=3, + retries={"tools": 3, "output": 3}, ) async def judge_answers( diff --git a/evaluations/tests/test_citation_evaluators.py b/evaluations/tests/test_citation_evaluators.py index 1cd88846..c049e7e7 100644 --- a/evaluations/tests/test_citation_evaluators.py +++ b/evaluations/tests/test_citation_evaluators.py @@ -45,7 +45,7 @@ class TestCitationMRREvaluator: assert self.evaluator.evaluate(ctx) == 0.0 def test_evaluation_name(self) -> None: - assert self.evaluator.evaluation_name == "cited_mrr" + assert self.evaluator.get_default_evaluation_name() == "cited_mrr" class TestCitationMAPEvaluator: @@ -79,4 +79,4 @@ class TestCitationMAPEvaluator: assert self.evaluator.evaluate(ctx) == 0.0 def test_evaluation_name(self) -> None: - assert self.evaluator.evaluation_name == "cited_map" + assert self.evaluator.get_default_evaluation_name() == "cited_map" diff --git a/haiku_rag_slim/pyproject.toml b/haiku_rag_slim/pyproject.toml index 11f8cd4b..545c1aaf 100644 --- a/haiku_rag_slim/pyproject.toml +++ b/haiku_rag_slim/pyproject.toml @@ -23,14 +23,14 @@ classifiers = [ dependencies = [ "docling-core>=2.75.0", - "haiku.skills>=0.16.0", + "haiku.skills>=0.17.0", "httpx>=0.28.1", "jinja2>=3.1.0", "jsonpatch>=1.33", "lancedb==0.30.2", "pathspec>=1.0.4", "pydantic>=2.12.5", - "pydantic-ai-slim[openai,fastmcp,logfire,ag-ui]>=1.96.0", + "pydantic-ai-slim[openai,fastmcp,logfire,ag-ui]>=1.100.0", "pydantic-monty>=0.0.17", "python-dotenv>=1.2.2", "pyyaml>=6.0.3", diff --git a/uv.lock b/uv.lock index 812dc184..9282c378 100644 --- a/uv.lock +++ b/uv.lock @@ -40,14 +40,14 @@ wheels = [ [[package]] name = "ag-ui-protocol" -version = "0.1.15" +version = "0.1.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/57/71/96c21ae7e2fb9b610c1a90d38bd2de8b6e5b2900a63001f3882f43e519af/ag_ui_protocol-0.1.15.tar.gz", hash = "sha256:5e23c1042c7d4e364d685e68d2fb74d37c16bc83c66d270102d8eaedce56ad82", size = 6269, upload-time = "2026-04-01T15:44:33.136Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/d7/5711eada86da9bd7684e58645653a1693ef20b66cc3efbb1deeafef80f8d/ag_ui_protocol-0.1.18.tar.gz", hash = "sha256:b37c672c3fd6bac12b316c39f45ad9db9f137bbb885489c79f268507029a22ff", size = 9937, upload-time = "2026-04-21T20:44:59.151Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/a0/a73398d30bb0f9ad70cd70426151a4a19527a7296e48a3a16a50e1d5db05/ag_ui_protocol-0.1.15-py3-none-any.whl", hash = "sha256:85cde077023ccbc37b5ce2ad953537883c262d210320f201fc2ec4e85408b06a", size = 8661, upload-time = "2026-04-01T15:44:32.079Z" }, + { url = "https://files.pythonhosted.org/packages/d8/74/913c9b8fc566c6da650aecbddf25a5d8186b54138df265eb9eb546f56141/ag_ui_protocol-0.1.18-py3-none-any.whl", hash = "sha256:d151c0f0a34160647f1571163f7185746f4326b15a56d1560de5082a7a0e7a12", size = 12607, upload-time = "2026-04-21T20:45:00.097Z" }, ] [[package]] @@ -1599,7 +1599,7 @@ requires-dist = [ { name = "cohere", marker = "extra == 'cohere'", specifier = ">=5.21.1" }, { name = "docling", marker = "extra == 'docling'", specifier = ">=2.93.0" }, { name = "docling-core", specifier = ">=2.75.0" }, - { name = "haiku-skills", specifier = ">=0.16.0" }, + { name = "haiku-skills", specifier = ">=0.17.0" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "jinja2", specifier = ">=3.1.0" }, { name = "jsonpatch", specifier = ">=1.33" }, @@ -1614,7 +1614,7 @@ requires-dist = [ { name = "pydantic-ai-slim", extras = ["google"], marker = "extra == 'google'" }, { name = "pydantic-ai-slim", extras = ["groq"], marker = "extra == 'groq'" }, { name = "pydantic-ai-slim", extras = ["mistral"], marker = "extra == 'mistral'" }, - { name = "pydantic-ai-slim", extras = ["openai", "fastmcp", "logfire", "ag-ui"], specifier = ">=1.96.0" }, + { name = "pydantic-ai-slim", extras = ["openai", "fastmcp", "logfire", "ag-ui"], specifier = ">=1.100.0" }, { name = "pydantic-ai-slim", extras = ["vertexai"], marker = "extra == 'vertexai'" }, { name = "pydantic-ai-slim", extras = ["voyageai"], marker = "extra == 'voyageai'" }, { name = "pydantic-monty", specifier = ">=0.0.17" }, @@ -1638,19 +1638,19 @@ provides-extras = ["docling", "s3", "voyageai", "mxbai", "cohere", "zeroentropy" [[package]] name = "haiku-skills" -version = "0.16.0" +version = "0.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ag-ui-protocol" }, { name = "jsonpatch" }, { name = "pydantic" }, - { name = "pydantic-ai-slim", extra = ["mcp", "openai"] }, + { name = "pydantic-ai-slim", extra = ["ag-ui", "mcp", "openai"] }, { name = "pyyaml" }, { name = "skills-ref" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8c/12/98ea5ee4ca14d4053019b4ec4b22e39af8ae1bc054aea107c87f5ecb025e/haiku_skills-0.16.0.tar.gz", hash = "sha256:e7bfa8141523912f3eb4469bf0b611408fa1e1e54707c9b475d0b3e04ea7ffbc", size = 256020, upload-time = "2026-04-28T08:44:23.347Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/e2/f96659f7fddbd6209934eb4b69c78b611f4a2890c8a76735c065d5b0aa12/haiku_skills-0.17.0.tar.gz", hash = "sha256:16cccdf5efa74085bd063271ae653d049bb5ea814d92a29c231343a8807cbaea", size = 187886, upload-time = "2026-05-21T09:38:51.411Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/ca/4cc0b026ee3e25d4b7f85267a210d1248988079fcac73649a09e9f9a5873/haiku_skills-0.16.0-py3-none-any.whl", hash = "sha256:50dec4e24594dceadc781242cafb20ced3b1fe743fdb7035a081756fbb402aa1", size = 32794, upload-time = "2026-04-28T08:44:21.855Z" }, + { url = "https://files.pythonhosted.org/packages/71/d2/6a2012bf23e870bfd73c1ef5dda308f408347bc60a81968ea0404477f34d/haiku_skills-0.17.0-py3-none-any.whl", hash = "sha256:4f8865e594d5c39bb1dcb3521eca2188f252a7fc1a7fbea0db6e3649d6185caf", size = 32972, upload-time = "2026-05-21T09:38:49.851Z" }, ] [[package]] @@ -3624,7 +3624,7 @@ email = [ [[package]] name = "pydantic-ai-slim" -version = "1.97.0" +version = "1.100.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "genai-prices" }, @@ -3635,9 +3635,9 @@ dependencies = [ { name = "pydantic-graph" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/b3/3cd6067bc6bc524a6a7374db49f954170c9c108e63462c881759ed404c14/pydantic_ai_slim-1.97.0.tar.gz", hash = "sha256:f7da3bc68cefa43819e744223bb024f7ff7921d99aefce791e00e33eae84597b", size = 716656, upload-time = "2026-05-15T22:28:41.919Z" } +sdist = { url = "https://files.pythonhosted.org/packages/68/db/3eb296369e3001f82d7552060c3811307809954b7c7ec30499f383d3c87a/pydantic_ai_slim-1.100.0.tar.gz", hash = "sha256:cc755c7970b2e041764b9d2f74d50cbad3cf7989b14cdbf62d356f25eb2a1222", size = 726289, upload-time = "2026-05-21T04:04:59.061Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/f1/fdd17bdd00c3562ebef7bf5dc04287679bfe7143ebb9bf75aa831f1a0bdf/pydantic_ai_slim-1.97.0-py3-none-any.whl", hash = "sha256:f4e086f6b2141f841aacfdc3a5825a3632bac463e2d49261aaad5789700e93ef", size = 890563, upload-time = "2026-05-15T22:28:32.509Z" }, + { url = "https://files.pythonhosted.org/packages/49/a6/164b070c59f7c69e81cb5fd38225da24c4587a8fe629af49c72709182ffc/pydantic_ai_slim-1.100.0-py3-none-any.whl", hash = "sha256:422a721b7a7157daff749a6eec9a4ba2e3e7efc28ae5a2bdfe468529eaf81aaf", size = 901788, upload-time = "2026-05-21T04:04:49.147Z" }, ] [package.optional-dependencies] @@ -3757,7 +3757,7 @@ wheels = [ [[package]] name = "pydantic-evals" -version = "1.97.0" +version = "1.100.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -3767,14 +3767,14 @@ dependencies = [ { name = "pyyaml" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ab/80/34c8b3a7623add32431978ef64774c22437a5752b7c19c6c8041c4933e50/pydantic_evals-1.97.0.tar.gz", hash = "sha256:6ecf3d32a4f18ac009bd8e0685497c45dcb15a226b9047e094cd2f18ca9db535", size = 77307, upload-time = "2026-05-15T22:28:43.377Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/c9/6d6299fa7e50dd51d7c03e7e8bcf32810f100f234cc6cf8ca35cedf01f0a/pydantic_evals-1.100.0.tar.gz", hash = "sha256:e536bf3b2d6351be797cdd1aab9797d034fbaf7a056873256cef06e1e80ac696", size = 78523, upload-time = "2026-05-21T04:05:00.621Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/07/ac/cd06b456a986ca59d7a98441a3caa67ac48aacbfa247014c134fc815de99/pydantic_evals-1.97.0-py3-none-any.whl", hash = "sha256:1781927b2e5610a15b37574c0222704a979ca6ae7d7db235dd70684b7d4a84f0", size = 92267, upload-time = "2026-05-15T22:28:34.084Z" }, + { url = "https://files.pythonhosted.org/packages/1f/8e/3b4161b016c676cab1d19f9d1b3672cb61e8f56315fb61bb3367123760d4/pydantic_evals-1.100.0-py3-none-any.whl", hash = "sha256:67f6e2467d5fc300d965118ef46b5cebb07e07227419ee64da9b381c28e34f47", size = 93526, upload-time = "2026-05-21T04:04:51.527Z" }, ] [[package]] name = "pydantic-graph" -version = "1.97.0" +version = "1.100.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -3782,9 +3782,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2b/03/a3f01a12155f16b5699e5b399df8ca88db1f5032264c52aff1cbefce3557/pydantic_graph-1.97.0.tar.gz", hash = "sha256:26dade3f9a3a090325f9bc52c72c6fe48470c8d18c746ffd577b7202a72c656b", size = 62551, upload-time = "2026-05-15T22:28:44.856Z" } +sdist = { url = "https://files.pythonhosted.org/packages/90/8b/eee672fa01eec3ea34e7d8962d54aa16d658ad0723466122a7ba2828caa1/pydantic_graph-1.100.0.tar.gz", hash = "sha256:7651fa6ccce9d88a35b1d2cfe79d5d1dbb2415457503009195014bf31f6075bd", size = 62559, upload-time = "2026-05-21T04:05:01.682Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/0b/317ffa52272ed3157733aaefa60e7a6337332dff08d9c5e3077042b2ca5b/pydantic_graph-1.97.0-py3-none-any.whl", hash = "sha256:db0c95e1686e0fd9843b558ff608fa90ed2cdc56d8b8a7249180216ad56ad764", size = 80091, upload-time = "2026-05-15T22:28:35.678Z" }, + { url = "https://files.pythonhosted.org/packages/bb/12/21d6a68743229553c8ba9ca19da73c2d7e18dc6f8fbfd56c8c12c5587cb6/pydantic_graph-1.100.0-py3-none-any.whl", hash = "sha256:ba0b0a70bfd320b58b7012614b857f4b12dbb95b233da7127a6ff973c03d24e7", size = 80101, upload-time = "2026-05-21T04:04:53.635Z" }, ] [[package]] From 80e3ae0280fc50c30b34e016fd0bc516bfe989f8 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Thu, 21 May 2026 13:45:40 +0300 Subject: [PATCH 2/4] clean up deprecation warnings: docling annotations + haiku.skills 0.17.1 --- CHANGELOG.md | 3 +- .../haiku/rag/store/models/document_item.py | 12 +++---- haiku_rag_slim/pyproject.toml | 2 +- tests/test_converters.py | 31 +++++++------------ uv.lock | 8 ++--- 5 files changed, 22 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 122329db..9a0bb5c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### Changed -- Bump `haiku.skills>=0.17.0` and `pydantic-ai-slim>=1.100.0` (the last pre-2.0 release). Migrate off two APIs slated for removal in pydantic-ai 2.0: `Agent(tool_retries=, output_retries=)` → `Agent(retries={"tools": …, "output": …})` in the LLM-as-judge evaluator, and `Evaluator.evaluation_name` class attribute → overriding `get_default_evaluation_name()` on `CitationMRREvaluator` / `CitationMAPEvaluator`. +- Bump `haiku.skills>=0.17.1` and `pydantic-ai-slim>=1.100.0` (the last pre-2.0 release). Migrate off two APIs slated for removal in pydantic-ai 2.0: `Agent(tool_retries=, output_retries=)` → `Agent(retries={"tools": …, "output": …})` in the LLM-as-judge evaluator, and `Evaluator.evaluation_name` class attribute → overriding `get_default_evaluation_name()` on `CitationMRREvaluator` / `CitationMAPEvaluator`. +- Drop the `item.annotations` fallback in `_picture_description_text`. Docling's `PictureItem` runs a `@model_validator(mode="after")` on load that migrates the deprecated `annotations` field into `meta.description`, so reading `meta.description.text` covers both legacy and current blobs. Tests in `test_converters.py` switched to `meta.description.text` for the same reason. - Documentation generator swapped from `mkdocs-material` to `zensical`. Drops `mkdocs` / `mkdocs-material` dev deps, replaces `mkdocs.yml` with `zensical.toml`, adds `overrides/main.html` (OG/Twitter share meta) and `docs/stylesheets/extra.css`. `build-docs` workflow now runs `uv run zensical build` and publishes via the GitHub Pages artifact actions instead of `mkdocs gh-deploy`. ### Fixed diff --git a/haiku_rag_slim/haiku/rag/store/models/document_item.py b/haiku_rag_slim/haiku/rag/store/models/document_item.py index 3daf3aed..f86080e7 100644 --- a/haiku_rag_slim/haiku/rag/store/models/document_item.py +++ b/haiku_rag_slim/haiku/rag/store/models/document_item.py @@ -25,19 +25,15 @@ class DocumentItem(BaseModel): def _picture_description_text(item: "PictureItem") -> str | None: """Return the VLM-generated description text for a PictureItem, if any. - Tries the modern ``meta.description`` location first (docling 2.91+) and - falls back to ``annotations`` entries that carry a ``text`` field - (PictureDescriptionData and similar). + Reads ``meta.description.text``. Pre-2.91 blobs that stored the + description under the deprecated ``annotations`` field are migrated to + ``meta`` by ``PictureItem``'s own ``@model_validator(mode="after")`` at + load time, so this single check covers both formats. """ if item.meta and item.meta.description: text = item.meta.description.text if text and text.strip(): return text - # Annotations is a tagged union; only some variants carry `text`. - for ann in item.annotations: - text = getattr(ann, "text", None) - if isinstance(text, str) and text.strip(): - return text return None diff --git a/haiku_rag_slim/pyproject.toml b/haiku_rag_slim/pyproject.toml index 545c1aaf..50c4600f 100644 --- a/haiku_rag_slim/pyproject.toml +++ b/haiku_rag_slim/pyproject.toml @@ -23,7 +23,7 @@ classifiers = [ dependencies = [ "docling-core>=2.75.0", - "haiku.skills>=0.17.0", + "haiku.skills>=0.17.1", "httpx>=0.28.1", "jinja2>=3.1.0", "jsonpatch>=1.33", diff --git a/tests/test_converters.py b/tests/test_converters.py index 67cc4ce7..6dda3bb4 100644 --- a/tests/test_converters.py +++ b/tests/test_converters.py @@ -829,19 +829,14 @@ class TestDoclingLocalConverter: # The document should have pictures with descriptions assert doc.pictures, "Document should have pictures" - # Check that at least one picture has a description annotation - from docling_core.types.doc.document import PictureDescriptionData - + # Check that at least one picture carries a VLM description. pictures_with_descriptions = [] for pic in doc.pictures: - for ann in pic.annotations: - if isinstance(ann, PictureDescriptionData): - pictures_with_descriptions.append(pic) - # Description should appear in markdown output - assert ann.text in markdown, ( - f"Picture description '{ann.text[:50]}...' should be in markdown" - ) - break + if pic.meta and pic.meta.description and pic.meta.description.text: + pictures_with_descriptions.append(pic) + assert pic.meta.description.text in markdown, ( + f"Picture description '{pic.meta.description.text[:50]}...' should be in markdown" + ) assert pictures_with_descriptions, ( "At least one picture should have a VLM description" @@ -1349,18 +1344,14 @@ class TestDoclingServeConverterIntegration: assert doc.pictures, "Document should have pictures" - from docling_core.types.doc.document import PictureDescriptionData - pictures_with_descriptions = [] markdown = doc.export_to_markdown() for pic in doc.pictures: - for ann in pic.annotations: - if isinstance(ann, PictureDescriptionData): - pictures_with_descriptions.append(pic) - assert ann.text in markdown, ( - f"Picture description '{ann.text[:50]}...' should be in markdown" - ) - break + if pic.meta and pic.meta.description and pic.meta.description.text: + pictures_with_descriptions.append(pic) + assert pic.meta.description.text in markdown, ( + f"Picture description '{pic.meta.description.text[:50]}...' should be in markdown" + ) assert pictures_with_descriptions, ( "At least one picture should have a VLM description" diff --git a/uv.lock b/uv.lock index 9282c378..d376f667 100644 --- a/uv.lock +++ b/uv.lock @@ -1599,7 +1599,7 @@ requires-dist = [ { name = "cohere", marker = "extra == 'cohere'", specifier = ">=5.21.1" }, { name = "docling", marker = "extra == 'docling'", specifier = ">=2.93.0" }, { name = "docling-core", specifier = ">=2.75.0" }, - { name = "haiku-skills", specifier = ">=0.17.0" }, + { name = "haiku-skills", specifier = ">=0.17.1" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "jinja2", specifier = ">=3.1.0" }, { name = "jsonpatch", specifier = ">=1.33" }, @@ -1638,7 +1638,7 @@ provides-extras = ["docling", "s3", "voyageai", "mxbai", "cohere", "zeroentropy" [[package]] name = "haiku-skills" -version = "0.17.0" +version = "0.17.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ag-ui-protocol" }, @@ -1648,9 +1648,9 @@ dependencies = [ { name = "pyyaml" }, { name = "skills-ref" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2f/e2/f96659f7fddbd6209934eb4b69c78b611f4a2890c8a76735c065d5b0aa12/haiku_skills-0.17.0.tar.gz", hash = "sha256:16cccdf5efa74085bd063271ae653d049bb5ea814d92a29c231343a8807cbaea", size = 187886, upload-time = "2026-05-21T09:38:51.411Z" } +sdist = { url = "https://files.pythonhosted.org/packages/01/90/7eb6c20aada4e861589ecc300bcf5c827335d803c4e225a79b0924dd9793/haiku_skills-0.17.1.tar.gz", hash = "sha256:062385ae67f61e37a9790721da50f7b38ed0b903e9a8efb2bd76b4b9fcf94651", size = 187965, upload-time = "2026-05-21T10:37:45.242Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/71/d2/6a2012bf23e870bfd73c1ef5dda308f408347bc60a81968ea0404477f34d/haiku_skills-0.17.0-py3-none-any.whl", hash = "sha256:4f8865e594d5c39bb1dcb3521eca2188f252a7fc1a7fbea0db6e3649d6185caf", size = 32972, upload-time = "2026-05-21T09:38:49.851Z" }, + { url = "https://files.pythonhosted.org/packages/c9/86/ff441d3c5fba2e66d29c135659d536dd47a5e920e4b351c9621a89599510/haiku_skills-0.17.1-py3-none-any.whl", hash = "sha256:7bdcafc5f184bb765eb9c86e0147d535272dc42c1dc8cef4ce1a4d1464376ff0", size = 32965, upload-time = "2026-05-21T10:37:44.192Z" }, ] [[package]] From 188d35023f1b0a52bdeb7b8fbe87348b2e80ff8f Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Thu, 21 May 2026 14:21:51 +0300 Subject: [PATCH 3/4] rotate chat TUI conversation id per launch / clear-chat --- CHANGELOG.md | 1 + haiku_rag_slim/haiku/rag/chat/app.py | 8 +++++++- tests/chat/test_chat_app.py | 4 +++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a0bb5c8..bd868b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Bump `haiku.skills>=0.17.1` and `pydantic-ai-slim>=1.100.0` (the last pre-2.0 release). Migrate off two APIs slated for removal in pydantic-ai 2.0: `Agent(tool_retries=, output_retries=)` → `Agent(retries={"tools": …, "output": …})` in the LLM-as-judge evaluator, and `Evaluator.evaluation_name` class attribute → overriding `get_default_evaluation_name()` on `CitationMRREvaluator` / `CitationMAPEvaluator`. - Drop the `item.annotations` fallback in `_picture_description_text`. Docling's `PictureItem` runs a `@model_validator(mode="after")` on load that migrates the deprecated `annotations` field into `meta.description`, so reading `meta.description.text` covers both legacy and current blobs. Tests in `test_converters.py` switched to `meta.description.text` for the same reason. +- Chat TUI now generates a stable per-launch `thread_id` (rotated on "Clear chat") instead of hardcoding `"tui"`. AGUIAdapter forwards it as the `gen_ai.conversation.id` OTel attribute, so multi-turn TUI sessions group into one Logfire conversation instead of collapsing every launch into a single bucket. - Documentation generator swapped from `mkdocs-material` to `zensical`. Drops `mkdocs` / `mkdocs-material` dev deps, replaces `mkdocs.yml` with `zensical.toml`, adds `overrides/main.html` (OG/Twitter share meta) and `docs/stylesheets/extra.css`. `build-docs` workflow now runs `uv run zensical build` and publishes via the GitHub Pages artifact actions instead of `mkdocs gh-deploy`. ### Fixed diff --git a/haiku_rag_slim/haiku/rag/chat/app.py b/haiku_rag_slim/haiku/rag/chat/app.py index ed4cd4a7..218f59f8 100644 --- a/haiku_rag_slim/haiku/rag/chat/app.py +++ b/haiku_rag_slim/haiku/rag/chat/app.py @@ -108,6 +108,10 @@ class ChatApp(App): self._is_processing = False self._current_worker: Worker[None] | None = None self._document_filter: list[str] = [] + # Stable per-launch id so multi-turn chats land in one Logfire + # conversation. AGUIAdapter reads run_input.thread_id and exports it + # as the `gen_ai.conversation.id` OTel attribute on every agent run. + self._conversation_id = str(uuid.uuid4()) def compose(self) -> "ComposeResult": """Compose the UI layout.""" @@ -207,7 +211,7 @@ class ChatApp(App): await chat_history.show_thinking() run_input = RunAgentInput( - thread_id="tui", + thread_id=self._conversation_id, run_id=str(uuid.uuid4()), messages=self._messages, state=self._state, @@ -375,6 +379,8 @@ class ChatApp(App): # Reset state if self._toolset: self._state = self._toolset.build_state_snapshot() + # Cleared chat starts a fresh Logfire conversation. + self._conversation_id = str(uuid.uuid4()) def action_focus_input(self) -> None: """Focus the input field, or cancel if processing.""" diff --git a/tests/chat/test_chat_app.py b/tests/chat/test_chat_app.py index 2853c566..e225cc54 100644 --- a/tests/chat/test_chat_app.py +++ b/tests/chat/test_chat_app.py @@ -219,7 +219,7 @@ async def test_chat_history_thinking_indicator(temp_db_path: Path): @pytest.mark.asyncio async def test_clear_chat_resets_state(temp_db_path: Path): - """Test that clearing chat resets state and messages.""" + """Test that clearing chat resets state, messages, and conversation id.""" from haiku.rag.chat.widgets.chat_history import ChatHistory app, mock_client = _make_app(temp_db_path) @@ -232,10 +232,12 @@ async def test_clear_chat_resets_state(temp_db_path: Path): await chat_history.add_message("assistant", "Hi there") assert len(chat_history.messages) == 2 + previous_conversation_id = app._conversation_id await app.action_clear_chat() await pilot.pause() assert len(chat_history.messages) == 0 + assert app._conversation_id != previous_conversation_id @pytest.mark.asyncio From e881ce285d57c43c4945a24bb1044398fc520bb9 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Thu, 21 May 2026 14:23:41 +0300 Subject: [PATCH 4/4] update orb benchmark --- docs/benchmarks.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/benchmarks.md b/docs/benchmarks.md index 16dab38e..8619f123 100644 --- a/docs/benchmarks.md +++ b/docs/benchmarks.md @@ -175,12 +175,9 @@ Two approaches are benchmarked separately: | Embedding Model | VLM | Skill model | QA accuracy | Mean `cited_map` | |------------------------|----------------------|------------------------------|-------------|------------------| -| `qwen3-embedding:4b` | Ollama / ministral-3 | `ollama:gpt-oss` | 0.94 | 0.86 | -| `qwen3-embedding:4b` | Ollama / ministral-3 | `vllm:Gemma-4-26B-A4B-NVFP4` | 0.90 | 0.89 | +| `qwen3-embedding:4b` | Ollama / ministral-3 | `vllm:Gemma-4-26B-A4B-NVFP4` | 0.88 | 0.89 | -*`ollama:gpt-oss` row measured on haiku.rag v0.44.0, on 2992 of 3044 completed cases.* -*`vllm:Gemma-4-26B-A4B-NVFP4` row measured on haiku.rag v0.47.0, with `mxbai-rerank-base-v2`, stopped at 674 of 3045 cases (cumulative means stable from case ~200).* -*Both judged by `ollama:qwen3.6` (current default).* +*Measured on haiku.rag v0.48.0, with `mxbai-rerank-base-v2`, on all 3045 cases. Judged by `vllm:Qwen3.6-35B-A3B-NVFP4`.* ## Inactive datasets