anysql-sdk 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.
Files changed (34) hide show
  1. anysql_sdk-0.1.0/.github/workflows/pr-check.yml +80 -0
  2. anysql_sdk-0.1.0/.github/workflows/release.yml +94 -0
  3. anysql_sdk-0.1.0/.gitignore +16 -0
  4. anysql_sdk-0.1.0/PKG-INFO +345 -0
  5. anysql_sdk-0.1.0/README.md +308 -0
  6. anysql_sdk-0.1.0/anysql/__init__.py +82 -0
  7. anysql_sdk-0.1.0/anysql/adapters/__init__.py +0 -0
  8. anysql_sdk-0.1.0/anysql/adapters/claude.py +103 -0
  9. anysql_sdk-0.1.0/anysql/adapters/generic.py +45 -0
  10. anysql_sdk-0.1.0/anysql/adapters/openai.py +108 -0
  11. anysql_sdk-0.1.0/anysql/cli.py +48 -0
  12. anysql_sdk-0.1.0/anysql/context.py +131 -0
  13. anysql_sdk-0.1.0/anysql/engine.py +386 -0
  14. anysql_sdk-0.1.0/anysql/schema.py +122 -0
  15. anysql_sdk-0.1.0/anysql/storage.py +73 -0
  16. anysql_sdk-0.1.0/anysql/tracers/__init__.py +0 -0
  17. anysql_sdk-0.1.0/anysql/tracers/agent.py +131 -0
  18. anysql_sdk-0.1.0/anysql/tracers/rag.py +116 -0
  19. anysql_sdk-0.1.0/docs/ANYSQL_CLAUDE_CODE.md +1648 -0
  20. anysql_sdk-0.1.0/docs/QUERIES.md +85 -0
  21. anysql_sdk-0.1.0/docs/plans/2026-03-09-anysql-implementation.md +2133 -0
  22. anysql_sdk-0.1.0/docs/plans/2026-03-09-anysql-v0.1.0-design.md +184 -0
  23. anysql_sdk-0.1.0/docs/plans/2026-03-09-pypi-cicd-design.md +68 -0
  24. anysql_sdk-0.1.0/docs/plans/2026-03-09-pypi-cicd-implementation.md +231 -0
  25. anysql_sdk-0.1.0/examples/realtime_claude_demo.py +152 -0
  26. anysql_sdk-0.1.0/examples/realtime_combined_demo.py +247 -0
  27. anysql_sdk-0.1.0/examples/realtime_openai_demo.py +158 -0
  28. anysql_sdk-0.1.0/pyproject.toml +52 -0
  29. anysql_sdk-0.1.0/tests/__init__.py +0 -0
  30. anysql_sdk-0.1.0/tests/test_adapters.py +199 -0
  31. anysql_sdk-0.1.0/tests/test_engine.py +239 -0
  32. anysql_sdk-0.1.0/tests/test_schema.py +91 -0
  33. anysql_sdk-0.1.0/tests/test_storage.py +95 -0
  34. anysql_sdk-0.1.0/tests/test_tracers.py +208 -0
@@ -0,0 +1,80 @@
1
+ # .github/workflows/pr-check.yml
2
+ name: PR Checks
3
+
4
+ on:
5
+ pull_request:
6
+ branches: [main]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ name: Tests (Python ${{ matrix.python-version }})
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ python-version: ["3.10", "3.11", "3.12"]
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+ - name: Install dependencies
25
+ run: pip install -e ".[dev]"
26
+ - name: Run tests
27
+ run: pytest tests/ -v --tb=short
28
+
29
+ lint:
30
+ name: Lint
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ - uses: actions/setup-python@v5
35
+ with:
36
+ python-version: "3.12"
37
+ - name: Install dependencies
38
+ run: pip install -e ".[dev]"
39
+ - name: Check lint
40
+ run: ruff check anysql/
41
+ - name: Check format
42
+ run: ruff format --check anysql/
43
+
44
+ version-check:
45
+ name: Version Bump Check
46
+ runs-on: ubuntu-latest
47
+ steps:
48
+ - uses: actions/checkout@v4
49
+ with:
50
+ fetch-depth: 0
51
+ - uses: actions/setup-python@v5
52
+ with:
53
+ python-version: "3.12"
54
+ - name: Check version was bumped
55
+ run: |
56
+ MAIN_VERSION=$(git show origin/main:pyproject.toml | python3 -c "
57
+ import sys, re
58
+ content = sys.stdin.read()
59
+ match = re.search(r'^version\s*=\s*\"([^\"]+)\"', content, re.MULTILINE)
60
+ if not match:
61
+ print('ERROR: could not find version in origin/main:pyproject.toml', file=sys.stderr)
62
+ sys.exit(1)
63
+ print(match.group(1))
64
+ ")
65
+ PR_VERSION=$(python3 -c "
66
+ import re, sys
67
+ content = open('pyproject.toml').read()
68
+ match = re.search(r'^version\s*=\s*\"([^\"]+)\"', content, re.MULTILINE)
69
+ if not match:
70
+ print('ERROR: could not find version in pyproject.toml', file=sys.stderr)
71
+ sys.exit(1)
72
+ print(match.group(1))
73
+ ")
74
+ echo "main version: $MAIN_VERSION"
75
+ echo "PR version: $PR_VERSION"
76
+ if [ "$MAIN_VERSION" = "$PR_VERSION" ]; then
77
+ echo "ERROR: Version $PR_VERSION already exists on main — bump the version in pyproject.toml"
78
+ exit 1
79
+ fi
80
+ echo "OK: version bumped $MAIN_VERSION → $PR_VERSION"
@@ -0,0 +1,94 @@
1
+ # .github/workflows/release.yml
2
+ name: Release
3
+
4
+ on:
5
+ push:
6
+ branches: [main]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ check-version:
13
+ name: Check version is new
14
+ runs-on: ubuntu-latest
15
+ outputs:
16
+ is_new: ${{ steps.check.outputs.is_new }}
17
+ version: ${{ steps.check.outputs.version }}
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0 # required: git tag -l needs full tag history
22
+ - name: Check if version tag exists
23
+ id: check
24
+ run: |
25
+ VERSION=$(python3 -c "
26
+ import re, sys
27
+ content = open('pyproject.toml').read()
28
+ match = re.search(r'^version\s*=\s*\"([^\"]+)\"', content, re.MULTILINE)
29
+ if not match:
30
+ print('ERROR: could not find version in pyproject.toml', file=sys.stderr)
31
+ sys.exit(1)
32
+ print(match.group(1))
33
+ ")
34
+ echo "Detected version: $VERSION"
35
+ if git tag -l "v$VERSION" | grep -q "v$VERSION"; then
36
+ echo "Version v$VERSION already tagged — skipping release"
37
+ echo "is_new=false" >> $GITHUB_OUTPUT
38
+ else
39
+ echo "Version v$VERSION is new — proceeding with release"
40
+ echo "is_new=true" >> $GITHUB_OUTPUT
41
+ fi
42
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
43
+
44
+ build:
45
+ name: Build distribution
46
+ needs: check-version
47
+ if: needs.check-version.outputs.is_new == 'true'
48
+ runs-on: ubuntu-latest
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ - uses: actions/setup-python@v5
52
+ with:
53
+ python-version: "3.12"
54
+ - name: Install build tools
55
+ run: pip install hatchling build
56
+ - name: Build wheel and sdist
57
+ run: python -m build
58
+ - name: Upload dist artifacts
59
+ uses: actions/upload-artifact@v4
60
+ with:
61
+ name: dist
62
+ path: dist/
63
+
64
+ publish:
65
+ name: Publish to PyPI
66
+ needs: [build, check-version]
67
+ if: needs.check-version.outputs.is_new == 'true' && needs.build.result == 'success'
68
+ runs-on: ubuntu-latest
69
+ environment: pypi
70
+ permissions:
71
+ id-token: write
72
+ steps:
73
+ - name: Download dist artifacts
74
+ uses: actions/download-artifact@v4
75
+ with:
76
+ name: dist
77
+ path: dist/
78
+ - name: Publish to PyPI
79
+ uses: pypa/gh-action-pypi-publish@release/v1
80
+
81
+ release:
82
+ name: Create GitHub Release
83
+ needs: [publish, check-version]
84
+ if: needs.check-version.outputs.is_new == 'true' && needs.publish.result == 'success'
85
+ runs-on: ubuntu-latest
86
+ permissions:
87
+ contents: write
88
+ steps:
89
+ - name: Create GitHub Release
90
+ uses: softprops/action-gh-release@v2
91
+ with:
92
+ tag_name: v${{ needs.check-version.outputs.version }}
93
+ name: anySQL v${{ needs.check-version.outputs.version }}
94
+ generate_release_notes: true
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ .Python
6
+ *.egg-info/
7
+ dist/
8
+ build/
9
+ .eggs/
10
+ *.egg
11
+ .venv/
12
+ venv/
13
+ .env
14
+ .DS_Store
15
+ *.sqlite
16
+ *.db
@@ -0,0 +1,345 @@
1
+ Metadata-Version: 2.4
2
+ Name: anysql-sdk
3
+ Version: 0.1.0
4
+ Summary: SQL analytics for AI systems — query LLM responses, agent traces, and RAG pipelines like a database
5
+ Project-URL: Homepage, https://anysql.org
6
+ Project-URL: Repository, https://github.com/sadayamuthu/anySQL
7
+ Project-URL: Documentation, https://docs.anysql.org
8
+ License: Apache-2.0
9
+ Keywords: agents,ai,anthropic,duckdb,eval,llm,observability,openai,rag,sql
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: duckdb>=0.10.0
19
+ Requires-Dist: pandas>=2.0.0
20
+ Requires-Dist: pyarrow>=14.0.0
21
+ Provides-Extra: all
22
+ Requires-Dist: anthropic>=0.25.0; extra == 'all'
23
+ Requires-Dist: langchain>=0.2.0; extra == 'all'
24
+ Requires-Dist: openai>=1.0.0; extra == 'all'
25
+ Provides-Extra: anthropic
26
+ Requires-Dist: anthropic>=0.25.0; extra == 'anthropic'
27
+ Provides-Extra: dev
28
+ Requires-Dist: black; extra == 'dev'
29
+ Requires-Dist: pytest-asyncio; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
31
+ Requires-Dist: ruff; extra == 'dev'
32
+ Provides-Extra: langchain
33
+ Requires-Dist: langchain>=0.2.0; extra == 'langchain'
34
+ Provides-Extra: openai
35
+ Requires-Dist: openai>=1.0.0; extra == 'openai'
36
+ Description-Content-Type: text/markdown
37
+
38
+ <div align="center">
39
+
40
+ # anySQL
41
+
42
+ <h3>SQL Analytics for AI Systems</h3>
43
+
44
+ <p>From vibes to queries.</p>
45
+
46
+ [![CI](https://img.shields.io/badge/CI-passing-brightgreen?style=flat-square)](https://github.com/karthik/anysql/actions)
47
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue?style=flat-square)](https://www.python.org/downloads/)
48
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-green?style=flat-square)](LICENSE)
49
+ [![PyPI](https://img.shields.io/badge/PyPI-anysql-orange?style=flat-square)](https://pypi.org/project/anysql/)
50
+
51
+ ---
52
+
53
+ [Quick Start](#quick-start) · [How It Works](#how-it-works) · [5 Use Cases](#the-5-use-cases) · [Installation](#installation) · [CLI Usage](#cli-usage) · [Examples](#examples)
54
+
55
+ </div>
56
+
57
+ ---
58
+
59
+ ## What is anySQL?
60
+
61
+ anySQL is an open-source SQL analytics engine for AI systems. It lets engineers query LLM responses, agent traces, and RAG pipelines with standard SQL — powered by DuckDB in-memory, persisted to SQLite, with zero configuration.
62
+
63
+ AI engineers debug with `print()` statements, JSON log files, and pre-built dashboards that show what the tool designer thought you'd want to see. What's missing is raw SQL over normalized AI telemetry data — specifically the cross-layer JOIN that lets you ask whether your RAG pipeline is failing at retrieval or generation.
64
+
65
+ ---
66
+
67
+ ## Quick Start
68
+
69
+ ```bash
70
+ # Install
71
+ pip install anysql
72
+
73
+ # Install with provider support
74
+ pip install "anysql[openai]"
75
+ pip install "anysql[anthropic]"
76
+ pip install "anysql[all]" # OpenAI + Anthropic + LangChain
77
+ ```
78
+
79
+ ```python
80
+ import anysql
81
+
82
+ # Initialize (in-memory by default, or pass a file path for persistence)
83
+ db = anysql.init()
84
+
85
+ # Wrap your OpenAI client — all calls are auto-logged
86
+ client = anysql.openai(openai_client)
87
+
88
+ # Wrap your Anthropic client
89
+ client = anysql.claude(anthropic_client)
90
+
91
+ # Tag pipeline runs for cost attribution
92
+ @anysql.context(feature="search", version="v2")
93
+ def run_search(query):
94
+ ...
95
+
96
+ # Query anything with standard SQL
97
+ df = db.query("SELECT model, AVG(cost_usd) FROM llm_responses GROUP BY model")
98
+
99
+ # Or use built-in analytics methods
100
+ df = db.model_comparison() # UC1: multi-model comparison
101
+ df = db.prompt_regressions() # UC2: regression detection
102
+ df = db.cost_by_feature() # UC3: cost attribution
103
+ df = db.tool_failure_rates() # UC4: agent debugging
104
+ df = db.rag_failure_modes() # UC5: RAG forensics
105
+ ```
106
+
107
+ ---
108
+
109
+ ## How It Works
110
+
111
+ ```
112
+ User Code
113
+ │
114
+ ├── @anysql.context(feature="x") ← Python contextvars, sync+async safe
115
+ ├── OpenAI/Claude wrapped client ← transparent proxy, one-line swap
116
+ ├── AgentTracer (LangChain callback) ← manual or callback-based
117
+ └── RAGTracer.after_retrieval() ← auto-detects LangChain/LlamaIndex/dict
118
+ │
119
+ ▼ insert()
120
+ AnySQL engine
121
+ ├── in-memory buffer (dict lists per table)
122
+ ├── SQLite persistence (JSON blobs, cross-session)
123
+ └── DuckDB (Arrow views, SQL at query time)
124
+ │
125
+ ▼ query()
126
+ 6 PyArrow tables as DuckDB views:
127
+ llm_responses, eval_results, pipeline_runs,
128
+ agent_tool_calls, agent_trace, rag_chunks
129
+ ```
130
+
131
+ **Key design decisions:**
132
+ - Schema enforcement at Arrow layer — SQLite stores raw JSON, validation happens at query time
133
+ - Dot-namespace tables (`llm.responses`) map to flat SQL view names (`llm_responses`)
134
+ - Contextvars for thread-safe and async-safe tagging — no manual pass-through required
135
+
136
+ ---
137
+
138
+ ## The 6 Canonical Tables
139
+
140
+ | Table | Use Cases | Join Keys |
141
+ |-------|-----------|-----------|
142
+ | `llm_responses` | UC1, UC2 | `response_id` |
143
+ | `eval_results` | UC1, UC2, UC5 | `response_id`, `run_id`, `query_id` |
144
+ | `pipeline_runs` | UC3 | `run_id`, `session_id` |
145
+ | `agent_tool_calls` | UC4 | `session_id` |
146
+ | `agent_trace` | UC4 | `session_id` |
147
+ | `rag_chunks` | UC5 | `query_id` ← cross-layer join key |
148
+
149
+ ---
150
+
151
+ ## The 5 Use Cases
152
+
153
+ | UC | Name | Key Methods | What It Answers |
154
+ |----|------|-------------|-----------------|
155
+ | UC1 | Multi-Model Comparison | `model_comparison()`, `model_by_task()` | Which model performs best on my task? |
156
+ | UC2 | Prompt Regression Detection | `prompt_regressions()`, `eval_debt()`, `silent_degradation()` | Did my last prompt change break something? |
157
+ | UC3 | Cost Attribution | `cost_by_feature()`, `cost_anomalies()` | Which feature is burning my LLM budget? |
158
+ | UC4 | Agent Debugging | `tool_failure_rates()`, `loop_detector()`, `session_diff()`, `human_intervention_points()` | Where is my agent getting stuck? |
159
+ | UC5 | RAG Forensics | `rag_failure_modes()`, `chunk_quality_ranking()`, `similarity_calibration()` | Is my RAG failing at retrieval or generation? |
160
+
161
+ The cross-layer join (UC5) is the killer feature — `query_id` threads RAG retrieval to eval results, enabling retrieval vs. generation failure classification.
162
+
163
+ ---
164
+
165
+ ## Installation
166
+
167
+ ### From PyPI
168
+
169
+ ```bash
170
+ pip install anysql
171
+ ```
172
+
173
+ ### Provider extras
174
+
175
+ ```bash
176
+ pip install "anysql[openai]" # + openai>=1.0.0
177
+ pip install "anysql[anthropic]" # + anthropic>=0.25.0
178
+ pip install "anysql[langchain]" # + langchain>=0.2.0
179
+ pip install "anysql[all]" # everything
180
+ ```
181
+
182
+ ---
183
+
184
+ ## CLI Usage
185
+
186
+ ```bash
187
+ # Run a SQL query against a persisted database
188
+ anysql query "SELECT model, COUNT(*) FROM llm_responses GROUP BY model"
189
+
190
+ # Show table row counts and basic stats
191
+ anysql stats
192
+
193
+ # Query a specific database file
194
+ anysql query "SELECT * FROM eval_results LIMIT 10" --db ./myproject.db
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Examples
200
+
201
+ Three runnable demos are included in `examples/`. All auto-detect missing API keys and fall back to mock mode — no downloads required.
202
+
203
+ | Demo | Dataset | Models |
204
+ |------|---------|--------|
205
+ | `realtime_openai_demo.py` | BBC News (2004–05), 12 articles | `gpt-4o`, `gpt-4o-mini` |
206
+ | `realtime_claude_demo.py` | AG News, 15 articles | `claude-sonnet-4-6`, `claude-haiku-4-5` |
207
+ | `realtime_combined_demo.py` | Reuters R8, 20 articles | All 4 models head-to-head |
208
+
209
+ ```bash
210
+ # Run combined demo (works without API keys)
211
+ python examples/realtime_combined_demo.py
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Adapter Usage
217
+
218
+ ### OpenAI
219
+
220
+ ```python
221
+ import openai
222
+ import anysql
223
+
224
+ db = anysql.init()
225
+ client = anysql.openai(openai.OpenAI())
226
+
227
+ # All calls now logged automatically
228
+ response = client.chat.completions.create(
229
+ model="gpt-4o",
230
+ messages=[{"role": "user", "content": "Summarize this article..."}]
231
+ )
232
+ ```
233
+
234
+ ### Anthropic
235
+
236
+ ```python
237
+ import anthropic
238
+ import anysql
239
+
240
+ db = anysql.init()
241
+ client = anysql.claude(anthropic.Anthropic())
242
+
243
+ response = client.messages.create(
244
+ model="claude-sonnet-4-6",
245
+ max_tokens=1024,
246
+ messages=[{"role": "user", "content": "Classify this text..."}]
247
+ )
248
+ ```
249
+
250
+ ### Agent Tracing
251
+
252
+ ```python
253
+ tracer = anysql.agent_tracer()
254
+
255
+ # Manual tracing
256
+ tracer.trace_tool_call(
257
+ session_id="sess-001",
258
+ tool_name="web_search",
259
+ input_data={"query": "latest news"},
260
+ output_data={"results": [...]},
261
+ success=True,
262
+ latency_ms=320,
263
+ )
264
+
265
+ # LangChain callback (automatic)
266
+ from langchain_openai import ChatOpenAI
267
+ llm = ChatOpenAI(callbacks=[tracer])
268
+ ```
269
+
270
+ ### RAG Tracing
271
+
272
+ ```python
273
+ rag = anysql.rag_tracer()
274
+
275
+ query_id = rag.before_retrieval(query="What is anySQL?")
276
+ chunks = retriever.get_relevant_documents(query)
277
+ rag.after_retrieval(query_id=query_id, chunks=chunks)
278
+
279
+ # Record eval result with cross-layer join key
280
+ rag.record_eval(
281
+ query_id=query_id,
282
+ score=0.92,
283
+ passed=True,
284
+ eval_type="faithfulness",
285
+ )
286
+ ```
287
+
288
+ ---
289
+
290
+ ## Development
291
+
292
+ ```bash
293
+ pip install -e ".[dev]"
294
+
295
+ pytest tests/ -v # Run tests
296
+ pytest tests/ --tb=short # Short failure output
297
+ ruff check anysql/ # Lint
298
+ ruff format anysql/ # Format
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Repository Structure
304
+
305
+ ```
306
+ anysql/
307
+ ├── anysql/
308
+ │ ├── __init__.py # Public API surface
309
+ │ ├── engine.py # DuckDB engine + UC analytics methods
310
+ │ ├── schema.py # 6 PyArrow schemas
311
+ │ ├── storage.py # SQLite persistence
312
+ │ ├── context.py # @context decorator + context_scope()
313
+ │ ├── cli.py # CLI entry point
314
+ │ ├── adapters/
315
+ │ │ ├── openai.py # OpenAI transparent proxy
316
+ │ │ ├── claude.py # Anthropic transparent proxy
317
+ │ │ └── generic.py # Generic JSON/dict adapter
318
+ │ └── tracers/
319
+ │ ├── agent.py # AgentTracer (manual + LangChain)
320
+ │ └── rag.py # RAGTracer (LangChain/LlamaIndex/dict)
321
+ ├── tests/ # 94 tests, all passing
322
+ ├── examples/ # 3 runnable demos
323
+ └── docs/
324
+ └── QUERIES.md # Canonical SQL query library
325
+ ```
326
+
327
+ ---
328
+
329
+ ## License
330
+
331
+ Apache 2.0
332
+
333
+ ---
334
+
335
+ <div align="center">
336
+
337
+ **anySQL is an open-source SQL analytics engine for AI systems**
338
+
339
+ anySQL is managed by [OpenAstra](https://openastra.org) · [anysql.org](https://anysql.org)
340
+
341
+ [PyPI](https://pypi.org/project/anysql/) · [GitHub](https://github.com/karthik/anysql) · [Docs](https://docs.anysql.org)
342
+
343
+ </div>
344
+
345
+ ---