Nils Durner commited on
Commit
8489337
1 Parent(s): 71a07ba

file-based settings storage

Browse files
Files changed (2) hide show
  1. app.py +15 -0
  2. settings_mgr.py +85 -0
app.py CHANGED
@@ -4,6 +4,7 @@ import os
4
  import boto3
5
 
6
  from doc2json import process_docx
 
7
 
8
  dump_controls = False
9
  log_to_console = False
@@ -130,6 +131,8 @@ with gr.Blocks() as demo:
130
  max_tokens = gr.Slider(1, 200000, label="Max. Tokens", elem_id="max_tokens", value=4000)
131
  save_button = gr.Button("Save Settings")
132
  load_button = gr.Button("Load Settings")
 
 
133
 
134
  load_button.click(load_settings, js="""
135
  () => {
@@ -155,6 +158,18 @@ with gr.Blocks() as demo:
155
  }
156
  """)
157
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  chatbot = gr.Chatbot(
159
  [],
160
  elem_id="chatbot",
 
4
  import boto3
5
 
6
  from doc2json import process_docx
7
+ from settings_mgr import generate_download_settings_js, generate_upload_settings_js
8
 
9
  dump_controls = False
10
  log_to_console = False
 
131
  max_tokens = gr.Slider(1, 200000, label="Max. Tokens", elem_id="max_tokens", value=4000)
132
  save_button = gr.Button("Save Settings")
133
  load_button = gr.Button("Load Settings")
134
+ dl_settings_button = gr.Button("Download Settings")
135
+ ul_settings_button = gr.Button("Upload Settings")
136
 
137
  load_button.click(load_settings, js="""
138
  () => {
 
158
  }
159
  """)
160
 
161
+ control_ids = [('aws_access', '#aws_access textarea'),
162
+ ('aws_secret', '#aws_secret textarea'),
163
+ ('aws_token', '#aws_token textarea'),
164
+ ('temp', '#temp input'),
165
+ ('max_tokens', '#max_tokens input'),
166
+ ('model', '#model'),
167
+ ('region', '#region')]
168
+ controls = [aws_access, aws_secret, aws_token, temp, max_tokens, model, region]
169
+
170
+ dl_settings_button.click(None, controls, js=generate_download_settings_js("amz_chat_settings.bin", control_ids))
171
+ ul_settings_button.click(None, None, None, js=generate_upload_settings_js(control_ids))
172
+
173
  chatbot = gr.Chatbot(
174
  [],
175
  elem_id="chatbot",
settings_mgr.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def generate_download_settings_js(dl_fn, control_ids):
2
+ js_code = """
3
+ async (""" + ", ".join([f'{ctrl[0]}' for ctrl in control_ids]) + """) => {
4
+ const password = prompt("Please enter a password for encryption", " ");
5
+ if (!password) {
6
+ alert("No password provided. Cancelling download.");
7
+ return;
8
+ }
9
+
10
+ let settings = {""" + ", ".join([f'"{ctrl[0]}": {ctrl[0]}' for ctrl in control_ids]) + """};
11
+ const settingsStr = JSON.stringify(settings);
12
+ const textEncoder = new TextEncoder();
13
+ const encodedSettings = textEncoder.encode(settingsStr);
14
+ const salt = crypto.getRandomValues(new Uint8Array(16));
15
+ const passwordBuffer = textEncoder.encode(password);
16
+ const keyMaterial = await crypto.subtle.importKey('raw', passwordBuffer, {name: 'PBKDF2'}, false, ['deriveKey']);
17
+ const key = await crypto.subtle.deriveKey(
18
+ {name: 'PBKDF2', salt: salt, iterations: 100000, hash: 'SHA-256'},
19
+ keyMaterial,
20
+ {name: 'AES-GCM', length: 256},
21
+ false,
22
+ ['encrypt']
23
+ );
24
+ const iv = crypto.getRandomValues(new Uint8Array(12));
25
+ const encryptedSettings = await crypto.subtle.encrypt({name: 'AES-GCM', iv: iv}, key, encodedSettings);
26
+ const blob = new Blob([salt, iv, new Uint8Array(encryptedSettings)], {type: 'application/octet-stream'});
27
+ const url = URL.createObjectURL(blob);
28
+ const a = document.createElement('a');
29
+ a.href = url;
30
+ a.download = '""" + dl_fn + """';
31
+ document.body.appendChild(a);
32
+ a.click();
33
+ document.body.removeChild(a);
34
+ URL.revokeObjectURL(url);
35
+ }"""
36
+ return js_code
37
+
38
+ def generate_upload_settings_js(control_ids):
39
+ js_code = """
40
+ async () => {
41
+ const input = document.createElement('input');
42
+ input.type = 'file';
43
+ input.onchange = async e => {
44
+ const file = e.target.files[0];
45
+ if (!file) {
46
+ alert("No file selected.");
47
+ return;
48
+ }
49
+
50
+ const password = prompt("Please enter the password for decryption", " ");
51
+ if (!password) {
52
+ alert("No password provided. Cancelling upload.");
53
+ return;
54
+ }
55
+
56
+ const arrayBuffer = await file.arrayBuffer();
57
+ const salt = arrayBuffer.slice(0, 16);
58
+ const iv = arrayBuffer.slice(16, 28);
59
+ const encryptedData = arrayBuffer.slice(28);
60
+ const textEncoder = new TextEncoder();
61
+ const passwordBuffer = textEncoder.encode(password);
62
+ const keyMaterial = await crypto.subtle.importKey('raw', passwordBuffer, {name: 'PBKDF2'}, false, ['deriveKey']);
63
+ const key = await crypto.subtle.deriveKey(
64
+ {name: 'PBKDF2', salt: salt, iterations: 100000, hash: 'SHA-256'},
65
+ keyMaterial,
66
+ {name: 'AES-GCM', length: 256},
67
+ false,
68
+ ['decrypt']
69
+ );
70
+
71
+ try {
72
+ const decryptedData = await crypto.subtle.decrypt({name: 'AES-GCM', iv: iv}, key, encryptedData);
73
+ const textDecoder = new TextDecoder();
74
+ const settingsStr = textDecoder.decode(decryptedData);
75
+ const settings = JSON.parse(settingsStr);
76
+ """ + "\n".join([f'document.querySelector("{ctrl[1]}").value = settings["{ctrl[0]}"];' for ctrl in control_ids]) + """
77
+ """ + "\n".join([f'document.querySelector("{ctrl[1]}").dispatchEvent(new InputEvent("input", {{ bubbles: true }}));' for ctrl in control_ids]) + """
78
+ } catch (err) {
79
+ alert("Failed to decrypt. Check your password and try again.");
80
+ console.error("Decryption failed:", err);
81
+ }
82
+ };
83
+ input.click();
84
+ }"""
85
+ return js_code