Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,7 +7,6 @@ from fastapi import FastAPI, File, UploadFile, Form, HTTPException
|
|
| 7 |
|
| 8 |
app = FastAPI()
|
| 9 |
|
| 10 |
-
# Voice choices from PersonaPlex repo
|
| 11 |
VOICE_CHOICES = [
|
| 12 |
"NATF0.pt", "NATF1.pt", "NATF2.pt", "NATF3.pt",
|
| 13 |
"NATM0.pt", "NATM1.pt", "NATM2.pt", "NATM3.pt",
|
|
@@ -33,9 +32,9 @@ def run_offline_inference(input_path, text_prompt, voice_prompt, seed, output_wa
|
|
| 33 |
prompt_file.write(text_prompt)
|
| 34 |
cmd += ["--text-prompt", prompt_file.name]
|
| 35 |
try:
|
| 36 |
-
subprocess.check_call(cmd, timeout=
|
| 37 |
except subprocess.TimeoutExpired:
|
| 38 |
-
raise RuntimeError("Inference timed out β
|
| 39 |
finally:
|
| 40 |
if os.path.exists(prompt_file.name):
|
| 41 |
os.unlink(prompt_file.name)
|
|
@@ -46,7 +45,6 @@ def gradio_generate(input_audio, text_prompt, voice_prompt, seed):
|
|
| 46 |
if input_audio is None:
|
| 47 |
raise gr.Error("Please record or upload audio for Sofia to hear you!")
|
| 48 |
|
| 49 |
-
# Use default persona if user leaves it blank
|
| 50 |
full_prompt = text_prompt.strip() or DEFAULT_PERSONA
|
| 51 |
|
| 52 |
try:
|
|
@@ -54,8 +52,7 @@ def gradio_generate(input_audio, text_prompt, voice_prompt, seed):
|
|
| 54 |
output_wav = os.path.join(tmpdir, "sofia_response.wav")
|
| 55 |
output_json = os.path.join(tmpdir, "sofia_response.json")
|
| 56 |
|
| 57 |
-
|
| 58 |
-
yield None, "Processing... Sofia is thinking (may take 1β3 minutes on CPU)..."
|
| 59 |
|
| 60 |
run_offline_inference(input_audio, full_prompt, voice_prompt, seed, output_wav, output_json)
|
| 61 |
|
|
@@ -64,29 +61,32 @@ def gradio_generate(input_audio, text_prompt, voice_prompt, seed):
|
|
| 64 |
|
| 65 |
yield output_wav, text
|
| 66 |
except Exception as e:
|
| 67 |
-
raise gr.Error(f"
|
| 68 |
|
| 69 |
-
# Create Gradio interface
|
| 70 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="pink", secondary_hue="purple")) as demo:
|
| 71 |
gr.Markdown("# Sofia β Your PersonaPlex AI Companion")
|
| 72 |
gr.Markdown(
|
| 73 |
-
"Record or upload audio β Sofia responds
|
| 74 |
-
"**
|
| 75 |
)
|
| 76 |
|
| 77 |
with gr.Row():
|
| 78 |
with gr.Column():
|
| 79 |
input_audio = gr.Audio(
|
| 80 |
-
sources=["microphone", "upload"],
|
| 81 |
-
type="filepath",
|
| 82 |
label="Speak to Sofia (mic or upload WAV/MP3)",
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
)
|
| 85 |
text_prompt = gr.Textbox(
|
| 86 |
label="Custom Persona / Role for Sofia (optional)",
|
| 87 |
placeholder=DEFAULT_PERSONA,
|
| 88 |
lines=4,
|
| 89 |
-
value=""
|
| 90 |
)
|
| 91 |
voice_prompt = gr.Dropdown(
|
| 92 |
choices=VOICE_CHOICES,
|
|
@@ -99,23 +99,19 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="pink", secondary_hue="purple"))
|
|
| 99 |
with gr.Column():
|
| 100 |
output_audio = gr.Audio(label="Sofia's Response (Audio)", autoplay=True)
|
| 101 |
output_text = gr.Textbox(label="Sofia's Response (Text)", lines=6)
|
| 102 |
-
status = gr.Textbox(label="Status", interactive=False)
|
| 103 |
|
| 104 |
-
# Use .submit() for better feedback on slow runs
|
| 105 |
submit_btn.click(
|
| 106 |
fn=gradio_generate,
|
| 107 |
inputs=[input_audio, text_prompt, voice_prompt, seed],
|
| 108 |
outputs=[output_audio, output_text],
|
| 109 |
-
api_name="generate_gradio" # optional
|
| 110 |
).then(
|
| 111 |
-
lambda: "Done! Play above β",
|
| 112 |
outputs=status
|
| 113 |
)
|
| 114 |
|
| 115 |
-
# Mount Gradio at root (cleaner URL: yourspace.hf.space directly shows UI)
|
| 116 |
gr.mount_gradio_app(app, demo, path="/")
|
| 117 |
|
| 118 |
-
# Keep the FastAPI /generate endpoint for external frontends
|
| 119 |
@app.post("/generate")
|
| 120 |
async def api_generate(
|
| 121 |
input_audio: UploadFile = File(...),
|
|
|
|
| 7 |
|
| 8 |
app = FastAPI()
|
| 9 |
|
|
|
|
| 10 |
VOICE_CHOICES = [
|
| 11 |
"NATF0.pt", "NATF1.pt", "NATF2.pt", "NATF3.pt",
|
| 12 |
"NATM0.pt", "NATM1.pt", "NATM2.pt", "NATM3.pt",
|
|
|
|
| 32 |
prompt_file.write(text_prompt)
|
| 33 |
cmd += ["--text-prompt", prompt_file.name]
|
| 34 |
try:
|
| 35 |
+
subprocess.check_call(cmd, timeout=900) # 15 min max (CPU can be slow)
|
| 36 |
except subprocess.TimeoutExpired:
|
| 37 |
+
raise RuntimeError("Inference timed out β CPU is slow, try shorter input audio.")
|
| 38 |
finally:
|
| 39 |
if os.path.exists(prompt_file.name):
|
| 40 |
os.unlink(prompt_file.name)
|
|
|
|
| 45 |
if input_audio is None:
|
| 46 |
raise gr.Error("Please record or upload audio for Sofia to hear you!")
|
| 47 |
|
|
|
|
| 48 |
full_prompt = text_prompt.strip() or DEFAULT_PERSONA
|
| 49 |
|
| 50 |
try:
|
|
|
|
| 52 |
output_wav = os.path.join(tmpdir, "sofia_response.wav")
|
| 53 |
output_json = os.path.join(tmpdir, "sofia_response.json")
|
| 54 |
|
| 55 |
+
yield None, "Processing... Sofia is thinking (expect 1β5+ minutes on free CPU)..."
|
|
|
|
| 56 |
|
| 57 |
run_offline_inference(input_audio, full_prompt, voice_prompt, seed, output_wav, output_json)
|
| 58 |
|
|
|
|
| 61 |
|
| 62 |
yield output_wav, text
|
| 63 |
except Exception as e:
|
| 64 |
+
raise gr.Error(f"Error: {str(e)}\n(Try shorter audio clips or check Space logs)")
|
| 65 |
|
|
|
|
| 66 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="pink", secondary_hue="purple")) as demo:
|
| 67 |
gr.Markdown("# Sofia β Your PersonaPlex AI Companion")
|
| 68 |
gr.Markdown(
|
| 69 |
+
"Record or upload short audio β Sofia responds! \n"
|
| 70 |
+
"**CPU note:** First load takes time (model download + init). Responses: 1β5+ min. Use short inputs (5β15 sec)."
|
| 71 |
)
|
| 72 |
|
| 73 |
with gr.Row():
|
| 74 |
with gr.Column():
|
| 75 |
input_audio = gr.Audio(
|
| 76 |
+
sources=["microphone", "upload"],
|
| 77 |
+
type="filepath",
|
| 78 |
label="Speak to Sofia (mic or upload WAV/MP3)",
|
| 79 |
+
# Fixed: Use proper WaveformOptions class
|
| 80 |
+
waveform_options=gr.WaveformOptions(
|
| 81 |
+
show_recording_waveform=True, # shows waveform while recording
|
| 82 |
+
show_controls=False # optional: hides extra player buttons if wanted
|
| 83 |
+
)
|
| 84 |
)
|
| 85 |
text_prompt = gr.Textbox(
|
| 86 |
label="Custom Persona / Role for Sofia (optional)",
|
| 87 |
placeholder=DEFAULT_PERSONA,
|
| 88 |
lines=4,
|
| 89 |
+
value=""
|
| 90 |
)
|
| 91 |
voice_prompt = gr.Dropdown(
|
| 92 |
choices=VOICE_CHOICES,
|
|
|
|
| 99 |
with gr.Column():
|
| 100 |
output_audio = gr.Audio(label="Sofia's Response (Audio)", autoplay=True)
|
| 101 |
output_text = gr.Textbox(label="Sofia's Response (Text)", lines=6)
|
| 102 |
+
status = gr.Textbox(label="Status", interactive=False, value="Ready...")
|
| 103 |
|
|
|
|
| 104 |
submit_btn.click(
|
| 105 |
fn=gradio_generate,
|
| 106 |
inputs=[input_audio, text_prompt, voice_prompt, seed],
|
| 107 |
outputs=[output_audio, output_text],
|
|
|
|
| 108 |
).then(
|
| 109 |
+
lambda: "Done! Play Sofia's response above β",
|
| 110 |
outputs=status
|
| 111 |
)
|
| 112 |
|
|
|
|
| 113 |
gr.mount_gradio_app(app, demo, path="/")
|
| 114 |
|
|
|
|
| 115 |
@app.post("/generate")
|
| 116 |
async def api_generate(
|
| 117 |
input_audio: UploadFile = File(...),
|