diff --git a/config_example.json b/config_example.json index 79d30f2a..d46f3573 100644 --- a/config_example.json +++ b/config_example.json @@ -33,7 +33,7 @@ "azure_embedding_model_name": "text-embedding-ada-002", // 你的 Azure OpenAI Embedding 模型名称 //== 基础配置 == - "language": "auto", // 界面语言,可选"auto", "zh_CN", "en_US", "ja_JP", "ko_KR", "sv_SE", "ru_RU", "vi_VN" + "language": "auto", // 界面语言,可选"auto", "zh_CN", "zh_TW", "en_US", "ja_JP", "ko_KR", "sv_SE", "ru_RU", "vi_VN" "users": [], // 用户列表,[["用户名1", "密码1"], ["用户名2", "密码2"], ...] "admin_list": [], // 管理员列表,["用户名1", "用户名2", ...] 只有管理员可以重启服务 "local_embedding": false, //是否在本地编制索引 diff --git a/locale/zh_TW.json b/locale/zh_TW.json new file mode 100644 index 00000000..45ded7e5 --- /dev/null +++ b/locale/zh_TW.json @@ -0,0 +1,30 @@ +{ + "gpt3.5turbo_description": "GPT-3.5 Turbo 是由 OpenAI 開發的一款僅限文字的大型語言模型。它基於 GPT-3 模型,並已經在大量數據上進行了微調。最新版本的 GPT-3.5 Turbo 進行了性能和精度優化,支援最大 16k tokens 的上下文窗口和最大 4096 tokens 的響應長度。此模型始終使用可用的最新版本的 GPT-3.5 Turbo。", + "gpt3.5turbo_instruct_description": "GPT3.5 Turbo Instruct 是 OpenAI 開發的文字補全模型,具有與 GPT-3 時代模型相似的功能。它兼容舊版的 Completions 端點,但不兼容 Chat Completions。該模型的上下文窗口為 4096 個 tokens。", + "gpt3.5turbo_16k_description": "舊版的 GPT-3.5 Turbo 模型,具有 16k tokens 的上下文窗口。", + "gpt4_description": "GPT-4 是 OpenAI 開發的一款僅限文字的大型語言模型。它具有 8192 個 tokens 的上下文窗口和 4096 個 tokens 的最大響應長度。該模型始終使用可用的最新版本的 GPT-4。建議使用 GPT-4 Turbo 以獲得更好的性能、更快的速度和更低的成本。", + "gpt4_32k_description": "GPT-4 32K 是 OpenAI 開發的一個僅限文字的大型語言模型。它具有 32,000 tokens 的上下文窗口和 4,096 tokens 的最大響應長度。這個模型從未廣泛推出,建議使用 GPT-4 Turbo。", + "gpt4turbo_description": "GPT-4 Turbo 是由 OpenAI 開發的一款多模態大型語言模型。它在廣泛的自然語言處理任務上提供最先進的性能,包括文字生成、翻譯、摘要、視覺問題回答等。GPT-4 Turbo 擁有最大 128k tokens 的上下文窗口和最大 4096 tokens 的響應長度。此模型始終使用可用的最新版本的 GPT-4 Turbo。", + "claude3_haiku_description": "Claude3 Haiku 是由 Anthropic 開發的一款多模態大型語言模型。它是 Claude 3 模型家族中最快、最緊湊的模型,旨在實現近乎即時的響應速度,但是性能不如 Sonnet 和 Opus。Claude3 Haiku 有最大 200k tokens 的上下文窗口和最大 4096 tokens 的響應長度。此模型始終使用可用的最新版本的 Claude3 Haiku。", + "claude3_sonnet_description": "Claude3 Sonnet 是由 Anthropic 開發的一款多模態大型語言模型。它在智慧與速度之間保持最佳平衡,適用於企業工作負載和大規模 AI 部署。Claude3 Sonnet 擁有最大 200k tokens 的上下文窗口和最大 4096 tokens 的響應長度。此模型始終使用可用的最新版本的 Claude3 Sonnet。", + "claude3_opus_description": "Claude3 Opus 是由 Anthropic 開發的一款多模態大型語言模型。它是 Claude 3 模型家族中最智慧、最大的模型,能夠在高度複雜的任務上呈現最頂尖的性能,呈現出類似人類的理解能力。Claude3 Opus 擁有最大 200k tokens 的上下文窗口和最大 4096 tokens 的響應長度。此模型始終使用可用的最新版本的 Claude3 Opus。", + "groq_llama3_8b_description": "採用 [Groq](https://console.groq.com/) 的 LLaMA 3 8B。Groq 是一個非常快速的語言模型推理服務。", + "groq_llama3_70b_description": "採用 [Groq](https://console.groq.com/) 的 LLaMA 3 70B。Groq 是一個非常快速的語言模型推理服務。", + "groq_mixtral_8x7b_description": "採用 [Groq](https://console.groq.com/) 的 Mixtral 8x7B。Groq 是一個非常快速的語言模型推理服務。", + "groq_gemma_7b_description": "採用 [Groq](https://console.groq.com/) 的 Gemma 7B。Groq 是一個非常快速的語言模型推理服務。", + "chuanhu_description": "一個能使用多種工具解決複雜問題的智慧體。", + "gpt_default_slogan": "今天能幫您些什麼?", + "claude_default_slogan": "我能幫您什麼忙?", + "chuanhu_slogan": "川虎今天能幫你做些什麼?", + "chuanhu_question_1": "今天杭州天氣如何?", + "chuanhu_question_2": "最近 Apple 發佈了什麼新品?", + "chuanhu_question_3": "現在顯卡的價格如何?", + "chuanhu_question_4": "TikTok 上有什麼新梗?", + "gpt4o_description": "OpenAI 的最先進的多模態旗艦模型,比 GPT-4 Turbo 更便宜、更快。", + "gpt4omini_description": "OpenAI 的經濟實惠且智慧的小型模型,適用於快速、輕量班導務。", + "gpt5_description": "跨領域編碼與智慧體任務的最佳模型。支援 400,000 token 上下文,單次可輸出至多 128,000 token。", + "gpt5mini_description": "面向明確任務的更快、更具性價比的 GPT-5 版本。支援 400,000 token 上下文,單次可輸出至多 128,000 token。", + "gpt5nano_description": "速度最快、性價比最高的 GPT-5 版本。支援 400,000 token 上下文,單次可輸出至多 128,000 token。", + "o1_description": "o1 系列的大型語言模型通過強化學習訓練,能夠執行復雜的推理任務。o1 模型在回答之前會進行思考,產生一長串內部思維鏈,然後再回應使用者。", + "no_permission_to_update_description": "你沒有權限更新。請聯繫管理員。管理員的設定方式為在組態檔 config.json 中的 admin_list 中添加使用者名。" +} diff --git a/modules/utils.py b/modules/utils.py index 9a17c3d1..da24c24f 100644 --- a/modules/utils.py +++ b/modules/utils.py @@ -1,36 +1,40 @@ # -*- coding:utf-8 -*- from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Tuple, Type -from enum import Enum -import logging -import commentjson as json -import os -import datetime + import csv -import threading -import requests +import datetime +import getpass +import hashlib import hmac import html -import hashlib +import logging +import os +import threading +from enum import Enum +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Tuple, Type +import colorama +import commentjson as json import gradio as gr +import pandas as pd import regex as re -import getpass -from pypinyin import lazy_pinyin +import requests import tiktoken from markdown import markdown from pygments import highlight -from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter -import pandas as pd -import colorama +from pygments.lexers import get_lexer_by_name +from pypinyin import lazy_pinyin +from modules.config import (admin_list, hide_history_when_not_logged_in, + retrieve_proxy) from modules.presets import * + from . import shared -from modules.config import retrieve_proxy, hide_history_when_not_logged_in, admin_list if TYPE_CHECKING: from typing import TypedDict + from .models.base_model import BaseLLMModel class DataframeData(TypedDict): @@ -145,6 +149,7 @@ def set_user_identifier(current_model, *args): def set_single_turn(current_model, *args): current_model.set_single_turn(*args) + def set_streaming(current_model, *args): current_model.set_streaming(*args) @@ -243,38 +248,47 @@ def convert_mdtext(md_text): # deprecated output += ALREADY_CONVERTED_MARK return output + def remove_html_tags(chatbot): def clean_text(text): # Regular expression to match code blocks, including all newlines - code_block_pattern = r'(```[\s\S]*?```)' + code_block_pattern = r"(```[\s\S]*?```)" # Split the text into code blocks and non-code blocks parts = re.split(code_block_pattern, text) cleaned_parts = [] for part in parts: - if part.startswith('```') and part.endswith('```'): + if part.startswith("```") and part.endswith("```"): # This is a code block, keep it exactly as is cleaned_parts.append(part) else: # This is not a code block, remove HTML tags # Remove all HTML tags - cleaned = re.sub(r'<[^>]+>', '', part) + cleaned = re.sub(r"<[^>]+>", "", part) # Remove any remaining HTML entities - cleaned = re.sub(r'&[#\w]+;', '', cleaned) + cleaned = re.sub(r"&[#\w]+;", "", cleaned) cleaned_parts.append(cleaned) # Don't strip here to preserve newlines # Join the cleaned parts back together - return ''.join(cleaned_parts) + return "".join(cleaned_parts) processed = [] for conv in chatbot: - if len(conv) == 2 and (isinstance(conv[0], tuple) or isinstance(conv[0], list)) and len(conv[0]) == 2 and conv[0][1] is None and conv[1] is None: + if ( + len(conv) == 2 + and (isinstance(conv[0], tuple) or isinstance(conv[0], list)) + and len(conv[0]) == 2 + and conv[0][1] is None + and conv[1] is None + ): # This is an image path sublist, keep it as-is processed.append(conv) else: # Apply clean_text to each item in the sublist - processed.append([clean_text(item) if item is not None else None for item in conv]) + processed.append( + [clean_text(item) if item is not None else None for item in conv] + ) return processed @@ -285,9 +299,7 @@ def clip_rawtext(chat_message, need_escape=True): hr_match = re.search(hr_pattern, chat_message, re.DOTALL) message_clipped = chat_message[: hr_match.start()] if hr_match else chat_message # second, avoid agent-prefix being escaped - agent_prefix_pattern = ( - r'(.*?)' - ) + agent_prefix_pattern = r"(.*?)" # agent_matches = re.findall(agent_prefix_pattern, message_clipped) agent_parts = re.split(agent_prefix_pattern, message_clipped, flags=re.DOTALL) final_message = "" @@ -300,7 +312,7 @@ def clip_rawtext(chat_message, need_escape=True): else f'
{part}'
)
else:
- part = part.replace(' data-fancybox="gallery"', '')
+ part = part.replace(' data-fancybox="gallery"', "")
final_message += part
return final_message
@@ -403,6 +415,7 @@ def construct_text(role, text):
def construct_user(text):
return construct_text("user", text)
+
def construct_image(path):
return construct_text("image", path)
@@ -470,25 +483,30 @@ def save_file(filename, model):
# check if history file path matches user_name
# if user access control is not enabled, user_name is empty, don't check
- assert os.path.basename(os.path.dirname(history_file_path)) == model.user_name or model.user_name == ""
+ assert (
+ os.path.basename(os.path.dirname(history_file_path)) == model.user_name
+ or model.user_name == ""
+ )
with open(history_file_path, "w", encoding="utf-8") as f:
json.dump(json_s, f, ensure_ascii=False, indent=4)
save_md_file(history_file_path)
return history_file_path
+
def save_md_file(json_file_path):
with open(json_file_path, "r", encoding="utf-8") as f:
json_data = json.load(f)
md_file_path = json_file_path[:-5] + ".md"
md_s = f"system: \n- {json_data['system']} \n"
- for data in json_data['history']:
+ for data in json_data["history"]:
md_s += f"\n{data['role']}: \n- {data['content']} \n"
with open(md_file_path, "w", encoding="utf8") as f:
f.write(md_s)
+
def sorted_by_pinyin(list):
return sorted(list, key=lambda char: lazy_pinyin(char)[0][0])
@@ -537,7 +555,9 @@ def get_history_names(user_name=""):
else:
user_history_dir = os.path.join(HISTORY_DIR, user_name)
# ensure the user history directory is inside the HISTORY_DIR
- assert os.path.realpath(user_history_dir).startswith(os.path.realpath(HISTORY_DIR))
+ assert os.path.realpath(user_history_dir).startswith(
+ os.path.realpath(HISTORY_DIR)
+ )
history_files = get_file_names_by_last_modified_time(
os.path.join(HISTORY_DIR, user_name)
)
@@ -567,27 +587,31 @@ def init_history_list(user_name="", prepend=None):
def filter_history(user_name, keyword):
history_names = get_history_names(user_name)
try:
- history_names = [name for name in history_names if re.search(keyword, name, timeout=0.01)]
+ history_names = [
+ name for name in history_names if re.search(keyword, name, timeout=0.01)
+ ]
return gr.update(choices=history_names)
except:
return gr.update(choices=history_names)
def load_template(filename, mode=0):
- logging.debug(f"加载模板文件{filename},模式为{mode}(0为返回字典和下拉菜单,1为返回下拉菜单,2为返回字典)")
+ logging.debug(
+ f"加载模板文件{filename},模式为{mode}(0为返回字典和下拉菜单,1为返回下拉菜单,2为返回字典)"
+ )
lines = []
template_file_path = os.path.join(TEMPLATES_DIR, filename)
# check if template_file_path is inside TEMPLATES_DIR
- if not os.path.realpath(template_file_path).startswith(os.path.realpath(TEMPLATES_DIR)):
+ if not os.path.realpath(template_file_path).startswith(
+ os.path.realpath(TEMPLATES_DIR)
+ ):
return "Invalid template file path"
if filename.endswith(".json"):
with open(template_file_path, "r", encoding="utf8") as f:
lines = json.load(f)
lines = [[i["act"], i["prompt"]] for i in lines]
else:
- with open(
- template_file_path, "r", encoding="utf8"
- ) as csvfile:
+ with open(template_file_path, "r", encoding="utf8") as csvfile:
reader = csv.reader(csvfile)
lines = list(reader)
lines = lines[1:]
@@ -612,7 +636,9 @@ def get_template_dropdown():
def get_template_content(templates, selection, original_system_prompt):
- logging.debug(f"应用模板中,选择为{selection},原始系统提示为{original_system_prompt}")
+ logging.debug(
+ f"应用模板中,选择为{selection},原始系统提示为{original_system_prompt}"
+ )
try:
return templates[selection]
except:
@@ -699,7 +725,9 @@ def fetch_ip():
SERVER_GEO_IP_MSG = i18n("您的IP区域:未知。")
else:
SERVER_GEO_IP_MSG = (
- i18n("获取IP地理位置失败。原因:") + f"{data['reason']}" + i18n("。你仍然可以使用聊天功能。")
+ i18n("获取IP地理位置失败。原因:")
+ + f"{data['reason']}"
+ + i18n("。你仍然可以使用聊天功能。")
)
else:
country = data["country_name"]
@@ -1013,11 +1041,25 @@ class SetupWizard:
def __init__(self, file_path="config.json") -> None:
self.config = {}
self.file_path = file_path
- language = input('请问是否需要更改语言?可选:"auto", "zh_CN", "en_US", "ja_JP", "ko_KR", "sv_SE", "ru_RU", "vi_VN"\nChange the language? Options: "auto", "zh_CN", "en_US", "ja_JP", "ko_KR", "sv_SE", "ru_RU", "vi_VN"\n目前正在使用中文(zh_CN)\nCurrently using Chinese(zh_CN)\n如果需要,请输入你想用的语言的代码:\nIf you need, please enter the code of the language you want to use:')
- if language.lower() in ["auto", "zh_cn", "en_us", "ja_jp", "ko_kr", "sv_se", "ru_ru", "vi_vn"]:
+ language = input(
+ '请问是否需要更改语言?可选:"auto", "zh_CN", "zh_TW", "en_US", "ja_JP", "ko_KR", "sv_SE", "ru_RU", "vi_VN"\nChange the language? Options: "auto", "zh_CN", "zh_TW", "en_US", "ja_JP", "ko_KR", "sv_SE", "ru_RU", "vi_VN"\n目前正在使用中文(zh_CN)\nCurrently using Chinese(zh_CN)\n如果需要,请输入你想用的语言的代码:\nIf you need, please enter the code of the language you want to use:'
+ )
+ if language.lower() in [
+ "auto",
+ "zh_cn",
+ "zh_tw",
+ "en_us",
+ "ja_jp",
+ "ko_kr",
+ "sv_se",
+ "ru_ru",
+ "vi_vn",
+ ]:
i18n.change_language(language)
else:
- print("你没有输入有效的语言代码,将使用默认语言中文(zh_CN)\nYou did not enter a valid language code, the default language Chinese(zh_CN) will be used.")
+ print(
+ "你没有输入有效的语言代码,将使用默认语言中文(zh_CN)\nYou did not enter a valid language code, the default language Chinese(zh_CN) will be used."
+ )
print(
i18n("正在进行首次设置,请按照提示进行配置,配置将会被保存在")
+ colorama.Fore.GREEN
@@ -1037,7 +1079,9 @@ def __init__(self, file_path="config.json") -> None:
)
print(
colorama.Back.GREEN
- + i18n("现在开始进行交互式配置。碰到不知道该怎么办的设置项时,请直接按回车键跳过,程序会自动选择合适的默认值。")
+ + i18n(
+ "现在开始进行交互式配置。碰到不知道该怎么办的设置项时,请直接按回车键跳过,程序会自动选择合适的默认值。"
+ )
+ colorama.Style.RESET_ALL
)
@@ -1076,7 +1120,8 @@ def set(self, config_items: List[ConfigItem], prompt: str):
config_value = []
while True:
config_value_item = input(
- generate_prompt_string(config_item) + i18n(",输入空行结束:")
+ generate_prompt_string(config_item)
+ + i18n(",输入空行结束:")
)
if config_value_item == "":
break
@@ -1103,7 +1148,13 @@ def set(self, config_items: List[ConfigItem], prompt: str):
def set_users(self):
# 询问设置用户账户
- choice = input(colorama.Fore.YELLOW + i18n("是否设置用户账户?设置后,用户需要登陆才可访问。输入 Yes(y) 或 No(n),默认No:") + colorama.Style.RESET_ALL)
+ choice = input(
+ colorama.Fore.YELLOW
+ + i18n(
+ "是否设置用户账户?设置后,用户需要登陆才可访问。输入 Yes(y) 或 No(n),默认No:"
+ )
+ + colorama.Style.RESET_ALL
+ )
if choice.lower() in ["y", "yes"]:
users = []
while True:
@@ -1174,7 +1225,9 @@ def setup_wizard():
"是否在本地编制知识库索引?如果是,可以在使用本地模型时离线使用知识库,否则使用OpenAI服务来编制索引(需要OpenAI API Key)。请确保你的电脑有至少16GB内存。本地索引模型需要从互联网下载。",
)
print(
- colorama.Back.GREEN + i18n("现在开始设置其他在线模型的API Key") + colorama.Style.RESET_ALL
+ colorama.Back.GREEN
+ + i18n("现在开始设置其他在线模型的API Key")
+ + colorama.Style.RESET_ALL
)
# Google Palm
wizard.set(
@@ -1209,7 +1262,9 @@ def setup_wizard():
[
ConfigItem(
"midjourney_proxy_api_base",
- i18n("你的") + "https://github.com/novicezk/midjourney-proxy" + i18n("代理地址"),
+ i18n("你的")
+ + "https://github.com/novicezk/midjourney-proxy"
+ + i18n("代理地址"),
type=ConfigType.String,
),
ConfigItem(
@@ -1238,7 +1293,9 @@ def setup_wizard():
ConfigItem(
"spark_api_secret", "讯飞星火 API Secret", type=ConfigType.Password
),
- ConfigItem("spark_api_key", "讯飞星火 API Key", type=ConfigType.Password),
+ ConfigItem(
+ "spark_api_key", "讯飞星火 API Key", type=ConfigType.Password
+ ),
],
"是否设置讯飞星火?如果设置,软件启动时会自动加载该API Key,无需在 UI 中手动输入。如果不设置,将无法使用 讯飞星火 模型。请注意不要搞混App ID和API Secret。",
)
@@ -1255,10 +1312,14 @@ def setup_wizard():
wizard.set(
[
ConfigItem(
- "ernie_api_key", "百度云中的文心一言 API Key", type=ConfigType.Password
+ "ernie_api_key",
+ "百度云中的文心一言 API Key",
+ type=ConfigType.Password,
),
ConfigItem(
- "ernie_secret_key", "百度云中的文心一言 Secret Key", type=ConfigType.Password
+ "ernie_secret_key",
+ "百度云中的文心一言 Secret Key",
+ type=ConfigType.Password,
),
],
"是否设置文心一言?如果设置,软件启动时会自动加载该API Key,无需在 UI 中手动输入。如果不设置,将无法使用 文心一言 模型。",
@@ -1300,7 +1361,9 @@ def setup_wizard():
"是否设置 Azure OpenAI?如果设置,软件启动时会自动加载该API Key,无需在 UI 中手动输入。如果不设置,将无法使用 Azure OpenAI 模型。",
)
print(
- colorama.Back.GREEN + i18n("现在开始进行软件功能设置") + colorama.Style.RESET_ALL
+ colorama.Back.GREEN
+ + i18n("现在开始进行软件功能设置")
+ + colorama.Style.RESET_ALL
)
# 用户列表
wizard.set_users()
@@ -1319,7 +1382,10 @@ def setup_wizard():
wizard.set(
[
ConfigItem(
- "check_update", "是否启用检查更新", type=ConfigType.Bool, default=True
+ "check_update",
+ "是否启用检查更新",
+ type=ConfigType.Bool,
+ default=True,
)
],
"是否启用检查更新?如果设置,软件启动时会自动检查更新。",
@@ -1493,20 +1559,34 @@ def setup_wizard():
"是否通过gradio分享?可以通过公网访问。",
)
wizard.save()
- print(colorama.Back.GREEN + i18n("设置完成。现在请重启本程序。") + colorama.Style.RESET_ALL)
+ print(
+ colorama.Back.GREEN
+ + i18n("设置完成。现在请重启本程序。")
+ + colorama.Style.RESET_ALL
+ )
exit()
def reboot_chuanhu():
import sys
+
print(colorama.Back.GREEN + i18n("正在尝试重启...") + colorama.Style.RESET_ALL)
os.execl(sys.executable, sys.executable, *sys.argv)
def setPlaceholder(model_name: str | None = "", model: BaseLLMModel | None = None):
from .webui import get_html
+
logo_class, slogan_class, question_class = "", "", ""
- model_logo, model_logo_round, model_slogan, model_question_1, model_question_2, model_question_3, model_question_4 = "", "", "", "", "", "", ""
+ (
+ model_logo,
+ model_logo_round,
+ model_slogan,
+ model_question_1,
+ model_question_2,
+ model_question_3,
+ model_question_4,
+ ) = ("", "", "", "", "", "", "")
if model is None:
try:
@@ -1522,10 +1602,18 @@ def setPlaceholder(model_name: str | None = "", model: BaseLLMModel | None = Non
except:
slogan_class = "hideK"
try:
- model_question_1 = i18n(MODEL_METADATA[model_name]["placeholder"]["question_1"])
- model_question_2 = i18n(MODEL_METADATA[model_name]["placeholder"]["question_2"])
- model_question_3 = i18n(MODEL_METADATA[model_name]["placeholder"]["question_3"])
- model_question_4 = i18n(MODEL_METADATA[model_name]["placeholder"]["question_4"])
+ model_question_1 = i18n(
+ MODEL_METADATA[model_name]["placeholder"]["question_1"]
+ )
+ model_question_2 = i18n(
+ MODEL_METADATA[model_name]["placeholder"]["question_2"]
+ )
+ model_question_3 = i18n(
+ MODEL_METADATA[model_name]["placeholder"]["question_3"]
+ )
+ model_question_4 = i18n(
+ MODEL_METADATA[model_name]["placeholder"]["question_4"]
+ )
except:
question_class = "hideK"
else:
@@ -1553,19 +1641,27 @@ def setPlaceholder(model_name: str | None = "", model: BaseLLMModel | None = Non
return ""
else:
# 除非明确指定为 squared 或 false 等,否则默认为圆角
- if model_logo_round.lower().strip() not in ["square", "squared", "false", "0", "no", "off"]:
+ if model_logo_round.lower().strip() not in [
+ "square",
+ "squared",
+ "false",
+ "0",
+ "no",
+ "off",
+ ]:
logo_class += " rounded"
return get_html("chatbot_placeholder.html").format(
- chatbot_ph_logo = model_logo,
- chatbot_ph_slogan = model_slogan,
- chatbot_ph_question_1 = model_question_1,
- chatbot_ph_question_2 = model_question_2,
- chatbot_ph_question_3 = model_question_3,
- chatbot_ph_question_4 = model_question_4,
- chatbot_ph_logo_class = logo_class,
- chatbot_ph_slogan_class = slogan_class,
- chatbot_ph_question_class = question_class
+ chatbot_ph_logo=model_logo,
+ chatbot_ph_slogan=model_slogan,
+ chatbot_ph_question_1=model_question_1,
+ chatbot_ph_question_2=model_question_2,
+ chatbot_ph_question_3=model_question_3,
+ chatbot_ph_question_4=model_question_4,
+ chatbot_ph_logo_class=logo_class,
+ chatbot_ph_slogan_class=slogan_class,
+ chatbot_ph_question_class=question_class,
)
+
def download_file(path):
print(path)
diff --git a/run_Linux.sh b/run_Linux.sh
old mode 100644
new mode 100755
diff --git a/run_Windows.bat b/run_Windows.bat
old mode 100644
new mode 100755
diff --git a/run_macOS.command b/run_macOS.command
old mode 100644
new mode 100755