| | """ |
| | ui/state.py |
| | ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| | VoiceVerse Pro β Centralised Session State & Config Contracts |
| | """ |
| |
|
| | from __future__ import annotations |
| |
|
| | from dataclasses import dataclass, field |
| | from enum import Enum |
| | from typing import List, Optional |
| |
|
| | from modules import RetrievedContext, IngestedFile |
| | from modules.tts_engine import TTSBackend |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | class OutputMode(str, Enum): |
| | TRANSCRIPT = "Audio Transcript" |
| | PODCAST = "Podcast (2 Speakers)" |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | @dataclass |
| | class SidebarConfig: |
| | |
| | hf_token: str = "" |
| |
|
| | |
| | output_mode: OutputMode = OutputMode.TRANSCRIPT |
| |
|
| | |
| | top_k: int = 4 |
| | chunk_size: int = 1000 |
| | chunk_overlap: int = 100 |
| |
|
| | |
| | model_id: str = "meta-llama/Llama-3.1-8B-Instruct" |
| | temperature: float = 0.65 |
| | max_tokens: int = 1024 |
| | target_words: int = 400 |
| |
|
| | |
| | tts_backend: TTSBackend = TTSBackend.SPEECHT5 |
| | |
| | speaker_id: int = 7306 |
| | |
| | female_speaker_id: int = 1580 |
| | male_speaker_id: int = 7306 |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | @dataclass |
| | class PipelineState: |
| | """ |
| | Single source of truth for pipeline progress. |
| | |
| | stage: |
| | 0 β idle |
| | 1 β documents indexed |
| | 2 β context retrieved |
| | 3 β script generated |
| | 4 β audio synthesised |
| | """ |
| | stage: int = 0 |
| |
|
| | ingested_files: List[IngestedFile] = field(default_factory=list) |
| | total_chunks: int = 0 |
| | retrieved_context: Optional[RetrievedContext] = None |
| | generated_script: Optional[str] = None |
| | audio_bytes: Optional[bytes] = None |
| | audio_format: str = "audio/wav" |
| |
|
| | def reset_from(self, stage: int) -> None: |
| | if stage <= 1: |
| | self.ingested_files = []; self.total_chunks = 0; self.stage = 0 |
| | if stage <= 2: |
| | self.retrieved_context = None |
| | if self.stage >= 2: self.stage = 1 |
| | if stage <= 3: |
| | self.generated_script = None |
| | if self.stage >= 3: self.stage = 2 |
| | if stage <= 4: |
| | self.audio_bytes = None; self.audio_format = "audio/wav" |
| | if self.stage >= 4: self.stage = 3 |
| |
|
| | @property |
| | def has_index(self) -> bool: return self.stage >= 1 |
| | @property |
| | def has_context(self) -> bool: return self.stage >= 2 and self.retrieved_context is not None |
| | @property |
| | def has_script(self) -> bool: return self.stage >= 3 and self.generated_script is not None |
| | @property |
| | def has_audio(self) -> bool: return self.stage >= 4 and self.audio_bytes is not None |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | def get_pipeline_state() -> PipelineState: |
| | import streamlit as st |
| | if "pipeline_state" not in st.session_state: |
| | st.session_state["pipeline_state"] = PipelineState() |
| | if "rag_engine" not in st.session_state: |
| | st.session_state["rag_engine"] = None |
| | return st.session_state["pipeline_state"] |