Spaces:
Sleeping
Sleeping
File size: 2,289 Bytes
35d8a1a 9316fdd 16e01d6 6001a3f 6c13d95 16e01d6 70de7cf 2246057 70de7cf 5fc28d8 4214d41 35d8a1a 6c13d95 5eaa3c8 35d8a1a 2246057 35d8a1a 16e01d6 824fa65 35d8a1a 2246057 8a56152 824fa65 35d8a1a 9316fdd 6001a3f 9316fdd 6001a3f 70de7cf 6001a3f 2246057 9316fdd 8350281 824fa65 35d8a1a 824fa65 16e01d6 70de7cf 4a3e249 70de7cf 82d921f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import io
import numpy as np
import soundfile as sf
import edge_tts
import miniaudio
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from scipy.signal import resample
from pydantic import BaseModel
from ltm import EmbeddingMemory
app = FastAPI()
memory = EmbeddingMemory()
VOICE = "pl-PL-ZofiaNeural"
class MemoryMessage(BaseModel):
session_id: str
role: str
content: str
class MemoryQuery(BaseModel):
session_id: str | None = None
query: str
top_k: int = 5
@app.post("/tts")
async def tts(data: dict):
text = data.get("text", "").strip()
if not text:
return {"error": "empty text"}
mp3_buffer = io.BytesIO()
communicate = edge_tts.Communicate(text, VOICE)
async for chunk in communicate.stream():
if chunk["type"] == "audio":
mp3_buffer.write(chunk["data"])
mp3_buffer.seek(0)
decoded = miniaudio.decode(mp3_buffer.read())
raw = decoded.samples
if decoded.sample_format == miniaudio.SampleFormat.SIGNED16:
audio = np.frombuffer(raw, dtype=np.int16).astype(np.float32) / 32768.0
elif decoded.sample_format == miniaudio.SampleFormat.FLOAT32:
audio = np.frombuffer(raw, dtype=np.float32)
else:
return {"error": "Unsupported audio format from decoder"}
if decoded.nchannels > 1:
audio = audio.reshape(-1, decoded.nchannels)
audio = np.mean(audio, axis=1)
peak = np.max(np.abs(audio)) if len(audio) else 0
if peak > 0:
audio = audio / max(peak, 1.0)
audio *= 0.3
pitch_factor = 1.1
audio = resample(audio, int(len(audio) / pitch_factor))
audio = np.clip(audio, -1.0, 1.0)
wav_buffer = io.BytesIO()
sf.write(wav_buffer, audio, decoded.sample_rate, format="WAV")
wav_buffer.seek(0)
return StreamingResponse(wav_buffer, media_type="audio/wav")
@app.post("/memory/store")
def store(msg: MemoryMessage):
memory.add_message(
session_id=msg.session_id,
role=msg.role,
content=msg.content
)
return {"status": "saved"}
@app.post("/memory/query")
def search_memory(data: MemoryQuery):
results = memory.search(
query=data.query,
session_id=data.session_id,
top_k=data.top_k
)
return results |