docketeer-deepinfra 0.0.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ .venv/
2
+ .envrc.private
3
+ .claude/settings.local.json
4
+ __pycache__/
5
+ *.pyc
6
+ *.egg-info/
7
+ dist/
8
+ build/
9
+ workspace/
10
+ .coverage
11
+ .loq_cache
12
+ .python-version
@@ -0,0 +1,61 @@
1
+ Metadata-Version: 2.4
2
+ Name: docketeer-deepinfra
3
+ Version: 0.0.14
4
+ Summary: DeepInfra inference backend plugin for Docketeer
5
+ Project-URL: Homepage, https://github.com/chrisguidry/docketeer
6
+ Project-URL: Repository, https://github.com/chrisguidry/docketeer
7
+ Project-URL: Issues, https://github.com/chrisguidry/docketeer/issues
8
+ Author-email: Chris Guidry <guid@omg.lol>
9
+ License-Expression: MIT
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
+ Requires-Python: >=3.12
15
+ Requires-Dist: docketeer
16
+ Requires-Dist: openai
17
+ Description-Content-Type: text/markdown
18
+
19
+ # docketeer-deepinfra
20
+
21
+ DeepInfra inference backend plugin for Docketeer.
22
+
23
+ This plugin provides inference through the DeepInfra native API.
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install docketeer-deepinfra
29
+ ```
30
+
31
+ ## Configuration
32
+
33
+ Configure the DeepInfra backend with environment variables:
34
+
35
+ ```bash
36
+ # Required: Your DeepInfra API key
37
+ export DOCKETEER_DEEPINFRA_API_KEY=your-api-key-here
38
+
39
+ # Optional: Override the API base URL (defaults to https://api.deepinfra.com)
40
+ export DOCKETEER_DEEPINFRA_BASE_URL=https://api.deepinfra.com
41
+
42
+ # Optional: Set the default model (defaults to meta-llama/Llama-3.3-70B-Instruct)
43
+ export DOCKETEER_DEEPINFRA_MODEL=meta-llama/Llama-3.3-70B-Instruct
44
+ ```
45
+
46
+ Then configure Docketeer to use the DeepInfra inference plugin:
47
+
48
+ ```bash
49
+ export DOCKETEER_INFERENCE=deepinfra
50
+ ```
51
+
52
+ ## Supported Models
53
+
54
+ Any model available on DeepInfra can be used. Common models include:
55
+
56
+ - `meta-llama/Llama-3.3-70B-Instruct` (default)
57
+ - `meta-llama/Llama-3.1-405B-Instruct`
58
+ - `Qwen/Qwen2.5-72B-Instruct`
59
+ - `deepseek-ai/DeepSeek-V3`
60
+
61
+ Set the model using `DOCKETEER_DEEPINFRA_MODEL` or by specifying the model in your Docketeer configuration.
@@ -0,0 +1,43 @@
1
+ # docketeer-deepinfra
2
+
3
+ DeepInfra inference backend plugin for Docketeer.
4
+
5
+ This plugin provides inference through the DeepInfra native API.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install docketeer-deepinfra
11
+ ```
12
+
13
+ ## Configuration
14
+
15
+ Configure the DeepInfra backend with environment variables:
16
+
17
+ ```bash
18
+ # Required: Your DeepInfra API key
19
+ export DOCKETEER_DEEPINFRA_API_KEY=your-api-key-here
20
+
21
+ # Optional: Override the API base URL (defaults to https://api.deepinfra.com)
22
+ export DOCKETEER_DEEPINFRA_BASE_URL=https://api.deepinfra.com
23
+
24
+ # Optional: Set the default model (defaults to meta-llama/Llama-3.3-70B-Instruct)
25
+ export DOCKETEER_DEEPINFRA_MODEL=meta-llama/Llama-3.3-70B-Instruct
26
+ ```
27
+
28
+ Then configure Docketeer to use the DeepInfra inference plugin:
29
+
30
+ ```bash
31
+ export DOCKETEER_INFERENCE=deepinfra
32
+ ```
33
+
34
+ ## Supported Models
35
+
36
+ Any model available on DeepInfra can be used. Common models include:
37
+
38
+ - `meta-llama/Llama-3.3-70B-Instruct` (default)
39
+ - `meta-llama/Llama-3.1-405B-Instruct`
40
+ - `Qwen/Qwen2.5-72B-Instruct`
41
+ - `deepseek-ai/DeepSeek-V3`
42
+
43
+ Set the model using `DOCKETEER_DEEPINFRA_MODEL` or by specifying the model in your Docketeer configuration.
@@ -0,0 +1,62 @@
1
+ [project]
2
+ name = "docketeer-deepinfra"
3
+ dynamic = ["version"]
4
+ description = "DeepInfra inference backend plugin for Docketeer"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Chris Guidry", email = "guid@omg.lol" }
8
+ ]
9
+ license = "MIT"
10
+ requires-python = ">=3.12"
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Programming Language :: Python :: 3",
14
+ "License :: OSI Approved :: MIT License",
15
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
16
+ ]
17
+ dependencies = [
18
+ "openai",
19
+ "docketeer",
20
+ ]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/chrisguidry/docketeer"
24
+ Repository = "https://github.com/chrisguidry/docketeer"
25
+ Issues = "https://github.com/chrisguidry/docketeer/issues"
26
+
27
+ [project.entry-points."docketeer.inference"]
28
+ deepinfra = "docketeer_deepinfra:create_backend"
29
+
30
+ [build-system]
31
+ requires = ["hatchling", "hatch-vcs"]
32
+ build-backend = "hatchling.build"
33
+
34
+ [tool.hatch.version]
35
+ source = "vcs"
36
+ raw-options.root = ".."
37
+
38
+ [tool.hatch.build.targets.wheel]
39
+ packages = ["src/docketeer_deepinfra"]
40
+
41
+ [tool.uv.sources]
42
+ docketeer = { workspace = true }
43
+
44
+ [tool.pytest_env]
45
+ DOCKETEER_DEEPINFRA_API_KEY = "test-key"
46
+ DOCKETEER_DEEPINFRA_BASE_URL = "https://api.deepinfra.com/v1"
47
+
48
+ [tool.pytest.ini_options]
49
+ minversion = "9.0"
50
+ timeout = 1
51
+ addopts = [
52
+ "--import-mode=importlib",
53
+ "--cov=docketeer_deepinfra",
54
+ "--cov=tests",
55
+ "--cov-branch",
56
+ "--cov-report=term-missing",
57
+ "--cov-fail-under=100",
58
+ ]
59
+ asyncio_mode = "auto"
60
+ filterwarnings = [
61
+ "error",
62
+ ]
@@ -0,0 +1,55 @@
1
+ """DeepInfra inference backend plugin for Docketeer."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ from typing import TYPE_CHECKING
7
+
8
+ from docketeer import environment
9
+ from docketeer.executor import CommandExecutor
10
+
11
+ if TYPE_CHECKING:
12
+ from docketeer.brain.backend import InferenceBackend
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+ DEFAULT_MODEL = "MiniMaxAI/MiniMax-M2.5"
17
+
18
+ # Tier to max tokens mapping
19
+ TIER_MAX_TOKENS = {
20
+ "smart": 128_000,
21
+ "balanced": 64_000,
22
+ "fast": 16_000,
23
+ }
24
+
25
+
26
+ def create_backend(executor: CommandExecutor | None) -> InferenceBackend:
27
+ """Factory function to create a DeepInfra backend.
28
+
29
+ This function is the entry point for the docketeer.inference plugin.
30
+ It creates a DeepInfra API backend.
31
+
32
+ Configuration (environment variables):
33
+ DEEPINFRA_API_KEY: Required. Your DeepInfra API key.
34
+ DEEPINFRA_BASE_URL: Optional. Defaults to https://api.deepinfra.com/v1/openai
35
+ DEEPINFRA_MODEL: Optional. Default model ID. Defaults to MiniMaxAI/MiniMax-M2.5
36
+
37
+ Args:
38
+ executor: CommandExecutor instance (unused for API backend)
39
+
40
+ Returns:
41
+ An InferenceBackend implementation
42
+
43
+ Raises:
44
+ KeyError: If API key is not configured
45
+ """
46
+ from docketeer_deepinfra.api_backend import DeepInfraAPIBackend
47
+
48
+ api_key = environment.get_str("DEEPINFRA_API_KEY")
49
+ base_url = environment.get_str(
50
+ "DEEPINFRA_BASE_URL", "https://api.deepinfra.com/v1/openai"
51
+ )
52
+ default_model = environment.get_str("DEEPINFRA_MODEL", DEFAULT_MODEL)
53
+ return DeepInfraAPIBackend(
54
+ api_key=api_key, base_url=base_url, default_model=default_model
55
+ )
@@ -0,0 +1,124 @@
1
+ """DeepInfraAPIBackend: InferenceBackend backed by DeepInfra via OpenAI SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import logging
7
+ from pathlib import Path
8
+ from typing import TYPE_CHECKING
9
+
10
+ from openai import APIError, AsyncOpenAI, AuthenticationError, RateLimitError
11
+
12
+ from docketeer import environment
13
+ from docketeer.brain.backend import (
14
+ BackendAuthError,
15
+ BackendError,
16
+ ContextTooLargeError,
17
+ InferenceBackend,
18
+ )
19
+ from docketeer.brain.core import InferenceModel
20
+ from docketeer_deepinfra import TIER_MAX_TOKENS
21
+ from docketeer_deepinfra.loop import _serialize_messages, agentic_loop
22
+
23
+ if TYPE_CHECKING:
24
+ from docketeer.brain.core import ProcessCallbacks
25
+ from docketeer.prompt import MessageParam, SystemBlock
26
+ from docketeer.tools import ToolContext, ToolDefinition
27
+
28
+ log = logging.getLogger(__name__)
29
+
30
+ DEFAULT_MODEL = "MiniMaxAI/MiniMax-M2.5"
31
+
32
+
33
+ class DeepInfraAPIBackend(InferenceBackend):
34
+ def __init__(
35
+ self,
36
+ api_key: str,
37
+ base_url: str = "https://api.deepinfra.com/v1",
38
+ default_model: str = DEFAULT_MODEL,
39
+ ) -> None:
40
+ self._api_key = api_key
41
+ self._base_url = base_url.rstrip("/")
42
+ self._default_model = default_model
43
+ self._client = AsyncOpenAI(
44
+ base_url=self._base_url,
45
+ api_key=api_key,
46
+ max_retries=0,
47
+ timeout=300.0,
48
+ )
49
+
50
+ async def __aexit__(self, *exc: object) -> None:
51
+ await self._client.close()
52
+
53
+ async def run_agentic_loop(
54
+ self,
55
+ tier: str,
56
+ system: list[SystemBlock],
57
+ messages: list[MessageParam],
58
+ tools: list[ToolDefinition],
59
+ tool_context: ToolContext,
60
+ audit_path: Path,
61
+ usage_path: Path,
62
+ callbacks: ProcessCallbacks | None,
63
+ *,
64
+ thinking: bool = False,
65
+ ) -> str:
66
+ # Resolve tier to InferenceModel using environment variables
67
+ model_id = environment.get_str(
68
+ f"DEEPINFRA_MODEL_{tier.upper()}", self._default_model
69
+ )
70
+ max_tokens = TIER_MAX_TOKENS.get(tier, 64_000)
71
+ model = InferenceModel(model_id=model_id, max_output_tokens=max_tokens)
72
+
73
+ try:
74
+ return await agentic_loop(
75
+ self._client,
76
+ model,
77
+ system,
78
+ messages,
79
+ tools,
80
+ tool_context,
81
+ audit_path,
82
+ usage_path,
83
+ callbacks.on_first_text if callbacks else None,
84
+ callbacks.on_text if callbacks else None,
85
+ callbacks.on_tool_start if callbacks else None,
86
+ callbacks.on_tool_end if callbacks else None,
87
+ callbacks.interrupted if callbacks else None,
88
+ default_model=self._default_model,
89
+ )
90
+ except RateLimitError as exc:
91
+ raise BackendAuthError(str(exc)) from exc
92
+ except AuthenticationError as exc:
93
+ raise BackendAuthError(str(exc)) from exc
94
+ except APIError as exc:
95
+ msg = str(exc).lower()
96
+ if "413" in msg or "payload too large" in msg or "context length" in msg:
97
+ raise ContextTooLargeError(str(exc)) from exc
98
+ raise BackendError(str(exc)) from exc
99
+
100
+ async def count_tokens(
101
+ self,
102
+ model_id: str,
103
+ system: list[SystemBlock],
104
+ tools: list[ToolDefinition],
105
+ messages: list[MessageParam],
106
+ ) -> int:
107
+ serialized = _serialize_messages(system, messages)
108
+ return len(json.dumps(serialized)) // 4
109
+
110
+ async def utility_complete(
111
+ self,
112
+ prompt: str,
113
+ *,
114
+ max_tokens: int = 1024,
115
+ ) -> str:
116
+ try:
117
+ response = await self._client.chat.completions.create(
118
+ model=self._default_model,
119
+ messages=[{"role": "user", "content": prompt}],
120
+ max_tokens=max_tokens,
121
+ )
122
+ return response.choices[0].message.content or ""
123
+ except APIError as exc:
124
+ raise BackendError(str(exc)) from exc