kssrag 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.
- kssrag/__init__.py +66 -0
- kssrag/cli.py +142 -0
- kssrag/config.py +193 -0
- kssrag/core/__init__.py +0 -0
- kssrag/core/agents.py +68 -0
- kssrag/core/chunkers.py +100 -0
- kssrag/core/retrievers.py +74 -0
- kssrag/core/vectorstores.py +397 -0
- kssrag/kssrag.py +116 -0
- kssrag/models/__init__.py +0 -0
- kssrag/models/local_llms.py +30 -0
- kssrag/models/openrouter.py +85 -0
- kssrag/server.py +116 -0
- kssrag/utils/__init__.py +0 -0
- kssrag/utils/document_loaders.py +40 -0
- kssrag/utils/helpers.py +55 -0
- kssrag/utils/preprocessors.py +30 -0
- kssrag-0.1.0.dist-info/METADATA +407 -0
- kssrag-0.1.0.dist-info/RECORD +26 -0
- kssrag-0.1.0.dist-info/WHEEL +5 -0
- kssrag-0.1.0.dist-info/entry_points.txt +2 -0
- kssrag-0.1.0.dist-info/licenses/LICENSE +0 -0
- kssrag-0.1.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/test_basic.py +43 -0
- tests/test_vectorstores.py +35 -0
kssrag/server.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from fastapi import FastAPI, HTTPException
|
|
2
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
from typing import Dict, Any, Optional, List
|
|
5
|
+
import uuid
|
|
6
|
+
|
|
7
|
+
from .core.agents import RAGAgent
|
|
8
|
+
from .utils.helpers import logger
|
|
9
|
+
from .config import config
|
|
10
|
+
|
|
11
|
+
class QueryRequest(BaseModel):
|
|
12
|
+
query: str
|
|
13
|
+
session_id: Optional[str] = None
|
|
14
|
+
|
|
15
|
+
class ServerConfig(BaseModel):
|
|
16
|
+
"""Configuration for the FastAPI server"""
|
|
17
|
+
host: str = config.SERVER_HOST
|
|
18
|
+
port: int = config.SERVER_PORT
|
|
19
|
+
cors_origins: List[str] = config.CORS_ORIGINS
|
|
20
|
+
cors_allow_credentials: bool = config.CORS_ALLOW_CREDENTIALS
|
|
21
|
+
cors_allow_methods: List[str] = config.CORS_ALLOW_METHODS
|
|
22
|
+
cors_allow_headers: List[str] = config.CORS_ALLOW_HEADERS
|
|
23
|
+
title: str = "KSS RAG API"
|
|
24
|
+
description: str = "A Retrieval-Augmented Generation API by Ksschkw"
|
|
25
|
+
version: str = "0.1.0"
|
|
26
|
+
|
|
27
|
+
def create_app(rag_agent: RAGAgent, server_config: Optional[ServerConfig] = None):
|
|
28
|
+
"""Create a FastAPI app for the RAG agent with configurable CORS"""
|
|
29
|
+
if server_config is None:
|
|
30
|
+
server_config = ServerConfig()
|
|
31
|
+
|
|
32
|
+
app = FastAPI(
|
|
33
|
+
title=server_config.title,
|
|
34
|
+
description=server_config.description,
|
|
35
|
+
version=server_config.version
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Configure CORS middleware
|
|
39
|
+
app.add_middleware(
|
|
40
|
+
CORSMiddleware,
|
|
41
|
+
allow_origins=server_config.cors_origins,
|
|
42
|
+
allow_credentials=server_config.cors_allow_credentials,
|
|
43
|
+
allow_methods=server_config.cors_allow_methods,
|
|
44
|
+
allow_headers=server_config.cors_allow_headers,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Session management
|
|
48
|
+
sessions = {}
|
|
49
|
+
|
|
50
|
+
@app.post("/query")
|
|
51
|
+
async def query_endpoint(request: QueryRequest):
|
|
52
|
+
"""Handle user queries"""
|
|
53
|
+
query = request.query
|
|
54
|
+
session_id = request.session_id or str(uuid.uuid4())
|
|
55
|
+
|
|
56
|
+
if not query.strip():
|
|
57
|
+
raise HTTPException(status_code=400, detail="Query cannot be empty")
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
# Get or create session
|
|
61
|
+
if session_id not in sessions:
|
|
62
|
+
logger.info(f"Creating new session: {session_id}")
|
|
63
|
+
# Create a new agent for this session
|
|
64
|
+
sessions[session_id] = RAGAgent(
|
|
65
|
+
retriever=rag_agent.retriever,
|
|
66
|
+
llm=rag_agent.llm,
|
|
67
|
+
system_prompt=rag_agent.system_prompt
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
agent = sessions[session_id]
|
|
71
|
+
response = agent.query(query)
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
"query": query,
|
|
75
|
+
"response": response,
|
|
76
|
+
"session_id": session_id
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
except Exception as e:
|
|
80
|
+
logger.error(f"Error handling query: {str(e)}")
|
|
81
|
+
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
|
|
82
|
+
|
|
83
|
+
@app.get("/health")
|
|
84
|
+
async def health_check():
|
|
85
|
+
"""Health check endpoint"""
|
|
86
|
+
return {
|
|
87
|
+
"status": "healthy",
|
|
88
|
+
"message": "KSS RAG API is running",
|
|
89
|
+
"version": server_config.version
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@app.get("/config")
|
|
93
|
+
async def get_config():
|
|
94
|
+
"""Get current server configuration"""
|
|
95
|
+
return server_config.dict()
|
|
96
|
+
|
|
97
|
+
@app.get("/sessions/{session_id}/clear")
|
|
98
|
+
async def clear_session(session_id: str):
|
|
99
|
+
"""Clear a session's conversation history"""
|
|
100
|
+
if session_id in sessions:
|
|
101
|
+
sessions[session_id].clear_conversation()
|
|
102
|
+
return {"message": f"Session {session_id} cleared"}
|
|
103
|
+
else:
|
|
104
|
+
raise HTTPException(status_code=404, detail="Session not found")
|
|
105
|
+
|
|
106
|
+
@app.get("/")
|
|
107
|
+
async def root():
|
|
108
|
+
"""Root endpoint with API information"""
|
|
109
|
+
return {
|
|
110
|
+
"message": "Welcome to KSS RAG API",
|
|
111
|
+
"version": server_config.version,
|
|
112
|
+
"docs": "/docs",
|
|
113
|
+
"health": "/health"
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return app, server_config
|
kssrag/utils/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import List, Dict, Any, Optional
|
|
3
|
+
from ..utils.helpers import logger
|
|
4
|
+
|
|
5
|
+
def load_txt_file(file_path: str) -> str:
|
|
6
|
+
"""Load text from a file"""
|
|
7
|
+
try:
|
|
8
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
9
|
+
return f.read()
|
|
10
|
+
except Exception as e:
|
|
11
|
+
logger.error(f"Failed to load text file: {str(e)}")
|
|
12
|
+
raise
|
|
13
|
+
|
|
14
|
+
def load_json_file(file_path: str) -> Any:
|
|
15
|
+
"""Load JSON from a file"""
|
|
16
|
+
try:
|
|
17
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
18
|
+
return json.load(f)
|
|
19
|
+
except Exception as e:
|
|
20
|
+
logger.error(f"Failed to load JSON file: {str(e)}")
|
|
21
|
+
raise
|
|
22
|
+
|
|
23
|
+
def load_document(file_path: str) -> str:
|
|
24
|
+
"""Load document from file (supports .txt)"""
|
|
25
|
+
if file_path.endswith('.txt'):
|
|
26
|
+
return load_txt_file(file_path)
|
|
27
|
+
else:
|
|
28
|
+
raise ValueError(f"Unsupported file type: {file_path}")
|
|
29
|
+
|
|
30
|
+
def load_json_documents(file_path: str, metadata_field: str = "name") -> List[Dict[str, Any]]:
|
|
31
|
+
"""Load documents from JSON file (like your drug data)"""
|
|
32
|
+
data = load_json_file(file_path)
|
|
33
|
+
|
|
34
|
+
# Apply limit for testing if specified
|
|
35
|
+
from ..config import config
|
|
36
|
+
if config.MAX_DOCS_FOR_TESTING:
|
|
37
|
+
data = data[:config.MAX_DOCS_FOR_TESTING]
|
|
38
|
+
logger.info(f"Limited to {config.MAX_DOCS_FOR_TESTING} documents for testing")
|
|
39
|
+
|
|
40
|
+
return data
|
kssrag/utils/helpers.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import importlib
|
|
3
|
+
|
|
4
|
+
# Set up logging
|
|
5
|
+
logging.basicConfig(
|
|
6
|
+
level=logging.INFO,
|
|
7
|
+
format='%(levelname)s:KSSRAG:%(message)s'
|
|
8
|
+
)
|
|
9
|
+
logger = logging.getLogger("KSSRAG")
|
|
10
|
+
|
|
11
|
+
# Your signature in the code
|
|
12
|
+
def kss_signature():
|
|
13
|
+
return "Built with HATE by Ksschkw (github.com/Ksschkw)"
|
|
14
|
+
|
|
15
|
+
def validate_config():
|
|
16
|
+
"""Validate the configuration"""
|
|
17
|
+
from ..config import config
|
|
18
|
+
|
|
19
|
+
if not config.OPENROUTER_API_KEY:
|
|
20
|
+
logger.warning("OPENROUTER_API_KEY not set. LLM functionality will not work.")
|
|
21
|
+
|
|
22
|
+
return True
|
|
23
|
+
|
|
24
|
+
def import_custom_component(import_path: str):
|
|
25
|
+
"""Import a custom component from a string path"""
|
|
26
|
+
try:
|
|
27
|
+
module_path, class_name = import_path.rsplit('.', 1)
|
|
28
|
+
module = importlib.import_module(module_path)
|
|
29
|
+
return getattr(module, class_name)
|
|
30
|
+
except (ImportError, AttributeError, ValueError) as e:
|
|
31
|
+
logger.error(f"Failed to import custom component {import_path}: {str(e)}")
|
|
32
|
+
raise
|
|
33
|
+
|
|
34
|
+
# import os
|
|
35
|
+
# import logging
|
|
36
|
+
# from .utils.helpers import logger
|
|
37
|
+
|
|
38
|
+
# def setup_faiss():
|
|
39
|
+
# """Handle FAISS initialization with proper error handling"""
|
|
40
|
+
# try:
|
|
41
|
+
# # Try to load with AVX2 support first
|
|
42
|
+
# logger.info("Loading faiss with AVX2 support.")
|
|
43
|
+
# from faiss.swigfaiss_avx2 import *
|
|
44
|
+
# logger.info("Successfully loaded faiss with AVX2 support.")
|
|
45
|
+
# return True
|
|
46
|
+
# except ImportError as e:
|
|
47
|
+
# logger.info(f"Could not load library with AVX2 support due to:\n{repr(e)}")
|
|
48
|
+
# logger.info("Falling back to standard FAISS without AVX2 support")
|
|
49
|
+
# try:
|
|
50
|
+
# from faiss.swigfaiss import *
|
|
51
|
+
# logger.info("Successfully loaded standard faiss.")
|
|
52
|
+
# return False
|
|
53
|
+
# except ImportError as e:
|
|
54
|
+
# logger.error(f"Failed to load any FAISS version: {repr(e)}")
|
|
55
|
+
# raise
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Text preprocessing utilities for document preparation
|
|
3
|
+
"""
|
|
4
|
+
import re
|
|
5
|
+
from typing import List
|
|
6
|
+
from .helpers import logger
|
|
7
|
+
|
|
8
|
+
def clean_text(text: str) -> str:
|
|
9
|
+
"""Clean text by removing extra whitespace and special characters"""
|
|
10
|
+
# Remove extra whitespace
|
|
11
|
+
text = re.sub(r'\s+', ' ', text)
|
|
12
|
+
# Remove special characters except basic punctuation
|
|
13
|
+
text = re.sub(r'[^\w\s.,!?;:]', '', text)
|
|
14
|
+
return text.strip()
|
|
15
|
+
|
|
16
|
+
def split_sentences(text: str) -> List[str]:
|
|
17
|
+
"""Split text into sentences"""
|
|
18
|
+
# Simple sentence splitting
|
|
19
|
+
sentences = re.split(r'[.!?]+', text)
|
|
20
|
+
return [s.strip() for s in sentences if s.strip()]
|
|
21
|
+
|
|
22
|
+
def preprocess_document(text: str, clean: bool = True, split: bool = False) -> str | List[str]:
|
|
23
|
+
"""Preprocess a document with various options"""
|
|
24
|
+
if clean:
|
|
25
|
+
text = clean_text(text)
|
|
26
|
+
|
|
27
|
+
if split:
|
|
28
|
+
return split_sentences(text)
|
|
29
|
+
|
|
30
|
+
return text
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kssrag
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A flexible Retrieval-Augmented Generation framework by Ksschkw
|
|
5
|
+
Home-page: https://github.com/Ksschkw/kssrag
|
|
6
|
+
Author: Ksschkw
|
|
7
|
+
Author-email: kookafor893@gmail.com
|
|
8
|
+
Project-URL: Bug Reports, https://github.com/Ksschkw/kssrag/issues
|
|
9
|
+
Project-URL: Source, https://github.com/Ksschkw/kssrag
|
|
10
|
+
Project-URL: Documentation, https://github.com/Ksschkw/kssrag/docs
|
|
11
|
+
Keywords: rag,retrieval,generation,ai,nlp,faiss,bm25
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
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.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Requires-Python: >=3.8, <4
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: fastapi>=0.104.0
|
|
27
|
+
Requires-Dist: uvicorn>=0.24.0
|
|
28
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
29
|
+
Requires-Dist: requests>=2.31.0
|
|
30
|
+
Requires-Dist: rank-bm25>=0.2.2
|
|
31
|
+
Requires-Dist: numpy>=1.26.0
|
|
32
|
+
Requires-Dist: faiss-cpu>=1.7.0
|
|
33
|
+
Requires-Dist: sentence-transformers>=3.0.0
|
|
34
|
+
Requires-Dist: pydantic>=2.0.0
|
|
35
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
36
|
+
Requires-Dist: rapidfuzz>=3.0.0
|
|
37
|
+
Requires-Dist: python-multipart>=0.0.6
|
|
38
|
+
Requires-Dist: pypdf>=3.0.0
|
|
39
|
+
Requires-Dist: scikit-learn>=1.0.0
|
|
40
|
+
Requires-Dist: scipy>=1.7.0
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: pytest; extra == "dev"
|
|
43
|
+
Requires-Dist: black; extra == "dev"
|
|
44
|
+
Requires-Dist: flake8; extra == "dev"
|
|
45
|
+
Requires-Dist: mypy; extra == "dev"
|
|
46
|
+
Provides-Extra: gpu
|
|
47
|
+
Requires-Dist: faiss-gpu>=1.7.0; extra == "gpu"
|
|
48
|
+
Provides-Extra: all
|
|
49
|
+
Requires-Dist: faiss-gpu>=1.7.0; extra == "all"
|
|
50
|
+
Requires-Dist: sentence-transformers[gpu]; extra == "all"
|
|
51
|
+
Dynamic: author
|
|
52
|
+
Dynamic: author-email
|
|
53
|
+
Dynamic: classifier
|
|
54
|
+
Dynamic: description
|
|
55
|
+
Dynamic: description-content-type
|
|
56
|
+
Dynamic: home-page
|
|
57
|
+
Dynamic: keywords
|
|
58
|
+
Dynamic: license-file
|
|
59
|
+
Dynamic: project-url
|
|
60
|
+
Dynamic: provides-extra
|
|
61
|
+
Dynamic: requires-dist
|
|
62
|
+
Dynamic: requires-python
|
|
63
|
+
Dynamic: summary
|
|
64
|
+
|
|
65
|
+
# 🚀 KSS RAG - Knowledge Retrieval Augmented Generation Framework
|
|
66
|
+
|
|
67
|
+
> Built by [Ksschkw](https://github.com/Ksschkw)
|
|
68
|
+
|
|
69
|
+

|
|
70
|
+

|
|
71
|
+

|
|
72
|
+

|
|
73
|
+

|
|
74
|
+
|
|
75
|
+
**The RAG framework that actually works on your machine - no excuses, no compromises.** 😎
|
|
76
|
+
|
|
77
|
+
## ✨ Why KSS RAG?
|
|
78
|
+
|
|
79
|
+
I built this because I was tired of:
|
|
80
|
+
- Using thesame codebase over and over 🤬 (I was not really tired, i was just bored)
|
|
81
|
+
- Dependencies that require PhD-level installation skills 🎓(This is just buzz)
|
|
82
|
+
- Documentation that assumes you already know everything 🤦 (Read a flipping book g)
|
|
83
|
+
- APIs that make simple things complicated - I MIGHT HATE GROQ (No shade)
|
|
84
|
+
- I built this for my personal use but you can `pip install kssrag` if you like
|
|
85
|
+
|
|
86
|
+
## 🚀 Quick Start
|
|
87
|
+
|
|
88
|
+
### Installation
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# pip installation
|
|
92
|
+
pip install kssrag
|
|
93
|
+
|
|
94
|
+
# or from source
|
|
95
|
+
git clone https://github.com/Ksschkw/kssrag
|
|
96
|
+
cd kssrag
|
|
97
|
+
pip install -e .
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Basic Usage
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from kssrag import KSSRAG
|
|
104
|
+
import os
|
|
105
|
+
|
|
106
|
+
os.environ["OPENROUTER_API_KEY"] = "your_key_here_do_not_share_this_you_little_dev"
|
|
107
|
+
|
|
108
|
+
rag = KSSRAG()
|
|
109
|
+
rag.load_document("document.txt")
|
|
110
|
+
response = rag.query("What's this about?")
|
|
111
|
+
print(response)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### CLI Usage
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Set your API key
|
|
118
|
+
export OPENROUTER_API_KEY="your_key_here"
|
|
119
|
+
|
|
120
|
+
# Query documents
|
|
121
|
+
python -m kssrag.cli query --file document.txt --query "Main ideas?"
|
|
122
|
+
|
|
123
|
+
# Start API server
|
|
124
|
+
python -m kssrag.cli server --file document.txt --port 8000
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 🐳 Docker Deployment
|
|
128
|
+
|
|
129
|
+
### Using Docker Compose (Recommended)
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Create environment file
|
|
133
|
+
echo "OPENROUTER_API_KEY=your_key_here" > .env
|
|
134
|
+
|
|
135
|
+
# Start services
|
|
136
|
+
docker-compose up -d
|
|
137
|
+
|
|
138
|
+
# View logs
|
|
139
|
+
docker-compose logs -f
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Manual Docker Build
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Build image
|
|
146
|
+
docker build -t kssrag .
|
|
147
|
+
|
|
148
|
+
# Run container
|
|
149
|
+
docker run -p 8000:8000 \
|
|
150
|
+
-e OPENROUTER_API_KEY="your_key_here" \
|
|
151
|
+
-v $(pwd)/documents:/app/documents \
|
|
152
|
+
kssrag
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## ⚙️ Configuration Mastery
|
|
156
|
+
|
|
157
|
+
### Environment Variables
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Required
|
|
161
|
+
OPENROUTER_API_KEY=your_openrouter_key
|
|
162
|
+
|
|
163
|
+
# Model settings
|
|
164
|
+
DEFAULT_MODEL=anthropic/claude-3-sonnet # This is a premium model incase you get an error, cheap ass
|
|
165
|
+
FALLBACK_MODELS=deepseek/deepseek-chat-v3.1:free,google/gemini-pro-1.5
|
|
166
|
+
|
|
167
|
+
# Vector stores
|
|
168
|
+
VECTOR_STORE_TYPE=hybrid_online #Uses FAISS+BM25 # hybrid_offline also available, uses tfidf + bm25
|
|
169
|
+
|
|
170
|
+
# Chunking
|
|
171
|
+
CHUNK_SIZE=800
|
|
172
|
+
CHUNK_OVERLAP=100
|
|
173
|
+
|
|
174
|
+
# Retrieval
|
|
175
|
+
TOP_K=8
|
|
176
|
+
FUZZY_MATCH_THRESHOLD=85
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Advanced Programmatic Configuration
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from kssrag import Config, VectorStoreType, RetrieverType
|
|
183
|
+
|
|
184
|
+
config = Config(
|
|
185
|
+
OPENROUTER_API_KEY="your_key",
|
|
186
|
+
DEFAULT_MODEL="anthropic/claude-3-sonnet",
|
|
187
|
+
VECTOR_STORE_TYPE=VectorStoreType.HYBRID_ONLINE,
|
|
188
|
+
RETRIEVER_TYPE=RetrieverType.HYBRID,
|
|
189
|
+
TOP_K=10,
|
|
190
|
+
CHUNK_SIZE=1000,
|
|
191
|
+
CHUNK_OVERLAP=150
|
|
192
|
+
)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## 🎯 Advanced Features
|
|
196
|
+
|
|
197
|
+
### Custom System Prompts
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
from kssrag.core.agents import RAGAgent
|
|
201
|
+
from kssrag.models.openrouter import OpenRouterLLM
|
|
202
|
+
|
|
203
|
+
custom_prompt = """You are an expert AI assistant. Answer questions confidently
|
|
204
|
+
and directly without prefacing with "Based on the context". Be authoritative
|
|
205
|
+
while staying truthful to the source material."""
|
|
206
|
+
|
|
207
|
+
llm = OpenRouterLLM(api_key="your_key", model="anthropic/claude-3-sonnet")
|
|
208
|
+
agent = RAGAgent(retriever=rag.retriever, llm=llm, system_prompt=custom_prompt)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Multiple Document Types
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
# Text files
|
|
215
|
+
rag.load_document("notes.txt")
|
|
216
|
+
|
|
217
|
+
# PDF documents
|
|
218
|
+
rag.load_document("research.pdf", format="pdf")
|
|
219
|
+
|
|
220
|
+
# JSON data
|
|
221
|
+
rag.load_document("data.json", format="json")
|
|
222
|
+
|
|
223
|
+
# With custom metadata
|
|
224
|
+
rag.load_document("file.txt", metadata={"source": "internal", "category": "technical"})
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## 📊 Performance Optimization
|
|
228
|
+
|
|
229
|
+
### Batch Processing
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
config = Config(
|
|
233
|
+
BATCH_SIZE=64, # Larger batches for better performance
|
|
234
|
+
MAX_DOCS_FOR_TESTING=1000 # Limit for testing
|
|
235
|
+
)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Cache Management
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
config = Config(
|
|
242
|
+
ENABLE_CACHE=True,
|
|
243
|
+
CACHE_DIR="./.rag_cache", # Custom cache location ---DO NOT DO THIS IF YOU ARE USIINF FAISS ON WINDOWS, f**k around and find out
|
|
244
|
+
LOG_LEVEL="DEBUG" # Detailed logging
|
|
245
|
+
)
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## 🧪 Testing & Validation
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
# Run all tests
|
|
252
|
+
python -m pytest tests/
|
|
253
|
+
|
|
254
|
+
# Specific test file
|
|
255
|
+
python -m pytest tests/test_basic.py
|
|
256
|
+
|
|
257
|
+
# With coverage report
|
|
258
|
+
python -m pytest --cov=kssrag tests/
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## 🚨 Troubleshooting
|
|
262
|
+
|
|
263
|
+
### Common Issues
|
|
264
|
+
|
|
265
|
+
**CLI Command Not Found**
|
|
266
|
+
```bash
|
|
267
|
+
# Use module syntax on Windows
|
|
268
|
+
python -m kssrag.cli query --file document.txt --query "Your question"
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**FAISS Windows Issues**
|
|
272
|
+
```bash
|
|
273
|
+
# Use hybrid offline vector store
|
|
274
|
+
setx VECTOR_STORE_TYPE hybrid_offline
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**API Key Issues**
|
|
278
|
+
```bash
|
|
279
|
+
# Verify your OpenRouter key
|
|
280
|
+
echo $OPENROUTER_API_KEY
|
|
281
|
+
|
|
282
|
+
# Or set it permanently
|
|
283
|
+
setx OPENROUTER_API_KEY "your_actual_key_here"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Debug Mode
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# Enable debug logging
|
|
290
|
+
setx LOG_LEVEL DEBUG
|
|
291
|
+
|
|
292
|
+
# Or in code
|
|
293
|
+
import logging
|
|
294
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## 📈 Production Deployment
|
|
298
|
+
|
|
299
|
+
### Environment Setup
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
# Create production environment
|
|
303
|
+
python -m venv venv
|
|
304
|
+
source venv/bin/activate # Linux/Mac
|
|
305
|
+
# venv\Scripts\activate # Windows
|
|
306
|
+
|
|
307
|
+
# Install with production dependencies
|
|
308
|
+
pip install kssrag
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Systemd Service (Linux)
|
|
312
|
+
|
|
313
|
+
```ini
|
|
314
|
+
#I do not know this, this is AI slop i do not know if it works, tho it might
|
|
315
|
+
# /etc/systemd/system/kssrag.service
|
|
316
|
+
[Unit]
|
|
317
|
+
Description=KSS RAG Service
|
|
318
|
+
After=network.target
|
|
319
|
+
|
|
320
|
+
[Service]
|
|
321
|
+
User=appuser
|
|
322
|
+
Group=appuser
|
|
323
|
+
WorkingDirectory=/opt/kssrag
|
|
324
|
+
Environment=OPENROUTER_API_KEY=your_key_here
|
|
325
|
+
ExecStart=/opt/kssrag/venv/bin/python -m kssrag.cli server --port 8000
|
|
326
|
+
Restart=always
|
|
327
|
+
|
|
328
|
+
[Install]
|
|
329
|
+
WantedBy=multi-user.target
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## 🤝 Contributing
|
|
333
|
+
|
|
334
|
+
### Development Setup
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
# Clone and setup
|
|
338
|
+
git clone https://github.com/Ksschkw/kssrag
|
|
339
|
+
cd kssrag
|
|
340
|
+
|
|
341
|
+
# Install development dependencies
|
|
342
|
+
pip install -e .[dev]
|
|
343
|
+
|
|
344
|
+
# Run tests
|
|
345
|
+
python -m pytest
|
|
346
|
+
|
|
347
|
+
# Code formatting
|
|
348
|
+
black kssrag/ tests/
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Code Structure
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
kssrag/
|
|
355
|
+
├── core/ # Core functionality
|
|
356
|
+
├── models/ # LLM integrations
|
|
357
|
+
├── utils/ # Utilities & helpers
|
|
358
|
+
├── config.py # Configuration management
|
|
359
|
+
├── server.py # FastAPI server
|
|
360
|
+
└── cli.py # Command-line interface
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## 📚 Learning Resources
|
|
364
|
+
|
|
365
|
+
### RAG Fundamentals
|
|
366
|
+
|
|
367
|
+
1. **Vectors**: Numerical representations of text
|
|
368
|
+
2. **Embeddings**: Dense vector representations capturing semantic meaning
|
|
369
|
+
3. **Vector Stores**: Databases optimized for vector similarity search
|
|
370
|
+
4. **Retrieval**: Finding relevant context for questions
|
|
371
|
+
5. **Generation**: Creating responses using retrieved context
|
|
372
|
+
|
|
373
|
+
### Next Steps
|
|
374
|
+
|
|
375
|
+
1. Experiment with different vector store types
|
|
376
|
+
2. Try various chunking strategies
|
|
377
|
+
3. Customize the system prompt for your use case
|
|
378
|
+
4. Explore different LLM models on OpenRouter
|
|
379
|
+
5. Monitor and optimize performance
|
|
380
|
+
|
|
381
|
+
## 🏆 Success Stories
|
|
382
|
+
|
|
383
|
+
> "NEIN
|
|
384
|
+
|
|
385
|
+
## 📞 Support
|
|
386
|
+
|
|
387
|
+
- **GitHub Issues**: [Bug reports & feature requests](https://github.com/Ksschkw/kssrag/issues)
|
|
388
|
+
- **Documentation**: [Full documentation](docs/)
|
|
389
|
+
- **Examples**: [Usage examples](examples/)
|
|
390
|
+
|
|
391
|
+
## 📜 License
|
|
392
|
+
|
|
393
|
+
MIT License - do whatever you want, just don't be a vigil (I hate vigils).
|
|
394
|
+
|
|
395
|
+
## 👨💻 About the Author
|
|
396
|
+
|
|
397
|
+
**Ksschkw** - Just check my github page g.
|
|
398
|
+
|
|
399
|
+
> "Built with HATE"
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
**Remember**: This IS just another RAG framework. This is the one that actually works when you need it to. 🚀 \
|
|
404
|
+
(Yes that was NOT a typo)
|
|
405
|
+
|
|
406
|
+
**Footprint**: Built with HATE by Ksschkw (github.com/Ksschkw) - 2025
|
|
407
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
kssrag/__init__.py,sha256=N1XfR8IRKtEJAzcOVyHnKXtgx-ztlrSFtFwiVkGbAX8,2041
|
|
2
|
+
kssrag/cli.py,sha256=eCJ8VhCzWIYUQEIPWJnzPPE298GWxWS8ienwf2eXpgk,6461
|
|
3
|
+
kssrag/config.py,sha256=vJUDJVfCoBy5QXw2YBGJBE6y_e5du4fq65EhT2pz3f0,6101
|
|
4
|
+
kssrag/kssrag.py,sha256=vy3oCHeHFAp_dJW0JjLbTxeEwCcwtXuOL_Ejmv0qz8Y,5251
|
|
5
|
+
kssrag/server.py,sha256=HR60UqVlimo9UrExv_zTh6faE4ueVuz-QKK7UtZxmAA,4029
|
|
6
|
+
kssrag/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
kssrag/core/agents.py,sha256=VRAeaj7x6u2xbxTGckAaSfMn0jeLafPuG0OHNEb3xLg,3273
|
|
8
|
+
kssrag/core/chunkers.py,sha256=om9f7FeAqvN4ppERrLq7WSwR4eQnQr-XziKAojFrtLE,3591
|
|
9
|
+
kssrag/core/retrievers.py,sha256=1e9c7ukUD4pFSVasOMTXSKoz_rapXQTl-FrSHK6Osqg,3037
|
|
10
|
+
kssrag/core/vectorstores.py,sha256=mP_cz3KCLQO9kediQsbEyH9wnJ5PMS_Bhn0w3AHU3wA,16822
|
|
11
|
+
kssrag/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
kssrag/models/local_llms.py,sha256=IsthEwiNG1QcvHrTpQWdd1kZuHa4-0bfGTxHe8F3i2M,1178
|
|
13
|
+
kssrag/models/openrouter.py,sha256=x_I3eQBP_3xO4wRKWAbsBRzRE_Ur7kGtUuF9YGVSo5U,3716
|
|
14
|
+
kssrag/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
kssrag/utils/document_loaders.py,sha256=TLfi1-4YIyvuyIqiNBqLG9zl_FoT65s-zp37yqYSq38,1388
|
|
16
|
+
kssrag/utils/helpers.py,sha256=ejgViGTixsjPt0U26xZKodkqlB2wRMQlDzCmCjskYfg,1899
|
|
17
|
+
kssrag/utils/preprocessors.py,sha256=_kbeZOWnbqbKKSBiyRP8QZAKx9uYMXgHfARcWBqC3JU,938
|
|
18
|
+
kssrag-0.1.0.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
tests/test_basic.py,sha256=JdBBRpP9wOo4BvvZTisidP40gGyK_azUoewJpoJaa5M,1275
|
|
21
|
+
tests/test_vectorstores.py,sha256=YOwI2bfqprzbq8ahIw4pbbbEOaKGcg-XPcLCO7WiLxE,1474
|
|
22
|
+
kssrag-0.1.0.dist-info/METADATA,sha256=L1eP9IPzxipFkJbDn_AAXbdEWpsCQfFiO0ilkK7wScQ,10342
|
|
23
|
+
kssrag-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
kssrag-0.1.0.dist-info/entry_points.txt,sha256=g4tQj5YUqPK3Osb9BI85tsErxleSBUENiqlnX0fWK5M,43
|
|
25
|
+
kssrag-0.1.0.dist-info/top_level.txt,sha256=sO9LGINa0GEjLoHTtufpz01yM5SmeTw6M4zWHEF0R2s,13
|
|
26
|
+
kssrag-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
tests/__init__.py
ADDED
|
File without changes
|