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>
|