Я разрабатываю приложение Streamlit для эксперимента с голосовым взаимодействием. Приложение позволяет участникам записывать звук, который затем обрабатывается с помощью STT (преобразование речи в текст), LangChain для обработки текста и TTS (преобразование текста в речь). Участники могут прекратить эксперимент в любое время, используя кнопку «Прекратить эксперимент». Однако я столкнулся с проблемой, из-за которой даже после нажатия кнопки завершения обработка звука продолжает работать.
import streamlit as st
from datetime import datetime
from pathlib import Path
import json
from stt import STTProcessor
from process import LangChainProcessor
from tts import TTSProcessor
from dotenv import load_dotenv
import time
load_dotenv()
st.sidebar.page_link('app.py', label='Start Screen')
# Define constants
DATA_DIR = Path("experiment_data")
DATA_DIR.mkdir(exist_ok=True)
class ConversationLogger:
def __init__(self, save_dir=DATA_DIR):
self.save_dir = Path(save_dir)
self.save_dir.mkdir(exist_ok=True)
self.logs = []
def initialize_for_participant(self, participant_id):
self.participant_id = participant_id
self.log_file = self.save_dir / f"{participant_id}_conversations.json"
if self.log_file.exists():
with open(self.log_file, 'r', encoding='utf-8') as f:
self.logs = json.load(f)
def log_conversation(self, stt_text, tts_text):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
entries = [
{"timestamp": timestamp, "text": stt_text, "role": "human"},
{"timestamp": timestamp, "text": tts_text, "role": "assistant"}
]
self.logs.extend(entries)
def save_to_file(self):
with open(self.log_file, 'w', encoding='utf-8') as f:
json.dump(self.logs, f, ensure_ascii=False, indent=2)
def format_for_llm(self):
"""Format conversation logs for LLM input"""
return "\n".join(
f"{entry['role']}: {entry['text']}"
for entry in self.logs[-10:] # Use only the last 10 entries
)
def get_conversation_history(self):
"""Get complete conversation logs for Streamlit display"""
return self.logs
def handle_experiment_termination(logger):
"""Handle experiment termination"""
try:
# Save final conversation logs
logger.save_to_file()
# Save termination information
end_info = {
"participant_id": st.session_state.participant_id,
"end_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
with open(DATA_DIR / f"{st.session_state.participant_id}_end_info.json", 'w', encoding='utf-8') as f:
json.dump(end_info, f, ensure_ascii=False, indent=2)
# Clear session
for key in ['participant_id', 'logger']:
if key in st.session_state:
del st.session_state[key]
return True
except Exception as e:
st.error(f"Error occurred during experiment termination: {str(e)}")
return False
def main():
if st.session_state.get('experiment_ended', False):
st.switch_page("pages/experiment_complete.py")
return
st.title("🎤 Voice Conversation Experiment")
if 'participant_id' not in st.session_state:
st.warning("⚠️ Participant registration is required.")
return
experiment_mode = st.radio(
"Select experiment mode",
["Discourse Marker Mode", "Basic Mode"],
horizontal=True, # Display horizontally
label_visibility="collapsed" # Hide label
)
# Initialize logger and participant settings
if 'logger' not in st.session_state:
logger = ConversationLogger()
logger.initialize_for_participant(st.session_state.participant_id)
st.session_state.logger = logger
stt_processor = STTProcessor()
lang_processor = LangChainProcessor()
tts_processor = TTSProcessor()
st.write(f"Participant ID: {st.session_state.participant_id}")
audio_file = st.audio_input("Record audio", key="audio_recorder")
if audio_file and not st.session_state.get("experiment_ended", False):
if 'experiment_ended' in st.session_state and st.session_state.experiment_ended:
st.switch_page("pages/experiment_complete.py")
return
with st.spinner("🔄 Processing audio..."):
try:
# STT processing
audio_bytes = audio_file.read()
stt_text = stt_processor.transcribe_audio(audio_bytes)
if not stt_text:
st.error("Failed to convert audio to text. Please try again.")
return
st.success("🎯 Recognized Text")
st.write(f"💬 {stt_text}")
# LangChain processing
conversation_history = st.session_state.logger.format_for_llm()
if experiment_mode == "Basic Mode":
tts_text = lang_processor.process_text(stt_text, conversation_history, modify=False)
elif experiment_mode == "Discourse Marker Mode":
tts_text = lang_processor.process_text(stt_text, conversation_history, modify=True)
st.info("🤖 AI's Response")
st.write(f"💭 {tts_text}")
# Log conversation
st.session_state.logger.log_conversation(stt_text, tts_text)
# TTS processing
if 'experiment_ended' in st.session_state and st.session_state.experiment_ended:
st.switch_page("pages/experiment_complete.py")
return
tts_processor.speak_text(tts_text)
except Exception as e:
st.error(f"An error occurred during processing: {str(e)}")
# Display conversation logs - use complete history
st.markdown("---")
with st.expander("Check current conversation history", expanded=False):
if 'logger' in st.session_state:
st.json(st.session_state.logger.get_conversation_history())
with st.expander("End Experiment", expanded=False):
st.warning("Once the experiment ends, you will no longer be able to continue voice conversations.")
if st.button("End Experiment", type="primary"):
# Immediately update session state
st.session_state.experiment_ended = True
st.session_state.stop_processing = True # Additional
try:
# Save final conversation logs
st.session_state.logger.save_to_file()
# Save termination information
end_info = {
"participant_id": st.session_state.participant_id,
"end_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
with open(DATA_DIR / f"{st.session_state.participant_id}_end_info.json", 'w', encoding='utf-8') as f:
json.dump(end_info, f, ensure_ascii=False, indent=2)
# Clear session
for key in ['participant_id', 'logger']:
st.session_state.pop(key, None)
st.
Буду очень признателен за любую помощь.
Я попытался реализовать асинхронную обработку или использовать состояние сеанса, чтобы предотвратить ненужный запуск обработки звука.
Я разрабатываю приложение Streamlit для эксперимента с голосовым взаимодействием. Приложение позволяет участникам записывать звук, который затем обрабатывается с помощью STT (преобразование речи в текст), LangChain для обработки текста и TTS (преобразование текста в речь). Участники могут прекратить эксперимент в любое время, используя кнопку «Прекратить эксперимент». Однако я столкнулся с проблемой, из-за которой даже после нажатия кнопки завершения обработка звука продолжает работать. [code]import streamlit as st from datetime import datetime from pathlib import Path import json from stt import STTProcessor from process import LangChainProcessor from tts import TTSProcessor from dotenv import load_dotenv import time
def save_to_file(self): with open(self.log_file, 'w', encoding='utf-8') as f: json.dump(self.logs, f, ensure_ascii=False, indent=2)
def format_for_llm(self): """Format conversation logs for LLM input""" return "\n".join( f"{entry['role']}: {entry['text']}" for entry in self.logs[-10:] # Use only the last 10 entries )
# Initialize logger and participant settings if 'logger' not in st.session_state: logger = ConversationLogger() logger.initialize_for_participant(st.session_state.participant_id) st.session_state.logger = logger
if audio_file and not st.session_state.get("experiment_ended", False): if 'experiment_ended' in st.session_state and st.session_state.experiment_ended: st.switch_page("pages/experiment_complete.py") return
with st.spinner("🔄 Processing audio..."): try: # STT processing audio_bytes = audio_file.read() stt_text = stt_processor.transcribe_audio(audio_bytes) if not stt_text: st.error("Failed to convert audio to text. Please try again.") return
# TTS processing if 'experiment_ended' in st.session_state and st.session_state.experiment_ended: st.switch_page("pages/experiment_complete.py") return tts_processor.speak_text(tts_text)
except Exception as e: st.error(f"An error occurred during processing: {str(e)}")
# Display conversation logs - use complete history st.markdown("---") with st.expander("Check current conversation history", expanded=False): if 'logger' in st.session_state: st.json(st.session_state.logger.get_conversation_history())
with st.expander("End Experiment", expanded=False): st.warning("Once the experiment ends, you will no longer be able to continue voice conversations.") if st.button("End Experiment", type="primary"): # Immediately update session state st.session_state.experiment_ended = True st.session_state.stop_processing = True # Additional try: # Save final conversation logs st.session_state.logger.save_to_file()
# Save termination information end_info = { "participant_id": st.session_state.participant_id, "end_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } with open(DATA_DIR / f"{st.session_state.participant_id}_end_info.json", 'w', encoding='utf-8') as f: json.dump(end_info, f, ensure_ascii=False, indent=2)
# Clear session for key in ['participant_id', 'logger']: st.session_state.pop(key, None)
st.
[/code] Буду очень признателен за любую помощь. Я попытался реализовать асинхронную обработку или использовать состояние сеанса, чтобы предотвратить ненужный запуск обработки звука.