seawolf2357 commited on
Commit
54990b5
·
verified ·
1 Parent(s): 868c0a3

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -179
app.py DELETED
@@ -1,179 +0,0 @@
1
- import asyncio
2
- import base64
3
- import json
4
- from pathlib import Path
5
-
6
- import gradio as gr
7
- import numpy as np
8
- import openai
9
- from dotenv import load_dotenv
10
- from fastapi import FastAPI
11
- from fastapi.responses import HTMLResponse, StreamingResponse
12
- from fastrtc import (
13
- AdditionalOutputs,
14
- AsyncStreamHandler,
15
- Stream,
16
- get_twilio_turn_credentials,
17
- wait_for_item,
18
- )
19
- from gradio.utils import get_space
20
- from openai.types.beta.realtime import ResponseAudioTranscriptDoneEvent
21
- import websockets.exceptions
22
- import logging
23
-
24
- load_dotenv()
25
-
26
- # 로깅 설정
27
- logging.basicConfig(level=logging.INFO)
28
- logger = logging.getLogger(__name__)
29
-
30
- cur_dir = Path(__file__).parent
31
-
32
- SAMPLE_RATE = 24000
33
-
34
-
35
- class OpenAIHandler(AsyncStreamHandler):
36
- def __init__(
37
- self,
38
- system_prompt="You are a helpful assistant. Be concise and clear in your responses."
39
- ) -> None:
40
- super().__init__(
41
- expected_layout="mono",
42
- output_sample_rate=SAMPLE_RATE,
43
- output_frame_size=480,
44
- input_sample_rate=SAMPLE_RATE,
45
- )
46
- self.connection = None
47
- self.output_queue = asyncio.Queue()
48
- self.system_prompt = system_prompt
49
-
50
- def copy(self):
51
- return OpenAIHandler(system_prompt=self.system_prompt)
52
-
53
- async def start_up(
54
- self,
55
- ):
56
- """Connect to realtime API. Run forever in separate thread to keep connection open."""
57
- self.client = openai.AsyncOpenAI()
58
- try:
59
- async with self.client.beta.realtime.connect(
60
- model="gpt-4o-mini-realtime-preview-2024-12-17"
61
- ) as conn:
62
- await conn.session.update(
63
- session={
64
- "turn_detection": {"type": "server_vad"},
65
- "system_prompt": self.system_prompt
66
- }
67
- )
68
- self.connection = conn
69
- async for event in self.connection:
70
- if event.type == "response.audio_transcript.done":
71
- await self.output_queue.put(AdditionalOutputs(event))
72
- if event.type == "response.audio.delta":
73
- await self.output_queue.put(
74
- (
75
- self.output_sample_rate,
76
- np.frombuffer(
77
- base64.b64decode(event.delta), dtype=np.int16
78
- ).reshape(1, -1),
79
- ),
80
- )
81
- except Exception as e:
82
- logger.error(f"Error in start_up: {e}")
83
- if self.connection:
84
- await self.connection.close()
85
- self.connection = None
86
-
87
- async def receive(self, frame: tuple[int, np.ndarray]) -> None:
88
- if not self.connection:
89
- logger.warning("No connection available")
90
- return
91
- try:
92
- _, array = frame
93
- array = array.squeeze()
94
- audio_message = base64.b64encode(array.tobytes()).decode("utf-8")
95
- await self.connection.input_audio_buffer.append(audio=audio_message) # type: ignore
96
- except websockets.exceptions.ConnectionClosedOK:
97
- logger.info("WebSocket connection closed normally")
98
- # 정상적인 종료는 무시하고 넘어감
99
- except Exception as e:
100
- logger.error(f"Error in receive: {e}")
101
- if self.connection:
102
- try:
103
- await self.connection.close()
104
- except:
105
- pass
106
- self.connection = None
107
-
108
- async def emit(self) -> tuple[int, np.ndarray] | AdditionalOutputs | None:
109
- try:
110
- return await wait_for_item(self.output_queue)
111
- except Exception as e:
112
- logger.error(f"Error in emit: {e}")
113
- return None
114
-
115
- async def shutdown(self) -> None:
116
- if self.connection:
117
- try:
118
- await self.connection.close()
119
- except Exception as e:
120
- logger.error(f"Error closing connection: {e}")
121
- finally:
122
- self.connection = None
123
-
124
-
125
- def update_chatbot(chatbot: list[dict], response: ResponseAudioTranscriptDoneEvent):
126
- chatbot.append({"role": "assistant", "content": response.transcript})
127
- return chatbot
128
-
129
-
130
- chatbot = gr.Chatbot(type="messages")
131
- latest_message = gr.Textbox(type="text", visible=False)
132
- stream = Stream(
133
- OpenAIHandler(system_prompt="당신은 친절한 한국어 AI 비서 '마우스'입니다. 모든 질문에 한국어로 간결하고 명확하게, 항상 존댓말로 답변하세요."),
134
- mode="send-receive",
135
- modality="audio",
136
- additional_inputs=[chatbot],
137
- additional_outputs=[chatbot],
138
- additional_outputs_handler=update_chatbot,
139
- rtc_configuration=get_twilio_turn_credentials() if get_space() else None,
140
- concurrency_limit=5 if get_space() else None,
141
- time_limit=90 if get_space() else None,
142
- )
143
-
144
- app = FastAPI()
145
-
146
- stream.mount(app)
147
-
148
-
149
- @app.get("/")
150
- async def _():
151
- rtc_config = get_twilio_turn_credentials() if get_space() else None
152
- html_content = (cur_dir / "index.html").read_text()
153
- html_content = html_content.replace("__RTC_CONFIGURATION__", json.dumps(rtc_config))
154
- return HTMLResponse(content=html_content)
155
-
156
-
157
- @app.get("/outputs")
158
- def _(webrtc_id: str):
159
- async def output_stream():
160
- import json
161
-
162
- async for output in stream.output_stream(webrtc_id):
163
- s = json.dumps({"role": "assistant", "content": output.args[0].transcript})
164
- yield f"event: output\ndata: {s}\n\n"
165
-
166
- return StreamingResponse(output_stream(), media_type="text/event-stream")
167
-
168
-
169
- if __name__ == "__main__":
170
- import os
171
-
172
- if (mode := os.getenv("MODE")) == "UI":
173
- stream.ui.launch(server_port=7860)
174
- elif mode == "PHONE":
175
- stream.fastphone(host="0.0.0.0", port=7860)
176
- else:
177
- import uvicorn
178
-
179
- uvicorn.run(app, host="0.0.0.0", port=7860)