BrianGithaiga commited on
Commit
d2c0716
·
verified ·
1 Parent(s): ead2ba8

Upload 4 files

Browse files
Files changed (4) hide show
  1. READ.me.md +43 -0
  2. app.py.py +263 -0
  3. combined (1).json +0 -0
  4. requirements.txt +7 -0
READ.me.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Swahili Chat Assistant
3
+ emoji: 🇹🇿
4
+ colorFrom: blue
5
+ colorTo: green
6
+ sdk: gradio
7
+ sdk_version: 4.0.0
8
+ app_file: app.py
9
+ pinned: false
10
+ ---
11
+
12
+ # Swahili Chat Assistant 🤖
13
+
14
+ A dual-interface chat assistant featuring:
15
+ - **Kiswahili Learning Assistant**: RAG-powered specialized Swahili education
16
+ - **General Conversation Assistant**: Open-ended chat using fine-tuned Swahili Gemma model
17
+
18
+ ## Model Used
19
+ This app uses my fine-tuned Swahili Gemma model: [BrianGithaiga/swahili-gemma-finetuned](https://huggingface.co/BrianGithaiga/swahili-gemma-finetuned)
20
+
21
+ ## Features
22
+ - 🎓 Educational RAG system for Swahili learning
23
+ - 💬 General conversation in Swahili
24
+ - 🚀 Fast inference with optimized tokenizer
25
+ - 📱 Responsive Gradio interface
26
+
27
+ ## Usage
28
+ 1. **Left Side**: Ask questions about Swahili literature, grammar, and culture
29
+ 2. **Right Side**: Have general conversations in Swahili
30
+
31
+ ## Technical Details
32
+ - **Base Model**: CraneAILabs/swahili-gemma-1b
33
+ - **Fine-tuned**: BrianGithaiga/swahili-gemma-finetuned
34
+ - **Framework**: Transformers + Gradio
35
+ - **Hosting**: Hugging Face Spaces
36
+
37
+ ## License
38
+ Apache-2.0 License
39
+
40
+ ## Model Performance
41
+ - Validation Loss: 1.3800
42
+ - Perplexity: 3.97
43
+ - Optimized for Swahili conversation
app.py.py ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import json
4
+ import numpy as np
5
+ import pandas as pd
6
+ from typing import List, Dict, Tuple
7
+ import re
8
+
9
+ # Install required packages (for Hugging Face Spaces compatibility)
10
+ os.system("pip install transformers==4.35.2 accelerate==0.24.1 sentencepiece==0.1.99 torch==2.1.2 gradio==4.13.0")
11
+
12
+ import torch
13
+ from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
14
+
15
+ print("PyTorch version:", torch.__version__)
16
+
17
+ class SwahiliLiteratureRAG:
18
+ def __init__(self, knowledge_base_path: str = None, model_name: str = None):
19
+ """
20
+ Initialize the RAG system
21
+ """
22
+ self.knowledge_base = self.load_knowledge_base(knowledge_base_path)
23
+ self.model = self.load_model(model_name)
24
+ self.similarity_threshold = 0.15
25
+ self.swahili_stop_words = {
26
+ 'ni', 'nini', 'na', 'ya', 'za', 'wa', 'la', 'kwa', 'katika', 'au', 'je',
27
+ 'hii', 'ile', 'hilo', 'hiyo', 'hayo', 'hao', 'yule', 'huyu', 'huu',
28
+ 'kuhusu', 'juu', 'chini', 'mbele', 'nyuma', 'ndani', 'nje', 'karibu',
29
+ 'mbali', 'hapa', 'pale', 'kule', 'sasa', 'jana', 'kesho', 'leo'
30
+ }
31
+
32
+ def load_knowledge_base(self, path: str = None) -> List[Dict]:
33
+ """Load your knowledge base from JSON file"""
34
+ if path and os.path.exists(path):
35
+ try:
36
+ with open(path, 'r', encoding='utf-8') as f:
37
+ return json.load(f)
38
+ except Exception as e:
39
+ print(f"Error loading knowledge base: {e}")
40
+
41
+ # Default sample data
42
+ return [
43
+ {
44
+ "instruction": "Eleza kuhusu Fasihi Simulizi.",
45
+ "input": "",
46
+ "output": "Fasihi simulizi ni sanaa inayotumia lugha kuwasilisha ujumbe unaomhusu binadamu..."
47
+ },
48
+ {
49
+ "instruction": "Tofautisha Fasihi na Sanaa Nyingine.",
50
+ "input": "",
51
+ "output": "Fasihi hutumia lugha na wahusika kuwasilisha maudhui..."
52
+ },
53
+ {
54
+ "instruction": "Tofautisha Fasihi Simulizi na Fasihi Andishi.",
55
+ "input": "",
56
+ "output": "Fasihi simulizi huwasilishwa kwa mdomo... Fasihi andishi huwasilishwa kwa maandishi..."
57
+ },
58
+ {
59
+ "instruction": "Eleza vipengele vya Fasihi Simulizi.",
60
+ "input": "",
61
+ "output": "Vipengele vya fasihi simulizi ni pamoja na lugha, mandhari, wahusika, maudhui, na mtindo."
62
+ }
63
+ ]
64
+
65
+ def load_model(self, model_name: str = None):
66
+ """Load your fine-tuned Gemma model from Hugging Face Hub"""
67
+ if not model_name:
68
+ print("No model name provided. Using knowledge base only.")
69
+ return None
70
+
71
+ try:
72
+ print(f"Loading model from Hugging Face: {model_name}")
73
+
74
+ # Load base tokenizer with special tokens
75
+ base_tokenizer = AutoTokenizer.from_pretrained(
76
+ "CraneAILabs/swahili-gemma-1b",
77
+ trust_remote_code=True
78
+ )
79
+
80
+ # Add special tokens
81
+ special_tokens = {
82
+ "additional_special_tokens": ["<|user|>", "<|assistant|>"],
83
+ "bos_token": "<start_of_turn>",
84
+ "eos_token": "<end_of_turn>"
85
+ }
86
+ base_tokenizer.add_special_tokens(special_tokens)
87
+ base_tokenizer.pad_token = base_tokenizer.eos_token
88
+
89
+ # Load model from Hugging Face Hub
90
+ model = AutoModelForCausalLM.from_pretrained(
91
+ model_name,
92
+ torch_dtype=torch.float32,
93
+ device_map="cpu",
94
+ trust_remote_code=True,
95
+ use_cache=True
96
+ )
97
+
98
+ pipe = pipeline(
99
+ "text-generation",
100
+ model=model,
101
+ tokenizer=base_tokenizer,
102
+ torch_dtype=torch.float32
103
+ )
104
+
105
+ print("✅ Model loaded successfully from Hugging Face Hub!")
106
+ return pipe
107
+
108
+ except Exception as e:
109
+ print(f"❌ Error loading model: {e}")
110
+ print("Continuing with knowledge base only...")
111
+ return None
112
+
113
+ # [KEEP ALL YOUR EXISTING METHODS - normalize_text, extract_key_terms, preprocess_query, calculate_similarity, retrieve_documents, generate_with_model, answer_query]
114
+
115
+ class GeneralChatbot:
116
+ def __init__(self, model_name: str = None):
117
+ """
118
+ Initialize general chatbot that uses model without RAG
119
+ """
120
+ self.model = self.load_model(model_name)
121
+
122
+ def load_model(self, model_name: str = None):
123
+ """Load the model for general conversation from Hugging Face Hub"""
124
+ if not model_name:
125
+ print("No model name provided for general chat. Using basic responses.")
126
+ return None
127
+
128
+ try:
129
+ print(f"Loading general chat model from Hugging Face: {model_name}")
130
+
131
+ # Load base tokenizer
132
+ base_tokenizer = AutoTokenizer.from_pretrained(
133
+ "CraneAILabs/swahili-gemma-1b",
134
+ trust_remote_code=True
135
+ )
136
+
137
+ # Add special tokens
138
+ special_tokens = {
139
+ "additional_special_tokens": ["<|user|>", "<|assistant|>"],
140
+ "bos_token": "<start_of_turn>",
141
+ "eos_token": "<end_of_turn>"
142
+ }
143
+ base_tokenizer.add_special_tokens(special_tokens)
144
+ base_tokenizer.pad_token = base_tokenizer.eos_token
145
+
146
+ # Load model from Hugging Face Hub
147
+ model = AutoModelForCausalLM.from_pretrained(
148
+ model_name,
149
+ torch_dtype=torch.float32,
150
+ device_map="cpu",
151
+ trust_remote_code=True,
152
+ use_cache=True
153
+ )
154
+
155
+ pipe = pipeline(
156
+ "text-generation",
157
+ model=model,
158
+ tokenizer=base_tokenizer,
159
+ torch_dtype=torch.float32
160
+ )
161
+
162
+ pipe.tokenizer = base_tokenizer
163
+
164
+ print("✅ General chat model loaded successfully!")
165
+ return pipe
166
+
167
+ except Exception as e:
168
+ print(f"❌ Error loading general chat model: {e}")
169
+ return None
170
+
171
+ def generate_response(self, query: str) -> str:
172
+ """Generate response using model's general knowledge only"""
173
+ if not query.strip():
174
+ return "Hello! How can I help you today?"
175
+
176
+ if self.model is None:
177
+ # Basic fallback responses
178
+ fallback_responses = {
179
+ "hello": "Hello! How are you doing today?",
180
+ "hi": "Hi there! What would you like to talk about?",
181
+ "how are you": "I'm doing well, thank you for asking! How about you?",
182
+ "what is your name": "I'm a general conversation assistant. What's your name?",
183
+ "bye": "Goodbye! Have a great day!",
184
+ "thank you": "You're welcome! Is there anything else I can help you with?",
185
+ }
186
+
187
+ query_lower = query.lower().strip()
188
+ for key, response in fallback_responses.items():
189
+ if key in query_lower:
190
+ return response
191
+
192
+ return "I understand you want to chat, but I don't have access to my full capabilities right now. What would you like to talk about?"
193
+
194
+ try:
195
+ # Use the chat format that the model was trained with
196
+ formatted_prompt = f"<start_of_turn>user\n{query}<end_of_turn>\n<start_of_turn>model\n"
197
+
198
+ response = self.model(
199
+ formatted_prompt,
200
+ max_new_tokens=150,
201
+ temperature=0.7,
202
+ do_sample=True,
203
+ repetition_penalty=1.1,
204
+ pad_token_id=self.model.tokenizer.eos_token_id,
205
+ eos_token_id=self.model.tokenizer.eos_token_id,
206
+ use_cache=True
207
+ )
208
+
209
+ generated_text = response[0]['generated_text']
210
+
211
+ # Extract assistant response
212
+ if "<start_of_turn>model\n" in generated_text:
213
+ answer = generated_text.split("<start_of_turn>model\n")[-1]
214
+ answer = answer.replace("<end_of_turn>", "").strip()
215
+ else:
216
+ answer = generated_text.replace(formatted_prompt, "").strip()
217
+
218
+ return answer if answer else "I'm not sure how to respond to that. Could you try rephrasing?"
219
+
220
+ except Exception as e:
221
+ print(f"Error generating general response: {e}")
222
+ return "I'm having trouble generating a response right now. What else would you like to talk about?"
223
+
224
+ # Initialize both systems
225
+ def initialize_systems():
226
+ """Initialize both RAG and general chat systems"""
227
+ # Use your Hugging Face model
228
+ model_name = "BrianGithaiga/swahili-gemma-finetuned"
229
+
230
+ # For knowledge base
231
+ knowledge_base_path = "combined.json" # Upload this file to your Space if needed
232
+
233
+ print("🚀 Initializing systems with model:", model_name)
234
+
235
+ # Initialize both systems
236
+ rag_system = SwahiliLiteratureRAG(knowledge_base_path, model_name)
237
+ general_chat = GeneralChatbot(model_name)
238
+
239
+ return rag_system, general_chat
240
+
241
+ # Create both system instances
242
+ print("Initializing both systems...")
243
+ rag_system, general_chat = initialize_systems()
244
+ print("Both systems initialized successfully!")
245
+
246
+ # [KEEP YOUR EXISTING create_app() FUNCTION EXACTLY AS IS]
247
+
248
+ # For Hugging Face Spaces deployment
249
+ if __name__ == "__main__":
250
+ # Set environment variables for better performance
251
+ os.environ['TORCH_LOGS'] = ''
252
+ os.environ['TORCHDYNAMO_VERBOSE'] = '0'
253
+ os.environ['TOKENIZERS_PARALLELISM'] = 'false'
254
+
255
+ print("Creating Gradio app...")
256
+ app = create_app()
257
+
258
+ # For Hugging Face Spaces
259
+ app.launch(
260
+ server_name="0.0.0.0",
261
+ server_port=7860,
262
+ share=False
263
+ )
combined (1).json ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ transformers>=4.35.0
2
+ accelerate>=0.24.0
3
+ sentencepiece>=0.1.99
4
+ torch>=2.1.0,<2.2.0
5
+ gradio>=4.13.0
6
+ numpy>=1.24.0
7
+ pandas>=2.0.0