diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 091cfb1..e1a2442 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.10.0" + ".": "0.10.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b204145..5bbb693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.10.1 (2025-12-09) + +Full Changelog: [v0.10.0...v0.10.1](https://github.com/ContextualAI/contextual-client-python/compare/v0.10.0...v0.10.1) + +### Bug Fixes + +* **compat:** update signatures of `model_dump` and `model_dump_json` for Pydantic v1 ([fdbee33](https://github.com/ContextualAI/contextual-client-python/commit/fdbee33a0cb13ef5bfc346bc969ff890c69c2c98)) +* ensure streams are always closed ([6bdc831](https://github.com/ContextualAI/contextual-client-python/commit/6bdc8314add1b629d570f4ad623540b12c4e9332)) +* **types:** allow pyright to infer TypedDict types within SequenceNotStr ([831b67d](https://github.com/ContextualAI/contextual-client-python/commit/831b67dbc9acbb586bd2b9c822dbb01cac56f580)) + + +### Chores + +* add missing docstrings ([9c019eb](https://github.com/ContextualAI/contextual-client-python/commit/9c019ebc453ca8ef0e2a587c57af09b995f2e581)) +* add Python 3.14 classifier and testing ([26541da](https://github.com/ContextualAI/contextual-client-python/commit/26541dab7cfa5d991a300fe0010bad88a4ecf733)) +* **deps:** mypy 1.18.1 has a regression, pin to 1.17 ([4566f14](https://github.com/ContextualAI/contextual-client-python/commit/4566f141302cad92947d2cd1ea927d44ffa441c7)) +* **docs:** use environment variables for authentication in code snippets ([92f7455](https://github.com/ContextualAI/contextual-client-python/commit/92f74555cddacdb3396094ac0742fb66f1c44bef)) +* update lockfile ([9dd374a](https://github.com/ContextualAI/contextual-client-python/commit/9dd374a4936f2269bc05ff5c8c672acaae629f86)) + ## 0.10.0 (2025-11-11) Full Changelog: [v0.9.0...v0.10.0](https://github.com/ContextualAI/contextual-client-python/compare/v0.9.0...v0.10.0) diff --git a/README.md b/README.md index ccdb4cc..7eb5680 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ pip install contextual-client[aiohttp] Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: ```python +import os import asyncio from contextual import DefaultAioHttpClient from contextual import AsyncContextualAI @@ -88,7 +89,7 @@ from contextual import AsyncContextualAI async def main() -> None: async with AsyncContextualAI( - api_key="My API Key", + api_key=os.environ.get("CONTEXTUAL_API_KEY"), # This is the default and can be omitted http_client=DefaultAioHttpClient(), ) as client: create_agent_output = await client.agents.create( diff --git a/pyproject.toml b/pyproject.toml index 9aba0a8..044ef52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,20 +1,22 @@ [project] name = "contextual-client" -version = "0.10.0" +version = "0.10.1" description = "The official Python library for the Contextual AI API" dynamic = ["readme"] license = "Apache-2.0" authors = [ { name = "Contextual AI", email = "support@contextual.ai" }, ] + dependencies = [ - "httpx>=0.23.0, <1", - "pydantic>=1.9.0, <3", - "typing-extensions>=4.10, <5", - "anyio>=3.5.0, <5", - "distro>=1.7.0, <2", - "sniffio", + "httpx>=0.23.0, <1", + "pydantic>=1.9.0, <3", + "typing-extensions>=4.10, <5", + "anyio>=3.5.0, <5", + "distro>=1.7.0, <2", + "sniffio", ] + requires-python = ">= 3.9" classifiers = [ "Typing :: Typed", @@ -24,6 +26,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Operating System :: OS Independent", "Operating System :: POSIX", "Operating System :: MacOS", @@ -45,7 +48,7 @@ managed = true # version pins are in requirements-dev.lock dev-dependencies = [ "pyright==1.1.399", - "mypy", + "mypy==1.17", "respx", "pytest", "pytest-asyncio", diff --git a/requirements-dev.lock b/requirements-dev.lock index d95129c..1cce592 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -12,40 +12,45 @@ -e file:. aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.12.8 +aiohttp==3.13.2 # via contextual-client # via httpx-aiohttp -aiosignal==1.3.2 +aiosignal==1.4.0 # via aiohttp -annotated-types==0.6.0 +annotated-types==0.7.0 # via pydantic -anyio==4.4.0 +anyio==4.12.0 # via contextual-client # via httpx -argcomplete==3.1.2 +argcomplete==3.6.3 # via nox async-timeout==5.0.1 # via aiohttp -attrs==25.3.0 +attrs==25.4.0 # via aiohttp -certifi==2023.7.22 + # via nox +backports-asyncio-runner==1.2.0 + # via pytest-asyncio +certifi==2025.11.12 # via httpcore # via httpx -colorlog==6.7.0 +colorlog==6.10.1 + # via nox +dependency-groups==1.3.1 # via nox -dirty-equals==0.6.0 -distlib==0.3.7 +dirty-equals==0.11 +distlib==0.4.0 # via virtualenv -distro==1.8.0 +distro==1.9.0 # via contextual-client -exceptiongroup==1.2.2 +exceptiongroup==1.3.1 # via anyio # via pytest -execnet==2.1.1 +execnet==2.1.2 # via pytest-xdist -filelock==3.12.4 +filelock==3.19.1 # via virtualenv -frozenlist==1.6.2 +frozenlist==1.8.0 # via aiohttp # via aiosignal h11==0.16.0 @@ -58,80 +63,87 @@ httpx==0.28.1 # via respx httpx-aiohttp==0.1.9 # via contextual-client -idna==3.4 +humanize==4.13.0 + # via nox +idna==3.11 # via anyio # via httpx # via yarl -importlib-metadata==7.0.0 -iniconfig==2.0.0 +importlib-metadata==8.7.0 +iniconfig==2.1.0 # via pytest markdown-it-py==3.0.0 # via rich mdurl==0.1.2 # via markdown-it-py -multidict==6.4.4 +multidict==6.7.0 # via aiohttp # via yarl -mypy==1.14.1 -mypy-extensions==1.0.0 +mypy==1.17.0 +mypy-extensions==1.1.0 # via mypy -nodeenv==1.8.0 +nodeenv==1.9.1 # via pyright -nox==2023.4.22 -packaging==23.2 +nox==2025.11.12 +packaging==25.0 + # via dependency-groups # via nox # via pytest -platformdirs==3.11.0 +pathspec==0.12.1 + # via mypy +platformdirs==4.4.0 # via virtualenv -pluggy==1.5.0 +pluggy==1.6.0 # via pytest -propcache==0.3.1 +propcache==0.4.1 # via aiohttp # via yarl -pydantic==2.11.9 +pydantic==2.12.5 # via contextual-client -pydantic-core==2.33.2 +pydantic-core==2.41.5 # via pydantic -pygments==2.18.0 +pygments==2.19.2 + # via pytest # via rich pyright==1.1.399 -pytest==8.3.3 +pytest==8.4.2 # via pytest-asyncio # via pytest-xdist -pytest-asyncio==0.24.0 -pytest-xdist==3.7.0 -python-dateutil==2.8.2 +pytest-asyncio==1.2.0 +pytest-xdist==3.8.0 +python-dateutil==2.9.0.post0 # via time-machine -pytz==2023.3.post1 - # via dirty-equals respx==0.22.0 -rich==13.7.1 -ruff==0.9.4 -setuptools==68.2.2 - # via nodeenv -six==1.16.0 +rich==14.2.0 +ruff==0.14.7 +six==1.17.0 # via python-dateutil -sniffio==1.3.0 - # via anyio +sniffio==1.3.1 # via contextual-client -time-machine==2.9.0 -tomli==2.0.2 +time-machine==2.19.0 +tomli==2.3.0 + # via dependency-groups # via mypy + # via nox # via pytest -typing-extensions==4.12.2 +typing-extensions==4.15.0 + # via aiosignal # via anyio # via contextual-client + # via exceptiongroup # via multidict # via mypy # via pydantic # via pydantic-core # via pyright + # via pytest-asyncio # via typing-inspection -typing-inspection==0.4.1 + # via virtualenv +typing-inspection==0.4.2 # via pydantic -virtualenv==20.24.5 +virtualenv==20.35.4 # via nox -yarl==1.20.0 +yarl==1.22.0 # via aiohttp -zipp==3.17.0 +zipp==3.23.0 # via importlib-metadata diff --git a/requirements.lock b/requirements.lock index b5c6c83..4afa4d7 100644 --- a/requirements.lock +++ b/requirements.lock @@ -12,28 +12,28 @@ -e file:. aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.12.8 +aiohttp==3.13.2 # via contextual-client # via httpx-aiohttp -aiosignal==1.3.2 +aiosignal==1.4.0 # via aiohttp -annotated-types==0.6.0 +annotated-types==0.7.0 # via pydantic -anyio==4.4.0 +anyio==4.12.0 # via contextual-client # via httpx async-timeout==5.0.1 # via aiohttp -attrs==25.3.0 +attrs==25.4.0 # via aiohttp -certifi==2023.7.22 +certifi==2025.11.12 # via httpcore # via httpx -distro==1.8.0 +distro==1.9.0 # via contextual-client -exceptiongroup==1.2.2 +exceptiongroup==1.3.1 # via anyio -frozenlist==1.6.2 +frozenlist==1.8.0 # via aiohttp # via aiosignal h11==0.16.0 @@ -45,31 +45,32 @@ httpx==0.28.1 # via httpx-aiohttp httpx-aiohttp==0.1.9 # via contextual-client -idna==3.4 +idna==3.11 # via anyio # via httpx # via yarl -multidict==6.4.4 +multidict==6.7.0 # via aiohttp # via yarl -propcache==0.3.1 +propcache==0.4.1 # via aiohttp # via yarl -pydantic==2.11.9 +pydantic==2.12.5 # via contextual-client -pydantic-core==2.33.2 +pydantic-core==2.41.5 # via pydantic -sniffio==1.3.0 - # via anyio +sniffio==1.3.1 # via contextual-client -typing-extensions==4.12.2 +typing-extensions==4.15.0 + # via aiosignal # via anyio # via contextual-client + # via exceptiongroup # via multidict # via pydantic # via pydantic-core # via typing-inspection -typing-inspection==0.4.1 +typing-inspection==0.4.2 # via pydantic -yarl==1.20.0 +yarl==1.22.0 # via aiohttp diff --git a/src/contextual/_models.py b/src/contextual/_models.py index fcec2cf..ca9500b 100644 --- a/src/contextual/_models.py +++ b/src/contextual/_models.py @@ -257,15 +257,16 @@ def model_dump( mode: Literal["json", "python"] | str = "python", include: IncEx | None = None, exclude: IncEx | None = None, + context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, + exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, - context: dict[str, Any] | None = None, - serialize_as_any: bool = False, fallback: Callable[[Any], Any] | None = None, + serialize_as_any: bool = False, ) -> dict[str, Any]: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump @@ -273,16 +274,24 @@ def model_dump( Args: mode: The mode in which `to_python` should run. - If mode is 'json', the dictionary will only contain JSON serializable types. - If mode is 'python', the dictionary may contain any Python objects. - include: A list of fields to include in the output. - exclude: A list of fields to exclude from the output. + If mode is 'json', the output will only contain JSON serializable types. + If mode is 'python', the output may contain non-JSON-serializable Python objects. + include: A set of fields to include in the output. + exclude: A set of fields to exclude from the output. + context: Additional context to pass to the serializer. by_alias: Whether to use the field's alias in the dictionary key if defined. - exclude_unset: Whether to exclude fields that are unset or None from the output. - exclude_defaults: Whether to exclude fields that are set to their default value from the output. - exclude_none: Whether to exclude fields that have a value of `None` from the output. - round_trip: Whether to enable serialization and deserialization round-trip support. - warnings: Whether to log warnings when invalid fields are encountered. + exclude_unset: Whether to exclude fields that have not been explicitly set. + exclude_defaults: Whether to exclude fields that are set to their default value. + exclude_none: Whether to exclude fields that have a value of `None`. + exclude_computed_fields: Whether to exclude computed fields. + While this can be useful for round-tripping, it is usually recommended to use the dedicated + `round_trip` parameter instead. + round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T]. + warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, + "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. + fallback: A function to call when an unknown value is encountered. If not provided, + a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. + serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. Returns: A dictionary representation of the model. @@ -299,6 +308,8 @@ def model_dump( raise ValueError("serialize_as_any is only supported in Pydantic v2") if fallback is not None: raise ValueError("fallback is only supported in Pydantic v2") + if exclude_computed_fields != False: + raise ValueError("exclude_computed_fields is only supported in Pydantic v2") dumped = super().dict( # pyright: ignore[reportDeprecated] include=include, exclude=exclude, @@ -315,15 +326,17 @@ def model_dump_json( self, *, indent: int | None = None, + ensure_ascii: bool = False, include: IncEx | None = None, exclude: IncEx | None = None, + context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, + exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, - context: dict[str, Any] | None = None, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> str: @@ -355,6 +368,10 @@ def model_dump_json( raise ValueError("serialize_as_any is only supported in Pydantic v2") if fallback is not None: raise ValueError("fallback is only supported in Pydantic v2") + if ensure_ascii != False: + raise ValueError("ensure_ascii is only supported in Pydantic v2") + if exclude_computed_fields != False: + raise ValueError("exclude_computed_fields is only supported in Pydantic v2") return super().json( # type: ignore[reportDeprecated] indent=indent, include=include, diff --git a/src/contextual/_streaming.py b/src/contextual/_streaming.py index deb13c2..837ce89 100644 --- a/src/contextual/_streaming.py +++ b/src/contextual/_streaming.py @@ -54,11 +54,12 @@ def __stream__(self) -> Iterator[_T]: process_data = self._client._process_response_data iterator = self._iter_events() - for sse in iterator: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) - - # As we might not fully consume the response stream, we need to close it explicitly - response.close() + try: + for sse in iterator: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) + finally: + # Ensure the response is closed even if the consumer doesn't read all data + response.close() def __enter__(self) -> Self: return self @@ -117,11 +118,12 @@ async def __stream__(self) -> AsyncIterator[_T]: process_data = self._client._process_response_data iterator = self._iter_events() - async for sse in iterator: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) - - # As we might not fully consume the response stream, we need to close it explicitly - await response.aclose() + try: + async for sse in iterator: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) + finally: + # Ensure the response is closed even if the consumer doesn't read all data + await response.aclose() async def __aenter__(self) -> Self: return self diff --git a/src/contextual/_types.py b/src/contextual/_types.py index a6a1882..89db9e1 100644 --- a/src/contextual/_types.py +++ b/src/contextual/_types.py @@ -243,6 +243,9 @@ class HttpxSendArgs(TypedDict, total=False): if TYPE_CHECKING: # This works because str.__contains__ does not accept object (either in typeshed or at runtime) # https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285 + # + # Note: index() and count() methods are intentionally omitted to allow pyright to properly + # infer TypedDict types when dict literals are used in lists assigned to SequenceNotStr. class SequenceNotStr(Protocol[_T_co]): @overload def __getitem__(self, index: SupportsIndex, /) -> _T_co: ... @@ -251,8 +254,6 @@ def __getitem__(self, index: slice, /) -> Sequence[_T_co]: ... def __contains__(self, value: object, /) -> bool: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T_co]: ... - def index(self, value: Any, start: int = 0, stop: int = ..., /) -> int: ... - def count(self, value: Any, /) -> int: ... def __reversed__(self) -> Iterator[_T_co]: ... else: # just point this to a normal `Sequence` at runtime to avoid having to special case diff --git a/src/contextual/_version.py b/src/contextual/_version.py index 5382f19..6db4226 100644 --- a/src/contextual/_version.py +++ b/src/contextual/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "contextual" -__version__ = "0.10.0" # x-release-please-version +__version__ = "0.10.1" # x-release-please-version diff --git a/src/contextual/types/agent_configs.py b/src/contextual/types/agent_configs.py index 1b7f9d4..8872aff 100644 --- a/src/contextual/types/agent_configs.py +++ b/src/contextual/types/agent_configs.py @@ -13,6 +13,8 @@ class ACLConfig(BaseModel): + """Parameters that affect the agent's ACL workflow""" + acl_active: Optional[bool] = None """Whether to enable ACL.""" @@ -21,6 +23,8 @@ class ACLConfig(BaseModel): class ReformulationConfig(BaseModel): + """Parameters that affect the agent's query reformulation""" + enable_query_decomposition: Optional[bool] = None """Whether to enable query decomposition.""" @@ -35,6 +39,8 @@ class ReformulationConfig(BaseModel): class TranslationConfig(BaseModel): + """Parameters that affect the agent's translation workflow""" + translate_confidence: Optional[float] = None """The confidence threshold for translation.""" @@ -43,6 +49,8 @@ class TranslationConfig(BaseModel): class AgentConfigs(BaseModel): + """Response to configs for different components""" + acl_config: Optional[ACLConfig] = None """Parameters that affect the agent's ACL workflow""" diff --git a/src/contextual/types/agent_configs_param.py b/src/contextual/types/agent_configs_param.py index 822e02a..e83d525 100644 --- a/src/contextual/types/agent_configs_param.py +++ b/src/contextual/types/agent_configs_param.py @@ -12,6 +12,8 @@ class ACLConfig(TypedDict, total=False): + """Parameters that affect the agent's ACL workflow""" + acl_active: bool """Whether to enable ACL.""" @@ -20,6 +22,8 @@ class ACLConfig(TypedDict, total=False): class ReformulationConfig(TypedDict, total=False): + """Parameters that affect the agent's query reformulation""" + enable_query_decomposition: bool """Whether to enable query decomposition.""" @@ -34,6 +38,8 @@ class ReformulationConfig(TypedDict, total=False): class TranslationConfig(TypedDict, total=False): + """Parameters that affect the agent's translation workflow""" + translate_confidence: float """The confidence threshold for translation.""" @@ -42,6 +48,8 @@ class TranslationConfig(TypedDict, total=False): class AgentConfigsParam(TypedDict, total=False): + """Response to configs for different components""" + acl_config: ACLConfig """Parameters that affect the agent's ACL workflow""" diff --git a/src/contextual/types/agent_metadata.py b/src/contextual/types/agent_metadata.py index 6598f8e..eb04b8a 100644 --- a/src/contextual/types/agent_metadata.py +++ b/src/contextual/types/agent_metadata.py @@ -10,6 +10,8 @@ class AgentUsages(BaseModel): + """Total API request counts for the agent.""" + eval: int """eval request count""" @@ -21,6 +23,8 @@ class AgentUsages(BaseModel): class AgentMetadata(BaseModel): + """Response to GET Agent request""" + datastore_ids: List[str] """The IDs of the datastore(s) associated with the agent""" diff --git a/src/contextual/types/agent_metadata_response.py b/src/contextual/types/agent_metadata_response.py index 0bb4734..4d5dc3b 100644 --- a/src/contextual/types/agent_metadata_response.py +++ b/src/contextual/types/agent_metadata_response.py @@ -11,6 +11,8 @@ class GetTwilightAgentResponseAgentUsages(BaseModel): + """Total API request counts for the agent.""" + eval: int """eval request count""" @@ -22,6 +24,8 @@ class GetTwilightAgentResponseAgentUsages(BaseModel): class GetTwilightAgentResponse(BaseModel): + """Response to GET Agent request""" + datastore_ids: List[str] """The IDs of the datastore(s) associated with the agent""" diff --git a/src/contextual/types/agents/query_create_params.py b/src/contextual/types/agents/query_create_params.py index ed08da1..41d9064 100644 --- a/src/contextual/types/agents/query_create_params.py +++ b/src/contextual/types/agents/query_create_params.py @@ -102,6 +102,8 @@ class QueryCreateParams(TypedDict, total=False): class Message(TypedDict, total=False): + """Message object for a message sent or received in a conversation""" + content: Required[str] """Content of the message""" @@ -116,6 +118,10 @@ class Message(TypedDict, total=False): class OverrideConfiguration(TypedDict, total=False): + """ + This will modify select configuration parameters for the agent during the response generation. + """ + enable_filter: bool """Override the filter_retrievals for the query. @@ -184,6 +190,8 @@ class OverrideConfiguration(TypedDict, total=False): class StructuredOutput(TypedDict, total=False): + """Custom output structure format.""" + json_schema: Required[Dict[str, object]] """The output json structure.""" diff --git a/src/contextual/types/agents/query_feedback_response.py b/src/contextual/types/agents/query_feedback_response.py index 303902b..d0d4070 100644 --- a/src/contextual/types/agents/query_feedback_response.py +++ b/src/contextual/types/agents/query_feedback_response.py @@ -6,5 +6,7 @@ class QueryFeedbackResponse(BaseModel): + """Response schema for feedback submission endpoint.""" + feedback_id: str """ID of the submitted or updated feedback.""" diff --git a/src/contextual/types/agents/query_response.py b/src/contextual/types/agents/query_response.py index 82e1b41..6b12050 100644 --- a/src/contextual/types/agents/query_response.py +++ b/src/contextual/types/agents/query_response.py @@ -19,6 +19,8 @@ class RetrievalContentCtxlMetadata(BaseModel): + """Default metadata from the retrieval""" + chunk_id: Optional[str] = None """Unique identifier for the chunk.""" @@ -80,6 +82,8 @@ class RetrievalContentCustomMetadataConfig(BaseModel): class RetrievalContent(BaseModel): + """Retrieval content object typing for v0.1 API.""" + content_id: str """Unique identifier of the retrieved content""" @@ -146,6 +150,8 @@ class RetrievalContent(BaseModel): class Attribution(BaseModel): + """Attribution for some claim made in a generated message`.""" + content_ids: List[str] """Content IDs of the sources for the attributed text""" @@ -157,6 +163,8 @@ class Attribution(BaseModel): class GroundednessScore(BaseModel): + """Groundedness scores in a generated message`.""" + end_idx: int """End index of the span in the generated message""" @@ -168,6 +176,8 @@ class GroundednessScore(BaseModel): class Message(BaseModel): + """Response to the query request""" + content: str """Content of the message""" @@ -179,6 +189,8 @@ class Message(BaseModel): class QueryResponse(BaseModel): + """Response body for POST /query""" + conversation_id: str """A unique identifier for the conversation. diff --git a/src/contextual/types/create_agent_output.py b/src/contextual/types/create_agent_output.py index d845c54..789ca75 100644 --- a/src/contextual/types/create_agent_output.py +++ b/src/contextual/types/create_agent_output.py @@ -8,6 +8,8 @@ class CreateAgentOutput(BaseModel): + """Response to POST /agents request""" + id: str """ID of the agent""" diff --git a/src/contextual/types/datastore.py b/src/contextual/types/datastore.py index d440903..1506ffd 100644 --- a/src/contextual/types/datastore.py +++ b/src/contextual/types/datastore.py @@ -10,6 +10,8 @@ class ConfigurationChunking(BaseModel): + """Configuration for document chunking""" + chunking_mode: Optional[Literal["hierarchy_depth", "hierarchy_heading", "static_length", "page_level"]] = None """Chunking mode to use. @@ -41,6 +43,8 @@ class ConfigurationChunking(BaseModel): class ConfigurationHTMLConfig(BaseModel): + """Configuration for HTML Extraction""" + max_chunk_length_tokens: Optional[int] = None """Target maximum length of text tokens chunks for chunking. @@ -49,6 +53,8 @@ class ConfigurationHTMLConfig(BaseModel): class ConfigurationParsing(BaseModel): + """Configuration for document parsing""" + enable_split_tables: Optional[bool] = None """ Whether to enable table splitting, which splits large tables into smaller tables @@ -79,6 +85,8 @@ class ConfigurationParsing(BaseModel): class Configuration(BaseModel): + """Configuration of the datastore""" + chunking: Optional[ConfigurationChunking] = None """Configuration for document chunking""" @@ -90,6 +98,8 @@ class Configuration(BaseModel): class Datastore(BaseModel): + """Datastore output entry with additional fields for public API.""" + id: str """ID of the datastore""" diff --git a/src/contextual/types/datastore_create_params.py b/src/contextual/types/datastore_create_params.py index 0ab8d94..e270961 100644 --- a/src/contextual/types/datastore_create_params.py +++ b/src/contextual/types/datastore_create_params.py @@ -22,6 +22,8 @@ class DatastoreCreateParams(TypedDict, total=False): class ConfigurationChunking(TypedDict, total=False): + """Configuration for document chunking""" + chunking_mode: Literal["hierarchy_depth", "hierarchy_heading", "static_length", "page_level"] """Chunking mode to use. @@ -53,6 +55,8 @@ class ConfigurationChunking(TypedDict, total=False): class ConfigurationHTMLConfig(TypedDict, total=False): + """Configuration for HTML Extraction""" + max_chunk_length_tokens: int """Target maximum length of text tokens chunks for chunking. @@ -61,6 +65,8 @@ class ConfigurationHTMLConfig(TypedDict, total=False): class ConfigurationParsing(TypedDict, total=False): + """Configuration for document parsing""" + enable_split_tables: bool """ Whether to enable table splitting, which splits large tables into smaller tables @@ -91,6 +97,8 @@ class ConfigurationParsing(TypedDict, total=False): class Configuration(TypedDict, total=False): + """Configuration of the datastore. If not provided, default configuration is used.""" + chunking: ConfigurationChunking """Configuration for document chunking""" diff --git a/src/contextual/types/datastore_metadata.py b/src/contextual/types/datastore_metadata.py index f1a0035..3e5037e 100644 --- a/src/contextual/types/datastore_metadata.py +++ b/src/contextual/types/datastore_metadata.py @@ -17,6 +17,8 @@ class ConfigurationChunking(BaseModel): + """Configuration for document chunking""" + chunking_mode: Optional[Literal["hierarchy_depth", "hierarchy_heading", "static_length", "page_level"]] = None """Chunking mode to use. @@ -48,6 +50,8 @@ class ConfigurationChunking(BaseModel): class ConfigurationHTMLConfig(BaseModel): + """Configuration for HTML Extraction""" + max_chunk_length_tokens: Optional[int] = None """Target maximum length of text tokens chunks for chunking. @@ -56,6 +60,8 @@ class ConfigurationHTMLConfig(BaseModel): class ConfigurationParsing(BaseModel): + """Configuration for document parsing""" + enable_split_tables: Optional[bool] = None """ Whether to enable table splitting, which splits large tables into smaller tables @@ -86,6 +92,8 @@ class ConfigurationParsing(BaseModel): class Configuration(BaseModel): + """Configuration for unstructured datastores.""" + chunking: Optional[ConfigurationChunking] = None """Configuration for document chunking""" @@ -97,6 +105,8 @@ class Configuration(BaseModel): class DatastoreUsages(BaseModel): + """Datastore usage""" + size_gb: float """Actual size of the datastore in GB""" diff --git a/src/contextual/types/datastore_update_params.py b/src/contextual/types/datastore_update_params.py index 8a4e448..12b7990 100644 --- a/src/contextual/types/datastore_update_params.py +++ b/src/contextual/types/datastore_update_params.py @@ -25,6 +25,8 @@ class DatastoreUpdateParams(TypedDict, total=False): class ConfigurationChunking(TypedDict, total=False): + """Configuration for document chunking""" + chunking_mode: Literal["hierarchy_depth", "hierarchy_heading", "static_length", "page_level"] """Chunking mode to use. @@ -56,6 +58,8 @@ class ConfigurationChunking(TypedDict, total=False): class ConfigurationHTMLConfig(TypedDict, total=False): + """Configuration for HTML Extraction""" + max_chunk_length_tokens: int """Target maximum length of text tokens chunks for chunking. @@ -64,6 +68,8 @@ class ConfigurationHTMLConfig(TypedDict, total=False): class ConfigurationParsing(TypedDict, total=False): + """Configuration for document parsing""" + enable_split_tables: bool """ Whether to enable table splitting, which splits large tables into smaller tables @@ -94,6 +100,11 @@ class ConfigurationParsing(TypedDict, total=False): class Configuration(TypedDict, total=False): + """Configuration of the datastore. + + If not provided, current configuration is retained. + """ + chunking: ConfigurationChunking """Configuration for document chunking""" diff --git a/src/contextual/types/datastores/base_metadata_filter.py b/src/contextual/types/datastores/base_metadata_filter.py index 8843ee5..91f59bc 100644 --- a/src/contextual/types/datastores/base_metadata_filter.py +++ b/src/contextual/types/datastores/base_metadata_filter.py @@ -9,6 +9,15 @@ class BaseMetadataFilter(BaseModel): + """Defines a custom metadata filter. + + The expected input is a dict which can have different operators, fields and values. For example: + + {"field": "title", "operator": "startswith", "value": "hr-"} + + Use **lowercase** for `value` when not using `equals` operator. For document_id and date_created the query is built using direct query without nesting. + """ + field: str """Field name to search for in the metadata""" diff --git a/src/contextual/types/datastores/base_metadata_filter_param.py b/src/contextual/types/datastores/base_metadata_filter_param.py index 0006f7f..77a7c71 100644 --- a/src/contextual/types/datastores/base_metadata_filter_param.py +++ b/src/contextual/types/datastores/base_metadata_filter_param.py @@ -11,6 +11,15 @@ class BaseMetadataFilterParam(TypedDict, total=False): + """Defines a custom metadata filter. + + The expected input is a dict which can have different operators, fields and values. For example: + + {"field": "title", "operator": "startswith", "value": "hr-"} + + Use **lowercase** for `value` when not using `equals` operator. For document_id and date_created the query is built using direct query without nesting. + """ + field: Required[str] """Field name to search for in the metadata""" diff --git a/src/contextual/types/datastores/composite_metadata_filter.py b/src/contextual/types/datastores/composite_metadata_filter.py index 049f45a..733c7b4 100644 --- a/src/contextual/types/datastores/composite_metadata_filter.py +++ b/src/contextual/types/datastores/composite_metadata_filter.py @@ -18,6 +18,11 @@ class CompositeMetadataFilter(BaseModel): + """\"Defines a custom metadata filter as a Composite MetadataFilter. + + Which can be be a list of filters or nested filters. + """ + filters: List[Filter] """Filters added to the query for filtering docs""" diff --git a/src/contextual/types/datastores/composite_metadata_filter_param.py b/src/contextual/types/datastores/composite_metadata_filter_param.py index b5a11f8..0810e59 100644 --- a/src/contextual/types/datastores/composite_metadata_filter_param.py +++ b/src/contextual/types/datastores/composite_metadata_filter_param.py @@ -17,6 +17,11 @@ class CompositeMetadataFilterParam(TypedDict, total=False): + """\"Defines a custom metadata filter as a Composite MetadataFilter. + + Which can be be a list of filters or nested filters. + """ + filters: Required[Iterable[Filter]] """Filters added to the query for filtering docs""" diff --git a/src/contextual/types/datastores/content_list_response.py b/src/contextual/types/datastores/content_list_response.py index 36766fd..343ef37 100644 --- a/src/contextual/types/datastores/content_list_response.py +++ b/src/contextual/types/datastores/content_list_response.py @@ -22,6 +22,8 @@ class DocumentContentEntry(BaseModel): class StructuredContentEntry(BaseModel): + """Tabular content entry used in query retrieval.""" + content_id: str """ID of the content""" diff --git a/src/contextual/types/datastores/document_get_parse_result_response.py b/src/contextual/types/datastores/document_get_parse_result_response.py index 18e64c8..1ee7cc6 100644 --- a/src/contextual/types/datastores/document_get_parse_result_response.py +++ b/src/contextual/types/datastores/document_get_parse_result_response.py @@ -18,6 +18,10 @@ class DocumentMetadataHierarchyBlockBoundingBox(BaseModel): + """ + The normalized bounding box of the block, as relative percentages of the page width and height + """ + x0: float """The x-coordinate of the top-left corner of the bounding box""" @@ -32,6 +36,8 @@ class DocumentMetadataHierarchyBlockBoundingBox(BaseModel): class DocumentMetadataHierarchyBlock(BaseModel): + """One logical block of content from a parsed page.""" + id: str """Unique ID of the block""" @@ -75,6 +81,10 @@ class DocumentMetadataHierarchyBlock(BaseModel): class DocumentMetadataHierarchy(BaseModel): + """ + Hierarchy of the document, as both heading blocks and a markdown table of contents + """ + blocks: Optional[List[DocumentMetadataHierarchyBlock]] = None """Heading blocks which define the hierarchy of the document""" @@ -83,6 +93,8 @@ class DocumentMetadataHierarchy(BaseModel): class DocumentMetadata(BaseModel): + """Document-level metadata parsed from the document""" + hierarchy: Optional[DocumentMetadataHierarchy] = None """ Hierarchy of the document, as both heading blocks and a markdown table of @@ -91,6 +103,10 @@ class DocumentMetadata(BaseModel): class PageBlockBoundingBox(BaseModel): + """ + The normalized bounding box of the block, as relative percentages of the page width and height + """ + x0: float """The x-coordinate of the top-left corner of the bounding box""" @@ -105,6 +121,8 @@ class PageBlockBoundingBox(BaseModel): class PageBlock(BaseModel): + """One logical block of content from a parsed page.""" + id: str """Unique ID of the block""" @@ -148,6 +166,8 @@ class PageBlock(BaseModel): class Page(BaseModel): + """Per-page parse results.""" + index: int """The index of the parsed page (zero-indexed)""" @@ -165,6 +185,8 @@ class Page(BaseModel): class DocumentGetParseResultResponse(BaseModel): + """/parse results reponse object.""" + file_name: str """The name of the file that was uploaded for parsing""" diff --git a/src/contextual/types/datastores/document_metadata.py b/src/contextual/types/datastores/document_metadata.py index c1bdd5a..69b6bec 100644 --- a/src/contextual/types/datastores/document_metadata.py +++ b/src/contextual/types/datastores/document_metadata.py @@ -26,6 +26,8 @@ class CustomMetadataConfig(BaseModel): class DocumentMetadata(BaseModel): + """Document description""" + id: str """ID of the document that was ingested""" diff --git a/src/contextual/types/datastores/ingestion_response.py b/src/contextual/types/datastores/ingestion_response.py index cd8558f..e1bd832 100644 --- a/src/contextual/types/datastores/ingestion_response.py +++ b/src/contextual/types/datastores/ingestion_response.py @@ -6,5 +6,7 @@ class IngestionResponse(BaseModel): + """Response body from POST /data/documents""" + id: str """ID of the document being ingested""" diff --git a/src/contextual/types/datastores/list_documents_response.py b/src/contextual/types/datastores/list_documents_response.py index 8f0be4a..064a061 100644 --- a/src/contextual/types/datastores/list_documents_response.py +++ b/src/contextual/types/datastores/list_documents_response.py @@ -9,6 +9,8 @@ class ListDocumentsResponse(BaseModel): + """Response body from GET /data/documents""" + documents: List[DocumentMetadata] """List of documents retrieved based on the user's GET request""" diff --git a/src/contextual/types/filter_and_rerank_config.py b/src/contextual/types/filter_and_rerank_config.py index 5057861..9c293f8 100644 --- a/src/contextual/types/filter_and_rerank_config.py +++ b/src/contextual/types/filter_and_rerank_config.py @@ -14,6 +14,8 @@ class FilterAndRerankConfig(BaseModel): + """Captures Filter and Rerank configurations for an Agent""" + default_metadata_filters: Optional[DefaultMetadataFilters] = None """ Optional metadata filter which is applied while retrieving from every datastore diff --git a/src/contextual/types/filter_and_rerank_config_param.py b/src/contextual/types/filter_and_rerank_config_param.py index 415293e..ff43d8f 100644 --- a/src/contextual/types/filter_and_rerank_config_param.py +++ b/src/contextual/types/filter_and_rerank_config_param.py @@ -13,6 +13,8 @@ class FilterAndRerankConfigParam(TypedDict, total=False): + """Captures Filter and Rerank configurations for an Agent""" + default_metadata_filters: DefaultMetadataFilters """ Optional metadata filter which is applied while retrieving from every datastore diff --git a/src/contextual/types/generate_create_params.py b/src/contextual/types/generate_create_params.py index 662a561..1233eec 100644 --- a/src/contextual/types/generate_create_params.py +++ b/src/contextual/types/generate_create_params.py @@ -56,6 +56,8 @@ class GenerateCreateParams(TypedDict, total=False): class Message(TypedDict, total=False): + """Message object for a message received in the /generate request""" + content: Required[str] """Content of the message""" diff --git a/src/contextual/types/generate_create_response.py b/src/contextual/types/generate_create_response.py index 25b08a7..46d8dd7 100644 --- a/src/contextual/types/generate_create_response.py +++ b/src/contextual/types/generate_create_response.py @@ -6,5 +6,7 @@ class GenerateCreateResponse(BaseModel): + """/generate result object.""" + response: str """The model's response to the last user message.""" diff --git a/src/contextual/types/generate_response_config.py b/src/contextual/types/generate_response_config.py index 4635750..62fc3a8 100644 --- a/src/contextual/types/generate_response_config.py +++ b/src/contextual/types/generate_response_config.py @@ -8,6 +8,8 @@ class GenerateResponseConfig(BaseModel): + """Captures advance LLM configurations for an Agent""" + avoid_commentary: Optional[bool] = None """ Flag to indicate whether the model should avoid providing additional commentary diff --git a/src/contextual/types/generate_response_config_param.py b/src/contextual/types/generate_response_config_param.py index ea39181..0ed9965 100644 --- a/src/contextual/types/generate_response_config_param.py +++ b/src/contextual/types/generate_response_config_param.py @@ -8,6 +8,8 @@ class GenerateResponseConfigParam(TypedDict, total=False): + """Captures advance LLM configurations for an Agent""" + avoid_commentary: bool """ Flag to indicate whether the model should avoid providing additional commentary diff --git a/src/contextual/types/global_config.py b/src/contextual/types/global_config.py index 716edde..1252bec 100644 --- a/src/contextual/types/global_config.py +++ b/src/contextual/types/global_config.py @@ -8,6 +8,8 @@ class GlobalConfig(BaseModel): + """Captures global configs""" + enable_filter: Optional[bool] = None """Enables filtering of retrieved chunks with a separate LLM""" diff --git a/src/contextual/types/global_config_param.py b/src/contextual/types/global_config_param.py index e09fa3a..625b81d 100644 --- a/src/contextual/types/global_config_param.py +++ b/src/contextual/types/global_config_param.py @@ -8,6 +8,8 @@ class GlobalConfigParam(TypedDict, total=False): + """Captures global configs""" + enable_filter: bool """Enables filtering of retrieved chunks with a separate LLM""" diff --git a/src/contextual/types/list_users_response.py b/src/contextual/types/list_users_response.py index 2cebb63..861511a 100644 --- a/src/contextual/types/list_users_response.py +++ b/src/contextual/types/list_users_response.py @@ -9,6 +9,8 @@ class UserPerAgentRole(BaseModel): + """The schema used to capture agent level roles""" + agent_id: str """ID of the agent on which to grant/revoke the role.""" @@ -20,6 +22,8 @@ class UserPerAgentRole(BaseModel): class User(BaseModel): + """The schema used for listing existing (activated / deactivated) users.""" + id: str email: str diff --git a/src/contextual/types/lmunit_create_response.py b/src/contextual/types/lmunit_create_response.py index 37c1d6b..6030d12 100644 --- a/src/contextual/types/lmunit_create_response.py +++ b/src/contextual/types/lmunit_create_response.py @@ -6,6 +6,8 @@ class LMUnitCreateResponse(BaseModel): + """LMUnit result object.""" + score: float """The response is scored on a continuous scale from 1 to 5 on the unit test. diff --git a/src/contextual/types/new_user_param.py b/src/contextual/types/new_user_param.py index 027d759..ae8f210 100644 --- a/src/contextual/types/new_user_param.py +++ b/src/contextual/types/new_user_param.py @@ -9,6 +9,8 @@ class PerAgentRole(TypedDict, total=False): + """The schema used to capture agent level roles""" + agent_id: Required[str] """ID of the agent on which to grant/revoke the role.""" @@ -20,6 +22,8 @@ class PerAgentRole(TypedDict, total=False): class NewUserParam(TypedDict, total=False): + """The schema used for creating new users or updating existing users.""" + email: Required[str] """The email of the user""" diff --git a/src/contextual/types/parse_create_response.py b/src/contextual/types/parse_create_response.py index 168854b..d255e0c 100644 --- a/src/contextual/types/parse_create_response.py +++ b/src/contextual/types/parse_create_response.py @@ -6,5 +6,7 @@ class ParseCreateResponse(BaseModel): + """/parse response object.""" + job_id: str """Unique ID of the parse job""" diff --git a/src/contextual/types/parse_job_results_response.py b/src/contextual/types/parse_job_results_response.py index 8d1565e..d9a367a 100644 --- a/src/contextual/types/parse_job_results_response.py +++ b/src/contextual/types/parse_job_results_response.py @@ -18,6 +18,10 @@ class DocumentMetadataHierarchyBlockBoundingBox(BaseModel): + """ + The normalized bounding box of the block, as relative percentages of the page width and height + """ + x0: float """The x-coordinate of the top-left corner of the bounding box""" @@ -32,6 +36,8 @@ class DocumentMetadataHierarchyBlockBoundingBox(BaseModel): class DocumentMetadataHierarchyBlock(BaseModel): + """One logical block of content from a parsed page.""" + id: str """Unique ID of the block""" @@ -75,6 +81,10 @@ class DocumentMetadataHierarchyBlock(BaseModel): class DocumentMetadataHierarchy(BaseModel): + """ + Hierarchy of the document, as both heading blocks and a markdown table of contents + """ + blocks: Optional[List[DocumentMetadataHierarchyBlock]] = None """Heading blocks which define the hierarchy of the document""" @@ -83,6 +93,8 @@ class DocumentMetadataHierarchy(BaseModel): class DocumentMetadata(BaseModel): + """Document-level metadata parsed from the document""" + hierarchy: Optional[DocumentMetadataHierarchy] = None """ Hierarchy of the document, as both heading blocks and a markdown table of @@ -91,6 +103,10 @@ class DocumentMetadata(BaseModel): class PageBlockBoundingBox(BaseModel): + """ + The normalized bounding box of the block, as relative percentages of the page width and height + """ + x0: float """The x-coordinate of the top-left corner of the bounding box""" @@ -105,6 +121,8 @@ class PageBlockBoundingBox(BaseModel): class PageBlock(BaseModel): + """One logical block of content from a parsed page.""" + id: str """Unique ID of the block""" @@ -148,6 +166,8 @@ class PageBlock(BaseModel): class Page(BaseModel): + """Per-page parse results.""" + index: int """The index of the parsed page (zero-indexed)""" @@ -165,6 +185,8 @@ class Page(BaseModel): class ParseJobResultsResponse(BaseModel): + """/parse results reponse object.""" + file_name: str """The name of the file that was uploaded for parsing""" diff --git a/src/contextual/types/parse_job_status_response.py b/src/contextual/types/parse_job_status_response.py index 768ccfd..18333cb 100644 --- a/src/contextual/types/parse_job_status_response.py +++ b/src/contextual/types/parse_job_status_response.py @@ -8,6 +8,8 @@ class ParseJobStatusResponse(BaseModel): + """/parse status reponse object.""" + file_name: str """The name of the file that was uploaded for parsing""" diff --git a/src/contextual/types/parse_jobs_response.py b/src/contextual/types/parse_jobs_response.py index d511f7f..42acdbd 100644 --- a/src/contextual/types/parse_jobs_response.py +++ b/src/contextual/types/parse_jobs_response.py @@ -20,6 +20,8 @@ class Job(BaseModel): class ParseJobsResponse(BaseModel): + """/parse list jobs object.""" + jobs: List[Job] """List of parse jobs""" diff --git a/src/contextual/types/rerank_create_response.py b/src/contextual/types/rerank_create_response.py index 091d3c7..1fbf4f5 100644 --- a/src/contextual/types/rerank_create_response.py +++ b/src/contextual/types/rerank_create_response.py @@ -8,6 +8,8 @@ class Result(BaseModel): + """Reranked result object.""" + index: int """Index of the document in the input list, starting with 0""" @@ -23,6 +25,8 @@ class Result(BaseModel): class RerankCreateResponse(BaseModel): + """Rerank output response.""" + results: List[Result] """ The ranked list of documents containing the index of the document and the diff --git a/src/contextual/types/retrieval_config.py b/src/contextual/types/retrieval_config.py index 663748f..9741455 100644 --- a/src/contextual/types/retrieval_config.py +++ b/src/contextual/types/retrieval_config.py @@ -8,6 +8,8 @@ class RetrievalConfig(BaseModel): + """Captures Retrieval configurations for an Agent""" + lexical_alpha: Optional[float] = None """The weight of lexical search during retrieval. diff --git a/src/contextual/types/retrieval_config_param.py b/src/contextual/types/retrieval_config_param.py index 9fa0b20..149b6b7 100644 --- a/src/contextual/types/retrieval_config_param.py +++ b/src/contextual/types/retrieval_config_param.py @@ -8,6 +8,8 @@ class RetrievalConfigParam(TypedDict, total=False): + """Captures Retrieval configurations for an Agent""" + lexical_alpha: float """The weight of lexical search during retrieval. diff --git a/src/contextual/types/user_update_params.py b/src/contextual/types/user_update_params.py index 229d81d..ed78a06 100644 --- a/src/contextual/types/user_update_params.py +++ b/src/contextual/types/user_update_params.py @@ -46,6 +46,8 @@ class UserUpdateParams(TypedDict, total=False): class PerAgentRole(TypedDict, total=False): + """The schema used to capture agent level roles""" + agent_id: Required[str] """ID of the agent on which to grant/revoke the role."""