change /chat endpoint to return a url

parent b0bf570e
...@@ -148,33 +148,18 @@ def create_app() -> FastAPI: ...@@ -148,33 +148,18 @@ def create_app() -> FastAPI:
"""Fetches the agent's text and audio response with proper CORS headers.""" """Fetches the agent's text and audio response with proper CORS headers."""
try: try:
print("Getting audio response...") print("Getting audio response...")
result = container.response_service.get_agent_response(student_id=student_id) result = container.response_service.get_agent_response(student_id=student_id)
if hasattr(result, 'status_code'): if hasattr(result, 'status_code'):
# This is already a Response object from response_service # This is already a Response object from response_service
print(f"Response headers: {dict(result.headers)}") print(f"Response headers: {dict(result.headers)}")
print(f"Response audio raw bytes size: {len(result.body) if result.body else 'N/A'}")
print(f"Response audio first 20 bytes: {result.body[:20] if result.body else 'N/A'}")
return result return result
else:
# If it's not a Response object, create one
print("Creating new response object")
response_text = result.get('text', 'No response available')
# Encode the response text in base64 for the header
encoded_text = base64.b64encode(response_text.encode('utf-8')).decode('utf-8')
# Create response with proper headers
response = Response(
content=result.get('audio', b''),
media_type="audio/mpeg",
headers={
"X-Response-Text": encoded_text,
"Access-Control-Expose-Headers": "X-Response-Text",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "*"
}
)
print(f"Created response with headers: {dict(response.headers)}") print(f"Created response with headers: {dict(response.headers)}")
return response return response
......
...@@ -43,4 +43,17 @@ class MinIOStorageRepository(StorageRepository): ...@@ -43,4 +43,17 @@ class MinIOStorageRepository(StorageRepository):
self.client.head_bucket(Bucket=bucket) self.client.head_bucket(Bucket=bucket)
return "connected" return "connected"
except Exception as e: except Exception as e:
return f"error: {str(e)}" return f"error: {str(e)}"
\ No newline at end of file
def get_file_url(self, bucket: str, file_path: str, expires: int = 3600) -> str:
"""Generate a presigned URL to share an S3 object"""
try:
url = self.client.generate_presigned_url(
'get_object',
Params={'Bucket': bucket, 'Key': file_path},
ExpiresIn=expires
)
return url
except ClientError as e:
print(f"Error generating presigned URL: {e}")
return None
\ No newline at end of file
...@@ -60,7 +60,7 @@ class ChatService: ...@@ -60,7 +60,7 @@ class ChatService:
self.response_manager.store_response( self.response_manager.store_response(
student_id = student_id, student_id = student_id,
text=agent_response_text, text=agent_response_text,
audio_filename=audio_data.get("filename"), audio_filepath=audio_data.get("filepath"),
audio_bytes=audio_data.get("bytes") audio_bytes=audio_data.get("bytes")
) )
...@@ -71,7 +71,7 @@ class ChatService: ...@@ -71,7 +71,7 @@ class ChatService:
"message": "Message processed and agent response ready", "message": "Message processed and agent response ready",
"student_id": student_id, "student_id": student_id,
"agent_response": agent_response_text, "agent_response": agent_response_text,
"audio_filename": audio_data.get("filename") "audio_filepath": audio_data.get("filepath")
} }
except Exception as e: except Exception as e:
...@@ -93,11 +93,11 @@ class ChatService: ...@@ -93,11 +93,11 @@ class ChatService:
# 3. Determine filename and upload (same as before) # 3. Determine filename and upload (same as before)
provider = os.getenv("TTS_PROVIDER", "openai").lower() provider = os.getenv("TTS_PROVIDER", "openai").lower()
file_extension = "wav" if provider == "custom" else "mp3" file_extension = "wav"
content_type = "audio/wav" if provider == "custom" else "audio/mpeg" content_type = "audio/wav"
timestamp = int(time.time()) timestamp = int(time.time())
filename = f"agent_response_{timestamp}.{file_extension}" filename = f"agent_response_{timestamp}_{student_id}.{file_extension}"
minio_file_path = f"audio/{filename}" minio_file_path = f"audio/{filename}"
self.storage_repo.upload_file( self.storage_repo.upload_file(
...@@ -106,9 +106,14 @@ class ChatService: ...@@ -106,9 +106,14 @@ class ChatService:
file_path=minio_file_path file_path=minio_file_path
) )
full_url = self.storage_repo.get_file_url(
bucket=self.config.minio_bucket,
file_path=minio_file_path,
expires=3600 # 1 hour
)
print(f"Successfully generated and uploaded stitched TTS audio: {filename}") print(f"Successfully generated and uploaded stitched TTS audio: {filename}")
return {"bytes": audio_bytes, "filename": filename} return {"bytes": audio_bytes, "filepath": full_url}
except Exception as e: except Exception as e:
print(f"Error in _generate_and_upload_audio: {e}") print(f"Error in _generate_and_upload_audio: {e}")
return {"bytes": None, "filename": None} return {"bytes": None, "filepath": None}
\ No newline at end of file \ No newline at end of file
...@@ -69,7 +69,7 @@ class OpenAIService(BaseTTSService): ...@@ -69,7 +69,7 @@ class OpenAIService(BaseTTSService):
model=Models.tts, model=Models.tts,
voice=voice, voice=voice,
input=text, input=text,
response_format="mp3" response_format="wav"
) )
audio_bytes = response.content audio_bytes = response.content
......
...@@ -22,7 +22,7 @@ class ResponseManager: ...@@ -22,7 +22,7 @@ class ResponseManager:
"""Creates a consistent key for Redis to avoid conflicts.""" """Creates a consistent key for Redis to avoid conflicts."""
return f"student_response:{student_id}" return f"student_response:{student_id}"
def store_response(self, student_id: str, text: str, audio_filename: Optional[str] = None, audio_bytes: Optional[bytes] = None) -> None: def store_response(self, student_id: str, text: str, audio_filepath: Optional[str] = None, audio_bytes: Optional[bytes] = None) -> None:
"""Stores a response for a specific student_id in Redis.""" """Stores a response for a specific student_id in Redis."""
key = self._get_key(student_id) key = self._get_key(student_id)
...@@ -31,7 +31,7 @@ class ResponseManager: ...@@ -31,7 +31,7 @@ class ResponseManager:
payload = { payload = {
"text": text, "text": text,
"audio_filename": audio_filename, "audio_filepath": audio_filepath,
"audio_bytes_b64": encoded_audio "audio_bytes_b64": encoded_audio
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment