vinfty 0.1.0__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.
- vinfty-0.1.0/LICENSE +21 -0
- vinfty-0.1.0/PKG-INFO +111 -0
- vinfty-0.1.0/README.md +82 -0
- vinfty-0.1.0/pyproject.toml +3 -0
- vinfty-0.1.0/setup.cfg +4 -0
- vinfty-0.1.0/setup.py +23 -0
- vinfty-0.1.0/tests/test_core.py +102 -0
- vinfty-0.1.0/vinfty/__init__.py +5 -0
- vinfty-0.1.0/vinfty/adapters/__init__.py +3 -0
- vinfty-0.1.0/vinfty/adapters/langchain.py +36 -0
- vinfty-0.1.0/vinfty/core.py +167 -0
- vinfty-0.1.0/vinfty.egg-info/PKG-INFO +111 -0
- vinfty-0.1.0/vinfty.egg-info/SOURCES.txt +13 -0
- vinfty-0.1.0/vinfty.egg-info/dependency_links.txt +1 -0
- vinfty-0.1.0/vinfty.egg-info/top_level.txt +1 -0
vinfty-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 V∞ Project
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
vinfty-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vinfty
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: V∞ — cognitive observability layer for any LLM orchestration framework
|
|
5
|
+
Home-page: https://github.com/twincosmos/vinfty
|
|
6
|
+
Author: V∞ Project
|
|
7
|
+
Author-email: vinfty@twincosmos.dev
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: cognitive-architecture observability llm-orchestration v-infty
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: author-email
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: keywords
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-python
|
|
28
|
+
Dynamic: summary
|
|
29
|
+
|
|
30
|
+
# V∞ (vinfty)
|
|
31
|
+
|
|
32
|
+
**Cognitive observability layer for any LLM orchestration framework.**
|
|
33
|
+
|
|
34
|
+
Vinfty is a featherweight (~300 lines) Python library that adds cognitive observability to your LLM pipelines — without replacing your existing tools. It measures **ont_self** (self-consistency), tracks **C_ij coupling** (cross-session memory coherence), and detects **HMM s₀/s₁ state transitions** — so you know whether your system is healthy, not just whether it returned a valid JSON.
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
pip install vinfty
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Why?
|
|
43
|
+
|
|
44
|
+
LangChain, CrewAI, AutoGen — they all solve "how to call LLMs in sequence." None of them answer:
|
|
45
|
+
|
|
46
|
+
- Is my agent system getting more coherent or more chaotic over time?
|
|
47
|
+
- Are my tool calls producing consistent results or contradicting each other?
|
|
48
|
+
- Is the system in a stable (s₀) or active-search (s₁) mode?
|
|
49
|
+
|
|
50
|
+
Vinfty adds that layer. It wraps any orchestration framework and gives you a **cognitive dashboard**: ont_self trajectory, coupling matrix, HMM state, palace routing.
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from vinfty import V9Orchestrator
|
|
56
|
+
|
|
57
|
+
engine = V9Orchestrator(active_k=100)
|
|
58
|
+
|
|
59
|
+
# Register any function as a tool → maps to a Palace domain
|
|
60
|
+
@engine.register(palace="P_search")
|
|
61
|
+
def search_web(q: str) -> str:
|
|
62
|
+
return f"search results for {q}"
|
|
63
|
+
|
|
64
|
+
@engine.register(palace="P_analysis")
|
|
65
|
+
def calculate(expr: str) -> float:
|
|
66
|
+
return eval(expr)
|
|
67
|
+
|
|
68
|
+
# Each call updates the cognitive state
|
|
69
|
+
engine.step("search latest LLM papers", tool=search_web)
|
|
70
|
+
engine.step("how many published this month?", tool=calculate)
|
|
71
|
+
|
|
72
|
+
# Check system health
|
|
73
|
+
report = engine.report()
|
|
74
|
+
# → {
|
|
75
|
+
# "ont_self": 0.72,
|
|
76
|
+
# "hmm_state": "s0"|"s1",
|
|
77
|
+
# "palace_flow": ["P_query", "P_search", "P_analysis"],
|
|
78
|
+
# "c_ij_density": 0.34,
|
|
79
|
+
# "memory_count": 12,
|
|
80
|
+
# }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Core Concepts
|
|
84
|
+
|
|
85
|
+
| Concept | What it measures | Analogy |
|
|
86
|
+
|---------|-----------------|---------|
|
|
87
|
+
| **ont_self** | System self-consistency | "Is my agent making consistent decisions?" |
|
|
88
|
+
| **C_ij** | Cross-session memory coupling | "Do past decisions influence present ones coherently?" |
|
|
89
|
+
| **HMM s₀/s₁** | Cognitive mode | "Is the system in stable execution (s₀) or active exploration (s₁)?" |
|
|
90
|
+
| **Palace** | Functional domain | "Which cognitive domain is each tool call serving?" |
|
|
91
|
+
|
|
92
|
+
## Adapters
|
|
93
|
+
|
|
94
|
+
Vinfty ships with adapters for common frameworks:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
# LangChain adapter
|
|
98
|
+
from vinfty.adapters.langchain import LangChainAdapter
|
|
99
|
+
|
|
100
|
+
adapter = LangChainAdapter(agent)
|
|
101
|
+
report = adapter.run_with_observability(user_query)
|
|
102
|
+
# Same result as agent.run(), plus cognitive report
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## No LLM Required
|
|
106
|
+
|
|
107
|
+
Vinfty is pure symbolic computation — no API keys, no GPU, no model weights. The cognitive metrics are derived from the **structure** of your tool calls and memory traces, not from the content of LLM responses.
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT
|
vinfty-0.1.0/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# V∞ (vinfty)
|
|
2
|
+
|
|
3
|
+
**Cognitive observability layer for any LLM orchestration framework.**
|
|
4
|
+
|
|
5
|
+
Vinfty is a featherweight (~300 lines) Python library that adds cognitive observability to your LLM pipelines — without replacing your existing tools. It measures **ont_self** (self-consistency), tracks **C_ij coupling** (cross-session memory coherence), and detects **HMM s₀/s₁ state transitions** — so you know whether your system is healthy, not just whether it returned a valid JSON.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
pip install vinfty
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Why?
|
|
14
|
+
|
|
15
|
+
LangChain, CrewAI, AutoGen — they all solve "how to call LLMs in sequence." None of them answer:
|
|
16
|
+
|
|
17
|
+
- Is my agent system getting more coherent or more chaotic over time?
|
|
18
|
+
- Are my tool calls producing consistent results or contradicting each other?
|
|
19
|
+
- Is the system in a stable (s₀) or active-search (s₁) mode?
|
|
20
|
+
|
|
21
|
+
Vinfty adds that layer. It wraps any orchestration framework and gives you a **cognitive dashboard**: ont_self trajectory, coupling matrix, HMM state, palace routing.
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from vinfty import V9Orchestrator
|
|
27
|
+
|
|
28
|
+
engine = V9Orchestrator(active_k=100)
|
|
29
|
+
|
|
30
|
+
# Register any function as a tool → maps to a Palace domain
|
|
31
|
+
@engine.register(palace="P_search")
|
|
32
|
+
def search_web(q: str) -> str:
|
|
33
|
+
return f"search results for {q}"
|
|
34
|
+
|
|
35
|
+
@engine.register(palace="P_analysis")
|
|
36
|
+
def calculate(expr: str) -> float:
|
|
37
|
+
return eval(expr)
|
|
38
|
+
|
|
39
|
+
# Each call updates the cognitive state
|
|
40
|
+
engine.step("search latest LLM papers", tool=search_web)
|
|
41
|
+
engine.step("how many published this month?", tool=calculate)
|
|
42
|
+
|
|
43
|
+
# Check system health
|
|
44
|
+
report = engine.report()
|
|
45
|
+
# → {
|
|
46
|
+
# "ont_self": 0.72,
|
|
47
|
+
# "hmm_state": "s0"|"s1",
|
|
48
|
+
# "palace_flow": ["P_query", "P_search", "P_analysis"],
|
|
49
|
+
# "c_ij_density": 0.34,
|
|
50
|
+
# "memory_count": 12,
|
|
51
|
+
# }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Core Concepts
|
|
55
|
+
|
|
56
|
+
| Concept | What it measures | Analogy |
|
|
57
|
+
|---------|-----------------|---------|
|
|
58
|
+
| **ont_self** | System self-consistency | "Is my agent making consistent decisions?" |
|
|
59
|
+
| **C_ij** | Cross-session memory coupling | "Do past decisions influence present ones coherently?" |
|
|
60
|
+
| **HMM s₀/s₁** | Cognitive mode | "Is the system in stable execution (s₀) or active exploration (s₁)?" |
|
|
61
|
+
| **Palace** | Functional domain | "Which cognitive domain is each tool call serving?" |
|
|
62
|
+
|
|
63
|
+
## Adapters
|
|
64
|
+
|
|
65
|
+
Vinfty ships with adapters for common frameworks:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# LangChain adapter
|
|
69
|
+
from vinfty.adapters.langchain import LangChainAdapter
|
|
70
|
+
|
|
71
|
+
adapter = LangChainAdapter(agent)
|
|
72
|
+
report = adapter.run_with_observability(user_query)
|
|
73
|
+
# Same result as agent.run(), plus cognitive report
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## No LLM Required
|
|
77
|
+
|
|
78
|
+
Vinfty is pure symbolic computation — no API keys, no GPU, no model weights. The cognitive metrics are derived from the **structure** of your tool calls and memory traces, not from the content of LLM responses.
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT
|
vinfty-0.1.0/setup.cfg
ADDED
vinfty-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="vinfty",
|
|
5
|
+
version="0.1.0",
|
|
6
|
+
description="V∞ — cognitive observability layer for any LLM orchestration framework",
|
|
7
|
+
long_description=open("README.md", encoding="utf-8").read(),
|
|
8
|
+
long_description_content_type="text/markdown",
|
|
9
|
+
author="V∞ Project",
|
|
10
|
+
author_email="vinfty@twincosmos.dev",
|
|
11
|
+
url="https://github.com/twincosmos/vinfty",
|
|
12
|
+
license="MIT",
|
|
13
|
+
packages=find_packages(),
|
|
14
|
+
python_requires=">=3.10",
|
|
15
|
+
classifiers=[
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
21
|
+
],
|
|
22
|
+
keywords="cognitive-architecture observability llm-orchestration v-infty",
|
|
23
|
+
)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
sys.path.insert(0, "..")
|
|
3
|
+
|
|
4
|
+
from vinfty.core import V9Orchestrator, _HMM
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_empty_ont_self():
|
|
8
|
+
engine = V9Orchestrator(active_k=50)
|
|
9
|
+
assert engine.ont_self() == 0.0, "empty → ont_self = 0"
|
|
10
|
+
print(" ✅ empty ont_self")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_single_memory():
|
|
14
|
+
engine = V9Orchestrator(active_k=50)
|
|
15
|
+
engine.step("hello", palace="P_test")
|
|
16
|
+
assert engine.ont_self() == 0.0, "single memory → ont_self = 0 (no pairs)"
|
|
17
|
+
print(" ✅ single memory ont_self")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_same_palace():
|
|
21
|
+
engine = V9Orchestrator(active_k=50)
|
|
22
|
+
for i in range(5):
|
|
23
|
+
engine.step(f"item {i}", palace="P_fixed")
|
|
24
|
+
assert engine.ont_self() >= 0.5, f"same palace → high ont_self (got {engine.ont_self():.4f})"
|
|
25
|
+
print(f" ✅ same palace ont_self = {engine.ont_self():.4f}")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_diff_palace():
|
|
29
|
+
engine = V9Orchestrator(active_k=50)
|
|
30
|
+
for i in range(5):
|
|
31
|
+
engine.step(f"item {i}", palace=f"P_{i}")
|
|
32
|
+
assert engine.ont_self() < 0.1, "diff palaces → near 0 ont_self"
|
|
33
|
+
print(f" ✅ diff palace ont_self = {engine.ont_self():.4f}")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_hmm_initial():
|
|
37
|
+
hmm = _HMM()
|
|
38
|
+
assert hmm.state == "s0", "init state = s0"
|
|
39
|
+
assert hmm.posterior_s1 == 0.0, "init posterior = 0"
|
|
40
|
+
print(" ✅ HMM initial state")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_hmm_update():
|
|
44
|
+
hmm = _HMM()
|
|
45
|
+
hmm.update(0.9) # large delta ratio → s1
|
|
46
|
+
assert hmm.state == "s1", "high delta ratio → s1"
|
|
47
|
+
hmm.update(0.0) # small delta ratio → s0
|
|
48
|
+
assert hmm.state == "s0", "low delta ratio → s0"
|
|
49
|
+
print(f" ✅ HMM state transition {hmm.state}")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_register_decorator():
|
|
53
|
+
engine = V9Orchestrator()
|
|
54
|
+
@engine.register(palace="P_test")
|
|
55
|
+
def foo(): pass
|
|
56
|
+
assert "foo" in engine._palace_registry
|
|
57
|
+
assert engine._palace_registry["foo"]["palace"] == "P_test"
|
|
58
|
+
print(" ✅ register decorator")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_report():
|
|
62
|
+
engine = V9Orchestrator(active_k=50)
|
|
63
|
+
for i in range(5):
|
|
64
|
+
engine.step(f"item {i}", palace="P_fixed")
|
|
65
|
+
r = engine.report()
|
|
66
|
+
assert "ont_self" in r
|
|
67
|
+
assert "hmm_state" in r
|
|
68
|
+
assert "c_ij_density" in r
|
|
69
|
+
assert r["memory_count"] == 5
|
|
70
|
+
print(f" ✅ report keys={list(r.keys())}")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_trace():
|
|
74
|
+
engine = V9Orchestrator(active_k=50)
|
|
75
|
+
engine.step("hello", palace="P_test")
|
|
76
|
+
t = engine.trace()
|
|
77
|
+
assert len(t) == 1
|
|
78
|
+
assert t[0]["palace"] == "P_test"
|
|
79
|
+
print(" ✅ trace")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_active_pool_pruning():
|
|
83
|
+
engine = V9Orchestrator(active_k=10)
|
|
84
|
+
for i in range(20):
|
|
85
|
+
engine.step(f"item {i}", palace="P_fixed")
|
|
86
|
+
assert len(engine.memories) == 10
|
|
87
|
+
assert len(engine.archive) == 10
|
|
88
|
+
print(" ✅ active pool pruning")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
test_empty_ont_self()
|
|
93
|
+
test_single_memory()
|
|
94
|
+
test_same_palace()
|
|
95
|
+
test_diff_palace()
|
|
96
|
+
test_hmm_initial()
|
|
97
|
+
test_hmm_update()
|
|
98
|
+
test_register_decorator()
|
|
99
|
+
test_report()
|
|
100
|
+
test_trace()
|
|
101
|
+
test_active_pool_pruning()
|
|
102
|
+
print("\n🎯 10/10 tests passed")
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""
|
|
2
|
+
vinfty.adapters.langchain — wrap a LangChain agent with cognitive observability.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
from vinfty.adapters.langchain import LangChainAdapter
|
|
6
|
+
|
|
7
|
+
adapter = LangChainAdapter(agent)
|
|
8
|
+
result, report = adapter.run("query")
|
|
9
|
+
print(report["ont_self"])
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Any, Optional
|
|
13
|
+
|
|
14
|
+
from vinfty.core import V9Orchestrator
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LangChainAdapter:
|
|
18
|
+
"""Wraps a LangChain agent and adds V9 cognitive observability."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, agent: Any, active_k: int = 100):
|
|
21
|
+
self.agent = agent
|
|
22
|
+
self.cog = V9Orchestrator(active_k=active_k)
|
|
23
|
+
|
|
24
|
+
def run(self, query: str, **kwargs) -> tuple[str, dict]:
|
|
25
|
+
"""Run query through agent, return (result, cognitive_report)."""
|
|
26
|
+
self.cog.step(query, palace="P_query")
|
|
27
|
+
result = self.agent.run(query, **kwargs)
|
|
28
|
+
self.cog.step(result, palace="P_response")
|
|
29
|
+
return result, self.cog.report()
|
|
30
|
+
|
|
31
|
+
def run_with_observability(self, query: str, **kwargs) -> str:
|
|
32
|
+
"""Run and print cognitive report alongside result."""
|
|
33
|
+
result, report = self.run(query, **kwargs)
|
|
34
|
+
print(f"[V∞] ont_self={report['ont_self']} state={report['hmm_state']} "
|
|
35
|
+
f"palaces={report['palace_count']} c_density={report['c_ij_density']}")
|
|
36
|
+
return result
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
vinfty.core — V9Orchestrator: cognitive state machine for tool-call observation.
|
|
3
|
+
|
|
4
|
+
No LLM dependency. Pure symbolic computation:
|
|
5
|
+
- ont_self = Σ C_ij · I_j (self-consistency)
|
|
6
|
+
- C_ij = 1 when memories share a Palace label
|
|
7
|
+
- HMM K=2 tracks s₀ (stable) / s₁ (searching) state
|
|
8
|
+
- Palace routing assigns tool calls to cognitive domains
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import math
|
|
12
|
+
import json
|
|
13
|
+
from collections import defaultdict
|
|
14
|
+
from typing import Callable, Optional
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class V9Orchestrator:
|
|
18
|
+
"""Lightweight cognitive engine tracking ont_self, C_ij coupling, HMM state."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, active_k: int = 100):
|
|
21
|
+
self.active_k = active_k
|
|
22
|
+
self.memories: list[dict] = []
|
|
23
|
+
self.archive: list[dict] = []
|
|
24
|
+
self._palace_registry: dict[str, Callable] = {}
|
|
25
|
+
self._hmm = _HMM()
|
|
26
|
+
self._last_scan = -1
|
|
27
|
+
|
|
28
|
+
# ── tool registration ──
|
|
29
|
+
|
|
30
|
+
def register(self, palace: str = "P_generic"):
|
|
31
|
+
"""Decorator: register a function as a tool belonging to a Palace domain."""
|
|
32
|
+
def decorator(fn):
|
|
33
|
+
self._palace_registry[fn.__name__] = {"fn": fn, "palace": palace}
|
|
34
|
+
return fn
|
|
35
|
+
return decorator
|
|
36
|
+
|
|
37
|
+
def register_tool(self, name: str, fn: Callable, palace: str = "P_generic"):
|
|
38
|
+
"""Register a tool by name."""
|
|
39
|
+
self._palace_registry[name] = {"fn": fn, "palace": palace}
|
|
40
|
+
|
|
41
|
+
# ── step / run ──
|
|
42
|
+
|
|
43
|
+
def step(self, content: str, tool: Optional[Callable] = None, **extra):
|
|
44
|
+
"""Process one interaction: store memory, update coupling, run HMM."""
|
|
45
|
+
mem = {
|
|
46
|
+
"content": content,
|
|
47
|
+
"palace": extra.get("palace", self._resolve_palace(content, tool)),
|
|
48
|
+
"confidence": extra.get("confidence", 0.5),
|
|
49
|
+
"tick": len(self.memories) + len(self.archive),
|
|
50
|
+
}
|
|
51
|
+
self.memories.append(mem)
|
|
52
|
+
# active pool pruning
|
|
53
|
+
if len(self.memories) > self.active_k:
|
|
54
|
+
excess = self.memories[:-self.active_k]
|
|
55
|
+
self.archive.extend(excess)
|
|
56
|
+
self.memories = self.memories[-self.active_k:]
|
|
57
|
+
if len(self.archive) > 2000:
|
|
58
|
+
self.archive = self.archive[-2000:]
|
|
59
|
+
# HMM update (convenience: rescan every step)
|
|
60
|
+
self._scan_hmm()
|
|
61
|
+
|
|
62
|
+
def run(self, tasks: list[str], **extra):
|
|
63
|
+
"""Process multiple string tasks in sequence."""
|
|
64
|
+
for t in tasks:
|
|
65
|
+
self.step(t, **extra)
|
|
66
|
+
|
|
67
|
+
# ── report ──
|
|
68
|
+
|
|
69
|
+
def report(self) -> dict:
|
|
70
|
+
"""Return current cognitive state summary."""
|
|
71
|
+
ont = self.ont_self()
|
|
72
|
+
c_density = self._coupling_density()
|
|
73
|
+
palace_counts = self._palace_distribution()
|
|
74
|
+
return {
|
|
75
|
+
"ont_self": round(ont, 4),
|
|
76
|
+
"c_ij_density": round(c_density, 4),
|
|
77
|
+
"hmm_state": self._hmm.state,
|
|
78
|
+
"hmm_s1_posterior": round(self._hmm.posterior_s1, 4),
|
|
79
|
+
"memory_count": len(self.memories),
|
|
80
|
+
"archive_count": len(self.archive),
|
|
81
|
+
"palace_count": len(palace_counts),
|
|
82
|
+
"palace_flow": [m.get("palace", "?") for m in self.memories[-5:]],
|
|
83
|
+
"palace_distribution": palace_counts,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
def ont_self(self) -> float:
|
|
87
|
+
"""Compute self-consistency: mean C_ij · I_j across all active pairs."""
|
|
88
|
+
mems = self.memories
|
|
89
|
+
n = len(mems)
|
|
90
|
+
if n < 2:
|
|
91
|
+
return 0.0
|
|
92
|
+
total = 0.0
|
|
93
|
+
pairs = 0
|
|
94
|
+
for i in range(n):
|
|
95
|
+
for j in range(i + 1, n):
|
|
96
|
+
c = 1.0 if mems[i].get("palace") == mems[j].get("palace") else 0.0
|
|
97
|
+
ii = mems[i].get("confidence", 0.5)
|
|
98
|
+
ij = mems[j].get("confidence", 0.5)
|
|
99
|
+
total += c * (ii + ij) / 2.0
|
|
100
|
+
pairs += 1
|
|
101
|
+
return total / pairs if pairs else 0.0
|
|
102
|
+
|
|
103
|
+
# ── trace ──
|
|
104
|
+
|
|
105
|
+
def trace(self) -> list[dict]:
|
|
106
|
+
"""Return full memory history with HMM labels for inspection."""
|
|
107
|
+
return [
|
|
108
|
+
{"content": m["content"][:60], "palace": m.get("palace"), "tick": m.get("tick")}
|
|
109
|
+
for m in (self.memories + self.archive)
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
# ── internals ──
|
|
113
|
+
|
|
114
|
+
def _resolve_palace(self, content: str, tool: Optional[Callable] = None) -> str:
|
|
115
|
+
if tool and tool.__name__ in self._palace_registry:
|
|
116
|
+
return self._palace_registry[tool.__name__]["palace"]
|
|
117
|
+
# fallback: hash-based palace for unrecognized content
|
|
118
|
+
h = hash(content) & 0xFFFF
|
|
119
|
+
return f"P_hash_{h % 64:02d}"
|
|
120
|
+
|
|
121
|
+
def _coupling_density(self) -> float:
|
|
122
|
+
mems = self.memories
|
|
123
|
+
if len(mems) < 2:
|
|
124
|
+
return 0.0
|
|
125
|
+
same = sum(1 for i in range(len(mems)) for j in range(i + 1, len(mems))
|
|
126
|
+
if mems[i].get("palace") == mems[j].get("palace"))
|
|
127
|
+
total = len(mems) * (len(mems) - 1) / 2.0
|
|
128
|
+
return same / total if total else 0.0
|
|
129
|
+
|
|
130
|
+
def _palace_distribution(self) -> dict:
|
|
131
|
+
counts = defaultdict(int)
|
|
132
|
+
for m in self.memories:
|
|
133
|
+
counts[m.get("palace", "?")] += 1
|
|
134
|
+
return dict(sorted(counts.items(), key=lambda x: -x[1]))
|
|
135
|
+
|
|
136
|
+
def _scan_hmm(self):
|
|
137
|
+
"""Update HMM state from memory delta distribution."""
|
|
138
|
+
mems = self.memories
|
|
139
|
+
if len(mems) < 3:
|
|
140
|
+
return
|
|
141
|
+
ticks = [m.get("tick", i) for i, m in enumerate(mems)]
|
|
142
|
+
deltas = [ticks[i] - ticks[i - 1] for i in range(1, len(ticks))]
|
|
143
|
+
# simple empirical update
|
|
144
|
+
mean_delta = sum(deltas) / len(deltas) if deltas else 1.0
|
|
145
|
+
large_delta_ratio = sum(1 for d in deltas if d > mean_delta * 1.5) / len(deltas) if deltas else 0.0
|
|
146
|
+
self._hmm.update(large_delta_ratio)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class _HMM:
|
|
150
|
+
"""Minimal 2-state HMM tracking s₀ (stable) / s₁ (searching)."""
|
|
151
|
+
|
|
152
|
+
def __init__(self):
|
|
153
|
+
self.state = "s0"
|
|
154
|
+
self.posterior_s1 = 0.0
|
|
155
|
+
self._A = [[0.85, 0.15], [0.20, 0.80]] # transition matrix
|
|
156
|
+
self._B = [[0.70, 0.30], [0.25, 0.75]] # emission (s0 prefers small-delta, s1 prefers large)
|
|
157
|
+
|
|
158
|
+
def update(self, large_ratio: float):
|
|
159
|
+
# simple forward pass
|
|
160
|
+
like_s0 = self._B[0][0] * (1 - large_ratio) + self._B[0][1] * large_ratio
|
|
161
|
+
like_s1 = self._B[1][0] * (1 - large_ratio) + self._B[1][1] * large_ratio
|
|
162
|
+
total = like_s0 + like_s1
|
|
163
|
+
self.posterior_s1 = like_s1 / total if total > 0 else 0.5
|
|
164
|
+
if self.state == "s0":
|
|
165
|
+
self.state = "s1" if self.posterior_s1 > 0.55 else "s0"
|
|
166
|
+
else:
|
|
167
|
+
self.state = "s0" if self.posterior_s1 < 0.40 else "s1"
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vinfty
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: V∞ — cognitive observability layer for any LLM orchestration framework
|
|
5
|
+
Home-page: https://github.com/twincosmos/vinfty
|
|
6
|
+
Author: V∞ Project
|
|
7
|
+
Author-email: vinfty@twincosmos.dev
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: cognitive-architecture observability llm-orchestration v-infty
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: author-email
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: keywords
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-python
|
|
28
|
+
Dynamic: summary
|
|
29
|
+
|
|
30
|
+
# V∞ (vinfty)
|
|
31
|
+
|
|
32
|
+
**Cognitive observability layer for any LLM orchestration framework.**
|
|
33
|
+
|
|
34
|
+
Vinfty is a featherweight (~300 lines) Python library that adds cognitive observability to your LLM pipelines — without replacing your existing tools. It measures **ont_self** (self-consistency), tracks **C_ij coupling** (cross-session memory coherence), and detects **HMM s₀/s₁ state transitions** — so you know whether your system is healthy, not just whether it returned a valid JSON.
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
pip install vinfty
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Why?
|
|
43
|
+
|
|
44
|
+
LangChain, CrewAI, AutoGen — they all solve "how to call LLMs in sequence." None of them answer:
|
|
45
|
+
|
|
46
|
+
- Is my agent system getting more coherent or more chaotic over time?
|
|
47
|
+
- Are my tool calls producing consistent results or contradicting each other?
|
|
48
|
+
- Is the system in a stable (s₀) or active-search (s₁) mode?
|
|
49
|
+
|
|
50
|
+
Vinfty adds that layer. It wraps any orchestration framework and gives you a **cognitive dashboard**: ont_self trajectory, coupling matrix, HMM state, palace routing.
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from vinfty import V9Orchestrator
|
|
56
|
+
|
|
57
|
+
engine = V9Orchestrator(active_k=100)
|
|
58
|
+
|
|
59
|
+
# Register any function as a tool → maps to a Palace domain
|
|
60
|
+
@engine.register(palace="P_search")
|
|
61
|
+
def search_web(q: str) -> str:
|
|
62
|
+
return f"search results for {q}"
|
|
63
|
+
|
|
64
|
+
@engine.register(palace="P_analysis")
|
|
65
|
+
def calculate(expr: str) -> float:
|
|
66
|
+
return eval(expr)
|
|
67
|
+
|
|
68
|
+
# Each call updates the cognitive state
|
|
69
|
+
engine.step("search latest LLM papers", tool=search_web)
|
|
70
|
+
engine.step("how many published this month?", tool=calculate)
|
|
71
|
+
|
|
72
|
+
# Check system health
|
|
73
|
+
report = engine.report()
|
|
74
|
+
# → {
|
|
75
|
+
# "ont_self": 0.72,
|
|
76
|
+
# "hmm_state": "s0"|"s1",
|
|
77
|
+
# "palace_flow": ["P_query", "P_search", "P_analysis"],
|
|
78
|
+
# "c_ij_density": 0.34,
|
|
79
|
+
# "memory_count": 12,
|
|
80
|
+
# }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Core Concepts
|
|
84
|
+
|
|
85
|
+
| Concept | What it measures | Analogy |
|
|
86
|
+
|---------|-----------------|---------|
|
|
87
|
+
| **ont_self** | System self-consistency | "Is my agent making consistent decisions?" |
|
|
88
|
+
| **C_ij** | Cross-session memory coupling | "Do past decisions influence present ones coherently?" |
|
|
89
|
+
| **HMM s₀/s₁** | Cognitive mode | "Is the system in stable execution (s₀) or active exploration (s₁)?" |
|
|
90
|
+
| **Palace** | Functional domain | "Which cognitive domain is each tool call serving?" |
|
|
91
|
+
|
|
92
|
+
## Adapters
|
|
93
|
+
|
|
94
|
+
Vinfty ships with adapters for common frameworks:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
# LangChain adapter
|
|
98
|
+
from vinfty.adapters.langchain import LangChainAdapter
|
|
99
|
+
|
|
100
|
+
adapter = LangChainAdapter(agent)
|
|
101
|
+
report = adapter.run_with_observability(user_query)
|
|
102
|
+
# Same result as agent.run(), plus cognitive report
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## No LLM Required
|
|
106
|
+
|
|
107
|
+
Vinfty is pure symbolic computation — no API keys, no GPU, no model weights. The cognitive metrics are derived from the **structure** of your tool calls and memory traces, not from the content of LLM responses.
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
tests/test_core.py
|
|
6
|
+
vinfty/__init__.py
|
|
7
|
+
vinfty/core.py
|
|
8
|
+
vinfty.egg-info/PKG-INFO
|
|
9
|
+
vinfty.egg-info/SOURCES.txt
|
|
10
|
+
vinfty.egg-info/dependency_links.txt
|
|
11
|
+
vinfty.egg-info/top_level.txt
|
|
12
|
+
vinfty/adapters/__init__.py
|
|
13
|
+
vinfty/adapters/langchain.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
vinfty
|