Merge pull request #315 from ggozad/fix/fix-tests-after-updates

Remove structured output support
This commit is contained in:
Yiorgis Gozadinos 2026-03-24 14:18:02 +02:00 committed by GitHub
commit 92b0408800
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 92 additions and 152 deletions

View file

@ -11,6 +11,7 @@
- **LLMJudge**: Custom evaluator now accepts `ModelConfig` instead of a model name string
- **Docling upgrade**: docling-core ≥2.70.2 (schema 1.10.0), docling ≥2.81.0. Adds field data model support for structured form/KV content, wide table chunking fixes, and rich table cell hang fix
- **pydantic-ai ≥1.70.0**: Bumped minimum version. Removed `structured_output_type` helper — all supported providers now handle native structured output, so agents pass result types directly
## [0.34.1] - 2026-03-16

View file

@ -6,7 +6,7 @@ requires-python = ">=3.12"
dependencies = [
"starlette>=0.50.0",
"uvicorn[standard]>=0.40.0",
"pydantic-ai-slim[ag-ui,anthropic,openai]>=1.46.0",
"pydantic-ai-slim[ag-ui,anthropic,openai]>=1.70.0",
"python-dotenv>=1.2.1",
"haiku.rag-slim>=0.34.1",
"logfire[pydantic-ai]>=3.17.0",

View file

@ -9,7 +9,7 @@ requires-python = ">=3.12"
dependencies = [
"haiku.rag-slim",
"pydantic-ai-slim[evals,logfire]>=1.66.0",
"pydantic-ai-slim[evals,logfire]>=1.70.0",
"datasets>=4.6.1",
"huggingface_hub>=0.20.0",
"typer>=0.21.0,<0.22.0",

View file

@ -13,7 +13,7 @@ from haiku.rag.config import Config
from haiku.rag.config.models import AppConfig, ModelConfig
from haiku.rag.store.models import SearchResult
from haiku.rag.tools.search import create_search_toolset
from haiku.rag.utils import get_model, structured_output_type
from haiku.rag.utils import get_model
@dataclass
@ -66,7 +66,7 @@ class QuestionAnswerAgent:
agent: Agent[_QARunDeps, RawSearchAnswer] = Agent( # ty: ignore[invalid-assignment]
model=model,
deps_type=_QARunDeps,
output_type=structured_output_type(RawSearchAnswer, model),
output_type=RawSearchAnswer,
instructions=system_prompt,
toolsets=[search_toolset],
retries=3,

View file

@ -19,7 +19,7 @@ from haiku.rag.agents.research.prompts import (
from haiku.rag.agents.research.state import ResearchDeps, ResearchState
from haiku.rag.config import Config
from haiku.rag.config.models import AppConfig
from haiku.rag.utils import build_prompt, get_model, structured_output_type
from haiku.rag.utils import build_prompt, get_model
def format_context_for_prompt(context: ResearchContext) -> str:
@ -68,7 +68,7 @@ async def _iterative_plan_logic(
model = get_model(model_config, config)
plan_agent: Agent[ResearchDependencies, IterativePlanResult] = Agent( # type: ignore[assignment]
model=model,
output_type=structured_output_type(IterativePlanResult, model),
output_type=IterativePlanResult,
instructions=effective_prompt,
retries=3,
deps_type=ResearchDependencies,
@ -118,7 +118,7 @@ async def _search_one_step_logic(
model = get_model(model_config, config)
agent: Agent[ResearchDependencies, RawSearchAnswer] = Agent( # type: ignore[assignment]
model=model,
output_type=structured_output_type(RawSearchAnswer, model),
output_type=RawSearchAnswer,
instructions=search_prompt,
retries=3,
deps_type=ResearchDependencies,
@ -220,7 +220,7 @@ def build_research_graph(
model = get_model(model_config, config)
agent: Agent[ResearchDependencies, ResearchReport] = Agent( # type: ignore[assignment]
model=model,
output_type=structured_output_type(ResearchReport, model),
output_type=ResearchReport,
instructions=synthesis_prompt,
retries=3,
deps_type=ResearchDependencies,

View file

@ -4,7 +4,7 @@ from haiku.rag.agents.rlm.dependencies import RLMDeps
from haiku.rag.agents.rlm.models import CodeExecution, RLMResult
from haiku.rag.agents.rlm.prompts import RLM_SYSTEM_PROMPT
from haiku.rag.config.models import AppConfig
from haiku.rag.utils import get_model, structured_output_type
from haiku.rag.utils import get_model
def create_rlm_agent(config: AppConfig) -> Agent[RLMDeps, RLMResult]:
@ -25,7 +25,7 @@ def create_rlm_agent(config: AppConfig) -> Agent[RLMDeps, RLMResult]:
agent: Agent[RLMDeps, RLMResult] = Agent( # type: ignore[invalid-assignment]
model,
deps_type=RLMDeps,
output_type=structured_output_type(RLMResult, model),
output_type=RLMResult,
instructions=RLM_SYSTEM_PROMPT,
retries=3,
)

View file

@ -318,20 +318,6 @@ def get_model(
return f"{provider}:{model}"
def structured_output_type(
result_type: type,
model: Any,
max_retries: int = 3,
) -> Any:
"""Return a NativeOutput or ToolOutput wrapper based on model capability."""
from pydantic_ai.models import Model
from pydantic_ai.output import NativeOutput, ToolOutput
if isinstance(model, Model) and model.profile.supports_json_schema_output:
return NativeOutput(result_type)
return ToolOutput(result_type, max_retries=max_retries)
def format_bytes(num_bytes: int) -> str:
"""Format bytes as human-readable string."""
size = float(num_bytes)

View file

@ -30,7 +30,7 @@ dependencies = [
"lancedb==0.29.2",
"pathspec>=1.0.4",
"pydantic>=2.12.5",
"pydantic-ai-slim[openai,fastmcp,logfire,ag-ui]>=1.66.0",
"pydantic-ai-slim[openai,fastmcp,logfire,ag-ui]>=1.70.0",
"pydantic-monty>=0.0.8",
"python-dotenv>=1.2.2",
"pyyaml>=6.0.3",

View file

@ -15,24 +15,11 @@ def vcr_cassette_dir():
class TestCreateRLMAgent:
def test_creates_agent_native_output_when_supported(self):
from pydantic_ai.output import NativeOutput
def test_creates_agent(self):
agent = create_rlm_agent(Config)
assert isinstance(agent, Agent)
assert agent.deps_type is RLMDeps
assert isinstance(agent.output_type, NativeOutput)
assert agent.output_type.outputs is RLMResult
def test_creates_agent_tool_output_when_not_supported(self):
from pydantic_ai.output import ToolOutput
config = AppConfig()
config.rlm.model.name = "qwen3"
agent = create_rlm_agent(config)
assert isinstance(agent, Agent)
assert isinstance(agent.output_type, ToolOutput)
assert agent.output_type.output is RLMResult
assert agent.output_type is RLMResult
def test_agent_has_execute_code_tool(self):
agent = create_rlm_agent(Config)

View file

@ -45,19 +45,17 @@ async def mcp_db(temp_db_path):
return temp_db_path
def _get_tool(mcp, name):
async def _get_tool(mcp, name):
"""Get a tool function from an MCP server by name."""
for tool in mcp._tool_manager._tools.values():
if tool.fn.__name__ == name:
return tool.fn
raise ValueError(f"Tool {name!r} not found in MCP server")
tool = await mcp.get_tool(name)
return tool.fn
class TestMCPReadTools:
@pytest.mark.asyncio
async def test_search_documents(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=True)
search = _get_tool(mcp, "search_documents")
search = await _get_tool(mcp, "search_documents")
results = await search(query="artificial intelligence")
assert len(results) > 0
@ -66,7 +64,7 @@ class TestMCPReadTools:
@pytest.mark.asyncio
async def test_search_documents_with_limit(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=True)
search = _get_tool(mcp, "search_documents")
search = await _get_tool(mcp, "search_documents")
results = await search(query="artificial intelligence", limit=1)
assert len(results) == 1
@ -74,10 +72,10 @@ class TestMCPReadTools:
@pytest.mark.asyncio
async def test_get_document(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=True)
get_doc = _get_tool(mcp, "get_document")
get_doc = await _get_tool(mcp, "get_document")
# First get the ID via list
list_docs = _get_tool(mcp, "list_documents")
list_docs = await _get_tool(mcp, "list_documents")
docs = await list_docs()
doc_id = docs[0].id
@ -89,9 +87,9 @@ class TestMCPReadTools:
@pytest.mark.asyncio
async def test_get_document_excludes_docling_fields(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=True)
get_doc = _get_tool(mcp, "get_document")
get_doc = await _get_tool(mcp, "get_document")
list_docs = _get_tool(mcp, "list_documents")
list_docs = await _get_tool(mcp, "list_documents")
docs = await list_docs()
doc_id = docs[0].id
@ -103,7 +101,7 @@ class TestMCPReadTools:
@pytest.mark.asyncio
async def test_get_document_not_found(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=True)
get_doc = _get_tool(mcp, "get_document")
get_doc = await _get_tool(mcp, "get_document")
result = await get_doc(document_id="nonexistent-id")
assert result is None
@ -111,7 +109,7 @@ class TestMCPReadTools:
@pytest.mark.asyncio
async def test_list_documents(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=True)
list_docs = _get_tool(mcp, "list_documents")
list_docs = await _get_tool(mcp, "list_documents")
results = await list_docs()
assert len(results) == 2
@ -120,7 +118,7 @@ class TestMCPReadTools:
@pytest.mark.asyncio
async def test_list_documents_with_limit(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=True)
list_docs = _get_tool(mcp, "list_documents")
list_docs = await _get_tool(mcp, "list_documents")
results = await list_docs(limit=1)
assert len(results) == 1
@ -128,7 +126,7 @@ class TestMCPReadTools:
@pytest.mark.asyncio
async def test_list_documents_with_filter(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=True)
list_docs = _get_tool(mcp, "list_documents")
list_docs = await _get_tool(mcp, "list_documents")
results = await list_docs(filter="title = 'AI Overview'")
assert len(results) == 1
@ -163,12 +161,12 @@ class TestMCPWriteTools:
async with HaikuRAG(temp_db_path, create=True):
pass
mcp = create_mcp_server(temp_db_path, read_only=False)
add_text = _get_tool(mcp, "add_document_from_text")
add_text = await _get_tool(mcp, "add_document_from_text")
doc_id = await add_text(content="Test content for MCP", title="MCP Test Doc")
assert doc_id is not None
get_doc = _get_tool(mcp, "get_document")
get_doc = await _get_tool(mcp, "get_document")
doc = await get_doc(document_id=doc_id)
assert doc.title == "MCP Test Doc"
assert doc.content == "Test content for MCP"
@ -176,8 +174,8 @@ class TestMCPWriteTools:
@pytest.mark.asyncio
async def test_delete_document(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=False)
list_docs = _get_tool(mcp, "list_documents")
delete_doc = _get_tool(mcp, "delete_document")
list_docs = await _get_tool(mcp, "list_documents")
delete_doc = await _get_tool(mcp, "delete_document")
docs = await list_docs()
assert len(docs) == 2
@ -191,7 +189,7 @@ class TestMCPWriteTools:
@pytest.mark.asyncio
async def test_delete_document_not_found(self, mcp_db):
mcp = create_mcp_server(mcp_db, read_only=False)
delete_doc = _get_tool(mcp, "delete_document")
delete_doc = await _get_tool(mcp, "delete_document")
result = await delete_doc(document_id="nonexistent-id")
assert result is False

View file

@ -139,38 +139,6 @@ Emoji test: 🚀 ✅ 📝"""
assert "🚀" in result_markdown
def test_structured_output_type_native():
from pydantic_ai.output import NativeOutput
from haiku.rag.utils import structured_output_type
model = get_model(ModelConfig(provider="openai", name="gpt-4o"))
result = structured_output_type(str, model)
assert isinstance(result, NativeOutput)
assert result.outputs is str
def test_structured_output_type_tool_fallback():
from pydantic_ai.output import ToolOutput
from haiku.rag.utils import structured_output_type
model = get_model(ModelConfig(provider="ollama", name="qwen3"))
result = structured_output_type(str, model)
assert isinstance(result, ToolOutput)
assert result.output is str
def test_structured_output_type_string_model():
from pydantic_ai.output import ToolOutput
from haiku.rag.utils import structured_output_type
result = structured_output_type(str, "unknown:model")
assert isinstance(result, ToolOutput)
assert result.output is str
def test_get_model_ollama():
"""Test get_model returns OpenAIChatModel for Ollama."""
model_config = ModelConfig(provider="ollama", name="llama3")

120
uv.lock
View file

@ -708,7 +708,7 @@ name = "cuda-bindings"
version = "13.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cuda-pathfinder" },
{ name = "cuda-pathfinder", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/52/c8/b2589d68acf7e3d63e2be330b84bc25712e97ed799affbca7edd7eae25d6/cuda_bindings-13.2.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e865447abfb83d6a98ad5130ed3c70b1fc295ae3eeee39fd07b4ddb0671b6788", size = 5722404, upload-time = "2026-03-11T00:12:44.041Z" },
@ -739,37 +739,37 @@ wheels = [
[package.optional-dependencies]
cublas = [
{ name = "nvidia-cublas", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cublas", marker = "sys_platform == 'linux'" },
]
cudart = [
{ name = "nvidia-cuda-runtime", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cuda-runtime", marker = "sys_platform == 'linux'" },
]
cufft = [
{ name = "nvidia-cufft", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cufft", marker = "sys_platform == 'linux'" },
]
cufile = [
{ name = "nvidia-cufile", marker = "sys_platform == 'linux'" },
]
cupti = [
{ name = "nvidia-cuda-cupti", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cuda-cupti", marker = "sys_platform == 'linux'" },
]
curand = [
{ name = "nvidia-curand", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-curand", marker = "sys_platform == 'linux'" },
]
cusolver = [
{ name = "nvidia-cusolver", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cusolver", marker = "sys_platform == 'linux'" },
]
cusparse = [
{ name = "nvidia-cusparse", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cusparse", marker = "sys_platform == 'linux'" },
]
nvjitlink = [
{ name = "nvidia-nvjitlink", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-nvjitlink", marker = "sys_platform == 'linux'" },
]
nvrtc = [
{ name = "nvidia-cuda-nvrtc", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cuda-nvrtc", marker = "sys_platform == 'linux'" },
]
nvtx = [
{ name = "nvidia-nvtx", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-nvtx", marker = "sys_platform == 'linux'" },
]
[[package]]
@ -1158,7 +1158,7 @@ name = "ffmpeg-python"
version = "0.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "future" },
{ name = "future", marker = "python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/dd/5e/d5f9105d59c1325759d838af4e973695081fbbc97182baf73afc78dec266/ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127", size = 21543, upload-time = "2019-07-06T00:19:08.989Z" }
wheels = [
@ -1492,7 +1492,7 @@ requires-dist = [
{ name = "gepa", specifier = ">=0.1.0" },
{ name = "haiku-rag-slim", editable = "haiku_rag_slim" },
{ name = "huggingface-hub", specifier = ">=0.20.0" },
{ name = "pydantic-ai-slim", extras = ["evals", "logfire"], specifier = ">=1.66.0" },
{ name = "pydantic-ai-slim", extras = ["evals", "logfire"], specifier = ">=1.70.0" },
{ name = "python-dotenv", specifier = ">=1.2.2" },
{ name = "typer", specifier = ">=0.21.0,<0.22.0" },
]
@ -1582,7 +1582,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.66.0" },
{ name = "pydantic-ai-slim", extras = ["openai", "fastmcp", "logfire", "ag-ui"], specifier = ">=1.70.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.8" },
@ -2037,14 +2037,14 @@ name = "langchain-core"
version = "1.2.21"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jsonpatch" },
{ name = "langsmith" },
{ name = "packaging" },
{ name = "pydantic" },
{ name = "pyyaml" },
{ name = "tenacity" },
{ name = "typing-extensions" },
{ name = "uuid-utils" },
{ name = "jsonpatch", marker = "python_full_version < '3.14'" },
{ name = "langsmith", marker = "python_full_version < '3.14'" },
{ name = "packaging", marker = "python_full_version < '3.14'" },
{ name = "pydantic", marker = "python_full_version < '3.14'" },
{ name = "pyyaml", marker = "python_full_version < '3.14'" },
{ name = "tenacity", marker = "python_full_version < '3.14'" },
{ name = "typing-extensions", marker = "python_full_version < '3.14'" },
{ name = "uuid-utils", marker = "python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/8b/e4/135ef5bbb5b97bdf15f777b86d7fba2ef8a162723ae96b3c7c1add9891a9/langchain_core-1.2.21.tar.gz", hash = "sha256:1a121d13976dc0908d5a8222262810ea483a4cf2b05006bdba75df5b11b554b3", size = 841063, upload-time = "2026-03-23T18:01:01.674Z" }
wheels = [
@ -2056,7 +2056,7 @@ name = "langchain-text-splitters"
version = "1.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "langchain-core" },
{ name = "langchain-core", marker = "python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/85/38/14121ead61e0e75f79c3a35e5148ac7c2fe754a55f76eab3eed573269524/langchain_text_splitters-1.1.1.tar.gz", hash = "sha256:34861abe7c07d9e49d4dc852d0129e26b32738b60a74486853ec9b6d6a8e01d2", size = 279352, upload-time = "2026-02-18T23:02:42.798Z" }
wheels = [
@ -2068,15 +2068,15 @@ name = "langsmith"
version = "0.7.22"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
{ name = "orjson", marker = "platform_python_implementation != 'PyPy'" },
{ name = "packaging" },
{ name = "pydantic" },
{ name = "requests" },
{ name = "requests-toolbelt" },
{ name = "uuid-utils" },
{ name = "xxhash" },
{ name = "zstandard" },
{ name = "httpx", marker = "python_full_version < '3.14'" },
{ name = "orjson", marker = "python_full_version < '3.14' and platform_python_implementation != 'PyPy'" },
{ name = "packaging", marker = "python_full_version < '3.14'" },
{ name = "pydantic", marker = "python_full_version < '3.14'" },
{ name = "requests", marker = "python_full_version < '3.14'" },
{ name = "requests-toolbelt", marker = "python_full_version < '3.14'" },
{ name = "uuid-utils", marker = "python_full_version < '3.14'" },
{ name = "xxhash", marker = "python_full_version < '3.14'" },
{ name = "zstandard", marker = "python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/be/2a/2d5e6c67396fd228670af278c4da7bd6db2b8d11deaf6f108490b6d3f561/langsmith-0.7.22.tar.gz", hash = "sha256:35bfe795d648b069958280760564632fd28ebc9921c04f3e209c0db6a6c7dc04", size = 1134923, upload-time = "2026-03-19T22:45:23.492Z" }
wheels = [
@ -2747,7 +2747,7 @@ name = "nvidia-cudnn-cu13"
version = "9.19.0.56"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "nvidia-cublas" },
{ name = "nvidia-cublas", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/f1/84/26025437c1e6b61a707442184fa0c03d083b661adf3a3eecfd6d21677740/nvidia_cudnn_cu13-9.19.0.56-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:6ed29ffaee1176c612daf442e4dd6cfeb6a0caa43ddcbeb59da94953030b1be4", size = 433781201, upload-time = "2026-02-03T20:40:53.805Z" },
@ -2759,7 +2759,7 @@ name = "nvidia-cufft"
version = "12.0.0.61"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "nvidia-nvjitlink" },
{ name = "nvidia-nvjitlink", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/8b/ae/f417a75c0259e85c1d2f83ca4e960289a5f814ed0cea74d18c353d3e989d/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2708c852ef8cd89d1d2068bdbece0aa188813a0c934db3779b9b1faa8442e5f5", size = 214053554, upload-time = "2025-09-04T08:31:38.196Z" },
@ -2789,9 +2789,9 @@ name = "nvidia-cusolver"
version = "12.0.4.66"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "nvidia-cublas" },
{ name = "nvidia-cusparse" },
{ name = "nvidia-nvjitlink" },
{ name = "nvidia-cublas", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "nvidia-cusparse", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "nvidia-nvjitlink", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/c8/c3/b30c9e935fc01e3da443ec0116ed1b2a009bb867f5324d3f2d7e533e776b/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:02c2457eaa9e39de20f880f4bd8820e6a1cfb9f9a34f820eb12a155aa5bc92d2", size = 223467760, upload-time = "2025-09-04T08:33:04.222Z" },
@ -2803,7 +2803,7 @@ name = "nvidia-cusparse"
version = "12.6.3.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "nvidia-nvjitlink" },
{ name = "nvidia-nvjitlink", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/f8/94/5c26f33738ae35276672f12615a64bd008ed5be6d1ebcb23579285d960a9/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:80bcc4662f23f1054ee334a15c72b8940402975e0eab63178fc7e670aa59472c", size = 162155568, upload-time = "2025-09-04T08:33:42.864Z" },
@ -2860,9 +2860,9 @@ name = "ocrmac"
version = "1.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "pillow" },
{ name = "pyobjc-framework-vision" },
{ name = "click", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "pillow", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "pyobjc-framework-vision", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5e/07/3e15ab404f75875c5e48c47163300eb90b7409044d8711fc3aaf52503f2e/ocrmac-1.0.1.tar.gz", hash = "sha256:507fe5e4cbd67b2d03f6729a52bbc11f9d0b58241134eb958a5daafd4b9d93d9", size = 1454317, upload-time = "2026-01-08T16:44:26.412Z" }
wheels = [
@ -3898,7 +3898,7 @@ name = "pyobjc-framework-cocoa"
version = "12.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyobjc-core" },
{ name = "pyobjc-core", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/02/a3/16ca9a15e77c061a9250afbae2eae26f2e1579eb8ca9462ae2d2c71e1169/pyobjc_framework_cocoa-12.1.tar.gz", hash = "sha256:5556c87db95711b985d5efdaaf01c917ddd41d148b1e52a0c66b1a2e2c5c1640", size = 2772191, upload-time = "2025-11-14T10:13:02.069Z" }
wheels = [
@ -3914,8 +3914,8 @@ name = "pyobjc-framework-coreml"
version = "12.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyobjc-core" },
{ name = "pyobjc-framework-cocoa" },
{ name = "pyobjc-core", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "pyobjc-framework-cocoa", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/30/2d/baa9ea02cbb1c200683cb7273b69b4bee5070e86f2060b77e6a27c2a9d7e/pyobjc_framework_coreml-12.1.tar.gz", hash = "sha256:0d1a4216891a18775c9e0170d908714c18e4f53f9dc79fb0f5263b2aa81609ba", size = 40465, upload-time = "2025-11-14T10:14:02.265Z" }
wheels = [
@ -3931,8 +3931,8 @@ name = "pyobjc-framework-quartz"
version = "12.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyobjc-core" },
{ name = "pyobjc-framework-cocoa" },
{ name = "pyobjc-core", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "pyobjc-framework-cocoa", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/94/18/cc59f3d4355c9456fc945eae7fe8797003c4da99212dd531ad1b0de8a0c6/pyobjc_framework_quartz-12.1.tar.gz", hash = "sha256:27f782f3513ac88ec9b6c82d9767eef95a5cf4175ce88a1e5a65875fee799608", size = 3159099, upload-time = "2025-11-14T10:21:24.31Z" }
wheels = [
@ -3948,10 +3948,10 @@ name = "pyobjc-framework-vision"
version = "12.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyobjc-core" },
{ name = "pyobjc-framework-cocoa" },
{ name = "pyobjc-framework-coreml" },
{ name = "pyobjc-framework-quartz" },
{ name = "pyobjc-core", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "pyobjc-framework-cocoa", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "pyobjc-framework-coreml", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
{ name = "pyobjc-framework-quartz", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c2/5a/08bb3e278f870443d226c141af14205ff41c0274da1e053b72b11dfc9fb2/pyobjc_framework_vision-12.1.tar.gz", hash = "sha256:a30959100e85dcede3a786c544e621ad6eb65ff6abf85721f805822b8c5fe9b0", size = 59538, upload-time = "2025-11-14T10:23:21.979Z" }
wheels = [
@ -4366,7 +4366,7 @@ name = "requests-toolbelt"
version = "1.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "requests" },
{ name = "requests", marker = "python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" }
wheels = [
@ -5321,16 +5321,16 @@ name = "voyageai"
version = "0.3.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohttp" },
{ name = "aiolimiter" },
{ name = "ffmpeg-python" },
{ name = "langchain-text-splitters" },
{ name = "aiohttp", marker = "python_full_version < '3.14'" },
{ name = "aiolimiter", marker = "python_full_version < '3.14'" },
{ name = "ffmpeg-python", marker = "python_full_version < '3.14'" },
{ name = "langchain-text-splitters", marker = "python_full_version < '3.14'" },
{ name = "numpy", marker = "python_full_version < '3.14'" },
{ name = "pillow" },
{ name = "pydantic" },
{ name = "requests" },
{ name = "tenacity" },
{ name = "tokenizers" },
{ name = "pillow", marker = "python_full_version < '3.14'" },
{ name = "pydantic", marker = "python_full_version < '3.14'" },
{ name = "requests", marker = "python_full_version < '3.14'" },
{ name = "tenacity", marker = "python_full_version < '3.14'" },
{ name = "tokenizers", marker = "python_full_version < '3.14'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/94/16/1b46b3cd401e1717a68197c1fe336d7bb4e0a1833f8105e1738f5b1add05/voyageai-0.3.7.tar.gz", hash = "sha256:826cd97f97223f42b5babc5c459c9c80f3a8215ce5c0e007b0b276550f790d24", size = 26485, upload-time = "2025-12-16T18:43:05.26Z" }
wheels = [