voice input [test mode]: init
This commit is contained in:
parent
05a85cee1e
commit
40b05641fe
@ -27,7 +27,6 @@ repos:
|
||||
- id: check-added-large-files
|
||||
- id: detect-private-key
|
||||
- id: requirements-txt-fixer
|
||||
- id: debug-statements
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.12.0
|
||||
@ -52,10 +51,3 @@ repos:
|
||||
- id: python-check-blanket-noqa
|
||||
- id: python-use-type-annotations
|
||||
- id: text-unicode-replacement-char
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.991
|
||||
hooks:
|
||||
- id: mypy
|
||||
additional_dependencies: [ types-PyYAML==6.0.10, types_requests==2.28.8, types-ujson==5.5.0 ]
|
||||
args: [ --ignore-missing-imports, --warn-no-return, --warn-redundant-casts, --disallow-incomplete-defs ]
|
||||
|
@ -1,3 +1,6 @@
|
||||
[global]
|
||||
showWarningOnDirectExecution = false
|
||||
|
||||
[theme]
|
||||
primaryColor = "#0E8388"
|
||||
backgroundColor = "#2C3333"
|
||||
|
BIN
assets/icons/rec_on.gif
Normal file
BIN
assets/icons/rec_on.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 331 KiB |
56
chat.py
56
chat.py
@ -10,17 +10,19 @@ from src.utils.conversation import get_user_input, show_chat_buttons, show_conve
|
||||
import streamlit as st
|
||||
|
||||
# --- PATH SETTINGS ---
|
||||
current_dir = Path(__file__).parent if "__file__" in locals() else Path.cwd()
|
||||
css_file = current_dir / "src/styles/.css"
|
||||
assets_dir = current_dir / "assets"
|
||||
icons_dir = assets_dir / "icons"
|
||||
img_dir = assets_dir / "img"
|
||||
tg_svg = icons_dir / "tg.svg"
|
||||
current_dir: Path = Path(__file__).parent if "__file__" in locals() else Path.cwd()
|
||||
css_file: Path = current_dir / "src/styles/.css"
|
||||
assets_dir: Path = current_dir / "assets"
|
||||
icons_dir: Path = assets_dir / "icons"
|
||||
img_dir: Path = assets_dir / "img"
|
||||
tg_svg: Path = icons_dir / "tg.svg"
|
||||
|
||||
# --- GENERAL SETTINGS ---
|
||||
PAGE_TITLE = "AI Talks"
|
||||
PAGE_ICON = "🤖"
|
||||
AI_MODEL_OPTIONS = [
|
||||
PAGE_TITLE: str = "AI Talks"
|
||||
PAGE_ICON: str = "🤖"
|
||||
LANG_EN: str = "En"
|
||||
LANG_RU: str = "Ru"
|
||||
AI_MODEL_OPTIONS: list[str] = [
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-4",
|
||||
"gpt-4-32k",
|
||||
@ -35,7 +37,7 @@ with open(css_file) as f:
|
||||
|
||||
selected_lang = option_menu(
|
||||
menu_title=None,
|
||||
options=["En", "Ru", ],
|
||||
options=[LANG_EN, LANG_RU, ],
|
||||
icons=["globe2", "globe"],
|
||||
menu_icon="cast",
|
||||
default_index=0,
|
||||
@ -44,36 +46,44 @@ selected_lang = option_menu(
|
||||
)
|
||||
|
||||
# Storing The Context
|
||||
if "locale" not in st.session_state:
|
||||
st.session_state.locale = en
|
||||
if "generated" not in st.session_state:
|
||||
st.session_state["generated"] = []
|
||||
st.session_state.generated = []
|
||||
if "past" not in st.session_state:
|
||||
st.session_state["past"] = []
|
||||
st.session_state.past = []
|
||||
if "messages" not in st.session_state:
|
||||
st.session_state["messages"] = []
|
||||
st.session_state.messages = []
|
||||
if "user_text" not in st.session_state:
|
||||
st.session_state["user_text"] = ""
|
||||
st.session_state.user_text = ""
|
||||
if "input_kind" not in st.session_state:
|
||||
st.session_state.input_kind = st.session_state.locale.input_kind_1
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if st.session_state.user_text:
|
||||
show_conversation()
|
||||
st.session_state.user_text = ""
|
||||
|
||||
c1, c2, c3 = st.columns(3)
|
||||
c1, c2 = st.columns(2)
|
||||
with c1, c2:
|
||||
c1.selectbox(label=st.session_state.locale.select_placeholder1, key="model", options=AI_MODEL_OPTIONS)
|
||||
role_kind = c2.radio(
|
||||
st.session_state.input_kind = c2.radio(
|
||||
label=st.session_state.locale.input_kind,
|
||||
options=(st.session_state.locale.input_kind_1, st.session_state.locale.input_kind_2),
|
||||
horizontal=True,
|
||||
)
|
||||
role_kind = c1.radio(
|
||||
label=st.session_state.locale.radio_placeholder,
|
||||
options=(st.session_state.locale.radio_text1, st.session_state.locale.radio_text2),
|
||||
horizontal=True,
|
||||
)
|
||||
match role_kind:
|
||||
case st.session_state.locale.radio_text1:
|
||||
c3.selectbox(label=st.session_state.locale.select_placeholder2, key="role",
|
||||
c2.selectbox(label=st.session_state.locale.select_placeholder2, key="role",
|
||||
options=st.session_state.locale.ai_role_options)
|
||||
case st.session_state.locale.radio_text2:
|
||||
c3.text_input(label=st.session_state.locale.select_placeholder3, key="role")
|
||||
c2.text_input(label=st.session_state.locale.select_placeholder3, key="role")
|
||||
|
||||
if st.session_state.user_text:
|
||||
show_conversation()
|
||||
st.session_state.user_text = ""
|
||||
get_user_input()
|
||||
show_chat_buttons()
|
||||
|
||||
@ -85,7 +95,7 @@ if __name__ == "__main__":
|
||||
case "Ru":
|
||||
st.session_state.locale = ru
|
||||
case _:
|
||||
locale = en
|
||||
st.session_state.locale = en
|
||||
st.markdown(f"<h1 style='text-align: center;'>{st.session_state.locale.title}</h1>", unsafe_allow_html=True)
|
||||
st.markdown("---")
|
||||
main()
|
||||
|
@ -1,8 +1,10 @@
|
||||
streamlit==1.20.0
|
||||
streamlit==1.21.0
|
||||
streamlit-chat==0.0.2.2
|
||||
streamlit_option_menu==0.3.2
|
||||
openai==0.27.2
|
||||
openai==0.27.4
|
||||
gtts==2.3.1
|
||||
pip==23.0.1
|
||||
bokeh==2.4.2
|
||||
streamlit-bokeh-events==0.1.2
|
||||
watchdog==3.0.0
|
||||
|
||||
|
@ -12,7 +12,7 @@ import streamlit as st
|
||||
US_AG = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36"
|
||||
|
||||
|
||||
class Chatbot:
|
||||
class BardChat:
|
||||
"""
|
||||
A class to interact with Google Bard.
|
||||
Parameters
|
||||
|
@ -3,20 +3,34 @@ from openai.error import InvalidRequestError, OpenAIError
|
||||
from requests.exceptions import TooManyRedirects
|
||||
from streamlit_chat import message
|
||||
|
||||
from src.utils.agi.bard import Chatbot
|
||||
from src.utils.agi.bard import BardChat
|
||||
from src.utils.agi.chat_gpt import chat_gpt_request
|
||||
from src.utils.stt import show_voice_input
|
||||
from src.utils.tts import show_player
|
||||
|
||||
|
||||
def clear_chat() -> None:
|
||||
st.session_state["generated"] = []
|
||||
st.session_state["past"] = []
|
||||
st.session_state["messages"] = []
|
||||
st.session_state["user_text"] = ""
|
||||
st.session_state.generated = []
|
||||
st.session_state.past = []
|
||||
st.session_state.messages = []
|
||||
st.session_state.user_text = ""
|
||||
|
||||
|
||||
def show_text_input() -> None:
|
||||
st.text_area(label=st.session_state.locale.chat_placeholder, value=st.session_state.user_text, key="user_text")
|
||||
|
||||
|
||||
def get_user_input():
|
||||
st.text_area(label=st.session_state.locale.chat_placeholder, value=st.session_state.user_text, key="user_text")
|
||||
match st.session_state.input_kind:
|
||||
case st.session_state.locale.input_kind_1:
|
||||
clear_chat()
|
||||
show_text_input()
|
||||
case st.session_state.locale.input_kind_2:
|
||||
clear_chat()
|
||||
show_voice_input()
|
||||
show_text_input()
|
||||
case _:
|
||||
show_text_input()
|
||||
|
||||
|
||||
def show_chat_buttons() -> None:
|
||||
@ -39,7 +53,7 @@ def show_chat(ai_content: str, user_text: str) -> None:
|
||||
st.session_state.generated.append(ai_content)
|
||||
if st.session_state.generated:
|
||||
for i in range(len(st.session_state.generated)):
|
||||
message(st.session_state["past"][i], is_user=True, key=str(i) + "_user", avatar_style="micah")
|
||||
message(st.session_state.past[i], is_user=True, key=str(i) + "_user", avatar_style="micah")
|
||||
message("", key=str(i))
|
||||
st.markdown(st.session_state.generated[i])
|
||||
|
||||
@ -67,7 +81,7 @@ def chat_gpt_conversation() -> None:
|
||||
|
||||
def bard_conversation() -> None:
|
||||
try:
|
||||
bard = Chatbot(st.secrets.api_credentials.bard_session)
|
||||
bard = BardChat(st.secrets.api_credentials.bard_session)
|
||||
ai_content = bard.ask(st.session_state.user_text)
|
||||
st.warning(ai_content.get("content"))
|
||||
except (TooManyRedirects, AttributeError) as err:
|
||||
|
@ -17,6 +17,10 @@ class Locale:
|
||||
chat_run_btn: str
|
||||
chat_clear_btn: str
|
||||
chat_save_btn: str
|
||||
speak_btn: str
|
||||
input_kind: str
|
||||
input_kind_1: str
|
||||
input_kind_2: str
|
||||
select_placeholder1: str
|
||||
select_placeholder2: str
|
||||
select_placeholder3: str
|
||||
@ -44,9 +48,13 @@ class EnLocale(Locale):
|
||||
donates1: str = "Russia"
|
||||
donates2: str = "World"
|
||||
chat_placeholder: str = "Start Your Conversation With AI:"
|
||||
chat_run_btn: str = "Run"
|
||||
chat_run_btn: str = "Ask"
|
||||
chat_clear_btn: str = "Clear"
|
||||
chat_save_btn: str = "Save"
|
||||
speak_btn: str = "Push to Speak"
|
||||
input_kind: str = "Input Kind"
|
||||
input_kind_1: str = "Text"
|
||||
input_kind_2: str = "Voice [test mode]"
|
||||
select_placeholder1: str = "Select Model"
|
||||
select_placeholder2: str = "Select Role"
|
||||
select_placeholder3: str = "Create Role"
|
||||
@ -83,9 +91,13 @@ class RuLocale(Locale):
|
||||
donates1: str = "Россия"
|
||||
donates2: str = "Остальной Мир"
|
||||
chat_placeholder: str = "Начните Вашу Беседу с ИИ:"
|
||||
chat_run_btn: str = "Запустить"
|
||||
chat_run_btn: str = "Спросить"
|
||||
chat_clear_btn: str = "Очистить"
|
||||
chat_save_btn: str = "Сохранить"
|
||||
speak_btn: str = "Нажмите и Говорите"
|
||||
input_kind: str = "Вид ввода"
|
||||
input_kind_1: str = "Текст"
|
||||
input_kind_2: str = "Голос [тестовый режим]"
|
||||
select_placeholder1: str = "Выберите Модель"
|
||||
select_placeholder2: str = "Выберите Роль"
|
||||
select_placeholder3: str = "Создайте Роль"
|
||||
|
@ -0,0 +1,83 @@
|
||||
import streamlit as st
|
||||
from bokeh.models import CustomJS
|
||||
from bokeh.models.widgets import Button
|
||||
from streamlit_bokeh_events import streamlit_bokeh_events
|
||||
|
||||
REC_GIF = "assets/icons/rec_on.gif"
|
||||
|
||||
|
||||
def get_js_code(lang: str) -> str:
|
||||
return """
|
||||
var value = "";
|
||||
var rand = 0;
|
||||
var recognition = new webkitSpeechRecognition();
|
||||
recognition.continuous = false;
|
||||
recognition.interimResults = true;
|
||||
""" + f"recognition.lang = '{lang}';" + """
|
||||
document.dispatchEvent(new CustomEvent("GET_ONREC", {detail: 'start'}));
|
||||
|
||||
recognition.onspeechstart = function () {
|
||||
document.dispatchEvent(new CustomEvent("GET_ONREC", {detail: 'running'}));
|
||||
}
|
||||
recognition.onsoundend = function () {
|
||||
document.dispatchEvent(new CustomEvent("GET_ONREC", {detail: 'stop'}));
|
||||
}
|
||||
recognition.onresult = function (e) {
|
||||
var value2 = "";
|
||||
for (var i = e.resultIndex; i < e.results.length; ++i) {
|
||||
if (e.results[i].isFinal) {
|
||||
value += e.results[i][0].transcript;
|
||||
rand = Math.random();
|
||||
|
||||
} else {
|
||||
value2 += e.results[i][0].transcript;
|
||||
}
|
||||
}
|
||||
document.dispatchEvent(new CustomEvent("GET_TEXT", {detail: {t:value, s:rand}}));
|
||||
document.dispatchEvent(new CustomEvent("GET_INTRM", {detail: value2}));
|
||||
|
||||
}
|
||||
recognition.onerror = function(e) {
|
||||
document.dispatchEvent(new CustomEvent("GET_ONREC", {detail: 'stop'}));
|
||||
}
|
||||
recognition.start();
|
||||
"""
|
||||
|
||||
|
||||
def show_speak_btn() -> Button:
|
||||
stt_button = Button(label=st.session_state.locale.speak_btn, button_type="success", width=100)
|
||||
stt_button.js_on_event("button_click", CustomJS(code=get_js_code(st.session_state.locale.lang_code)))
|
||||
return stt_button
|
||||
|
||||
|
||||
def get_bokeh_result() -> dict:
|
||||
stt_button = show_speak_btn()
|
||||
return streamlit_bokeh_events(
|
||||
bokeh_plot=stt_button,
|
||||
events="GET_TEXT,GET_ONREC,GET_INTRM",
|
||||
key="listen",
|
||||
refresh_on_update=False,
|
||||
override_height=75,
|
||||
debounce_time=0,
|
||||
)
|
||||
|
||||
|
||||
def show_voice_input() -> None:
|
||||
if "input" not in st.session_state:
|
||||
st.session_state.input = {"text": "", "session": 0}
|
||||
result = get_bokeh_result()
|
||||
if result:
|
||||
if "GET_TEXT" in result:
|
||||
if result.get("GET_TEXT")["t"] != "" and result.get("GET_TEXT")["s"] != st.session_state.input["session"]:
|
||||
st.session_state.input["text"] = result.get("GET_TEXT")["t"]
|
||||
st.session_state.input["session"] = result.get("GET_TEXT")["s"]
|
||||
if "GET_ONREC" in result:
|
||||
placeholder = st.container()
|
||||
if result.get("GET_ONREC") == "start":
|
||||
placeholder.image(REC_GIF)
|
||||
st.session_state.input["text"] = ""
|
||||
elif result.get("GET_ONREC") == "running":
|
||||
placeholder.image(REC_GIF)
|
||||
elif result.get("GET_ONREC") == "stop":
|
||||
if st.session_state.input["text"] != "":
|
||||
st.session_state.user_text = st.session_state.input["text"]
|
Loading…
Reference in New Issue
Block a user