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: check-added-large-files
|
||||||
- id: detect-private-key
|
- id: detect-private-key
|
||||||
- id: requirements-txt-fixer
|
- id: requirements-txt-fixer
|
||||||
- id: debug-statements
|
|
||||||
|
|
||||||
- repo: https://github.com/pycqa/isort
|
- repo: https://github.com/pycqa/isort
|
||||||
rev: 5.12.0
|
rev: 5.12.0
|
||||||
@ -52,10 +51,3 @@ repos:
|
|||||||
- id: python-check-blanket-noqa
|
- id: python-check-blanket-noqa
|
||||||
- id: python-use-type-annotations
|
- id: python-use-type-annotations
|
||||||
- id: text-unicode-replacement-char
|
- 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]
|
[theme]
|
||||||
primaryColor = "#0E8388"
|
primaryColor = "#0E8388"
|
||||||
backgroundColor = "#2C3333"
|
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
|
import streamlit as st
|
||||||
|
|
||||||
# --- PATH SETTINGS ---
|
# --- PATH SETTINGS ---
|
||||||
current_dir = Path(__file__).parent if "__file__" in locals() else Path.cwd()
|
current_dir: Path = Path(__file__).parent if "__file__" in locals() else Path.cwd()
|
||||||
css_file = current_dir / "src/styles/.css"
|
css_file: Path = current_dir / "src/styles/.css"
|
||||||
assets_dir = current_dir / "assets"
|
assets_dir: Path = current_dir / "assets"
|
||||||
icons_dir = assets_dir / "icons"
|
icons_dir: Path = assets_dir / "icons"
|
||||||
img_dir = assets_dir / "img"
|
img_dir: Path = assets_dir / "img"
|
||||||
tg_svg = icons_dir / "tg.svg"
|
tg_svg: Path = icons_dir / "tg.svg"
|
||||||
|
|
||||||
# --- GENERAL SETTINGS ---
|
# --- GENERAL SETTINGS ---
|
||||||
PAGE_TITLE = "AI Talks"
|
PAGE_TITLE: str = "AI Talks"
|
||||||
PAGE_ICON = "🤖"
|
PAGE_ICON: str = "🤖"
|
||||||
AI_MODEL_OPTIONS = [
|
LANG_EN: str = "En"
|
||||||
|
LANG_RU: str = "Ru"
|
||||||
|
AI_MODEL_OPTIONS: list[str] = [
|
||||||
"gpt-3.5-turbo",
|
"gpt-3.5-turbo",
|
||||||
"gpt-4",
|
"gpt-4",
|
||||||
"gpt-4-32k",
|
"gpt-4-32k",
|
||||||
@ -35,7 +37,7 @@ with open(css_file) as f:
|
|||||||
|
|
||||||
selected_lang = option_menu(
|
selected_lang = option_menu(
|
||||||
menu_title=None,
|
menu_title=None,
|
||||||
options=["En", "Ru", ],
|
options=[LANG_EN, LANG_RU, ],
|
||||||
icons=["globe2", "globe"],
|
icons=["globe2", "globe"],
|
||||||
menu_icon="cast",
|
menu_icon="cast",
|
||||||
default_index=0,
|
default_index=0,
|
||||||
@ -44,36 +46,44 @@ selected_lang = option_menu(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Storing The Context
|
# Storing The Context
|
||||||
|
if "locale" not in st.session_state:
|
||||||
|
st.session_state.locale = en
|
||||||
if "generated" not in st.session_state:
|
if "generated" not in st.session_state:
|
||||||
st.session_state["generated"] = []
|
st.session_state.generated = []
|
||||||
if "past" not in st.session_state:
|
if "past" not in st.session_state:
|
||||||
st.session_state["past"] = []
|
st.session_state.past = []
|
||||||
if "messages" not in st.session_state:
|
if "messages" not in st.session_state:
|
||||||
st.session_state["messages"] = []
|
st.session_state.messages = []
|
||||||
if "user_text" not in st.session_state:
|
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:
|
def main() -> None:
|
||||||
if st.session_state.user_text:
|
c1, c2 = st.columns(2)
|
||||||
show_conversation()
|
|
||||||
st.session_state.user_text = ""
|
|
||||||
|
|
||||||
c1, c2, c3 = st.columns(3)
|
|
||||||
with c1, c2:
|
with c1, c2:
|
||||||
c1.selectbox(label=st.session_state.locale.select_placeholder1, key="model", options=AI_MODEL_OPTIONS)
|
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,
|
label=st.session_state.locale.radio_placeholder,
|
||||||
options=(st.session_state.locale.radio_text1, st.session_state.locale.radio_text2),
|
options=(st.session_state.locale.radio_text1, st.session_state.locale.radio_text2),
|
||||||
horizontal=True,
|
horizontal=True,
|
||||||
)
|
)
|
||||||
match role_kind:
|
match role_kind:
|
||||||
case st.session_state.locale.radio_text1:
|
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)
|
options=st.session_state.locale.ai_role_options)
|
||||||
case st.session_state.locale.radio_text2:
|
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()
|
get_user_input()
|
||||||
show_chat_buttons()
|
show_chat_buttons()
|
||||||
|
|
||||||
@ -85,7 +95,7 @@ if __name__ == "__main__":
|
|||||||
case "Ru":
|
case "Ru":
|
||||||
st.session_state.locale = ru
|
st.session_state.locale = ru
|
||||||
case _:
|
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(f"<h1 style='text-align: center;'>{st.session_state.locale.title}</h1>", unsafe_allow_html=True)
|
||||||
st.markdown("---")
|
st.markdown("---")
|
||||||
main()
|
main()
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
streamlit==1.20.0
|
streamlit==1.21.0
|
||||||
streamlit-chat==0.0.2.2
|
streamlit-chat==0.0.2.2
|
||||||
streamlit_option_menu==0.3.2
|
streamlit_option_menu==0.3.2
|
||||||
openai==0.27.2
|
openai==0.27.4
|
||||||
gtts==2.3.1
|
gtts==2.3.1
|
||||||
pip==23.0.1
|
pip==23.0.1
|
||||||
|
bokeh==2.4.2
|
||||||
|
streamlit-bokeh-events==0.1.2
|
||||||
watchdog==3.0.0
|
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"
|
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.
|
A class to interact with Google Bard.
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -3,20 +3,34 @@ from openai.error import InvalidRequestError, OpenAIError
|
|||||||
from requests.exceptions import TooManyRedirects
|
from requests.exceptions import TooManyRedirects
|
||||||
from streamlit_chat import message
|
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.agi.chat_gpt import chat_gpt_request
|
||||||
|
from src.utils.stt import show_voice_input
|
||||||
from src.utils.tts import show_player
|
from src.utils.tts import show_player
|
||||||
|
|
||||||
|
|
||||||
def clear_chat() -> None:
|
def clear_chat() -> None:
|
||||||
st.session_state["generated"] = []
|
st.session_state.generated = []
|
||||||
st.session_state["past"] = []
|
st.session_state.past = []
|
||||||
st.session_state["messages"] = []
|
st.session_state.messages = []
|
||||||
st.session_state["user_text"] = ""
|
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():
|
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:
|
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)
|
st.session_state.generated.append(ai_content)
|
||||||
if st.session_state.generated:
|
if st.session_state.generated:
|
||||||
for i in range(len(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))
|
message("", key=str(i))
|
||||||
st.markdown(st.session_state.generated[i])
|
st.markdown(st.session_state.generated[i])
|
||||||
|
|
||||||
@ -67,7 +81,7 @@ def chat_gpt_conversation() -> None:
|
|||||||
|
|
||||||
def bard_conversation() -> None:
|
def bard_conversation() -> None:
|
||||||
try:
|
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)
|
ai_content = bard.ask(st.session_state.user_text)
|
||||||
st.warning(ai_content.get("content"))
|
st.warning(ai_content.get("content"))
|
||||||
except (TooManyRedirects, AttributeError) as err:
|
except (TooManyRedirects, AttributeError) as err:
|
||||||
|
@ -17,6 +17,10 @@ class Locale:
|
|||||||
chat_run_btn: str
|
chat_run_btn: str
|
||||||
chat_clear_btn: str
|
chat_clear_btn: str
|
||||||
chat_save_btn: str
|
chat_save_btn: str
|
||||||
|
speak_btn: str
|
||||||
|
input_kind: str
|
||||||
|
input_kind_1: str
|
||||||
|
input_kind_2: str
|
||||||
select_placeholder1: str
|
select_placeholder1: str
|
||||||
select_placeholder2: str
|
select_placeholder2: str
|
||||||
select_placeholder3: str
|
select_placeholder3: str
|
||||||
@ -44,9 +48,13 @@ class EnLocale(Locale):
|
|||||||
donates1: str = "Russia"
|
donates1: str = "Russia"
|
||||||
donates2: str = "World"
|
donates2: str = "World"
|
||||||
chat_placeholder: str = "Start Your Conversation With AI:"
|
chat_placeholder: str = "Start Your Conversation With AI:"
|
||||||
chat_run_btn: str = "Run"
|
chat_run_btn: str = "Ask"
|
||||||
chat_clear_btn: str = "Clear"
|
chat_clear_btn: str = "Clear"
|
||||||
chat_save_btn: str = "Save"
|
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_placeholder1: str = "Select Model"
|
||||||
select_placeholder2: str = "Select Role"
|
select_placeholder2: str = "Select Role"
|
||||||
select_placeholder3: str = "Create Role"
|
select_placeholder3: str = "Create Role"
|
||||||
@ -83,9 +91,13 @@ class RuLocale(Locale):
|
|||||||
donates1: str = "Россия"
|
donates1: str = "Россия"
|
||||||
donates2: str = "Остальной Мир"
|
donates2: str = "Остальной Мир"
|
||||||
chat_placeholder: str = "Начните Вашу Беседу с ИИ:"
|
chat_placeholder: str = "Начните Вашу Беседу с ИИ:"
|
||||||
chat_run_btn: str = "Запустить"
|
chat_run_btn: str = "Спросить"
|
||||||
chat_clear_btn: str = "Очистить"
|
chat_clear_btn: str = "Очистить"
|
||||||
chat_save_btn: str = "Сохранить"
|
chat_save_btn: str = "Сохранить"
|
||||||
|
speak_btn: str = "Нажмите и Говорите"
|
||||||
|
input_kind: str = "Вид ввода"
|
||||||
|
input_kind_1: str = "Текст"
|
||||||
|
input_kind_2: str = "Голос [тестовый режим]"
|
||||||
select_placeholder1: str = "Выберите Модель"
|
select_placeholder1: str = "Выберите Модель"
|
||||||
select_placeholder2: str = "Выберите Роль"
|
select_placeholder2: str = "Выберите Роль"
|
||||||
select_placeholder3: 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