bendex 0.1.0__py3-none-any.whl

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.
bendex/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ from bendex.monitor import monitor, status, get_config
2
+
3
+ __version__ = "0.1.0"
4
+ __all__ = ["monitor", "status", "get_config"]
bendex/monitor.py ADDED
@@ -0,0 +1,63 @@
1
+ """
2
+ Bendex Monitor -- geometric LLM inference monitoring.
3
+ Grounds drift detection in Fisher-Rao information geometry.
4
+ """
5
+ import os
6
+ import httpx
7
+ from typing import Optional
8
+
9
+ SENTRY_URL = "https://web-production-6e47f.up.railway.app"
10
+ _config = {}
11
+
12
+ def monitor(
13
+ deployment: str,
14
+ model: str = "gpt-4o",
15
+ sentry_url: str = SENTRY_URL,
16
+ api_key: Optional[str] = None,
17
+ verbose: bool = True,
18
+ ):
19
+ """
20
+ Initialize Bendex monitoring for an LLM deployment.
21
+
22
+ Usage:
23
+ import bendex
24
+ bendex.monitor(deployment="my-app", model="gpt-4o")
25
+
26
+ # Then use OpenAI as normal -- all calls are monitored
27
+ from openai import OpenAI
28
+ client = OpenAI()
29
+ response = client.chat.completions.create(...)
30
+ """
31
+ _config["deployment"] = deployment
32
+ _config["model"] = model
33
+ _config["sentry_url"] = sentry_url
34
+ _config["api_key"] = api_key or os.environ.get("BENDEX_API_KEY", "")
35
+ _config["verbose"] = verbose
36
+ _config["active"] = True
37
+
38
+ # Patch OpenAI client
39
+ from bendex.patch import patch_openai
40
+ patch_openai(_config)
41
+
42
+ if verbose:
43
+ print(f"✓ Bendex monitoring active")
44
+ print(f" deployment : {deployment}")
45
+ print(f" model : {model}")
46
+ print(f" sentry : {sentry_url}")
47
+ print(f" dashboard : {sentry_url}/dashboard")
48
+ print(f" τ* : 1.2247 (Landauer threshold)")
49
+
50
+ def status():
51
+ """Check connection to Sentry."""
52
+ if not _config.get("active"):
53
+ print("Bendex not initialized. Call bendex.monitor() first.")
54
+ return
55
+ try:
56
+ r = httpx.get(f"{_config['sentry_url']}/sentry/health", timeout=5)
57
+ data = r.json()
58
+ print(f"✓ Sentry connected: {data}")
59
+ except Exception as e:
60
+ print(f"✗ Sentry unreachable: {e}")
61
+
62
+ def get_config():
63
+ return _config.copy()
bendex/patch.py ADDED
@@ -0,0 +1,65 @@
1
+ """
2
+ OpenAI client patcher -- routes calls through Bendex Sentry.
3
+ Patches the OpenAI Python SDK transparently.
4
+ """
5
+ import functools
6
+
7
+ _original_create = None
8
+ _patched = False
9
+
10
+ def patch_openai(config: dict):
11
+ """Patch the OpenAI chat completions client to route through Sentry."""
12
+ global _original_create, _patched
13
+
14
+ if _patched:
15
+ return
16
+
17
+ try:
18
+ import openai
19
+ from openai.resources.chat.completions import Completions
20
+
21
+ _original_create = Completions.create
22
+
23
+ @functools.wraps(_original_create)
24
+ def patched_create(self, *args, **kwargs):
25
+ # Inject Sentry routing headers
26
+ extra_headers = kwargs.pop("extra_headers", {}) or {}
27
+ extra_headers["X-Sentry-Deployment"] = config.get("deployment", "bendex")
28
+ extra_headers["X-Sentry-Model-Version"] = kwargs.get("model", config.get("model", "gpt-4o"))
29
+
30
+ if config.get("api_key"):
31
+ extra_headers["X-Bendex-API-Key"] = config["api_key"]
32
+
33
+ kwargs["extra_headers"] = extra_headers
34
+
35
+ # Redirect base URL to Sentry proxy
36
+ original_base = self._client.base_url
37
+ sentry_url = config.get("sentry_url", "https://web-production-6e47f.up.railway.app")
38
+
39
+ try:
40
+ self._client.base_url = f"{sentry_url}/v1"
41
+ result = _original_create(self, *args, **kwargs)
42
+ return result
43
+ finally:
44
+ self._client.base_url = original_base
45
+
46
+ Completions.create = patched_create
47
+ _patched = True
48
+
49
+ if config.get("verbose"):
50
+ print(f" patch : openai.chat.completions.create → Sentry proxy")
51
+
52
+ except ImportError:
53
+ if config.get("verbose"):
54
+ print(" openai not installed -- install with: pip install openai")
55
+ except Exception as e:
56
+ if config.get("verbose"):
57
+ print(f" patch failed: {e}")
58
+
59
+ def unpatch_openai():
60
+ """Restore original OpenAI client."""
61
+ global _original_create, _patched
62
+ if _patched and _original_create:
63
+ from openai.resources.chat.completions import Completions
64
+ Completions.create = _original_create
65
+ _patched = False
@@ -0,0 +1,22 @@
1
+ Metadata-Version: 2.4
2
+ Name: bendex
3
+ Version: 0.1.0
4
+ Summary: Geometric LLM inference monitor grounded in Fisher-Rao information geometry
5
+ Home-page: https://bendexgeometry.com
6
+ Author: Hannah Nine
7
+ Author-email: 9hannahnine@gmail.com
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Requires-Python: >=3.8
14
+ Requires-Dist: httpx>=0.27.0
15
+ Requires-Dist: openai>=1.0.0
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: classifier
19
+ Dynamic: home-page
20
+ Dynamic: requires-dist
21
+ Dynamic: requires-python
22
+ Dynamic: summary
@@ -0,0 +1,7 @@
1
+ bendex/__init__.py,sha256=tEub5BSI1N6wFukvl35ycC2etSH3ofh8pxgQLXSwq6g,124
2
+ bendex/monitor.py,sha256=N2SNMYbxc_lMw7EIVcdQ2iHlNoT3-B2wi5LsO9Pt8ys,1848
3
+ bendex/patch.py,sha256=ckQaUxSFYK7koEnXZqelhI8KU2MWGwhBDM-z-c-GAqs,2208
4
+ bendex-0.1.0.dist-info/METADATA,sha256=3G3roVBtCPlHNA4JHgITSe6yHqqAQGNWEAqiccW7qTo,710
5
+ bendex-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
6
+ bendex-0.1.0.dist-info/top_level.txt,sha256=NALpCIi35gDcZbh0Y-sD8EoDgCrrFnO51r29uuxkmTQ,7
7
+ bendex-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ bendex