Spaces:
Paused
Paused
Update codebase and configure automatic environment switcher (excluding MLX adapters)
Browse files- .gitignore +5 -1
- app.py +22 -4
- data/mintoak/leads.jsonl +1 -0
- data/mintoak/train.jsonl +0 -0
- data/mintoak/valid.jsonl +0 -0
- scripts/mintoak/chat_server.py +2 -2
- scripts/mintoak/evaluate_rag.py +2 -2
- scripts/mintoak/fine_tune.sh +2 -2
- scripts/mintoak/generate_html_report.py +3 -3
- scripts/mintoak/rag_assistant.py +1 -1
- scripts/mintoak/templates/index.html +1 -1
.gitignore
CHANGED
|
@@ -1,2 +1,6 @@
|
|
| 1 |
data/mintoak/chroma_db/
|
| 2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
data/mintoak/chroma_db/
|
| 2 |
+
adapters/
|
| 3 |
+
mlx-env/
|
| 4 |
+
.DS_Store
|
| 5 |
+
__pycache__/
|
| 6 |
+
*.pyc
|
app.py
CHANGED
|
@@ -14,7 +14,15 @@ from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStream
|
|
| 14 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 15 |
CHROMA_DB_PATH = os.path.join(BASE_DIR, "data/mintoak/chroma_db")
|
| 16 |
COLLECTION_NAME = "mintoak_content"
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
PORT = 7860 # Hugging Face Spaces requires port 7860
|
| 19 |
|
| 20 |
# Init Flask
|
|
@@ -48,12 +56,12 @@ if _collection.count() == 0 and os.path.exists(CHUNKS_JSON_PATH):
|
|
| 48 |
)
|
| 49 |
print(f"Database populated with {_collection.count()} chunks!")
|
| 50 |
|
| 51 |
-
# Load Model on GPU (CUDA)
|
| 52 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 53 |
-
print(f"Loading
|
| 54 |
_tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
|
| 55 |
|
| 56 |
-
# Using float16 for fast GPU inference
|
| 57 |
if device == "cuda":
|
| 58 |
_model = AutoModelForCausalLM.from_pretrained(
|
| 59 |
MODEL_PATH,
|
|
@@ -375,8 +383,18 @@ def chat():
|
|
| 375 |
thread = Thread(target=_model.generate, kwargs=generation_kwargs)
|
| 376 |
thread.start()
|
| 377 |
|
|
|
|
| 378 |
for token_text in streamer:
|
| 379 |
full_response += token_text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 380 |
yield f"data: {json.dumps({'event': 'token', 'token': token_text})}\n\n"
|
| 381 |
|
| 382 |
latency = round(time.time() - t0, 2)
|
|
|
|
| 14 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 15 |
CHROMA_DB_PATH = os.path.join(BASE_DIR, "data/mintoak/chroma_db")
|
| 16 |
COLLECTION_NAME = "mintoak_content"
|
| 17 |
+
# Automatically choose model size based on environment
|
| 18 |
+
# Hugging Face Spaces sets "HF_SPACE" or "SPACE_ID" automatically
|
| 19 |
+
IS_HF_SPACE = "HF_SPACE" in os.environ or "SPACE_ID" in os.environ
|
| 20 |
+
if IS_HF_SPACE:
|
| 21 |
+
MODEL_PATH = "Qwen/Qwen2.5-7B-Instruct" # 7B model on Hugging Face
|
| 22 |
+
print("Running on Hugging Face Spaces. Using Qwen 2.5 7B model.")
|
| 23 |
+
else:
|
| 24 |
+
MODEL_PATH = "Qwen/Qwen2.5-1.5B-Instruct" # 1.5B model locally
|
| 25 |
+
print("Running locally. Using Qwen 2.5 1.5B model.")
|
| 26 |
PORT = 7860 # Hugging Face Spaces requires port 7860
|
| 27 |
|
| 28 |
# Init Flask
|
|
|
|
| 56 |
)
|
| 57 |
print(f"Database populated with {_collection.count()} chunks!")
|
| 58 |
|
| 59 |
+
# Load Model on GPU (CUDA) if available
|
| 60 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 61 |
+
print(f"Loading base model {MODEL_PATH} on device: {device}...")
|
| 62 |
_tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
|
| 63 |
|
| 64 |
+
# Using float16 for fast GPU inference if CUDA is available
|
| 65 |
if device == "cuda":
|
| 66 |
_model = AutoModelForCausalLM.from_pretrained(
|
| 67 |
MODEL_PATH,
|
|
|
|
| 383 |
thread = Thread(target=_model.generate, kwargs=generation_kwargs)
|
| 384 |
thread.start()
|
| 385 |
|
| 386 |
+
citation_started = False
|
| 387 |
for token_text in streamer:
|
| 388 |
full_response += token_text
|
| 389 |
+
|
| 390 |
+
if citation_started:
|
| 391 |
+
continue
|
| 392 |
+
|
| 393 |
+
last_snippet = full_response[-40:].lower()
|
| 394 |
+
if "👉" in token_text or "for more details" in last_snippet or "details, visit" in last_snippet:
|
| 395 |
+
citation_started = True
|
| 396 |
+
continue
|
| 397 |
+
|
| 398 |
yield f"data: {json.dumps({'event': 'token', 'token': token_text})}\n\n"
|
| 399 |
|
| 400 |
latency = round(time.time() - t0, 2)
|
data/mintoak/leads.jsonl
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"timestamp": "2026-05-30 11:16:59", "name": "Rutvij", "email": "rutvijdoshi07@gmail.com", "query": "I want to know the demo about mintoak products for my business", "conversation_id": "conv_1780119934617_475w"}
|
data/mintoak/train.jsonl
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/mintoak/valid.jsonl
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/mintoak/chat_server.py
CHANGED
|
@@ -26,7 +26,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath
|
|
| 26 |
CHROMA_DB_PATH = os.path.join(BASE_DIR, "data/mintoak/chroma_db")
|
| 27 |
COLLECTION_NAME = "mintoak_content"
|
| 28 |
CHUNKS_JSON = os.path.join(BASE_DIR, "data/mintoak/mintoak_chunks.json")
|
| 29 |
-
MODEL_PATH = "mlx-community/Qwen2.5-
|
| 30 |
ADAPTER_PATH = os.path.join(BASE_DIR, "adapters/mintoak")
|
| 31 |
PORT = 5001
|
| 32 |
|
|
@@ -119,7 +119,7 @@ QUERY_ENHANCEMENT_RULES = [
|
|
| 119 |
},
|
| 120 |
{
|
| 121 |
"keywords": ["document", "documents", "checklist", "paperwork", "certificates"],
|
| 122 |
-
"expansion": "
|
| 123 |
"prompt_note": "Ensure you list the specific documents needed: registration certificates, GST certificates, cancelled cheques, and board resolutions.",
|
| 124 |
"top_k": 3
|
| 125 |
},
|
|
|
|
| 26 |
CHROMA_DB_PATH = os.path.join(BASE_DIR, "data/mintoak/chroma_db")
|
| 27 |
COLLECTION_NAME = "mintoak_content"
|
| 28 |
CHUNKS_JSON = os.path.join(BASE_DIR, "data/mintoak/mintoak_chunks.json")
|
| 29 |
+
MODEL_PATH = "mlx-community/Qwen2.5-7B-Instruct-4bit"
|
| 30 |
ADAPTER_PATH = os.path.join(BASE_DIR, "adapters/mintoak")
|
| 31 |
PORT = 5001
|
| 32 |
|
|
|
|
| 119 |
},
|
| 120 |
{
|
| 121 |
"keywords": ["document", "documents", "checklist", "paperwork", "certificates"],
|
| 122 |
+
"expansion": "Mintoak DigiOnboard merchant onboarding documents checklist GST PAN registration certificates cancelled cheques board resolutions",
|
| 123 |
"prompt_note": "Ensure you list the specific documents needed: registration certificates, GST certificates, cancelled cheques, and board resolutions.",
|
| 124 |
"top_k": 3
|
| 125 |
},
|
scripts/mintoak/evaluate_rag.py
CHANGED
|
@@ -10,7 +10,7 @@ from mlx_lm.sample_utils import make_sampler
|
|
| 10 |
# Configurations matching rag_assistant.py
|
| 11 |
CHROMA_DB_PATH = "data/mintoak/chroma_db"
|
| 12 |
COLLECTION_NAME = "mintoak_content"
|
| 13 |
-
MODEL_PATH = "mlx-community/Qwen2.5-
|
| 14 |
ADAPTER_PATH = "adapters/mintoak"
|
| 15 |
CHUNKS_JSON_PATH = "data/mintoak/mintoak_chunks.json"
|
| 16 |
|
|
@@ -231,7 +231,7 @@ def main():
|
|
| 231 |
import argparse
|
| 232 |
import sys
|
| 233 |
|
| 234 |
-
parser = argparse.ArgumentParser(description="
|
| 235 |
parser.add_argument("--batch_size", type=int, default=50, help="Batch size for progress updates & saving")
|
| 236 |
parser.add_argument("--max_cases", type=int, default=None, help="Maximum number of test cases to run")
|
| 237 |
parser.add_argument("--progress_file", type=str, default="data/mintoak/eval_progress.json", help="Path to save intermediate evaluation progress")
|
|
|
|
| 10 |
# Configurations matching rag_assistant.py
|
| 11 |
CHROMA_DB_PATH = "data/mintoak/chroma_db"
|
| 12 |
COLLECTION_NAME = "mintoak_content"
|
| 13 |
+
MODEL_PATH = "mlx-community/Qwen2.5-7B-Instruct-4bit"
|
| 14 |
ADAPTER_PATH = "adapters/mintoak"
|
| 15 |
CHUNKS_JSON_PATH = "data/mintoak/mintoak_chunks.json"
|
| 16 |
|
|
|
|
| 231 |
import argparse
|
| 232 |
import sys
|
| 233 |
|
| 234 |
+
parser = argparse.ArgumentParser(description="Mintoak RAG Evaluator")
|
| 235 |
parser.add_argument("--batch_size", type=int, default=50, help="Batch size for progress updates & saving")
|
| 236 |
parser.add_argument("--max_cases", type=int, default=None, help="Maximum number of test cases to run")
|
| 237 |
parser.add_argument("--progress_file", type=str, default="data/mintoak/eval_progress.json", help="Path to save intermediate evaluation progress")
|
scripts/mintoak/fine_tune.sh
CHANGED
|
@@ -28,7 +28,7 @@ echo "Creating folder adapters/mintoak..."
|
|
| 28 |
mkdir -p adapters/mintoak
|
| 29 |
|
| 30 |
echo "Starting MLX LoRA Fine-Tuning..."
|
| 31 |
-
echo "Using base model: mlx-community/Qwen2.5-
|
| 32 |
echo "Data directory: ./data/mintoak"
|
| 33 |
echo "Adapters output path: ./adapters/mintoak"
|
| 34 |
|
|
@@ -44,7 +44,7 @@ echo "Adapters output path: ./adapters/mintoak"
|
|
| 44 |
# --num-layers: Number of layers we are fine-tuning (out of the base model's layers)
|
| 45 |
# --adapter-path: The output folder where the adapters (.safetensors) and config will be saved
|
| 46 |
python -m mlx_lm lora \
|
| 47 |
-
--model mlx-community/Qwen2.5-
|
| 48 |
--train \
|
| 49 |
--data ./data/mintoak \
|
| 50 |
--iters 50 \
|
|
|
|
| 28 |
mkdir -p adapters/mintoak
|
| 29 |
|
| 30 |
echo "Starting MLX LoRA Fine-Tuning..."
|
| 31 |
+
echo "Using base model: mlx-community/Qwen2.5-7B-Instruct-4bit"
|
| 32 |
echo "Data directory: ./data/mintoak"
|
| 33 |
echo "Adapters output path: ./adapters/mintoak"
|
| 34 |
|
|
|
|
| 44 |
# --num-layers: Number of layers we are fine-tuning (out of the base model's layers)
|
| 45 |
# --adapter-path: The output folder where the adapters (.safetensors) and config will be saved
|
| 46 |
python -m mlx_lm lora \
|
| 47 |
+
--model mlx-community/Qwen2.5-7B-Instruct-4bit \
|
| 48 |
--train \
|
| 49 |
--data ./data/mintoak \
|
| 50 |
--iters 50 \
|
scripts/mintoak/generate_html_report.py
CHANGED
|
@@ -136,8 +136,8 @@ def main():
|
|
| 136 |
<head>
|
| 137 |
<meta charset="UTF-8">
|
| 138 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 139 |
-
<title>
|
| 140 |
-
<meta name="description" content="Interactive evaluation report for
|
| 141 |
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
| 142 |
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js"></script>
|
| 143 |
<style>
|
|
@@ -416,7 +416,7 @@ def main():
|
|
| 416 |
<div class="topbar-brand">
|
| 417 |
<div class="topbar-logo">M</div>
|
| 418 |
<div>
|
| 419 |
-
<div class="topbar-title">
|
| 420 |
<div class="topbar-sub">{total_cases} test cases · generated {__import__('datetime').datetime.now().strftime('%d %b %Y, %H:%M')}</div>
|
| 421 |
</div>
|
| 422 |
</div>
|
|
|
|
| 136 |
<head>
|
| 137 |
<meta charset="UTF-8">
|
| 138 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 139 |
+
<title>Mintoak RAG Evaluation Dashboard</title>
|
| 140 |
+
<meta name="description" content="Interactive evaluation report for Mintoak RAG Assistant — {total_cases} test cases, {pass_rate:.1f}% pass rate.">
|
| 141 |
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
| 142 |
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js"></script>
|
| 143 |
<style>
|
|
|
|
| 416 |
<div class="topbar-brand">
|
| 417 |
<div class="topbar-logo">M</div>
|
| 418 |
<div>
|
| 419 |
+
<div class="topbar-title">Mintoak RAG · Evaluation Dashboard</div>
|
| 420 |
<div class="topbar-sub">{total_cases} test cases · generated {__import__('datetime').datetime.now().strftime('%d %b %Y, %H:%M')}</div>
|
| 421 |
</div>
|
| 422 |
</div>
|
scripts/mintoak/rag_assistant.py
CHANGED
|
@@ -22,7 +22,7 @@ COLLECTION_NAME = "mintoak_content"
|
|
| 22 |
CHUNKS_JSON_PATH = "data/mintoak/mintoak_chunks.json"
|
| 23 |
|
| 24 |
# The base language model we are loading from Hugging Face / local cache
|
| 25 |
-
MODEL_PATH = "mlx-community/Qwen2.5-
|
| 26 |
|
| 27 |
# Path to the directory containing our trained fine-tuning LoRA adapters
|
| 28 |
ADAPTER_PATH = "adapters/mintoak"
|
|
|
|
| 22 |
CHUNKS_JSON_PATH = "data/mintoak/mintoak_chunks.json"
|
| 23 |
|
| 24 |
# The base language model we are loading from Hugging Face / local cache
|
| 25 |
+
MODEL_PATH = "mlx-community/Qwen2.5-7B-Instruct-4bit"
|
| 26 |
|
| 27 |
# Path to the directory containing our trained fine-tuning LoRA adapters
|
| 28 |
ADAPTER_PATH = "adapters/mintoak"
|
scripts/mintoak/templates/index.html
CHANGED
|
@@ -1793,7 +1793,7 @@
|
|
| 1793 |
botBubbleEl.innerHTML = marked.parse(displayText);
|
| 1794 |
scrollBottom();
|
| 1795 |
} else if (data.event === 'done') {
|
| 1796 |
-
let finalContent = accumulatedText;
|
| 1797 |
let leadCapture = false;
|
| 1798 |
if (finalContent.includes('[CAPTURE_LEAD]')) {
|
| 1799 |
finalContent = finalContent.replace('[CAPTURE_LEAD]', '').trim();
|
|
|
|
| 1793 |
botBubbleEl.innerHTML = marked.parse(displayText);
|
| 1794 |
scrollBottom();
|
| 1795 |
} else if (data.event === 'done') {
|
| 1796 |
+
let finalContent = data.text || accumulatedText;
|
| 1797 |
let leadCapture = false;
|
| 1798 |
if (finalContent.includes('[CAPTURE_LEAD]')) {
|
| 1799 |
finalContent = finalContent.replace('[CAPTURE_LEAD]', '').trim();
|