sozograph 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.
@@ -0,0 +1,54 @@
1
+ # -----------------------------
2
+ # Python
3
+ # -----------------------------
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # Virtual environments
9
+ .venv/
10
+ venv/
11
+ ENV/
12
+ env/
13
+
14
+ # Build artifacts
15
+ build/
16
+ dist/
17
+ *.egg-info/
18
+ .eggs/
19
+
20
+ # Packaging
21
+ pip-wheel-metadata/
22
+
23
+ # -----------------------------
24
+ # Environment / secrets
25
+ # -----------------------------
26
+ .env
27
+ .env.*
28
+ !.env.example
29
+
30
+ # -----------------------------
31
+ # Editors / IDEs
32
+ # -----------------------------
33
+ .vscode/
34
+ .idea/
35
+ *.swp
36
+ *.swo
37
+ .DS_Store
38
+
39
+ # -----------------------------
40
+ # Testing / coverage
41
+ # -----------------------------
42
+ .pytest_cache/
43
+ .coverage
44
+ htmlcov/
45
+
46
+ # -----------------------------
47
+ # Logs
48
+ # -----------------------------
49
+ *.log
50
+
51
+ # -----------------------------
52
+ # OS
53
+ # -----------------------------
54
+ Thumbs.db
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sozo Analytics Lab
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.
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.4
2
+ Name: sozograph
3
+ Version: 0.1.0
4
+ Summary: SozoGraph v1: transcript/db object -> portable cognitive passport JSON
5
+ Project-URL: Homepage, https://github.com/quantilytix/sozograph
6
+ Project-URL: Repository, https://github.com/quantilytix/sozograph
7
+ Project-URL: Issues, https://github.com/quantilytix/sozograph/issues
8
+ Author: Rairo Mukamuri
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,context,gemini,knowledge,memory,passport
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: google-genai>=0.6.0
22
+ Requires-Dist: pydantic>=2.7.0
23
+ Requires-Dist: python-dotenv>=1.0.1
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
26
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+
30
+ # SozoGraph (v1) — The Cognitive Passport
31
+
32
+ **SozoGraph** turns interaction history (transcripts + DB objects) into a **portable cognitive snapshot** you can pass into any AI agent context on the fly.
33
+
34
+ It answers one question cleanly:
35
+
36
+ > "Given everything that has happened so far, what should an agent **currently believe** about this user?"
37
+
38
+ Not:
39
+ - what was said
40
+ - what is similar
41
+ - what might be relevant
42
+
43
+ But:
44
+ - what is true now
45
+ - what is stable
46
+ - what is unresolved
47
+ - what is contradictory (resolved by time)
48
+
49
+ ---
50
+
51
+ ## Why this exists (the problem)
52
+
53
+ Most "memory" systems are either:
54
+ - **prompt stuffing** (expensive, degrades reasoning, no forgetting)
55
+ - **vector RAG** (good recall, weak truth/temporal consistency)
56
+ - **app-specific notes** (non-portable, brittle schemas)
57
+
58
+ So agents keep acting like "goldfish" even when data exists.
59
+
60
+ SozoGraph v1 is a **truth-layer memory object**:
61
+ - typed (facts vs preferences vs entities vs open loops)
62
+ - temporal (new updates override old; contradictions are explicit)
63
+ - portable (a lightweight JSON passport + a compact context string)
64
+
65
+ ---
66
+
67
+ ## Install
68
+
69
+ ```bash
70
+ pip install sozograph
71
+ ```
72
+
73
+ -----
74
+
75
+ ## Configure
76
+
77
+ Create a `.env` file (see `.env.example`):
78
+
79
+ ```env
80
+ GEMINI_API_KEY=your_key_here
81
+ SOZOGRAPH_EXTRACTOR_MODEL=gemini-3-flash
82
+ SOZOGRAPH_ENABLE_FALLBACK_SUMMARIZER=true
83
+ SOZOGRAPH_MAX_INTERACTION_CHARS=4000
84
+ SOZOGRAPH_DEFAULT_CONTEXT_BUDGET=3000
85
+ ```
86
+
87
+ -----
88
+
89
+ ## Quickstart
90
+
91
+ ### 1) Single transcript → Passport
92
+
93
+ ```python
94
+ from sozograph import SozoGraph
95
+
96
+ sg = SozoGraph()
97
+
98
+ passport, stats = sg.ingest(
99
+ "I'm Quantilytix. I build software and want direct answers. I'm working on SozoGraph v1.",
100
+ meta={"user_key": "u_123", "source": "transcript:demo-1"}
101
+ )
102
+
103
+ print(passport.to_compact_dict())
104
+ print(stats) # per-interaction merge stats
105
+ ```
106
+
107
+ -----
108
+
109
+ ### 2) List of transcripts / message history (supported ✅)
110
+
111
+ ```python
112
+ history = [
113
+ {"createdAt": "2026-02-01T10:00:00Z", "project_title": "SozoFix", "transcript": "I'm renovating my kitchen."},
114
+ {"createdAt": "2026-02-02T09:30:00Z", "project_title": "SozoFix", "transcript": "I prefer rustic style and hate glossy paint."},
115
+ {"createdAt": "2026-02-03T12:10:00Z", "project_title": "SozoGraph", "transcript": "We need portable memory JSON. No infra. Truth-layer."},
116
+ ]
117
+
118
+ # You can ingest a list directly. SozoGraph will coerce items internally.
119
+ passport, _ = sg.ingest(history, hint="firestore") # hint optional; see below
120
+ ```
121
+
122
+ **Tip:** If your list items aren’t “docs”, you can pass them as plain dicts and let fallback summarization help when needed. If your dicts contain a `transcript` field, extraction will still succeed (it will stringify deterministically).
123
+
124
+ -----
125
+
126
+ ### 3) Firestore object ingestion (objects-only)
127
+
128
+ You fetch your Firestore data in your app, then pass the dict here:
129
+
130
+ ```python
131
+ firestore_doc = {
132
+ "id": "abc123",
133
+ "createdAt": "2026-02-03T10:00:00Z",
134
+ "title": "User Profile Update",
135
+ "notes": "User says they prefer direct answers.",
136
+ "companyCode": "QX",
137
+ }
138
+
139
+ passport, _ = sg.ingest(
140
+ firestore_doc,
141
+ hint="firestore",
142
+ meta={"source": "firestore:/users/abc123", "user_key": "u_abc123"}
143
+ )
144
+ ```
145
+
146
+ -----
147
+
148
+ ### 4) Firebase Realtime DB ingestion (path + value)
149
+
150
+ RTDB is tree-based, so pass an envelope:
151
+
152
+ ```python
153
+ rtdb_snapshot = {
154
+ "path": "/users/u1/profile",
155
+ "value": {
156
+ "updatedAt": 1738560000000,
157
+ "displayName": "Quantilytix",
158
+ "preferences": {"tone": "direct"}
159
+ }
160
+ }
161
+
162
+ passport, _ = sg.ingest(rtdb_snapshot, hint="rtdb", meta={"user_key": "u1"})
163
+ ```
164
+
165
+ -----
166
+
167
+ ### 5) Supabase ingestion (table + row)
168
+
169
+ ```python
170
+ supabase_row = {
171
+ "table": "events",
172
+ "row": {
173
+ "id": 77,
174
+ "created_at": "2026-02-03T11:22:00Z",
175
+ "event": "user_preference_update",
176
+ "notes": "User wants strategy alignment before code."
177
+ }
178
+ }
179
+
180
+ passport, _ = sg.ingest(supabase_row, hint="supabase", meta={"user_key": "u1"})
181
+ ```
182
+ # SozoGraph Test Fixtures
183
+
184
+ These fixtures are **intentionally small and human-readable**.
185
+
186
+ They are designed to test:
187
+ - transcript ingestion
188
+ - Firestore document ingestion
189
+ - Firebase Realtime Database snapshots
190
+ - Supabase row ingestion
191
+
192
+ They are NOT meant to simulate production-scale data.
193
+ If a fixture grows beyond what a human would comfortably read,
194
+ it is probably violating SozoGraph v1 philosophy.
195
+ -----
196
+
197
+ ## Export a compact agent “briefing” (context injection)
198
+
199
+ You can inject this into any agent prompt:
200
+
201
+ ```python
202
+ briefing = sg.export_context(passport, budget_chars=2500)
203
+ print(briefing)
204
+ ```
205
+
206
+ **Example output format:**
207
+
208
+ ```
209
+ SOZOGRAPH PASSPORT v1
210
+ User: u1
211
+ Updated: 2026-02-03T12:34:56+00:00
212
+
213
+ Facts (current beliefs):
214
+ - role: software development
215
+ - current_project: sozograph v1
216
+ ...
217
+
218
+ Preferences:
219
+ - tone: direct
220
+ ...
221
+
222
+ Open loops:
223
+ - finalize v1 repo + publish pip package
224
+ ...
225
+ ```
226
+
227
+ -----
228
+
229
+ ## How SozoGraph v1 works
230
+
231
+ ### Ingestion pipeline (v1)
232
+
233
+ 1. Coerce input into canonical `Interaction` objects (deterministic)
234
+ 1. If the derived text is weak/noisy, call Gemini fallback summarizer (optional)
235
+ 1. Use Gemini extractor (strict JSON) to propose memory updates
236
+ 1. Use deterministic resolver to merge:
237
+
238
+ - temporal priority (latest wins)
239
+ - explicit contradictions record changes
240
+ - de-dupe entities + aliases
241
+ - keep open loops short and recent
242
+
243
+ ### What SozoGraph v1 is NOT
244
+
245
+ - Not a graph database
246
+ - Not RAG
247
+ - Not embeddings
248
+ - Not a long transcript store
249
+ - Not a tool that fetches from DB (objects-only by design)
250
+
251
+ -----
252
+
253
+ ## Roadmap (upcoming features)
254
+
255
+ ### v1.x (near-term)
256
+
257
+ - Better input detection for common “transcript list” shapes (e.g. `{transcript, createdAt}`)
258
+ - CLI:
259
+ - `sozograph ingest transcript.txt --out passport.json`
260
+ - `sozograph render passport.json --budget 3000`
261
+ - Stronger JSON recovery if a model response is slightly malformed
262
+ - More deterministic evidence linking (source-id mapping improvements)
263
+
264
+ ### v1.5 (planned, optional)
265
+
266
+ - Graph engine support (Neo4j Aura / Memgraph) via Bolt
267
+ - Cypher-style relational queries over memory
268
+ - Temporal deprecation on edges
269
+ - Export “active truth subgraph” to context
270
+
271
+ ### v2 (optional)
272
+
273
+ - Foundational model adapters (non-Gemini backends)
274
+ - MCP tool server integration
275
+ - Hybrid patterns (graph + vector) only where needed
276
+
277
+ -----
278
+
279
+ ## Contributing
280
+
281
+ We want contributions, but keep v1 disciplined.
282
+
283
+ ### Good contributions
284
+
285
+ - Adapters for additional object shapes (still objects-only)
286
+ - Resolver improvements (deterministic)
287
+ - Tests for merge/contradiction edge-cases
288
+ - Prompt tuning for more stable key extraction
289
+
290
+ ### What won’t be accepted in v1
291
+
292
+ - Adding DB client dependencies (firebase-admin, supabase clients, etc.)
293
+ - Building RAG/embeddings into core
294
+ - Turning v1 into a graph project
295
+
296
+ ### How to contribute
297
+
298
+ 1. Fork the repo
299
+ 1. Create a branch: `feat/<short-name>`
300
+ 1. Add tests where relevant
301
+ 1. Open a PR with a short explanation and sample input/output
302
+
303
+ -----
304
+
305
+ ## License
306
+
307
+ MIT — Sozo Analytics Lab
308
+
@@ -0,0 +1,280 @@
1
+
2
+ # SozoGraph (v1) — The Cognitive Passport
3
+
4
+ **SozoGraph** turns interaction history (transcripts + DB objects) into a **portable cognitive snapshot** you can pass into any AI agent context on the fly.
5
+
6
+ It answers one question cleanly:
7
+
8
+ > "Given everything that has happened so far, what should an agent **currently believe** about this user?"
9
+
10
+ Not:
11
+ - what was said
12
+ - what is similar
13
+ - what might be relevant
14
+
15
+ But:
16
+ - what is true now
17
+ - what is stable
18
+ - what is unresolved
19
+ - what is contradictory (resolved by time)
20
+
21
+ ---
22
+
23
+ ## Why this exists (the problem)
24
+
25
+ Most "memory" systems are either:
26
+ - **prompt stuffing** (expensive, degrades reasoning, no forgetting)
27
+ - **vector RAG** (good recall, weak truth/temporal consistency)
28
+ - **app-specific notes** (non-portable, brittle schemas)
29
+
30
+ So agents keep acting like "goldfish" even when data exists.
31
+
32
+ SozoGraph v1 is a **truth-layer memory object**:
33
+ - typed (facts vs preferences vs entities vs open loops)
34
+ - temporal (new updates override old; contradictions are explicit)
35
+ - portable (a lightweight JSON passport + a compact context string)
36
+
37
+ ---
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ pip install sozograph
43
+ ```
44
+
45
+ -----
46
+
47
+ ## Configure
48
+
49
+ Create a `.env` file (see `.env.example`):
50
+
51
+ ```env
52
+ GEMINI_API_KEY=your_key_here
53
+ SOZOGRAPH_EXTRACTOR_MODEL=gemini-3-flash
54
+ SOZOGRAPH_ENABLE_FALLBACK_SUMMARIZER=true
55
+ SOZOGRAPH_MAX_INTERACTION_CHARS=4000
56
+ SOZOGRAPH_DEFAULT_CONTEXT_BUDGET=3000
57
+ ```
58
+
59
+ -----
60
+
61
+ ## Quickstart
62
+
63
+ ### 1) Single transcript → Passport
64
+
65
+ ```python
66
+ from sozograph import SozoGraph
67
+
68
+ sg = SozoGraph()
69
+
70
+ passport, stats = sg.ingest(
71
+ "I'm Quantilytix. I build software and want direct answers. I'm working on SozoGraph v1.",
72
+ meta={"user_key": "u_123", "source": "transcript:demo-1"}
73
+ )
74
+
75
+ print(passport.to_compact_dict())
76
+ print(stats) # per-interaction merge stats
77
+ ```
78
+
79
+ -----
80
+
81
+ ### 2) List of transcripts / message history (supported ✅)
82
+
83
+ ```python
84
+ history = [
85
+ {"createdAt": "2026-02-01T10:00:00Z", "project_title": "SozoFix", "transcript": "I'm renovating my kitchen."},
86
+ {"createdAt": "2026-02-02T09:30:00Z", "project_title": "SozoFix", "transcript": "I prefer rustic style and hate glossy paint."},
87
+ {"createdAt": "2026-02-03T12:10:00Z", "project_title": "SozoGraph", "transcript": "We need portable memory JSON. No infra. Truth-layer."},
88
+ ]
89
+
90
+ # You can ingest a list directly. SozoGraph will coerce items internally.
91
+ passport, _ = sg.ingest(history, hint="firestore") # hint optional; see below
92
+ ```
93
+
94
+ **Tip:** If your list items aren’t “docs”, you can pass them as plain dicts and let fallback summarization help when needed. If your dicts contain a `transcript` field, extraction will still succeed (it will stringify deterministically).
95
+
96
+ -----
97
+
98
+ ### 3) Firestore object ingestion (objects-only)
99
+
100
+ You fetch your Firestore data in your app, then pass the dict here:
101
+
102
+ ```python
103
+ firestore_doc = {
104
+ "id": "abc123",
105
+ "createdAt": "2026-02-03T10:00:00Z",
106
+ "title": "User Profile Update",
107
+ "notes": "User says they prefer direct answers.",
108
+ "companyCode": "QX",
109
+ }
110
+
111
+ passport, _ = sg.ingest(
112
+ firestore_doc,
113
+ hint="firestore",
114
+ meta={"source": "firestore:/users/abc123", "user_key": "u_abc123"}
115
+ )
116
+ ```
117
+
118
+ -----
119
+
120
+ ### 4) Firebase Realtime DB ingestion (path + value)
121
+
122
+ RTDB is tree-based, so pass an envelope:
123
+
124
+ ```python
125
+ rtdb_snapshot = {
126
+ "path": "/users/u1/profile",
127
+ "value": {
128
+ "updatedAt": 1738560000000,
129
+ "displayName": "Quantilytix",
130
+ "preferences": {"tone": "direct"}
131
+ }
132
+ }
133
+
134
+ passport, _ = sg.ingest(rtdb_snapshot, hint="rtdb", meta={"user_key": "u1"})
135
+ ```
136
+
137
+ -----
138
+
139
+ ### 5) Supabase ingestion (table + row)
140
+
141
+ ```python
142
+ supabase_row = {
143
+ "table": "events",
144
+ "row": {
145
+ "id": 77,
146
+ "created_at": "2026-02-03T11:22:00Z",
147
+ "event": "user_preference_update",
148
+ "notes": "User wants strategy alignment before code."
149
+ }
150
+ }
151
+
152
+ passport, _ = sg.ingest(supabase_row, hint="supabase", meta={"user_key": "u1"})
153
+ ```
154
+ # SozoGraph Test Fixtures
155
+
156
+ These fixtures are **intentionally small and human-readable**.
157
+
158
+ They are designed to test:
159
+ - transcript ingestion
160
+ - Firestore document ingestion
161
+ - Firebase Realtime Database snapshots
162
+ - Supabase row ingestion
163
+
164
+ They are NOT meant to simulate production-scale data.
165
+ If a fixture grows beyond what a human would comfortably read,
166
+ it is probably violating SozoGraph v1 philosophy.
167
+ -----
168
+
169
+ ## Export a compact agent “briefing” (context injection)
170
+
171
+ You can inject this into any agent prompt:
172
+
173
+ ```python
174
+ briefing = sg.export_context(passport, budget_chars=2500)
175
+ print(briefing)
176
+ ```
177
+
178
+ **Example output format:**
179
+
180
+ ```
181
+ SOZOGRAPH PASSPORT v1
182
+ User: u1
183
+ Updated: 2026-02-03T12:34:56+00:00
184
+
185
+ Facts (current beliefs):
186
+ - role: software development
187
+ - current_project: sozograph v1
188
+ ...
189
+
190
+ Preferences:
191
+ - tone: direct
192
+ ...
193
+
194
+ Open loops:
195
+ - finalize v1 repo + publish pip package
196
+ ...
197
+ ```
198
+
199
+ -----
200
+
201
+ ## How SozoGraph v1 works
202
+
203
+ ### Ingestion pipeline (v1)
204
+
205
+ 1. Coerce input into canonical `Interaction` objects (deterministic)
206
+ 1. If the derived text is weak/noisy, call Gemini fallback summarizer (optional)
207
+ 1. Use Gemini extractor (strict JSON) to propose memory updates
208
+ 1. Use deterministic resolver to merge:
209
+
210
+ - temporal priority (latest wins)
211
+ - explicit contradictions record changes
212
+ - de-dupe entities + aliases
213
+ - keep open loops short and recent
214
+
215
+ ### What SozoGraph v1 is NOT
216
+
217
+ - Not a graph database
218
+ - Not RAG
219
+ - Not embeddings
220
+ - Not a long transcript store
221
+ - Not a tool that fetches from DB (objects-only by design)
222
+
223
+ -----
224
+
225
+ ## Roadmap (upcoming features)
226
+
227
+ ### v1.x (near-term)
228
+
229
+ - Better input detection for common “transcript list” shapes (e.g. `{transcript, createdAt}`)
230
+ - CLI:
231
+ - `sozograph ingest transcript.txt --out passport.json`
232
+ - `sozograph render passport.json --budget 3000`
233
+ - Stronger JSON recovery if a model response is slightly malformed
234
+ - More deterministic evidence linking (source-id mapping improvements)
235
+
236
+ ### v1.5 (planned, optional)
237
+
238
+ - Graph engine support (Neo4j Aura / Memgraph) via Bolt
239
+ - Cypher-style relational queries over memory
240
+ - Temporal deprecation on edges
241
+ - Export “active truth subgraph” to context
242
+
243
+ ### v2 (optional)
244
+
245
+ - Foundational model adapters (non-Gemini backends)
246
+ - MCP tool server integration
247
+ - Hybrid patterns (graph + vector) only where needed
248
+
249
+ -----
250
+
251
+ ## Contributing
252
+
253
+ We want contributions, but keep v1 disciplined.
254
+
255
+ ### Good contributions
256
+
257
+ - Adapters for additional object shapes (still objects-only)
258
+ - Resolver improvements (deterministic)
259
+ - Tests for merge/contradiction edge-cases
260
+ - Prompt tuning for more stable key extraction
261
+
262
+ ### What won’t be accepted in v1
263
+
264
+ - Adding DB client dependencies (firebase-admin, supabase clients, etc.)
265
+ - Building RAG/embeddings into core
266
+ - Turning v1 into a graph project
267
+
268
+ ### How to contribute
269
+
270
+ 1. Fork the repo
271
+ 1. Create a branch: `feat/<short-name>`
272
+ 1. Add tests where relevant
273
+ 1. Open a PR with a short explanation and sample input/output
274
+
275
+ -----
276
+
277
+ ## License
278
+
279
+ MIT — Sozo Analytics Lab
280
+