sonoisa commited on
Commit
83db5da
·
verified ·
1 Parent(s): 7c13fd9

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +499 -14
index.html CHANGED
@@ -1,19 +1,504 @@
1
- <!doctype html>
 
 
 
 
2
  <html>
3
  <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  </head>
9
  <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  </body>
19
- </html>
 
1
+ <!--
2
+ Copyright (c) 2024 Isao Sonobe
3
+ Released under the MIT license
4
+ https://opensource.org/license/mit/
5
+ -->
6
  <html>
7
  <head>
8
+ <meta charset="UTF-8">
9
+ <meta name="viewport" content="width=device-width, initial-scale=1">
10
+ <title>Chat with your PDF</title>
11
+ <meta name="description" content="Chat with your PDF">
12
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/[email protected]/dist/lite.css" />
13
+ <style>
14
+ html, body {
15
+ margin: 0;
16
+ padding: 0;
17
+ height: 100%;
18
+ background: var(--body-background-fill);
19
+ }
20
+
21
+ footer {
22
+ display: none !important;
23
+ }
24
+
25
+ #chatbot {
26
+ height: auto !important;
27
+ min-height: 500px;
28
+ }
29
+
30
+ .chatbot {
31
+ white-space: pre-wrap;
32
+ }
33
+
34
+ .gallery-item > .gallery {
35
+ max-width: 380px;
36
+ }
37
+ </style>
38
  </head>
39
  <body>
40
+ <gradio-lite>
41
+ <gradio-requirements>
42
+ pdfminer.six==20231228
43
+ pyodide-http==0.2.1
44
+ </gradio-requirements>
45
+
46
+ <gradio-file name="chat_history.json">
47
+ [[null, "ようこそ! PDFのテキストを参照しながら対話できるチャットボットです。\nPDFファイルをアップロードするとテキストが抽出されます。\nメッセージの中に{context}と書くと、抽出されたテキストがその部分に埋め込まれて対話が行われます。一番下のExamplesにその例があります。\nメッセージを書くときにShift+Enterを入力すると改行できます。"]]
48
+ </gradio-file>
49
+
50
+ <gradio-file name="app.py" entrypoint>
51
+ import os
52
+
53
+ # Gradioによるアナリティクスを無効化
54
+ os.putenv("GRADIO_ANALYTICS_ENABLED", "False")
55
+ os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
56
+
57
+ import gradio as gr
58
+ import base64
59
+ from pathlib import Path
60
+ import json
61
+
62
+ import pyodide_http
63
+ pyodide_http.patch_all()
64
+
65
+ from pdfminer.pdfinterp import PDFResourceManager
66
+ from pdfminer.converter import TextConverter
67
+ from pdfminer.pdfinterp import PDFPageInterpreter
68
+ from pdfminer.pdfpage import PDFPage
69
+ from pdfminer.layout import LAParams
70
+ from io import StringIO
71
+
72
+ # openaiライブラリのインストール方法は https://github.com/pyodide/pyodide/issues/4292 を参考にしました。
73
+ import micropip
74
+ await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/multidict/multidict-4.7.6-py3-none-any.whl", keep_going=True)
75
+ await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/frozenlist/frozenlist-1.4.0-py3-none-any.whl", keep_going=True)
76
+ await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/aiohttp/aiohttp-4.0.0a2.dev0-py3-none-any.whl", keep_going=True)
77
+ await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/openai/openai-1.3.7-py3-none-any.whl", keep_going=True)
78
+ await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/urllib3/urllib3-2.1.0-py3-none-any.whl", keep_going=True)
79
+ await micropip.install("ssl")
80
+ import ssl
81
+ await micropip.install("httpx", keep_going=True)
82
+ import httpx
83
+ await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/urllib3/urllib3-2.1.0-py3-none-any.whl", keep_going=True)
84
+ import urllib3
85
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
86
+ await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/tiktoken/tiktoken-0.5.1-cp311-cp311-emscripten_3_1_45_wasm32.whl", keep_going=True)
87
+
88
+
89
+ class URLLib3Transport(httpx.BaseTransport):
90
+ """
91
+ urllib3を使用してhttpxのリクエストを処理するカスタムトランスポートクラス
92
+ """
93
+ def __init__(self):
94
+ self.pool = urllib3.PoolManager()
95
+
96
+ def handle_request(self, request: httpx.Request):
97
+ payload = json.loads(request.content.decode("utf-8"))
98
+ urllib3_response = self.pool.request(request.method, str(request.url), headers=request.headers, json=payload)
99
+ stream = httpx.ByteStream(urllib3_response.data)
100
+ return httpx.Response(urllib3_response.status, headers=urllib3_response.headers, stream=stream)
101
+
102
+ http_client = httpx.Client(transport=URLLib3Transport())
103
+
104
+ from openai import OpenAI, AzureOpenAI
105
+ import tiktoken
106
+
107
+
108
+ OPENAI_TOKENIZER = tiktoken.get_encoding("cl100k_base")
109
+
110
+
111
+ def extract_text(pdf_filename):
112
+ """
113
+ PDFファイルからテキストを抽出する。
114
+
115
+ Args:
116
+ pdf_filename (str): 抽出するPDFファイルのパス
117
+
118
+ Returns:
119
+ str: PDFファイルから抽出されたテキスト
120
+ """
121
+ with open(pdf_filename, "rb") as pdf_file:
122
+ output = StringIO()
123
+ resource_manager = PDFResourceManager()
124
+ laparams = LAParams()
125
+ text_converter = TextConverter(resource_manager, output, laparams=laparams)
126
+ page_interpreter = PDFPageInterpreter(resource_manager, text_converter)
127
+
128
+ for i_page in PDFPage.get_pages(pdf_file):
129
+ try:
130
+ page_interpreter.process_page(i_page)
131
+ except Exception as e:
132
+ # print(e)
133
+ pass
134
+
135
+ output_text = output.getvalue()
136
+ output.close()
137
+ text_converter.close()
138
+ return output_text
139
+
140
+
141
+ def get_character_count_info(char_count, token_count):
142
+ """
143
+ 文字数とトークン数の情報を文字列で返す。
144
+
145
+ Args:
146
+ char_count (int): 文字数
147
+ token_count (int): トークン数
148
+
149
+ Returns:
150
+ str: 文字数とトークン数の情報を含む文字列
151
+ """
152
+ return f"""{char_count:,} character{'s' if char_count > 1 else ''}
153
+ {token_count:,} token{'s' if token_count > 1 else ''}"""
154
+
155
+
156
+ def update_context_element(pdf_file_obj):
157
+ """
158
+ PDFファイルからテキストを抽出し、コンテキスト要素を更新する。
159
+
160
+ Args:
161
+ pdf_file_obj (File): アップロードされたPDFファイルオブジェクト
162
+
163
+ Returns:
164
+ Tuple: コンテキストテキストボックスに格納する抽出されたテキスト情報と、その文字数情報
165
+ """
166
+ context = extract_text(pdf_file_obj.name)
167
+ return gr.update(value=context, interactive=True), count_characters(context)
168
+
169
+
170
+ def count_characters(text):
171
+ """
172
+ テキストの文字数とトークン数を計算する。
173
+
174
+ Args:
175
+ text (str): 文字数とトークン数を計算するテキスト
176
+
177
+ Returns:
178
+ str: 文字数とトークン数の情報を含む文字列
179
+ """
180
+ tokens = OPENAI_TOKENIZER.encode(text)
181
+ return get_character_count_info(len(text), len(tokens))
182
+
183
+
184
+ def process_prompt(prompt, history, context, platform, endpoint, azure_deployment, azure_api_version, api_key, model_name, max_tokens, temperature):
185
+ """
186
+ ユーザーのプロンプトを処理し、ChatGPTによる生成結果を返す。
187
+
188
+ Args:
189
+ prompt (str): ユーザーからの入力プロンプト
190
+ history (list): チャット履歴
191
+ context (str): チャットコンテキスト
192
+ platform (str): 使用するAIプラットフォーム
193
+ endpoint (str): AIサービスのエンドポイント
194
+ azure_deployment (str): Azureのデプロイメント名
195
+ azure_api_version (str): Azure APIのバージョン
196
+ api_key (str): APIキー
197
+ model_name (str): 使用するAIモデルの名前
198
+ max_tokens (int): 生成する最大トークン数
199
+ temperature (float): クリエイティビティの度合いを示す温度パラメータ
200
+
201
+ Returns:
202
+ str: ChatGPTによる生成結果
203
+ """
204
+ try:
205
+ messages = []
206
+ for user_message, assistant_message in history:
207
+ if user_message is not None and assistant_message is not None:
208
+ messages.append({ "role": "user", "content": user_message })
209
+ messages.append({ "role": "assistant", "content": assistant_message })
210
+
211
+ prompt = prompt.replace("{context}", context)
212
+ messages.append({ "role": "user", "content": prompt })
213
+
214
+ if platform == "OpenAI":
215
+ openai_client = OpenAI(
216
+ base_url=endpoint,
217
+ api_key=api_key,
218
+ http_client=http_client
219
+ )
220
+ else: # Azure
221
+ openai_client = AzureOpenAI(
222
+ azure_endpoint=endpoint,
223
+ api_version=azure_api_version,
224
+ azure_deployment=azure_deployment,
225
+ api_key=api_key,
226
+ http_client=http_client
227
+ )
228
+
229
+ completion = openai_client.chat.completions.create(
230
+ messages=messages,
231
+ model=model_name,
232
+ max_tokens=max_tokens,
233
+ temperature=temperature,
234
+ stream=False
235
+ )
236
+
237
+ if hasattr(completion, "error"):
238
+ raise gr.Error(completion.error["message"])
239
+ else:
240
+ message = completion.choices[0].message
241
+ return message.content
242
+
243
+ except Exception as e:
244
+ if hasattr(e, "message"):
245
+ raise gr.Error(e.message)
246
+ else:
247
+ raise gr.Error(str(e))
248
+
249
+
250
+ def load_api_key(file_obj):
251
+ """
252
+ APIキーファイルからAPIキーを読み込む。
253
+
254
+ Args:
255
+ file_obj (File): APIキーファイルオブジェクト
256
+
257
+ Returns:
258
+ str: 読み込まれたAPIキー文字列
259
+ """
260
+ try:
261
+ with open(file_obj.name, "r", encoding="utf-8") as api_key_file:
262
+ return api_key_file.read().strip()
263
+ except Exception as e:
264
+ raise gr.Error(str(e))
265
+
266
+
267
+ def main():
268
+ """
269
+ アプリケーションのメイン関数。Gradioインターフェースを設定し、アプリケーションを起動する。
270
+ """
271
+ try:
272
+ # クエリパラメータに保存されていることもあるチャット履歴を読み出す。
273
+ with open("chat_history.json", "r", encoding="utf-8") as f:
274
+ CHAT_HISTORY = json.load(f)
275
+ except Exception as e:
276
+ print(e)
277
+ CHAT_HISTORY = []
278
+
279
+ # localStorageから設定情報ををロードする。
280
+ js_define_utilities_and_load_settings = """() => {
281
+ const KEY_PREFIX = "serverless_chat_with_your_pdf:";
282
+
283
+ const loadSettings = () => {
284
+ const getItem = (key, defaultValue) => {
285
+ const jsonValue = localStorage.getItem(KEY_PREFIX + key);
286
+ if (jsonValue) {
287
+ return JSON.parse(jsonValue);
288
+ } else {
289
+ return defaultValue;
290
+ }
291
+ };
292
+
293
+ const platform = getItem("platform", "OpenAI");
294
+ const endpoint = getItem("endpoint", "https://api.openai.com/v1");
295
+ const azure_deployment = getItem("azure_deployment", "");
296
+ const azure_api_version = getItem("azure_api_version", "");
297
+ const model_name = getItem("model_name", "gpt-4-turbo-preview");
298
+ const max_tokens = getItem("max_tokens", 1024);
299
+ const temperature = getItem("temperature", 0.2);
300
+ const save_chat_history_to_url = getItem("save_chat_history_to_url", false);
301
+
302
+ return [platform, endpoint, azure_deployment, azure_api_version, model_name, max_tokens, temperature, save_chat_history_to_url];
303
+ };
304
+
305
+ globalThis.resetSettings = () => {
306
+ for (let key in localStorage) {
307
+ if (key.startsWith(KEY_PREFIX)) {
308
+ localStorage.removeItem(key);
309
+ }
310
+ }
311
+
312
+ return loadSettings();
313
+ };
314
+
315
+ globalThis.saveItem = (key, value) => {
316
+ localStorage.setItem(KEY_PREFIX + key, JSON.stringify(value));
317
+ };
318
+
319
+ return loadSettings();
320
+ }
321
+ """
322
+
323
+ # should_saveがtrueであればURLにチャット履歴を保存し、falseであればチャット履歴を削除する。
324
+ save_or_delete_chat_history = '''(hist, should_save) => {
325
+ saveItem("save_chat_history_to_url", should_save);
326
+ if (!should_save) {
327
+ const url = new URL(window.location.href);
328
+ url.searchParams.delete("history");
329
+ window.history.replaceState({path:url.href}, '', url.href);
330
+ } else {
331
+ const compressedHistory = LZString.compressToEncodedURIComponent(JSON.stringify(hist));
332
+ const url = new URL(window.location.href);
333
+ url.searchParams.set("history", compressedHistory);
334
+ window.history.replaceState({path:url.href}, '', url.href);
335
+ }
336
+ }'''
337
+
338
+ with gr.Blocks(theme=gr.themes.Default(), analytics_enabled=False) as app:
339
+ with gr.Tabs():
340
+ with gr.TabItem("Settings"):
341
+ with gr.Row():
342
+ with gr.Column():
343
+ platform = gr.Radio(label="Platform", interactive=True,
344
+ choices=["OpenAI", "Azure"], value="OpenAI")
345
+ platform.change(None, inputs=platform, outputs=None,
346
+ js='(x) => saveItem("platform", x)', show_progress="hidden")
347
+
348
+ with gr.Row():
349
+ endpoint = gr.Textbox(label="Endpoint", interactive=True)
350
+ endpoint.change(None, inputs=endpoint, outputs=None,
351
+ js='(x) => saveItem("endpoint", x)', show_progress="hidden")
352
+
353
+ azure_deployment = gr.Textbox(label="Azure Deployment", interactive=True)
354
+ azure_deployment.change(None, inputs=azure_deployment, outputs=None,
355
+ js='(x) => saveItem("azure_deployment", x)', show_progress="hidden")
356
+
357
+ azure_api_version = gr.Textbox(label="Azure API Version", interactive=True)
358
+ azure_api_version.change(None, inputs=azure_api_version, outputs=None,
359
+ js='(x) => saveItem("azure_api_version", x)', show_progress="hidden")
360
+
361
+ with gr.Row():
362
+ api_key_file = gr.File(file_count="single", file_types=["text"],
363
+ height=80, label="API Key File")
364
+ api_key = gr.Textbox(label="API Key", type="password", interactive=True)
365
+ # 注意: 秘密情報をlocalStorageに保存してはならない。他者に秘密情報が盗まれる危険性があるからである。
366
+
367
+ api_key_file.upload(fn=load_api_key, inputs=api_key_file, outputs=api_key,
368
+ show_progress="hidden")
369
+ api_key_file.clear(fn=lambda: None, inputs=None, outputs=api_key, show_progress="hidden")
370
+
371
+ model_name = gr.Textbox(label="model", interactive=True)
372
+ model_name.change(None, inputs=model_name, outputs=None,
373
+ js='(x) => saveItem("model_name", x)', show_progress="hidden")
374
+
375
+ max_tokens = gr.Number(label="Max Tokens", interactive=True,
376
+ minimum=0, precision=0, step=1)
377
+ max_tokens.change(None, inputs=max_tokens, outputs=None,
378
+ js='(x) => saveItem("max_tokens", x)', show_progress="hidden")
379
+
380
+ temperature = gr.Slider(label="Temperature", interactive=True,
381
+ minimum=0.0, maximum=1.0, step=0.1)
382
+ temperature.change(None, inputs=temperature, outputs=None,
383
+ js='(x) => saveItem("temperature", x)', show_progress="hidden")
384
+
385
+ save_chat_history_to_url = gr.Checkbox(label="Save Chat History to URL", interactive=True)
386
+
387
+ setting_items = [platform, endpoint, azure_deployment, azure_api_version, model_name, max_tokens, temperature, save_chat_history_to_url]
388
+ reset_button = gr.Button("Reset Settings")
389
+ reset_button.click(None, inputs=None, outputs=setting_items,
390
+ js="() => resetSettings()", show_progress="hidden")
391
+
392
+ with gr.TabItem("Chat"):
393
+ with gr.Row():
394
+ with gr.Column(scale=1):
395
+ pdf_file = gr.File(file_count="single", file_types=[".pdf"],
396
+ height=80, label="PDF")
397
+ context = gr.Textbox(label="Context", lines=20,
398
+ interactive=True, autoscroll=False, show_copy_button=True)
399
+ char_counter = gr.Textbox(label="Statistics", value=get_character_count_info(0, 0),
400
+ lines=2, max_lines=2, interactive=False, container=True)
401
+
402
+ pdf_file.upload(fn=update_context_element, inputs=pdf_file, outputs=[context, char_counter])
403
+ pdf_file.clear(fn=lambda: None, inputs=None, outputs=context, show_progress="hidden")
404
+
405
+ context.change(fn=count_characters, inputs=context, outputs=char_counter, show_progress="hidden")
406
+
407
+ with gr.Column(scale=2):
408
+ chatbot = gr.Chatbot(
409
+ CHAT_HISTORY,
410
+ elem_id="chatbot", render=False, height=500, show_copy_button=True,
411
+ render_markdown=False, likeable=False, layout="bubble",
412
+ avatar_images=[None, Path("robot.png")])
413
+
414
+ chatbot.change(None, inputs=[chatbot, save_chat_history_to_url], outputs=None,
415
+ # チャット履歴をクエリパラメータに保存する。
416
+ js=save_or_delete_chat_history, show_progress="hidden")
417
+
418
+ save_chat_history_to_url.change(None, inputs=[chatbot, save_chat_history_to_url], outputs=None,
419
+ js=save_or_delete_chat_history, show_progress="hidden")
420
+
421
+ chat = gr.ChatInterface(process_prompt,
422
+ title="Chat with your PDF",
423
+ chatbot=chatbot,
424
+ textbox=gr.Textbox(
425
+ placeholder="Type a message...",
426
+ render=False, container=False, scale=7),
427
+ additional_inputs=[context, platform, endpoint, azure_deployment, azure_api_version, api_key, model_name, max_tokens, temperature],
428
+ examples=[['''制約条件に従い、以下の研究論文で提案されている技術や手法について要約してください。
429
+
430
+ # 制約条件
431
+ * 要約者: 大学教授
432
+ * 想定読者: 大学院生
433
+ * 要約結果の言語: 日本語
434
+ * 要約結果の構成:
435
+ 1. どんな研究であるか
436
+ 2. 先行研究に比べて優れている点は何か
437
+ 3. 提案されている技術や手法の重要な点は何か
438
+ 4. どのような方法で有効であると評価したか
439
+ 5. 何か議論はあるか
440
+ 6. 次に読むべき論文は何か
441
+
442
+ # 研究論文
443
+ """
444
+ {context}
445
+ """
446
+
447
+ # 要約結果'''], ['''制約条件に従い、以下の文書の内容を要約してください。
448
+
449
+ # 制約条件
450
+ * 要約者: 大学教授
451
+ * 想定読者: 大学院生
452
+ * 形式: 箇条書き
453
+ * 分量: 20項目
454
+ * 要約結果の言語: 日本語
455
+
456
+ # 文書
457
+ """
458
+ {context}
459
+ """
460
+
461
+ # 要約'''], ['''制約条件に従い、以下の文書から情報を抽出してください。
462
+
463
+ # 制約条件
464
+ * 抽出する情報: 課題や問題点について言及している全ての文。一つも見落とさないでください。
465
+ * 出力形式: 箇条書き
466
+ * 出力言語: 元の言語の文章と、その日本語訳
467
+
468
+ # 文書
469
+ """
470
+ {context}
471
+ """
472
+
473
+ # 抽出結果'''], ["続きを生成してください。"]])
474
+
475
+ app.load(None, inputs=None, outputs=setting_items,
476
+ js=js_define_utilities_and_load_settings, show_progress="hidden")
477
+
478
+ app.queue().launch()
479
+
480
+ main()
481
+ </gradio-file>
482
+
483
+ <!-- DALL-Eを用いて作ったボットアイコン -->
484
+ <gradio-file name="robot.png" url="https://raw.githubusercontent.com/sonoisa/misc/main/resources/icons/chatbot_icon.png" />
485
+ </gradio-lite>
486
+
487
+ <script language="javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/libs/lz-string.min.js"></script>
488
+ <script language="javascript">
489
+ (function () {
490
+ // クエリパラメータにチャット履歴が記録されていたらそれをロードし、chat_history.jsonファイルに書き出す。
491
+ const url = new URL(window.location.href);
492
+
493
+ if (url.searchParams.has("history")) {
494
+ const compressedHistory = url.searchParams.get("history");
495
+ hist = LZString.decompressFromEncodedURIComponent(compressedHistory);
496
+
497
+ const chat_history_element = document.querySelector('gradio-file[name="chat_history.json"]');
498
+ chat_history_element.textContent = hist;
499
+ }
500
+ })();
501
+ </script>
502
+ <script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/[email protected]/dist/lite.js"></script>
503
  </body>
504
+ </html>