Compare commits

1 Commits

7 changed files with 253 additions and 45 deletions

View File

@@ -5,6 +5,7 @@ description = "Add your description here"
readme = "README.md" readme = "README.md"
requires-python = ">=3.13" requires-python = ">=3.13"
dependencies = [ dependencies = [
"openai>=2.0.0",
"qdrant-client==1.13", "qdrant-client==1.13",
"vault-settings>=0.1.0", "vault-settings>=0.1.0",
] ]

View File

@@ -11,10 +11,6 @@ from .engine import Backend, get_engine
from .models import Chunk, Condition from .models import Chunk, Condition
class QueryError(ValueError):
"""Raised when query parameters are invalid."""
class EmbedderNotConfiguredError(ValueError): class EmbedderNotConfiguredError(ValueError):
"""Raised when embedder is required but not configured.""" """Raised when embedder is required but not configured."""
@@ -79,8 +75,7 @@ class Client:
async def semantic_search( async def semantic_search(
self, self,
query: str | list[float] | None = None, query: str | list[float],
embedding: list[float] | None = None,
limit: int = 10, limit: int = 10,
conditions: list[Condition] | None = None, conditions: list[Condition] | None = None,
threshold: float | None = None, threshold: float | None = None,
@@ -88,8 +83,7 @@ class Client:
"""Perform semantic search using vector similarity. """Perform semantic search using vector similarity.
Args: Args:
query: Text query to embed (requires embedder to be configured) query: Text query to embed (requires embedder) or pre-computed vector
embedding: Pre-computed query vector as a list of floats
limit: Maximum number of results to return (default: 10) limit: Maximum number of results to return (default: 10)
conditions: Optional list of filter conditions to apply conditions: Optional list of filter conditions to apply
threshold: Optional minimum similarity score threshold threshold: Optional minimum similarity score threshold
@@ -98,28 +92,18 @@ class Client:
List of search results with chunk IDs, scores, and metadata List of search results with chunk IDs, scores, and metadata
Raises: Raises:
ValueError: If neither query nor embedding is provided, or if query EmbedderNotConfiguredError: If query is a string but no embedder is configured
is provided but no embedder is configured
""" """
if query is None and embedding is None: # Handle query parameter
msg = "Either 'query' or 'embedding' must be provided" if isinstance(query, str):
raise QueryError(msg) if self.embedder is None:
msg = "Cannot use text query without an embedder"
if query is not None and embedding is not None: raise EmbedderNotConfiguredError(msg)
msg = "Only one of 'query' or 'embedding' should be provided" embedding = self.embedder.embed(query)
raise QueryError(msg) else:
# query is already a list[float]
# Handle query string embedding = query
if query is not None:
if isinstance(query, str):
if self.embedder is None:
msg = "Cannot use 'query' parameter without an embedder"
raise EmbedderNotConfiguredError(msg)
embedding = self.embedder.embed(query)
else:
# query is already a list[float]
embedding = query
return await self.engine.semantic_search( return await self.engine.semantic_search(
embedding, self.collection, limit, conditions, threshold embedding, self.collection, limit, conditions, threshold

View File

@@ -17,6 +17,10 @@ class Settings(VaultSettings):
qdrant_url: The URL endpoint for the vector database server (e.g., Qdrant). qdrant_url: The URL endpoint for the vector database server (e.g., Qdrant).
qdrant_api_key: Optional API key for authenticating with the vector database. qdrant_api_key: Optional API key for authenticating with the vector database.
If None, the connection will be made without authentication. If None, the connection will be made without authentication.
azure_openai_endpoint: Azure OpenAI endpoint URL.
azure_openai_api_key: Azure OpenAI API key.
azure_openai_api_version: Azure OpenAI API version (e.g., "2024-02-01").
azure_openai_embedding_model: Azure OpenAI embedding model name.
Example: Example:
>>> settings = Settings() >>> settings = Settings()
@@ -34,3 +38,7 @@ class Settings(VaultSettings):
qdrant_url: str qdrant_url: str
qdrant_api_key: str | None = None qdrant_api_key: str | None = None
azure_openai_endpoint: str | None = None
azure_openai_api_key: str | None = None
azure_openai_api_version: str | None = None
azure_openai_embedding_model: str | None = None

View File

@@ -1 +1,115 @@
"""Embedder class using Azure AI Foundry.""" """Embedder package.
This package provides an abstract embedder interface and concrete implementations
for different embedding service providers. It uses a factory pattern with caching
to provide efficient embedder instantiation.
The package includes:
- Abstract BaseEmbedder class
- AzureEmbedder implementation for Azure OpenAI
- EmbedderBackend enum for specifying embedder types
- Factory function with overloaded type hints for type safety
Example:
>>> from searchbox.embedder import get_embedder, EmbedderBackend
>>> embedder = get_embedder(EmbedderBackend.AZURE)
>>> embedding = embedder.embed("Hello world")
"""
from enum import StrEnum
from functools import cache
from typing import Literal, overload
from .azure import AzureEmbedder
from .base import BaseEmbedder
class UnknownEmbedderError(Exception):
"""Exception raised when an unknown embedder is requested."""
def __init__(self, backend: str):
"""Initialize the exception with the unknown backend."""
super().__init__(f"Unknown embedder type: {backend}")
class EmbedderBackend(StrEnum):
"""Enumeration of supported embedder backends.
This enum defines the available embedder implementations that can
be used with the embedder factory. Each backend corresponds to a specific
embedding service provider.
Attributes:
AZURE: Azure OpenAI embedder backend
Example:
>>> backend = EmbedderBackend.AZURE
>>> print(backend) # "azure"
>>> embedder = get_embedder(backend)
"""
AZURE = "azure"
@overload
def get_embedder(backend: Literal["azure"]) -> AzureEmbedder: ...
@overload
def get_embedder(
backend: Literal["azure"],
model: str,
azure_endpoint: str,
api_key: str,
openai_api_version: str,
) -> AzureEmbedder: ...
@overload
def get_embedder(backend: EmbedderBackend, **kwargs: str) -> BaseEmbedder: ...
@cache
def get_embedder(backend: EmbedderBackend, **kwargs: str) -> BaseEmbedder:
"""Get an embedder instance for the specified backend.
This factory function creates and returns embedder instances based on the
specified backend type. Instances are cached using functools.cache, so
multiple calls with the same backend will return the same instance.
Args:
backend: The embedder backend to use. Must be an EmbedderBackend enum value.
**kwargs: Additional keyword arguments to pass to the embedder constructor.
Returns:
An embedder instance implementing the BaseEmbedder interface. The specific
type depends on the backend:
- EmbedderBackend.AZURE returns AzureEmbedder
Raises:
UnknownEmbedderError: If an unknown backend type is provided.
ValueError: If required settings are missing when using from_settings.
Example:
>>> embedder = get_embedder(EmbedderBackend.AZURE)
>>> isinstance(embedder, AzureEmbedder) # True
>>> # Type checker knows the exact type for literals:
>>> azure_embedder = get_embedder(EmbedderBackend.AZURE) # Type: AzureEmbedder
"""
if backend == EmbedderBackend.AZURE:
return AzureEmbedder(**kwargs) if kwargs else AzureEmbedder.from_settings()
else:
raise UnknownEmbedderError(backend)
__all__ = [
"BaseEmbedder",
"AzureEmbedder",
"EmbedderBackend",
"get_embedder",
"UnknownEmbedderError",
]

View File

@@ -2,6 +2,7 @@
from openai import AzureOpenAI from openai import AzureOpenAI
from ..config import Settings
from .base import BaseEmbedder from .base import BaseEmbedder
@@ -52,6 +53,42 @@ class AzureEmbedder(BaseEmbedder):
api_version=openai_api_version, api_version=openai_api_version,
) )
@classmethod
def from_settings(cls) -> "AzureEmbedder":
"""Initialize the Azure embedder from Settings.
Returns:
Initialized AzureEmbedder instance.
Raises:
ValueError: If required settings are not configured.
"""
settings = Settings() # type: ignore[reportCallArgs]
if not all(
[
settings.azure_openai_endpoint,
settings.azure_openai_api_key,
settings.azure_openai_api_version,
settings.azure_openai_embedding_model,
]
):
msg = (
"Missing required Azure OpenAI settings. "
"Ensure AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_API_KEY, "
"AZURE_OPENAI_API_VERSION, and AZURE_OPENAI_EMBEDDING_MODEL "
"are set."
)
raise ValueError(msg)
return cls(
model=settings.azure_openai_embedding_model, # type: ignore[arg-type]
azure_endpoint=settings.azure_openai_endpoint, # type: ignore[arg-type]
api_key=settings.azure_openai_api_key, # type: ignore[arg-type]
openai_api_version=settings.azure_openai_api_version, # type: ignore[arg-type]
)
def embed(self, text: str) -> list[float]: def embed(self, text: str) -> list[float]:
"""Generate embedding vector for the given text. """Generate embedding vector for the given text.

View File

@@ -1,13 +1,13 @@
"""Main MCP server implementation for vector search operations. """Main MCP server implementation for vector search operations.
This module sets up and configures the FastMCP server with vector search capabilities. This module sets up and configures the FastMCP server with vector search capabilities.
It creates a Qdrant engine instance and exposes the semantic search functionality It creates engine and embedder instances and exposes the semantic search functionality
as an MCP tool. as an MCP tool.
The server provides: The server provides:
- Semantic search tool for vector similarity queries - Semantic search tool for vector similarity queries
- Support for various search conditions and filters - Support for various search conditions and filters
- Integration with Qdrant vector database - Integration with vector databases and embedding services
Example: Example:
The server is typically started using the run function from the package: The server is typically started using the run function from the package:
@@ -22,38 +22,36 @@ from fastmcp import FastMCP
from starlette.requests import Request from starlette.requests import Request
from starlette.responses import JSONResponse from starlette.responses import JSONResponse
from ..client import Backend, Client from ..client import Client
from ..embedder.azure import AzureEmbedder from ..embedder import EmbedderBackend, get_embedder
mcp = FastMCP("Searchbox MCP") mcp = FastMCP("Searchbox MCP")
# Initialize Azure embedder # Initialize embedder map
embedder = AzureEmbedder( embedder_map = {
model="", "azure": get_embedder(EmbedderBackend.AZURE),
azure_endpoint="", }
api_key="",
openai_api_version="",
)
@mcp.tool(exclude_args=["backend", "collection", "limit", "threshold"]) @mcp.tool(exclude_args=["backend", "collection", "embedder", "limit", "threshold"])
async def get_information( async def get_information(
query: Annotated[str, "The user query"], query: Annotated[str, "The user query"],
backend: str = "qdrant", backend: str = "qdrant",
collection: str = "default", collection: str = "default",
embedder: str = "azure",
limit: int = 10, limit: int = 10,
threshold: float | None = None, threshold: float | None = None,
): ):
"""Search a private repository for information using semantic search. """Search a private repository for information using semantic search.
The query will be automatically converted to an embedding vector using The query will be automatically converted to an embedding vector using
Azure OpenAI's text-embedding-3-large model before searching. the specified embedder before searching.
""" """
# Create client with embedder # Create client with embedder
client = Client( client = Client(
backend=Backend.QDRANT if backend == "qdrant" else Backend.QDRANT, backend=backend, # type: ignore[arg-type]
collection=collection, collection=collection,
embedder=embedder, embedder=embedder_map[embedder],
) )
# Perform semantic search with automatic embedding # Perform semantic search with automatic embedding

68
uv.lock generated
View File

@@ -1,5 +1,5 @@
version = 1 version = 1
revision = 3 revision = 2
requires-python = ">=3.13" requires-python = ">=3.13"
[[package]] [[package]]
@@ -295,6 +295,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f0/8b/2c95f0645c6f40211896375e6fa51f504b8ccb29c21f6ae661fe87ab044e/cyclopts-3.24.0-py3-none-any.whl", hash = "sha256:809d04cde9108617106091140c3964ee6fceb33cecdd537f7ffa360bde13ed71", size = 86154, upload-time = "2025-09-08T15:40:56.41Z" }, { url = "https://files.pythonhosted.org/packages/f0/8b/2c95f0645c6f40211896375e6fa51f504b8ccb29c21f6ae661fe87ab044e/cyclopts-3.24.0-py3-none-any.whl", hash = "sha256:809d04cde9108617106091140c3964ee6fceb33cecdd537f7ffa360bde13ed71", size = 86154, upload-time = "2025-09-08T15:40:56.41Z" },
] ]
[[package]]
name = "distro"
version = "1.9.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" },
]
[[package]] [[package]]
name = "dnspython" name = "dnspython"
version = "2.8.0" version = "2.8.0"
@@ -625,6 +634,42 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" }, { url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" },
] ]
[[package]]
name = "jiter"
version = "0.11.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/9d/c0/a3bb4cc13aced219dd18191ea66e874266bd8aa7b96744e495e1c733aa2d/jiter-0.11.0.tar.gz", hash = "sha256:1d9637eaf8c1d6a63d6562f2a6e5ab3af946c66037eb1b894e8fad75422266e4", size = 167094, upload-time = "2025-09-15T09:20:38.212Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/97/c4/d530e514d0f4f29b2b68145e7b389cbc7cac7f9c8c23df43b04d3d10fa3e/jiter-0.11.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:4441a91b80a80249f9a6452c14b2c24708f139f64de959943dfeaa6cb915e8eb", size = 305021, upload-time = "2025-09-15T09:19:43.523Z" },
{ url = "https://files.pythonhosted.org/packages/7a/77/796a19c567c5734cbfc736a6f987affc0d5f240af8e12063c0fb93990ffa/jiter-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ff85fc6d2a431251ad82dbd1ea953affb5a60376b62e7d6809c5cd058bb39471", size = 314384, upload-time = "2025-09-15T09:19:44.849Z" },
{ url = "https://files.pythonhosted.org/packages/14/9c/824334de0b037b91b6f3fa9fe5a191c83977c7ec4abe17795d3cb6d174cf/jiter-0.11.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5e86126d64706fd28dfc46f910d496923c6f95b395138c02d0e252947f452bd", size = 337389, upload-time = "2025-09-15T09:19:46.094Z" },
{ url = "https://files.pythonhosted.org/packages/a2/95/ed4feab69e6cf9b2176ea29d4ef9d01a01db210a3a2c8a31a44ecdc68c38/jiter-0.11.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ad8bd82165961867a10f52010590ce0b7a8c53da5ddd8bbb62fef68c181b921", size = 360519, upload-time = "2025-09-15T09:19:47.494Z" },
{ url = "https://files.pythonhosted.org/packages/b5/0c/2ad00f38d3e583caba3909d95b7da1c3a7cd82c0aa81ff4317a8016fb581/jiter-0.11.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b42c2cd74273455ce439fd9528db0c6e84b5623cb74572305bdd9f2f2961d3df", size = 487198, upload-time = "2025-09-15T09:19:49.116Z" },
{ url = "https://files.pythonhosted.org/packages/ea/8b/919b64cf3499b79bdfba6036da7b0cac5d62d5c75a28fb45bad7819e22f0/jiter-0.11.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0062dab98172dd0599fcdbf90214d0dcde070b1ff38a00cc1b90e111f071982", size = 377835, upload-time = "2025-09-15T09:19:50.468Z" },
{ url = "https://files.pythonhosted.org/packages/29/7f/8ebe15b6e0a8026b0d286c083b553779b4dd63db35b43a3f171b544de91d/jiter-0.11.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb948402821bc76d1f6ef0f9e19b816f9b09f8577844ba7140f0b6afe994bc64", size = 347655, upload-time = "2025-09-15T09:19:51.726Z" },
{ url = "https://files.pythonhosted.org/packages/8e/64/332127cef7e94ac75719dda07b9a472af6158ba819088d87f17f3226a769/jiter-0.11.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25a5b1110cca7329fd0daf5060faa1234be5c11e988948e4f1a1923b6a457fe1", size = 386135, upload-time = "2025-09-15T09:19:53.075Z" },
{ url = "https://files.pythonhosted.org/packages/20/c8/557b63527442f84c14774159948262a9d4fabb0d61166f11568f22fc60d2/jiter-0.11.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:bf11807e802a214daf6c485037778843fadd3e2ec29377ae17e0706ec1a25758", size = 516063, upload-time = "2025-09-15T09:19:54.447Z" },
{ url = "https://files.pythonhosted.org/packages/86/13/4164c819df4a43cdc8047f9a42880f0ceef5afeb22e8b9675c0528ebdccd/jiter-0.11.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:dbb57da40631c267861dd0090461222060960012d70fd6e4c799b0f62d0ba166", size = 508139, upload-time = "2025-09-15T09:19:55.764Z" },
{ url = "https://files.pythonhosted.org/packages/fa/70/6e06929b401b331d41ddb4afb9f91cd1168218e3371972f0afa51c9f3c31/jiter-0.11.0-cp313-cp313-win32.whl", hash = "sha256:8e36924dad32c48d3c5e188d169e71dc6e84d6cb8dedefea089de5739d1d2f80", size = 206369, upload-time = "2025-09-15T09:19:57.048Z" },
{ url = "https://files.pythonhosted.org/packages/f4/0d/8185b8e15de6dce24f6afae63380e16377dd75686d56007baa4f29723ea1/jiter-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:452d13e4fd59698408087235259cebe67d9d49173b4dacb3e8d35ce4acf385d6", size = 202538, upload-time = "2025-09-15T09:19:58.35Z" },
{ url = "https://files.pythonhosted.org/packages/13/3a/d61707803260d59520721fa326babfae25e9573a88d8b7b9cb54c5423a59/jiter-0.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:089f9df9f69532d1339e83142438668f52c97cd22ee2d1195551c2b1a9e6cf33", size = 313737, upload-time = "2025-09-15T09:19:59.638Z" },
{ url = "https://files.pythonhosted.org/packages/cd/cc/c9f0eec5d00f2a1da89f6bdfac12b8afdf8d5ad974184863c75060026457/jiter-0.11.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29ed1fe69a8c69bf0f2a962d8d706c7b89b50f1332cd6b9fbda014f60bd03a03", size = 346183, upload-time = "2025-09-15T09:20:01.442Z" },
{ url = "https://files.pythonhosted.org/packages/a6/87/fc632776344e7aabbab05a95a0075476f418c5d29ab0f2eec672b7a1f0ac/jiter-0.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:a4d71d7ea6ea8786291423fe209acf6f8d398a0759d03e7f24094acb8ab686ba", size = 204225, upload-time = "2025-09-15T09:20:03.102Z" },
{ url = "https://files.pythonhosted.org/packages/ee/3b/e7f45be7d3969bdf2e3cd4b816a7a1d272507cd0edd2d6dc4b07514f2d9a/jiter-0.11.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9a6dff27eca70930bdbe4cbb7c1a4ba8526e13b63dc808c0670083d2d51a4a72", size = 304414, upload-time = "2025-09-15T09:20:04.357Z" },
{ url = "https://files.pythonhosted.org/packages/06/32/13e8e0d152631fcc1907ceb4943711471be70496d14888ec6e92034e2caf/jiter-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ae2a7593a62132c7d4c2abbee80bbbb94fdc6d157e2c6cc966250c564ef774", size = 314223, upload-time = "2025-09-15T09:20:05.631Z" },
{ url = "https://files.pythonhosted.org/packages/0c/7e/abedd5b5a20ca083f778d96bba0d2366567fcecb0e6e34ff42640d5d7a18/jiter-0.11.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b13a431dba4b059e9e43019d3022346d009baf5066c24dcdea321a303cde9f0", size = 337306, upload-time = "2025-09-15T09:20:06.917Z" },
{ url = "https://files.pythonhosted.org/packages/ac/e2/30d59bdc1204c86aa975ec72c48c482fee6633120ee9c3ab755e4dfefea8/jiter-0.11.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:af62e84ca3889604ebb645df3b0a3f3bcf6b92babbff642bd214616f57abb93a", size = 360565, upload-time = "2025-09-15T09:20:08.283Z" },
{ url = "https://files.pythonhosted.org/packages/fe/88/567288e0d2ed9fa8f7a3b425fdaf2cb82b998633c24fe0d98f5417321aa8/jiter-0.11.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6f3b32bb723246e6b351aecace52aba78adb8eeb4b2391630322dc30ff6c773", size = 486465, upload-time = "2025-09-15T09:20:09.613Z" },
{ url = "https://files.pythonhosted.org/packages/18/6e/7b72d09273214cadd15970e91dd5ed9634bee605176107db21e1e4205eb1/jiter-0.11.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:adcab442f4a099a358a7f562eaa54ed6456fb866e922c6545a717be51dbed7d7", size = 377581, upload-time = "2025-09-15T09:20:10.884Z" },
{ url = "https://files.pythonhosted.org/packages/58/52/4db456319f9d14deed325f70102577492e9d7e87cf7097bda9769a1fcacb/jiter-0.11.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9967c2ab338ee2b2c0102fd379ec2693c496abf71ffd47e4d791d1f593b68e2", size = 347102, upload-time = "2025-09-15T09:20:12.175Z" },
{ url = "https://files.pythonhosted.org/packages/ce/b4/433d5703c38b26083aec7a733eb5be96f9c6085d0e270a87ca6482cbf049/jiter-0.11.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e7d0bed3b187af8b47a981d9742ddfc1d9b252a7235471ad6078e7e4e5fe75c2", size = 386477, upload-time = "2025-09-15T09:20:13.428Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7a/a60bfd9c55b55b07c5c441c5085f06420b6d493ce9db28d069cc5b45d9f3/jiter-0.11.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:f6fe0283e903ebc55f1a6cc569b8c1f3bf4abd026fed85e3ff8598a9e6f982f0", size = 516004, upload-time = "2025-09-15T09:20:14.848Z" },
{ url = "https://files.pythonhosted.org/packages/2e/46/f8363e5ecc179b4ed0ca6cb0a6d3bfc266078578c71ff30642ea2ce2f203/jiter-0.11.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:4ee5821e3d66606b29ae5b497230b304f1376f38137d69e35f8d2bd5f310ff73", size = 507855, upload-time = "2025-09-15T09:20:16.176Z" },
{ url = "https://files.pythonhosted.org/packages/90/33/396083357d51d7ff0f9805852c288af47480d30dd31d8abc74909b020761/jiter-0.11.0-cp314-cp314-win32.whl", hash = "sha256:c2d13ba7567ca8799f17c76ed56b1d49be30df996eb7fa33e46b62800562a5e2", size = 205802, upload-time = "2025-09-15T09:20:17.661Z" },
{ url = "https://files.pythonhosted.org/packages/e7/ab/eb06ca556b2551d41de7d03bf2ee24285fa3d0c58c5f8d95c64c9c3281b1/jiter-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:fb4790497369d134a07fc763cc88888c46f734abdd66f9fdf7865038bf3a8f40", size = 313405, upload-time = "2025-09-15T09:20:18.918Z" },
{ url = "https://files.pythonhosted.org/packages/af/22/7ab7b4ec3a1c1f03aef376af11d23b05abcca3fb31fbca1e7557053b1ba2/jiter-0.11.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e2bbf24f16ba5ad4441a9845e40e4ea0cb9eed00e76ba94050664ef53ef4406", size = 347102, upload-time = "2025-09-15T09:20:20.16Z" },
]
[[package]] [[package]]
name = "jsonschema" name = "jsonschema"
version = "4.25.1" version = "4.25.1"
@@ -933,6 +978,25 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/eb/59/0db51308fa479f9325ade08c343a5164153ad01dbb83b62ff661e1129d2e/onnxruntime-1.23.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ed85686e08cfb29ee96365b9a49e8a350aff7557c13d63d9f07ca3ad68975074", size = 17281939, upload-time = "2025-09-25T19:16:16.16Z" }, { url = "https://files.pythonhosted.org/packages/eb/59/0db51308fa479f9325ade08c343a5164153ad01dbb83b62ff661e1129d2e/onnxruntime-1.23.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ed85686e08cfb29ee96365b9a49e8a350aff7557c13d63d9f07ca3ad68975074", size = 17281939, upload-time = "2025-09-25T19:16:16.16Z" },
] ]
[[package]]
name = "openai"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "distro" },
{ name = "httpx" },
{ name = "jiter" },
{ name = "pydantic" },
{ name = "sniffio" },
{ name = "tqdm" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d8/5d/74fa2b0358ef15d113b1a6ca2323cee0034020b085a81a94eeddc6914de9/openai-2.0.0.tar.gz", hash = "sha256:6b9513b485f856b0be6bc44c518831acb58e37a12bed72fcc52b1177d1fb34a8", size = 565732, upload-time = "2025-09-30T17:35:57.632Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/69/41/86ddc9cdd885acc02ee50ec24ea1c5e324eea0c7a471ee841a7088653558/openai-2.0.0-py3-none-any.whl", hash = "sha256:a79f493651f9843a6c54789a83f3b2db56df0e1770f7dcbe98bcf0e967ee2148", size = 955538, upload-time = "2025-09-30T17:35:54.695Z" },
]
[[package]] [[package]]
name = "openapi-core" name = "openapi-core"
version = "0.19.5" version = "0.19.5"
@@ -1530,6 +1594,7 @@ name = "searchbox"
version = "0.1.1" version = "0.1.1"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "openai" },
{ name = "qdrant-client" }, { name = "qdrant-client" },
{ name = "vault-settings" }, { name = "vault-settings" },
] ]
@@ -1552,6 +1617,7 @@ dev = [
[package.metadata] [package.metadata]
requires-dist = [ requires-dist = [
{ name = "fastmcp", marker = "extra == 'mcp'", specifier = ">=2.12.4" }, { name = "fastmcp", marker = "extra == 'mcp'", specifier = ">=2.12.4" },
{ name = "openai", specifier = ">=2.0.0" },
{ name = "qdrant-client", specifier = "==1.13" }, { name = "qdrant-client", specifier = "==1.13" },
{ name = "vault-settings", specifier = ">=0.1.0" }, { name = "vault-settings", specifier = ">=0.1.0" },
] ]