Nikita Makarov commited on
Commit
3a37184
Β·
1 Parent(s): 369b798

updated structure

Browse files
.gitignore CHANGED
@@ -4,50 +4,41 @@ __pycache__/
4
  *$py.class
5
  *.so
6
  .Python
7
- build/
8
- develop-eggs/
9
- dist/
10
- downloads/
11
- eggs/
12
- .eggs/
13
- lib/
14
- lib64/
15
- parts/
16
- sdist/
17
- var/
18
- wheels/
19
  *.egg-info/
20
- .installed.cfg
21
- *.egg
22
 
23
- # Virtual Environment
 
24
  venv/
25
- env/
26
  ENV/
27
- .venv
 
 
 
 
 
 
 
 
 
28
 
29
  # IDE
30
  .vscode/
31
  .idea/
32
  *.swp
33
  *.swo
34
- *~
35
 
36
  # OS
37
  .DS_Store
38
  Thumbs.db
39
 
40
- # Environment variables
41
- .env
42
-
43
- # User data
44
- user_data.json
45
- *.mp3
46
- *.wav
47
-
48
- # Logs
49
- *.log
50
 
51
- # HuggingFace
52
- flagged/
53
 
 
 
 
4
  *$py.class
5
  *.so
6
  .Python
 
 
 
 
 
 
 
 
 
 
 
 
7
  *.egg-info/
8
+ dist/
9
+ build/
10
 
11
+ # Virtual environments
12
+ .venv/
13
  venv/
 
14
  ENV/
15
+
16
+ # Audio files (generated)
17
+ audio/*.mp3
18
+ audio/*.wav
19
+
20
+ # Logs
21
+ logs/*.log
22
+
23
+ # User data
24
+ user_data.json
25
 
26
  # IDE
27
  .vscode/
28
  .idea/
29
  *.swp
30
  *.swo
 
31
 
32
  # OS
33
  .DS_Store
34
  Thumbs.db
35
 
36
+ # Temporary files
37
+ *.part
38
+ *.tmp
 
 
 
 
 
 
 
39
 
40
+ # ChromaDB
41
+ chroma_db/
42
 
43
+ # Music cache
44
+ music_cache/
README.md CHANGED
@@ -30,6 +30,25 @@ tags:
30
 
31
  **AI Radio** is an intelligent, personalized radio station powered by cutting-edge AI technology. It creates a unique listening experience tailored to your preferences, mood, and interests. Built for the **MCP 1st Birthday Competition**, this app demonstrates autonomous agent behavior, MCP integration, and advanced RAG capabilities.
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  ## ✨ Features
34
 
35
  ### 🎡 Personalized Music
@@ -118,10 +137,16 @@ google_api_key: str = "your-gemini-api-key-here"
118
 
119
  4. Run the app:
120
  ```bash
 
 
 
 
 
 
121
  python app.py
122
  ```
123
 
124
- 5. Open your browser to `http://localhost:7860`
125
 
126
  ## πŸ“– How to Use
127
 
 
30
 
31
  **AI Radio** is an intelligent, personalized radio station powered by cutting-edge AI technology. It creates a unique listening experience tailored to your preferences, mood, and interests. Built for the **MCP 1st Birthday Competition**, this app demonstrates autonomous agent behavior, MCP integration, and advanced RAG capabilities.
32
 
33
+ ## πŸ“ Project Structure
34
+
35
+ ```
36
+ ai_radio/
37
+ β”œβ”€β”€ src/ # Source code
38
+ β”‚ β”œβ”€β”€ app.py # Main Gradio application
39
+ β”‚ β”œβ”€β”€ config.py # Configuration
40
+ β”‚ β”œβ”€β”€ radio_agent.py # AI agent logic
41
+ β”‚ β”œβ”€β”€ tts_service.py # Text-to-speech service
42
+ β”‚ β”œβ”€β”€ rag_system.py # RAG system
43
+ β”‚ β”œβ”€β”€ voice_input.py # Voice input handling
44
+ β”‚ └── mcp_servers/ # MCP server implementations
45
+ β”œβ”€β”€ docs/ # Documentation files
46
+ β”œβ”€β”€ audio/ # Generated audio files
47
+ β”œβ”€β”€ logs/ # Log files
48
+ β”œβ”€β”€ requirements.txt # Python dependencies
49
+ └── run.py # Application entry point
50
+ ```
51
+
52
  ## ✨ Features
53
 
54
  ### 🎡 Personalized Music
 
137
 
138
  4. Run the app:
139
  ```bash
140
+ python run.py
141
+ ```
142
+
143
+ Or from the src directory:
144
+ ```bash
145
+ cd src
146
  python app.py
147
  ```
148
 
149
+ 5. Open your browser to `http://localhost:7863`
150
 
151
  ## πŸ“– How to Use
152
 
ARCHITECTURE.md β†’ docs/ARCHITECTURE.md RENAMED
File without changes
DEPLOYMENT.md β†’ docs/DEPLOYMENT.md RENAMED
File without changes
GET_GEMINI_KEY.md β†’ docs/GET_GEMINI_KEY.md RENAMED
File without changes
INSTALL_FFMPEG.md β†’ docs/INSTALL_FFMPEG.md RENAMED
File without changes
INSTALL_VOICE_INPUT.md β†’ docs/INSTALL_VOICE_INPUT.md RENAMED
File without changes
PROJECT_OVERVIEW.txt β†’ docs/PROJECT_OVERVIEW.txt RENAMED
File without changes
PROJECT_SUMMARY.md β†’ docs/PROJECT_SUMMARY.md RENAMED
File without changes
QUICKSTART.md β†’ docs/QUICKSTART.md RENAMED
File without changes
SETUP_GUIDE.md β†’ docs/SETUP_GUIDE.md RENAMED
File without changes
START_HERE.md β†’ docs/START_HERE.md RENAMED
File without changes
run.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Entry point for AI Radio application"""
3
+ import sys
4
+ import os
5
+
6
+ # Add src directory to Python path
7
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
8
+
9
+ # Import and run the app
10
+ from app import demo
11
+
12
+ if __name__ == "__main__":
13
+ demo.launch(
14
+ server_name="0.0.0.0",
15
+ server_port=7863,
16
+ share=False
17
+ )
18
+
src/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ """AI Radio - Personalized Radio Station with AI Host"""
2
+
app.py β†’ src/app.py RENAMED
@@ -7,6 +7,13 @@ import re
7
  from typing import Dict, Any, List, Optional
8
  import threading
9
 
 
 
 
 
 
 
 
10
  from config import get_config
11
  from radio_agent import RadioAgent
12
  from tts_service import TTSService
@@ -180,7 +187,7 @@ def play_next_segment():
180
  if getattr(tts_service, "available", True):
181
  audio_bytes = tts_service.text_to_speech(next_batch)
182
  if audio_bytes:
183
- host_audio_file = f"segment_{radio_state['current_segment_index']}_batch_{batch_index}.mp3"
184
  tts_service.save_audio(audio_bytes, host_audio_file)
185
 
186
  # Build display info (same news segment)
@@ -233,7 +240,7 @@ def play_next_segment():
233
  if text and getattr(tts_service, "available", True):
234
  audio_bytes = tts_service.text_to_speech(text)
235
  if audio_bytes:
236
- host_audio_file = f"segment_{radio_state['current_segment_index']}.mp3"
237
  tts_service.save_audio(audio_bytes, host_audio_file)
238
 
239
  elif segment["type"] == "news":
@@ -245,7 +252,7 @@ def play_next_segment():
245
  if getattr(tts_service, "available", True):
246
  audio_bytes = tts_service.text_to_speech(first_batch)
247
  if audio_bytes:
248
- host_audio_file = f"segment_{radio_state['current_segment_index']}_batch_1.mp3"
249
  tts_service.save_audio(audio_bytes, host_audio_file)
250
  # Store remaining batches for sequential playback
251
  segment["remaining_batches"] = script_batches[1:] if len(script_batches) > 1 else []
@@ -266,7 +273,7 @@ def play_next_segment():
266
  if commentary and getattr(tts_service, "available", True):
267
  audio_bytes = tts_service.text_to_speech(commentary)
268
  if audio_bytes:
269
- host_audio_file = f"segment_{radio_state['current_segment_index']}_host.mp3"
270
  tts_service.save_audio(audio_bytes, host_audio_file)
271
 
272
  # Get music track and create streaming player
@@ -363,7 +370,7 @@ def play_next_segment():
363
  if intro and getattr(tts_service, "available", True):
364
  audio_bytes = tts_service.text_to_speech(intro)
365
  if audio_bytes:
366
- host_audio_file = f"segment_{radio_state['current_segment_index']}_host.mp3"
367
  tts_service.save_audio(audio_bytes, host_audio_file)
368
 
369
  # Progress info
@@ -561,7 +568,7 @@ def handle_voice_request():
561
  if getattr(tts_service, "available", True):
562
  audio_bytes = tts_service.text_to_speech(host_response)
563
  if audio_bytes:
564
- audio_file = f"voice_request_{int(time.time())}.mp3"
565
  tts_service.save_audio(audio_bytes, audio_file)
566
 
567
  # Create music player HTML
 
7
  from typing import Dict, Any, List, Optional
8
  import threading
9
 
10
+ # Get project root directory (parent of src/)
11
+ PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
12
+ AUDIO_DIR = os.path.join(PROJECT_ROOT, "audio")
13
+ LOG_DIR = os.path.join(PROJECT_ROOT, "logs")
14
+ os.makedirs(AUDIO_DIR, exist_ok=True)
15
+ os.makedirs(LOG_DIR, exist_ok=True)
16
+
17
  from config import get_config
18
  from radio_agent import RadioAgent
19
  from tts_service import TTSService
 
187
  if getattr(tts_service, "available", True):
188
  audio_bytes = tts_service.text_to_speech(next_batch)
189
  if audio_bytes:
190
+ host_audio_file = os.path.join(AUDIO_DIR, f"segment_{radio_state['current_segment_index']}_batch_{batch_index}.mp3")
191
  tts_service.save_audio(audio_bytes, host_audio_file)
192
 
193
  # Build display info (same news segment)
 
240
  if text and getattr(tts_service, "available", True):
241
  audio_bytes = tts_service.text_to_speech(text)
242
  if audio_bytes:
243
+ host_audio_file = os.path.join(AUDIO_DIR, f"segment_{radio_state['current_segment_index']}.mp3")
244
  tts_service.save_audio(audio_bytes, host_audio_file)
245
 
246
  elif segment["type"] == "news":
 
252
  if getattr(tts_service, "available", True):
253
  audio_bytes = tts_service.text_to_speech(first_batch)
254
  if audio_bytes:
255
+ host_audio_file = os.path.join(AUDIO_DIR, f"segment_{radio_state['current_segment_index']}_batch_1.mp3")
256
  tts_service.save_audio(audio_bytes, host_audio_file)
257
  # Store remaining batches for sequential playback
258
  segment["remaining_batches"] = script_batches[1:] if len(script_batches) > 1 else []
 
273
  if commentary and getattr(tts_service, "available", True):
274
  audio_bytes = tts_service.text_to_speech(commentary)
275
  if audio_bytes:
276
+ host_audio_file = os.path.join(AUDIO_DIR, f"segment_{radio_state['current_segment_index']}_host.mp3")
277
  tts_service.save_audio(audio_bytes, host_audio_file)
278
 
279
  # Get music track and create streaming player
 
370
  if intro and getattr(tts_service, "available", True):
371
  audio_bytes = tts_service.text_to_speech(intro)
372
  if audio_bytes:
373
+ host_audio_file = os.path.join(AUDIO_DIR, f"segment_{radio_state['current_segment_index']}_host.mp3")
374
  tts_service.save_audio(audio_bytes, host_audio_file)
375
 
376
  # Progress info
 
568
  if getattr(tts_service, "available", True):
569
  audio_bytes = tts_service.text_to_speech(host_response)
570
  if audio_bytes:
571
+ audio_file = os.path.join(AUDIO_DIR, f"voice_request_{int(time.time())}.mp3")
572
  tts_service.save_audio(audio_bytes, audio_file)
573
 
574
  # Create music player HTML
config.py β†’ src/config.py RENAMED
File without changes
demo_assets.py β†’ src/demo_assets.py RENAMED
File without changes
{mcp_servers β†’ src/mcp_servers}/__init__.py RENAMED
File without changes
{mcp_servers β†’ src/mcp_servers}/music_server.py RENAMED
File without changes
{mcp_servers β†’ src/mcp_servers}/news_server.py RENAMED
File without changes
{mcp_servers β†’ src/mcp_servers}/podcast_server.py RENAMED
File without changes
radio_agent.py β†’ src/radio_agent.py RENAMED
@@ -16,7 +16,9 @@ from rag_system import RadioRAGSystem
16
  # -----------------------------------------------------------------------------
17
  # LLM Logging Setup
18
  # -----------------------------------------------------------------------------
19
- LOG_DIR = "logs"
 
 
20
  os.makedirs(LOG_DIR, exist_ok=True)
21
 
22
  llm_logger = logging.getLogger("ai_radio.llm")
 
16
  # -----------------------------------------------------------------------------
17
  # LLM Logging Setup
18
  # -----------------------------------------------------------------------------
19
+ # Get project root directory (parent of src/)
20
+ PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
21
+ LOG_DIR = os.path.join(PROJECT_ROOT, "logs")
22
  os.makedirs(LOG_DIR, exist_ok=True)
23
 
24
  llm_logger = logging.getLogger("ai_radio.llm")
rag_system.py β†’ src/rag_system.py RENAMED
@@ -7,6 +7,9 @@ from llama_index.core import VectorStoreIndex, Document, Settings
7
  from llama_index.core.storage.storage_context import StorageContext
8
  from llama_index.core.vector_stores import SimpleVectorStore
9
  from llama_index.llms.openai import OpenAI as LlamaOpenAI
 
 
 
10
  # from llama_index.embeddings.gemini import GeminiEmbedding # Commented out - using Nebius instead
11
  # from llama_index.llms.gemini import Gemini # Commented out - using Nebius instead
12
 
@@ -65,7 +68,7 @@ class RadioRAGSystem:
65
  # Load existing index or create new one
66
  self.index = None
67
  self.documents = []
68
- self.user_data_file = "user_data.json"
69
 
70
  self._load_user_data()
71
 
 
7
  from llama_index.core.storage.storage_context import StorageContext
8
  from llama_index.core.vector_stores import SimpleVectorStore
9
  from llama_index.llms.openai import OpenAI as LlamaOpenAI
10
+
11
+ # Get project root directory (parent of src/)
12
+ PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
13
  # from llama_index.embeddings.gemini import GeminiEmbedding # Commented out - using Nebius instead
14
  # from llama_index.llms.gemini import Gemini # Commented out - using Nebius instead
15
 
 
68
  # Load existing index or create new one
69
  self.index = None
70
  self.documents = []
71
+ self.user_data_file = os.path.join(PROJECT_ROOT, "user_data.json")
72
 
73
  self._load_user_data()
74
 
test_app.py β†’ src/test_app.py RENAMED
File without changes
tts_service.py β†’ src/tts_service.py RENAMED
File without changes
voice_input.py β†’ src/voice_input.py RENAMED
File without changes