raglite-toolkit 1.0.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.
- raglite_toolkit-1.0.0/.github/workflows/publish.yml +36 -0
- raglite_toolkit-1.0.0/.gitignore +44 -0
- raglite_toolkit-1.0.0/LICENSE +21 -0
- raglite_toolkit-1.0.0/PKG-INFO +388 -0
- raglite_toolkit-1.0.0/README.md +343 -0
- raglite_toolkit-1.0.0/examples/basic.py +47 -0
- raglite_toolkit-1.0.0/examples/multi_provider.py +60 -0
- raglite_toolkit-1.0.0/examples/ollama_test.py +186 -0
- raglite_toolkit-1.0.0/examples/sample.txt +24 -0
- raglite_toolkit-1.0.0/examples/serve.py +52 -0
- raglite_toolkit-1.0.0/pyproject.toml +74 -0
- raglite_toolkit-1.0.0/src/raglite/__init__.py +114 -0
- raglite_toolkit-1.0.0/src/raglite/api/__init__.py +4 -0
- raglite_toolkit-1.0.0/src/raglite/api/schemas.py +26 -0
- raglite_toolkit-1.0.0/src/raglite/api/server.py +198 -0
- raglite_toolkit-1.0.0/src/raglite/chunking/__init__.py +4 -0
- raglite_toolkit-1.0.0/src/raglite/chunking/base.py +13 -0
- raglite_toolkit-1.0.0/src/raglite/chunking/recursive.py +34 -0
- raglite_toolkit-1.0.0/src/raglite/cli.py +212 -0
- raglite_toolkit-1.0.0/src/raglite/config.py +65 -0
- raglite_toolkit-1.0.0/src/raglite/constants.py +18 -0
- raglite_toolkit-1.0.0/src/raglite/core/__init__.py +1 -0
- raglite_toolkit-1.0.0/src/raglite/core/document.py +361 -0
- raglite_toolkit-1.0.0/src/raglite/embeddings/__init__.py +13 -0
- raglite_toolkit-1.0.0/src/raglite/embeddings/base.py +41 -0
- raglite_toolkit-1.0.0/src/raglite/embeddings/factory.py +18 -0
- raglite_toolkit-1.0.0/src/raglite/embeddings/local.py +66 -0
- raglite_toolkit-1.0.0/src/raglite/embeddings/models.py +11 -0
- raglite_toolkit-1.0.0/src/raglite/embeddings/remote.py +158 -0
- raglite_toolkit-1.0.0/src/raglite/errors.py +47 -0
- raglite_toolkit-1.0.0/src/raglite/llm/__init__.py +14 -0
- raglite_toolkit-1.0.0/src/raglite/llm/answer.py +311 -0
- raglite_toolkit-1.0.0/src/raglite/llm/factory.py +119 -0
- raglite_toolkit-1.0.0/src/raglite/llm/models.py +12 -0
- raglite_toolkit-1.0.0/src/raglite/llm/prompt.py +62 -0
- raglite_toolkit-1.0.0/src/raglite/loaders/__init__.py +34 -0
- raglite_toolkit-1.0.0/src/raglite/loaders/base.py +11 -0
- raglite_toolkit-1.0.0/src/raglite/loaders/docx.py +15 -0
- raglite_toolkit-1.0.0/src/raglite/loaders/json.py +40 -0
- raglite_toolkit-1.0.0/src/raglite/loaders/markdown.py +11 -0
- raglite_toolkit-1.0.0/src/raglite/loaders/pdf.py +17 -0
- raglite_toolkit-1.0.0/src/raglite/loaders/txt.py +15 -0
- raglite_toolkit-1.0.0/src/raglite/retrieval/__init__.py +3 -0
- raglite_toolkit-1.0.0/src/raglite/retrieval/retriever.py +57 -0
- raglite_toolkit-1.0.0/src/raglite/types.py +95 -0
- raglite_toolkit-1.0.0/src/raglite/utils/__init__.py +1 -0
- raglite_toolkit-1.0.0/src/raglite/utils/hash.py +26 -0
- raglite_toolkit-1.0.0/src/raglite/utils/logger.py +44 -0
- raglite_toolkit-1.0.0/src/raglite/vectordb/__init__.py +4 -0
- raglite_toolkit-1.0.0/src/raglite/vectordb/base.py +55 -0
- raglite_toolkit-1.0.0/src/raglite/vectordb/memory.py +108 -0
- raglite_toolkit-1.0.0/tests/__init__.py +1 -0
- raglite_toolkit-1.0.0/tests/conftest.py +74 -0
- raglite_toolkit-1.0.0/tests/integration/__init__.py +1 -0
- raglite_toolkit-1.0.0/tests/integration/test_api.py +112 -0
- raglite_toolkit-1.0.0/tests/integration/test_ask.py +102 -0
- raglite_toolkit-1.0.0/tests/integration/test_document.py +142 -0
- raglite_toolkit-1.0.0/tests/integration/test_ollama.py +330 -0
- raglite_toolkit-1.0.0/tests/unit/__init__.py +1 -0
- raglite_toolkit-1.0.0/tests/unit/test_chunking.py +55 -0
- raglite_toolkit-1.0.0/tests/unit/test_cli.py +159 -0
- raglite_toolkit-1.0.0/tests/unit/test_config.py +41 -0
- raglite_toolkit-1.0.0/tests/unit/test_errors.py +43 -0
- raglite_toolkit-1.0.0/tests/unit/test_hash.py +72 -0
- raglite_toolkit-1.0.0/tests/unit/test_loaders.py +100 -0
- raglite_toolkit-1.0.0/tests/unit/test_prompt.py +68 -0
- raglite_toolkit-1.0.0/tests/unit/test_retriever.py +69 -0
- raglite_toolkit-1.0.0/tests/unit/test_vectordb.py +114 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Publish Python Package to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-n-publish:
|
|
10
|
+
name: Build and publish Python distribution to PyPI
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write # Mandatory for Trusted Publishing (OIDC)
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout code
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Install build tools
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install build
|
|
29
|
+
|
|
30
|
+
- name: Build distribution packages
|
|
31
|
+
run: python -m build
|
|
32
|
+
|
|
33
|
+
- name: Publish package distribution to PyPI
|
|
34
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
35
|
+
with:
|
|
36
|
+
skip-existing: true
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
*.so
|
|
7
|
+
*.egg
|
|
8
|
+
*.egg-info/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.eggs/
|
|
12
|
+
wheels/
|
|
13
|
+
|
|
14
|
+
# Virtual environments
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
|
|
19
|
+
# pytest / coverage
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
htmlcov/
|
|
23
|
+
coverage.xml
|
|
24
|
+
|
|
25
|
+
# raglite index stores
|
|
26
|
+
.raglite/
|
|
27
|
+
.raglite_*/
|
|
28
|
+
|
|
29
|
+
# IDE
|
|
30
|
+
.idea/
|
|
31
|
+
.vscode/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
|
|
35
|
+
# macOS
|
|
36
|
+
.DS_Store
|
|
37
|
+
|
|
38
|
+
# Environment variables
|
|
39
|
+
.env
|
|
40
|
+
.env.local
|
|
41
|
+
*.env
|
|
42
|
+
|
|
43
|
+
# Logs
|
|
44
|
+
*.log
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
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,388 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: raglite-toolkit
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Build semantic search, multi-provider question answering, and REST APIs over your documents in a few lines of Python.
|
|
5
|
+
Project-URL: Homepage, https://github.com/piyush-anand/raglite
|
|
6
|
+
Project-URL: Repository, https://github.com/piyush-anand/raglite
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/piyush-anand/raglite/issues
|
|
8
|
+
Author: Piyush Anand
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: anthropic,embeddings,llm,ollama,openai,rag,retrieval-augmented-generation,semantic-search,vector-store
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
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 :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: anthropic>=0.18.0
|
|
24
|
+
Requires-Dist: cohere>=5.0.0
|
|
25
|
+
Requires-Dist: fastapi>=0.100.0
|
|
26
|
+
Requires-Dist: google-generativeai>=0.3.0
|
|
27
|
+
Requires-Dist: httpx>=0.25.0
|
|
28
|
+
Requires-Dist: mistralai>=1.0.0
|
|
29
|
+
Requires-Dist: openai>=1.0.0
|
|
30
|
+
Requires-Dist: pydantic>=2.0
|
|
31
|
+
Requires-Dist: pypdf>=4.0
|
|
32
|
+
Requires-Dist: python-docx>=1.0
|
|
33
|
+
Requires-Dist: sentence-transformers>=2.2.0
|
|
34
|
+
Requires-Dist: uvicorn>=0.20.0
|
|
35
|
+
Requires-Dist: voyageai>=0.1.0
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: httpx>=0.25.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
|
|
42
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
43
|
+
Requires-Dist: twine>=5.0.0; extra == 'dev'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# raglite-toolkit
|
|
47
|
+
|
|
48
|
+
> Build semantic search, multi-provider question answering, and REST APIs over your documents in a few lines of Python.
|
|
49
|
+
|
|
50
|
+
**raglite-toolkit** is a Python port of the [`raglite-toolkit`](https://github.com/creatorpiyush/raglite) TypeScript package with full feature parity.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- 📄 **PDF, TXT, JSON, Markdown, DOCX** loaders out of the box
|
|
57
|
+
- 🤖 **Multi-provider LLMs** — OpenAI, Anthropic (Claude), Google (Gemini), Mistral, Cohere, Groq, xAI, Ollama
|
|
58
|
+
- 🔢 **Multi-provider embeddings** — OpenAI, Google, Mistral, Cohere, Voyage, Ollama, or a **local** offline sentence-transformer (no API key needed)
|
|
59
|
+
- 📐 **Cosine similarity** scoring with L2-normalized vectors
|
|
60
|
+
- ♻️ **Content-hash cache** — reindexes only when the file actually changes
|
|
61
|
+
- 🗂 **Per-document namespacing** — indexes are isolated, two documents never collide
|
|
62
|
+
- 🌐 **REST API** via FastAPI with optional **bearer-token auth**
|
|
63
|
+
- ⚡ **Streaming** answers
|
|
64
|
+
- 🐍 **Python-native** — Pydantic models, type-annotated, fully testable
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install raglite-toolkit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
For **local offline embeddings** (no API key required):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pip install raglite-toolkit sentence-transformers
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
> `sentence-transformers` is included by default. The `all-MiniLM-L6-v2` model (~90 MB) is downloaded automatically on first use.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Quick Start
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from raglite import Document
|
|
88
|
+
|
|
89
|
+
doc = Document("./policy.pdf", {
|
|
90
|
+
"embeddings": {"provider": "openai", "apiKey": "sk-..."},
|
|
91
|
+
"llm": {"provider": "anthropic", "apiKey": "sk-ant-..."},
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
doc.build() # chunk → embed → persist
|
|
95
|
+
|
|
96
|
+
hits = doc.search("refund policy", top_k=3)
|
|
97
|
+
|
|
98
|
+
answer = doc.ask("What is the refund policy?")
|
|
99
|
+
print(answer.text)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Fully Offline — No API Key Needed
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from raglite import Document
|
|
108
|
+
|
|
109
|
+
doc = Document("./policy.pdf", {
|
|
110
|
+
"embeddings": {"provider": "local"}, # sentence-transformers offline
|
|
111
|
+
"llm": {"provider": "ollama", # local Ollama instance
|
|
112
|
+
"model": "llama3.2",
|
|
113
|
+
"baseURL": "http://localhost:11434/api"},
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
doc.build()
|
|
117
|
+
print(doc.ask("What is the refund policy?").text)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Choose Any LLM at Ask-Time
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
# Switch LLMs without rebuilding the index — embeddings are reused
|
|
126
|
+
for llm in [
|
|
127
|
+
{"provider": "openai", "model": "gpt-4o", "apiKey": "sk-..."},
|
|
128
|
+
{"provider": "anthropic", "model": "claude-3-5-sonnet-20241022","apiKey": "sk-ant-..."},
|
|
129
|
+
{"provider": "google", "model": "gemini-2.0-flash", "apiKey": "AI..."},
|
|
130
|
+
{"provider": "groq", "model": "llama-3.3-70b-versatile", "apiKey": "gsk_..."},
|
|
131
|
+
]:
|
|
132
|
+
answer = doc.ask("Summarize this document", {"llm": llm})
|
|
133
|
+
print(f"[{llm['provider']}] {answer.text[:120]}")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Streaming
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
for chunk in doc.ask_stream("Explain the introduction"):
|
|
142
|
+
print(chunk, end="", flush=True)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## REST API
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
handle = doc.serve({
|
|
151
|
+
"port": 8085,
|
|
152
|
+
"llm": {"provider": "openai", "apiKey": "sk-..."},
|
|
153
|
+
"bearerToken": "my-secret-token",
|
|
154
|
+
})
|
|
155
|
+
print(f"Serving on {handle.url}")
|
|
156
|
+
|
|
157
|
+
# ... later
|
|
158
|
+
handle.close()
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Endpoints
|
|
162
|
+
|
|
163
|
+
| Method | Path | Auth? | Description |
|
|
164
|
+
|--------|-----------|-------|-------------|
|
|
165
|
+
| `GET` | `/health` | ❌ | Liveness + index stats |
|
|
166
|
+
| `GET` | `/info` | ✅ | Configuration snapshot |
|
|
167
|
+
| `POST` | `/search` | ✅ | Semantic search |
|
|
168
|
+
| `POST` | `/ask` | ✅ | Question answering |
|
|
169
|
+
|
|
170
|
+
### Example `curl` calls
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Health check (no auth)
|
|
174
|
+
curl http://127.0.0.1:8085/health
|
|
175
|
+
|
|
176
|
+
# Search
|
|
177
|
+
curl -X POST http://127.0.0.1:8085/search \
|
|
178
|
+
-H 'Authorization: Bearer my-secret-token' \
|
|
179
|
+
-H 'Content-Type: application/json' \
|
|
180
|
+
-d '{"query": "refund policy", "topK": 3}'
|
|
181
|
+
|
|
182
|
+
# Ask (non-streaming)
|
|
183
|
+
curl -X POST http://127.0.0.1:8085/ask \
|
|
184
|
+
-H 'Authorization: Bearer my-secret-token' \
|
|
185
|
+
-H 'Content-Type: application/json' \
|
|
186
|
+
-d '{"question": "What is the refund policy?"}'
|
|
187
|
+
|
|
188
|
+
# Ask (streaming)
|
|
189
|
+
curl -X POST http://127.0.0.1:8085/ask \
|
|
190
|
+
-H 'Authorization: Bearer my-secret-token' \
|
|
191
|
+
-H 'Content-Type: application/json' \
|
|
192
|
+
-d '{"question": "Summarize the document", "stream": true}'
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## CLI
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# Index a document
|
|
201
|
+
raglite index ./policy.pdf --embed-provider local
|
|
202
|
+
|
|
203
|
+
# Semantic search
|
|
204
|
+
raglite search ./policy.pdf "refund policy" --top-k 5
|
|
205
|
+
|
|
206
|
+
# Ask a question (streaming)
|
|
207
|
+
raglite ask ./policy.pdf "What is the refund policy?" \
|
|
208
|
+
--llm-provider openai --llm-key $OPENAI_API_KEY --stream
|
|
209
|
+
|
|
210
|
+
# Serve a REST API
|
|
211
|
+
raglite serve ./policy.pdf \
|
|
212
|
+
--llm-provider openai --llm-key $OPENAI_API_KEY \
|
|
213
|
+
--port 8085 --token $RAGLITE_TOKEN
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Supported Providers
|
|
219
|
+
|
|
220
|
+
### LLMs
|
|
221
|
+
|
|
222
|
+
| Provider | `provider` key | Default model |
|
|
223
|
+
|----------------|----------------|---------------|
|
|
224
|
+
| OpenAI | `openai` | `gpt-4o-mini` |
|
|
225
|
+
| Anthropic | `anthropic` | `claude-3-5-sonnet-20241022` |
|
|
226
|
+
| Google | `google` | `gemini-2.0-flash` |
|
|
227
|
+
| Mistral | `mistral` | `mistral-large-latest` |
|
|
228
|
+
| Cohere | `cohere` | `command-r-plus` |
|
|
229
|
+
| Groq | `groq` | `llama-3.3-70b-versatile` |
|
|
230
|
+
| xAI (Grok) | `xai` | `grok-2-latest` |
|
|
231
|
+
| Ollama (local) | `ollama` | `llama3.2` |
|
|
232
|
+
|
|
233
|
+
### Embeddings
|
|
234
|
+
|
|
235
|
+
| Provider | `provider` key | Default model |
|
|
236
|
+
|----------------|----------------|---------------|
|
|
237
|
+
| OpenAI | `openai` | `text-embedding-3-small` |
|
|
238
|
+
| Google | `google` | `text-embedding-004` |
|
|
239
|
+
| Mistral | `mistral` | `mistral-embed` |
|
|
240
|
+
| Cohere | `cohere` | `embed-english-v3.0` |
|
|
241
|
+
| Voyage | `voyage` | `voyage-3` |
|
|
242
|
+
| Ollama (local) | `ollama` | `nomic-embed-text` |
|
|
243
|
+
| Local (offline)| `local` | `all-MiniLM-L6-v2` |
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Configuration Reference
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
Document("./policy.pdf", {
|
|
251
|
+
# Chunking
|
|
252
|
+
"chunkSize": 500, # words per chunk (default: 500)
|
|
253
|
+
"overlap": 50, # overlapping words between chunks (default: 50)
|
|
254
|
+
|
|
255
|
+
# Retrieval
|
|
256
|
+
"topK": 5, # default results returned (default: 5)
|
|
257
|
+
"scoreThreshold": 0.0, # minimum cosine similarity (0..1, default: 0)
|
|
258
|
+
|
|
259
|
+
# Storage
|
|
260
|
+
"storeDir": ".raglite", # where indexes are persisted (default: .raglite)
|
|
261
|
+
|
|
262
|
+
# Providers
|
|
263
|
+
"embeddings": {"provider": "local"},
|
|
264
|
+
"llm": {"provider": "openai", "model": "gpt-4o-mini", "apiKey": "sk-..."},
|
|
265
|
+
|
|
266
|
+
# Logging
|
|
267
|
+
"logLevel": "info", # "silent" | "info" | "debug" (default: info)
|
|
268
|
+
})
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## How Caching Works
|
|
274
|
+
|
|
275
|
+
Every `build()` call fingerprints the source file with a **SHA-256 content hash** and persists it alongside the vectors. The cached index is reused only if **all** of the following match the stored index:
|
|
276
|
+
|
|
277
|
+
| Factor | Triggers rebuild if changed |
|
|
278
|
+
|--------|-----------------------------|
|
|
279
|
+
| File content | SHA-256 hash differs |
|
|
280
|
+
| Chunk size | `chunkSize` changed |
|
|
281
|
+
| Overlap | `overlap` changed |
|
|
282
|
+
| Embedding provider/model | Provider or model string changed |
|
|
283
|
+
| Library version | Package version bumped |
|
|
284
|
+
|
|
285
|
+
Pass `rebuild=True` to `build()` to force a fresh index regardless.
|
|
286
|
+
|
|
287
|
+
Each document is stored under `.raglite/<sha256-prefix>/`, so multiple documents in the same project never overwrite each other.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Advanced Usage
|
|
292
|
+
|
|
293
|
+
### Custom Vector Store
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
from raglite.vectordb.base import VectorStore
|
|
297
|
+
|
|
298
|
+
class MyVectorStore(VectorStore):
|
|
299
|
+
# Implement: load, reset, add, search, count,
|
|
300
|
+
# save_index_metadata, read_index_metadata
|
|
301
|
+
...
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Custom Loader
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
from raglite.loaders.base import BaseLoader
|
|
308
|
+
from raglite.loaders import get_loader
|
|
309
|
+
|
|
310
|
+
class CsvLoader(BaseLoader):
|
|
311
|
+
def load(self) -> str:
|
|
312
|
+
# read CSV, return string
|
|
313
|
+
...
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Custom Chunker
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
from raglite.chunking.base import BaseChunker
|
|
320
|
+
|
|
321
|
+
class SentenceChunker(BaseChunker):
|
|
322
|
+
def split(self, text: str) -> list[str]:
|
|
323
|
+
...
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Direct Embedder Access
|
|
327
|
+
|
|
328
|
+
```python
|
|
329
|
+
from raglite import create_embedder
|
|
330
|
+
|
|
331
|
+
embedder = create_embedder({"provider": "openai", "apiKey": "sk-..."})
|
|
332
|
+
vectors = embedder.embed_documents(["chunk one", "chunk two"])
|
|
333
|
+
query_vec = embedder.embed_query("refund policy")
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Development
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
# Clone and set up
|
|
342
|
+
git clone <repo>
|
|
343
|
+
cd raglite-py
|
|
344
|
+
|
|
345
|
+
# Create virtual environment
|
|
346
|
+
python3.12 -m venv .venv
|
|
347
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
348
|
+
|
|
349
|
+
# Install in editable mode with dev dependencies
|
|
350
|
+
pip install -e ".[dev]"
|
|
351
|
+
|
|
352
|
+
# Run tests (76 tests, ~5s, no network required)
|
|
353
|
+
pytest
|
|
354
|
+
|
|
355
|
+
# Run with coverage
|
|
356
|
+
pytest --cov=raglite --cov-report=term-missing
|
|
357
|
+
|
|
358
|
+
# Run examples (uses local offline embeddings)
|
|
359
|
+
python examples/basic.py
|
|
360
|
+
python examples/multi_provider.py # requires API keys in env
|
|
361
|
+
python examples/serve.py
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Test Structure
|
|
365
|
+
|
|
366
|
+
```
|
|
367
|
+
tests/
|
|
368
|
+
├── unit/
|
|
369
|
+
│ ├── test_chunking.py # RecursiveChunker algorithm
|
|
370
|
+
│ ├── test_vectordb.py # MemoryVectorStore (cosine, persistence, isolation)
|
|
371
|
+
│ ├── test_loaders.py # TxtLoader, MarkdownLoader, JsonLoader
|
|
372
|
+
│ ├── test_prompt.py # system/user prompt builders
|
|
373
|
+
│ ├── test_errors.py # exception hierarchy
|
|
374
|
+
│ ├── test_config.py # config defaults and overrides
|
|
375
|
+
│ ├── test_hash.py # SHA-256 file hashing + namespace generation
|
|
376
|
+
│ ├── test_retriever.py # Retriever with mocked embedder
|
|
377
|
+
│ └── test_cli.py # CLI commands and argument parsing
|
|
378
|
+
└── integration/
|
|
379
|
+
├── test_document.py # build/cache/search lifecycle (mocked embeddings)
|
|
380
|
+
├── test_ask.py # ask/stream with mocked LLM generation
|
|
381
|
+
└── test_api.py # FastAPI endpoints via TestClient
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## License
|
|
387
|
+
|
|
388
|
+
MIT
|