llm-context-toolkit 0.1.1__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.
- llm_context_toolkit-0.1.1/CHANGELOG.md +80 -0
- llm_context_toolkit-0.1.1/ENVIRONMENT_VARIABLES.md +15 -0
- llm_context_toolkit-0.1.1/LICENSE +21 -0
- llm_context_toolkit-0.1.1/MANIFEST.in +11 -0
- llm_context_toolkit-0.1.1/PKG-INFO +546 -0
- llm_context_toolkit-0.1.1/README.md +505 -0
- llm_context_toolkit-0.1.1/VERSION +1 -0
- llm_context_toolkit-0.1.1/docs/USER_MANUAL.md +1528 -0
- llm_context_toolkit-0.1.1/examples/example_1_context_resolution.py +87 -0
- llm_context_toolkit-0.1.1/examples/example_2_metadata_selection.py +151 -0
- llm_context_toolkit-0.1.1/examples/example_3_combined_workflow.py +129 -0
- llm_context_toolkit-0.1.1/llm_context_toolkit/__init__.py +275 -0
- llm_context_toolkit-0.1.1/llm_context_toolkit/context_resolver.py +1383 -0
- llm_context_toolkit-0.1.1/llm_context_toolkit/metadata_selector.py +1366 -0
- llm_context_toolkit-0.1.1/llm_context_toolkit.egg-info/PKG-INFO +546 -0
- llm_context_toolkit-0.1.1/llm_context_toolkit.egg-info/SOURCES.txt +22 -0
- llm_context_toolkit-0.1.1/llm_context_toolkit.egg-info/dependency_links.txt +1 -0
- llm_context_toolkit-0.1.1/llm_context_toolkit.egg-info/requires.txt +22 -0
- llm_context_toolkit-0.1.1/llm_context_toolkit.egg-info/top_level.txt +1 -0
- llm_context_toolkit-0.1.1/pyproject.toml +99 -0
- llm_context_toolkit-0.1.1/requirements.txt +6 -0
- llm_context_toolkit-0.1.1/setup.cfg +4 -0
- llm_context_toolkit-0.1.1/setup.py +54 -0
- llm_context_toolkit-0.1.1/tests/test_basic.py +203 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to llm-context-toolkit will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-05-16
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release of llm-context-toolkit
|
|
12
|
+
- ContextResolver for resolving contextual and follow-up questions
|
|
13
|
+
- MetadataSelector for intelligent metadata selection from large catalogs
|
|
14
|
+
- TurnContextCard for compact conversation state management
|
|
15
|
+
- Support for multiple selection strategies (lexical, TF-IDF, embeddings, hybrid)
|
|
16
|
+
- Combined `resolve_and_select()` workflow API
|
|
17
|
+
- Comprehensive documentation and user manual
|
|
18
|
+
- Example scripts demonstrating common use cases
|
|
19
|
+
- Basic test suite
|
|
20
|
+
- Pure Python implementation with zero required dependencies
|
|
21
|
+
- Optional dependencies for enhanced features (scikit-learn, sentence-transformers)
|
|
22
|
+
- Context type detection (fresh, follow-up, modify, suggest, clarify)
|
|
23
|
+
- Intent delta extraction for query modifications
|
|
24
|
+
- 90-98% token reduction through intelligent selection
|
|
25
|
+
- 80%+ memory reduction using compact context cards
|
|
26
|
+
- Framework-agnostic design
|
|
27
|
+
- Multi-tenant isolation support
|
|
28
|
+
- Debug mode for detailed scoring information
|
|
29
|
+
- Compression metrics and reporting
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
|
|
33
|
+
#### Context Resolution
|
|
34
|
+
- Detect and resolve contextual follow-up questions
|
|
35
|
+
- Maintain conversation state without full chat history
|
|
36
|
+
- Support for explicit turn references ("make the 3rd one monthly")
|
|
37
|
+
- Suggestion request detection ("what else can we analyze?")
|
|
38
|
+
- Ambiguity detection with clarification prompts
|
|
39
|
+
- Configurable confidence thresholds
|
|
40
|
+
- Optional LLM fallback for complex cases
|
|
41
|
+
|
|
42
|
+
#### Metadata Selection
|
|
43
|
+
- Lexical keyword matching (pure Python)
|
|
44
|
+
- TF-IDF scoring (optional, requires scikit-learn)
|
|
45
|
+
- Semantic embeddings (optional, requires sentence-transformers)
|
|
46
|
+
- Hybrid strategy combining all available methods
|
|
47
|
+
- Role-aware column scoring (metric, dimension, date, etc.)
|
|
48
|
+
- Business synonym support
|
|
49
|
+
- Intent-based column selection
|
|
50
|
+
- Join/relationship detection
|
|
51
|
+
- Budget limiting for output size control
|
|
52
|
+
- Required/excluded table and column constraints
|
|
53
|
+
|
|
54
|
+
### Documentation
|
|
55
|
+
- Comprehensive README with quick start
|
|
56
|
+
- Detailed user manual (70+ pages)
|
|
57
|
+
- API reference documentation
|
|
58
|
+
- 3 complete usage examples
|
|
59
|
+
- Development guide
|
|
60
|
+
- MIT license
|
|
61
|
+
|
|
62
|
+
### Quality
|
|
63
|
+
- Type hints throughout
|
|
64
|
+
- Dataclass-based APIs
|
|
65
|
+
- No exceptions in normal flow
|
|
66
|
+
- Safe defaults
|
|
67
|
+
- Extensive inline documentation
|
|
68
|
+
- Test coverage for core functionality
|
|
69
|
+
|
|
70
|
+
## [Unreleased]
|
|
71
|
+
|
|
72
|
+
### Planned
|
|
73
|
+
- Additional selection strategies
|
|
74
|
+
- Performance optimizations for very large catalogs
|
|
75
|
+
- Caching support for embedding models
|
|
76
|
+
- More example integrations (OpenAI, Anthropic, etc.)
|
|
77
|
+
- Enhanced debug visualization
|
|
78
|
+
- Benchmark suite
|
|
79
|
+
- Extended test coverage
|
|
80
|
+
- Integration guides for popular frameworks
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# llm-context-toolkit Environment Variables
|
|
2
|
+
|
|
3
|
+
## Build-Time Variables
|
|
4
|
+
|
|
5
|
+
### LLM_CONTEXT_TOOLKIT_CYTHONIZE
|
|
6
|
+
- **Type:** String
|
|
7
|
+
- **Default:** unset or `0`
|
|
8
|
+
- **Description:** Enables Cython compilation for protected wheel builds
|
|
9
|
+
- **Accepted values:** `1` to enable, any other value to skip
|
|
10
|
+
|
|
11
|
+
## Runtime Variables
|
|
12
|
+
|
|
13
|
+
This library has **no required environment variables**. It is a pure Python library that works with the standard library only.
|
|
14
|
+
|
|
15
|
+
Optional provider-specific environment variables (for LLM integration in your application) are managed by the LLM provider you choose to use alongside this toolkit.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sreeyenan
|
|
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,11 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
include pyproject.toml
|
|
4
|
+
include setup.py
|
|
5
|
+
include VERSION
|
|
6
|
+
include requirements.txt
|
|
7
|
+
include CHANGELOG.md
|
|
8
|
+
include ENVIRONMENT_VARIABLES.md
|
|
9
|
+
recursive-include docs *.md
|
|
10
|
+
recursive-include examples *.py
|
|
11
|
+
recursive-include llm_context_toolkit *.py
|
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llm-context-toolkit
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A comprehensive toolkit for LLM context management with intelligent metadata selection and contextual question resolution
|
|
5
|
+
Author-email: sreeyenan <sreeyenanek@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/sreeyenan/llm_context_toolkit
|
|
7
|
+
Project-URL: Documentation, https://github.com/sreeyenan/llm_context_toolkit#readme
|
|
8
|
+
Project-URL: Repository, https://github.com/sreeyenan/llm_context_toolkit
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/sreeyenan/llm_context_toolkit/issues
|
|
10
|
+
Keywords: llm,context,metadata,ai,nlp,text-to-sql,rag,chatbot,conversation
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
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
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Provides-Extra: tfidf
|
|
24
|
+
Requires-Dist: scikit-learn>=1.0.0; extra == "tfidf"
|
|
25
|
+
Provides-Extra: embeddings
|
|
26
|
+
Requires-Dist: sentence-transformers>=2.0.0; extra == "embeddings"
|
|
27
|
+
Provides-Extra: protected
|
|
28
|
+
Requires-Dist: Cython>=3.0; extra == "protected"
|
|
29
|
+
Provides-Extra: all
|
|
30
|
+
Requires-Dist: scikit-learn>=1.0.0; extra == "all"
|
|
31
|
+
Requires-Dist: sentence-transformers>=2.0.0; extra == "all"
|
|
32
|
+
Requires-Dist: Cython>=3.0; extra == "all"
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-asyncio>=0.20.0; extra == "dev"
|
|
36
|
+
Requires-Dist: black>=22.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: isort>=5.10.0; extra == "dev"
|
|
38
|
+
Requires-Dist: mypy>=0.990; extra == "dev"
|
|
39
|
+
Requires-Dist: flake8>=5.0.0; extra == "dev"
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
# llm-context-toolkit
|
|
43
|
+
|
|
44
|
+
**Version:** 0.1.0
|
|
45
|
+
**Author:** [sreeyenan](https://github.com/sreeyenan)
|
|
46
|
+
**License:** MIT
|
|
47
|
+
**Python:** 3.10+
|
|
48
|
+
|
|
49
|
+
**A comprehensive toolkit for LLM context management with intelligent metadata selection and contextual question resolution.**
|
|
50
|
+
|
|
51
|
+
[](https://pypi.org/project/llm-context-toolkit/)
|
|
52
|
+
[](https://www.python.org/downloads/)
|
|
53
|
+
[](https://opensource.org/licenses/MIT)
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## ๐ฏ What This Library Does
|
|
58
|
+
|
|
59
|
+
`llm-context-toolkit` solves two critical problems when building LLM-powered AI systems:
|
|
60
|
+
|
|
61
|
+
1. **Context Resolution** - Converts short, contextual messages into complete standalone instructions
|
|
62
|
+
2. **Metadata Selection** - Intelligently selects only relevant metadata from large catalogs
|
|
63
|
+
|
|
64
|
+
### The Problem
|
|
65
|
+
|
|
66
|
+
When building Text-to-SQL, RAG systems, or dashboard AI assistants, you face these challenges:
|
|
67
|
+
|
|
68
|
+
- **Contextual questions are hard to understand**: "make it monthly", "what else?", "same for payments"
|
|
69
|
+
- **Full metadata catalogs are too large**: Sending 50+ tables with 500+ columns to an LLM wastes tokens, increases cost, and reduces accuracy
|
|
70
|
+
- **Chat history grows unbounded**: Passing full conversation history is expensive and often unnecessary
|
|
71
|
+
|
|
72
|
+
### The Solution
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from llm_context_toolkit import resolve_and_select
|
|
76
|
+
|
|
77
|
+
# One line to resolve context + select metadata
|
|
78
|
+
resolution, selection = resolve_and_select(
|
|
79
|
+
current_question="make it monthly",
|
|
80
|
+
metadata_catalog=tenant_catalog,
|
|
81
|
+
context_cards=[previous_turn_card],
|
|
82
|
+
database="client_db"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Result:
|
|
86
|
+
# - Resolved question: "Show monthly revenue by region for last 6 months"
|
|
87
|
+
# - Selected metadata: 1 table, 3 columns (from 42 tables, 890 columns)
|
|
88
|
+
# - Token reduction: 95.5% (47000 โ 2100 tokens)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## ๐ Key Features
|
|
94
|
+
|
|
95
|
+
### Context Resolution
|
|
96
|
+
- โ
Converts contextual messages into standalone questions
|
|
97
|
+
- โ
Detects follow-ups, modifications, fresh questions, and suggestion requests
|
|
98
|
+
- โ
Maintains state using compact `TurnContextCard` objects
|
|
99
|
+
- โ
No full chat history needed (90%+ memory reduction)
|
|
100
|
+
- โ
Rule-based resolution (no API calls required)
|
|
101
|
+
- โ
Optional LLM fallback for ambiguous cases
|
|
102
|
+
|
|
103
|
+
### Metadata Selection
|
|
104
|
+
- โ
Selects only relevant tables and columns from large catalogs
|
|
105
|
+
- โ
90-98% token reduction for LLM prompts
|
|
106
|
+
- โ
Multiple strategies: lexical, TF-IDF, embeddings, hybrid
|
|
107
|
+
- โ
No API key required for core functionality
|
|
108
|
+
- โ
Supports business metadata (synonyms, descriptions, roles)
|
|
109
|
+
- โ
Works with any database schema (SQL, NoSQL, graph, etc.)
|
|
110
|
+
|
|
111
|
+
### Framework-Agnostic
|
|
112
|
+
- โ
Works with any LLM (OpenAI, Anthropic, Gemini, Groq, local models)
|
|
113
|
+
- โ
Works with any SQL engine (PostgreSQL, MySQL, ClickHouse, etc.)
|
|
114
|
+
- โ
Works with any framework (FastAPI, Flask, Django, etc.)
|
|
115
|
+
- โ
Works with any vector database for RAG
|
|
116
|
+
- โ
Pure Python with zero required dependencies
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## ๐ฆ Installation
|
|
121
|
+
|
|
122
|
+
### Minimal Installation (Pure Python)
|
|
123
|
+
```bash
|
|
124
|
+
pip install llm-context-toolkit
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### With Optional Enhanced Features
|
|
128
|
+
```bash
|
|
129
|
+
# TF-IDF strategy for better lexical matching
|
|
130
|
+
pip install llm-context-toolkit[tfidf]
|
|
131
|
+
|
|
132
|
+
# Local embedding support for semantic matching
|
|
133
|
+
pip install llm-context-toolkit[embeddings]
|
|
134
|
+
|
|
135
|
+
# Everything
|
|
136
|
+
pip install llm-context-toolkit[all]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## ๐ Quick Start
|
|
142
|
+
|
|
143
|
+
### 1. Basic Context Resolution
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from llm_context_toolkit import ContextResolver, TurnContextCard
|
|
147
|
+
|
|
148
|
+
# Previous conversation turn
|
|
149
|
+
previous_card = TurnContextCard(
|
|
150
|
+
turn_id=1,
|
|
151
|
+
user_question="Show total revenue by region",
|
|
152
|
+
resolved_question="Show total revenue by region",
|
|
153
|
+
query_state={
|
|
154
|
+
"active_tables": ["sales_orders"],
|
|
155
|
+
"metrics": ["revenue"],
|
|
156
|
+
"group_by": ["region"],
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# Resolve a contextual follow-up
|
|
161
|
+
resolver = ContextResolver()
|
|
162
|
+
resolution = resolver.resolve(
|
|
163
|
+
current_question="make it monthly",
|
|
164
|
+
context_cards=[previous_card]
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
print(resolution.resolved_question)
|
|
168
|
+
# "Show monthly revenue by region"
|
|
169
|
+
|
|
170
|
+
print(resolution.metadata_search_query)
|
|
171
|
+
# "monthly revenue region order_date sales_orders"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 2. Basic Metadata Selection
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
from llm_context_toolkit import MetadataSelector
|
|
178
|
+
|
|
179
|
+
catalog = {
|
|
180
|
+
"database": "client_db",
|
|
181
|
+
"tables": [
|
|
182
|
+
{
|
|
183
|
+
"table_name": "sales_orders",
|
|
184
|
+
"columns": [
|
|
185
|
+
{"name": "revenue", "role": "metric", "synonyms": ["sales", "income"]},
|
|
186
|
+
{"name": "region", "role": "dimension", "synonyms": ["zone", "area"]},
|
|
187
|
+
{"name": "order_date", "role": "date"},
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
selector = MetadataSelector()
|
|
194
|
+
result = selector.select(
|
|
195
|
+
question="Show total sales by region for last 6 months",
|
|
196
|
+
catalog=catalog
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
print(result.selected_metadata)
|
|
200
|
+
# Only relevant table and columns selected
|
|
201
|
+
print(result.metrics.summary())
|
|
202
|
+
# "tables 42 โ 1 (97.6% cut), columns 890 โ 3 (99.7% cut), tokens ~47000 โ ~500 (98.9% cut)"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### 3. Combined Workflow (Recommended)
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
from llm_context_toolkit import resolve_and_select, TurnContextCard
|
|
209
|
+
|
|
210
|
+
# One call to handle both resolution and selection
|
|
211
|
+
resolution, selection = resolve_and_select(
|
|
212
|
+
current_question="consider monthly?",
|
|
213
|
+
metadata_catalog=tenant_catalog,
|
|
214
|
+
context_cards=[previous_card],
|
|
215
|
+
database="client_abc_db"
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
# Handle clarification requests
|
|
219
|
+
if resolution.route == "clarify":
|
|
220
|
+
return {"message": resolution.clarification_question}
|
|
221
|
+
|
|
222
|
+
# Now pass to your LLM
|
|
223
|
+
prompt = f"""
|
|
224
|
+
Question: {resolution.resolved_question}
|
|
225
|
+
|
|
226
|
+
Available Schema:
|
|
227
|
+
{selection.selected_metadata}
|
|
228
|
+
|
|
229
|
+
Generate SQL for this question.
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
# Send to OpenAI, Anthropic, Gemini, etc.
|
|
233
|
+
sql = your_llm.generate(prompt)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## ๐ Typical Pipeline
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
User Message: "make it monthly"
|
|
242
|
+
โ
|
|
243
|
+
ContextResolver
|
|
244
|
+
โ
|
|
245
|
+
Resolved: "Show monthly revenue by region for last 6 months"
|
|
246
|
+
Search Query: "monthly revenue region order_date"
|
|
247
|
+
โ
|
|
248
|
+
MetadataSelector
|
|
249
|
+
โ
|
|
250
|
+
Selected: 1 table (sales_orders), 3 columns (revenue, region, order_date)
|
|
251
|
+
Token Reduction: 47000 โ 2100 tokens (95.5% reduction)
|
|
252
|
+
โ
|
|
253
|
+
LLM Prompt
|
|
254
|
+
โ
|
|
255
|
+
SQL/Config/Answer Generation
|
|
256
|
+
โ
|
|
257
|
+
Save new TurnContextCard
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## ๐ Use Cases
|
|
263
|
+
|
|
264
|
+
### Text-to-SQL
|
|
265
|
+
```python
|
|
266
|
+
# User: "Show revenue by region"
|
|
267
|
+
# โ SQL: SELECT region, sum(revenue) FROM sales_orders GROUP BY region
|
|
268
|
+
|
|
269
|
+
# User: "make it monthly"
|
|
270
|
+
# โ SQL: SELECT toStartOfMonth(order_date) AS month, region, sum(revenue)
|
|
271
|
+
# FROM sales_orders GROUP BY month, region
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Text-to-Query-Config
|
|
275
|
+
```python
|
|
276
|
+
# User: "Show revenue by region as a bar chart"
|
|
277
|
+
# โ Config: {"type": "bar", "x": "region", "y": "sum(revenue)"}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### RAG / Document Q&A
|
|
281
|
+
```python
|
|
282
|
+
# Previous: "What are the compliance requirements?"
|
|
283
|
+
# User: "what about privacy only?"
|
|
284
|
+
# โ Resolved: "What are the privacy-specific compliance requirements?"
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Dashboard AI Assistant
|
|
288
|
+
```python
|
|
289
|
+
# User: "what else can we analyze?"
|
|
290
|
+
# โ Suggestions: ["Revenue by product category", "Monthly trend analysis", "Top 10 regions"]
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## ๐๏ธ Architecture
|
|
296
|
+
|
|
297
|
+
### Context Resolution Flow
|
|
298
|
+
```
|
|
299
|
+
User Message
|
|
300
|
+
โ
|
|
301
|
+
Detect explicit references (turn #3, chart 2, etc.)
|
|
302
|
+
โ
|
|
303
|
+
Rank recent context cards by relevance
|
|
304
|
+
โ
|
|
305
|
+
Classify: fresh | follow-up | modify | suggest | clarify
|
|
306
|
+
โ
|
|
307
|
+
Extract intent delta (granularity, filters, etc.)
|
|
308
|
+
โ
|
|
309
|
+
Compose resolved question + metadata search query
|
|
310
|
+
โ
|
|
311
|
+
Output: ContextResolution
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Metadata Selection Flow
|
|
315
|
+
```
|
|
316
|
+
Question + Full Catalog (42 tables, 890 columns)
|
|
317
|
+
โ
|
|
318
|
+
Parse intent (metrics, dates, grouping, trends)
|
|
319
|
+
โ
|
|
320
|
+
Score tables (lexical + TF-IDF + embeddings)
|
|
321
|
+
โ
|
|
322
|
+
Select top K tables (default: 3)
|
|
323
|
+
โ
|
|
324
|
+
Score columns within selected tables
|
|
325
|
+
โ
|
|
326
|
+
Select top N columns per table (default: 25)
|
|
327
|
+
โ
|
|
328
|
+
Include relationships between selected tables
|
|
329
|
+
โ
|
|
330
|
+
Output: Selected metadata (1-3 tables, 5-30 columns)
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## ๐ฏ Core Concepts
|
|
336
|
+
|
|
337
|
+
### TurnContextCard
|
|
338
|
+
Compact memory object storing structured context from a previous AI turn.
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
TurnContextCard(
|
|
342
|
+
turn_id=1,
|
|
343
|
+
user_question="Show revenue by region",
|
|
344
|
+
resolved_question="Show total revenue by region for last 6 months",
|
|
345
|
+
task_type="text_to_sql",
|
|
346
|
+
artifact_type="sql",
|
|
347
|
+
topic_keywords=["revenue", "region", "sales"],
|
|
348
|
+
entities=["sales_orders", "revenue", "region"],
|
|
349
|
+
query_state={
|
|
350
|
+
"active_tables": ["sales_orders"],
|
|
351
|
+
"metrics": ["revenue"],
|
|
352
|
+
"dimensions": ["region"],
|
|
353
|
+
"filters": [{"column": "order_date", "operation": "last_6_months"}],
|
|
354
|
+
},
|
|
355
|
+
sql="SELECT region, sum(revenue) FROM sales_orders WHERE order_date >= ...",
|
|
356
|
+
)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**Why not store full chat history?**
|
|
360
|
+
- Full history: 1000+ tokens per turn ร 10 turns = 10,000+ tokens
|
|
361
|
+
- Context cards: ~200 tokens per turn ร 10 turns = 2,000 tokens
|
|
362
|
+
- **80% reduction before metadata selection even starts**
|
|
363
|
+
|
|
364
|
+
### ContextType
|
|
365
|
+
Classification of how the current question relates to previous context:
|
|
366
|
+
|
|
367
|
+
- `fresh_question` - New independent question
|
|
368
|
+
- `follow_up_latest` - Continues from latest result
|
|
369
|
+
- `follow_up_specific_turn` - References a specific older turn
|
|
370
|
+
- `modify_previous_query` - Modifies a previous result
|
|
371
|
+
- `suggestion_request` - Asks for related suggestions
|
|
372
|
+
- `clarification_needed` - Too ambiguous to resolve
|
|
373
|
+
|
|
374
|
+
### Selection Strategies
|
|
375
|
+
- **lexical** - Pure Python keyword matching (no dependencies)
|
|
376
|
+
- **tfidf** - TF-IDF scoring (requires scikit-learn)
|
|
377
|
+
- **embedding** - Semantic similarity (requires sentence-transformers)
|
|
378
|
+
- **hybrid** - Combines all available strategies (recommended)
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## ๐ง Configuration
|
|
383
|
+
|
|
384
|
+
### Resolver Configuration
|
|
385
|
+
```python
|
|
386
|
+
from llm_context_toolkit import ResolverConfig, ContextResolver
|
|
387
|
+
|
|
388
|
+
config = ResolverConfig(
|
|
389
|
+
max_recent_cards=10, # How many recent cards to consider
|
|
390
|
+
min_confidence_threshold=0.75, # Minimum confidence to resolve
|
|
391
|
+
allow_llm_fallback=False, # Use LLM for ambiguous cases
|
|
392
|
+
enable_debug=True, # Include debug information
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
resolver = ContextResolver(config=config)
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Selector Configuration
|
|
399
|
+
```python
|
|
400
|
+
from llm_context_toolkit import SelectorConfig, MetadataSelector
|
|
401
|
+
|
|
402
|
+
config = SelectorConfig(
|
|
403
|
+
strategy="hybrid", # lexical | tfidf | embedding | hybrid
|
|
404
|
+
top_k_tables=3, # Max tables to select
|
|
405
|
+
max_columns_per_table=25, # Max columns per table
|
|
406
|
+
max_output_chars=10000, # Budget limit for output
|
|
407
|
+
use_embeddings_if_available=True, # Use embeddings if installed
|
|
408
|
+
embedding_model_name_or_path="./models/all-MiniLM-L6-v2", # Local model
|
|
409
|
+
include_debug=True, # Include scoring details
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
selector = MetadataSelector(config=config)
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## ๐ Real-World Results
|
|
418
|
+
|
|
419
|
+
### Token Reduction Examples
|
|
420
|
+
|
|
421
|
+
| Scenario | Input Tokens | Output Tokens | Reduction |
|
|
422
|
+
|----------|--------------|---------------|-----------|
|
|
423
|
+
| Small catalog (5 tables, 50 cols) | ~3,000 | ~400 | 86.7% |
|
|
424
|
+
| Medium catalog (20 tables, 200 cols) | ~12,000 | ~800 | 93.3% |
|
|
425
|
+
| Large catalog (50 tables, 500 cols) | ~30,000 | ~1,200 | 96.0% |
|
|
426
|
+
| Very large (100 tables, 1000 cols) | ~60,000 | ~1,500 | 97.5% |
|
|
427
|
+
|
|
428
|
+
### Cost Impact
|
|
429
|
+
Assuming GPT-4 pricing ($10/1M input tokens):
|
|
430
|
+
|
|
431
|
+
- Large catalog: 30,000 tokens โ 1,200 tokens = **$0.30 โ $0.012 per query (96% cost reduction)**
|
|
432
|
+
- 10,000 queries/month: **$3,000 โ $120/month savings = $34,560/year**
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## ๐ฌ Advanced Usage
|
|
437
|
+
|
|
438
|
+
### Custom LLM Fallback for Ambiguous Cases
|
|
439
|
+
```python
|
|
440
|
+
from llm_context_toolkit import ContextResolver
|
|
441
|
+
|
|
442
|
+
def my_llm_fallback(question, card_summaries, preliminary):
|
|
443
|
+
# Call your LLM to resolve ambiguous cases
|
|
444
|
+
prompt = f"Question: {question}\nContext: {card_summaries}\nResolve this."
|
|
445
|
+
response = your_llm_client.generate(prompt)
|
|
446
|
+
return {"resolved_question": response["question"], ...}
|
|
447
|
+
|
|
448
|
+
resolver = ContextResolver(llm_fallback=my_llm_fallback)
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Multi-Tenant Isolation
|
|
452
|
+
```python
|
|
453
|
+
# Always pass database override from your tenant resolver
|
|
454
|
+
client_id = request.headers["X-Client-ID"]
|
|
455
|
+
database = tenant_resolver.get_database(client_id)
|
|
456
|
+
|
|
457
|
+
resolution, selection = resolve_and_select(
|
|
458
|
+
current_question=user_question,
|
|
459
|
+
metadata_catalog=tenant_catalogs[client_id],
|
|
460
|
+
database=database, # Ensures LLM only sees this tenant's data
|
|
461
|
+
)
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### State Extraction for Next Turn
|
|
465
|
+
```python
|
|
466
|
+
# After generating SQL/config, extract state for next turn
|
|
467
|
+
from llm_context_toolkit import TurnContextCard
|
|
468
|
+
|
|
469
|
+
next_card = TurnContextCard(
|
|
470
|
+
turn_id=current_turn_id + 1,
|
|
471
|
+
user_question=resolution.current_question,
|
|
472
|
+
resolved_question=resolution.resolved_question,
|
|
473
|
+
query_state={
|
|
474
|
+
"active_tables": [t["table_name"] for t in selection.selected_metadata["tables"]],
|
|
475
|
+
"metrics": extract_metrics_from_sql(generated_sql),
|
|
476
|
+
"dimensions": extract_dimensions_from_sql(generated_sql),
|
|
477
|
+
# ... extract other state
|
|
478
|
+
},
|
|
479
|
+
sql=generated_sql,
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
# Store for next turn
|
|
483
|
+
context_store.save(session_id, next_card)
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## ๐งช Testing
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
# Run tests
|
|
492
|
+
pytest
|
|
493
|
+
|
|
494
|
+
# Run with coverage
|
|
495
|
+
pytest --cov=llm_context_toolkit
|
|
496
|
+
|
|
497
|
+
# Run specific test
|
|
498
|
+
pytest tests/test_context_resolver.py::test_fresh_question
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## ๐ Documentation
|
|
504
|
+
|
|
505
|
+
- [Full User Manual](docs/USER_MANUAL.md) - Complete reference guide
|
|
506
|
+
- [Context Resolver Guide](docs/CONTEXT_RESOLVER.md) - Detailed context resolution documentation
|
|
507
|
+
- [Metadata Selector Guide](docs/METADATA_SELECTOR.md) - Detailed metadata selection documentation
|
|
508
|
+
- [Examples](examples/) - Code examples for common use cases
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## ๐ค Contributing
|
|
513
|
+
|
|
514
|
+
Contributions are welcome! Please:
|
|
515
|
+
|
|
516
|
+
1. Fork the repository
|
|
517
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
518
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
519
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
520
|
+
5. Open a Pull Request
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## ๐ License
|
|
525
|
+
|
|
526
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
## ๐ Acknowledgments
|
|
531
|
+
|
|
532
|
+
This library was built to solve real-world problems in multi-tenant analytics systems with Text-to-SQL, dashboard AI assistants, and natural language query interfaces.
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
## ๐ง Support
|
|
537
|
+
|
|
538
|
+
- ๐ [Documentation](docs/USER_MANUAL.md)
|
|
539
|
+
- ๏ฟฝ [Changelog](CHANGELOG.md)
|
|
540
|
+
- ๐ง [Environment Variables](ENVIRONMENT_VARIABLES.md)
|
|
541
|
+
- ๐ [Issue Tracker](https://github.com/sreeyenan/llm_context_toolkit/issues)
|
|
542
|
+
- ๐ฌ [Discussions](https://github.com/sreeyenan/llm_context_toolkit/discussions)
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
**Made with โค๏ธ by sreeyenan**
|