stratifyai 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.
Files changed (57) hide show
  1. cli/__init__.py +5 -0
  2. cli/stratifyai_cli.py +1753 -0
  3. stratifyai/__init__.py +113 -0
  4. stratifyai/api_key_helper.py +372 -0
  5. stratifyai/caching.py +279 -0
  6. stratifyai/chat/__init__.py +54 -0
  7. stratifyai/chat/builder.py +366 -0
  8. stratifyai/chat/stratifyai_anthropic.py +194 -0
  9. stratifyai/chat/stratifyai_bedrock.py +200 -0
  10. stratifyai/chat/stratifyai_deepseek.py +194 -0
  11. stratifyai/chat/stratifyai_google.py +194 -0
  12. stratifyai/chat/stratifyai_grok.py +194 -0
  13. stratifyai/chat/stratifyai_groq.py +195 -0
  14. stratifyai/chat/stratifyai_ollama.py +201 -0
  15. stratifyai/chat/stratifyai_openai.py +209 -0
  16. stratifyai/chat/stratifyai_openrouter.py +201 -0
  17. stratifyai/chunking.py +158 -0
  18. stratifyai/client.py +292 -0
  19. stratifyai/config.py +1273 -0
  20. stratifyai/cost_tracker.py +257 -0
  21. stratifyai/embeddings.py +245 -0
  22. stratifyai/exceptions.py +91 -0
  23. stratifyai/models.py +59 -0
  24. stratifyai/providers/__init__.py +5 -0
  25. stratifyai/providers/anthropic.py +330 -0
  26. stratifyai/providers/base.py +183 -0
  27. stratifyai/providers/bedrock.py +634 -0
  28. stratifyai/providers/deepseek.py +39 -0
  29. stratifyai/providers/google.py +39 -0
  30. stratifyai/providers/grok.py +39 -0
  31. stratifyai/providers/groq.py +39 -0
  32. stratifyai/providers/ollama.py +43 -0
  33. stratifyai/providers/openai.py +344 -0
  34. stratifyai/providers/openai_compatible.py +372 -0
  35. stratifyai/providers/openrouter.py +39 -0
  36. stratifyai/py.typed +2 -0
  37. stratifyai/rag.py +381 -0
  38. stratifyai/retry.py +185 -0
  39. stratifyai/router.py +643 -0
  40. stratifyai/summarization.py +179 -0
  41. stratifyai/utils/__init__.py +11 -0
  42. stratifyai/utils/bedrock_validator.py +136 -0
  43. stratifyai/utils/code_extractor.py +327 -0
  44. stratifyai/utils/csv_extractor.py +197 -0
  45. stratifyai/utils/file_analyzer.py +192 -0
  46. stratifyai/utils/json_extractor.py +219 -0
  47. stratifyai/utils/log_extractor.py +267 -0
  48. stratifyai/utils/model_selector.py +324 -0
  49. stratifyai/utils/provider_validator.py +442 -0
  50. stratifyai/utils/token_counter.py +186 -0
  51. stratifyai/vectordb.py +344 -0
  52. stratifyai-0.1.0.dist-info/METADATA +263 -0
  53. stratifyai-0.1.0.dist-info/RECORD +57 -0
  54. stratifyai-0.1.0.dist-info/WHEEL +5 -0
  55. stratifyai-0.1.0.dist-info/entry_points.txt +2 -0
  56. stratifyai-0.1.0.dist-info/licenses/LICENSE +21 -0
  57. stratifyai-0.1.0.dist-info/top_level.txt +2 -0
stratifyai/vectordb.py ADDED
@@ -0,0 +1,344 @@
1
+ """Vector database integration for RAG and semantic search.
2
+
3
+ This module provides abstraction for storing and retrieving document embeddings
4
+ using ChromaDB (with potential support for other vector databases).
5
+ """
6
+
7
+ from dataclasses import dataclass
8
+ from typing import List, Optional, Dict, Any
9
+ from pathlib import Path
10
+ import uuid
11
+ from datetime import datetime
12
+
13
+ try:
14
+ import chromadb
15
+ from chromadb.config import Settings
16
+ CHROMADB_AVAILABLE = True
17
+ except ImportError:
18
+ CHROMADB_AVAILABLE = False
19
+
20
+ from .embeddings import EmbeddingProvider
21
+ from .exceptions import LLMAbstractionError
22
+
23
+
24
+ @dataclass
25
+ class SearchResult:
26
+ """Result from a semantic search query.
27
+
28
+ Attributes:
29
+ document: The matched document text
30
+ metadata: Document metadata (file, chunk_idx, etc.)
31
+ distance: Distance score (lower = more similar)
32
+ doc_id: Unique document ID
33
+ """
34
+ document: str
35
+ metadata: Dict[str, Any]
36
+ distance: float
37
+ doc_id: str
38
+
39
+
40
+ class VectorDBClient:
41
+ """Client for vector database operations using ChromaDB.
42
+
43
+ Provides document storage, retrieval, and semantic search capabilities.
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ embedding_provider: EmbeddingProvider,
49
+ persist_directory: Optional[str] = None
50
+ ):
51
+ """Initialize vector database client.
52
+
53
+ Args:
54
+ embedding_provider: Provider for generating embeddings
55
+ persist_directory: Directory to persist database (default: ./chroma_db)
56
+
57
+ Raises:
58
+ LLMAbstractionError: If ChromaDB is not installed
59
+ """
60
+ if not CHROMADB_AVAILABLE:
61
+ raise LLMAbstractionError(
62
+ "ChromaDB is not installed. Install with: pip install chromadb"
63
+ )
64
+
65
+ self.embedding_provider = embedding_provider
66
+ self.persist_directory = persist_directory or "./chroma_db"
67
+
68
+ # Initialize ChromaDB client
69
+ self.client = chromadb.PersistentClient(
70
+ path=self.persist_directory,
71
+ settings=Settings(anonymized_telemetry=False)
72
+ )
73
+
74
+ def create_collection(
75
+ self,
76
+ name: str,
77
+ metadata: Optional[Dict[str, Any]] = None
78
+ ) -> str:
79
+ """Create a new collection.
80
+
81
+ Args:
82
+ name: Collection name
83
+ metadata: Optional collection metadata
84
+
85
+ Returns:
86
+ Collection name
87
+
88
+ Raises:
89
+ LLMAbstractionError: If collection already exists
90
+ """
91
+ try:
92
+ self.client.create_collection(
93
+ name=name,
94
+ metadata=metadata or {}
95
+ )
96
+ return name
97
+ except Exception as e:
98
+ if "already exists" in str(e).lower():
99
+ raise LLMAbstractionError(
100
+ f"Collection '{name}' already exists. Use get_collection() or delete it first."
101
+ )
102
+ raise LLMAbstractionError(f"Failed to create collection: {str(e)}")
103
+
104
+ def get_collection(self, name: str):
105
+ """Get an existing collection.
106
+
107
+ Args:
108
+ name: Collection name
109
+
110
+ Returns:
111
+ ChromaDB collection object
112
+
113
+ Raises:
114
+ LLMAbstractionError: If collection doesn't exist
115
+ """
116
+ try:
117
+ return self.client.get_collection(name=name)
118
+ except Exception as e:
119
+ raise LLMAbstractionError(
120
+ f"Collection '{name}' not found. Create it with create_collection()."
121
+ )
122
+
123
+ def get_or_create_collection(self, name: str):
124
+ """Get existing collection or create if it doesn't exist.
125
+
126
+ Args:
127
+ name: Collection name
128
+
129
+ Returns:
130
+ ChromaDB collection object
131
+ """
132
+ return self.client.get_or_create_collection(name=name)
133
+
134
+ def list_collections(self) -> List[str]:
135
+ """List all collections.
136
+
137
+ Returns:
138
+ List of collection names
139
+ """
140
+ collections = self.client.list_collections()
141
+ return [col.name for col in collections]
142
+
143
+ def delete_collection(self, name: str) -> None:
144
+ """Delete a collection.
145
+
146
+ Args:
147
+ name: Collection name
148
+ """
149
+ try:
150
+ self.client.delete_collection(name=name)
151
+ except Exception as e:
152
+ raise LLMAbstractionError(f"Failed to delete collection: {str(e)}")
153
+
154
+ def add_documents(
155
+ self,
156
+ collection_name: str,
157
+ documents: List[str],
158
+ metadatas: Optional[List[Dict[str, Any]]] = None,
159
+ ids: Optional[List[str]] = None
160
+ ) -> List[str]:
161
+ """Add documents to a collection.
162
+
163
+ Args:
164
+ collection_name: Collection name
165
+ documents: List of document texts
166
+ metadatas: Optional list of metadata dicts (one per document)
167
+ ids: Optional list of document IDs (generated if not provided)
168
+
169
+ Returns:
170
+ List of document IDs
171
+ """
172
+ if not documents:
173
+ return []
174
+
175
+ # Get or create collection
176
+ collection = self.get_or_create_collection(collection_name)
177
+
178
+ # Generate IDs if not provided
179
+ if ids is None:
180
+ ids = [str(uuid.uuid4()) for _ in documents]
181
+
182
+ # Add timestamp to metadata
183
+ if metadatas is None:
184
+ metadatas = [{} for _ in documents]
185
+
186
+ for metadata in metadatas:
187
+ if "timestamp" not in metadata:
188
+ metadata["timestamp"] = datetime.now().isoformat()
189
+
190
+ # Generate embeddings
191
+ embedding_result = self.embedding_provider.generate_embeddings(documents)
192
+
193
+ # Add to collection
194
+ collection.add(
195
+ documents=documents,
196
+ embeddings=embedding_result.embeddings,
197
+ metadatas=metadatas,
198
+ ids=ids
199
+ )
200
+
201
+ return ids
202
+
203
+ def query(
204
+ self,
205
+ collection_name: str,
206
+ query_text: str,
207
+ n_results: int = 5,
208
+ where: Optional[Dict[str, Any]] = None
209
+ ) -> List[SearchResult]:
210
+ """Query collection with semantic search.
211
+
212
+ Args:
213
+ collection_name: Collection name
214
+ query_text: Query text
215
+ n_results: Number of results to return (default: 5)
216
+ where: Optional metadata filter
217
+
218
+ Returns:
219
+ List of SearchResult objects
220
+ """
221
+ collection = self.get_collection(collection_name)
222
+
223
+ # Generate query embedding
224
+ query_embedding = self.embedding_provider.generate_embedding(query_text)
225
+
226
+ # Query collection
227
+ results = collection.query(
228
+ query_embeddings=[query_embedding],
229
+ n_results=n_results,
230
+ where=where
231
+ )
232
+
233
+ # Parse results
234
+ search_results = []
235
+ if results["documents"] and results["documents"][0]:
236
+ for i in range(len(results["documents"][0])):
237
+ search_results.append(
238
+ SearchResult(
239
+ document=results["documents"][0][i],
240
+ metadata=results["metadatas"][0][i] if results["metadatas"] else {},
241
+ distance=results["distances"][0][i] if results["distances"] else 0.0,
242
+ doc_id=results["ids"][0][i]
243
+ )
244
+ )
245
+
246
+ return search_results
247
+
248
+ def get_collection_count(self, collection_name: str) -> int:
249
+ """Get the number of documents in a collection.
250
+
251
+ Args:
252
+ collection_name: Collection name
253
+
254
+ Returns:
255
+ Number of documents
256
+ """
257
+ collection = self.get_collection(collection_name)
258
+ return collection.count()
259
+
260
+ def delete_documents(
261
+ self,
262
+ collection_name: str,
263
+ ids: List[str]
264
+ ) -> None:
265
+ """Delete documents from a collection by ID.
266
+
267
+ Args:
268
+ collection_name: Collection name
269
+ ids: List of document IDs to delete
270
+ """
271
+ collection = self.get_collection(collection_name)
272
+ collection.delete(ids=ids)
273
+
274
+ def update_documents(
275
+ self,
276
+ collection_name: str,
277
+ ids: List[str],
278
+ documents: Optional[List[str]] = None,
279
+ metadatas: Optional[List[Dict[str, Any]]] = None
280
+ ) -> None:
281
+ """Update documents in a collection.
282
+
283
+ Args:
284
+ collection_name: Collection name
285
+ ids: List of document IDs to update
286
+ documents: Optional new document texts
287
+ metadatas: Optional new metadatas
288
+ """
289
+ collection = self.get_collection(collection_name)
290
+
291
+ update_kwargs = {"ids": ids}
292
+
293
+ if documents is not None:
294
+ # Generate new embeddings
295
+ embedding_result = self.embedding_provider.generate_embeddings(documents)
296
+ update_kwargs["documents"] = documents
297
+ update_kwargs["embeddings"] = embedding_result.embeddings
298
+
299
+ if metadatas is not None:
300
+ update_kwargs["metadatas"] = metadatas
301
+
302
+ collection.update(**update_kwargs)
303
+
304
+ def get_documents(
305
+ self,
306
+ collection_name: str,
307
+ ids: Optional[List[str]] = None,
308
+ where: Optional[Dict[str, Any]] = None,
309
+ limit: Optional[int] = None
310
+ ) -> List[Dict[str, Any]]:
311
+ """Retrieve documents from a collection.
312
+
313
+ Args:
314
+ collection_name: Collection name
315
+ ids: Optional list of document IDs to retrieve
316
+ where: Optional metadata filter
317
+ limit: Maximum number of documents to return
318
+
319
+ Returns:
320
+ List of documents with metadata
321
+ """
322
+ collection = self.get_collection(collection_name)
323
+
324
+ get_kwargs = {}
325
+ if ids is not None:
326
+ get_kwargs["ids"] = ids
327
+ if where is not None:
328
+ get_kwargs["where"] = where
329
+ if limit is not None:
330
+ get_kwargs["limit"] = limit
331
+
332
+ results = collection.get(**get_kwargs)
333
+
334
+ # Format results
335
+ documents = []
336
+ if results["documents"]:
337
+ for i in range(len(results["documents"])):
338
+ documents.append({
339
+ "id": results["ids"][i],
340
+ "document": results["documents"][i],
341
+ "metadata": results["metadatas"][i] if results["metadatas"] else {}
342
+ })
343
+
344
+ return documents
@@ -0,0 +1,263 @@
1
+ Metadata-Version: 2.4
2
+ Name: stratifyai
3
+ Version: 0.1.0
4
+ Summary: Unified multi-provider LLM abstraction module with intelligent routing, cost tracking, and caching
5
+ Author-email: Steven Cotton <cototnbytes@gmail.com>
6
+ Maintainer-email: Steven Cotton <cototnbytes@gmail.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/Bytes0211/stratifyai
9
+ Project-URL: Repository, https://github.com/Bytes0211/stratifyai
10
+ Project-URL: Documentation, https://github.com/Bytes0211/stratifyai#readme
11
+ Project-URL: Bug Tracker, https://github.com/Bytes0211/stratifyai/issues
12
+ Keywords: llm,openai,anthropic,google,gemini,ai,chatgpt,claude,deepseek,groq,grok,ollama,multi-provider,abstraction,routing,cost-tracking,caching
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: openai>=1.12.0
27
+ Requires-Dist: anthropic>=0.18.0
28
+ Requires-Dist: google-genai>=1.0.0
29
+ Requires-Dist: aioboto3>=12.0.0
30
+ Requires-Dist: boto3>=1.34.0
31
+ Requires-Dist: python-dotenv>=1.0.0
32
+ Requires-Dist: pydantic>=2.0.0
33
+ Requires-Dist: typing-extensions>=4.0.0
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=9.0.0; extra == "dev"
36
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
37
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
38
+ Requires-Dist: pytest-mock>=3.0.0; extra == "dev"
39
+ Requires-Dist: black>=23.0.0; extra == "dev"
40
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
41
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
42
+ Provides-Extra: cli
43
+ Requires-Dist: typer>=0.9.0; extra == "cli"
44
+ Requires-Dist: rich>=13.0.0; extra == "cli"
45
+ Provides-Extra: web
46
+ Requires-Dist: fastapi>=0.115.0; extra == "web"
47
+ Requires-Dist: uvicorn[standard]>=0.34.0; extra == "web"
48
+ Requires-Dist: websockets>=14.0; extra == "web"
49
+ Provides-Extra: rag
50
+ Requires-Dist: chromadb>=0.5.0; extra == "rag"
51
+ Provides-Extra: all
52
+ Requires-Dist: stratifyai[cli,dev,rag,web]; extra == "all"
53
+ Dynamic: license-file
54
+
55
+ ![StratifyAI](stratifyai_trans_logo.png)
56
+
57
+
58
+ # StratifyAI — Unified Multi‑Provider LLM Interface
59
+
60
+ ![Python](https://img.shields.io/badge/python-3.10%2B-blue) ![License](https://img.shields.io/badge/license-MIT-green) ![Tests](https://img.shields.io/badge/tests-300%2B%20passing-brightgreen) ![Providers](https://img.shields.io/badge/providers-9-orange)
61
+
62
+ **Status:** Phase 7.8 Complete
63
+ **Providers:** 9 Operational
64
+ **Features:** Routing • RAG • Caching • Streaming • CLI • Web UI • Builder Pattern
65
+
66
+ StratifyAI is a production‑ready Python framework that provides a unified interface for 9+ LLM providers, including OpenAI, Anthropic, Google, DeepSeek, Groq, Grok, OpenRouter, Ollama, and AWS Bedrock. It eliminates vendor lock‑in, simplifies multi‑model development, and enables intelligent routing, cost tracking, caching, streaming, and RAG workflows.
67
+
68
+ ---
69
+
70
+ ## Features
71
+
72
+ ### Core
73
+
74
+ - Unified API for 9+ LLM providers
75
+ - Async-first architecture with sync wrappers
76
+ - Automatic provider detection
77
+ - Cost tracking and budget enforcement
78
+ - Latency tracking on all responses
79
+ - Retry logic with fallback models
80
+ - Streaming support for all providers
81
+ - Response caching + provider prompt caching
82
+ - Intelligent routing (cost, quality, latency, hybrid)
83
+ - Capability filtering (vision, tools, reasoning)
84
+ - Model metadata and context window awareness
85
+ - **Builder pattern** for fluent configuration
86
+
87
+ ### Advanced
88
+
89
+ - Large‑file handling with chunking and progressive summarization
90
+ - File extraction (CSV schema, JSON schema, logs, code structure)
91
+ - Auto model selection for extraction tasks
92
+ - RAG pipeline with embeddings + vector DB (ChromaDB)
93
+ - Semantic search and citation tracking
94
+ - Rich/Typer CLI with interactive mode
95
+ - Optional FastAPI web interface
96
+
97
+ ---
98
+
99
+ ## Installation
100
+
101
+ ```bash
102
+ git clone https://github.com/Bytes0211/stratifyai.git
103
+ cd stratifyai
104
+ pip install -e .
105
+ ```
106
+
107
+ Or using `uv`:
108
+
109
+ ```bash
110
+ uv sync
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Configuration
116
+
117
+ ```bash
118
+ cp .env.example .env
119
+ # Add your API keys
120
+ ```
121
+
122
+ Check configured providers:
123
+
124
+ ```bash
125
+ stratifyai check-keys
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Quick Start
131
+
132
+ ### CLI Usage
133
+
134
+ ```bash
135
+ stratifyai chat -p openai -m gpt-4o-mini -t "Hello"
136
+ stratifyai route "Explain relativity" --strategy hybrid
137
+ stratifyai interactive
138
+ stratifyai cache-stats
139
+ ```
140
+
141
+ ### Python Example (LLMClient)
142
+
143
+ ```python
144
+ from stratifyai import LLMClient
145
+ from stratifyai.models import Message, ChatRequest, ChatResponse
146
+
147
+ client: LLMClient = LLMClient()
148
+ request: ChatRequest = ChatRequest(
149
+ model="gpt-4o-mini",
150
+ messages=[Message(role="user", content="Explain quantum computing")]
151
+ )
152
+
153
+ # Async (recommended)
154
+ response: ChatResponse = await client.chat_completion(request)
155
+
156
+ # Sync wrapper for scripts/CLI
157
+ response: ChatResponse = client.chat_completion_sync(request)
158
+
159
+ print(response.content)
160
+ print(f"Cost: ${response.usage.cost_usd:.6f}")
161
+ print(f"Latency: {response.latency_ms:.0f}ms")
162
+ ```
163
+
164
+ ### Python Example (Chat Package - Simplified)
165
+
166
+ ```python
167
+ from stratifyai.chat import anthropic, openai
168
+ from stratifyai.models import ChatResponse
169
+
170
+ # Quick usage - model is always required
171
+ response: ChatResponse = await anthropic.chat("Hello!", model="claude-sonnet-4-5")
172
+ print(response.content)
173
+
174
+ # With options
175
+ response: ChatResponse = await openai.chat(
176
+ "Explain quantum computing",
177
+ model="gpt-4o-mini",
178
+ system="Be concise",
179
+ temperature=0.5
180
+ )
181
+ ```
182
+
183
+ ### Builder Pattern (Fluent Configuration)
184
+
185
+ ```python
186
+ from stratifyai.chat import anthropic
187
+ from stratifyai.chat.builder import ChatBuilder
188
+ from stratifyai.models import ChatResponse
189
+
190
+ # Configure once, use multiple times
191
+ client: ChatBuilder = (
192
+ anthropic
193
+ .with_model("claude-sonnet-4-5")
194
+ .with_system("You are a helpful assistant")
195
+ .with_temperature(0.7)
196
+ )
197
+
198
+ # All subsequent calls use the configured settings
199
+ response: ChatResponse = await client.chat("Hello!")
200
+ response: ChatResponse = await client.chat("Tell me more")
201
+
202
+ # Stream with builder
203
+ async for chunk in client.chat_stream("Write a story"):
204
+ print(chunk.content, end="", flush=True)
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Routing
210
+
211
+ - **Cost**: choose cheapest model
212
+ - **Quality**: choose highest‑quality model
213
+ - **Latency**: choose fastest model
214
+ - **Hybrid (default)**: dynamic weighting based on complexity
215
+
216
+ ---
217
+
218
+ ## RAG
219
+
220
+ - Embeddings (OpenAI)
221
+ - ChromaDB vector storage
222
+ - Semantic search
223
+ - Document indexing
224
+ - Retrieval‑augmented generation
225
+ - Citation tracking
226
+
227
+ ---
228
+
229
+ ## Project Structure
230
+
231
+ ```
232
+ stratifyai/
233
+ ├── llm_abstraction/ # Core package
234
+ │ ├── providers/ # Provider implementations (9 providers)
235
+ │ ├── router.py # Intelligent routing
236
+ │ ├── models.py # Data models
237
+ │ └── utils/ # Utilities (token counting, extraction)
238
+ ├── chat/ # Simplified chat modules with builder pattern
239
+ │ ├── builder.py # ChatBuilder class
240
+ │ └── stratifyai_*.py # Provider-specific modules
241
+ ├── cli/ # Typer CLI
242
+ ├── api/ # Optional FastAPI server
243
+ ├── examples/ # Usage examples
244
+ └── docs/ # Technical documentation
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Testing
250
+
251
+ ```bash
252
+ pytest # Run all tests
253
+ pytest -v # Verbose output
254
+ ```
255
+
256
+ **Test Coverage:** 300+ tests across all modules
257
+
258
+ ---
259
+
260
+ ## License
261
+
262
+ Internal project — All rights reserved.
263
+
@@ -0,0 +1,57 @@
1
+ cli/__init__.py,sha256=Bwi6ibJLRbqK0oIP_U0pvypH0nKXUBMbufZPnXMkI2E,96
2
+ cli/stratifyai_cli.py,sha256=aliOcAg0qxeSKaM4QZoIydS_YDCUm2Sb9Sv-vXNafRg,82568
3
+ stratifyai/__init__.py,sha256=yjmHcAcorD5txlNZwmamljOnN3nHCosBY2_0CE26TaE,2873
4
+ stratifyai/api_key_helper.py,sha256=fkhb1iUGcGg5il-L7KbjbtS27pAm41McNyvEqMW2fVE,12733
5
+ stratifyai/caching.py,sha256=NSm7SA1hruVC4rgg-0MPFNlMYT5i3JNKAkvlexGICiY,8475
6
+ stratifyai/chunking.py,sha256=vNXPoBwegQmdHQKXnQeGPdk4wwOrNzk2BYk__figEAY,5042
7
+ stratifyai/client.py,sha256=93uNaXrlxZ02VywJFwPV07P7E0l9NfuS87wgxk5ZtkM,9025
8
+ stratifyai/config.py,sha256=cbF10BwWQTOuKm5OPmYlJGaAKyVN_jmjBs7yWGc26kc,36230
9
+ stratifyai/cost_tracker.py,sha256=f8A631iz-OOE16rPkoHDQeqMZcG46LmyCWweLcS6BKg,8774
10
+ stratifyai/embeddings.py,sha256=FZkApJYVgI7TB0azttan-5qV6SNdg_P8O1bANbkCXK8,7642
11
+ stratifyai/exceptions.py,sha256=ZfKrgP0ZyVfuETouQRyUxraN3Cy4631m5hXjBvXvNSE,2802
12
+ stratifyai/models.py,sha256=6T3V3U2eyZQRGF91QDl9kWB-yC6FdalTIT2XovQb0Yo,1867
13
+ stratifyai/py.typed,sha256=UlkhTBVJqiS1Epx-KILVobCtCGlhR6YKM79R8vO1HdU,61
14
+ stratifyai/rag.py,sha256=Yu-u-G5BYvJ-Ac9kuZ3cbMO4yL4NhIP0OZqlfnigv08,12302
15
+ stratifyai/retry.py,sha256=OqiBuPzDkhRPLyjwRX6E5HFuQ6QbsMh4f-7GSldQoRM,5992
16
+ stratifyai/router.py,sha256=qQs58BaKDxKGZ_AIp2_-NGSqpttzB9OrKikmpoFyvlg,23585
17
+ stratifyai/summarization.py,sha256=FslLun2fzKqX3dVTAHG-rzAz2DH6D9C_u74rA7tHrYU,5261
18
+ stratifyai/vectordb.py,sha256=ErLOvk4X82YfZDOkoAkrgHVY3YvukT2KDRhMA02-bqw,10708
19
+ stratifyai/chat/__init__.py,sha256=foW5mE5OWmBIW0ADURWUzcznJyiyfBl_h11blZIBBSQ,1417
20
+ stratifyai/chat/builder.py,sha256=W9Rwh64u5uvJlnJH1vi3q_Og6XiXaD8juxcHD5Z3wRE,12962
21
+ stratifyai/chat/stratifyai_anthropic.py,sha256=Jqpf1oXQAg2pzLm4AZCidC-raJoEg6NORpIiUAhyNrU,5894
22
+ stratifyai/chat/stratifyai_bedrock.py,sha256=gZ_X3N56-Dg_h5vqWEqCf1TVF_PVkPR11t4WTTb1q20,6061
23
+ stratifyai/chat/stratifyai_deepseek.py,sha256=6y0uEVk4FyIon59K_4hqsXkIz-wPa5MYgthQJGoqTNE,5724
24
+ stratifyai/chat/stratifyai_google.py,sha256=rwOoixvlC5ssfOq-ifAWFAiUwqOKrAJAOyEfr0bcq_g,5733
25
+ stratifyai/chat/stratifyai_grok.py,sha256=Of3PuL5EdWtTi_4IY6fqag3YQWxQRWZU4Fx_ZBauOU8,5647
26
+ stratifyai/chat/stratifyai_groq.py,sha256=IoA6qZZeN0n6fhWTl71_v0XahDs6CDYe1g8WBbPDvQw,5779
27
+ stratifyai/chat/stratifyai_ollama.py,sha256=nj-RdOdosmPLixkoI4ceMGHNnBGcDIW8vQIHUt3NvO8,5989
28
+ stratifyai/chat/stratifyai_openai.py,sha256=217C-FnkvNKwJNCsMt5mp_YUkjBmipXbckUmVE7HW1w,6410
29
+ stratifyai/chat/stratifyai_openrouter.py,sha256=jxAed4mPH26AJF7qhWpbLy83yR-LYlox5mZXTA739y4,6088
30
+ stratifyai/providers/__init__.py,sha256=huQSk2r1ZEQPxIim6U5VpYvOQi2QfVbImVzbyXYSEHQ,96
31
+ stratifyai/providers/anthropic.py,sha256=cogWjpFsoOc2k7wQ6QzEiIi1imU6RgUUdkk7VFL1XDM,11800
32
+ stratifyai/providers/base.py,sha256=WJ6W_HUAcejtqDljRPK37KgUgB4SJtQ-kC6zO0tmnPs,5252
33
+ stratifyai/providers/bedrock.py,sha256=GPaRB1enqxmxNzWpiVgX67ubGzt0hnwGXLDU6GIw4HY,24739
34
+ stratifyai/providers/deepseek.py,sha256=Y-ZT_xh2aXBHXEVh5NWXQnANv6pDEmIHcxwplHSlQ24,1145
35
+ stratifyai/providers/google.py,sha256=fi-8KBMzESTHMe1bmrZfOu8o5mKizIAaPG1puZAiGo4,1142
36
+ stratifyai/providers/grok.py,sha256=O0oUGAo3hNZ-B07n0Zh0qWQsqDborLC-b38ItOwo88s,1111
37
+ stratifyai/providers/groq.py,sha256=XTGsHwubuSXgCMSTGJBTIddvNQFz6Hg4eIIaxERMXWY,1097
38
+ stratifyai/providers/ollama.py,sha256=Uvr8K0aAW3TSUckC64-g7chj8WD9qJBzT2ndRllBZEI,1404
39
+ stratifyai/providers/openai.py,sha256=Ddm9nDvmRGlAqeG7rSwe7yD42SHyEhho0dVFj5Xh5ww,12831
40
+ stratifyai/providers/openai_compatible.py,sha256=TWI81E4NujphNOTCFYZnsYjiWBibs78mdUIt53vXenU,14290
41
+ stratifyai/providers/openrouter.py,sha256=ESXfH_OpElTj6-Bsqqt2vf6h5ydVtxE7QygxhkXmpHI,1169
42
+ stratifyai/utils/__init__.py,sha256=ToRceBu1Mx4vNhYP0a_WuONAgfK4gry8j_G8YW6159A,274
43
+ stratifyai/utils/bedrock_validator.py,sha256=9ZCQWYKCf4b0IqaLrcSJ038WocjXHiiB0qxcrobOssA,4530
44
+ stratifyai/utils/code_extractor.py,sha256=adQDg1KyDYLZC-i2Rrzs6Pdm94SQGs1eNqkc-rmAh6w,10916
45
+ stratifyai/utils/csv_extractor.py,sha256=essTu8ILDHKgBeFeZxVdxr7yFUKPAHcetGbCwR-Ybqc,6113
46
+ stratifyai/utils/file_analyzer.py,sha256=Gcps6V8k1P18pf3MZyk6oUkQiIyP7XLxYLChDn6X548,6292
47
+ stratifyai/utils/json_extractor.py,sha256=WzaloLrlqhoDjAHcRIwYWnmYYu81WqTugNbW1JDRzpg,6720
48
+ stratifyai/utils/log_extractor.py,sha256=Nz2x9xPvRVdp5yk6cTLQ5CHK4Fi5oNKQG2t2k9eFiRM,8118
49
+ stratifyai/utils/model_selector.py,sha256=LSPc23MWiCkX2ikygkjdDgXdujqLctk1ANuMRKMJ-S8,11922
50
+ stratifyai/utils/provider_validator.py,sha256=LAB2kljZ3NPlXaMwH9njiFhp0EYzRwvwSX7Pcphj9NQ,14726
51
+ stratifyai/utils/token_counter.py,sha256=58hkX3q4yObZVwo3lvn7OGPh7puiWNind7yX3Qem_1o,6432
52
+ stratifyai-0.1.0.dist-info/licenses/LICENSE,sha256=UEMslgLRhi7sYtDIwMY0IjEppiVEgqgMIdsulgYdb0Q,1068
53
+ stratifyai-0.1.0.dist-info/METADATA,sha256=JymZhbU_A7N3A35YYEoBr-sU1jeLc8SCbviLWINnUIU,7694
54
+ stratifyai-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
55
+ stratifyai-0.1.0.dist-info/entry_points.txt,sha256=aWXYCRBSld8hzAtCPAqsl2NHKJIJkIgc63uQOO2PcUQ,55
56
+ stratifyai-0.1.0.dist-info/top_level.txt,sha256=0_JiuYll_AXJr5e4qXzbCs8LYykDxGaEjawwI69vEhM,15
57
+ stratifyai-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ stratifyai = cli.stratifyai_cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Scott Jones
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,2 @@
1
+ cli
2
+ stratifyai