CashOutSolo commited on
Commit
cf8a9f8
ยท
verified ยท
1 Parent(s): 2d7bd93

Rename app py to app.py

Browse files
Files changed (2) hide show
  1. app py +0 -0
  2. app.py +223 -0
app py DELETED
File without changes
app.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import glob
4
+ import re
5
+ import pandas as pd
6
+ import gradio as gr
7
+ import spaces # <--- REQUIRED FOR HUGGING FACE ZEROGPU TIERS
8
+ from pypdf import PdfReader
9
+ import docx2txt
10
+ import speech_recognition as sr
11
+ from pydub import AudioSegment
12
+ from llama_index.core.node_parser import SentenceSplitter
13
+
14
+ # Directory mounts mapping perfectly to your storage volume
15
+ UPLOAD_DIR = "/data/raw_inputs"
16
+ PROCESSED_DIR = "/data/processed_jsonl"
17
+ MASTER_FILE = "/data/master_dataset.jsonl"
18
+
19
+ os.makedirs(UPLOAD_DIR, exist_ok=True)
20
+ os.makedirs(PROCESSED_DIR, exist_ok=True)
21
+
22
+ # -------------------------------------------------------------
23
+ # CORE PIPELINE LOGIC (TRANSCRIBER, PARSER, CHUNKER)
24
+ # -------------------------------------------------------------
25
+ @spaces.GPU # <--- TELLS HUGGING FACE TO ALLOCATE GPU POWER FOR TRANSCRIBING
26
+ def transcribe_video_audio(file_path):
27
+ try:
28
+ gr.Info(f"๐ŸŽฌ Extracting track layers from {os.path.basename(file_path)}...")
29
+ audio = AudioSegment.from_file(file_path, format="mp4")
30
+ temp_wav = file_path + ".wav"
31
+ audio.set_channels(1).set_frame_rate(16000).export(temp_wav, format="wav")
32
+
33
+ recognizer = sr.Recognizer()
34
+ with sr.AudioFile(temp_wav) as source:
35
+ audio_data = recognizer.record(source)
36
+
37
+ gr.Info("๐Ÿ—ฃ๏ธ Processing Speech-to-Text conversion...")
38
+ extracted_text = recognizer.recognize_google(audio_data)
39
+
40
+ if os.path.exists(temp_wav):
41
+ os.remove(temp_wav)
42
+
43
+ return extracted_text.strip()
44
+ except Exception as e:
45
+ return f"[Audio Transcription Error]: {str(e)}"
46
+
47
+ def clean_text_formatting(text):
48
+ text = re.sub(r"\.([^ ])", r". \1", text)
49
+ while " " in text:
50
+ text = text.replace(" ", " ")
51
+ return text.strip()
52
+
53
+ def parse_incoming_file_to_text(file_path):
54
+ ext = os.path.splitext(file_path)[1].lower()
55
+ text = ""
56
+ if ext == ".txt":
57
+ with open(file_path, "r", encoding="utf-8") as f:
58
+ text = f.read()
59
+ elif ext == ".pdf":
60
+ reader = PdfReader(file_path)
61
+ for page in reader.pages:
62
+ t = page.extract_text()
63
+ if t: text += t + "\n"
64
+ elif ext == ".docx":
65
+ text = docx2txt.process(file_path)
66
+ elif ext in [".csv", ".xlsx"]:
67
+ df = pd.read_csv(file_path) if ext == ".csv" else pd.read_excel(file_path)
68
+ text = df.to_string(index=False)
69
+ elif ext in [".mp4", ".wav", ".mp3"]:
70
+ text = transcribe_video_audio(file_path)
71
+
72
+ return clean_text_formatting(text)
73
+
74
+ def structure_unsloth_rows(chunks, archetype):
75
+ rows = []
76
+ for idx, chunk in enumerate(chunks):
77
+ if "๐ŸŽญ Persona" in archetype or "๐Ÿ“š Domain Expert" in archetype:
78
+ sys_msg = "You are an advanced interactive chatbot avatar."
79
+ if "๐ŸŽญ Persona" in archetype:
80
+ sys_msg = "You are an immersive roleplay companion bot."
81
+ rows.append({
82
+ "conversations": [
83
+ {"from": "system", "value": sys_msg},
84
+ {"from": "human", "value": f"Context chunk {idx}: {chunk[:100]}..."},
85
+ {"from": "gpt", "value": chunk}
86
+ ]
87
+ })
88
+ elif "๐Ÿงฎ Math Wizard" in archetype or "๐Ÿ“ˆ Day Trading" in archetype:
89
+ instr = "Deconstruct structural math patterns or trading indicator calculations."
90
+ if "๐Ÿ“ˆ Day Trading" in archetype:
91
+ instr = "Parse market metrics and technical data to extract signals."
92
+ rows.append({
93
+ "instruction": instr,
94
+ "input": f"Data segment context: {idx}",
95
+ "output": chunk
96
+ })
97
+ elif "๐Ÿ’ป Code Assistant" in archetype:
98
+ rows.append({
99
+ "instruction": "Compile modular scripts based on requirements.",
100
+ "input": f"Code Requirements Segment: {idx}",
101
+ "output": chunk
102
+ })
103
+ else:
104
+ rows.append({"text": chunk})
105
+ return rows
106
+
107
+ @spaces.GPU # <--- DECORATES THE TOP LEVEL CONVERSION Pipeline FOR ZEROGPU STABILITY
108
+ def execute_dataset_builder_pipeline(files, archetype, enable_chunking, chunk_size, chunk_overlap):
109
+ if not files:
110
+ return "โš ๏ธ Target file loading queue is empty. Please upload files."
111
+
112
+ for f in glob.glob(os.path.join(PROCESSED_DIR, "*.jsonl")):
113
+ os.remove(f)
114
+
115
+ total_files_compiled = 0
116
+ all_extracted_text_blocks = []
117
+
118
+ for file_obj in files:
119
+ raw_text = parse_incoming_file_to_text(file_obj.name)
120
+ if raw_text:
121
+ all_extracted_text_blocks.append(raw_text)
122
+ total_files_compiled += 1
123
+
124
+ if not all_extracted_text_blocks:
125
+ return "โŒ Failed to extract content from assets."
126
+
127
+ combined_master_string = "\n\n--- FILE SPLIT ---\n\n".join(all_extracted_text_blocks)
128
+
129
+ if enable_chunking:
130
+ splitter = SentenceSplitter(chunk_size=int(chunk_size), chunk_overlap=int(chunk_overlap))
131
+ final_text_chunks = splitter.split_text(combined_master_string)
132
+ else:
133
+ final_text_chunks = all_extracted_text_blocks
134
+
135
+ formatted_dataset_objects = structure_unsloth_rows(final_text_chunks, archetype)
136
+
137
+ with open(MASTER_FILE, "w", encoding="utf-8") as master_f:
138
+ for obj in formatted_dataset_objects:
139
+ master_f.write(json.dumps(obj) + "\n")
140
+
141
+ return f"๐Ÿ”ฅ Conversion Complete!\n\nโ€ข Processed: {total_files_compiled}/{len(files)} files\nโ€ข Rows: {len(formatted_dataset_objects)}\nโ€ข Saved At: {MASTER_FILE}"
142
+
143
+ # -------------------------------------------------------------
144
+ # THEME TOGGLE SWITCH LOGIC โ˜€๏ธ/๐ŸŒ™
145
+ # -------------------------------------------------------------
146
+ def toggle_theme(current_theme):
147
+ if current_theme == "dark":
148
+ return gr.update(variant="light"), "light"
149
+ return gr.update(variant="dark"), "dark"
150
+
151
+ js_theme_switcher = """
152
+ function(theme) {
153
+ const documentElement = document.documentElement;
154
+ if (theme === 'dark') {
155
+ documentElement.classList.add('dark');
156
+ } else {
157
+ documentElement.classList.remove('dark');
158
+ }
159
+ return theme;
160
+ }
161
+ """
162
+
163
+ archetype_choices = [
164
+ "๐ŸŽญ Persona / Roleplay (e.g., Girlfriend, AI Companion)",
165
+ "๐Ÿ“š Domain Expert (e.g., History Expert, Legal Advisor)",
166
+ "๐Ÿงฎ Math Wizard (e.g., Algebra, Calculus solvers)",
167
+ "๐Ÿ“ˆ Day Trading / Quant (e.g., XGBoost, Price Action Data)",
168
+ "๐Ÿ’ป Code Assistant (e.g., Scripting, SQL Generation)",
169
+ "๐Ÿ“– Raw Knowledge Base (Continued Pre-Training)"
170
+ ]
171
+
172
+ custom_theme = gr.themes.Default(
173
+ primary_hue="green",
174
+ secondary_hue="zinc",
175
+ neutral_hue="zinc"
176
+ )
177
+
178
+ # Removed theme and title parameters from constructor to prevent Gradio 6 layout deprecation warnings
179
+ with gr.Blocks() as demo:
180
+ ui_theme_state = gr.State("dark")
181
+
182
+ with gr.Row():
183
+ gr.HTML("<h1 style='flex-grow: 1; margin: 0; color: #22c55e;'>๐Ÿฆ™ UN-SLOTH DATASET STUDIO</h1>")
184
+ theme_toggle_btn = gr.Button("๐ŸŒ“ Toggle Light/Dark Mode", scale=0, min_width=200)
185
+
186
+ gr.Markdown("Transform diverse media configurations into flawless JSONL files optimized for instant Unsloth training.")
187
+
188
+ with gr.Row():
189
+ with gr.Column(scale=1):
190
+ file_uploader = gr.File(file_count="multiple", label="๐Ÿ“ฅ Drop Assets Here (.pdf, .txt, .docx, .mp4)")
191
+ archetype_dropdown = gr.Dropdown(choices=archetype_choices, value=archetype_choices[0], label="๐Ÿค– Choose Target AI Archetype Layout Mapping")
192
+
193
+ with gr.Accordion("โœ‚๏ธ Text Chunking Control Panel", open=True):
194
+ chunk_toggle = gr.Checkbox(value=True, label="Enable Smart Text Chunking Segmentation")
195
+ size_input = gr.Number(value=256, label="Chunk Token Size Limit", minimum=10, maximum=4096, step=1)
196
+ overlap_input = gr.Number(value=30, label="Overlap Token Boundary Buffer", minimum=0, maximum=1024, step=1)
197
+
198
+ run_btn = gr.Button("๐Ÿš€ Run Conversion & Combine Files", variant="primary")
199
+
200
+ with gr.Column(scale=1):
201
+ log_monitor = gr.Textbox(label="๐Ÿ–ฅ๏ธ Core Engine Pipeline Logs", lines=15)
202
+
203
+ run_btn.click(
204
+ fn=execute_dataset_builder_pipeline,
205
+ inputs=[file_uploader, archetype_dropdown, chunk_toggle, size_input, overlap_input],
206
+ outputs=log_monitor
207
+ )
208
+
209
+ theme_toggle_btn.click(
210
+ fn=toggle_theme,
211
+ inputs=[ui_theme_state],
212
+ outputs=[theme_toggle_btn, ui_theme_state]
213
+ ).then(
214
+ fn=None,
215
+ inputs=[ui_theme_state],
216
+ js=js_theme_switcher
217
+ )
218
+
219
+ demo.load(fn=lambda: "dark", outputs=ui_theme_state).then(fn=None, inputs=[ui_theme_state], js=js_theme_switcher)
220
+
221
+ if __name__ == "__main__":
222
+ # Theme configuration parameters passed to launch method matching Gradio 6 guidelines
223
+ demo.launch(theme=custom_theme)