Upgrade gradio-lite
Browse files- index.html +140 -24
index.html
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
<!--
|
2 |
Copyright (c) 2024 Isao Sonobe
|
3 |
Released under the MIT license
|
@@ -27,9 +28,62 @@ https://opensource.org/license/mit/
|
|
27 |
min-height: 500px;
|
28 |
}
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
.chatbot {
|
31 |
white-space: pre-wrap;
|
32 |
}
|
|
|
33 |
|
34 |
.gallery-item > .gallery {
|
35 |
max-width: 380px;
|
@@ -82,7 +136,7 @@ import httpx
|
|
82 |
await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/urllib3/urllib3-2.1.0-py3-none-any.whl", keep_going=True)
|
83 |
import urllib3
|
84 |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
85 |
-
await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/tiktoken/tiktoken-0.5.
|
86 |
|
87 |
|
88 |
import gradio as gr
|
@@ -111,6 +165,7 @@ from rank_bm25 import BM25Okapi
|
|
111 |
|
112 |
from openai import OpenAI, AzureOpenAI
|
113 |
import tiktoken
|
|
|
114 |
|
115 |
|
116 |
class URLLib3Transport(httpx.BaseTransport):
|
@@ -138,7 +193,28 @@ class Page:
|
|
138 |
content: str
|
139 |
|
140 |
|
141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
JANOME_TOKENIZER = JanomeTokenizer()
|
143 |
JANOME_ANALYZER = JanomeAnalyzer(tokenizer=JANOME_TOKENIZER,
|
144 |
token_filters=[POSStopFilter(["記号,空白"]), LowerCaseFilter()])
|
@@ -218,6 +294,32 @@ def extract_pages_from_page_tag(document_with_page_tag):
|
|
218 |
return pages
|
219 |
|
220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
def add_s(values):
|
222 |
"""
|
223 |
複数形のsを必要に応じて付けるために用いる関数。
|
@@ -432,7 +534,9 @@ def get_openai_messages(prompt, history, context):
|
|
432 |
messages = []
|
433 |
for user_message, assistant_message in history:
|
434 |
if user_message is not None and assistant_message is not None:
|
|
|
435 |
user_message = user_message.replace("{context}", context)
|
|
|
436 |
messages.append({ "role": "user", "content": user_message })
|
437 |
messages.append({ "role": "assistant", "content": assistant_message })
|
438 |
|
@@ -598,7 +702,6 @@ async def process_prompt(prompt, history, context, platform, endpoint, azure_dep
|
|
598 |
raise gr.Error(str(e))
|
599 |
|
600 |
|
601 |
-
|
602 |
def load_api_key(file_obj):
|
603 |
"""
|
604 |
APIキーファイルからAPIキーを読み込む。
|
@@ -631,16 +734,16 @@ def get_cost_info(prompt_token_count):
|
|
631 |
|
632 |
# デフォルト設定値
|
633 |
DEFAULT_SETTINGS = {
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
|
645 |
|
646 |
def main():
|
@@ -1054,8 +1157,16 @@ def main():
|
|
1054 |
chatbot = gr.Chatbot(
|
1055 |
CHAT_HISTORY,
|
1056 |
elem_id="chatbot", height=500, show_copy_button=True,
|
1057 |
-
sanitize_html=
|
1058 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1059 |
|
1060 |
message_state = gr.State()
|
1061 |
chatbot_state = gr.State(chatbot.value) if chatbot.value else gr.State([])
|
@@ -1076,6 +1187,7 @@ def main():
|
|
1076 |
undo_button = gr.Button("↩️ Undo", variant="secondary", size="sm")
|
1077 |
clear_button = gr.Button("🗑️ Clear", variant="secondary", size="sm")
|
1078 |
|
|
|
1079 |
def estimate_message_cost(prompt, history, context):
|
1080 |
token_count = 0
|
1081 |
messages = get_openai_messages(prompt, history, context)
|
@@ -1085,6 +1197,7 @@ def main():
|
|
1085 |
|
1086 |
return gr.update(value=get_cost_info(token_count))
|
1087 |
|
|
|
1088 |
message_textbox.change(estimate_message_cost, inputs=[message_textbox, chatbot, context], outputs=cost_info, queue=False, show_progress="hidden")
|
1089 |
|
1090 |
example_title_textbox = gr.Textbox(visible=False, interactive=True)
|
@@ -1092,17 +1205,21 @@ def main():
|
|
1092 |
inputs=example_title_textbox, outputs=message_textbox,
|
1093 |
fn=lambda title: examples[title], run_on_click=True)
|
1094 |
|
|
|
1095 |
def append_message_to_history(message, history):
|
|
|
1096 |
history.append([message, None])
|
1097 |
return history, history
|
1098 |
|
|
|
1099 |
def undo_chat(history):
|
1100 |
if history:
|
1101 |
message, _ = history.pop()
|
1102 |
message = message or ""
|
1103 |
else:
|
1104 |
message = ""
|
1105 |
-
return history, history, message
|
|
|
1106 |
|
1107 |
async def submit_message(message, history_with_input, *args):
|
1108 |
history = history_with_input[:-1]
|
@@ -1110,10 +1227,12 @@ def main():
|
|
1110 |
inputs.extend(args)
|
1111 |
|
1112 |
generator = process_prompt(*inputs)
|
|
|
1113 |
|
1114 |
has_response = False
|
1115 |
async for response in generator:
|
1116 |
has_response = True
|
|
|
1117 |
update = history + [[message, response]]
|
1118 |
yield update, update
|
1119 |
|
@@ -1121,10 +1240,11 @@ def main():
|
|
1121 |
update = history + [[message, None]]
|
1122 |
yield update, update
|
1123 |
|
|
|
1124 |
submit_triggers = [message_textbox.submit, submit_button.click]
|
1125 |
|
1126 |
-
submit_event = gr.events.on(
|
1127 |
-
inputs=[message_textbox], outputs=[message_textbox, message_state], queue=False
|
1128 |
).then(
|
1129 |
append_message_to_history, inputs=[message_state, chatbot_state], outputs=[chatbot, chatbot_state], queue=False
|
1130 |
).then(
|
@@ -1181,16 +1301,12 @@ def main():
|
|
1181 |
estimate_message_cost, inputs=[message_textbox, chatbot, context], outputs=cost_info, show_progress="hidden"
|
1182 |
)
|
1183 |
|
1184 |
-
app.load(None, inputs=None, outputs=setting_items,
|
1185 |
-
js=js_define_utilities_and_load_settings, show_progress="hidden")
|
1186 |
|
1187 |
app.queue().launch()
|
1188 |
|
1189 |
main()
|
1190 |
</gradio-file>
|
1191 |
-
|
1192 |
-
<!-- DALL-Eを用いて作ったボットアイコン -->
|
1193 |
-
<gradio-file name="robot.png" url="https://raw.githubusercontent.com/sonoisa/misc/main/resources/icons/chatbot_icon.png" />
|
1194 |
</gradio-lite>
|
1195 |
|
1196 |
<script language="javascript" src="https://cdn.jsdelivr.net/npm/lz-string@1.5.0/libs/lz-string.min.js"></script>
|
@@ -1208,6 +1324,6 @@ main()
|
|
1208 |
}
|
1209 |
})();
|
1210 |
</script>
|
1211 |
-
<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite@4.
|
1212 |
</body>
|
1213 |
</html>
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
<!--
|
3 |
Copyright (c) 2024 Isao Sonobe
|
4 |
Released under the MIT license
|
|
|
28 |
min-height: 500px;
|
29 |
}
|
30 |
|
31 |
+
#chatbot h1 {
|
32 |
+
font-size: 2em;
|
33 |
+
margin-block-start: 0.67em;
|
34 |
+
margin-block-end: 0em;
|
35 |
+
margin-inline-start: 0px;
|
36 |
+
margin-inline-end: 0px;
|
37 |
+
font-weight: bold;
|
38 |
+
}
|
39 |
+
|
40 |
+
#chatbot h2 {
|
41 |
+
font-size: 1.5em;
|
42 |
+
margin-block-start: 0.83em;
|
43 |
+
margin-block-end: 0em;
|
44 |
+
margin-inline-start: 0px;
|
45 |
+
margin-inline-end: 0px;
|
46 |
+
font-weight: bold;
|
47 |
+
}
|
48 |
+
|
49 |
+
#chatbot h3 {
|
50 |
+
font-size: 1.17em;
|
51 |
+
margin-block-start: 1em;
|
52 |
+
margin-block-end: 0em;
|
53 |
+
margin-inline-start: 0px;
|
54 |
+
margin-inline-end: 0px;
|
55 |
+
font-weight: bold;
|
56 |
+
}
|
57 |
+
|
58 |
+
#chatbot h4 {
|
59 |
+
margin-block-start: 1.33em;
|
60 |
+
margin-block-end: 0em;
|
61 |
+
margin-inline-start: 0px;
|
62 |
+
margin-inline-end: 0px;
|
63 |
+
font-weight: bold;
|
64 |
+
}
|
65 |
+
|
66 |
+
#chatbot h5 {
|
67 |
+
margin-block-start: 1.67em;
|
68 |
+
margin-block-end: 0em;
|
69 |
+
margin-inline-start: 0px;
|
70 |
+
margin-inline-end: 0px;
|
71 |
+
font-weight: bold;
|
72 |
+
}
|
73 |
+
|
74 |
+
#chatbot h6 {
|
75 |
+
margin-block-start: 1.83em;
|
76 |
+
margin-block-end: 0em;
|
77 |
+
margin-inline-start: 0px;
|
78 |
+
margin-inline-end: 0px;
|
79 |
+
font-weight: bold;
|
80 |
+
}
|
81 |
+
|
82 |
+
/*
|
83 |
.chatbot {
|
84 |
white-space: pre-wrap;
|
85 |
}
|
86 |
+
*/
|
87 |
|
88 |
.gallery-item > .gallery {
|
89 |
max-width: 380px;
|
|
|
136 |
await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/urllib3/urllib3-2.1.0-py3-none-any.whl", keep_going=True)
|
137 |
import urllib3
|
138 |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
139 |
+
await micropip.install("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/tiktoken/tiktoken-0.5.2-cp311-cp311-emscripten_3_1_46_wasm32.whl", keep_going=True)
|
140 |
|
141 |
|
142 |
import gradio as gr
|
|
|
165 |
|
166 |
from openai import OpenAI, AzureOpenAI
|
167 |
import tiktoken
|
168 |
+
import requests
|
169 |
|
170 |
|
171 |
class URLLib3Transport(httpx.BaseTransport):
|
|
|
193 |
content: str
|
194 |
|
195 |
|
196 |
+
def load_tiktoken_model(model_url):
|
197 |
+
resp = requests.get(model_url)
|
198 |
+
resp.raise_for_status()
|
199 |
+
return resp.content
|
200 |
+
|
201 |
+
# OPENAI_TOKENIZER = tiktoken.get_encoding("cl100k_base")
|
202 |
+
OPENAI_TOKENIZER = tiktoken.Encoding(
|
203 |
+
name="cl100k_base",
|
204 |
+
pat_str=r"""'(?i:[sdmt]|ll|ve|re)|[^\r\n\p{L}\p{N}]?+\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]++[\r\n]*|\s*[\r\n]|\s+(?!\S)|\s+""",
|
205 |
+
mergeable_ranks={
|
206 |
+
base64.b64decode(token): int(rank)
|
207 |
+
for token, rank in (line.split() for line in load_tiktoken_model("https://raw.githubusercontent.com/sonoisa/pyodide_wheels/main/tiktoken/cl100k_base.tiktoken").splitlines() if line)
|
208 |
+
},
|
209 |
+
special_tokens={
|
210 |
+
"<|endoftext|>": 100257,
|
211 |
+
"<|fim_prefix|>": 100258,
|
212 |
+
"<|fim_middle|>": 100259,
|
213 |
+
"<|fim_suffix|>": 100260,
|
214 |
+
"<|endofprompt|>": 100276,
|
215 |
+
}
|
216 |
+
)
|
217 |
+
|
218 |
JANOME_TOKENIZER = JanomeTokenizer()
|
219 |
JANOME_ANALYZER = JanomeAnalyzer(tokenizer=JANOME_TOKENIZER,
|
220 |
token_filters=[POSStopFilter(["記号,空白"]), LowerCaseFilter()])
|
|
|
294 |
return pages
|
295 |
|
296 |
|
297 |
+
def escape_latex(unescaped_text):
|
298 |
+
"""
|
299 |
+
Chatbotのmarkdownで数式が表示されるように \\(, \\), \\[, \\] をバックスラッシュでエスケープする。
|
300 |
+
|
301 |
+
Args:
|
302 |
+
unescaped_text (str): エスケープ対象文字列
|
303 |
+
|
304 |
+
Returns:
|
305 |
+
str: エスケープされた文字列
|
306 |
+
"""
|
307 |
+
return re.sub(r"(\\[\(\)\[\]])", r"\\\1", unescaped_text)
|
308 |
+
|
309 |
+
|
310 |
+
def unescape_latex(escaped_text):
|
311 |
+
"""
|
312 |
+
Chatbotのmarkdownで数式が表示されるようにエスケープされていた \\(, \\), \\[, \\] をエスケープされていない元の括弧に変換する。
|
313 |
+
|
314 |
+
Args:
|
315 |
+
escaped_text (str): エスケープされた文字列
|
316 |
+
|
317 |
+
Returns:
|
318 |
+
str: エスケープされていない文字列
|
319 |
+
"""
|
320 |
+
return re.sub(r"\\(\\[\(\)\[\]])", r"\1", escaped_text)
|
321 |
+
|
322 |
+
|
323 |
def add_s(values):
|
324 |
"""
|
325 |
複数形のsを必要に応じて付けるために用いる関数。
|
|
|
534 |
messages = []
|
535 |
for user_message, assistant_message in history:
|
536 |
if user_message is not None and assistant_message is not None:
|
537 |
+
user_message = unescape_latex(user_message)
|
538 |
user_message = user_message.replace("{context}", context)
|
539 |
+
assistant_message = unescape_latex(assistant_message)
|
540 |
messages.append({ "role": "user", "content": user_message })
|
541 |
messages.append({ "role": "assistant", "content": assistant_message })
|
542 |
|
|
|
702 |
raise gr.Error(str(e))
|
703 |
|
704 |
|
|
|
705 |
def load_api_key(file_obj):
|
706 |
"""
|
707 |
APIキーファイルからAPIキーを読み込む。
|
|
|
734 |
|
735 |
# デフォルト設定値
|
736 |
DEFAULT_SETTINGS = {
|
737 |
+
"setting_name": "Default",
|
738 |
+
"platform": "OpenAI",
|
739 |
+
"endpoint": "https://api.openai.com/v1",
|
740 |
+
"azure_deployment": "",
|
741 |
+
"azure_api_version": "",
|
742 |
+
"model_name": "gpt-4-turbo-preview",
|
743 |
+
"max_tokens": 4096,
|
744 |
+
"temperature": 0.2,
|
745 |
+
"save_chat_history_to_url": False
|
746 |
+
};
|
747 |
|
748 |
|
749 |
def main():
|
|
|
1157 |
chatbot = gr.Chatbot(
|
1158 |
CHAT_HISTORY,
|
1159 |
elem_id="chatbot", height=500, show_copy_button=True,
|
1160 |
+
sanitize_html=True, render_markdown=True,
|
1161 |
+
latex_delimiters=[
|
1162 |
+
# { "left": "$$", "right": "$$", "display": True },
|
1163 |
+
# { "left": "$", "right": "$", "display": False },
|
1164 |
+
{ "left": "\\(", "right": "\\)", "display": False },
|
1165 |
+
{ "left": "\\[", "right": "\\]", "display": True },
|
1166 |
+
],
|
1167 |
+
likeable=False, layout="bubble",
|
1168 |
+
avatar_images=[None, "https://raw.githubusercontent.com/sonoisa/misc/main/resources/icons/chatbot_icon.png"]
|
1169 |
+
)
|
1170 |
|
1171 |
message_state = gr.State()
|
1172 |
chatbot_state = gr.State(chatbot.value) if chatbot.value else gr.State([])
|
|
|
1187 |
undo_button = gr.Button("↩️ Undo", variant="secondary", size="sm")
|
1188 |
clear_button = gr.Button("🗑️ Clear", variant="secondary", size="sm")
|
1189 |
|
1190 |
+
|
1191 |
def estimate_message_cost(prompt, history, context):
|
1192 |
token_count = 0
|
1193 |
messages = get_openai_messages(prompt, history, context)
|
|
|
1197 |
|
1198 |
return gr.update(value=get_cost_info(token_count))
|
1199 |
|
1200 |
+
|
1201 |
message_textbox.change(estimate_message_cost, inputs=[message_textbox, chatbot, context], outputs=cost_info, queue=False, show_progress="hidden")
|
1202 |
|
1203 |
example_title_textbox = gr.Textbox(visible=False, interactive=True)
|
|
|
1205 |
inputs=example_title_textbox, outputs=message_textbox,
|
1206 |
fn=lambda title: examples[title], run_on_click=True)
|
1207 |
|
1208 |
+
|
1209 |
def append_message_to_history(message, history):
|
1210 |
+
message = escape_latex(message)
|
1211 |
history.append([message, None])
|
1212 |
return history, history
|
1213 |
|
1214 |
+
|
1215 |
def undo_chat(history):
|
1216 |
if history:
|
1217 |
message, _ = history.pop()
|
1218 |
message = message or ""
|
1219 |
else:
|
1220 |
message = ""
|
1221 |
+
return history, history, unescape_latex(message)
|
1222 |
+
|
1223 |
|
1224 |
async def submit_message(message, history_with_input, *args):
|
1225 |
history = history_with_input[:-1]
|
|
|
1227 |
inputs.extend(args)
|
1228 |
|
1229 |
generator = process_prompt(*inputs)
|
1230 |
+
message = escape_latex(message)
|
1231 |
|
1232 |
has_response = False
|
1233 |
async for response in generator:
|
1234 |
has_response = True
|
1235 |
+
response = escape_latex(response)
|
1236 |
update = history + [[message, response]]
|
1237 |
yield update, update
|
1238 |
|
|
|
1240 |
update = history + [[message, None]]
|
1241 |
yield update, update
|
1242 |
|
1243 |
+
|
1244 |
submit_triggers = [message_textbox.submit, submit_button.click]
|
1245 |
|
1246 |
+
submit_event = gr.events.on(
|
1247 |
+
submit_triggers, lambda message: ("", message), inputs=[message_textbox], outputs=[message_textbox, message_state], queue=False
|
1248 |
).then(
|
1249 |
append_message_to_history, inputs=[message_state, chatbot_state], outputs=[chatbot, chatbot_state], queue=False
|
1250 |
).then(
|
|
|
1301 |
estimate_message_cost, inputs=[message_textbox, chatbot, context], outputs=cost_info, show_progress="hidden"
|
1302 |
)
|
1303 |
|
1304 |
+
app.load(None, inputs=None, outputs=setting_items, js=js_define_utilities_and_load_settings, show_progress="hidden")
|
|
|
1305 |
|
1306 |
app.queue().launch()
|
1307 |
|
1308 |
main()
|
1309 |
</gradio-file>
|
|
|
|
|
|
|
1310 |
</gradio-lite>
|
1311 |
|
1312 |
<script language="javascript" src="https://cdn.jsdelivr.net/npm/lz-string@1.5.0/libs/lz-string.min.js"></script>
|
|
|
1324 |
}
|
1325 |
})();
|
1326 |
</script>
|
1327 |
+
<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite@4.26.0/dist/lite.js"></script>
|
1328 |
</body>
|
1329 |
</html>
|